Explorar o código

Merge pull request #606 from Seldaek/aliasprio

Fix priority of aliases when mixing root package aliases with branch-alias ones, fixes #576
Nils Adermann %!s(int64=13) %!d(string=hai) anos
pai
achega
540f9a09b2

+ 38 - 2
src/Composer/DependencyResolver/DefaultPolicy.php

@@ -69,6 +69,8 @@ class DefaultPolicy implements PolicyInterface
             $literals = $this->pruneToBestVersion($literals);
 
             $literals = $this->pruneToHighestPriorityOrInstalled($pool, $installedMap, $literals);
+
+            $literals = $this->pruneRemoteAliases($literals);
         }
 
         $selected = call_user_func_array('array_merge', $packages);
@@ -210,8 +212,8 @@ class DefaultPolicy implements PolicyInterface
     }
 
     /**
-    * Assumes that installed packages come first and then all highest priority packages
-    */
+     * Assumes that installed packages come first and then all highest priority packages
+     */
     protected function pruneToHighestPriorityOrInstalled(Pool $pool, array $installedMap, array $literals)
     {
         $selected = array();
@@ -239,4 +241,38 @@ class DefaultPolicy implements PolicyInterface
 
         return $selected;
     }
+
+    /**
+     * Assumes that locally aliased (in root package requires) packages take priority over branch-alias ones
+     *
+     * If no package is a local alias, nothing happens
+     */
+    protected function pruneRemoteAliases(array $literals)
+    {
+        $hasLocalAlias = false;
+
+        foreach ($literals as $literal) {
+            $package = $literal->getPackage();
+
+            if ($package instanceof AliasPackage && $package->isRootPackageAlias()) {
+                $hasLocalAlias = true;
+                break;
+            }
+        }
+
+        if (!$hasLocalAlias) {
+            return $literals;
+        }
+
+        $selected = array();
+        foreach ($literals as $literal) {
+            $package = $literal->getPackage();
+
+            if ($package instanceof AliasPackage && $package->isRootPackageAlias()) {
+                $selected[] = $literal;
+            }
+        }
+
+        return $selected;
+    }
 }

+ 4 - 2
src/Composer/Installer.php

@@ -383,14 +383,16 @@ class Installer
             foreach ($this->repositoryManager->findPackages($alias['package'], $alias['version']) as $package) {
                 $package->setAlias($alias['alias_normalized']);
                 $package->setPrettyAlias($alias['alias']);
-                $package->getRepository()->addPackage(new AliasPackage($package, $alias['alias_normalized'], $alias['alias']));
+                $package->getRepository()->addPackage($aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias']));
+                $aliasPackage->setRootPackageAlias(true);
             }
             foreach ($this->repositoryManager->getLocalRepositories() as $repo) {
                 foreach ($repo->findPackages($alias['package'], $alias['version']) as $package) {
                     $package->setAlias($alias['alias_normalized']);
                     $package->setPrettyAlias($alias['alias']);
-                    $package->getRepository()->addPackage(new AliasPackage($package, $alias['alias_normalized'], $alias['alias']));
+                    $package->getRepository()->addPackage($aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias']));
                     $package->getRepository()->removePackage($package);
+                    $aliasPackage->setRootPackageAlias(true);
                 }
             }
         }

+ 22 - 0
src/Composer/Package/AliasPackage.php

@@ -27,6 +27,7 @@ class AliasPackage extends BasePackage
     protected $prettyVersion;
     protected $dev;
     protected $aliasOf;
+    protected $rootPackageAlias = false;
 
     protected $requires;
     protected $conflicts;
@@ -146,6 +147,27 @@ class AliasPackage extends BasePackage
         return $this->devRequires;
     }
 
+    /**
+     * Stores whether this is an alias created by an aliasing in the requirements of the root package or not
+     *
+     * Use by the policy for sorting manually aliased packages first, see #576
+     *
+     * @param Boolean $value
+     */
+    public function setRootPackageAlias($value)
+    {
+        return $this->rootPackageAlias = $value;
+    }
+
+    /**
+     * @see setRootPackageAlias
+     * @return Boolean
+     */
+    public function isRootPackageAlias()
+    {
+        return $this->rootPackageAlias;
+    }
+
     /**
      * {@inheritDoc}
      */

+ 30 - 0
tests/Composer/Test/DependencyResolver/DefaultPolicyTest.php

@@ -18,6 +18,7 @@ use Composer\DependencyResolver\DefaultPolicy;
 use Composer\DependencyResolver\Pool;
 use Composer\DependencyResolver\Literal;
 use Composer\Package\Link;
+use Composer\Package\AliasPackage;
 use Composer\Package\LinkConstraint\VersionConstraint;
 use Composer\Test\TestCase;
 
@@ -99,6 +100,35 @@ class DefaultPolicyTest extends TestCase
         $this->assertEquals($expected, $selected);
     }
 
+    public function testSelectLocalReposFirst()
+    {
+        $this->repoImportant = new ArrayRepository;
+
+        $this->repo->addPackage($packageA = $this->getPackage('A', 'dev-master'));
+        $this->repo->addPackage($packageAAlias = new AliasPackage($packageA, '2.1.9999999.9999999-dev', '2.1.x-dev'));
+        $this->repoImportant->addPackage($packageAImportant = $this->getPackage('A', 'dev-feature-a'));
+        $this->repoImportant->addPackage($packageAAliasImportant = new AliasPackage($packageAImportant, '2.1.9999999.9999999-dev', '2.1.x-dev'));
+        $this->repoImportant->addPackage($packageA2Important = $this->getPackage('A', 'dev-master'));
+        $this->repoImportant->addPackage($packageA2AliasImportant = new AliasPackage($packageA2Important, '2.1.9999999.9999999-dev', '2.1.x-dev'));
+        $packageAAliasImportant->setRootPackageAlias(true);
+
+        $this->pool->addRepository($this->repoInstalled);
+        $this->pool->addRepository($this->repoImportant);
+        $this->pool->addRepository($this->repo);
+
+        $packages = $this->pool->whatProvides('a', new VersionConstraint('=', '2.1.9999999.9999999-dev'));
+        $literals = array();
+        foreach ($packages as $package) {
+            $literals[] = new Literal($package, true);
+        }
+
+        $expected = array(new Literal($packageAAliasImportant, true));
+
+        $selected = $this->policy->selectPreferedPackages($this->pool, array(), $literals);
+
+        $this->assertEquals($expected, $selected);
+    }
+
     public function testSelectAllProviders()
     {
         $this->repo->addPackage($packageA = $this->getPackage('A', '1.0'));