Skip to content

Commit 4120051

Browse files
committed
Add support for blacklisted packages
This will be used in SUSE's ptf packages and also to retract released updates. The idea is that it is not possible to pull in a blacklisted package via a dependency, they can only be installed by a job that directly addresses them (the SETEVR bit is set).
1 parent cea2f34 commit 4120051

14 files changed

Lines changed: 333 additions & 6 deletions

File tree

ext/libsolvext.ver

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ SOLV_1.0 {
4242
repo_add_zyppdb_products;
4343
repo_find_all_pubkeys;
4444
repo_find_pubkey;
45+
repo_mark_retracted_packages;
4546
repo_verify_sigdata;
4647
rpm_byfp;
4748
rpm_byrpmdbid;

ext/repo_updateinfoxml.c

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,3 +490,92 @@ repo_add_updateinfoxml(Repo *repo, FILE *fp, int flags)
490490
return pd.ret;
491491
}
492492

493+
#ifdef SUSE
494+
495+
static int
496+
repo_mark_retracted_packages_cmp(const void *ap, const void *bp, void *dp)
497+
{
498+
Id *a = (Id *)ap;
499+
Id *b = (Id *)bp;
500+
if (a[1] != b[1])
501+
return a[1] - b[1];
502+
if (a[2] != b[2])
503+
return a[2] - b[2];
504+
if (a[0] != b[0])
505+
return a[0] - b[0];
506+
return 0;
507+
}
508+
509+
510+
void
511+
repo_mark_retracted_packages(Repo *repo, Id retractedmarker)
512+
{
513+
Pool *pool = repo->pool;
514+
int i, p;
515+
Solvable *s;
516+
Id con, *conp;
517+
Id retractedname, retractedevr;
518+
519+
Queue q;
520+
queue_init(&q);
521+
for (p = 1; p < pool->nsolvables; p++)
522+
{
523+
const char *status;
524+
s = pool->solvables + p;
525+
if (strncmp(pool_id2str(pool, s->name), "patch:", 6) != 0)
526+
{
527+
if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
528+
continue;
529+
queue_push2(&q, p, s->name);
530+
queue_push2(&q, s->evr, s->arch);
531+
continue;
532+
}
533+
status = solvable_lookup_str(s, UPDATE_STATUS);
534+
if (!status || strcmp(status, "retracted") != 0)
535+
continue;
536+
if (!s->conflicts)
537+
continue;
538+
conp = s->repo->idarraydata + s->conflicts;
539+
while ((con = *conp++) != 0)
540+
{
541+
Reldep *rd;
542+
Id name, evr, arch;
543+
if (!ISRELDEP(con))
544+
continue;
545+
rd = GETRELDEP(pool, con);
546+
if (rd->flags != REL_LT)
547+
continue;
548+
name = rd->name;
549+
evr = rd->evr;
550+
arch = 0;
551+
if (ISRELDEP(name))
552+
{
553+
rd = GETRELDEP(pool, name);
554+
name = rd->name;
555+
if (rd->flags == REL_ARCH)
556+
arch = rd->evr;
557+
}
558+
queue_push2(&q, 0, name);
559+
queue_push2(&q, evr, arch);
560+
}
561+
}
562+
if (q.count)
563+
solv_sort(q.elements, q.count / 4, sizeof(Id) * 4, repo_mark_retracted_packages_cmp, repo->pool);
564+
retractedname = retractedevr = 0;
565+
for (i = 0; i < q.count; i += 4)
566+
{
567+
if (!q.elements[i])
568+
{
569+
retractedname = q.elements[i + 1];
570+
retractedevr = q.elements[i + 2];
571+
}
572+
else if (q.elements[i + 1] == retractedname && q.elements[i + 2] == retractedevr)
573+
{
574+
s = pool->solvables + q.elements[i];
575+
s->provides = repo_addid_dep(repo, s->provides, retractedmarker, 0);
576+
}
577+
}
578+
queue_free(&q);
579+
}
580+
581+
#endif

ext/repo_updateinfoxml.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,6 @@
66
*/
77

88
extern int repo_add_updateinfoxml(Repo *repo, FILE *fp, int flags);
9+
10+
extern void repo_mark_retracted_packages(Repo *repo, Id retractedmarker);
11+

