Переглянути джерело

Implement getProviders equally on all repos

Jordi Boggiano 5 роки тому
батько
коміт
08cee4c3e9

+ 27 - 0
src/Composer/Repository/ArrayRepository.php

@@ -204,6 +204,33 @@ class ArrayRepository implements RepositoryInterface
         $this->packageMap = null;
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    public function getProviders($packageName)
+    {
+        $result = array();
+
+        foreach ($this->getPackages() as $candidate) {
+            if (isset($result[$candidate->getName()])) {
+                continue;
+            }
+            foreach ($candidate->getProvides() as $link) {
+                if ($packageName === $link->getTarget()) {
+                    $result[$candidate->getName()] = array(
+                        'name' => $candidate->getName(),
+                        'description' => $candidate->getDescription(),
+                        'type' => $candidate->getType(),
+                        'repository' => $candidate->getSourceUrl() ?: '',
+                    );
+                    continue 2;
+                }
+            }
+        }
+
+        return $result;
+    }
+
     protected function createAliasPackage(PackageInterface $package, $alias, $prettyAlias)
     {
         return new AliasPackage($package instanceof AliasPackage ? $package->getAliasOf() : $package, $alias, $prettyAlias);

+ 31 - 6
src/Composer/Repository/ComposerRepository.php

@@ -421,15 +421,40 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
 
     public function getProviders($packageName)
     {
-        if (!$this->providersApiUrl) {
-            // TODO should this return the info based on getPackages in other cases?
-            return array();
+        $this->loadRootServerFile();
+        $result = array();
+
+        if ($this->providersApiUrl) {
+            $apiResult = $this->httpDownloader->get(str_replace('%package%', $packageName, $this->providersApiUrl), $this->options)->decodeJson();
+
+            foreach ($apiResult['providers'] as $provider) {
+                $result[$provider['name']] = $provider;
+            }
+
+            return $result;
+        }
+
+        if ($this->hasPartialPackages()) {
+            foreach ($this->partialPackagesByName as $versions) {
+                foreach ($versions as $candidate) {
+                    if (isset($result[$candidate['name']]) || !isset($candidate['provide'][$packageName])) {
+                        continue;
+                    }
+                    $result[$candidate['name']] = array(
+                        'name' => $candidate['name'],
+                        'description' => isset($candidate['description']) ? $candidate['description'] : '',
+                        'type' => isset($candidate['type']) ? $candidate['type'] : '',
+                        'repository' => '',
+                    );
+                }
+            }
         }
 
-        $result = $this->httpDownloader->get(str_replace('%package%', $packageName, $this->providersApiUrl), $this->options)->decodeJson();
+        if ($this->packages) {
+            $result = array_merge($result, parent::getProviders($packageName));
+        }
 
-        // TODO filter packageName out here?
-        return $result['providers'];
+        return $result;
     }
 
     private function getProviderNames()

+ 14 - 0
src/Composer/Repository/CompositeRepository.php

@@ -147,6 +147,20 @@ class CompositeRepository implements RepositoryInterface
         return $packages ? call_user_func_array('array_merge', $packages) : array();
     }
 
+    /**
+     * {@inheritdoc}
+     */
+    public function getProviders($packageName)
+    {
+        $results = array();
+        foreach ($this->repositories as $repository) {
+            /* @var $repository RepositoryInterface */
+            $results[] = $repository->getProviders($packageName);
+        }
+
+        return $results ? call_user_func_array('array_merge', $results) : array();
+    }
+
     /**
      * {@inheritdoc}
      */

+ 1 - 1
src/Composer/Repository/LockArrayRepository.php

@@ -19,7 +19,7 @@ namespace Composer\Repository;
  *
  * @author Nils Adermann <naderman@naderman.de>
  */
-class LockArrayRepository extends ArrayRepository implements RepositoryInterface
+class LockArrayRepository extends ArrayRepository
 {
     public function getRepoName()
     {

+ 11 - 0
src/Composer/Repository/RepositoryInterface.php

@@ -84,6 +84,17 @@ interface RepositoryInterface extends \Countable
      */
     public function search($query, $mode = 0, $type = null);
 
+    /**
+     * Returns a list of packages providing a given package name
+     *
+     * Packages which have the same name as $packageName should not be returned, only those that have a "provide" on it.
+     *
+     * @param string $packageName package name which must be provided
+     *
+     * @return array[] an array with the provider name as key and value of array('name' => '...', 'description' => '...', 'type' => '...', 'repository' => '...url to source repo if available...')
+     */
+    public function getProviders($packageName);
+
     /**
      * Returns a name representing this repository to the user
      *

+ 2 - 17
src/Composer/Repository/RepositorySet.php

@@ -167,23 +167,8 @@ class RepositorySet
     {
         $providers = array();
         foreach ($this->repositories as $repository) {
-            if ($repository instanceof ComposerRepository) {
-                if ($repoProviders = $repository->getProviders($packageName)) {
-                    $providers = array_merge($providers, $repoProviders);
-                }
-            } else {
-                foreach ($repository->getPackages() as $candidate) {
-                    foreach ($candidate->getProvides() as $link) {
-                        if ($packageName === $link->getTarget()) {
-                            $providers[] = array(
-                                'name' => $candidate->getName(),
-                                'description' => $candidate->getDescription(),
-                                'type' => $candidate->getType(),
-                            );
-                            continue 2;
-                        }
-                    }
-                }
+            if ($repoProviders = $repository->getProviders($packageName)) {
+                $providers = array_merge($providers, $repoProviders);
             }
         }
 

+ 21 - 15
tests/Composer/Test/Fixtures/installer/solver-problems.test

@@ -47,7 +47,8 @@ Test the error output of solver problems.
                 { "name": "dependency/pkg", "version": "1.0.0" },
                 { "name": "dependency/unstable-pkg", "version": "1.0.0-dev" },
                 { "name": "stable-requiree-excluded/pkg", "version": "1.0.1" },
-                { "name": "stable-requiree-excluded/pkg", "version": "1.0.0" }
+                { "name": "stable-requiree-excluded/pkg", "version": "1.0.0" },
+                { "name": "api/provider", "description": "Provides the missing API", "version": "1.0.0", "provide": { "missing/provided-api": "1.*" } }
             ]
         }
     ],
@@ -59,6 +60,7 @@ Test the error output of solver problems.
         "package/found5": "2.*",
         "package/found6": "2.*",
         "package/found7": "2.*",
+        "missing/provided-api": "2.*",
         "conflict/requirer": "2.*",
         "conflict/requirer2": "2.*",
         "unstable/package": "2.*",
@@ -107,41 +109,45 @@ Updating dependencies
 Your requirements could not be resolved to an installable set of packages.
 
   Problem 1
-    - Root composer.json requires unstable/package 2.*, found unstable/package[2.0.0-alpha] but it does not match your minimum-stability.
+    - Root composer.json requires missing/provided-api 2.*, it could not be found in any version, but the following packages provide it:
+      - api/provider Provides the missing API
+      Consider requiring one of these to satisfy the missing/provided-api requirement.
   Problem 2
-    - Root composer.json requires non-existent/pkg, it could not be found in any version, there may be a typo in the package name.
+    - Root composer.json requires unstable/package 2.*, found unstable/package[2.0.0-alpha] but it does not match your minimum-stability.
   Problem 3
-    - Root composer.json requires stable-requiree-excluded/pkg 1.0.1, found stable-requiree-excluded/pkg[1.0.1] 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 whitelist it for update.
+    - Root composer.json requires non-existent/pkg, it could not be found in any version, there may be a typo in the package name.
   Problem 4
-    - Root composer.json requires linked library lib-xml 1002.* but it has the wrong version installed or is missing from your system, make sure to load the extension providing it.
+    - Root composer.json requires stable-requiree-excluded/pkg 1.0.1, found stable-requiree-excluded/pkg[1.0.1] 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 whitelist it for update.
   Problem 5
-    - Root composer.json requires linked library lib-icu 1001.* but it has the wrong version installed, try upgrading the intl extension.
+    - Root composer.json requires linked library lib-xml 1002.* but it has the wrong version installed or is missing from your system, make sure to load the extension providing it.
   Problem 6
-    - Root composer.json requires PHP extension ext-xml 1002.* but it has the wrong version (%s) installed. Install or enable PHP's xml extension.
+    - Root composer.json requires linked library lib-icu 1001.* but it has the wrong version installed, try upgrading the intl extension.
   Problem 7
-    - Root composer.json requires php 1 but your php version (%s) does not satisfy that requirement.
+    - Root composer.json requires PHP extension ext-xml 1002.* but it has the wrong version (%s) installed. Install or enable PHP's xml extension.
   Problem 8
+    - Root composer.json requires php 1 but your php version (%s) does not satisfy that requirement.
+  Problem 9
     - Root composer.json requires package/found 2.* -> satisfiable by package/found[2.0.0].
     - package/found 2.0.0 requires unstable/package2 2.* -> found unstable/package2[2.0.0-alpha] but it does not match your minimum-stability.
-  Problem 9
+  Problem 10
     - Root composer.json requires package/found2 2.* -> satisfiable by package/found2[2.0.0].
     - package/found2 2.0.0 requires invalid/💩package * -> could not be found, it looks like its name is invalid, "💩" is not allowed in package names.
-  Problem 10
+  Problem 11
     - Root composer.json requires package/found3 2.* -> satisfiable by package/found3[2.0.0].
     - package/found3 2.0.0 requires unstable/package2 2.* -> found unstable/package2[2.0.0-alpha] but it does not match your minimum-stability.
-  Problem 11
+  Problem 12
     - Root composer.json requires package/found4 2.* -> satisfiable by package/found4[2.0.0].
     - package/found4 2.0.0 requires non-existent/pkg2 1.* -> could not be found in any version, there may be a typo in the package name.
-  Problem 12
+  Problem 13
     - Root composer.json requires package/found6 2.* -> satisfiable by package/found6[2.0.0].
     - package/found6 2.0.0 requires stable-requiree-excluded/pkg2 1.0.1 -> found stable-requiree-excluded/pkg2[1.0.0] but it does not match your constraint.
-  Problem 13
+  Problem 14
     - Root composer.json requires package/found7 2.* -> satisfiable by package/found7[2.0.0].
     - package/found7 2.0.0 requires php-64bit 1.0.1 -> your php-64bit version (%s) does not satisfy that requirement.
-  Problem 14
+  Problem 15
     - Root composer.json requires requirer/pkg 1.* -> satisfiable by requirer/pkg[1.0.0].
     - requirer/pkg 1.0.0 requires dependency/pkg 1.0.0 -> found dependency/pkg[1.0.0] but it conflicts with your root composer.json require (2.*).
-  Problem 15
+  Problem 16
     - requirer/pkg 1.0.0 requires dependency/pkg 1.0.0 -> found dependency/pkg[1.0.0] but it conflicts with your root composer.json require (2.*).
     - package/found5 2.0.0 requires requirer/pkg 1.* -> satisfiable by requirer/pkg[1.0.0].
     - Root composer.json requires package/found5 2.* -> satisfiable by package/found5[2.0.0].