diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index ea44bae3a9..43580a51f7 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -684,6 +684,7 @@ phutil_register_library_map(array( 'PhabricatorFlagQuery' => 'applications/flag/query/PhabricatorFlagQuery.php', 'PhabricatorFormExample' => 'applications/uiexample/examples/PhabricatorFormExample.php', 'PhabricatorGarbageCollectorDaemon' => 'infrastructure/daemon/PhabricatorGarbageCollectorDaemon.php', + 'PhabricatorGitGraphStream' => 'applications/repository/daemon/PhabricatorGitGraphStream.php', 'PhabricatorGoodForNothingWorker' => 'infrastructure/daemon/workers/worker/PhabricatorGoodForNothingWorker.php', 'PhabricatorHandleObjectSelectorDataView' => 'applications/phid/handle/view/PhabricatorHandleObjectSelectorDataView.php', 'PhabricatorHash' => 'infrastructure/util/PhabricatorHash.php', diff --git a/src/applications/repository/daemon/PhabricatorGitGraphStream.php b/src/applications/repository/daemon/PhabricatorGitGraphStream.php new file mode 100644 index 0000000000..62a2382098 --- /dev/null +++ b/src/applications/repository/daemon/PhabricatorGitGraphStream.php @@ -0,0 +1,96 @@ +repository = $repository; + + $future = $repository->getLocalCommandFuture( + "log --format=%s %s --", + '%H%x01%P%x01%ct', + $start_commit); + + $this->iterator = new LinesOfALargeExecFuture($future); + $this->iterator->setDelimiter("\n"); + $this->iterator->rewind(); + } + + public function getParents($commit) { + if (!isset($this->parents[$commit])) { + $this->parseUntil($commit); + } + return $this->parents[$commit]; + } + + public function getCommitDate($commit) { + if (!isset($this->dates[$commit])) { + $this->parseUntil($commit); + } + return $this->dates[$commit]; + } + + private function parseUntil($commit) { + if ($this->isParsed($commit)) { + return; + } + + $gitlog = $this->iterator; + + while ($gitlog->valid()) { + $line = $gitlog->current(); + $gitlog->next(); + + $line = trim($line); + if (!strlen($line)) { + break; + } + list($hash, $parents, $epoch) = explode("\1", $line); + + if ($parents) { + $parents = explode(' ', $parents); + } else { + // First commit. + $parents = array(); + } + + $this->dates[$hash] = $epoch; + $this->parents[$hash] = $parents; + + if ($this->isParsed($commit)) { + return; + } + } + + throw new Exception("No such commit '{$commit}' in repository!"); + } + + private function isParsed($commit) { + return isset($this->dates[$commit]); + } + +} diff --git a/src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php b/src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php index b887404df8..4eb9ccebeb 100644 --- a/src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php +++ b/src/applications/repository/daemon/PhabricatorRepositoryPullLocalDaemon.php @@ -614,12 +614,11 @@ final class PhabricatorRepositoryPullLocalDaemon $seen_parent = array(); + $stream = new PhabricatorGitGraphStream($repository, $commit); + while (true) { $target = array_pop($discover); - list($parents) = $repository->execxLocalCommand( - 'log -n1 --pretty="%%P" %s', - $target); - $parents = array_filter(explode(' ', trim($parents))); + $parents = $stream->getParents($target); foreach ($parents as $parent) { if (isset($seen_parent[$parent])) { // We end up in a loop here somehow when we parse Arcanist if we @@ -656,9 +655,7 @@ final class PhabricatorRepositoryPullLocalDaemon while (true) { $target = array_pop($insert); - list($epoch) = $repository->execxLocalCommand( - 'log -n1 --pretty="%%ct" %s', - $target); + $epoch = $stream->getCommitDate($target); $epoch = trim($epoch); if ($branch !== null) {