ext/testcase.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ static struct job2str {
5959
{ SOLVER_ALLOWUNINSTALL, "allowuninstall" },
6060
{ SOLVER_FAVOR, "favor" },
6161
{ SOLVER_DISFAVOR, "disfavor" },
62+
{ SOLVER_BLACKLIST, "blacklist" },
6263
{ 0, 0 }
6364
};
6465

@@ -1190,6 +1191,7 @@ static struct rclass2str {
11901191
{ SOLVER_RULE_LEARNT, "learnt" },
11911192
{ SOLVER_RULE_BEST, "best" },
11921193
{ SOLVER_RULE_YUMOBS, "yumobs" },
1194+
{ SOLVER_RULE_BLACK, "black" },
11931195
{ SOLVER_RULE_RECOMMENDS, "recommends" },
11941196
{ 0, 0 }
11951197
};

src/problems.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,12 @@ convertsolution(Solver *solv, Id why, Queue *solutionq)
719719
}
720720
return;
721721
}
722+
if (why >= solv->blackrules && why < solv->blackrules_end)
723+
{
724+
queue_push(solutionq, SOLVER_SOLUTION_BLACK);
725+
assert(solv->rules[why].p < 0);
726+
queue_push(solutionq, -solv->rules[why].p);
727+
}
722728
}
723729

