diff --git a/src/Activities.php b/src/Activities.php index 4ba4609..4d41e23 100644 --- a/src/Activities.php +++ b/src/Activities.php @@ -6,7 +6,11 @@ use Innmind\CLI\Console; use Innmind\OperatingSystem\OperatingSystem; use Innmind\Time\Period; -use Innmind\Immutable\Set; +use Innmind\Immutable\{ + Set, + Attempt, + Sequence, +}; final class Activities { @@ -33,10 +37,13 @@ private function __construct( $this->activities = $activities; } + /** + * @return Attempt + */ public function __invoke( Console $console, OperatingSystem $os, - ): Console { + ): Attempt { // If no activities yet we wait a little bit to avoid always calling // this method. // The better approach would be to use sockets and to monitor them so we @@ -46,27 +53,32 @@ public function __invoke( // exit this method periodically to allow the source to be restarted in // order to check if any agent crashed in order to restart it. if (\count($this->activities) === 0) { - $_ = $os + return $os ->process() ->halt(Period::millisecond(500)) - ->unwrap(); + ->map(static fn() => $console); } - while ($activity = \array_shift($this->activities)) { - $this->iteration->start(); - $console = ($this->trigger)( - $console, - $os, - $activity, - $this->triggers, - ); + $activities = Sequence::of(...$this->activities); + $this->activities = []; - if ($activity !== Activity::start) { - $console = $this->iteration->end($console); - } - } + return $activities + ->sink($console) + ->attempt(function($console, $activity) use ($os) { + $this->iteration->start(); + $console = ($this->trigger)( + $console, + $os, + $activity, + $this->triggers, + ); + + if ($activity !== Activity::start) { + return $console->flatMap($this->iteration->end(...)); + } - return $console; + return $console; + }); } /** diff --git a/src/Command/Work.php b/src/Command/Work.php index d95f197..909d6d1 100644 --- a/src/Command/Work.php +++ b/src/Command/Work.php @@ -46,7 +46,7 @@ public function __invoke(Console $console): Attempt static fn() => Triggers::cases(), ); - return Attempt::result(($this->monitor)($console, Set::of(...$triggers))); + return ($this->monitor)($console, Set::of(...$triggers)); } /** diff --git a/src/Iteration.php b/src/Iteration.php index 2bc2dc6..d4277aa 100644 --- a/src/Iteration.php +++ b/src/Iteration.php @@ -4,7 +4,10 @@ namespace Innmind\LabStation; use Innmind\CLI\Console; -use Innmind\Immutable\Str; +use Innmind\Immutable\{ + Str, + Attempt, +}; final class Iteration { @@ -20,17 +23,20 @@ public function failing(): void $this->shouldClearTerminal = false; } - public function end(Console $console): Console + /** + * @return Attempt + */ + public function end(Console $console): Attempt { if (!$this->shouldClearTerminal) { - return $console; + return Attempt::result($console); } if ($console->options()->contains('keep-output')) { - return $console; + return Attempt::result($console); } // clear terminal - return $console->output(Str::of("\033[2J\033[H"))->unwrap(); + return $console->output(Str::of("\033[2J\033[H")); } } diff --git a/src/Monitor.php b/src/Monitor.php index 5bf99cc..3f01a0c 100644 --- a/src/Monitor.php +++ b/src/Monitor.php @@ -9,6 +9,7 @@ use Innmind\Immutable\{ Set, Sequence, + Attempt, }; final class Monitor @@ -36,8 +37,10 @@ public function __construct( /** * @param Set $triggers + * + * @return Attempt */ - public function __invoke(Console $console, Set $triggers): Console + public function __invoke(Console $console, Set $triggers): Attempt { $project = $console->workingDirectory(); $scheduler = Scheduler::of($this->os); @@ -46,11 +49,9 @@ public function __invoke(Console $console, Set $triggers): Console $this->iteration, $triggers, ); - /** @var array{Console, boolean} */ - $carry = [$console, false]; - [$console] = $scheduler - ->sink($carry) + return $scheduler + ->sink(Attempt::result($console)) ->with( new Monitor\Loop( $this->agents, @@ -58,7 +59,5 @@ public function __invoke(Console $console, Set $triggers): Console $project, ), ); - - return $console; } } diff --git a/src/Monitor/Loop.php b/src/Monitor/Loop.php index 6a3d0e6..c7d1f26 100644 --- a/src/Monitor/Loop.php +++ b/src/Monitor/Loop.php @@ -12,6 +12,7 @@ use Innmind\OperatingSystem\OperatingSystem; use Innmind\Url\Path; use Innmind\Immutable\{ + Attempt, Sequence, Predicate\Instance, }; @@ -22,6 +23,7 @@ final class Loop private Sequence $agents; private Activities $activities; private Path $project; + private bool $started = false; /** * @param Sequence $agents @@ -37,22 +39,22 @@ public function __construct( } /** - * @param array{Console, boolean} $carry - * @param Continuation $continuation + * @param Attempt $console + * @param Continuation> $continuation * - * @return Continuation + * @return Continuation> */ public function __invoke( - array $carry, + Attempt $console, OperatingSystem $os, Continuation $continuation, ): Continuation { - [$console, $started] = $carry; + if (!$this->started) { + $this->started = true; - if (!$started) { return $continuation ->schedule($this->agents->map($this->buildTask(...))) - ->carryWith([$console, true]); + ->carryWith($console); } $continuation = $continuation->schedule( @@ -62,12 +64,14 @@ public function __invoke( ->map($this->buildTask(...)), ); - $console = ($this->activities)( - $console, - $os, + return $console->match( + fn($console) => $continuation->carryWith( + ($this->activities)($console, $os), + ), + static fn($e) => $continuation + ->carryWith(Attempt::error($e)) + ->terminate(), ); - - return $continuation->carryWith([$console, $started]); } /** diff --git a/src/Trigger.php b/src/Trigger.php index e48a61a..9b2b159 100644 --- a/src/Trigger.php +++ b/src/Trigger.php @@ -5,17 +5,22 @@ use Innmind\CLI\Console; use Innmind\OperatingSystem\OperatingSystem; -use Innmind\Immutable\Set; +use Innmind\Immutable\{ + Set, + Attempt, +}; interface Trigger { /** * @param Set $triggers + * + * @return Attempt */ public function __invoke( Console $console, OperatingSystem $os, Activity $activity, Set $triggers, - ): Console; + ): Attempt; } diff --git a/src/Trigger/All.php b/src/Trigger/All.php index d27a76e..e7b8866 100644 --- a/src/Trigger/All.php +++ b/src/Trigger/All.php @@ -9,7 +9,11 @@ }; use Innmind\CLI\Console; use Innmind\OperatingSystem\OperatingSystem; -use Innmind\Immutable\Set; +use Innmind\Immutable\{ + Set, + Sequence, + Attempt, +}; final class All implements Trigger { @@ -30,11 +34,14 @@ public function __invoke( OperatingSystem $os, Activity $activity, Set $triggers, - ): Console { - foreach ($this->triggers as $trigger) { - $console = $trigger($console, $os, $activity, $triggers); - } - - return $console; + ): Attempt { + return Sequence::of(...$this->triggers) + ->sink($console) + ->attempt(static fn($console, $trigger) => $trigger( + $console, + $os, + $activity, + $triggers, + )); } } diff --git a/src/Trigger/BlackBox.php b/src/Trigger/BlackBox.php index bd71a9b..ab947f2 100644 --- a/src/Trigger/BlackBox.php +++ b/src/Trigger/BlackBox.php @@ -11,11 +11,17 @@ }; use Innmind\OperatingSystem\OperatingSystem; use Innmind\CLI\Console; -use Innmind\Server\Control\Server\Command; +use Innmind\Server\Control\Server\{ + Command, + Process, +}; use Innmind\Filesystem\Name; use Innmind\Immutable\{ Map, Set, + Attempt, + Str, + SideEffect, }; final class BlackBox implements Trigger @@ -33,9 +39,9 @@ public function __invoke( OperatingSystem $os, Activity $activity, Set $triggers, - ): Console { + ): Attempt { if (!$triggers->contains(Triggers::proofs)) { - return $console; + return Attempt::result($console); } return match ($activity) { @@ -43,24 +49,32 @@ public function __invoke( Activity::proofsModified => $this->attempt($console, $os), Activity::fixturesModified => $this->attempt($console, $os), Activity::propertiesModified => $this->attempt($console, $os), - default => $console, + default => Attempt::result($console), }; } - private function attempt(Console $console, OperatingSystem $os): Console + /** + * @return Attempt + */ + private function attempt(Console $console, OperatingSystem $os): Attempt { return $os ->filesystem() ->mount($console->workingDirectory()) - ->unwrap() - ->get(Name::of('blackbox.php')) - ->match( - fn() => $this->run($console, $os), - static fn() => $console, + ->flatMap( + fn($adapter) => $adapter + ->get(Name::of('blackbox.php')) + ->match( + fn() => $this->run($console, $os), + static fn() => Attempt::result($console), + ), ); } - private function run(Console $console, OperatingSystem $os): Console + /** + * @return Attempt + */ + private function run(Console $console, OperatingSystem $os): Attempt { /** @var Map */ $variables = $console @@ -72,7 +86,7 @@ private function run(Console $console, OperatingSystem $os): Console )) ->put('LAB_STATION', 'true'); - $process = $os + return $os ->control() ->processes() ->execute( @@ -81,13 +95,29 @@ private function run(Console $console, OperatingSystem $os): Console ->withWorkingDirectory($console->workingDirectory()) ->withEnvironments($variables), ) - ->unwrap(); + ->eitherWay( + fn($process) => $this->blackbox($process, $console, $os), + static fn() => $console->output(Str::of("Failed to run BlackBox\n")), + ); + } + + /** + * @return Attempt + */ + private function blackbox( + Process $process, + Console $console, + OperatingSystem $os, + ): Attempt { $console = $process ->output() ->map(static fn($chunk) => $chunk->data()) ->sink($console) ->attempt(static fn(Console $console, $line) => $console->output($line)) - ->unwrap(); + ->match( + static fn($console) => $console, + static fn($e) => $e, + ); $successful = $process->wait()->match( static fn() => true, static fn() => false, @@ -97,8 +127,12 @@ private function run(Console $console, OperatingSystem $os): Console $this->iteration->failing(); } + if ($console instanceof \Throwable) { + return Attempt::error($console); + } + if ($console->options()->contains('silent')) { - return $console; + return Attempt::result($console); } return $os @@ -112,11 +146,12 @@ private function run(Console $console, OperatingSystem $os): Console }, ), ) - ->either() - ->flatMap(static fn($process) => $process->wait()) - ->match( - static fn() => $console, - static fn() => $console, - ); + ->flatMap( + static fn($process) => $process + ->wait() + ->attempt(static fn() => new \Exception) + ->recover(static fn() => Attempt::result(SideEffect::identity)), + ) + ->map(static fn() => $console); } } diff --git a/src/Trigger/CodingStandard.php b/src/Trigger/CodingStandard.php index c002a3b..4822c05 100644 --- a/src/Trigger/CodingStandard.php +++ b/src/Trigger/CodingStandard.php @@ -11,11 +11,17 @@ }; use Innmind\CLI\Console; use Innmind\OperatingSystem\OperatingSystem; -use Innmind\Server\Control\Server\Command; +use Innmind\Server\Control\Server\{ + Command, + Process, +}; use Innmind\Filesystem\Name; use Innmind\Immutable\{ Map, Set, + Attempt, + Str, + SideEffect, }; final class CodingStandard implements Trigger @@ -33,9 +39,9 @@ public function __invoke( OperatingSystem $os, Activity $activity, Set $triggers, - ): Console { + ): Attempt { if (!$triggers->contains(Triggers::codingStandard)) { - return $console; + return Attempt::result($console); } return match ($activity) { @@ -44,31 +50,37 @@ public function __invoke( Activity::proofsModified => $this->attempt($console, $os), Activity::fixturesModified => $this->attempt($console, $os), Activity::propertiesModified => $this->attempt($console, $os), - default => $console, + default => Attempt::result($console), }; } - private function attempt(Console $console, OperatingSystem $os): Console + /** + * @return Attempt + */ + private function attempt(Console $console, OperatingSystem $os): Attempt { - $directory = $os + return $os ->filesystem() ->mount($console->workingDirectory()) - ->unwrap(); - - return $directory - ->get(Name::of('.php_cs.dist')) - ->otherwise(static fn() => $directory->get(Name::of('.php-cs-fixer.dist.php'))) - ->match( - fn($file) => $this->run($console, $os, $file->name()), - static fn() => $console, + ->flatMap( + fn($directory) => $directory + ->get(Name::of('.php_cs.dist')) + ->otherwise(static fn() => $directory->get(Name::of('.php-cs-fixer.dist.php'))) + ->match( + fn($file) => $this->run($console, $os, $file->name()), + static fn() => Attempt::result($console), + ), ); } + /** + * @return Attempt + */ private function run( Console $console, OperatingSystem $os, Name $file, - ): Console { + ): Attempt { /** @var Map */ $variables = $console ->variables() @@ -91,17 +103,33 @@ private function run( ->withArgument('udiff'); } - $process = $os + return $os ->control() ->processes() ->execute($command) - ->unwrap(); + ->eitherWay( + fn($process) => $this->cs($process, $console, $os), + static fn() => $console->output(Str::of("Failed to run CS\n")), + ); + } + + /** + * @return Attempt + */ + private function cs( + Process $process, + Console $console, + OperatingSystem $os, + ): Attempt { $console = $process ->output() ->map(static fn($chunk) => $chunk->data()) ->sink($console) ->attempt(static fn(Console $console, $line) => $console->output($line)) - ->unwrap(); + ->match( + static fn($console) => $console, + static fn($e) => $e, + ); $successful = $process->wait()->match( static fn() => true, static fn() => false, @@ -111,8 +139,12 @@ private function run( $this->iteration->failing(); } + if ($console instanceof \Throwable) { + return Attempt::error($console); + } + if ($console->options()->contains('silent')) { - return $console; + return Attempt::result($console); } return $os @@ -126,11 +158,12 @@ private function run( }, ), ) - ->either() - ->flatMap(static fn($process) => $process->wait()) - ->match( - static fn() => $console, - static fn() => $console, - ); + ->flatMap( + static fn($process) => $process + ->wait() + ->attempt(static fn() => new \Exception) + ->recover(static fn() => Attempt::result(SideEffect::identity)), + ) + ->map(static fn() => $console); } } diff --git a/src/Trigger/ComposerUpdate.php b/src/Trigger/ComposerUpdate.php index 5b22282..c753454 100644 --- a/src/Trigger/ComposerUpdate.php +++ b/src/Trigger/ComposerUpdate.php @@ -18,6 +18,7 @@ Map, Str, Set, + Attempt, }; final class ComposerUpdate implements Trigger @@ -28,35 +29,44 @@ public function __invoke( OperatingSystem $os, Activity $activity, Set $triggers, - ): Console { + ): Attempt { if (!$triggers->contains(Triggers::composerUpdate)) { - return $console; + return Attempt::result($console); } return match ($activity) { Activity::start => $this->ask($console, $os), - default => $console, + default => Attempt::result($console), }; } - private function ask(Console $console, OperatingSystem $os): Console + /** + * @return Attempt + */ + private function ask(Console $console, OperatingSystem $os): Attempt { $ask = Question::of('Update dependencies? [Y/n]'); - [$response, $console] = $ask($console)->unwrap(); - return $response - ->maybe() - ->filter(static fn($response) => match ($response->toString()) { - 'y', '' => true, - default => false, - }) - ->match( - fn() => $this->run($console, $os), - static fn() => $console, - ); + return $ask($console)->flatMap(function($response) use ($os) { + [$response, $console] = $response; + + return $response + ->maybe() + ->filter(static fn($response) => match ($response->toString()) { + 'y', '' => true, + default => false, + }) + ->match( + fn() => $this->run($console, $os), + static fn() => Attempt::result($console), + ); + }); } - private function run(Console $console, OperatingSystem $os): Console + /** + * @return Attempt + */ + private function run(Console $console, OperatingSystem $os): Attempt { /** @var Map */ $variables = $console->variables()->filter( @@ -73,13 +83,15 @@ private function run(Console $console, OperatingSystem $os): Console ->withWorkingDirectory($console->workingDirectory()) ->withEnvironments($variables), ) - ->unwrap() - ->output() - ->map(static fn($chunk) => $chunk->data()) - ->sink($console) - ->attempt(static fn(Console $console, $line) => $console->output($line)) - ->unwrap() - ->output(Str::of("Dependencies updated!\n")) - ->unwrap(); + ->flatMap( + static fn($process) => $process + ->output() + ->map(static fn($chunk) => $chunk->data()) + ->sink($console) + ->attempt(static fn(Console $console, $line) => $console->output($line)), + ) + ->flatMap(static fn($console) => $console->output( + Str::of("Dependencies updated!\n"), + )); } } diff --git a/src/Trigger/DockerCompose.php b/src/Trigger/DockerCompose.php index ee6871f..80db1ed 100644 --- a/src/Trigger/DockerCompose.php +++ b/src/Trigger/DockerCompose.php @@ -16,6 +16,7 @@ Map, Str, Set, + Attempt, }; final class DockerCompose implements Trigger @@ -26,31 +27,39 @@ public function __invoke( OperatingSystem $os, Activity $activity, Set $triggers, - ): Console { + ): Attempt { if (!$triggers->contains(Triggers::dockerCompose)) { - return $console; + return Attempt::result($console); } return match ($activity) { Activity::start => $this->attempt($console, $os), - default => $console, + default => Attempt::result($console), }; } - private function attempt(Console $console, OperatingSystem $os): Console + /** + * @return Attempt + */ + private function attempt(Console $console, OperatingSystem $os): Attempt { return $os ->filesystem() ->mount($console->workingDirectory()) - ->unwrap() - ->get(Name::of('docker-compose.yml')) - ->match( - fn() => $this->run($console, $os), - static fn() => $console, + ->flatMap( + fn($adapter) => $adapter + ->get(Name::of('docker-compose.yml')) + ->match( + fn() => $this->run($console, $os), + static fn() => Attempt::result($console), + ), ); } - private function run(Console $console, OperatingSystem $os): Console + /** + * @return Attempt + */ + private function run(Console $console, OperatingSystem $os): Attempt { /** @var Map */ $variables = $console @@ -67,13 +76,14 @@ private function run(Console $console, OperatingSystem $os): Console ->withWorkingDirectory($console->workingDirectory()) ->withEnvironments($variables), ) - ->either() - ->flatMap(static fn($process) => $process->wait()) - ->match( - static fn() => $console, - static fn() => $console - ->error(Str::of("Failed to start docker\n")) - ->unwrap(), - ); + ->flatMap( + static fn($process) => $process + ->wait() + ->attempt(static fn() => new \Exception), + ) + ->map(static fn() => $console) + ->recover(static fn() => $console->error( + Str::of("Failed to start docker\n"), + )); } } diff --git a/src/Trigger/Psalm.php b/src/Trigger/Psalm.php index fad32ce..e74fc73 100644 --- a/src/Trigger/Psalm.php +++ b/src/Trigger/Psalm.php @@ -11,11 +11,17 @@ }; use Innmind\CLI\Console; use Innmind\OperatingSystem\OperatingSystem; -use Innmind\Server\Control\Server\Command; +use Innmind\Server\Control\Server\{ + Command, + Process, +}; use Innmind\Filesystem\Name; use Innmind\Immutable\{ Map, Set, + Attempt, + Str, + SideEffect, }; final class Psalm implements Trigger @@ -33,38 +39,46 @@ public function __invoke( OperatingSystem $os, Activity $activity, Set $triggers, - ): Console { + ): Attempt { if (!$triggers->contains(Triggers::psalm)) { - return $console; + return Attempt::result($console); } return match ($activity) { Activity::sourcesModified => $this->attempt($console, $os), - default => $console, + default => Attempt::result($console), }; } - private function attempt(Console $console, OperatingSystem $os): Console + /** + * @return Attempt + */ + private function attempt(Console $console, OperatingSystem $os): Attempt { return $os ->filesystem() ->mount($console->workingDirectory()) - ->unwrap() - ->get(Name::of('psalm.xml')) - ->match( - fn() => $this->run($console, $os), - static fn() => $console, + ->flatMap( + fn($adapter) => $adapter + ->get(Name::of('psalm.xml')) + ->match( + fn() => $this->run($console, $os), + static fn() => Attempt::result($console), + ), ); } - private function run(Console $console, OperatingSystem $os): Console + /** + * @return Attempt + */ + private function run(Console $console, OperatingSystem $os): Attempt { /** @var Map */ $variables = $console->variables()->filter( static fn($key) => \in_array($key, ['HOME', 'USER', 'PATH'], true), ); - $process = $os + return $os ->control() ->processes() ->execute( @@ -73,13 +87,29 @@ private function run(Console $console, OperatingSystem $os): Console ->withWorkingDirectory($console->workingDirectory()) ->withEnvironments($variables), ) - ->unwrap(); + ->eitherWay( + fn($process) => $this->psalm($process, $console, $os), + static fn() => $console->output(Str::of("Failed to run Psalm\n")), + ); + } + + /** + * @return Attempt + */ + private function psalm( + Process $process, + Console $console, + OperatingSystem $os, + ): Attempt { $console = $process ->output() ->map(static fn($chunk) => $chunk->data()) ->sink($console) ->attempt(static fn(Console $console, $line) => $console->output($line)) - ->unwrap(); + ->match( + static fn($console) => $console, + static fn($e) => $e, + ); $successful = $process->wait()->match( static fn() => true, static fn() => false, @@ -89,8 +119,12 @@ private function run(Console $console, OperatingSystem $os): Console $this->iteration->failing(); } + if ($console instanceof \Throwable) { + return Attempt::error($console); + } + if ($console->options()->contains('silent')) { - return $console; + return Attempt::result($console); } return $os @@ -104,11 +138,12 @@ private function run(Console $console, OperatingSystem $os): Console }, ), ) - ->either() - ->flatMap(static fn($process) => $process->wait()) - ->match( - static fn() => $console, - static fn() => $console, - ); + ->flatMap( + static fn($process) => $process + ->wait() + ->attempt(static fn() => new \Exception) + ->recover(static fn() => Attempt::result(SideEffect::identity)), + ) + ->map(static fn() => $console); } } diff --git a/src/Trigger/Tests.php b/src/Trigger/Tests.php index 061ecbd..d2272ff 100644 --- a/src/Trigger/Tests.php +++ b/src/Trigger/Tests.php @@ -11,11 +11,17 @@ }; use Innmind\CLI\Console; use Innmind\OperatingSystem\OperatingSystem; -use Innmind\Server\Control\Server\Command; +use Innmind\Server\Control\Server\{ + Command, + Process, +}; use Innmind\Filesystem\Name; use Innmind\Immutable\{ Map, Set, + Attempt, + Str, + SideEffect, }; final class Tests implements Trigger @@ -33,40 +39,48 @@ public function __invoke( OperatingSystem $os, Activity $activity, Set $triggers, - ): Console { + ): Attempt { if (!$triggers->contains(Triggers::tests)) { - return $console; + return Attempt::result($console); } return match ($activity) { Activity::sourcesModified => $this->attempt($console, $os), Activity::testsModified => $this->attempt($console, $os), Activity::fixturesModified => $this->attempt($console, $os), - default => $console, + default => Attempt::result($console), }; } - private function attempt(Console $console, OperatingSystem $os): Console + /** + * @return Attempt + */ + private function attempt(Console $console, OperatingSystem $os): Attempt { return $os ->filesystem() ->mount($console->workingDirectory()) - ->unwrap() - ->get(Name::of('phpunit.xml.dist')) - ->match( - fn() => $this->run($console, $os), - static fn() => $console, + ->flatMap( + fn($adapter) => $adapter + ->get(Name::of('phpunit.xml.dist')) + ->match( + fn() => $this->run($console, $os), + static fn() => Attempt::result($console), + ), ); } - private function run(Console $console, OperatingSystem $os): Console + /** + * @return Attempt + */ + private function run(Console $console, OperatingSystem $os): Attempt { /** @var Map */ $variables = $console ->variables() ->filter(static fn($key) => $key === 'PATH'); - $process = $os + return $os ->control() ->processes() ->execute( @@ -76,13 +90,29 @@ private function run(Console $console, OperatingSystem $os): Console ->withWorkingDirectory($console->workingDirectory()) ->withEnvironments($variables), ) - ->unwrap(); + ->eitherWay( + fn($process) => $this->phpunit($process, $console, $os), + static fn() => $console->output(Str::of("Failed to run PHPUnit\n")), + ); + } + + /** + * @return Attempt + */ + private function phpunit( + Process $process, + Console $console, + OperatingSystem $os, + ): Attempt { $console = $process ->output() ->map(static fn($chunk) => $chunk->data()) ->sink($console) ->attempt(static fn(Console $console, $line) => $console->output($line)) - ->unwrap(); + ->match( + static fn($console) => $console, + static fn($e) => $e, + ); $successful = $process->wait()->match( static fn() => true, static fn() => false, @@ -92,8 +122,12 @@ private function run(Console $console, OperatingSystem $os): Console $this->iteration->failing(); } + if ($console instanceof \Throwable) { + return Attempt::error($console); + } + if ($console->options()->contains('silent')) { - return $console; + return Attempt::result($console); } return $os @@ -107,11 +141,12 @@ private function run(Console $console, OperatingSystem $os): Console }, ), ) - ->either() - ->flatMap(static fn($process) => $process->wait()) - ->match( - static fn() => $console, - static fn() => $console, - ); + ->flatMap( + static fn($process) => $process + ->wait() + ->attempt(static fn() => new \Exception) + ->recover(static fn() => Attempt::result(SideEffect::identity)), + ) + ->map(static fn() => $console); } } diff --git a/tests/IterationTest.php b/tests/IterationTest.php index 0801e20..a09a5b3 100644 --- a/tests/IterationTest.php +++ b/tests/IterationTest.php @@ -30,7 +30,7 @@ public function testEndingAnIterationWithoutAStartWillClearTheTerminal() new Options, ); - $console = $iteration->end($console); + $console = $iteration->end($console)->unwrap(); $this->assertSame( ["\033[2J\033[H"], $console @@ -57,7 +57,7 @@ public function testNormalIterationWithoutAFailureWillClearTheTerminal() ); $iteration->start(); - $console = $iteration->end($console); + $console = $iteration->end($console)->unwrap(); $this->assertSame( ["\033[2J\033[H"], $console @@ -85,7 +85,7 @@ public function testNormalIterationWithAFailureWillNotClearTheTerminal() $iteration->start(); $iteration->failing(); - $console = $iteration->end($console); + $console = $iteration->end($console)->unwrap(); $this->assertSame( [], $console @@ -112,7 +112,7 @@ public function testNormalIterationWithoutAFailureWillNotClearTheTerminalWhenExp ); $iteration->start(); - $console = $iteration->end($console); + $console = $iteration->end($console)->unwrap(); $this->assertSame( [], $console @@ -140,7 +140,7 @@ public function testNormalIterationWithAFailureWillNotClearTheTerminalWhenExplic $iteration->start(); $iteration->failing(); - $console = $iteration->end($console); + $console = $iteration->end($console)->unwrap(); $this->assertSame( [], $console @@ -168,9 +168,9 @@ public function testClearTheTerminalEvenWhenPreviousIterationFailed() $iteration->start(); $iteration->failing(); - $console = $iteration->end($console); + $console = $iteration->end($console)->unwrap(); $iteration->start(); - $console = $iteration->end($console); + $console = $iteration->end($console)->unwrap(); $this->assertSame( ["\033[2J\033[H"], $console diff --git a/tests/Trigger/AllTest.php b/tests/Trigger/AllTest.php index b4094f4..fc10d04 100644 --- a/tests/Trigger/AllTest.php +++ b/tests/Trigger/AllTest.php @@ -15,7 +15,10 @@ Command\Options, }; use Innmind\OperatingSystem\OperatingSystem; -use Innmind\Immutable\Set; +use Innmind\Immutable\{ + Set, + Attempt, +}; use Innmind\BlackBox\PHPUnit\Framework\TestCase; class AllTest extends TestCase @@ -34,8 +37,8 @@ public function __invoke( OperatingSystem $os, Activity $activity, Set $triggers, - ): Console { - return $console; + ): Attempt { + return Attempt::result($console); } }, new class implements Trigger { @@ -44,8 +47,8 @@ public function __invoke( OperatingSystem $os, Activity $activity, Set $triggers, - ): Console { - return $console; + ): Attempt { + return Attempt::result($console); } }, new class implements Trigger { @@ -54,8 +57,8 @@ public function __invoke( OperatingSystem $os, Activity $activity, Set $triggers, - ): Console { - return $console; + ): Attempt { + return Attempt::result($console); } }, ); @@ -74,6 +77,6 @@ public function __invoke( ); $os = OperatingSystem::new(); - $this->assertSame($console, $trigger($console, $os, $activity, $triggers)); + $this->assertSame($console, $trigger($console, $os, $activity, $triggers)->unwrap()); } } diff --git a/tests/Trigger/BlackBoxTest.php b/tests/Trigger/BlackBoxTest.php index 284966a..cd0bf12 100644 --- a/tests/Trigger/BlackBoxTest.php +++ b/tests/Trigger/BlackBoxTest.php @@ -75,7 +75,7 @@ public function testDoNothingWhenNotOfExpectedType() $os, Activity::start, ISet::of(Triggers::tests), - )); + )->unwrap()); } public function testDoNothingWhenTriggerNotEnabled(): BB\Proof @@ -103,7 +103,7 @@ public function testDoNothingWhenTriggerNotEnabled(): BB\Proof $os, $type, ISet::of(), - ); + )->unwrap(); $this->assertSame( [], $console @@ -191,8 +191,8 @@ function($command) use (&$count) { $os, $type, ISet::of(Triggers::proofs), - ); - $console = $iteration->end($console); + )->unwrap(); + $console = $iteration->end($console)->unwrap(); $this->assertSame( ['some output', 'some error', "\033[2J\033[H"], $console @@ -242,8 +242,8 @@ public function testDoesntTriggerWhenNoBlackBoxFile(): BB\Proof $os, $type, ISet::of(Triggers::proofs), - ); - $console = $iteration->end($console); + )->unwrap(); + $console = $iteration->end($console)->unwrap(); $this->assertSame( ["\033[2J\033[H"], $console @@ -314,8 +314,8 @@ function($command) use (&$count) { $os, Activity::sourcesModified, ISet::of(Triggers::proofs), - ); - $console = $iteration->end($console); + )->unwrap(); + $console = $iteration->end($console)->unwrap(); $this->assertSame( [], $console @@ -388,8 +388,8 @@ function($command) use (&$count) { $os, Activity::sourcesModified, ISet::of(Triggers::proofs), - ); - $console = $iteration->end($console); + )->unwrap(); + $console = $iteration->end($console)->unwrap(); $this->assertSame( [], $console @@ -455,8 +455,8 @@ function($command) use (&$count) { $os, Activity::sourcesModified, ISet::of(Triggers::proofs), - ); - $console = $iteration->end($console); + )->unwrap(); + $console = $iteration->end($console)->unwrap(); $this->assertSame( ["\033[2J\033[H"], $console diff --git a/tests/Trigger/CodingStandardTest.php b/tests/Trigger/CodingStandardTest.php index c2dafad..bb950c9 100644 --- a/tests/Trigger/CodingStandardTest.php +++ b/tests/Trigger/CodingStandardTest.php @@ -76,7 +76,7 @@ public function testDoNothingWhenNotOfExpectedType() $os, Activity::start, Set::of(Triggers::codingStandard), - )); + )->unwrap()); } public function testDoNothingWhenToolNotInstalled() @@ -106,7 +106,7 @@ public function testDoNothingWhenToolNotInstalled() $os, Activity::sourcesModified, Set::of(Triggers::codingStandard), - )); + )->unwrap()); } public function testDoNothingWhenTriggerNotEnabled() @@ -131,7 +131,7 @@ public function testDoNothingWhenTriggerNotEnabled() $os, Activity::sourcesModified, Set::of(), - ); + )->unwrap(); $this->assertSame( [], $console @@ -216,8 +216,8 @@ function($command) use (&$count) { $os, $activity, Set::of(Triggers::codingStandard), - ); - $console = $iteration->end($console); + )->unwrap(); + $console = $iteration->end($console)->unwrap(); $this->assertSame( ['some output', 'some error', "\033[2J\033[H"], $console @@ -288,8 +288,8 @@ function($command) use (&$count) { $os, Activity::sourcesModified, Set::of(Triggers::codingStandard), - ); - $console = $iteration->end($console); + )->unwrap(); + $console = $iteration->end($console)->unwrap(); $this->assertSame( [], $console @@ -365,8 +365,8 @@ function($command) use (&$count) { $os, Activity::testsModified, Set::of(Triggers::codingStandard), - ); - $console = $iteration->end($console); + )->unwrap(); + $console = $iteration->end($console)->unwrap(); $this->assertSame( ['some output', 'some error', "\033[2J\033[H"], $console @@ -439,8 +439,8 @@ function($command) use (&$count) { $os, Activity::sourcesModified, Set::of(Triggers::codingStandard), - ); - $console = $iteration->end($console); + )->unwrap(); + $console = $iteration->end($console)->unwrap(); $this->assertSame( [], $console @@ -506,8 +506,8 @@ function($command) use (&$count) { $os, Activity::sourcesModified, Set::of(Triggers::codingStandard), - ); - $console = $iteration->end($console); + )->unwrap(); + $console = $iteration->end($console)->unwrap(); $this->assertSame( ["\033[2J\033[H"], $console diff --git a/tests/Trigger/ComposerUpdateTest.php b/tests/Trigger/ComposerUpdateTest.php index ea4b648..3f621b9 100644 --- a/tests/Trigger/ComposerUpdateTest.php +++ b/tests/Trigger/ComposerUpdateTest.php @@ -61,7 +61,7 @@ public function testDoNothingWhenNotOfExpectedType() $os, Activity::sourcesModified, Set::of(Triggers::composerUpdate), - )); + )->unwrap()); } public function testDoNothingWhenTriggerNotEnabled() @@ -86,7 +86,7 @@ public function testDoNothingWhenTriggerNotEnabled() $os, Activity::start, Set::of(), - ); + )->unwrap(); $this->assertSame( [], $console @@ -142,7 +142,7 @@ function($command) { $os, Activity::start, Set::of(Triggers::composerUpdate), - ); + )->unwrap(); $this->assertSame( ['Update dependencies? [Y/n] ', 'some output', 'some error', "Dependencies updated!\n"], $console @@ -175,7 +175,7 @@ public function testDoesntTriggerUpdateWhenNegativeResponse() $os, Activity::start, Set::of(Triggers::composerUpdate), - ); + )->unwrap(); $this->assertSame( ['Update dependencies? [Y/n] '], $console diff --git a/tests/Trigger/DockerComposeTest.php b/tests/Trigger/DockerComposeTest.php index 73fa632..a35c759 100644 --- a/tests/Trigger/DockerComposeTest.php +++ b/tests/Trigger/DockerComposeTest.php @@ -66,7 +66,7 @@ public function testDoesntStartDockerComposeWhenNotStartActivity() $os, Activity::sourcesModified, Set::of(Triggers::dockerCompose), - )); + )->unwrap()); } public function testDoesntStartDockerComposeWhenNoConfigFile() @@ -98,7 +98,7 @@ public function testDoesntStartDockerComposeWhenNoConfigFile() $os, Activity::start, Set::of(Triggers::dockerCompose), - )); + )->unwrap()); } public function testDoNothingWhenTriggerNotEnabled() @@ -123,7 +123,7 @@ public function testDoNothingWhenTriggerNotEnabled() $os, Activity::start, Set::of(), - ); + )->unwrap(); $this->assertSame( [], $console @@ -183,6 +183,6 @@ function($command) { $os, Activity::start, Set::of(Triggers::dockerCompose), - )); + )->unwrap()); } } diff --git a/tests/Trigger/PsalmTest.php b/tests/Trigger/PsalmTest.php index 2c0dd80..361e607 100644 --- a/tests/Trigger/PsalmTest.php +++ b/tests/Trigger/PsalmTest.php @@ -67,7 +67,7 @@ public function testDoNothingWhenNotOfExpectedType() $os, Activity::start, Set::of(Triggers::psalm), - )); + )->unwrap()); } public function testDoNothingWhenPsalmNotInstalled() @@ -95,7 +95,7 @@ public function testDoNothingWhenPsalmNotInstalled() $os, Activity::sourcesModified, Set::of(Triggers::psalm), - )); + )->unwrap()); } public function testDoNothingWhenTriggerNotEnabled() @@ -119,7 +119,7 @@ public function testDoNothingWhenTriggerNotEnabled() $os, Activity::sourcesModified, Set::of(), - ); + )->unwrap(); $this->assertSame( [], $console @@ -197,8 +197,8 @@ function($command) use (&$count) { $os, Activity::sourcesModified, Set::of(Triggers::psalm), - ); - $console = $iteration->end($console); + )->unwrap(); + $console = $iteration->end($console)->unwrap(); $this->assertSame( ['some output', 'some error', "\033[2J\033[H"], $console @@ -268,8 +268,8 @@ function($command) use (&$count) { $os, Activity::sourcesModified, Set::of(Triggers::psalm), - ); - $console = $iteration->end($console); + )->unwrap(); + $console = $iteration->end($console)->unwrap(); $this->assertSame( [], $console @@ -342,8 +342,8 @@ function($command) use (&$count) { $os, Activity::sourcesModified, Set::of(Triggers::psalm), - ); - $console = $iteration->end($console); + )->unwrap(); + $console = $iteration->end($console)->unwrap(); $this->assertSame( [], $console @@ -410,8 +410,8 @@ function($command) use (&$count) { $os, Activity::sourcesModified, Set::of(Triggers::psalm), - ); - $console = $iteration->end($console); + )->unwrap(); + $console = $iteration->end($console)->unwrap(); $this->assertSame( ["\033[2J\033[H"], $console diff --git a/tests/Trigger/TestsTest.php b/tests/Trigger/TestsTest.php index e2b3664..3efdfa0 100644 --- a/tests/Trigger/TestsTest.php +++ b/tests/Trigger/TestsTest.php @@ -75,7 +75,7 @@ public function testDoNothingWhenNotOfExpectedType() $os, Activity::start, ISet::of(Triggers::tests), - )); + )->unwrap()); } public function testDoNothingWhenTriggerNotEnabled(): BlackBox\Proof @@ -102,7 +102,7 @@ public function testDoNothingWhenTriggerNotEnabled(): BlackBox\Proof $os, $type, ISet::of(), - ); + )->unwrap(); $this->assertSame( [], $console @@ -187,8 +187,8 @@ function($command) use (&$count) { $os, $type, ISet::of(Triggers::tests), - ); - $console = $iteration->end($console); + )->unwrap(); + $console = $iteration->end($console)->unwrap(); $this->assertSame( ['some output', 'some error', "\033[2J\033[H"], $console @@ -241,8 +241,8 @@ public function testDoesntTriggerWhenNoPHPUnitFile(): BlackBox\Proof $os, $type, ISet::of(Triggers::tests), - ); - $console = $iteration->end($console); + )->unwrap(); + $console = $iteration->end($console)->unwrap(); $this->assertSame( ["\033[2J\033[H"], $console @@ -313,8 +313,8 @@ function($command) use (&$count) { $os, Activity::sourcesModified, ISet::of(Triggers::tests), - ); - $console = $iteration->end($console); + )->unwrap(); + $console = $iteration->end($console)->unwrap(); $this->assertSame( [], $console @@ -387,8 +387,8 @@ function($command) use (&$count) { $os, Activity::sourcesModified, ISet::of(Triggers::tests), - ); - $console = $iteration->end($console); + )->unwrap(); + $console = $iteration->end($console)->unwrap(); $this->assertSame( [], $console @@ -455,8 +455,8 @@ function($command) use (&$count) { $os, Activity::sourcesModified, ISet::of(Triggers::tests), - ); - $console = $iteration->end($console); + )->unwrap(); + $console = $iteration->end($console)->unwrap(); $this->assertSame( ["\033[2J\033[H"], $console