diff --git a/src/Composer/DependencyResolver/RuleSet.php b/src/Composer/DependencyResolver/RuleSet.php
index 1f444c788..9e8ecf29b 100644
--- a/src/Composer/DependencyResolver/RuleSet.php
+++ b/src/Composer/DependencyResolver/RuleSet.php
@@ -20,16 +20,12 @@ class RuleSet implements \IteratorAggregate, \Countable
// highest priority => lowest number
const TYPE_PACKAGE = 0;
const TYPE_JOB = 1;
- const TYPE_FEATURE = 3;
- const TYPE_CHOICE = 4;
- const TYPE_LEARNED = 5;
+ const TYPE_LEARNED = 4;
protected static $types = array(
-1 => 'UNKNOWN',
self::TYPE_PACKAGE => 'PACKAGE',
- self::TYPE_FEATURE => 'FEATURE',
self::TYPE_JOB => 'JOB',
- self::TYPE_CHOICE => 'CHOICE',
self::TYPE_LEARNED => 'LEARNED',
);
diff --git a/src/Composer/DependencyResolver/Solver.php b/src/Composer/DependencyResolver/Solver.php
index aa014035c..afa8f6996 100644
--- a/src/Composer/DependencyResolver/Solver.php
+++ b/src/Composer/DependencyResolver/Solver.php
@@ -30,13 +30,21 @@ class Solver
protected $ruleToJob = array();
protected $addedMap = array();
protected $updateMap = array();
- protected $noObsoletes = array();
protected $watches = array();
protected $removeWatches = array();
protected $decisionMap;
protected $installedMap;
- protected $packageToFeatureRule = array();
+ protected $packageToUpdateRule = array();
+
+ protected $decisionQueue = array();
+ protected $decisionQueueWhy = array();
+ protected $decisionQueueFree = array();
+ protected $propagateIndex;
+ protected $branches = array();
+ protected $problems = array();
+ protected $learnedPool = array();
+ protected $recommendsIndex;
public function __construct(PolicyInterface $policy, Pool $pool, RepositoryInterface $installed)
{
@@ -237,50 +245,38 @@ class Solver
}
// check obsoletes and implicit obsoletes of a package
- // if ignoreinstalledsobsoletes is not set, we're also checking
- // obsoletes of installed packages (like newer rpm versions)
- //
- /** TODO if ($this->noInstalledObsoletes) */
- if (true) {
- $noObsoletes = isset($this->noObsoletes[$package->getId()]);
- $isInstalled = (isset($this->installedMap[$package->getId()]));
+ $isInstalled = (isset($this->installedMap[$package->getId()]));
- foreach ($package->getReplaces() as $link) {
- $obsoleteProviders = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
+ foreach ($package->getReplaces() as $link) {
+ $obsoleteProviders = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
- foreach ($obsoleteProviders as $provider) {
- if ($provider === $package) {
- continue;
- }
-
- $reason = ($isInstalled) ? Rule::RULE_INSTALLED_PACKAGE_OBSOLETES : Rule::RULE_PACKAGE_OBSOLETES;
- $this->addRule(RuleSet::TYPE_PACKAGE, $this->createConflictRule($package, $provider, $reason, (string) $link));
+ foreach ($obsoleteProviders as $provider) {
+ if ($provider === $package) {
+ continue;
}
+
+ $reason = ($isInstalled) ? Rule::RULE_INSTALLED_PACKAGE_OBSOLETES : Rule::RULE_PACKAGE_OBSOLETES;
+ $this->addRule(RuleSet::TYPE_PACKAGE, $this->createConflictRule($package, $provider, $reason, (string) $link));
}
+ }
- // check implicit obsoletes
- // for installed packages we only need to check installed/installed problems,
- // as the others are picked up when looking at the uninstalled package.
- if (!$isInstalled) {
- $obsoleteProviders = $this->pool->whatProvides($package->getName(), null);
+ // check implicit obsoletes
+ // for installed packages we only need to check installed/installed problems,
+ // as the others are picked up when looking at the uninstalled package.
+ if (!$isInstalled) {
+ $obsoleteProviders = $this->pool->whatProvides($package->getName(), null);
- foreach ($obsoleteProviders as $provider) {
- if ($provider === $package) {
- continue;
- }
-
- if ($isInstalled && !isset($this->installedMap[$provider->getId()])) {
- continue;
- }
-
- // obsolete same packages even when noObsoletes
- if ($noObsoletes && (!$package->equals($provider))) {
- continue;
- }
-
- $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));
+ foreach ($obsoleteProviders as $provider) {
+ if ($provider === $package) {
+ continue;
}
+
+ if ($isInstalled && !isset($this->installedMap[$provider->getId()])) {
+ continue;
+ }
+
+ $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));
}
}
}
@@ -431,7 +427,7 @@ class Solver
// push all of our rules (can only be feature or job rules)
// asserting this literal on the problem stack
- foreach ($this->rules->getIteratorFor(array(RuleSet::TYPE_JOB, RuleSet::TYPE_FEATURE)) as $assertRule) {
+ foreach ($this->rules->getIteratorFor(RuleSet::TYPE_JOB) as $assertRule) {
if ($assertRule->isDisabled() || !$assertRule->isAssertion() || $assertRule->isWeak()) {
continue;
}
@@ -492,370 +488,22 @@ class Solver
}
$this->disableProblem($why);
- /** TODO solver_reenablepolicyrules(solv, -(v + 1)); */
}
}
- protected function addChoiceRules()
+ protected function setupInstalledMap()
{
-
-// void
-// solver_addchoicerules(Solver *solv)
-// {
-// Pool *pool = solv->pool;
-// Map m, mneg;
-// Rule *r;
-// Queue q, qi;
-// int i, j, rid, havechoice;
-// Id p, d, *pp;
-// Id p2, pp2;
-// Solvable *s, *s2;
-//
-// solv->choicerules = solv->nrules;
-// if (!pool->installed)
-// {
-// solv->choicerules_end = solv->nrules;
-// return;
-// }
-// solv->choicerules_ref = sat_calloc(solv->rpmrules_end, sizeof(Id));
-// queue_init(&q);
-// queue_init(&qi);
-// map_init(&m, pool->nsolvables);
-// map_init(&mneg, pool->nsolvables);
-// /* set up negative assertion map from infarch and dup rules */
-// for (rid = solv->infarchrules, r = solv->rules + rid; rid < solv->infarchrules_end; rid++, r++)
-// if (r->p < 0 && !r->w2 && (r->d == 0 || r->d == -1))
-// MAPSET(&mneg, -r->p);
-// for (rid = solv->duprules, r = solv->rules + rid; rid < solv->duprules_end; rid++, r++)
-// if (r->p < 0 && !r->w2 && (r->d == 0 || r->d == -1))
-// MAPSET(&mneg, -r->p);
-// for (rid = 1; rid < solv->rpmrules_end ; rid++)
-// {
-// r = solv->rules + rid;
-// if (r->p >= 0 || ((r->d == 0 || r->d == -1) && r->w2 < 0))
-// continue; /* only look at requires rules */
-// // solver_printrule(solv, SAT_DEBUG_RESULT, r);
-// queue_empty(&q);
-// queue_empty(&qi);
-// havechoice = 0;
-// FOR_RULELITERALS(p, pp, r)
-// {
-// if (p < 0)
-// continue;
-// s = pool->solvables + p;
-// if (!s->repo)
-// continue;
-// if (s->repo == pool->installed)
-// {
-// queue_push(&q, p);
-// continue;
-// }
-// /* check if this package is "blocked" by a installed package */
-// s2 = 0;
-// FOR_PROVIDES(p2, pp2, s->name)
-// {
-// s2 = pool->solvables + p2;
-// if (s2->repo != pool->installed)
-// continue;
-// if (!pool->implicitobsoleteusesprovides && s->name != s2->name)
-// continue;
-// if (pool->obsoleteusescolors && !pool_colormatch(pool, s, s2))
-// continue;
-// break;
-// }
-// if (p2)
-// {
-// /* found installed package p2 that we can update to p */
-// if (MAPTST(&mneg, p))
-// continue;
-// if (policy_is_illegal(solv, s2, s, 0))
-// continue;
-// queue_push(&qi, p2);
-// queue_push(&q, p);
-// continue;
-// }
-// if (s->obsoletes)
-// {
-// Id obs, *obsp = s->repo->idarraydata + s->obsoletes;
-// s2 = 0;
-// while ((obs = *obsp++) != 0)
-// {
-// FOR_PROVIDES(p2, pp2, obs)
-// {
-// s2 = pool->solvables + p2;
-// if (s2->repo != pool->installed)
-// continue;
-// if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, pool->solvables + p2, obs))
-// continue;
-// if (pool->obsoleteusescolors && !pool_colormatch(pool, s, s2))
-// continue;
-// break;
-// }
-// if (p2)
-// break;
-// }
-// if (obs)
-// {
-// /* found installed package p2 that we can update to p */
-// if (MAPTST(&mneg, p))
-// continue;
-// if (policy_is_illegal(solv, s2, s, 0))
-// continue;
-// queue_push(&qi, p2);
-// queue_push(&q, p);
-// continue;
-// }
-// }
-// /* package p is independent of the installed ones */
-// havechoice = 1;
-// }
-// if (!havechoice || !q.count)
-// continue; /* no choice */
-//
-// /* now check the update rules of the installed package.
-// * if all packages of the update rules are contained in
-// * the dependency rules, there's no need to set up the choice rule */
-// map_empty(&m);
-// FOR_RULELITERALS(p, pp, r)
-// if (p > 0)
-// MAPSET(&m, p);
-// for (i = 0; i < qi.count; i++)
-// {
-// if (!qi.elements[i])
-// continue;
-// Rule *ur = solv->rules + solv->updaterules + (qi.elements[i] - pool->installed->start);
-// if (!ur->p)
-// ur = solv->rules + solv->featurerules + (qi.elements[i] - pool->installed->start);
-// if (!ur->p)
-// continue;
-// FOR_RULELITERALS(p, pp, ur)
-// if (!MAPTST(&m, p))
-// break;
-// if (p)
-// break;
-// for (j = i + 1; j < qi.count; j++)
-// if (qi.elements[i] == qi.elements[j])
-// qi.elements[j] = 0;
-// }
-// if (i == qi.count)
-// {
-// #if 0
-// printf("skipping choice ");
-// solver_printrule(solv, SAT_DEBUG_RESULT, solv->rules + rid);
-// #endif
-// continue;
-// }
-// d = q.count ? pool_queuetowhatprovides(pool, &q) : 0;
-// solver_addrule(solv, r->p, d);
-// queue_push(&solv->weakruleq, solv->nrules - 1);
-// solv->choicerules_ref[solv->nrules - 1 - solv->choicerules] = rid;
-// #if 0
-// printf("OLD ");
-// solver_printrule(solv, SAT_DEBUG_RESULT, solv->rules + rid);
-// printf("WEAK CHOICE ");
-// solver_printrule(solv, SAT_DEBUG_RESULT, solv->rules + solv->nrules - 1);
-// #endif
-// }
-// queue_free(&q);
-// queue_free(&qi);
-// map_free(&m);
-// map_free(&mneg);
-// solv->choicerules_end = solv->nrules;
-// }
- }
-
-/***********************************************************************
- ***
- *** Policy rule disabling/reenabling
- ***
- *** Disable all policy rules that conflict with our jobs. If a job
- *** gets disabled later on, reenable the involved policy rules again.
- ***
- *** /
-
-#define DISABLE_UPDATE 1
-#define DISABLE_INFARCH 2
-#define DISABLE_DUP 3
-*/
- protected function jobToDisableQueue(array $job, array $disableQueue)
- {
- switch ($job['cmd']) {
- case 'install':
- foreach ($job['packages'] as $package) {
- if (isset($this->installedMap[$package->getId()])) {
- $disableQueue[] = array('type' => 'update', 'package' => $package);
- }
-
- /* all job packages obsolete * /
- qstart = q->count;
- pass = 0;
- memset(&omap, 0, sizeof(omap));
- FOR_JOB_SELECT(p, pp, select, what)
- {
- Id p2, pp2;
-
- if (pass == 1)
- map_grow(&omap, installed->end - installed->start);
- s = pool->solvables + p;
- if (s->obsoletes)
- {
- Id obs, *obsp;
- obsp = s->repo->idarraydata + s->obsoletes;
- while ((obs = *obsp++) != 0)
- FOR_PROVIDES(p2, pp2, obs)
- {
- Solvable *ps = pool->solvables + p2;
- if (ps->repo != installed)
- continue;
- if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, ps, obs))
- continue;
- if (pool->obsoleteusescolors && !pool_colormatch(pool, s, ps))
- continue;
- if (pass)
- MAPSET(&omap, p2 - installed->start);
- else
- queue_push2(q, DISABLE_UPDATE, p2);
- }
- }
- FOR_PROVIDES(p2, pp2, s->name)
- {
- Solvable *ps = pool->solvables + p2;
- if (ps->repo != installed)
- continue;
- if (!pool->implicitobsoleteusesprovides && ps->name != s->name)
- continue;
- if (pool->obsoleteusescolors && !pool_colormatch(pool, s, ps))
- continue;
- if (pass)
- MAPSET(&omap, p2 - installed->start);
- else
- queue_push2(q, DISABLE_UPDATE, p2);
- }
- if (pass)
- {
- for (i = j = qstart; i < q->count; i += 2)
- {
- if (MAPTST(&omap, q->elements[i + 1] - installed->start))
- {
- MAPCLR(&omap, q->elements[i + 1] - installed->start);
- q->elements[j + 1] = q->elements[i + 1];
- j += 2;
- }
- }
- queue_truncate(q, j);
- }
- if (q->count == qstart)
- break;
- pass++;
- }
- if (omap.size)
- map_free(&omap);
-
- if (qstart == q->count)
- return; /* nothing to prune * /
- if ((set & (SOLVER_SETEVR | SOLVER_SETARCH | SOLVER_SETVENDOR)) == (SOLVER_SETEVR | SOLVER_SETARCH | SOLVER_SETVENDOR))
- return; /* all is set */
-
- /* now that we know which installed packages are obsoleted check each of them * /
- for (i = j = qstart; i < q->count; i += 2)
- {
- Solvable *is = pool->solvables + q->elements[i + 1];
- FOR_JOB_SELECT(p, pp, select, what)
- {
- int illegal = 0;
- s = pool->solvables + p;
- if ((set & SOLVER_SETEVR) != 0)
- illegal |= POLICY_ILLEGAL_DOWNGRADE; /* ignore * /
- if ((set & SOLVER_SETARCH) != 0)
- illegal |= POLICY_ILLEGAL_ARCHCHANGE; /* ignore * /
- if ((set & SOLVER_SETVENDOR) != 0)
- illegal |= POLICY_ILLEGAL_VENDORCHANGE; /* ignore * /
- illegal = policy_is_illegal(solv, is, s, illegal);
- if (illegal && illegal == POLICY_ILLEGAL_DOWNGRADE && (set & SOLVER_SETEV) != 0)
- {
- /* it's ok if the EV is different * /
- if (evrcmp(pool, is->evr, s->evr, EVRCMP_COMPARE_EVONLY) != 0)
- illegal = 0;
- }
- if (illegal)
- break;
- }
- if (!p)
- {
- /* no package conflicts with the update rule * /
- /* thus keep the DISABLE_UPDATE * /
- q->elements[j + 1] = q->elements[i + 1];
- j += 2;
- }
- }
- queue_truncate(q, j);
- return;*/
- }
- break;
-
- case 'remove':
- foreach ($job['packages'] as $package) {
- if (isset($this->installedMap[$package->getId()])) {
- $disableQueue[] = array('type' => 'update', 'package' => $package);
- }
- }
- break;
- }
-
- return $disableQueue;
- }
-
- protected function disableUpdateRule($package)
- {
- if (isset($this->packageToFeatureRule[$package->getId()])) {
- $this->packageToFeatureRule[$package->getId()]->disable();
- }
- }
-
- /**
- * Disables all policy rules that conflict with jobs
- */
- protected function disablePolicyRules()
- {
- $lastJob = null;
- $allQueue = array();
-
- $iterator = $this->rules->getIteratorFor(RuleSet::TYPE_JOB);
- foreach ($iterator as $rule) {
- if ($rule->isDisabled()) {
- continue;
- }
-
- $job = $this->ruleToJob[$rule->getId()];
-
- if ($job === $lastJob) {
- continue;
- }
-
- $lastJob = $job;
-
- $allQueue = $this->jobToDisableQueue($job, $allQueue);
- }
-
- foreach ($allQueue as $disable) {
- switch ($disable['type']) {
- case 'update':
- $this->disableUpdateRule($disable['package']);
- break;
- default:
- throw new \RuntimeException("Unsupported disable type: " . $disable['type']);
- }
+ $this->installedMap = array();
+ foreach ($this->installed->getPackages() as $package) {
+ $this->installedMap[$package->getId()] = $package;
}
}
public function solve(Request $request)
{
$this->jobs = $request->getJobs();
- $installedPackages = $this->installed->getPackages();
- $this->installedMap = array();
- foreach ($installedPackages as $package) {
- $this->installedMap[$package->getId()] = $package;
- }
+
+ $this->setupInstalledMap();
if (version_compare(PHP_VERSION, '5.3.4', '>=')) {
$this->decisionMap = new \SplFixedArray($this->pool->getMaxId() + 1);
@@ -876,18 +524,18 @@ class Solver
switch ($job['cmd']) {
case 'update-all':
- foreach ($installedPackages as $package) {
+ foreach ($this->installedMap as $package) {
$this->updateMap[$package->getId()] = true;
}
break;
}
}
- foreach ($installedPackages as $package) {
+ foreach ($this->installedMap as $package) {
$this->addRulesForPackage($package);
}
- foreach ($installedPackages as $package) {
+ foreach ($this->installedMap as $package) {
$this->addRulesForUpdatePackages($package);
}
@@ -903,15 +551,11 @@ class Solver
}
}
- // solver_addrpmrulesforweak(solv, &addedmap);
-
- foreach ($installedPackages as $package) {
+ 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->packageToFeatureRule[$package->getId()] = $rule;
+ $this->packageToUpdateRule[$package->getId()] = $rule;
}
foreach ($this->jobs as $job) {
@@ -952,23 +596,15 @@ class Solver
}
}
- $this->addChoiceRules();
-
foreach ($this->rules as $rule) {
$this->addWatchesToRule($rule);
}
- /* disable update rules that conflict with our job */
- $this->disablePolicyRules();
-
/* make decisions based on job/update assertions */
$this->makeAssertionRuleDecisions();
$installRecommended = 0;
$this->runSat(true, $installRecommended);
- //$this->printDecisionMap();
- //findrecommendedsuggested(solv);
- //solver_prepare_solutions(solv);
if ($this->problems) {
throw new SolverProblemsException($this->problems);
@@ -989,8 +625,8 @@ class Solver
if (!$literal->isWanted() && isset($this->installedMap[$package->getId()])) {
$literals = array();
- if (isset($this->packageToFeatureRule[$package->getId()])) {
- $literals = array_merge($literals, $this->packageToFeatureRule[$package->getId()]->getLiterals());
+ if (isset($this->packageToUpdateRule[$package->getId()])) {
+ $literals = array_merge($literals, $this->packageToUpdateRule[$package->getId()]->getLiterals());
}
foreach ($literals as $updateLiteral) {
@@ -1032,18 +668,21 @@ 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);
}
- protected $decisionQueue = array();
- protected $decisionQueueWhy = array();
- protected $decisionQueueFree = array();
- protected $propagateIndex;
- protected $branches = array();
- protected $problems = array();
- protected $learnedPool = array();
- protected $recommendsIndex;
-
protected function literalFromId($id)
{
$package = $this->pool->packageById(abs($id));
@@ -1536,17 +1175,7 @@ class Solver
$why = $lastWeakWhy;
}
- if ($lastWeakWhy->getType() == RuleSet::TYPE_CHOICE) {
- $this->disableChoiceRules($lastWeakWhy);
- }
-
$this->disableProblem($why);
-
- /**
-@TODO what does v < 0 mean here? ($why == v)
- if (v < 0)
- solver_reenablepolicyrules(solv, -(v + 1));
-*/
$this->resetSolver();
return true;
@@ -1637,9 +1266,7 @@ class Solver
// * here's the main loop:
// * 1) propagate new decisions (only needed once)
// * 2) fulfill jobs
- // * 3) try to keep installed packages
// * 4) fulfill all unresolved rules
- // * 5) install recommended packages
// * 6) minimalize solution if we had choices
// * if we encounter a problem, we rewind to a safe level and restart
// * with step 1
@@ -1654,8 +1281,6 @@ class Solver
$minimizationSteps = 0;
$installedPos = 0;
- $this->installedPackages = $this->installed->getPackages();
-
while (true) {
if (1 === $level) {
@@ -1727,125 +1352,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/src/Composer/Downloader/FileDownloader.php b/src/Composer/Downloader/FileDownloader.php
index 356934514..3e15acf80 100644
--- a/src/Composer/Downloader/FileDownloader.php
+++ b/src/Composer/Downloader/FileDownloader.php
@@ -64,7 +64,7 @@ class FileDownloader implements DownloaderInterface
$fileName = $this->getFileName($package, $path);
- $this->io->write(" - Package " . $package->getName() . " (" . $package->getPrettyVersion() . ")");
+ $this->io->write(" - Installing " . $package->getName() . " (" . $package->getPrettyVersion() . ")");
$processUrl = $this->processUrl($url);
@@ -101,6 +101,7 @@ class FileDownloader implements DownloaderInterface
*/
public function remove(PackageInterface $package, $path)
{
+ $this->io->write(" - Removing " . $package->getName() . " (" . $package->getPrettyVersion() . ")");
if (!$this->filesystem->removeDirectory($path)) {
throw new \RuntimeException('Could not completely delete '.$path.', aborting.');
}
diff --git a/src/Composer/Downloader/VcsDownloader.php b/src/Composer/Downloader/VcsDownloader.php
index 2d19bba40..cacc74fc4 100644
--- a/src/Composer/Downloader/VcsDownloader.php
+++ b/src/Composer/Downloader/VcsDownloader.php
@@ -50,7 +50,7 @@ abstract class VcsDownloader implements DownloaderInterface
throw new \InvalidArgumentException('Package '.$package->getPrettyName().' is missing reference information');
}
- $this->io->write(" - Package " . $package->getName() . " (" . $package->getPrettyVersion() . ")");
+ $this->io->write(" - Installing " . $package->getName() . " (" . $package->getPrettyVersion() . ")");
$this->filesystem->removeDirectory($path);
$this->doDownload($package, $path);
$this->io->write('');
@@ -65,7 +65,7 @@ abstract class VcsDownloader implements DownloaderInterface
throw new \InvalidArgumentException('Package '.$target->getPrettyName().' is missing reference information');
}
- $this->io->write(" - Package " . $target->getName() . " (" . $target->getPrettyVersion() . ")");
+ $this->io->write(" - Installing " . $target->getName() . " (" . $target->getPrettyVersion() . ")");
$this->enforceCleanDirectory($path);
$this->doUpdate($initial, $target, $path);
$this->io->write('');
@@ -77,6 +77,7 @@ abstract class VcsDownloader implements DownloaderInterface
public function remove(PackageInterface $package, $path)
{
$this->enforceCleanDirectory($path);
+ $this->io->write(" - Removing " . $package->getName() . " (" . $package->getPrettyVersion() . ")");
if (!$this->filesystem->removeDirectory($path)) {
throw new \RuntimeException('Could not completely delete '.$path.', aborting.');
}
diff --git a/src/Composer/Installer.php b/src/Composer/Installer.php
index e4219c860..d7f51badb 100644
--- a/src/Composer/Installer.php
+++ b/src/Composer/Installer.php
@@ -259,9 +259,11 @@ class Installer
}
}
- // fix the version all installed packages that are not in the current local repo to prevent rogue updates
+ // fix the version of all installed packages (+ platform) that are not
+ // in the current local repo to prevent rogue updates (e.g. non-dev
+ // updating when in dev)
foreach ($installedRepo->getPackages() as $package) {
- if ($package->getRepository() === $localRepo || $package->getRepository() instanceof PlatformRepository) {
+ if ($package->getRepository() === $localRepo) {
continue;
}
diff --git a/src/Composer/Installer/LibraryInstaller.php b/src/Composer/Installer/LibraryInstaller.php
index 0da923654..9be2e1d1d 100644
--- a/src/Composer/Installer/LibraryInstaller.php
+++ b/src/Composer/Installer/LibraryInstaller.php
@@ -127,6 +127,13 @@ class LibraryInstaller implements InstallerInterface
$this->downloadManager->remove($package, $downloadPath);
$this->removeBinaries($package);
$repo->removePackage($package);
+
+ if (strpos($package->getName(), '/')) {
+ $packageVendorDir = dirname($downloadPath);
+ if (is_dir($packageVendorDir) && !glob($packageVendorDir.'/*')) {
+ @rmdir($packageVendorDir);
+ }
+ }
}
/**
diff --git a/tests/Composer/Test/DependencyResolver/RuleSetIteratorTest.php b/tests/Composer/Test/DependencyResolver/RuleSetIteratorTest.php
index 28db18131..56084f32a 100644
--- a/tests/Composer/Test/DependencyResolver/RuleSetIteratorTest.php
+++ b/tests/Composer/Test/DependencyResolver/RuleSetIteratorTest.php
@@ -27,7 +27,7 @@ class ResultSetIteratorTest extends \PHPUnit_Framework_TestCase
new Rule(array(), 'job1', null),
new Rule(array(), 'job2', null),
),
- RuleSet::TYPE_FEATURE => array(
+ RuleSet::TYPE_LEARNED => array(
new Rule(array(), 'update1', null),
),
RuleSet::TYPE_PACKAGE => array(),
@@ -46,7 +46,7 @@ class ResultSetIteratorTest extends \PHPUnit_Framework_TestCase
$expected = array(
$this->rules[RuleSet::TYPE_JOB][0],
$this->rules[RuleSet::TYPE_JOB][1],
- $this->rules[RuleSet::TYPE_FEATURE][0],
+ $this->rules[RuleSet::TYPE_LEARNED][0],
);
$this->assertEquals($expected, $result);
@@ -64,7 +64,7 @@ class ResultSetIteratorTest extends \PHPUnit_Framework_TestCase
$expected = array(
RuleSet::TYPE_JOB,
RuleSet::TYPE_JOB,
- RuleSet::TYPE_FEATURE,
+ RuleSet::TYPE_LEARNED,
);
$this->assertEquals($expected, $result);
diff --git a/tests/Composer/Test/DependencyResolver/RuleSetTest.php b/tests/Composer/Test/DependencyResolver/RuleSetTest.php
index 54ad88a58..f319651ae 100644
--- a/tests/Composer/Test/DependencyResolver/RuleSetTest.php
+++ b/tests/Composer/Test/DependencyResolver/RuleSetTest.php
@@ -27,17 +27,15 @@ class RuleSetTest extends TestCase
new Rule(array(), 'job1', null),
new Rule(array(), 'job2', null),
),
- RuleSet::TYPE_FEATURE => array(
+ RuleSet::TYPE_LEARNED => array(
new Rule(array(), 'update1', null),
),
- RuleSet::TYPE_LEARNED => array(),
- RuleSet::TYPE_CHOICE => array(),
);
$ruleSet = new RuleSet;
$ruleSet->add($rules[RuleSet::TYPE_JOB][0], RuleSet::TYPE_JOB);
- $ruleSet->add($rules[RuleSet::TYPE_FEATURE][0], RuleSet::TYPE_FEATURE);
+ $ruleSet->add($rules[RuleSet::TYPE_LEARNED][0], RuleSet::TYPE_LEARNED);
$ruleSet->add($rules[RuleSet::TYPE_JOB][1], RuleSet::TYPE_JOB);
$this->assertEquals($rules, $ruleSet->getRules());
@@ -80,7 +78,7 @@ class RuleSetTest extends TestCase
$rule1 = new Rule(array(), 'job1', null);
$rule2 = new Rule(array(), 'job1', null);
$ruleSet->add($rule1, RuleSet::TYPE_JOB);
- $ruleSet->add($rule2, RuleSet::TYPE_FEATURE);
+ $ruleSet->add($rule2, RuleSet::TYPE_LEARNED);
$iterator = $ruleSet->getIterator();
@@ -96,9 +94,9 @@ class RuleSetTest extends TestCase
$rule2 = new Rule(array(), 'job1', null);
$ruleSet->add($rule1, RuleSet::TYPE_JOB);
- $ruleSet->add($rule2, RuleSet::TYPE_FEATURE);
+ $ruleSet->add($rule2, RuleSet::TYPE_LEARNED);
- $iterator = $ruleSet->getIteratorFor(RuleSet::TYPE_FEATURE);
+ $iterator = $ruleSet->getIteratorFor(RuleSet::TYPE_LEARNED);
$this->assertSame($rule2, $iterator->current());
}
@@ -110,7 +108,7 @@ class RuleSetTest extends TestCase
$rule2 = new Rule(array(), 'job1', null);
$ruleSet->add($rule1, RuleSet::TYPE_JOB);
- $ruleSet->add($rule2, RuleSet::TYPE_FEATURE);
+ $ruleSet->add($rule2, RuleSet::TYPE_LEARNED);
$iterator = $ruleSet->getIteratorWithout(RuleSet::TYPE_JOB);
@@ -142,7 +140,7 @@ class RuleSetTest extends TestCase
->method('equal')
->will($this->returnValue(false));
- $ruleSet->add($rule, RuleSet::TYPE_FEATURE);
+ $ruleSet->add($rule, RuleSet::TYPE_LEARNED);
$this->assertTrue($ruleSet->containsEqual($rule));
$this->assertFalse($ruleSet->containsEqual($rule2));
@@ -155,9 +153,9 @@ class RuleSetTest extends TestCase
$literal = new Literal($this->getPackage('foo', '2.1'), true);
$rule = new Rule(array($literal), 'job1', null);
- $ruleSet->add($rule, RuleSet::TYPE_FEATURE);
+ $ruleSet->add($rule, RuleSet::TYPE_JOB);
- $this->assertContains('FEATURE : (+foo-2.1.0.0)', $ruleSet->__toString());
+ $this->assertContains('JOB : (+foo-2.1.0.0)', $ruleSet->__toString());
}
private function getRuleMock()
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');