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"
30 cookie_gzread(void *cookie, char *buf, size_t nbytes)
32 return gzread((gzFile *)cookie, buf, nbytes);
36 cookie_gzclose(void *cookie)
38 return gzclose((gzFile *)cookie);
42 myfopen(const char *fn)
44 cookie_io_functions_t cio;
50 suf = strrchr(fn, '.');
51 if (!suf || strcmp(suf, ".gz") != 0)
52 return fopen(fn, "r");
53 gzf = gzopen(fn, "r");
56 memset(&cio, 0, sizeof(cio));
57 cio.read = cookie_gzread;
58 cio.close = cookie_gzclose;
59 return fopencookie(gzf, "r", cio);
63 showproblems(Solver *solv, Solvable *s, Queue *cand, Queue *badguys)
65 Pool *pool = solv->pool;
73 printf("can't install %s:\n", solvable2str(pool, s));
74 while ((problem = solver_next_problem(solv, problem)) != 0)
76 solver_findallproblemrules(solv, problem, &rids);
77 for (jj = 0; jj < rids.count; jj++)
79 Id probr = rids.elements[jj];
83 solver_allruleinfos(solv, probr, &rinfo);
84 for (k = 0; k < rinfo.count; k += 4)
86 Id dep, source, target;
87 source = rinfo.elements[k + 1];
88 target = rinfo.elements[k + 2];
89 dep = rinfo.elements[k + 3];
90 switch (rinfo.elements[k])
92 case SOLVER_PROBLEM_DISTUPGRADE_RULE:
94 case SOLVER_PROBLEM_INFARCH_RULE:
95 printf(" %s has inferior architecture\n", solvid2str(pool, source));
97 case SOLVER_PROBLEM_UPDATE_RULE:
98 printf(" update rule for %s\n", solvid2str(pool, source));
100 queue_pushunique(badguys, source);
103 /* only drop update problem packages from cand so that we see all problems of this patch */
104 for (l = 0; l < cand->count; l++)
105 if (cand->elements[l] == source || cand->elements[l] == -source)
107 if (l == cand->count)
111 for (l = 0; l < cand->count; l++)
112 if (cand->elements[l] < 0)
113 cand->elements[l] = -cand->elements[l];
116 for (l = 0; l < cand->count; l++)
117 if (cand->elements[l] == source)
119 cand->elements[l] = -source;
122 case SOLVER_PROBLEM_JOB_RULE:
124 case SOLVER_PROBLEM_RPM_RULE:
125 printf(" some dependency problem\n");
127 case SOLVER_PROBLEM_JOB_NOTHING_PROVIDES_DEP:
128 printf(" nothing provides requested %s\n", dep2str(pool, dep));
130 case SOLVER_PROBLEM_NOT_INSTALLABLE:
131 printf(" package %s is not installable\n", solvid2str(pool, source));
133 case SOLVER_PROBLEM_NOTHING_PROVIDES_DEP:
134 printf(" nothing provides %s needed by %s\n", dep2str(pool, dep), solvid2str(pool, source));
137 Reldep *rd = GETRELDEP(pool, dep);
138 if (!ISRELDEP(rd->name))
141 FOR_PROVIDES(rp, rpp, rd->name)
142 printf(" (we have %s)\n", solvid2str(pool, rp));
146 case SOLVER_PROBLEM_SAME_NAME:
147 printf(" cannot install both %s and %s\n", solvid2str(pool, source), solvid2str(pool, target));
149 case SOLVER_PROBLEM_PACKAGE_CONFLICT:
150 printf(" package %s conflicts with %s provided by %s\n", solvid2str(pool, source), dep2str(pool, dep), solvid2str(pool, target));
152 case SOLVER_PROBLEM_PACKAGE_OBSOLETES:
153 printf(" package %s obsoletes %s provided by %s\n", solvid2str(pool, source), dep2str(pool, dep), solvid2str(pool, target));
155 case SOLVER_PROBLEM_DEP_PROVIDERS_NOT_INSTALLABLE:
156 printf(" package %s requires %s, but none of the providers can be installed\n", solvid2str(pool, source), dep2str(pool, dep));
158 case SOLVER_PROBLEM_SELF_CONFLICT:
159 printf(" package %s conflicts with %s provided by itself\n", solvid2str(pool, source), dep2str(pool, dep));
170 toinst(Solver *solv, Repo *repo, Repo *instrepo)
172 Pool *pool = solv->pool;
176 for (k = 0; k < solv->decisionq.count; k++)
178 p = solv->decisionq.elements[k];
179 if (p < 0 || p == SYSTEMSOLVABLE)
182 /* printf(" toinstall %s\n", solvid2str(pool, p));*/
184 pool->solvables[p].repo = instrepo;
189 dump_instrepo(Repo *instrepo, Pool *pool)
194 printf("instrepo..\n");
195 FOR_REPO_SOLVABLES(instrepo, p, s)
196 printf(" %s\n", solvable2str(pool, s));
201 frominst(Solver *solv, Repo *repo, Repo *instrepo)
203 Pool *pool = solv->pool;
206 for (k = 1; k < pool->nsolvables; k++)
207 if (pool->solvables[k].repo == instrepo)
208 pool->solvables[k].repo = repo;
215 printf("%s: <arch> <patchnameprefix> [--install-available] [repos] [--updaterepos] [repos]...\n"
216 "\t --install-available: installation repository is available during update\n"
217 "\t repos: repository ending in\n"
218 "\t\tpackages, packages.gz, primary.xml.gz, updateinfo.xml.gz or .solv\n",
228 int install_available;
233 #define SHOW_PATCH(c) if (!(c)->shown++) printf("%s:\n", solvable2str(pool, s));
234 #define PERF_DEBUGGING 0
239 test_all_old_patches_included(context_t *c, Id pid)
243 Solvable *s = pool->solvables + pid;
244 /* Test 1: are all old patches included */
245 FOR_PROVIDES(p, pp, s->name)
247 Solvable *s2 = pool->solvables + p;
252 if (evrcmp(pool, s->evr, s2->evr, EVRCMP_COMPARE) <= 0)
254 conp2 = s2->repo->idarraydata + s2->conflicts;
255 while ((con2 = *conp2++) != 0)
260 rd2 = GETRELDEP(pool, con2);
261 conp = s->repo->idarraydata + s->conflicts;
262 while ((con = *conp++) != 0)
266 rd = GETRELDEP(pool, con);
267 if (rd->name == rd2->name)
273 printf(" %s contained %s\n", solvable2str(pool, s2), dep2str(pool, rd2->name));
277 if (evrcmp(pool, rd->evr, rd2->evr, EVRCMP_COMPARE) < 0)
280 printf(" %s required newer version %s-%s of %s-%s\n",
281 solvable2str(pool, s2), dep2str(pool, rd2->name), dep2str(pool, rd2->evr),
282 dep2str(pool, rd->name), dep2str(pool, rd->evr));
291 test_all_packages_installable(context_t *c, Id pid)
297 unsigned int now, solver_runs;
299 Solvable *s = pool->solvables + pid;
306 conp = s->repo->idarraydata + s->conflicts;
307 while ((con = *conp++) != 0)
309 FOR_PROVIDES(p, pp, con)
312 queue_push(&job, SOLVER_INSTALL|SOLVER_SOLVABLE|SOLVER_WEAK);
315 /* also set up some minimal system */
316 queue_push(&job, SOLVER_INSTALL|SOLVER_SOLVABLE_PROVIDES|SOLVER_WEAK);
317 queue_push(&job, str2id(pool, "rpm", 1));
318 queue_push(&job, SOLVER_INSTALL|SOLVER_SOLVABLE_PROVIDES|SOLVER_WEAK);
319 queue_push(&job, str2id(pool, "aaa_base", 1));
321 solv = solver_create(pool);
322 solv->dontinstallrecommended = 0;
324 solver_solve(solv, &job);
325 if (solv->problems.count)
328 printf("error installing original package\n");
329 showproblems(solv, s, 0, 0);
331 toinst(solv, c->repo, c->instrepo);
335 dump_instrepo(instrepo, pool);
338 if (!c->install_available)
341 for (i = 1; i < c->updatestart; i++)
343 if (pool->solvables[i].repo != c->repo || i == pid)
345 queue_push(&job, SOLVER_ERASE|SOLVER_SOLVABLE);
349 queue_push(&job, SOLVER_INSTALL_SOLVABLE);
350 queue_push(&job, pid);
351 solv = solver_create(pool);
352 /*solv->dontinstallrecommended = 1;*/
354 solver_solve(solv, &job);
355 if (solv->problems.count)
358 showproblems(solv, s, 0, 0);
360 frominst(solv, c->repo, c->instrepo);
366 printf(" test_all_packages_installable took %d ms in %d runs\n", sat_timems(now), solver_runs);
370 test_can_upgrade_all_packages(context_t *c, Id pid)
379 unsigned int now, solver_runs;
380 Solvable *s = pool->solvables + pid;
384 queue_init(&badguys);
389 /* Test 3: can we upgrade all packages? */
390 for (p = 1; p < pool->nsolvables; p++)
392 Solvable *s = pool->solvables + p;
395 if (strchr(id2str(pool, s->name), ':'))
396 continue; /* only packages, please */
397 if (!pool_installable(pool, s))
399 queue_push(&cand, p);
403 solv = solver_create(pool);
405 for (i = 0; i < badguys.count; i++)
407 queue_push(&job, SOLVER_ERASE|SOLVER_SOLVABLE|SOLVER_WEAK);
408 queue_push(&job, badguys.elements[i]);
410 conp = s->repo->idarraydata + s->conflicts;
411 while ((con = *conp++) != 0)
413 queue_push(&job, SOLVER_INSTALL|SOLVER_SOLVABLE_PROVIDES|SOLVER_WEAK);
414 queue_push(&job, con);
416 for (i = 0; i < cand.count; i++)
418 p = cand.elements[i];
419 queue_push(&job, SOLVER_INSTALL|SOLVER_SOLVABLE|SOLVER_WEAK);
423 solver_solve(solv, &job);
425 solver_printdecisions(solv);
427 /* put packages into installed repo and prune them from cand */
428 toinst(solv, c->repo, c->instrepo);
429 for (i = 0; i < cand.count; i++)
431 p = cand.elements[i];
432 if (p > 0 && solv->decisionmap[p] > 0)
433 cand.elements[i] = -p; /* drop candidate */
437 /* now the interesting part: test patch */
439 if (!c->install_available)
441 for (i = 1; i < c->updatestart; i++)
443 if (pool->solvables[i].repo != c->repo || i == pid)
445 queue_push(&job, SOLVER_ERASE|SOLVER_SOLVABLE);
449 queue_push(&job, SOLVER_INSTALL_SOLVABLE);
450 queue_push(&job, pid);
451 solv = solver_create(pool);
452 solv->dontinstallrecommended = 1;
454 solver_solve(solv, &job);
456 if (solv->problems.count)
459 showproblems(solv, s, &cand, &badguys);
461 frominst(solv, c->repo, c->instrepo);
463 /* now drop all negative elements from cand */
464 for (i = j = 0; i < cand.count; i++)
466 if (cand.elements[i] < 0)
468 cand.elements[j++] = cand.elements[i];
471 break; /* no progress */
475 printf(" test_can_upgrade_all_packages took %d ms in %d runs\n", sat_timems(now), solver_runs);
479 test_no_ga_package_fulfills_dependency(context_t *c, Id pid)
482 Solvable *s = pool->solvables + pid;
484 /* Test 4: no GA package fulfills patch dependency */
485 conp = s->repo->idarraydata + s->conflicts;
486 while ((con = *conp++) != 0)
493 rd = GETRELDEP(pool, con);
494 FOR_PROVIDES(rp, rpp, rd->name)
496 Solvable *s2 = pool_id2solvable(pool, rp);
497 if (rp < c->updatestart
498 && evrcmp(pool, rd->evr, s2->evr, EVRCMP_COMPARE) < 0
499 && pool_match_nevr_rel(pool, s2, rd->name)
503 printf(" conflict %s < %s satisfied by non-updated package %s\n",
504 dep2str(pool, rd->name), dep2str(pool, rd->evr), solvable2str(pool, s2));
512 main(int argc, char **argv)
514 char *arch, *mypatch;
523 c.install_available = 0;
531 pool = pool_create();
532 pool_setarch(pool, arch);
533 static const char* langs[] = {"en"};
534 pool_set_languages(pool, langs, 1);
537 pool_setdebuglevel(pool, 2);
542 c.repo = repo_create(pool, 0);
543 c.instrepo = repo_create(pool, 0);
544 for (i = 3; i < argc; i++)
546 if (!strcmp(argv[i], "--updaterepos"))
548 c.updatestart = pool->nsolvables;
552 if (!strcmp(argv[i], "--install-available"))
554 c.install_available = 1;
559 if (!strcmp(argv[i], "-"))
561 else if ((fp = myfopen(argv[i])) == 0)
566 if (l >= 8 && !strcmp(argv[i] + l - 8, "packages"))
568 repo_add_susetags(c.repo, fp, 0, 0, 0);
570 else if (l >= 11 && !strcmp(argv[i] + l - 11, "packages.gz"))
572 repo_add_susetags(c.repo, fp, 0, 0, 0);
574 else if (l >= 14 && !strcmp(argv[i] + l - 14, "primary.xml.gz"))
576 repo_add_rpmmd(c.repo, fp, 0, 0);
578 else if (l >= 17 && !strcmp(argv[i] + l - 17, "updateinfo.xml.gz"))
580 repo_add_updateinfoxml(c.repo, fp, 0);
582 else if (repo_add_solv(c.repo, fp))
584 fprintf(stderr, "could not add repo %s\n", argv[i]);
591 pool_addfileprovides(pool);
593 /* bad hack ahead: clone repo */
594 c.instrepo->idarraydata = c.repo->idarraydata;
595 c.instrepo->idarraysize = c.repo->idarraysize;
596 c.instrepo->start = c.repo->start;
597 c.instrepo->end = c.repo->end;
598 c.instrepo->nsolvables = c.repo->nsolvables; /* sic! */
599 c.instrepo->lastoff = c.repo->lastoff; /* sic! */
600 pool_set_installed(pool, c.instrepo);
601 pool_createwhatprovides(pool);
603 for (pid = 1; pid < pool->nsolvables; pid++)
606 Solvable *s = pool->solvables + pid;
609 if (!pool_installable(pool, s))
611 pname = id2str(pool, s->name);
612 if (strncmp(pname, "patch:", 6) != 0)
617 if (strncmp(mypatch, pname + 6, strlen(pname + 6)) != 0)
619 if (strcmp(mypatch, pname + 6) != 0)
621 l = strlen(pname + 6);
622 if (mypatch[l] != '-')
624 if (strcmp(mypatch + l + 1, id2str(pool, s->evr)) != 0)
630 FOR_PROVIDES(p, pp, s->name)
632 Solvable *s2 = pool->solvables + p;
633 if (evrcmp(pool, s->evr, s2->evr, EVRCMP_COMPARE) < 0)
637 /* printf("found a newer one for %s\n", pname+6); */
638 continue; /* found a newer one */
646 printf("testing patch %s-%s\n", pname + 6, id2str(pool, s->evr));
649 test_all_old_patches_included(&c, pid);
650 test_all_packages_installable(&c, pid);
651 test_can_upgrade_all_packages(&c, pid);
652 test_no_ga_package_fulfills_dependency(&c, pid);