Changeset View
Changeset View
Standalone View
Standalone View
src/workflow/ArcanistCommitWorkflow.php
| Show First 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | EOTEXT | ||||
| public function getRevisionID() { | public function getRevisionID() { | ||||
| return $this->revisionID; | return $this->revisionID; | ||||
| } | } | ||||
| public function getArguments() { | public function getArguments() { | ||||
| return array( | return array( | ||||
| 'show' => array( | 'show' => array( | ||||
| 'help' => | 'help' => pht( | ||||
| 'Show the command which would be issued, but do not actually '. | 'Show the command which would be issued, but do not actually '. | ||||
| 'commit anything.', | 'commit anything.'), | ||||
| ), | ), | ||||
| 'revision' => array( | 'revision' => array( | ||||
| 'param' => 'revision_id', | 'param' => 'revision_id', | ||||
| 'help' => | 'help' => pht( | ||||
| 'Commit a specific revision. If you do not specify a revision, '. | 'Commit a specific revision. If you do not specify a revision, '. | ||||
| 'arc will look for committable revisions.', | 'arc will look for committable revisions.'), | ||||
| ), | ), | ||||
| ); | ); | ||||
| } | } | ||||
| public function run() { | public function run() { | ||||
| $repository_api = $this->getRepositoryAPI(); | $repository_api = $this->getRepositoryAPI(); | ||||
| $revision_id = $this->normalizeRevisionID($this->getArgument('revision')); | $revision_id = $this->normalizeRevisionID($this->getArgument('revision')); | ||||
| if (!$revision_id) { | if (!$revision_id) { | ||||
| $revisions = $repository_api->loadWorkingCopyDifferentialRevisions( | $revisions = $repository_api->loadWorkingCopyDifferentialRevisions( | ||||
| $this->getConduit(), | $this->getConduit(), | ||||
| array( | array( | ||||
| 'authors' => array($this->getUserPHID()), | 'authors' => array($this->getUserPHID()), | ||||
| 'status' => 'status-accepted', | 'status' => 'status-accepted', | ||||
| )); | )); | ||||
| if (count($revisions) == 0) { | if (count($revisions) == 0) { | ||||
| throw new ArcanistUsageException( | throw new ArcanistUsageException( | ||||
| pht( | |||||
| "Unable to identify the revision in the working copy. Use ". | "Unable to identify the revision in the working copy. Use ". | ||||
| "'--revision <revision_id>' to select a revision."); | "'%s' to select a revision.", | ||||
| '--revision <revision_id>')); | |||||
| } else if (count($revisions) > 1) { | } else if (count($revisions) > 1) { | ||||
| throw new ArcanistUsageException( | throw new ArcanistUsageException( | ||||
| "More than one revision exists in the working copy:\n\n". | pht( | ||||
| $this->renderRevisionList($revisions)."\n". | "More than one revision exists in the working copy:\n\n%s\n". | ||||
| "Use '--revision <revision_id>' to select a revision."); | "Use '%s' to select a revision.", | ||||
| $this->renderRevisionList($revisions), | |||||
| '--revision <revision_id>')); | |||||
| } | } | ||||
| } else { | } else { | ||||
| $revisions = $this->getConduit()->callMethodSynchronous( | $revisions = $this->getConduit()->callMethodSynchronous( | ||||
| 'differential.query', | 'differential.query', | ||||
| array( | array( | ||||
| 'ids' => array($revision_id), | 'ids' => array($revision_id), | ||||
| )); | )); | ||||
| if (count($revisions) == 0) { | if (count($revisions) == 0) { | ||||
| throw new ArcanistUsageException( | throw new ArcanistUsageException( | ||||
| "Revision 'D{$revision_id}' does not exist."); | pht( | ||||
| "Revision '%s' does not exist.", | |||||
| "D{$revision_id}")); | |||||
| } | } | ||||
| } | } | ||||
| $revision = head($revisions); | $revision = head($revisions); | ||||
| $this->revisionID = $revision['id']; | $this->revisionID = $revision['id']; | ||||
| $revision_id = $revision['id']; | $revision_id = $revision['id']; | ||||
| $is_show = $this->getArgument('show'); | $is_show = $this->getArgument('show'); | ||||
| Show All 18 Lines | public function run() { | ||||
| $message = $event->getValue('message'); | $message = $event->getValue('message'); | ||||
| if ($is_show) { | if ($is_show) { | ||||
| echo $message."\n"; | echo $message."\n"; | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| $revision_title = $revision['title']; | $revision_title = $revision['title']; | ||||
| echo "Committing 'D{$revision_id}: {$revision_title}'...\n"; | echo pht( | ||||
| "Committing '%s: %s'...\n", | |||||
| "D{$revision_id}", | |||||
| $revision_title); | |||||
| $files = $this->getCommitFileList($revision); | $files = $this->getCommitFileList($revision); | ||||
| $tmp_file = new TempFile(); | $tmp_file = new TempFile(); | ||||
| Filesystem::writeFile($tmp_file, $message); | Filesystem::writeFile($tmp_file, $message); | ||||
| $command = csprintf( | $command = csprintf( | ||||
| 'svn commit %Ls --encoding utf-8 -F %s', | 'svn commit %Ls --encoding utf-8 -F %s', | ||||
| $files, | $files, | ||||
| $tmp_file); | $tmp_file); | ||||
| // make sure to specify LANG on non-windows systems to suppress any fancy | // make sure to specify LANG on non-windows systems to suppress any fancy | ||||
| // warnings; see @{method:getSVNLangEnvVar}. | // warnings; see @{method:getSVNLangEnvVar}. | ||||
| if (!phutil_is_windows()) { | if (!phutil_is_windows()) { | ||||
| $command = csprintf('LANG=%C %C', $this->getSVNLangEnvVar(), $command); | $command = csprintf('LANG=%C %C', $this->getSVNLangEnvVar(), $command); | ||||
| } | } | ||||
| chdir($repository_api->getPath()); | chdir($repository_api->getPath()); | ||||
| $err = phutil_passthru('%C', $command); | $err = phutil_passthru('%C', $command); | ||||
| if ($err) { | if ($err) { | ||||
| throw new Exception("Executing 'svn commit' failed!"); | throw new Exception(pht("Executing '%s' failed!", 'svn commit')); | ||||
| } | } | ||||
| $this->askForRepositoryUpdate(); | $this->askForRepositoryUpdate(); | ||||
| $mark_workflow = $this->buildChildWorkflow( | $mark_workflow = $this->buildChildWorkflow( | ||||
| 'close-revision', | 'close-revision', | ||||
| array( | array( | ||||
| '--finalize', | '--finalize', | ||||
| Show All 31 Lines | foreach ($status as $path => $mask) { | ||||
| $commit_paths[$path] = true; | $commit_paths[$path] = true; | ||||
| } | } | ||||
| if (!empty($commit_paths[$path])) { | if (!empty($commit_paths[$path])) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| foreach ($commit_paths as $will_commit => $ignored) { | foreach ($commit_paths as $will_commit => $ignored) { | ||||
| if (Filesystem::isDescendant($path, $will_commit)) { | if (Filesystem::isDescendant($path, $will_commit)) { | ||||
| throw new ArcanistUsageException( | throw new ArcanistUsageException( | ||||
| "This commit includes the directory '{$will_commit}', but ". | pht( | ||||
| "it contains a modified path ('{$path}') which is NOT included ". | "This commit includes the directory '%s', but it contains a ". | ||||
| "in the commit. Subversion can not handle this operation and ". | "modified path ('%s') which is NOT included in the commit. ". | ||||
| "will commit the path anyway. You need to sort out the working ". | "Subversion can not handle this operation and will commit the ". | ||||
| "copy changes to '{$path}' before you may proceed with the ". | "path anyway. You need to sort out the working copy changes to ". | ||||
| "commit."); | "'%s' before you may proceed with the commit.", | ||||
| $will_commit, | |||||
| $path, | |||||
| $path)); | |||||
| } | } | ||||
| } | } | ||||
| $modified_but_not_included[] = $path; | $modified_but_not_included[] = $path; | ||||
| } | } | ||||
| if ($modified_but_not_included) { | if ($modified_but_not_included) { | ||||
| $prefix = pht( | $prefix = pht( | ||||
| '%s locally modified path(s) are not included in this revision:', | '%s locally modified path(s) are not included in this revision:', | ||||
| Show All 28 Lines | if ($do_not_exist) { | ||||
| $this->promptFileWarning($prefix, $prompt, $do_not_exist); | $this->promptFileWarning($prefix, $prompt, $do_not_exist); | ||||
| } | } | ||||
| $files = array_keys($commit_paths); | $files = array_keys($commit_paths); | ||||
| $files = ArcanistSubversionAPI::escapeFileNamesForSVN($files); | $files = ArcanistSubversionAPI::escapeFileNamesForSVN($files); | ||||
| if (empty($files)) { | if (empty($files)) { | ||||
| throw new ArcanistUsageException( | throw new ArcanistUsageException( | ||||
| 'There is nothing left to commit. None of the modified paths exist.'); | pht( | ||||
| 'There is nothing left to commit. '. | |||||
| 'None of the modified paths exist.')); | |||||
| } | } | ||||
| return $files; | return $files; | ||||
| } | } | ||||
| protected function promptFileWarning($prefix, $prompt, array $paths) { | protected function promptFileWarning($prefix, $prompt, array $paths) { | ||||
| echo $prefix."\n\n"; | echo $prefix."\n\n"; | ||||
| foreach ($paths as $path) { | foreach ($paths as $path) { | ||||
| Show All 37 Lines | EOTEXT | ||||
| private function runSanityChecks(array $revision) { | private function runSanityChecks(array $revision) { | ||||
| $repository_api = $this->getRepositoryAPI(); | $repository_api = $this->getRepositoryAPI(); | ||||
| $revision_id = $revision['id']; | $revision_id = $revision['id']; | ||||
| $revision_title = $revision['title']; | $revision_title = $revision['title']; | ||||
| $confirm = array(); | $confirm = array(); | ||||
| if ($revision['status'] != ArcanistDifferentialRevisionStatus::ACCEPTED) { | if ($revision['status'] != ArcanistDifferentialRevisionStatus::ACCEPTED) { | ||||
| $confirm[] = | $confirm[] = pht( | ||||
| "Revision 'D{$revision_id}: {$revision_title}' has not been accepted. ". | "Revision '%s: %s' has not been accepted. Commit this revision anyway?", | ||||
| "Commit this revision anyway?"; | "D{$revision_id}", | ||||
| $revision_title); | |||||
| } | } | ||||
| if ($revision['authorPHID'] != $this->getUserPHID()) { | if ($revision['authorPHID'] != $this->getUserPHID()) { | ||||
| $confirm[] = | $confirm[] = pht( | ||||
| "You are not the author of 'D{$revision_id}: {$revision_title}'. ". | "You are not the author of '%s: %s'. Commit this revision anyway?", | ||||
| "Commit this revision anyway?"; | "D{$revision_id}", | ||||
| $revision_title); | |||||
| } | } | ||||
| $revision_source = idx($revision, 'branch'); | $revision_source = idx($revision, 'branch'); | ||||
| $current_source = $repository_api->getBranchName(); | $current_source = $repository_api->getBranchName(); | ||||
| if ($revision_source != $current_source) { | if ($revision_source != $current_source) { | ||||
| $confirm[] = | $confirm[] = pht( | ||||
| "Revision 'D{$revision_id}: {$revision_title}' was generated from ". | "Revision '%s: %s' was generated from '%s', but current working ". | ||||
| "'{$revision_source}', but current working copy root is ". | "copy root is '%s'. Commit this revision anyway?", | ||||
| "'{$current_source}'. Commit this revision anyway?"; | "D{$revision_id}", | ||||
| $revision_title, | |||||
| $revision_source, | |||||
| $current_source); | |||||
| } | } | ||||
| foreach ($confirm as $thing) { | foreach ($confirm as $thing) { | ||||
| if (!phutil_console_confirm($thing)) { | if (!phutil_console_confirm($thing)) { | ||||
| throw new ArcanistUserAbortException(); | throw new ArcanistUserAbortException(); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||