Sfoglia il codice sorgente

Implement getProviders on reposet for all repo types and add replacers

This way errors during require dev extraction make more sense
Nils Adermann 5 anni fa
parent
commit
1f467046d7

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

@@ -248,7 +248,7 @@ class Problem
             return array("- Root composer.json requires $packageName, it ", 'could not be found, it looks like its name is invalid, "'.$illegalChars.'" is not allowed in package names.');
         }
 
-        if ($providers = $repositorySet->getProviders($packageName)) {
+        if ($providers = $repositorySet->getProvidersAndReplacers($packageName)) {
             $maxProviders = 20;
             $providersStr = implode(array_map(function ($p) {
                 return "      - ${p['name']} ".substr($p['description'], 0, 100)."\n";

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

@@ -31,7 +31,7 @@ class SolverProblemsException extends \RuntimeException
         parent::__construct('Failed resolving dependencies with '.count($problems).' problems, call getPrettyString to get formatted details', 2);
     }
 
-    public function getPrettyString(RepositorySet $repositorySet, Request $request, Pool $pool)
+    public function getPrettyString(RepositorySet $repositorySet, Request $request, Pool $pool, $isDevExtraction = false)
     {
         $installedMap = $request->getPresentMap(true);
         $text = "\n";
@@ -44,7 +44,7 @@ class SolverProblemsException extends \RuntimeException
             }
         }
 
-        if (strpos($text, 'could not be found') || strpos($text, 'no matching package found')) {
+        if (!$isDevExtraction && (strpos($text, 'could not be found') || strpos($text, 'no matching package found'))) {
             $text .= "\nPotential causes:\n - A typo in the package name\n - The package is not available in a stable-enough version according to your minimum-stability setting\n   see <https://getcomposer.org/doc/04-schema.md#minimum-stability> for more details.\n - It's a private package and you forgot to add a custom repository to find it\n\nRead <https://getcomposer.org/doc/articles/troubleshooting.md> for further common problems.";
         }
 

+ 3 - 2
src/Composer/Installer.php

@@ -573,8 +573,9 @@ class Installer
             $solver = null;
         } catch (SolverProblemsException $e) {
             $this->io->writeError('<error>Unable to find a compatible set of packages based on your non-dev requirements alone.</error>', true, IOInterface::QUIET);
-            $this->io->writeError('Your requirements can be successfully resolved when require-dev packages are present.');
-            $this->io->writeError($e->getPrettyString($repositorySet, $request, $pool));
+            $this->io->writeError('Your requirements can be resolved successfully when require-dev packages are present.');
+            $this->io->writeError('You may need to move packages from require-dev or some of their dependencies to require.');
+            $this->io->writeError($e->getPrettyString($repositorySet, $request, $pool, true));
 
             return max(1, $e->getCode());
         }

+ 18 - 4
src/Composer/Repository/RepositorySet.php

@@ -163,17 +163,31 @@ class RepositorySet
         return $candidates;
     }
 
-    public function getProviders($packageName)
+    public function getProvidersAndReplacers($packageName)
     {
+        $providers = array();
         foreach ($this->repositories as $repository) {
             if ($repository instanceof ComposerRepository) {
-                if ($providers = $repository->getProviders($packageName)) {
-                    return $providers;
+                if ($repoProviders = $repository->getProviders($packageName)) {
+                    $providers = array_merge($providers, $repoProviders);
+                }
+            } else {
+                foreach ($repository->getPackages() as $candidate) {
+                    foreach (array_merge($candidate->getProvides(), $candidate->getReplaces()) as $link) {
+                        if ($packageName === $link->getTarget()) {
+                            $providers[] = array(
+                                'name' => $candidate->getName(),
+                                'description' => $candidate->getDescription(),
+                                'type' => $candidate->getType(),
+                            );
+                            continue 2;
+                        }
+                    }
                 }
             }
         }
 
-        return array();
+        return $providers;
     }
 
     public function isPackageAcceptable($names, $stability)

+ 40 - 0
tests/Composer/Test/Fixtures/installer/provider-dev-require-cannot-satisfy-require.test

@@ -0,0 +1,40 @@
+--TEST--
+Test that an appropriate error is thrown if a requirement is only satisfied by a package provided by a dependency of a dev requirement.
+--COMPOSER--
+{
+    "repositories": [
+        {
+            "type": "package",
+            "package": [
+                {"name": "provider/requirer", "version": "1.0.0", "type": "metapackage", "require": {"b/b": "1.0.0"}},
+                {"name": "b/b", "version": "1.0.0", "type": "metapackage", "provide": {"provided/pkg": "1.0.0"}}
+            ]
+        }
+    ],
+    "require": {
+        "provided/pkg": "1.0.0"
+    },
+    "require-dev": {
+        "provider/requirer": "1.0.0"
+    }
+}
+
+--RUN--
+update
+
+--EXPECT-EXIT-CODE--
+2
+
+--EXPECT-OUTPUT--
+Loading composer repositories with package information
+Updating dependencies
+Unable to find a compatible set of packages based on your non-dev requirements alone.
+Your requirements can be resolved successfully when require-dev packages are present.
+You may need to move packages from require-dev or some of their dependencies to require.
+
+  Problem 1
+    - Root composer.json requires provided/pkg 1.0.0, it could not be found in any version, but the following packages provide it:
+      - b/b
+      Consider requiring one of these to satisfy the provided/pkg requirement.
+
+--EXPECT--