From: Michael Schroeder Date: Wed, 21 Dec 2022 12:52:41 +0000 (+0100) Subject: Move replace solution types from the bindings to the library X-Git-Tag: 0.7.24~10 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=685a7c850a53058f50697cedea483f076695a614;p=thirdparty%2Flibsolv.git Move replace solution types from the bindings to the library This adds two new functions: solver_all_solutionelements() return a queue with (type,p,rp) solution triplets. solver_solutionelementtype2str() this is similar to solver_solutionelement2str(), but also takes a type parameter so that the replace types result in different strings. Make use of the two functions in the example solver to show how they work. --- diff --git a/bindings/solv.i b/bindings/solv.i index 5d82832b..ef3f31c2 100644 --- a/bindings/solv.i +++ b/bindings/solv.i @@ -773,13 +773,6 @@ typedef int bool; #define RARRAY_LEN(ary) (RARRAY(ary)->len) #endif -#define SOLVER_SOLUTION_ERASE -100 -#define SOLVER_SOLUTION_REPLACE -101 -#define SOLVER_SOLUTION_REPLACE_DOWNGRADE -102 -#define SOLVER_SOLUTION_REPLACE_ARCHCHANGE -103 -#define SOLVER_SOLUTION_REPLACE_VENDORCHANGE -104 -#define SOLVER_SOLUTION_REPLACE_NAMECHANGE -105 - typedef void *AppObjectPtr; typedef Id DepId; @@ -839,7 +832,6 @@ typedef struct { Solver *solv; Id problemid; Id solutionid; - Id id; Id type; Id p; @@ -1273,7 +1265,6 @@ typedef struct { Solver *const solv; Id const problemid; Id const solutionid; - Id const id; Id const type; } Solutionelement; @@ -1283,7 +1274,7 @@ typedef struct { Id const type; Id const dep_id; Id const chosen_id; - int level; + int const level; } Alternative; %nodefaultctor Transaction; @@ -3463,94 +3454,32 @@ returnself(matchsolvable) int element_count() { return solver_solutionelement_count($self->solv, $self->problemid, $self->id); } - - %typemap(out) Queue elements Queue2Array(Solutionelement *, 4, new_Solutionelement(arg1->solv, arg1->problemid, arg1->id, id, idp[1], idp[2], idp[3])); + %typemap(out) Queue elements Queue2Array(Solutionelement *, 3, new_Solutionelement(arg1->solv, arg1->problemid, arg1->id, id, idp[1], idp[2])); %newobject elements; Queue elements(bool expandreplaces=0) { Queue q; - int i, cnt; queue_init(&q); - cnt = solver_solutionelement_count($self->solv, $self->problemid, $self->id); - for (i = 1; i <= cnt; i++) - { - Id p, rp, type; - solver_next_solutionelement($self->solv, $self->problemid, $self->id, i - 1, &p, &rp); - if (p > 0) { - type = rp ? SOLVER_SOLUTION_REPLACE : SOLVER_SOLUTION_ERASE; - } else { - type = p; - p = rp; - rp = 0; - } - if (type == SOLVER_SOLUTION_REPLACE && expandreplaces) { - int illegal = policy_is_illegal(self->solv, self->solv->pool->solvables + p, self->solv->pool->solvables + rp, 0); - if (illegal) { - if ((illegal & POLICY_ILLEGAL_DOWNGRADE) != 0) { - queue_push2(&q, i, SOLVER_SOLUTION_REPLACE_DOWNGRADE); - queue_push2(&q, p, rp); - } - if ((illegal & POLICY_ILLEGAL_ARCHCHANGE) != 0) { - queue_push2(&q, i, SOLVER_SOLUTION_REPLACE_ARCHCHANGE); - queue_push2(&q, p, rp); - } - if ((illegal & POLICY_ILLEGAL_VENDORCHANGE) != 0) { - queue_push2(&q, i, SOLVER_SOLUTION_REPLACE_VENDORCHANGE); - queue_push2(&q, p, rp); - } - if ((illegal & POLICY_ILLEGAL_NAMECHANGE) != 0) { - queue_push2(&q, i, SOLVER_SOLUTION_REPLACE_NAMECHANGE); - queue_push2(&q, p, rp); - } - continue; - } - } - queue_push2(&q, i, type); - queue_push2(&q, p, rp); - } + solver_all_solutionelements($self->solv, $self->problemid, $self->id, expandreplaces, &q); return q; } } %extend Solutionelement { - Solutionelement(Solver *solv, Id problemid, Id solutionid, Id id, Id type, Id p, Id rp) { + Solutionelement(Solver *solv, Id problemid, Id solutionid, Id type, Id p, Id rp) { Solutionelement *e; e = solv_calloc(1, sizeof(*e)); e->solv = solv; e->problemid = problemid; e->solutionid = solutionid; - e->id = id; e->type = type; e->p = p; e->rp = rp; return e; } const char *str() { - Id p = $self->type; - Id rp = $self->p; - int illegal = 0; - if (p == SOLVER_SOLUTION_ERASE) - { - p = rp; - rp = 0; - } - else if (p == SOLVER_SOLUTION_REPLACE) - { - p = rp; - rp = $self->rp; - } - else if (p == SOLVER_SOLUTION_REPLACE_DOWNGRADE) - illegal = POLICY_ILLEGAL_DOWNGRADE; - else if (p == SOLVER_SOLUTION_REPLACE_ARCHCHANGE) - illegal = POLICY_ILLEGAL_ARCHCHANGE; - else if (p == SOLVER_SOLUTION_REPLACE_VENDORCHANGE) - illegal = POLICY_ILLEGAL_VENDORCHANGE; - else if (p == SOLVER_SOLUTION_REPLACE_NAMECHANGE) - illegal = POLICY_ILLEGAL_NAMECHANGE; - if (illegal) - return pool_tmpjoin($self->solv->pool, "allow ", policy_illegal2str($self->solv, illegal, $self->solv->pool->solvables + $self->p, $self->solv->pool->solvables + $self->rp), 0); - return solver_solutionelement2str($self->solv, p, rp); - } - %typemap(out) Queue replaceelements Queue2Array(Solutionelement *, 1, new_Solutionelement(arg1->solv, arg1->problemid, arg1->solutionid, arg1->id, id, arg1->p, arg1->rp)); + return solver_solutionelementtype2str($self->solv, $self->type, $self->p, $self->rp); + } + %typemap(out) Queue replaceelements Queue2Array(Solutionelement *, 1, new_Solutionelement(arg1->solv, arg1->problemid, arg1->solutionid, id, arg1->p, arg1->rp)); %newobject replaceelements; Queue replaceelements() { Queue q; @@ -4375,19 +4304,19 @@ rb_eval_string( } %} Queue choices_raw() { - Queue r; - queue_init_clone(&r, &$self->choices); - return r; + Queue q; + queue_init_clone(&q, &$self->choices); + return q; } %typemap(out) Queue choices Queue2Array(XSolvable *, 1, new_XSolvable(arg1->solv->pool, id)); Queue choices() { int i; - Queue r; - queue_init_clone(&r, &$self->choices); - for (i = 0; i < r.count; i++) - if (r.elements[i] < 0) - r.elements[i] = -r.elements[i]; - return r; + Queue q; + queue_init_clone(&q, &$self->choices); + for (i = 0; i < q.count; i++) + if (q.elements[i] < 0) + q.elements[i] = -q.elements[i]; + return q; } #if defined(SWIGPERL) || defined(SWIGTCL) %rename("str") __str__; diff --git a/examples/solv/solv.c b/examples/solv/solv.c index 99d56056..f7c0468b 100644 --- a/examples/solv/solv.c +++ b/examples/solv/solv.c @@ -788,14 +788,26 @@ rerunsolver: for (problem = 1; problem <= pcnt; problem++) { int take = 0; + Id rid; printf("Problem %d/%d:\n", problem, pcnt); - solver_printprobleminfo(solv, problem); + rid = solver_findproblemrule(solv, problem); + if (rid) + { + Id source, target, dep; + SolverRuleinfo type = solver_ruleinfo(solv, rid, &source, &target, &dep); + printf("%s\n", solver_problemruleinfo2str(solv, type, source, target, dep)); + } printf("\n"); scnt = solver_solution_count(solv, problem); for (solution = 1; solution <= scnt; solution++) { + Queue sq; printf("Solution %d:\n", solution); - solver_printsolution(solv, problem, solution); + queue_init(&sq); + solver_all_solutionelements(solv, problem, solution, 1, &sq); + for (i = 0; i < sq.count; i += 3) + printf(" - %s\n", solver_solutionelementtype2str(solv, sq.elements[i], sq.elements[i + 1], sq.elements[i + 2])); + queue_free(&sq); printf("\n"); } for (;;) diff --git a/src/libsolv.ver b/src/libsolv.ver index 402c2567..b9f9f960 100644 --- a/src/libsolv.ver +++ b/src/libsolv.ver @@ -342,6 +342,7 @@ SOLV_1.0 { solvable_trivial_installable_queue; solvable_trivial_installable_repo; solvable_unset; + solver_all_solutionelements; solver_allruleinfos; solver_allweakdepinfos; solver_alternative2str; @@ -414,6 +415,7 @@ SOLV_1.0 { solver_set_flag; solver_solution_count; solver_solutionelement2str; + solver_solutionelementtype2str; solver_solutionelement_count; solver_solutionelement_internalid; solver_solutionelement_extrajobflags; diff --git a/src/problems.c b/src/problems.c index 58dd4de9..b0a421c2 100644 --- a/src/problems.c +++ b/src/problems.c @@ -22,6 +22,7 @@ #include "pool.h" #include "util.h" #include "evr.h" +#include "policy.h" #include "solverdebug.h" /**********************************************************************************/ @@ -986,6 +987,7 @@ solver_solutionelement_internalid(Solver *solv, Id problem, Id solution) return solv->solutions.elements[solidx + 2 * solv->solutions.elements[solidx] + 3]; } +/* currently just SOLVER_CLEANDEPS */ Id solver_solutionelement_extrajobflags(Solver *solv, Id problem, Id solution) { @@ -1040,6 +1042,56 @@ solver_next_solutionelement(Solver *solv, Id problem, Id solution, Id element, I return element + 1; } +static inline void +queue_push3(Queue *q, Id id1, Id id2, Id id3) +{ + queue_push(q, id1); + queue_push2(q, id2, id3); +} + +static void +add_expanded_replace(Solver *solv, Id p, Id rp, Queue *q) +{ + int illegal = policy_is_illegal(solv, solv->pool->solvables + p, solv->pool->solvables + rp, 0); + if ((illegal & POLICY_ILLEGAL_DOWNGRADE) != 0) + queue_push3(q, SOLVER_SOLUTION_REPLACE_DOWNGRADE, p, rp); + if ((illegal & POLICY_ILLEGAL_ARCHCHANGE) != 0) + queue_push3(q, SOLVER_SOLUTION_REPLACE_ARCHCHANGE, p, rp); + if ((illegal & POLICY_ILLEGAL_VENDORCHANGE) != 0) + queue_push3(q, SOLVER_SOLUTION_REPLACE_VENDORCHANGE, p, rp); + if ((illegal & POLICY_ILLEGAL_NAMECHANGE) != 0) + queue_push3(q, SOLVER_SOLUTION_REPLACE_NAMECHANGE, p, rp); + if (!illegal || (illegal & ~(POLICY_ILLEGAL_DOWNGRADE | POLICY_ILLEGAL_ARCHCHANGE | POLICY_ILLEGAL_VENDORCHANGE | POLICY_ILLEGAL_NAMECHANGE))) + queue_push3(q, SOLVER_SOLUTION_REPLACE, p, rp); +} + +/* solutionelements are (type, p, rp) triplets */ +void +solver_all_solutionelements(Solver *solv, Id problem, Id solution, int expandreplaces, Queue *q) +{ + int i, cnt; + Id solidx = solv->problems.elements[problem * 2 - 1]; + solidx = solv->solutions.elements[solidx + solution]; + queue_empty(q); + if (!solidx) + return; + cnt = solv->solutions.elements[solidx++]; + for (i = 0; i < cnt; i++) + { + Id p = solv->solutions.elements[solidx++]; + Id rp = solv->solutions.elements[solidx++]; + if (p > 0) + { + if (rp && expandreplaces) + add_expanded_replace(solv, p, rp, q); + else + queue_push3(q, rp ? SOLVER_SOLUTION_REPLACE : SOLVER_SOLUTION_ERASE, p, rp); + } + else + queue_push3(q, p, rp, 0); + } +} + void solver_take_solutionelement(Solver *solv, Id p, Id rp, Id extrajobflags, Queue *job) { @@ -1057,6 +1109,11 @@ solver_take_solutionelement(Solver *solv, Id p, Id rp, Id extrajobflags, Queue * job->elements[rp] = 0; return; } + if (p == SOLVER_SOLUTION_ERASE) + { + p = rp; + rp = 0; + } if (rp <= 0 && p <= 0) return; /* just in case */ if (rp > 0) @@ -1402,62 +1459,66 @@ solver_problem2str(Solver *solv, Id problem) } const char * -solver_solutionelement2str(Solver *solv, Id p, Id rp) +solver_solutionelementtype2str(Solver *solv, int type, Id p, Id rp) { Pool *pool = solv->pool; - if (p == SOLVER_SOLUTION_JOB || p == SOLVER_SOLUTION_POOLJOB) - { - Id how, what; - if (p == SOLVER_SOLUTION_JOB) - rp += solv->pooljobcnt; - how = solv->job.elements[rp - 1]; - what = solv->job.elements[rp]; - return pool_tmpjoin(pool, "do not ask to ", pool_job2str(pool, how, what, 0), 0); - } - else if (p == SOLVER_SOLUTION_INFARCH) + Solvable *s; + const char *str; + + switch (type) { - Solvable *s = pool->solvables + rp; + case SOLVER_SOLUTION_JOB: + case SOLVER_SOLUTION_POOLJOB: + if (type == SOLVER_SOLUTION_JOB) + p += solv->pooljobcnt; + return pool_tmpjoin(pool, "do not ask to ", pool_job2str(pool, solv->job.elements[p - 1], solv->job.elements[p], 0), 0); + case SOLVER_SOLUTION_INFARCH: + s = pool->solvables + p; if (solv->installed && s->repo == solv->installed) return pool_tmpjoin(pool, "keep ", pool_solvable2str(pool, s), " despite the inferior architecture"); else return pool_tmpjoin(pool, "install ", pool_solvable2str(pool, s), " despite the inferior architecture"); - } - else if (p == SOLVER_SOLUTION_DISTUPGRADE) - { - Solvable *s = pool->solvables + rp; + case SOLVER_SOLUTION_DISTUPGRADE: + s = pool->solvables + p; if (solv->installed && s->repo == solv->installed) return pool_tmpjoin(pool, "keep obsolete ", pool_solvable2str(pool, s), 0); else return pool_tmpjoin(pool, "install ", pool_solvable2str(pool, s), " from excluded repository"); - } - else if (p == SOLVER_SOLUTION_BEST) - { - Solvable *s = pool->solvables + rp; + case SOLVER_SOLUTION_BEST: + s = pool->solvables + p; if (solv->installed && s->repo == solv->installed) return pool_tmpjoin(pool, "keep old ", pool_solvable2str(pool, s), 0); else return pool_tmpjoin(pool, "install ", pool_solvable2str(pool, s), " despite the old version"); + case SOLVER_SOLUTION_BLACK: + return pool_tmpjoin(pool, "install ", pool_solvid2str(pool, p), 0); + case SOLVER_SOLUTION_STRICTREPOPRIORITY: + return pool_tmpjoin(pool, "install ", pool_solvid2str(pool, p), " despite the repo priority"); + + /* replace types: p -> rp */ + case SOLVER_SOLUTION_ERASE: + return pool_tmpjoin(pool, "allow deinstallation of ", pool_solvid2str(pool, p), 0); + case SOLVER_SOLUTION_REPLACE: + str = pool_tmpjoin(pool, "allow replacement of ", pool_solvid2str(pool, p), 0); + return pool_tmpappend(pool, str, " with ", pool_solvid2str(pool, rp)); + case SOLVER_SOLUTION_REPLACE_DOWNGRADE: + return pool_tmpjoin(pool, "allow ", policy_illegal2str(solv, POLICY_ILLEGAL_DOWNGRADE, pool->solvables + p, pool->solvables + rp), 0); + case SOLVER_SOLUTION_REPLACE_ARCHCHANGE: + return pool_tmpjoin(pool, "allow ", policy_illegal2str(solv, POLICY_ILLEGAL_ARCHCHANGE, pool->solvables + p, pool->solvables + rp), 0); + case SOLVER_SOLUTION_REPLACE_VENDORCHANGE: + return pool_tmpjoin(pool, "allow ", policy_illegal2str(solv, POLICY_ILLEGAL_VENDORCHANGE, pool->solvables + p, pool->solvables + rp), 0); + case SOLVER_SOLUTION_REPLACE_NAMECHANGE: + return pool_tmpjoin(pool, "allow ", policy_illegal2str(solv, POLICY_ILLEGAL_NAMECHANGE, pool->solvables + p, pool->solvables + rp), 0); + default: + break; } - else if (p == SOLVER_SOLUTION_BLACK) - { - Solvable *s = pool->solvables + rp; - return pool_tmpjoin(pool, "install ", pool_solvable2str(pool, s), 0); - } - else if (p > 0 && rp == 0) - return pool_tmpjoin(pool, "allow deinstallation of ", pool_solvid2str(pool, p), 0); - else if (p == SOLVER_SOLUTION_STRICTREPOPRIORITY) - { - Solvable *s = pool->solvables + rp; - return pool_tmpjoin(pool, "install ", pool_solvable2str(pool, s), " despite the repo priority"); - } - else if (p > 0 && rp > 0) - { - const char *sp = pool_solvid2str(pool, p); - const char *srp = pool_solvid2str(pool, rp); - const char *str = pool_tmpjoin(pool, "allow replacement of ", sp, 0); - return pool_tmpappend(pool, str, " with ", srp); - } - else - return "bad solution element"; + return "bad solution element"; } +const char * +solver_solutionelement2str(Solver *solv, Id p, Id rp) +{ + if (p > 0) + return solver_solutionelementtype2str(solv, rp ? SOLVER_SOLUTION_REPLACE : SOLVER_SOLUTION_ERASE, p, rp); + return solver_solutionelementtype2str(solv, p, rp, 0); +} diff --git a/src/problems.h b/src/problems.h index f9b1efc3..9e4ad1ff 100644 --- a/src/problems.h +++ b/src/problems.h @@ -29,6 +29,13 @@ struct s_Solver; #define SOLVER_SOLUTION_POOLJOB (-4) #define SOLVER_SOLUTION_BLACK (-5) #define SOLVER_SOLUTION_STRICTREPOPRIORITY (-6) +/* replace solution types */ +#define SOLVER_SOLUTION_ERASE (-100) +#define SOLVER_SOLUTION_REPLACE (-101) +#define SOLVER_SOLUTION_REPLACE_DOWNGRADE (-102) +#define SOLVER_SOLUTION_REPLACE_ARCHCHANGE (-103) +#define SOLVER_SOLUTION_REPLACE_VENDORCHANGE (-104) +#define SOLVER_SOLUTION_REPLACE_NAMECHANGE (-105) void solver_recordproblem(struct s_Solver *solv, Id rid); void solver_fixproblem(struct s_Solver *solv, Id rid); @@ -45,6 +52,7 @@ unsigned int solver_solutionelement_count(struct s_Solver *solv, Id problem, Id Id solver_solutionelement_internalid(struct s_Solver *solv, Id problem, Id solution); Id solver_solutionelement_extrajobflags(struct s_Solver *solv, Id problem, Id solution); Id solver_next_solutionelement(struct s_Solver *solv, Id problem, Id solution, Id element, Id *p, Id *rp); +void solver_all_solutionelements(struct s_Solver *solv, Id problem, Id solution, int expandreplaces, Queue *q); void solver_take_solutionelement(struct s_Solver *solv, Id p, Id rp, Id extrajobflags, Queue *job); void solver_take_solution(struct s_Solver *solv, Id problem, Id solution, Queue *job); @@ -55,6 +63,7 @@ void solver_findallproblemrules(struct s_Solver *solv, Id problem, Queue *rules) extern const char *solver_problemruleinfo2str(struct s_Solver *solv, SolverRuleinfo type, Id source, Id target, Id dep); extern const char *solver_problem2str(struct s_Solver *solv, Id problem); extern const char *solver_solutionelement2str(struct s_Solver *solv, Id p, Id rp); +extern const char *solver_solutionelementtype2str(struct s_Solver *solv, int type, Id p, Id rp); #ifdef __cplusplus } diff --git a/src/solverdebug.c b/src/solverdebug.c index 5902cdb4..1c53d4e7 100644 --- a/src/solverdebug.c +++ b/src/solverdebug.c @@ -505,43 +505,17 @@ solver_printcompleteprobleminfo(Solver *solv, Id problem) queue_free(&q); } -static int illegals[] = { - POLICY_ILLEGAL_DOWNGRADE, - POLICY_ILLEGAL_NAMECHANGE, - POLICY_ILLEGAL_ARCHCHANGE, - POLICY_ILLEGAL_VENDORCHANGE, - 0 -}; - void solver_printsolution(Solver *solv, Id problem, Id solution) { Pool *pool = solv->pool; - Id p, rp, element; - - element = 0; - while ((element = solver_next_solutionelement(solv, problem, solution, element, &p, &rp)) != 0) - { - if (p > 0 && rp > 0) - { - /* for replacements we want to know why it was illegal */ - Solvable *s = pool->solvables + p, *rs = pool->solvables + rp; - int illegal = policy_is_illegal(solv, s, rs, 0); - if (illegal) - { - int i; - for (i = 0; illegals[i]; i++) - if ((illegal & illegals[i]) != 0) - { - POOL_DEBUG(SOLV_DEBUG_RESULT, " - allow %s\n", policy_illegal2str(solv, illegals[i], s, rs)); - illegal ^= illegals[i]; - } - if (!illegal) - continue; - } - } - POOL_DEBUG(SOLV_DEBUG_RESULT, " - %s\n", solver_solutionelement2str(solv, p, rp)); - } + Queue q; + int i; + queue_init(&q); + solver_all_solutionelements(solv, problem, solution, 1, &q); + for (i = 0; i < q.count; i += 3) + POOL_DEBUG(SOLV_DEBUG_RESULT, " - %s\n", solver_solutionelementtype2str(solv, q.elements[i], q.elements[i + 1], q.elements[i + 2])); + queue_free(&q); } void