From 30e0a1f30086e2d11d1f7bc2a58f333d0875ec3f Mon Sep 17 00:00:00 2001 From: Enjoys Date: Fri, 20 May 2022 18:56:27 +0300 Subject: [PATCH 1/4] Allow merging deep scripts with setting merge-scripts-deep --- src/ExtraPackage.php | 21 ++++++++++--- src/PluginState.php | 20 ++++++++++++ tests/phpunit/MergePluginTest.php | 31 +++++++++++++++++++ .../testMergeScriptsDeep/composer.json | 15 +++++++++ .../testMergeScriptsDeep/composer.local.json | 13 ++++++++ 5 files changed, 96 insertions(+), 4 deletions(-) create mode 100644 tests/phpunit/fixtures/testMergeScriptsDeep/composer.json create mode 100644 tests/phpunit/fixtures/testMergeScriptsDeep/composer.local.json diff --git a/src/ExtraPackage.php b/src/ExtraPackage.php index 4a81b79..f4ee2b3 100644 --- a/src/ExtraPackage.php +++ b/src/ExtraPackage.php @@ -538,15 +538,28 @@ public function mergeScripts(RootPackageInterface $root, PluginState $state) $rootScripts = $root->getScripts(); $unwrapped = self::unwrapIfNeeded($root, 'setScripts'); - if ($state->replaceDuplicateLinks()) { + if ($state->shouldMergeScriptsDeep()) { + if ($state->replaceDuplicateLinks()) { + $unwrapped->setScripts( + self::mergeExtraArray($state->shouldMergeScripts(), $rootScripts, $scripts) + ); + return; + } $unwrapped->setScripts( - array_merge($rootScripts, $scripts) + self::mergeExtraArray($state->shouldMergeScripts(), $scripts, $rootScripts) ); - } else { + return; + } + + if ($state->replaceDuplicateLinks()) { $unwrapped->setScripts( - array_merge($scripts, $rootScripts) + array_merge($rootScripts, $scripts) ); + return; } + $unwrapped->setScripts( + array_merge($scripts, $rootScripts) + ); } /** diff --git a/src/PluginState.php b/src/PluginState.php index 2a0178f..a8c325e 100644 --- a/src/PluginState.php +++ b/src/PluginState.php @@ -105,6 +105,12 @@ class PluginState */ protected $mergeScripts = false; + /** + * @var bool $mergeScriptsDeep + */ + protected $mergeScriptsDeep = false; + + /** * @var bool $firstInstall */ @@ -161,6 +167,7 @@ public function loadSettings() 'merge-extra' => false, 'merge-extra-deep' => false, 'merge-scripts' => false, + 'merge-scripts-deep' => false, ], $extra['merge-plugin'] ?? [] ); @@ -176,6 +183,7 @@ public function loadSettings() $this->mergeExtra = (bool)$config['merge-extra']; $this->mergeExtraDeep = (bool)$config['merge-extra-deep']; $this->mergeScripts = (bool)$config['merge-scripts']; + $this->mergeScriptsDeep = (bool)$config['merge-scripts-deep']; } /** @@ -397,5 +405,17 @@ public function shouldMergeScripts() { return $this->mergeScripts; } + + /** + * Should the scripts section be deep merged? + * + * By default, the scripts section is not merged. + * + * @return bool + */ + public function shouldMergeScriptsDeep() + { + return $this->mergeScriptsDeep; + } } // vim:sw=4:ts=4:sts=4:et: diff --git a/tests/phpunit/MergePluginTest.php b/tests/phpunit/MergePluginTest.php index 3c7d420..ac0c403 100644 --- a/tests/phpunit/MergePluginTest.php +++ b/tests/phpunit/MergePluginTest.php @@ -1149,6 +1149,37 @@ function ($args) use ($that) { $this->triggerPlugin($root->reveal(), $dir); } + public function testMergeScriptsDeep() + { + $that = $this; + $dir = $this->fixtureDir(__FUNCTION__); + + $root = $this->rootFromJson("{$dir}/composer.json"); + + $root->setScripts(Argument::type('array'))->will( + function ($args) use ($that) { + $scripts = $args[0]; + $that->assertCount(3, $scripts); + $that->assertArrayHasKey('example-script2', $scripts); + $that->assertArrayHasKey('example-script3', $scripts); + $that->assertEquals("echo 'goodbye world'", $scripts['example-script2']); + $that->assertCount(3, $scripts['example-script3']); + $that->assertEquals( + ["echo 'hola world'", "echo 'hola again world'", "echo 'adios world'"], + $scripts['example-script3'] + ); + } + )->shouldBeCalled(); + + $root->getRepositories()->shouldNotBeCalled(); + $root->getConflicts()->shouldNotBeCalled(); + $root->getReplaces()->shouldNotBeCalled(); + $root->getProvides()->shouldNotBeCalled(); + $root->getSuggests()->shouldNotBeCalled(); + + $this->triggerPlugin($root->reveal(), $dir); + } + /** * @dataProvider provideOnPostPackageInstall * @param string $package Package installed diff --git a/tests/phpunit/fixtures/testMergeScriptsDeep/composer.json b/tests/phpunit/fixtures/testMergeScriptsDeep/composer.json new file mode 100644 index 0000000..077e499 --- /dev/null +++ b/tests/phpunit/fixtures/testMergeScriptsDeep/composer.json @@ -0,0 +1,15 @@ +{ + "extra": { + "merge-plugin": { + "merge-scripts": true, + "merge-scripts-deep": true, + "include": "composer.local.json" + } + }, + "scripts": { + "example-script2": "echo 'goodbye world'", + "example-script3": [ + "echo 'adios world'" + ] + } +} \ No newline at end of file diff --git a/tests/phpunit/fixtures/testMergeScriptsDeep/composer.local.json b/tests/phpunit/fixtures/testMergeScriptsDeep/composer.local.json new file mode 100644 index 0000000..13d9cbc --- /dev/null +++ b/tests/phpunit/fixtures/testMergeScriptsDeep/composer.local.json @@ -0,0 +1,13 @@ +{ + "scripts": { + "example-script": [ + "echo 'hello world'", + "echo 'hello again world'" + ], + "example-script2": "echo 'hello world'", + "example-script3": [ + "echo 'hola world'", + "echo 'hola again world'" + ] + } +} \ No newline at end of file From b49ea6838318ec1faf3009bd2058c64802d42c5a Mon Sep 17 00:00:00 2001 From: enjoys Date: Fri, 20 May 2022 23:14:28 +0300 Subject: [PATCH 2/4] use array_merge_recursive --- src/ExtraPackage.php | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/ExtraPackage.php b/src/ExtraPackage.php index f4ee2b3..8932075 100644 --- a/src/ExtraPackage.php +++ b/src/ExtraPackage.php @@ -539,15 +539,7 @@ public function mergeScripts(RootPackageInterface $root, PluginState $state) $unwrapped = self::unwrapIfNeeded($root, 'setScripts'); if ($state->shouldMergeScriptsDeep()) { - if ($state->replaceDuplicateLinks()) { - $unwrapped->setScripts( - self::mergeExtraArray($state->shouldMergeScripts(), $rootScripts, $scripts) - ); - return; - } - $unwrapped->setScripts( - self::mergeExtraArray($state->shouldMergeScripts(), $scripts, $rootScripts) - ); + $unwrapped->setScripts(array_merge_recursive($rootScripts, $scripts)); return; } From 5a2d7950c794518b64b01e4ed8627b4ae9748e51 Mon Sep 17 00:00:00 2001 From: enjoys Date: Fri, 20 May 2022 23:14:44 +0300 Subject: [PATCH 3/4] updated tests --- tests/phpunit/MergePluginTest.php | 18 +++++++++++------- .../testMergeScriptsDeep/composer.json | 13 ++++++++----- .../testMergeScriptsDeep/composer.local.json | 15 ++++++++------- 3 files changed, 27 insertions(+), 19 deletions(-) diff --git a/tests/phpunit/MergePluginTest.php b/tests/phpunit/MergePluginTest.php index ac0c403..222e1e4 100644 --- a/tests/phpunit/MergePluginTest.php +++ b/tests/phpunit/MergePluginTest.php @@ -1156,18 +1156,22 @@ public function testMergeScriptsDeep() $root = $this->rootFromJson("{$dir}/composer.json"); + $root->setScripts(Argument::type('array'))->will( function ($args) use ($that) { $scripts = $args[0]; - $that->assertCount(3, $scripts); - $that->assertArrayHasKey('example-script2', $scripts); - $that->assertArrayHasKey('example-script3', $scripts); - $that->assertEquals("echo 'goodbye world'", $scripts['example-script2']); - $that->assertCount(3, $scripts['example-script3']); + var_dump($scripts); + $that->assertCount(4, $scripts); + $that->assertArrayHasKey('script2', $scripts); + $that->assertArrayHasKey('script3', $scripts); + $that->assertEquals(["echo 'script2-root'", "echo 'script2-1'"], $scripts['script2']); + $that->assertCount(3, $scripts['script3']); $that->assertEquals( - ["echo 'hola world'", "echo 'hola again world'", "echo 'adios world'"], - $scripts['example-script3'] + ["echo 'script3-root'", "echo 'script3-1'", "echo 'script3-2'"], + $scripts['script3'] ); + $that->assertCount(2, $scripts['script4']); + $that->assertEquals(["echo 'script4'", "echo 'script4'"], $scripts['script4']); } )->shouldBeCalled(); diff --git a/tests/phpunit/fixtures/testMergeScriptsDeep/composer.json b/tests/phpunit/fixtures/testMergeScriptsDeep/composer.json index 077e499..ef73d7a 100644 --- a/tests/phpunit/fixtures/testMergeScriptsDeep/composer.json +++ b/tests/phpunit/fixtures/testMergeScriptsDeep/composer.json @@ -3,13 +3,16 @@ "merge-plugin": { "merge-scripts": true, "merge-scripts-deep": true, - "include": "composer.local.json" + "include": [ + "composer.local.json" + ] } }, "scripts": { - "example-script2": "echo 'goodbye world'", - "example-script3": [ - "echo 'adios world'" - ] + "script2": "echo 'script2-root'", + "script3": [ + "echo 'script3-root'" + ], + "script4": "echo 'script4'" } } \ No newline at end of file diff --git a/tests/phpunit/fixtures/testMergeScriptsDeep/composer.local.json b/tests/phpunit/fixtures/testMergeScriptsDeep/composer.local.json index 13d9cbc..9c75f8b 100644 --- a/tests/phpunit/fixtures/testMergeScriptsDeep/composer.local.json +++ b/tests/phpunit/fixtures/testMergeScriptsDeep/composer.local.json @@ -1,13 +1,14 @@ { "scripts": { - "example-script": [ - "echo 'hello world'", - "echo 'hello again world'" + + "script1": "echo 'script1-1'", + "script2": "echo 'script2-1'", + "script3": [ + "echo 'script3-1'", + "echo 'script3-2'" ], - "example-script2": "echo 'hello world'", - "example-script3": [ - "echo 'hola world'", - "echo 'hola again world'" + "script4": [ + "echo 'script4'" ] } } \ No newline at end of file From 16d2eabeecb9d04f7addf0b380d497df87a3c057 Mon Sep 17 00:00:00 2001 From: enjoys Date: Fri, 20 May 2022 21:10:58 +0300 Subject: [PATCH 4/4] updated README.md --- README.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 12fee59..655aecb 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,8 @@ Usage "merge-dev": true, "merge-extra": false, "merge-extra-deep": false, - "merge-scripts": false + "merge-scripts": false, + "merge-scripts-deep": false } } } @@ -190,6 +191,14 @@ the master config wins over the version found in any imported config). If and the last key found will win (e.g. the key in the master config is replaced by the key in the imported config). +if `"merge-scripts-deep": true` (required `"merge-scripts": true`), the scripts will be merged, not replaced, with +the first option found, or the last one, depending on the settings, as +with only `"merge-scripts": true`. +For example, _root: script => 1, imported: script => 2, the output will be script => [1, 2]_, +but with the same values, at the moment, they will be repeated +_root: script => 1, imported: script => 1, output: script => [1, 1]_ + + Note: [custom commands][] added by merged configuration will work when invoked as `composer run-script my-cool-command` but will not be available using the normal `composer my-cool-command` shortcut.