mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-11-29 10:12:41 +01:00
Implement a revision resolver for arc browse <commit>
Summary: Ref T10895. This allows `arc browse <commit name>` to resolve to a revision, if an associated open revision exists. Test Plan: Ran `arc browse` with various arguments. Reviewers: chad Reviewed By: chad Maniphest Tasks: T10895 Differential Revision: https://secure.phabricator.com/D16933
This commit is contained in:
parent
d00de495bc
commit
84857e4890
8 changed files with 166 additions and 26 deletions
|
@ -47,6 +47,7 @@ phutil_register_library_map(array(
|
|||
'ArcanistBrowseObjectNameURIHardpointLoader' => 'browse/loader/ArcanistBrowseObjectNameURIHardpointLoader.php',
|
||||
'ArcanistBrowsePathURIHardpointLoader' => 'browse/loader/ArcanistBrowsePathURIHardpointLoader.php',
|
||||
'ArcanistBrowseRef' => 'browse/ref/ArcanistBrowseRef.php',
|
||||
'ArcanistBrowseRevisionURIHardpointLoader' => 'browse/loader/ArcanistBrowseRevisionURIHardpointLoader.php',
|
||||
'ArcanistBrowseURIHardpointLoader' => 'browse/loader/ArcanistBrowseURIHardpointLoader.php',
|
||||
'ArcanistBrowseURIRef' => 'browse/ref/ArcanistBrowseURIRef.php',
|
||||
'ArcanistBrowseWorkflow' => 'browse/workflow/ArcanistBrowseWorkflow.php',
|
||||
|
@ -168,6 +169,7 @@ phutil_register_library_map(array(
|
|||
'ArcanistGeneratedLinterTestCase' => 'lint/linter/__tests__/ArcanistGeneratedLinterTestCase.php',
|
||||
'ArcanistGetConfigWorkflow' => 'workflow/ArcanistGetConfigWorkflow.php',
|
||||
'ArcanistGitAPI' => 'repository/api/ArcanistGitAPI.php',
|
||||
'ArcanistGitCommitMessageHardpointLoader' => 'loader/ArcanistGitCommitMessageHardpointLoader.php',
|
||||
'ArcanistGitHardpointLoader' => 'loader/ArcanistGitHardpointLoader.php',
|
||||
'ArcanistGitLandEngine' => 'land/ArcanistGitLandEngine.php',
|
||||
'ArcanistGitRevisionHardpointLoader' => 'loader/ArcanistGitRevisionHardpointLoader.php',
|
||||
|
@ -487,6 +489,7 @@ phutil_register_library_map(array(
|
|||
'ArcanistBrowseObjectNameURIHardpointLoader' => 'ArcanistBrowseURIHardpointLoader',
|
||||
'ArcanistBrowsePathURIHardpointLoader' => 'ArcanistBrowseURIHardpointLoader',
|
||||
'ArcanistBrowseRef' => 'ArcanistRef',
|
||||
'ArcanistBrowseRevisionURIHardpointLoader' => 'ArcanistBrowseURIHardpointLoader',
|
||||
'ArcanistBrowseURIHardpointLoader' => 'ArcanistHardpointLoader',
|
||||
'ArcanistBrowseURIRef' => 'ArcanistRef',
|
||||
'ArcanistBrowseWorkflow' => 'ArcanistWorkflow',
|
||||
|
@ -608,6 +611,7 @@ phutil_register_library_map(array(
|
|||
'ArcanistGeneratedLinterTestCase' => 'ArcanistLinterTestCase',
|
||||
'ArcanistGetConfigWorkflow' => 'ArcanistWorkflow',
|
||||
'ArcanistGitAPI' => 'ArcanistRepositoryAPI',
|
||||
'ArcanistGitCommitMessageHardpointLoader' => 'ArcanistGitHardpointLoader',
|
||||
'ArcanistGitHardpointLoader' => 'ArcanistHardpointLoader',
|
||||
'ArcanistGitLandEngine' => 'ArcanistLandEngine',
|
||||
'ArcanistGitRevisionHardpointLoader' => 'ArcanistGitHardpointLoader',
|
||||
|
|
|
@ -33,9 +33,6 @@ final class ArcanistBrowseCommitHardpointLoader
|
|||
|
||||
$commit_map = array();
|
||||
foreach ($refs as $key => $ref) {
|
||||
$is_commit = $ref->hasType(
|
||||
ArcanistBrowseCommitURIHardpointLoader::BROWSETYPE);
|
||||
|
||||
$token = $ref->getToken();
|
||||
|
||||
if ($token === '.') {
|
||||
|
@ -44,14 +41,16 @@ final class ArcanistBrowseCommitHardpointLoader
|
|||
continue;
|
||||
}
|
||||
|
||||
// Always resolve the empty token; top-level loaders filter out
|
||||
// irrelevant tokens before this stage.
|
||||
if ($token === null) {
|
||||
if ($is_commit) {
|
||||
$token = $api->getHeadCommit();
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
$token = $api->getHeadCommit();
|
||||
}
|
||||
|
||||
// TODO: We should pull a full commit ref out of the API as soon as it
|
||||
// is able to provide them. In particular, we currently miss Git tree
|
||||
// hashes which reduces the accuracy of lookups.
|
||||
|
||||
try {
|
||||
$commit = $api->getCanonicalRevisionName($token);
|
||||
if ($commit) {
|
||||
|
|
|
@ -47,7 +47,6 @@ final class ArcanistBrowseCommitURIHardpointLoader
|
|||
}
|
||||
|
||||
$refs = $this->getRefsWithSupportedTypes($refs);
|
||||
|
||||
if (!$refs) {
|
||||
return array();
|
||||
}
|
||||
|
@ -80,7 +79,7 @@ final class ArcanistBrowseCommitURIHardpointLoader
|
|||
$uri = $commit_ref->getURI();
|
||||
if ($uri !== null) {
|
||||
$results[$key][] = id(new ArcanistBrowseURIRef())
|
||||
->setURI()
|
||||
->setURI($uri)
|
||||
->setType(self::BROWSETYPE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
<?php
|
||||
|
||||
final class ArcanistBrowseRevisionURIHardpointLoader
|
||||
extends ArcanistBrowseURIHardpointLoader {
|
||||
|
||||
const LOADERKEY = 'browse.uri.revision';
|
||||
const BROWSETYPE = 'revision';
|
||||
|
||||
public function loadHardpoints(array $refs, $hardpoint) {
|
||||
$query = $this->getQuery();
|
||||
|
||||
$working_ref = $query->getWorkingCopyRef();
|
||||
if (!$working_ref) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$repository_ref = $query->getRepositoryRef();
|
||||
if (!$repository_ref) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$refs = $this->getRefsWithSupportedTypes($refs);
|
||||
if (!$refs) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$this->newQuery($refs)
|
||||
->needHardpoints(
|
||||
array(
|
||||
'commitRefs',
|
||||
))
|
||||
->execute();
|
||||
|
||||
$states = array();
|
||||
$map = array();
|
||||
foreach ($refs as $key => $ref) {
|
||||
foreach ($ref->getCommitRefs() as $commit_ref) {
|
||||
$hash = $commit_ref->getCommitHash();
|
||||
$states[$hash] = id(clone $working_ref)
|
||||
->setCommitRef($commit_ref);
|
||||
$map[$hash][] = $key;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$states) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$this->newQuery($states)
|
||||
->needHardpoints(
|
||||
array(
|
||||
'revisionRefs',
|
||||
))
|
||||
->execute();
|
||||
|
||||
$results = array();
|
||||
foreach ($states as $hash => $state) {
|
||||
foreach ($state->getRevisionRefs() as $revision) {
|
||||
if ($revision->isClosed()) {
|
||||
// Don't resolve closed revisions.
|
||||
continue;
|
||||
}
|
||||
|
||||
$uri = $revision->getURI();
|
||||
|
||||
foreach ($map[$hash] as $key) {
|
||||
$results[$key][] = id(new ArcanistBrowseURIRef())
|
||||
->setURI($uri)
|
||||
->setType(self::BROWSETYPE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -68,13 +68,6 @@ EOTEXT
|
|||
$console = PhutilConsole::getConsole();
|
||||
|
||||
$targets = $this->getArgument('targets');
|
||||
if (!$targets) {
|
||||
throw new ArcanistUsageException(
|
||||
pht(
|
||||
'Specify one or more paths or objects to browse. Use the '.
|
||||
'command "%s" if you want to browse this directory.',
|
||||
'arc browse .'));
|
||||
}
|
||||
$targets = array_fuse($targets);
|
||||
|
||||
if (!$targets) {
|
||||
|
@ -222,11 +215,19 @@ EOTEXT
|
|||
// If anything failed to resolve, this is also an error.
|
||||
if ($zero_hits) {
|
||||
foreach ($zero_hits as $ref) {
|
||||
echo tsprintf(
|
||||
"%s\n",
|
||||
pht(
|
||||
'Unable to resolve argument "%s".',
|
||||
$ref->getToken()));
|
||||
$token = $ref->getToken();
|
||||
if ($token === null) {
|
||||
echo tsprintf(
|
||||
"%s\n",
|
||||
pht(
|
||||
'Unable to resolve default browse target.'));
|
||||
} else {
|
||||
echo tsprintf(
|
||||
"%s\n",
|
||||
pht(
|
||||
'Unable to resolve argument "%s".',
|
||||
$ref->getToken()));
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($loaders as $loader) {
|
||||
|
|
41
src/loader/ArcanistGitCommitMessageHardpointLoader.php
Normal file
41
src/loader/ArcanistGitCommitMessageHardpointLoader.php
Normal file
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
final class ArcanistGitCommitMessageHardpointLoader
|
||||
extends ArcanistGitHardpointLoader {
|
||||
|
||||
const LOADERKEY = 'git.commit.message';
|
||||
|
||||
public function canLoadRef(ArcanistRef $ref) {
|
||||
return ($ref instanceof ArcanistCommitRef);
|
||||
}
|
||||
|
||||
public function canLoadHardpoint(ArcanistRef $ref, $hardpoint) {
|
||||
return ($hardpoint == 'message');
|
||||
}
|
||||
|
||||
public function loadHardpoints(array $refs, $hardpoint) {
|
||||
$api = $this->getQuery()->getRepositoryAPI();
|
||||
|
||||
|
||||
$futures = array();
|
||||
foreach ($refs as $ref_key => $ref) {
|
||||
$hash = $ref->getCommitHash();
|
||||
|
||||
$futures[$ref_key] = $api->execFutureLocal(
|
||||
'log -n1 --format=%C %s --',
|
||||
'%s%n%n%b',
|
||||
$hash);
|
||||
}
|
||||
|
||||
$iterator = $this->newFutureIterator($futures);
|
||||
|
||||
$results = array();
|
||||
foreach ($iterator as $ref_key => $future) {
|
||||
list($stdout) = $future->resolvex();
|
||||
$results[$ref_key] = $stdout;
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
}
|
|
@ -33,10 +33,12 @@ final class ArcanistGitRevisionHardpointLoader
|
|||
$commit->getCommitHash(),
|
||||
);
|
||||
|
||||
$commit_hashes[] = array(
|
||||
'gttr',
|
||||
$commit->getTreeHash(),
|
||||
);
|
||||
if ($commit->getTreeHash()) {
|
||||
$commit_hashes[] = array(
|
||||
'gttr',
|
||||
$commit->getTreeHash(),
|
||||
);
|
||||
}
|
||||
|
||||
foreach ($commit_hashes as $hash) {
|
||||
$hashes[] = $hash;
|
||||
|
|
|
@ -28,6 +28,22 @@ final class ArcanistRevisionRef
|
|||
return idx($this->parameters, 'statusName');
|
||||
}
|
||||
|
||||
public function isClosed() {
|
||||
// TODO: This should use sensible constants, not English language
|
||||
// display text.
|
||||
switch ($this->getStatusDisplayName()) {
|
||||
case 'Abandoned':
|
||||
case 'Closed':
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getURI() {
|
||||
return idx($this->parameters, 'uri');
|
||||
}
|
||||
|
||||
public function getFullName() {
|
||||
return pht('%s: %s', $this->getMonogram(), $this->getName());
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue