Lines 100.00% 11 / 11
Methods 100.00% 1 / 1
Classes 100.00% 1 / 1
Name Lines Methods CRAP
 runCommand 100.00% 11 / 11 100.00% 1 / 1 3
20final readonly class AmpExternalCommandRunner implements ExternalCommandRunner
21{
22    public function runCommand(array $command, Duration $timeout, Cancellation $cancellation): ExternalCommandResult
23    {
24        $process = Process::start($command);
25        $process->getStdin()->close();
26        // Both pipes drain while the command runs, so a chatty composer install cannot fill one and stall.
27        /** @var Future<string> $output */
28        $output = async(static fn(): string => buffer($process->getStdout()));
29        /** @var Future<string> $errorOutput */
30        $errorOutput = async(static fn(): string => buffer($process->getStderr()));
31
32        try {
33            $exitCode = $process->join(new CompositeCancellation($cancellation, new TimeoutCancellation($timeout->toSeconds())));
34        } catch (CancelledException $e) {
35            $process->kill();
36
37            if ($cancellation->isRequested()) {
38                throw $e;
39            }
40
41            throw DeployException::createForReason(DeployError::CommandTimedOut, $e, command: implode(' ', $command), timeout: (string) $timeout);
42        }
43
44        return new ExternalCommandResult($exitCode, $output->await(), $errorOutput->await());
45    }
46}