From: Michael Schroeder Date: Mon, 21 Sep 2015 11:47:02 +0000 (+0200) Subject: Support SOLVER_ALLOWUNINSTALL jobs X-Git-Tag: 0.6.13~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c40f2227bf6e7784044a7bc2449ff9b40cb3a95c;p=thirdparty%2Flibsolv.git Support SOLVER_ALLOWUNINSTALL jobs This works like the SOLVER_FLAG_ALLOW_UNINSTALL flag, but limited to a specific set of packages. --- diff --git a/bindings/solv.i b/bindings/solv.i index 0c37f6c6..823dedac 100644 --- a/bindings/solv.i +++ b/bindings/solv.i @@ -1171,6 +1171,7 @@ typedef struct { static const Id SOLVER_VERIFY = SOLVER_VERIFY; static const Id SOLVER_DROP_ORPHANED = SOLVER_DROP_ORPHANED; static const Id SOLVER_USERINSTALLED = SOLVER_USERINSTALLED; + static const Id SOLVER_ALLOWUNINSTALL = SOLVER_ALLOWUNINSTALL; static const Id SOLVER_JOBMASK = SOLVER_JOBMASK; static const Id SOLVER_WEAK = SOLVER_WEAK; static const Id SOLVER_ESSENTIAL = SOLVER_ESSENTIAL; diff --git a/doc/libsolv-bindings.3 b/doc/libsolv-bindings.3 index 9fe26c13..dc86e1f9 100644 --- a/doc/libsolv-bindings.3 +++ b/doc/libsolv-bindings.3 @@ -2,12 +2,12 @@ .\" Title: Libsolv-Bindings .\" Author: [see the "Author" section] .\" Generator: DocBook XSL Stylesheets v1.78.0 -.\" Date: 08/28/2015 +.\" Date: 09/21/2015 .\" Manual: LIBSOLV .\" Source: libsolv .\" Language: English .\" -.TH "LIBSOLV\-BINDINGS" "3" "08/28/2015" "libsolv" "LIBSOLV" +.TH "LIBSOLV\-BINDINGS" "3" "09/21/2015" "libsolv" "LIBSOLV" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -3251,6 +3251,11 @@ Fix dependency problems of matching installed packages\&. The default is to igno The matching installed packages are considered to be installed by a user, thus not installed to fulfill some dependency\&. This is needed input for the calculation of unneeded packages for jobs that have the SOLVER_CLEANDEPS flag set\&. .RE .PP +\fBSOLVER_ALLOWUNINSTALL\fR +.RS 4 +Allow the solver to deinstall the matching installed packages if they get into the way of resolving a dependency\&. This is like the SOLVER_FLAG_ALLOW_UNINSTALL flag, but limited to a specific set of packages\&. +.RE +.PP \fBSOLVER_JOBMASK\fR .RS 4 A mask containing all the above action bits\&. diff --git a/doc/libsolv-bindings.txt b/doc/libsolv-bindings.txt index 175d922e..13d73bd3 100644 --- a/doc/libsolv-bindings.txt +++ b/doc/libsolv-bindings.txt @@ -1873,6 +1873,11 @@ thus not installed to fulfill some dependency. This is needed input for the calculation of unneeded packages for jobs that have the SOLVER_CLEANDEPS flag set. +*SOLVER_ALLOWUNINSTALL*:: +Allow the solver to deinstall the matching installed packages if they get +into the way of resolving a dependency. This is like the +SOLVER_FLAG_ALLOW_UNINSTALL flag, but limited to a specific set of packages. + *SOLVER_JOBMASK*:: A mask containing all the above action bits. diff --git a/ext/testcase.c b/ext/testcase.c index e4346fe7..3c404515 100644 --- a/ext/testcase.c +++ b/ext/testcase.c @@ -33,18 +33,19 @@ static struct job2str { Id job; const char *str; } job2str[] = { - { SOLVER_NOOP, "noop" }, - { SOLVER_INSTALL, "install" }, - { SOLVER_ERASE, "erase" }, - { SOLVER_UPDATE, "update" }, - { SOLVER_WEAKENDEPS, "weakendeps" }, - { SOLVER_MULTIVERSION, "multiversion" }, - { SOLVER_MULTIVERSION, "noobsoletes" }, /* old name */ - { SOLVER_LOCK, "lock" }, - { SOLVER_DISTUPGRADE, "distupgrade" }, - { SOLVER_VERIFY, "verify" }, - { SOLVER_DROP_ORPHANED, "droporphaned" }, - { SOLVER_USERINSTALLED, "userinstalled" }, + { SOLVER_NOOP, "noop" }, + { SOLVER_INSTALL, "install" }, + { SOLVER_ERASE, "erase" }, + { SOLVER_UPDATE, "update" }, + { SOLVER_WEAKENDEPS, "weakendeps" }, + { SOLVER_MULTIVERSION, "multiversion" }, + { SOLVER_MULTIVERSION, "noobsoletes" }, /* old name */ + { SOLVER_LOCK, "lock" }, + { SOLVER_DISTUPGRADE, "distupgrade" }, + { SOLVER_VERIFY, "verify" }, + { SOLVER_DROP_ORPHANED, "droporphaned" }, + { SOLVER_USERINSTALLED, "userinstalled" }, + { SOLVER_ALLOWUNINSTALL, "allowuninstall" }, { 0, 0 } }; diff --git a/src/solver.c b/src/solver.c index b89e0d17..3358b6b0 100644 --- a/src/solver.c +++ b/src/solver.c @@ -200,15 +200,25 @@ autouninstall(Solver *solv, Id *problem) int lastfeature = 0, lastupdate = 0; Id v; Id extraflags = -1; + Map *m = 0; + if (!solv->allowuninstall && !solv->allowuninstall_all) + { + if (!solv->allowuninstallmap.size) + return 0; /* why did we get called? */ + m = &solv->allowuninstallmap; + } for (i = 0; (v = problem[i]) != 0; i++) { if (v < 0) extraflags &= solv->job.elements[-v - 1]; if (v >= solv->updaterules && v < solv->updaterules_end) { + Rule *r; + if (m && !MAPTST(m, v - solv->updaterules)) + continue; /* check if identical to feature rule, we don't like that */ - Rule *r = solv->rules + solv->featurerules + (v - solv->updaterules); + r = solv->rules + solv->featurerules + (v - solv->updaterules); if (!r->p) { /* update rule == feature rule */ @@ -427,8 +437,16 @@ makeruledecisions(Solver *solv) v = ri; queue_push(&solv->problems, v); queue_push(&solv->problems, 0); - if (solv->allowuninstall && v >= solv->featurerules && v < solv->updaterules_end) - solv->problems.count = oldproblemcount; + if (v >= solv->featurerules && v < solv->updaterules_end) + { + if (solv->allowuninstall || solv->allowuninstall_all || solv->allowuninstallmap.size) + if (autouninstall(solv, solv->problems.elements + oldproblemcount + 1) != 0) + { + solv->problems.count = oldproblemcount; + havedisabled = 1; + break; /* start over */ + } + } solver_disableproblem(solv, v); havedisabled = 1; break; /* start over */ @@ -458,8 +476,16 @@ makeruledecisions(Solver *solv) v = ri; queue_push(&solv->problems, v); queue_push(&solv->problems, 0); - if (solv->allowuninstall && v >= solv->featurerules && v < solv->updaterules_end) - solv->problems.count = oldproblemcount; + if (v >= solv->featurerules && v < solv->updaterules_end) + { + if (solv->allowuninstall || solv->allowuninstall_all || solv->allowuninstallmap.size) + if (autouninstall(solv, solv->problems.elements + oldproblemcount + 1) != 0) + { + solv->problems.count = oldproblemcount; + havedisabled = 1; + break; /* start over */ + } + } solver_disableproblem(solv, v); havedisabled = 1; break; /* start over */ @@ -507,8 +533,13 @@ makeruledecisions(Solver *solv) } queue_push(&solv->problems, 0); - if (solv->allowuninstall && (v = autouninstall(solv, solv->problems.elements + oldproblemcount + 1)) != 0) - solv->problems.count = oldproblemcount; + if (solv->allowuninstall || solv->allowuninstall_all || solv->allowuninstallmap.size) + if (autouninstall(solv, solv->problems.elements + oldproblemcount + 1) != 0) + { + solv->problems.count = oldproblemcount; + havedisabled = 1; + break; /* start over */ + } for (i = oldproblemcount + 1; i < solv->problems.count - 1; i++) solver_disableproblem(solv, solv->problems.elements[i]); @@ -1245,13 +1276,14 @@ analyze_unsolvable(Solver *solv, Rule *cr, int disablerules) return 0; } - if (solv->allowuninstall && (v = autouninstall(solv, solv->problems.elements + oldproblemcount + 1)) != 0) - { - solv->problems.count = oldproblemcount; - solv->learnt_pool.count = oldlearntpoolcount; - solver_reset(solv); - return 0; - } + if (solv->allowuninstall || solv->allowuninstall_all || solv->allowuninstallmap.size) + if (autouninstall(solv, solv->problems.elements + oldproblemcount + 1) != 0) + { + solv->problems.count = oldproblemcount; + solv->learnt_pool.count = oldlearntpoolcount; + solver_reset(solv); + return 0; + } /* finish proof */ if (record_proof) @@ -1672,6 +1704,7 @@ solver_free(Solver *solv) map_free(&solv->dupinvolvedmap); map_free(&solv->droporphanedmap); map_free(&solv->cleandepsmap); + map_free(&solv->allowuninstallmap); solv_free(solv->decisionmap); solv_free(solv->rules); @@ -3359,6 +3392,8 @@ solver_solve(Solver *solv, Queue *job) map_zerosize(&solv->dupinvolvedmap); solv->droporphanedmap_all = 0; map_zerosize(&solv->droporphanedmap); + solv->allowuninstall_all = 0; + map_zerosize(&solv->allowuninstallmap); map_zerosize(&solv->cleandepsmap); map_zerosize(&solv->weakrulemap); queue_empty(&solv->weakruleq); @@ -3873,6 +3908,20 @@ solver_solve(Solver *solv, Queue *job) case SOLVER_USERINSTALLED: POOL_DEBUG(SOLV_DEBUG_JOB, "job: user installed %s\n", solver_select2str(pool, select, what)); break; + case SOLVER_ALLOWUNINSTALL: + POOL_DEBUG(SOLV_DEBUG_JOB, "job: allowuninstall %s\n", solver_select2str(pool, select, what)); + if (select == SOLVER_SOLVABLE_ALL || (select == SOLVER_SOLVABLE_REPO && installed && what == installed->repoid)) + solv->allowuninstall_all = 1; + FOR_JOB_SELECT(p, pp, select, what) + { + s = pool->solvables + p; + if (s->repo != installed) + continue; + if (!solv->allowuninstallmap.size) + map_grow(&solv->allowuninstallmap, installed->end - installed->start); + MAPSET(&solv->allowuninstallmap, p - installed->start); + } + break; default: POOL_DEBUG(SOLV_DEBUG_JOB, "job: unknown job\n"); break; @@ -5082,6 +5131,9 @@ pool_job2str(Pool *pool, Id how, Id what, Id flagmask) case SOLVER_USERINSTALLED: strstart = "regard ", strend = " as userinstalled"; break; + case SOLVER_ALLOWUNINSTALL: + strstart = "allow deinstallation of "; + break; default: strstart = "unknown job "; break; diff --git a/src/solver.h b/src/solver.h index 1a47ae01..2ae9c8d5 100644 --- a/src/solver.h +++ b/src/solver.h @@ -195,6 +195,10 @@ struct _Solver { int keep_orphans; /* how to treat orphans */ int break_orphans; /* how to treat orphans */ Queue *brokenorphanrules; /* broken rules of orphaned packages */ + + Map allowuninstallmap; /* ok to uninstall those */ + int allowuninstall_all; + #endif /* LIBSOLV_INTERNAL */ }; @@ -223,7 +227,8 @@ typedef struct _Solver Solver; #define SOLVER_DISTUPGRADE 0x0700 #define SOLVER_VERIFY 0x0800 #define SOLVER_DROP_ORPHANED 0x0900 -#define SOLVER_USERINSTALLED 0x0a00 +#define SOLVER_USERINSTALLED 0x0a00 +#define SOLVER_ALLOWUNINSTALL 0x0b00 #define SOLVER_JOBMASK 0xff00