Skip to content

Commit 08bdfac

Browse files
author
epriestley
committed
Make Subversion URI construction more consistent
Summary: Ref T2230. SVN has some weird rules about path construction. Particularly, if you're missing a "/" in the remote URI right now, the change parsing step doesn't build the right paths. Instead, build the right paths more intelligently. Test Plan: Added and executed unit tests. Imported an SVN repo. Reviewers: btrahan Reviewed By: btrahan CC: aran, jpeffer Maniphest Tasks: T2230 Differential Revision: https://secure.phabricator.com/D7590
1 parent 6eb02af commit 08bdfac

File tree

3 files changed

+75
-21
lines changed

3 files changed

+75
-21
lines changed

src/applications/repository/storage/PhabricatorRepository.php

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,14 @@ public function getLocalPath() {
156156
}
157157

158158
public function getSubversionBaseURI() {
159+
$subpath = $this->getDetail('svn-subpath');
160+
if (!strlen($subpath)) {
161+
$subpath = null;
162+
}
163+
return $this->getSubversionPathURI($subpath);
164+
}
165+
166+
public function getSubversionPathURI($path = null, $commit = null) {
159167
$vcs = $this->getVersionControlSystem();
160168
if ($vcs != PhabricatorRepositoryType::REPOSITORY_TYPE_SVN) {
161169
throw new Exception("Not a subversion repository!");
@@ -167,12 +175,23 @@ public function getSubversionBaseURI() {
167175
$uri = $this->getDetail('remote-uri');
168176
}
169177

170-
$subpath = $this->getDetail('svn-subpath');
171-
if ($subpath) {
172-
$subpath = '/'.ltrim($subpath, '/');
178+
$uri = rtrim($uri, '/');
179+
180+
if (strlen($path)) {
181+
$path = rawurlencode($path);
182+
$path = str_replace('%2F', '/', $path);
183+
$uri = $uri.'/'.ltrim($path, '/');
184+
}
185+
186+
if ($path !== null || $commit !== null) {
187+
$uri .= '@';
188+
}
189+
190+
if ($commit !== null) {
191+
$uri .= $commit;
173192
}
174193

175-
return $uri.$subpath;
194+
return $uri;
176195
}
177196

178197
public function execRemoteCommand($pattern /* , $arg, ... */) {

src/applications/repository/storage/__tests__/PhabricatorRepositoryTestCase.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,46 @@ public function testBranchFilter() {
5555
'Do not track unlisted branches.');
5656
}
5757

58+
public function testSubversionPathInfo() {
59+
$svn = PhabricatorRepositoryType::REPOSITORY_TYPE_SVN;
60+
61+
$repo = new PhabricatorRepository();
62+
$repo->setVersionControlSystem($svn);
63+
64+
$repo->setDetail('remote-uri', 'http://svn.example.com/repo');
65+
$this->assertEqual(
66+
'http://svn.example.com/repo',
67+
$repo->getSubversionPathURI());
68+
69+
$repo->setDetail('remote-uri', 'http://svn.example.com/repo/');
70+
$this->assertEqual(
71+
'http://svn.example.com/repo',
72+
$repo->getSubversionPathURI());
73+
74+
$repo->setDetail('hosting-enabled', true);
75+
76+
$repo->setDetail('local-path', '/var/repo/SVN');
77+
$this->assertEqual(
78+
'file:///var/repo/SVN',
79+
$repo->getSubversionPathURI());
80+
81+
$repo->setDetail('local-path', '/var/repo/SVN/');
82+
$this->assertEqual(
83+
'file:///var/repo/SVN',
84+
$repo->getSubversionPathURI());
85+
86+
$this->assertEqual(
87+
'file:///var/repo/SVN/a@',
88+
$repo->getSubversionPathURI('a'));
89+
90+
$this->assertEqual(
91+
'file:///var/repo/SVN/a@1',
92+
$repo->getSubversionPathURI('a', 1));
93+
94+
$this->assertEqual(
95+
'file:///var/repo/SVN/%3F@22',
96+
$repo->getSubversionPathURI('?', 22));
97+
}
98+
99+
58100
}

src/applications/repository/worker/commitchangeparser/PhabricatorRepositorySvnCommitChangeParserWorker.php

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ protected function parseCommitChanges(
2424
// recursive paths were affected if it was moved or copied. This is very
2525
// complicated and has many special cases.
2626

27-
$uri = $repository->getDetail('remote-uri');
27+
$uri = $repository->getSubversionPathURI();
2828
$svn_commit = $commit->getCommitIdentifier();
2929

3030
// Pull the top-level path changes out of "svn log". This is pretty
@@ -561,7 +561,7 @@ private function lookupPathFileTypes(
561561
array $paths) {
562562

563563
$result_map = array();
564-
$repository_uri = $repository->getDetail('remote-uri');
564+
$repository_uri = $repository->getSubversionPathURI();
565565

566566
if (isset($paths['/'])) {
567567
$result_map['/'] = DifferentialChangeType::FILE_DIRECTORY;
@@ -572,9 +572,10 @@ private function lookupPathFileTypes(
572572
$path_mapping = array();
573573
foreach ($paths as $path => $lookup) {
574574
$parent = dirname($lookup['rawPath']);
575-
$parent = ltrim($parent, '/');
576-
$parent = $this->encodeSVNPath($parent);
577-
$parent = $repository_uri.$parent.'@'.$lookup['rawCommit'];
575+
$parent = $repository->getSubversionPathURI(
576+
$parent,
577+
$lookup['rawCommit']);
578+
578579
$parent = escapeshellarg($parent);
579580
$parents[$parent] = true;
580581
$path_mapping[$parent][] = dirname($path);
@@ -626,12 +627,6 @@ private function lookupPathFileTypes(
626627
return $result_map;
627628
}
628629

629-
private function encodeSVNPath($path) {
630-
$path = rawurlencode($path);
631-
$path = str_replace('%2F', '/', $path);
632-
return $path;
633-
}
634-
635630
private function getFileTypeFromSVNKind($kind) {
636631
$kind = (string)$kind;
637632
switch ($kind) {
@@ -648,9 +643,9 @@ private function lookupRecursiveFileList(
648643

649644
$path = $info['rawPath'];
650645
$rev = $info['rawCommit'];
651-
$path = $this->encodeSVNPath($path);
652646

653-
$hashkey = md5($repository->getDetail('remote-uri').$path.'@'.$rev);
647+
$path_uri = $repository->getSubversionPathURI($path, $rev);
648+
$hashkey = md5($path_uri);
654649

655650
// This method is quite horrible. The underlying challenge is that some
656651
// commits in the Facebook repository are enormous, taking multiple hours
@@ -664,10 +659,8 @@ private function lookupRecursiveFileList(
664659
if (!Filesystem::pathExists($cache_loc)) {
665660
$tmp = new TempFile();
666661
$repository->execxRemoteCommand(
667-
'--xml ls -R %s%s@%d > %s',
668-
$repository->getDetail('remote-uri'),
669-
$path,
670-
$rev,
662+
'--xml ls -R %s > %s',
663+
$path_uri,
671664
$tmp);
672665
execx(
673666
'mv %s %s',

0 commit comments

Comments
 (0)