From 2cb2cde096ab2b2f4d3d0b5c36fb406ea6856abe Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Fri, 27 Apr 2012 18:13:37 +0200 Subject: [PATCH] Installed packages are now always removed unless otherwise requested This means that an update request must always be accompanied by an install request, otherwise the package might be removed rather than updated. --- src/Composer/DependencyResolver/Solver.php | 135 ++---------------- .../Test/DependencyResolver/SolverTest.php | 31 +++- 2 files changed, 39 insertions(+), 127 deletions(-) diff --git a/src/Composer/DependencyResolver/Solver.php b/src/Composer/DependencyResolver/Solver.php index 15b1f46ea..0cb754284 100644 --- a/src/Composer/DependencyResolver/Solver.php +++ b/src/Composer/DependencyResolver/Solver.php @@ -730,14 +730,12 @@ class Solver } } - // solver_addrpmrulesforweak(solv, &addedmap); - foreach ($this->installedMap as $package) { $updates = $this->policy->findUpdatePackages($this, $this->pool, $this->installedMap, $package); $rule = $this->createUpdateRule($package, $updates, Rule::RULE_INTERNAL_ALLOW_UPDATE, (string) $package); $rule->setWeak(true); - $this->addRule(RuleSet::TYPE_FEATURE, $rule); + //$this->addRule(RuleSet::TYPE_FEATURE, $rule); $this->packageToFeatureRule[$package->getId()] = $rule; } @@ -857,6 +855,18 @@ class Solver } } + foreach ($this->decisionMap as $packageId => $decision) { + if ($packageId === 0) { + continue; + } + + if (0 == $decision && isset($this->installedMap[$packageId])) { + $transaction[] = new Operation\UninstallOperation( + $this->pool->packageById($packageId), null + ); + } + } + return array_reverse($transaction); } @@ -1546,125 +1556,6 @@ class Solver } } - // handle installed packages - if ($level < $systemLevel) { - // use two passes if any packages are being updated - // -> better user experience - for ($pass = (count($this->updateMap)) ? 0 : 1; $pass < 2; $pass++) { - $passLevel = $level; - for ($i = $installedPos, $n = 0; $n < count($this->installedPackages); $i++, $n++) { - $repeat = false; - - if ($i == count($this->installedPackages)) { - $i = 0; - } - $literal = new Literal($this->installedPackages[$i], true); - - if ($this->decisionsContain($literal)) { - continue; - } - - // only process updates in first pass - /** TODO: && or || ? **/ - if (0 === $pass && !isset($this->updateMap[$literal->getPackageId()])) { - continue; - } - - $rule = null; - - if (isset($this->packageToFeatureRule[$literal->getPackageId()])) { - $rule = $this->packageToFeatureRule[$literal->getPackageId()]; - } - - if (!$rule || $rule->isDisabled()) { - continue; - } - - $updateRuleLiterals = $rule->getLiterals(); - - $decisionQueue = array(); - if (!isset($this->noUpdate[$literal->getPackageId()]) && ( - $this->decidedRemove($literal->getPackage()) || - isset($this->updateMap[$literal->getPackageId()]) || - !$literal->equals($updateRuleLiterals[0]) - )) { - foreach ($updateRuleLiterals as $ruleLiteral) { - if ($this->decidedInstall($ruleLiteral->getPackage())) { - // already fulfilled - $decisionQueue = array(); - break; - } - if ($this->undecided($ruleLiteral->getPackage())) { - $decisionQueue[] = $ruleLiteral; - } - } - } - - if (sizeof($decisionQueue)) { - $oLevel = $level; - $level = $this->selectAndInstall($level, $decisionQueue, $disableRules, $rule); - - if (0 === $level) { - return; - } - - if ($level <= $oLevel) { - $repeat = true; - } - } else if (!$repeat && $this->undecided($literal->getPackage())) { - // still undecided? keep package. - $oLevel = $level; - if (isset($this->cleanDepsMap[$literal->getPackageId()])) { - // clean deps removes package - $level = $this->setPropagateLearn($level, $literal->invert(), $disableRules, null); - } else { - // ckeeping package - $level = $this->setPropagateLearn($level, $literal, $disableRules, $rule); - } - - - if (0 === $level) { - return; - } - - if ($level <= $oLevel) { - $repeat = true; - } - } - - if ($repeat) { - if (1 === $level || $level < $passLevel) { - // trouble - break; - } - if ($level < $oLevel) { - // redo all - $n = 0; - } - - // repeat - $i--; - $n--; - continue; - } - } - - if ($n < count($this->installedPackages)) { - $installedPos = $i; // retry this problem next time - break; - } - - $installedPos = 0; - } - - $systemLevel = $level + 1; - - if ($pass < 2) { - // had trouble => retry - continue; - } - } - if ($level < $systemLevel) { $systemLevel = $level; } diff --git a/tests/Composer/Test/DependencyResolver/SolverTest.php b/tests/Composer/Test/DependencyResolver/SolverTest.php index 49355a5a4..2bc5a928a 100644 --- a/tests/Composer/Test/DependencyResolver/SolverTest.php +++ b/tests/Composer/Test/DependencyResolver/SolverTest.php @@ -54,6 +54,16 @@ class SolverTest extends TestCase )); } + public function testSolverRemoveIfNotInstalled() + { + $this->repoInstalled->addPackage($packageA = $this->getPackage('A', '1.0')); + $this->reposComplete(); + + $this->checkSolverResult(array( + array('job' => 'remove', 'package' => $packageA), + )); + } + public function testInstallNonExistingPackageFails() { $this->repo->addPackage($this->getPackage('A', '1.0')); @@ -176,6 +186,7 @@ class SolverTest extends TestCase $this->repo->addPackage($newPackageA = $this->getPackage('A', '1.1')); $this->reposComplete(); + $this->request->install('A'); $this->request->update('A'); $this->checkSolverResult(array( @@ -191,6 +202,7 @@ class SolverTest extends TestCase $this->repo->addPackage($newPackageB = $this->getPackage('B', '1.1')); $packageA->setRequires(array(new Link('A', 'B', null, 'requires'))); + $newPackageA->setRequires(array(new Link('A', 'B', null, 'requires'))); $this->reposComplete(); @@ -209,6 +221,7 @@ class SolverTest extends TestCase $this->repo->addPackage($this->getPackage('A', '1.0')); $this->reposComplete(); + $this->request->install('A'); $this->request->update('A'); $this->checkSolverResult(array()); @@ -223,6 +236,8 @@ class SolverTest extends TestCase $this->reposComplete(); + $this->request->install('A'); + $this->request->install('B'); $this->request->update('A'); $this->checkSolverResult(array( @@ -267,7 +282,7 @@ class SolverTest extends TestCase public function testSolverUpdateFullyConstrainedPrunesInstalledPackages() { $this->repoInstalled->addPackage($packageA = $this->getPackage('A', '1.0')); - $this->repoInstalled->addPackage($this->getPackage('B', '1.0')); + $this->repoInstalled->addPackage($packageB = $this->getPackage('B', '1.0')); $this->repo->addPackage($newPackageA = $this->getPackage('A', '1.2')); $this->repo->addPackage($this->getPackage('A', '2.0')); $this->reposComplete(); @@ -275,10 +290,15 @@ class SolverTest extends TestCase $this->request->install('A', $this->getVersionConstraint('<', '2.0.0.0')); $this->request->update('A', $this->getVersionConstraint('=', '1.0.0.0')); - $this->checkSolverResult(array(array( - 'job' => 'update', - 'from' => $packageA, - 'to' => $newPackageA, + $this->checkSolverResult(array( + array( + 'job' => 'remove', + 'package' => $packageB, + ), + array( + 'job' => 'update', + 'from' => $packageA, + 'to' => $newPackageA, ))); } @@ -297,6 +317,7 @@ class SolverTest extends TestCase $this->reposComplete(); $this->request->install('A'); + $this->request->install('C'); $this->request->update('C'); $this->request->remove('D');