Skip to content

Commit

Permalink
Fix handling of virtual packages when searching for packages or when …
Browse files Browse the repository at this point in the history
…looking up the preferred version (init & require command), refs #10489
  • Loading branch information
Seldaek committed Feb 16, 2022
1 parent 8b52546 commit 2a2440c
Showing 1 changed file with 41 additions and 16 deletions.
57 changes: 41 additions & 16 deletions src/Composer/Command/InitCommand.php
Expand Up @@ -577,28 +577,36 @@ final protected function determineRequirements(InputInterface $input, OutputInte
}
$matches = array_values($matches);

$exactMatch = null;
$choices = array();
foreach ($matches as $position => $foundPackage) {
$abandoned = '';
if (isset($foundPackage['abandoned'])) {
if (is_string($foundPackage['abandoned'])) {
$replacement = sprintf('Use %s instead', $foundPackage['abandoned']);
} else {
$replacement = 'No replacement was suggested';
}
$abandoned = sprintf('<warning>Abandoned. %s.</warning>', $replacement);
}

$choices[] = sprintf(' <info>%5s</info> %s %s', "[$position]", $foundPackage['name'], $abandoned);
if ($foundPackage['name'] === $package) {
$exactMatch = false;
foreach ($matches as $match) {
if ($match['name'] === $package) {
$exactMatch = true;
break;
}
}

// no match, prompt which to pick
if (!$exactMatch) {
$providers = $this->getRepos()->getProviders($package);
if (count($providers) > 0) {
array_unshift($matches, array('name' => $package, 'description' => ''));
}

$choices = array();
foreach ($matches as $position => $foundPackage) {
$abandoned = '';
if (isset($foundPackage['abandoned'])) {
if (is_string($foundPackage['abandoned'])) {
$replacement = sprintf('Use %s instead', $foundPackage['abandoned']);
} else {
$replacement = 'No replacement was suggested';
}
$abandoned = sprintf('<warning>Abandoned. %s.</warning>', $replacement);
}

$choices[] = sprintf(' <info>%5s</info> %s %s', "[$position]", $foundPackage['name'], $abandoned);
}

$io->writeError(array(
'',
sprintf('Found <info>%s</info> packages matching <info>%s</info>', count($matches), $package),
Expand Down Expand Up @@ -893,7 +901,8 @@ private function findBestVersionAndNameForPackage(InputInterface $input, $name,
$platformRequirementFilter = PlatformRequirementFilterFactory::fromBoolOrList($ignorePlatformReqs);

// find the latest version allowed in this repo set
$versionSelector = new VersionSelector($this->getRepositorySet($input, $minimumStability), $platformRepo);
$repoSet = $this->getRepositorySet($input, $minimumStability);
$versionSelector = new VersionSelector($repoSet, $platformRepo);
$effectiveMinimumStability = $minimumStability ?: $this->getMinimumStability($input);

$package = $versionSelector->findBestCandidate($name, $requiredVersion, $preferredStability, $platformRequirementFilter);
Expand All @@ -905,6 +914,22 @@ private function findBestVersionAndNameForPackage(InputInterface $input, $name,
return array($name, $requiredVersion ?: '*');
}

// Check if it is a virtual package provided by others
$providers = $repoSet->getProviders($name);
if (count($providers) > 0) {
$constraint = '*';
if ($input->isInteractive()) {
$constraint = $this->getIO()->askAndValidate('Package "<info>'.$name.'</info>" does not exist but is provided by '.count($providers).' packages. Which version constraint would you like to use? [<info>*</info>] ', function ($value) {
$parser = new VersionParser();
$parser->parseConstraints($value);

return $value;
}, 3, '*');
}

return array($name, $constraint);
}

// Check whether the package requirements were the problem
if (!($platformRequirementFilter instanceof IgnoreAllPlatformRequirementFilter) && ($candidate = $versionSelector->findBestCandidate($name, $requiredVersion, $preferredStability, PlatformRequirementFilterFactory::ignoreAll()))) {
throw new \InvalidArgumentException(sprintf(
Expand Down

0 comments on commit 2a2440c

Please sign in to comment.