diff --git a/src/Composer/DependencyResolver/DefaultPolicy.php b/src/Composer/DependencyResolver/DefaultPolicy.php index 6be7dcc23..4d2c25855 100644 --- a/src/Composer/DependencyResolver/DefaultPolicy.php +++ b/src/Composer/DependencyResolver/DefaultPolicy.php @@ -60,14 +60,14 @@ class DefaultPolicy implements PolicyInterface return $pool->getPriority($package->getRepository()); } - public function selectPreferedPackages(Pool $pool, array $installedMap, array $literals, Rule $rule = null) + public function selectPreferedPackages(Pool $pool, array $installedMap, array $literals, $requiredPackage = null) { $packages = $this->groupLiteralsByNamePreferInstalled($pool, $installedMap, $literals); foreach ($packages as &$literals) { $policy = $this; - usort($literals, function ($a, $b) use ($policy, $pool, $installedMap, $rule) { - return $policy->compareByPriorityPreferInstalled($pool, $installedMap, $pool->literalToPackage($a), $pool->literalToPackage($b), $rule, true); + usort($literals, function ($a, $b) use ($policy, $pool, $installedMap, $requiredPackage) { + return $policy->compareByPriorityPreferInstalled($pool, $installedMap, $pool->literalToPackage($a), $pool->literalToPackage($b), $requiredPackage, true); }); } @@ -82,8 +82,8 @@ class DefaultPolicy implements PolicyInterface $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, $installedMap, $rule) { - return $policy->compareByPriorityPreferInstalled($pool, $installedMap, $pool->literalToPackage($a), $pool->literalToPackage($b), $rule); + usort($selected, function ($a, $b) use ($policy, $pool, $installedMap, $requiredPackage) { + return $policy->compareByPriorityPreferInstalled($pool, $installedMap, $pool->literalToPackage($a), $pool->literalToPackage($b), $requiredPackage); }); return $selected; @@ -112,7 +112,7 @@ class DefaultPolicy implements PolicyInterface /** * @protected */ - public function compareByPriorityPreferInstalled(Pool $pool, array $installedMap, PackageInterface $a, PackageInterface $b, Rule $rule = null, $ignoreReplace = false) + public function compareByPriorityPreferInstalled(Pool $pool, array $installedMap, PackageInterface $a, PackageInterface $b, $requiredPackage = null, $ignoreReplace = false) { if ($a->getRepository() === $b->getRepository()) { // prefer aliases to the original package @@ -138,21 +138,14 @@ class DefaultPolicy implements PolicyInterface // for replacers not replacing each other, put a higher prio on replacing // packages with the same vendor as the required package - if ($rule) { - if ($rule->getReason() === Rule::RULE_JOB_INSTALL) { - $required = $rule->getReasonData(); - } elseif ($rule->getReason() === Rule::RULE_PACKAGE_REQUIRES) { - $required = $rule->getReasonData()->getTarget(); - } + if ($requiredPackage && false !== ($pos = strpos($requiredPackage, '/'))) { + $requiredVendor = substr($requiredPackage, 0, $pos); - if ($required && (false !== ($pos = strpos($required, '/')))) { - $requiredVendor = substr($required, 0, $pos); - $aIsSameVendor = substr($a->getName(), 0, $pos) === $requiredVendor; - $bIsSameVendor = substr($b->getName(), 0, $pos) === $requiredVendor; + $aIsSameVendor = substr($a->getName(), 0, $pos) === $requiredVendor; + $bIsSameVendor = substr($b->getName(), 0, $pos) === $requiredVendor; - if ($bIsSameVendor !== $aIsSameVendor) { - return $aIsSameVendor ? -1 : 1; - } + if ($bIsSameVendor !== $aIsSameVendor) { + return $aIsSameVendor ? -1 : 1; } } } diff --git a/src/Composer/DependencyResolver/Rule.php b/src/Composer/DependencyResolver/Rule.php index 13c253848..a69d3bc10 100644 --- a/src/Composer/DependencyResolver/Rule.php +++ b/src/Composer/DependencyResolver/Rule.php @@ -82,14 +82,15 @@ class Rule return $this->job; } - public function getReason() + public function getRequiredPackage() { - return $this->reason; - } + if ($this->reason === self::RULE_JOB_INSTALL) { + return $this->reasonData; + } - public function getReasonData() - { - return $this->reasonData; + if ($this->reason === self::RULE_PACKAGE_REQUIRES) { + return $this->reasonData->getTarget(); + } } /** diff --git a/src/Composer/DependencyResolver/Solver.php b/src/Composer/DependencyResolver/Solver.php index 05bb0b400..f65f6e0e2 100644 --- a/src/Composer/DependencyResolver/Solver.php +++ b/src/Composer/DependencyResolver/Solver.php @@ -321,7 +321,7 @@ class Solver private function selectAndInstall($level, array $decisionQueue, $disableRules, Rule $rule) { // choose best package to install from decisionQueue - $literals = $this->policy->selectPreferedPackages($this->pool, $this->installedMap, $decisionQueue, $rule); + $literals = $this->policy->selectPreferedPackages($this->pool, $this->installedMap, $decisionQueue, $rule->getRequiredPackage()); $selectedLiteral = array_shift($literals); diff --git a/tests/Composer/Test/DependencyResolver/DefaultPolicyTest.php b/tests/Composer/Test/DependencyResolver/DefaultPolicyTest.php index 3a17bf7ba..1e8503f2c 100644 --- a/tests/Composer/Test/DependencyResolver/DefaultPolicyTest.php +++ b/tests/Composer/Test/DependencyResolver/DefaultPolicyTest.php @@ -195,6 +195,7 @@ class DefaultPolicyTest extends TestCase public function testPreferReplacingPackageFromSameVendor() { + // test with default order $this->repo->addPackage($packageB = $this->getPackage('vendor-b/replacer', '1.0')); $this->repo->addPackage($packageA = $this->getPackage('vendor-a/replacer', '1.0')); @@ -206,16 +207,21 @@ class DefaultPolicyTest extends TestCase $literals = array($packageA->getId(), $packageB->getId()); $expected = $literals; - // test with install rule - $rule = new Rule($this->pool, $literals, Rule::RULE_JOB_INSTALL, 'vendor-a/package'); - $selected = $this->policy->selectPreferedPackages($this->pool, array(), $literals, $rule); - + $selected = $this->policy->selectPreferedPackages($this->pool, array(), $literals, 'vendor-a/package'); $this->assertEquals($expected, $selected); - // test with requires rule - $rule = new Rule($this->pool, $literals, Rule::RULE_PACKAGE_REQUIRES, new Link('foo', 'vendor-a/package')); - $selected = $this->policy->selectPreferedPackages($this->pool, array(), $literals, $rule); + // test with reversed order in repo + $repo = new ArrayRepository; + $repo->addPackage($packageA = clone $packageA); + $repo->addPackage($packageB = clone $packageB); + $pool = new Pool('dev'); + $pool->addRepository($this->repo); + + $literals = array($packageA->getId(), $packageB->getId()); + $expected = $literals; + + $selected = $this->policy->selectPreferedPackages($this->pool, array(), $literals, 'vendor-a/package'); $this->assertEquals($expected, $selected); }