Skip to content

Commit

Permalink
Merge b941ee3 into 6d86ecf
Browse files Browse the repository at this point in the history
  • Loading branch information
azjezz committed May 7, 2022
2 parents 6d86ecf + b941ee3 commit 61fb6bf
Show file tree
Hide file tree
Showing 9 changed files with 78 additions and 62 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Expand Up @@ -67,3 +67,7 @@
* **BC** - `Psl\Result\ResultInterface::getException()` method has been renamed to `Psl\Result\ResultInterface::getThrowable()`
* **BC** - `Psl\Result\wrap` function now catches all `Throwable`s instead of only `Exception`s
* introduced a new `Psl\Result\reflect` function
* **BC** - `Psl\Shell\escape_argument` function has been removed, `Shell\execute` arguments are now always escaped.
* **BC** - `$escape_arguments` argument of `Shell\execute` function has been removed.
* introduced a new `Psl\Shell\ErrorOutputBehavior` enum
* added a new `$error_output_behavior` argument to `Shell\execute` function, which can be used to return the command error output content, as well as the standard output content.
1 change: 1 addition & 0 deletions config/.phpcs.xml
Expand Up @@ -15,6 +15,7 @@
<exclude-pattern>*/src/Psl/Hash/Hmac/Algorithm.php</exclude-pattern>
<exclude-pattern>*/src/Psl/OS/OperatingSystemFamily.php</exclude-pattern>
<exclude-pattern>*/src/Psl/Password/Algorithm.php</exclude-pattern>
<exclude-pattern>*/src/Psl/Shell/ErrorOutputBehavior.php</exclude-pattern>

<arg name="basepath" value="."/>
<arg name="colors"/>
Expand Down
7 changes: 5 additions & 2 deletions docs/component/shell.md
Expand Up @@ -12,7 +12,10 @@

#### `Functions`

- [escape_argument](./../../src/Psl/Shell/escape_argument.php#L17)
- [execute](./../../src/Psl/Shell/execute.php#L42)
- [execute](./../../src/Psl/Shell/execute.php#L41)

#### `Enums`

- [ErrorOutputBehavior](./../../src/Psl/Shell/ErrorOutputBehavior.php#L7)


3 changes: 2 additions & 1 deletion src/Psl/Internal/Loader.php
Expand Up @@ -377,8 +377,8 @@ final class Loader
'Psl\Encoding\Base64\decode',
'Psl\Encoding\Hex\encode',
'Psl\Encoding\Hex\decode',
'Psl\Shell\escape_argument',
'Psl\Shell\execute',
'Psl\Shell\Internal\escape_argument',
'Psl\Html\encode',
'Psl\Html\encode_special_characters',
'Psl\Html\decode',
Expand Down Expand Up @@ -743,6 +743,7 @@ final class Loader
'Psl\Hash\Hmac\Algorithm',
'Psl\OS\OperatingSystemFamily',
'Psl\Password\Algorithm',
'Psl\Shell\ErrorOutputBehavior'
];

public const TYPE_CONSTANTS = 1;
Expand Down
27 changes: 27 additions & 0 deletions src/Psl/Shell/ErrorOutputBehavior.php
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace Psl\Shell;

enum ErrorOutputBehavior {
/**
* Discard the standard error output.
*/
case DISCARD;

/**
* Append the standard error output content to the standard output content.
*/
case APPEND;

/**
* Prepend the standard error output content to the standard output content.
*/
case PREPEND;

/**
* Replace the standard output content with the standard error output content.
*/
case REPLACE;
}
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace Psl\Shell;
namespace Psl\Shell\Internal;

use Psl\Regex;
use Psl\Str\Byte;
Expand All @@ -13,6 +13,8 @@
* Escape a string to be used as a shell argument.
*
* @psalm-taint-escape shell
*
* @internal
*/
function escape_argument(string $argument): string
{
Expand Down
25 changes: 8 additions & 17 deletions src/Psl/Shell/execute.php
Expand Up @@ -30,7 +30,6 @@
* use the default value ( the current directory )
* @param array<string, string> $environment A dict with the environment variables for the command that
* will be run.
* @param bool $escape_arguments If set to true ( default ), all $arguments will be escaped using `escape_argument`.
*
* @psalm-taint-sink shell $command
*
Expand All @@ -44,23 +43,10 @@ function execute(
array $arguments = [],
?string $working_directory = null,
array $environment = [],
bool $escape_arguments = true,
ErrorOutputBehavior $error_output_behavior = ErrorOutputBehavior::DISCARD,
?float $timeout = null
): string {
if ($escape_arguments) {
$arguments = Vec\map(
$arguments,
/**
* @param string $argument
*
* @return string
*
* @pure
*/
static fn(string $argument): string => escape_argument($argument)
);
}

$arguments = Vec\map($arguments, Internal\escape_argument(...));
$commandline = Str\join([$command, ...$arguments], ' ');

/** @psalm-suppress MissingThrowsDocblock - safe ( $offset is within-of-bounds ) */
Expand Down Expand Up @@ -201,5 +187,10 @@ static function (array $m) use (
throw new Exception\FailedExecutionException($commandline, $stdout_content, $stderr_content, $code);
}

return $stdout_content;
return match ($error_output_behavior) {
ErrorOutputBehavior::PREPEND => $stderr_content . $stdout_content,
ErrorOutputBehavior::APPEND => $stdout_content . $stderr_content,
ErrorOutputBehavior::REPLACE => $stderr_content,
ErrorOutputBehavior::DISCARD => $stdout_content,
};
}
41 changes: 0 additions & 41 deletions tests/unit/Shell/EscapeArgumentTest.php

This file was deleted.

28 changes: 28 additions & 0 deletions tests/unit/Shell/ExecuteTest.php
Expand Up @@ -91,4 +91,32 @@ public function testItThrowsWhenWorkingDirectoryDoesntExist(): void

Shell\execute(PHP_BINARY, ['-r', 'echo getcwd();'], $dir);
}

public function testErrorOutputIsDiscarded(): void
{
$result = Shell\execute(PHP_BINARY, ['-r', 'fwrite(STDOUT, "hello"); fwrite(STDERR, " world");']);

static::assertSame('hello', $result);
}

public function testErrorOutputIsAppended(): void
{
$result = Shell\execute(PHP_BINARY, ['-r', 'fwrite(STDOUT, "hello"); fwrite(STDERR, " world");'], error_output_behavior: Shell\ErrorOutputBehavior::APPEND);

static::assertSame('hello world', $result);
}

public function testErrorOutputIsPrepended(): void
{
$result = Shell\execute(PHP_BINARY, ['-r', 'fwrite(STDOUT, "hello"); fwrite(STDERR, " world");'], error_output_behavior: Shell\ErrorOutputBehavior::PREPEND);

static::assertSame(' worldhello', $result);
}

public function testErrorOutputIsReplacingStandardOutput(): void
{
$result = Shell\execute(PHP_BINARY, ['-r', 'fwrite(STDOUT, "hello"); fwrite(STDERR, " world");'], error_output_behavior: Shell\ErrorOutputBehavior::REPLACE);

static::assertSame(' world', $result);
}
}

0 comments on commit 61fb6bf

Please sign in to comment.