From 5e6ccae116de28497004408823b13b8a64e157ed Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Sun, 18 Dec 2022 00:02:43 +0100 Subject: [PATCH] Improve version selection in archive command, fixes #4794 (#11230) --- phpstan/baseline-8.1.neon | 5 +++++ phpstan/baseline.neon | 5 ----- src/Composer/Command/ArchiveCommand.php | 29 ++++++++++++++++++++++--- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/phpstan/baseline-8.1.neon b/phpstan/baseline-8.1.neon index 085b10dd7..29e52ed7c 100644 --- a/phpstan/baseline-8.1.neon +++ b/phpstan/baseline-8.1.neon @@ -10,6 +10,11 @@ parameters: count: 1 path: ../src/Composer/Autoload/ClassLoader.php + - + message: "#^Casting to string something that's already string\\.$#" + count: 1 + path: ../src/Composer/Command/ArchiveCommand.php + - message: "#^Only booleans are allowed in an if condition, string\\|false given\\.$#" count: 1 diff --git a/phpstan/baseline.neon b/phpstan/baseline.neon index ad2864c58..3ba4b362c 100644 --- a/phpstan/baseline.neon +++ b/phpstan/baseline.neon @@ -180,11 +180,6 @@ parameters: count: 1 path: ../src/Composer/Command/ArchiveCommand.php - - - message: "#^Only booleans are allowed in an elseif condition, array\\ given\\.$#" - count: 1 - path: ../src/Composer/Command/ArchiveCommand.php - - message: "#^Only booleans are allowed in an if condition, Composer\\\\Composer\\|null given\\.$#" count: 3 diff --git a/src/Composer/Command/ArchiveCommand.php b/src/Composer/Command/ArchiveCommand.php index a356cc50f..e0189109b 100644 --- a/src/Composer/Command/ArchiveCommand.php +++ b/src/Composer/Command/ArchiveCommand.php @@ -18,8 +18,12 @@ use Composer\Config; use Composer\Composer; use Composer\Package\BasePackage; use Composer\Package\CompletePackageInterface; +use Composer\Package\Version\VersionParser; +use Composer\Package\Version\VersionSelector; +use Composer\Pcre\Preg; use Composer\Repository\CompositeRepository; use Composer\Repository\RepositoryFactory; +use Composer\Repository\RepositorySet; use Composer\Script\ScriptEvents; use Composer\Plugin\CommandEvent; use Composer\Plugin\PluginEvents; @@ -156,22 +160,38 @@ EOT if ($composer = $this->tryComposer()) { $localRepo = $composer->getRepositoryManager()->getLocalRepository(); $repo = new CompositeRepository(array_merge([$localRepo], $composer->getRepositoryManager()->getRepositories())); + $minStability = $composer->getPackage()->getMinimumStability(); } else { $defaultRepos = RepositoryFactory::defaultReposWithDefaultManager($io); $io->writeError('No composer.json found in the current directory, searching packages from ' . implode(', ', array_keys($defaultRepos))); $repo = new CompositeRepository($defaultRepos); + $minStability = 'stable'; } - $packages = $repo->findPackages($packageName, $version); + if ($version !== null && Preg::isMatchStrictGroups('{@(stable|RC|beta|alpha|dev)$}i', $version, $match)) { + $minStability = $match[1]; + $version = (string) substr($version, 0, -strlen($match[0])); + } + + $repoSet = new RepositorySet($minStability); + $repoSet->addRepository($repo); + $parser = new VersionParser(); + $constraint = $version !== null ? $parser->parseConstraints($version) : null; + $packages = $repoSet->findPackages(strtolower($packageName), $constraint); if (count($packages) > 1) { - $package = reset($packages); + $versionSelector = new VersionSelector($repoSet); + $package = $versionSelector->findBestCandidate(strtolower($packageName), $version, $minStability); + if ($package === false) { + $package = reset($packages); + } + $io->writeError('Found multiple matches, selected '.$package->getPrettyString().'.'); $io->writeError('Alternatives were '.implode(', ', array_map(static function ($p): string { return $p->getPrettyString(); }, $packages)).'.'); $io->writeError('Please use a more specific constraint to pick a different package.'); - } elseif ($packages) { + } elseif (count($packages) === 1) { $package = reset($packages); $io->writeError('Found an exact match '.$package->getPrettyString().'.'); } else { @@ -183,6 +203,9 @@ EOT if (!$package instanceof CompletePackageInterface) { throw new \LogicException('Expected a CompletePackageInterface instance but found '.get_class($package)); } + if (!$package instanceof BasePackage) { + throw new \LogicException('Expected a BasePackage instance but found '.get_class($package)); + } return $package; }