From cb0aa2685e94d23a6bd9f0cda0fb8ce3cb5fbde6 Mon Sep 17 00:00:00 2001 From: Michael Schroeder Date: Thu, 15 Nov 2012 17:27:59 +0100 Subject: [PATCH] implement update to specific update targets --- bindings/solv.i | 6 ++ examples/solv.c | 16 +--- src/libsolv.ver | 1 + src/solver.c | 228 ++++++++++++++++++++++++++++++++++++++++++++++++++------ src/solver.h | 3 + 5 files changed, 219 insertions(+), 35 deletions(-) diff --git a/bindings/solv.i b/bindings/solv.i index 3fdd4a8..2dc04bb 100644 --- a/bindings/solv.i +++ b/bindings/solv.i @@ -801,6 +801,12 @@ typedef struct { pool_job2solvables($self->pool, &q, $self->how, $self->what); return q; } +#ifdef SWIGRUBY + %rename("isemptyupdate?") isemptyupdate; +#endif + bool isemptyupdate() { + return pool_isemptyupdatejob($self->pool, $self->how, $self->what); + } bool __eq__(Job *j) { return $self->pool == j->pool && $self->how == j->how && $self->what == j->what; diff --git a/examples/solv.c b/examples/solv.c index 707b775..25575e1 100644 --- a/examples/solv.c +++ b/examples/solv.c @@ -2773,21 +2773,9 @@ main(int argc, char **argv) // add mode for (i = 0; i < job.count; i += 2) { - if (mode == SOLVER_UPDATE) - { - /* make update of not installed packages an install */ - FOR_JOB_SELECT(p, pp, job.elements[i], job.elements[i + 1]) - if (pool->installed && pool->solvables[p].repo == pool->installed) - break; - if (!p) - { - job.elements[i] |= SOLVER_INSTALL; - if (cleandeps) - job.elements[i] |= SOLVER_CLEANDEPS; - continue; - } - } job.elements[i] |= mode; + if (mode == SOLVER_UPDATE && pool_isemptyupdatejob(pool, job.elements[i], job.elements[i + 1])) + job.elements[i] ^= SOLVER_UPDATE ^ SOLVER_INSTALL; if (cleandeps) job.elements[i] |= SOLVER_CLEANDEPS; } diff --git a/src/libsolv.ver b/src/libsolv.ver index 1745473..6262777 100644 --- a/src/libsolv.ver +++ b/src/libsolv.ver @@ -71,6 +71,7 @@ SOLV_1.0 { pool_id2langid; pool_id2rel; pool_id2str; + pool_isemptyupdatejob; pool_job2solvables; pool_job2str; pool_lookup_bin_checksum; diff --git a/src/solver.c b/src/solver.c index 323d2be..22a992e 100644 --- a/src/solver.c +++ b/src/solver.c @@ -23,6 +23,7 @@ #include "pool.h" #include "util.h" #include "policy.h" +#include "poolarch.h" #include "solverdebug.h" #define RULES_BLOCK 63 @@ -1424,6 +1425,11 @@ solver_free(Solver *solv) queue_free(solv->cleandeps_mistakes); solv->cleandeps_mistakes = solv_free(solv->cleandeps_mistakes); } + if (solv->update_targets) + { + queue_free(solv->update_targets); + solv->update_targets = solv_free(solv->update_targets); + } map_free(&solv->recommendsmap); map_free(&solv->suggestsmap); @@ -1581,6 +1587,24 @@ cleandeps_check_mistakes(Solver *solv, int level) return mademistake; } +static void +prune_to_update_targets(Solver *solv, Id *cp, Queue *q) +{ + int i, j; + Id p, *cp2; + for (i = j = 0; i < q->count; i++) + { + p = q->elements[i]; + for (cp2 = cp; *cp2; cp2++) + if (*cp2 == p) + { + q->elements[j++] = p; + break; + } + } + queue_truncate(q, j); +} + /*------------------------------------------------------------------- * * solver_run_sat @@ -1773,17 +1797,22 @@ solver_run_sat(Solver *solv, int disablerules, int doweak) while ((p = pool->whatprovidesdata[d++]) != 0) if (solv->decisionmap[p] >= 0) queue_push(&dq, p); - policy_filter_unwanted(solv, &dq, POLICY_MODE_CHOOSE); - p = dq.elements[0]; - if (p != i && solv->decisionmap[p] == 0) + if (dq.count && solv->update_targets && solv->update_targets->elements[i - installed->start]) + prune_to_update_targets(solv, solv->update_targets->elements + solv->update_targets->elements[i - installed->start], &dq); + if (dq.count) { - rr = solv->rules + solv->featurerules + (i - solv->installed->start); - if (!rr->p) /* update rule == feature rule? */ - rr = rr - solv->featurerules + solv->updaterules; - dq.count = 1; + policy_filter_unwanted(solv, &dq, POLICY_MODE_CHOOSE); + p = dq.elements[0]; + if (p != i && solv->decisionmap[p] == 0) + { + rr = solv->rules + solv->featurerules + (i - solv->installed->start); + if (!rr->p) /* update rule == feature rule? */ + rr = rr - solv->featurerules + solv->updaterules; + dq.count = 1; + } + else + dq.count = 0; } - else - dq.count = 0; } else { @@ -1800,6 +1829,8 @@ solver_run_sat(Solver *solv, int disablerules, int doweak) } } } + if (dq.count && solv->update_targets && solv->update_targets->elements[i - installed->start]) + prune_to_update_targets(solv, solv->update_targets->elements + solv->update_targets->elements[i - installed->start], &dq); /* install best version */ if (dq.count) { @@ -2559,6 +2590,92 @@ solver_addjobrule(Solver *solv, Id p, Id d, Id job, int weak) queue_push(&solv->weakruleq, solv->nrules - 1); } +static void +add_update_target(Solver *solv, Id p) +{ + Pool *pool = solv->pool; + Solvable *s = pool->solvables + p; + Repo *installed = solv->installed; + Id pi, pip; + if (!solv->update_targets) + { + solv->update_targets = solv_calloc(1, sizeof(Queue)); + queue_init(solv->update_targets); + } + FOR_PROVIDES(pi, pip, s->name) + { + Solvable *si = pool->solvables + pi; + if (si->name != s->name || si->repo != installed) + continue; + queue_push2(solv->update_targets, pi, p); + } + if (s->obsoletes) + { + Id obs, *obsp = s->repo->idarraydata + s->obsoletes; + while ((obs = *obsp++) != 0) + { + FOR_PROVIDES(pi, pip, obs) + { + Solvable *si = pool->solvables + pi; + if (si->repo != installed) + continue; + if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, si, obs)) + continue; + if (pool->obsoleteusescolors && !pool_colormatch(pool, s, si)) + continue; + queue_push2(solv->update_targets, pi, p); + } + } + } +} + +static int +transform_update_targets_sortfn(const void *ap, const void *bp, void *dp) +{ + const Id *a = ap; + const Id *b = bp; + if (a[0] - b[0]) + return a[0] - b[0]; + return a[1] - b[1]; +} + +static void +transform_update_targets(Solver *solv) +{ + Repo *installed = solv->installed; + Queue *update_targets = solv->update_targets; + int i, j; + Id p, lastp; + + if (!update_targets->count) + { + queue_free(update_targets); + solv->update_targets = solv_free(update_targets); + return; + } + if (update_targets->count > 2) + solv_sort(update_targets->elements, update_targets->count >> 1, 2 * sizeof(Id), transform_update_targets_sortfn, solv); + queue_insertn(update_targets, 0, installed->end - installed->start); + lastp = 0; + for (i = j = installed->end - installed->start; i < update_targets->count; i += 2) + { + p = update_targets->elements[i]; + if (p != lastp) + { + if (!solv->updatemap.size) + map_grow(&solv->updatemap, installed->end - installed->start); + MAPSET(&solv->updatemap, p - installed->start); + update_targets->elements[j++] = 0; + update_targets->elements[p - installed->start] = j; + lastp = p; + } + update_targets->elements[j++] = update_targets->elements[i + 1]; + } + queue_truncate(update_targets, j); + queue_push(update_targets, 0); +} + + /* * * solve job queue @@ -2602,6 +2719,11 @@ solver_solve(Solver *solv, Queue *job) queue_free(&solv->job); queue_init_clone(&solv->job, job); + if (solv->update_targets) + { + queue_free(solv->update_targets); + solv->update_targets = solv_free(solv->update_targets); + } /* * create basic rule set of all involved packages * use addedmap bitmap to make sure we don't create rules twice @@ -2633,29 +2755,48 @@ solver_solve(Solver *solv, Queue *job) switch (how & SOLVER_JOBMASK) { case SOLVER_VERIFY: - if (select == SOLVER_SOLVABLE_ALL || (select == SOLVER_SOLVABLE_REPO && solv->installed && what == solv->installed->repoid)) + if (select == SOLVER_SOLVABLE_ALL || (select == SOLVER_SOLVABLE_REPO && installed && what == installed->repoid)) solv->fixmap_all = 1; FOR_JOB_SELECT(p, pp, select, what) { s = pool->solvables + p; - if (!solv->installed || s->repo != solv->installed) + if (s->repo != installed) continue; if (!solv->fixmap.size) - map_grow(&solv->fixmap, solv->installed->end - solv->installed->start); - MAPSET(&solv->fixmap, p - solv->installed->start); + map_grow(&solv->fixmap, installed->end - installed->start); + MAPSET(&solv->fixmap, p - installed->start); } break; case SOLVER_UPDATE: - if (select == SOLVER_SOLVABLE_ALL || (select == SOLVER_SOLVABLE_REPO && solv->installed && what == solv->installed->repoid)) + if (select == SOLVER_SOLVABLE_ALL || (select == SOLVER_SOLVABLE_REPO && installed && what == installed->repoid)) solv->updatemap_all = 1; - FOR_JOB_SELECT(p, pp, select, what) + else if (select == SOLVER_SOLVABLE_REPO && what != installed->repoid) { - s = pool->solvables + p; - if (!solv->installed || s->repo != solv->installed) - continue; - if (!solv->updatemap.size) - map_grow(&solv->updatemap, solv->installed->end - solv->installed->start); - MAPSET(&solv->updatemap, p - solv->installed->start); + Repo *repo = pool_id2repo(pool, what); + if (!repo) + break; + /* targeted update */ + FOR_REPO_SOLVABLES(repo, p, s) + add_update_target(solv, p); + } + else + { + int targeted = 1; + FOR_JOB_SELECT(p, pp, select, what) + { + s = pool->solvables + p; + if (s->repo != installed) + continue; + if (!solv->updatemap.size) + map_grow(&solv->updatemap, installed->end - installed->start); + MAPSET(&solv->updatemap, p - installed->start); + targeted = 0; + } + if (targeted) + { + FOR_JOB_SELECT(p, pp, select, what) + add_update_target(solv, p); + } } break; default: @@ -2663,6 +2804,9 @@ solver_solve(Solver *solv, Queue *job) } } + if (solv->update_targets) + transform_update_targets(solv); + oldnrules = solv->nrules; FOR_REPO_SOLVABLES(installed, p, s) solver_addrpmrulesforsolvable(solv, s, &addedmap); @@ -3667,3 +3811,45 @@ pool_job2solvables(Pool *pool, Queue *pkgs, Id how, Id what) } } +int +pool_isemptyupdatejob(Pool *pool, Id how, Id what) +{ + Id p, pp, pi, pip; + Id select = how & SOLVER_SELECTMASK; + if ((how & SOLVER_JOBMASK) != SOLVER_UPDATE) + return 0; + if (select == SOLVER_SOLVABLE_ALL || select == SOLVER_SOLVABLE_REPO) + return 0; + if (!pool->installed) + return 1; + FOR_JOB_SELECT(p, pp, select, what) + if (pool->solvables[p].repo == pool->installed) + return 0; + /* hard work */ + FOR_JOB_SELECT(p, pp, select, what) + { + Solvable *s = pool->solvables + p; + FOR_PROVIDES(pi, pip, s->name) + if (pool->solvables[pi].name == s->name && pool->solvables[pi].repo == pool->installed) + return 0; + if (s->obsoletes) + { + Id obs, *obsp = s->repo->idarraydata + s->obsoletes; + while ((obs = *obsp++) != 0) + { + FOR_PROVIDES(pi, pip, obs) + { + Solvable *si = pool->solvables + pi; + if (si->repo != pool->installed) + continue; + if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, si, obs)) + continue; + if (pool->obsoleteusescolors && !pool_colormatch(pool, s, si)) + continue; + return 0; + } + } + } + } + return 1; +} diff --git a/src/solver.h b/src/solver.h index 1f04c1d..08fed65 100644 --- a/src/solver.h +++ b/src/solver.h @@ -214,6 +214,8 @@ struct _Solver { Queue *cleandeps_updatepkgs; /* packages we update in cleandeps mode */ Queue *cleandeps_mistakes; /* mistakes we made */ + + Queue *update_targets; /* update to specific packages */ #endif /* LIBSOLV_INTERNAL */ }; @@ -326,6 +328,7 @@ int solver_calc_installsizechange(Solver *solv); void solver_trivial_installable(Solver *solv, Queue *pkgs, Queue *res); void pool_job2solvables(Pool *pool, Queue *pkgs, Id how, Id what); +int pool_isemptyupdatejob(Pool *pool, Id how, Id what); /* iterate over all literals of a rule */ /* WARNING: loop body must not relocate whatprovidesdata, e.g. by -- 2.7.4