Add warning when outdated command rejects an existing version due to platform requirements, fixes #11016 (#11113)
parent
8ed7c46179
commit
822fd640d0
|
@ -1379,7 +1379,17 @@ EOT
|
|||
}
|
||||
}
|
||||
|
||||
$candidate = $versionSelector->findBestCandidate($name, $targetVersion, $bestStability, $platformReqFilter);
|
||||
if ($this->getIO()->isVerbose()) {
|
||||
$showWarnings = true;
|
||||
} else {
|
||||
$showWarnings = static function (PackageInterface $candidate) use ($package): bool {
|
||||
if (str_starts_with($candidate->getVersion(), 'dev-') || str_starts_with($package->getVersion(), 'dev-')) {
|
||||
return false;
|
||||
}
|
||||
return version_compare($candidate->getVersion(), $package->getVersion(), '<=');
|
||||
};
|
||||
}
|
||||
$candidate = $versionSelector->findBestCandidate($name, $targetVersion, $bestStability, $platformReqFilter, 0, $this->getIO(), $showWarnings);
|
||||
while ($candidate instanceof AliasPackage) {
|
||||
$candidate = $candidate->getAliasOf();
|
||||
}
|
||||
|
|
|
@ -65,9 +65,10 @@ class VersionSelector
|
|||
* @param string $targetPackageVersion
|
||||
* @param PlatformRequirementFilterInterface|bool|string[] $platformRequirementFilter
|
||||
* @param IOInterface|null $io If passed, warnings will be output there in case versions cannot be selected due to platform requirements
|
||||
* @param callable(PackageInterface):bool|bool $showWarnings
|
||||
* @return PackageInterface|false
|
||||
*/
|
||||
public function findBestCandidate(string $packageName, ?string $targetPackageVersion = null, string $preferredStability = 'stable', $platformRequirementFilter = null, int $repoSetFlags = 0, ?IOInterface $io = null)
|
||||
public function findBestCandidate(string $packageName, ?string $targetPackageVersion = null, string $preferredStability = 'stable', $platformRequirementFilter = null, int $repoSetFlags = 0, ?IOInterface $io = null, $showWarnings = true)
|
||||
{
|
||||
if (!isset(BasePackage::$stabilities[$preferredStability])) {
|
||||
// If you get this, maybe you are still relying on the Composer 1.x signature where the 3rd arg was the php version
|
||||
|
@ -114,6 +115,8 @@ class VersionSelector
|
|||
if (count($this->platformConstraints) > 0 && !($platformRequirementFilter instanceof IgnoreAllPlatformRequirementFilter)) {
|
||||
/** @var array<string, true> $alreadyWarnedNames */
|
||||
$alreadyWarnedNames = [];
|
||||
/** @var array<string, true> $alreadySeenNames */
|
||||
$alreadySeenNames = [];
|
||||
|
||||
foreach ($candidates as $pkg) {
|
||||
$reqs = $pkg->getRequires();
|
||||
|
@ -137,14 +140,16 @@ class VersionSelector
|
|||
$reason = 'is missing from your platform';
|
||||
}
|
||||
|
||||
if ($io !== null) {
|
||||
$isFirst = !isset($alreadyWarnedNames[$pkg->getName()]);
|
||||
$isLatestVersion = !isset($alreadySeenNames[$pkg->getName()]);
|
||||
$alreadySeenNames[$pkg->getName()] = true;
|
||||
if ($io !== null && ($showWarnings === true || (is_callable($showWarnings) && $showWarnings($pkg)))) {
|
||||
$isFirstWarning = !isset($alreadyWarnedNames[$pkg->getName()]);
|
||||
$alreadyWarnedNames[$pkg->getName()] = true;
|
||||
$latest = $isFirst ? "'s latest version" : '';
|
||||
$latest = $isLatestVersion ? "'s latest version" : '';
|
||||
$io->writeError(
|
||||
'<warning>Cannot use '.$pkg->getPrettyName().$latest.' '.$pkg->getPrettyVersion().' as it '.$link->getDescription().' '.$link->getTarget().' '.$link->getPrettyConstraint().' which '.$reason.'.</>',
|
||||
true,
|
||||
$isFirst ? IOInterface::NORMAL : IOInterface::VERBOSE
|
||||
$isFirstWarning ? IOInterface::NORMAL : IOInterface::VERBOSE
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -167,6 +167,88 @@ outdated/patch 1.0.0 <highlight>! 1.0.1</highlight>',
|
|||
];
|
||||
}
|
||||
|
||||
public function testOutdatedFiltersAccordingToPlatformReqsAndWarns(): void
|
||||
{
|
||||
$this->initTempComposer([
|
||||
'repositories' => [
|
||||
'packages' => [
|
||||
'type' => 'package',
|
||||
'package' => [
|
||||
['name' => 'vendor/package', 'description' => 'generic description', 'version' => '1.0.0'],
|
||||
['name' => 'vendor/package', 'description' => 'generic description', 'version' => '1.1.0', 'require' => ['ext-missing' => '3']],
|
||||
['name' => 'vendor/package', 'description' => 'generic description', 'version' => '1.2.0', 'require' => ['ext-missing' => '3']],
|
||||
['name' => 'vendor/package', 'description' => 'generic description', 'version' => '1.3.0', 'require' => ['ext-missing' => '3']],
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$this->createInstalledJson([
|
||||
$this->getPackage('vendor/package', '1.1.0'),
|
||||
]);
|
||||
|
||||
$appTester = $this->getApplicationTester();
|
||||
$appTester->run(['command' => 'outdated']);
|
||||
self::assertSame("<warning>Cannot use vendor/package 1.1.0 as it requires ext-missing 3 which is missing from your platform.
|
||||
Legend:
|
||||
! patch or minor release available - update recommended
|
||||
~ major release available - update possible
|
||||
|
||||
Direct dependencies required in composer.json:
|
||||
Everything up to date
|
||||
|
||||
Transitive dependencies not required in composer.json:
|
||||
vendor/package 1.1.0 ~ 1.0.0", trim($appTester->getDisplay(true)));
|
||||
|
||||
$appTester = $this->getApplicationTester();
|
||||
$appTester->run(['command' => 'outdated', '--verbose' => true]);
|
||||
self::assertSame("<warning>Cannot use vendor/package's latest version 1.3.0 as it requires ext-missing 3 which is missing from your platform.
|
||||
<warning>Cannot use vendor/package 1.2.0 as it requires ext-missing 3 which is missing from your platform.
|
||||
<warning>Cannot use vendor/package 1.1.0 as it requires ext-missing 3 which is missing from your platform.
|
||||
Legend:
|
||||
! patch or minor release available - update recommended
|
||||
~ major release available - update possible
|
||||
|
||||
Direct dependencies required in composer.json:
|
||||
Everything up to date
|
||||
|
||||
Transitive dependencies not required in composer.json:
|
||||
vendor/package 1.1.0 ~ 1.0.0", trim($appTester->getDisplay(true)));
|
||||
}
|
||||
|
||||
public function testOutdatedFiltersAccordingToPlatformReqsWithoutWarningForHigherVersions(): void
|
||||
{
|
||||
$this->initTempComposer([
|
||||
'repositories' => [
|
||||
'packages' => [
|
||||
'type' => 'package',
|
||||
'package' => [
|
||||
['name' => 'vendor/package', 'description' => 'generic description', 'version' => '1.0.0'],
|
||||
['name' => 'vendor/package', 'description' => 'generic description', 'version' => '1.1.0'],
|
||||
['name' => 'vendor/package', 'description' => 'generic description', 'version' => '1.2.0'],
|
||||
['name' => 'vendor/package', 'description' => 'generic description', 'version' => '1.3.0', 'require' => ['php' => '^99']],
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$this->createInstalledJson([
|
||||
$this->getPackage('vendor/package', '1.1.0'),
|
||||
]);
|
||||
|
||||
$appTester = $this->getApplicationTester();
|
||||
$appTester->run(['command' => 'outdated']);
|
||||
self::assertSame("Legend:
|
||||
! patch or minor release available - update recommended
|
||||
~ major release available - update possible
|
||||
|
||||
Direct dependencies required in composer.json:
|
||||
Everything up to date
|
||||
|
||||
Transitive dependencies not required in composer.json:
|
||||
vendor/package 1.1.0 <highlight>! 1.2.0</highlight>", trim($appTester->getDisplay(true)));
|
||||
}
|
||||
|
||||
public function testShowPlatformOnlyShowsPlatformPackages(): void
|
||||
{
|
||||
$this->initTempComposer([
|
||||
|
|
Loading…
Reference in New Issue