Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14077196
D21078.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
33 KB
Referenced Files
None
Subscribers
None
D21078.diff
View Options
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -54,6 +54,7 @@
'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 @@
'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 @@
'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 @@
'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 @@
'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 @@
'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 @@
'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 @@
'ArcanistBraceFormattingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistBraceFormattingXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistBranchRef' => 'ArcanistRef',
+ 'ArcanistBranchRefPro' => 'ArcanistRefPro',
'ArcanistBranchWorkflow' => 'ArcanistFeatureWorkflow',
'ArcanistBrowseCommitHardpointLoader' => 'ArcanistHardpointLoader',
'ArcanistBrowseCommitURIHardpointLoader' => 'ArcanistBrowseURIHardpointLoader',
@@ -1058,7 +1071,10 @@
'ArcanistCommentStyleXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistCommentStyleXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistCommitRef' => 'ArcanistRef',
+ 'ArcanistCommitRefInspector' => 'ArcanistRefInspector',
+ 'ArcanistCommitRefPro' => 'ArcanistRefPro',
'ArcanistCommitUpstreamHardpointLoader' => 'ArcanistHardpointLoader',
+ 'ArcanistCommitUpstreamHardpointQuery' => 'ArcanistWorkflowHardpointQuery',
'ArcanistCommitWorkflow' => 'ArcanistWorkflow',
'ArcanistCompilerLintRenderer' => 'ArcanistLintRenderer',
'ArcanistComposerLinter' => 'ArcanistLinter',
@@ -1159,6 +1175,7 @@
'ArcanistGetConfigWorkflow' => 'ArcanistWorkflow',
'ArcanistGitAPI' => 'ArcanistRepositoryAPI',
'ArcanistGitCommitMessageHardpointLoader' => 'ArcanistGitHardpointLoader',
+ 'ArcanistGitCommitMessageHardpointQuery' => 'ArcanistWorkflowHardpointQuery',
'ArcanistGitHardpointLoader' => 'ArcanistHardpointLoader',
'ArcanistGitLandEngine' => 'ArcanistLandEngine',
'ArcanistGitRevisionHardpointLoader' => 'ArcanistGitHardpointLoader',
@@ -1182,6 +1199,7 @@
'ArcanistHardpointRequest' => 'Phobject',
'ArcanistHardpointRequestList' => 'Phobject',
'ArcanistHardpointTask' => 'Phobject',
+ 'ArcanistHardpointTaskResult' => 'Phobject',
'ArcanistHelpWorkflow' => 'ArcanistWorkflow',
'ArcanistHexadecimalNumericScalarCasingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistHexadecimalNumericScalarCasingXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
@@ -1201,6 +1219,7 @@
'ArcanistInlineHTMLXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistInnerFunctionXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistInnerFunctionXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
+ 'ArcanistInspectWorkflow' => 'ArcanistArcWorkflow',
'ArcanistInstallCertificateWorkflow' => 'ArcanistWorkflow',
'ArcanistInstanceOfOperatorXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistInstanceofOperatorXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
@@ -1337,6 +1356,8 @@
'ArcanistRaggedClassTreeEdgeXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistRaggedClassTreeEdgeXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistRef' => 'Phobject',
+ 'ArcanistRefInspector' => 'Phobject',
+ 'ArcanistRefPro' => 'ArcanistHardpointObject',
'ArcanistRefQuery' => 'Phobject',
'ArcanistRepositoryAPI' => 'Phobject',
'ArcanistRepositoryAPIMiscTestCase' => 'PhutilTestCase',
@@ -1444,12 +1465,15 @@
'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',
diff --git a/src/hardpoint/ArcanistHardpointList.php b/src/hardpoint/ArcanistHardpointList.php
--- a/src/hardpoint/ArcanistHardpointList.php
+++ b/src/hardpoint/ArcanistHardpointList.php
@@ -46,6 +46,10 @@
return isset($this->attached[$hardpoint]);
}
+ public function getHardpoints() {
+ return $this->hardpoints;
+ }
+
public function getHardpointDefinition($object, $hardpoint) {
if (!$this->hasHardpoint($object, $hardpoint)) {
throw new Exception(
diff --git a/src/hardpoint/ArcanistHardpointTask.php b/src/hardpoint/ArcanistHardpointTask.php
--- a/src/hardpoint/ArcanistHardpointTask.php
+++ b/src/hardpoint/ArcanistHardpointTask.php
@@ -100,6 +100,7 @@
$generator->next();
}
+ $generator_result = null;
if ($generator->valid()) {
$result = $generator->current();
@@ -152,17 +153,25 @@
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);
diff --git a/src/hardpoint/ArcanistHardpointTaskResult.php b/src/hardpoint/ArcanistHardpointTaskResult.php
new file mode 100644
--- /dev/null
+++ b/src/hardpoint/ArcanistHardpointTaskResult.php
@@ -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;
+ }
+
+}
diff --git a/src/inspector/ArcanistCommitRefInspector.php b/src/inspector/ArcanistCommitRefInspector.php
new file mode 100644
--- /dev/null
+++ b/src/inspector/ArcanistCommitRefInspector.php
@@ -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]);
+ }
+
+}
diff --git a/src/inspector/ArcanistRefInspector.php b/src/inspector/ArcanistRefInspector.php
new file mode 100644
--- /dev/null
+++ b/src/inspector/ArcanistRefInspector.php
@@ -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();
+ }
+
+}
diff --git a/src/query/ArcanistCommitUpstreamHardpointQuery.php b/src/query/ArcanistCommitUpstreamHardpointQuery.php
new file mode 100644
--- /dev/null
+++ b/src/query/ArcanistCommitUpstreamHardpointQuery.php
@@ -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);
+ }
+
+}
diff --git a/src/query/ArcanistGitCommitMessageHardpointQuery.php b/src/query/ArcanistGitCommitMessageHardpointQuery.php
new file mode 100644
--- /dev/null
+++ b/src/query/ArcanistGitCommitMessageHardpointQuery.php
@@ -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);
+ }
+
+}
diff --git a/src/query/ArcanistWorkingCopyCommitHardpointQuery.php b/src/query/ArcanistWorkingCopyCommitHardpointQuery.php
new file mode 100644
--- /dev/null
+++ b/src/query/ArcanistWorkingCopyCommitHardpointQuery.php
@@ -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);
+ }
+
+}
diff --git a/src/ref/ArcanistBranchRefPro.php b/src/ref/ArcanistBranchRefPro.php
new file mode 100644
--- /dev/null
+++ b/src/ref/ArcanistBranchRefPro.php
@@ -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);
+ }
+
+}
diff --git a/src/ref/ArcanistCommitRefPro.php b/src/ref/ArcanistCommitRefPro.php
new file mode 100644
--- /dev/null
+++ b/src/ref/ArcanistCommitRefPro.php
@@ -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);
+ }
+
+}
diff --git a/src/ref/ArcanistRefPro.php b/src/ref/ArcanistRefPro.php
new file mode 100644
--- /dev/null
+++ b/src/ref/ArcanistRefPro.php
@@ -0,0 +1,8 @@
+<?php
+
+abstract class ArcanistRefPro
+ extends ArcanistHardpointObject {
+
+ abstract public function getRefDisplayName();
+
+}
diff --git a/src/ref/ArcanistWorkingCopyStateRefPro.php b/src/ref/ArcanistWorkingCopyStateRefPro.php
new file mode 100644
--- /dev/null
+++ b/src/ref/ArcanistWorkingCopyStateRefPro.php
@@ -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);
+ }
+
+}
diff --git a/src/repository/api/ArcanistFilesystemAPI.php b/src/repository/api/ArcanistFilesystemAPI.php
--- a/src/repository/api/ArcanistFilesystemAPI.php
+++ b/src/repository/api/ArcanistFilesystemAPI.php
@@ -82,7 +82,7 @@
}
public function getRemoteURI() {
- throw new PhutilMethodNotImplementedException();
+ return null;
}
public function supportsLocalCommits() {
@@ -90,7 +90,9 @@
}
protected function buildLocalFuture(array $argv) {
- throw new PhutilMethodNotImplementedException();
+ $future = newv('ExecFuture', $argv);
+ $future->setCWD($this->getPath());
+ return $future;
}
public function supportsCommitRanges() {
diff --git a/src/toolset/query/ArcanistWorkflowHardpointQuery.php b/src/toolset/query/ArcanistWorkflowHardpointQuery.php
new file mode 100644
--- /dev/null
+++ b/src/toolset/query/ArcanistWorkflowHardpointQuery.php
@@ -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);
+ }
+
+}
diff --git a/src/workflow/ArcanistInspectWorkflow.php b/src/workflow/ArcanistInspectWorkflow.php
new file mode 100644
--- /dev/null
+++ b/src/workflow/ArcanistInspectWorkflow.php
@@ -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;
+ }
+
+}
diff --git a/src/workflow/ArcanistWorkflow.php b/src/workflow/ArcanistWorkflow.php
--- a/src/workflow/ArcanistWorkflow.php
+++ b/src/workflow/ArcanistWorkflow.php
@@ -76,6 +76,8 @@
private $configurationEngine;
private $configurationSourceList;
+ private $hardpointEngine;
+
final public function setToolset(ArcanistToolset $toolset) {
$this->toolset = $toolset;
return $this;
@@ -2329,4 +2331,40 @@
->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;
+ }
+
}
diff --git a/src/workingcopy/ArcanistFilesystemWorkingCopy.php b/src/workingcopy/ArcanistFilesystemWorkingCopy.php
--- a/src/workingcopy/ArcanistFilesystemWorkingCopy.php
+++ b/src/workingcopy/ArcanistFilesystemWorkingCopy.php
@@ -14,7 +14,7 @@
}
protected function newRepositoryAPI() {
- return new ArcanistFilesystemAPI();
+ return new ArcanistFilesystemAPI($this->getPath());
}
public function getProjectConfigurationFilePath() {
diff --git a/src/workingcopy/ArcanistWorkingCopy.php b/src/workingcopy/ArcanistWorkingCopy.php
--- a/src/workingcopy/ArcanistWorkingCopy.php
+++ b/src/workingcopy/ArcanistWorkingCopy.php
@@ -57,7 +57,7 @@
$working_copy = new ArcanistFilesystemWorkingCopy();
- self::configureWorkingCopy($working_copy, $ancestor_path, $path);
+ self::configureWorkingCopy($working_copy, $path, $path);
return $working_copy;
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Nov 22, 9:54 PM (18 h, 8 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6776089
Default Alt Text
D21078.diff (33 KB)
Attached To
Mode
D21078: Introduce "arc inspect" and some of the new ref/hardpoint classes
Attached
Detach File
Event Timeline
Log In to Comment