# composer-normalize [![Integrate](https://github.com/ergebnis/composer-normalize/actions/workflows/integrate.yaml/badge.svg?branch=main)](https://github.com/ergebnis/composer-normalize/actions/workflows/integrate.yaml) [![Merge](https://github.com/ergebnis/composer-normalize/actions/workflows/merge.yaml/badge.svg)](https://github.com/ergebnis/composer-normalize/actions/workflows/merge.yaml) [![Release](https://github.com/ergebnis/composer-normalize/actions/workflows/release.yaml/badge.svg)](https://github.com/ergebnis/composer-normalize/actions/workflows/release.yaml) [![Renew](https://github.com/ergebnis/composer-normalize/actions/workflows/renew.yaml/badge.svg)](https://github.com/ergebnis/composer-normalize/actions/workflows/renew.yaml) [![Code Coverage](https://codecov.io/gh/ergebnis/composer-normalize/branch/main/graph/badge.svg)](https://codecov.io/gh/ergebnis/composer-normalize) [![Latest Stable Version](https://poser.pugx.org/ergebnis/composer-normalize/v/stable)](https://packagist.org/packages/ergebnis/composer-normalize) [![Total Downloads](https://poser.pugx.org/ergebnis/composer-normalize/downloads)](https://packagist.org/packages/ergebnis/composer-normalize) [![Monthly Downloads](https://poser.pugx.org/ergebnis/composer-normalize/d/monthly)](https://packagist.org/packages/ergebnis/composer-normalize) This project provides a [`composer`](https://getcomposer.org) plugin for normalizing [`composer.json`](https://getcomposer.org/doc/04-schema.md). [![Hmm, kinda cool I guess](https://user-images.githubusercontent.com/605483/150120621-1eb65e19-b924-481c-a9e5-e762f1f3cfc9.png)](https://github.com/laravel/laravel/pull/4856#issuecomment-439705243) ## Why When it comes to formatting `composer.json`, you have the following options: - you can format it manually (and request changes when contributors format it differently) - you can stop caring - or you can use `ergebnis/composer-normalize` `ergebnis/composer-normalize` normalizes `composer.json`, so you don't have to. :bulb: If you want to find out more, take a look at the [examples](#examples) and read this [blog post](https://localheinz.com/blog/2018/01/15/normalizing-composer.json/). ## Installation ### Composer Run ```sh composer require --dev ergebnis/composer-normalize ``` to install `ergebnis/composer-normalize` as a composer plugin. Run ```shell composer config allow-plugins.ergebnis/composer-normalize true ``` to allow `ergebnis/composer-normalize` to run as a composer plugin. :bulb: The `allow-plugins` has been added to `composer/composer` to add an extra layer of security. For reference, see - https://github.com/composer/composer/pull/10314 - https://getcomposer.org/doc/06-config.md#allow-plugins ### Phar Head over to http://github.com/ergebnis/composer-normalize/releases/latest and download the latest `composer-normalize.phar`. Run ```sh chmod +x composer-normalize.phar ``` to make the downloaded `composer-normalize.phar` executable. ### Phive Run ```sh phive install ergebnis/composer-normalize ``` to install `ergebnis/composer-normalize` with [PHIVE](https://phar.io). ## Usage ### Composer Run ```sh composer normalize ``` to normalize `composer.json` in the working directory. ### Phar Run ```sh ./composer-normalize.phar ``` to normalize `composer.json` in the working directory. ### Phive Run ```sh ./tools/composer-normalize ``` to normalize `composer.json` in the working directory. ### Details The `NormalizeCommand` provided by the `NormalizePlugin` within this package will - determine whether a `composer.json` exists - determine whether a `composer.lock` exists, and if so, whether it is up to date (unless the `--no-check-lock` option is used) - use [`Ergebnis\Json\Normalizer\Vendor\Composer\ComposerJsonNormalizer`](https://github.com/ergebnis/json-normalizer#vendorcomposercomposerjsonnormalizer) to normalize the content of `composer.json` - format the normalized content (either as sniffed, or as specified using the `--indent-size` and `--indent-style` options) - write the normalized and formatted content of `composer.json` back to the file - update the hash in `composer.lock` if it exists and if an update is necessary ### Arguments - `file`: Path to `composer.json` file (optional, defaults to `composer.json` in working directory) ### Options - `--diff`: Show the results of normalizing - `--dry-run`: Show the results of normalizing, but do not modify any files - `--indent-size`: Indent size (an integer greater than 0); should be used with the `--indent-style` option - `--indent-style`: Indent style (one of "space", "tab"); should be used with the `--indent-size` option - `--no-check-lock`: Do not check if lock file is up to date - `--no-update-lock`: Do not update lock file if it exists As an alternative to specifying the `--indent-size` and `--indent-style` options, you can also use composer [extra](https://getcomposer.org/doc/04-schema.md#extra) to configure these options in `composer.json`: ```json { "extra": { "composer-normalize": { "indent-size": 2, "indent-style": "space" } } } ``` :bulb: The configuration provided in composer extra always overrides the configuration provided via command line options. ### Continuous Integration If you want to run this in continuous integration services, use the `--dry-run` option. ```sh composer normalize --dry-run ``` In case `composer.json` is not normalized (or `composer.lock` is not up-to-date), the command will fail with an exit code of `1` and show a diff. ## Examples ### `pestphp/pest` Running ```sh composer normalize ``` against https://github.com/pestphp/pest/blob/v0.3.19/composer.json yields the following diff: ```diff diff --git a/composer.json b/composer.json index 1cfbf1e..204f20f 100644 --- a/composer.json +++ b/composer.json @@ -25,6 +25,32 @@ "pestphp/pest-plugin-init": "^0.3", "phpunit/phpunit": ">= 9.3.7 <= 9.5.0" }, + "require-dev": { + "illuminate/console": "^7.16.1", + "illuminate/support": "^7.16.1", + "laravel/dusk": "^6.9.1", + "mockery/mockery": "^1.4.1", + "pestphp/pest-dev-tools": "dev-master" + }, + "config": { + "preferred-install": "dist", + "sort-packages": true + }, + "extra": { + "branch-alias": { + "dev-master": "0.3.x-dev" + }, + "laravel": { + "providers": [ + "Pest\\Laravel\\PestServiceProvider" + ] + }, + "pest": { + "plugins": [ + "Pest\\Plugins\\Version" + ] + } + }, "autoload": { "psr-4": { "Pest\\": "src/" @@ -42,49 +68,23 @@ "tests/Autoload.php" ] }, - "require-dev": { - "illuminate/console": "^7.16.1", - "illuminate/support": "^7.16.1", - "laravel/dusk": "^6.9.1", - "mockery/mockery": "^1.4.1", - "pestphp/pest-dev-tools": "dev-master" - }, "minimum-stability": "dev", "prefer-stable": true, - "config": { - "sort-packages": true, - "preferred-install": "dist" - }, "bin": [ "bin/pest" ], "scripts": { "lint": "php-cs-fixer fix -v", - "test:lint": "php-cs-fixer fix -v --dry-run", - "test:types": "phpstan analyse --ansi --memory-limit=0", - "test:unit": "php bin/pest --colors=always --exclude-group=integration", - "test:integration": "php bin/pest --colors=always --group=integration", - "update:snapshots": "REBUILD_SNAPSHOTS=true php bin/pest --colors=always", "test": [ "@test:lint", "@test:types", "@test:unit", "@test:integration" - ] - }, - "extra": { - "branch-alias": { - "dev-master": "0.3.x-dev" - }, - "pest": { - "plugins": [ - "Pest\\Plugins\\Version" - ] - }, - "laravel": { - "providers": [ - "Pest\\Laravel\\PestServiceProvider" - ] - } + ], + "test:integration": "php bin/pest --colors=always --group=integration", + "test:lint": "php-cs-fixer fix -v --dry-run", + "test:types": "phpstan analyse --ansi --memory-limit=0", + "test:unit": "php bin/pest --colors=always --exclude-group=integration", + "update:snapshots": "REBUILD_SNAPSHOTS=true php bin/pest --colors=always" } } ``` ### `phpspec/phpspec` Running ```sh composer normalize ``` against https://github.com/phpspec/phpspec/blob/7.0.1/composer.json yields the following diff: ```diff diff --git a/composer.json b/composer.json index 90150a37..276a2ecd 100644 --- a/composer.json +++ b/composer.json @@ -1,72 +1,73 @@ { - "name": "phpspec/phpspec", - "description": "Specification-oriented BDD framework for PHP 7.1+", - "keywords": ["BDD", "SpecBDD", "TDD", "spec", "specification", "tests", "testing"], - "homepage": "http://phpspec.net/", - "type": "library", - "license": "MIT", - "authors": [ + "name": "phpspec/phpspec", + "type": "library", + "description": "Specification-oriented BDD framework for PHP 7.1+", + "keywords": [ + "BDD", + "SpecBDD", + "TDD", + "spec", + "specification", + "tests", + "testing" + ], + "homepage": "http://phpspec.net/", + "license": "MIT", + "authors": [ { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" }, { - "name": "Marcello Duarte", - "homepage": "http://marcelloduarte.net/" + "name": "Marcello Duarte", + "homepage": "http://marcelloduarte.net/" }, { - "name": "Ciaran McNulty", - "homepage": "https://ciaranmcnulty.com/" + "name": "Ciaran McNulty", + "homepage": "https://ciaranmcnulty.com/" } ], - "require": { - "php": "^7.3 || 8.0.*", - "phpspec/prophecy": "^1.9", - "phpspec/php-diff": "^1.0.0", - "sebastian/exporter": "^3.0 || ^4.0", - "symfony/console": "^3.4 || ^4.4 || ^5.0", + "php": "^7.3 || 8.0.*", + "ext-tokenizer": "*", + "doctrine/instantiator": "^1.0.5", + "phpspec/php-diff": "^1.0.0", + "phpspec/prophecy": "^1.9", + "sebastian/exporter": "^3.0 || ^4.0", + "symfony/console": "^3.4 || ^4.4 || ^5.0", "symfony/event-dispatcher": "^3.4 || ^4.4 || ^5.0", - "symfony/process": "^3.4 || ^4.4 || ^5.0", - "symfony/finder": "^3.4 || ^4.4 || ^5.0", - "symfony/yaml": "^3.4 || ^4.4 || ^5.0", - "doctrine/instantiator": "^1.0.5", - "ext-tokenizer": "*" + "symfony/finder": "^3.4 || ^4.4 || ^5.0", + "symfony/process": "^3.4 || ^4.4 || ^5.0", + "symfony/yaml": "^3.4 || ^4.4 || ^5.0" + }, + "conflict": { + "sebastian/comparator": "<1.2.4" }, - "require-dev": { - "behat/behat": "^3.3", - "symfony/filesystem": "^3.4 || ^4.0 || ^5.0", - "phpunit/phpunit": "^8.0 || ^9.0" + "behat/behat": "^3.3", + "phpunit/phpunit": "^8.0 || ^9.0", + "symfony/filesystem": "^3.4 || ^4.0 || ^5.0" }, - "suggest": { "phpspec/nyan-formatters": "Adds Nyan formatters" }, - - "conflict": { - "sebastian/comparator" : "<1.2.4" + "extra": { + "branch-alias": { + "dev-main": "7.0.x-dev" + } }, - "autoload": { "psr-0": { "PhpSpec": "src/" } }, - "autoload-dev": { "psr-0": { "spec\\PhpSpec": "." } }, - - "bin": ["bin/phpspec"], - - "extra": { - "branch-alias": { - "dev-main": "7.0.x-dev" - } - } - + "bin": [ + "bin/phpspec" + ] } ``` ### `phpunit/phpunit` Running ```sh composer normalize ``` against https://github.com/sebastianbergmann/phpunit/blob/9.5.0/composer.json yields the following diff: ```diff diff --git a/composer.json b/composer.json index fd6461fc3..23c3a3596 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "phpunit/phpunit", - "description": "The PHP Unit Testing framework.", "type": "library", + "description": "The PHP Unit Testing framework.", "keywords": [ "phpunit", "xunit", @@ -16,10 +16,6 @@ "role": "lead" } ], - "support": { - "issues": "https://github.com/sebastianbergmann/phpunit/issues" - }, - "prefer-stable": true, "require": { "php": ">=7.3", "ext-dom": "*", @@ -54,20 +50,22 @@ "ext-PDO": "*", "phpspec/prophecy-phpunit": "^2.0.1" }, + "suggest": { + "ext-soap": "*", + "ext-xdebug": "*" + }, "config": { + "optimize-autoloader": true, "platform": { "php": "7.3.0" }, - "optimize-autoloader": true, "sort-packages": true }, - "suggest": { - "ext-soap": "*", - "ext-xdebug": "*" + "extra": { + "branch-alias": { + "dev-master": "9.5-dev" + } }, - "bin": [ - "phpunit" - ], "autoload": { "classmap": [ "src/" @@ -86,9 +84,11 @@ "tests/_files/NamespaceCoveredFunction.php" ] }, - "extra": { - "branch-alias": { - "dev-master": "9.5-dev" - } + "prefer-stable": true, + "bin": [ + "phpunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues" } } ``` ## Changelog The maintainers of this project record notable changes to this project in a [changelog](CHANGELOG.md). ## Contributing The maintainers of this project suggest following the [contribution guide](.github/CONTRIBUTING.md). ## Code of Conduct The maintainers of this project ask contributors to follow the [code of conduct](https://github.com/ergebnis/.github/blob/main/CODE_OF_CONDUCT.md). ## General Support Policy The maintainers of this project provide limited support. ## PHP Version Support Policy This project currently supports the following PHP versions: - [PHP 7.4](https://www.php.net/releases/#7.4.0) (has reached its end of life on November 28, 2022) - [PHP 8.0](https://www.php.net/releases/#8.0.0) (has reached its end of life on November 26, 2023) - [PHP 8.1](https://www.php.net/releases/#8.1.0) (has reached its end of life on December 31, 2025) - [PHP 8.2](https://www.php.net/releases/#8.2.0) - [PHP 8.3](https://www.php.net/releases/#8.3.0) - [PHP 8.4](https://www.php.net/releases/#8.4.0) - [PHP 8.5](https://www.php.net/releases/#8.5.0) The maintainers of this project add support for a PHP version following its initial release and _may_ drop support for a PHP version when it has reached its [end of life](https://www.php.net/supported-versions.php). ## Security Policy This project has a [security policy](.github/SECURITY.md). ## License This project uses the [MIT license](LICENSE.md). ## Social Follow [@localheinz](https://x.com/intent/follow?screen_name=localheinz) and [@ergebnis](https://x.com/intent/follow?screen_name=ergebnis) on X.