1
0
Fork 0
mirror of https://github.com/composer/composer synced 2025-05-09 16:42:57 +00:00

Let the solver handle aliases instead of the installer

This commit is contained in:
Nils Adermann 2012-04-27 19:41:53 +02:00
parent d74eec9bd5
commit 0c1944a9d0
13 changed files with 382 additions and 109 deletions

View file

@ -0,0 +1,66 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer\DependencyResolver\Operation;
use Composer\Package\AliasPackage;
/**
* Solver install operation.
*
* @author Konstantin Kudryashov <ever.zet@gmail.com>
*/
class MarkAliasInstalledOperation extends SolverOperation
{
protected $package;
/**
* Initializes operation.
*
* @param PackageInterface $package package instance
* @param string $reason operation reason
*/
public function __construct(AliasPackage $package, $reason = null)
{
parent::__construct($reason);
$this->package = $package;
}
/**
* Returns package instance.
*
* @return PackageInterface
*/
public function getPackage()
{
return $this->package;
}
/**
* Returns job type.
*
* @return string
*/
public function getJobType()
{
return 'markAliasInstalled';
}
/**
* {@inheritDoc}
*/
public function __toString()
{
return 'Marking '.$this->package->getPrettyName().' ('.$this->package->getPrettyVersion().') as installed, alias of '.$this->package->getAliasOf()->getPrettyName().' ('.$this->package->getAliasOf()->getPrettyVersion().')';
}
}

View file

@ -0,0 +1,66 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer\DependencyResolver\Operation;
use Composer\Package\AliasPackage;
/**
* Solver install operation.
*
* @author Nils Adermann <naderman@naderman.de>
*/
class MarkAliasUninstalledOperation extends SolverOperation
{
protected $package;
/**
* Initializes operation.
*
* @param PackageInterface $package package instance
* @param string $reason operation reason
*/
public function __construct(AliasPackage $package, $reason = null)
{
parent::__construct($reason);
$this->package = $package;
}
/**
* Returns package instance.
*
* @return PackageInterface
*/
public function getPackage()
{
return $this->package;
}
/**
* Returns job type.
*
* @return string
*/
public function getJobType()
{
return 'markAliasUninstalled';
}
/**
* {@inheritDoc}
*/
public function __toString()
{
return 'Marking '.$this->package->getPrettyName().' ('.$this->package->getPrettyVersion().') as uninstalled, alias of '.$this->package->getAliasOf()->getPrettyName().' ('.$this->package->getAliasOf()->getPrettyVersion().')';
}
}

View file

@ -29,6 +29,7 @@ class Rule
const RULE_PACKAGE_SAME_NAME = 10;
const RULE_PACKAGE_IMPLICIT_OBSOLETES = 11;
const RULE_LEARNED = 12;
const RULE_PACKAGE_ALIAS = 13;
protected $disabled;
protected $literals;
@ -235,6 +236,8 @@ class Rule
return $ruleText;
case self::RULE_LEARNED:
return 'learned: '.$ruleText;
case self::RULE_PACKAGE_ALIAS:
return $ruleText;
}
}

View file

