@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Make repository discovery partially testable

Summary:
Ref T2784. Begins pulling discovery into Engines and covering it with tests. In particular:

- Discovery is currently a one-shot process where we find all the new commits and write them to the database in one go. Split it apart so we find and return the new commits first, then write them to the database separately. This makes things simpler and more testable.
- This diff only brings SVN into an engine (and only the "find the commits" part), since it's simpler than Git or Mercurial.
- Creates a base Engine class and moves common functionality there.
- Restores the `--verbose` flag to `repository pull`.

Test Plan: Added unit tests. Ran `bin/repository discover`. Ran `bin/phd debug pulllocal`.

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T2784

Differential Revision: https://secure.phabricator.com/D5906

+357 -138
+7 -2
src/__phutil_library_map__.php
··· 1283 1283 'PhabricatorRepositoryCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/PhabricatorRepositoryCommitMessageParserWorker.php', 1284 1284 'PhabricatorRepositoryCommitOwnersWorker' => 'applications/repository/worker/PhabricatorRepositoryCommitOwnersWorker.php', 1285 1285 'PhabricatorRepositoryCommitParserWorker' => 'applications/repository/worker/PhabricatorRepositoryCommitParserWorker.php', 1286 + 'PhabricatorRepositoryCommitRef' => 'applications/repository/engine/PhabricatorRepositoryCommitRef.php', 1286 1287 'PhabricatorRepositoryCommitSearchIndexer' => 'applications/repository/search/PhabricatorRepositoryCommitSearchIndexer.php', 1287 1288 'PhabricatorRepositoryConfigOptions' => 'applications/repository/PhabricatorRepositoryConfigOptions.php', 1288 1289 'PhabricatorRepositoryController' => 'applications/repository/controller/PhabricatorRepositoryController.php', 1289 1290 'PhabricatorRepositoryCreateController' => 'applications/repository/controller/PhabricatorRepositoryCreateController.php', 1290 1291 'PhabricatorRepositoryDAO' => 'applications/repository/storage/PhabricatorRepositoryDAO.php', 1291 1292 'PhabricatorRepositoryDeleteController' => 'applications/repository/controller/PhabricatorRepositoryDeleteController.php', 1293 + 'PhabricatorRepositoryDiscoveryEngine' => 'applications/repository/engine/PhabricatorRepositoryDiscoveryEngine.php', 1292 1294 'PhabricatorRepositoryEditController' => 'applications/repository/controller/PhabricatorRepositoryEditController.php', 1295 + 'PhabricatorRepositoryEngine' => 'applications/repository/engine/PhabricatorRepositoryEngine.php', 1293 1296 'PhabricatorRepositoryGitCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/PhabricatorRepositoryGitCommitChangeParserWorker.php', 1294 1297 'PhabricatorRepositoryGitCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/PhabricatorRepositoryGitCommitMessageParserWorker.php', 1295 1298 'PhabricatorRepositoryListController' => 'applications/repository/controller/PhabricatorRepositoryListController.php', ··· 1302 1305 'PhabricatorRepositoryMercurialCommitMessageParserWorker' => 'applications/repository/worker/commitmessageparser/PhabricatorRepositoryMercurialCommitMessageParserWorker.php', 1303 1306 'PhabricatorRepositoryPullEngine' => 'applications/repository/engine/PhabricatorRepositoryPullEngine.php', 1304 1307 'PhabricatorRepositoryPullLocalDaemon' => 'applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php', 1305 - 'PhabricatorRepositoryPullLocalDaemonTestCase' => 'applications/repository/daemon/__tests__/PhabricatorRepositoryPullLocalDaemonTestCase.php', 1306 1308 'PhabricatorRepositoryQuery' => 'applications/repository/query/PhabricatorRepositoryQuery.php', 1307 1309 'PhabricatorRepositoryShortcut' => 'applications/repository/storage/PhabricatorRepositoryShortcut.php', 1308 1310 'PhabricatorRepositorySvnCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/PhabricatorRepositorySvnCommitChangeParserWorker.php', ··· 1488 1490 'PhabricatorWorkerTaskDetailController' => 'applications/daemon/controller/PhabricatorWorkerTaskDetailController.php', 1489 1491 'PhabricatorWorkerTaskUpdateController' => 'applications/daemon/controller/PhabricatorWorkerTaskUpdateController.php', 1490 1492 'PhabricatorWorkerTestCase' => 'infrastructure/daemon/workers/__tests__/PhabricatorWorkerTestCase.php', 1493 + 'PhabricatorWorkingCopyDiscoveryTestCase' => 'applications/repository/engine/__tests__/PhabricatorWorkingCopyDiscoveryTestCase.php', 1491 1494 'PhabricatorWorkingCopyPullTestCase' => 'applications/repository/engine/__tests__/PhabricatorWorkingCopyPullTestCase.php', 1492 1495 'PhabricatorWorkingCopyTestCase' => 'applications/repository/engine/__tests__/PhabricatorWorkingCopyTestCase.php', 1493 1496 'PhabricatorWorkpanelView' => 'view/layout/PhabricatorWorkpanelView.php', ··· 3014 3017 'PhabricatorRepositoryCreateController' => 'PhabricatorRepositoryController', 3015 3018 'PhabricatorRepositoryDAO' => 'PhabricatorLiskDAO', 3016 3019 'PhabricatorRepositoryDeleteController' => 'PhabricatorRepositoryController', 3020 + 'PhabricatorRepositoryDiscoveryEngine' => 'PhabricatorRepositoryEngine', 3017 3021 'PhabricatorRepositoryEditController' => 'PhabricatorRepositoryController', 3018 3022 'PhabricatorRepositoryGitCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker', 3019 3023 'PhabricatorRepositoryGitCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker', ··· 3025 3029 'PhabricatorRepositoryManagementWorkflow' => 'PhutilArgumentWorkflow', 3026 3030 'PhabricatorRepositoryMercurialCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker', 3027 3031 'PhabricatorRepositoryMercurialCommitMessageParserWorker' => 'PhabricatorRepositoryCommitMessageParserWorker', 3032 + 'PhabricatorRepositoryPullEngine' => 'PhabricatorRepositoryEngine', 3028 3033 'PhabricatorRepositoryPullLocalDaemon' => 'PhabricatorDaemon', 3029 - 'PhabricatorRepositoryPullLocalDaemonTestCase' => 'PhabricatorTestCase', 3030 3034 'PhabricatorRepositoryQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 3031 3035 'PhabricatorRepositoryShortcut' => 'PhabricatorRepositoryDAO', 3032 3036 'PhabricatorRepositorySvnCommitChangeParserWorker' => 'PhabricatorRepositoryCommitChangeParserWorker', ··· 3197 3201 'PhabricatorWorkerTaskDetailController' => 'PhabricatorDaemonController', 3198 3202 'PhabricatorWorkerTaskUpdateController' => 'PhabricatorDaemonController', 3199 3203 'PhabricatorWorkerTestCase' => 'PhabricatorTestCase', 3204 + 'PhabricatorWorkingCopyDiscoveryTestCase' => 'PhabricatorWorkingCopyTestCase', 3200 3205 'PhabricatorWorkingCopyPullTestCase' => 'PhabricatorWorkingCopyTestCase', 3201 3206 'PhabricatorWorkingCopyTestCase' => 'PhabricatorTestCase', 3202 3207 'PhabricatorWorkpanelView' => 'AphrontView',
+26 -106
src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php
··· 31 31 32 32 private $commitCache = array(); 33 33 private $repair; 34 + private $discoveryEngines = array(); 34 35 35 36 public function setRepair($repair) { 36 37 $this->repair = $repair; ··· 183 184 case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: 184 185 return $this->executeGitDiscover($repository); 185 186 case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: 186 - return $this->executeSvnDiscover($repository); 187 + $refs = $this->getDiscoveryEngine($repository) 188 + ->discoverCommits(); 189 + break; 187 190 case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: 188 191 return $this->executeHgDiscover($repository); 189 192 default: 190 193 throw new Exception("Unknown VCS '{$vcs}'!"); 191 194 } 195 + 196 + foreach ($refs as $ref) { 197 + $this->recordCommit( 198 + $repository, 199 + $ref->getIdentifier(), 200 + $ref->getEpoch(), 201 + $ref->getBranch()); 202 + } 203 + 204 + return (bool)count($refs); 192 205 } 193 206 207 + private function getDiscoveryEngine(PhabricatorRepository $repository) { 208 + $id = $repository->getID(); 209 + if (empty($this->discoveryEngines[$id])) { 210 + $engine = id(new PhabricatorRepositoryDiscoveryEngine()) 211 + ->setRepository($repository) 212 + ->setVerbose($this->getVerbose()) 213 + ->setRepairMode($this->repair); 214 + 215 + $this->discoveryEngines[$id] = $engine; 216 + } 217 + return $this->discoveryEngines[$id]; 218 + } 194 219 195 220 private function isKnownCommit( 196 221 PhabricatorRepository $repository, ··· 679 704 $epoch = $stream->getCommitDate($target); 680 705 $this->recordCommit($repository, $target, $epoch); 681 706 } 682 - } 683 - 684 - 685 - /* -( Subversion Implementation )------------------------------------------ */ 686 - 687 - 688 - private function executeSvnDiscover( 689 - PhabricatorRepository $repository) { 690 - 691 - $uri = $this->executeSvnGetBaseSVNLogURI($repository); 692 - 693 - list($xml) = $repository->execxRemoteCommand( 694 - 'log --xml --quiet --limit 1 %s@HEAD', 695 - $uri); 696 - 697 - $results = $this->executeSvnParseLogXML($xml); 698 - $commit = head_key($results); 699 - $epoch = head($results); 700 - 701 - if ($this->isKnownCommit($repository, $commit)) { 702 - return false; 703 - } 704 - 705 - $this->executeSvnDiscoverCommit($repository, $commit, $epoch); 706 - return true; 707 - } 708 - 709 - private function executeSvnDiscoverCommit( 710 - PhabricatorRepository $repository, 711 - $commit, 712 - $epoch) { 713 - 714 - $uri = $this->executeSvnGetBaseSVNLogURI($repository); 715 - 716 - $discover = array( 717 - $commit => $epoch, 718 - ); 719 - $upper_bound = $commit; 720 - 721 - $limit = 1; 722 - while ($upper_bound > 1 && 723 - !$this->isKnownCommit($repository, $upper_bound)) { 724 - // Find all the unknown commits on this path. Note that we permit 725 - // importing an SVN subdirectory rather than the entire repository, so 726 - // commits may be nonsequential. 727 - list($err, $xml, $stderr) = $repository->execRemoteCommand( 728 - ' log --xml --quiet --limit %d %s@%d', 729 - $limit, 730 - $uri, 731 - $upper_bound - 1); 732 - if ($err) { 733 - if (preg_match('/(path|File) not found/', $stderr)) { 734 - // We've gone all the way back through history and this path was not 735 - // affected by earlier commits. 736 - break; 737 - } else { 738 - throw new Exception("svn log error #{$err}: {$stderr}"); 739 - } 740 - } 741 - $discover += $this->executeSvnParseLogXML($xml); 742 - 743 - $upper_bound = min(array_keys($discover)); 744 - 745 - // Discover 2, 4, 8, ... 256 logs at a time. This allows us to initially 746 - // import large repositories fairly quickly, while pulling only as much 747 - // data as we need in the common case (when we've already imported the 748 - // repository and are just grabbing one commit at a time). 749 - $limit = min($limit * 2, 256); 750 - } 751 - 752 - // NOTE: We do writes only after discovering all the commits so that we're 753 - // never left in a state where we've missed commits -- if the discovery 754 - // script terminates it can always resume and restore the import to a good 755 - // state. This is also why we sort the discovered commits so we can do 756 - // writes forward from the smallest one. 757 - 758 - ksort($discover); 759 - foreach ($discover as $commit => $epoch) { 760 - $this->recordCommit($repository, $commit, $epoch); 761 - } 762 - } 763 - 764 - private function executeSvnParseLogXML($xml) { 765 - $xml = phutil_utf8ize($xml); 766 - 767 - $result = array(); 768 - 769 - $log = new SimpleXMLElement($xml); 770 - foreach ($log->logentry as $entry) { 771 - $commit = (int)$entry['revision']; 772 - $epoch = (int)strtotime((string)$entry->date[0]); 773 - $result[$commit] = $epoch; 774 - } 775 - 776 - return $result; 777 - } 778 - 779 - 780 - private function executeSvnGetBaseSVNLogURI( 781 - PhabricatorRepository $repository) { 782 - 783 - $uri = $repository->getDetail('remote-uri'); 784 - $subpath = $repository->getDetail('svn-subpath'); 785 - 786 - return $uri.$subpath; 787 707 } 788 708 789 709 }
+23 -2
src/applications/repository/daemon/__tests__/PhabricatorRepositoryPullLocalDaemonTestCase.php src/applications/repository/engine/__tests__/PhabricatorWorkingCopyDiscoveryTestCase.php
··· 1 1 <?php 2 2 3 - final class PhabricatorRepositoryPullLocalDaemonTestCase 4 - extends PhabricatorTestCase { 3 + final class PhabricatorWorkingCopyDiscoveryTestCase 4 + extends PhabricatorWorkingCopyTestCase { 5 + 6 + public function testSubversionCommitDiscovery() { 7 + $repo = $this->buildPulledRepository('ST'); 8 + 9 + $engine = id(new PhabricatorRepositoryDiscoveryEngine()) 10 + ->setRepository($repo); 11 + 12 + $refs = $engine->discoverCommits($repo); 13 + $this->assertEqual( 14 + array( 15 + 1368319433, 16 + 1368319448, 17 + ), 18 + mpull($refs, 'getEpoch'), 19 + 'Commit Epochs'); 20 + 21 + // The next time through, these should be cached as already discovered. 22 + 23 + $refs = $engine->discoverCommits($repo); 24 + $this->assertEqual(array(), $refs); 25 + } 5 26 6 27 public function testExecuteGitVerifySameOrigin() { 7 28 $cases = array(
+36
src/applications/repository/engine/PhabricatorRepositoryCommitRef.php
··· 1 + <?php 2 + 3 + final class PhabricatorRepositoryCommitRef { 4 + 5 + private $identifier; 6 + private $epoch; 7 + private $branch; 8 + 9 + public function setIdentifier($identifier) { 10 + $this->identifier = $identifier; 11 + return $this; 12 + } 13 + 14 + public function getIdentifier() { 15 + return $this->identifier; 16 + } 17 + 18 + public function setEpoch($epoch) { 19 + $this->epoch = $epoch; 20 + return $this; 21 + } 22 + 23 + public function getEpoch() { 24 + return $this->epoch; 25 + } 26 + 27 + public function setBranch($branch) { 28 + $this->branch = $branch; 29 + return $this; 30 + } 31 + 32 + public function getBranch() { 33 + return $this->branch; 34 + } 35 + 36 + }
+173
src/applications/repository/engine/PhabricatorRepositoryDiscoveryEngine.php
··· 1 + <?php 2 + 3 + /** 4 + * @task discover Discovering Repositories 5 + * @task svn Discovering Subversion Repositories 6 + * @task git Discovering Git Repositories 7 + * @task hg Discovering Mercurial Repositories 8 + * @task internal Internals 9 + */ 10 + final class PhabricatorRepositoryDiscoveryEngine 11 + extends PhabricatorRepositoryEngine { 12 + 13 + private $repairMode; 14 + private $commitCache = array(); 15 + const MAX_COMMIT_CACHE_SIZE = 2048; 16 + 17 + 18 + /* -( Discovering Repositories )------------------------------------------- */ 19 + 20 + 21 + public function setRepairMode($repair_mode) { 22 + $this->repairMode = $repair_mode; 23 + return $this; 24 + } 25 + 26 + 27 + public function getRepairMode() { 28 + return $this->repairMode; 29 + } 30 + 31 + 32 + /** 33 + * @task discovery 34 + */ 35 + public function discoverCommits() { 36 + $repository = $this->getRepository(); 37 + 38 + $vcs = $repository->getVersionControlSystem(); 39 + switch ($vcs) { 40 + case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: 41 + $refs = $this->discoverSubversionCommits(); 42 + break; 43 + /* 44 + 45 + TODO: Implement these! 46 + 47 + case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: 48 + $refs = $this->executeGitDiscovery(); 49 + break; 50 + case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL: 51 + $refs = $this->executeMercurialDiscovery(); 52 + break; 53 + 54 + */ 55 + default: 56 + throw new Exception("Unknown VCS '{$vcs}'!"); 57 + } 58 + 59 + // Mark discovered commits in the cache. 60 + foreach ($refs as $ref) { 61 + $this->commitCache[$ref->getIdentifier()] = true; 62 + } 63 + 64 + return $refs; 65 + } 66 + 67 + 68 + /* -( Discovering Subversion Repositories )-------------------------------- */ 69 + 70 + 71 + /** 72 + * @task svn 73 + */ 74 + private function discoverSubversionCommits() { 75 + $repository = $this->getRepository(); 76 + 77 + $upper_bound = null; 78 + $limit = 1; 79 + $refs = array(); 80 + do { 81 + // Find all the unknown commits on this path. Note that we permit 82 + // importing an SVN subdirectory rather than the entire repository, so 83 + // commits may be nonsequential. 84 + 85 + if ($upper_bound === null) { 86 + $at_rev = 'HEAD'; 87 + } else { 88 + $at_rev = ($upper_bound - 1); 89 + } 90 + 91 + try { 92 + list($xml, $stderr) = $repository->execxRemoteCommand( 93 + 'log --xml --quiet --limit %d %s@%s', 94 + $limit, 95 + $repository->getSubversionBaseURI(), 96 + $at_rev); 97 + } catch (CommandException $ex) { 98 + $stderr = $ex->getStdErr(); 99 + if (preg_match('/(path|File) not found/', $stderr)) { 100 + // We've gone all the way back through history and this path was not 101 + // affected by earlier commits. 102 + break; 103 + } 104 + throw $ex; 105 + } 106 + 107 + $xml = phutil_utf8ize($xml); 108 + $log = new SimpleXMLElement($xml); 109 + foreach ($log->logentry as $entry) { 110 + $identifier = (int)$entry['revision']; 111 + $epoch = (int)strtotime((string)$entry->date[0]); 112 + $refs[$identifier] = id(new PhabricatorRepositoryCommitRef()) 113 + ->setIdentifier($identifier) 114 + ->setEpoch($epoch); 115 + 116 + if ($upper_bound === null) { 117 + $upper_bound = $identifier; 118 + } else { 119 + $upper_bound = min($upper_bound, $identifier); 120 + } 121 + } 122 + 123 + // Discover 2, 4, 8, ... 256 logs at a time. This allows us to initially 124 + // import large repositories fairly quickly, while pulling only as much 125 + // data as we need in the common case (when we've already imported the 126 + // repository and are just grabbing one commit at a time). 127 + $limit = min($limit * 2, 256); 128 + 129 + } while ($upper_bound > 1 && !$this->isKnownCommit($upper_bound)); 130 + 131 + krsort($refs); 132 + while ($refs && $this->isKnownCommit(last($refs)->getIdentifier())) { 133 + array_pop($refs); 134 + } 135 + $refs = array_reverse($refs); 136 + 137 + return $refs; 138 + } 139 + 140 + 141 + /* -( Internals )---------------------------------------------------------- */ 142 + 143 + 144 + private function isKnownCommit($identifier) { 145 + if (isset($this->commitCache[$identifier])) { 146 + return true; 147 + } 148 + 149 + if ($this->repairMode) { 150 + // In repair mode, rediscover the entire repository, ignoring the 151 + // database state. We can hit the local cache above, but if we miss it 152 + // stop the script from going to the database cache. 153 + return false; 154 + } 155 + 156 + $commit = id(new PhabricatorRepositoryCommit())->loadOneWhere( 157 + 'repositoryID = %d AND commitIdentifier = %s', 158 + $this->getRepository()->getID(), 159 + $identifier); 160 + 161 + if (!$commit) { 162 + return false; 163 + } 164 + 165 + $this->commitCache[$identifier] = true; 166 + while (count($this->commitCache) > self::MAX_COMMIT_CACHE_SIZE) { 167 + array_shift($this->commitCache); 168 + } 169 + 170 + return true; 171 + } 172 + 173 + }
+62
src/applications/repository/engine/PhabricatorRepositoryEngine.php
··· 1 + <?php 2 + 3 + /** 4 + * @task config Configuring Repository Engines 5 + * @task internal Internals 6 + */ 7 + abstract class PhabricatorRepositoryEngine { 8 + 9 + private $repository; 10 + private $verbose; 11 + 12 + /** 13 + * @task config 14 + */ 15 + public function setRepository(PhabricatorRepository $repository) { 16 + $this->repository = $repository; 17 + return $this; 18 + } 19 + 20 + 21 + /** 22 + * @task config 23 + */ 24 + protected function getRepository() { 25 + if ($this->repository === null) { 26 + throw new Exception("Call setRepository() to provide a repository!"); 27 + } 28 + 29 + return $this->repository; 30 + } 31 + 32 + 33 + /** 34 + * @task config 35 + */ 36 + public function setVerbose($verbose) { 37 + $this->verbose = $verbose; 38 + return $this; 39 + } 40 + 41 + 42 + /** 43 + * @task config 44 + */ 45 + public function getVerbose() { 46 + return $this->verbose; 47 + } 48 + 49 + 50 + /** 51 + * @task internal 52 + */ 53 + protected function log($pattern /* ... */) { 54 + if ($this->getVerbose()) { 55 + $console = PhutilConsole::getConsole(); 56 + $argv = func_get_args(); 57 + call_user_func_array(array($console, 'writeLog'), $argv); 58 + } 59 + return $this; 60 + } 61 + 62 + }
+13 -16
src/applications/repository/engine/PhabricatorRepositoryPullEngine.php
··· 10 10 * @task hg Pulling Mercurial Working Copies 11 11 * @task internal Internals 12 12 */ 13 - final class PhabricatorRepositoryPullEngine { 14 - 15 - private $repository; 13 + final class PhabricatorRepositoryPullEngine 14 + extends PhabricatorRepositoryEngine { 16 15 17 16 18 17 /* -( Pulling Working Copies )--------------------------------------------- */ 19 18 20 19 21 - public function setRepository(PhabricatorRepository $repository) { 22 - $this->repository = $repository; 23 - return $this; 24 - } 25 - 26 - private function getRepository() { 27 - return $this->repository; 28 - } 29 - 30 20 public function pullRepository() { 31 21 $repository = $this->getRepository(); 32 22 33 - if (!$repository) { 34 - throw new Exception("Call setRepository() before pullRepository()!"); 35 - } 36 - 37 23 $is_hg = false; 38 24 $is_git = false; 39 25 40 26 $vcs = $repository->getVersionControlSystem(); 27 + $callsign = $repository->getCallsign(); 41 28 switch ($vcs) { 42 29 case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN: 43 30 // We never pull a local copy of Subversion repositories. 31 + $this->log( 32 + "Repository '%s' is a Subversion repository, which does not require ". 33 + "a local working copy to be pulled.", 34 + $callsign); 44 35 return; 45 36 case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT: 46 37 $is_git = true; ··· 65 56 } 66 57 67 58 if (!Filesystem::pathExists($local_path)) { 59 + $this->log( 60 + "Creating a new working copy for repository '%s'.", 61 + $callsign); 68 62 if ($is_git) { 69 63 $this->executeGitCreate(); 70 64 } else { 71 65 $this->executeMercurialCreate(); 72 66 } 73 67 } else { 68 + $this->log( 69 + "Updating the working copy for repository '%s'.", 70 + $callsign); 74 71 if ($is_git) { 75 72 $this->executeGitUpdate(); 76 73 } else {
-12
src/applications/repository/engine/__tests__/PhabricatorWorkingCopyTestCase.php
··· 3 3 abstract class PhabricatorWorkingCopyTestCase extends PhabricatorTestCase { 4 4 5 5 private $dirs = array(); 6 - private $repos = array(); 7 - private $pulled = array(); 8 6 9 7 protected function getPhabricatorTestCaseConfiguration() { 10 8 return array( ··· 13 11 } 14 12 15 13 protected function buildBareRepository($callsign) { 16 - if (isset($this->repos[$callsign])) { 17 - return $this->repos[$callsign]; 18 - } 19 - 20 14 $data_dir = dirname(__FILE__).'/data/'; 21 15 22 16 $types = array( ··· 67 61 $this->dirs[] = $dir; 68 62 $this->dirs[] = $local; 69 63 70 - $this->repos[$callsign] = $repo; 71 - 72 64 return $repo; 73 65 } 74 66 ··· 78 70 79 71 protected function buildPulledRepository($callsign) { 80 72 $repository = $this->buildBareRepository($callsign); 81 - 82 - if (isset($this->pulled[$callsign])) { 83 - return $repository; 84 - } 85 73 86 74 id(new PhabricatorRepositoryPullEngine()) 87 75 ->setRepository($repository)
src/applications/repository/engine/__tests__/data/ST.svn.tgz

This is a binary file and will not be displayed.

+5
src/applications/repository/management/PhabricatorRepositoryManagementPullWorkflow.php
··· 11 11 ->setArguments( 12 12 array( 13 13 array( 14 + 'name' => 'verbose', 15 + 'help' => 'Show additional debugging information.', 16 + ), 17 + array( 14 18 'name' => 'repos', 15 19 'wildcard' => true, 16 20 ), ··· 32 36 33 37 id(new PhabricatorRepositoryPullEngine()) 34 38 ->setRepository($repo) 39 + ->setVerbose($args->getArg('verbose')) 35 40 ->pullRepository(); 36 41 } 37 42
+12
src/applications/repository/storage/PhabricatorRepository.php
··· 90 90 return $this->getDetail('local-path'); 91 91 } 92 92 93 + public function getSubversionBaseURI() { 94 + $vcs = $this->getVersionControlSystem(); 95 + if ($vcs != PhabricatorRepositoryType::REPOSITORY_TYPE_SVN) { 96 + throw new Exception("Not a subversion repository!"); 97 + } 98 + 99 + $uri = $this->getDetail('remote-uri'); 100 + $subpath = $this->getDetail('svn-subpath'); 101 + 102 + return $uri.$subpath; 103 + } 104 + 93 105 public function execRemoteCommand($pattern /* , $arg, ... */) { 94 106 $args = func_get_args(); 95 107 $args = $this->formatRemoteCommand($args);