Changeset View
Changeset View
Standalone View
Standalone View
src/future/exec/PhutilExecPassthru.php
<?php | <?php | ||||
/** | /** | ||||
* Execute a command which takes over stdin, stdout and stderr, similar to | * Execute a command which takes over stdin, stdout and stderr, similar to | ||||
* `passthru()`, but which preserves TTY semantics, escapes arguments, and is | * `passthru()`, but which preserves TTY semantics, escapes arguments, and is | ||||
* traceable. | * traceable. | ||||
* | * | ||||
* Passthru commands use the `STDIN`, `STDOUT` and `STDERR` of the parent | * Passthru commands use the `STDIN`, `STDOUT` and `STDERR` of the parent | ||||
* process, so input can be read from the console and output is printed to it. | * process, so input can be read from the console and output is printed to it. | ||||
* This is primarily useful for executing things like `$EDITOR` from command | * This is primarily useful for executing things like `$EDITOR` from command | ||||
* line scripts. | * line scripts. | ||||
* | * | ||||
* $exec = new PhutilExecPassthru('ls %s', $dir); | * $exec = new PhutilExecPassthru('nano -- %s', $filename); | ||||
* $err = $exec->execute(); | * $err = $exec->resolve(); | ||||
* | * | ||||
* You can set the current working directory for the command with | * You can set the current working directory for the command with | ||||
* @{method:setCWD}, and set the environment with @{method:setEnv}. | * @{method:setCWD}, and set the environment with @{method:setEnv}. | ||||
* | * | ||||
* @task command Executing Passthru Commands | * @task command Executing Passthru Commands | ||||
*/ | */ | ||||
final class PhutilExecPassthru extends PhutilExecutableFuture { | final class PhutilExecPassthru extends PhutilExecutableFuture { | ||||
private $stdinData; | private $stdinData; | ||||
public function write($data) { | public function write($data) { | ||||
$this->stdinData = $data; | $this->stdinData = $data; | ||||
return $this; | return $this; | ||||
} | } | ||||
/* -( Executing Passthru Commands )---------------------------------------- */ | /* -( Executing Passthru Commands )---------------------------------------- */ | ||||
public function execute() { | |||||
phlog( | |||||
pht( | |||||
'The "execute()" method of "PhutilExecPassthru" is deprecated and '. | |||||
'calls should be replaced with "resolve()". See T13660.')); | |||||
return $this->resolve(); | |||||
} | |||||
/** | /** | ||||
* Execute this command. | * Execute this command. | ||||
* | * | ||||
* @return int Error code returned by the subprocess. | * @return int Error code returned by the subprocess. | ||||
* | * | ||||
* @task command | * @task command | ||||
*/ | */ | ||||
public function execute() { | private function executeCommand() { | ||||
$command = $this->getCommand(); | $command = $this->getCommand(); | ||||
$is_write = ($this->stdinData !== null); | $is_write = ($this->stdinData !== null); | ||||
if ($is_write) { | if ($is_write) { | ||||
$stdin_spec = array('pipe', 'r'); | $stdin_spec = array('pipe', 'r'); | ||||
} else { | } else { | ||||
$stdin_spec = STDIN; | $stdin_spec = PhutilSystem::getStdinHandle(); | ||||
} | } | ||||
$spec = array($stdin_spec, STDOUT, STDERR); | $spec = array( | ||||
$stdin_spec, | |||||
PhutilSystem::getStdoutHandle(), | |||||
PhutilSystem::getStderrHandle(), | |||||
); | |||||
$pipes = array(); | $pipes = array(); | ||||
$unmasked_command = $command->getUnmaskedString(); | $unmasked_command = $command->getUnmaskedString(); | ||||
if ($this->hasEnv()) { | if ($this->hasEnv()) { | ||||
$env = $this->getEnv(); | $env = $this->getEnv(); | ||||
} else { | } else { | ||||
$env = null; | $env = null; | ||||
▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | /* -( Future )------------------------------------------------------------- */ | ||||
public function isReady() { | public function isReady() { | ||||
// This isn't really a future because it executes synchronously and has | // This isn't really a future because it executes synchronously and has | ||||
// full control of the console. We're just implementing the interfaces to | // full control of the console. We're just implementing the interfaces to | ||||
// make it easier to share code with ExecFuture. | // make it easier to share code with ExecFuture. | ||||
if (!$this->hasResult()) { | if (!$this->hasResult()) { | ||||
$result = $this->execute(); | $result = $this->executeCommand(); | ||||
$this->setResult($result); | $this->setResult($result); | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
Show All 21 Lines |
Content licensed under Creative Commons Attribution-ShareAlike 4.0 (CC-BY-SA) unless otherwise noted; code licensed under Apache 2.0 or other open source licenses. · CC BY-SA 4.0 · Apache 2.0