diff --git a/src/land/engine/ArcanistGitLandEngine.php b/src/land/engine/ArcanistGitLandEngine.php --- a/src/land/engine/ArcanistGitLandEngine.php +++ b/src/land/engine/ArcanistGitLandEngine.php @@ -174,10 +174,9 @@ 'Synchronizing "%s" from Perforce...', $target->getRef())); - $err = $api->execPassthru( + $err = $this->newPassthru( 'p4 sync --silent --branch %s --', $target->getRemote().'/'.$target->getRef()); - if ($err) { throw new ArcanistUsageException( pht( @@ -416,12 +415,11 @@ // fix conflicts and run "arc land" again. $flags_argv[] = '--conflict=quit'; - $err = $api->execPassthru( + $err = $this->newPassthru( '%LR p4 submit %LR --commit %R --', $config_argv, $flags_argv, $into_commit); - if ($err) { throw new ArcanistUsageException( pht( @@ -435,7 +433,7 @@ pht('PUSHING'), pht('Pushing changes to "%s".', $this->getOntoRemote())); - $err = $api->execPassthru( + $err = $this->newPassthru( 'push -- %s %Ls', $this->getOntoRemote(), $this->newOntoRefArguments($into_commit)); @@ -1298,9 +1296,7 @@ $ignore_failure = false) { $api = $this->getRepositoryAPI(); - // TODO: Format this fetch nicely as a workflow command. - - $err = $api->execPassthru( + $err = $this->newPassthru( 'fetch --no-tags --quiet -- %s %s', $target->getRemote(), $target->getRef()); diff --git a/src/land/engine/ArcanistLandEngine.php b/src/land/engine/ArcanistLandEngine.php --- a/src/land/engine/ArcanistLandEngine.php +++ b/src/land/engine/ArcanistLandEngine.php @@ -1548,4 +1548,20 @@ return $sets; } + final protected function newPassthru($pattern /* , ... */) { + $workflow = $this->getWorkflow(); + $argv = func_get_args(); + + $api = $this->getRepositoryAPI(); + + $passthru = call_user_func_array( + array($api, 'newPassthru'), + $argv); + + $command = $workflow->newCommand($passthru) + ->setResolveOnError(true); + + return $command->execute(); + } + } diff --git a/src/land/engine/ArcanistMercurialLandEngine.php b/src/land/engine/ArcanistMercurialLandEngine.php --- a/src/land/engine/ArcanistMercurialLandEngine.php +++ b/src/land/engine/ArcanistMercurialLandEngine.php @@ -360,14 +360,14 @@ // TODO: Support bookmarks. // TODO: Deal with bookmark save/restore behavior. - // TODO: Format this nicely with passthru. // TODO: Raise a good error message when the ref does not exist. - $api->execPassthru( + $err = $this->newPassthru( 'pull -b %s -- %s', $target->getRef(), $target->getRemote()); + // TODO: Deal with errors. // TODO: Deal with multiple branch heads. list($stdout) = $api->execxLocal( @@ -507,7 +507,7 @@ // TODO: This does not respect "--into" or "--onto" properly. - $api->execxLocal( + $this->newPassthru( 'push --rev %s -- %s', hgsprintf('%s', $into_commit), $this->getOntoRemote()); diff --git a/src/repository/api/ArcanistGitAPI.php b/src/repository/api/ArcanistGitAPI.php --- a/src/repository/api/ArcanistGitAPI.php +++ b/src/repository/api/ArcanistGitAPI.php @@ -20,12 +20,11 @@ protected function buildLocalFuture(array $argv) { $argv[0] = 'git '.$argv[0]; - $future = newv('ExecFuture', $argv); - $future->setCWD($this->getPath()); - return $future; + return newv('ExecFuture', $argv) + ->setCWD($this->getPath()); } - public function execPassthru($pattern /* , ... */) { + public function newPassthru($pattern /* , ... */) { $args = func_get_args(); static $git = null; @@ -43,10 +42,10 @@ $args[0] = $git.' '.$args[0]; - return call_user_func_array('phutil_passthru', $args); + return newv('PhutilExecPassthru', $args) + ->setCWD($this->getPath()); } - public function getSourceControlSystemName() { return 'git'; } diff --git a/src/repository/api/ArcanistMercurialAPI.php b/src/repository/api/ArcanistMercurialAPI.php --- a/src/repository/api/ArcanistMercurialAPI.php +++ b/src/repository/api/ArcanistMercurialAPI.php @@ -27,18 +27,16 @@ return $future; } - public function execPassthru($pattern /* , ... */) { + public function newPassthru($pattern /* , ... */) { $args = func_get_args(); $env = $this->getMercurialEnvironmentVariables(); $args[0] = 'hg '.$args[0]; - $passthru = newv('PhutilExecPassthru', $args) + return newv('PhutilExecPassthru', $args) ->setEnv($env) ->setCWD($this->getPath()); - - return $passthru->resolve(); } public function getSourceControlSystemName() { diff --git a/src/repository/api/ArcanistRepositoryAPI.php b/src/repository/api/ArcanistRepositoryAPI.php --- a/src/repository/api/ArcanistRepositoryAPI.php +++ b/src/repository/api/ArcanistRepositoryAPI.php @@ -675,6 +675,20 @@ ->setResolveOnError(false); } + public function newPassthru($pattern /* , ... */) { + throw new PhutilMethodNotImplementedException(); + } + + final public function execPassthru($pattern /* , ... */) { + $args = func_get_args(); + + $future = call_user_func_array( + array($this, 'newPassthru'), + $args); + + return $future->resolve(); + } + final public function setRuntime(ArcanistRuntime $runtime) { $this->runtime = $runtime; return $this; diff --git a/src/toolset/command/ArcanistCommand.php b/src/toolset/command/ArcanistCommand.php --- a/src/toolset/command/ArcanistCommand.php +++ b/src/toolset/command/ArcanistCommand.php @@ -5,6 +5,7 @@ private $logEngine; private $executableFuture; + private $resolveOnError = false; public function setExecutableFuture(PhutilExecutableFuture $future) { $this->executableFuture = $future; @@ -24,6 +25,15 @@ return $this->logEngine; } + public function setResolveOnError($resolve_on_error) { + $this->resolveOnError = $resolve_on_error; + return $this; + } + + public function getResolveOnError() { + return $this->resolveOnError; + } + public function execute() { $log = $this->getLogEngine(); $future = $this->getExecutableFuture(); @@ -41,7 +51,7 @@ $log->writeNewline(); - if ($err) { + if ($err && !$this->getResolveOnError()) { $log->writeError( pht('ERROR'), pht( @@ -55,5 +65,7 @@ '', ''); } + + return $err; } }