diff --git a/src/Command/RecipesCommand.php b/src/Command/RecipesCommand.php index cb1d601fb..7a631e705 100644 --- a/src/Command/RecipesCommand.php +++ b/src/Command/RecipesCommand.php @@ -13,6 +13,7 @@ use Composer\Command\BaseCommand; use Composer\Downloader\TransportException; +use Composer\Package\Package; use Composer\Util\HttpDownloader; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -62,19 +63,25 @@ protected function execute(InputInterface $input, OutputInterface $output) // Inspect one or all packages $package = $input->getArgument('package'); if (null !== $package) { - $packages = [0 => ['name' => strtolower($package)]]; + $packages = [strtolower($package)]; } else { $locker = $this->getComposer()->getLocker(); $lockData = $locker->getLockData(); // Merge all packages installed - $packages = array_merge($lockData['packages'], $lockData['packages-dev']); + $packages = array_column(array_merge($lockData['packages'], $lockData['packages-dev']), 'name'); + $packages = array_unique(array_merge($packages, array_keys($this->symfonyLock->all()))); } $operations = []; - foreach ($packages as $value) { - if (null === $pkg = $installedRepo->findPackage($value['name'], '*')) { - $this->getIO()->writeError(sprintf('Package %s is not installed', $value['name'])); + foreach ($packages as $name) { + $pkg = $installedRepo->findPackage($name, '*'); + + if (!$pkg && $this->symfonyLock->has($name)) { + $pkgVersion = $this->symfonyLock->get($name)['version']; + $pkg = new Package($name, $pkgVersion, $pkgVersion); + } elseif (!$pkg) { + $this->getIO()->writeError(sprintf('Package %s is not installed', $name)); continue; } diff --git a/src/Command/UpdateRecipesCommand.php b/src/Command/UpdateRecipesCommand.php index 9a663cc7c..942aca35c 100644 --- a/src/Command/UpdateRecipesCommand.php +++ b/src/Command/UpdateRecipesCommand.php @@ -13,6 +13,7 @@ use Composer\Command\BaseCommand; use Composer\IO\IOInterface; +use Composer\Package\Package; use Composer\Util\ProcessExecutor; use Symfony\Component\Console\Exception\RuntimeException; use Symfony\Component\Console\Formatter\OutputFormatterStyle; @@ -122,7 +123,9 @@ protected function execute(InputInterface $input, OutputInterface $output): int return 1; } - $originalRecipe = $this->getRecipe($packageName, $recipeRef, $recipeVersion); + $installedRepo = $this->getComposer()->getRepositoryManager()->getLocalRepository(); + $package = $installedRepo->findPackage($packageName, '*') ?? new Package($packageName, $packageLockData['version'], $packageLockData['version']); + $originalRecipe = $this->getRecipe($package, $recipeRef, $recipeVersion); if (null === $originalRecipe) { $io->writeError([ @@ -134,7 +137,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int return 1; } - $newRecipe = $this->getRecipe($packageName); + $newRecipe = $this->getRecipe($package); if ($newRecipe->getRef() === $originalRecipe->getRef()) { $io->write(sprintf('This recipe for %s is already at the latest version.', $packageName)); @@ -259,13 +262,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int return 0; } - private function getRecipe(string $packageName, string $recipeRef = null, string $recipeVersion = null): ?Recipe + private function getRecipe(Package $package, string $recipeRef = null, string $recipeVersion = null): ?Recipe { - $installedRepo = $this->getComposer()->getRepositoryManager()->getLocalRepository(); - $package = $installedRepo->findPackage($packageName, '*'); - if (null === $package) { - throw new RuntimeException(sprintf('Could not find package "%s". Try running "composer install".', $packageName)); - } $operation = new InformationOperation($package); if (null !== $recipeRef) { $operation->setSpecificRecipeVersion($recipeRef, $recipeVersion); @@ -278,10 +276,10 @@ private function getRecipe(string $packageName, string $recipeRef = null, string return new Recipe( $package, - $packageName, + $package->getName(), $operation->getOperationType(), - $recipes['manifests'][$packageName], - $recipes['locks'][$packageName] ?? [] + $recipes['manifests'][$package->getName()], + $recipes['locks'][$package->getName()] ?? [] ); } @@ -358,19 +356,13 @@ private function generateChangelog(Recipe $originalRecipe): ?array private function askForPackage(IOInterface $io, Lock $symfonyLock): ?string { $installedRepo = $this->getComposer()->getRepositoryManager()->getLocalRepository(); - $locker = $this->getComposer()->getLocker(); - $lockData = $locker->getLockData(); - - // Merge all packages installed - $packages = array_merge($lockData['packages'], $lockData['packages-dev']); $operations = []; - foreach ($packages as $value) { - if (null === $pkg = $installedRepo->findPackage($value['name'], '*')) { - continue; + foreach ($symfonyLock->all() as $name => $lock) { + if (isset($lock['recipe']['ref'])) { + $package = $installedRepo->findPackage($name, '*') ?? new Package($name, $lock['version'], $lock['version']); + $operations[] = new InformationOperation($package); } - - $operations[] = new InformationOperation($pkg); } $recipes = $this->flex->fetchRecipes($operations, false); diff --git a/src/Downloader.php b/src/Downloader.php index deff2661e..2adf00df8 100644 --- a/src/Downloader.php +++ b/src/Downloader.php @@ -239,7 +239,6 @@ public function getRecipes(array $operations): array } if (null !== $this->endpoints) { - $data['locks'][$package->getName()]['version'] = $version; continue; } diff --git a/src/Flex.php b/src/Flex.php index f20808c0d..76a880b99 100644 --- a/src/Flex.php +++ b/src/Flex.php @@ -206,7 +206,7 @@ public function configureInstaller() $this->installer = $trace['object']->setSuggestedPackagesReporter(new SuggestedPackagesReporter(new NullIO())); $updateAllowList = \Closure::bind(function () { - return $this->updateWhitelist ?? $this->updateAllowList; + return $this->updateWhitelist ?? $this->updateAllowList ?? null; }, $this->installer, $this->installer)(); if (['php' => 0] === $updateAllowList) { @@ -284,7 +284,7 @@ public function recordOperations(InstallerEvent $event) }, null, Transaction::class)(); foreach ($transation->getOperations() as $operation) { - if ($this->shouldRecordOperation($operation, $event->isDevMode(), $event->getComposer())) { + if (!$operation instanceof UninstallOperation && $this->shouldRecordOperation($operation, $event->isDevMode(), $event->getComposer())) { $this->operations[] = $operation; } } @@ -606,9 +606,7 @@ public function fetchRecipes(array $operations, bool $reset): array } else { $recipes[$name] = $recipe; } - } - - if (!isset($manifests[$name])) { + } else { $bundles = []; if (null === $devPackages) { @@ -626,6 +624,10 @@ public function fetchRecipes(array $operations, bool $reset): array 'manifest' => ['bundles' => $bundles], ]; $recipes[$name] = new Recipe($package, $name, $job, $manifest); + + if ($operation instanceof InstallOperation) { + $this->lock->set($name, ['version' => $package->getPrettyVersion()]); + } } } } @@ -810,6 +812,7 @@ public static function getSubscribedEvents(): array $events = [ PackageEvents::POST_PACKAGE_UPDATE => 'enableThanksReminder', PackageEvents::POST_PACKAGE_INSTALL => 'recordFlexInstall', + PackageEvents::POST_PACKAGE_UNINSTALL => 'record', InstallerEvents::PRE_OPERATIONS_EXEC => 'recordOperations', PluginEvents::PRE_POOL_CREATE => 'truncatePackages', ScriptEvents::POST_CREATE_PROJECT_CMD => 'configureProject',