From 436a112651a83045bca8c396ee219b83dc7f2122 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Tue, 11 Oct 2022 13:34:45 +0200 Subject: [PATCH] Clarify temporary constraint usages and throw if an unresolvable constraint is provided --- doc/03-cli.md | 5 +++-- src/Composer/Command/UpdateCommand.php | 19 +++++++++++++------ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/doc/03-cli.md b/doc/03-cli.md index 221cae101..e871d055b 100644 --- a/doc/03-cli.md +++ b/doc/03-cli.md @@ -176,8 +176,9 @@ you can skip `--with` and instead use constraints with the partial update syntax php composer.phar update vendor/package:2.0.1 vendor/package2:3.0.* ``` -The custom constraint has to be a subset of the existing constraint you have, -and this feature is only available for your root package dependencies. +> **Note:** For packages also required in your composer.json the custom constraint +> must be a subset of the existing constraint. The composer.json constraints still +> apply and the composer.json is not modified by these temporary update constraints. ### Options diff --git a/src/Composer/Command/UpdateCommand.php b/src/Composer/Command/UpdateCommand.php index 5a0469d32..92e0f200a 100644 --- a/src/Composer/Command/UpdateCommand.php +++ b/src/Composer/Command/UpdateCommand.php @@ -21,6 +21,7 @@ use Composer\Pcre\Preg; use Composer\Plugin\CommandEvent; use Composer\Plugin\PluginEvents; use Composer\Package\Version\VersionParser; +use Composer\Semver\Intervals; use Composer\Util\HttpDownloader; use Composer\Advisory\Auditor; use Symfony\Component\Console\Helper\Table; @@ -147,16 +148,22 @@ EOT } } - $parser = new VersionParser; - $temporaryConstraints = []; - foreach ($reqs as $package => $constraint) { - $temporaryConstraints[strtolower($package)] = $parser->parseConstraints($constraint); - } - $rootPackage = $composer->getPackage(); $rootPackage->setReferences(RootPackageLoader::extractReferences($reqs, $rootPackage->getReferences())); $rootPackage->setStabilityFlags(RootPackageLoader::extractStabilityFlags($reqs, $rootPackage->getMinimumStability(), $rootPackage->getStabilityFlags())); + $parser = new VersionParser; + $temporaryConstraints = []; + $rootRequirements = array_merge($rootPackage->getRequires(), $rootPackage->getDevRequires()); + foreach ($reqs as $package => $constraint) { + $package = strtolower($package); + $parsedConstraint = $parser->parseConstraints($constraint); + $temporaryConstraints[$package] = $parsedConstraint; + if (isset($rootRequirements[$package]) && !Intervals::haveIntersections($parsedConstraint, $rootRequirements[$package]->getConstraint())) { + throw new \InvalidArgumentException('The temporary constraint "'.$constraint.'" for "'.$package.'" must be a subset of the constraint in your composer.json ('.$rootRequirements[$package]->getPrettyConstraint().')'); + } + } + if ($input->getOption('interactive')) { $packages = $this->getPackagesInteractively($io, $input, $output, $composer, $packages); }