mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-12-22 21:40:54 +01:00
Update "arc amend" for Toolsets
Summary: Ref T13490. Moves "arc amend" to Toolsets with modern ref/hardpoint code. Test Plan: Ran "arc amend --show", "--revision", etc. Hit all the prompts and errors, probably? Maniphest Tasks: T13490 Differential Revision: https://secure.phabricator.com/D21095
This commit is contained in:
parent
ff4c1e7c81
commit
0f2e277cd9
19 changed files with 476 additions and 311 deletions
|
@ -411,6 +411,7 @@ phutil_register_library_map(array(
|
|||
'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 @@ phutil_register_library_map(array(
|
|||
'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 @@ phutil_register_library_map(array(
|
|||
'ArcanistAliasFunctionXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
|
||||
'ArcanistAliasWorkflow' => 'ArcanistWorkflow',
|
||||
'ArcanistAliasesConfigOption' => 'ArcanistListConfigOption',
|
||||
'ArcanistAmendWorkflow' => 'ArcanistWorkflow',
|
||||
'ArcanistAmendWorkflow' => 'ArcanistArcWorkflow',
|
||||
'ArcanistAnoidWorkflow' => 'ArcanistArcWorkflow',
|
||||
'ArcanistArcConfigurationEngineExtension' => 'ArcanistConfigurationEngineExtension',
|
||||
'ArcanistArcToolset' => 'ArcanistToolset',
|
||||
|
@ -1035,14 +1035,14 @@ phutil_register_library_map(array(
|
|||
'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 @@ phutil_register_library_map(array(
|
|||
'ArcanistCommitRef' => 'ArcanistRef',
|
||||
'ArcanistCommitSymbolRef' => 'ArcanistSymbolRef',
|
||||
'ArcanistCommitSymbolRefInspector' => 'ArcanistRefInspector',
|
||||
'ArcanistCommitUpstreamHardpointQuery' => 'ArcanistWorkflowHardpointQuery',
|
||||
'ArcanistCommitUpstreamHardpointQuery' => 'ArcanistRuntimeHardpointQuery',
|
||||
'ArcanistCommitWorkflow' => 'ArcanistWorkflow',
|
||||
'ArcanistCompilerLintRenderer' => 'ArcanistLintRenderer',
|
||||
'ArcanistComposerLinter' => 'ArcanistLinter',
|
||||
|
@ -1298,7 +1298,7 @@ phutil_register_library_map(array(
|
|||
'ArcanistMercurialWorkingCopy' => 'ArcanistWorkingCopy',
|
||||
'ArcanistMergeConflictLinter' => 'ArcanistLinter',
|
||||
'ArcanistMergeConflictLinterTestCase' => 'ArcanistLinterTestCase',
|
||||
'ArcanistMessageRevisionHardpointQuery' => 'ArcanistWorkflowHardpointQuery',
|
||||
'ArcanistMessageRevisionHardpointQuery' => 'ArcanistRuntimeHardpointQuery',
|
||||
'ArcanistMissingArgumentTerminatorException' => 'Exception',
|
||||
'ArcanistMissingLinterException' => 'Exception',
|
||||
'ArcanistModifierOrderingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
|
||||
|
@ -1381,13 +1381,13 @@ phutil_register_library_map(array(
|
|||
'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 @@ phutil_register_library_map(array(
|
|||
'ArcanistRubyLinter' => 'ArcanistExternalLinter',
|
||||
'ArcanistRubyLinterTestCase' => 'ArcanistExternalLinterTestCase',
|
||||
'ArcanistRuntimeConfigurationSource' => 'ArcanistDictionaryConfigurationSource',
|
||||
'ArcanistRuntimeHardpointQuery' => 'ArcanistHardpointQuery',
|
||||
'ArcanistScalarConfigOption' => 'ArcanistConfigOption',
|
||||
'ArcanistScalarHardpoint' => 'ArcanistHardpoint',
|
||||
'ArcanistScriptAndRegexLinter' => 'ArcanistLinter',
|
||||
|
@ -1478,7 +1479,7 @@ phutil_register_library_map(array(
|
|||
'ArcanistRef',
|
||||
'ArcanistDisplayRefInterface',
|
||||
),
|
||||
'ArcanistUserSymbolHardpointQuery' => 'ArcanistWorkflowHardpointQuery',
|
||||
'ArcanistUserSymbolHardpointQuery' => 'ArcanistRuntimeHardpointQuery',
|
||||
'ArcanistUserSymbolRef' => 'ArcanistSymbolRef',
|
||||
'ArcanistUserSymbolRefInspector' => 'ArcanistRefInspector',
|
||||
'ArcanistVariableReferenceSpacingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
|
||||
|
@ -1492,11 +1493,10 @@ phutil_register_library_map(array(
|
|||
'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',
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
|
||||
final class ArcanistBrowseCommitHardpointQuery
|
||||
extends ArcanistWorkflowHardpointQuery {
|
||||
extends ArcanistRuntimeHardpointQuery {
|
||||
|
||||
public function getHardpoints() {
|
||||
return array(
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
|
||||
abstract class ArcanistBrowseURIHardpointQuery
|
||||
extends ArcanistWorkflowHardpointQuery {
|
||||
extends ArcanistRuntimeHardpointQuery {
|
||||
|
||||
public function getSupportedBrowseType() {
|
||||
return $this->getPhobjectClassConstant('BROWSETYPE', 32);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
|
||||
final class ArcanistCommitUpstreamHardpointQuery
|
||||
extends ArcanistWorkflowHardpointQuery {
|
||||
extends ArcanistRuntimeHardpointQuery {
|
||||
|
||||
public function getHardpoints() {
|
||||
return array(
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
|
||||
final class ArcanistMessageRevisionHardpointQuery
|
||||
extends ArcanistWorkflowHardpointQuery {
|
||||
extends ArcanistRuntimeHardpointQuery {
|
||||
|
||||
public function getHardpoints() {
|
||||
return array(
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
|
||||
abstract class ArcanistWorkflowGitHardpointQuery
|
||||
extends ArcanistWorkflowHardpointQuery {
|
||||
extends ArcanistRuntimeHardpointQuery {
|
||||
|
||||
final protected function canLoadHardpoint() {
|
||||
$api = $this->getRepositoryAPI();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
|
||||
final class ArcanistWorkingCopyCommitHardpointQuery
|
||||
extends ArcanistWorkflowHardpointQuery {
|
||||
extends ArcanistRuntimeHardpointQuery {
|
||||
|
||||
public function getHardpoints() {
|
||||
return array(
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
|
||||
final class ArcanistRevisionCommitMessageHardpointQuery
|
||||
extends ArcanistWorkflowHardpointQuery {
|
||||
extends ArcanistRuntimeHardpointQuery {
|
||||
|
||||
public function getHardpoints() {
|
||||
return array(
|
||||
|
|
|
@ -79,6 +79,10 @@ final class ArcanistRevisionRef
|
|||
return $this->sources;
|
||||
}
|
||||
|
||||
public function getCommitMessage() {
|
||||
return $this->getHardpoint(self::HARDPOINT_COMMITMESSAGE);
|
||||
}
|
||||
|
||||
public function getDisplayRefObjectName() {
|
||||
return $this->getMonogram();
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
|
||||
final class ArcanistRevisionSymbolHardpointQuery
|
||||
extends ArcanistWorkflowHardpointQuery {
|
||||
extends ArcanistRuntimeHardpointQuery {
|
||||
|
||||
public function getHardpoints() {
|
||||
return array(
|
||||
|
|
|
@ -8,7 +8,7 @@ final class ArcanistUserRef
|
|||
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 @@ final class ArcanistUserRef
|
|||
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 @@ final class ArcanistUserRef
|
|||
}
|
||||
|
||||
public function getDisplayRefObjectName() {
|
||||
return '@'.$this->getUsername();
|
||||
return $this->getMonogram();
|
||||
}
|
||||
|
||||
public function getDisplayRefTitle() {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<?php
|
||||
|
||||
final class ArcanistUserSymbolHardpointQuery
|
||||
extends ArcanistWorkflowHardpointQuery {
|
||||
extends ArcanistRuntimeHardpointQuery {
|
||||
|
||||
public function getHardpoints() {
|
||||
return array(
|
||||
|
|
|
@ -1687,4 +1687,8 @@ final class ArcanistGitAPI extends ArcanistRepositoryAPI {
|
|||
return null;
|
||||
}
|
||||
|
||||
protected function newCurrentCommitSymbol() {
|
||||
return 'HEAD';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -39,6 +39,10 @@ abstract class ArcanistRepositoryAPI extends Phobject {
|
|||
private $symbolicBaseCommit;
|
||||
private $resolvedBaseCommit;
|
||||
|
||||
private $runtime;
|
||||
private $currentWorkingCopyStateRef = false;
|
||||
private $currentCommitRef = false;
|
||||
|
||||
abstract public function getSourceControlSystemName();
|
||||
|
||||
public function getDiffLinesOfContext() {
|
||||
|
@ -665,6 +669,64 @@ abstract class ArcanistRepositoryAPI extends Phobject {
|
|||
return null;
|
||||
}
|
||||
|
||||
final public function newFuture($pattern /* , ... */) {
|
||||
$args = func_get_args();
|
||||
return $this->buildLocalFuture($args)
|
||||
->setResolveOnError(false);
|
||||
}
|
||||
|
||||
final public function setRuntime(ArcanistRuntime $runtime) {
|
||||
$this->runtime = $runtime;
|
||||
return $this;
|
||||
}
|
||||
|
||||
final public function getRuntime() {
|
||||
return $this->runtime;
|
||||
}
|
||||
|
||||
final protected function getSymbolEngine() {
|
||||
return $this->getRuntime()->getSymbolEngine();
|
||||
}
|
||||
|
||||
final public function getCurrentWorkingCopyStateRef() {
|
||||
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 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();
|
||||
}
|
||||
|
@ -672,41 +734,4 @@ abstract class ArcanistRepositoryAPI extends Phobject {
|
|||
final public function newBranchRef() {
|
||||
return new ArcanistBranchRef();
|
||||
}
|
||||
|
||||
final public function getCurrentCommitRef() {
|
||||
$commit_hash = $this->newCurrentCommitHash();
|
||||
return $this->newCommitRef()
|
||||
->setCommitHash($commit_hash);
|
||||
}
|
||||
|
||||
protected function newCurrentCommitRef() {
|
||||
$commit_hash = $this->newCurrentCommitHash();
|
||||
return $this->newCommitRefForSymbol($commit_hash);
|
||||
}
|
||||
|
||||
protected function newCommitRefForSymbol() {
|
||||
throw new ArcanistCapabilityNotSupportedException($this);
|
||||
}
|
||||
|
||||
protected function newCurrentCommitHash() {
|
||||
throw new ArcanistCapabilityNotSupportedException($this);
|
||||
}
|
||||
|
||||
final public function getCurrentWorkingCopyStateRef() {
|
||||
return $this->newCurrentWorkingCopyStateRef();
|
||||
}
|
||||
|
||||
protected function newCurrentWorkingCopyStateRef() {
|
||||
$commit_ref = $this->getCurrentCommitRef();
|
||||
|
||||
return id(new ArcanistWorkingCopyStateRef())
|
||||
->setCommitRef($commit_ref);
|
||||
}
|
||||
|
||||
final public function newFuture($pattern /* , ... */) {
|
||||
$args = func_get_args();
|
||||
return $this->buildLocalFuture($args)
|
||||
->setResolveOnError(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -8,6 +8,12 @@ final class ArcanistRuntime {
|
|||
|
||||
private $stack = array();
|
||||
|
||||
private $viewer;
|
||||
private $hardpointEngine;
|
||||
private $symbolEngine;
|
||||
private $conduitEngine;
|
||||
private $workingCopy;
|
||||
|
||||
public function execute(array $argv) {
|
||||
|
||||
try {
|
||||
|
@ -108,6 +114,7 @@ final class ArcanistRuntime {
|
|||
$this->workflows = $workflows;
|
||||
|
||||
$conduit_engine = $this->newConduitEngine($config);
|
||||
$this->conduitEngine = $conduit_engine;
|
||||
|
||||
$phutil_workflows = array();
|
||||
foreach ($workflows as $key => $workflow) {
|
||||
|
@ -301,9 +308,14 @@ final class ArcanistRuntime {
|
|||
->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 @@ final class ArcanistRuntime {
|
|||
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 @@ final class ArcanistRuntime {
|
|||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 class ArcanistWorkflowHardpointQuery
|
|||
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 @@ abstract class ArcanistWorkflowHardpointQuery
|
|||
}
|
||||
|
||||
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 @@ abstract class ArcanistWorkflowHardpointQuery
|
|||
}
|
||||
|
||||
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.
|
|
@ -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]
|
||||
public function getWorkflowInformation() {
|
||||
$help = pht(<<<EOTEXT
|
||||
Amend the working copy, synchronizing the local commit message from
|
||||
Differential.
|
||||
|
||||
Supported in Mercurial 2.2 and newer.
|
||||
EOTEXT
|
||||
);
|
||||
|
||||
return $this->newWorkflowInformation()
|
||||
->setSynopsis(
|
||||
pht('Amend the working copy, synchronizing the local commit message.'))
|
||||
->addExample('**amend** [options] -- ')
|
||||
->setHelp($help);
|
||||
}
|
||||
|
||||
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.
|
||||
EOTEXT
|
||||
);
|
||||
}
|
||||
|
||||
public function requiresWorkingCopy() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function requiresConduit() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function requiresAuthentication() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function requiresRepositoryAPI() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getArguments() {
|
||||
public function getWorkflowArguments() {
|
||||
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->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 run() {
|
||||
protected function newPrompts() {
|
||||
return array(
|
||||
$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 runWorkflow() {
|
||||
$symbols = $this->getSymbolEngine();
|
||||
|
||||
$is_show = $this->getArgument('show');
|
||||
|
||||
$repository_api = $this->getRepositoryAPI();
|
||||
if (!$is_show) {
|
||||
if (!$repository_api->supportsAmend()) {
|
||||
throw new ArcanistUsageException(
|
||||
$this->requireAmendSupport($repository_api);
|
||||
}
|
||||
|
||||
$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 ($revision_symbol === null) {
|
||||
$revision_ref = $this->selectRevisionRef($revision_refs);
|
||||
} else {
|
||||
$revision_ref = $symbols->loadRevisionForSymbol($revision_symbol);
|
||||
if (!$revision_ref) {
|
||||
throw new PhutilArgumentUsageException(
|
||||
pht(
|
||||
"You may only run '%s' in a git or hg ".
|
||||
"(version 2.2 or newer) working copy.",
|
||||
'arc amend'));
|
||||
}
|
||||
|
||||
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.'));
|
||||
}
|
||||
|
||||
if ($repository_api->getUncommittedChanges()) {
|
||||
throw new ArcanistUsageException(
|
||||
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'));
|
||||
}
|
||||
|
||||
$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');
|
||||
|
||||
if (!$revision_id) {
|
||||
if (count($in_working_copy) == 0) {
|
||||
throw new ArcanistUsageException(
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$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}")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$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}"));
|
||||
}
|
||||
$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();
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
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));
|
||||
$this->loadHardpoints(
|
||||
$revision_ref,
|
||||
ArcanistRevisionRef::HARDPOINT_COMMITMESSAGE);
|
||||
|
||||
$message = $revision_ref->getCommitMessage();
|
||||
|
||||
if ($is_show) {
|
||||
echo tsprintf(
|
||||
"%B\n",
|
||||
$message);
|
||||
} else {
|
||||
$repository_api->amendCommit($message);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getSupportedRevisionControlSystems() {
|
||||
return array('git', 'hg');
|
||||
private function requireAmendSupport(ArcanistRepositoryAPI $api) {
|
||||
if (!$api->supportsAmend()) {
|
||||
if ($api instanceof ArcanistMercurialAPI) {
|
||||
throw new PhutilArgumentUsageException(
|
||||
pht(
|
||||
'"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.'));
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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.'));
|
||||
}
|
||||
}
|
||||
|
||||
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 (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'));
|
||||
|
||||
throw new PhutilArgumentUsageException(
|
||||
pht(
|
||||
'Use "--revision <id>" to specify which revision you want '.
|
||||
'to amend.'));
|
||||
}
|
||||
|
||||
return head($revisions);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -76,9 +76,6 @@ abstract class ArcanistWorkflow extends Phobject {
|
|||
private $configurationEngine;
|
||||
private $configurationSourceList;
|
||||
|
||||
private $viewer;
|
||||
private $hardpointEngine;
|
||||
private $symbolEngine;
|
||||
private $promptMap;
|
||||
|
||||
final public function setToolset(ArcanistToolset $toolset) {
|
||||
|
@ -2303,45 +2300,7 @@ abstract class ArcanistWorkflow extends Phobject {
|
|||
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 @@ abstract class ArcanistWorkflow extends Phobject {
|
|||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -38,6 +38,23 @@ function xsprintf_terminal($userdata, &$pattern, &$pos, &$value, &$length) {
|
|||
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;
|
||||
|
|
Loading…
Reference in a new issue