Browse Source

Fix detection of fixed package problems to include more cases, fixes #8910

Jordi Boggiano 4 years ago
parent
commit
98e5f81a5f

+ 2 - 2
src/Composer/DependencyResolver/Problem.php

@@ -133,11 +133,11 @@ class Problem
         return "\n    - ".implode("\n    - ", $result);
     }
 
-    public function isCausedByLock()
+    public function isCausedByLock(RepositorySet $repositorySet, Request $request, Pool $pool)
     {
         foreach ($this->reasons as $sectionRules) {
             foreach ($sectionRules as $rule) {
-                if ($rule->isCausedByLock()) {
+                if ($rule->isCausedByLock($repositorySet, $request, $pool)) {
                     return true;
                 }
             }

+ 42 - 2
src/Composer/DependencyResolver/Rule.php

@@ -17,7 +17,9 @@ use Composer\Package\Link;
 use Composer\Package\PackageInterface;
 use Composer\Package\AliasPackage;
 use Composer\Repository\RepositorySet;
+use Composer\Repository\PlatformRepository;
 use Composer\Package\Version\VersionParser;
+use Composer\Semver\Constraint\Constraint;
 
 /**
  * @author Nils Adermann <naderman@naderman.de>
@@ -122,9 +124,47 @@ abstract class Rule
 
     abstract public function isAssertion();
 
-    public function isCausedByLock()
+    public function isCausedByLock(RepositorySet $repositorySet, Request $request, Pool $pool)
     {
-        return $this->getReason() === self::RULE_FIXED && $this->reasonData['lockable'];
+        if ($this->getReason() === self::RULE_FIXED && $this->reasonData['lockable']) {
+            return true;
+        }
+
+        if ($this->getReason() === self::RULE_PACKAGE_REQUIRES) {
+            if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $this->reasonData->getTarget())) {
+                return false;
+            }
+            foreach ($request->getFixedPackages() as $package) {
+                if ($package->getName() === $this->reasonData->getTarget()) {
+                    if ($pool->isUnacceptableFixedPackage($package)) {
+                        return true;
+                    }
+                    if (!$this->reasonData->getConstraint()->matches(new Constraint('=', $package->getVersion()))) {
+                        return true;
+                    }
+                    break;
+                }
+            }
+        }
+
+        if ($this->getReason() === self::RULE_ROOT_REQUIRE) {
+            if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $this->reasonData['packageName'])) {
+                return false;
+            }
+            foreach ($request->getFixedPackages() as $package) {
+                if ($package->getName() === $this->reasonData['packageName']) {
+                    if ($pool->isUnacceptableFixedPackage($package)) {
+                        return true;
+                    }
+                    if (!$this->reasonData['constraint']->matches(new Constraint('=', $package->getVersion()))) {
+                        return true;
+                    }
+                    break;
+                }
+            }
+        }
+
+        return false;
     }
 
     public function getPrettyString(RepositorySet $repositorySet, Request $request, Pool $pool, $isVerbose, array $installedMap = array(), array $learnedPool = array())

+ 2 - 2
src/Composer/DependencyResolver/SolverProblemsException.php

@@ -45,7 +45,7 @@ class SolverProblemsException extends \RuntimeException
                 $hasExtensionProblems = true;
             }
 
-            $isCausedByLock |= $problem->isCausedByLock();
+            $isCausedByLock |= $problem->isCausedByLock($repositorySet, $request, $pool);
         }
 
         $i = 1;
@@ -63,7 +63,7 @@ class SolverProblemsException extends \RuntimeException
         }
 
         if ($isCausedByLock && !$isDevExtraction) {
-            $text .= "\nUse the option --with-all-dependencies to allow updates and removals for packages currently locked to specific versions.";
+            $text .= "\nUse the option --with-all-dependencies to allow upgrades, downgrades and removals for packages currently locked to specific versions.";
         }
 
         if (strpos($text, 'found composer-plugin-api[2.0.0] but it does not match') && strpos($text, '- ocramius/package-versions')) {

+ 1 - 1
tests/Composer/Test/Fixtures/installer/alias-solver-problems2.test

@@ -49,6 +49,6 @@ Your requirements could not be resolved to an installable set of packages.
     - locked/pkg dev-master requires locked/dependency 1.0.0 -> found locked/dependency[1.0.0] in lock file but not in remote repositories, make sure you avoid updating this package to keep the one from lock file.
     - Root composer.json requires locked/pkg *@dev -> satisfiable by locked/pkg[dev-master].
 
-Use the option --with-all-dependencies to allow updates and removals for packages currently locked to specific versions.
+Use the option --with-all-dependencies to allow upgrades, downgrades and removals for packages currently locked to specific versions.
 --EXPECT--
 

+ 2 - 0
tests/Composer/Test/Fixtures/installer/partial-update-downgrades-non-allow-listed-unstable.test

@@ -60,3 +60,5 @@ Your requirements could not be resolved to an installable set of packages.
 
   Problem 1
     - b/unstable is fixed to 1.1.0-alpha (lock file version) by a partial update but that version is rejected by your minimum-stability. Make sure you list it as an argument for the update command.
+
+Use the option --with-all-dependencies to allow upgrades, downgrades and removals for packages currently locked to specific versions.

+ 2 - 0
tests/Composer/Test/Fixtures/installer/problems-reduce-versions.test

@@ -112,5 +112,7 @@ Your requirements could not be resolved to an installable set of packages.
   Problem 1
     - Root composer.json requires b/b ^1.1 || ^2.0 || ^3.0, found b/b[1.1.0, ..., 1.2.9, 2.0.0, ..., 2.3.0-RC, 3.0.0, 3.0.1, 3.0.2, 3.0.3] but the package is fixed to 1.0.0 (lock file version) by a partial update and that version does not match. Make sure you list it as an argument for the update command.
 
+Use the option --with-all-dependencies to allow upgrades, downgrades and removals for packages currently locked to specific versions.
+
 --EXPECT--
 

+ 1 - 1
tests/Composer/Test/Fixtures/installer/root-alias-change-with-circular-dep.test

@@ -62,6 +62,6 @@ Your lock file does not contain a compatible set of packages. Please run compose
     - b/requirer is locked to version 1.0.0 and an update of this package was not requested.
     - b/requirer 1.0.0 requires root/pkg ^1 -> found root/pkg[2.x-dev] but it does not match the constraint.
 
-Use the option --with-all-dependencies to allow updates and removals for packages currently locked to specific versions.
+Use the option --with-all-dependencies to allow upgrades, downgrades and removals for packages currently locked to specific versions.
 
 --EXPECT--

+ 5 - 2
tests/Composer/Test/Fixtures/installer/solver-problems.test

@@ -159,9 +159,12 @@ Potential causes:
  - It's a private package and you forgot to add a custom repository to find it
 
 Read <https://getcomposer.org/doc/articles/troubleshooting.md> for further common problems.
-  To enable extensions, verify that they are enabled in your .ini files:
+
+To enable extensions, verify that they are enabled in your .ini files:
 __inilist__
-  You can also run `php --ini` inside terminal to see which files are used by PHP in CLI mode.
+You can also run `php --ini` inside terminal to see which files are used by PHP in CLI mode.
+
+Use the option --with-all-dependencies to allow upgrades, downgrades and removals for packages currently locked to specific versions.
 
 --EXPECT--
 

+ 1 - 1
tests/Composer/Test/Fixtures/installer/update-allow-list-require-new-replace.test

@@ -51,5 +51,5 @@ Your requirements could not be resolved to an installable set of packages.
     - new/pkg[1.0.0] cannot be installed as that would require removing current/dep[1.0.0]. new/pkg replaces current/dep and thus cannot coexist with it.
     - Root composer.json requires new/pkg 1.* -> satisfiable by new/pkg[1.0.0].
 
-Use the option --with-all-dependencies to allow updates and removals for packages currently locked to specific versions.
+Use the option --with-all-dependencies to allow upgrades, downgrades and removals for packages currently locked to specific versions.
 --EXPECT--