diff --git a/doc/going-further/extending-castor/remote-imports.md b/doc/going-further/extending-castor/remote-imports.md index 79869313..827623ce 100644 --- a/doc/going-further/extending-castor/remote-imports.md +++ b/doc/going-further/extending-castor/remote-imports.md @@ -85,7 +85,6 @@ import('package://organization/package', source: [ > standard `composer.json` to your repository and import your newly created > package by using the `composer://` scheme and the `vcs` argument. -<<<<<<< HEAD ## Import only a specific file No matter where does the package come from (Composer package, git repository, diff --git a/src/Console/ApplicationFactory.php b/src/Console/ApplicationFactory.php index 4e3815b7..dbd1e214 100644 --- a/src/Console/ApplicationFactory.php +++ b/src/Console/ApplicationFactory.php @@ -50,7 +50,7 @@ public static function create(): SymfonyApplication $cache = new FilesystemAdapter(directory: $cacheDir); $logger = new Logger('castor', [], [new ProcessProcessor()]); $fs = new Filesystem(); - $importer = new Importer($logger, new Composer($logger)); + $importer = new Importer($logger, new Composer($logger), $fs); $eventDispatcher = new EventDispatcher(logger: $logger); $eventDispatcher->addSubscriber(new RemoteImportSubscriber($importer)); diff --git a/src/Remote/Composer.php b/src/Remote/Composer.php index dcd55b03..c33d426c 100644 --- a/src/Remote/Composer.php +++ b/src/Remote/Composer.php @@ -2,9 +2,11 @@ namespace Castor\Remote; +use Castor\GlobalHelper; use Castor\PathHelper; use Castor\Remote\Exception\ComposerError; use Psr\Log\LoggerInterface; +use Symfony\Component\Console\Helper\ProgressIndicator; use Symfony\Component\Process\Process; class Composer @@ -66,14 +68,24 @@ public function require(string $package, string $version): void $requirements = []; } - $this->run('require', $package . ':' . $version); + $progressIndicator = new ProgressIndicator(GlobalHelper::getOutput(), null, 100, ['⠏', '⠛', '⠹', '⢸', '⣰', '⣤', '⣆', '⡇']); + $progressIndicator->start(sprintf('Downloading remote package "%s', $package)); + + $this->run(['require', $package . ':' . $version], callback: function () use ($progressIndicator) { + $progressIndicator->advance(); + }); + + $progressIndicator->finish(sprintf('Imported package "%s', $package)); $requirements[$package] = $version; $this->writeJsonFile(PathHelper::getRoot() . self::PATH_CASTOR_REQUIREMENTS, $requirements); } - private function run(string ...$args): void + /** + * @param string[] $args + */ + private function run(array $args, callable $callback): void { $this->logger->debug('Running Composer command.', [ 'args' => implode(' ', $args), @@ -85,7 +97,7 @@ private function run(string ...$args): void $process->setEnv([ 'COMPOSER_VENDOR_DIR' => $dir, ]); - $process->run(); + $process->run($callback); if (!$process->isSuccessful()) { throw new ComposerError('The Composer process failed: ' . $process->getErrorOutput()); diff --git a/src/Remote/EventSubscriber/RemoteImportSubscriber.php b/src/Remote/EventSubscriber/RemoteImportSubscriber.php index 406398c7..48ff58f9 100644 --- a/src/Remote/EventSubscriber/RemoteImportSubscriber.php +++ b/src/Remote/EventSubscriber/RemoteImportSubscriber.php @@ -2,6 +2,7 @@ namespace Castor\Remote\EventSubscriber; +use Castor\Event\AfterApplicationInitializationEvent; use Castor\Event\BeforeApplicationInitializationEvent; use Castor\Remote\Importer; use Symfony\Component\EventDispatcher\EventSubscriberInterface; @@ -16,12 +17,18 @@ public function __construct( public static function getSubscribedEvents(): array { return [ - BeforeApplicationInitializationEvent::class => 'onInitialize', + BeforeApplicationInitializationEvent::class => 'beforeInitialize', + AfterApplicationInitializationEvent::class => 'afterInitialize', ]; } - public function onInitialize(BeforeApplicationInitializationEvent $event): void + public function beforeInitialize(BeforeApplicationInitializationEvent $event): void { $this->importer->reset(); } + + public function afterInitialize(AfterApplicationInitializationEvent $event): void + { + $this->importer->cleanIfNoRemotes(); + } } diff --git a/src/Remote/Importer.php b/src/Remote/Importer.php index 160f0364..398c5345 100644 --- a/src/Remote/Importer.php +++ b/src/Remote/Importer.php @@ -8,6 +8,7 @@ use Castor\Remote\Exception\ImportError; use Castor\Remote\Exception\InvalidImportFormat; use Psr\Log\LoggerInterface; +use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Process\ExecutableFinder; /** @internal */ @@ -16,6 +17,7 @@ class Importer public function __construct( private readonly LoggerInterface $logger, private readonly Composer $composer, + private readonly Filesystem $filesystem, ) { } @@ -73,6 +75,17 @@ public function reset(): void ]); } + public function cleanIfNoRemotes(): void + { + $json = $this->composer->getConfiguration(); + + if (\count($json['require'] ?? []) > 0) { + return; + } + + $this->filesystem->remove(PathHelper::getRoot() . Composer::VENDOR_DIR); + } + /** * @param ?array{ * url?: string, diff --git a/tests/Examples/Remote/RemoteImportRemoteTasksTest.php.output.txt b/tests/Examples/Remote/RemoteImportRemoteTasksTest.php.output.txt index 41083c96..14105d68 100644 --- a/tests/Examples/Remote/RemoteImportRemoteTasksTest.php.output.txt +++ b/tests/Examples/Remote/RemoteImportRemoteTasksTest.php.output.txt @@ -1,3 +1,12 @@ + Downloading remote package "pyrech/castor-example + Imported package "pyrech/castor-example + + Downloading remote package "pyrech/castor-example-package-not-published + Imported package "pyrech/castor-example-package-not-published + + Downloading remote package "pyrech/foobar + Imported package "pyrech/foobar + Hello from example! =================== diff --git a/tests/TaskTestCase.php b/tests/TaskTestCase.php index 9bd7a45a..0030a229 100644 --- a/tests/TaskTestCase.php +++ b/tests/TaskTestCase.php @@ -25,6 +25,8 @@ public function runTask(array $args, ?string $cwd = null, bool $needRemote = fal if (!$needRemote) { $extraEnv['CASTOR_NO_REMOTE'] = 1; + } elseif (file_exists($castorRequirementsFile = __DIR__ . '/../.castor/vendor/castor-requirements.json')) { + unlink($castorRequirementsFile); } if ($coverage) {