Page MenuHomePhabricator

D21095.diff
No OneTemporary

D21095.diff

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
@@ -411,6 +411,7 @@
'ArcanistRubyLinterTestCase' => 'lint/linter/__tests__/ArcanistRubyLinterTestCase.php',
'ArcanistRuntime' => 'runtime/ArcanistRuntime.php',
'ArcanistRuntimeConfigurationSource' => 'config/source/ArcanistRuntimeConfigurationSource.php',
+ 'ArcanistRuntimeHardpointQuery' => 'toolset/query/ArcanistRuntimeHardpointQuery.php',
'ArcanistScalarConfigOption' => 'config/option/ArcanistScalarConfigOption.php',
'ArcanistScalarHardpoint' => 'hardpoint/ArcanistScalarHardpoint.php',
'ArcanistScriptAndRegexLinter' => 'lint/linter/ArcanistScriptAndRegexLinter.php',
@@ -507,7 +508,6 @@
'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',
'ArcanistWorkingCopyCommitHardpointQuery' => 'query/ArcanistWorkingCopyCommitHardpointQuery.php',
@@ -1006,7 +1006,7 @@
'ArcanistAliasFunctionXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistAliasWorkflow' => 'ArcanistWorkflow',
'ArcanistAliasesConfigOption' => 'ArcanistListConfigOption',
- 'ArcanistAmendWorkflow' => 'ArcanistWorkflow',
+ 'ArcanistAmendWorkflow' => 'ArcanistArcWorkflow',
'ArcanistAnoidWorkflow' => 'ArcanistArcWorkflow',
'ArcanistArcConfigurationEngineExtension' => 'ArcanistConfigurationEngineExtension',
'ArcanistArcToolset' => 'ArcanistToolset',
@@ -1035,14 +1035,14 @@
'ArcanistBraceFormattingXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistBranchRef' => 'ArcanistRef',
'ArcanistBranchWorkflow' => 'ArcanistFeatureBaseWorkflow',
- 'ArcanistBrowseCommitHardpointQuery' => 'ArcanistWorkflowHardpointQuery',
+ 'ArcanistBrowseCommitHardpointQuery' => 'ArcanistRuntimeHardpointQuery',
'ArcanistBrowseCommitURIHardpointQuery' => 'ArcanistBrowseURIHardpointQuery',
'ArcanistBrowseObjectNameURIHardpointQuery' => 'ArcanistBrowseURIHardpointQuery',
'ArcanistBrowsePathURIHardpointQuery' => 'ArcanistBrowseURIHardpointQuery',
'ArcanistBrowseRef' => 'ArcanistRef',
'ArcanistBrowseRefInspector' => 'ArcanistRefInspector',
'ArcanistBrowseRevisionURIHardpointQuery' => 'ArcanistBrowseURIHardpointQuery',
- 'ArcanistBrowseURIHardpointQuery' => 'ArcanistWorkflowHardpointQuery',
+ 'ArcanistBrowseURIHardpointQuery' => 'ArcanistRuntimeHardpointQuery',
'ArcanistBrowseURIRef' => 'ArcanistRef',
'ArcanistBrowseWorkflow' => 'ArcanistArcWorkflow',
'ArcanistBuildPlanRef' => 'Phobject',
@@ -1085,7 +1085,7 @@
'ArcanistCommitRef' => 'ArcanistRef',
'ArcanistCommitSymbolRef' => 'ArcanistSymbolRef',
'ArcanistCommitSymbolRefInspector' => 'ArcanistRefInspector',
- 'ArcanistCommitUpstreamHardpointQuery' => 'ArcanistWorkflowHardpointQuery',
+ 'ArcanistCommitUpstreamHardpointQuery' => 'ArcanistRuntimeHardpointQuery',
'ArcanistCommitWorkflow' => 'ArcanistWorkflow',
'ArcanistCompilerLintRenderer' => 'ArcanistLintRenderer',
'ArcanistComposerLinter' => 'ArcanistLinter',
@@ -1298,7 +1298,7 @@
'ArcanistMercurialWorkingCopy' => 'ArcanistWorkingCopy',
'ArcanistMergeConflictLinter' => 'ArcanistLinter',
'ArcanistMergeConflictLinterTestCase' => 'ArcanistLinterTestCase',
- 'ArcanistMessageRevisionHardpointQuery' => 'ArcanistWorkflowHardpointQuery',
+ 'ArcanistMessageRevisionHardpointQuery' => 'ArcanistRuntimeHardpointQuery',
'ArcanistMissingArgumentTerminatorException' => 'Exception',
'ArcanistMissingLinterException' => 'Exception',
'ArcanistModifierOrderingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
@@ -1381,13 +1381,13 @@
'ArcanistReusedIteratorXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistReusedIteratorXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistRevertWorkflow' => 'ArcanistWorkflow',
- 'ArcanistRevisionCommitMessageHardpointQuery' => 'ArcanistWorkflowHardpointQuery',
+ 'ArcanistRevisionCommitMessageHardpointQuery' => 'ArcanistRuntimeHardpointQuery',
'ArcanistRevisionRef' => array(
'ArcanistRef',
'ArcanistDisplayRefInterface',
),
'ArcanistRevisionRefSource' => 'Phobject',
- 'ArcanistRevisionSymbolHardpointQuery' => 'ArcanistWorkflowHardpointQuery',
+ 'ArcanistRevisionSymbolHardpointQuery' => 'ArcanistRuntimeHardpointQuery',
'ArcanistRevisionSymbolRef' => 'ArcanistSymbolRef',
'ArcanistRevisionSymbolRefInspector' => 'ArcanistRefInspector',
'ArcanistRuboCopLinter' => 'ArcanistExternalLinter',
@@ -1395,6 +1395,7 @@
'ArcanistRubyLinter' => 'ArcanistExternalLinter',
'ArcanistRubyLinterTestCase' => 'ArcanistExternalLinterTestCase',
'ArcanistRuntimeConfigurationSource' => 'ArcanistDictionaryConfigurationSource',
+ 'ArcanistRuntimeHardpointQuery' => 'ArcanistHardpointQuery',
'ArcanistScalarConfigOption' => 'ArcanistConfigOption',
'ArcanistScalarHardpoint' => 'ArcanistHardpoint',
'ArcanistScriptAndRegexLinter' => 'ArcanistLinter',
@@ -1478,7 +1479,7 @@
'ArcanistRef',
'ArcanistDisplayRefInterface',
),
- 'ArcanistUserSymbolHardpointQuery' => 'ArcanistWorkflowHardpointQuery',
+ 'ArcanistUserSymbolHardpointQuery' => 'ArcanistRuntimeHardpointQuery',
'ArcanistUserSymbolRef' => 'ArcanistSymbolRef',
'ArcanistUserSymbolRefInspector' => 'ArcanistRefInspector',
'ArcanistVariableReferenceSpacingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
@@ -1492,11 +1493,10 @@
'ArcanistWildConfigOption' => 'ArcanistConfigOption',
'ArcanistWorkflow' => 'Phobject',
'ArcanistWorkflowArgument' => 'Phobject',
- 'ArcanistWorkflowGitHardpointQuery' => 'ArcanistWorkflowHardpointQuery',
- 'ArcanistWorkflowHardpointQuery' => 'ArcanistHardpointQuery',
+ 'ArcanistWorkflowGitHardpointQuery' => 'ArcanistRuntimeHardpointQuery',
'ArcanistWorkflowInformation' => 'Phobject',
'ArcanistWorkingCopy' => 'Phobject',
- 'ArcanistWorkingCopyCommitHardpointQuery' => 'ArcanistWorkflowHardpointQuery',
+ 'ArcanistWorkingCopyCommitHardpointQuery' => 'ArcanistRuntimeHardpointQuery',
'ArcanistWorkingCopyConfigurationSource' => 'ArcanistFilesystemConfigurationSource',
'ArcanistWorkingCopyIdentity' => 'Phobject',
'ArcanistWorkingCopyPath' => 'Phobject',
diff --git a/src/browse/query/ArcanistBrowseCommitHardpointQuery.php b/src/browse/query/ArcanistBrowseCommitHardpointQuery.php
--- a/src/browse/query/ArcanistBrowseCommitHardpointQuery.php
+++ b/src/browse/query/ArcanistBrowseCommitHardpointQuery.php
@@ -1,7 +1,7 @@
<?php
final class ArcanistBrowseCommitHardpointQuery
- extends ArcanistWorkflowHardpointQuery {
+ extends ArcanistRuntimeHardpointQuery {
public function getHardpoints() {
return array(
diff --git a/src/browse/query/ArcanistBrowseURIHardpointQuery.php b/src/browse/query/ArcanistBrowseURIHardpointQuery.php
--- a/src/browse/query/ArcanistBrowseURIHardpointQuery.php
+++ b/src/browse/query/ArcanistBrowseURIHardpointQuery.php
@@ -1,7 +1,7 @@
<?php
abstract class ArcanistBrowseURIHardpointQuery
- extends ArcanistWorkflowHardpointQuery {
+ extends ArcanistRuntimeHardpointQuery {
public function getSupportedBrowseType() {
return $this->getPhobjectClassConstant('BROWSETYPE', 32);
diff --git a/src/query/ArcanistCommitUpstreamHardpointQuery.php b/src/query/ArcanistCommitUpstreamHardpointQuery.php
--- a/src/query/ArcanistCommitUpstreamHardpointQuery.php
+++ b/src/query/ArcanistCommitUpstreamHardpointQuery.php
@@ -1,7 +1,7 @@
<?php
final class ArcanistCommitUpstreamHardpointQuery
- extends ArcanistWorkflowHardpointQuery {
+ extends ArcanistRuntimeHardpointQuery {
public function getHardpoints() {
return array(
diff --git a/src/query/ArcanistMessageRevisionHardpointQuery.php b/src/query/ArcanistMessageRevisionHardpointQuery.php
--- a/src/query/ArcanistMessageRevisionHardpointQuery.php
+++ b/src/query/ArcanistMessageRevisionHardpointQuery.php
@@ -1,7 +1,7 @@
<?php
final class ArcanistMessageRevisionHardpointQuery
- extends ArcanistWorkflowHardpointQuery {
+ extends ArcanistRuntimeHardpointQuery {
public function getHardpoints() {
return array(
diff --git a/src/query/ArcanistWorkflowGitHardpointQuery.php b/src/query/ArcanistWorkflowGitHardpointQuery.php
--- a/src/query/ArcanistWorkflowGitHardpointQuery.php
+++ b/src/query/ArcanistWorkflowGitHardpointQuery.php
@@ -1,7 +1,7 @@
<?php
abstract class ArcanistWorkflowGitHardpointQuery
- extends ArcanistWorkflowHardpointQuery {
+ extends ArcanistRuntimeHardpointQuery {
final protected function canLoadHardpoint() {
$api = $this->getRepositoryAPI();
diff --git a/src/query/ArcanistWorkingCopyCommitHardpointQuery.php b/src/query/ArcanistWorkingCopyCommitHardpointQuery.php
--- a/src/query/ArcanistWorkingCopyCommitHardpointQuery.php
+++ b/src/query/ArcanistWorkingCopyCommitHardpointQuery.php
@@ -1,7 +1,7 @@
<?php
final class ArcanistWorkingCopyCommitHardpointQuery
- extends ArcanistWorkflowHardpointQuery {
+ extends ArcanistRuntimeHardpointQuery {
public function getHardpoints() {
return array(
diff --git a/src/ref/revision/ArcanistRevisionCommitMessageHardpointQuery.php b/src/ref/revision/ArcanistRevisionCommitMessageHardpointQuery.php
--- a/src/ref/revision/ArcanistRevisionCommitMessageHardpointQuery.php
+++ b/src/ref/revision/ArcanistRevisionCommitMessageHardpointQuery.php
@@ -1,7 +1,7 @@
<?php
final class ArcanistRevisionCommitMessageHardpointQuery
- extends ArcanistWorkflowHardpointQuery {
+ extends ArcanistRuntimeHardpointQuery {
public function getHardpoints() {
return array(
diff --git a/src/ref/revision/ArcanistRevisionRef.php b/src/ref/revision/ArcanistRevisionRef.php
--- a/src/ref/revision/ArcanistRevisionRef.php
+++ b/src/ref/revision/ArcanistRevisionRef.php
@@ -79,6 +79,10 @@
return $this->sources;
}
+ public function getCommitMessage() {
+ return $this->getHardpoint(self::HARDPOINT_COMMITMESSAGE);
+ }
+
public function getDisplayRefObjectName() {
return $this->getMonogram();
}
diff --git a/src/ref/revision/ArcanistRevisionSymbolHardpointQuery.php b/src/ref/revision/ArcanistRevisionSymbolHardpointQuery.php
--- a/src/ref/revision/ArcanistRevisionSymbolHardpointQuery.php
+++ b/src/ref/revision/ArcanistRevisionSymbolHardpointQuery.php
@@ -1,7 +1,7 @@
<?php
final class ArcanistRevisionSymbolHardpointQuery
- extends ArcanistWorkflowHardpointQuery {
+ extends ArcanistRuntimeHardpointQuery {
public function getHardpoints() {
return array(
diff --git a/src/ref/user/ArcanistUserRef.php b/src/ref/user/ArcanistUserRef.php
--- a/src/ref/user/ArcanistUserRef.php
+++ b/src/ref/user/ArcanistUserRef.php
@@ -8,7 +8,7 @@
private $parameters;
public function getRefDisplayName() {
- return pht('User "%s"', $this->getUsername());
+ return pht('User "%s"', $this->getMonogram());
}
public static function newFromConduit(array $parameters) {
@@ -29,6 +29,18 @@
return self::newFromConduit($parameters);
}
+ public function getID() {
+ return idx($this->parameters, 'id');
+ }
+
+ public function getPHID() {
+ return idx($this->parameters, 'phid');
+ }
+
+ public function getMonogram() {
+ return '@'.$this->getUsername();
+ }
+
public function getUsername() {
return idxv($this->parameters, array('fields', 'username'));
}
@@ -38,7 +50,7 @@
}
public function getDisplayRefObjectName() {
- return '@'.$this->getUsername();
+ return $this->getMonogram();
}
public function getDisplayRefTitle() {
diff --git a/src/ref/user/ArcanistUserSymbolHardpointQuery.php b/src/ref/user/ArcanistUserSymbolHardpointQuery.php
--- a/src/ref/user/ArcanistUserSymbolHardpointQuery.php
+++ b/src/ref/user/ArcanistUserSymbolHardpointQuery.php
@@ -1,7 +1,7 @@
<?php
final class ArcanistUserSymbolHardpointQuery
- extends ArcanistWorkflowHardpointQuery {
+ extends ArcanistRuntimeHardpointQuery {
public function getHardpoints() {
return array(
diff --git a/src/repository/api/ArcanistGitAPI.php b/src/repository/api/ArcanistGitAPI.php
--- a/src/repository/api/ArcanistGitAPI.php
+++ b/src/repository/api/ArcanistGitAPI.php
@@ -1687,4 +1687,8 @@
return null;
}
+ protected function newCurrentCommitSymbol() {
+ return 'HEAD';
+ }
+
}
diff --git a/src/repository/api/ArcanistRepositoryAPI.php b/src/repository/api/ArcanistRepositoryAPI.php
--- a/src/repository/api/ArcanistRepositoryAPI.php
+++ b/src/repository/api/ArcanistRepositoryAPI.php
@@ -39,6 +39,10 @@
private $symbolicBaseCommit;
private $resolvedBaseCommit;
+ private $runtime;
+ private $currentWorkingCopyStateRef = false;
+ private $currentCommitRef = false;
+
abstract public function getSourceControlSystemName();
public function getDiffLinesOfContext() {
@@ -665,48 +669,69 @@
return null;
}
- final public function newCommitRef() {
- return new ArcanistCommitRef();
- }
-
- final public function newBranchRef() {
- return new ArcanistBranchRef();
- }
-
- final public function getCurrentCommitRef() {
- $commit_hash = $this->newCurrentCommitHash();
- return $this->newCommitRef()
- ->setCommitHash($commit_hash);
+ final public function newFuture($pattern /* , ... */) {
+ $args = func_get_args();
+ return $this->buildLocalFuture($args)
+ ->setResolveOnError(false);
}
- protected function newCurrentCommitRef() {
- $commit_hash = $this->newCurrentCommitHash();
- return $this->newCommitRefForSymbol($commit_hash);
+ final public function setRuntime(ArcanistRuntime $runtime) {
+ $this->runtime = $runtime;
+ return $this;
}
- protected function newCommitRefForSymbol() {
- throw new ArcanistCapabilityNotSupportedException($this);
+ final public function getRuntime() {
+ return $this->runtime;
}
- protected function newCurrentCommitHash() {
- throw new ArcanistCapabilityNotSupportedException($this);
+ final protected function getSymbolEngine() {
+ return $this->getRuntime()->getSymbolEngine();
}
final public function getCurrentWorkingCopyStateRef() {
- return $this->newCurrentWorkingCopyStateRef();
+ if ($this->currentWorkingCopyStateRef === false) {
+ $ref = $this->newCurrentWorkingCopyStateRef();
+ $this->currentWorkingCopyStateRef = $ref;
+ }
+
+ return $this->currentWorkingCopyStateRef;
}
protected function newCurrentWorkingCopyStateRef() {
$commit_ref = $this->getCurrentCommitRef();
+ if (!$commit_ref) {
+ return null;
+ }
+
return id(new ArcanistWorkingCopyStateRef())
->setCommitRef($commit_ref);
}
- final public function newFuture($pattern /* , ... */) {
- $args = func_get_args();
- return $this->buildLocalFuture($args)
- ->setResolveOnError(false);
+ final public function getCurrentCommitRef() {
+ if ($this->currentCommitRef === false) {
+ $this->currentCommitRef = $this->newCurrentCommitRef();
+ }
+ return $this->currentCommitRef;
+ }
+
+ protected function newCurrentCommitRef() {
+ $symbols = $this->getSymbolEngine();
+
+ $commit_symbol = $this->newCurrentCommitSymbol();
+
+ return $symbols->loadCommitForSymbol($commit_symbol);
}
+ protected function newCurrentCommitSymbol() {
+ throw new ArcanistCapabilityNotSupportedException($this);
+ }
+
+ final public function newCommitRef() {
+ return new ArcanistCommitRef();
+ }
+
+ final public function newBranchRef() {
+ return new ArcanistBranchRef();
+ }
}
diff --git a/src/runtime/ArcanistRuntime.php b/src/runtime/ArcanistRuntime.php
--- a/src/runtime/ArcanistRuntime.php
+++ b/src/runtime/ArcanistRuntime.php
@@ -8,6 +8,12 @@
private $stack = array();
+ private $viewer;
+ private $hardpointEngine;
+ private $symbolEngine;
+ private $conduitEngine;
+ private $workingCopy;
+
public function execute(array $argv) {
try {
@@ -108,6 +114,7 @@
$this->workflows = $workflows;
$conduit_engine = $this->newConduitEngine($config);
+ $this->conduitEngine = $conduit_engine;
$phutil_workflows = array();
foreach ($workflows as $key => $workflow) {
@@ -301,9 +308,14 @@
->setArguments($args);
$working_copy = ArcanistWorkingCopy::newFromWorkingDirectory(getcwd());
- if ($working_copy) {
- $engine->setWorkingCopy($working_copy);
- }
+
+ $engine->setWorkingCopy($working_copy);
+
+ $this->workingCopy = $working_copy;
+
+ $working_copy
+ ->getRepositoryAPI()
+ ->setRuntime($this);
return $engine;
}
@@ -682,6 +694,10 @@
return $this->stack;
}
+ public function getCurrentWorkflow() {
+ return last($this->stack);
+ }
+
private function newConduitEngine(ArcanistConfigurationSourceList $config) {
$conduit_uri = $config->getConfig('phabricator.uri');
@@ -744,4 +760,81 @@
return phutil_passthru('%Ls', $effect->getArguments());
}
+ public function getSymbolEngine() {
+ if ($this->symbolEngine === null) {
+ $this->symbolEngine = $this->newSymbolEngine();
+ }
+ return $this->symbolEngine;
+ }
+
+ private function newSymbolEngine() {
+ return id(new ArcanistSymbolEngine())
+ ->setWorkflow($this);
+ }
+
+ public function getHardpointEngine() {
+ if ($this->hardpointEngine === null) {
+ $this->hardpointEngine = $this->newHardpointEngine();
+ }
+ return $this->hardpointEngine;
+ }
+
+ private function newHardpointEngine() {
+ $engine = new ArcanistHardpointEngine();
+
+ $queries = ArcanistRuntimeHardpointQuery::getAllQueries();
+
+ foreach ($queries as $key => $query) {
+ $queries[$key] = id(clone $query)
+ ->setRuntime($this);
+ }
+
+ $engine->setQueries($queries);
+
+ return $engine;
+ }
+
+ public function getViewer() {
+ if (!$this->viewer) {
+ $viewer = $this->getSymbolEngine()
+ ->loadUserForSymbol('viewer()');
+
+ // TODO: Deal with anonymous stuff.
+ if (!$viewer) {
+ throw new Exception(pht('No viewer!'));
+ }
+
+ $this->viewer = $viewer;
+ }
+
+ return $this->viewer;
+ }
+
+ public function loadHardpoints($objects, $requests) {
+ if (!is_array($objects)) {
+ $objects = array($objects);
+ }
+
+ if (!is_array($requests)) {
+ $requests = array($requests);
+ }
+
+ $engine = $this->getHardpointEngine();
+
+ $requests = $engine->requestHardpoints(
+ $objects,
+ $requests);
+
+ // TODO: Wait for only the required requests.
+ $engine->waitForRequests(array());
+ }
+
+ public function getWorkingCopy() {
+ return $this->workingCopy;
+ }
+
+ public function getConduitEngine() {
+ return $this->conduitEngine;
+ }
+
}
diff --git a/src/toolset/query/ArcanistWorkflowHardpointQuery.php b/src/toolset/query/ArcanistRuntimeHardpointQuery.php
rename from src/toolset/query/ArcanistWorkflowHardpointQuery.php
rename to src/toolset/query/ArcanistRuntimeHardpointQuery.php
--- a/src/toolset/query/ArcanistWorkflowHardpointQuery.php
+++ b/src/toolset/query/ArcanistRuntimeHardpointQuery.php
@@ -1,22 +1,22 @@
<?php
-abstract class ArcanistWorkflowHardpointQuery
+abstract class ArcanistRuntimeHardpointQuery
extends ArcanistHardpointQuery {
- private $workflow;
+ private $runtime;
private $canLoadHardpoint;
- final public function setWorkflow(ArcanistWorkflow $workflow) {
- $this->workflow = $workflow;
+ final public function setRuntime(ArcanistRuntime $runtime) {
+ $this->runtime = $runtime;
return $this;
}
- final public function getWorkflow() {
- return $this->workflow;
+ final public function getRuntime() {
+ return $this->runtime;
}
final public function getWorkingCopy() {
- return $this->getWorkflow()->getWorkingCopy();
+ return $this->getRuntime()->getWorkingCopy();
}
final public function getRepositoryAPI() {
@@ -52,7 +52,7 @@
abstract protected function canLoadRef(ArcanistRef $ref);
final public function newConduitSearch($method, $constraints) {
- $conduit_engine = $this->getWorkflow()
+ $conduit_engine = $this->getRuntime()
->getConduitEngine();
$conduit_future = id(new ConduitSearchFuture())
@@ -69,7 +69,7 @@
}
final public function newConduit($method, $parameters) {
- $conduit_engine = $this->getWorkflow()
+ $conduit_engine = $this->getRuntime()
->getConduitEngine();
$call_object = $conduit_engine->newCall($method, $parameters);
@@ -84,7 +84,10 @@
}
final public function yieldRepositoryRef() {
- $workflow = $this->getWorkflow();
+ // TODO: This should probably move to Runtime.
+
+ $runtime = $this->getRuntime();
+ $workflow = $runtime->getCurrentWorkflow();
// TODO: This is currently a blocking request, but should yield to the
// hardpoint engine in the future.
diff --git a/src/workflow/ArcanistAmendWorkflow.php b/src/workflow/ArcanistAmendWorkflow.php
--- a/src/workflow/ArcanistAmendWorkflow.php
+++ b/src/workflow/ArcanistAmendWorkflow.php
@@ -1,210 +1,278 @@
<?php
-/**
- * Synchronizes commit messages from Differential.
- */
-final class ArcanistAmendWorkflow extends ArcanistWorkflow {
+final class ArcanistAmendWorkflow
+ extends ArcanistArcWorkflow {
public function getWorkflowName() {
return 'amend';
}
- public function getCommandSynopses() {
- return phutil_console_format(<<<EOTEXT
- **amend** [--revision __revision_id__] [--show]
-EOTEXT
- );
- }
+ public function getWorkflowInformation() {
+ $help = pht(<<<EOTEXT
+Amend the working copy, synchronizing the local commit message from
+Differential.
- public function getCommandHelp() {
- return phutil_console_format(<<<EOTEXT
- Supports: git, hg
- Amend the working copy, synchronizing the local commit message from
- Differential.
-
- Supported in Mercurial 2.2 and newer.
+Supported in Mercurial 2.2 and newer.
EOTEXT
);
- }
- public function requiresWorkingCopy() {
- return true;
+ return $this->newWorkflowInformation()
+ ->setSynopsis(
+ pht('Amend the working copy, synchronizing the local commit message.'))
+ ->addExample('**amend** [options] -- ')
+ ->setHelp($help);
}
- public function requiresConduit() {
- return true;
- }
-
- public function requiresAuthentication() {
- return true;
- }
-
- public function requiresRepositoryAPI() {
- return true;
+ public function getWorkflowArguments() {
+ return array(
+ $this->newWorkflowArgument('show')
+ ->setHelp(
+ pht(
+ 'Show the amended commit message, without modifying the '.
+ 'working copy.')),
+ $this->newWorkflowArgument('revision')
+ ->setParameter('id')
+ ->setHelp(
+ pht(
+ 'Use the message from a specific revision. If you do not specify '.
+ 'a revision, arc will guess which revision is in the working '.
+ 'copy.')),
+ );
}
- public function getArguments() {
+ protected function newPrompts() {
return array(
- 'show' => array(
- 'help' => pht(
- 'Show the amended commit message, without modifying the '.
- 'working copy.'),
- ),
- 'revision' => array(
- 'param' => 'revision_id',
- 'help' => pht(
- 'Use the message from a specific revision. If you do not specify '.
- 'a revision, arc will guess which revision is in the working '.
- 'copy.'),
- ),
+ $this->newPrompt('arc.amend.unrelated')
+ ->setDescription(
+ pht(
+ 'Confirms use of a revision that does not appear to be '.
+ 'present in the working copy.')),
+ $this->newPrompt('arc.amend.author')
+ ->setDescription(
+ pht(
+ 'Confirms use of a revision that you are not the author '.
+ 'of.')),
+ $this->newPrompt('arc.amend.immutable')
+ ->setDescription(
+ pht(
+ 'Confirms history mutation in a working copy marked as '.
+ 'immutable.')),
);
}
- public function run() {
+ public function runWorkflow() {
+ $symbols = $this->getSymbolEngine();
+
$is_show = $this->getArgument('show');
$repository_api = $this->getRepositoryAPI();
if (!$is_show) {
- if (!$repository_api->supportsAmend()) {
- throw new ArcanistUsageException(
- pht(
- "You may only run '%s' in a git or hg ".
- "(version 2.2 or newer) working copy.",
- 'arc amend'));
- }
+ $this->requireAmendSupport($repository_api);
+ }
- if ($this->isHistoryImmutable()) {
- throw new ArcanistUsageException(
- pht(
- 'This project is marked as adhering to a conservative history '.
- 'mutability doctrine (having an immutable local history), which '.
- 'precludes amending commit messages.'));
- }
+ $revision_symbol = $this->getArgument('revision');
+
+ // We only care about the local working copy state if we need it to
+ // figure out which revision we're operating on, or we're planning to
+ // mutate it. If the caller is running "arc amend --show --revision X",
+ // the local state does not matter.
+
+ $need_state =
+ ($revision_symbol === null) ||
+ (!$is_show);
+
+ if ($need_state) {
+ $state_ref = $repository_api->getCurrentWorkingCopyStateRef();
+
+ $this->loadHardpoints(
+ $state_ref,
+ ArcanistWorkingCopyStateRef::HARDPOINT_REVISIONREFS);
+
+ $revision_refs = $state_ref->getRevisionRefs();
+ }
- if ($repository_api->getUncommittedChanges()) {
- throw new ArcanistUsageException(
+ if ($revision_symbol === null) {
+ $revision_ref = $this->selectRevisionRef($revision_refs);
+ } else {
+ $revision_ref = $symbols->loadRevisionForSymbol($revision_symbol);
+ if (!$revision_ref) {
+ throw new PhutilArgumentUsageException(
pht(
- 'You have uncommitted changes in this branch. Stage and commit '.
- '(or revert) them before proceeding.'));
+ 'Revision "%s" does not exist, or you do not have permission '.
+ 'to see it.',
+ $revision_symbol));
}
}
- $revision_id = null;
- if ($this->getArgument('revision')) {
- $revision_id = $this->normalizeRevisionID($this->getArgument('revision'));
+ if (!$is_show) {
+ echo tsprintf(
+ "%s\n\n%s\n",
+ pht('Amending commit message to reflect revision:'),
+ $revision_ref->newDisplayRef());
+
+ $this->confirmAmendAuthor($revision_ref);
+ $this->confirmAmendNotFound($revision_ref, $state_ref);
}
- $repository_api->setBaseCommitArgumentRules('arc:this');
- $in_working_copy = $repository_api->loadWorkingCopyDifferentialRevisions(
- $this->getConduit(),
- array(
- 'status' => 'status-any',
- ));
- $in_working_copy = ipull($in_working_copy, null, 'id');
+ $this->loadHardpoints(
+ $revision_ref,
+ ArcanistRevisionRef::HARDPOINT_COMMITMESSAGE);
+
+ $message = $revision_ref->getCommitMessage();
+
+ if ($is_show) {
+ echo tsprintf(
+ "%B\n",
+ $message);
+ } else {
+ $repository_api->amendCommit($message);
+ }
- if (!$revision_id) {
- if (count($in_working_copy) == 0) {
- throw new ArcanistUsageException(
+ return 0;
+ }
+
+ private function requireAmendSupport(ArcanistRepositoryAPI $api) {
+ if (!$api->supportsAmend()) {
+ if ($api instanceof ArcanistMercurialAPI) {
+ throw new PhutilArgumentUsageException(
pht(
- "No revision specified with '%s', and no revisions found ".
- "in the working copy. Use '%s' to specify which revision ".
- "you want to amend.",
- '--revision',
- '--revision <id>'));
- } else if (count($in_working_copy) > 1) {
- $message = pht(
- "More than one revision was found in the working copy:\n%s\n".
- "Use '%s' to specify which revision you want to amend.",
- $this->renderRevisionList($in_working_copy),
- '--revision <id>');
- throw new ArcanistUsageException($message);
- } else {
- $revision_id = key($in_working_copy);
- $revision = $in_working_copy[$revision_id];
- if ($revision['authorPHID'] != $this->getUserPHID()) {
- $other_author = $this->getConduit()->callMethodSynchronous(
- 'user.query',
- array(
- 'phids' => array($revision['authorPHID']),
- ));
- $other_author = ipull($other_author, 'userName', 'phid');
- $other_author = $other_author[$revision['authorPHID']];
- $rev_title = $revision['title'];
- $ok = phutil_console_confirm(
- pht(
- "You are amending the revision '%s' but you are not ".
- "the author. Amend this revision by %s?",
- "D{$revision_id}: {$rev_title}",
- $other_author));
- if (!$ok) {
- throw new ArcanistUserAbortException();
- }
- }
+ '"arc amend" is only supported under Mercurial 2.2 or newer. '.
+ 'Older versions of Mercurial do not support the "--amend" flag '.
+ 'to "hg commit ...", which this workflow requires.'));
}
+
+ throw new PhutilArgumentUsageException(
+ pht(
+ '"arc amend" must be run from inside a working copy of a '.
+ 'repository using a version control system that supports '.
+ 'amending commits, like Git or Mercurial.'));
}
- $conduit = $this->getConduit();
- try {
- $message = $conduit->callMethodSynchronous(
- 'differential.getcommitmessage',
- array(
- 'revision_id' => $revision_id,
- 'edit' => false,
- ));
- } catch (ConduitClientException $ex) {
- if (strpos($ex->getMessage(), 'ERR_NOT_FOUND') === false) {
- throw $ex;
- } else {
- throw new ArcanistUsageException(
- pht("Revision '%s' does not exist.", "D{$revision_id}")
- );
- }
+ if ($this->isHistoryImmutable()) {
+ echo tsprintf(
+ "%!\n\n%W\n",
+ pht('IMMUTABLE WORKING COPY'),
+ pht(
+ 'This working copy is configured to have an immutable local '.
+ 'history, using the "history.immutable" configuration option. '.
+ 'Amending the working copy will mutate local history.'));
+
+ $prompt = pht('Are you sure you want to mutate history?');
+
+ $this->getPrompt('arc.amend.immutable')
+ ->setQuery($prompt)
+ ->execute();
}
- $revision = $conduit->callMethodSynchronous(
- 'differential.query',
- array(
- 'ids' => array($revision_id),
- ));
- if (empty($revision)) {
- throw new Exception(
- pht("Failed to lookup information for '%s'!", "D{$revision_id}"));
+ return;
+
+ if ($api->getUncommittedChanges()) {
+ // TODO: Make this class of error show the uncommitted changes.
+
+ // TODO: This only needs to check for staged-but-uncommitted changes.
+ // We can safely amend with untracked and unstaged changes.
+
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'You have uncommitted changes in this working copy. Commit or '.
+ 'revert them before proceeding.'));
}
- $revision = head($revision);
- $revision_title = $revision['title'];
+ }
- if (!$is_show) {
- if ($revision_id && empty($in_working_copy[$revision_id])) {
- $ok = phutil_console_confirm(
- pht(
- "The revision '%s' does not appear to be in the working copy. Are ".
- "you sure you want to amend HEAD with the commit message for '%s'?",
- "D{$revision_id}",
- "D{$revision_id}: {$revision_title}"));
- if (!$ok) {
- throw new ArcanistUserAbortException();
- }
- }
+ private function selectRevisionRef(array $revisions) {
+ if (!$revisions) {
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'No revision specified with "--revision", and no revisions found '.
+ 'that match the current working copy state. Use "--revision <id>" '.
+ 'to specify which revision you want to amend.'));
}
- if ($is_show) {
- echo $message."\n";
- } else {
- echo pht(
- "Amending commit message to reflect revision %s.\n",
- phutil_console_format(
- '**D%d: %s**',
- $revision_id,
- $revision_title));
+ if (count($revisions) > 1) {
+ echo tsprintf(
+ "%!\n%W\n\n%B\n",
+ pht('MULTIPLE REVISIONS IN WORKING COPY'),
+ pht('More than one revision was found in the working copy:'),
+ mpull($revisions, 'newDisplayRef'));
- $repository_api->amendCommit($message);
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'Use "--revision <id>" to specify which revision you want '.
+ 'to amend.'));
}
- return 0;
+ return head($revisions);
}
- public function getSupportedRevisionControlSystems() {
- return array('git', 'hg');
+ private function confirmAmendAuthor(ArcanistRevisionRef $revision_ref) {
+ $viewer = $this->getViewer();
+ $viewer_phid = $viewer->getPHID();
+
+ $author_phid = $revision_ref->getAuthorPHID();
+
+ if ($viewer_phid === $author_phid) {
+ return;
+ }
+
+ $symbols = $this->getSymbolEngine();
+ $author_ref = $symbols->loadUserForSymbol($author_phid);
+ if (!$author_ref) {
+ // If we don't have any luck loading the author, skip this warning.
+ return;
+ }
+
+ echo tsprintf(
+ "%!\n\n%W\n\n%s",
+ pht('NOT REVISION AUTHOR'),
+ array(
+ pht(
+ 'You are amending the working copy using information from '.
+ 'a revision you are not the author of.'),
+ "\n\n",
+ pht(
+ 'The author of this revision (%s) is:',
+ $revision_ref->getMonogram()),
+ ),
+ $author_ref->newDisplayRef());
+
+ $prompt = pht(
+ 'Amend working copy using revision owned by %s?',
+ $author_ref->getMonogram());
+
+ $this->getPrompt('arc.amend.author')
+ ->setQuery($prompt)
+ ->execute();
+ }
+
+ private function confirmAmendNotFound(
+ ArcanistRevisionRef $revision_ref,
+ ArcanistWorkingCopyStateRef $state_ref) {
+
+ $local_refs = $state_ref->getRevisionRefs();
+ $local_refs = mpull($local_refs, null, 'getPHID');
+
+ $revision_phid = $revision_ref->getPHID();
+ $is_local = isset($local_refs[$revision_phid]);
+
+ if ($is_local) {
+ return;
+ }
+
+ echo tsprintf(
+ "%!\n\n%W\n",
+ pht('UNRELATED REVISION'),
+ pht(
+ 'You are amending the working copy using information from '.
+ 'a revision that does not appear to be associated with the '.
+ 'current state of the working copy.'));
+
+ $prompt = pht(
+ 'Amend working copy using unrelated revision %s?',
+ $revision_ref->getMonogram());
+
+ $this->getPrompt('arc.amend.unrelated')
+ ->setQuery($prompt)
+ ->execute();
}
}
diff --git a/src/workflow/ArcanistWorkflow.php b/src/workflow/ArcanistWorkflow.php
--- a/src/workflow/ArcanistWorkflow.php
+++ b/src/workflow/ArcanistWorkflow.php
@@ -76,9 +76,6 @@
private $configurationEngine;
private $configurationSourceList;
- private $viewer;
- private $hardpointEngine;
- private $symbolEngine;
private $promptMap;
final public function setToolset(ArcanistToolset $toolset) {
@@ -2303,45 +2300,7 @@
final public function loadHardpoints(
$objects,
$requests) {
-
- if (!is_array($objects)) {
- $objects = array($objects);
- }
-
- if (!is_array($requests)) {
- $requests = 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;
+ return $this->getRuntime()->loadHardpoints($objects, $requests);
}
protected function newPrompts() {
@@ -2404,31 +2363,11 @@
}
final protected function getSymbolEngine() {
- if ($this->symbolEngine === null) {
- $this->symbolEngine = $this->newSymbolEngine();
- }
- return $this->symbolEngine;
- }
-
- private function newSymbolEngine() {
- return id(new ArcanistSymbolEngine())
- ->setWorkflow($this);
+ return $this->getRuntime()->getSymbolEngine();
}
final protected function getViewer() {
- if (!$this->viewer) {
- $viewer = $this->getSymbolEngine()
- ->loadUserForSymbol('viewer()');
-
- // TODO: Deal with anonymous stuff.
- if (!$viewer) {
- throw new Exception(pht('No viewer!'));
- }
-
- $this->viewer = $viewer;
- }
-
- return $this->viewer;
+ return $this->getRuntime()->getViewer();
}
}
diff --git a/src/xsprintf/tsprintf.php b/src/xsprintf/tsprintf.php
--- a/src/xsprintf/tsprintf.php
+++ b/src/xsprintf/tsprintf.php
@@ -38,6 +38,23 @@
case 'R':
$type = 's';
break;
+ case 'W':
+ $value = PhutilTerminalString::escapeStringValue($value, true);
+ $value = phutil_console_wrap($value);
+ $type = 's';
+ break;
+ case '!':
+ $value = tsprintf('<bg:yellow>** <!> %s **</bg>', $value);
+ $value = PhutilTerminalString::escapeStringValue($value, false);
+ $type = 's';
+ break;
+ default:
+ throw new Exception(
+ pht(
+ 'Unsupported escape sequence "%s" found in pattern: %s',
+ $type,
+ $pattern));
+ break;
}
$pattern[$pos] = $type;

File Metadata

Mime Type
text/plain
Expires
Mon, Feb 3, 10:30 AM (1 h, 51 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7086734
Default Alt Text
D21095.diff (38 KB)

Event Timeline