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) {
|
while ($candidate instanceof AliasPackage) {
|
||||||
$candidate = $candidate->getAliasOf();
|
$candidate = $candidate->getAliasOf();
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,9 +65,10 @@ class VersionSelector
|
||||||
* @param string $targetPackageVersion
|
* @param string $targetPackageVersion
|
||||||
* @param PlatformRequirementFilterInterface|bool|string[] $platformRequirementFilter
|
* @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 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
|
* @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 (!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
|
// 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)) {
|
if (count($this->platformConstraints) > 0 && !($platformRequirementFilter instanceof IgnoreAllPlatformRequirementFilter)) {
|
||||||
/** @var array<string, true> $alreadyWarnedNames */
|
/** @var array<string, true> $alreadyWarnedNames */
|
||||||
$alreadyWarnedNames = [];
|
$alreadyWarnedNames = [];
|
||||||
|
/** @var array<string, true> $alreadySeenNames */
|
||||||
|
$alreadySeenNames = [];
|
||||||
|
|
||||||
foreach ($candidates as $pkg) {
|
foreach ($candidates as $pkg) {
|
||||||
$reqs = $pkg->getRequires();
|
$reqs = $pkg->getRequires();
|
||||||
|
@ -137,14 +140,16 @@ class VersionSelector
|
||||||
$reason = 'is missing from your platform';
|
$reason = 'is missing from your platform';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($io !== null) {
|
$isLatestVersion = !isset($alreadySeenNames[$pkg->getName()]);
|
||||||
$isFirst = !isset($alreadyWarnedNames[$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;
|
$alreadyWarnedNames[$pkg->getName()] = true;
|
||||||
$latest = $isFirst ? "'s latest version" : '';
|
$latest = $isLatestVersion ? "'s latest version" : '';
|
||||||
$io->writeError(
|
$io->writeError(
|
||||||
'<warning>Cannot use '.$pkg->getPrettyName().$latest.' '.$pkg->getPrettyVersion().' as it '.$link->getDescription().' '.$link->getTarget().' '.$link->getPrettyConstraint().' which '.$reason.'.</>',
|
'<warning>Cannot use '.$pkg->getPrettyName().$latest.' '.$pkg->getPrettyVersion().' as it '.$link->getDescription().' '.$link->getTarget().' '.$link->getPrettyConstraint().' which '.$reason.'.</>',
|
||||||
true,
|
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
|
public function testShowPlatformOnlyShowsPlatformPackages(): void
|
||||||
{
|
{
|
||||||
$this->initTempComposer([
|
$this->initTempComposer([
|
||||||
|
|
Loading…
Reference in New Issue