diff --git a/src/applications/diffusion/controller/DiffusionRefTableController.php b/src/applications/diffusion/controller/DiffusionRefTableController.php index 2f113e225b..f3f005594d 100644 --- a/src/applications/diffusion/controller/DiffusionRefTableController.php +++ b/src/applications/diffusion/controller/DiffusionRefTableController.php @@ -66,18 +66,32 @@ final class DiffusionRefTableController extends DiffusionController { $type = idx($cache, 'type'); } - $identifier = idx($vcs, 'identifier'); - if ($identifier !== null) { - $identifier = DiffusionView::linkCommit( + $hash = idx($vcs, 'identifier'); + if ($hash !== null) { + $hash = DiffusionView::linkCommit( $repository, - $identifier); + $hash); } - $cache_identifier = idx($cache, 'identifier'); - if ($cache_identifier !== null) { - $cache_identifier = DiffusionView::linkCommit( + $cached_hash = idx($cache, 'identifier'); + if ($cached_hash !== null) { + $cache_hash = DiffusionView::linkCommit( $repository, - $cache_identifier); + $cached_hash); + } + + $closed = idx($vcs, 'closed', false); + if (!$vcs) { + $state = null; + } else { + $state = $closed ? pht('Closed') : pht('Open'); + } + + $cached_closed = idx($cache, 'closed', false); + if (!$cache) { + $cached_state = null; + } else { + $cached_state = $cached_closed ? pht('Closed') : pht('Open'); } $alternate = idx($vcs, 'alternate'); @@ -90,8 +104,10 @@ final class DiffusionRefTableController extends DiffusionController { $rows[] = array( $ref, $type, - $identifier, - $cache_identifier, + $hash, + $cached_hash, + $state, + $cached_state, $alternate, ); } @@ -102,8 +118,10 @@ final class DiffusionRefTableController extends DiffusionController { array( pht('Ref'), pht('Type'), - pht('Identifier'), - pht('Cached'), + pht('Hash'), + pht('Cached Hash'), + pht('State'), + pht('Cached State'), pht('Alternate'), )); diff --git a/src/applications/diffusion/query/lowlevel/DiffusionLowLevelResolveRefsQuery.php b/src/applications/diffusion/query/lowlevel/DiffusionLowLevelResolveRefsQuery.php index a187077832..66ecbb2f2c 100644 --- a/src/applications/diffusion/query/lowlevel/DiffusionLowLevelResolveRefsQuery.php +++ b/src/applications/diffusion/query/lowlevel/DiffusionLowLevelResolveRefsQuery.php @@ -140,15 +140,72 @@ final class DiffusionLowLevelResolveRefsQuery private function resolveMercurialRefs() { $repository = $this->getRepository(); + // First, pull all of the branch heads in the repository. Doing this in + // bulk is much faster than querying each individual head if we're + // checking even a small number of refs. $futures = array(); - foreach ($this->refs as $ref) { + $futures['all'] = $repository->getLocalCommandFuture( + 'log --template=%s --rev %s', + '{node} {branch}\\n', + hgsprintf('head()')); + $futures['open'] = $repository->getLocalCommandFuture( + 'log --template=%s --rev %s', + '{node} {branch}\\n', + hgsprintf('head() and not closed()')); + + + $map = array(); + foreach (new FutureIterator($futures) as $key => $future) { + list($stdout) = $future->resolvex(); + $lines = phutil_split_lines($stdout, $retain_endings = false); + foreach ($lines as $idx => $line) { + list($node, $branch) = explode(' ', $line, 2); + $map[$branch]['nodes'][] = $node; + if ($key == 'open') { + $map[$branch]['open'] = true; + } + } + } + + $results = array(); + $unresolved = $this->refs; + foreach ($unresolved as $key => $ref) { + if (!isset($map[$ref])) { + continue; + } + + $is_closed = !idx($map[$ref], 'open', false); + foreach ($map[$ref]['nodes'] as $node) { + $results[$ref][$node] = array( + 'type' => 'branch', + 'identifier' => $node, + 'closed' => $is_closed, + ); + } + + unset($unresolved[$key]); + } + + // Strip the node keys off the result list. + foreach ($results as $ref => $result_list) { + $results[$ref] = array_values($result_list); + } + + if (!$unresolved) { + return $results; + } + + // If we still have unresolved refs (which might be things like "tip"), + // try to resolve them individually. + + $futures = array(); + foreach ($unresolved as $ref) { $futures[$ref] = $repository->getLocalCommandFuture( 'log --template=%s --rev %s', '{node}', hgsprintf('%s', $ref)); } - $results = array(); foreach (new FutureIterator($futures) as $ref => $future) { try { list($stdout) = $future->resolvex();