From 8bb81217d5d2ac9fb0b8acf9aa445e2983e6c468 Mon Sep 17 00:00:00 2001 From: epriestley Date: Fri, 10 Apr 2020 05:28:55 -0700 Subject: [PATCH] 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 --- src/__phutil_library_map__.php | 14 +++- src/hardpoint/ArcanistHardpointObject.php | 8 ++ src/hardpoint/ArcanistObjectListHardpoint.php | 25 ++++++ .../ArcanistWorkingCopyStateRefInspector.php | 26 ++++++ ...ArcanistGitCommitMessageHardpointQuery.php | 7 +- ...stGitWorkingCopyRevisionHardpointQuery.php | 81 +++++++++++++++++++ .../ArcanistMessageRevisionHardpointQuery.php | 76 +++++++++++++++++ .../ArcanistWorkflowGitHardpointQuery.php | 11 +++ src/ref/ArcanistRevisionRefPro.php | 76 +++++++++++++++++ src/ref/ArcanistWorkingCopyStateRefPro.php | 16 +--- src/workflow/ArcanistInspectWorkflow.php | 16 +++- 11 files changed, 335 insertions(+), 21 deletions(-) create mode 100644 src/hardpoint/ArcanistObjectListHardpoint.php create mode 100644 src/inspector/ArcanistWorkingCopyStateRefInspector.php create mode 100644 src/query/ArcanistGitWorkingCopyRevisionHardpointQuery.php create mode 100644 src/query/ArcanistMessageRevisionHardpointQuery.php create mode 100644 src/query/ArcanistWorkflowGitHardpointQuery.php create mode 100644 src/ref/ArcanistRevisionRefPro.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 53c43926..33d8b522 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -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', diff --git a/src/hardpoint/ArcanistHardpointObject.php b/src/hardpoint/ArcanistHardpointObject.php index e7a85433..93a3bac9 100644 --- a/src/hardpoint/ArcanistHardpointObject.php +++ b/src/hardpoint/ArcanistHardpointObject.php @@ -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) { diff --git a/src/hardpoint/ArcanistObjectListHardpoint.php b/src/hardpoint/ArcanistObjectListHardpoint.php new file mode 100644 index 00000000..d7fd7701 --- /dev/null +++ b/src/hardpoint/ArcanistObjectListHardpoint.php @@ -0,0 +1,25 @@ +getPHID(); + if (!isset($old[$phid])) { + $old[$phid] = $item; + } + } + + return $old; + } + +} diff --git a/src/inspector/ArcanistWorkingCopyStateRefInspector.php b/src/inspector/ArcanistWorkingCopyStateRefInspector.php new file mode 100644 index 00000000..3651c632 --- /dev/null +++ b/src/inspector/ArcanistWorkingCopyStateRefInspector.php @@ -0,0 +1,26 @@ +setCommitHash($commit_hash); + + return id(new ArcanistWorkingCopyStateRefPro()) + ->setCommitRef($commit_ref); + } + +} diff --git a/src/query/ArcanistGitCommitMessageHardpointQuery.php b/src/query/ArcanistGitCommitMessageHardpointQuery.php index 7d513f41..2f76e954 100644 --- a/src/query/ArcanistGitCommitMessageHardpointQuery.php +++ b/src/query/ArcanistGitCommitMessageHardpointQuery.php @@ -1,7 +1,7 @@ getRepositoryAPI(); - return ($api instanceof ArcanistGitAPI); - } - public function loadHardpoint(array $refs, $hardpoint) { $api = $this->getRepositoryAPI(); diff --git a/src/query/ArcanistGitWorkingCopyRevisionHardpointQuery.php b/src/query/ArcanistGitWorkingCopyRevisionHardpointQuery.php new file mode 100644 index 00000000..8029803b --- /dev/null +++ b/src/query/ArcanistGitWorkingCopyRevisionHardpointQuery.php @@ -0,0 +1,81 @@ +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]; + } + +} diff --git a/src/query/ArcanistMessageRevisionHardpointQuery.php b/src/query/ArcanistMessageRevisionHardpointQuery.php new file mode 100644 index 00000000..70ef8936 --- /dev/null +++ b/src/query/ArcanistMessageRevisionHardpointQuery.php @@ -0,0 +1,76 @@ +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); + } + +} diff --git a/src/query/ArcanistWorkflowGitHardpointQuery.php b/src/query/ArcanistWorkflowGitHardpointQuery.php new file mode 100644 index 00000000..b8519c55 --- /dev/null +++ b/src/query/ArcanistWorkflowGitHardpointQuery.php @@ -0,0 +1,11 @@ +getRepositoryAPI(); + return ($api instanceof ArcanistGitAPI); + } + +} diff --git a/src/ref/ArcanistRevisionRefPro.php b/src/ref/ArcanistRevisionRefPro.php new file mode 100644 index 00000000..f8707211 --- /dev/null +++ b/src/ref/ArcanistRevisionRefPro.php @@ -0,0 +1,76 @@ +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; + } + +} diff --git a/src/ref/ArcanistWorkingCopyStateRefPro.php b/src/ref/ArcanistWorkingCopyStateRefPro.php index 05d05516..f6f0d810 100644 --- a/src/ref/ArcanistWorkingCopyStateRefPro.php +++ b/src/ref/ArcanistWorkingCopyStateRefPro.php @@ -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); } diff --git a/src/workflow/ArcanistInspectWorkflow.php b/src/workflow/ArcanistInspectWorkflow.php index 33add3d7..4c5f91ee 100644 --- a/src/workflow/ArcanistInspectWorkflow.php +++ b/src/workflow/ArcanistInspectWorkflow.php @@ -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'; }