@ -14,6 +14,7 @@ namespace Composer\DependencyResolver;
use Composer\Repository\RepositoryInterface;
use Composer\Package\PackageInterface;
use Composer\Package\AliasPackage;
use Composer\DependencyResolver\Operation;
/**
@ -255,8 +256,10 @@ class Solver
continue;
}
$reason = ($isInstalled) ? Rule::RULE_INSTALLED_PACKAGE_OBSOLETES : Rule::RULE_PACKAGE_OBSOLETES;
$this->addRule(RuleSet::TYPE_PACKAGE, $this->createConflictRule($package, $provider, $reason, (string) $link));
if (!$this->obsoleteImpossibleForAlias($package, $provider)) {
$reason = ($isInstalled) ? Rule::RULE_INSTALLED_PACKAGE_OBSOLETES : Rule::RULE_PACKAGE_OBSOLETES;
$this->addRule(RuleSet::TYPE_PACKAGE, $this->createConflictRule($package, $provider, $reason, (string) $link));
}
}
}
@ -271,17 +274,31 @@ class Solver
continue;
}
if ($isInstalled && !isset($this->installedMap[$provider->getId()])) {
continue;
if (($package instanceof AliasPackage) && $package->getAliasOf() === $provider) {
$this->addRule(RuleSet::TYPE_PACKAGE, $rule = $this->createRequireRule($package, array($provider), Rule::RULE_PACKAGE_ALIAS, (string) $package));
} else if (!$this->obsoleteImpossibleForAlias($package, $provider)) {
$reason = ($package->getName() == $provider->getName()) ? Rule::RULE_PACKAGE_SAME_NAME : Rule::RULE_PACKAGE_IMPLICIT_OBSOLETES;
$this->addRule(RuleSet::TYPE_PACKAGE, $rule = $this->createConflictRule($package, $provider, $reason, (string) $package));
}
$reason = ($package->getName() == $provider->getName()) ? Rule::RULE_PACKAGE_SAME_NAME : Rule::RULE_PACKAGE_IMPLICIT_OBSOLETES;
$this->addRule(RuleSet::TYPE_PACKAGE, $rule = $this->createConflictRule($package, $provider, $reason, (string) $package));
}
}
}
}
protected function obsoleteImpossibleForAlias($package, $provider)
{
$packageIsAlias = $package instanceof AliasPackage;
$providerIsAlias = $provider instanceof AliasPackage;
$impossible = (
($packageIsAlias && $package->getAliasOf() === $provider) ||
($providerIsAlias && $provider->getAliasOf() === $package) ||
($packageIsAlias && $providerIsAlias && $provider->getAliasOf() === $package->getAliasOf())
);
return $impossible;
}
/**
* Adds all rules for all update packages of a given package
*
@ -646,7 +663,15 @@ class Solver
}
if ($literal->isWanted()) {
if ($package instanceof AliasPackage) {
$transaction[] = new Operation\MarkAliasInstalledOperation(
$package, $this->decisionQueueWhy[$i]
);
continue;
}
if (isset($installMeansUpdateMap[$literal->getPackageId()])) {
$source = $installMeansUpdateMap[$literal->getPackageId()];
$transaction[] = new Operation\UpdateOperation(
@ -662,9 +687,47 @@ class Solver
);
}
} else if (!isset($ignoreRemove[$package->getId()])) {
$transaction[] = new Operation\UninstallOperation(
$package, $this->decisionQueueWhy[$i]
);
if ($package instanceof AliasPackage) {
$transaction[] = new Operation\MarkAliasInstalledOperation(
$package, $this->decisionQueueWhy[$i]
);
} else {
$transaction[] = new Operation\UninstallOperation(
$package, $this->decisionQueueWhy[$i]
);
}
}
}
$allDecidedMap = $this->decisionMap;
foreach ($this->decisionMap as $packageId => $decision) {
if ($decision != 0) {
$package = $this->pool->packageById($packageId);
if ($package instanceof AliasPackage) {
$allDecidedMap[$package->getAliasOf()->getId()] = $decision;
}
}
}
foreach ($allDecidedMap as $packageId => $decision) {
if ($packageId === 0) {
continue;
}
if (0 == $decision && isset($this->installedMap[$packageId])) {
$package = $this->pool->packageById($packageId);
if ($package instanceof AliasPackage) {
$transaction[] = new Operation\MarkAliasInstalledOperation(
$package, null
);
} else {
$transaction[] = new Operation\UninstallOperation(
$package, null
);
}
$this->decisionMap[$packageId] = -1;
}
}
@ -674,9 +737,19 @@ class Solver
}
if (0 == $decision && isset($this->installedMap[$packageId])) {
$transaction[] = new Operation\UninstallOperation(
$this->pool->packageById($packageId), null
);
$package = $this->pool->packageById($packageId);
if ($package instanceof AliasPackage) {
$transaction[] = new Operation\MarkAliasInstalledOperation(
$package, null
);
} else {
$transaction[] = new Operation\UninstallOperation(
$package, null
);
}
$this->decisionMap[$packageId] = -1;
}
}
@ -733,7 +806,7 @@ class Solver
protected function decisionsSatisfy(Literal $l)
{
return ($l->isWanted() && $this->decisionMap[$l->getPackageId()] > 0) ||
(!$l->isWanted() && $this->decisionMap[$l->getPackageId()] <= 0);
(!$l->isWanted() && $this->decisionMap[$l->getPackageId()] < 0);
}
protected function decisionsConflict(Literal $l)
@ -876,11 +949,6 @@ class Solver
break;
}
/** TODO: implement recommendations
*if (v > 0 && solv->recommendations.count && v == solv->recommendations.elements[solv->recommendations.count - 1])
* solv->recommendations.count--;
*/
$this->decisionMap[$literal->getPackageId()] = 0;
array_pop($this->decisionQueue);
array_pop($this->decisionQueueWhy);
@ -1060,14 +1128,19 @@ class Solver
$l1num++;
$l1retry = true;
}
$rule = $this->decisionQueueWhy[$decisionId];
}
$rule = $this->decisionQueueWhy[$decisionId];
}
$why = count($this->learnedPool) - 1;
assert($learnedLiterals[0] !== null);
$newRule = new Rule($learnedLiterals, Rule::RULE_LEARNED, $why);
if (count($learnedLiterals) === 1 && $learnedLiterals[0] === null) {
$newRule = new Rule(array(), Rule::RULE_LEARNED, $why);
} else {
assert($learnedLiterals[0] !== null);
$newRule = new Rule($learnedLiterals, Rule::RULE_LEARNED, $why);
}
return array($learnedLiterals[0], $ruleLevel, $newRule, $why);
}
@ -1178,7 +1251,7 @@ class Solver
$this->disableProblem($why);
$this->resetSolver();
return true;
return 1;
}
if ($disableRules) {
@ -1191,10 +1264,10 @@ class Solver
}
$this->resetSolver();
return true;
return 1;
}
return false;
return 0;
}
private function disableProblem($why)
@ -1266,8 +1339,8 @@ class Solver
// * here's the main loop:
// * 1) propagate new decisions (only needed once)
// * 2) fulfill jobs
// * 4) fulfill all unresolved rules
// * 6) minimalize solution if we had choices
// * 3) fulfill all unresolved rules
// * 4) minimalize solution if we had choices
// * if we encounter a problem, we rewind to a safe level and restart
// * with step 1
// */
@ -1403,18 +1476,14 @@ class Solver
return;
}
// open suse sat-solver uses this, but why is $level == 1 trouble?
// SYSTEMSOLVABLE related? we don't have that, so should work
//if ($level < $systemLevel || $level == 1) {
if ($level < $systemLevel) {
break; // trouble
}
// something changed, so look at all rules again
$n = -1;
}
if ($level < $systemLevel) {
continue;
}
// minimization step
if (count($this->branches)) {