From 29ae6fae35f4116bbfe4c8b96ccc3f687eb07cd9 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 3 May 2023 16:49:12 +0200 Subject: [PATCH] Skip auto-installing when the root package's extra.discovery is enough (#239) --- .github/workflows/plugin.yml | 2 +- CHANGELOG.md | 3 ++- src/Composer/Plugin.php | 23 ++++++++++++++++++++--- tests/Composer/PluginTest.php | 8 ++++++-- tests/plugin/pinning/composer.json | 3 +++ tests/plugin/pinning/test.php | 16 +++++++++++++++- 6 files changed, 47 insertions(+), 8 deletions(-) diff --git a/.github/workflows/plugin.yml b/.github/workflows/plugin.yml index 1ad9e1f..18763c9 100644 --- a/.github/workflows/plugin.yml +++ b/.github/workflows/plugin.yml @@ -42,4 +42,4 @@ jobs: jq '.repositories[0].url="'$(pwd)'"' tests/plugin/pinning/composer.json > /tmp/plugin-pinning/composer.json cd /tmp/plugin-pinning composer update - [ 'Slim\Psr7\Factory\RequestFactory' == $(php test.php) ] + [ 'Slim\Psr7\Factory\RequestFactory-MyClient' == $(php test.php) ] diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f41839..abbab8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,10 @@ # Change Log -## 1.18.0 - 2023-XX-XX +## 1.18.0 - 2023-05-03 - [#235](https://github.com/php-http/discovery/pull/235) - Deprecate HttpClientDiscovery, use Psr18ClientDiscovery instead - [#238](https://github.com/php-http/discovery/pull/238) - Skip requiring php-http/message-factory when installing symfony/http-client 6.3+ +- [#239](https://github.com/php-http/discovery/pull/239) - Skip auto-installing when the root package's extra.discovery is enough ## 1.17.0 - 2023-04-26 diff --git a/src/Composer/Plugin.php b/src/Composer/Plugin.php index 06db0a2..bba2e2b 100644 --- a/src/Composer/Plugin.php +++ b/src/Composer/Plugin.php @@ -149,8 +149,18 @@ public function postUpdate(Event $event) $composer->getPackage()->getRequires(), $composer->getPackage()->getDevRequires(), ]; + $pinnedAbstractions = []; + $pinned = $composer->getPackage()->getExtra()['discovery'] ?? []; + foreach (self::INTERFACE_MAP as $abstraction => $interfaces) { + foreach (isset($pinned[$abstraction]) ? [] : $interfaces as $interface) { + if (!isset($pinned[$interface])) { + continue 2; + } + } + $pinnedAbstractions[$abstraction] = true; + } - $missingRequires = $this->getMissingRequires($repo, $requires, 'project' === $composer->getPackage()->getType()); + $missingRequires = $this->getMissingRequires($repo, $requires, 'project' === $composer->getPackage()->getType(), $pinnedAbstractions); $missingRequires = [ 'require' => array_fill_keys(array_merge([], ...array_values($missingRequires[0])), '*'), 'require-dev' => array_fill_keys(array_merge([], ...array_values($missingRequires[1])), '*'), @@ -229,7 +239,7 @@ public function postUpdate(Event $event) } } - public function getMissingRequires(InstalledRepositoryInterface $repo, array $requires, bool $isProject): array + public function getMissingRequires(InstalledRepositoryInterface $repo, array $requires, bool $isProject, array $pinnedAbstractions): array { $allPackages = []; $devPackages = method_exists($repo, 'getDevPackageNames') ? array_fill_keys($repo->getDevPackageNames(), true) : []; @@ -269,7 +279,14 @@ public function getMissingRequires(InstalledRepositoryInterface $repo, array $re $rules = array_intersect_key(self::PROVIDE_RULES, $rules); while ($rules) { - $abstractions[] = $abstraction = key($rules); + $abstraction = key($rules); + + if (isset($pinnedAbstractions[$abstraction])) { + unset($rules[$abstraction]); + continue; + } + + $abstractions[] = $abstraction; foreach (array_shift($rules) as $candidate => $deps) { [$candidate, $version] = explode(':', $candidate, 2) + [1 => null]; diff --git a/tests/Composer/PluginTest.php b/tests/Composer/PluginTest.php index 947d219..5c18925 100644 --- a/tests/Composer/PluginTest.php +++ b/tests/Composer/PluginTest.php @@ -17,11 +17,11 @@ class PluginTest extends TestCase /** * @dataProvider provideMissingRequires */ - public function testMissingRequires(array $expected, InstalledArrayRepository $repo, array $rootRequires, array $rootDevRequires) + public function testMissingRequires(array $expected, InstalledArrayRepository $repo, array $rootRequires, array $rootDevRequires, $pinnedAbstractions = []) { $plugin = new Plugin(); - $this->assertSame($expected, $plugin->getMissingRequires($repo, [$rootRequires, $rootDevRequires], true)); + $this->assertSame($expected, $plugin->getMissingRequires($repo, [$rootRequires, $rootDevRequires], true, $pinnedAbstractions)); } public static function provideMissingRequires() @@ -50,6 +50,10 @@ public static function provideMissingRequires() yield 'async-httplug' => [$expected, $repo, $rootRequires, []]; + unset($expected[0]['php-http/async-client-implementation']); + + yield 'pinned' => [$expected, $repo, $rootRequires, [], ['php-http/async-client-implementation' => true]]; + $repo = new InstalledArrayRepository([ 'php-http/discovery' => new Package('php-http/discovery', '1.0.0.0', '1.0'), 'nyholm/psr7' => new Package('nyholm/psr7', '1.0.0.0', '1.0'), diff --git a/tests/plugin/pinning/composer.json b/tests/plugin/pinning/composer.json index 4ce129b..dcf5e33 100644 --- a/tests/plugin/pinning/composer.json +++ b/tests/plugin/pinning/composer.json @@ -13,6 +13,8 @@ "require": { "nyholm/psr7": "*", "php-http/discovery": "99.99.x-dev", + "psr/http-client": "*", + "psr/http-client-implementation": "*", "slim/psr7": "*" }, "config": { @@ -22,6 +24,7 @@ }, "extra": { "discovery": { + "Psr\\Http\\Client\\ClientInterface": "MyClient", "Psr\\Http\\Message\\RequestFactoryInterface": "Slim\\Psr7\\Factory\\RequestFactory" } } diff --git a/tests/plugin/pinning/test.php b/tests/plugin/pinning/test.php index f91883a..f9fd9b3 100644 --- a/tests/plugin/pinning/test.php +++ b/tests/plugin/pinning/test.php @@ -1,7 +1,21 @@ createResponse(); + } +} + +echo get_class(Psr17FactoryDiscovery::findRequestFactory()); +echo '-', get_class(Psr18ClientDiscovery::find()); +echo "\n";