1
0
Fork 0
mirror of https://we.phorge.it/source/arcanist.git synced 2024-11-25 16:22:42 +01:00

Bring a "pro" WorkingCopyState ref to "master"

Summary:
Ref T11968. Continue bringing modern yield-based hardpoint code into "master" in the parallel "Pro" classtree.

Adds "working-copy(commit-hash)" as an inspectable ref.

Test Plan: Inspected working copy refs, saw them resolve revisions by commit hash and commit message.

Maniphest Tasks: T11968

Differential Revision: https://secure.phabricator.com/D21079
This commit is contained in:
epriestley 2020-04-10 05:28:55 -07:00
parent adea2550f5
commit 8bb81217d5
11 changed files with 335 additions and 21 deletions

View file

@ -213,6 +213,7 @@ phutil_register_library_map(array(
'ArcanistGitRevisionHardpointLoader' => 'loader/ArcanistGitRevisionHardpointLoader.php',
'ArcanistGitUpstreamPath' => 'repository/api/ArcanistGitUpstreamPath.php',
'ArcanistGitWorkingCopy' => 'workingcopy/ArcanistGitWorkingCopy.php',
'ArcanistGitWorkingCopyRevisionHardpointQuery' => 'query/ArcanistGitWorkingCopyRevisionHardpointQuery.php',
'ArcanistGlobalVariableXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistGlobalVariableXHPASTLinterRule.php',
'ArcanistGlobalVariableXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistGlobalVariableXHPASTLinterRuleTestCase.php',
'ArcanistGoLintLinter' => 'lint/linter/ArcanistGoLintLinter.php',
@ -320,6 +321,7 @@ phutil_register_library_map(array(
'ArcanistMergeConflictLinter' => 'lint/linter/ArcanistMergeConflictLinter.php',
'ArcanistMergeConflictLinterTestCase' => 'lint/linter/__tests__/ArcanistMergeConflictLinterTestCase.php',
'ArcanistMessageRevisionHardpointLoader' => 'loader/ArcanistMessageRevisionHardpointLoader.php',
'ArcanistMessageRevisionHardpointQuery' => 'query/ArcanistMessageRevisionHardpointQuery.php',
'ArcanistMissingArgumentTerminatorException' => 'exception/ArcanistMissingArgumentTerminatorException.php',
'ArcanistMissingLinterException' => 'lint/linter/exception/ArcanistMissingLinterException.php',
'ArcanistModifierOrderingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistModifierOrderingXHPASTLinterRule.php',
@ -340,6 +342,7 @@ phutil_register_library_map(array(
'ArcanistNoParentScopeXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistNoParentScopeXHPASTLinterRuleTestCase.php',
'ArcanistNoURIConduitException' => 'conduit/ArcanistNoURIConduitException.php',
'ArcanistNoneLintRenderer' => 'lint/renderer/ArcanistNoneLintRenderer.php',
'ArcanistObjectListHardpoint' => 'hardpoint/ArcanistObjectListHardpoint.php',
'ArcanistObjectOperatorSpacingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistObjectOperatorSpacingXHPASTLinterRule.php',
'ArcanistObjectOperatorSpacingXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistObjectOperatorSpacingXHPASTLinterRuleTestCase.php',
'ArcanistPEP8Linter' => 'lint/linter/ArcanistPEP8Linter.php',
@ -403,6 +406,7 @@ phutil_register_library_map(array(
'ArcanistReusedIteratorXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistReusedIteratorXHPASTLinterRuleTestCase.php',
'ArcanistRevertWorkflow' => 'workflow/ArcanistRevertWorkflow.php',
'ArcanistRevisionRef' => 'ref/ArcanistRevisionRef.php',
'ArcanistRevisionRefPro' => 'ref/ArcanistRevisionRefPro.php',
'ArcanistRevisionRefSource' => 'ref/ArcanistRevisionRefSource.php',
'ArcanistRuboCopLinter' => 'lint/linter/ArcanistRuboCopLinter.php',
'ArcanistRuboCopLinterTestCase' => 'lint/linter/__tests__/ArcanistRuboCopLinterTestCase.php',
@ -498,6 +502,7 @@ phutil_register_library_map(array(
'ArcanistWildConfigOption' => 'config/option/ArcanistWildConfigOption.php',
'ArcanistWorkflow' => 'workflow/ArcanistWorkflow.php',
'ArcanistWorkflowArgument' => 'toolset/ArcanistWorkflowArgument.php',
'ArcanistWorkflowGitHardpointQuery' => 'query/ArcanistWorkflowGitHardpointQuery.php',
'ArcanistWorkflowHardpointQuery' => 'toolset/query/ArcanistWorkflowHardpointQuery.php',
'ArcanistWorkflowInformation' => 'toolset/ArcanistWorkflowInformation.php',
'ArcanistWorkingCopy' => 'workingcopy/ArcanistWorkingCopy.php',
@ -506,6 +511,7 @@ phutil_register_library_map(array(
'ArcanistWorkingCopyIdentity' => 'workingcopyidentity/ArcanistWorkingCopyIdentity.php',
'ArcanistWorkingCopyPath' => 'workingcopy/ArcanistWorkingCopyPath.php',
'ArcanistWorkingCopyStateRef' => 'ref/ArcanistWorkingCopyStateRef.php',
'ArcanistWorkingCopyStateRefInspector' => 'inspector/ArcanistWorkingCopyStateRefInspector.php',
'ArcanistWorkingCopyStateRefPro' => 'ref/ArcanistWorkingCopyStateRefPro.php',
'ArcanistXHPASTLintNamingHook' => 'lint/linter/xhpast/ArcanistXHPASTLintNamingHook.php',
'ArcanistXHPASTLintNamingHookTestCase' => 'lint/linter/xhpast/__tests__/ArcanistXHPASTLintNamingHookTestCase.php',
@ -1175,12 +1181,13 @@ phutil_register_library_map(array(
'ArcanistGetConfigWorkflow' => 'ArcanistWorkflow',
'ArcanistGitAPI' => 'ArcanistRepositoryAPI',
'ArcanistGitCommitMessageHardpointLoader' => 'ArcanistGitHardpointLoader',
'ArcanistGitCommitMessageHardpointQuery' => 'ArcanistWorkflowHardpointQuery',
'ArcanistGitCommitMessageHardpointQuery' => 'ArcanistWorkflowGitHardpointQuery',
'ArcanistGitHardpointLoader' => 'ArcanistHardpointLoader',
'ArcanistGitLandEngine' => 'ArcanistLandEngine',
'ArcanistGitRevisionHardpointLoader' => 'ArcanistGitHardpointLoader',
'ArcanistGitUpstreamPath' => 'Phobject',
'ArcanistGitWorkingCopy' => 'ArcanistWorkingCopy',
'ArcanistGitWorkingCopyRevisionHardpointQuery' => 'ArcanistWorkflowGitHardpointQuery',
'ArcanistGlobalVariableXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistGlobalVariableXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistGoLintLinter' => 'ArcanistExternalLinter',
@ -1288,6 +1295,7 @@ phutil_register_library_map(array(
'ArcanistMergeConflictLinter' => 'ArcanistLinter',
'ArcanistMergeConflictLinterTestCase' => 'ArcanistLinterTestCase',
'ArcanistMessageRevisionHardpointLoader' => 'ArcanistHardpointLoader',
'ArcanistMessageRevisionHardpointQuery' => 'ArcanistWorkflowHardpointQuery',
'ArcanistMissingArgumentTerminatorException' => 'Exception',
'ArcanistMissingLinterException' => 'Exception',
'ArcanistModifierOrderingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
@ -1308,6 +1316,7 @@ phutil_register_library_map(array(
'ArcanistNoParentScopeXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistNoURIConduitException' => 'ArcanistConduitException',
'ArcanistNoneLintRenderer' => 'ArcanistLintRenderer',
'ArcanistObjectListHardpoint' => 'ArcanistHardpoint',
'ArcanistObjectOperatorSpacingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistObjectOperatorSpacingXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistPEP8Linter' => 'ArcanistExternalLinter',
@ -1371,6 +1380,7 @@ phutil_register_library_map(array(
'ArcanistReusedIteratorXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistRevertWorkflow' => 'ArcanistWorkflow',
'ArcanistRevisionRef' => 'ArcanistRef',
'ArcanistRevisionRefPro' => 'ArcanistRefPro',
'ArcanistRevisionRefSource' => 'Phobject',
'ArcanistRuboCopLinter' => 'ArcanistExternalLinter',
'ArcanistRuboCopLinterTestCase' => 'ArcanistExternalLinterTestCase',
@ -1465,6 +1475,7 @@ phutil_register_library_map(array(
'ArcanistWildConfigOption' => 'ArcanistConfigOption',
'ArcanistWorkflow' => 'Phobject',
'ArcanistWorkflowArgument' => 'Phobject',
'ArcanistWorkflowGitHardpointQuery' => 'ArcanistWorkflowHardpointQuery',
'ArcanistWorkflowHardpointQuery' => 'ArcanistHardpointQuery',
'ArcanistWorkflowInformation' => 'Phobject',
'ArcanistWorkingCopy' => 'Phobject',
@ -1473,6 +1484,7 @@ phutil_register_library_map(array(
'ArcanistWorkingCopyIdentity' => 'Phobject',
'ArcanistWorkingCopyPath' => 'Phobject',
'ArcanistWorkingCopyStateRef' => 'ArcanistRef',
'ArcanistWorkingCopyStateRefInspector' => 'ArcanistRefInspector',
'ArcanistWorkingCopyStateRefPro' => 'ArcanistRefPro',
'ArcanistXHPASTLintNamingHook' => 'Phobject',
'ArcanistXHPASTLintNamingHookTestCase' => 'PhutilTestCase',

View file

@ -64,6 +64,14 @@ abstract class ArcanistHardpointObject
->setHardpointKey($hardpoint_key);
}
final protected function newTemplateHardpoint(
$hardpoint_key,
ArcanistHardpoint $template) {
return id(clone $template)
->setHardpointKey($hardpoint_key);
}
final public function getHardpointList() {
if ($this->hardpointList === null) {

View file

@ -0,0 +1,25 @@
<?php
final class ArcanistObjectListHardpoint
extends ArcanistHardpoint {
public function isVectorHardpoint() {
return true;
}
public function mergeHardpointValues(
ArcanistHardpointObject $object,
$old,
$new) {
foreach ($new as $item) {
$phid = $item->getPHID();
if (!isset($old[$phid])) {
$old[$phid] = $item;
}
}
return $old;
}
}

View file

@ -0,0 +1,26 @@
<?php
final class ArcanistWorkingCopyStateRefInspector
extends ArcanistRefInspector {
public function getInspectFunctionName() {
return 'working-copy';
}
public function newInspectRef(array $argv) {
if (count($argv) !== 1) {
throw new PhutilArgumentUsageException(
pht(
'Expected exactly one argument to "working-copy(...)" with a '.
'commit hash.'));
}
$commit_hash = $argv[0];
$commit_ref = id(new ArcanistCommitRefPro())
->setCommitHash($commit_hash);
return id(new ArcanistWorkingCopyStateRefPro())
->setCommitRef($commit_ref);
}
}

View file

@ -1,7 +1,7 @@
<?php
final class ArcanistGitCommitMessageHardpointQuery
extends ArcanistWorkflowHardpointQuery {
extends ArcanistWorkflowGitHardpointQuery {
public function getHardpoints() {
return array(
@ -13,11 +13,6 @@ final class ArcanistGitCommitMessageHardpointQuery
return ($ref instanceof ArcanistCommitRefPro);
}
protected function canLoadHardpoint() {
$api = $this->getRepositoryAPI();
return ($api instanceof ArcanistGitAPI);
}
public function loadHardpoint(array $refs, $hardpoint) {
$api = $this->getRepositoryAPI();

View file

@ -0,0 +1,81 @@
<?php
final class ArcanistGitWorkingCopyRevisionHardpointQuery
extends ArcanistWorkflowGitHardpointQuery {
public function getHardpoints() {
return array(
ArcanistWorkingCopyStateRefPro::HARDPOINT_REVISIONREFS,
);
}
protected function canLoadRef(ArcanistRefPro $ref) {
return ($ref instanceof ArcanistWorkingCopyStateRefPro);
}
public function loadHardpoint(array $refs, $hardpoint) {
yield $this->yieldRequests(
$refs,
array(
ArcanistWorkingCopyStateRefPro::HARDPOINT_COMMITREF,
));
$hashes = array();
$map = array();
foreach ($refs as $ref_key => $ref) {
$commit = $ref->getCommitRef();
$commit_hashes = array();
$commit_hashes[] = array(
'gtcm',
$commit->getCommitHash(),
);
if ($commit->getTreeHash()) {
$commit_hashes[] = array(
'gttr',
$commit->getTreeHash(),
);
}
foreach ($commit_hashes as $hash) {
$hashes[] = $hash;
$hash_key = $this->getHashKey($hash);
$map[$hash_key][$ref_key] = $ref;
}
}
$results = array_fill_keys(array_keys($refs), array());
if ($hashes) {
$revisions = (yield $this->yieldConduit(
'differential.query',
array(
'commitHashes' => $hashes,
)));
foreach ($revisions as $dict) {
$revision_hashes = idx($dict, 'hashes');
if (!$revision_hashes) {
continue;
}
$revision_ref = ArcanistRevisionRefPro::newFromConduit($dict);
foreach ($revision_hashes as $revision_hash) {
$hash_key = $this->getHashKey($revision_hash);
$state_refs = idx($map, $hash_key, array());
foreach ($state_refs as $ref_key => $state_ref) {
$results[$ref_key][] = $revision_ref;
}
}
}
}
yield $this->yieldMap($results);
}
private function getHashKey(array $hash) {
return $hash[0].':'.$hash[1];
}
}

View file

@ -0,0 +1,76 @@
<?php
final class ArcanistMessageRevisionHardpointQuery
extends ArcanistWorkflowHardpointQuery {
public function getHardpoints() {
return array(
ArcanistWorkingCopyStateRefPro::HARDPOINT_REVISIONREFS,
);
}
protected function canLoadRef(ArcanistRefPro $ref) {
return ($ref instanceof ArcanistWorkingCopyStateRefPro);
}
public function loadHardpoint(array $refs, $hardpoint) {
yield $this->yieldRequests(
$refs,
array(
ArcanistWorkingCopyStateRefPro::HARDPOINT_COMMITREF,
));
$commit_refs = array();
foreach ($refs as $ref) {
$commit_refs[] = $ref->getCommitRef();
}
yield $this->yieldRequests(
$commit_refs,
array(
ArcanistCommitRefPro::HARDPOINT_MESSAGE,
));
$map = array();
foreach ($refs as $ref_key => $ref) {
$commit_ref = $ref->getCommitRef();
$corpus = $commit_ref->getMessage();
$id = null;
try {
$message = ArcanistDifferentialCommitMessage::newFromRawCorpus($corpus);
$id = $message->getRevisionID();
} catch (ArcanistUsageException $ex) {
continue;
}
if (!$id) {
continue;
}
$map[$id][$ref_key] = $ref;
}
$results = array();
if ($map) {
$revisions = (yield $this->yieldConduit(
'differential.query',
array(
'ids' => array_keys($map),
)));
foreach ($revisions as $dict) {
$revision_ref = ArcanistRevisionRefPro::newFromConduit($dict);
$id = $dict['id'];
$state_refs = idx($map, $id, array());
foreach ($state_refs as $ref_key => $state_ref) {
$results[$ref_key][] = $revision_ref;
}
}
}
yield $this->yieldMap($results);
}
}

View file

@ -0,0 +1,11 @@
<?php
abstract class ArcanistWorkflowGitHardpointQuery
extends ArcanistWorkflowHardpointQuery {
final protected function canLoadHardpoint() {
$api = $this->getRepositoryAPI();
return ($api instanceof ArcanistGitAPI);
}
}

View file

@ -0,0 +1,76 @@
<?php
final class ArcanistRevisionRefPro
extends ArcanistRefPro {
private $parameters;
private $sources = array();
public function getRefDisplayName() {
return pht('Revision %s', $this->getMonogram());
}
public function defineHardpoints() {
return array();
}
public static function newFromConduit(array $dict) {
$ref = new self();
$ref->parameters = $dict;
return $ref;
}
public function getMonogram() {
return 'D'.$this->getID();
}
public function getStatusDisplayName() {
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());
}
public function getID() {
return idx($this->parameters, 'id');
}
public function getPHID() {
return idx($this->parameters, 'phid');
}
public function getName() {
return idx($this->parameters, 'title');
}
public function getAuthorPHID() {
return idx($this->parameters, 'authorPHID');
}
public function addSource(ArcanistRevisionRefSource $source) {
$this->sources[] = $source;
return $this;
}
public function getSources() {
return $this->sources;
}
}

View file

@ -4,7 +4,6 @@ final class ArcanistWorkingCopyStateRefPro
extends ArcanistRefPro {
const HARDPOINT_COMMITREF = 'commitRef';
const HARDPOINT_BRANCHREF = 'branchRef';
const HARDPOINT_REVISIONREFS = 'revisionRefs';
public function getRefDisplayName() {
@ -14,22 +13,15 @@ final class ArcanistWorkingCopyStateRefPro
}
protected function newHardpoints() {
$object_list = new ArcanistObjectListHardpoint();
return array(
$this->newHardpoint(self::HARDPOINT_COMMITREF),
$this->newHardpoint(self::HARDPOINT_BRANCHREF),
$this->newVectorHardpoint(self::HARDPOINT_REVISIONREFS),
$this->newTemplateHardpoint(self::HARDPOINT_REVISIONREFS, $object_list),
);
}
public function attachBranchRef(ArcanistBranchRef $branch_ref) {
return $this->attachHardpoint(self::HARDPOINT_BRANCHREF, $branch_ref);
}
public function getBranchRef() {
return $this->getHardpoint(self::HARDPOINT_BRANCHREF);
}
public function setCommitRef(ArcanistCommitRef $commit_ref) {
// TODO: This should be "attachCommitRef()".
public function setCommitRef(ArcanistCommitRefPro $commit_ref) {
return $this->attachHardpoint(self::HARDPOINT_COMMITREF, $commit_ref);
}

View file

@ -54,11 +54,13 @@ EOTEXT
$ref_lists = array();
foreach ($objects as $description) {
$matches = null;
if (!preg_match('/^(\w+)(?:\(([^)]+)\))?\z/', $description, $matches)) {
$pattern = '/^([\w-]+)(?:\(([^)]+)\))?\z/';
if (!preg_match($pattern, $description, $matches)) {
throw new PhutilArgumentUsageException(
pht(
'Object specification "%s" is unknown, expected a specification '.
'like "commit(HEAD)".'));
'like "commit(HEAD)".',
$description));
}
$function = $matches[1];
@ -149,11 +151,21 @@ EOTEXT
if ($ref->hasAttachedHardpoint($hardpoint_key)) {
$mode = '*';
$value = $ref->getHardpoint($hardpoint_key);
if ($value instanceof ArcanistRefPro) {
$children[] = $value;
} else if (is_array($value)) {
foreach ($value as $key => $child) {
if ($child instanceof ArcanistRefPro) {
$children[] = $child;
} else {
$values[] = $value;
}
}
} else {
$values[] = $value;
}
} else {
$mode = 'o';
}