Skip to content

Commit

Permalink
Merge pull request #40 from utopia-php/PLA-1644
Browse files Browse the repository at this point in the history
feat: support array-based commands in execute to avoid allocating subshell
  • Loading branch information
christyjacob4 authored Sep 23, 2024
2 parents f8af1d6 + 0632875 commit 70877c9
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 3 deletions.
10 changes: 7 additions & 3 deletions src/CLI/Console.php
Original file line number Diff line number Diff line change
Expand Up @@ -124,15 +124,19 @@ public static function exit(int $status = 0): void
*
* This function was inspired by: https://stackoverflow.com/a/13287902/2299554
*
* @param string $cmd
* @param array|string $cmd
* @param string $input
* @param string $output
* @param int $timeout
* @return int
*/
public static function execute(string $cmd, string $input, string &$output, int $timeout = -1, callable $onProgress = null): int
public static function execute(array|string $cmd, string $input, string &$output, int $timeout = -1, callable $onProgress = null): int
{
$cmd = '( '.$cmd.' ) 3>/dev/null ; echo $? >&3';
// If the $cmd is passed as string, it will be wrapped into a subshell by \proc_open
// Forward stdout and exit codes from the subshell.
if (is_string($cmd)) {
$cmd = '( '.$cmd.' ) 3>/dev/null ; echo $? >&3';
}

$pipes = [];
$process = \proc_open(
Expand Down
38 changes: 38 additions & 0 deletions tests/CLI/ConsoleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,44 @@ public function testExecuteBasic()
$this->assertEquals(0, $code);
}

public function testExecuteArray()
{
$output = '';
$input = '';
$cmd = ['php', '-r', "echo 'hello world';"];
$code = Console::execute($cmd, $input, $output, 10);

$this->assertEquals('hello world', $output);
$this->assertEquals(0, $code);
}

// Validate existing environment variables are passed down to the executed command.
public function testExecuteEnvVariables()
{
$randomData = base64_encode(random_bytes(10));
putenv("FOO={$randomData}");

$output = '';
$input = '';
$cmd = ['printenv'];
$code = Console::execute($cmd, $input, $output, 10);

$this->assertEquals(0, $code);

$data = [];
foreach (explode("\n", $output) as $row) {
if (empty($row)) {
continue;
}
$kv = explode('=', $row, 2);
$this->assertEquals(2, count($kv), $row);
$data[$kv[0]] = $kv[1];
}

$this->assertArrayHasKey('FOO', $data);
$this->assertEquals($randomData, $data['FOO']);
}

public function testExecuteStream()
{
$output = '';
Expand Down

0 comments on commit 70877c9

Please sign in to comment.