Correct a parameter order swap in "diffusion.historyquery" for Mercurial
[phabricator.git] / src / applications / repository / daemon / PhabricatorGitGraphStream.php
blob39b1fe39ed0173b4a39c72bab0ec0671024d951f
1 <?php
3 final class PhabricatorGitGraphStream
4 extends PhabricatorRepositoryGraphStream {
6 private $repository;
7 private $iterator;
8 private $startCommit;
10 private $parents = array();
11 private $dates = array();
13 public function __construct(
14 PhabricatorRepository $repository,
15 $start_commit = null) {
17 $this->repository = $repository;
18 $this->startCommit = $start_commit;
20 if ($start_commit !== null) {
21 $future = $repository->getLocalCommandFuture(
22 'log %s %s --',
23 '--format=%H%x01%P%x01%ct',
24 gitsprintf('%s', $start_commit));
25 } else {
26 $future = $repository->getLocalCommandFuture(
27 'log %s --all --',
28 '--format=%H%x01%P%x01%ct');
31 $this->iterator = new LinesOfALargeExecFuture($future);
32 $this->iterator->setDelimiter("\n");
33 $this->iterator->rewind();
36 public function getParents($commit) {
37 if (!isset($this->parents[$commit])) {
38 $this->parseUntil($commit);
40 $parents = $this->parents[$commit];
42 // NOTE: In Git, it is possible for a commit to list the same parent more
43 // than once. See T5226. Discard duplicate parents.
45 return array_unique($parents);
48 public function getCommitDate($commit) {
49 if (!isset($this->dates[$commit])) {
50 $this->parseUntil($commit);
52 return $this->dates[$commit];
55 private function parseUntil($commit) {
56 if ($this->isParsed($commit)) {
57 return;
60 $gitlog = $this->iterator;
62 while ($gitlog->valid()) {
63 $line = $gitlog->current();
64 $gitlog->next();
66 $line = trim($line);
67 if (!strlen($line)) {
68 break;
70 list($hash, $parents, $epoch) = explode("\1", $line);
72 if ($parents) {
73 $parents = explode(' ', $parents);
74 } else {
75 // First commit.
76 $parents = array();
79 $this->dates[$hash] = $epoch;
80 $this->parents[$hash] = $parents;
82 if ($this->isParsed($commit)) {
83 return;
87 if ($this->startCommit !== null) {
88 throw new Exception(
89 pht(
90 'Commit "%s" is not a reachable ancestor of "%s".',
91 $commit,
92 $this->startCommit));
93 } else {
94 throw new Exception(
95 pht(
96 'Commit "%s" is not a reachable ancestor of any ref.',
97 $commit));
101 private function isParsed($commit) {
102 return isset($this->dates[$commit]);