diff --git a/src/repository/api/ArcanistGitAPI.php b/src/repository/api/ArcanistGitAPI.php --- a/src/repository/api/ArcanistGitAPI.php +++ b/src/repository/api/ArcanistGitAPI.php @@ -966,19 +966,43 @@ * @return list> Dictionary of branch information. */ public function getAllBranches() { - list($ref_list) = $this->execxLocal( - 'for-each-ref --format=%s refs/heads', - '%(refname)'); - $refs = explode("\n", rtrim($ref_list)); + $field_list = array( + '%(refname)', + '%(objectname)', + '%(committerdate:raw)', + '%(tree)', + '%(subject)', + '%(subject)%0a%0a%(body)', + '%02', + ); + + list($stdout) = $this->execxLocal( + 'for-each-ref --format=%s -- refs/heads', + implode('%01', $field_list)); $current = $this->getBranchName(); $result = array(); - foreach ($refs as $ref) { + + $lines = explode("\2", $stdout); + foreach ($lines as $line) { + $line = trim($line); + if (!strlen($line)) { + continue; + } + + $fields = explode("\1", $line, 6); + list($ref, $hash, $epoch, $tree, $desc, $text) = $fields; + $branch = $this->getBranchNameFromRef($ref); if ($branch) { $result[] = array( 'current' => ($branch === $current), - 'name' => $branch, + 'name' => $branch, + 'hash' => $hash, + 'tree' => $tree, + 'epoch' => (int)$epoch, + 'desc' => $desc, + 'text' => $text, ); } } diff --git a/src/workflow/ArcanistFeatureWorkflow.php b/src/workflow/ArcanistFeatureWorkflow.php --- a/src/workflow/ArcanistFeatureWorkflow.php +++ b/src/workflow/ArcanistFeatureWorkflow.php @@ -174,38 +174,37 @@ private function loadCommitInfo(array $branches) { $repository_api = $this->getRepositoryAPI(); - $futures = array(); - foreach ($branches as $branch) { - if ($repository_api instanceof ArcanistMercurialAPI) { + $branches = ipull($branches, null, 'name'); + + if ($repository_api instanceof ArcanistMercurialAPI) { + $futures = array(); + foreach ($branches as $branch) { $futures[$branch['name']] = $repository_api->execFutureLocal( 'log -l 1 --template %s -r %s', "{node}\1{date|hgdate}\1{p1node}\1{desc|firstline}\1{desc}", hgsprintf('%s', $branch['name'])); - } else { - // NOTE: "-s" is an option deep in git's diff argument parser that - // doesn't seem to have much documentation and has no long form. It - // suppresses any diff output. - $futures[$branch['name']] = $repository_api->execFutureLocal( - 'show -s --format=%C %s --', - '%H%x01%ct%x01%T%x01%s%x01%s%n%n%b', - $branch['name']); } - } - $branches = ipull($branches, null, 'name'); + $futures = id(new FutureIterator($futures)) + ->limit(16); + foreach ($futures as $name => $future) { + list($info) = $future->resolvex(); + + $fields = explode("\1", trim($info), 5); + list($hash, $epoch, $tree, $desc, $text) = $fields; + + $branches[$name] += array( + 'hash' => $hash, + 'desc' => $desc, + 'tree' => $tree, + 'epoch' => (int)$epoch, + 'text' => $text, + ); + } + } - $futures = id(new FutureIterator($futures)) - ->limit(16); - foreach ($futures as $name => $future) { - list($info) = $future->resolvex(); - list($hash, $epoch, $tree, $desc, $text) = explode("\1", trim($info), 5); - - $branch = $branches[$name] + array( - 'hash' => $hash, - 'desc' => $desc, - 'tree' => $tree, - 'epoch' => (int)$epoch, - ); + foreach ($branches as $name => $branch) { + $text = $branch['text']; try { $message = ArcanistDifferentialCommitMessage::newFromRawCorpus($text); @@ -332,6 +331,11 @@ ); } + if (!$out) { + // All of the revisions are closed or abandoned. + return; + } + $len_name = max(array_map('strlen', ipull($out, 'name'))) + 2; $len_status = max(array_map('strlen', ipull($out, 'status'))) + 2;