mirror of
https://we.phorge.it/source/arcanist.git
synced 2024-11-25 16:22:42 +01:00
Added automatic stash / unstash support for Git in arc diff.
Summary: - Added arc.autostash option to have this behaviour off by default (but configurable on a per-project basis). - Automatic stashing of changes now informs the user of how to restore their working directory if Arcanist unexpectedly terminates. - Fixed an issue with finalizeWorkingCopy when the workflow didn't require a clean working copy. Test Plan: Test `arc diff` when there are changes in the working directory; by default it should tell you to stash or commit. Turn on the arc.autostash option and try again; it should automatically stash with a message on how to recover, and it should restore the working directory automatically under almost any circumstances (other than an unrecoverable error). Reviewers: epriestley Reviewed By: epriestley CC: aran, Korvin Differential Revision: https://secure.phabricator.com/D5385
This commit is contained in:
parent
9963323b91
commit
2900ab6abd
5 changed files with 72 additions and 4 deletions
|
@ -268,8 +268,14 @@ try {
|
||||||
|
|
||||||
$config->willRunWorkflow($command, $workflow);
|
$config->willRunWorkflow($command, $workflow);
|
||||||
$workflow->willRunWorkflow();
|
$workflow->willRunWorkflow();
|
||||||
|
try {
|
||||||
$err = $workflow->run();
|
$err = $workflow->run();
|
||||||
$config->didRunWorkflow($command, $workflow, $err);
|
$config->didRunWorkflow($command, $workflow, $err);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$workflow->finalize();
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
$workflow->finalize();
|
||||||
exit((int)$err);
|
exit((int)$err);
|
||||||
|
|
||||||
} catch (ArcanistNoEffectException $ex) {
|
} catch (ArcanistNoEffectException $ex) {
|
||||||
|
|
|
@ -94,6 +94,16 @@ final class ArcanistSettings {
|
||||||
"Password to use for basic auth over http transports",
|
"Password to use for basic auth over http transports",
|
||||||
'example' => '"bobhasasecret"',
|
'example' => '"bobhasasecret"',
|
||||||
),
|
),
|
||||||
|
'arc.autostash' => array(
|
||||||
|
'type' => 'bool',
|
||||||
|
'help' =>
|
||||||
|
'Whether arc should permit the automatic stashing of changes in '.
|
||||||
|
'the working directory when requiring a clean working copy. '.
|
||||||
|
'This option should only be used when users understand how '.
|
||||||
|
'to restore their working directory from the local stash if '.
|
||||||
|
'an Arcanist operation causes an unrecoverable error.',
|
||||||
|
'example' => 'false',
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1000,4 +1000,17 @@ final class ArcanistGitAPI extends ArcanistRepositoryAPI {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function canStashChanges() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function stashChanges() {
|
||||||
|
$this->execxLocal('stash');
|
||||||
|
$this->reloadWorkingCopy();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function unstashChanges() {
|
||||||
|
$this->execxLocal('stash pop');
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -422,6 +422,17 @@ abstract class ArcanistRepositoryAPI {
|
||||||
|
|
||||||
abstract protected function buildLocalFuture(array $argv);
|
abstract protected function buildLocalFuture(array $argv);
|
||||||
|
|
||||||
|
public function canStashChanges() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function stashChanges() {
|
||||||
|
throw new ArcanistCapabilityNotSupportedException($this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function unstashChanges() {
|
||||||
|
throw new ArcanistCapabilityNotSupportedException($this);
|
||||||
|
}
|
||||||
|
|
||||||
/* -( Scratch Files )------------------------------------------------------ */
|
/* -( Scratch Files )------------------------------------------------------ */
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,8 @@ abstract class ArcanistBaseWorkflow extends Phobject {
|
||||||
private $passedArguments;
|
private $passedArguments;
|
||||||
private $command;
|
private $command;
|
||||||
|
|
||||||
|
private $stashed;
|
||||||
|
|
||||||
private $projectInfo;
|
private $projectInfo;
|
||||||
|
|
||||||
private $arcanistConfiguration;
|
private $arcanistConfiguration;
|
||||||
|
@ -77,6 +79,14 @@ abstract class ArcanistBaseWorkflow extends Phobject {
|
||||||
|
|
||||||
abstract public function run();
|
abstract public function run();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finalizes any cleanup operations that need to occur regardless of
|
||||||
|
* whether the command succeeded or failed.
|
||||||
|
*/
|
||||||
|
public function finalize() {
|
||||||
|
$this->finalizeWorkingCopy();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the command used to invoke this workflow from the command like,
|
* Return the command used to invoke this workflow from the command like,
|
||||||
* e.g. "help" for @{class:ArcanistHelpWorkflow}.
|
* e.g. "help" for @{class:ArcanistHelpWorkflow}.
|
||||||
|
@ -761,6 +771,14 @@ abstract class ArcanistBaseWorkflow extends Phobject {
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function finalizeWorkingCopy() {
|
||||||
|
if ($this->stashed) {
|
||||||
|
$api = $this->getRepositoryAPI();
|
||||||
|
$api->unstashChanges();
|
||||||
|
echo "Restored stashed changes to the working directory.\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function requireCleanWorkingCopy() {
|
public function requireCleanWorkingCopy() {
|
||||||
$api = $this->getRepositoryAPI();
|
$api = $this->getRepositoryAPI();
|
||||||
|
|
||||||
|
@ -837,11 +855,21 @@ abstract class ArcanistBaseWorkflow extends Phobject {
|
||||||
if ($this->askForAdd()) {
|
if ($this->askForAdd()) {
|
||||||
$api->addToCommit($unstaged);
|
$api->addToCommit($unstaged);
|
||||||
$must_commit += array_flip($unstaged);
|
$must_commit += array_flip($unstaged);
|
||||||
|
} else {
|
||||||
|
$permit_autostash = $this->getWorkingCopy()->getConfigFromAnySource(
|
||||||
|
'arc.autostash',
|
||||||
|
false);
|
||||||
|
if ($permit_autostash && $api->canStashChanges()) {
|
||||||
|
echo "Stashing uncommitted changes. (You can restore them with ".
|
||||||
|
"`git stash pop`.)\n";
|
||||||
|
$api->stashChanges();
|
||||||
|
$this->stashed = true;
|
||||||
} else {
|
} else {
|
||||||
throw new ArcanistUsageException(
|
throw new ArcanistUsageException(
|
||||||
"Stage and commit (or revert) them before proceeding.");
|
"Stage and commit (or revert) them before proceeding.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$uncommitted = $api->getUncommittedChanges();
|
$uncommitted = $api->getUncommittedChanges();
|
||||||
foreach ($uncommitted as $key => $path) {
|
foreach ($uncommitted as $key => $path) {
|
||||||
|
|
Loading…
Reference in a new issue