mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-11-25 16:22:42 +01:00
Introduce "arc inspect" and some of the new ref/hardpoint classes
Summary: Ref T11968. Inches toward the new ref/hardpoint code by introducing the modern refs as "RefPro" objects and supporting an "arc inspect <object>" to load objects and hardpoints. This doesn't impact any existing runtime behavior. Test Plan: Ran "arc inspect [--all] commit(...)", got hardpoint queries and yield-based data fetching. Maniphest Tasks: T11968 Differential Revision: https://secure.phabricator.com/D21078
This commit is contained in:
parent
92b29f53f3
commit
adea2550f5
19 changed files with 803 additions and 12 deletions
|
@ -54,6 +54,7 @@ phutil_register_library_map(array(
|
|||
'ArcanistBraceFormattingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistBraceFormattingXHPASTLinterRule.php',
|
||||
'ArcanistBraceFormattingXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistBraceFormattingXHPASTLinterRuleTestCase.php',
|
||||
'ArcanistBranchRef' => 'ref/ArcanistBranchRef.php',
|
||||
'ArcanistBranchRefPro' => 'ref/ArcanistBranchRefPro.php',
|
||||
'ArcanistBranchWorkflow' => 'workflow/ArcanistBranchWorkflow.php',
|
||||
'ArcanistBrowseCommitHardpointLoader' => 'browse/loader/ArcanistBrowseCommitHardpointLoader.php',
|
||||
'ArcanistBrowseCommitURIHardpointLoader' => 'browse/loader/ArcanistBrowseCommitURIHardpointLoader.php',
|
||||
|
@ -102,7 +103,10 @@ phutil_register_library_map(array(
|
|||
'ArcanistCommentStyleXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistCommentStyleXHPASTLinterRule.php',
|
||||
'ArcanistCommentStyleXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistCommentStyleXHPASTLinterRuleTestCase.php',
|
||||
'ArcanistCommitRef' => 'ref/ArcanistCommitRef.php',
|
||||
'ArcanistCommitRefInspector' => 'inspector/ArcanistCommitRefInspector.php',
|
||||
'ArcanistCommitRefPro' => 'ref/ArcanistCommitRefPro.php',
|
||||
'ArcanistCommitUpstreamHardpointLoader' => 'loader/ArcanistCommitUpstreamHardpointLoader.php',
|
||||
'ArcanistCommitUpstreamHardpointQuery' => 'query/ArcanistCommitUpstreamHardpointQuery.php',
|
||||
'ArcanistCommitWorkflow' => 'workflow/ArcanistCommitWorkflow.php',
|
||||
'ArcanistCompilerLintRenderer' => 'lint/renderer/ArcanistCompilerLintRenderer.php',
|
||||
'ArcanistComposerLinter' => 'lint/linter/ArcanistComposerLinter.php',
|
||||
|
@ -203,6 +207,7 @@ phutil_register_library_map(array(
|
|||
'ArcanistGetConfigWorkflow' => 'workflow/ArcanistGetConfigWorkflow.php',
|
||||
'ArcanistGitAPI' => 'repository/api/ArcanistGitAPI.php',
|
||||
'ArcanistGitCommitMessageHardpointLoader' => 'loader/ArcanistGitCommitMessageHardpointLoader.php',
|
||||
'ArcanistGitCommitMessageHardpointQuery' => 'query/ArcanistGitCommitMessageHardpointQuery.php',
|
||||
'ArcanistGitHardpointLoader' => 'loader/ArcanistGitHardpointLoader.php',
|
||||
'ArcanistGitLandEngine' => 'land/ArcanistGitLandEngine.php',
|
||||
'ArcanistGitRevisionHardpointLoader' => 'loader/ArcanistGitRevisionHardpointLoader.php',
|
||||
|
@ -226,6 +231,7 @@ phutil_register_library_map(array(
|
|||
'ArcanistHardpointRequest' => 'hardpoint/ArcanistHardpointRequest.php',
|
||||
'ArcanistHardpointRequestList' => 'hardpoint/ArcanistHardpointRequestList.php',
|
||||
'ArcanistHardpointTask' => 'hardpoint/ArcanistHardpointTask.php',
|
||||
'ArcanistHardpointTaskResult' => 'hardpoint/ArcanistHardpointTaskResult.php',
|
||||
'ArcanistHelpWorkflow' => 'toolset/workflow/ArcanistHelpWorkflow.php',
|
||||
'ArcanistHexadecimalNumericScalarCasingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistHexadecimalNumericScalarCasingXHPASTLinterRule.php',
|
||||
'ArcanistHexadecimalNumericScalarCasingXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistHexadecimalNumericScalarCasingXHPASTLinterRuleTestCase.php',
|
||||
|
@ -245,6 +251,7 @@ phutil_register_library_map(array(
|
|||
'ArcanistInlineHTMLXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistInlineHTMLXHPASTLinterRuleTestCase.php',
|
||||
'ArcanistInnerFunctionXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistInnerFunctionXHPASTLinterRule.php',
|
||||
'ArcanistInnerFunctionXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistInnerFunctionXHPASTLinterRuleTestCase.php',
|
||||
'ArcanistInspectWorkflow' => 'workflow/ArcanistInspectWorkflow.php',
|
||||
'ArcanistInstallCertificateWorkflow' => 'workflow/ArcanistInstallCertificateWorkflow.php',
|
||||
'ArcanistInstanceOfOperatorXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistInstanceOfOperatorXHPASTLinterRule.php',
|
||||
'ArcanistInstanceofOperatorXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistInstanceofOperatorXHPASTLinterRuleTestCase.php',
|
||||
|
@ -381,6 +388,8 @@ phutil_register_library_map(array(
|
|||
'ArcanistRaggedClassTreeEdgeXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistRaggedClassTreeEdgeXHPASTLinterRule.php',
|
||||
'ArcanistRaggedClassTreeEdgeXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistRaggedClassTreeEdgeXHPASTLinterRuleTestCase.php',
|
||||
'ArcanistRef' => 'ref/ArcanistRef.php',
|
||||
'ArcanistRefInspector' => 'inspector/ArcanistRefInspector.php',
|
||||
'ArcanistRefPro' => 'ref/ArcanistRefPro.php',
|
||||
'ArcanistRefQuery' => 'ref/ArcanistRefQuery.php',
|
||||
'ArcanistRepositoryAPI' => 'repository/api/ArcanistRepositoryAPI.php',
|
||||
'ArcanistRepositoryAPIMiscTestCase' => 'repository/api/__tests__/ArcanistRepositoryAPIMiscTestCase.php',
|
||||
|
@ -489,12 +498,15 @@ phutil_register_library_map(array(
|
|||
'ArcanistWildConfigOption' => 'config/option/ArcanistWildConfigOption.php',
|
||||
'ArcanistWorkflow' => 'workflow/ArcanistWorkflow.php',
|
||||
'ArcanistWorkflowArgument' => 'toolset/ArcanistWorkflowArgument.php',
|
||||
'ArcanistWorkflowHardpointQuery' => 'toolset/query/ArcanistWorkflowHardpointQuery.php',
|
||||
'ArcanistWorkflowInformation' => 'toolset/ArcanistWorkflowInformation.php',
|
||||
'ArcanistWorkingCopy' => 'workingcopy/ArcanistWorkingCopy.php',
|
||||
'ArcanistWorkingCopyCommitHardpointQuery' => 'query/ArcanistWorkingCopyCommitHardpointQuery.php',
|
||||
'ArcanistWorkingCopyConfigurationSource' => 'config/source/ArcanistWorkingCopyConfigurationSource.php',
|
||||
'ArcanistWorkingCopyIdentity' => 'workingcopyidentity/ArcanistWorkingCopyIdentity.php',
|
||||
'ArcanistWorkingCopyPath' => 'workingcopy/ArcanistWorkingCopyPath.php',
|
||||
'ArcanistWorkingCopyStateRef' => 'ref/ArcanistWorkingCopyStateRef.php',
|
||||
'ArcanistWorkingCopyStateRefPro' => 'ref/ArcanistWorkingCopyStateRefPro.php',
|
||||
'ArcanistXHPASTLintNamingHook' => 'lint/linter/xhpast/ArcanistXHPASTLintNamingHook.php',
|
||||
'ArcanistXHPASTLintNamingHookTestCase' => 'lint/linter/xhpast/__tests__/ArcanistXHPASTLintNamingHookTestCase.php',
|
||||
'ArcanistXHPASTLintSwitchHook' => 'lint/linter/xhpast/ArcanistXHPASTLintSwitchHook.php',
|
||||
|
@ -1010,6 +1022,7 @@ phutil_register_library_map(array(
|
|||
'ArcanistBraceFormattingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
|
||||
'ArcanistBraceFormattingXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
|
||||
'ArcanistBranchRef' => 'ArcanistRef',
|
||||
'ArcanistBranchRefPro' => 'ArcanistRefPro',
|
||||
'ArcanistBranchWorkflow' => 'ArcanistFeatureWorkflow',
|
||||
'ArcanistBrowseCommitHardpointLoader' => 'ArcanistHardpointLoader',
|
||||
'ArcanistBrowseCommitURIHardpointLoader' => 'ArcanistBrowseURIHardpointLoader',
|
||||
|
@ -1058,7 +1071,10 @@ phutil_register_library_map(array(
|
|||
'ArcanistCommentStyleXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
|
||||
'ArcanistCommentStyleXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
|
||||
'ArcanistCommitRef' => 'ArcanistRef',
|
||||
'ArcanistCommitRefInspector' => 'ArcanistRefInspector',
|
||||
'ArcanistCommitRefPro' => 'ArcanistRefPro',
|
||||
'ArcanistCommitUpstreamHardpointLoader' => 'ArcanistHardpointLoader',
|
||||
'ArcanistCommitUpstreamHardpointQuery' => 'ArcanistWorkflowHardpointQuery',
|
||||
'ArcanistCommitWorkflow' => 'ArcanistWorkflow',
|
||||
'ArcanistCompilerLintRenderer' => 'ArcanistLintRenderer',
|
||||
'ArcanistComposerLinter' => 'ArcanistLinter',
|
||||
|
@ -1159,6 +1175,7 @@ phutil_register_library_map(array(
|
|||
'ArcanistGetConfigWorkflow' => 'ArcanistWorkflow',
|
||||
'ArcanistGitAPI' => 'ArcanistRepositoryAPI',
|
||||
'ArcanistGitCommitMessageHardpointLoader' => 'ArcanistGitHardpointLoader',
|
||||
'ArcanistGitCommitMessageHardpointQuery' => 'ArcanistWorkflowHardpointQuery',
|
||||
'ArcanistGitHardpointLoader' => 'ArcanistHardpointLoader',
|
||||
'ArcanistGitLandEngine' => 'ArcanistLandEngine',
|
||||
'ArcanistGitRevisionHardpointLoader' => 'ArcanistGitHardpointLoader',
|
||||
|
@ -1182,6 +1199,7 @@ phutil_register_library_map(array(
|
|||
'ArcanistHardpointRequest' => 'Phobject',
|
||||
'ArcanistHardpointRequestList' => 'Phobject',
|
||||
'ArcanistHardpointTask' => 'Phobject',
|
||||
'ArcanistHardpointTaskResult' => 'Phobject',
|
||||
'ArcanistHelpWorkflow' => 'ArcanistWorkflow',
|
||||
'ArcanistHexadecimalNumericScalarCasingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
|
||||
'ArcanistHexadecimalNumericScalarCasingXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
|
||||
|
@ -1201,6 +1219,7 @@ phutil_register_library_map(array(
|
|||
'ArcanistInlineHTMLXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
|
||||
'ArcanistInnerFunctionXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
|
||||
'ArcanistInnerFunctionXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
|
||||
'ArcanistInspectWorkflow' => 'ArcanistArcWorkflow',
|
||||
'ArcanistInstallCertificateWorkflow' => 'ArcanistWorkflow',
|
||||
'ArcanistInstanceOfOperatorXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
|
||||
'ArcanistInstanceofOperatorXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
|
||||
|
@ -1337,6 +1356,8 @@ phutil_register_library_map(array(
|
|||
'ArcanistRaggedClassTreeEdgeXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
|
||||
'ArcanistRaggedClassTreeEdgeXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
|
||||
'ArcanistRef' => 'Phobject',
|
||||
'ArcanistRefInspector' => 'Phobject',
|
||||
'ArcanistRefPro' => 'ArcanistHardpointObject',
|
||||
'ArcanistRefQuery' => 'Phobject',
|
||||
'ArcanistRepositoryAPI' => 'Phobject',
|
||||
'ArcanistRepositoryAPIMiscTestCase' => 'PhutilTestCase',
|
||||
|
@ -1444,12 +1465,15 @@ phutil_register_library_map(array(
|
|||
'ArcanistWildConfigOption' => 'ArcanistConfigOption',
|
||||
'ArcanistWorkflow' => 'Phobject',
|
||||
'ArcanistWorkflowArgument' => 'Phobject',
|
||||
'ArcanistWorkflowHardpointQuery' => 'ArcanistHardpointQuery',
|
||||
'ArcanistWorkflowInformation' => 'Phobject',
|
||||
'ArcanistWorkingCopy' => 'Phobject',
|
||||
'ArcanistWorkingCopyCommitHardpointQuery' => 'ArcanistWorkflowHardpointQuery',
|
||||
'ArcanistWorkingCopyConfigurationSource' => 'ArcanistFilesystemConfigurationSource',
|
||||
'ArcanistWorkingCopyIdentity' => 'Phobject',
|
||||
'ArcanistWorkingCopyPath' => 'Phobject',
|
||||
'ArcanistWorkingCopyStateRef' => 'ArcanistRef',
|
||||
'ArcanistWorkingCopyStateRefPro' => 'ArcanistRefPro',
|
||||
'ArcanistXHPASTLintNamingHook' => 'Phobject',
|
||||
'ArcanistXHPASTLintNamingHookTestCase' => 'PhutilTestCase',
|
||||
'ArcanistXHPASTLintSwitchHook' => 'Phobject',
|
||||
|
|
|
@ -46,6 +46,10 @@ final class ArcanistHardpointList
|
|||
return isset($this->attached[$hardpoint]);
|
||||
}
|
||||
|
||||
public function getHardpoints() {
|
||||
return $this->hardpoints;
|
||||
}
|
||||
|
||||
public function getHardpointDefinition($object, $hardpoint) {
|
||||
if (!$this->hasHardpoint($object, $hardpoint)) {
|
||||
throw new Exception(
|
||||
|
|
|
@ -100,6 +100,7 @@ final class ArcanistHardpointTask
|
|||
$generator->next();
|
||||
}
|
||||
|
||||
$generator_result = null;
|
||||
if ($generator->valid()) {
|
||||
$result = $generator->current();
|
||||
|
||||
|
@ -152,17 +153,25 @@ final class ArcanistHardpointTask
|
|||
return true;
|
||||
}
|
||||
|
||||
throw new Exception(
|
||||
pht(
|
||||
'Hardpoint generator (for query "%s") yielded an unexpected '.
|
||||
'value. Generators may only yield "Future" or '.
|
||||
'"ArcanistHardpointRequest" objects, got "%s".',
|
||||
get_class($query),
|
||||
phutil_describe_type($result)));
|
||||
if ($result instanceof ArcanistHardpointTaskResult) {
|
||||
$generator_result = $result;
|
||||
} else {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'Hardpoint generator (for query "%s") yielded an unexpected '.
|
||||
'value (of type "%s").',
|
||||
get_class($query),
|
||||
phutil_describe_type($result)));
|
||||
}
|
||||
}
|
||||
|
||||
$this->generator = null;
|
||||
$result = $generator->getReturn();
|
||||
|
||||
if ($generator_result !== null) {
|
||||
$result = $generator_result->getValue();
|
||||
} else {
|
||||
$result = $generator->getReturn();
|
||||
}
|
||||
|
||||
$this->attachResult($result);
|
||||
|
||||
|
|
16
src/hardpoint/ArcanistHardpointTaskResult.php
Normal file
16
src/hardpoint/ArcanistHardpointTaskResult.php
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
final class ArcanistHardpointTaskResult
|
||||
extends Phobject {
|
||||
|
||||
private $value;
|
||||
|
||||
public function __construct($value) {
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
public function getValue() {
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
}
|
22
src/inspector/ArcanistCommitRefInspector.php
Normal file
22
src/inspector/ArcanistCommitRefInspector.php
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
final class ArcanistCommitRefInspector
|
||||
extends ArcanistRefInspector {
|
||||
|
||||
public function getInspectFunctionName() {
|
||||
return 'commit';
|
||||
}
|
||||
|
||||
public function newInspectRef(array $argv) {
|
||||
if (count($argv) !== 1) {
|
||||
throw new PhutilArgumentUsageException(
|
||||
pht(
|
||||
'Expected exactly one argument to "commit(...)" with a '.
|
||||
'commit hash.'));
|
||||
}
|
||||
|
||||
return id(new ArcanistCommitRefPro())
|
||||
->setCommitHash($argv[0]);
|
||||
}
|
||||
|
||||
}
|
16
src/inspector/ArcanistRefInspector.php
Normal file
16
src/inspector/ArcanistRefInspector.php
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
abstract class ArcanistRefInspector
|
||||
extends Phobject {
|
||||
|
||||
abstract public function getInspectFunctionName();
|
||||
abstract public function newInspectRef(array $argv);
|
||||
|
||||
final public static function getAllInspectors() {
|
||||
return id(new PhutilClassMapQuery())
|
||||
->setAncestorClass(__CLASS__)
|
||||
->setUniqueMethod('getInspectFunctionName')
|
||||
->execute();
|
||||
}
|
||||
|
||||
}
|
53
src/query/ArcanistCommitUpstreamHardpointQuery.php
Normal file
53
src/query/ArcanistCommitUpstreamHardpointQuery.php
Normal file
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
final class ArcanistCommitUpstreamHardpointQuery
|
||||
extends ArcanistWorkflowHardpointQuery {
|
||||
|
||||
public function getHardpoints() {
|
||||
return array(
|
||||
ArcanistCommitRefPro::HARDPOINT_UPSTREAM,
|
||||
);
|
||||
}
|
||||
|
||||
protected function canLoadRef(ArcanistRefPro $ref) {
|
||||
return ($ref instanceof ArcanistCommitRefPro);
|
||||
}
|
||||
|
||||
public function loadHardpoint(array $refs, $hardpoint) {
|
||||
$repository_ref = (yield $this->yieldRepositoryRef());
|
||||
if (!$repository_ref) {
|
||||
yield $this->yieldValue($refs, null);
|
||||
}
|
||||
$repository_phid = $repository_ref->getPHID();
|
||||
|
||||
$commit_map = array();
|
||||
foreach ($refs as $key => $ref) {
|
||||
$hash = $ref->getCommitHash();
|
||||
$commit_map[$hash][] = $key;
|
||||
}
|
||||
|
||||
$commit_info = (yield $this->yieldConduit(
|
||||
'diffusion.querycommits',
|
||||
array(
|
||||
'repositoryPHID' => $repository_phid,
|
||||
'names' => array_keys($commit_map),
|
||||
)));
|
||||
|
||||
$results = array();
|
||||
foreach ($commit_map as $hash => $keys) {
|
||||
$commit_phid = idx($commit_info['identifierMap'], $hash);
|
||||
if ($commit_phid) {
|
||||
$commit_data = idx($commit_info['data'], $commit_phid);
|
||||
} else {
|
||||
$commit_data = null;
|
||||
}
|
||||
|
||||
foreach ($keys as $key) {
|
||||
$results[$key] = $commit_data;
|
||||
}
|
||||
}
|
||||
|
||||
yield $this->yieldMap($results);
|
||||
}
|
||||
|
||||
}
|
53
src/query/ArcanistGitCommitMessageHardpointQuery.php
Normal file
53
src/query/ArcanistGitCommitMessageHardpointQuery.php
Normal file
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
final class ArcanistGitCommitMessageHardpointQuery
|
||||
extends ArcanistWorkflowHardpointQuery {
|
||||
|
||||
public function getHardpoints() {
|
||||
return array(
|
||||
ArcanistCommitRefPro::HARDPOINT_MESSAGE,
|
||||
);
|
||||
}
|
||||
|
||||
protected function canLoadRef(ArcanistRefPro $ref) {
|
||||
return ($ref instanceof ArcanistCommitRefPro);
|
||||
}
|
||||
|
||||
protected function canLoadHardpoint() {
|
||||
$api = $this->getRepositoryAPI();
|
||||
return ($api instanceof ArcanistGitAPI);
|
||||
}
|
||||
|
||||
public function loadHardpoint(array $refs, $hardpoint) {
|
||||
$api = $this->getRepositoryAPI();
|
||||
|
||||
$hashes = mpull($refs, 'getCommitHash');
|
||||
$unique_hashes = array_fuse($hashes);
|
||||
|
||||
// TODO: Update this to use "%B", see T5028. We can also bulk-resolve
|
||||
// these with "git show --quiet --format=... hash hash hash ... --".
|
||||
|
||||
$futures = array();
|
||||
foreach ($unique_hashes as $hash) {
|
||||
$futures[$hash] = $api->execFutureLocal(
|
||||
'log -n1 --format=%s %s --',
|
||||
'%s%n%n%b',
|
||||
$hash);
|
||||
}
|
||||
|
||||
yield $this->yieldFutures($futures);
|
||||
|
||||
$messages = array();
|
||||
foreach ($futures as $hash => $future) {
|
||||
list($stdout) = $future->resolvex();
|
||||
$messages[$hash] = $stdout;
|
||||
}
|
||||
|
||||
foreach ($hashes as $ref_key => $hash) {
|
||||
$hashes[$ref_key] = $messages[$hash];
|
||||
}
|
||||
|
||||
yield $this->yieldMap($hashes);
|
||||
}
|
||||
|
||||
}
|
39
src/query/ArcanistWorkingCopyCommitHardpointQuery.php
Normal file
39
src/query/ArcanistWorkingCopyCommitHardpointQuery.php
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
final class ArcanistWorkingCopyCommitHardpointQuery
|
||||
extends ArcanistWorkflowHardpointQuery {
|
||||
|
||||
public function getHardpoints() {
|
||||
return array(
|
||||
ArcanistWorkingCopyStateRefPro::HARDPOINT_COMMITREF,
|
||||
);
|
||||
}
|
||||
|
||||
protected function canLoadRef(ArcanistRefPro $ref) {
|
||||
return ($ref instanceof ArcanistWorkingCopyStateRefPro);
|
||||
}
|
||||
|
||||
public function loadHardpoint(array $refs, $hardpoint) {
|
||||
yield $this->yieldRequests(
|
||||
$refs,
|
||||
array(
|
||||
ArcanistWorkingCopyStateRefPro::HARDPOINT_BRANCHREF,
|
||||
));
|
||||
|
||||
$branch_refs = mpull($refs, 'getBranchRef');
|
||||
|
||||
yield $this->yieldRequests(
|
||||
$branch_refs,
|
||||
array(
|
||||
ArcanistBranchRefPro::HARDPOINT_COMMITREF,
|
||||
));
|
||||
|
||||
$results = array();
|
||||
foreach ($refs as $key => $ref) {
|
||||
$results[$key] = $ref->getBranchRef()->getCommitRef();
|
||||
}
|
||||
|
||||
yield $this->yieldMap($results);
|
||||
}
|
||||
|
||||
}
|
57
src/ref/ArcanistBranchRefPro.php
Normal file
57
src/ref/ArcanistBranchRefPro.php
Normal file
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
|
||||
final class ArcanistBranchRefPro
|
||||
extends ArcanistRefPro {
|
||||
|
||||
const HARDPOINT_COMMITREF = 'commitRef';
|
||||
|
||||
private $branchName;
|
||||
private $refName;
|
||||
private $isCurrentBranch;
|
||||
|
||||
public function getRefDisplayName() {
|
||||
return pht('Branch %s', $this->getBranchName());
|
||||
}
|
||||
|
||||
protected function newHardpoints() {
|
||||
return array(
|
||||
$this->newHardpoint(self::HARDPOINT_COMMITREF),
|
||||
);
|
||||
}
|
||||
|
||||
public function setBranchName($branch_name) {
|
||||
$this->branchName = $branch_name;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getBranchName() {
|
||||
return $this->branchName;
|
||||
}
|
||||
|
||||
public function setRefName($ref_name) {
|
||||
$this->refName = $ref_name;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getRefName() {
|
||||
return $this->refName;
|
||||
}
|
||||
|
||||
public function setIsCurrentBranch($is_current_branch) {
|
||||
$this->isCurrentBranch = $is_current_branch;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getIsCurrentBranch() {
|
||||
return $this->isCurrentBranch;
|
||||
}
|
||||
|
||||
public function attachCommitRef(ArcanistCommitRef $ref) {
|
||||
return $this->attachHardpoint(self::HARDPOINT_COMMITREF, $ref);
|
||||
}
|
||||
|
||||
public function getCommitRef() {
|
||||
return $this->getHardpoint(self::HARDPOINT_COMMITREF);
|
||||
}
|
||||
|
||||
}
|
93
src/ref/ArcanistCommitRefPro.php
Normal file
93
src/ref/ArcanistCommitRefPro.php
Normal file
|
@ -0,0 +1,93 @@
|
|||
<?php
|
||||
|
||||
final class ArcanistCommitRefPro
|
||||
extends ArcanistRefPro {
|
||||
|
||||
private $commitHash;
|
||||
private $treeHash;
|
||||
private $commitEpoch;
|
||||
private $authorEpoch;
|
||||
private $upstream;
|
||||
|
||||
const HARDPOINT_MESSAGE = 'message';
|
||||
const HARDPOINT_UPSTREAM = 'upstream';
|
||||
|
||||
public function getRefDisplayName() {
|
||||
return pht('Commit "%s"', $this->getCommitHash());
|
||||
}
|
||||
|
||||
protected function newHardpoints() {
|
||||
return array(
|
||||
$this->newHardpoint(self::HARDPOINT_MESSAGE),
|
||||
$this->newHardpoint(self::HARDPOINT_UPSTREAM),
|
||||
);
|
||||
}
|
||||
|
||||
public function setCommitHash($commit_hash) {
|
||||
$this->commitHash = $commit_hash;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCommitHash() {
|
||||
return $this->commitHash;
|
||||
}
|
||||
|
||||
public function setTreeHash($tree_hash) {
|
||||
$this->treeHash = $tree_hash;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTreeHash() {
|
||||
return $this->treeHash;
|
||||
}
|
||||
|
||||
public function setCommitEpoch($commit_epoch) {
|
||||
$this->commitEpoch = $commit_epoch;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCommitEpoch() {
|
||||
return $this->commitEpoch;
|
||||
}
|
||||
|
||||
public function setAuthorEpoch($author_epoch) {
|
||||
$this->authorEpoch = $author_epoch;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getAuthorEpoch() {
|
||||
return $this->authorEpoch;
|
||||
}
|
||||
|
||||
public function getSummary() {
|
||||
$message = $this->getMessage();
|
||||
|
||||
$message = trim($message);
|
||||
$lines = phutil_split_lines($message, false);
|
||||
|
||||
return head($lines);
|
||||
}
|
||||
|
||||
public function attachMessage($message) {
|
||||
return $this->attachHardpoint(self::HARDPOINT_MESSAGE, $message);
|
||||
}
|
||||
|
||||
public function getMessage() {
|
||||
return $this->getHardpoint(self::HARDPOINT_MESSAGE);
|
||||
}
|
||||
|
||||
public function getURI() {
|
||||
return $this->getUpstreamProperty('uri');
|
||||
}
|
||||
|
||||
private function getUpstreamProperty($key, $default = null) {
|
||||
$upstream = $this->getHardpoint(self::HARDPOINT_UPSTREAM);
|
||||
|
||||
if (!$upstream) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
return idx($upstream, $key, $default);
|
||||
}
|
||||
|
||||
}
|
8
src/ref/ArcanistRefPro.php
Normal file
8
src/ref/ArcanistRefPro.php
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
|
||||
abstract class ArcanistRefPro
|
||||
extends ArcanistHardpointObject {
|
||||
|
||||
abstract public function getRefDisplayName();
|
||||
|
||||
}
|
62
src/ref/ArcanistWorkingCopyStateRefPro.php
Normal file
62
src/ref/ArcanistWorkingCopyStateRefPro.php
Normal file
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
final class ArcanistWorkingCopyStateRefPro
|
||||
extends ArcanistRefPro {
|
||||
|
||||
const HARDPOINT_COMMITREF = 'commitRef';
|
||||
const HARDPOINT_BRANCHREF = 'branchRef';
|
||||
const HARDPOINT_REVISIONREFS = 'revisionRefs';
|
||||
|
||||
public function getRefDisplayName() {
|
||||
// TODO: This could check attached hardpoints and render something more
|
||||
// insightful.
|
||||
return pht('Working Copy State');
|
||||
}
|
||||
|
||||
protected function newHardpoints() {
|
||||
return array(
|
||||
$this->newHardpoint(self::HARDPOINT_COMMITREF),
|
||||
$this->newHardpoint(self::HARDPOINT_BRANCHREF),
|
||||
$this->newVectorHardpoint(self::HARDPOINT_REVISIONREFS),
|
||||
);
|
||||
}
|
||||
|
||||
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) {
|
||||
return $this->attachHardpoint(self::HARDPOINT_COMMITREF, $commit_ref);
|
||||
}
|
||||
|
||||
public function getCommitRef() {
|
||||
return $this->getHardpoint(self::HARDPOINT_COMMITREF);
|
||||
}
|
||||
|
||||
public function getRevisionRefs() {
|
||||
return $this->getHardpoint(self::HARDPOINT_REVISIONREFS);
|
||||
}
|
||||
|
||||
public function getRevisionRef() {
|
||||
if ($this->hasAmbiguousRevisionRefs()) {
|
||||
throw new Exception(
|
||||
pht('State has multiple ambiguous revisions refs.'));
|
||||
}
|
||||
|
||||
$refs = $this->getRevisionRefs();
|
||||
if ($refs) {
|
||||
return head($refs);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function hasAmbiguousRevisionRefs() {
|
||||
return (count($this->getRevisionRefs()) > 1);
|
||||
}
|
||||
|
||||
}
|
|
@ -82,7 +82,7 @@ final class ArcanistFilesystemAPI
|
|||
}
|
||||
|
||||
public function getRemoteURI() {
|
||||
throw new PhutilMethodNotImplementedException();
|
||||
return null;
|
||||
}
|
||||
|
||||
public function supportsLocalCommits() {
|
||||
|
@ -90,7 +90,9 @@ final class ArcanistFilesystemAPI
|
|||
}
|
||||
|
||||
protected function buildLocalFuture(array $argv) {
|
||||
throw new PhutilMethodNotImplementedException();
|
||||
$future = newv('ExecFuture', $argv);
|
||||
$future->setCWD($this->getPath());
|
||||
return $future;
|
||||
}
|
||||
|
||||
public function supportsCommitRanges() {
|
||||
|
|
88
src/toolset/query/ArcanistWorkflowHardpointQuery.php
Normal file
88
src/toolset/query/ArcanistWorkflowHardpointQuery.php
Normal file
|
@ -0,0 +1,88 @@
|
|||
<?php
|
||||
|
||||
abstract class ArcanistWorkflowHardpointQuery
|
||||
extends ArcanistHardpointQuery {
|
||||
|
||||
private $workflow;
|
||||
private $canLoadHardpoint;
|
||||
|
||||
final public function setWorkflow(ArcanistWorkflow $workflow) {
|
||||
$this->workflow = $workflow;
|
||||
return $this;
|
||||
}
|
||||
|
||||
final public function getWorkflow() {
|
||||
return $this->workflow;
|
||||
}
|
||||
|
||||
final public function getWorkingCopy() {
|
||||
return $this->getWorkflow()->getWorkingCopy();
|
||||
}
|
||||
|
||||
final public function getRepositoryAPI() {
|
||||
return $this->getWorkingCopy()->getRepositoryAPI();
|
||||
}
|
||||
|
||||
public static function getAllQueries() {
|
||||
return id(new PhutilClassMapQuery())
|
||||
->setAncestorClass(__CLASS__)
|
||||
->execute();
|
||||
}
|
||||
|
||||
final public function canLoadObject(ArcanistHardpointObject $object) {
|
||||
if ($this->canLoadHardpoint === null) {
|
||||
$this->canLoadHardpoint = $this->canLoadHardpoint();
|
||||
}
|
||||
|
||||
if (!$this->canLoadHardpoint) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$object instanceof ArcanistRefPro) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->canLoadRef($object);
|
||||
}
|
||||
|
||||
protected function canLoadHardpoint() {
|
||||
return true;
|
||||
}
|
||||
|
||||
abstract protected function canLoadRef(ArcanistRefPro $ref);
|
||||
|
||||
final public function yieldConduit($method, array $parameters) {
|
||||
$conduit_engine = $this->getWorkflow()
|
||||
->getConduitEngine();
|
||||
|
||||
$call_object = $conduit_engine->newCall($method, $parameters);
|
||||
$call_future = $conduit_engine->newFuture($call_object);
|
||||
|
||||
return $this->yieldFuture($call_future);
|
||||
}
|
||||
|
||||
final public function yieldRepositoryRef() {
|
||||
$workflow = $this->getWorkflow();
|
||||
|
||||
// TODO: This is currently a blocking request, but should yield to the
|
||||
// hardpoint engine in the future.
|
||||
|
||||
$repository_ref = $workflow->getRepositoryRef();
|
||||
$ref_future = new ImmediateFuture($repository_ref);
|
||||
|
||||
return $this->yieldFuture($ref_future);
|
||||
}
|
||||
|
||||
final public function yieldValue(array $refs, $value) {
|
||||
assert_instances_of($refs, 'ArcanistRefPro');
|
||||
|
||||
$keys = array_keys($refs);
|
||||
$map = array_fill_keys($keys, $value);
|
||||
return $this->yieldMap($map);
|
||||
}
|
||||
|
||||
final public function yieldMap(array $map) {
|
||||
return new ArcanistHardpointTaskResult($map);
|
||||
}
|
||||
|
||||
}
|
207
src/workflow/ArcanistInspectWorkflow.php
Normal file
207
src/workflow/ArcanistInspectWorkflow.php
Normal file
|
@ -0,0 +1,207 @@
|
|||
<?php
|
||||
|
||||
final class ArcanistInspectWorkflow
|
||||
extends ArcanistArcWorkflow {
|
||||
|
||||
public function getWorkflowName() {
|
||||
return 'inspect';
|
||||
}
|
||||
|
||||
public function getWorkflowInformation() {
|
||||
$help = pht(<<<EOTEXT
|
||||
Inspect internal object properties.
|
||||
EOTEXT
|
||||
);
|
||||
|
||||
return $this->newWorkflowInformation()
|
||||
->setSynopsis(pht('Show internal object information.'))
|
||||
->addExample(pht('**inspect** [__options__] -- __object__'))
|
||||
->setHelp($help);
|
||||
}
|
||||
|
||||
public function getWorkflowArguments() {
|
||||
return array(
|
||||
$this->newWorkflowArgument('all')
|
||||
->setHelp(pht('Load all object hardpoints.')),
|
||||
$this->newWorkflowArgument('objects')
|
||||
->setWildcard(true),
|
||||
);
|
||||
}
|
||||
|
||||
public function runWorkflow() {
|
||||
$is_all = $this->getArgument('all');
|
||||
$objects = $this->getArgument('objects');
|
||||
|
||||
$inspectors = ArcanistRefInspector::getAllInspectors();
|
||||
|
||||
if (!$objects) {
|
||||
echo tsprintf(
|
||||
"%s\n\n",
|
||||
pht('Choose an object to inspect:'));
|
||||
|
||||
foreach ($inspectors as $inspector) {
|
||||
echo tsprintf(
|
||||
" - %s\n",
|
||||
$inspector->getInspectFunctionName());
|
||||
}
|
||||
|
||||
echo tsprintf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
$all_refs = array();
|
||||
$ref_lists = array();
|
||||
foreach ($objects as $description) {
|
||||
$matches = null;
|
||||
if (!preg_match('/^(\w+)(?:\(([^)]+)\))?\z/', $description, $matches)) {
|
||||
throw new PhutilArgumentUsageException(
|
||||
pht(
|
||||
'Object specification "%s" is unknown, expected a specification '.
|
||||
'like "commit(HEAD)".'));
|
||||
}
|
||||
|
||||
$function = $matches[1];
|
||||
|
||||
if (!isset($inspectors[$function])) {
|
||||
ksort($inspectors);
|
||||
throw new PhutilArgumentUsageException(
|
||||
pht(
|
||||
'Unknown object type "%s", supported types are: %s.',
|
||||
$function,
|
||||
implode(', ', array_keys($inspectors))));
|
||||
}
|
||||
|
||||
$inspector = $inspectors[$function];
|
||||
|
||||
if (isset($matches[2])) {
|
||||
$arguments = array($matches[2]);
|
||||
} else {
|
||||
$arguments = array();
|
||||
}
|
||||
|
||||
$ref = $inspector->newInspectRef($arguments);
|
||||
|
||||
$ref_lists[get_class($ref)][] = $ref;
|
||||
$all_refs[] = $ref;
|
||||
}
|
||||
|
||||
if ($is_all) {
|
||||
foreach ($ref_lists as $ref_class => $refs) {
|
||||
$ref = head($refs);
|
||||
|
||||
$hardpoint_list = $ref->getHardpointList();
|
||||
$hardpoints = $hardpoint_list->getHardpoints();
|
||||
|
||||
if ($hardpoints) {
|
||||
$hardpoint_keys = mpull($hardpoints, 'getHardpointKey');
|
||||
|
||||
$this->loadHardpoints(
|
||||
$refs,
|
||||
$hardpoint_keys);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$list = array();
|
||||
foreach ($all_refs as $ref) {
|
||||
$out = $this->describeRef($ref, 0);
|
||||
$list[] = implode('', $out);
|
||||
}
|
||||
$list = implode("\n", $list);
|
||||
|
||||
echo tsprintf('%B', $list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private function describeRef(ArcanistRefPro $ref, $depth) {
|
||||
$indent = str_repeat(' ', $depth);
|
||||
|
||||
$out = array();
|
||||
$out[] = tsprintf(
|
||||
"%s+ [%s] %s\n",
|
||||
$indent,
|
||||
get_class($ref),
|
||||
$ref->getRefDisplayName());
|
||||
|
||||
$hardpoint_list = $ref->getHardpointList();
|
||||
foreach ($hardpoint_list->getHardpoints() as $hardpoint) {
|
||||
$lines = $this->describeHardpoint($ref, $hardpoint, $depth + 1);
|
||||
foreach ($lines as $line) {
|
||||
$out[] = $line;
|
||||
}
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
private function describeHardpoint(
|
||||
ArcanistRefPro $ref,
|
||||
ArcanistHardpoint $hardpoint,
|
||||
$depth) {
|
||||
$indent = str_repeat(' ', $depth);
|
||||
|
||||
$children = array();
|
||||
$values = array();
|
||||
|
||||
$hardpoint_key = $hardpoint->getHardpointKey();
|
||||
if ($ref->hasAttachedHardpoint($hardpoint_key)) {
|
||||
$mode = '*';
|
||||
$value = $ref->getHardpoint($hardpoint_key);
|
||||
if ($value instanceof ArcanistRefPro) {
|
||||
$children[] = $value;
|
||||
} else {
|
||||
$values[] = $value;
|
||||
}
|
||||
} else {
|
||||
$mode = 'o';
|
||||
}
|
||||
|
||||
$out = array();
|
||||
$out[] = tsprintf(
|
||||
"%s%s [%s] %s\n",
|
||||
$indent,
|
||||
$mode,
|
||||
get_class($hardpoint),
|
||||
$hardpoint->getHardpointKey());
|
||||
|
||||
foreach ($children as $child) {
|
||||
$lines = $this->describeRef($child, $depth + 1);
|
||||
foreach ($lines as $line) {
|
||||
$out[] = $line;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($values as $value) {
|
||||
$lines = $this->describeValue($value, $depth + 1);
|
||||
foreach ($lines as $line) {
|
||||
$out[] = $line;
|
||||
}
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
private function describeValue($value, $depth) {
|
||||
$indent = str_repeat(' ', $depth);
|
||||
|
||||
if (is_string($value)) {
|
||||
$display_value = '"'.addcslashes(substr($value, 0, 64), "\n\r\t\\\"").'"';
|
||||
} else if (is_scalar($value)) {
|
||||
$display_value = phutil_string_cast($value);
|
||||
} else if ($value === null) {
|
||||
$display_value = 'null';
|
||||
} else {
|
||||
$display_value = phutil_describe_type($value);
|
||||
}
|
||||
|
||||
$out = array();
|
||||
$out[] = tsprintf(
|
||||
"%s> %s\n",
|
||||
$indent,
|
||||
$display_value);
|
||||
return $out;
|
||||
}
|
||||
|
||||
}
|
|
@ -76,6 +76,8 @@ abstract class ArcanistWorkflow extends Phobject {
|
|||
private $configurationEngine;
|
||||
private $configurationSourceList;
|
||||
|
||||
private $hardpointEngine;
|
||||
|
||||
final public function setToolset(ArcanistToolset $toolset) {
|
||||
$this->toolset = $toolset;
|
||||
return $this;
|
||||
|
@ -2329,4 +2331,40 @@ abstract class ArcanistWorkflow extends Phobject {
|
|||
->setExecutableFuture($future);
|
||||
}
|
||||
|
||||
final protected function loadHardpoints(
|
||||
array $objects,
|
||||
array $requests) {
|
||||
|
||||
$engine = $this->getHardpointEngine();
|
||||
|
||||
$requests = $engine->requestHardpoints(
|
||||
$objects,
|
||||
$requests);
|
||||
|
||||
// TODO: Wait for only the required requests.
|
||||
$engine->waitForRequests(array());
|
||||
}
|
||||
|
||||
private function getHardpointEngine() {
|
||||
if ($this->hardpointEngine === null) {
|
||||
$this->hardpointEngine = $this->newHardpointEngine();
|
||||
}
|
||||
return $this->hardpointEngine;
|
||||
}
|
||||
|
||||
private function newHardpointEngine() {
|
||||
$engine = new ArcanistHardpointEngine();
|
||||
|
||||
$queries = ArcanistWorkflowHardpointQuery::getAllQueries();
|
||||
|
||||
foreach ($queries as $key => $query) {
|
||||
$queries[$key] = id(clone $query)
|
||||
->setWorkflow($this);
|
||||
}
|
||||
|
||||
$engine->setQueries($queries);
|
||||
|
||||
return $engine;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ final class ArcanistFilesystemWorkingCopy
|
|||
}
|
||||
|
||||
protected function newRepositoryAPI() {
|
||||
return new ArcanistFilesystemAPI();
|
||||
return new ArcanistFilesystemAPI($this->getPath());
|
||||
}
|
||||
|
||||
public function getProjectConfigurationFilePath() {
|
||||
|
|
|
@ -57,7 +57,7 @@ abstract class ArcanistWorkingCopy
|
|||
|
||||
$working_copy = new ArcanistFilesystemWorkingCopy();
|
||||
|
||||
self::configureWorkingCopy($working_copy, $ancestor_path, $path);
|
||||
self::configureWorkingCopy($working_copy, $path, $path);
|
||||
|
||||
return $working_copy;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue