|
@@ -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]);
|