From 342ca96b36a7ff1be2f2e68a5b4687ac23df7cd0 Mon Sep 17 00:00:00 2001 From: Joel Wurtz Date: Fri, 26 Jul 2024 14:55:16 +0200 Subject: [PATCH] feat(execute): introduce remote execution command --- src/Console/ApplicationFactory.php | 2 + src/Console/Command/ExecuteCommand.php | 94 ++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 src/Console/Command/ExecuteCommand.php diff --git a/src/Console/ApplicationFactory.php b/src/Console/ApplicationFactory.php index d2c478af..dac37335 100644 --- a/src/Console/ApplicationFactory.php +++ b/src/Console/ApplicationFactory.php @@ -5,6 +5,7 @@ use Castor\Console\Command\CompileCommand; use Castor\Console\Command\ComposerCommand; use Castor\Console\Command\DebugCommand; +use Castor\Console\Command\ExecuteCommand; use Castor\Console\Command\RepackCommand; use Castor\Container; use Castor\Helper\PathHelper; @@ -196,6 +197,7 @@ private static function configureContainer(ContainerConfigurator $c, bool $repac '$containerBuilder' => service(ContainerInterface::class), ]) ->call('add', [service(DebugCommand::class)]) + ->call('add', [service(ExecuteCommand::class)]) ->call('setDispatcher', [service(EventDispatcherInterface::class)]) ->call('setCatchErrors', [true]) ; diff --git a/src/Console/Command/ExecuteCommand.php b/src/Console/Command/ExecuteCommand.php new file mode 100644 index 00000000..16812813 --- /dev/null +++ b/src/Console/Command/ExecuteCommand.php @@ -0,0 +1,94 @@ +addArgument('package', InputArgument::REQUIRED, 'Package to execute') + ->ignoreValidationErrors() + ; + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + // Create temporary directory + $tmpDir = tempnam(sys_get_temp_dir(), 'castor-exec-'); + + if (!$tmpDir) { + throw new \RuntimeException('Could not create temporary directory'); + } + + unlink($tmpDir); + + // format of execute is + // vendor/package:version@binary + $name = $input->getArgument('package'); + $nameSplitted = explode('@', $name); + + if (\count($nameSplitted) >= 2) { + $package = $nameSplitted[0]; + $binary = $nameSplitted[1]; + } else { + $package = $name; + $binary = null; + } + + $fs = new Filesystem(); + $composerJsonPath = $tmpDir . '/composer.json'; + $vendorDirectory = $tmpDir . '/vendor'; + $tokens = $this->getRawTokens($input); + + $args = []; + $foundPackageName = false; + + foreach ($tokens as $token) { + if ($foundPackageName) { + $args[] = $token; + } else { + if ($token === $name) { + $foundPackageName = true; + } + } + } + + try { + $fs->mkdir($tmpDir, 0o755); + $this->composer->run($composerJsonPath, $vendorDirectory, ['require', $package, '--no-interaction'], $output, $input->isInteractive()); + run_phar($vendorDirectory . '/bin/' . $binary, $args); + } finally { + $fs->remove($tmpDir); + } + + return Command::SUCCESS; + } +}