diff --git a/README.md b/README.md index 41a10a5d..160565e5 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,7 @@ This package makes use of the following normalizers provided by [`localheinz/jso Additionally, it provides and makes use of the following normalizers: * [`Localheinz\Composer\Normalize\Normalizer\ConfigHashNormalizer`](#confighashnormalizer) +* [`Localheinz\Composer\Normalize\Normalizer\PackageHashNormalizer`](#packagehashnormalizer) ### `ConfigHashNormalizer` @@ -51,6 +52,24 @@ the `ConfigHashNormalizer` will sort the `config` section by key in ascending or :bulb: Find out more about the `config` section at https://getcomposer.org/doc/06-config.md. +### `PackageHashNormalizer` + +If `composer.json` contains any configuration in the + +* `conflict` +* `provide` +* `replaces` +* `require` +* `require-dev` +* `suggest` + +sections, the `PackageHashNormalizer` will sort the content of these sections. + +:bulb: This transfers the behaviour from using the `--sort-packages` or +`sort-packages` configuration flag to other sections. Find out more about +the `--sort-packages` flag and configuration at https://getcomposer.org/doc/06-config.md#sort-packages +and https://getcomposer.org/doc/03-cli.md#require. + ## Contributing Please have a look at [`CONTRIBUTING.md`](.github/CONTRIBUTING.md). @@ -62,3 +81,11 @@ Please have a look at [`CODE_OF_CONDUCT.md`](.github/CODE_OF_CONDUCT.md). ## License This package is licensed using the MIT License. + +## Credits + +The algorithm for sorting packages in the [`PackageHashNormalizer`](src/Normalizer/PackageHashNormalizer.php) has +been adopted from [`Composer\Json\JsonManipulator::sortPackages()`](https://github.com/composer/composer/blob/1.6.2/src/Composer/Json/JsonManipulator.php#L110-L146) +(originally licensed under MIT by [Nils Adermann](https://github.com/naderman) and [Jordi Boggiano](https://github.com/seldaek)), +which I initially contributed to `composer/composer` with [`composer/composer#3549`](https://github.com/composer/composer/pull/3549) +and [`composer/composer#3872`](https://github.com/composer/composer/pull/3872). diff --git a/src/NormalizePlugin.php b/src/NormalizePlugin.php index 09054e47..a3632783 100644 --- a/src/NormalizePlugin.php +++ b/src/NormalizePlugin.php @@ -48,7 +48,8 @@ public function getCommands(): array { return [ new Command\NormalizeCommand(new AutoFormatNormalizer(new ChainNormalizer( - new Normalizer\ConfigHashNormalizer() + new Normalizer\ConfigHashNormalizer(), + new Normalizer\PackageHashNormalizer() ))), ]; } diff --git a/src/Normalizer/PackageHashNormalizer.php b/src/Normalizer/PackageHashNormalizer.php new file mode 100644 index 00000000..2a603741 --- /dev/null +++ b/src/Normalizer/PackageHashNormalizer.php @@ -0,0 +1,102 @@ + $value) { + $decoded->{$name} = $this->sortPackages((array) $decoded->{$name}); + } + + return \json_encode($decoded); + } + + /** + * This code is adopted from composer/composer (originally licensed under MIT by Nils Adermann + * and Jordi Boggiano ). + * + * @see https://github.com/composer/composer/blob/1.6.2/src/Composer/Json/JsonManipulator.php#L110-L146 + * + * @param string[] $packages + * + * @return string[] + */ + private function sortPackages(array $packages): array + { + $prefix = function ($requirement) { + if (\preg_match(Repository\PlatformRepository::PLATFORM_PACKAGE_REGEX, $requirement)) { + return \preg_replace( + [ + '/^php/', + '/^hhvm/', + '/^ext/', + '/^lib/', + '/^\D/', + ], + [ + '0-$0', + '1-$0', + '2-$0', + '3-$0', + '4-$0', + ], + $requirement + ); + } + + return '5-' . $requirement; + }; + + \uksort($packages, function ($a, $b) use ($prefix) { + return \strnatcmp($prefix($a), $prefix($b)); + }); + + return $packages; + } +} diff --git a/test/Unit/Normalizer/PackageHashNormalizerTest.php b/test/Unit/Normalizer/PackageHashNormalizerTest.php new file mode 100644 index 00000000..3310f9e8 --- /dev/null +++ b/test/Unit/Normalizer/PackageHashNormalizerTest.php @@ -0,0 +1,99 @@ +assertSame($json, $normalizer->normalize($json)); + } + + /** + * @dataProvider providerProperty + * + * @param string $property + */ + public function testNormalizeSortsPackageHashIfPropertyExists(string $property) + { + $json = <<assertSame(\json_encode(\json_decode($normalized)), $normalizer->normalize($json)); + } + + public function providerProperty(): \Generator + { + $values = [ + 'conflict', + 'provide', + 'replaces', + 'require', + 'require-dev', + 'suggest', + ]; + + foreach ($values as $value) { + yield $value => [ + $value, + ]; + } + } +}