diff --git a/src/Concerns/RunsCommands.php b/src/Concerns/RunsCommands.php index ce1a4c4..18b3002 100644 --- a/src/Concerns/RunsCommands.php +++ b/src/Concerns/RunsCommands.php @@ -18,9 +18,13 @@ protected function runCommand(string $command, ?string $workingPath = null, bool */ protected function runCommands(array $commands, ?string $workingPath = null, bool $disableOutput = false): Process { + // --no-ansi and --quiet are Composer flags: the commands that are not Composer must not get them + // (GNU rm refuses an option it does not know, so `pollora new --force` failed on Linux). $skipFlags = static fn (string $value): bool => str_starts_with($value, 'chmod') || str_starts_with($value, 'git') - || str_starts_with($value, 'ddev'); + || str_starts_with($value, 'ddev') + || str_starts_with($value, 'rm ') + || str_starts_with($value, 'rd '); if (! $this->output->isDecorated()) { $commands = array_map(static fn (string $value): string => $skipFlags($value) ? $value : $value.' --no-ansi', $commands); diff --git a/tests/Unit/RunsCommandsFlagsTest.php b/tests/Unit/RunsCommandsFlagsTest.php new file mode 100644 index 0000000..c98ea31 --- /dev/null +++ b/tests/Unit/RunsCommandsFlagsTest.php @@ -0,0 +1,56 @@ + $commands + */ +function runsCommandsLine(array $commands, bool $quiet = false): string +{ + $runner = new class + { + use RunsCommands; + + public BufferedOutput $output; + + public ArrayInput $input; + + public function build(array $commands): string + { + return $this->runCommands($commands, disableOutput: true)->getCommandLine(); + } + }; + + $runner->output = new BufferedOutput; // not decorated, as when the output is not a terminal + $runner->input = new ArrayInput($quiet ? ['--quiet' => true] : [], new InputDefinition([new InputOption('quiet', null, InputOption::VALUE_NONE)])); + + return $runner->build($commands); +} + +it('does not hand the Composer flags to rm, as GNU rm refuses an option it does not know', function (): void { + $gone = sys_get_temp_dir().'/pollora-cli-flags-'.bin2hex(random_bytes(4)); + + expect(runsCommandsLine(['rm -rf "'.$gone.'"']))->toBe('rm -rf "'.$gone.'"') + ->and(runsCommandsLine(['rm -rf "'.$gone.'"'], quiet: true))->toBe('rm -rf "'.$gone.'"'); +}); + +it('does not hand the Composer flags to rd, the Windows way of removing a directory', function (): void { + expect(runsCommandsLine(['rd /s /q "C:\\gone"']))->toBe('rd /s /q "C:\\gone"'); +}); + +it('still hands --no-ansi to the other commands when the output is not decorated, and --quiet when asked', function (): void { + expect(runsCommandsLine(['echo composer']))->toBe('echo composer --no-ansi') + ->and(runsCommandsLine(['echo composer'], quiet: true))->toBe('echo composer --no-ansi --quiet'); +}); + +it('still leaves chmod, git and ddev without flags', function (): void { + expect(runsCommandsLine(['chmod +x x', 'git init']))->toBe('chmod +x x && git init'); +});