724730
/*
@@ -981,6 +987,8 @@ solver_solutionelement_extrajobflags(Solver *solv, Id problem, Id solution)
981987
* -> add (SOLVER_INSTALL|SOLVER_SOLVABLE, rp) to the job
982988
* SOLVER_SOLUTION_BEST pkgid
983989
* -> add (SOLVER_INSTALL|SOLVER_SOLVABLE, rp) to the job
990+
* SOLVER_SOLUTION_BLACK pkgid
991+
* -> add (SOLVER_INSTALL|SOLVER_SOLVABLE, rp) to the job
984992
* SOLVER_SOLUTION_JOB jobidx
985993
* -> remove job (jobidx - 1, jobidx) from job queue
986994
* SOLVER_SOLUTION_POOLJOB jobidx
@@ -1331,6 +1339,8 @@ solver_problemruleinfo2str(Solver *solv, SolverRuleinfo type, Id source, Id targ
13311339
s = pool_tmpjoin(pool, "both package ", pool_solvid2str(pool, source), " and ");
13321340
s = pool_tmpjoin(pool, s, pool_solvid2str(pool, target), " obsolete ");
13331341
return pool_tmpappend(pool, s, pool_dep2str(pool, dep), 0);
1342+
case SOLVER_RULE_BLACK:
1343+
return pool_tmpjoin(pool, "package ", pool_solvid2str(pool, source), " can only be installed by a direct request");
13341344
default:
13351345
return "bad problem rule type";
13361346
}
@@ -1385,6 +1395,11 @@ solver_solutionelement2str(Solver *solv, Id p, Id rp)
13851395
else
13861396
return pool_tmpjoin(pool, "install ", pool_solvable2str(pool, s), " despite the old version");
13871397
}
1398+
else if (p == SOLVER_SOLUTION_BLACK)
1399+
{
1400+
Solvable *s = pool->solvables + rp;
1401+
return pool_tmpjoin(pool, "install ", pool_solvable2str(pool, s), 0);
1402+
}
13881403
else if (p > 0 && rp == 0)
13891404
return pool_tmpjoin(pool, "allow deinstallation of ", pool_solvid2str(pool, p), 0);
13901405
else if (p > 0 && rp > 0)

src/problems.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,12 @@ extern "C" {
2222

2323
struct s_Solver;
2424

25-
#define SOLVER_SOLUTION_JOB (0)
26-
#define SOLVER_SOLUTION_DISTUPGRADE (-1)
27-
#define SOLVER_SOLUTION_INFARCH (-2)
28-
#define SOLVER_SOLUTION_BEST (-3)
29-
#define SOLVER_SOLUTION_POOLJOB (-4)
25+
#define SOLVER_SOLUTION_JOB (0)
26+
#define SOLVER_SOLUTION_DISTUPGRADE (-1)
27+
#define SOLVER_SOLUTION_INFARCH (-2)
28+
#define SOLVER_SOLUTION_BEST (-3)
29+
#define SOLVER_SOLUTION_POOLJOB (-4)
30+
#define SOLVER_SOLUTION_BLACK (-5)
3031

3132
void solver_recordproblem(struct s_Solver *solv, Id rid);
3233
void solver_fixproblem(struct s_Solver *solv, Id rid);

src/rules.c

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2101,6 +2101,97 @@ reenableduprule(Solver *solv, Id name)
21012101
}
21022102
}
21032103

2104+
/***********************************************************************
2105+
***
2106+
*** Black rule part
2107+
***/
2108+
2109+
static inline void
2110+
disableblackrule(Solver *solv, Id p)
2111+
{
2112+
Rule *r;
2113+
int i;
2114+
for (i = solv->blackrules, r = solv->rules + i; i < solv->blackrules_end; i++, r++)
2115+
if (r->p == -p)
2116+
solver_disablerule(solv, r);
2117+
}
2118+
2119+
static inline void
2120+
reenableblackrule(Solver *solv, Id p)
2121+
{
2122+
Pool *pool = solv->pool;
2123+
Rule *r;
2124+
int i;
2125+
for (i = solv->blackrules, r = solv->rules + i; i < solv->blackrules_end; i++, r++)
2126+
if (r->p == -p)
2127+
{
2128+
solver_enablerule(solv, r);
2129+
IF_POOLDEBUG (SOLV_DEBUG_SOLUTIONS)
2130+
{
2131+
POOL_DEBUG(SOLV_DEBUG_SOLUTIONS, "@@@ re-enabling ");
2132+
solver_printruleclass(solv, SOLV_DEBUG_SOLUTIONS, r);
2133+
}
2134+
}
2135+
}
2136+
2137+
void
2138+
solver_addblackrules(Solver *solv)
2139+
{
2140+
int i;
2141+
Id how, select, what, p, pp;
2142+
Queue *job = &solv->job;
2143+
Pool *pool = solv->pool;
2144+
Repo *installed = solv->installed;
2145+
Map updatemap;
2146+
2147+
map_init(&updatemap, 0);
2148+
solv->blackrules = solv->nrules;
2149+
if (installed)
2150+
{
2151+
for (i = 0; i < job->count; i += 2)
2152+
{
2153+
how = job->elements[i];
2154+
select = job->elements[i] & SOLVER_SELECTMASK;
2155+
what = job->elements[i + 1];
2156+
switch (how & SOLVER_JOBMASK)
2157+
{
2158+
case SOLVER_BLACKLIST:
2159+
FOR_JOB_SELECT(p, pp, select, what)
2160+
{
2161+
Solvable *s = pool->solvables + p;
2162+
if (s->repo != installed)
2163+
continue;
2164+
if (!updatemap.size)
2165+
map_grow(&updatemap, pool->ss.nstrings);
2166+
if (s->name > 0 && s->name < pool->ss.nstrings)
2167+
MAPSET(&updatemap, s->name);
2168+
}
2169+
}
2170+
}
2171+
}
2172+
for (i = 0; i < job->count; i += 2)
2173+
{
2174+
how = job->elements[i];
2175+
select = job->elements[i] & SOLVER_SELECTMASK;
2176+
what = job->elements[i + 1];
2177+
switch (how & SOLVER_JOBMASK)
2178+
{
2179+
case SOLVER_BLACKLIST:
2180+
FOR_JOB_SELECT(p, pp, select, what)
2181+
{
2182+
Solvable *s = pool->solvables + p;
2183+
if (s->repo == installed)
2184+
continue;
2185+
if (updatemap.size && s->name > 0 && s->name < pool->ss.nstrings && MAPTST(&updatemap, s->name))
2186+
continue; /* installed package with same name is already blacklisted */
2187+
solver_addrule(solv, -p, 0, 0);
2188+
}
2189+
break;
2190+
}
2191+
}
2192+
map_free(&updatemap);
2193+
solv->blackrules_end = solv->nrules;
2194+
}
21042195

