2013-11-04 14:13:07 -08:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Resolves references (like short commit names, branch names, tag names, etc.)
|
|
|
|
* into canonical, stable commit identifiers. This query works for all
|
|
|
|
* repository types.
|
2015-01-23 13:31:17 -08:00
|
|
|
*
|
|
|
|
* This query will always resolve refs which can be resolved, but may need to
|
|
|
|
* perform VCS operations. A faster (but less complete) counterpart query is
|
|
|
|
* available in @{class:DiffusionCachedResolveRefsQuery}; that query can
|
|
|
|
* resolve most refs without VCS operations.
|
2013-11-04 14:13:07 -08:00
|
|
|
*/
|
|
|
|
final class DiffusionLowLevelResolveRefsQuery
|
|
|
|
extends DiffusionLowLevelQuery {
|
|
|
|
|
|
|
|
private $refs;
|
2015-04-27 03:51:53 -07:00
|
|
|
private $types;
|
2013-11-04 14:13:07 -08:00
|
|
|
|
|
|
|
public function withRefs(array $refs) {
|
|
|
|
$this->refs = $refs;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2015-04-27 03:51:53 -07:00
|
|
|
public function withTypes(array $types) {
|
|
|
|
$this->types = $types;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2015-01-16 06:56:32 +11:00
|
|
|
protected function executeQuery() {
|
2013-11-04 14:13:07 -08:00
|
|
|
if (!$this->refs) {
|
|
|
|
return array();
|
|
|
|
}
|
|
|
|
|
2016-05-10 07:13:44 -07:00
|
|
|
$repository = $this->getRepository();
|
|
|
|
if (!$repository->hasLocalWorkingCopy()) {
|
|
|
|
return array();
|
|
|
|
}
|
|
|
|
|
2013-11-04 14:13:07 -08:00
|
|
|
switch ($this->getRepository()->getVersionControlSystem()) {
|
|
|
|
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
|
|
|
|
$result = $this->resolveGitRefs();
|
|
|
|
break;
|
|
|
|
case PhabricatorRepositoryType::REPOSITORY_TYPE_MERCURIAL:
|
|
|
|
$result = $this->resolveMercurialRefs();
|
|
|
|
break;
|
|
|
|
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
|
|
|
|
$result = $this->resolveSubversionRefs();
|
|
|
|
break;
|
|
|
|
default:
|
2015-05-22 17:27:56 +10:00
|
|
|
throw new Exception(pht('Unsupported repository type!'));
|
2013-11-04 14:13:07 -08:00
|
|
|
}
|
|
|
|
|
2015-04-27 03:51:53 -07:00
|
|
|
if ($this->types !== null) {
|
|
|
|
$result = $this->filterRefsByType($result, $this->types);
|
|
|
|
}
|
|
|
|
|
2013-11-04 14:13:07 -08:00
|
|
|
return $result;
|
|
|
|
}
|
|
|
|
|
|
|
|
private function resolveGitRefs() {
|
|
|
|
$repository = $this->getRepository();
|
|
|
|
|
2015-04-29 13:21:12 -07:00
|
|
|
$unresolved = array_fuse($this->refs);
|
|
|
|
$results = array();
|
|
|
|
|
|
|
|
// First, resolve branches and tags.
|
|
|
|
$ref_map = id(new DiffusionLowLevelGitRefQuery())
|
|
|
|
->setRepository($repository)
|
Version clustered, observed repositories in a reasonable way (by largest discovered HEAD)
Summary:
Ref T4292. For hosted, clustered repositories we have a good way to increment the internal version of the repository: every time a user pushes something, we increment the version by 1.
We don't have a great way to do this for observed/remote repositories because when we `git fetch` we might get nothing, or we might get some changes, and we can't easily tell //what// changes we got.
For example, if we see that another node is at "version 97", and we do a fetch and see some changes, we don't know if we're in sync with them (i.e., also at "version 97") or ahead of them (at "version 98").
This implements a simple way to version an observed repository:
- Take the head of every branch/tag.
- Look them up.
- Pick the biggest internal ID number.
This will work //except// when branches are deleted, which could cause the version to go backward if the "biggest commit" is the one that was deleted. This should be OK, since it's rare and the effects are minor and the repository will "self-heal" on the next actual push.
Test Plan:
- Created an observed repository.
- Ran `bin/repository update` and observed a sensible version number appear in the version table.
- Pushed to the remote, did another update, saw a sensible update.
- Did an update with no push, saw no effect on version number.
- Toggled repository to hosted, saw the version reset.
- Simulated read traffic to out-of-sync node, saw it do a remote fetch.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4292
Differential Revision: https://secure.phabricator.com/D15986
2016-05-27 06:21:19 -07:00
|
|
|
->withRefTypes(
|
|
|
|
array(
|
|
|
|
PhabricatorRepositoryRefCursor::TYPE_BRANCH,
|
|
|
|
PhabricatorRepositoryRefCursor::TYPE_TAG,
|
|
|
|
))
|
2015-04-29 13:21:12 -07:00
|
|
|
->execute();
|
|
|
|
$ref_map = mgroup($ref_map, 'getShortName');
|
|
|
|
|
|
|
|
$tag_prefix = 'refs/tags/';
|
|
|
|
foreach ($unresolved as $ref) {
|
|
|
|
if (empty($ref_map[$ref])) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach ($ref_map[$ref] as $result) {
|
|
|
|
$fields = $result->getRawFields();
|
|
|
|
$objectname = idx($fields, 'refname');
|
|
|
|
if (!strncmp($objectname, $tag_prefix, strlen($tag_prefix))) {
|
|
|
|
$type = 'tag';
|
|
|
|
} else {
|
|
|
|
$type = 'branch';
|
|
|
|
}
|
|
|
|
|
|
|
|
$info = array(
|
|
|
|
'type' => $type,
|
|
|
|
'identifier' => $result->getCommitIdentifier(),
|
|
|
|
);
|
|
|
|
|
|
|
|
if ($type == 'tag') {
|
|
|
|
$alternate = idx($fields, 'objectname');
|
|
|
|
if ($alternate) {
|
|
|
|
$info['alternate'] = $alternate;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$results[$ref][] = $info;
|
|
|
|
}
|
|
|
|
|
|
|
|
unset($unresolved[$ref]);
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we resolved everything, we're done.
|
|
|
|
if (!$unresolved) {
|
|
|
|
return $results;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try to resolve anything else. This stuff either doesn't exist or is
|
|
|
|
// some ref like "HEAD^^^".
|
2013-11-04 14:13:07 -08:00
|
|
|
$future = $repository->getLocalCommandFuture('cat-file --batch-check');
|
2015-04-29 13:21:12 -07:00
|
|
|
$future->write(implode("\n", $unresolved));
|
2013-11-04 14:13:07 -08:00
|
|
|
list($stdout) = $future->resolvex();
|
|
|
|
|
|
|
|
$lines = explode("\n", rtrim($stdout, "\n"));
|
2015-04-29 13:21:12 -07:00
|
|
|
if (count($lines) !== count($unresolved)) {
|
2015-05-22 17:27:56 +10:00
|
|
|
throw new Exception(
|
|
|
|
pht(
|
|
|
|
'Unexpected line count from `%s`!',
|
|
|
|
'git cat-file'));
|
2013-11-04 14:13:07 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
$hits = array();
|
|
|
|
$tags = array();
|
|
|
|
|
2015-04-29 13:21:12 -07:00
|
|
|
$lines = array_combine($unresolved, $lines);
|
2013-11-04 14:13:07 -08:00
|
|
|
foreach ($lines as $ref => $line) {
|
|
|
|
$parts = explode(' ', $line);
|
|
|
|
if (count($parts) < 2) {
|
2015-05-22 17:27:56 +10:00
|
|
|
throw new Exception(
|
|
|
|
pht(
|
|
|
|
'Failed to parse `%s` output: %s',
|
|
|
|
'git cat-file',
|
|
|
|
$line));
|
2013-11-04 14:13:07 -08:00
|
|
|
}
|
|
|
|
list($identifier, $type) = $parts;
|
|
|
|
|
|
|
|
if ($type == 'missing') {
|
|
|
|
// This is either an ambiguous reference which resolves to several
|
|
|
|
// objects, or an invalid reference. For now, always treat it as
|
|
|
|
// invalid. It would be nice to resolve all possibilities for
|
|
|
|
// ambiguous references at some point, although the strategy for doing
|
|
|
|
// so isn't clear to me.
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch ($type) {
|
|
|
|
case 'commit':
|
|
|
|
break;
|
|
|
|
case 'tag':
|
|
|
|
$tags[] = $identifier;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
throw new Exception(
|
2015-05-22 17:27:56 +10:00
|
|
|
pht(
|
|
|
|
'Unexpected object type from `%s`: %s',
|
|
|
|
'git cat-file',
|
|
|
|
$line));
|
2013-11-04 14:13:07 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
$hits[] = array(
|
|
|
|
'ref' => $ref,
|
|
|
|
'type' => $type,
|
|
|
|
'identifier' => $identifier,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
$tag_map = array();
|
|
|
|
if ($tags) {
|
|
|
|
// If some of the refs were tags, just load every tag in order to figure
|
|
|
|
// out which commits they map to. This might be somewhat inefficient in
|
|
|
|
// repositories with a huge number of tags.
|
|
|
|
$tag_refs = id(new DiffusionLowLevelGitRefQuery())
|
|
|
|
->setRepository($repository)
|
2016-12-14 14:41:26 -05:00
|
|
|
->withRefTypes(
|
|
|
|
array(
|
|
|
|
PhabricatorRepositoryRefCursor::TYPE_TAG,
|
|
|
|
))
|
2013-11-04 14:13:07 -08:00
|
|
|
->executeQuery();
|
|
|
|
foreach ($tag_refs as $tag_ref) {
|
|
|
|
$tag_map[$tag_ref->getShortName()] = $tag_ref->getCommitIdentifier();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$results = array();
|
|
|
|
foreach ($hits as $hit) {
|
|
|
|
$type = $hit['type'];
|
|
|
|
$ref = $hit['ref'];
|
|
|
|
|
|
|
|
$alternate = null;
|
|
|
|
if ($type == 'tag') {
|
|
|
|
$alternate = $identifier;
|
|
|
|
$identifier = idx($tag_map, $ref);
|
|
|
|
if (!$identifier) {
|
2015-05-22 17:27:56 +10:00
|
|
|
throw new Exception(
|
|
|
|
pht(
|
|
|
|
"Failed to look up tag '%s'!",
|
|
|
|
$ref));
|
2013-11-04 14:13:07 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$result = array(
|
|
|
|
'type' => $type,
|
|
|
|
'identifier' => $identifier,
|
|
|
|
);
|
|
|
|
|
|
|
|
if ($alternate !== null) {
|
|
|
|
$result['alternate'] = $alternate;
|
|
|
|
}
|
|
|
|
|
|
|
|
$results[$ref][] = $result;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $results;
|
|
|
|
}
|
|
|
|
|
|
|
|
private function resolveMercurialRefs() {
|
|
|
|
$repository = $this->getRepository();
|
|
|
|
|
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
2015-04-27 03:50:20 -07:00
|
|
|
// 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.
|
2015-04-27 03:50:55 -07:00
|
|
|
$branches = id(new DiffusionLowLevelMercurialBranchesQuery())
|
|
|
|
->setRepository($repository)
|
|
|
|
->executeQuery();
|
|
|
|
|
|
|
|
$branches = mgroup($branches, 'getShortName');
|
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
2015-04-27 03:50:20 -07:00
|
|
|
|
|
|
|
$results = array();
|
|
|
|
$unresolved = $this->refs;
|
|
|
|
foreach ($unresolved as $key => $ref) {
|
2015-04-27 03:50:55 -07:00
|
|
|
if (empty($branches[$ref])) {
|
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
2015-04-27 03:50:20 -07:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2015-04-27 03:50:55 -07:00
|
|
|
foreach ($branches[$ref] as $branch) {
|
|
|
|
$fields = $branch->getRawFields();
|
|
|
|
|
|
|
|
$results[$ref][] = array(
|
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
2015-04-27 03:50:20 -07:00
|
|
|
'type' => 'branch',
|
2015-04-27 03:50:55 -07:00
|
|
|
'identifier' => $branch->getCommitIdentifier(),
|
|
|
|
'closed' => idx($fields, 'closed', false),
|
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
2015-04-27 03:50:20 -07:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
unset($unresolved[$key]);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!$unresolved) {
|
|
|
|
return $results;
|
|
|
|
}
|
|
|
|
|
Improve "refengine" performance for testing large numbers of Mercurial branches
Summary:
See PHI158. In the RefEngine, we test if any old branch positions have been removed from the repository. This is uncommon (but not impossible) in Mercurial, and corresponds to users deleting branches in Git.
Currently, we end up running `hg log` for each position, in parallel. Because of Python's large startup overhead, this can be resource intensive for repositories with a large number of branches.
We have to do this in the general case because the caller may be asking us to resolve `tip`, `newfeature`, `tip~3`, `9`, etc. However, in the specific case where the refs are 40-digit hashes, we can bulk resolve them if they exist, like this:
```
hg log ... --rev (abcd or def0 or ab12 or ...)
```
In the general case, we could probably do less of this than we currently do (instead of testing all old heads, we could prune the list by removing commits which we know are still pointed to by current heads) but that's a slightly more involved change and the effect here is already dramatic.
Test Plan:
Verified that CPU usage drops from ~110s -> ~0.9s:
Before:
```
epriestley@orbital ~/dev/phabricator $ time ./bin/repository refs nss
Updating refs in "nss"...
Done.
real 0m14.676s
user 1m24.714s
sys 0m21.645s
```
After:
```
epriestley@orbital ~/dev/phabricator $ time ./bin/repository refs nss
Updating refs in "nss"...
Done.
real 0m0.861s
user 0m0.882s
sys 0m0.213s
```
- Manually resolved `blue`, `tip`, `9`, etc., got expected results.
- Tried to resolve invalid hashes, got expected result (no resolution).
Reviewers: amckinley
Reviewed By: amckinley
Differential Revision: https://secure.phabricator.com/D18717
2017-10-20 10:15:07 -07:00
|
|
|
// If some of the refs look like hashes, try to bulk resolve them. This
|
|
|
|
// workflow happens via RefEngine and bulk resolution is dramatically
|
|
|
|
// faster than individual resolution. See PHI158.
|
|
|
|
|
|
|
|
$hashlike = array();
|
|
|
|
foreach ($unresolved as $key => $ref) {
|
|
|
|
if (preg_match('/^[a-f0-9]{40}\z/', $ref)) {
|
|
|
|
$hashlike[$key] = $ref;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (count($hashlike) > 1) {
|
|
|
|
$hashlike_map = array();
|
|
|
|
|
|
|
|
$hashlike_groups = array_chunk($hashlike, 64, true);
|
|
|
|
foreach ($hashlike_groups as $hashlike_group) {
|
|
|
|
$hashlike_arg = array();
|
|
|
|
foreach ($hashlike_group as $hashlike_ref) {
|
|
|
|
$hashlike_arg[] = hgsprintf('%s', $hashlike_ref);
|
|
|
|
}
|
|
|
|
$hashlike_arg = '('.implode(' or ', $hashlike_arg).')';
|
|
|
|
|
|
|
|
list($err, $refs) = $repository->execLocalCommand(
|
|
|
|
'log --template=%s --rev %s',
|
|
|
|
'{node}\n',
|
|
|
|
$hashlike_arg);
|
|
|
|
if ($err) {
|
|
|
|
// NOTE: If any ref fails to resolve, Mercurial will exit with an
|
|
|
|
// error. We just give up on the whole group and resolve it
|
|
|
|
// individually below. In theory, we could split it into subgroups
|
|
|
|
// but the pathway where this bulk resolution matters rarely tries
|
|
|
|
// to resolve missing refs (see PHI158).
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
$refs = phutil_split_lines($refs, false);
|
|
|
|
|
|
|
|
foreach ($refs as $ref) {
|
|
|
|
$hashlike_map[$ref] = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach ($unresolved as $key => $ref) {
|
|
|
|
if (!isset($hashlike_map[$ref])) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
$results[$ref][] = array(
|
|
|
|
'type' => 'commit',
|
|
|
|
'identifier' => $ref,
|
|
|
|
);
|
|
|
|
|
|
|
|
unset($unresolved[$key]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!$unresolved) {
|
|
|
|
return $results;
|
|
|
|
}
|
|
|
|
|
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
2015-04-27 03:50:20 -07:00
|
|
|
// If we still have unresolved refs (which might be things like "tip"),
|
|
|
|
// try to resolve them individually.
|
|
|
|
|
|
|
|
$futures = array();
|
|
|
|
foreach ($unresolved as $ref) {
|
2013-11-04 14:13:07 -08:00
|
|
|
$futures[$ref] = $repository->getLocalCommandFuture(
|
|
|
|
'log --template=%s --rev %s',
|
|
|
|
'{node}',
|
|
|
|
hgsprintf('%s', $ref));
|
|
|
|
}
|
|
|
|
|
2014-12-30 23:13:38 +11:00
|
|
|
foreach (new FutureIterator($futures) as $ref => $future) {
|
2013-11-04 14:13:07 -08:00
|
|
|
try {
|
|
|
|
list($stdout) = $future->resolvex();
|
|
|
|
} catch (CommandException $ex) {
|
2017-02-18 09:24:56 +00:00
|
|
|
if (preg_match('/ambiguous identifier/', $ex->getStderr())) {
|
2013-11-04 14:13:07 -08:00
|
|
|
// This indicates that the ref ambiguously matched several things.
|
|
|
|
// Eventually, it would be nice to return all of them, but it is
|
|
|
|
// unclear how to best do that. For now, treat it as a miss instead.
|
|
|
|
continue;
|
|
|
|
}
|
2017-02-18 09:24:56 +00:00
|
|
|
if (preg_match('/unknown revision/', $ex->getStderr())) {
|
2015-04-28 08:56:16 -07:00
|
|
|
// No matches for this ref.
|
|
|
|
continue;
|
|
|
|
}
|
2013-11-04 14:13:07 -08:00
|
|
|
throw $ex;
|
|
|
|
}
|
|
|
|
|
|
|
|
// It doesn't look like we can figure out the type (commit/branch/rev)
|
|
|
|
// from this output very easily. For now, just call everything a commit.
|
|
|
|
$type = 'commit';
|
|
|
|
|
|
|
|
$results[$ref][] = array(
|
|
|
|
'type' => $type,
|
|
|
|
'identifier' => trim($stdout),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $results;
|
|
|
|
}
|
|
|
|
|
|
|
|
private function resolveSubversionRefs() {
|
2015-01-23 13:31:17 -08:00
|
|
|
// We don't have any VCS logic for Subversion, so just use the cached
|
|
|
|
// query.
|
|
|
|
return id(new DiffusionCachedResolveRefsQuery())
|
|
|
|
->setRepository($this->getRepository())
|
|
|
|
->withRefs($this->refs)
|
|
|
|
->execute();
|
2013-11-04 14:13:07 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|