1
0
Fork 0
mirror of https://we.phorge.it/source/arcanist.git synced 2024-11-14 02:42:40 +01:00

Port "arc help" to Toolsets

Summary: Ref T13395. Make "arc help" run as a toolset command, not a classic command.

Test Plan: Ran "arc help".

Maniphest Tasks: T13395

Differential Revision: https://secure.phabricator.com/D20991
This commit is contained in:
epriestley 2020-02-13 14:30:22 -08:00
parent c471983697
commit 0e95fcbb7f
5 changed files with 85 additions and 228 deletions

View file

@ -30,6 +30,7 @@ phutil_register_library_map(array(
'ArcanistAnoidWorkflow' => 'workflow/ArcanistAnoidWorkflow.php', 'ArcanistAnoidWorkflow' => 'workflow/ArcanistAnoidWorkflow.php',
'ArcanistArcConfigurationEngineExtension' => 'config/arc/ArcanistArcConfigurationEngineExtension.php', 'ArcanistArcConfigurationEngineExtension' => 'config/arc/ArcanistArcConfigurationEngineExtension.php',
'ArcanistArcToolset' => 'toolset/ArcanistArcToolset.php', 'ArcanistArcToolset' => 'toolset/ArcanistArcToolset.php',
'ArcanistArcWorkflow' => 'toolset/workflow/ArcanistArcWorkflow.php',
'ArcanistArrayCombineXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistArrayCombineXHPASTLinterRule.php', 'ArcanistArrayCombineXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistArrayCombineXHPASTLinterRule.php',
'ArcanistArrayCombineXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistArrayCombineXHPASTLinterRuleTestCase.php', 'ArcanistArrayCombineXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistArrayCombineXHPASTLinterRuleTestCase.php',
'ArcanistArrayIndexSpacingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistArrayIndexSpacingXHPASTLinterRule.php', 'ArcanistArrayIndexSpacingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistArrayIndexSpacingXHPASTLinterRule.php',
@ -213,7 +214,7 @@ phutil_register_library_map(array(
'ArcanistHLintLinter' => 'lint/linter/ArcanistHLintLinter.php', 'ArcanistHLintLinter' => 'lint/linter/ArcanistHLintLinter.php',
'ArcanistHLintLinterTestCase' => 'lint/linter/__tests__/ArcanistHLintLinterTestCase.php', 'ArcanistHLintLinterTestCase' => 'lint/linter/__tests__/ArcanistHLintLinterTestCase.php',
'ArcanistHardpointLoader' => 'loader/ArcanistHardpointLoader.php', 'ArcanistHardpointLoader' => 'loader/ArcanistHardpointLoader.php',
'ArcanistHelpWorkflow' => 'workflow/ArcanistHelpWorkflow.php', 'ArcanistHelpWorkflow' => 'toolset/workflow/ArcanistHelpWorkflow.php',
'ArcanistHexadecimalNumericScalarCasingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistHexadecimalNumericScalarCasingXHPASTLinterRule.php', 'ArcanistHexadecimalNumericScalarCasingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistHexadecimalNumericScalarCasingXHPASTLinterRule.php',
'ArcanistHexadecimalNumericScalarCasingXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistHexadecimalNumericScalarCasingXHPASTLinterRuleTestCase.php', 'ArcanistHexadecimalNumericScalarCasingXHPASTLinterRuleTestCase' => 'lint/linter/xhpast/rules/__tests__/ArcanistHexadecimalNumericScalarCasingXHPASTLinterRuleTestCase.php',
'ArcanistHgClientChannel' => 'hgdaemon/ArcanistHgClientChannel.php', 'ArcanistHgClientChannel' => 'hgdaemon/ArcanistHgClientChannel.php',
@ -968,6 +969,7 @@ phutil_register_library_map(array(
'ArcanistAnoidWorkflow' => 'ArcanistWorkflow', 'ArcanistAnoidWorkflow' => 'ArcanistWorkflow',
'ArcanistArcConfigurationEngineExtension' => 'ArcanistConfigurationEngineExtension', 'ArcanistArcConfigurationEngineExtension' => 'ArcanistConfigurationEngineExtension',
'ArcanistArcToolset' => 'ArcanistToolset', 'ArcanistArcToolset' => 'ArcanistToolset',
'ArcanistArcWorkflow' => 'ArcanistWorkflow',
'ArcanistArrayCombineXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistArrayCombineXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
'ArcanistArrayCombineXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase', 'ArcanistArrayCombineXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
'ArcanistArrayIndexSpacingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule', 'ArcanistArrayIndexSpacingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',

View file

@ -0,0 +1,11 @@
<?php
abstract class ArcanistArcWorkflow
extends ArcanistWorkflow {
public function supportsToolset(ArcanistToolset $toolset) {
$key = $toolset->getToolsetKey();
return ($key === 'arc');
}
}

View file

@ -0,0 +1,18 @@
<?php
final class ArcanistHelpWorkflow
extends ArcanistWorkflow {
public function getWorkflowName() {
return 'help';
}
public function newPhutilWorkflow() {
return new PhutilHelpArgumentWorkflow();
}
public function supportsToolset(ArcanistToolset $toolset) {
return true;
}
}

View file

@ -1,221 +0,0 @@
<?php
/**
* Seduces the reader with majestic prose.
*/
final class ArcanistHelpWorkflow extends ArcanistWorkflow {
public function getWorkflowName() {
return 'help';
}
public function getCommandSynopses() {
return phutil_console_format(<<<EOTEXT
**help** [__command__]
**help** --full
EOTEXT
);
}
public function getCommandHelp() {
return phutil_console_format(<<<EOTEXT
Supports: english
Shows this help. With __command__, shows help about a specific
command.
EOTEXT
);
}
public function getArguments() {
return array(
'full' => array(
'help' => pht('Print detailed information about each command.'),
),
'*' => 'command',
);
}
public function run() {
$arc_config = $this->getArcanistConfiguration();
$workflows = $arc_config->buildAllWorkflows();
ksort($workflows);
$target = null;
if ($this->getArgument('command')) {
$target = head($this->getArgument('command'));
if (empty($workflows[$target])) {
throw new ArcanistUsageException(
pht(
"Unrecognized command '%s'. Try '%s'.",
$target,
'arc help'));
}
}
$cmdref = array();
foreach ($workflows as $command => $workflow) {
if ($target && $target != $command) {
continue;
}
if (!$target && !$this->getArgument('full')) {
$cmdref[] = $workflow->getCommandSynopses();
continue;
}
$optref = array();
$arguments = $workflow->getArguments();
$config_arguments = $arc_config->getCustomArgumentsForCommand($command);
// This juggling is to put the extension arguments after the normal
// arguments, and make sure the normal arguments aren't overwritten.
ksort($arguments);
ksort($config_arguments);
foreach ($config_arguments as $argument => $spec) {
if (empty($arguments[$argument])) {
$arguments[$argument] = $spec;
}
}
foreach ($arguments as $argument => $spec) {
if ($argument == '*') {
continue;
}
if (!empty($spec['hide'])) {
continue;
}
if (isset($spec['param'])) {
if (isset($spec['short'])) {
$optref[] = phutil_console_format(
' __--%s__ __%s__, __-%s__ __%s__',
$argument,
$spec['param'],
$spec['short'],
$spec['param']);
} else {
$optref[] = phutil_console_format(
' __--%s__ __%s__',
$argument,
$spec['param']);
}
} else {
if (isset($spec['short'])) {
$optref[] = phutil_console_format(
' __--%s__, __-%s__',
$argument,
$spec['short']);
} else {
$optref[] = phutil_console_format(
' __--%s__',
$argument);
}
}
if (isset($config_arguments[$argument])) {
$optref[] = ' '.
pht('(This is a custom option for this project.)');
}
if (isset($spec['supports'])) {
$optref[] = ' '.
pht('Supports: %s', implode(', ', $spec['supports']));
}
if (isset($spec['help'])) {
$docs = $spec['help'];
} else {
$docs = pht('This option is not documented.');
}
$docs = phutil_console_wrap($docs, 14);
$optref[] = "{$docs}\n";
}
if ($optref) {
$optref = implode("\n", $optref);
$optref = "\n\n".$optref;
} else {
$optref = "\n";
}
$cmdref[] =
$workflow->getCommandSynopses()."\n".
$workflow->getCommandHelp().
$optref;
}
$cmdref = implode("\n\n", $cmdref);
if ($target) {
echo "\n".$cmdref."\n";
return;
}
$self = 'arc';
echo phutil_console_format(<<<EOTEXT
**NAME**
**{$self}** - arcanist, a code review and revision management utility
**SYNOPSIS**
**{$self}** __command__ [__options__] [__args__]
This help file provides a detailed command reference.
**COMMAND REFERENCE**
{$cmdref}
EOTEXT
);
if (!$this->getArgument('full')) {
echo pht(
"Run '%s' to get commands and options descriptions.\n",
'arc help --full');
return;
}
echo phutil_console_format(<<<EOTEXT
**OPTION REFERENCE**
__--trace__
Debugging command. Shows underlying commands as they are executed,
and full stack traces when exceptions are thrown.
__--no-ansi__
Output in plain ASCII text only, without color or style.
__--ansi__
Use formatting even in environments which probably don't support it.
Example: arc --ansi unit | less -r
__--load-phutil-library=/path/to/library__
Ignore libraries listed in .arcconfig and explicitly load specified
libraries instead. Mostly useful for Arcanist development.
__--conduit-uri__ __uri__
Ignore configured Conduit URI and use an explicit one instead. Mostly
useful for Arcanist development.
__--conduit-token__ __token__
Ignore configured credentials and use an explicit API token instead.
__--conduit-version__ __version__
Ignore software version and claim to be running some other version
instead. Mostly useful for Arcanist development. May cause bad things
to happen.
__--conduit-timeout__ __timeout__
Override the default Conduit timeout. Specified in seconds.
__--config__ __key=value__
Specify a runtime configuration value. This will take precedence
over static values, and only affect the current arcanist invocation.
__--skip-arcconfig__
Skip the working copy configuration file
__--arcrc-file__ __filename__
Use provided file instead of ~/.arcrc.
EOTEXT
);
}
}

View file

@ -72,11 +72,54 @@ abstract class ArcanistWorkflow extends Phobject {
private $changeCache = array(); private $changeCache = array();
private $conduitEngine; private $conduitEngine;
private $toolset;
private $runtime;
private $configurationEngine;
private $configurationSourceList;
final public function setToolset(ArcanistToolset $toolset) {
$this->toolset = $toolset;
return $this;
}
final public function getToolset() {
return $this->toolset;
}
final public function setRuntime(ArcanistRuntime $runtime) {
$this->runtime = $runtime;
return $this;
}
final public function getRuntime() {
return $this->runtime;
}
final public function setConfigurationEngine(
ArcanistConfigurationEngine $engine) {
$this->configurationEngine = $engine;
return $this;
}
final public function getConfigurationEngine() {
return $this->configurationEngine;
}
final public function setConfigurationSourceList(
ArcanistConfigurationSourceList $list) {
$this->configurationSourceList = $list;
return $this;
}
final public function getConfigurationSourceList() {
return $this->configurationSourceList;
}
public function __construct() {} public function __construct() {}
public function run() {
abstract public function run(); throw new PhutilMethodNotImplementedException();
}
/** /**
* Finalizes any cleanup operations that need to occur regardless of * Finalizes any cleanup operations that need to occur regardless of
@ -99,17 +142,21 @@ abstract class ArcanistWorkflow extends Phobject {
* *
* @return string 6-space indented list of available command synopses. * @return string 6-space indented list of available command synopses.
*/ */
abstract public function getCommandSynopses(); public function getCommandSynopses() {
return array();
}
/** /**
* Return console formatted string with command help printed in `arc help`. * Return console formatted string with command help printed in `arc help`.
* *
* @return string 10-space indented help to use the command. * @return string 10-space indented help to use the command.
*/ */
abstract public function getCommandHelp(); public function getCommandHelp() {
return null;
}
final public function supportsToolset($toolset) { public function supportsToolset(ArcanistToolset $toolset) {
return ($toolset === 'arc'); return false;
} }