21052196
/***********************************************************************
21062197
***
@@ -2114,6 +2205,7 @@ reenableduprule(Solver *solv, Id name)
21142205
#define DISABLE_UPDATE 1
21152206
#define DISABLE_INFARCH 2
21162207
#define DISABLE_DUP 3
2208+
#define DISABLE_BLACK 4
21172209

21182210
static void
21192211
jobtodisablelist(Solver *solv, Id how, Id what, Queue *q)
@@ -2213,6 +2305,16 @@ jobtodisablelist(Solver *solv, Id how, Id what, Queue *q)
22132305
}
22142306
}
22152307
}
2308+
if ((set & SOLVER_SETEVR) != 0 && solv->blackrules != solv->blackrules_end)
2309+
{
2310+
if (select == SOLVER_SOLVABLE)
2311+
queue_push2(q, DISABLE_BLACK, what);
2312+
else
2313+
{
2314+
FOR_JOB_SELECT(p, pp, select, what)
2315+
queue_push2(q, DISABLE_BLACK, p);
2316+
}
2317+
}
22162318
if (!installed || installed->end == installed->start)
22172319
return;
22182320
/* now the hard part: disable some update rules */
@@ -2386,6 +2488,9 @@ solver_disablepolicyrules(Solver *solv)
23862488
case DISABLE_DUP:
23872489
disableduprule(solv, arg);
23882490
break;
2491+
case DISABLE_BLACK:
2492+
disableblackrule(solv, arg);
2493+
break;
23892494
default:
23902495
break;
23912496
}
@@ -2489,6 +2594,9 @@ solver_reenablepolicyrules(Solver *solv, int jobidx)
24892594
case DISABLE_DUP:
24902595
reenableduprule(solv, arg);
24912596
break;
2597+
case DISABLE_BLACK:
2598+
reenableblackrule(solv, arg);
2599+
break;
24922600
}
24932601
}
24942602
queue_free(&q);
@@ -2815,6 +2923,12 @@ solver_ruleinfo(Solver *solv, Id rid, Id *fromp, Id *top, Id *depp)
28152923
*depp = solv->yumobsrules_info[rid - solv->yumobsrules];
28162924
return SOLVER_RULE_YUMOBS;
28172925
}
2926+
if (rid >= solv->blackrules && rid < solv->blackrules_end)
2927+
{
2928+
if (fromp)
2929+
*fromp = -r->p;
2930+
return SOLVER_RULE_BLACK;
2931+
}
28182932
if (rid >= solv->choicerules && rid < solv->choicerules_end)
28192933
return SOLVER_RULE_CHOICE;
28202934
if (rid >= solv->recommendsrules && rid < solv->recommendsrules_end)
@@ -2845,10 +2959,14 @@ solver_ruleclass(Solver *solv, Id rid)
28452959
return SOLVER_RULE_BEST;
28462960
if (rid >= solv->yumobsrules && rid < solv->yumobsrules_end)
28472961
return SOLVER_RULE_YUMOBS;
2962+
if (rid >= solv->blackrules && rid < solv->blackrules_end)
2963+
return SOLVER_RULE_BLACK;
28482964
if (rid >= solv->choicerules && rid < solv->choicerules_end)
28492965
return SOLVER_RULE_CHOICE;
28502966
if (rid >= solv->recommendsrules && rid < solv->recommendsrules_end)
28512967
return SOLVER_RULE_RECOMMENDS;
2968+
if (rid >= solv->blackrules && rid < solv->blackrules_end)
2969+
return SOLVER_RULE_BLACK;
28522970
if (rid >= solv->learntrules && rid < solv->nrules)
28532971
return SOLVER_RULE_LEARNT;
28542972
return SOLVER_RULE_UNKNOWN;

src/rules.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ typedef enum {
7272
SOLVER_RULE_LEARNT = 0x800,
7373
SOLVER_RULE_BEST = 0x900,
7474
SOLVER_RULE_YUMOBS = 0xa00,
75-
SOLVER_RULE_RECOMMENDS = 0xb00
75+
SOLVER_RULE_RECOMMENDS = 0xb00,
76+
SOLVER_RULE_BLACK = 0xc00
7677
} SolverRuleinfo;
7778

7879
#define SOLVER_RULE_TYPEMASK 0xff00
@@ -134,6 +135,9 @@ extern void solver_addbestrules(struct s_Solver *solv, int havebestinstalljobs,
134135
/* yumobs rules */
135136
extern void solver_addyumobsrules(struct s_Solver *solv);
136137

138+
/* black rules */
139+
extern void solver_addblackrules(struct s_Solver *solv);
140+
137141
/* recommends rules */
138142
extern void solver_addrecommendsrules(struct s_Solver *solv);
139143

0 commit comments

Comments
 (0)