1
0
Fork 0

Add warning when outdated command rejects an existing version due to platform requirements, fixes #11016 (#11113)

pull/11115/head
Jordi Boggiano 2022-10-12 13:57:14 +02:00 committed by GitHub
parent 8ed7c46179
commit 822fd640d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 103 additions and 6 deletions

View File

@ -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();
}

View File

@ -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
);
}

View File

@ -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([