From 6b97524b259c33f87760df2f242688a7d0c402c7 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Tue, 15 Mar 2022 22:11:19 +0100 Subject: [PATCH 1/4] Load plugins which modify install path early, fixes #10618 (#10621) --- doc/articles/plugins.md | 9 ++++++++ src/Composer/Plugin/PluginManager.php | 13 ++++++++++- src/Composer/Util/PackageSorter.php | 7 +++--- .../Composer/Test/Util/PackageSorterTest.php | 22 +++++++++++++++++-- 4 files changed, 45 insertions(+), 6 deletions(-) diff --git a/doc/articles/plugins.md b/doc/articles/plugins.md index fc017e688..b9d38a56e 100644 --- a/doc/articles/plugins.md +++ b/doc/articles/plugins.md @@ -323,6 +323,15 @@ hint to Composer that the plugin should be installed on its own before proceedin the rest of the package downloads. This slightly slows down the overall installation process however, so do not use it in plugins which do not absolutely require it. +### plugin-modifies-install-path + +Some special plugins modify the install path of packages. + +As of Composer 2.2.9, you can specify `{"extra": {"plugin-modifies-install-path": true}}` +in your composer.json to hint to Composer that the plugin should be activated as soon +as possible to prevent any bad side-effects from Composer assuming packages are installed +in another location than they actually are. + ## Plugin Autoloading Due to plugins being loaded by Composer at runtime, and to ensure that plugins which diff --git a/src/Composer/Plugin/PluginManager.php b/src/Composer/Plugin/PluginManager.php index fc89f9e52..4ffd59064 100644 --- a/src/Composer/Plugin/PluginManager.php +++ b/src/Composer/Plugin/PluginManager.php @@ -477,7 +477,18 @@ class PluginManager private function loadRepository(RepositoryInterface $repo, $isGlobalRepo) { $packages = $repo->getPackages(); - $sortedPackages = PackageSorter::sortPackages($packages); + + $weights = array(); + foreach ($packages as $package) { + if ($package->getType() === 'composer-plugin') { + $extra = $package->getExtra(); + if ($package->getName() === 'composer/installers' || (isset($extra['plugin-modifies-install-path']) && $extra['plugin-modifies-install-path'] === true)) { + $weights[$package->getName()] = -10000; + } + } + } + + $sortedPackages = PackageSorter::sortPackages($packages, $weights); foreach ($sortedPackages as $package) { if (!($package instanceof CompletePackage)) { continue; diff --git a/src/Composer/Util/PackageSorter.php b/src/Composer/Util/PackageSorter.php index 63e4a93cb..f9e48fdb5 100644 --- a/src/Composer/Util/PackageSorter.php +++ b/src/Composer/Util/PackageSorter.php @@ -23,9 +23,10 @@ class PackageSorter * Packages of equal weight are sorted alphabetically * * @param PackageInterface[] $packages + * @param array $weights Pre-set weights for some packages to give them more (negative number) or less (positive) weight offsets * @return PackageInterface[] sorted array */ - public static function sortPackages(array $packages) + public static function sortPackages(array $packages, array $weights = array()) { $usageList = array(); @@ -41,7 +42,7 @@ class PackageSorter } $computing = array(); $computed = array(); - $computeImportance = function ($name) use (&$computeImportance, &$computing, &$computed, $usageList) { + $computeImportance = function ($name) use (&$computeImportance, &$computing, &$computed, $usageList, $weights) { // reusing computed importance if (isset($computed[$name])) { return $computed[$name]; @@ -53,7 +54,7 @@ class PackageSorter } $computing[$name] = true; - $weight = 0; + $weight = isset($weights[$name]) ? $weights[$name] : 0; if (isset($usageList[$name])) { foreach ($usageList[$name] as $user) { diff --git a/tests/Composer/Test/Util/PackageSorterTest.php b/tests/Composer/Test/Util/PackageSorterTest.php index 5790ba04f..da8235766 100644 --- a/tests/Composer/Test/Util/PackageSorterTest.php +++ b/tests/Composer/Test/Util/PackageSorterTest.php @@ -127,6 +127,23 @@ class PackageSorterTest extends TestCase 'foo/baz', ), ), + 'pre-weighted packages bumped to top incl their deps' => array( + array( + $this->createPackage('foo/bar', array('foo/dep')), + $this->createPackage('foo/bar2', array('foo/dep2')), + $this->createPackage('foo/dep', array()), + $this->createPackage('foo/dep2', array()), + ), + array( + 'foo/dep', + 'foo/bar', + 'foo/dep2', + 'foo/bar2', + ), + array( + 'foo/bar' => -1000 + ) + ), ); } @@ -135,10 +152,11 @@ class PackageSorterTest extends TestCase * * @param Package[] $packages * @param string[] $expectedOrderedList + * @param array $weights */ - public function testSortingOrdersDependenciesHigherThanPackage($packages, $expectedOrderedList) + public function testSortingOrdersDependenciesHigherThanPackage($packages, $expectedOrderedList, $weights = array()) { - $sortedPackages = PackageSorter::sortPackages($packages); + $sortedPackages = PackageSorter::sortPackages($packages, $weights); $sortedPackageNames = array_map(function ($package) { return $package->getName(); }, $sortedPackages); From 173b558072b2f6446a92be5ce0d1156596afe297 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Tue, 15 Mar 2022 22:13:32 +0100 Subject: [PATCH 2/4] Update changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 46ad54018..868375d45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +### [2.2.9] 2022-03-15 + + * Fixed regression with plugins that modify install path of packages, [see docs](https://getcomposer.org/doc/articles/plugins.md#plugin-modifies-install-path) if you are authoring such a plugin (#10621) + ### [2.2.8] 2022-03-15 * Fixed `files` autoloading sort order to be fully deterministic (#10617) @@ -1402,6 +1406,7 @@ * Initial release +[2.2.9]: https://github.com/composer/composer/compare/2.2.8...2.2.9 [2.2.8]: https://github.com/composer/composer/compare/2.2.7...2.2.8 [2.2.7]: https://github.com/composer/composer/compare/2.2.6...2.2.7 [2.2.6]: https://github.com/composer/composer/compare/2.2.5...2.2.6 From 07eccf080ad63d55d95a7c9133506db7d9029264 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Tue, 15 Mar 2022 22:13:37 +0100 Subject: [PATCH 3/4] Release 2.2.9 --- src/Composer/Composer.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Composer/Composer.php b/src/Composer/Composer.php index 624e02507..59c10e837 100644 --- a/src/Composer/Composer.php +++ b/src/Composer/Composer.php @@ -52,10 +52,10 @@ class Composer * const RELEASE_DATE = '@release_date@'; * const SOURCE_VERSION = '1.8-dev+source'; */ - const VERSION = '@package_version@'; - const BRANCH_ALIAS_VERSION = '@package_branch_alias_version@'; - const RELEASE_DATE = '@release_date@'; - const SOURCE_VERSION = '2.2.999-dev+source'; + const VERSION = '2.2.9'; + const BRANCH_ALIAS_VERSION = ''; + const RELEASE_DATE = '2022-03-15 22:13:37'; + const SOURCE_VERSION = ''; /** * Version number of the internal composer-runtime-api package From 78bdd8127b91cfd5589955826d7ff9f6228f44c1 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Tue, 15 Mar 2022 22:13:38 +0100 Subject: [PATCH 4/4] Reverting release version changes --- src/Composer/Composer.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Composer/Composer.php b/src/Composer/Composer.php index 59c10e837..624e02507 100644 --- a/src/Composer/Composer.php +++ b/src/Composer/Composer.php @@ -52,10 +52,10 @@ class Composer * const RELEASE_DATE = '@release_date@'; * const SOURCE_VERSION = '1.8-dev+source'; */ - const VERSION = '2.2.9'; - const BRANCH_ALIAS_VERSION = ''; - const RELEASE_DATE = '2022-03-15 22:13:37'; - const SOURCE_VERSION = ''; + const VERSION = '@package_version@'; + const BRANCH_ALIAS_VERSION = '@package_branch_alias_version@'; + const RELEASE_DATE = '@release_date@'; + const SOURCE_VERSION = '2.2.999-dev+source'; /** * Version number of the internal composer-runtime-api package