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 #ifdef ENABLE_SUSEREPO
24 #include "repo_susetags.h"
27 #include "repo_updateinfoxml.h"
28 #include "repo_rpmmd.h"
31 #include "solverdebug.h"
33 #include "solv_xfopen.h"
36 showproblems(Solver *solv, Solvable *s, Queue *cand, Queue *badguys)
38 Pool *pool = solv->pool;
46 printf("can't install %s:\n", pool_solvable2str(pool, s));
47 while ((problem = solver_next_problem(solv, problem)) != 0)
49 solver_findallproblemrules(solv, problem, &rids);
50 for (jj = 0; jj < rids.count; jj++)
52 Id probr = rids.elements[jj];
56 solver_allruleinfos(solv, probr, &rinfo);
57 for (k = 0; k < rinfo.count; k += 4)
59 Id dep, source, target;
60 source = rinfo.elements[k + 1];
61 target = rinfo.elements[k + 2];
62 dep = rinfo.elements[k + 3];
63 switch (rinfo.elements[k])
65 case SOLVER_RULE_DISTUPGRADE:
67 case SOLVER_RULE_INFARCH:
68 printf(" %s has inferior architecture\n", pool_solvid2str(pool, source));
70 case SOLVER_RULE_UPDATE:
71 printf(" update rule for %s\n", pool_solvid2str(pool, source));
73 queue_pushunique(badguys, source);
76 /* only drop update problem packages from cand so that we see all problems of this patch */
77 for (l = 0; l < cand->count; l++)
78 if (cand->elements[l] == source || cand->elements[l] == -source)
84 for (l = 0; l < cand->count; l++)
85 if (cand->elements[l] < 0)
86 cand->elements[l] = -cand->elements[l];
89 for (l = 0; l < cand->count; l++)
90 if (cand->elements[l] == source)
92 cand->elements[l] = -source;
96 case SOLVER_RULE_JOB_PROVIDED_BY_SYSTEM:
99 printf(" some dependency problem\n");
101 case SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP:
102 printf(" nothing provides requested %s\n", pool_dep2str(pool, dep));
104 case SOLVER_RULE_RPM_NOT_INSTALLABLE:
105 printf(" package %s is not installable\n", pool_solvid2str(pool, source));
107 case SOLVER_RULE_RPM_NOTHING_PROVIDES_DEP:
108 printf(" nothing provides %s needed by %s\n", pool_dep2str(pool, dep), pool_solvid2str(pool, source));
111 Reldep *rd = GETRELDEP(pool, dep);
112 if (!ISRELDEP(rd->name))
115 FOR_PROVIDES(rp, rpp, rd->name)
116 printf(" (we have %s)\n", pool_solvid2str(pool, rp));
120 case SOLVER_RULE_RPM_SAME_NAME:
121 printf(" cannot install both %s and %s\n", pool_solvid2str(pool, source), pool_solvid2str(pool, target));
123 case SOLVER_RULE_RPM_PACKAGE_CONFLICT:
124 printf(" package %s conflicts with %s provided by %s\n", pool_solvid2str(pool, source), pool_dep2str(pool, dep), pool_solvid2str(pool, target));
126 case SOLVER_RULE_RPM_PACKAGE_OBSOLETES:
127 printf(" package %s obsoletes %s provided by %s\n", pool_solvid2str(pool, source), pool_dep2str(pool, dep), pool_solvid2str(pool, target));
129 case SOLVER_RULE_RPM_PACKAGE_REQUIRES:
130 printf(" package %s requires %s, but none of the providers can be installed\n", pool_solvid2str(pool, source), pool_dep2str(pool, dep));
132 case SOLVER_RULE_RPM_SELF_CONFLICT:
133 printf(" package %s conflicts with %s provided by itself\n", pool_solvid2str(pool, source), pool_dep2str(pool, dep));
144 toinst(Solver *solv, Repo *repo, Repo *instrepo)
146 Pool *pool = solv->pool;
152 solver_get_decisionqueue(solv, &q);
153 for (k = 0; k < q.count; k++)
156 if (p < 0 || p == SYSTEMSOLVABLE)
159 /* printf(" toinstall %s\n", pool_solvid2str(pool, p));*/
161 pool->solvables[p].repo = instrepo;
167 dump_instrepo(Repo *instrepo, Pool *pool)
172 printf("instrepo..\n");
173 FOR_REPO_SOLVABLES(instrepo, p, s)
174 printf(" %s\n", pool_solvable2str(pool, s));
179 frominst(Solver *solv, Repo *repo, Repo *instrepo)
181 Pool *pool = solv->pool;
184 for (k = 1; k < pool->nsolvables; k++)
185 if (pool->solvables[k].repo == instrepo)
186 pool->solvables[k].repo = repo;
193 printf("%s: <arch> <patchnameprefix> [--install-available] [repos] [--updaterepos] [repos]...\n"
194 "\t --install-available: installation repository is available during update\n"
195 "\t repos: repository ending in\n"
196 "\t\tpackages, packages.gz, primary.xml.gz, updateinfo.xml.gz or .solv\n",
206 int install_available;
211 #define SHOW_PATCH(c) if (!(c)->shown++) printf("%s:\n", pool_solvable2str(pool, s));
212 #define PERF_DEBUGGING 0
217 test_all_old_patches_included(context_t *c, Id pid)
221 Solvable *s = pool->solvables + pid;
222 /* Test 1: are all old patches included */
223 FOR_PROVIDES(p, pp, s->name)
225 Solvable *s2 = pool->solvables + p;
230 if (pool_evrcmp(pool, s->evr, s2->evr, EVRCMP_COMPARE) <= 0)
232 conp2 = s2->repo->idarraydata + s2->conflicts;
233 while ((con2 = *conp2++) != 0)
238 rd2 = GETRELDEP(pool, con2);
239 conp = s->repo->idarraydata + s->conflicts;
240 while ((con = *conp++) != 0)
244 rd = GETRELDEP(pool, con);
245 if (rd->name == rd2->name)
251 printf(" %s contained %s\n", pool_solvable2str(pool, s2), pool_dep2str(pool, rd2->name));
255 if (pool_evrcmp(pool, rd->evr, rd2->evr, EVRCMP_COMPARE) < 0)
258 printf(" %s required newer version %s-%s of %s-%s\n",
259 pool_solvable2str(pool, s2), pool_dep2str(pool, rd2->name), pool_dep2str(pool, rd2->evr),
260 pool_dep2str(pool, rd->name), pool_dep2str(pool, rd->evr));
269 test_all_packages_installable(context_t *c, Id pid)
275 unsigned int now, solver_runs;
277 Solvable *s = pool->solvables + pid;
281 now = solv_timems(0);
284 conp = s->repo->idarraydata + s->conflicts;
285 while ((con = *conp++) != 0)
287 FOR_PROVIDES(p, pp, con)
290 queue_push(&job, SOLVER_INSTALL|SOLVER_SOLVABLE|SOLVER_WEAK);
293 /* also set up some minimal system */
294 queue_push(&job, SOLVER_INSTALL|SOLVER_SOLVABLE_PROVIDES|SOLVER_WEAK);
295 queue_push(&job, pool_str2id(pool, "rpm", 1));
296 queue_push(&job, SOLVER_INSTALL|SOLVER_SOLVABLE_PROVIDES|SOLVER_WEAK);
297 queue_push(&job, pool_str2id(pool, "aaa_base", 1));
299 solv = solver_create(pool);
300 /* solver_set_flag(solv, SOLVER_FLAG_IGNORE_RECOMMENDED, 1); */
302 if (solver_solve(solv, &job))
305 printf("error installing original package\n");
306 showproblems(solv, s, 0, 0);
308 toinst(solv, c->repo, c->instrepo);
312 dump_instrepo(instrepo, pool);
315 if (!c->install_available)
318 for (i = 1; i < c->updatestart; i++)
320 if (pool->solvables[i].repo != c->repo || i == pid)
322 queue_push(&job, SOLVER_ERASE|SOLVER_SOLVABLE);
326 queue_push(&job, SOLVER_INSTALL|SOLVER_SOLVABLE);
327 queue_push(&job, pid);
328 solv = solver_create(pool);
329 /* solver_set_flag(solv, SOLVER_FLAG_IGNORE_RECOMMENDED, 1); */
331 if (solver_solve(solv, &job))
334 showproblems(solv, s, 0, 0);
336 frominst(solv, c->repo, c->instrepo);
342 printf(" test_all_packages_installable took %d ms in %d runs\n", solv_timems(now), solver_runs);
346 test_can_upgrade_all_packages(context_t *c, Id pid)
355 unsigned int now, solver_runs;
356 Solvable *s = pool->solvables + pid;
360 queue_init(&badguys);
362 now = solv_timems(0);
365 /* Test 3: can we upgrade all packages? */
366 for (p = 1; p < pool->nsolvables; p++)
368 Solvable *s = pool->solvables + p;
371 if (strchr(pool_id2str(pool, s->name), ':'))
372 continue; /* only packages, please */
373 if (!pool_installable(pool, s))
375 queue_push(&cand, p);
379 solv = solver_create(pool);
381 for (i = 0; i < badguys.count; i++)
383 queue_push(&job, SOLVER_ERASE|SOLVER_SOLVABLE|SOLVER_WEAK);
384 queue_push(&job, badguys.elements[i]);
386 conp = s->repo->idarraydata + s->conflicts;
387 while ((con = *conp++) != 0)
389 queue_push(&job, SOLVER_INSTALL|SOLVER_SOLVABLE_PROVIDES|SOLVER_WEAK);
390 queue_push(&job, con);
392 for (i = 0; i < cand.count; i++)
394 p = cand.elements[i];
395 queue_push(&job, SOLVER_INSTALL|SOLVER_SOLVABLE|SOLVER_WEAK);
399 solver_solve(solv, &job);
401 solver_printdecisions(solv);
403 /* put packages into installed repo and prune them from cand */
404 toinst(solv, c->repo, c->instrepo);
405 for (i = 0; i < cand.count; i++)
407 p = cand.elements[i];
408 if (p > 0 && solver_get_decisionlevel(solv, p) > 0)
409 cand.elements[i] = -p; /* drop candidate */
413 /* now the interesting part: test patch */
415 if (!c->install_available)
417 for (i = 1; i < c->updatestart; i++)
419 if (pool->solvables[i].repo != c->repo || i == pid)
421 queue_push(&job, SOLVER_ERASE|SOLVER_SOLVABLE);
425 queue_push(&job, SOLVER_INSTALL|SOLVER_SOLVABLE);
426 queue_push(&job, pid);
427 solv = solver_create(pool);
428 solver_set_flag(solv, SOLVER_FLAG_IGNORE_RECOMMENDED, 1);
430 if (solver_solve(solv, &job))
433 showproblems(solv, s, &cand, &badguys);
435 frominst(solv, c->repo, c->instrepo);
437 /* now drop all negative elements from cand */
438 for (i = j = 0; i < cand.count; i++)
440 if (cand.elements[i] < 0)
442 cand.elements[j++] = cand.elements[i];
445 break; /* no progress */
449 printf(" test_can_upgrade_all_packages took %d ms in %d runs\n", solv_timems(now), solver_runs);
453 test_no_ga_package_fulfills_dependency(context_t *c, Id pid)
456 Solvable *s = pool->solvables + pid;
458 /* Test 4: no GA package fulfills patch dependency */
459 conp = s->repo->idarraydata + s->conflicts;
460 while ((con = *conp++) != 0)
467 rd = GETRELDEP(pool, con);
468 FOR_PROVIDES(rp, rpp, rd->name)
470 Solvable *s2 = pool_id2solvable(pool, rp);
471 if (rp < c->updatestart
472 && pool_evrcmp(pool, rd->evr, s2->evr, EVRCMP_COMPARE) < 0
473 && pool_match_nevr_rel(pool, s2, rd->name)
477 printf(" conflict %s < %s satisfied by non-updated package %s\n",
478 pool_dep2str(pool, rd->name), pool_dep2str(pool, rd->evr), pool_solvable2str(pool, s2));
486 main(int argc, char **argv)
488 char *arch, *mypatch;
496 static const char* langs[] = {"en"};
498 c.install_available = 0;
506 pool = pool_create();
507 pool_setarch(pool, arch);
508 pool_set_languages(pool, langs, 1);
511 pool_setdebuglevel(pool, 2);
516 c.repo = repo_create(pool, 0);
517 c.instrepo = repo_create(pool, 0);
518 for (i = 3; i < argc; i++)
520 if (!strcmp(argv[i], "--updaterepos"))
522 c.updatestart = pool->nsolvables;
526 if (!strcmp(argv[i], "--install-available"))
528 c.install_available = 1;
533 if (!strcmp(argv[i], "-"))
535 else if ((fp = solv_xfopen(argv[i], 0)) == 0)
544 #ifdef ENABLE_SUSEREPO
545 else if (l >= 8 && !strcmp(argv[i] + l - 8, "packages"))
547 r = repo_add_susetags(c.repo, fp, 0, 0, 0);
549 else if (l >= 11 && !strcmp(argv[i] + l - 11, "packages.gz"))
551 r = repo_add_susetags(c.repo, fp, 0, 0, 0);
555 else if (l >= 14 && !strcmp(argv[i] + l - 14, "primary.xml.gz"))
557 r = repo_add_rpmmd(c.repo, fp, 0, 0);
559 else if (l >= 17 && !strcmp(argv[i] + l - 17, "updateinfo.xml.gz"))
561 r = repo_add_updateinfoxml(c.repo, fp, 0);
565 r = repo_add_solv(c.repo, fp, 0);
568 fprintf(stderr, "could not add repo %s: %s\n", argv[i], pool_errstr(pool));
575 pool_addfileprovides(pool);
577 /* bad hack ahead: clone repo */
578 c.instrepo->idarraydata = c.repo->idarraydata;
579 c.instrepo->idarraysize = c.repo->idarraysize;
580 c.instrepo->start = c.repo->start;
581 c.instrepo->end = c.repo->end;
582 c.instrepo->nsolvables = c.repo->nsolvables; /* sic! */
583 pool_set_installed(pool, c.instrepo);
584 pool_createwhatprovides(pool);
586 for (pid = 1; pid < pool->nsolvables; pid++)
590 s = pool->solvables + pid;
593 if (!pool_installable(pool, s))
595 pname = pool_id2str(pool, s->name);
596 if (strncmp(pname, "patch:", 6) != 0)
601 if (strncmp(mypatch, pname + 6, strlen(pname + 6)) != 0)
603 if (strcmp(mypatch, pname + 6) != 0)
605 l = strlen(pname + 6);
606 if (mypatch[l] != '-')
608 if (strcmp(mypatch + l + 1, pool_id2str(pool, s->evr)) != 0)
614 FOR_PROVIDES(p, pp, s->name)
616 Solvable *s2 = pool->solvables + p;
617 if (pool_evrcmp(pool, s->evr, s2->evr, EVRCMP_COMPARE) < 0)
621 /* printf("found a newer one for %s\n", pname+6); */
622 continue; /* found a newer one */
630 printf("testing patch %s-%s\n", pname + 6, pool_id2str(pool, s->evr));
633 test_all_old_patches_included(&c, pid);
634 test_all_packages_installable(&c, pid);
635 test_can_upgrade_all_packages(&c, pid);
636 test_no_ga_package_fulfills_dependency(&c, pid);