diff --git a/src/Symfony/Component/Process/CHANGELOG.md b/src/Symfony/Component/Process/CHANGELOG.md index 3e33cd0bc936a..d7308566337c7 100644 --- a/src/Symfony/Component/Process/CHANGELOG.md +++ b/src/Symfony/Component/Process/CHANGELOG.md @@ -1,6 +1,12 @@ CHANGELOG ========= + +7.3 +--- + + * Add `RunProcessMessage::fromShellCommandline()` to instantiate a Process via the fromShellCommandline method + 7.1 --- diff --git a/src/Symfony/Component/Process/Messenger/RunProcessMessage.php b/src/Symfony/Component/Process/Messenger/RunProcessMessage.php index b2c33fe3b3c3a..d14ac23650fbd 100644 --- a/src/Symfony/Component/Process/Messenger/RunProcessMessage.php +++ b/src/Symfony/Component/Process/Messenger/RunProcessMessage.php @@ -16,6 +16,8 @@ */ class RunProcessMessage implements \Stringable { + public ?string $commandLine = null; + public function __construct( public readonly array $command, public readonly ?string $cwd = null, @@ -27,6 +29,19 @@ public function __construct( public function __toString(): string { - return implode(' ', $this->command); + return $this->commandLine ?? implode(' ', $this->command); + } + + /** + * Create a process message instance that will instantiate a Process using the fromShellCommandline method. + * + * @see Process::fromShellCommandline + */ + public static function fromShellCommandline(string $command, ?string $cwd = null, ?array $env = null, mixed $input = null, ?float $timeout = 60): self + { + $message = new self([], $cwd, $env, $input, $timeout); + $message->commandLine = $command; + + return $message; } } diff --git a/src/Symfony/Component/Process/Messenger/RunProcessMessageHandler.php b/src/Symfony/Component/Process/Messenger/RunProcessMessageHandler.php index 41c1934cc07f8..69bfa6a183683 100644 --- a/src/Symfony/Component/Process/Messenger/RunProcessMessageHandler.php +++ b/src/Symfony/Component/Process/Messenger/RunProcessMessageHandler.php @@ -22,7 +22,10 @@ final class RunProcessMessageHandler { public function __invoke(RunProcessMessage $message): RunProcessContext { - $process = new Process($message->command, $message->cwd, $message->env, $message->input, $message->timeout); + $process = match ($message->commandLine) { + null => new Process($message->command, $message->cwd, $message->env, $message->input, $message->timeout), + default => Process::fromShellCommandline($message->commandLine, $message->cwd, $message->env, $message->input, $message->timeout), + }; try { return new RunProcessContext($message, $process->mustRun()); diff --git a/src/Symfony/Component/Process/Tests/Messenger/RunProcessMessageHandlerTest.php b/src/Symfony/Component/Process/Tests/Messenger/RunProcessMessageHandlerTest.php index e095fa09d9bd4..b5b9ab14101e1 100644 --- a/src/Symfony/Component/Process/Tests/Messenger/RunProcessMessageHandlerTest.php +++ b/src/Symfony/Component/Process/Tests/Messenger/RunProcessMessageHandlerTest.php @@ -44,4 +44,28 @@ public function testRunFailedProcess() $this->fail('Exception not thrown'); } + + public function testRunSuccessfulProcessFromShellCommandline() + { + $context = (new RunProcessMessageHandler())(RunProcessMessage::fromShellCommandline('ls | grep Test', cwd: __DIR__)); + + $this->assertSame('ls | grep Test', $context->message->commandLine); + $this->assertSame(0, $context->exitCode); + $this->assertStringContainsString(basename(__FILE__), $context->output); + } + + public function testRunFailedProcessFromShellCommandline() + { + try { + (new RunProcessMessageHandler())(RunProcessMessage::fromShellCommandline('invalid')); + $this->fail('Exception not thrown'); + } catch (RunProcessFailedException $e) { + $this->assertSame('invalid', $e->context->message->commandLine); + $this->assertContains( + $e->context->exitCode, + [null, '\\' === \DIRECTORY_SEPARATOR ? 1 : 127], + 'Exit code should be 1 on Windows, 127 on other systems, or null', + ); + } + } }