repo_add_zyppdb_products;
repo_find_all_pubkeys;
repo_find_pubkey;
+ repo_mark_retracted_packages;
repo_verify_sigdata;
rpm_byfp;
rpm_byrpmdbid;
return pd.ret;
}
+#ifdef SUSE
+
+static int
+repo_mark_retracted_packages_cmp(const void *ap, const void *bp, void *dp)
+{
+ Id *a = (Id *)ap;
+ Id *b = (Id *)bp;
+ if (a[1] != b[1])
+ return a[1] - b[1];
+ if (a[2] != b[2])
+ return a[2] - b[2];
+ if (a[0] != b[0])
+ return a[0] - b[0];
+ return 0;
+}
+
+
+void
+repo_mark_retracted_packages(Repo *repo, Id retractedmarker)
+{
+ Pool *pool = repo->pool;
+ int i, p;
+ Solvable *s;
+ Id con, *conp;
+ Id retractedname, retractedevr;
+
+ Queue q;
+ queue_init(&q);
+ for (p = 1; p < pool->nsolvables; p++)
+ {
+ const char *status;
+ s = pool->solvables + p;
+ if (strncmp(pool_id2str(pool, s->name), "patch:", 6) != 0)
+ {
+ if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
+ continue;
+ queue_push2(&q, p, s->name);
+ queue_push2(&q, s->evr, s->arch);
+ continue;
+ }
+ status = solvable_lookup_str(s, UPDATE_STATUS);
+ if (!status || strcmp(status, "retracted") != 0)
+ continue;
+ if (!s->conflicts)
+ continue;
+ conp = s->repo->idarraydata + s->conflicts;
+ while ((con = *conp++) != 0)
+ {
+ Reldep *rd;
+ Id name, evr, arch;
+ if (!ISRELDEP(con))
+ continue;
+ rd = GETRELDEP(pool, con);
+ if (rd->flags != REL_LT)
+ continue;
+ name = rd->name;
+ evr = rd->evr;
+ arch = 0;
+ if (ISRELDEP(name))
+ {
+ rd = GETRELDEP(pool, name);
+ name = rd->name;
+ if (rd->flags == REL_ARCH)
+ arch = rd->evr;
+ }
+ queue_push2(&q, 0, name);
+ queue_push2(&q, evr, arch);
+ }
+ }
+ if (q.count)
+ solv_sort(q.elements, q.count / 4, sizeof(Id) * 4, repo_mark_retracted_packages_cmp, repo->pool);
+ retractedname = retractedevr = 0;
+ for (i = 0; i < q.count; i += 4)
+ {
+ if (!q.elements[i])
+ {
+ retractedname = q.elements[i + 1];
+ retractedevr = q.elements[i + 2];
+ }
+ else if (q.elements[i + 1] == retractedname && q.elements[i + 2] == retractedevr)
+ {
+ s = pool->solvables + q.elements[i];
+ s->provides = repo_addid_dep(repo, s->provides, retractedmarker, 0);
+ }
+ }
+ queue_free(&q);
+}
+
+#endif
*/
extern int repo_add_updateinfoxml(Repo *repo, FILE *fp, int flags);
+
+extern void repo_mark_retracted_packages(Repo *repo, Id retractedmarker);
+
{ SOLVER_ALLOWUNINSTALL, "allowuninstall" },
{ SOLVER_FAVOR, "favor" },
{ SOLVER_DISFAVOR, "disfavor" },
+ { SOLVER_BLACKLIST, "blacklist" },
{ 0, 0 }
};
{ SOLVER_RULE_LEARNT, "learnt" },
{ SOLVER_RULE_BEST, "best" },
{ SOLVER_RULE_YUMOBS, "yumobs" },
+ { SOLVER_RULE_BLACK, "black" },
{ SOLVER_RULE_RECOMMENDS, "recommends" },
{ 0, 0 }
};
}
return;
}
+ if (why >= solv->blackrules && why < solv->blackrules_end)
+ {
+ queue_push(solutionq, SOLVER_SOLUTION_BLACK);
+ assert(solv->rules[why].p < 0);
+ queue_push(solutionq, -solv->rules[why].p);
+ }
}
/*
* -> add (SOLVER_INSTALL|SOLVER_SOLVABLE, rp) to the job
* SOLVER_SOLUTION_BEST pkgid
* -> add (SOLVER_INSTALL|SOLVER_SOLVABLE, rp) to the job
+ * SOLVER_SOLUTION_BLACK pkgid
+ * -> add (SOLVER_INSTALL|SOLVER_SOLVABLE, rp) to the job
* SOLVER_SOLUTION_JOB jobidx
* -> remove job (jobidx - 1, jobidx) from job queue
* SOLVER_SOLUTION_POOLJOB jobidx
s = pool_tmpjoin(pool, "both package ", pool_solvid2str(pool, source), " and ");
s = pool_tmpjoin(pool, s, pool_solvid2str(pool, target), " obsolete ");
return pool_tmpappend(pool, s, pool_dep2str(pool, dep), 0);
+ case SOLVER_RULE_BLACK:
+ return pool_tmpjoin(pool, "package ", pool_solvid2str(pool, source), " can only be installed by a direct request");
default:
return "bad problem rule type";
}
else
return pool_tmpjoin(pool, "install ", pool_solvable2str(pool, s), " despite the old version");
}
+ 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 > 0 && rp > 0)
struct s_Solver;
-#define SOLVER_SOLUTION_JOB (0)
-#define SOLVER_SOLUTION_DISTUPGRADE (-1)
-#define SOLVER_SOLUTION_INFARCH (-2)
-#define SOLVER_SOLUTION_BEST (-3)
-#define SOLVER_SOLUTION_POOLJOB (-4)
+#define SOLVER_SOLUTION_JOB (0)
+#define SOLVER_SOLUTION_DISTUPGRADE (-1)
+#define SOLVER_SOLUTION_INFARCH (-2)
+#define SOLVER_SOLUTION_BEST (-3)
+#define SOLVER_SOLUTION_POOLJOB (-4)
+#define SOLVER_SOLUTION_BLACK (-5)
void solver_recordproblem(struct s_Solver *solv, Id rid);
void solver_fixproblem(struct s_Solver *solv, Id rid);
}
}
+/***********************************************************************
+ ***
+ *** Black rule part
+ ***/
+
+static inline void
+disableblackrule(Solver *solv, Id p)
+{
+ Rule *r;
+ int i;
+ for (i = solv->blackrules, r = solv->rules + i; i < solv->blackrules_end; i++, r++)
+ if (r->p == -p)
+ solver_disablerule(solv, r);
+}
+
+static inline void
+reenableblackrule(Solver *solv, Id p)
+{
+ Pool *pool = solv->pool;
+ Rule *r;
+ int i;
+ for (i = solv->blackrules, r = solv->rules + i; i < solv->blackrules_end; i++, r++)
+ if (r->p == -p)
+ {
+ solver_enablerule(solv, r);
+ IF_POOLDEBUG (SOLV_DEBUG_SOLUTIONS)
+ {
+ POOL_DEBUG(SOLV_DEBUG_SOLUTIONS, "@@@ re-enabling ");
+ solver_printruleclass(solv, SOLV_DEBUG_SOLUTIONS, r);
+ }
+ }
+}
+
+void
+solver_addblackrules(Solver *solv)
+{
+ int i;
+ Id how, select, what, p, pp;
+ Queue *job = &solv->job;
+ Pool *pool = solv->pool;
+ Repo *installed = solv->installed;
+ Map updatemap;
+
+ map_init(&updatemap, 0);
+ solv->blackrules = solv->nrules;
+ if (installed)
+ {
+ for (i = 0; i < job->count; i += 2)
+ {
+ how = job->elements[i];
+ select = job->elements[i] & SOLVER_SELECTMASK;
+ what = job->elements[i + 1];
+ switch (how & SOLVER_JOBMASK)
+ {
+ case SOLVER_BLACKLIST:
+ FOR_JOB_SELECT(p, pp, select, what)
+ {
+ Solvable *s = pool->solvables + p;
+ if (s->repo != installed)
+ continue;
+ if (!updatemap.size)
+ map_grow(&updatemap, pool->ss.nstrings);
+ if (s->name > 0 && s->name < pool->ss.nstrings)
+ MAPSET(&updatemap, s->name);
+ }
+ }
+ }
+ }
+ for (i = 0; i < job->count; i += 2)
+ {
+ how = job->elements[i];
+ select = job->elements[i] & SOLVER_SELECTMASK;
+ what = job->elements[i + 1];
+ switch (how & SOLVER_JOBMASK)
+ {
+ case SOLVER_BLACKLIST:
+ FOR_JOB_SELECT(p, pp, select, what)
+ {
+ Solvable *s = pool->solvables + p;
+ if (s->repo == installed)
+ continue;
+ if (updatemap.size && s->name > 0 && s->name < pool->ss.nstrings && MAPTST(&updatemap, s->name))
+ continue; /* installed package with same name is already blacklisted */
+ solver_addrule(solv, -p, 0, 0);
+ }
+ break;
+ }
+ }
+ map_free(&updatemap);
+ solv->blackrules_end = solv->nrules;
+}
/***********************************************************************
***
#define DISABLE_UPDATE 1
#define DISABLE_INFARCH 2
#define DISABLE_DUP 3
+#define DISABLE_BLACK 4
static void
jobtodisablelist(Solver *solv, Id how, Id what, Queue *q)
}
}
}
+ if ((set & SOLVER_SETEVR) != 0 && solv->blackrules != solv->blackrules_end)
+ {
+ if (select == SOLVER_SOLVABLE)
+ queue_push2(q, DISABLE_BLACK, what);
+ else
+ {
+ FOR_JOB_SELECT(p, pp, select, what)
+ queue_push2(q, DISABLE_BLACK, p);
+ }
+ }
if (!installed || installed->end == installed->start)
return;
/* now the hard part: disable some update rules */
case DISABLE_DUP:
disableduprule(solv, arg);
break;
+ case DISABLE_BLACK:
+ disableblackrule(solv, arg);
+ break;
default:
break;
}
case DISABLE_DUP:
reenableduprule(solv, arg);
break;
+ case DISABLE_BLACK:
+ reenableblackrule(solv, arg);
+ break;
}
}
queue_free(&q);
*depp = solv->yumobsrules_info[rid - solv->yumobsrules];
return SOLVER_RULE_YUMOBS;
}
+ if (rid >= solv->blackrules && rid < solv->blackrules_end)
+ {
+ if (fromp)
+ *fromp = -r->p;
+ return SOLVER_RULE_BLACK;
+ }
if (rid >= solv->choicerules && rid < solv->choicerules_end)
return SOLVER_RULE_CHOICE;
if (rid >= solv->recommendsrules && rid < solv->recommendsrules_end)
return SOLVER_RULE_BEST;
if (rid >= solv->yumobsrules && rid < solv->yumobsrules_end)
return SOLVER_RULE_YUMOBS;
+ if (rid >= solv->blackrules && rid < solv->blackrules_end)
+ return SOLVER_RULE_BLACK;
if (rid >= solv->choicerules && rid < solv->choicerules_end)
return SOLVER_RULE_CHOICE;
if (rid >= solv->recommendsrules && rid < solv->recommendsrules_end)
return SOLVER_RULE_RECOMMENDS;
+ if (rid >= solv->blackrules && rid < solv->blackrules_end)
+ return SOLVER_RULE_BLACK;
if (rid >= solv->learntrules && rid < solv->nrules)
return SOLVER_RULE_LEARNT;
return SOLVER_RULE_UNKNOWN;
SOLVER_RULE_LEARNT = 0x800,
SOLVER_RULE_BEST = 0x900,
SOLVER_RULE_YUMOBS = 0xa00,
- SOLVER_RULE_RECOMMENDS = 0xb00
+ SOLVER_RULE_RECOMMENDS = 0xb00,
+ SOLVER_RULE_BLACK = 0xc00
} SolverRuleinfo;
#define SOLVER_RULE_TYPEMASK 0xff00
/* yumobs rules */
extern void solver_addyumobsrules(struct s_Solver *solv);
+/* black rules */
+extern void solver_addblackrules(struct s_Solver *solv);
+
/* recommends rules */
extern void solver_addrecommendsrules(struct s_Solver *solv);
int hasbestinstalljob = 0;
int hasfavorjob = 0;
int haslockjob = 0;
+ int hasblacklistjob = 0;
solve_start = solv_timems(0);
POOL_DEBUG(SOLV_DEBUG_JOB, "job: %s %s\n", (how & SOLVER_JOBMASK) == SOLVER_FAVOR ? "favor" : "disfavor", solver_select2str(pool, select, what));
hasfavorjob = 1;
break;
+ case SOLVER_BLACKLIST:
+ POOL_DEBUG(SOLV_DEBUG_JOB, "job: blacklist %s\n", solver_select2str(pool, select, what));
+ hasblacklistjob = 1;
+ break;
default:
POOL_DEBUG(SOLV_DEBUG_JOB, "job: unknown job\n");
break;
else
solv->yumobsrules = solv->yumobsrules_end = solv->nrules;
+ if (hasblacklistjob)
+ solver_addblackrules(solv);
+ else
+ solv->blackrules = solv->blackrules_end = solv->nrules;
+
if (solv->havedisfavored && solv->strongrecommends && solv->recommendsruleq)
solver_addrecommendsrules(solv);
else
case SOLVER_DISFAVOR:
strstart = "disfavor ";
break;
+ case SOLVER_BLACKLIST:
+ strstart = "blacklist ";
+ break;
default:
strstart = "unknown job ";
break;
Id yumobsrules_end;
Id *yumobsrules_info; /* the dependency for each rule */
+ Id blackrules; /* rules from blacklisted packages */
+ Id blackrules_end;
+
Id choicerules; /* choice rules (always weak) */
Id choicerules_end;
Id *choicerules_info; /* the rule we used to generate the choice rule */
#define SOLVER_ALLOWUNINSTALL 0x0b00
#define SOLVER_FAVOR 0x0c00
#define SOLVER_DISFAVOR 0x0d00
+#define SOLVER_BLACKLIST 0x0e00
#define SOLVER_JOBMASK 0xff00
POOL_DEBUG(type, "FEATURE ");
else if (p >= solv->yumobsrules && p < solv->yumobsrules_end)
POOL_DEBUG(type, "YUMOBS ");
+ else if (p >= solv->blackrules && p < solv->blackrules_end)
+ POOL_DEBUG(type, "BLACK ");
else if (p >= solv->recommendsrules && p < solv->recommendsrules_end)
POOL_DEBUG(type, "RECOMMENDS ");
solver_printrule(solv, type, r);
--- /dev/null
+repo system 0 testtags <inline>
+#>=Pkg: ptf-2 1 1 noarch
+#>=Prv: ptf-package()
+repo available 0 testtags <inline>
+#>=Pkg: ptf-1 1 1 noarch
+#>=Prv: ptf-package()
+#>=Pkg: ptf-2 2 1 noarch
+#>=Prv: ptf-package()
+#>=Pkg: A 1 1 noarch
+#>=Req: ptf-1
+
+system i686 * system
+
+#
+# test 1: a ptf package cannot be pulled in via a dependency
+#
+job blacklist provides ptf-package()
+job install name A
+result transaction,problems <inline>
+#>problem 78613afb info package A-1-1.noarch requires ptf-1, but none of the providers can be installed
+#>problem 78613afb solution 23f73f5b deljob install name A
+#>problem 78613afb solution b79aeb6f allow ptf-1-1-1.noarch@available
+
+#
+# test 2: a ptf package cannot be pulled in via a unspecific job
+#
+nextjob
+job blacklist provides ptf-package()
+job install name ptf-1
+result transaction,problems <inline>
+#>problem 021b17e2 info package ptf-1-1-1.noarch cannot only be installed by a direct request
+#>problem 021b17e2 solution 932a6c2f deljob install name ptf-1
+#>problem 021b17e2 solution b79aeb6f allow ptf-1-1-1.noarch@available
+
+#
+# test 3: a ptf package can be pulled in via a specific job
+#
+nextjob
+job blacklist provides ptf-package()
+job install name ptf-1 [setevr]
+result transaction,problems <inline>
+#>install ptf-1-1-1.noarch@available
+
+#
+# test 4: a ptf package can be updated
+#
+nextjob
+job blacklist provides ptf-package()
+job update all packages
+result transaction,problems <inline>
+#>upgrade ptf-2-1-1.noarch@system ptf-2-2-1.noarch@available
+
--- /dev/null
+repo system 0 testtags <inline>
+#>=Pkg: B 1 1 noarch
+repo available 0 testtags <inline>
+#>=Pkg: patch 1 1 noarch
+#>=Con: B < 2-1
+#>=Pkg: B 2 1 noarch
+#>=Prv: retracted-patch-package()
+
+system i686 * system
+
+job blacklist provides retracted-patch-package()
+job install name patch
+#>problem 3a66200a info package patch-1-1.noarch conflicts with B < 2-1 provided by B-1-1.noarch
+#>problem 3a66200a solution 14805cf8 deljob install name patch
+#>problem 3a66200a solution 4a9277b8 allow B-2-1.noarch@available
+#>problem 3a66200a solution 718064ed erase B-1-1.noarch@system
+
+nextjob
+job blacklist provides retracted-patch-package()
+job install pkg B-2-1.noarch@available
+result transaction,problems <inline>
+#>upgrade B-1-1.noarch@system B-2-1.noarch@available
#ifdef SUSE
if (add_auto)
repo_add_autopattern(repo, 0);
+ repo_mark_retracted_packages(repo, pool_str2id(pool, "retracted-patch-package()", 1));
#endif
tool_write(repo, stdout);
pool_free(pool);