├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── composer.json ├── resource └── schema.json └── src ├── Command └── NormalizeCommand.php ├── Exception ├── Exception.php └── ShouldNotHappen.php ├── NormalizePlugin.php └── Version.php /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## Unreleased 8 | 9 | For a full diff see [`2.47.0...main`][2.47.0...main]. 10 | 11 | ## [`2.47.0`][2.47.0] 12 | 13 | For a full diff see [`2.46.0...2.47.0`][2.46.0...2.47.0]. 14 | 15 | ### Changed 16 | 17 | - Updated `schema.json` ([#1441]), by [@ergebnis-bot] 18 | 19 | ## [`2.46.0`][2.46.0] 20 | 21 | For a full diff see [`2.45.0...2.46.0`][2.45.0...2.46.0]. 22 | 23 | ### Changed 24 | 25 | - Updated `schema.json` ([#1419]), by [@ergebnis-bot] 26 | - Updated `ergerbnis/json-normalizer` ([#1440]), by [@localheinz] 27 | 28 | ## [`2.45.0`][2.45.0] 29 | 30 | For a full diff see [`2.44.0...2.45.0`][2.44.0...2.45.0]. 31 | 32 | ### Added 33 | 34 | - Added support for PHP 8.4 ([#1377]), by [@ruudk] 35 | 36 | ### Changed 37 | 38 | - Updated `schema.json` ([#1405]), by [@ergebnis-bot] 39 | - Allowed installation of `justinrainbow/json-schema:^6.0.0` ([#1410]), by [@tacman] 40 | - Updated `composer/composer` ([#1416]), by [@localheinz] 41 | 42 | ## [`2.44.0`][2.44.0] 43 | 44 | For a full diff see [`2.43.0...2.44.0`][2.43.0...2.44.0]. 45 | 46 | ### Changed 47 | 48 | - Updated `schema.json` ([#1363]), by [@ergebnis-bot] 49 | - Allowed installation on PHP 8.4 ([#1381]), by [@localheinz] 50 | 51 | ## [`2.43.0`][2.43.0] 52 | 53 | For a full diff see [`2.42.0...2.43.0`][2.42.0...2.43.0]. 54 | 55 | ### Changed 56 | 57 | - Updated `schema.json` ([#1312]), by [@ergebnis-bot] 58 | 59 | ### Fixed 60 | 61 | - Updated `composer/composer` ([#1349]), by [@localheinz] 62 | 63 | ## [`2.42.0`][2.42.0] 64 | 65 | For a full diff see [`2.41.1...2.42.0`][2.41.1...2.42.0]. 66 | 67 | ### Changed 68 | 69 | - Required `ergebnis/json:^1.2.0` ([#1273]), by [@dependabot] 70 | - Required `ergebnis/json-printer:^3.5.0` ([#1275]), by [@dependabot] 71 | - Required `ergebnis/json-normalizer:^4.5.0` ([#1277]), by [@localheinz] 72 | - Added support for PHP 8.0 ([#1278]), by [@localheinz] 73 | - Added support for PHP 7.4 ([#1279]), by [@localheinz] 74 | 75 | ## [`2.41.1`][2.41.1] 76 | 77 | For a full diff see [`2.41.0...2.41.1`][2.41.0...2.41.1]. 78 | 79 | ### Fixed 80 | 81 | - Required `ergebnis/json-normalizer:^4.4.1` ([#1243]), by [@dependabot] 82 | 83 | ## [`2.41.0`][2.41.0] 84 | 85 | For a full diff see [`2.40.0...2.41.0`][2.40.0...2.41.0]. 86 | 87 | ### Changed 88 | 89 | - Required `ergebnis/json-normalizer:^4.4.0` ([#1241]), by [@dependabot] 90 | 91 | ### Fixed 92 | 93 | - Updated `composer/composer` ([#1237]), by [@localheinz] 94 | 95 | ## [`2.40.0`][2.40.0] 96 | 97 | For a full diff see [`2.39.0...2.40.0`][2.39.0...2.40.0]. 98 | 99 | ### Changed 100 | 101 | - Updated `schema.json` ([#1204]), by [@ergebnis-bot] 102 | 103 | ### Fixed 104 | 105 | - Prevented installation of `symfony/console:^7.0.0` ([#1234]), by [@localheinz] 106 | 107 | ## [`2.39.0`][2.39.0] 108 | 109 | For a full diff see [`2.38.0...2.39.0`][2.38.0...2.39.0]. 110 | 111 | ### Changed 112 | 113 | - Required `ergebnis/json:^1.1.0` ([#1191]), by [@localheinz] 114 | - Required `ergebnis/json-normalizer:^4.3.0` ([#1192]), by [@localheinz] 115 | - Required `ergebnis/json-printer:^3.4.0` ([#1195]), by [@localheinz] 116 | 117 | ## [`2.38.0`][2.38.0] 118 | 119 | For a full diff see [`2.37.0...2.38.0`][2.37.0...2.38.0]. 120 | 121 | ### Changed 122 | 123 | - Added support for PHP 8.3 ([#1189]), by [@localheinz] 124 | 125 | ### Fixed 126 | 127 | - Adjusted `Command\NormalizeCommand` to respect `--no-ansi`, `--no-plugins`, `--no-scripts` options ([#1184]), by [@mxr576] 128 | - Updated `composer/composer` ([#1188]), by [@localheinz] 129 | 130 | ## [`2.37.0`][2.37.0] 131 | 132 | For a full diff see [`2.36.0...2.37.0`][2.36.0...2.37.0]. 133 | 134 | ### Changed 135 | 136 | - Updated `schema.json` ([#1170]), by [@ergebnis-bot] 137 | 138 | ### Fixed 139 | 140 | - Updated `composer/composer` ([#1171]), by [@localheinz] 141 | 142 | ## [`2.36.0`][2.36.0] 143 | 144 | For a full diff see [`2.35.0...2.36.0`][2.35.0...2.36.0]. 145 | 146 | ### Changed 147 | 148 | - Updated `schema.json` ([#1155]), by [@ergebnis-bot] 149 | - Required `composer/composer:2.6.1` for compiling `composer-normalize.phar` ([#1158]), by [@localheinz] 150 | 151 | ## [`2.35.0`][2.35.0] 152 | 153 | For a full diff see [`2.34.0...2.35.0`][2.34.0...2.35.0]. 154 | 155 | ### Changed 156 | 157 | - Started passing through `--no-plugins` and `--no-scripts` options ([#1141]), by [@mxr576] 158 | 159 | ## [`2.34.0`][2.34.0] 160 | 161 | For a full diff see [`2.33.0...2.34.0`][2.33.0...2.34.0]. 162 | 163 | ### Changed 164 | 165 | - Updated `schema.json` ([#1136]), by [@ergebnis-bot] 166 | 167 | ## [`2.33.0`][2.33.0] 168 | 169 | For a full diff see [`2.32.0...2.33.0`][2.32.0...2.33.0]. 170 | 171 | ### Changed 172 | 173 | - Required `ergebnis/json-normalizer:^4.2.0` ([#1127]), by [@dependabot] 174 | 175 | ## [`2.32.0`][2.32.0] 176 | 177 | For a full diff see [`2.31.0...2.32.0`][2.31.0...2.32.0]. 178 | 179 | ### Changed 180 | 181 | - Dropped support for PHP 8.0 ([#1118]), by [@localheinz] 182 | 183 | ### Fixed 184 | 185 | - Required `composer/composer:2.5.8` for compiling `composer-normalize.phar` ([#1125]), by [@localheinz] 186 | 187 | ## [`2.31.0`][2.31.0] 188 | 189 | For a full diff see [`2.30.2...2.31.0`][2.30.2...2.31.0]. 190 | 191 | ### Changed 192 | 193 | - Updated `schema.json` ([#1070]), by [@ergebnis-bot] 194 | - Required `ergebnis/json-normalizer:^4.1.0` ([#1095]), by [@dependabot] 195 | - Started passing through `--no-ansi` option to `UpdateCommand` ([#827]), by [@localheinz] 196 | 197 | ### Fixed 198 | 199 | - Required `composer/composer:2.5.5` for compiling `composer-normalize.phar` ([#1094]), by [@localheinz] 200 | 201 | ## [`2.30.2`][2.30.2] 202 | 203 | For a full diff see [`2.30.1...2.30.2`][2.30.1...2.30.2]. 204 | 205 | ### Fixed 206 | 207 | - Required `ergebnis/json-normalizer:^4.0.2` ([#1062]), by [@localheinz] 208 | 209 | ## [`2.30.1`][2.30.1] 210 | 211 | For a full diff see [`2.30.0...2.30.1`][2.30.0...2.30.1]. 212 | 213 | ### Fixed 214 | 215 | - Required `ergebnis/json-normalizer:^4.0.1` ([#1060]), by [@localheinz] 216 | 217 | ## [`2.30.0`][2.30.0] 218 | 219 | For a full diff see [`2.29.0...2.30.0`][2.29.0...2.30.0]. 220 | 221 | ### Changed 222 | 223 | - Started injecting `Printer\Printer` instead of `Formatter\Formatter` into `NormalizeCommand` ([#1008]), by [@ergebnis-bot] 224 | - Required `composer/composer:2.5.1` for compiling `composer-normalize.phar` ([#1020]), by [@localheinz] 225 | - Required `ergebnis/json-normalizer:^4.0.0` ([#1056]), by [@dependabot] 226 | 227 | ## [`2.29.0`][2.29.0] 228 | 229 | For a full diff see [`2.28.3...2.29.0`][2.28.3...2.29.0]. 230 | 231 | ### Changed 232 | 233 | - Updated `schema.json` ([#959]), by [@ergebnis-bot] 234 | - Dropped support for PHP 7.4 ([#998]), by [@localheinz] 235 | - Required `composer/composer:2.4.4` for compiling `composer-normalize.phar` ([#1004]), by [@localheinz] 236 | 237 | ## [`2.28.3`][2.28.3] 238 | 239 | For a full diff see [`2.28.2...2.28.3`][2.28.2...2.28.3]. 240 | 241 | ### Fixed 242 | 243 | - Required `composer/composer:2.3.9` for compiling `composer-normalize.phar` ([#942]), by [@localheinz] 244 | 245 | ## [`2.28.2`][2.28.2] 246 | 247 | For a full diff see [`2.28.1...2.28.2`][2.28.1...2.28.2]. 248 | 249 | ### Fixed 250 | 251 | - Required `composer/composer:2.3.8` for compiling `composer-normalize.phar` ([#941]), by [@localheinz] 252 | 253 | ## [`2.28.1`][2.28.1] 254 | 255 | For a full diff see [`2.28.0...2.28.1`][2.28.0...2.28.1]. 256 | 257 | ### Removed 258 | 259 | - Removed banner ([#938]), by [@localheinz] 260 | 261 | ## [`2.28.0`][2.28.0] 262 | 263 | For a full diff see [`2.27.0...2.28.0`][2.27.0...2.28.0]. 264 | 265 | ### Changed 266 | 267 | - Updated `schema.json` ([#933]), by [@ergebnis-bot] 268 | 269 | ## [`2.27.0`][2.27.0] 270 | 271 | For a full diff see [`2.26.0...2.27.0`][2.26.0...2.27.0]. 272 | 273 | ### Changed 274 | 275 | - Updated `schema.json` ([#930]), by [@ergebnis-bot] 276 | 277 | ## [`2.26.0`][2.26.0] 278 | 279 | For a full diff see [`2.25.2...2.26.0`][2.25.2...2.26.0]. 280 | 281 | ### Changed 282 | 283 | - Updated `schema.json` ([#923]), by [@ergebnis-bot] 284 | 285 | ## [`2.25.2`][2.25.2] 286 | 287 | For a full diff see [`2.25.1...2.25.2`][2.25.1...2.25.2]. 288 | 289 | ### Changed 290 | 291 | - Updated `schema.json` ([#916]), by [@ergebnis-bot] 292 | - Required `composer/composer:2.3.5` for compiling `composer-normalize.phar` ([#922]), by [@localheinz] 293 | 294 | ### Fixed 295 | 296 | - Updated `justinrainbow/json-schema` ([#920]), by [@dependabot] 297 | 298 | ## [`2.25.1`][2.25.1] 299 | 300 | For a full diff see [`2.25.0...2.25.1`][2.25.0...2.25.1]. 301 | 302 | ### Changed 303 | 304 | - Required `composer/composer:2.3.1` for compiling `composer-normalize.phar` ([#915]), by [@localheinz] 305 | 306 | ## [`2.25.0`][2.25.0] 307 | 308 | For a full diff see [`2.24.1...2.25.0`][2.24.1...2.25.0]. 309 | 310 | ### Changed 311 | 312 | - Updated `schema.json` ([#912]), by [@ergebnis-bot] 313 | - Required `composer/composer:2.3.0` for compiling `composer-normalize.phar` ([#913]), by [@localheinz] 314 | 315 | ## [`2.24.1`][2.24.1] 316 | 317 | For a full diff see [`2.24.0...2.24.1`][2.24.0...2.24.1]. 318 | 319 | ### Fixed 320 | 321 | - Required `composer/composer:2.2.9` for compiling `composer-normalize.phar` ([#904]), by [@localheinz] 322 | - Updated `humbug/box` ([#905]), by [@localheinz] 323 | 324 | ## [`2.24.0`][2.24.0] 325 | 326 | For a full diff see [`2.23.1...2.24.0`][2.23.1...2.24.0]. 327 | 328 | ### Added 329 | 330 | - Added Stand with Ukraine banner ([#899]), by [@localheinz] 331 | 332 | ## [`2.23.1`][2.23.1] 333 | 334 | For a full diff see [`2.23.0...2.23.1`][2.23.0...2.23.1]. 335 | 336 | ### Fixed 337 | 338 | - Required `composer/composer:2.2.5` for compiling `composer-normalize.phar` ([#871]), by [@localheinz] 339 | - Prevented updates of `ergebnis/json-normalizer` beyond `2.1.0` for now ([#877]), by [@localheinz] 340 | 341 | ## [`2.23.0`][2.23.0] 342 | 343 | For a full diff see [`2.22.0...2.23.0`][2.22.0...2.23.0]. 344 | 345 | ### Changed 346 | 347 | - Updated `ergebnis/json-normalizer` ([#864]), by [@localheinz] 348 | 349 | ### Fixed 350 | 351 | - Required `composer/composer:2.2.3` for compiling `composer-normalize.phar` ([#863]), by [@localheinz] 352 | 353 | ## [`2.22.0`][2.22.0] 354 | 355 | For a full diff see [`2.21.0...2.22.0`][2.21.0...2.22.0]. 356 | 357 | ### Changed 358 | 359 | - Required `ergebnis/json-normalizer:^2.0.0` ([#858]), by [@dependabot] 360 | 361 | ## [`2.21.0`][2.21.0] 362 | 363 | For a full diff see [`2.20.0...2.21.0`][2.20.0...2.21.0]. 364 | 365 | ### Changed 366 | 367 | - Dropped support for PHP 7.3 ([#852]), by [@localheinz] 368 | 369 | ## [`2.20.0`][2.20.0] 370 | 371 | For a full diff see [`2.19.0...2.20.0`][2.19.0...2.20.0]. 372 | 373 | ### Changed 374 | 375 | - Dropped support for PHP 7.2 ([#845]), by [@localheinz] 376 | 377 | ## [`2.19.0`][2.19.0] 378 | 379 | For a full diff see [`2.18.0...2.19.0`][2.18.0...2.19.0]. 380 | 381 | ### Changed 382 | 383 | - Required `composer/composer:2.2.1` for compiling `composer-normalize.phar` ([#842]), by [@localheinz] 384 | 385 | ## [`2.18.0`][2.18.0] 386 | 387 | For a full diff see [`2.17.0...2.18.0`][2.17.0...2.18.0]. 388 | 389 | ### Changed 390 | 391 | - Updated `schema.json` ([#829]), by [@ergebnis-bot] 392 | 393 | ## [`2.17.0`][2.17.0] 394 | 395 | For a full diff see [`2.16.0...2.17.0`][2.16.0...2.17.0]. 396 | 397 | ### Changed 398 | 399 | - Updated `schema.json` ([#816]), by [@ergebnis-bot] 400 | 401 | ### Fixed 402 | 403 | - Required `composer/composer:2.1.14` for compiling `composer-normalize.phar` ([#825]), by [@localheinz] 404 | 405 | ## [`2.16.0`][2.16.0] 406 | 407 | For a full diff see [`2.15.0...2.16.0`][2.15.0...2.16.0]. 408 | 409 | ### Changed 410 | 411 | - Required `composer/composer:2.1.12` for compiling `composer-normalize.phar` ([#804]), by [@localheinz] 412 | - Dropped support for `composer/composer:^1.0.0` ([#807]), by [@localheinz] 413 | 414 | ## [`2.15.0`][2.15.0] 415 | 416 | For a full diff see [`2.14.0...2.15.0`][2.14.0...2.15.0]. 417 | 418 | ### Changed 419 | 420 | - Updated `schema.json` ([#754]), by [@ergebnis-bot] 421 | 422 | ## [`2.14.0`][2.14.0] 423 | 424 | For a full diff see [`2.13.4...2.14.0`][2.13.4...2.14.0]. 425 | 426 | ### Changed 427 | 428 | - Updated `schema.json` ([#744]), by [@ergebnis-bot] 429 | 430 | ### Fixed 431 | 432 | - Updated `composer/composer` ([#750]), by [@localheinz] 433 | 434 | ## [`2.13.4`][2.13.4] 435 | 436 | For a full diff see [`2.13.3...2.13.4`][2.13.3...2.13.4]. 437 | 438 | ### Fixed 439 | 440 | - Required `composer/composer:2.0.13` for compiling `composer-normalize.phar` ([#743]), by [@localheinz] 441 | 442 | ## [`2.13.3`][2.13.3] 443 | 444 | For a full diff see [`2.13.2...2.13.3`][2.13.2...2.13.3]. 445 | 446 | ### Fixed 447 | 448 | - Required `ergebnis/json-normalizer:^1.0.3` which correctly sorts `composer-plugin-api` ([#707]), by [@dependabot] 449 | 450 | ## [`2.13.2`][2.13.2] 451 | 452 | For a full diff see [`2.13.1...2.13.2`][2.13.1...2.13.2]. 453 | 454 | ### Fixed 455 | 456 | - Required `ergebnis/json-normalizer:^1.0.2` which ignores the `config.preferred-install` hash only instead of all properties with the name `preferred-install` ([#647]), by [@localheinz] 457 | 458 | ## [`2.13.1`][2.13.1] 459 | 460 | For a full diff see [`2.13.0...2.13.1`][2.13.0...2.13.1]. 461 | 462 | :clown_face: Made a mistake tagging this release *before- pulling changes merged into `main`. 463 | 464 | ## [`2.13.0`][2.13.0] 465 | 466 | For a full diff see [`2.12.2...2.13.0`][2.12.2...2.13.0]. 467 | 468 | ### Changed 469 | 470 | - Brought back support for `composer/composer:^1.0.0` ([#644]), by [@localheinz] 471 | 472 | ## [`2.12.2`][2.12.2] 473 | 474 | For a full diff see [`2.12.1...2.12.2`][2.12.1...2.12.2]. 475 | 476 | ### Fixed 477 | 478 | - Required `ergebnis/json-normalizer:^1.0.1` which ignores the `preferred-install` hash when sorting configuration hashes by key ([#646]), by [@dependabot] 479 | 480 | ## [`2.12.1`][2.12.1] 481 | 482 | For a full diff see [`2.12.0...2.12.1`][2.12.0...2.12.1]. 483 | 484 | ### Fixed 485 | 486 | - Show version of plugin instead of version of `Composer\Console\Application` when running as development dependency ([#643]), by [@localheinz] 487 | 488 | ## [`2.12.0`][2.12.0] 489 | 490 | For a full diff see [`2.11.0...2.12.0`][2.11.0...2.12.0]. 491 | 492 | ### Added 493 | 494 | - Started showing plugin and author name when running `composer normalize` ([#641]), by [@localheinz] 495 | 496 | ### Changed 497 | 498 | - Required `ergebnis/json-normalizer:^1.0.0` which allows recursively sorting config hashes ([#634]), by [@dependabot] 499 | 500 | ### Fixed 501 | 502 | - Required `composer/composer:2.0.8` for `composer-normalize.phar` ([#640]), by [@localheinz] 503 | 504 | ## [`2.11.0`][2.11.0] 505 | 506 | For a full diff see [`2.10.0...2.11.0`][2.10.0...2.11.0]. 507 | 508 | ### Changed 509 | 510 | - Updated `schema.json` ([#615]), by [@ergebnis-bot] 511 | 512 | ## [`2.10.0`][2.10.0] 513 | 514 | For a full diff see [`2.9.1...2.10.0`][2.9.1...2.10.0]. 515 | 516 | ### Added 517 | 518 | - Allowed configuration via composer extra ([#608]), by [@localheinz] 519 | 520 | ## [`2.9.1`][2.9.1] 521 | 522 | For a full diff see [`2.9.0...2.9.1`][2.9.0...2.9.1]. 523 | 524 | ### Fixed 525 | 526 | - Required at least `composer/composer:^1.10.17` and used `composer/composer:1.10.17` for `composer-normalize.phar` ([#596]), by [@localheinz] 527 | - Dropped support for `composer/composer:^1.0.0` ([#597]), by [@localheinz] 528 | 529 | ## [`2.9.0`][2.9.0] 530 | 531 | For a full diff see [`2.8.2...2.9.0`][2.8.2...2.9.0]. 532 | 533 | ### Changed 534 | 535 | - Updated `schema.json` ([#572]), by [@ergebnis-bot] 536 | 537 | ### Fixed 538 | 539 | - Required at least `composer/composer:^1.10.15` and used `composer/composer:1.10.15` for `composer-normalize.phar` ([#582]), by [@localheinz] 540 | 541 | ## [`2.8.2`][2.8.2] 542 | 543 | For a full diff see [`2.8.1...2.8.2`][2.8.1...2.8.2]. 544 | 545 | ### Changed 546 | 547 | - Require at least `composer/composer:^1.10.13` ([#554]), by [@localheinz] 548 | 549 | ## [`2.8.1`][2.8.1] 550 | 551 | For a full diff see [`2.8.0...2.8.1`][2.8.0...2.8.1]. 552 | 553 | ### Changed 554 | 555 | - Dropped support for PHP 7.1 ([#529]), by [@localheinz] 556 | 557 | ## [`2.8.0`][2.8.0] 558 | 559 | For a full diff see [`2.7.0...2.8.0`][2.7.0...2.8.0]. 560 | 561 | ### Changed 562 | 563 | - Updated `schema.json` ([#526]), by [@ergebnis-bot] 564 | 565 | ## [`2.7.0`][2.7.0] 566 | 567 | For a full diff see [`2.6.1...2.7.0`][2.6.1...2.7.0]. 568 | 569 | ### Added 570 | 571 | - Added `--no-check-lock` option which allows skipping validation of `composer.lock` ([#515]), by [@localheinz] 572 | 573 | ### Changed 574 | 575 | - Updated `schema.json` ([#512]), by [@ergebnis-bot] 576 | 577 | ## [`2.6.1`][2.6.1] 578 | 579 | For a full diff see [`2.6.0...2.6.1`][2.6.0...2.6.1]. 580 | 581 | ### Fixed 582 | 583 | - Added support for PHP 8.0, for real ([#484], [#485], [#487]), by [@dependabot] 584 | 585 | ## [`2.6.0`][2.6.0] 586 | 587 | For a full diff see [`2.5.2...2.6.0`][2.5.2...2.6.0]. 588 | 589 | ### Added 590 | 591 | - Added support for PHP 8.0 ([#465]), by [@core23] 592 | 593 | ## [`2.5.2`][2.5.2] 594 | 595 | For a full diff see [`2.5.1...2.5.2`][2.5.1...2.5.2]. 596 | 597 | ### Fixed 598 | 599 | - Started ignoring platform requirements when updating the lock file ([#481]), by [@localheinz] 600 | 601 | ## [`2.5.1`][2.5.1] 602 | 603 | For a full diff see [`2.5.0...2.5.1`][2.5.0...2.5.1]. 604 | 605 | ### Fixed 606 | 607 | - Started updating lock files with a new `Composer\Console\Application` instead of reusing the current instance ([#420]), by [@localheinz] 608 | - Stopped using the deprecated `--no-suggest` option when updating the lock file ([#422]), by [@localheinz] 609 | - Started relaxing schema in place to avoid issues resolving references and the like on Windows ([#424]), by [@localheinz] 610 | 611 | ## [`2.5.0`][2.5.0] 612 | 613 | For a full diff see [`2.4.0...2.5.0`][2.4.0...2.5.0]. 614 | 615 | ### Changed 616 | 617 | - Apply lax validation to `composer.json` ([#416]), by [@localheinz] 618 | 619 | ## [`2.4.0`][2.4.0] 620 | 621 | For a full diff see [`2.3.2...2.4.0`][2.3.2...2.4.0]. 622 | 623 | ### Changed 624 | 625 | - Started showing validation error messages as obtained from validation instead of relying on on executing composer validate ([#406]), by [@localheinz] 626 | - Made plugin compatible with `composer/composer:^2.0.0` ([#412]), by [@localheinz] 627 | 628 | ## [`2.3.2`][2.3.2] 629 | 630 | For a full diff see [`2.3.1...2.3.2`][2.3.1...2.3.2]. 631 | 632 | ### Fixed 633 | 634 | - Fixed a reference that prevented an upload of release assets ([#380]), by [@localheinz] 635 | 636 | ## [`2.3.1`][2.3.1] 637 | 638 | For a full diff see [`2.3.0...2.3.1`][2.3.0...2.3.1]. 639 | 640 | ### Fixed 641 | 642 | - Updated `composer/composer` ([#379]), by [@localheinz] 643 | 644 | ## [`2.3.0`][2.3.0] 645 | 646 | For a full diff see [`2.2.4...2.3.0`][2.2.4...2.3.0]. 647 | 648 | ### Changed 649 | 650 | - Updated `schema.json` ([#374]), by [@ergebnis-bot] 651 | 652 | ## [`2.2.4`][2.2.4] 653 | 654 | For a full diff see [`2.2.3...2.2.4`][2.2.3...2.2.4]. 655 | 656 | ### Fixed 657 | 658 | - Use real path to `schema.json` ([#364]), by [@localheinz] 659 | 660 | ## [`2.2.3`][2.2.3] 661 | 662 | For a full diff see [`2.2.2...2.2.3`][2.2.2...2.2.3]. 663 | 664 | ### Changed 665 | 666 | - Updated `schema.json` ([#354]), by [@ergebnis-bot] 667 | 668 | ## [`2.2.2`][2.2.2] 669 | 670 | For a full diff see [`2.2.1...2.2.2`][2.2.1...2.2.2]. 671 | 672 | ### Changed 673 | 674 | - Updated `schema.json` ([#322]), by [@localheinz] 675 | 676 | ## [`2.2.1`][2.2.1] 677 | 678 | For a full diff see [`2.2.0...2.2.1`][2.2.0...2.2.1]. 679 | 680 | ### Changed 681 | 682 | - Removed dependency on `ergebnis/composer-json-normalizer` ([#316]), by [@localheinz] 683 | 684 | ## [`2.2.0`][2.2.0] 685 | 686 | For a full diff see [`2.1.2...2.2.0`][2.1.2...2.2.0]. 687 | 688 | ### Added 689 | 690 | - Added `--diff` option ([#303]), by [@localheinz] 691 | 692 | ## [`2.1.2`][2.1.2] 693 | 694 | For a full diff see [`2.1.1...2.1.2`][2.1.1...2.1.2]. 695 | 696 | ### Fixed 697 | 698 | - Allow passing argument and options to the command ([#301]), by [@localheinz] 699 | 700 | ## [`2.1.1`][2.1.1] 701 | 702 | For a full diff see [`2.1.0...2.1.1`][2.1.0...2.1.1]. 703 | 704 | ### Fixed 705 | 706 | - Actually run `composer validate` to show validation errors when `composer.json` is not valid according to its schema ([#297]), by [@localheinz] 707 | 708 | ## [`2.1.0`][2.1.0] 709 | 710 | For a full diff see [`2.0.2...2.1.0`][2.0.2...2.1.0]. 711 | 712 | ### Added 713 | 714 | - Started compiling, signing, and uploading `composer-normalize.phar` and `composer-normalize.phar.asc` to release assets when a tag is pushed ([#292]), by [@localheinz] 715 | 716 | ## [`2.0.2`][2.0.2] 717 | 718 | For a full diff see [`2.0.1...2.0.2`][2.0.1...2.0.2]. 719 | 720 | ### Fixed 721 | 722 | - Brought back support for PHP 7.1 ([#280]), by [@localheinz] 723 | 724 | ## [`2.0.1`][2.0.1] 725 | 726 | For a full diff see [`2.0.0...2.0.1`][2.0.0...2.0.1] 727 | 728 | ## Changed 729 | 730 | - Removed `Ergebnis\Composer\Normalize\Command\SchemaUriResolver` and checked in `schema.json` instead ([#273]), by [@localheinz] 731 | 732 | ## [`2.0.0`][2.0.0] 733 | 734 | For a full diff see [`1.3.1...2.0.0`][1.3.1...2.0.0]. 735 | 736 | ## Changed 737 | 738 | - Started using `ergebnis/composer-json-normalizer` instead of `localheinz/composer-json-normalizer`, `ergebnis/json-normalizer` instead of `localheinz/json-normalizer`, and `ergebnis/json-printer` instead of `localheinz/json-printer` ([#261]), by [@localheinz] 739 | - Removed default values for parameters `$formatter` and `$differ` of constructor of `Ergebnis\Composer\Normalize\Command\NormalizeCommand` ([#262]), by [@localheinz] 740 | - Renamed vendor namespace `Localheinz` to `Ergebnis` after move to [@ergebnis] ([#267]), by [@localheinz] 741 | 742 | Run 743 | 744 | ``` 745 | $ composer remove localheinz/composer-normalize 746 | ``` 747 | 748 | and 749 | 750 | ``` 751 | $ composer require ergebnis/composer-normalize 752 | ``` 753 | 754 | to update. 755 | 756 | Run 757 | 758 | ``` 759 | $ find . -type f -exec sed -i '.bak' 's/Localheinz\\Composer\\Normalizer/Ergebnis\\Composer\\Normalize/g' {} \; 760 | ``` 761 | 762 | to replace occurrences of `Localheinz\Composer\Normalize` with `Ergebnis\Composer\Normalize`. 763 | 764 | Run 765 | 766 | ``` 767 | $ find -type f -name '*.bak' -delete 768 | ``` 769 | 770 | to delete backup files created in the previous step. 771 | - Marked `Ergebnis\Composer\Normalize\Command\NormalizeCommand` and `Ergebnis\Composer\Normalize\Command\SchemaUriResolver` as internal to allow modifications without the need for major releases ([#270]), by [@localheinz] 772 | 773 | ### Fixed 774 | 775 | - Dropped support for PHP 7.1 ([#235]), by [@localheinz] 776 | 777 | ## [`1.3.1`][1.3.1] 778 | 779 | For a full diff see [`1.3.0...1.3.1`][1.3.0...1.3.1]. 780 | 781 | ### Fixed 782 | 783 | - Started using `localheinz/diff` to avoid issues using `sebastian/diff` ([#207]), by [@localheinz] 784 | 785 | ## [`1.3.0`][1.3.0] 786 | 787 | For a full diff see [`1.2.0...1.3.0`][1.2.0...1.3.0]. 788 | 789 | ### Changed 790 | 791 | - Resolve local and fall back to remote schema so that command works offline and behind proxies ([#190]), by [@localheinz] 792 | 793 | ## [`1.2.0`][1.2.0] 794 | 795 | For a full diff see [`1.1.4...1.2.0`][1.1.4...1.2.0]. 796 | 797 | ### Changed 798 | 799 | - Started using the `StrictUnifiedDiffOutputBuilder` when available to create more condensed diffs when using the `--dry-run` option ([#80]), by [@localheinz] 800 | 801 | ## [`1.1.4`][1.1.4] 802 | 803 | For a full diff see [`1.1.3...1.1.4`][1.1.3...1.1.4]. 804 | 805 | ### Fixed 806 | 807 | - Removed requirement for `composer.json` to be writable when using the `--dry-run` option ([#177]), by [@localheinz] 808 | 809 | ## [`1.1.3`][1.1.3] 810 | 811 | For a full diff see [`1.1.2...1.1.3`][1.1.2...1.1.3]. 812 | 813 | ### Fixed 814 | 815 | - Reversed use of red and green for rendering diff when using the `--dry-run` option ([#173]), by [@TravisCarden] 816 | 817 | ## [`1.1.2`][1.1.2] 818 | 819 | For a full diff see [`1.1.1...1.1.2`][1.1.1...1.1.2]. 820 | 821 | ### Fixed 822 | 823 | - Reverted deprecation of the `file` argument of the `NormalizeCommand` as it turns out that the same functionality can _not_ be achieved using the `--working-dir` option ([#166]), by [@localheinz] 824 | 825 | ## [`1.1.1`][1.1.1] 826 | 827 | For a full diff see [`1.1.0...1.1.1`][1.1.0...1.1.1]. 828 | 829 | ### Removed 830 | 831 | - Updated [`localheinz/composer-json-normalizer`](http://github.com/localheinz/composer-json-normalizer), which effectively removed a dependency on [`composer/composer`](https://github.com/composer/composer) ([#157]), by [@localheinz] 832 | 833 | ## [`1.1.0`][1.1.0] 834 | 835 | For a full diff see [`1.0.0...1.1.0`][1.0.0...1.1.0]. 836 | 837 | ### Deprecated 838 | 839 | - Deprecated the `file` argument of the `NormalizeCommand` as the same functionality can be achieved using the `--working-dir` option ([#145]), by [@localheinz] 840 | 841 | ### Fixed 842 | 843 | - Force reading `composer.json` and `composer.lock` after normalization to ensure `composer.lock` is updated when not fresh after normalization ([#139]), by [@localheinz] 844 | 845 | ## [`1.0.0`][1.0.0] 846 | 847 | For a full diff see [`0.9.0...1.0.0`][0.9.0...1.0.0]. 848 | 849 | ### Added 850 | 851 | - Added this changelog ([#94]), by [@localheinz] 852 | 853 | ### Removed 854 | 855 | - Removed normalizers after extracting package [`localheinz/composer-json-normalizer`](https://github.com/localheinz/composer-json-normalizer) ([#106]), by [@localheinz] 856 | 857 | ## [`0.9.0`][0.9.0] 858 | 859 | For a full diff see [`0.8.0...0.9.0`][0.8.0...0.9.0]. 860 | 861 | ### Changed 862 | 863 | - The `ConfigHashNormalizer` now also sorts the `scripts-descriptions` section ([#89]), by [@localheinz] 864 | 865 | ### Fixed 866 | 867 | - When validation of `composer.lock` fails prior to normalization, it is now recommended to update the lock file only ([#86]), by [@svenluijten] 868 | 869 | ## [`0.8.0`][0.8.0] 870 | 871 | For a full diff see [`0.7.0...0.8.0`][0.7.0...0.8.0]. 872 | 873 | ### Changed 874 | 875 | - The `ConfigHashNormalizer` now also sorts the `extra` section ([#60]), by [@localheinz] 876 | 877 | ## [`0.7.0`][0.7.0] 878 | 879 | For a full diff see [`0.6.0...0.7.0`][0.6.0...0.7.0]. 880 | 881 | ### Changed 882 | 883 | - Updated `localheinz/json-normalizer`, which now sniffs the new-line character and uses it for printing instead of using `PHP_EOL` ([#62]), by [@localheinz] 884 | 885 | ## [`0.6.0`][0.6.0] 886 | 887 | For a full diff see [`0.5.0...0.6.0`][0.5.0...0.6.0]. 888 | 889 | ### Added 890 | 891 | - Added a `file` argument to the `NormalizeCommand`, so the path to `composer.json` can be specified now, ([#51]), by [@localheinz] 892 | 893 | ## [`0.5.0`][0.5.0] 894 | 895 | For a full diff see [`0.4.0...0.5.0`][0.4.0...0.5.0]. 896 | 897 | ### Changed 898 | 899 | - Updated `localheinz/json-normalizer`, which significantly improves the `SchemaNormalizer` employed to do the major normalization of `composer.json` ([#42]), by [@localheinz] 900 | 901 | ## [`0.4.0`][0.4.0] 902 | 903 | For a full diff see [`0.3.0...0.4.0`][0.3.0...0.4.0]. 904 | 905 | ### Added 906 | 907 | - Added `--dry-run` option, which allows usage in Continuous Integration systems, as it renders a diff and exits with a non-zero exit code ([#38]), by [@localheinz] 908 | 909 | ## [`0.3.0`][0.3.0] 910 | 911 | For a full diff see [`0.2.0...0.3.0`][0.2.0...0.3.0]. 912 | 913 | ### Fixed 914 | 915 | - Dropped support for PHP 7.0, which allows proper handling of empty PSR-4 namespace prefixes ([#30]), by [@localheinz] 916 | 917 | ## [`0.2.0`][0.2.0] 918 | 919 | For a full diff see [`0.1.0...0.2.0`][0.1.0...0.2.0]. 920 | 921 | ### Added 922 | 923 | - Added `--no-update-lock` option, which allows skipping the update of `composer.lock` after normalization ([#28]), by [@localheinz] 924 | - Added the `VersionConstraintNormalizer`, which normalizes version constraints ([#18]), by [@localheinz] 925 | 926 | ### Fixed 927 | 928 | - Using the `--no-scripts` option when invoking the `UpdateCommand` to update `composer.lock` ([#19]), by [@localheinz] 929 | 930 | ## [`0.1.0`][0.1.0] 931 | 932 | For a full diff see [`81bc3a8...0.1.0`][81bc3a8...0.1.0]. 933 | 934 | ### Added 935 | 936 | - Added `NormalizeCommand` ([#1]), by [@localheinz] 937 | - Added `ConfigHashNormalizer`, which sorts entries in the `config` section by key ([#2]), by [@localheinz] 938 | - Added the `NormalizePlugin`, which provides the `NormalizeCommand` ([#3]), by [@localheinz] 939 | - Added the `PackageHashNormalizer` which sorts packages in the `conflict`, `provide`, `replaces`, `require`, `require-dev`, and `suggest` sections using the same algorithm that is used by the `sort-packages` option of composer itself ([#6]), by [@localheinz] 940 | - Added the `BinNormalizer`, which sorts entries in the `bin` section by 941 | - Added the `ComposerJsonNormalizer`, which composes all of the above normalizers along with the `SchemaNormalizer`, to normalize `composer.json` according to its underlying JSON schema ([#8] and [#10]), by [@localheinz] 942 | 943 | [0.1.0]: https://github.com/ergebnis/composer-normalize/releases/tag/0.1.0 944 | [0.2.0]: https://github.com/ergebnis/composer-normalize/releases/tag/0.2.0 945 | [0.3.0]: https://github.com/ergebnis/composer-normalize/releases/tag/0.3.0 946 | [0.4.0]: https://github.com/ergebnis/composer-normalize/releases/tag/0.4.0 947 | [0.5.0]: https://github.com/ergebnis/composer-normalize/releases/tag/0.5.0 948 | [0.6.0]: https://github.com/ergebnis/composer-normalize/releases/tag/0.6.0 949 | [0.7.0]: https://github.com/ergebnis/composer-normalize/releases/tag/0.7.0 950 | [0.8.0]: https://github.com/ergebnis/composer-normalize/releases/tag/0.8.0 951 | [0.9.0]: https://github.com/ergebnis/composer-normalize/releases/tag/0.9.0 952 | [1.0.0]: https://github.com/ergebnis/composer-normalize/releases/tag/1.0.0 953 | [1.1.0]: https://github.com/ergebnis/composer-normalize/releases/tag/1.1.0 954 | [1.1.1]: https://github.com/ergebnis/composer-normalize/releases/tag/1.1.1 955 | [1.1.2]: https://github.com/ergebnis/composer-normalize/releases/tag/1.1.2 956 | [1.1.3]: https://github.com/ergebnis/composer-normalize/releases/tag/1.1.3 957 | [1.1.4]: https://github.com/ergebnis/composer-normalize/releases/tag/1.1.4 958 | [1.2.0]: https://github.com/ergebnis/composer-normalize/releases/tag/1.2.0 959 | [1.3.0]: https://github.com/ergebnis/composer-normalize/releases/tag/1.3.0 960 | [1.3.1]: https://github.com/ergebnis/composer-normalize/releases/tag/1.3.1 961 | [2.0.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.0.0 962 | [2.0.1]: https://github.com/ergebnis/composer-normalize/releases/tag/2.0.1 963 | [2.0.2]: https://github.com/ergebnis/composer-normalize/releases/tag/2.0.2 964 | [2.1.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.1.0 965 | [2.1.1]: https://github.com/ergebnis/composer-normalize/releases/tag/2.1.1 966 | [2.1.2]: https://github.com/ergebnis/composer-normalize/releases/tag/2.1.2 967 | [2.2.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.2.0 968 | [2.2.1]: https://github.com/ergebnis/composer-normalize/releases/tag/2.2.1 969 | [2.2.2]: https://github.com/ergebnis/composer-normalize/releases/tag/2.2.2 970 | [2.2.3]: https://github.com/ergebnis/composer-normalize/releases/tag/2.2.3 971 | [2.2.4]: https://github.com/ergebnis/composer-normalize/releases/tag/2.2.4 972 | [2.3.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.3.0 973 | [2.3.1]: https://github.com/ergebnis/composer-normalize/releases/tag/2.3.1 974 | [2.3.2]: https://github.com/ergebnis/composer-normalize/releases/tag/2.3.2 975 | [2.4.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.4.0 976 | [2.5.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.5.0 977 | [2.5.1]: https://github.com/ergebnis/composer-normalize/releases/tag/2.5.1 978 | [2.5.2]: https://github.com/ergebnis/composer-normalize/releases/tag/2.5.2 979 | [2.6.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.6.0 980 | [2.6.1]: https://github.com/ergebnis/composer-normalize/releases/tag/2.6.1 981 | [2.7.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.7.0 982 | [2.8.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.8.0 983 | [2.8.1]: https://github.com/ergebnis/composer-normalize/releases/tag/2.8.1 984 | [2.8.2]: https://github.com/ergebnis/composer-normalize/releases/tag/2.8.2 985 | [2.9.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.9.0 986 | [2.9.1]: https://github.com/ergebnis/composer-normalize/releases/tag/2.9.1 987 | [2.10.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.10.0 988 | [2.11.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.11.0 989 | [2.12.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.12.0 990 | [2.12.1]: https://github.com/ergebnis/composer-normalize/releases/tag/2.12.1 991 | [2.12.2]: https://github.com/ergebnis/composer-normalize/releases/tag/2.12.2 992 | [2.13.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.13.0 993 | [2.13.1]: https://github.com/ergebnis/composer-normalize/releases/tag/2.13.1 994 | [2.13.2]: https://github.com/ergebnis/composer-normalize/releases/tag/2.13.2 995 | [2.13.3]: https://github.com/ergebnis/composer-normalize/releases/tag/2.13.3 996 | [2.13.4]: https://github.com/ergebnis/composer-normalize/releases/tag/2.13.4 997 | [2.14.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.14.0 998 | [2.15.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.15.0 999 | [2.16.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.16.0 1000 | [2.17.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.17.0 1001 | [2.18.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.18.0 1002 | [2.19.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.19.0 1003 | [2.20.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.20.0 1004 | [2.21.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.21.0 1005 | [2.22.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.22.0 1006 | [2.23.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.23.0 1007 | [2.23.1]: https://github.com/ergebnis/composer-normalize/releases/tag/2.23.1 1008 | [2.24.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.24.0 1009 | [2.24.1]: https://github.com/ergebnis/composer-normalize/releases/tag/2.24.1 1010 | [2.25.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.25.0 1011 | [2.25.1]: https://github.com/ergebnis/composer-normalize/releases/tag/2.25.1 1012 | [2.25.2]: https://github.com/ergebnis/composer-normalize/releases/tag/2.25.2 1013 | [2.26.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.26.0 1014 | [2.27.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.27.0 1015 | [2.28.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.28.0 1016 | [2.28.1]: https://github.com/ergebnis/composer-normalize/releases/tag/2.28.1 1017 | [2.28.2]: https://github.com/ergebnis/composer-normalize/releases/tag/2.28.2 1018 | [2.28.3]: https://github.com/ergebnis/composer-normalize/releases/tag/2.28.3 1019 | [2.29.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.29.0 1020 | [2.30.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.30.0 1021 | [2.30.1]: https://github.com/ergebnis/composer-normalize/releases/tag/2.30.1 1022 | [2.30.2]: https://github.com/ergebnis/composer-normalize/releases/tag/2.30.2 1023 | [2.31.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.31.0 1024 | [2.32.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.32.0 1025 | [2.33.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.33.0 1026 | [2.34.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.34.0 1027 | [2.35.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.35.0 1028 | [2.36.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.36.0 1029 | [2.37.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.37.0 1030 | [2.38.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.38.0 1031 | [2.39.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.39.0 1032 | [2.40.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.40.0 1033 | [2.41.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.41.0 1034 | [2.41.1]: https://github.com/ergebnis/composer-normalize/releases/tag/2.41.1 1035 | [2.42.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.42.0 1036 | [2.43.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.43.0 1037 | [2.44.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.44.0 1038 | [2.45.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.45.0 1039 | [2.46.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.46.0 1040 | [2.47.0]: https://github.com/ergebnis/composer-normalize/releases/tag/2.47.0 1041 | 1042 | [81bc3a8...0.1.0]: https://github.com/ergebnis/composer-normalize/compare/81bc3a8...0.1.0 1043 | [0.1.0...0.2.0]: https://github.com/ergebnis/composer-normalize/compare/0.1.0...0.2.0 1044 | [0.2.0...0.3.0]: https://github.com/ergebnis/composer-normalize/compare/0.2.0...0.3.0 1045 | [0.3.0...0.4.0]: https://github.com/ergebnis/composer-normalize/compare/0.3.0...0.4.0 1046 | [0.4.0...0.5.0]: https://github.com/ergebnis/composer-normalize/compare/0.4.0...0.5.0 1047 | [0.5.0...0.6.0]: https://github.com/ergebnis/composer-normalize/compare/0.5.0...0.6.0 1048 | [0.6.0...0.7.0]: https://github.com/ergebnis/composer-normalize/compare/0.6.0...0.7.0 1049 | [0.7.0...0.8.0]: https://github.com/ergebnis/composer-normalize/compare/0.7.0...0.8.0 1050 | [0.8.0...0.9.0]: https://github.com/ergebnis/composer-normalize/compare/0.8.0...0.9.0 1051 | [0.9.0...1.0.0]: https://github.com/ergebnis/composer-normalize/compare/0.9.0...1.0.0 1052 | [1.0.0...1.1.0]: https://github.com/ergebnis/composer-normalize/compare/1.0.0...1.1.0 1053 | [1.1.0...1.1.1]: https://github.com/ergebnis/composer-normalize/compare/1.1.0...1.1.1 1054 | [1.1.1...1.1.2]: https://github.com/ergebnis/composer-normalize/compare/1.1.1...1.1.2 1055 | [1.1.2...1.1.3]: https://github.com/ergebnis/composer-normalize/compare/1.1.2...1.1.3 1056 | [1.1.3...1.1.4]: https://github.com/ergebnis/composer-normalize/compare/1.1.3...1.1.4 1057 | [1.1.4...1.2.0]: https://github.com/ergebnis/composer-normalize/compare/1.1.4...1.2.0 1058 | [1.2.0...1.3.0]: https://github.com/ergebnis/composer-normalize/compare/1.2.0...1.3.0 1059 | [1.3.0...1.3.1]: https://github.com/ergebnis/composer-normalize/compare/1.3.0...1.3.1 1060 | [1.3.1...2.0.0]: https://github.com/ergebnis/composer-normalize/compare/1.3.1...2.0.0 1061 | [2.0.0...2.0.1]: https://github.com/ergebnis/composer-normalize/compare/2.0.0...2.0.1 1062 | [2.0.1...2.0.2]: https://github.com/ergebnis/composer-normalize/compare/2.0.1...2.0.2 1063 | [2.0.2...2.1.0]: https://github.com/ergebnis/composer-normalize/compare/2.0.2...2.1.0 1064 | [2.1.0...2.1.1]: https://github.com/ergebnis/composer-normalize/compare/2.1.0...2.1.1 1065 | [2.1.1...2.1.2]: https://github.com/ergebnis/composer-normalize/compare/2.1.1...2.1.2 1066 | [2.1.2...2.2.0]: https://github.com/ergebnis/composer-normalize/compare/2.1.2...2.2.0 1067 | [2.2.0...2.2.1]: https://github.com/ergebnis/composer-normalize/compare/2.2.0...2.2.1 1068 | [2.2.1...2.2.2]: https://github.com/ergebnis/composer-normalize/compare/2.2.1...2.2.2 1069 | [2.2.2...2.2.3]: https://github.com/ergebnis/composer-normalize/compare/2.2.2...2.2.3 1070 | [2.2.3...2.2.4]: https://github.com/ergebnis/composer-normalize/compare/2.2.3...2.2.4 1071 | [2.2.4...2.3.0]: https://github.com/ergebnis/composer-normalize/compare/2.2.4...2.3.0 1072 | [2.3.0...2.3.1]: https://github.com/ergebnis/composer-normalize/compare/2.3.0...2.3.1 1073 | [2.3.1...2.3.2]: https://github.com/ergebnis/composer-normalize/compare/2.3.1...2.3.2 1074 | [2.3.2...2.4.0]: https://github.com/ergebnis/composer-normalize/compare/2.4.0...main 1075 | [2.4.0...2.5.0]: https://github.com/ergebnis/composer-normalize/compare/2.4.0...2.5.0 1076 | [2.5.0...2.5.1]: https://github.com/ergebnis/composer-normalize/compare/2.5.0...2.5.1 1077 | [2.5.1...2.5.2]: https://github.com/ergebnis/composer-normalize/compare/2.5.1...2.5.2 1078 | [2.5.2...2.6.0]: https://github.com/ergebnis/composer-normalize/compare/2.5.2...2.6.0 1079 | [2.6.0...2.6.1]: https://github.com/ergebnis/composer-normalize/compare/2.6.0...2.6.1 1080 | [2.6.1...2.7.0]: https://github.com/ergebnis/composer-normalize/compare/2.6.1...2.7.0 1081 | [2.7.0...2.8.0]: https://github.com/ergebnis/composer-normalize/compare/2.7.0...2.8.0 1082 | [2.8.0...2.8.1]: https://github.com/ergebnis/composer-normalize/compare/2.8.0...2.8.1 1083 | [2.8.1...2.8.2]: https://github.com/ergebnis/composer-normalize/compare/2.8.1...2.8.2 1084 | [2.8.2...2.9.0]: https://github.com/ergebnis/composer-normalize/compare/2.8.2...2.9.0 1085 | [2.9.0...2.9.1]: https://github.com/ergebnis/composer-normalize/compare/2.9.0...2.9.1 1086 | [2.9.1...2.10.0]: https://github.com/ergebnis/composer-normalize/compare/2.9.1...2.10.0 1087 | [2.10.0...2.11.0]: https://github.com/ergebnis/composer-normalize/compare/2.10.0...2.11.0 1088 | [2.11.0...2.12.0]: https://github.com/ergebnis/composer-normalize/compare/2.11.0...2.12.0 1089 | [2.12.0...2.12.1]: https://github.com/ergebnis/composer-normalize/compare/2.12.0...2.12.1 1090 | [2.12.1...2.12.2]: https://github.com/ergebnis/composer-normalize/compare/2.12.1...2.12.2 1091 | [2.12.2...2.13.0]: https://github.com/ergebnis/composer-normalize/compare/2.12.2...2.13.0 1092 | [2.13.0...2.13.1]: https://github.com/ergebnis/composer-normalize/compare/2.13.0...2.13.1 1093 | [2.13.1...2.13.2]: https://github.com/ergebnis/composer-normalize/compare/2.13.1...2.13.2 1094 | [2.13.2...2.13.3]: https://github.com/ergebnis/composer-normalize/compare/2.13.2...2.13.3 1095 | [2.13.3...2.13.4]: https://github.com/ergebnis/composer-normalize/compare/2.13.3...2.13.4 1096 | [2.13.4...2.14.0]: https://github.com/ergebnis/composer-normalize/compare/2.13.4...2.14.0 1097 | [2.14.0...2.15.0]: https://github.com/ergebnis/composer-normalize/compare/2.14.0...2.15.0 1098 | [2.15.0...2.16.0]: https://github.com/ergebnis/composer-normalize/compare/2.15.0...2.16.0 1099 | [2.16.0...2.17.0]: https://github.com/ergebnis/composer-normalize/compare/2.16.0...2.17.0 1100 | [2.17.0...2.18.0]: https://github.com/ergebnis/composer-normalize/compare/2.17.0...2.18.0 1101 | [2.18.0...2.19.0]: https://github.com/ergebnis/composer-normalize/compare/2.18.0...2.19.0 1102 | [2.19.0...2.20.0]: https://github.com/ergebnis/composer-normalize/compare/2.19.0...2.20.0 1103 | [2.20.0...2.21.0]: https://github.com/ergebnis/composer-normalize/compare/2.20.0...2.21.0 1104 | [2.21.0...2.22.0]: https://github.com/ergebnis/composer-normalize/compare/2.21.0...2.22.0 1105 | [2.22.0...2.23.0]: https://github.com/ergebnis/composer-normalize/compare/2.22.0...2.23.0 1106 | [2.23.0...2.23.1]: https://github.com/ergebnis/composer-normalize/compare/2.23.0...2.23.1 1107 | [2.23.1...2.24.0]: https://github.com/ergebnis/composer-normalize/compare/2.23.1...2.24.0 1108 | [2.24.0...2.24.1]: https://github.com/ergebnis/composer-normalize/compare/2.24.0...2.24.1 1109 | [2.24.1...2.25.0]: https://github.com/ergebnis/composer-normalize/compare/2.24.1...2.25.0 1110 | [2.25.0...2.25.1]: https://github.com/ergebnis/composer-normalize/compare/2.25.0...2.25.1 1111 | [2.25.1...2.25.2]: https://github.com/ergebnis/composer-normalize/compare/2.25.1...2.25.2 1112 | [2.25.2...2.26.0]: https://github.com/ergebnis/composer-normalize/compare/2.25.2...2.26.0 1113 | [2.26.0...2.27.0]: https://github.com/ergebnis/composer-normalize/compare/2.26.0...2.27.0 1114 | [2.27.0...2.28.0]: https://github.com/ergebnis/composer-normalize/compare/2.27.0...2.28.0 1115 | [2.28.0...2.28.1]: https://github.com/ergebnis/composer-normalize/compare/2.28.0...2.28.1 1116 | [2.28.1...2.28.2]: https://github.com/ergebnis/composer-normalize/compare/2.28.1...2.28.2 1117 | [2.28.2...2.28.3]: https://github.com/ergebnis/composer-normalize/compare/2.28.2...2.38.3 1118 | [2.28.3...2.29.0]: https://github.com/ergebnis/composer-normalize/compare/2.28.3...2.29.0 1119 | [2.29.0...2.30.0]: https://github.com/ergebnis/composer-normalize/compare/2.29.0...2.30.0 1120 | [2.30.0...2.30.1]: https://github.com/ergebnis/composer-normalize/compare/2.30.0...2.30.1 1121 | [2.30.1...2.30.2]: https://github.com/ergebnis/composer-normalize/compare/2.30.1...2.30.2 1122 | [2.30.2...2.31.0]: https://github.com/ergebnis/composer-normalize/compare/2.30.2...2.31.0 1123 | [2.31.0...2.32.0]: https://github.com/ergebnis/composer-normalize/compare/2.31.0...2.32.0 1124 | [2.32.0...2.33.0]: https://github.com/ergebnis/composer-normalize/compare/2.32.0...2.33.0 1125 | [2.33.0...2.34.0]: https://github.com/ergebnis/composer-normalize/compare/2.33.0...2.34.0 1126 | [2.34.0...2.35.0]: https://github.com/ergebnis/composer-normalize/compare/2.34.0...2.35.0 1127 | [2.35.0...2.36.0]: https://github.com/ergebnis/composer-normalize/compare/2.35.0...2.36.0 1128 | [2.36.0...2.37.0]: https://github.com/ergebnis/composer-normalize/compare/2.36.0...2.37.0 1129 | [2.37.0...2.38.0]: https://github.com/ergebnis/composer-normalize/compare/2.37.0...2.38.0 1130 | [2.38.0...2.39.0]: https://github.com/ergebnis/composer-normalize/compare/2.38.0...2.39.0 1131 | [2.39.0...2.40.0]: https://github.com/ergebnis/composer-normalize/compare/2.39.0...2.40.0 1132 | [2.40.0...2.41.0]: https://github.com/ergebnis/composer-normalize/compare/2.40.0...2.41.0 1133 | [2.41.0...2.41.1]: https://github.com/ergebnis/composer-normalize/compare/2.41.0...2.41.1 1134 | [2.41.1...2.42.0]: https://github.com/ergebnis/composer-normalize/compare/2.41.1...2.42.0 1135 | [2.42.0...2.43.0]: https://github.com/ergebnis/composer-normalize/compare/2.42.0...2.43.0 1136 | [2.43.0...2.44.0]: https://github.com/ergebnis/composer-normalize/compare/2.43.0...2.44.0 1137 | [2.44.0...2.45.0]: https://github.com/ergebnis/composer-normalize/compare/2.44.0...2.45.0 1138 | [2.45.0...2.46.0]: https://github.com/ergebnis/composer-normalize/compare/2.45.0...2.46.0 1139 | [2.46.0...2.47.0]: https://github.com/ergebnis/composer-normalize/compare/2.46.0...2.47.0 1140 | [2.47.0...main]: https://github.com/ergebnis/composer-normalize/compare/2.47.0...main 1141 | 1142 | [#1]: https://github.com/ergebnis/composer-normalize/pull/1 1143 | [#2]: https://github.com/ergebnis/composer-normalize/pull/2 1144 | [#3]: https://github.com/ergebnis/composer-normalize/pull/3 1145 | [#6]: https://github.com/ergebnis/composer-normalize/pull/6 1146 | [#8]: https://github.com/ergebnis/composer-normalize/pull/8 1147 | [#10]: https://github.com/ergebnis/composer-normalize/pull/10 1148 | [#18]: https://github.com/ergebnis/composer-normalize/pull/18 1149 | [#19]: https://github.com/ergebnis/composer-normalize/pull/19 1150 | [#28]: https://github.com/ergebnis/composer-normalize/pull/28 1151 | [#30]: https://github.com/ergebnis/composer-normalize/pull/30 1152 | [#38]: https://github.com/ergebnis/composer-normalize/pull/38 1153 | [#42]: https://github.com/ergebnis/composer-normalize/pull/42 1154 | [#51]: https://github.com/ergebnis/composer-normalize/pull/51 1155 | [#60]: https://github.com/ergebnis/composer-normalize/pull/60 1156 | [#62]: https://github.com/ergebnis/composer-normalize/pull/62 1157 | [#80]: https://github.com/ergebnis/composer-normalize/pull/80 1158 | [#86]: https://github.com/ergebnis/composer-normalize/pull/86 1159 | [#89]: https://github.com/ergebnis/composer-normalize/pull/89 1160 | [#94]: https://github.com/ergebnis/composer-normalize/pull/94 1161 | [#106]: https://github.com/ergebnis/composer-normalize/pull/106 1162 | [#139]: https://github.com/ergebnis/composer-normalize/pull/139 1163 | [#145]: https://github.com/ergebnis/composer-normalize/pull/145 1164 | [#157]: https://github.com/ergebnis/composer-normalize/pull/157 1165 | [#166]: https://github.com/ergebnis/composer-normalize/pull/166 1166 | [#173]: https://github.com/ergebnis/composer-normalize/pull/173 1167 | [#177]: https://github.com/ergebnis/composer-normalize/pull/177 1168 | [#190]: https://github.com/ergebnis/composer-normalize/pull/190 1169 | [#207]: https://github.com/ergebnis/composer-normalize/pull/207 1170 | [#235]: https://github.com/ergebnis/composer-normalize/pull/235 1171 | [#261]: https://github.com/ergebnis/composer-normalize/pull/261 1172 | [#262]: https://github.com/ergebnis/composer-normalize/pull/262 1173 | [#267]: https://github.com/ergebnis/composer-normalize/pull/267 1174 | [#270]: https://github.com/ergebnis/composer-normalize/pull/270 1175 | [#273]: https://github.com/ergebnis/composer-normalize/pull/273 1176 | [#280]: https://github.com/ergebnis/composer-normalize/pull/280 1177 | [#292]: https://github.com/ergebnis/composer-normalize/pull/292 1178 | [#297]: https://github.com/ergebnis/composer-normalize/pull/297 1179 | [#301]: https://github.com/ergebnis/composer-normalize/pull/301 1180 | [#303]: https://github.com/ergebnis/composer-normalize/pull/303 1181 | [#316]: https://github.com/ergebnis/composer-normalize/pull/316 1182 | [#322]: https://github.com/ergebnis/composer-normalize/pull/322 1183 | [#354]: https://github.com/ergebnis/composer-normalize/pull/354 1184 | [#364]: https://github.com/ergebnis/composer-normalize/pull/364 1185 | [#374]: https://github.com/ergebnis/composer-normalize/pull/374 1186 | [#379]: https://github.com/ergebnis/composer-normalize/pull/379 1187 | [#380]: https://github.com/ergebnis/composer-normalize/pull/380 1188 | [#406]: https://github.com/ergebnis/composer-normalize/pull/406 1189 | [#412]: https://github.com/ergebnis/composer-normalize/pull/412 1190 | [#416]: https://github.com/ergebnis/composer-normalize/pull/416 1191 | [#420]: https://github.com/ergebnis/composer-normalize/pull/420 1192 | [#422]: https://github.com/ergebnis/composer-normalize/pull/422 1193 | [#424]: https://github.com/ergebnis/composer-normalize/pull/424 1194 | [#465]: https://github.com/ergebnis/composer-normalize/pull/465 1195 | [#481]: https://github.com/ergebnis/composer-normalize/pull/481 1196 | [#484]: https://github.com/ergebnis/composer-normalize/pull/484 1197 | [#485]: https://github.com/ergebnis/composer-normalize/pull/485 1198 | [#487]: https://github.com/ergebnis/composer-normalize/pull/487 1199 | [#512]: https://github.com/ergebnis/composer-normalize/pull/512 1200 | [#515]: https://github.com/ergebnis/composer-normalize/pull/515 1201 | [#526]: https://github.com/ergebnis/composer-normalize/pull/526 1202 | [#529]: https://github.com/ergebnis/composer-normalize/pull/529 1203 | [#554]: https://github.com/ergebnis/composer-normalize/pull/554 1204 | [#572]: https://github.com/ergebnis/composer-normalize/pull/572 1205 | [#582]: https://github.com/ergebnis/composer-normalize/pull/582 1206 | [#596]: https://github.com/ergebnis/composer-normalize/pull/596 1207 | [#597]: https://github.com/ergebnis/composer-normalize/pull/597 1208 | [#608]: https://github.com/ergebnis/composer-normalize/pull/608 1209 | [#615]: https://github.com/ergebnis/composer-normalize/pull/615 1210 | [#634]: https://github.com/ergebnis/composer-normalize/pull/634 1211 | [#640]: https://github.com/ergebnis/composer-normalize/pull/640 1212 | [#641]: https://github.com/ergebnis/composer-normalize/pull/641 1213 | [#643]: https://github.com/ergebnis/composer-normalize/pull/643 1214 | [#644]: https://github.com/ergebnis/composer-normalize/pull/644 1215 | [#646]: https://github.com/ergebnis/composer-normalize/pull/646 1216 | [#647]: https://github.com/ergebnis/composer-normalize/pull/647 1217 | [#707]: https://github.com/ergebnis/composer-normalize/pull/707 1218 | [#743]: https://github.com/ergebnis/composer-normalize/pull/743 1219 | [#744]: https://github.com/ergebnis/composer-normalize/pull/744 1220 | [#750]: https://github.com/ergebnis/composer-normalize/pull/750 1221 | [#754]: https://github.com/ergebnis/composer-normalize/pull/754 1222 | [#804]: https://github.com/ergebnis/composer-normalize/pull/804 1223 | [#807]: https://github.com/ergebnis/composer-normalize/pull/807 1224 | [#816]: https://github.com/ergebnis/composer-normalize/pull/816 1225 | [#825]: https://github.com/ergebnis/composer-normalize/pull/825 1226 | [#827]: https://github.com/ergebnis/composer-normalize/pull/827 1227 | [#829]: https://github.com/ergebnis/composer-normalize/pull/829 1228 | [#842]: https://github.com/ergebnis/composer-normalize/pull/842 1229 | [#845]: https://github.com/ergebnis/composer-normalize/pull/845 1230 | [#852]: https://github.com/ergebnis/composer-normalize/pull/852 1231 | [#858]: https://github.com/ergebnis/composer-normalize/pull/858 1232 | [#863]: https://github.com/ergebnis/composer-normalize/pull/863 1233 | [#864]: https://github.com/ergebnis/composer-normalize/pull/864 1234 | [#871]: https://github.com/ergebnis/composer-normalize/pull/871 1235 | [#875]: https://github.com/ergebnis/composer-normalize/pull/875 1236 | [#877]: https://github.com/ergebnis/composer-normalize/pull/877 1237 | [#899]: https://github.com/ergebnis/composer-normalize/pull/899 1238 | [#904]: https://github.com/ergebnis/composer-normalize/pull/904 1239 | [#905]: https://github.com/ergebnis/composer-normalize/pull/905 1240 | [#912]: https://github.com/ergebnis/composer-normalize/pull/912 1241 | [#913]: https://github.com/ergebnis/composer-normalize/pull/913 1242 | [#915]: https://github.com/ergebnis/composer-normalize/pull/915 1243 | [#916]: https://github.com/ergebnis/composer-normalize/pull/916 1244 | [#920]: https://github.com/ergebnis/composer-normalize/pull/920 1245 | [#922]: https://github.com/ergebnis/composer-normalize/pull/922 1246 | [#923]: https://github.com/ergebnis/composer-normalize/pull/923 1247 | [#930]: https://github.com/ergebnis/composer-normalize/pull/930 1248 | [#933]: https://github.com/ergebnis/composer-normalize/pull/933 1249 | [#938]: https://github.com/ergebnis/composer-normalize/pull/938 1250 | [#941]: https://github.com/ergebnis/composer-normalize/pull/941 1251 | [#942]: https://github.com/ergebnis/composer-normalize/pull/942 1252 | [#959]: https://github.com/ergebnis/composer-normalize/pull/959 1253 | [#998]: https://github.com/ergebnis/composer-normalize/pull/998 1254 | [#1004]: https://github.com/ergebnis/composer-normalize/pull/1004 1255 | [#1008]: https://github.com/ergebnis/composer-normalize/pull/1008 1256 | [#1020]: https://github.com/ergebnis/composer-normalize/pull/1020 1257 | [#1056]: https://github.com/ergebnis/composer-normalize/pull/1056 1258 | [#1060]: https://github.com/ergebnis/composer-normalize/pull/1060 1259 | [#1062]: https://github.com/ergebnis/composer-normalize/pull/1062 1260 | [#1070]: https://github.com/ergebnis/composer-normalize/pull/1070 1261 | [#1094]: https://github.com/ergebnis/composer-normalize/pull/1094 1262 | [#1095]: https://github.com/ergebnis/composer-normalize/pull/1095 1263 | [#1118]: https://github.com/ergebnis/composer-normalize/pull/1118 1264 | [#1125]: https://github.com/ergebnis/composer-normalize/pull/1125 1265 | [#1127]: https://github.com/ergebnis/composer-normalize/pull/1127 1266 | [#1136]: https://github.com/ergebnis/composer-normalize/pull/1136 1267 | [#1141]: https://github.com/ergebnis/composer-normalize/pull/1141 1268 | [#1155]: https://github.com/ergebnis/composer-normalize/pull/1155 1269 | [#1158]: https://github.com/ergebnis/composer-normalize/pull/1158 1270 | [#1170]: https://github.com/ergebnis/composer-normalize/pull/1170 1271 | [#1171]: https://github.com/ergebnis/composer-normalize/pull/1171 1272 | [#1188]: https://github.com/ergebnis/composer-normalize/pull/1188 1273 | [#1189]: https://github.com/ergebnis/composer-normalize/pull/1189 1274 | [#1191]: https://github.com/ergebnis/composer-normalize/pull/1191 1275 | [#1192]: https://github.com/ergebnis/composer-normalize/pull/1192 1276 | [#1195]: https://github.com/ergebnis/composer-normalize/pull/1195 1277 | [#1204]: https://github.com/ergebnis/composer-normalize/pull/1204 1278 | [#1234]: https://github.com/ergebnis/composer-normalize/pull/1234 1279 | [#1237]: https://github.com/ergebnis/composer-normalize/pull/1237 1280 | [#1241]: https://github.com/ergebnis/composer-normalize/pull/1241 1281 | [#1243]: https://github.com/ergebnis/composer-normalize/pull/1243 1282 | [#1273]: https://github.com/ergebnis/composer-normalize/pull/1273 1283 | [#1275]: https://github.com/ergebnis/composer-normalize/pull/1275 1284 | [#1277]: https://github.com/ergebnis/composer-normalize/pull/1277 1285 | [#1278]: https://github.com/ergebnis/composer-normalize/pull/1278 1286 | [#1279]: https://github.com/ergebnis/composer-normalize/pull/1279 1287 | [#1312]: https://github.com/ergebnis/composer-normalize/pull/1312 1288 | [#1349]: https://github.com/ergebnis/composer-normalize/pull/1349 1289 | [#1363]: https://github.com/ergebnis/composer-normalize/pull/1363 1290 | [#1377]: https://github.com/ergebnis/composer-normalize/pull/1377 1291 | [#1381]: https://github.com/ergebnis/composer-normalize/pull/1381 1292 | [#1405]: https://github.com/ergebnis/composer-normalize/pull/1405 1293 | [#1410]: https://github.com/ergebnis/composer-normalize/pull/1410 1294 | [#1416]: https://github.com/ergebnis/composer-normalize/pull/1416 1295 | [#1419]: https://github.com/ergebnis/composer-normalize/pull/1419 1296 | [#1440]: https://github.com/ergebnis/composer-normalize/pull/1440 1297 | [#1441]: https://github.com/ergebnis/composer-normalize/pull/1441 1298 | 1299 | [@core23]: https://github.com/core23 1300 | [@dependabot]: https://github.com/dependabot 1301 | [@ergebnis-bot]: https://github.com/ergebnis-bot 1302 | [@ergebnis]: https://github.com/ergebnis 1303 | [@localheinz]: https://github.com/localheinz 1304 | [@mxr576]: https://github.com/mxr576 1305 | [@ruudk]: https://github.com/ruudk 1306 | [@svenluijten]: https://github.com/svenluijten 1307 | [@tacman]: https://github.com/tacman 1308 | [@TravisCarden]: https://github.com/TravisCarden 1309 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | 3 | Copyright (c) 2018-2025 Andreas Möller 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 6 | documentation files (the _Software_), to deal in the Software without restriction, including without limitation the 7 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit 8 | persons to whom the Software is furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the 11 | Software. 12 | 13 | THE SOFTWARE IS PROVIDED **AS IS**, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 14 | WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 15 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 16 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # composer-normalize 2 | 3 | [![Integrate](https://github.com/ergebnis/composer-normalize/workflows/Integrate/badge.svg)](https://github.com/ergebnis/composer-normalize/actions) 4 | [![Merge](https://github.com/ergebnis/composer-normalize/workflows/Merge/badge.svg)](https://github.com/ergebnis/composer-normalize/actions) 5 | [![Release](https://github.com/ergebnis/composer-normalize/workflows/Release/badge.svg)](https://github.com/ergebnis/composer-normalize/actions) 6 | [![Renew](https://github.com/ergebnis/composer-normalize/workflows/Renew/badge.svg)](https://github.com/ergebnis/composer-normalize/actions) 7 | [![Update](https://github.com/ergebnis/composer-normalize/workflows/Update/badge.svg)](https://github.com/ergebnis/composer-normalize/actions) 8 | 9 | [![Code Coverage](https://codecov.io/gh/ergebnis/composer-normalize/branch/main/graph/badge.svg)](https://codecov.io/gh/ergebnis/composer-normalize) 10 | 11 | [![Latest Stable Version](https://poser.pugx.org/ergebnis/composer-normalize/v/stable)](https://packagist.org/packages/ergebnis/composer-normalize) 12 | [![Total Downloads](https://poser.pugx.org/ergebnis/composer-normalize/downloads)](https://packagist.org/packages/ergebnis/composer-normalize) 13 | [![Monthly Downloads](http://poser.pugx.org/ergebnis/composer-normalize/d/monthly)](https://packagist.org/packages/ergebnis/composer-normalize) 14 | 15 | This project provides a [`composer`](https://getcomposer.org) plugin for normalizing [`composer.json`](https://getcomposer.org/doc/04-schema.md). 16 | 17 | [![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) 18 | 19 | ## Why 20 | 21 | When it comes to formatting `composer.json`, you have the following options: 22 | 23 | - you can format it manually (and request changes when contributors format it differently) 24 | - you can stop caring 25 | - or you can use `ergebnis/composer-normalize` 26 | 27 | `ergebnis/composer-normalize` normalizes `composer.json`, so you don't have to. 28 | 29 | :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/). 30 | 31 | ## Installation 32 | 33 | ### Composer 34 | 35 | Run 36 | 37 | ```sh 38 | composer require --dev ergebnis/composer-normalize 39 | ``` 40 | 41 | to install `ergebnis/composer-normalize` as a composer plugin. 42 | 43 | Run 44 | 45 | ```shell 46 | composer config allow-plugins.ergebnis/composer-normalize true 47 | ``` 48 | 49 | to allow `ergebnis/composer-normalize` to run as a composer plugin. 50 | 51 | :bulb: The `allow-plugins` has been added to `composer/composer` to add an extra layer of security. 52 | 53 | For reference, see 54 | 55 | - https://github.com/composer/composer/pull/10314 56 | - https://getcomposer.org/doc/06-config.md#allow-plugins 57 | 58 | ### Phar 59 | 60 | Head over to http://github.com/ergebnis/composer-normalize/releases/latest and download the latest `composer-normalize.phar`. 61 | 62 | Run 63 | 64 | ```sh 65 | chmod +x composer-normalize.phar 66 | ``` 67 | 68 | to make the downloaded `composer-normalize.phar` executable. 69 | 70 | ### Phive 71 | 72 | Run 73 | 74 | ```sh 75 | phive install ergebnis/composer-normalize 76 | ``` 77 | 78 | to install `ergebnis/composer-normalize` with [PHIVE](https://phar.io). 79 | 80 | ## Usage 81 | 82 | ### Composer 83 | 84 | Run 85 | 86 | ```sh 87 | composer normalize 88 | ``` 89 | 90 | to normalize `composer.json` in the working directory. 91 | 92 | ### Phar 93 | 94 | Run 95 | 96 | ```sh 97 | ./composer-normalize.phar 98 | ``` 99 | 100 | to normalize `composer.json` in the working directory. 101 | 102 | ### Phive 103 | 104 | Run 105 | 106 | ```sh 107 | ./tools/composer-normalize 108 | ``` 109 | 110 | to normalize `composer.json` in the working directory. 111 | 112 | ### Details 113 | 114 | The `NormalizeCommand` provided by the `NormalizePlugin` within this package will 115 | 116 | - determine whether a `composer.json` exists 117 | - determine whether a `composer.lock` exists, and if so, whether it is up to date (unless the `--no-check-lock` option is used) 118 | - use [`Ergebnis\Json\Normalizer\Vendor\Composer\ComposerJsonNormalizer`](https://github.com/ergebnis/json-normalizer#vendorcomposercomposerjsonnormalizer) to normalize the content of `composer.json` 119 | - format the normalized content (either as sniffed, or as specified using the `--indent-size` and `--indent-style` options) 120 | - write the normalized and formatted content of `composer.json` back to the file 121 | - update the hash in `composer.lock` if it exists and if an update is necessary 122 | 123 | ### Arguments 124 | 125 | - `file`: Path to `composer.json` file (optional, defaults to `composer.json` in working directory) 126 | 127 | ### Options 128 | 129 | - `--diff`: Show the results of normalizing 130 | - `--dry-run`: Show the results of normalizing, but do not modify any files 131 | - `--indent-size`: Indent size (an integer greater than 0); should be used with the `--indent-style` option 132 | - `--indent-style`: Indent style (one of "space", "tab"); should be used with the `--indent-size` option 133 | - `--no-check-lock`: Do not check if lock file is up to date 134 | - `--no-update-lock`: Do not update lock file if it exists 135 | 136 | 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`: 137 | 138 | ```json 139 | { 140 | "extra": { 141 | "composer-normalize": { 142 | "indent-size": 2, 143 | "indent-style": "space" 144 | } 145 | } 146 | } 147 | ``` 148 | 149 | :bulb: The configuration provided in composer extra always overrides the configuration provided via command line options. 150 | 151 | ### Continuous Integration 152 | 153 | If you want to run this in continuous integration services, use the `--dry-run` option. 154 | 155 | ```sh 156 | composer normalize --dry-run 157 | ``` 158 | 159 | In case `composer.json` is not normalized (or `composer.lock` is not up-to-date), the command will 160 | fail with an exit code of `1` and show a diff. 161 | 162 | ## Examples 163 | 164 | ### `pestphp/pest` 165 | 166 | Running 167 | 168 | ```sh 169 | composer normalize 170 | ``` 171 | 172 | against https://github.com/pestphp/pest/blob/v0.3.19/composer.json yields the following diff: 173 | 174 | ```diff 175 | diff --git a/composer.json b/composer.json 176 | index 1cfbf1e..204f20f 100644 177 | --- a/composer.json 178 | +++ b/composer.json 179 | @@ -25,6 +25,32 @@ 180 | "pestphp/pest-plugin-init": "^0.3", 181 | "phpunit/phpunit": ">= 9.3.7 <= 9.5.0" 182 | }, 183 | + "require-dev": { 184 | + "illuminate/console": "^7.16.1", 185 | + "illuminate/support": "^7.16.1", 186 | + "laravel/dusk": "^6.9.1", 187 | + "mockery/mockery": "^1.4.1", 188 | + "pestphp/pest-dev-tools": "dev-master" 189 | + }, 190 | + "config": { 191 | + "preferred-install": "dist", 192 | + "sort-packages": true 193 | + }, 194 | + "extra": { 195 | + "branch-alias": { 196 | + "dev-master": "0.3.x-dev" 197 | + }, 198 | + "laravel": { 199 | + "providers": [ 200 | + "Pest\\Laravel\\PestServiceProvider" 201 | + ] 202 | + }, 203 | + "pest": { 204 | + "plugins": [ 205 | + "Pest\\Plugins\\Version" 206 | + ] 207 | + } 208 | + }, 209 | "autoload": { 210 | "psr-4": { 211 | "Pest\\": "src/" 212 | @@ -42,49 +68,23 @@ 213 | "tests/Autoload.php" 214 | ] 215 | }, 216 | - "require-dev": { 217 | - "illuminate/console": "^7.16.1", 218 | - "illuminate/support": "^7.16.1", 219 | - "laravel/dusk": "^6.9.1", 220 | - "mockery/mockery": "^1.4.1", 221 | - "pestphp/pest-dev-tools": "dev-master" 222 | - }, 223 | "minimum-stability": "dev", 224 | "prefer-stable": true, 225 | - "config": { 226 | - "sort-packages": true, 227 | - "preferred-install": "dist" 228 | - }, 229 | "bin": [ 230 | "bin/pest" 231 | ], 232 | "scripts": { 233 | "lint": "php-cs-fixer fix -v", 234 | - "test:lint": "php-cs-fixer fix -v --dry-run", 235 | - "test:types": "phpstan analyse --ansi --memory-limit=0", 236 | - "test:unit": "php bin/pest --colors=always --exclude-group=integration", 237 | - "test:integration": "php bin/pest --colors=always --group=integration", 238 | - "update:snapshots": "REBUILD_SNAPSHOTS=true php bin/pest --colors=always", 239 | "test": [ 240 | "@test:lint", 241 | "@test:types", 242 | "@test:unit", 243 | "@test:integration" 244 | - ] 245 | - }, 246 | - "extra": { 247 | - "branch-alias": { 248 | - "dev-master": "0.3.x-dev" 249 | - }, 250 | - "pest": { 251 | - "plugins": [ 252 | - "Pest\\Plugins\\Version" 253 | - ] 254 | - }, 255 | - "laravel": { 256 | - "providers": [ 257 | - "Pest\\Laravel\\PestServiceProvider" 258 | - ] 259 | - } 260 | + ], 261 | + "test:integration": "php bin/pest --colors=always --group=integration", 262 | + "test:lint": "php-cs-fixer fix -v --dry-run", 263 | + "test:types": "phpstan analyse --ansi --memory-limit=0", 264 | + "test:unit": "php bin/pest --colors=always --exclude-group=integration", 265 | + "update:snapshots": "REBUILD_SNAPSHOTS=true php bin/pest --colors=always" 266 | } 267 | } 268 | ``` 269 | 270 | ### `phpspec/phpspec` 271 | 272 | Running 273 | 274 | ```sh 275 | composer normalize 276 | ``` 277 | 278 | against https://github.com/phpspec/phpspec/blob/7.0.1/composer.json yields the following diff: 279 | 280 | ```diff 281 | diff --git a/composer.json b/composer.json 282 | index 90150a37..276a2ecd 100644 283 | --- a/composer.json 284 | +++ b/composer.json 285 | @@ -1,72 +1,73 @@ 286 | { 287 | - "name": "phpspec/phpspec", 288 | - "description": "Specification-oriented BDD framework for PHP 7.1+", 289 | - "keywords": ["BDD", "SpecBDD", "TDD", "spec", "specification", "tests", "testing"], 290 | - "homepage": "http://phpspec.net/", 291 | - "type": "library", 292 | - "license": "MIT", 293 | - "authors": [ 294 | + "name": "phpspec/phpspec", 295 | + "type": "library", 296 | + "description": "Specification-oriented BDD framework for PHP 7.1+", 297 | + "keywords": [ 298 | + "BDD", 299 | + "SpecBDD", 300 | + "TDD", 301 | + "spec", 302 | + "specification", 303 | + "tests", 304 | + "testing" 305 | + ], 306 | + "homepage": "http://phpspec.net/", 307 | + "license": "MIT", 308 | + "authors": [ 309 | { 310 | - "name": "Konstantin Kudryashov", 311 | - "email": "ever.zet@gmail.com", 312 | - "homepage": "http://everzet.com" 313 | + "name": "Konstantin Kudryashov", 314 | + "email": "ever.zet@gmail.com", 315 | + "homepage": "http://everzet.com" 316 | }, 317 | { 318 | - "name": "Marcello Duarte", 319 | - "homepage": "http://marcelloduarte.net/" 320 | + "name": "Marcello Duarte", 321 | + "homepage": "http://marcelloduarte.net/" 322 | }, 323 | { 324 | - "name": "Ciaran McNulty", 325 | - "homepage": "https://ciaranmcnulty.com/" 326 | + "name": "Ciaran McNulty", 327 | + "homepage": "https://ciaranmcnulty.com/" 328 | } 329 | ], 330 | - 331 | "require": { 332 | - "php": "^7.3 || 8.0.*", 333 | - "phpspec/prophecy": "^1.9", 334 | - "phpspec/php-diff": "^1.0.0", 335 | - "sebastian/exporter": "^3.0 || ^4.0", 336 | - "symfony/console": "^3.4 || ^4.4 || ^5.0", 337 | + "php": "^7.3 || 8.0.*", 338 | + "ext-tokenizer": "*", 339 | + "doctrine/instantiator": "^1.0.5", 340 | + "phpspec/php-diff": "^1.0.0", 341 | + "phpspec/prophecy": "^1.9", 342 | + "sebastian/exporter": "^3.0 || ^4.0", 343 | + "symfony/console": "^3.4 || ^4.4 || ^5.0", 344 | "symfony/event-dispatcher": "^3.4 || ^4.4 || ^5.0", 345 | - "symfony/process": "^3.4 || ^4.4 || ^5.0", 346 | - "symfony/finder": "^3.4 || ^4.4 || ^5.0", 347 | - "symfony/yaml": "^3.4 || ^4.4 || ^5.0", 348 | - "doctrine/instantiator": "^1.0.5", 349 | - "ext-tokenizer": "*" 350 | + "symfony/finder": "^3.4 || ^4.4 || ^5.0", 351 | + "symfony/process": "^3.4 || ^4.4 || ^5.0", 352 | + "symfony/yaml": "^3.4 || ^4.4 || ^5.0" 353 | + }, 354 | + "conflict": { 355 | + "sebastian/comparator": "<1.2.4" 356 | }, 357 | - 358 | "require-dev": { 359 | - "behat/behat": "^3.3", 360 | - "symfony/filesystem": "^3.4 || ^4.0 || ^5.0", 361 | - "phpunit/phpunit": "^8.0 || ^9.0" 362 | + "behat/behat": "^3.3", 363 | + "phpunit/phpunit": "^8.0 || ^9.0", 364 | + "symfony/filesystem": "^3.4 || ^4.0 || ^5.0" 365 | }, 366 | - 367 | "suggest": { 368 | "phpspec/nyan-formatters": "Adds Nyan formatters" 369 | }, 370 | - 371 | - "conflict": { 372 | - "sebastian/comparator" : "<1.2.4" 373 | + "extra": { 374 | + "branch-alias": { 375 | + "dev-main": "7.0.x-dev" 376 | + } 377 | }, 378 | - 379 | "autoload": { 380 | "psr-0": { 381 | "PhpSpec": "src/" 382 | } 383 | }, 384 | - 385 | "autoload-dev": { 386 | "psr-0": { 387 | "spec\\PhpSpec": "." 388 | } 389 | }, 390 | - 391 | - "bin": ["bin/phpspec"], 392 | - 393 | - "extra": { 394 | - "branch-alias": { 395 | - "dev-main": "7.0.x-dev" 396 | - } 397 | - } 398 | - 399 | + "bin": [ 400 | + "bin/phpspec" 401 | + ] 402 | } 403 | ``` 404 | 405 | ### `phpunit/phpunit` 406 | 407 | Running 408 | 409 | ```sh 410 | composer normalize 411 | ``` 412 | 413 | against https://github.com/sebastianbergmann/phpunit/blob/9.5.0/composer.json yields the following diff: 414 | 415 | ```diff 416 | diff --git a/composer.json b/composer.json 417 | index fd6461fc3..23c3a3596 100644 418 | --- a/composer.json 419 | +++ b/composer.json 420 | @@ -1,7 +1,7 @@ 421 | { 422 | "name": "phpunit/phpunit", 423 | - "description": "The PHP Unit Testing framework.", 424 | "type": "library", 425 | + "description": "The PHP Unit Testing framework.", 426 | "keywords": [ 427 | "phpunit", 428 | "xunit", 429 | @@ -16,10 +16,6 @@ 430 | "role": "lead" 431 | } 432 | ], 433 | - "support": { 434 | - "issues": "https://github.com/sebastianbergmann/phpunit/issues" 435 | - }, 436 | - "prefer-stable": true, 437 | "require": { 438 | "php": ">=7.3", 439 | "ext-dom": "*", 440 | @@ -54,20 +50,22 @@ 441 | "ext-PDO": "*", 442 | "phpspec/prophecy-phpunit": "^2.0.1" 443 | }, 444 | + "suggest": { 445 | + "ext-soap": "*", 446 | + "ext-xdebug": "*" 447 | + }, 448 | "config": { 449 | + "optimize-autoloader": true, 450 | "platform": { 451 | "php": "7.3.0" 452 | }, 453 | - "optimize-autoloader": true, 454 | "sort-packages": true 455 | }, 456 | - "suggest": { 457 | - "ext-soap": "*", 458 | - "ext-xdebug": "*" 459 | + "extra": { 460 | + "branch-alias": { 461 | + "dev-master": "9.5-dev" 462 | + } 463 | }, 464 | - "bin": [ 465 | - "phpunit" 466 | - ], 467 | "autoload": { 468 | "classmap": [ 469 | "src/" 470 | @@ -86,9 +84,11 @@ 471 | "tests/_files/NamespaceCoveredFunction.php" 472 | ] 473 | }, 474 | - "extra": { 475 | - "branch-alias": { 476 | - "dev-master": "9.5-dev" 477 | - } 478 | + "prefer-stable": true, 479 | + "bin": [ 480 | + "phpunit" 481 | + ], 482 | + "support": { 483 | + "issues": "https://github.com/sebastianbergmann/phpunit/issues" 484 | } 485 | } 486 | ``` 487 | 488 | ## Changelog 489 | 490 | The maintainers of this project record notable changes to this project in a [changelog](CHANGELOG.md). 491 | 492 | ## Contributing 493 | 494 | The maintainers of this project suggest following the [contribution guide](.github/CONTRIBUTING.md). 495 | 496 | ## Code of Conduct 497 | 498 | The maintainers of this project ask contributors to follow the [code of conduct](https://github.com/ergebnis/.github/blob/main/CODE_OF_CONDUCT.md). 499 | 500 | ## General Support Policy 501 | 502 | The maintainers of this project provide limited support. 503 | 504 | You can support the maintenance of this project by [sponsoring @localheinz](https://github.com/sponsors/localheinz) or [requesting an invoice for services related to this project](mailto:am@localheinz.com?subject=ergebnis/composer-normalize:%20Requesting%20invoice%20for%20services). 505 | 506 | ## PHP Version Support Policy 507 | 508 | This project supports PHP versions with [active and security support](https://www.php.net/supported-versions.php). 509 | 510 | The maintainers of this project add support for a PHP version following its initial release and drop support for a PHP version when it has reached the end of security support. 511 | 512 | ## Security Policy 513 | 514 | This project has a [security policy](.github/SECURITY.md). 515 | 516 | ## License 517 | 518 | This project uses the [MIT license](LICENSE.md). 519 | 520 | ## Social 521 | 522 | Follow [@localheinz](https://twitter.com/intent/follow?screen_name=localheinz) and [@ergebnis](https://twitter.com/intent/follow?screen_name=ergebnis) on Twitter. 523 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ergebnis/composer-normalize", 3 | "description": "Provides a composer plugin for normalizing composer.json.", 4 | "license": "MIT", 5 | "type": "composer-plugin", 6 | "keywords": [ 7 | "composer", 8 | "normalizer", 9 | "normalize", 10 | "plugin" 11 | ], 12 | "authors": [ 13 | { 14 | "name": "Andreas Möller", 15 | "email": "am@localheinz.com", 16 | "homepage": "https://localheinz.com" 17 | } 18 | ], 19 | "homepage": "https://github.com/ergebnis/composer-normalize", 20 | "support": { 21 | "issues": "https://github.com/ergebnis/composer-normalize/issues", 22 | "source": "https://github.com/ergebnis/composer-normalize", 23 | "security": "https://github.com/ergebnis/composer-normalize/blob/main/.github/SECURITY.md" 24 | }, 25 | "require": { 26 | "php": "~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0", 27 | "ext-json": "*", 28 | "composer-plugin-api": "^2.0.0", 29 | "ergebnis/json": "^1.4.0", 30 | "ergebnis/json-normalizer": "^4.9.0", 31 | "ergebnis/json-printer": "^3.7.0", 32 | "justinrainbow/json-schema": "^5.2.12 || ^6.0.0", 33 | "localheinz/diff": "^1.2.0" 34 | }, 35 | "require-dev": { 36 | "composer/composer": "^2.8.3", 37 | "ergebnis/license": "^2.6.0", 38 | "ergebnis/php-cs-fixer-config": "^6.46.0", 39 | "ergebnis/phpstan-rules": "^2.10.2", 40 | "ergebnis/phpunit-slow-test-detector": "^2.19.1", 41 | "fakerphp/faker": "^1.24.1", 42 | "infection/infection": "~0.26.6", 43 | "phpstan/extension-installer": "^1.4.3", 44 | "phpstan/phpstan": "^2.1.17", 45 | "phpstan/phpstan-deprecation-rules": "^2.0.3", 46 | "phpstan/phpstan-phpunit": "^2.0.6", 47 | "phpstan/phpstan-strict-rules": "^2.0.4", 48 | "phpunit/phpunit": "^9.6.20", 49 | "rector/rector": "^2.0.17", 50 | "symfony/filesystem": "^5.4.41" 51 | }, 52 | "minimum-stability": "dev", 53 | "prefer-stable": true, 54 | "autoload": { 55 | "psr-4": { 56 | "Ergebnis\\Composer\\Normalize\\": "src/" 57 | } 58 | }, 59 | "autoload-dev": { 60 | "psr-4": { 61 | "Ergebnis\\Composer\\Normalize\\Test\\": "test/" 62 | } 63 | }, 64 | "config": { 65 | "allow-plugins": { 66 | "composer/package-versions-deprecated": true, 67 | "infection/extension-installer": true, 68 | "phpstan/extension-installer": true 69 | }, 70 | "audit": { 71 | "abandoned": "report" 72 | }, 73 | "platform": { 74 | "php": "7.4.33" 75 | }, 76 | "preferred-install": "dist", 77 | "sort-packages": true 78 | }, 79 | "extra": { 80 | "branch-alias": { 81 | "dev-main": "2.44-dev" 82 | }, 83 | "class": "Ergebnis\\Composer\\Normalize\\NormalizePlugin", 84 | "composer-normalize": { 85 | "indent-size": 2, 86 | "indent-style": "space" 87 | }, 88 | "plugin-optional": true 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /resource/schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json-schema.org/draft-04/schema#", 3 | "title": "Composer Package", 4 | "type": "object", 5 | "properties": { 6 | "name": { 7 | "type": "string", 8 | "description": "Package name, including 'vendor-name/' prefix.", 9 | "pattern": "^[a-z0-9]([_.-]?[a-z0-9]+)*/[a-z0-9](([_.]|-{1,2})?[a-z0-9]+)*$" 10 | }, 11 | "description": { 12 | "type": "string", 13 | "description": "Short package description." 14 | }, 15 | "license": { 16 | "type": [ 17 | "string", 18 | "array" 19 | ], 20 | "description": "License name. Or an array of license names." 21 | }, 22 | "type": { 23 | "description": "Package type, either 'library' for common packages, 'composer-plugin' for plugins, 'metapackage' for empty packages, or a custom type ([a-z0-9-]+) defined by whatever project this package applies to.", 24 | "type": "string", 25 | "pattern": "^[a-z0-9-]+$" 26 | }, 27 | "abandoned": { 28 | "type": [ 29 | "boolean", 30 | "string" 31 | ], 32 | "description": "Indicates whether this package has been abandoned, it can be boolean or a package name/URL pointing to a recommended alternative. Defaults to false." 33 | }, 34 | "version": { 35 | "type": "string", 36 | "description": "Package version, see https://getcomposer.org/doc/04-schema.md#version for more info on valid schemes.", 37 | "pattern": "^[vV]?\\d+(?:[.-]\\d+){0,3}[._-]?(?:(?:[sS][tT][aA][bB][lL][eE]|[bB][eE][tT][aA]|[bB]|[rR][cC]|[aA][lL][pP][hH][aA]|[aA]|[pP][aA][tT][cC][hH]|[pP][lL]|[pP])(?:(?:[.-]?\\d+)*+)?)?(?:[.-]?[dD][eE][vV]|\\.x-dev)?(?:\\+.*)?$|^dev-.*$" 38 | }, 39 | "default-branch": { 40 | "type": [ 41 | "boolean" 42 | ], 43 | "description": "Internal use only, do not specify this in composer.json. Indicates whether this version is the default branch of the linked VCS repository. Defaults to false." 44 | }, 45 | "non-feature-branches": { 46 | "type": [ 47 | "array" 48 | ], 49 | "description": "A set of string or regex patterns for non-numeric branch names that will not be handled as feature branches.", 50 | "items": { 51 | "type": "string" 52 | } 53 | }, 54 | "keywords": { 55 | "type": "array", 56 | "items": { 57 | "type": "string", 58 | "description": "A tag/keyword that this package relates to." 59 | } 60 | }, 61 | "readme": { 62 | "type": "string", 63 | "description": "Relative path to the readme document." 64 | }, 65 | "time": { 66 | "type": "string", 67 | "description": "Package release date, in 'YYYY-MM-DD', 'YYYY-MM-DD HH:MM:SS' or 'YYYY-MM-DDTHH:MM:SSZ' format." 68 | }, 69 | "authors": { 70 | "$ref": "#/definitions/authors" 71 | }, 72 | "homepage": { 73 | "type": "string", 74 | "description": "Homepage URL for the project.", 75 | "format": "uri" 76 | }, 77 | "support": { 78 | "type": "object", 79 | "properties": { 80 | "email": { 81 | "type": "string", 82 | "description": "Email address for support.", 83 | "format": "email" 84 | }, 85 | "issues": { 86 | "type": "string", 87 | "description": "URL to the issue tracker.", 88 | "format": "uri" 89 | }, 90 | "forum": { 91 | "type": "string", 92 | "description": "URL to the forum.", 93 | "format": "uri" 94 | }, 95 | "wiki": { 96 | "type": "string", 97 | "description": "URL to the wiki.", 98 | "format": "uri" 99 | }, 100 | "irc": { 101 | "type": "string", 102 | "description": "IRC channel for support, as irc://server/channel.", 103 | "format": "uri" 104 | }, 105 | "chat": { 106 | "type": "string", 107 | "description": "URL to the support chat.", 108 | "format": "uri" 109 | }, 110 | "source": { 111 | "type": "string", 112 | "description": "URL to browse or download the sources.", 113 | "format": "uri" 114 | }, 115 | "docs": { 116 | "type": "string", 117 | "description": "URL to the documentation.", 118 | "format": "uri" 119 | }, 120 | "rss": { 121 | "type": "string", 122 | "description": "URL to the RSS feed.", 123 | "format": "uri" 124 | }, 125 | "security": { 126 | "type": "string", 127 | "description": "URL to the vulnerability disclosure policy (VDP).", 128 | "format": "uri" 129 | } 130 | } 131 | }, 132 | "funding": { 133 | "type": "array", 134 | "description": "A list of options to fund the development and maintenance of the package.", 135 | "items": { 136 | "type": "object", 137 | "properties": { 138 | "type": { 139 | "type": "string", 140 | "description": "Type of funding or platform through which funding is possible." 141 | }, 142 | "url": { 143 | "type": "string", 144 | "description": "URL to a website with details on funding and a way to fund the package.", 145 | "format": "uri" 146 | } 147 | } 148 | } 149 | }, 150 | "source": { 151 | "$ref": "#/definitions/source" 152 | }, 153 | "dist": { 154 | "$ref": "#/definitions/dist" 155 | }, 156 | "_comment": { 157 | "type": [ 158 | "array", 159 | "string" 160 | ], 161 | "description": "A key to store comments in" 162 | }, 163 | "require": { 164 | "type": "object", 165 | "description": "This is an object of package name (keys) and version constraints (values) that are required to run this package.", 166 | "additionalProperties": { 167 | "type": "string" 168 | } 169 | }, 170 | "require-dev": { 171 | "type": "object", 172 | "description": "This is an object of package name (keys) and version constraints (values) that this package requires for developing it (testing tools and such).", 173 | "additionalProperties": { 174 | "type": "string" 175 | } 176 | }, 177 | "replace": { 178 | "type": "object", 179 | "description": "This is an object of package name (keys) and version constraints (values) that can be replaced by this package.", 180 | "additionalProperties": { 181 | "type": "string" 182 | } 183 | }, 184 | "conflict": { 185 | "type": "object", 186 | "description": "This is an object of package name (keys) and version constraints (values) that conflict with this package.", 187 | "additionalProperties": { 188 | "type": "string" 189 | } 190 | }, 191 | "provide": { 192 | "type": "object", 193 | "description": "This is an object of package name (keys) and version constraints (values) that this package provides in addition to this package's name.", 194 | "additionalProperties": { 195 | "type": "string" 196 | } 197 | }, 198 | "suggest": { 199 | "type": "object", 200 | "description": "This is an object of package name (keys) and descriptions (values) that this package suggests work well with it (this will be suggested to the user during installation).", 201 | "additionalProperties": { 202 | "type": "string" 203 | } 204 | }, 205 | "repositories": { 206 | "type": [ 207 | "object", 208 | "array" 209 | ], 210 | "description": "A set of additional repositories where packages can be found.", 211 | "additionalProperties": { 212 | "anyOf": [ 213 | { 214 | "$ref": "#/definitions/repository" 215 | }, 216 | { 217 | "type": "boolean", 218 | "enum": [ 219 | false 220 | ] 221 | } 222 | ] 223 | }, 224 | "items": { 225 | "anyOf": [ 226 | { 227 | "$ref": "#/definitions/repository" 228 | }, 229 | { 230 | "type": "object", 231 | "additionalProperties": { 232 | "type": "boolean", 233 | "enum": [ 234 | false 235 | ] 236 | }, 237 | "minProperties": 1, 238 | "maxProperties": 1 239 | } 240 | ] 241 | } 242 | }, 243 | "minimum-stability": { 244 | "type": [ 245 | "string" 246 | ], 247 | "description": "The minimum stability the packages must have to be install-able. Possible values are: dev, alpha, beta, RC, stable.", 248 | "enum": [ 249 | "dev", 250 | "alpha", 251 | "beta", 252 | "rc", 253 | "RC", 254 | "stable" 255 | ] 256 | }, 257 | "prefer-stable": { 258 | "type": [ 259 | "boolean" 260 | ], 261 | "description": "If set to true, stable packages will be preferred to dev packages when possible, even if the minimum-stability allows unstable packages." 262 | }, 263 | "autoload": { 264 | "$ref": "#/definitions/autoload" 265 | }, 266 | "autoload-dev": { 267 | "type": "object", 268 | "description": "Description of additional autoload rules for development purpose (eg. a test suite).", 269 | "properties": { 270 | "psr-0": { 271 | "type": "object", 272 | "description": "This is an object of namespaces (keys) and the directories they can be found into (values, can be arrays of paths) by the autoloader.", 273 | "additionalProperties": { 274 | "type": [ 275 | "string", 276 | "array" 277 | ], 278 | "items": { 279 | "type": "string" 280 | } 281 | } 282 | }, 283 | "psr-4": { 284 | "type": "object", 285 | "description": "This is an object of namespaces (keys) and the PSR-4 directories they can map to (values, can be arrays of paths) by the autoloader.", 286 | "additionalProperties": { 287 | "type": [ 288 | "string", 289 | "array" 290 | ], 291 | "items": { 292 | "type": "string" 293 | } 294 | } 295 | }, 296 | "classmap": { 297 | "type": "array", 298 | "description": "This is an array of paths that contain classes to be included in the class-map generation process." 299 | }, 300 | "files": { 301 | "type": "array", 302 | "description": "This is an array of files that are always required on every request." 303 | } 304 | } 305 | }, 306 | "target-dir": { 307 | "description": "DEPRECATED: Forces the package to be installed into the given subdirectory path. This is used for autoloading PSR-0 packages that do not contain their full path. Use forward slashes for cross-platform compatibility.", 308 | "type": "string" 309 | }, 310 | "include-path": { 311 | "type": [ 312 | "array" 313 | ], 314 | "description": "DEPRECATED: A list of directories which should get added to PHP's include path. This is only present to support legacy projects, and all new code should preferably use autoloading.", 315 | "items": { 316 | "type": "string" 317 | } 318 | }, 319 | "bin": { 320 | "type": [ 321 | "string", 322 | "array" 323 | ], 324 | "description": "A set of files, or a single file, that should be treated as binaries and symlinked into bin-dir (from config).", 325 | "items": { 326 | "type": "string" 327 | } 328 | }, 329 | "archive": { 330 | "type": [ 331 | "object" 332 | ], 333 | "description": "Options for creating package archives for distribution.", 334 | "properties": { 335 | "name": { 336 | "type": "string", 337 | "description": "A base name for archive." 338 | }, 339 | "exclude": { 340 | "type": "array", 341 | "description": "A list of patterns for paths to exclude or include if prefixed with an exclamation mark." 342 | } 343 | } 344 | }, 345 | "php-ext": { 346 | "type": "object", 347 | "description": "Settings for PHP extension packages.", 348 | "properties": { 349 | "extension-name": { 350 | "type": "string", 351 | "description": "If specified, this will be used as the name of the extension, where needed by tooling. If this is not specified, the extension name will be derived from the Composer package name (e.g. `vendor/name` would become `ext-name`). The extension name may be specified with or without the `ext-` prefix, and tools that use this must normalise this appropriately.", 352 | "example": "ext-xdebug" 353 | }, 354 | "priority": { 355 | "type": "integer", 356 | "description": "This is used to add a prefix to the INI file, e.g. `90-xdebug.ini` which affects the loading order. The priority is a number in the range 10-99 inclusive, with 10 being the highest priority (i.e. will be processed first), and 99 being the lowest priority (i.e. will be processed last). There are two digits so that the files sort correctly on any platform, whether the sorting is natural or not.", 357 | "minimum": 10, 358 | "maximum": 99, 359 | "example": 80, 360 | "default": 80 361 | }, 362 | "support-zts": { 363 | "type": "boolean", 364 | "description": "Does this package support Zend Thread Safety", 365 | "example": false, 366 | "default": true 367 | }, 368 | "support-nts": { 369 | "type": "boolean", 370 | "description": "Does this package support non-Thread Safe mode", 371 | "example": false, 372 | "default": true 373 | }, 374 | "build-path": { 375 | "type": [ 376 | "string", 377 | "null" 378 | ], 379 | "description": "If specified, this is the subdirectory that will be used to build the extension instead of the root of the project.", 380 | "example": "my-extension-source", 381 | "default": null 382 | }, 383 | "download-url-method": { 384 | "type": "string", 385 | "description": "If specified, this technique will be used to override the URL that PIE uses to download the asset. The default, if not specified, is composer-default.", 386 | "enum": [ 387 | "composer-default", 388 | "pre-packaged-source" 389 | ], 390 | "example": "composer-default" 391 | }, 392 | "os-families": { 393 | "type": "array", 394 | "minItems": 1, 395 | "description": "An array of OS families to mark as compatible with the extension. Specifying this property will mean this package is not installable with PIE on any OS family not listed here. Must not be specified alongside os-families-exclude.", 396 | "items": { 397 | "type": "string", 398 | "enum": [ 399 | "windows", 400 | "bsd", 401 | "darwin", 402 | "solaris", 403 | "linux", 404 | "unknown" 405 | ], 406 | "description": "The name of the OS family to mark as compatible." 407 | } 408 | }, 409 | "os-families-exclude": { 410 | "type": "array", 411 | "minItems": 1, 412 | "description": "An array of OS families to mark as incompatible with the extension. Specifying this property will mean this package is installable on any OS family except those listed here. Must not be specified alongside os-families.", 413 | "items": { 414 | "type": "string", 415 | "enum": [ 416 | "windows", 417 | "bsd", 418 | "darwin", 419 | "solaris", 420 | "linux", 421 | "unknown" 422 | ], 423 | "description": "The name of the OS family to exclude." 424 | } 425 | }, 426 | "configure-options": { 427 | "type": "array", 428 | "description": "These configure options make up the flags that can be passed to ./configure when installing the extension.", 429 | "items": { 430 | "type": "object", 431 | "required": [ 432 | "name" 433 | ], 434 | "properties": { 435 | "name": { 436 | "type": "string", 437 | "description": "The name of the flag, this would typically be prefixed with `--`, for example, the value 'the-flag' would be passed as `./configure --the-flag`.", 438 | "example": "without-xdebug-compression", 439 | "pattern": "^[a-zA-Z0-9][a-zA-Z0-9-_]*$" 440 | }, 441 | "needs-value": { 442 | "type": "boolean", 443 | "description": "If this is set to true, the flag needs a value (e.g. --with-somelib=), otherwise it is a flag without a value (e.g. --enable-some-feature).", 444 | "example": false, 445 | "default": false 446 | }, 447 | "description": { 448 | "type": "string", 449 | "description": "The description of what the flag does or means.", 450 | "example": "Disable compression through zlib" 451 | } 452 | } 453 | } 454 | } 455 | }, 456 | "allOf": [ 457 | { 458 | "not": { 459 | "required": [ 460 | "os-families", 461 | "os-families-exclude" 462 | ] 463 | } 464 | } 465 | ] 466 | }, 467 | "config": { 468 | "type": "object", 469 | "description": "Composer options.", 470 | "properties": { 471 | "platform": { 472 | "type": "object", 473 | "description": "This is an object of package name (keys) and version (values) that will be used to mock the platform packages on this machine, the version can be set to false to make it appear like the package is not present.", 474 | "additionalProperties": { 475 | "type": [ 476 | "string", 477 | "boolean" 478 | ] 479 | } 480 | }, 481 | "allow-plugins": { 482 | "type": [ 483 | "object", 484 | "boolean" 485 | ], 486 | "description": "This is an object of {\"pattern\": true|false} with packages which are allowed to be loaded as plugins, or true to allow all, false to allow none. Defaults to {} which prompts when an unknown plugin is added.", 487 | "additionalProperties": { 488 | "type": [ 489 | "boolean" 490 | ] 491 | } 492 | }, 493 | "process-timeout": { 494 | "type": "integer", 495 | "description": "The timeout in seconds for process executions, defaults to 300 (5mins)." 496 | }, 497 | "use-include-path": { 498 | "type": "boolean", 499 | "description": "If true, the Composer autoloader will also look for classes in the PHP include path." 500 | }, 501 | "use-parent-dir": { 502 | "type": [ 503 | "string", 504 | "boolean" 505 | ], 506 | "description": "When running Composer in a directory where there is no composer.json, if there is one present in a directory above Composer will by default ask you whether you want to use that directory's composer.json instead. One of: true (always use parent if needed), false (never ask or use it) or \"prompt\" (ask every time), defaults to prompt." 507 | }, 508 | "preferred-install": { 509 | "type": [ 510 | "string", 511 | "object" 512 | ], 513 | "description": "The install method Composer will prefer to use, defaults to auto and can be any of source, dist, auto, or an object of {\"pattern\": \"preference\"}.", 514 | "additionalProperties": { 515 | "type": [ 516 | "string" 517 | ] 518 | } 519 | }, 520 | "audit": { 521 | "type": "object", 522 | "description": "Security audit configuration options", 523 | "properties": { 524 | "ignore": { 525 | "anyOf": [ 526 | { 527 | "type": "object", 528 | "description": "A list of advisory ids, remote ids or CVE ids (keys) and the explanations (values) for why they're being ignored. The listed items are reported but let the audit command pass.", 529 | "additionalProperties": { 530 | "type": [ 531 | "string", 532 | "string" 533 | ] 534 | } 535 | }, 536 | { 537 | "type": "array", 538 | "description": "A set of advisory ids, remote ids or CVE ids that are reported but let the audit command pass.", 539 | "items": { 540 | "type": "string" 541 | } 542 | } 543 | ] 544 | }, 545 | "abandoned": { 546 | "enum": [ 547 | "ignore", 548 | "report", 549 | "fail" 550 | ], 551 | "description": "Whether abandoned packages should be ignored, reported as problems or cause an audit failure." 552 | } 553 | } 554 | }, 555 | "notify-on-install": { 556 | "type": "boolean", 557 | "description": "Composer allows repositories to define a notification URL, so that they get notified whenever a package from that repository is installed. This option allows you to disable that behaviour, defaults to true." 558 | }, 559 | "github-protocols": { 560 | "type": "array", 561 | "description": "A list of protocols to use for github.com clones, in priority order, defaults to [\"https\", \"ssh\", \"git\"].", 562 | "items": { 563 | "type": "string" 564 | } 565 | }, 566 | "github-oauth": { 567 | "type": "object", 568 | "description": "An object of domain name => github API oauth tokens, typically {\"github.com\":\"\"}.", 569 | "additionalProperties": { 570 | "type": "string" 571 | } 572 | }, 573 | "gitlab-oauth": { 574 | "type": "object", 575 | "description": "An object of domain name => gitlab API oauth tokens, typically {\"gitlab.com\":{\"expires-at\":\"\", \"refresh-token\":\"\", \"token\":\"\"}}.", 576 | "additionalProperties": { 577 | "type": [ 578 | "string", 579 | "object" 580 | ], 581 | "required": [ 582 | "token" 583 | ], 584 | "properties": { 585 | "expires-at": { 586 | "type": "integer", 587 | "description": "The expiration date for this GitLab token" 588 | }, 589 | "refresh-token": { 590 | "type": "string", 591 | "description": "The refresh token used for GitLab authentication" 592 | }, 593 | "token": { 594 | "type": "string", 595 | "description": "The token used for GitLab authentication" 596 | } 597 | } 598 | } 599 | }, 600 | "gitlab-token": { 601 | "type": "object", 602 | "description": "An object of domain name => gitlab private tokens, typically {\"gitlab.com\":\"\"}, or an object with username and token keys.", 603 | "additionalProperties": { 604 | "type": [ 605 | "string", 606 | "object" 607 | ], 608 | "required": [ 609 | "username", 610 | "token" 611 | ], 612 | "properties": { 613 | "username": { 614 | "type": "string", 615 | "description": "The username used for GitLab authentication" 616 | }, 617 | "token": { 618 | "type": "string", 619 | "description": "The token used for GitLab authentication" 620 | } 621 | } 622 | } 623 | }, 624 | "gitlab-protocol": { 625 | "enum": [ 626 | "git", 627 | "http", 628 | "https" 629 | ], 630 | "description": "A protocol to force use of when creating a repository URL for the `source` value of the package metadata. One of `git` or `http`. By default, Composer will generate a git URL for private repositories and http one for public repos." 631 | }, 632 | "bearer": { 633 | "type": "object", 634 | "description": "An object of domain name => bearer authentication token, for example {\"example.com\":\"\"}.", 635 | "additionalProperties": { 636 | "type": "string" 637 | } 638 | }, 639 | "disable-tls": { 640 | "type": "boolean", 641 | "description": "Defaults to `false`. If set to true all HTTPS URLs will be tried with HTTP instead and no network level encryption is performed. Enabling this is a security risk and is NOT recommended. The better way is to enable the php_openssl extension in php.ini." 642 | }, 643 | "secure-http": { 644 | "type": "boolean", 645 | "description": "Defaults to `true`. If set to true only HTTPS URLs are allowed to be downloaded via Composer. If you really absolutely need HTTP access to something then you can disable it, but using \"Let's Encrypt\" to get a free SSL certificate is generally a better alternative." 646 | }, 647 | "secure-svn-domains": { 648 | "type": "array", 649 | "description": "A list of domains which should be trusted/marked as using a secure Subversion/SVN transport. By default svn:// protocol is seen as insecure and will throw. This is a better/safer alternative to disabling `secure-http` altogether.", 650 | "items": { 651 | "type": "string" 652 | } 653 | }, 654 | "cafile": { 655 | "type": "string", 656 | "description": "A way to set the path to the openssl CA file. In PHP 5.6+ you should rather set this via openssl.cafile in php.ini, although PHP 5.6+ should be able to detect your system CA file automatically." 657 | }, 658 | "capath": { 659 | "type": "string", 660 | "description": "If cafile is not specified or if the certificate is not found there, the directory pointed to by capath is searched for a suitable certificate. capath must be a correctly hashed certificate directory." 661 | }, 662 | "http-basic": { 663 | "type": "object", 664 | "description": "An object of domain name => {\"username\": \"...\", \"password\": \"...\"}.", 665 | "additionalProperties": { 666 | "type": "object", 667 | "required": [ 668 | "username", 669 | "password" 670 | ], 671 | "properties": { 672 | "username": { 673 | "type": "string", 674 | "description": "The username used for HTTP Basic authentication" 675 | }, 676 | "password": { 677 | "type": "string", 678 | "description": "The password used for HTTP Basic authentication" 679 | } 680 | } 681 | } 682 | }, 683 | "store-auths": { 684 | "type": [ 685 | "string", 686 | "boolean" 687 | ], 688 | "description": "What to do after prompting for authentication, one of: true (store), false (do not store) or \"prompt\" (ask every time), defaults to prompt." 689 | }, 690 | "vendor-dir": { 691 | "type": "string", 692 | "description": "The location where all packages are installed, defaults to \"vendor\"." 693 | }, 694 | "bin-dir": { 695 | "type": "string", 696 | "description": "The location where all binaries are linked, defaults to \"vendor/bin\"." 697 | }, 698 | "data-dir": { 699 | "type": "string", 700 | "description": "The location where old phar files are stored, defaults to \"$home\" except on XDG Base Directory compliant unixes." 701 | }, 702 | "cache-dir": { 703 | "type": "string", 704 | "description": "The location where all caches are located, defaults to \"~/.composer/cache\" on *nix and \"%LOCALAPPDATA%\\Composer\" on windows." 705 | }, 706 | "cache-files-dir": { 707 | "type": "string", 708 | "description": "The location where files (zip downloads) are cached, defaults to \"{$cache-dir}/files\"." 709 | }, 710 | "cache-repo-dir": { 711 | "type": "string", 712 | "description": "The location where repo (git/hg repo clones) are cached, defaults to \"{$cache-dir}/repo\"." 713 | }, 714 | "cache-vcs-dir": { 715 | "type": "string", 716 | "description": "The location where vcs infos (git clones, github api calls, etc. when reading vcs repos) are cached, defaults to \"{$cache-dir}/vcs\"." 717 | }, 718 | "cache-ttl": { 719 | "type": "integer", 720 | "description": "The default cache time-to-live, defaults to 15552000 (6 months)." 721 | }, 722 | "cache-files-ttl": { 723 | "type": "integer", 724 | "description": "The cache time-to-live for files, defaults to the value of cache-ttl." 725 | }, 726 | "cache-files-maxsize": { 727 | "type": [ 728 | "string", 729 | "integer" 730 | ], 731 | "description": "The cache max size for the files cache, defaults to \"300MiB\"." 732 | }, 733 | "cache-read-only": { 734 | "type": [ 735 | "boolean" 736 | ], 737 | "description": "Whether to use the Composer cache in read-only mode." 738 | }, 739 | "bin-compat": { 740 | "enum": [ 741 | "auto", 742 | "full", 743 | "proxy", 744 | "symlink" 745 | ], 746 | "description": "The compatibility of the binaries, defaults to \"auto\" (automatically guessed), can be \"full\" (compatible with both Windows and Unix-based systems) and \"proxy\" (only bash-style proxy)." 747 | }, 748 | "discard-changes": { 749 | "type": [ 750 | "string", 751 | "boolean" 752 | ], 753 | "description": "The default style of handling dirty updates, defaults to false and can be any of true, false or \"stash\"." 754 | }, 755 | "autoloader-suffix": { 756 | "type": "string", 757 | "description": "Optional string to be used as a suffix for the generated Composer autoloader. When null a random one will be generated." 758 | }, 759 | "optimize-autoloader": { 760 | "type": "boolean", 761 | "description": "Always optimize when dumping the autoloader." 762 | }, 763 | "prepend-autoloader": { 764 | "type": "boolean", 765 | "description": "If false, the composer autoloader will not be prepended to existing autoloaders, defaults to true." 766 | }, 767 | "classmap-authoritative": { 768 | "type": "boolean", 769 | "description": "If true, the composer autoloader will not scan the filesystem for classes that are not found in the class map, defaults to false." 770 | }, 771 | "apcu-autoloader": { 772 | "type": "boolean", 773 | "description": "If true, the Composer autoloader will check for APCu and use it to cache found/not-found classes when the extension is enabled, defaults to false." 774 | }, 775 | "github-domains": { 776 | "type": "array", 777 | "description": "A list of domains to use in github mode. This is used for GitHub Enterprise setups, defaults to [\"github.com\"].", 778 | "items": { 779 | "type": "string" 780 | } 781 | }, 782 | "github-expose-hostname": { 783 | "type": "boolean", 784 | "description": "Defaults to true. If set to false, the OAuth tokens created to access the github API will have a date instead of the machine hostname." 785 | }, 786 | "gitlab-domains": { 787 | "type": "array", 788 | "description": "A list of domains to use in gitlab mode. This is used for custom GitLab setups, defaults to [\"gitlab.com\"].", 789 | "items": { 790 | "type": "string" 791 | } 792 | }, 793 | "bitbucket-oauth": { 794 | "type": "object", 795 | "description": "An object of domain name => {\"consumer-key\": \"...\", \"consumer-secret\": \"...\"}.", 796 | "additionalProperties": { 797 | "type": "object", 798 | "required": [ 799 | "consumer-key", 800 | "consumer-secret" 801 | ], 802 | "properties": { 803 | "consumer-key": { 804 | "type": "string", 805 | "description": "The consumer-key used for OAuth authentication" 806 | }, 807 | "consumer-secret": { 808 | "type": "string", 809 | "description": "The consumer-secret used for OAuth authentication" 810 | }, 811 | "access-token": { 812 | "type": "string", 813 | "description": "The OAuth token retrieved from Bitbucket's API, this is written by Composer and you should not set it nor modify it." 814 | }, 815 | "access-token-expiration": { 816 | "type": "integer", 817 | "description": "The generated token's expiration timestamp, this is written by Composer and you should not set it nor modify it." 818 | } 819 | } 820 | } 821 | }, 822 | "use-github-api": { 823 | "type": "boolean", 824 | "description": "Defaults to true. If set to false, globally disables the use of the GitHub API for all GitHub repositories and clones the repository as it would for any other repository." 825 | }, 826 | "archive-format": { 827 | "type": "string", 828 | "description": "The default archiving format when not provided on cli, defaults to \"tar\"." 829 | }, 830 | "archive-dir": { 831 | "type": "string", 832 | "description": "The default archive path when not provided on cli, defaults to \".\"." 833 | }, 834 | "htaccess-protect": { 835 | "type": "boolean", 836 | "description": "Defaults to true. If set to false, Composer will not create .htaccess files in the composer home, cache, and data directories." 837 | }, 838 | "sort-packages": { 839 | "type": "boolean", 840 | "description": "Defaults to false. If set to true, Composer will sort packages when adding/updating a new dependency." 841 | }, 842 | "lock": { 843 | "type": "boolean", 844 | "description": "Defaults to true. If set to false, Composer will not create a composer.lock file." 845 | }, 846 | "platform-check": { 847 | "type": [ 848 | "boolean", 849 | "string" 850 | ], 851 | "description": "Defaults to \"php-only\" which checks only the PHP version. Setting to true will also check the presence of required PHP extensions. If set to false, Composer will not create and require a platform_check.php file as part of the autoloader bootstrap." 852 | }, 853 | "bump-after-update": { 854 | "type": [ 855 | "string", 856 | "boolean" 857 | ], 858 | "description": "Defaults to false and can be any of true, false, \"dev\"` or \"no-dev\"`. If set to true, Composer will run the bump command after running the update command. If set to \"dev\" or \"no-dev\" then only the corresponding dependencies will be bumped." 859 | }, 860 | "allow-missing-requirements": { 861 | "type": [ 862 | "boolean" 863 | ], 864 | "description": "Defaults to false. If set to true, Composer will allow install when lock file is not up to date with the latest changes in composer.json." 865 | } 866 | } 867 | }, 868 | "extra": { 869 | "type": [ 870 | "object", 871 | "array" 872 | ], 873 | "description": "Arbitrary extra data that can be used by plugins, for example, package of type composer-plugin may have a 'class' key defining an installer class name.", 874 | "additionalProperties": true 875 | }, 876 | "scripts": { 877 | "type": [ 878 | "object" 879 | ], 880 | "description": "Script listeners that will be executed before/after some events.", 881 | "properties": { 882 | "pre-install-cmd": { 883 | "type": [ 884 | "array", 885 | "string" 886 | ], 887 | "description": "Occurs before the install command is executed, contains one or more Class::method callables or shell commands." 888 | }, 889 | "post-install-cmd": { 890 | "type": [ 891 | "array", 892 | "string" 893 | ], 894 | "description": "Occurs after the install command is executed, contains one or more Class::method callables or shell commands." 895 | }, 896 | "pre-update-cmd": { 897 | "type": [ 898 | "array", 899 | "string" 900 | ], 901 | "description": "Occurs before the update command is executed, contains one or more Class::method callables or shell commands." 902 | }, 903 | "post-update-cmd": { 904 | "type": [ 905 | "array", 906 | "string" 907 | ], 908 | "description": "Occurs after the update command is executed, contains one or more Class::method callables or shell commands." 909 | }, 910 | "pre-status-cmd": { 911 | "type": [ 912 | "array", 913 | "string" 914 | ], 915 | "description": "Occurs before the status command is executed, contains one or more Class::method callables or shell commands." 916 | }, 917 | "post-status-cmd": { 918 | "type": [ 919 | "array", 920 | "string" 921 | ], 922 | "description": "Occurs after the status command is executed, contains one or more Class::method callables or shell commands." 923 | }, 924 | "pre-package-install": { 925 | "type": [ 926 | "array", 927 | "string" 928 | ], 929 | "description": "Occurs before a package is installed, contains one or more Class::method callables or shell commands." 930 | }, 931 | "post-package-install": { 932 | "type": [ 933 | "array", 934 | "string" 935 | ], 936 | "description": "Occurs after a package is installed, contains one or more Class::method callables or shell commands." 937 | }, 938 | "pre-package-update": { 939 | "type": [ 940 | "array", 941 | "string" 942 | ], 943 | "description": "Occurs before a package is updated, contains one or more Class::method callables or shell commands." 944 | }, 945 | "post-package-update": { 946 | "type": [ 947 | "array", 948 | "string" 949 | ], 950 | "description": "Occurs after a package is updated, contains one or more Class::method callables or shell commands." 951 | }, 952 | "pre-package-uninstall": { 953 | "type": [ 954 | "array", 955 | "string" 956 | ], 957 | "description": "Occurs before a package has been uninstalled, contains one or more Class::method callables or shell commands." 958 | }, 959 | "post-package-uninstall": { 960 | "type": [ 961 | "array", 962 | "string" 963 | ], 964 | "description": "Occurs after a package has been uninstalled, contains one or more Class::method callables or shell commands." 965 | }, 966 | "pre-autoload-dump": { 967 | "type": [ 968 | "array", 969 | "string" 970 | ], 971 | "description": "Occurs before the autoloader is dumped, contains one or more Class::method callables or shell commands." 972 | }, 973 | "post-autoload-dump": { 974 | "type": [ 975 | "array", 976 | "string" 977 | ], 978 | "description": "Occurs after the autoloader is dumped, contains one or more Class::method callables or shell commands." 979 | }, 980 | "post-root-package-install": { 981 | "type": [ 982 | "array", 983 | "string" 984 | ], 985 | "description": "Occurs after the root-package is installed, contains one or more Class::method callables or shell commands." 986 | }, 987 | "post-create-project-cmd": { 988 | "type": [ 989 | "array", 990 | "string" 991 | ], 992 | "description": "Occurs after the create-project command is executed, contains one or more Class::method callables or shell commands." 993 | } 994 | } 995 | }, 996 | "scripts-descriptions": { 997 | "type": [ 998 | "object" 999 | ], 1000 | "description": "Descriptions for custom commands, shown in console help.", 1001 | "additionalProperties": { 1002 | "type": "string" 1003 | } 1004 | }, 1005 | "scripts-aliases": { 1006 | "type": [ 1007 | "object" 1008 | ], 1009 | "description": "Aliases for custom commands.", 1010 | "additionalProperties": { 1011 | "type": "array" 1012 | } 1013 | } 1014 | }, 1015 | "definitions": { 1016 | "authors": { 1017 | "type": "array", 1018 | "description": "List of authors that contributed to the package. This is typically the main maintainers, not the full list.", 1019 | "items": { 1020 | "type": "object", 1021 | "additionalProperties": false, 1022 | "required": [ 1023 | "name" 1024 | ], 1025 | "properties": { 1026 | "name": { 1027 | "type": "string", 1028 | "description": "Full name of the author." 1029 | }, 1030 | "email": { 1031 | "type": "string", 1032 | "description": "Email address of the author.", 1033 | "format": "email" 1034 | }, 1035 | "homepage": { 1036 | "type": "string", 1037 | "description": "Homepage URL for the author.", 1038 | "format": "uri" 1039 | }, 1040 | "role": { 1041 | "type": "string", 1042 | "description": "Author's role in the project." 1043 | } 1044 | } 1045 | } 1046 | }, 1047 | "autoload": { 1048 | "type": "object", 1049 | "description": "Description of how the package can be autoloaded.", 1050 | "properties": { 1051 | "psr-0": { 1052 | "type": "object", 1053 | "description": "This is an object of namespaces (keys) and the directories they can be found in (values, can be arrays of paths) by the autoloader.", 1054 | "additionalProperties": { 1055 | "type": [ 1056 | "string", 1057 | "array" 1058 | ], 1059 | "items": { 1060 | "type": "string" 1061 | } 1062 | } 1063 | }, 1064 | "psr-4": { 1065 | "type": "object", 1066 | "description": "This is an object of namespaces (keys) and the PSR-4 directories they can map to (values, can be arrays of paths) by the autoloader.", 1067 | "additionalProperties": { 1068 | "type": [ 1069 | "string", 1070 | "array" 1071 | ], 1072 | "items": { 1073 | "type": "string" 1074 | } 1075 | } 1076 | }, 1077 | "classmap": { 1078 | "type": "array", 1079 | "description": "This is an array of paths that contain classes to be included in the class-map generation process." 1080 | }, 1081 | "files": { 1082 | "type": "array", 1083 | "description": "This is an array of files that are always required on every request." 1084 | }, 1085 | "exclude-from-classmap": { 1086 | "type": "array", 1087 | "description": "This is an array of patterns to exclude from autoload classmap generation. (e.g. \"exclude-from-classmap\": [\"/test/\", \"/tests/\", \"/Tests/\"]" 1088 | } 1089 | } 1090 | }, 1091 | "repository": { 1092 | "type": "object", 1093 | "anyOf": [ 1094 | { 1095 | "$ref": "#/definitions/composer-repository" 1096 | }, 1097 | { 1098 | "$ref": "#/definitions/vcs-repository" 1099 | }, 1100 | { 1101 | "$ref": "#/definitions/path-repository" 1102 | }, 1103 | { 1104 | "$ref": "#/definitions/artifact-repository" 1105 | }, 1106 | { 1107 | "$ref": "#/definitions/pear-repository" 1108 | }, 1109 | { 1110 | "$ref": "#/definitions/package-repository" 1111 | } 1112 | ] 1113 | }, 1114 | "composer-repository": { 1115 | "type": "object", 1116 | "required": [ 1117 | "type", 1118 | "url" 1119 | ], 1120 | "properties": { 1121 | "type": { 1122 | "type": "string", 1123 | "enum": [ 1124 | "composer" 1125 | ] 1126 | }, 1127 | "url": { 1128 | "type": "string" 1129 | }, 1130 | "canonical": { 1131 | "type": "boolean" 1132 | }, 1133 | "only": { 1134 | "type": "array", 1135 | "items": { 1136 | "type": "string" 1137 | } 1138 | }, 1139 | "exclude": { 1140 | "type": "array", 1141 | "items": { 1142 | "type": "string" 1143 | } 1144 | }, 1145 | "options": { 1146 | "type": "object", 1147 | "additionalProperties": true 1148 | }, 1149 | "allow_ssl_downgrade": { 1150 | "type": "boolean" 1151 | }, 1152 | "force-lazy-providers": { 1153 | "type": "boolean" 1154 | } 1155 | } 1156 | }, 1157 | "vcs-repository": { 1158 | "type": "object", 1159 | "required": [ 1160 | "type", 1161 | "url" 1162 | ], 1163 | "properties": { 1164 | "type": { 1165 | "type": "string", 1166 | "enum": [ 1167 | "vcs", 1168 | "github", 1169 | "git", 1170 | "gitlab", 1171 | "bitbucket", 1172 | "git-bitbucket", 1173 | "hg", 1174 | "fossil", 1175 | "perforce", 1176 | "svn" 1177 | ] 1178 | }, 1179 | "url": { 1180 | "type": "string" 1181 | }, 1182 | "canonical": { 1183 | "type": "boolean" 1184 | }, 1185 | "only": { 1186 | "type": "array", 1187 | "items": { 1188 | "type": "string" 1189 | } 1190 | }, 1191 | "exclude": { 1192 | "type": "array", 1193 | "items": { 1194 | "type": "string" 1195 | } 1196 | }, 1197 | "no-api": { 1198 | "type": "boolean" 1199 | }, 1200 | "secure-http": { 1201 | "type": "boolean" 1202 | }, 1203 | "svn-cache-credentials": { 1204 | "type": "boolean" 1205 | }, 1206 | "trunk-path": { 1207 | "type": [ 1208 | "string", 1209 | "boolean" 1210 | ] 1211 | }, 1212 | "branches-path": { 1213 | "type": [ 1214 | "string", 1215 | "boolean" 1216 | ] 1217 | }, 1218 | "tags-path": { 1219 | "type": [ 1220 | "string", 1221 | "boolean" 1222 | ] 1223 | }, 1224 | "package-path": { 1225 | "type": "string" 1226 | }, 1227 | "depot": { 1228 | "type": "string" 1229 | }, 1230 | "branch": { 1231 | "type": "string" 1232 | }, 1233 | "unique_perforce_client_name": { 1234 | "type": "string" 1235 | }, 1236 | "p4user": { 1237 | "type": "string" 1238 | }, 1239 | "p4password": { 1240 | "type": "string" 1241 | } 1242 | } 1243 | }, 1244 | "path-repository": { 1245 | "type": "object", 1246 | "required": [ 1247 | "type", 1248 | "url" 1249 | ], 1250 | "properties": { 1251 | "type": { 1252 | "type": "string", 1253 | "enum": [ 1254 | "path" 1255 | ] 1256 | }, 1257 | "url": { 1258 | "type": "string" 1259 | }, 1260 | "canonical": { 1261 | "type": "boolean" 1262 | }, 1263 | "only": { 1264 | "type": "array", 1265 | "items": { 1266 | "type": "string" 1267 | } 1268 | }, 1269 | "exclude": { 1270 | "type": "array", 1271 | "items": { 1272 | "type": "string" 1273 | } 1274 | }, 1275 | "options": { 1276 | "type": "object", 1277 | "properties": { 1278 | "reference": { 1279 | "type": [ 1280 | "string" 1281 | ], 1282 | "enum": [ 1283 | "none", 1284 | "config", 1285 | "auto" 1286 | ] 1287 | }, 1288 | "symlink": { 1289 | "type": [ 1290 | "boolean", 1291 | "null" 1292 | ] 1293 | }, 1294 | "relative": { 1295 | "type": [ 1296 | "boolean" 1297 | ] 1298 | }, 1299 | "versions": { 1300 | "type": "object", 1301 | "additionalProperties": { 1302 | "type": "string" 1303 | } 1304 | } 1305 | }, 1306 | "additionalProperties": true 1307 | } 1308 | } 1309 | }, 1310 | "artifact-repository": { 1311 | "type": "object", 1312 | "required": [ 1313 | "type", 1314 | "url" 1315 | ], 1316 | "properties": { 1317 | "type": { 1318 | "type": "string", 1319 | "enum": [ 1320 | "artifact" 1321 | ] 1322 | }, 1323 | "url": { 1324 | "type": "string" 1325 | }, 1326 | "canonical": { 1327 | "type": "boolean" 1328 | }, 1329 | "only": { 1330 | "type": "array", 1331 | "items": { 1332 | "type": "string" 1333 | } 1334 | }, 1335 | "exclude": { 1336 | "type": "array", 1337 | "items": { 1338 | "type": "string" 1339 | } 1340 | } 1341 | } 1342 | }, 1343 | "pear-repository": { 1344 | "type": "object", 1345 | "required": [ 1346 | "type", 1347 | "url" 1348 | ], 1349 | "properties": { 1350 | "type": { 1351 | "type": "string", 1352 | "enum": [ 1353 | "pear" 1354 | ] 1355 | }, 1356 | "url": { 1357 | "type": "string" 1358 | }, 1359 | "canonical": { 1360 | "type": "boolean" 1361 | }, 1362 | "only": { 1363 | "type": "array", 1364 | "items": { 1365 | "type": "string" 1366 | } 1367 | }, 1368 | "exclude": { 1369 | "type": "array", 1370 | "items": { 1371 | "type": "string" 1372 | } 1373 | }, 1374 | "vendor-alias": { 1375 | "type": "string" 1376 | } 1377 | } 1378 | }, 1379 | "package-repository": { 1380 | "type": "object", 1381 | "required": [ 1382 | "type", 1383 | "package" 1384 | ], 1385 | "properties": { 1386 | "type": { 1387 | "type": "string", 1388 | "enum": [ 1389 | "package" 1390 | ] 1391 | }, 1392 | "canonical": { 1393 | "type": "boolean" 1394 | }, 1395 | "only": { 1396 | "type": "array", 1397 | "items": { 1398 | "type": "string" 1399 | } 1400 | }, 1401 | "exclude": { 1402 | "type": "array", 1403 | "items": { 1404 | "type": "string" 1405 | } 1406 | }, 1407 | "package": { 1408 | "oneOf": [ 1409 | { 1410 | "$ref": "#/definitions/inline-package" 1411 | }, 1412 | { 1413 | "type": "array", 1414 | "items": { 1415 | "$ref": "#/definitions/inline-package" 1416 | } 1417 | } 1418 | ] 1419 | } 1420 | } 1421 | }, 1422 | "inline-package": { 1423 | "type": "object", 1424 | "required": [ 1425 | "name", 1426 | "version" 1427 | ], 1428 | "properties": { 1429 | "name": { 1430 | "type": "string", 1431 | "description": "Package name, including 'vendor-name/' prefix." 1432 | }, 1433 | "type": { 1434 | "type": "string" 1435 | }, 1436 | "target-dir": { 1437 | "description": "DEPRECATED: Forces the package to be installed into the given subdirectory path. This is used for autoloading PSR-0 packages that do not contain their full path. Use forward slashes for cross-platform compatibility.", 1438 | "type": "string" 1439 | }, 1440 | "description": { 1441 | "type": "string" 1442 | }, 1443 | "keywords": { 1444 | "type": "array", 1445 | "items": { 1446 | "type": "string" 1447 | } 1448 | }, 1449 | "homepage": { 1450 | "type": "string", 1451 | "format": "uri" 1452 | }, 1453 | "version": { 1454 | "type": "string" 1455 | }, 1456 | "time": { 1457 | "type": "string" 1458 | }, 1459 | "license": { 1460 | "type": [ 1461 | "string", 1462 | "array" 1463 | ] 1464 | }, 1465 | "authors": { 1466 | "$ref": "#/definitions/authors" 1467 | }, 1468 | "require": { 1469 | "type": "object", 1470 | "additionalProperties": { 1471 | "type": "string" 1472 | } 1473 | }, 1474 | "replace": { 1475 | "type": "object", 1476 | "additionalProperties": { 1477 | "type": "string" 1478 | } 1479 | }, 1480 | "conflict": { 1481 | "type": "object", 1482 | "additionalProperties": { 1483 | "type": "string" 1484 | } 1485 | }, 1486 | "provide": { 1487 | "type": "object", 1488 | "additionalProperties": { 1489 | "type": "string" 1490 | } 1491 | }, 1492 | "require-dev": { 1493 | "type": "object", 1494 | "additionalProperties": { 1495 | "type": "string" 1496 | } 1497 | }, 1498 | "suggest": { 1499 | "type": "object", 1500 | "additionalProperties": { 1501 | "type": "string" 1502 | } 1503 | }, 1504 | "extra": { 1505 | "type": [ 1506 | "object", 1507 | "array" 1508 | ], 1509 | "additionalProperties": true 1510 | }, 1511 | "autoload": { 1512 | "$ref": "#/definitions/autoload" 1513 | }, 1514 | "archive": { 1515 | "type": [ 1516 | "object" 1517 | ], 1518 | "properties": { 1519 | "exclude": { 1520 | "type": "array" 1521 | } 1522 | } 1523 | }, 1524 | "bin": { 1525 | "type": [ 1526 | "string", 1527 | "array" 1528 | ], 1529 | "description": "A set of files, or a single file, that should be treated as binaries and symlinked into bin-dir (from config).", 1530 | "items": { 1531 | "type": "string" 1532 | } 1533 | }, 1534 | "include-path": { 1535 | "type": [ 1536 | "array" 1537 | ], 1538 | "description": "DEPRECATED: A list of directories which should get added to PHP's include path. This is only present to support legacy projects, and all new code should preferably use autoloading.", 1539 | "items": { 1540 | "type": "string" 1541 | } 1542 | }, 1543 | "source": { 1544 | "$ref": "#/definitions/source" 1545 | }, 1546 | "dist": { 1547 | "$ref": "#/definitions/dist" 1548 | } 1549 | }, 1550 | "additionalProperties": true 1551 | }, 1552 | "source": { 1553 | "type": "object", 1554 | "required": [ 1555 | "type", 1556 | "url", 1557 | "reference" 1558 | ], 1559 | "properties": { 1560 | "type": { 1561 | "type": "string" 1562 | }, 1563 | "url": { 1564 | "type": "string" 1565 | }, 1566 | "reference": { 1567 | "type": "string" 1568 | }, 1569 | "mirrors": { 1570 | "type": "array" 1571 | } 1572 | } 1573 | }, 1574 | "dist": { 1575 | "type": "object", 1576 | "required": [ 1577 | "type", 1578 | "url" 1579 | ], 1580 | "properties": { 1581 | "type": { 1582 | "type": "string" 1583 | }, 1584 | "url": { 1585 | "type": "string" 1586 | }, 1587 | "reference": { 1588 | "type": "string" 1589 | }, 1590 | "shasum": { 1591 | "type": "string" 1592 | }, 1593 | "mirrors": { 1594 | "type": "array" 1595 | } 1596 | } 1597 | } 1598 | }, 1599 | "additionalProperties": true, 1600 | "required": [] 1601 | } -------------------------------------------------------------------------------- /src/Command/NormalizeCommand.php: -------------------------------------------------------------------------------- 1 | factory = $factory; 46 | $this->normalizer = $normalizer; 47 | $this->printer = $printer; 48 | $this->differ = $differ; 49 | 50 | parent::__construct('normalize'); 51 | } 52 | 53 | protected function configure(): void 54 | { 55 | $this->setDescription('Normalizes composer.json according to its JSON schema (https://getcomposer.org/schema.json).'); 56 | $this->setDefinition([ 57 | new Console\Input\InputArgument( 58 | 'file', 59 | Console\Input\InputArgument::OPTIONAL, 60 | 'Path to composer.json file', 61 | ), 62 | new Console\Input\InputOption( 63 | 'diff', 64 | null, 65 | Console\Input\InputOption::VALUE_NONE, 66 | 'Show the results of normalizing', 67 | ), 68 | new Console\Input\InputOption( 69 | 'dry-run', 70 | null, 71 | Console\Input\InputOption::VALUE_NONE, 72 | 'Show the results of normalizing, but do not modify any files', 73 | ), 74 | new Console\Input\InputOption( 75 | 'indent-size', 76 | null, 77 | Console\Input\InputOption::VALUE_REQUIRED, 78 | 'Indent size (an integer greater than 0); should be used with the --indent-style option', 79 | ), 80 | new Console\Input\InputOption( 81 | 'indent-style', 82 | null, 83 | Console\Input\InputOption::VALUE_REQUIRED, 84 | \sprintf( 85 | 'Indent style (one of "%s"); should be used with the --indent-size option', 86 | \implode('", "', \array_keys(Normalizer\Format\Indent::CHARACTERS)), 87 | ), 88 | ), 89 | new Console\Input\InputOption( 90 | 'no-check-lock', 91 | null, 92 | Console\Input\InputOption::VALUE_NONE, 93 | 'Do not check if lock file is up to date', 94 | ), 95 | new Console\Input\InputOption( 96 | 'no-update-lock', 97 | null, 98 | Console\Input\InputOption::VALUE_NONE, 99 | 'Do not update lock file if it exists', 100 | ), 101 | ]); 102 | } 103 | 104 | protected function execute( 105 | Console\Input\InputInterface $input, 106 | Console\Output\OutputInterface $output 107 | ): int { 108 | $io = $this->getIO(); 109 | 110 | $io->write([ 111 | \sprintf( 112 | 'Running %s.', 113 | Version::long(), 114 | ), 115 | '', 116 | ]); 117 | 118 | $indent = null; 119 | 120 | try { 121 | $indentFromInput = self::indentFromInput($input); 122 | } catch (\RuntimeException $exception) { 123 | $io->writeError(\sprintf( 124 | '%s', 125 | $exception->getMessage(), 126 | )); 127 | 128 | return 1; 129 | } 130 | 131 | if (null !== $indentFromInput) { 132 | $indent = $indentFromInput; 133 | } 134 | 135 | $composerFile = $input->getArgument('file'); 136 | 137 | if (!\is_string($composerFile)) { 138 | $composerFile = Factory::getComposerFile(); 139 | } 140 | 141 | $composer = $this->factory->createComposer( 142 | $io, 143 | $composerFile, 144 | ); 145 | 146 | if (!$composer instanceof Composer) { 147 | throw Exception\ShouldNotHappen::create(); 148 | } 149 | 150 | try { 151 | $indentFromExtra = self::indentFromExtra($composer->getPackage()->getExtra()); 152 | } catch (\RuntimeException $exception) { 153 | $io->writeError(\sprintf( 154 | '%s', 155 | $exception->getMessage(), 156 | )); 157 | 158 | return 1; 159 | } 160 | 161 | if (null !== $indentFromExtra) { 162 | $indent = $indentFromExtra; 163 | } 164 | 165 | if ( 166 | null !== $indentFromInput 167 | && null !== $indentFromExtra 168 | ) { 169 | $io->write('Configuration provided via options and composer extra. Using configuration from composer extra.'); 170 | } 171 | 172 | if ( 173 | false === $input->getOption('dry-run') 174 | && !\is_writable($composerFile) 175 | ) { 176 | $io->writeError(\sprintf( 177 | '%s is not writable.', 178 | $composerFile, 179 | )); 180 | 181 | return 1; 182 | } 183 | 184 | $locker = $composer->getLocker(); 185 | 186 | if ( 187 | false === $input->getOption('no-check-lock') 188 | && $locker->isLocked() 189 | && !$locker->isFresh() 190 | ) { 191 | $io->writeError('The lock file is not up to date with the latest changes in composer.json, it is recommended that you run `composer update --lock`.'); 192 | 193 | return 1; 194 | } 195 | 196 | /** @var string $encoded */ 197 | $encoded = \file_get_contents($composerFile); 198 | 199 | $json = Json::fromString($encoded); 200 | 201 | $format = Normalizer\Format\Format::fromJson($json); 202 | 203 | if (null !== $indent) { 204 | $format = $format->withIndent($indent); 205 | } 206 | 207 | $normalizer = new Normalizer\ChainNormalizer( 208 | $this->normalizer, 209 | new class($this->printer, $format) implements Normalizer\Normalizer { 210 | private Normalizer\Format\Format $format; 211 | private Printer\PrinterInterface $printer; 212 | 213 | public function __construct( 214 | Printer\PrinterInterface $printer, 215 | Normalizer\Format\Format $format 216 | ) { 217 | $this->printer = $printer; 218 | $this->format = $format; 219 | } 220 | 221 | public function normalize(Json $json): Json 222 | { 223 | $encoded = \json_encode( 224 | $json->decoded(), 225 | $this->format->jsonEncodeOptions()->toInt(), 226 | ); 227 | 228 | $printed = $this->printer->print( 229 | $encoded, 230 | $this->format->indent()->toString(), 231 | $this->format->newLine()->toString(), 232 | ); 233 | 234 | if (!$this->format->hasFinalNewLine()) { 235 | return Json::fromString($printed); 236 | } 237 | 238 | return Json::fromString($printed . $this->format->newLine()->toString()); 239 | } 240 | }, 241 | ); 242 | 243 | try { 244 | $normalized = $normalizer->normalize($json); 245 | } catch (Normalizer\Exception\OriginalInvalidAccordingToSchema $exception) { 246 | $io->writeError('Original composer.json does not match the expected JSON schema:'); 247 | 248 | self::showValidationErrors( 249 | $io, 250 | ...$exception->errors(), 251 | ); 252 | 253 | return 1; 254 | } catch (Normalizer\Exception\NormalizedInvalidAccordingToSchema $exception) { 255 | $io->writeError('Normalized composer.json does not match the expected JSON schema:'); 256 | 257 | self::showValidationErrors( 258 | $io, 259 | ...$exception->errors(), 260 | ); 261 | 262 | return 1; 263 | } catch (\RuntimeException $exception) { 264 | $io->writeError(\sprintf( 265 | '%s', 266 | $exception->getMessage(), 267 | )); 268 | 269 | return 1; 270 | } 271 | 272 | if ($json->encoded() === $normalized->encoded()) { 273 | $io->write(\sprintf( 274 | '%s is already normalized.', 275 | $composerFile, 276 | )); 277 | 278 | return 0; 279 | } 280 | 281 | if ( 282 | true === $input->getOption('diff') 283 | || true === $input->getOption('dry-run') 284 | ) { 285 | $io->writeError(\sprintf( 286 | '%s is not normalized.', 287 | $composerFile, 288 | )); 289 | 290 | $diff = $this->differ->diff( 291 | $json->encoded(), 292 | $normalized->encoded(), 293 | ); 294 | 295 | $io->write([ 296 | '', 297 | '---------- begin diff ----------', 298 | self::formatDiff($diff), 299 | '----------- end diff -----------', 300 | '', 301 | ]); 302 | } 303 | 304 | if (true === $input->getOption('dry-run')) { 305 | return 1; 306 | } 307 | 308 | \file_put_contents( 309 | $composerFile, 310 | $normalized->encoded(), 311 | ); 312 | 313 | $io->write(\sprintf( 314 | 'Successfully normalized %s.', 315 | $composerFile, 316 | )); 317 | 318 | if ( 319 | true === $input->getOption('no-update-lock') 320 | || !$locker->isLocked() 321 | ) { 322 | return 0; 323 | } 324 | 325 | $io->write('Updating lock file.'); 326 | 327 | $application = new Application(); 328 | 329 | $application->setAutoExit(false); 330 | 331 | return self::updateLockerInWorkingDirectory( 332 | $application, 333 | $input, 334 | $output, 335 | \dirname($composerFile), 336 | ); 337 | } 338 | 339 | /** 340 | * @throws \RuntimeException 341 | */ 342 | private static function indentFromInput(Console\Input\InputInterface $input): ?Normalizer\Format\Indent 343 | { 344 | /** @var null|string $indentSize */ 345 | $indentSize = $input->getOption('indent-size'); 346 | 347 | /** @var null|string $indentStyle */ 348 | $indentStyle = $input->getOption('indent-style'); 349 | 350 | if ( 351 | null === $indentSize 352 | && null === $indentStyle 353 | ) { 354 | return null; 355 | } 356 | 357 | if (null === $indentSize) { 358 | throw new \RuntimeException('When using the indent-style option, an indent size needs to be specified using the indent-size option.'); 359 | } 360 | 361 | if (null === $indentStyle) { 362 | throw new \RuntimeException(\sprintf( 363 | 'When using the indent-size option, an indent style (one of "%s") needs to be specified using the indent-style option.', 364 | \implode('", "', \array_keys(Normalizer\Format\Indent::CHARACTERS)), 365 | )); 366 | } 367 | 368 | if ( 369 | (string) (int) $indentSize !== $indentSize 370 | || 1 > $indentSize 371 | ) { 372 | throw new \RuntimeException(\sprintf( 373 | 'Indent size needs to be an integer greater than 0, but "%s" is not.', 374 | $indentSize, 375 | )); 376 | } 377 | 378 | if (!\array_key_exists($indentStyle, Normalizer\Format\Indent::CHARACTERS)) { 379 | throw new \RuntimeException(\sprintf( 380 | 'Indent style needs to be one of "%s", but "%s" is not.', 381 | \implode('", "', \array_keys(Normalizer\Format\Indent::CHARACTERS)), 382 | $indentStyle, 383 | )); 384 | } 385 | 386 | return Normalizer\Format\Indent::fromSizeAndStyle( 387 | (int) $indentSize, 388 | $indentStyle, 389 | ); 390 | } 391 | 392 | /** 393 | * @throws \RuntimeException 394 | */ 395 | private static function indentFromExtra(array $extra): ?Normalizer\Format\Indent 396 | { 397 | if (!\array_key_exists('composer-normalize', $extra)) { 398 | return null; 399 | } 400 | 401 | $configuration = $extra['composer-normalize']; 402 | 403 | $requiredKeys = [ 404 | 'indent-size', 405 | 'indent-style', 406 | ]; 407 | 408 | if (!\is_array($configuration)) { 409 | throw new \RuntimeException(\sprintf( 410 | 'Configuration in composer extra requires keys "%s" with corresponding values."', 411 | \implode('", "', $requiredKeys), 412 | )); 413 | } 414 | 415 | $missingKeys = \array_diff( 416 | $requiredKeys, 417 | \array_keys($configuration), 418 | ); 419 | 420 | if ([] !== $missingKeys) { 421 | throw new \RuntimeException(\sprintf( 422 | 'Configuration in composer extra requires keys "%s" with corresponding values."', 423 | \implode('", "', $requiredKeys), 424 | )); 425 | } 426 | 427 | $extraKeys = \array_diff( 428 | \array_keys($configuration), 429 | $requiredKeys, 430 | ); 431 | 432 | if ([] !== $extraKeys) { 433 | throw new \RuntimeException(\sprintf( 434 | 'Configuration in composer extra does not allow extra keys "%s"."', 435 | \implode('", "', $extraKeys), 436 | )); 437 | } 438 | 439 | $indentSize = $configuration['indent-size']; 440 | 441 | if (!\is_int($indentSize)) { 442 | throw new \RuntimeException(\sprintf( 443 | 'Indent size needs to be an integer, got %s instead.', 444 | \gettype($indentSize), 445 | )); 446 | } 447 | 448 | if (1 > $indentSize) { 449 | throw new \RuntimeException(\sprintf( 450 | 'Indent size needs to be an integer greater than 0, but %d is not.', 451 | $indentSize, 452 | )); 453 | } 454 | 455 | $indentStyle = $configuration['indent-style']; 456 | 457 | if (!\is_string($indentStyle)) { 458 | throw new \RuntimeException(\sprintf( 459 | 'Indent style needs to be a string, got %s instead.', 460 | \gettype($indentStyle), 461 | )); 462 | } 463 | 464 | if (!\array_key_exists($indentStyle, Normalizer\Format\Indent::CHARACTERS)) { 465 | throw new \RuntimeException(\sprintf( 466 | 'Indent style needs to be one of "%s", but "%s" is not.', 467 | \implode('", "', \array_keys(Normalizer\Format\Indent::CHARACTERS)), 468 | $indentStyle, 469 | )); 470 | } 471 | 472 | return Normalizer\Format\Indent::fromSizeAndStyle( 473 | $indentSize, 474 | $indentStyle, 475 | ); 476 | } 477 | 478 | private static function showValidationErrors( 479 | IO\IOInterface $io, 480 | string ...$errors 481 | ): void { 482 | foreach ($errors as $error) { 483 | $io->writeError(\sprintf( 484 | '- %s', 485 | $error, 486 | )); 487 | } 488 | 489 | $io->writeError('See https://getcomposer.org/doc/04-schema.md for details on the schema'); 490 | } 491 | 492 | private static function formatDiff(string $diff): string 493 | { 494 | $lines = \explode( 495 | "\n", 496 | $diff, 497 | ); 498 | 499 | $formatted = \array_map(static function (string $line): string { 500 | $replaced = \preg_replace( 501 | [ 502 | '/^(\+.*)$/', 503 | '/^(-.*)$/', 504 | ], 505 | [ 506 | '$1', 507 | '$1', 508 | ], 509 | $line, 510 | ); 511 | 512 | if (!\is_string($replaced)) { 513 | throw Exception\ShouldNotHappen::create(); 514 | } 515 | 516 | return $replaced; 517 | }, $lines); 518 | 519 | return \implode( 520 | "\n", 521 | $formatted, 522 | ); 523 | } 524 | 525 | /** 526 | * @see https://getcomposer.org/doc/03-cli.md#update 527 | * 528 | * @throws \Exception 529 | */ 530 | private static function updateLockerInWorkingDirectory( 531 | Console\Application $application, 532 | Console\Input\InputInterface $input, 533 | Console\Output\OutputInterface $output, 534 | string $workingDirectory 535 | ): int { 536 | $parameters = [ 537 | 'command' => 'update', 538 | '--ignore-platform-reqs' => true, 539 | '--lock' => true, 540 | '--no-autoloader' => true, 541 | '--working-dir' => $workingDirectory, 542 | ]; 543 | 544 | if ($input->hasParameterOption('--no-ansi')) { 545 | $parameters[] = '--no-ansi'; 546 | } 547 | 548 | if ($input->hasParameterOption('--no-plugins')) { 549 | $parameters[] = '--no-plugins'; 550 | } 551 | 552 | if ($input->hasParameterOption('--no-scripts')) { 553 | $parameters[] = '--no-scripts'; 554 | } 555 | 556 | return $application->run( 557 | new Console\Input\ArrayInput($parameters), 558 | $output, 559 | ); 560 | } 561 | } 562 | -------------------------------------------------------------------------------- /src/Exception/Exception.php: -------------------------------------------------------------------------------- 1 | self::class, 51 | ]; 52 | } 53 | 54 | public function getCommands(): array 55 | { 56 | return [ 57 | new Command\NormalizeCommand( 58 | new Factory(), 59 | new Normalizer\Vendor\Composer\ComposerJsonNormalizer(\sprintf( 60 | 'file://%s', 61 | \realpath(__DIR__ . '/../resource/schema.json'), 62 | )), 63 | new Printer\Printer(), 64 | new Diff\Differ(new Diff\Output\StrictUnifiedDiffOutputBuilder([ 65 | 'fromFile' => 'original', 66 | 'toFile' => 'normalized', 67 | ])), 68 | ), 69 | ]; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/Version.php: -------------------------------------------------------------------------------- 1 | Andreas Möller and contributors'; 30 | 31 | $version = self::$version; 32 | 33 | if ('@' . 'git@' === $version) { 34 | return \sprintf( 35 | '%s %s', 36 | $name, 37 | $attribution, 38 | ); 39 | } 40 | 41 | return \sprintf( 42 | '%s %s %s', 43 | $name, 44 | $version, 45 | $attribution, 46 | ); 47 | } 48 | } 49 | --------------------------------------------------------------------------------