Changeset View
Changeset View
Standalone View
Standalone View
src/workflow/ArcanistWorkflow.php
Show First 20 Lines • Show All 803 Lines • ▼ Show 20 Lines | if (!$this->repositoryAPI) { | ||||
$workflow = get_class($this); | $workflow = get_class($this); | ||||
throw new Exception( | throw new Exception( | ||||
"This workflow ('{$workflow}') requires a Repository API, override ". | "This workflow ('{$workflow}') requires a Repository API, override ". | ||||
"requiresRepositoryAPI() to return true."); | "requiresRepositoryAPI() to return true."); | ||||
} | } | ||||
return $this->repositoryAPI; | return $this->repositoryAPI; | ||||
} | } | ||||
final protected function shouldRequireCleanUntrackedFiles() { | |||||
return empty($this->arguments['allow-untracked']); | |||||
} | |||||
final public function setCommitMode($mode) { | final public function setCommitMode($mode) { | ||||
$this->commitMode = $mode; | $this->commitMode = $mode; | ||||
return $this; | return $this; | ||||
} | } | ||||
final public function finalizeWorkingCopy() { | final public function finalizeWorkingCopy() { | ||||
if ($this->stashed) { | if ($this->stashed) { | ||||
$api = $this->getRepositoryAPI(); | $api = $this->getRepositoryAPI(); | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | final public function requireCleanWorkingCopy() { | ||||
} | } | ||||
$uncommitted = $api->getUncommittedChanges(); | $uncommitted = $api->getUncommittedChanges(); | ||||
$unstaged = $api->getUnstagedChanges(); | $unstaged = $api->getUnstagedChanges(); | ||||
// We only want files which are purely uncommitted. | // We only want files which are purely uncommitted. | ||||
$uncommitted = array_diff($uncommitted, $unstaged); | $uncommitted = array_diff($uncommitted, $unstaged); | ||||
$untracked = $api->getUntrackedChanges(); | |||||
if (!$this->shouldRequireCleanUntrackedFiles()) { | |||||
$untracked = array(); | |||||
} | |||||
$should_commit = false; | $should_commit = false; | ||||
if ($untracked || $unstaged || $uncommitted) { | if ($unstaged || $uncommitted) { | ||||
// NOTE: We're running this because it builds a cache and can take a | // NOTE: We're running this because it builds a cache and can take a | ||||
// perceptible amount of time to arrive at an answer, but we don't want | // perceptible amount of time to arrive at an answer, but we don't want | ||||
// to pause in the middle of printing the output below. | // to pause in the middle of printing the output below. | ||||
$this->getShouldAmend(); | $this->getShouldAmend(); | ||||
echo pht( | echo pht( | ||||
"You have uncommitted changes in this working copy.\n\n%s", | "You have uncommitted changes in this working copy.\n\n%s", | ||||
$working_copy_desc); | $working_copy_desc); | ||||
$lists = array(); | $lists = array(); | ||||
if ($untracked) { | |||||
if ($api instanceof ArcanistGitAPI) { | |||||
$hint = pht( | |||||
'(To ignore these %s change(s), add them to ".git/info/exclude".)', | |||||
new PhutilNumber(count($untracked))); | |||||
} else if ($api instanceof ArcanistSubversionAPI) { | |||||
$hint = pht( | |||||
'(To ignore these %s change(s), add them to "svn:ignore".)', | |||||
new PhutilNumber(count($untracked))); | |||||
} else if ($api instanceof ArcanistMercurialAPI) { | |||||
$hint = pht( | |||||
'(To ignore these %s change(s), add them to ".hgignore".)', | |||||
new PhutilNumber(count($untracked))); | |||||
} | |||||
$untracked_list = " ".implode("\n ", $untracked); | |||||
$lists[] = pht( | |||||
" Untracked changes in working copy:\n %s\n%s", | |||||
$hint, | |||||
$untracked_list); | |||||
} | |||||
if ($unstaged) { | if ($unstaged) { | ||||
$unstaged_list = " ".implode("\n ", $unstaged); | $unstaged_list = " ".implode("\n ", $unstaged); | ||||
$lists[] = pht( | $lists[] = pht( | ||||
" Unstaged changes in working copy:\n%s", | " Unstaged changes in working copy:\n%s", | ||||
$unstaged_list); | $unstaged_list); | ||||
} | } | ||||
if ($uncommitted) { | if ($uncommitted) { | ||||
$uncommitted_list = " ".implode("\n ", $uncommitted); | $uncommitted_list = " ".implode("\n ", $uncommitted); | ||||
$lists[] = pht( | $lists[] = pht( | ||||
" Uncommitted changes in working copy:\n%s", | " Uncommitted changes in working copy:\n%s", | ||||
$uncommitted_list); | $uncommitted_list); | ||||
} | } | ||||
echo implode("\n\n", $lists)."\n"; | echo implode("\n\n", $lists)."\n"; | ||||
$all_uncommitted = array_merge($untracked, $unstaged, $uncommitted); | $all_uncommitted = array_merge($unstaged, $uncommitted); | ||||
if ($this->askForAdd($all_uncommitted)) { | if ($this->askForAdd($all_uncommitted)) { | ||||
if ($untracked) { | |||||
$api->addToCommit($untracked); | |||||
} | |||||
if ($unstaged) { | if ($unstaged) { | ||||
$api->addToCommit($unstaged); | $api->addToCommit($unstaged); | ||||
} | } | ||||
$should_commit = true; | $should_commit = true; | ||||
} else { | } else { | ||||
$permit_autostash = $this->getConfigFromAnySource( | $permit_autostash = $this->getConfigFromAnySource( | ||||
'arc.autostash', | 'arc.autostash', | ||||
false); | false); | ||||
if ($permit_autostash && $api->canStashChanges()) { | if ($permit_autostash && $api->canStashChanges()) { | ||||
echo "Stashing uncommitted changes. (You can restore them with ". | echo "Stashing uncommitted changes. (You can restore them with ". | ||||
"`git stash pop`.)\n"; | "`git stash pop`.)\n"; | ||||
$api->stashChanges(); | $api->stashChanges(); | ||||
$this->stashed = true; | $this->stashed = true; | ||||
} else { | } else { | ||||
if ($untracked && !$unstaged && !$uncommitted) { | |||||
// Give a tailored message if there are only untracked files, | |||||
// because the advice to commit files does not make sense in | |||||
// Subversion. | |||||
throw new ArcanistUsageException( | |||||
pht( | |||||
'You can not continue with untracked changes. Add them, '. | |||||
'discard them, or mark them as ignored before proceeding.')); | |||||
} else { | |||||
throw new ArcanistUsageException( | throw new ArcanistUsageException( | ||||
pht( | pht( | ||||
'You can not continue with uncommitted changes. Commit '. | 'You can not continue with uncommitted changes. Commit '. | ||||
'or discard them before proceeding.')); | 'or discard them before proceeding.')); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | |||||
if ($should_commit) { | if ($should_commit) { | ||||
if ($this->getShouldAmend()) { | if ($this->getShouldAmend()) { | ||||
$commit = head($api->getLocalCommitInformation()); | $commit = head($api->getLocalCommitInformation()); | ||||
$api->amendCommit($commit['message']); | $api->amendCommit($commit['message']); | ||||
} else if ($api->supportsLocalCommits()) { | } else if ($api->supportsLocalCommits()) { | ||||
$template = | $template = | ||||
"\n\n". | "\n\n". | ||||
"# ".pht('Enter a commit message.')."\n#\n". | "# ".pht('Enter a commit message.')."\n#\n". | ||||
"# ".pht('Changes:')."\n#\n"; | "# ".pht('Changes:')."\n#\n"; | ||||
foreach ($untracked as $untracked_path) { | |||||
$template .= "# ".$untracked_path." (".pht('Added').")\n"; | |||||
} | |||||
$paths = array_merge($uncommitted, $unstaged); | $paths = array_merge($uncommitted, $unstaged); | ||||
$paths = array_unique($paths); | $paths = array_unique($paths); | ||||
sort($paths); | sort($paths); | ||||
foreach ($paths as $path) { | foreach ($paths as $path) { | ||||
$template .= "# ".$path."\n"; | $template .= "# ".$path."\n"; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 964 Lines • Show Last 20 Lines |