diff --git a/src/Console/ApplicationFactory.php b/src/Console/ApplicationFactory.php
index 96f9974c..867638ad 100644
--- a/src/Console/ApplicationFactory.php
+++ b/src/Console/ApplicationFactory.php
@@ -52,7 +52,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 UpdateCastorListener(
$cache,
diff --git a/src/Remote/Composer.php b/src/Remote/Composer.php
index dcd55b03..077a151d 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/Importer.php b/src/Remote/Importer.php
index 29f2d74f..599a5dfc 100644
--- a/src/Remote/Importer.php
+++ b/src/Remote/Importer.php
@@ -9,6 +9,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 */
@@ -17,6 +18,7 @@ class Importer
public function __construct(
private readonly LoggerInterface $logger,
private readonly Composer $composer,
+ private readonly Filesystem $filesystem,
) {
}
@@ -77,6 +79,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/src/Remote/Listener/RemoteImportListener.php b/src/Remote/Listener/RemoteImportListener.php
index 75fc6087..ff9893c4 100644
--- a/src/Remote/Listener/RemoteImportListener.php
+++ b/src/Remote/Listener/RemoteImportListener.php
@@ -2,6 +2,7 @@
namespace Castor\Remote\Listener;
+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/tests/Examples/Remote/RemoteImportRemoteTasksTest.php.output.txt b/tests/Examples/Remote/RemoteImportRemoteTasksTest.php.output.txt
index 41083c96..959db5dd 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) {