mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-12-22 21:40:54 +01:00
Add a "CommitSymbolRef" for resolving symbolic commits into stable commit hashes
Summary: Ref T13490. Frequently, we know the symbolic name of a commit (like "master") but need the immutable identifier for it (the commit hash). Provide a Ref and Query for doing this lookup. Test Plan: Ran `arc inspect symbol(...)` with various symbols, saw appropriate resolutions, nulls, or errors. Maniphest Tasks: T13490 Differential Revision: https://secure.phabricator.com/D21090
This commit is contained in:
parent
92be6df0eb
commit
4cc05c377d
5 changed files with 187 additions and 0 deletions
|
@ -104,6 +104,8 @@ phutil_register_library_map(array(
|
|||
'ArcanistCommentStyleXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistCommentStyleXHPASTLinterRuleTestCase.php',
|
||||
'ArcanistCommitRef' => 'ref/ArcanistCommitRef.php',
|
||||
'ArcanistCommitRefInspector' => 'inspector/ArcanistCommitRefInspector.php',
|
||||
'ArcanistCommitSymbolRef' => 'ref/commitsymbol/ArcanistCommitSymbolRef.php',
|
||||
'ArcanistCommitSymbolRefInspector' => 'ref/commitsymbol/ArcanistCommitSymbolRefInspector.php',
|
||||
'ArcanistCommitUpstreamHardpointQuery' => 'query/ArcanistCommitUpstreamHardpointQuery.php',
|
||||
'ArcanistCommitWorkflow' => 'workflow/ArcanistCommitWorkflow.php',
|
||||
'ArcanistCompilerLintRenderer' => 'lint/renderer/ArcanistCompilerLintRenderer.php',
|
||||
|
@ -206,6 +208,7 @@ phutil_register_library_map(array(
|
|||
'ArcanistGetConfigWorkflow' => 'workflow/ArcanistGetConfigWorkflow.php',
|
||||
'ArcanistGitAPI' => 'repository/api/ArcanistGitAPI.php',
|
||||
'ArcanistGitCommitMessageHardpointQuery' => 'query/ArcanistGitCommitMessageHardpointQuery.php',
|
||||
'ArcanistGitCommitSymbolCommitHardpointQuery' => 'ref/commitsymbol/ArcanistGitCommitSymbolCommitHardpointQuery.php',
|
||||
'ArcanistGitLandEngine' => 'land/ArcanistGitLandEngine.php',
|
||||
'ArcanistGitUpstreamPath' => 'repository/api/ArcanistGitUpstreamPath.php',
|
||||
'ArcanistGitWorkingCopy' => 'workingcopy/ArcanistGitWorkingCopy.php',
|
||||
|
@ -1066,6 +1069,8 @@ phutil_register_library_map(array(
|
|||
'ArcanistCommentStyleXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
|
||||
'ArcanistCommitRef' => 'ArcanistRef',
|
||||
'ArcanistCommitRefInspector' => 'ArcanistRefInspector',
|
||||
'ArcanistCommitSymbolRef' => 'ArcanistRef',
|
||||
'ArcanistCommitSymbolRefInspector' => 'ArcanistRefInspector',
|
||||
'ArcanistCommitUpstreamHardpointQuery' => 'ArcanistWorkflowHardpointQuery',
|
||||
'ArcanistCommitWorkflow' => 'ArcanistWorkflow',
|
||||
'ArcanistCompilerLintRenderer' => 'ArcanistLintRenderer',
|
||||
|
@ -1168,6 +1173,7 @@ phutil_register_library_map(array(
|
|||
'ArcanistGetConfigWorkflow' => 'ArcanistWorkflow',
|
||||
'ArcanistGitAPI' => 'ArcanistRepositoryAPI',
|
||||
'ArcanistGitCommitMessageHardpointQuery' => 'ArcanistWorkflowGitHardpointQuery',
|
||||
'ArcanistGitCommitSymbolCommitHardpointQuery' => 'ArcanistWorkflowGitHardpointQuery',
|
||||
'ArcanistGitLandEngine' => 'ArcanistLandEngine',
|
||||
'ArcanistGitUpstreamPath' => 'Phobject',
|
||||
'ArcanistGitWorkingCopy' => 'ArcanistWorkingCopy',
|
||||
|
|
37
src/ref/commitsymbol/ArcanistCommitSymbolRef.php
Normal file
37
src/ref/commitsymbol/ArcanistCommitSymbolRef.php
Normal file
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
final class ArcanistCommitSymbolRef
|
||||
extends ArcanistRef {
|
||||
|
||||
private $symbol;
|
||||
|
||||
const HARDPOINT_COMMIT = 'ref.commit-symbol';
|
||||
|
||||
public function getRefDisplayName() {
|
||||
return pht('Commit Symbol "%s"', $this->getSymbol());
|
||||
}
|
||||
|
||||
protected function newHardpoints() {
|
||||
return array(
|
||||
$this->newHardpoint(self::HARDPOINT_COMMIT),
|
||||
);
|
||||
}
|
||||
|
||||
public function setSymbol($symbol) {
|
||||
$this->symbol = $symbol;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSymbol() {
|
||||
return $this->symbol;
|
||||
}
|
||||
|
||||
public function attachCommit(ArcanistCommitRef $commit) {
|
||||
return $this->attachHardpoint(self::HARDPOINT_COMMIT, $commit);
|
||||
}
|
||||
|
||||
public function getCommit() {
|
||||
return $this->getHardpoint(self::HARDPOINT_COMMIT);
|
||||
}
|
||||
|
||||
}
|
22
src/ref/commitsymbol/ArcanistCommitSymbolRefInspector.php
Normal file
22
src/ref/commitsymbol/ArcanistCommitSymbolRefInspector.php
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
final class ArcanistCommitSymbolRefInspector
|
||||
extends ArcanistRefInspector {
|
||||
|
||||
public function getInspectFunctionName() {
|
||||
return 'symbol';
|
||||
}
|
||||
|
||||
public function newInspectRef(array $argv) {
|
||||
if (count($argv) !== 1) {
|
||||
throw new PhutilArgumentUsageException(
|
||||
pht(
|
||||
'Expected exactly one argument to "symbol(...)" with a '.
|
||||
'commit symbol.'));
|
||||
}
|
||||
|
||||
return id(new ArcanistCommitSymbolRef())
|
||||
->setSymbol($argv[0]);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
<?php
|
||||
|
||||
final class ArcanistGitCommitSymbolCommitHardpointQuery
|
||||
extends ArcanistWorkflowGitHardpointQuery {
|
||||
|
||||
public function getHardpoints() {
|
||||
return array(
|
||||
ArcanistCommitSymbolRef::HARDPOINT_COMMIT,
|
||||
);
|
||||
}
|
||||
|
||||
protected function canLoadRef(ArcanistRef $ref) {
|
||||
return ($ref instanceof ArcanistCommitSymbolRef);
|
||||
}
|
||||
|
||||
public function loadHardpoint(array $refs, $hardpoint) {
|
||||
$symbol_map = array();
|
||||
foreach ($refs as $key => $ref) {
|
||||
$symbol_map[$key] = $ref->getSymbol();
|
||||
}
|
||||
|
||||
$symbol_set = array_fuse($symbol_map);
|
||||
foreach ($symbol_set as $symbol) {
|
||||
$this->validateSymbol($symbol);
|
||||
}
|
||||
|
||||
$api = $this->getRepositoryAPI();
|
||||
|
||||
$symbol_list = implode("\n", $symbol_set);
|
||||
|
||||
$future = $api->newFuture('cat-file --batch-check --')
|
||||
->write($symbol_list);
|
||||
|
||||
list($stdout) = (yield $this->yieldFuture($future));
|
||||
|
||||
$lines = phutil_split_lines($stdout, $retain_endings = false);
|
||||
|
||||
if (count($lines) !== count($symbol_set)) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'Execution of "git cat-file --batch-check" emitted an unexpected '.
|
||||
'number of lines, expected %s but got %s.',
|
||||
phutil_count($symbol_set),
|
||||
phutil_count($lines)));
|
||||
}
|
||||
|
||||
$hash_map = array();
|
||||
|
||||
$pairs = array_combine($symbol_set, $lines);
|
||||
foreach ($pairs as $symbol => $line) {
|
||||
$parts = explode(' ', $line, 3);
|
||||
|
||||
if (count($parts) < 2) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'Execution of "git cat-file --batch-check" emitted an '.
|
||||
'unexpected line ("%s").',
|
||||
$line));
|
||||
}
|
||||
|
||||
list($hash, $type) = $parts;
|
||||
|
||||
// NOTE: For now, symbols which map to tags (which, in turn, map to
|
||||
// commits) are ignored here.
|
||||
|
||||
if ($type !== 'commit') {
|
||||
$hash_map[$symbol] = null;
|
||||
continue;
|
||||
}
|
||||
|
||||
$hash_map[$symbol] = $hash;
|
||||
}
|
||||
|
||||
$results = array();
|
||||
foreach ($symbol_map as $key => $symbol) {
|
||||
$results[$key] = $hash_map[$symbol];
|
||||
}
|
||||
|
||||
yield $this->yieldMap($results);
|
||||
}
|
||||
|
||||
private function validateSymbol($symbol) {
|
||||
if (strpos($symbol, "\n") !== false) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'Commit symbol "%s" contains a newline. This is not a valid '.
|
||||
'character in a Git commit symbol.',
|
||||
addcslashes($symbol, "\\\n")));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -673,6 +673,36 @@ abstract class ArcanistRepositoryAPI extends Phobject {
|
|||
return new ArcanistBranchRef();
|
||||
}
|
||||
|
||||
final public function getCurrentCommitRef() {
|
||||
$commit_hash = $this->newCurrentCommitHash();
|
||||
return $this->newCommitRef()
|
||||
->setCommitHash($commit_hash);
|
||||
}
|
||||
|
||||
protected function newCurrentCommitRef() {
|
||||
$commit_hash = $this->newCurrentCommitHash();
|
||||
return $this->newCommitRefForSymbol($commit_hash);
|
||||
}
|
||||
|
||||
protected function newCommitRefForSymbol() {
|
||||
throw new ArcanistCapabilityNotSupportedException($this);
|
||||
}
|
||||
|
||||
protected function newCurrentCommitHash() {
|
||||
throw new ArcanistCapabilityNotSupportedException($this);
|
||||
}
|
||||
|
||||
final public function getCurrentWorkingCopyStateRef() {
|
||||
return $this->newCurrentWorkingCopyStateRef();
|
||||
}
|
||||
|
||||
protected function newCurrentWorkingCopyStateRef() {
|
||||
$commit_ref = $this->getCurrentCommitRef();
|
||||
|
||||
return id(new ArcanistWorkingCopyStateRef())
|
||||
->setCommitRef($commit_ref);
|
||||
}
|
||||
|
||||
final public function newFuture($pattern /* , ... */) {
|
||||
$args = func_get_args();
|
||||
return $this->buildLocalFuture($args)
|
||||
|
|
Loading…
Reference in a new issue