diff --git a/src/Composer/DependencyResolver/PoolOptimizer.php b/src/Composer/DependencyResolver/PoolOptimizer.php index bfb10a589269..4aa6ffe324d8 100644 --- a/src/Composer/DependencyResolver/PoolOptimizer.php +++ b/src/Composer/DependencyResolver/PoolOptimizer.php @@ -418,6 +418,19 @@ private function optimizeImpossiblePackagesAway(Request $request, Pool $pool) } foreach ($request->getLockedPackages() as $package) { + // If this locked package is no longer required by root or anything in the pool, it may get uninstalled so do not apply its requirements + // In a case where a requirement WERE to appear in the pool by a package that would not be used, it would've been unlocked and so not filtered still + $ignoreUnusedPackage = false; + foreach ($package->getNames(false) as $packageName) { + if (!isset($this->requireConstraintsPerPackage[$packageName])) { + $ignoreUnusedPackage = true; + } + } + + if ($ignoreUnusedPackage) { + continue; + } + foreach ($package->getRequires() as $link) { $require = $link->getTarget(); if (!isset($packageIndex[$require])) { diff --git a/tests/Composer/Test/DependencyResolver/Fixtures/poolbuilder/filter-impossible-oackages-only-required.test b/tests/Composer/Test/DependencyResolver/Fixtures/poolbuilder/filter-impossible-oackages-only-required.test new file mode 100644 index 000000000000..2705f2d4e088 --- /dev/null +++ b/tests/Composer/Test/DependencyResolver/Fixtures/poolbuilder/filter-impossible-oackages-only-required.test @@ -0,0 +1,54 @@ +--TEST-- +When filtering packages from the pool that cannot meet the fixed/locked requirements, ensure that the requirements for a package that is not required anywhere is not used to filter, as it will be ultimately be removed. + +--REQUEST-- +{ + "require": { + "first/pkg": "*", + "second/pkg": "1.1.0" + }, + "locked": [ + {"name": "first/pkg", "version": "1.0.0", "require": {"second/pkg": "^1.0"}}, + {"name": "second/pkg", "version": "1.0.0", "require": {"third/pkg": "1.0.0"}}, + {"name": "third/pkg", "version": "1.0.0", "require": {"fourth/pkg": "1.0.0"}}, + {"name": "fourth/pkg", "version": "1.0.0"} + ], + "allowList": [ + "first/pkg" + ], + "allowTransitiveDeps": true +} + +--FIXED-- +[ +] + +--PACKAGE-REPOS-- +[ + [ + {"name": "first/pkg", "version": "1.0.0", "require": {"second/pkg": "*"}}, + {"name": "second/pkg", "version": "1.0.0", "require": {"third/pkg": "1.0.0"}}, + {"name": "second/pkg", "version": "1.1.0", "require": {"fourth/pkg": "2.0.0"}}, + {"name": "third/pkg", "version": "1.0.0", "require": {"fourth/pkg": "1.0.0"}}, + {"name": "fourth/pkg", "version": "1.0.0"}, + {"name": "fourth/pkg", "version": "2.0.0"} + ] +] + +--EXPECT-- +[ + "third/pkg-1.0.0.0 (locked)", + "first/pkg-1.0.0.0", + "second/pkg-1.1.0.0", + "fourth/pkg-1.0.0.0", + "fourth/pkg-2.0.0.0" +] + +--EXPECT-OPTIMIZED-- +[ + "third/pkg-1.0.0.0 (locked)", + "first/pkg-1.0.0.0", + "second/pkg-1.1.0.0", + "fourth/pkg-1.0.0.0", + "fourth/pkg-2.0.0.0" +]