mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-11-22 14:52:40 +01:00
Port "arc upgrade" to Toolsets
Summary: Ref T13490. Allows "arc upgrade" to run through the new Toolsets infrastructure. Test Plan: Ran "arc upgrade", although you can't upgrade feature branches so this can't be entirely tested until it hits "master". Maniphest Tasks: T13490 Differential Revision: https://secure.phabricator.com/D21006
This commit is contained in:
parent
d4e4271b57
commit
ee66b15bd4
7 changed files with 177 additions and 114 deletions
|
@ -95,6 +95,7 @@ phutil_register_library_map(array(
|
||||||
'ArcanistClosureLinterTestCase' => 'lint/linter/__tests__/ArcanistClosureLinterTestCase.php',
|
'ArcanistClosureLinterTestCase' => 'lint/linter/__tests__/ArcanistClosureLinterTestCase.php',
|
||||||
'ArcanistCoffeeLintLinter' => 'lint/linter/ArcanistCoffeeLintLinter.php',
|
'ArcanistCoffeeLintLinter' => 'lint/linter/ArcanistCoffeeLintLinter.php',
|
||||||
'ArcanistCoffeeLintLinterTestCase' => 'lint/linter/__tests__/ArcanistCoffeeLintLinterTestCase.php',
|
'ArcanistCoffeeLintLinterTestCase' => 'lint/linter/__tests__/ArcanistCoffeeLintLinterTestCase.php',
|
||||||
|
'ArcanistCommand' => 'toolset/command/ArcanistCommand.php',
|
||||||
'ArcanistCommentRemover' => 'parser/ArcanistCommentRemover.php',
|
'ArcanistCommentRemover' => 'parser/ArcanistCommentRemover.php',
|
||||||
'ArcanistCommentRemoverTestCase' => 'parser/__tests__/ArcanistCommentRemoverTestCase.php',
|
'ArcanistCommentRemoverTestCase' => 'parser/__tests__/ArcanistCommentRemoverTestCase.php',
|
||||||
'ArcanistCommentSpacingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistCommentSpacingXHPASTLinterRule.php',
|
'ArcanistCommentSpacingXHPASTLinterRule' => 'lint/linter/xhpast/rules/ArcanistCommentSpacingXHPASTLinterRule.php',
|
||||||
|
@ -1036,6 +1037,7 @@ phutil_register_library_map(array(
|
||||||
'ArcanistClosureLinterTestCase' => 'ArcanistExternalLinterTestCase',
|
'ArcanistClosureLinterTestCase' => 'ArcanistExternalLinterTestCase',
|
||||||
'ArcanistCoffeeLintLinter' => 'ArcanistExternalLinter',
|
'ArcanistCoffeeLintLinter' => 'ArcanistExternalLinter',
|
||||||
'ArcanistCoffeeLintLinterTestCase' => 'ArcanistExternalLinterTestCase',
|
'ArcanistCoffeeLintLinterTestCase' => 'ArcanistExternalLinterTestCase',
|
||||||
|
'ArcanistCommand' => 'Phobject',
|
||||||
'ArcanistCommentRemover' => 'Phobject',
|
'ArcanistCommentRemover' => 'Phobject',
|
||||||
'ArcanistCommentRemoverTestCase' => 'PhutilTestCase',
|
'ArcanistCommentRemoverTestCase' => 'PhutilTestCase',
|
||||||
'ArcanistCommentSpacingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
|
'ArcanistCommentSpacingXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
|
||||||
|
@ -1399,7 +1401,7 @@ phutil_register_library_map(array(
|
||||||
'ArcanistUnnecessarySymbolAliasXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
|
'ArcanistUnnecessarySymbolAliasXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
|
||||||
'ArcanistUnsafeDynamicStringXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
|
'ArcanistUnsafeDynamicStringXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
|
||||||
'ArcanistUnsafeDynamicStringXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
|
'ArcanistUnsafeDynamicStringXHPASTLinterRuleTestCase' => 'ArcanistXHPASTLinterRuleTestCase',
|
||||||
'ArcanistUpgradeWorkflow' => 'ArcanistWorkflow',
|
'ArcanistUpgradeWorkflow' => 'ArcanistArcWorkflow',
|
||||||
'ArcanistUploadWorkflow' => 'ArcanistWorkflow',
|
'ArcanistUploadWorkflow' => 'ArcanistWorkflow',
|
||||||
'ArcanistUsageException' => 'Exception',
|
'ArcanistUsageException' => 'Exception',
|
||||||
'ArcanistUseStatementNamespacePrefixXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
|
'ArcanistUseStatementNamespacePrefixXHPASTLinterRule' => 'ArcanistXHPASTLinterRule',
|
||||||
|
|
|
@ -33,7 +33,6 @@ final class ExecFuture extends PhutilExecutableFuture {
|
||||||
|
|
||||||
private $stdoutPos = 0;
|
private $stdoutPos = 0;
|
||||||
private $stderrPos = 0;
|
private $stderrPos = 0;
|
||||||
private $command = null;
|
|
||||||
|
|
||||||
private $readBufferSize;
|
private $readBufferSize;
|
||||||
private $stdoutSizeLimit = PHP_INT_MAX;
|
private $stdoutSizeLimit = PHP_INT_MAX;
|
||||||
|
@ -55,42 +54,13 @@ final class ExecFuture extends PhutilExecutableFuture {
|
||||||
2 => array('pipe', 'w'), // stderr
|
2 => array('pipe', 'w'), // stderr
|
||||||
);
|
);
|
||||||
|
|
||||||
|
protected function didConstruct() {
|
||||||
/* -( Creating ExecFutures )----------------------------------------------- */
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new ExecFuture.
|
|
||||||
*
|
|
||||||
* $future = new ExecFuture('wc -l %s', $file_path);
|
|
||||||
*
|
|
||||||
* @param string `sprintf()`-style command string which will be passed
|
|
||||||
* through @{function:csprintf} with the rest of the arguments.
|
|
||||||
* @param ... Zero or more additional arguments for @{function:csprintf}.
|
|
||||||
* @return ExecFuture ExecFuture for running the specified command.
|
|
||||||
* @task create
|
|
||||||
*/
|
|
||||||
public function __construct($command) {
|
|
||||||
$argv = func_get_args();
|
|
||||||
$this->command = call_user_func_array('csprintf', $argv);
|
|
||||||
$this->stdin = new PhutilRope();
|
$this->stdin = new PhutilRope();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -( Command Information )------------------------------------------------ */
|
/* -( Command Information )------------------------------------------------ */
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve the raw command to be executed.
|
|
||||||
*
|
|
||||||
* @return string Raw command.
|
|
||||||
* @task info
|
|
||||||
*/
|
|
||||||
public function getCommand() {
|
|
||||||
return $this->command;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the byte limit for the stderr buffer.
|
* Retrieve the byte limit for the stderr buffer.
|
||||||
*
|
*
|
||||||
|
@ -349,7 +319,7 @@ final class ExecFuture extends PhutilExecutableFuture {
|
||||||
public function resolvex($timeout = null) {
|
public function resolvex($timeout = null) {
|
||||||
list($err, $stdout, $stderr) = $this->resolve($timeout);
|
list($err, $stdout, $stderr) = $this->resolve($timeout);
|
||||||
if ($err) {
|
if ($err) {
|
||||||
$cmd = $this->command;
|
$cmd = $this->getCommand();
|
||||||
|
|
||||||
if ($this->getWasKilledByTimeout()) {
|
if ($this->getWasKilledByTimeout()) {
|
||||||
// NOTE: The timeout can be a float and PhutilNumber only handles
|
// NOTE: The timeout can be a float and PhutilNumber only handles
|
||||||
|
@ -385,7 +355,7 @@ final class ExecFuture extends PhutilExecutableFuture {
|
||||||
public function resolveJSON($timeout = null) {
|
public function resolveJSON($timeout = null) {
|
||||||
list($stdout, $stderr) = $this->resolvex($timeout);
|
list($stdout, $stderr) = $this->resolvex($timeout);
|
||||||
if (strlen($stderr)) {
|
if (strlen($stderr)) {
|
||||||
$cmd = $this->command;
|
$cmd = $this->getCommand();
|
||||||
throw new CommandException(
|
throw new CommandException(
|
||||||
pht(
|
pht(
|
||||||
"JSON command '%s' emitted text to stderr when none was expected: %d",
|
"JSON command '%s' emitted text to stderr when none was expected: %d",
|
||||||
|
@ -399,7 +369,7 @@ final class ExecFuture extends PhutilExecutableFuture {
|
||||||
try {
|
try {
|
||||||
return phutil_json_decode($stdout);
|
return phutil_json_decode($stdout);
|
||||||
} catch (PhutilJSONParserException $ex) {
|
} catch (PhutilJSONParserException $ex) {
|
||||||
$cmd = $this->command;
|
$cmd = $this->getCommand();
|
||||||
throw new CommandException(
|
throw new CommandException(
|
||||||
pht(
|
pht(
|
||||||
"JSON command '%s' did not produce a valid JSON object on stdout: %s",
|
"JSON command '%s' did not produce a valid JSON object on stdout: %s",
|
||||||
|
@ -579,7 +549,7 @@ final class ExecFuture extends PhutilExecutableFuture {
|
||||||
$this->profilerCallID = $profiler->beginServiceCall(
|
$this->profilerCallID = $profiler->beginServiceCall(
|
||||||
array(
|
array(
|
||||||
'type' => 'exec',
|
'type' => 'exec',
|
||||||
'command' => (string)$this->command,
|
'command' => phutil_string_cast($this->getCommand()),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -588,10 +558,8 @@ final class ExecFuture extends PhutilExecutableFuture {
|
||||||
$this->start = microtime(true);
|
$this->start = microtime(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
$unmasked_command = $this->command;
|
$unmasked_command = $this->getCommand();
|
||||||
if ($unmasked_command instanceof PhutilCommandString) {
|
|
||||||
$unmasked_command = $unmasked_command->getUnmaskedString();
|
$unmasked_command = $unmasked_command->getUnmaskedString();
|
||||||
}
|
|
||||||
|
|
||||||
$pipes = array();
|
$pipes = array();
|
||||||
|
|
||||||
|
@ -674,7 +642,7 @@ final class ExecFuture extends PhutilExecutableFuture {
|
||||||
pht(
|
pht(
|
||||||
'Call to "proc_open()" to open a subprocess failed: %s',
|
'Call to "proc_open()" to open a subprocess failed: %s',
|
||||||
$err),
|
$err),
|
||||||
$this->command,
|
$this->getCommand(),
|
||||||
1,
|
1,
|
||||||
'',
|
'',
|
||||||
'');
|
'');
|
||||||
|
|
|
@ -20,30 +20,12 @@
|
||||||
*/
|
*/
|
||||||
final class PhutilExecPassthru extends PhutilExecutableFuture {
|
final class PhutilExecPassthru extends PhutilExecutableFuture {
|
||||||
|
|
||||||
|
|
||||||
private $command;
|
|
||||||
private $passthruResult;
|
private $passthruResult;
|
||||||
|
|
||||||
|
|
||||||
/* -( Executing Passthru Commands )---------------------------------------- */
|
/* -( Executing Passthru Commands )---------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build a new passthru command.
|
|
||||||
*
|
|
||||||
* $exec = new PhutilExecPassthru('ls %s', $dir);
|
|
||||||
*
|
|
||||||
* @param string Command pattern. See @{function:csprintf}.
|
|
||||||
* @param ... Pattern arguments.
|
|
||||||
*
|
|
||||||
* @task command
|
|
||||||
*/
|
|
||||||
public function __construct($pattern /* , ... */) {
|
|
||||||
$args = func_get_args();
|
|
||||||
$this->command = call_user_func_array('csprintf', $args);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute this command.
|
* Execute this command.
|
||||||
*
|
*
|
||||||
|
@ -52,7 +34,7 @@ final class PhutilExecPassthru extends PhutilExecutableFuture {
|
||||||
* @task command
|
* @task command
|
||||||
*/
|
*/
|
||||||
public function execute() {
|
public function execute() {
|
||||||
$command = $this->command;
|
$command = $this->getCommand();
|
||||||
|
|
||||||
$profiler = PhutilServiceProfiler::getInstance();
|
$profiler = PhutilServiceProfiler::getInstance();
|
||||||
$call_id = $profiler->beginServiceCall(
|
$call_id = $profiler->beginServiceCall(
|
||||||
|
@ -65,11 +47,7 @@ final class PhutilExecPassthru extends PhutilExecutableFuture {
|
||||||
$spec = array(STDIN, STDOUT, STDERR);
|
$spec = array(STDIN, STDOUT, STDERR);
|
||||||
$pipes = array();
|
$pipes = array();
|
||||||
|
|
||||||
if ($command instanceof PhutilCommandString) {
|
|
||||||
$unmasked_command = $command->getUnmaskedString();
|
$unmasked_command = $command->getUnmaskedString();
|
||||||
} else {
|
|
||||||
$unmasked_command = $command;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->hasEnv()) {
|
if ($this->hasEnv()) {
|
||||||
$env = $this->getEnv();
|
$env = $this->getEnv();
|
||||||
|
|
|
@ -5,10 +5,38 @@
|
||||||
*/
|
*/
|
||||||
abstract class PhutilExecutableFuture extends Future {
|
abstract class PhutilExecutableFuture extends Future {
|
||||||
|
|
||||||
|
private $command;
|
||||||
private $env;
|
private $env;
|
||||||
private $cwd;
|
private $cwd;
|
||||||
|
|
||||||
|
final public function __construct($pattern /* , ... */) {
|
||||||
|
$args = func_get_args();
|
||||||
|
|
||||||
|
if ($pattern instanceof PhutilCommandString) {
|
||||||
|
if (count($args) !== 1) {
|
||||||
|
throw new Exception(
|
||||||
|
pht(
|
||||||
|
'Command (of class "%s") was constructed with a '.
|
||||||
|
'"PhutilCommandString", but also passed arguments. '.
|
||||||
|
'When using a preprebuilt command, you must not pass '.
|
||||||
|
'arguments.',
|
||||||
|
get_class($this)));
|
||||||
|
}
|
||||||
|
$this->command = $pattern;
|
||||||
|
} else {
|
||||||
|
$this->command = call_user_func_array('csprintf', $args);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->didConstruct();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function didConstruct() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final public function getCommand() {
|
||||||
|
return $this->command;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set environmental variables for the command.
|
* Set environmental variables for the command.
|
||||||
|
|
59
src/toolset/command/ArcanistCommand.php
Normal file
59
src/toolset/command/ArcanistCommand.php
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class ArcanistCommand
|
||||||
|
extends Phobject {
|
||||||
|
|
||||||
|
private $logEngine;
|
||||||
|
private $executableFuture;
|
||||||
|
|
||||||
|
public function setExecutableFuture(PhutilExecutableFuture $future) {
|
||||||
|
$this->executableFuture = $future;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getExecutableFuture() {
|
||||||
|
return $this->executableFuture;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setLogEngine(ArcanistLogEngine $log_engine) {
|
||||||
|
$this->logEngine = $log_engine;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLogEngine() {
|
||||||
|
return $this->logEngine;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute() {
|
||||||
|
$log = $this->getLogEngine();
|
||||||
|
$future = $this->getExecutableFuture();
|
||||||
|
$command = $future->getCommand();
|
||||||
|
|
||||||
|
$log->writeNewline();
|
||||||
|
|
||||||
|
$log->writeStatus(
|
||||||
|
' $ ',
|
||||||
|
tsprintf('**%s**', phutil_string_cast($command)));
|
||||||
|
|
||||||
|
$log->writeNewline();
|
||||||
|
|
||||||
|
$err = $future->resolve();
|
||||||
|
|
||||||
|
$log->writeNewline();
|
||||||
|
|
||||||
|
if ($err) {
|
||||||
|
$log->writeError(
|
||||||
|
pht('ERROR'),
|
||||||
|
pht(
|
||||||
|
'Command exited with error code %d.',
|
||||||
|
$err));
|
||||||
|
|
||||||
|
throw new CommandException(
|
||||||
|
pht('Command exited with nonzero error code.'),
|
||||||
|
$command,
|
||||||
|
$err,
|
||||||
|
'',
|
||||||
|
'');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,30 +1,31 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
final class ArcanistUpgradeWorkflow
|
||||||
* Upgrade arcanist itself.
|
extends ArcanistArcWorkflow {
|
||||||
*/
|
|
||||||
final class ArcanistUpgradeWorkflow extends ArcanistWorkflow {
|
|
||||||
|
|
||||||
public function getWorkflowName() {
|
public function getWorkflowName() {
|
||||||
return 'upgrade';
|
return 'upgrade';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCommandSynopses() {
|
public function getWorkflowInformation() {
|
||||||
return phutil_console_format(<<<EOTEXT
|
$help = pht(<<<EOTEXT
|
||||||
**upgrade**
|
Upgrade Arcanist to the latest version.
|
||||||
EOTEXT
|
EOTEXT
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return $this->newWorkflowInformation()
|
||||||
|
->setSynopsis(pht('Upgrade Arcanist to the latest version.'))
|
||||||
|
->addExample(pht('**upgrade**'))
|
||||||
|
->setHelp($help);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCommandHelp() {
|
public function getWorkflowArguments() {
|
||||||
return phutil_console_format(<<<EOTEXT
|
return array();
|
||||||
Supports: cli
|
|
||||||
Upgrade arcanist and libphutil to the latest versions.
|
|
||||||
EOTEXT
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function run() {
|
public function runWorkflow() {
|
||||||
|
$log = $this->getLogEngine();
|
||||||
|
|
||||||
$roots = array(
|
$roots = array(
|
||||||
'arcanist' => dirname(phutil_get_library_root('arcanist')),
|
'arcanist' => dirname(phutil_get_library_root('arcanist')),
|
||||||
);
|
);
|
||||||
|
@ -32,41 +33,46 @@ EOTEXT
|
||||||
$supported_branches = array(
|
$supported_branches = array(
|
||||||
'master',
|
'master',
|
||||||
'stable',
|
'stable',
|
||||||
'experimental',
|
|
||||||
);
|
);
|
||||||
$supported_branches = array_fuse($supported_branches);
|
$supported_branches = array_fuse($supported_branches);
|
||||||
|
|
||||||
foreach ($roots as $lib => $root) {
|
foreach ($roots as $library => $root) {
|
||||||
echo phutil_console_format(
|
$log->writeStatus(
|
||||||
"%s\n",
|
pht('PREPARING'),
|
||||||
pht('Upgrading %s...', $lib));
|
|
||||||
|
|
||||||
$working_copy = ArcanistWorkingCopyIdentity::newFromPath($root);
|
|
||||||
$configuration_manager = clone $this->getConfigurationManager();
|
|
||||||
$configuration_manager->setWorkingCopyIdentity($working_copy);
|
|
||||||
$repository = ArcanistRepositoryAPI::newAPIFromConfigurationManager(
|
|
||||||
$configuration_manager);
|
|
||||||
|
|
||||||
if (!Filesystem::pathExists($repository->getMetadataPath())) {
|
|
||||||
throw new ArcanistUsageException(
|
|
||||||
pht(
|
pht(
|
||||||
"%s must be in its git working copy to be automatically upgraded. ".
|
'Preparing to upgrade "%s"...',
|
||||||
"This copy of %s (in '%s') is not in a git working copy.",
|
$library));
|
||||||
$lib,
|
|
||||||
$lib,
|
$is_git = false;
|
||||||
$root));
|
|
||||||
|
$working_copy = ArcanistWorkingCopy::newFromWorkingDirectory($root);
|
||||||
|
if ($working_copy) {
|
||||||
|
$repository_api = $working_copy->newRepositoryAPI();
|
||||||
|
if ($repository_api instanceof ArcanistGitAPI) {
|
||||||
|
$is_git = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->setRepositoryAPI($repository);
|
if (!$is_git) {
|
||||||
|
throw new PhutilArgumentUsageException(
|
||||||
|
pht(
|
||||||
|
'The "arc upgrade" workflow uses "git pull" to upgrade '.
|
||||||
|
'Arcanist, but the "arcanist/" directory (in "%s") is not a Git '.
|
||||||
|
'working copy. You must leave "arcanist/" as a Git '.
|
||||||
|
'working copy to use "arc upgrade".',
|
||||||
|
$root));
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE: Don't use requireCleanWorkingCopy() here because it tries to
|
// NOTE: Don't use requireCleanWorkingCopy() here because it tries to
|
||||||
// amend changes and generally move the workflow forward. We just want to
|
// amend changes and generally move the workflow forward. We just want to
|
||||||
// abort if there are local changes and make the user sort things out.
|
// abort if there are local changes and make the user sort things out.
|
||||||
$uncommitted = $repository->getUncommittedStatus();
|
$uncommitted = $repository_api->getUncommittedStatus();
|
||||||
if ($uncommitted) {
|
if ($uncommitted) {
|
||||||
$message = pht(
|
$message = pht(
|
||||||
'You have uncommitted changes in the working copy for this '.
|
'You have uncommitted changes in the working copy ("%s") for this '.
|
||||||
'library:');
|
'library ("%s"):',
|
||||||
|
$root,
|
||||||
|
$library);
|
||||||
|
|
||||||
$list = id(new PhutilConsoleList())
|
$list = id(new PhutilConsoleList())
|
||||||
->setWrap(false)
|
->setWrap(false)
|
||||||
|
@ -75,29 +81,45 @@ EOTEXT
|
||||||
id(new PhutilConsoleBlock())
|
id(new PhutilConsoleBlock())
|
||||||
->addParagraph($message)
|
->addParagraph($message)
|
||||||
->addList($list)
|
->addList($list)
|
||||||
|
->addParagraph(
|
||||||
|
pht(
|
||||||
|
'Discard these changes before running "arc upgrade".'))
|
||||||
->draw();
|
->draw();
|
||||||
|
|
||||||
throw new ArcanistUsageException(
|
throw new PhutilArgumentUsageException(
|
||||||
pht('`arc upgrade` can only upgrade clean working copies.'));
|
pht('"arc upgrade" can only upgrade clean working copies.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$branch_name = $repository->getBranchName();
|
$branch_name = $repository_api->getBranchName();
|
||||||
if (!isset($supported_branches[$branch_name])) {
|
if (!isset($supported_branches[$branch_name])) {
|
||||||
throw new ArcanistUsageException(
|
throw new PhutilArgumentUsageException(
|
||||||
pht(
|
pht(
|
||||||
'Library "%s" (in "%s") is on branch "%s", but this branch is '.
|
'Library "%s" (in "%s") is on branch "%s", but this branch is '.
|
||||||
'not supported for automatic upgrades. Supported branches are: '.
|
'not supported for automatic upgrades. Supported branches are: '.
|
||||||
'%s.',
|
'%s.',
|
||||||
$lib,
|
$library,
|
||||||
$root,
|
$root,
|
||||||
$branch_name,
|
$branch_name,
|
||||||
implode(', ', array_keys($supported_branches))));
|
implode(', ', array_keys($supported_branches))));
|
||||||
}
|
}
|
||||||
|
|
||||||
chdir($root);
|
$log->writeStatus(
|
||||||
|
pht('UPGRADING'),
|
||||||
|
pht(
|
||||||
|
'Upgrading "%s" (on branch "%s").',
|
||||||
|
$library,
|
||||||
|
$branch_name));
|
||||||
|
|
||||||
|
$command = csprintf(
|
||||||
|
'git pull --rebase origin -- %R',
|
||||||
|
$branch_name);
|
||||||
|
|
||||||
|
$future = (new PhutilExecPassthru($command))
|
||||||
|
->setCWD($root);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
execx('git pull --rebase');
|
$this->newCommand($future)
|
||||||
|
->execute();
|
||||||
} catch (Exception $ex) {
|
} catch (Exception $ex) {
|
||||||
// If we failed, try to go back to the old state, then throw the
|
// If we failed, try to go back to the old state, then throw the
|
||||||
// original exception.
|
// original exception.
|
||||||
|
@ -106,10 +128,10 @@ EOTEXT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
echo phutil_console_format(
|
$log->writeSuccess(
|
||||||
"**%s** %s\n",
|
pht('UPGRADED'),
|
||||||
pht('Updated!'),
|
pht('Your copy of Arcanist is now up to date.'));
|
||||||
pht('Your copy of arc is now up to date.'));
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2243,4 +2243,10 @@ abstract class ArcanistWorkflow extends Phobject {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final public function newCommand(PhutilExecutableFuture $future) {
|
||||||
|
return id(new ArcanistCommand())
|
||||||
|
->setLogEngine($this->getLogEngine())
|
||||||
|
->setExecutableFuture($future);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue