diff options
author | Michael Schroeder <mls@suse.de> | 2014-04-03 13:08:08 +0200 |
---|---|---|
committer | Michael Schroeder <mls@suse.de> | 2014-04-03 13:08:08 +0200 |
commit | b2ef9eb3b18a0b543f7011ed33165b7ff6e7f425 (patch) | |
tree | ec58234512c0883e638562875f7ce5fd58beb2c0 | |
parent | e020dfa80052de2a2f89ff3f9dd2baaff1924f3f (diff) | |
download | libsolv-b2ef9eb3b18a0b543f7011ed33165b7ff6e7f425.tar.gz libsolv-b2ef9eb3b18a0b543f7011ed33165b7ff6e7f425.tar.bz2 libsolv-b2ef9eb3b18a0b543f7011ed33165b7ff6e7f425.zip |
add pool_add_userinstalled_jobs and solver_get_userinstalled functions
-rw-r--r-- | src/libsolv.ver | 2 | ||||
-rw-r--r-- | src/solver.c | 243 | ||||
-rw-r--r-- | src/solver.h | 5 |
3 files changed, 250 insertions, 0 deletions
diff --git a/src/libsolv.ver b/src/libsolv.ver index 4be79f9..91337ea 100644 --- a/src/libsolv.ver +++ b/src/libsolv.ver @@ -41,6 +41,7 @@ SOLV_1.0 { policy_illegal_vendorchange; policy_is_illegal; pool_add_fileconflicts_deps; + pool_add_userinstalled_jobs; pool_addfileprovides; pool_addfileprovides_queue; pool_addrelproviders; @@ -336,6 +337,7 @@ SOLV_1.0 { solver_get_orphaned; solver_get_recommendations; solver_get_unneeded; + solver_get_userinstalled; solver_next_problem; solver_next_solution; solver_next_solutionelement; diff --git a/src/solver.c b/src/solver.c index 9fe3f23..deb0736 100644 --- a/src/solver.c +++ b/src/solver.c @@ -26,6 +26,7 @@ #include "poolarch.h" #include "solverdebug.h" #include "cplxdeps.h" +#include "linkedpkg.h" #define RULES_BLOCK 63 @@ -4480,6 +4481,248 @@ pool_isemptyupdatejob(Pool *pool, Id how, Id what) return 1; } +static int +get_userinstalled_cmp(const void *ap, const void *bp, void *dp) +{ + return *(Id *)ap - *(Id *)bp; +} + +static int +get_userinstalled_cmp_names(const void *ap, const void *bp, void *dp) +{ + Pool *pool = dp; + return strcmp(pool_id2str(pool, *(Id *)ap), pool_id2str(pool, *(Id *)bp)); +} + +static void +get_userinstalled_sort_uniq(Pool *pool, Queue *q, int flags) +{ + Id lastp = -1; + int i, j; + if ((flags & GET_USERINSTALLED_NAMES) != 0) + solv_sort(q->elements, q->count, sizeof(Id), get_userinstalled_cmp_names, pool); + else + solv_sort(q->elements, q->count, sizeof(Id), get_userinstalled_cmp, 0); + for (i = j = 0; i < q->count; i++) + if (q->elements[i] != lastp) + q->elements[j++] = lastp = q->elements[i]; + queue_truncate(q, j); +} + +void +solver_get_userinstalled(Solver *solv, Queue *q, int flags) +{ + Pool *pool = solv->pool; + Id p, p2, pp; + Solvable *s; + Repo *installed = solv->installed; + int i, j; + Map userinstalled; + + map_init(&userinstalled, 0); + queue_empty(q); + /* first process jobs */ + for (i = 0; i < solv->job.count; i += 2) + { + Id how = solv->job.elements[i]; + Id what, select; + if (installed && (how & SOLVER_JOBMASK) == SOLVER_USERINSTALLED) + { + if (!userinstalled.size) + map_grow(&userinstalled, installed->end - installed->start); + what = solv->job.elements[i + 1]; + select = how & SOLVER_SELECTMASK; + if (select == SOLVER_SOLVABLE_ALL || (select == SOLVER_SOLVABLE_REPO && what == installed->repoid)) + FOR_REPO_SOLVABLES(installed, p, s) + MAPSET(&userinstalled, p - installed->start); + FOR_JOB_SELECT(p, pp, select, what) + if (pool->solvables[p].repo == installed) + MAPSET(&userinstalled, p - installed->start); + continue; + } + if ((how & SOLVER_JOBMASK) != SOLVER_INSTALL) + continue; + what = solv->job.elements[i + 1]; + select = how & SOLVER_SELECTMASK; + FOR_JOB_SELECT(p, pp, select, what) + if (solv->decisionmap[p] > 0) + { + queue_push(q, p); +#ifdef ENABLE_LINKED_PKGS + if (has_package_link(pool, pool->solvables + p)) + { + int j; + Queue lq; + queue_init(&lq); + find_package_link(pool, pool->solvables + p, 0, &lq, 0, 0); + for (j = 0; j < lq.count; j++) + if (solv->decisionmap[lq.elements[j]] > 0) + queue_push(q, lq.elements[j]); + } +#endif + } + } + /* now process updates of userinstalled packages */ + if (installed && userinstalled.size) + { + for (i = 1; i < solv->decisionq.count; i++) + { + p = solv->decisionq.elements[i]; + if (p <= 0) + continue; + s = pool->solvables + p; + if (!s->repo) + continue; + if (s->repo == installed) + { + if (MAPTST(&userinstalled, p - installed->start)) + queue_push(q, p); + continue; + } + /* new package, check if we replace a userinstalled one */ + FOR_PROVIDES(p2, pp, s->name) + { + Solvable *ps = pool->solvables + p2; + if (p2 == p || ps->repo != installed || !MAPTST(&userinstalled, p2 - installed->start)) + continue; + if (!pool->implicitobsoleteusesprovides && s->name != ps->name) + continue; + if (pool->implicitobsoleteusescolors && !pool_colormatch(pool, s, ps)) + continue; + queue_push(q, p); + break; + } + if (!p2 && s->repo != installed && s->obsoletes) + { + Id obs, *obsp = s->repo->idarraydata + s->obsoletes; + while ((obs = *obsp++) != 0) + { + FOR_PROVIDES(p2, pp, obs) + { + Solvable *ps = pool->solvables + p2; + if (p2 == p || ps->repo != installed || !MAPTST(&userinstalled, p2 - installed->start)) + continue; + if (!pool->obsoleteusesprovides && !pool_match_nevr(pool, ps, obs)) + continue; + if (pool->obsoleteusescolors && !pool_colormatch(pool, s, ps)) + continue; + queue_push(q, p); + break; + } + if (p2) + break; + } + } + } + } + map_free(&userinstalled); + /* convert to names if asked */ + if ((flags & GET_USERINSTALLED_NAMES) != 0) + { + for (i = 0; i < q->count; i++) + { + s = pool->solvables + q->elements[i]; + q->elements[i] = s->name; + } + } + /* sort and unify */ + if (q->count > 1) + get_userinstalled_sort_uniq(pool, q, flags); + /* invert if asked */ + if ((flags & GET_USERINSTALLED_INVERTED) != 0) + { + /* first generate queue with all installed packages */ + Queue invq; + queue_init(&invq); + for (i = 1; i < solv->decisionq.count; i++) + { + p = solv->decisionq.elements[i]; + if (p <= 0) + continue; + s = pool->solvables + p; + if (!s->repo) + continue; + if ((flags & GET_USERINSTALLED_NAMES) != 0) + queue_push(&invq, s->name); + else + queue_push(&invq, p); + } + /* push q on invq, just in case... */ + queue_insertn(&invq, invq.count, q->count, q->elements); + if (invq.count > 1) + get_userinstalled_sort_uniq(pool, &invq, flags); + /* subtract queues (easy as they are sorted and invq is a superset of q) */ + if (q->count) + { + for (i = j = 0; i < invq.count; i++) + if (invq.elements[i] == q->elements[j]) + { + invq.elements[i] = 0; + if (++j >= q->count) + break; + } + queue_empty(q); + } + for (i = j = 0; i < invq.count; i++) + if (invq.elements[i]) + queue_push(q, invq.elements[i]); + queue_free(&invq); + } +} + +void +pool_add_userinstalled_jobs(Pool *pool, Queue *q, Queue *job, int flags) +{ + int i; + + if (flags & GET_USERINSTALLED_INVERTED) + { + Queue invq; + Id p, lastid; + Solvable *s; + int bad; + if (!pool->installed) + return; + queue_init(&invq); + FOR_REPO_SOLVABLES(pool->installed, p, s) + queue_push(&invq, flags & GET_USERINSTALLED_NAMES ? s->name : p); + queue_insertn(&invq, invq.count, q->count, q->elements); + if (invq.count > 1) + get_userinstalled_sort_uniq(pool, &invq, flags); + /* now the fun part, add q again, sort, and remove all dups */ + queue_insertn(&invq, invq.count, q->count, q->elements); + if (invq.count > 1) + { + if ((flags & GET_USERINSTALLED_NAMES) != 0) + solv_sort(invq.elements, invq.count, sizeof(Id), get_userinstalled_cmp_names, pool); + else + solv_sort(invq.elements, invq.count, sizeof(Id), get_userinstalled_cmp, 0); + } + lastid = -1; + bad = 1; + for (i = 0; i < invq.count; i++) + { + if (invq.elements[i] == lastid) + { + bad = 1; + continue; + } + if (!bad) + queue_push2(job, SOLVER_USERINSTALLED | (flags & GET_USERINSTALLED_NAMES ? SOLVER_SOLVABLE_NAME : SOLVER_SOLVABLE), lastid); + bad = 0; + lastid = invq.elements[i]; + } + if (!bad) + queue_push2(job, SOLVER_USERINSTALLED | (flags & GET_USERINSTALLED_NAMES ? SOLVER_SOLVABLE_NAME : SOLVER_SOLVABLE), lastid); + queue_free(&invq); + } + else + { + for (i = 0; i < q->count; i++) + queue_push2(job, SOLVER_USERINSTALLED | (flags & GET_USERINSTALLED_NAMES ? SOLVER_SOLVABLE_NAME : SOLVER_SOLVABLE), q->elements[i]); + } +} + const char * solver_select2str(Pool *pool, Id select, Id what) { diff --git a/src/solver.h b/src/solver.h index b14e367..daa0e08 100644 --- a/src/solver.h +++ b/src/solver.h @@ -280,6 +280,9 @@ typedef struct _Solver Solver; #define SOLVER_FLAG_DUP_ALLOW_VENDORCHANGE 16 #define SOLVER_FLAG_DUP_ALLOW_NAMECHANGE 17 +#define GET_USERINSTALLED_NAMES (1 << 0) /* package names instead if ids */ +#define GET_USERINSTALLED_INVERTED (1 << 1) /* autoinstalled */ + extern Solver *solver_create(Pool *pool); extern void solver_free(Solver *solv); extern int solver_solve(Solver *solv, Queue *job); @@ -295,6 +298,8 @@ extern void solver_get_decisionblock(Solver *solv, int level, Queue *decisionq); extern void solver_get_orphaned(Solver *solv, Queue *orphanedq); extern void solver_get_recommendations(Solver *solv, Queue *recommendationsq, Queue *suggestionsq, int noselected); extern void solver_get_unneeded(Solver *solv, Queue *unneededq, int filtered); +extern void solver_get_userinstalled(Solver *solv, Queue *q, int flags); +extern void pool_add_userinstalled_jobs(Pool *pool, Queue *q, Queue *job, int flags); extern int solver_describe_decision(Solver *solv, Id p, Id *infop); extern void solver_describe_weakdep_decision(Solver *solv, Id p, Queue *whyq); |