ergebnis/composer-normalize

Provides a composer plugin for normalizing composer.json.

Fund package maintenance!
localheinz

Installs: 1 919 240

Dependents: 468

Suggesters: 3

Security: 0

Stars: 606

Watchers: 10

Forks: 18

Open Issues: 6

Type:composer-plugin


README

Integrate Prune Release Renew Update

Code Coverage Type Coverage

Latest Stable Version Total Downloads

Provides a composer plugin for normalizing composer.json.

Hmm, kinda cool I guess

Why

When it comes to formatting composer.json, you have the following options:

  • you can stop caring
  • you can format it manually (and request changes when contributors format it differently)
  • you can use ergebnis/composer-normalize

ergebnis/composer-normalize normalizes composer.json, so you don't have to.

💡 If you want to find out more, take a look at the examples and read this blog post.

Installation

Composer

Run

$ composer require --dev ergebnis/composer-normalize

to install ergebnis/composer-normalize as a composer plugin.

Phar

Head over to http://github.com/ergebnis/composer-normalize/releases/latest and download the latest composer-normalize.phar.

Run

$ chmod +x composer-normalize.phar

to make the downloaded composer-normalize.phar executable.

Phive

Run

$ phive install ergebnis/composer-normalize

to install ergebnis/composer-normalize with PHIVE.

Usage

Composer

Run

$ composer normalize

to normalize composer.json in the working directory.

Phar

Run

$ ./composer-normalize.phar

to normalize composer.json in the working directory.

Phive

Run

$ ./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 normalizers 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 to configure these options in composer.json:

{
  "extra": {
    "composer-normalize": {
      "indent-size": 2,
      "indent-style": "space",
    }
  }
}

💡 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.

$ 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.

Normalizers

The ComposerJsonNormalizer composes normalizers provided by ergebnis/json-normalizer:

as well as the following normalizers provided by this package:

BinNormalizer

If composer.json contains an array of scripts in the bin section, the BinNormalizer will sort the elements of the bin section by value in ascending order.

💡 Find out more about the bin section at https://getcomposer.org/doc/04-schema.md#bin.

ConfigHashNormalizer

If composer.json contains any configuration in the

  • config
  • extra
  • scripts-descriptions

sections, the ConfigHashNormalizer will sort the content of these sections by key in ascending order.

💡 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
  • replace
  • require
  • require-dev
  • suggest

sections, the PackageHashNormalizer will sort the content of these sections.

💡 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.

VersionConstraintNormalizer

If composer.json contains version constraints in the

  • conflict
  • provide
  • replace
  • require
  • require-dev

sections, the VersionConstraintNormalizer will ensure that

  • all constraints are trimmed
  • and constraints are separated by a single space ( ) or a comma (,)
  • or constraints are separated by double-pipe with a single space before and after (||)
  • range constraints are separated by a single space ( )

💡 Find out more about version constraints at https://getcomposer.org/doc/articles/versions.md.

Examples

pestphp/pest

Running

$ composer normalize

against https://github.com/pestphp/pest/blob/v0.3.19/composer.json yields the following 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

$ composer normalize

against https://github.com/phpspec/phpspec/blob/7.0.1/composer.json yields the following 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

$ composer normalize

against https://github.com/phpspec/phpspec/blob/7.0.1/composer.json yields the following 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

Please have a look at CHANGELOG.md.

Contributing

Please have a look at CONTRIBUTING.md.

Code of Conduct

Please have a look at CODE_OF_CONDUCT.md.

License

This package is licensed using the MIT License.

Please have a look at LICENSE.md.

Credits

The algorithm for sorting packages in the PackageHashNormalizer has been adopted from Composer\Json\JsonManipulator::sortPackages() (originally licensed under MIT by Nils Adermann and Jordi Boggiano), which I initially contributed to composer/composer with composer/composer#3549 and composer/composer#3872.

Curious what I am building?

📬 Subscribe to my list, and I will occasionally send you an email to let you know what I am working on.