5 * Copyright (c) 2009, Novell Inc.
7 * This program is licensed under the BSD license, read LICENSE.BSD
8 * for further information
22 #include "repo_solv.h"
23 #include "repo_susetags.h"
24 #include "repo_updateinfoxml.h"
25 #include "repo_rpmmd.h"
27 #include "solverdebug.h"
29 #include "sat_xfopen.h"
32 showproblems(Solver *solv, Solvable *s, Queue *cand, Queue *badguys)
34 Pool *pool = solv->pool;
42 printf("can't install %s:\n", pool_solvable2str(pool, s));
43 while ((problem = solver_next_problem(solv, problem)) != 0)
45 solver_findallproblemrules(solv, problem, &rids);
46 for (jj = 0; jj < rids.count; jj++)
48 Id probr = rids.elements[jj];
52 solver_allruleinfos(solv, probr, &rinfo);
53 for (k = 0; k < rinfo.count; k += 4)
55 Id dep, source, target;
56 source = rinfo.elements[k + 1];
57 target = rinfo.elements[k + 2];
58 dep = rinfo.elements[k + 3];
59 switch (rinfo.elements[k])
61 case SOLVER_RULE_DISTUPGRADE:
63 case SOLVER_RULE_INFARCH:
64 printf(" %s has inferior architecture\n", pool_solvid2str(pool, source));
66 case SOLVER_RULE_UPDATE:
67 printf(" update rule for %s\n", pool_solvid2str(pool, source));
69 queue_pushunique(badguys, source);
72 /* only drop update problem packages from cand so that we see all problems of this patch */
73 for (l = 0; l < cand->count; l++)
74 if (cand->elements[l] == source || cand->elements[l] == -source)
80 for (l = 0; l < cand->count; l++)
81 if (cand->elements[l] < 0)
82 cand->elements[l] = -cand->elements[l];
85 for (l = 0; l < cand->count; l++)
86 if (cand->elements[l] == source)
88 cand->elements[l] = -source;
94 printf(" some dependency problem\n");
96 case SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP:
97 printf(" nothing provides requested %s\n", pool_dep2str(pool, dep));
99 case SOLVER_RULE_RPM_NOT_INSTALLABLE:
100 printf(" package %s is not installable\n", pool_solvid2str(pool, source));
102 case SOLVER_RULE_RPM_NOTHING_PROVIDES_DEP:
103 printf(" nothing provides %s needed by %s\n", pool_dep2str(pool, dep), pool_solvid2str(pool, source));
106 Reldep *rd = GETRELDEP(pool, dep);
107 if (!ISRELDEP(rd->name))
110 FOR_PROVIDES(rp, rpp, rd->name)
111 printf(" (we have %s)\n", pool_solvid2str(pool, rp));
115 case SOLVER_RULE_RPM_SAME_NAME:
116 printf(" cannot install both %s and %s\n", pool_solvid2str(pool, source), pool_solvid2str(pool, target));
118 case SOLVER_RULE_RPM_PACKAGE_CONFLICT:
119 printf(" package %s conflicts with %s provided by %s\n", pool_solvid2str(pool, source), pool_dep2str(pool, dep), pool_solvid2str(pool, target));
121 case SOLVER_RULE_RPM_PACKAGE_OBSOLETES:
122 printf(" package %s obsoletes %s provided by %s\n", pool_solvid2str(pool, source), pool_dep2str(pool, dep), pool_solvid2str(pool, target));
124 case SOLVER_RULE_RPM_PACKAGE_REQUIRES:
125 printf(" package %s requires %s, but none of the providers can be installed\n", pool_solvid2str(pool, source), pool_dep2str(pool, dep));
127 case SOLVER_RULE_RPM_SELF_CONFLICT:
128 printf(" package %s conflicts with %s provided by itself\n", pool_solvid2str(pool, source), pool_dep2str(pool, dep));
139 toinst(Solver *solv, Repo *repo, Repo *instrepo)
141 Pool *pool = solv->pool;
145 for (k = 0; k < solv->decisionq.count; k++)
147 p = solv->decisionq.elements[k];
148 if (p < 0 || p == SYSTEMSOLVABLE)
151 /* printf(" toinstall %s\n", pool_solvid2str(pool, p));*/
153 pool->solvables[p].repo = instrepo;
158 dump_instrepo(Repo *instrepo, Pool *pool)
163 printf("instrepo..\n");
164 FOR_REPO_SOLVABLES(instrepo, p, s)
165 printf(" %s\n", pool_solvable2str(pool, s));
170 frominst(Solver *solv, Repo *repo, Repo *instrepo)
172 Pool *pool = solv->pool;
175 for (k = 1; k < pool->nsolvables; k++)
176 if (pool->solvables[k].repo == instrepo)
177 pool->solvables[k].repo = repo;
184 printf("%s: <arch> <patchnameprefix> [--install-available] [repos] [--updaterepos] [repos]...\n"
185 "\t --install-available: installation repository is available during update\n"
186 "\t repos: repository ending in\n"
187 "\t\tpackages, packages.gz, primary.xml.gz, updateinfo.xml.gz or .solv\n",
197 int install_available;
202 #define SHOW_PATCH(c) if (!(c)->shown++) printf("%s:\n", pool_solvable2str(pool, s));
203 #define PERF_DEBUGGING 0
208 test_all_old_patches_included(context_t *c, Id pid)
212 Solvable *s = pool->solvables + pid;
213 /* Test 1: are all old patches included */
214 FOR_PROVIDES(p, pp, s->name)
216 Solvable *s2 = pool->solvables + p;
221 if (pool_evrcmp(pool, s->evr, s2->evr, EVRCMP_COMPARE) <= 0)
223 conp2 = s2->repo->idarraydata + s2->conflicts;
224 while ((con2 = *conp2++) != 0)
229 rd2 = GETRELDEP(pool, con2);
230 conp = s->repo->idarraydata + s->conflicts;
231 while ((con = *conp++) != 0)
235 rd = GETRELDEP(pool, con);
236 if (rd->name == rd2->name)
242 printf(" %s contained %s\n", pool_solvable2str(pool, s2), pool_dep2str(pool, rd2->name));
246 if (pool_evrcmp(pool, rd->evr, rd2->evr, EVRCMP_COMPARE) < 0)
249 printf(" %s required newer version %s-%s of %s-%s\n",
250 pool_solvable2str(pool, s2), pool_dep2str(pool, rd2->name), pool_dep2str(pool, rd2->evr),
251 pool_dep2str(pool, rd->name), pool_dep2str(pool, rd->evr));
260 test_all_packages_installable(context_t *c, Id pid)
266 unsigned int now, solver_runs;
268 Solvable *s = pool->solvables + pid;
275 conp = s->repo->idarraydata + s->conflicts;
276 while ((con = *conp++) != 0)
278 FOR_PROVIDES(p, pp, con)
281 queue_push(&job, SOLVER_INSTALL|SOLVER_SOLVABLE|SOLVER_WEAK);
284 /* also set up some minimal system */
285 queue_push(&job, SOLVER_INSTALL|SOLVER_SOLVABLE_PROVIDES|SOLVER_WEAK);
286 queue_push(&job, pool_str2id(pool, "rpm", 1));
287 queue_push(&job, SOLVER_INSTALL|SOLVER_SOLVABLE_PROVIDES|SOLVER_WEAK);
288 queue_push(&job, pool_str2id(pool, "aaa_base", 1));
290 solv = solver_create(pool);
291 solv->dontinstallrecommended = 0;
293 if (solver_solve(solv, &job))
296 printf("error installing original package\n");
297 showproblems(solv, s, 0, 0);
299 toinst(solv, c->repo, c->instrepo);
303 dump_instrepo(instrepo, pool);
306 if (!c->install_available)
309 for (i = 1; i < c->updatestart; i++)
311 if (pool->solvables[i].repo != c->repo || i == pid)
313 queue_push(&job, SOLVER_ERASE|SOLVER_SOLVABLE);
317 queue_push(&job, SOLVER_INSTALL|SOLVER_SOLVABLE);
318 queue_push(&job, pid);
319 solv = solver_create(pool);
320 /*solv->dontinstallrecommended = 1;*/
322 if (solver_solve(solv, &job))
325 showproblems(solv, s, 0, 0);
327 frominst(solv, c->repo, c->instrepo);
333 printf(" test_all_packages_installable took %d ms in %d runs\n", sat_timems(now), solver_runs);
337 test_can_upgrade_all_packages(context_t *c, Id pid)
346 unsigned int now, solver_runs;
347 Solvable *s = pool->solvables + pid;
351 queue_init(&badguys);
356 /* Test 3: can we upgrade all packages? */
357 for (p = 1; p < pool->nsolvables; p++)
359 Solvable *s = pool->solvables + p;
362 if (strchr(pool_id2str(pool, s->name), ':'))
363 continue; /* only packages, please */
364 if (!pool_installable(pool, s))
366 queue_push(&cand, p);
370 solv = solver_create(pool);
372 for (i = 0; i < badguys.count; i++)
374 queue_push(&job, SOLVER_ERASE|SOLVER_SOLVABLE|SOLVER_WEAK);
375 queue_push(&job, badguys.elements[i]);
377 conp = s->repo->idarraydata + s->conflicts;
378 while ((con = *conp++) != 0)
380 queue_push(&job, SOLVER_INSTALL|SOLVER_SOLVABLE_PROVIDES|SOLVER_WEAK);
381 queue_push(&job, con);
383 for (i = 0; i < cand.count; i++)
385 p = cand.elements[i];
386 queue_push(&job, SOLVER_INSTALL|SOLVER_SOLVABLE|SOLVER_WEAK);
390 solver_solve(solv, &job);
392 solver_printdecisions(solv);
394 /* put packages into installed repo and prune them from cand */
395 toinst(solv, c->repo, c->instrepo);
396 for (i = 0; i < cand.count; i++)
398 p = cand.elements[i];
399 if (p > 0 && solv->decisionmap[p] > 0)
400 cand.elements[i] = -p; /* drop candidate */
404 /* now the interesting part: test patch */
406 if (!c->install_available)
408 for (i = 1; i < c->updatestart; i++)
410 if (pool->solvables[i].repo != c->repo || i == pid)
412 queue_push(&job, SOLVER_ERASE|SOLVER_SOLVABLE);
416 queue_push(&job, SOLVER_INSTALL|SOLVER_SOLVABLE);
417 queue_push(&job, pid);
418 solv = solver_create(pool);
419 solv->dontinstallrecommended = 1;
421 if (solver_solve(solv, &job))
424 showproblems(solv, s, &cand, &badguys);
426 frominst(solv, c->repo, c->instrepo);
428 /* now drop all negative elements from cand */
429 for (i = j = 0; i < cand.count; i++)
431 if (cand.elements[i] < 0)
433 cand.elements[j++] = cand.elements[i];
436 break; /* no progress */
440 printf(" test_can_upgrade_all_packages took %d ms in %d runs\n", sat_timems(now), solver_runs);
444 test_no_ga_package_fulfills_dependency(context_t *c, Id pid)
447 Solvable *s = pool->solvables + pid;
449 /* Test 4: no GA package fulfills patch dependency */
450 conp = s->repo->idarraydata + s->conflicts;
451 while ((con = *conp++) != 0)
458 rd = GETRELDEP(pool, con);
459 FOR_PROVIDES(rp, rpp, rd->name)
461 Solvable *s2 = pool_id2solvable(pool, rp);
462 if (rp < c->updatestart
463 && pool_evrcmp(pool, rd->evr, s2->evr, EVRCMP_COMPARE) < 0
464 && pool_match_nevr_rel(pool, s2, rd->name)
468 printf(" conflict %s < %s satisfied by non-updated package %s\n",
469 pool_dep2str(pool, rd->name), pool_dep2str(pool, rd->evr), pool_solvable2str(pool, s2));
477 main(int argc, char **argv)
479 char *arch, *mypatch;
488 c.install_available = 0;
496 pool = pool_create();
497 pool_setarch(pool, arch);
498 static const char* langs[] = {"en"};
499 pool_set_languages(pool, langs, 1);
502 pool_setdebuglevel(pool, 2);
507 c.repo = repo_create(pool, 0);
508 c.instrepo = repo_create(pool, 0);
509 for (i = 3; i < argc; i++)
511 if (!strcmp(argv[i], "--updaterepos"))
513 c.updatestart = pool->nsolvables;
517 if (!strcmp(argv[i], "--install-available"))
519 c.install_available = 1;
524 if (!strcmp(argv[i], "-"))
526 else if ((fp = sat_xfopen(argv[i], 0)) == 0)
531 if (l >= 8 && !strcmp(argv[i] + l - 8, "packages"))
533 repo_add_susetags(c.repo, fp, 0, 0, 0);
535 else if (l >= 11 && !strcmp(argv[i] + l - 11, "packages.gz"))
537 repo_add_susetags(c.repo, fp, 0, 0, 0);
539 else if (l >= 14 && !strcmp(argv[i] + l - 14, "primary.xml.gz"))
541 repo_add_rpmmd(c.repo, fp, 0, 0);
543 else if (l >= 17 && !strcmp(argv[i] + l - 17, "updateinfo.xml.gz"))
545 repo_add_updateinfoxml(c.repo, fp, 0);
547 else if (repo_add_solv(c.repo, fp))
549 fprintf(stderr, "could not add repo %s\n", argv[i]);
556 pool_addfileprovides(pool);
558 /* bad hack ahead: clone repo */
559 c.instrepo->idarraydata = c.repo->idarraydata;
560 c.instrepo->idarraysize = c.repo->idarraysize;
561 c.instrepo->start = c.repo->start;
562 c.instrepo->end = c.repo->end;
563 c.instrepo->nsolvables = c.repo->nsolvables; /* sic! */
564 c.instrepo->lastoff = c.repo->lastoff; /* sic! */
565 pool_set_installed(pool, c.instrepo);
566 pool_createwhatprovides(pool);
568 for (pid = 1; pid < pool->nsolvables; pid++)
571 Solvable *s = pool->solvables + pid;
574 if (!pool_installable(pool, s))
576 pname = pool_id2str(pool, s->name);
577 if (strncmp(pname, "patch:", 6) != 0)
582 if (strncmp(mypatch, pname + 6, strlen(pname + 6)) != 0)
584 if (strcmp(mypatch, pname + 6) != 0)
586 l = strlen(pname + 6);
587 if (mypatch[l] != '-')
589 if (strcmp(mypatch + l + 1, pool_id2str(pool, s->evr)) != 0)
595 FOR_PROVIDES(p, pp, s->name)
597 Solvable *s2 = pool->solvables + p;
598 if (pool_evrcmp(pool, s->evr, s2->evr, EVRCMP_COMPARE) < 0)
602 /* printf("found a newer one for %s\n", pname+6); */
603 continue; /* found a newer one */
611 printf("testing patch %s-%s\n", pname + 6, pool_id2str(pool, s->evr));
614 test_all_old_patches_included(&c, pid);
615 test_all_packages_installable(&c, pid);
616 test_can_upgrade_all_packages(&c, pid);
617 test_no_ga_package_fulfills_dependency(&c, pid);