瀏覽代碼

Prefer original packages over replaced packages of same repository priority

Nils Adermann 13 年之前
父節點
當前提交
571c14adf9

+ 37 - 3
src/Composer/DependencyResolver/DefaultPolicy.php

@@ -75,7 +75,7 @@ class DefaultPolicy implements PolicyInterface
         foreach ($packages as &$literals) {
         foreach ($packages as &$literals) {
             $policy = $this;
             $policy = $this;
             usort($literals, function ($a, $b) use ($policy, $pool, $installed) {
             usort($literals, function ($a, $b) use ($policy, $pool, $installed) {
-                return $policy->compareByPriorityPreferInstalled($pool, $installed, $a->getPackage(), $b->getPackage());
+                return $policy->compareByPriorityPreferInstalled($pool, $installed, $a->getPackage(), $b->getPackage(), true);
             });
             });
         }
         }
 
 
@@ -87,6 +87,11 @@ class DefaultPolicy implements PolicyInterface
 
 
         $selected = call_user_func_array('array_merge', $packages);
         $selected = call_user_func_array('array_merge', $packages);
 
 
+        // now sort the result across all packages to respect replaces across packages
+        usort($selected, function ($a, $b) use ($policy, $pool, $installed) {
+            return $policy->compareByPriorityPreferInstalled($pool, $installed, $a->getPackage(), $b->getPackage());
+        });
+
         return $selected;
         return $selected;
     }
     }
 
 
@@ -110,10 +115,26 @@ class DefaultPolicy implements PolicyInterface
         return $packages;
         return $packages;
     }
     }
 
 
-    public function compareByPriorityPreferInstalled(Pool $pool, RepositoryInterface $installed, PackageInterface $a, PackageInterface $b)
+    public function compareByPriorityPreferInstalled(Pool $pool, RepositoryInterface $installed, PackageInterface $a, PackageInterface $b, $ignoreReplace = false)
     {
     {
         if ($a->getRepository() === $b->getRepository()) {
         if ($a->getRepository() === $b->getRepository()) {
-            return 0;
+
+            if (!$ignoreReplace) {
+                // return original, not replaced
+                if ($this->replaces($a, $b)) {
+                    return 1; // use b
+                }
+                if ($this->replaces($b, $a)) {
+                    return -1; // use a
+                }
+            }
+
+            // priority equal, sort by package id to make reproducible
+            if ($a->getId() === $b->getId()) {
+                return 0;
+            }
+
+            return ($a->getId() < $b->getId()) ? -1 : 1;
         }
         }
 
 
         if ($a->getRepository() === $installed) {
         if ($a->getRepository() === $installed) {
@@ -127,6 +148,19 @@ class DefaultPolicy implements PolicyInterface
         return ($this->getPriority($pool, $a) > $this->getPriority($pool, $b)) ? -1 : 1;
         return ($this->getPriority($pool, $a) > $this->getPriority($pool, $b)) ? -1 : 1;
     }
     }
 
 
+    protected function replaces(PackageInterface $source, PackageInterface $target)
+    {
+        foreach ($source->getReplaces() as $link) {
+            if ($link->getTarget() === $target->getName() &&
+                (null === $link->getConstraint() ||
+                $link->getConstraint()->matches(new VersionConstraint('==', $target->getVersion())))) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
     protected function pruneToBestVersion($literals)
     protected function pruneToBestVersion($literals)
     {
     {
         $bestLiterals = array($literals[0]);
         $bestLiterals = array($literals[0]);

+ 2 - 3
tests/Composer/Test/DependencyResolver/DefaultPolicyTest.php

@@ -135,9 +135,8 @@ class DefaultPolicyTest extends \PHPUnit_Framework_TestCase
         $this->assertEquals($expected, $selected);
         $this->assertEquals($expected, $selected);
     }
     }
 
 
-    public function testSelectNonReplacingFromSameRepo()
+    public function testPreferNonReplacingFromSameRepo()
     {
     {
-        $this->markTestIncomplete();
 
 
         $this->repo->addPackage($packageA = new MemoryPackage('A', '1.0'));
         $this->repo->addPackage($packageA = new MemoryPackage('A', '1.0'));
         $this->repo->addPackage($packageB = new MemoryPackage('B', '2.0'));
         $this->repo->addPackage($packageB = new MemoryPackage('B', '2.0'));
@@ -147,7 +146,7 @@ class DefaultPolicyTest extends \PHPUnit_Framework_TestCase
         $this->pool->addRepository($this->repo);
         $this->pool->addRepository($this->repo);
 
 
         $literals = array(new Literal($packageA, true), new Literal($packageB, true));
         $literals = array(new Literal($packageA, true), new Literal($packageB, true));
-        $expected = array(new Literal($packageA, true));
+        $expected = array(new Literal($packageA, true), new Literal($packageB, true));
 
 
         $selected = $this->policy->selectPreferedPackages($this->pool, $this->repoInstalled, $literals);
         $selected = $this->policy->selectPreferedPackages($this->pool, $this->repoInstalled, $literals);
 
 

+ 1 - 1
tests/Composer/Test/DependencyResolver/SolverTest.php

@@ -209,7 +209,7 @@ class SolverTest extends \PHPUnit_Framework_TestCase
         $this->request->install('A');
         $this->request->install('A');
 
 
         $this->checkSolverResult(array(
         $this->checkSolverResult(array(
-            array('job' => 'install', 'package' => $packageB),
+            array('job' => 'install', 'package' => $packageA),
         ));
         ));
     }
     }