1
0
Fork 0
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:
James Rhodes 2013-03-21 15:51:39 -07:00 committed by epriestley
parent 9963323b91
commit 2900ab6abd
5 changed files with 72 additions and 4 deletions

View file

@ -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) {

View file

@ -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',
),
); );
} }

View file

@ -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');
}
} }

View file

@ -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 )------------------------------------------------------ */

View file

@ -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) {