From 613450e58a90538e92de4cf7be62a1fa11afd917 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Thu, 2 Apr 2020 00:08:53 +0200 Subject: [PATCH] PoolBuilder: properly clean up alias packages when unfixing packages Prevent aliases to be duplicated: no need to apply root aliases from composer.json on packages currently locked, they should have their aliases in the lock file, otherwise request an update. --- .../DependencyResolver/PoolBuilder.php | 22 +++-- ...te-allow-list-with-dependencies-alias.test | 84 ++++++++++++++++--- 2 files changed, 88 insertions(+), 18 deletions(-) diff --git a/src/Composer/DependencyResolver/PoolBuilder.php b/src/Composer/DependencyResolver/PoolBuilder.php index 69e6c8a4a..55f3b4c9e 100644 --- a/src/Composer/DependencyResolver/PoolBuilder.php +++ b/src/Composer/DependencyResolver/PoolBuilder.php @@ -220,7 +220,9 @@ class PoolBuilder } } - if (isset($this->rootAliases[$name][$package->getVersion()])) { + // if propogateUpdate is false we are loading a fixed package, root aliases do not apply as they are manually + // loaded as separate packages in this case + if ($propagateUpdate && isset($this->rootAliases[$name][$package->getVersion()])) { $alias = $this->rootAliases[$name][$package->getVersion()]; if ($package instanceof AliasPackage) { $basePackage = $package->getAliasOf(); @@ -345,11 +347,19 @@ class PoolBuilder private function unfixPackage(Request $request, $name) { // remove locked package by this name which was already initialized - foreach ($this->packages as $i => $loadedPackage) { - if ($loadedPackage->getName() === $name && $loadedPackage->getRepository() === $request->getLockedRepository()) { - $request->unfixPackage($loadedPackage); - unset($this->packages[$i]); - unset($this->aliasMap[spl_object_hash($loadedPackage)]); + foreach ($request->getLockedRepository()->getPackages() as $lockedPackage) { + if (!($lockedPackage instanceof AliasPackage) && $lockedPackage->getName() === $name) { + if (false !== $index = array_search($lockedPackage, $this->packages, true)) { + $request->unfixPackage($lockedPackage); + unset($this->packages[$index]); + if (isset($this->aliasMap[spl_object_hash($lockedPackage)])) { + foreach ($this->aliasMap[spl_object_hash($lockedPackage)] as $aliasIndex => $aliasPackage) { + $request->unfixPackage($aliasPackage); + unset($this->packages[$aliasIndex]); + } + unset($this->aliasMap[spl_object_hash($lockedPackage)]); + } + } } } diff --git a/tests/Composer/Test/Fixtures/installer/update-allow-list-with-dependencies-alias.test b/tests/Composer/Test/Fixtures/installer/update-allow-list-with-dependencies-alias.test index 24eb95538..b4685bb09 100644 --- a/tests/Composer/Test/Fixtures/installer/update-allow-list-with-dependencies-alias.test +++ b/tests/Composer/Test/Fixtures/installer/update-allow-list-with-dependencies-alias.test @@ -7,33 +7,52 @@ Require a new package in the composer.json and updating with its name as an argu "type": "package", "package": [ { "name": "current/pkg", "version": "1.0.0", "require": { "current/dep": "<1.2.0" } }, - { "name": "current/pkg", "version": "1.1.0", "require": { "current/dep": "^1.0" } }, + { "name": "current/dep", "version": "dev-master", "extra": {"branch-alias": {"dev-master": "1.0.x-dev"}}}, { "name": "current/dep", "version": "1.0.0" }, - { "name": "current/dep", "version": "1.1.0" }, + { "name": "current/dep", "version": "1.1.0", "require": {"current/dep2": "*"} }, { "name": "current/dep", "version": "1.2.0" }, - { "name": "new/pkg", "version": "1.0.0", "require": { "current/dep": "^1.1" } }, + { "name": "current/dep2", "version": "dev-master", "extra": {"branch-alias": {"dev-master": "1.0.x-dev"}}}, + { "name": "new/pkg", "version": "1.0.0", "require": { "current/dep": "^1.1", "current/dep2": "*"} }, { "name": "new/pkg", "version": "1.1.0", "require": { "current/dep": "^1.2" } } ] } ], "require": { - "current/pkg": "1.*", + "current/dep": "dev-master as 1.1.0", + "current/dep2": "dev-master as 1.1.0", + "current/pkg": "1.0.0 as 2.0.0", "new/pkg": "1.*" - } + }, + "minimum-stability": "dev" } --INSTALLED-- [ - { "name": "current/pkg", "version": "1.0.0", "require": { "current/dep": "<1.2.0" } }, - { "name": "current/dep", "version": "1.0.0" } + { "name": "current/dep", "version": "dev-master", "extra": {"branch-alias": {"dev-master": "1.0.x-dev"}}}, + { "name": "current/dep2", "version": "dev-master", "extra": {"branch-alias": {"dev-master": "1.0.x-dev"}}}, + { "name": "current/pkg", "version": "1.0.0", "require": { "current/dep": "<1.2.0" } } ] --LOCK-- { "packages": [ - { "name": "current/pkg", "version": "1.0.0", "require": { "current/dep": "<1.2.0" } }, - { "name": "current/dep", "version": "1.0.0" } + { "name": "current/dep", "version": "dev-master", "extra": {"branch-alias": {"dev-master": "1.0.x-dev"}}, "type": "library"}, + { "name": "current/dep2", "version": "dev-master", "extra": {"branch-alias": {"dev-master": "1.0.x-dev"}}, "type": "library"}, + { "name": "current/pkg", "version": "1.0.0", "require": { "current/dep": "<1.2.0" } } ], "packages-dev": [], - "aliases": [], + "aliases": [ + { + "alias": "1.1.0", + "alias_normalized": "1.1.0.0", + "version": "dev-master", + "package": "current/dep" + }, + { + "alias": "1.1.0", + "alias_normalized": "1.1.0.0", + "version": "dev-master", + "package": "current/dep2" + } + ], "minimum-stability": "dev", "stability-flags": [], "prefer-stable": false, @@ -42,7 +61,48 @@ Require a new package in the composer.json and updating with its name as an argu "platform-dev": [] } --RUN-- -update new/pkg --with-dependencies +update new/pkg --with-all-dependencies +--EXPECT-LOCK-- +{ + "packages": [ + { "name": "current/dep", "version": "dev-master", "extra": {"branch-alias": {"dev-master": "1.0.x-dev"}}, "type": "library"}, + { "name": "current/dep2", "version": "dev-master", "extra": {"branch-alias": {"dev-master": "1.0.x-dev"}}, "type": "library"}, + { "name": "current/pkg", "version": "1.0.0", "require": { "current/dep": "<1.2.0" }, "type": "library"}, + { "name": "new/pkg", "version": "1.0.0", "require": { "current/dep": "^1.1", "current/dep2": "*"}, "type": "library"} + ], + "packages-dev": [], + "aliases": [ + { + "alias": "1.1.0", + "alias_normalized": "1.1.0.0", + "version": "dev-master", + "package": "current/dep" + }, + { + "alias": "1.1.0", + "alias_normalized": "1.1.0.0", + "version": "dev-master", + "package": "current/dep2" + }, + { + "alias": "2.0.0", + "alias_normalized": "2.0.0.0", + "version": "1.0.0.0", + "package": "current/pkg" + } + ], + "minimum-stability": "dev", + "stability-flags": { + "current/dep": 20, + "current/dep2": 20 + }, + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [] +} --EXPECT-- -Upgrading current/dep (1.0.0 => 1.1.0) +Marking current/dep (1.1.0) as installed, alias of current/dep (dev-master) +Marking current/pkg (2.0.0) as installed, alias of current/pkg (1.0.0) +Marking current/dep2 (1.1.0) as installed, alias of current/dep2 (dev-master) Installing new/pkg (1.0.0)