From 043b33ed382b6232f8451a85ff1ab415c5a4e5eb Mon Sep 17 00:00:00 2001 From: Dane Powell Date: Sat, 6 Apr 2019 08:44:23 -0700 Subject: [PATCH 1/6] Fixes #8065: Sort plugins deterministically before loading. --- src/Composer/Autoload/AutoloadGenerator.php | 3 ++- src/Composer/Plugin/PluginManager.php | 11 ++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index 7ea1a3444..2d4c481b1 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -28,6 +28,7 @@ use Composer\Script\ScriptEvents; */ class AutoloadGenerator { + /** * @var EventDispatcher */ @@ -959,7 +960,7 @@ INITIALIZER; * @param array $packageMap * @return array */ - protected function sortPackageMap(array $packageMap) + public function sortPackageMap(array $packageMap) { $packages = array(); $paths = array(); diff --git a/src/Composer/Plugin/PluginManager.php b/src/Composer/Plugin/PluginManager.php index e8f4b58c3..da9fb5c20 100644 --- a/src/Composer/Plugin/PluginManager.php +++ b/src/Composer/Plugin/PluginManager.php @@ -15,10 +15,10 @@ namespace Composer\Plugin; use Composer\Composer; use Composer\EventDispatcher\EventSubscriberInterface; use Composer\IO\IOInterface; +use Composer\Package\CompletePackage; use Composer\Package\Package; use Composer\Package\Version\VersionParser; use Composer\Repository\RepositoryInterface; -use Composer\Package\AliasPackage; use Composer\Package\PackageInterface; use Composer\Package\Link; use Composer\Semver\Constraint\Constraint; @@ -253,8 +253,13 @@ class PluginManager */ private function loadRepository(RepositoryInterface $repo) { - foreach ($repo->getPackages() as $package) { /** @var PackageInterface $package */ - if ($package instanceof AliasPackage) { + $packages = $repo->getPackages(); + $generator = $this->composer->getAutoloadGenerator(); + $packageMap = $generator->buildPackageMap($this->composer->getInstallationManager(), $this->composer->getPackage(), $packages); + $sortedPackageMap = array_reverse($generator->sortPackageMap($packageMap)); + foreach ($sortedPackageMap as $fullPackage) { + $package = $fullPackage[0]; /** @var PackageInterface $package */ + if (!($package instanceof CompletePackage)) { continue; } if ('composer-plugin' === $package->getType()) { From 3e6300b5e810aada05581769f25c07f30f1f5a75 Mon Sep 17 00:00:00 2001 From: Dane Powell Date: Sat, 6 Apr 2019 08:49:45 -0700 Subject: [PATCH 2/6] code style fix. --- src/Composer/Autoload/AutoloadGenerator.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index 2d4c481b1..272c6b920 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -28,7 +28,6 @@ use Composer\Script\ScriptEvents; */ class AutoloadGenerator { - /** * @var EventDispatcher */ From a908e22a91895fc63cfa173667ef395b3b6f5447 Mon Sep 17 00:00:00 2001 From: Dane Powell Date: Sat, 6 Apr 2019 08:53:32 -0700 Subject: [PATCH 3/6] Fixed code style issues. --- src/Composer/Plugin/PluginManager.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Composer/Plugin/PluginManager.php b/src/Composer/Plugin/PluginManager.php index da9fb5c20..cca4efe54 100644 --- a/src/Composer/Plugin/PluginManager.php +++ b/src/Composer/Plugin/PluginManager.php @@ -255,7 +255,8 @@ class PluginManager { $packages = $repo->getPackages(); $generator = $this->composer->getAutoloadGenerator(); - $packageMap = $generator->buildPackageMap($this->composer->getInstallationManager(), $this->composer->getPackage(), $packages); + $rootPackage = $this->composer->getPackage(); /** @var PackageInterface $rootPackage */ + $packageMap = $generator->buildPackageMap($this->composer->getInstallationManager(), $rootPackage, $packages); $sortedPackageMap = array_reverse($generator->sortPackageMap($packageMap)); foreach ($sortedPackageMap as $fullPackage) { $package = $fullPackage[0]; /** @var PackageInterface $package */ From 266a41e0464c8ccf23949e3794189dc4ccf3caba Mon Sep 17 00:00:00 2001 From: Dane Powell Date: Tue, 9 Apr 2019 10:55:33 -0700 Subject: [PATCH 4/6] Refactor sortPackageMap to depend on separate sortPackage function. --- src/Composer/Autoload/AutoloadGenerator.php | 54 +++++++++++++++------ src/Composer/Plugin/PluginManager.php | 7 +-- src/Composer/Util/PackageSorter.php | 10 ++++ 3 files changed, 51 insertions(+), 20 deletions(-) create mode 100644 src/Composer/Util/PackageSorter.php diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index 272c6b920..6fc602429 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -17,6 +17,7 @@ use Composer\EventDispatcher\EventDispatcher; use Composer\Installer\InstallationManager; use Composer\IO\IOInterface; use Composer\Package\AliasPackage; +use Composer\Package\Link; use Composer\Package\PackageInterface; use Composer\Repository\InstalledRepositoryInterface; use Composer\Util\Filesystem; @@ -956,27 +957,18 @@ INITIALIZER; * * Packages of equal weight retain the original order * - * @param array $packageMap + * @param array $packages * @return array */ - public function sortPackageMap(array $packageMap) - { - $packages = array(); - $paths = array(); + public function sortPackages(array $packages) { $usageList = array(); - foreach ($packageMap as $item) { - list($package, $path) = $item; - $name = $package->getName(); - $packages[$name] = $package; - $paths[$name] = $path; - - foreach (array_merge($package->getRequires(), $package->getDevRequires()) as $link) { + foreach ($packages as $package) { /** @var PackageInterface $package */ + foreach (array_merge($package->getRequires(), $package->getDevRequires()) as $link) { /** @var Link $link */ $target = $link->getTarget(); - $usageList[$target][] = $name; + $usageList[$target][] = $package->getName(); } } - $computing = array(); $computed = array(); $computeImportance = function ($name) use (&$computeImportance, &$computing, &$computed, $usageList) { @@ -1034,9 +1026,41 @@ INITIALIZER; $stable_sort($weightList); - $sortedPackageMap = array(); + $sortedPackages = array(); foreach (array_keys($weightList) as $name) { + $sortedPackages[] = $packages[$name]; + } + return $sortedPackages; + } + + /** + * Sorts packages by dependency weight + * + * Packages of equal weight retain the original order + * + * @param array $packageMap + * @return array + */ + public function sortPackageMap(array $packageMap) + { + $packages = array(); + $paths = array(); + + foreach ($packageMap as $item) { + list($package, $path) = $item; + $name = $package->getName(); + $packages[$name] = $package; + $paths[$name] = $path; + } + + $sortedPackages = $this->sortPackages($packages); + + + $sortedPackageMap = array(); + + foreach ($sortedPackages as $package) { + $name = $package->getName(); $sortedPackageMap[] = array($packages[$name], $paths[$name]); } diff --git a/src/Composer/Plugin/PluginManager.php b/src/Composer/Plugin/PluginManager.php index cca4efe54..3810992d0 100644 --- a/src/Composer/Plugin/PluginManager.php +++ b/src/Composer/Plugin/PluginManager.php @@ -255,11 +255,8 @@ class PluginManager { $packages = $repo->getPackages(); $generator = $this->composer->getAutoloadGenerator(); - $rootPackage = $this->composer->getPackage(); /** @var PackageInterface $rootPackage */ - $packageMap = $generator->buildPackageMap($this->composer->getInstallationManager(), $rootPackage, $packages); - $sortedPackageMap = array_reverse($generator->sortPackageMap($packageMap)); - foreach ($sortedPackageMap as $fullPackage) { - $package = $fullPackage[0]; /** @var PackageInterface $package */ + $sortedPackages = array_reverse($generator->sortPackages($packages)); + foreach ($sortedPackages as $package) { if (!($package instanceof CompletePackage)) { continue; } diff --git a/src/Composer/Util/PackageSorter.php b/src/Composer/Util/PackageSorter.php new file mode 100644 index 000000000..2899fc959 --- /dev/null +++ b/src/Composer/Util/PackageSorter.php @@ -0,0 +1,10 @@ + Date: Tue, 9 Apr 2019 10:58:36 -0700 Subject: [PATCH 5/6] Move sortPackages to static helper class. --- src/Composer/Autoload/AutoloadGenerator.php | 86 +-------------------- src/Composer/Plugin/PluginManager.php | 4 +- src/Composer/Util/PackageSorter.php | 82 ++++++++++++++++++++ 3 files changed, 86 insertions(+), 86 deletions(-) diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index 6fc602429..5637157e1 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -17,11 +17,11 @@ use Composer\EventDispatcher\EventDispatcher; use Composer\Installer\InstallationManager; use Composer\IO\IOInterface; use Composer\Package\AliasPackage; -use Composer\Package\Link; use Composer\Package\PackageInterface; use Composer\Repository\InstalledRepositoryInterface; use Composer\Util\Filesystem; use Composer\Script\ScriptEvents; +use Composer\Util\PackageSorter; /** * @author Igor Wiedler @@ -952,88 +952,6 @@ INITIALIZER; ); } - /** - * Sorts packages by dependency weight - * - * Packages of equal weight retain the original order - * - * @param array $packages - * @return array - */ - public function sortPackages(array $packages) { - $usageList = array(); - - foreach ($packages as $package) { /** @var PackageInterface $package */ - foreach (array_merge($package->getRequires(), $package->getDevRequires()) as $link) { /** @var Link $link */ - $target = $link->getTarget(); - $usageList[$target][] = $package->getName(); - } - } - $computing = array(); - $computed = array(); - $computeImportance = function ($name) use (&$computeImportance, &$computing, &$computed, $usageList) { - // reusing computed importance - if (isset($computed[$name])) { - return $computed[$name]; - } - - // canceling circular dependency - if (isset($computing[$name])) { - return 0; - } - - $computing[$name] = true; - $weight = 0; - - if (isset($usageList[$name])) { - foreach ($usageList[$name] as $user) { - $weight -= 1 - $computeImportance($user); - } - } - - unset($computing[$name]); - $computed[$name] = $weight; - - return $weight; - }; - - $weightList = array(); - - foreach ($packages as $name => $package) { - $weight = $computeImportance($name); - $weightList[$name] = $weight; - } - - $stable_sort = function (&$array) { - static $transform, $restore; - - $i = 0; - - if (!$transform) { - $transform = function (&$v, $k) use (&$i) { - $v = array($v, ++$i, $k, $v); - }; - - $restore = function (&$v, $k) { - $v = $v[3]; - }; - } - - array_walk($array, $transform); - asort($array); - array_walk($array, $restore); - }; - - $stable_sort($weightList); - - $sortedPackages = array(); - - foreach (array_keys($weightList) as $name) { - $sortedPackages[] = $packages[$name]; - } - return $sortedPackages; - } - /** * Sorts packages by dependency weight * @@ -1054,7 +972,7 @@ INITIALIZER; $paths[$name] = $path; } - $sortedPackages = $this->sortPackages($packages); + $sortedPackages = PackageSorter::sortPackages($packages); $sortedPackageMap = array(); diff --git a/src/Composer/Plugin/PluginManager.php b/src/Composer/Plugin/PluginManager.php index 3810992d0..bb9b66d83 100644 --- a/src/Composer/Plugin/PluginManager.php +++ b/src/Composer/Plugin/PluginManager.php @@ -24,6 +24,7 @@ use Composer\Package\Link; use Composer\Semver\Constraint\Constraint; use Composer\DependencyResolver\Pool; use Composer\Plugin\Capability\Capability; +use Composer\Util\PackageSorter; /** * Plugin manager @@ -254,8 +255,7 @@ class PluginManager private function loadRepository(RepositoryInterface $repo) { $packages = $repo->getPackages(); - $generator = $this->composer->getAutoloadGenerator(); - $sortedPackages = array_reverse($generator->sortPackages($packages)); + $sortedPackages = array_reverse(PackageSorter::sortPackages($packages)); foreach ($sortedPackages as $package) { if (!($package instanceof CompletePackage)) { continue; diff --git a/src/Composer/Util/PackageSorter.php b/src/Composer/Util/PackageSorter.php index 2899fc959..8d8c9a06c 100644 --- a/src/Composer/Util/PackageSorter.php +++ b/src/Composer/Util/PackageSorter.php @@ -3,8 +3,90 @@ namespace Composer\Util; +use Composer\Package\Link; +use Composer\Package\PackageInterface; class PackageSorter { + /** + * Sorts packages by dependency weight + * + * Packages of equal weight retain the original order + * + * @param array $packages + * @return array + */ + public static function sortPackages(array $packages) { + $usageList = array(); + foreach ($packages as $package) { /** @var PackageInterface $package */ + foreach (array_merge($package->getRequires(), $package->getDevRequires()) as $link) { /** @var Link $link */ + $target = $link->getTarget(); + $usageList[$target][] = $package->getName(); + } + } + $computing = array(); + $computed = array(); + $computeImportance = function ($name) use (&$computeImportance, &$computing, &$computed, $usageList) { + // reusing computed importance + if (isset($computed[$name])) { + return $computed[$name]; + } + + // canceling circular dependency + if (isset($computing[$name])) { + return 0; + } + + $computing[$name] = true; + $weight = 0; + + if (isset($usageList[$name])) { + foreach ($usageList[$name] as $user) { + $weight -= 1 - $computeImportance($user); + } + } + + unset($computing[$name]); + $computed[$name] = $weight; + + return $weight; + }; + + $weightList = array(); + + foreach ($packages as $name => $package) { + $weight = $computeImportance($name); + $weightList[$name] = $weight; + } + + $stable_sort = function (&$array) { + static $transform, $restore; + + $i = 0; + + if (!$transform) { + $transform = function (&$v, $k) use (&$i) { + $v = array($v, ++$i, $k, $v); + }; + + $restore = function (&$v) { + $v = $v[3]; + }; + } + + array_walk($array, $transform); + asort($array); + array_walk($array, $restore); + }; + + $stable_sort($weightList); + + $sortedPackages = array(); + + foreach (array_keys($weightList) as $name) { + $sortedPackages[] = $packages[$name]; + } + return $sortedPackages; + } } From 3501423eabe7348a6f0db9f547e7e211ff5a4210 Mon Sep 17 00:00:00 2001 From: Dane Powell Date: Tue, 9 Apr 2019 11:15:19 -0700 Subject: [PATCH 6/6] Undo previous change. --- src/Composer/Autoload/AutoloadGenerator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index 5637157e1..325fb2c87 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -960,7 +960,7 @@ INITIALIZER; * @param array $packageMap * @return array */ - public function sortPackageMap(array $packageMap) + protected function sortPackageMap(array $packageMap) { $packages = array(); $paths = array();