Skip to content

Commit

Permalink
feat(execute): introduce remote execution command
Browse files Browse the repository at this point in the history
  • Loading branch information
joelwurtz committed Jul 26, 2024
1 parent f449806 commit d361ea7
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/Console/ApplicationFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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])
;
Expand Down
94 changes: 94 additions & 0 deletions src/Console/Command/ExecuteCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?php

namespace Castor\Console\Command;

use Castor\Console\Input\GetRawTokenTrait;
use Castor\Import\Remote\Composer;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\Filesystem\Filesystem;

use function Castor\run_phar;

/** @internal */
#[AsCommand(
name: 'castor:execute',
description: 'Execute a remote task from a packagist directory',
aliases: ['execute'],
)]
final class ExecuteCommand extends Command
{
use GetRawTokenTrait;

public function __construct(
#[Autowire(lazy: true)]
private readonly Composer $composer,
) {
parent::__construct();
}

protected function configure(): void
{
$this
->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;
}
}

0 comments on commit d361ea7

Please sign in to comment.