mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-19 12:00:55 +01:00
Improve low-level branch resolution in Mercurial
Summary: Ref T7100. Ref T7108. Ref T6160. Several issues: - High load for mercurial repositories with huge numbers of branches (T7108). - In Mercurial, we resolve refs individually (one `hg` call per ref). - Each repository update also updates all refs, which requires resolving all of them. - For repositories with a huge number of branches, - We don't distinguish between closed branches (a Mercurial-only concept) and open branches (T6160). - In Git, when a branch is merged, it ceases to exist. - In Mercurial, when a branch is merged, it still exists, it's just "closed". Normally, no one cares about these branches. - In the low-level query, correctly identify which refs we resolve as branches. - In the low-level query, correctly mark closed branches as closed. - This marginally improves ref handling in general (see T7100). Test Plan: {F384366} {F384367} Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T6160, T7108, T7100 Differential Revision: https://secure.phabricator.com/D12548
This commit is contained in:
parent
7f43cde82d
commit
21c4aeb032
2 changed files with 89 additions and 14 deletions
|
@ -66,18 +66,32 @@ final class DiffusionRefTableController extends DiffusionController {
|
||||||
$type = idx($cache, 'type');
|
$type = idx($cache, 'type');
|
||||||
}
|
}
|
||||||
|
|
||||||
$identifier = idx($vcs, 'identifier');
|
$hash = idx($vcs, 'identifier');
|
||||||
if ($identifier !== null) {
|
if ($hash !== null) {
|
||||||
$identifier = DiffusionView::linkCommit(
|
$hash = DiffusionView::linkCommit(
|
||||||
$repository,
|
$repository,
|
||||||
$identifier);
|
$hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
$cache_identifier = idx($cache, 'identifier');
|
$cached_hash = idx($cache, 'identifier');
|
||||||
if ($cache_identifier !== null) {
|
if ($cached_hash !== null) {
|
||||||
$cache_identifier = DiffusionView::linkCommit(
|
$cache_hash = DiffusionView::linkCommit(
|
||||||
$repository,
|
$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');
|
$alternate = idx($vcs, 'alternate');
|
||||||
|
@ -90,8 +104,10 @@ final class DiffusionRefTableController extends DiffusionController {
|
||||||
$rows[] = array(
|
$rows[] = array(
|
||||||
$ref,
|
$ref,
|
||||||
$type,
|
$type,
|
||||||
$identifier,
|
$hash,
|
||||||
$cache_identifier,
|
$cached_hash,
|
||||||
|
$state,
|
||||||
|
$cached_state,
|
||||||
$alternate,
|
$alternate,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -102,8 +118,10 @@ final class DiffusionRefTableController extends DiffusionController {
|
||||||
array(
|
array(
|
||||||
pht('Ref'),
|
pht('Ref'),
|
||||||
pht('Type'),
|
pht('Type'),
|
||||||
pht('Identifier'),
|
pht('Hash'),
|
||||||
pht('Cached'),
|
pht('Cached Hash'),
|
||||||
|
pht('State'),
|
||||||
|
pht('Cached State'),
|
||||||
pht('Alternate'),
|
pht('Alternate'),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
|
@ -140,15 +140,72 @@ final class DiffusionLowLevelResolveRefsQuery
|
||||||
private function resolveMercurialRefs() {
|
private function resolveMercurialRefs() {
|
||||||
$repository = $this->getRepository();
|
$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();
|
$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(
|
$futures[$ref] = $repository->getLocalCommandFuture(
|
||||||
'log --template=%s --rev %s',
|
'log --template=%s --rev %s',
|
||||||
'{node}',
|
'{node}',
|
||||||
hgsprintf('%s', $ref));
|
hgsprintf('%s', $ref));
|
||||||
}
|
}
|
||||||
|
|
||||||
$results = array();
|
|
||||||
foreach (new FutureIterator($futures) as $ref => $future) {
|
foreach (new FutureIterator($futures) as $ref => $future) {
|
||||||
try {
|
try {
|
||||||
list($stdout) = $future->resolvex();
|
list($stdout) = $future->resolvex();
|
||||||
|
|
Loading…
Reference in a new issue