2 * Copyright (c) 2007, Novell Inc.
4 * This program is licensed under the BSD license, read LICENSE.BSD
5 * for further information
21 #include "selection.h"
26 str2archid(Pool *pool, const char *arch)
31 id = pool_str2id(pool, arch, 0);
32 if (!id || id == ARCH_SRC || id == ARCH_NOSRC || id == ARCH_NOARCH)
34 if (pool->id2arch && (id > pool->lastarch || !pool->id2arch[id]))
40 selection_prune(Pool *pool, Queue *selection)
44 for (i = j = 0; i < selection->count; i += 2)
46 Id select = selection->elements[i] & SOLVER_SELECTMASK;
48 if (select == SOLVER_SOLVABLE_ALL)
50 else if (select == SOLVER_SOLVABLE_REPO)
53 Repo *repo = pool_id2repo(pool, selection->elements[i + 1]);
55 FOR_REPO_SOLVABLES(repo, p, s)
60 FOR_JOB_SELECT(p, pp, select, selection->elements[i + 1])
65 selection->elements[j] = selection->elements[i];
66 selection->elements[j + 1] = selection->elements[i + 1];
69 queue_truncate(selection, j);
74 selection_solvables_sortcmp(const void *ap, const void *bp, void *dp)
76 return *(const Id *)ap - *(const Id *)bp;
80 selection_solvables(Pool *pool, Queue *selection, Queue *pkgs)
85 for (i = 0; i < selection->count; i += 2)
87 Id select = selection->elements[i] & SOLVER_SELECTMASK;
88 if (select == SOLVER_SOLVABLE_ALL)
93 if (select == SOLVER_SOLVABLE_REPO)
96 Repo *repo = pool_id2repo(pool, selection->elements[i + 1]);
98 FOR_REPO_SOLVABLES(repo, p, s)
103 FOR_JOB_SELECT(p, pp, select, selection->elements[i + 1])
110 solv_sort(pkgs->elements, pkgs->count, sizeof(Id), selection_solvables_sortcmp, NULL);
111 lastid = pkgs->elements[0];
112 for (i = j = 1; i < pkgs->count; i++)
113 if (pkgs->elements[i] != lastid)
114 pkgs->elements[j++] = lastid = pkgs->elements[i];
115 queue_truncate(pkgs, j);
119 selection_flatten(Pool *pool, Queue *selection)
123 if (selection->count <= 1)
125 for (i = 0; i < selection->count; i += 2)
126 if ((selection->elements[i] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_ALL)
128 selection->elements[0] = selection->elements[i];
129 selection->elements[1] = selection->elements[i + 1];
130 queue_truncate(selection, 2);
134 selection_solvables(pool, selection, &q);
137 queue_empty(selection);
140 queue_truncate(selection, 2);
143 selection->elements[0] = SOLVER_SOLVABLE_ONE_OF;
144 selection->elements[1] = pool_queuetowhatprovides(pool, &q);
148 selection->elements[0] = SOLVER_SOLVABLE | SOLVER_NOAUTOSET;
149 selection->elements[1] = q.elements[0];
154 selection_limit_rel(Pool *pool, Queue *selection, Id relflags, Id relevr)
157 for (i = 0; i < selection->count; i += 2)
159 Id select = selection->elements[i] & SOLVER_SELECTMASK;
160 Id id = selection->elements[i + 1];
161 if (select == SOLVER_SOLVABLE || select == SOLVER_SOLVABLE_ONE_OF)
163 /* done by selection_addsrc */
166 Id rel = 0, relname = 0;
170 FOR_JOB_SELECT(p, pp, select, id)
172 Solvable *s = pool->solvables + p;
173 if (!rel || s->name != relname)
176 rel = pool_rel2id(pool, relname, relevr, relflags, 1);
178 if (pool_match_nevr(pool, s, rel))
187 selection->elements[i] = SOLVER_SOLVABLE | SOLVER_NOAUTOSET;
188 selection->elements[i + 1] = q.elements[0];
192 selection->elements[i] = SOLVER_SOLVABLE_ONE_OF;
193 selection->elements[i + 1] = pool_queuetowhatprovides(pool, &q);
199 if (select != SOLVER_SOLVABLE_NAME && select != SOLVER_SOLVABLE_PROVIDES)
200 continue; /* actually internal error */
201 if (relflags == REL_ARCH && (relevr == ARCH_SRC || relevr == ARCH_NOSRC) && ISRELDEP(id))
203 Reldep *rd = GETRELDEP(pool, id);
204 if (rd->flags == REL_ARCH && rd->evr == ARCH_SRC)
207 selection->elements[i + 1] = pool_rel2id(pool, id, relevr, relflags, 1);
208 if (relflags == REL_ARCH)
209 selection->elements[i] |= SOLVER_SETARCH;
210 if (relflags == REL_EQ && select == SOLVER_SOLVABLE_NAME && selection->elements[i])
212 if (pool->disttype == DISTTYPE_DEB)
213 selection->elements[i] |= SOLVER_SETEVR; /* debian can't match version only like rpm */
215 selection->elements[i] |= strchr(pool_id2str(pool, relevr), '-') != 0 ? SOLVER_SETEVR : SOLVER_SETEV;
218 selection_prune(pool, selection);
222 selection_addsrc(Pool *pool, Queue *selection, int flags)
228 if ((flags & SELECTION_INSTALLED_ONLY) != 0)
229 return; /* sources can't be installed */
231 for (i = 0; i < selection->count; i += 2)
233 if (selection->elements[i] != SOLVER_SOLVABLE_NAME)
235 name = selection->elements[i + 1];
238 FOR_POOL_SOLVABLES(p)
240 Solvable *s = pool->solvables + p;
243 if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
245 else if (!pool_installable(pool, s))
249 if (!havesrc || !q.count)
253 selection->elements[i] = SOLVER_SOLVABLE | SOLVER_NOAUTOSET;
254 selection->elements[i + 1] = q.elements[0];
258 selection->elements[i] = SOLVER_SOLVABLE_ONE_OF;
259 selection->elements[i + 1] = pool_queuetowhatprovides(pool, &q);
266 selection_depglob(Pool *pool, Queue *selection, const char *name, int flags)
273 if ((flags & SELECTION_SOURCE_ONLY) != 0)
275 flags &= ~SELECTION_PROVIDES; /* sources don't provide anything */
276 flags &= ~SELECTION_WITH_SOURCE;
279 if (!(flags & (SELECTION_NAME|SELECTION_PROVIDES)))
282 if ((flags & SELECTION_INSTALLED_ONLY) != 0 && !pool->installed)
285 if (!(flags & SELECTION_NOCASE))
287 id = pool_str2id(pool, name, 0);
290 if ((flags & (SELECTION_SOURCE_ONLY | SELECTION_WITH_SOURCE)) != 0 && (flags & SELECTION_NAME) != 0)
292 /* src rpms don't have provides, so we must check every solvable */
293 FOR_PROVIDES(p, pp, id) /* try fast path first */
295 Solvable *s = pool->solvables + p;
298 if ((flags & SELECTION_INSTALLED_ONLY) != 0 && s->repo != pool->installed)
300 if ((flags & SELECTION_SOURCE_ONLY) != 0)
301 id = pool_rel2id(pool, id, ARCH_SRC, REL_ARCH, 1);
302 queue_push2(selection, SOLVER_SOLVABLE_NAME, id);
303 if ((flags & SELECTION_WITH_SOURCE) != 0)
304 selection_addsrc(pool, selection, flags);
305 return SELECTION_NAME;
308 FOR_POOL_SOLVABLES(p) /* slow path */
310 Solvable *s = pool->solvables + p;
311 if (s->name == id && (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC))
313 if ((flags & SELECTION_INSTALLED_ONLY) != 0 && s->repo != pool->installed)
314 continue; /* just in case... src rpms can't be installed */
315 if ((flags & SELECTION_SOURCE_ONLY) != 0)
316 id = pool_rel2id(pool, id, ARCH_SRC, REL_ARCH, 1);
317 queue_push2(selection, SOLVER_SOLVABLE_NAME, id);
318 if ((flags & SELECTION_WITH_SOURCE) != 0)
319 selection_addsrc(pool, selection, flags);
320 return SELECTION_NAME;
324 FOR_PROVIDES(p, pp, id)
326 Solvable *s = pool->solvables + p;
327 if ((flags & SELECTION_INSTALLED_ONLY) != 0 && s->repo != pool->installed)
330 if (s->name == id && (flags & SELECTION_NAME) != 0)
332 if ((flags & SELECTION_SOURCE_ONLY) != 0)
333 id = pool_rel2id(pool, id, ARCH_SRC, REL_ARCH, 1);
334 queue_push2(selection, SOLVER_SOLVABLE_NAME, id);
335 if ((flags & SELECTION_WITH_SOURCE) != 0)
336 selection_addsrc(pool, selection, flags);
337 return SELECTION_NAME;
340 if (match && (flags & SELECTION_PROVIDES) != 0)
342 queue_push2(selection, SOLVER_SOLVABLE_PROVIDES, id);
343 return SELECTION_PROVIDES;
348 if ((flags & SELECTION_GLOB) != 0 && strpbrk(name, "[*?") != 0)
351 if (!doglob && !(flags & SELECTION_NOCASE))
354 if (doglob && (flags & SELECTION_NOCASE) != 0)
355 globflags = FNM_CASEFOLD;
357 #if 0 /* doesn't work with selection_limit_rel yet */
358 if (doglob && !strcmp(name, "*") && (flags & SELECTION_FLAT) != 0)
360 /* can't do this for SELECTION_PROVIDES, as src rpms don't provide anything */
361 if ((flags & SELECTION_NAME) != 0)
363 queue_push2(selection, SOLVER_SOLVABLE_ALL, 0);
364 return SELECTION_NAME;
369 if ((flags & SELECTION_NAME) != 0)
371 /* looks like a name glob. hard work. */
372 FOR_POOL_SOLVABLES(p)
374 Solvable *s = pool->solvables + p;
375 if (!pool_installable(pool, s))
376 if (!(flags & SELECTION_SOURCE_ONLY) || (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC))
378 if ((flags & SELECTION_INSTALLED_ONLY) != 0 && s->repo != pool->installed)
381 if ((doglob ? fnmatch(name, pool_id2str(pool, id), globflags) : strcasecmp(name, pool_id2str(pool, id))) == 0)
383 if ((flags & SELECTION_SOURCE_ONLY) != 0)
384 id = pool_rel2id(pool, id, ARCH_SRC, REL_ARCH, 1);
385 /* queue_pushunique2 */
386 for (i = 0; i < selection->count; i += 2)
387 if (selection->elements[i] == SOLVER_SOLVABLE_NAME && selection->elements[i + 1] == id)
389 if (i == selection->count)
390 queue_push2(selection, SOLVER_SOLVABLE_NAME, id);
396 if ((flags & SELECTION_WITH_SOURCE) != 0)
397 selection_addsrc(pool, selection, flags);
398 return SELECTION_NAME;
401 if ((flags & SELECTION_PROVIDES))
403 /* looks like a dep glob. really hard work. */
404 for (id = 1; id < pool->ss.nstrings; id++)
406 if (!pool->whatprovides[id])
408 if ((doglob ? fnmatch(name, pool_id2str(pool, id), globflags) : strcasecmp(name, pool_id2str(pool, id))) == 0)
410 if ((flags & SELECTION_INSTALLED_ONLY) != 0)
412 FOR_PROVIDES(p, pp, id)
413 if (pool->solvables[p].repo == pool->installed)
418 queue_push2(selection, SOLVER_SOLVABLE_PROVIDES, id);
423 return SELECTION_PROVIDES;
429 selection_depglob_arch(Pool *pool, Queue *selection, const char *name, int flags)
435 if ((ret = selection_depglob(pool, selection, name, flags)) != 0)
437 /* check if theres an .arch suffix */
438 if ((r = strrchr(name, '.')) != 0 && r[1] && (archid = str2archid(pool, r + 1)) != 0)
440 char *rname = solv_strdup(name);
442 if (archid == ARCH_SRC || archid == ARCH_NOSRC)
443 flags |= SELECTION_SOURCE_ONLY;
444 if ((ret = selection_depglob(pool, selection, rname, flags)) != 0)
446 selection_limit_rel(pool, selection, REL_ARCH, archid);
456 selection_filelist(Pool *pool, Queue *selection, const char *name, int flags)
462 type = !(flags & SELECTION_GLOB) || strpbrk(name, "[*?") == 0 ? SEARCH_STRING : SEARCH_GLOB;
463 if ((flags & SELECTION_NOCASE) != 0)
464 type |= SEARCH_NOCASE;
466 dataiterator_init(&di, pool, flags & SELECTION_INSTALLED_ONLY ? pool->installed : 0, 0, SOLVABLE_FILELIST, name, type|SEARCH_FILES|SEARCH_COMPLETE_FILELIST);
467 while (dataiterator_step(&di))
469 Solvable *s = pool->solvables + di.solvid;
472 if (!pool_installable(pool, s))
473 if (!(flags & SELECTION_SOURCE_ONLY) || (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC))
475 if ((flags & SELECTION_INSTALLED_ONLY) != 0 && s->repo != pool->installed)
477 queue_push(&q, di.solvid);
478 dataiterator_skip_solvable(&di);
480 dataiterator_free(&di);
484 queue_push2(selection, SOLVER_SOLVABLE_ONE_OF, pool_queuetowhatprovides(pool, &q));
486 queue_push2(selection, SOLVER_SOLVABLE | SOLVER_NOAUTOSET, q.elements[0]);
488 return SELECTION_FILELIST;
492 selection_rel(Pool *pool, Queue *selection, const char *name, int flags)
497 /* relation case, support:
501 rname = solv_strdup(name);
502 if ((r = strpbrk(rname, "<=>")) != 0)
504 int nend = r - rname;
516 while (*r && *r == ' ' && *r == '\t')
518 while (nend && (rname[nend - 1] == ' ' || rname[nend -1 ] == '\t'))
527 if ((ret = selection_depglob_arch(pool, selection, rname, flags)) != 0)
530 selection_limit_rel(pool, selection, rflags, pool_str2id(pool, r, 1));
539 selection_nevra(Pool *pool, Queue *selection, const char *name, int flags)
541 char *rname, *r, *r2;
547 * nameglob-version.arch
548 * nameglob-version-release
549 * nameglob-version-release.arch
551 flags |= SELECTION_NAME;
552 flags &= ~SELECTION_PROVIDES;
554 if (pool->disttype == DISTTYPE_DEB)
556 if ((r = strchr(name, '_')) == 0)
558 rname = solv_strdup(name); /* so we can modify it */
559 r = rname + (r - name);
561 if ((ret = selection_depglob(pool, selection, rname, flags)) == 0)
566 /* is there a vaild arch? */
567 if ((r2 = strchr(r, '_')) != 0 && r[1] && (archid = str2archid(pool, r + 1)) != 0)
569 *r2 = 0; /* split off */
570 selection_limit_rel(pool, selection, REL_ARCH, archid);
572 selection_limit_rel(pool, selection, REL_EQ, pool_str2id(pool, r, 1));
577 if ((r = strrchr(name, '-')) == 0)
579 rname = solv_strdup(name); /* so we can modify it */
580 r = rname + (r - name);
583 /* split off potential arch part from version */
584 if ((r2 = strrchr(r + 1, '.')) != 0 && r2[1] && (archid = str2archid(pool, r2 + 1)) != 0)
585 *r2 = 0; /* found valid arch, split it off */
586 if (archid == ARCH_SRC || archid == ARCH_NOSRC)
587 flags |= SELECTION_SOURCE_ONLY;
589 /* try with just the version */
590 if ((ret = selection_depglob(pool, selection, rname, flags)) == 0)
592 /* no luck, try with version-release */
593 if ((r2 = strrchr(rname, '-')) == 0)
601 if ((ret = selection_depglob(pool, selection, rname, flags)) == 0)
608 selection_limit_rel(pool, selection, REL_ARCH, archid);
609 selection_limit_rel(pool, selection, REL_EQ, pool_str2id(pool, r + 1, 1));
615 selection_make(Pool *pool, Queue *selection, const char *name, int flags)
620 queue_empty(selection);
621 if (*name == '/' && (flags & SELECTION_FILELIST))
622 ret = selection_filelist(pool, selection, name, flags);
623 if (!ret && (r = strpbrk(name, "<=>")) != 0)
624 ret = selection_rel(pool, selection, name, flags);
626 ret = selection_depglob_arch(pool, selection, name, flags);
627 if (!ret && (flags & SELECTION_NAME) != 0)
628 ret = selection_nevra(pool, selection, name, flags);
629 if (ret && (flags & SELECTION_FLAT) != 0)
630 selection_flatten(pool, selection);
635 selection_limit(Pool *pool, Queue *sel1, Queue *sel2)
643 if (!sel1->count || !sel2->count)
648 if (sel1->count == 2 && (sel1->elements[0] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_ALL)
650 /* XXX: not 100% correct, but very useful */
652 queue_init_clone(sel1, sel2);
656 map_init(&m2, pool->nsolvables);
657 for (i = 0; i < sel2->count; i += 2)
659 Id select = sel2->elements[i] & SOLVER_SELECTMASK;
660 if (select == SOLVER_SOLVABLE_ALL)
662 if (select == SOLVER_SOLVABLE_REPO)
665 Repo *repo = pool_id2repo(pool, sel2->elements[i + 1]);
667 FOR_REPO_SOLVABLES(repo, p, s)
672 FOR_JOB_SELECT(p, pp, select, sel2->elements[i + 1])
676 if (sel2->count == 2) /* XXX: AND all setmasks instead? */
677 setflags = sel2->elements[0] & SOLVER_SETMASK & ~SOLVER_NOAUTOSET;
678 for (i = j = 0; i < sel1->count; i += 2)
680 Id select = sel1->elements[i] & SOLVER_SELECTMASK;
683 if (select == SOLVER_SOLVABLE_ALL)
685 FOR_POOL_SOLVABLES(p)
693 else if (select == SOLVER_SOLVABLE_REPO)
696 Repo *repo = pool_id2repo(pool, sel1->elements[i + 1]);
698 FOR_REPO_SOLVABLES(repo, p, s)
708 FOR_JOB_SELECT(p, pp, select, sel1->elements[i + 1])
711 queue_pushunique(&q1, p);
720 sel1->elements[j] = sel1->elements[i] | setflags;
721 sel1->elements[j + 1] = sel1->elements[i + 1];
723 else if (q1.count > 1)
725 sel1->elements[j] = (sel1->elements[i] & ~SOLVER_SELECTMASK) | SOLVER_SOLVABLE_ONE_OF | setflags;
726 sel1->elements[j + 1] = pool_queuetowhatprovides(pool, &q1);
730 sel1->elements[j] = (sel1->elements[i] & ~SOLVER_SELECTMASK) | SOLVER_SOLVABLE | SOLVER_NOAUTOSET | setflags;
731 sel1->elements[j + 1] = q1.elements[0];
735 queue_truncate(sel1, j);
739 selection_add(Pool *pool, Queue *sel1, Queue *sel2)
742 for (i = 0; i < sel2->count; i++)
743 queue_push(sel1, sel2->elements[i]);