2 * Copyright (c) 2012, Novell Inc.
4 * This program is licensed under the BSD license, read LICENSE.BSD
5 * for further information
21 #include "selection.h"
33 str2archid(Pool *pool, const char *arch)
38 id = pool_str2id(pool, arch, 0);
39 if (!id || id == ARCH_SRC || id == ARCH_NOSRC || id == ARCH_NOARCH)
41 if (pool->id2arch && pool_arch2score(pool, id) == 0)
46 /* remove empty jobs from the selection */
48 selection_prune(Pool *pool, Queue *selection)
52 for (i = j = 0; i < selection->count; i += 2)
54 Id select = selection->elements[i] & SOLVER_SELECTMASK;
56 if (select == SOLVER_SOLVABLE_ALL)
58 else if (select == SOLVER_SOLVABLE_REPO)
61 Repo *repo = pool_id2repo(pool, selection->elements[i + 1]);
64 FOR_REPO_SOLVABLES(repo, p, s)
70 FOR_JOB_SELECT(p, pp, select, selection->elements[i + 1])
75 selection->elements[j] = selection->elements[i];
76 selection->elements[j + 1] = selection->elements[i + 1];
79 queue_truncate(selection, j);
84 selection_solvables_sortcmp(const void *ap, const void *bp, void *dp)
86 return *(const Id *)ap - *(const Id *)bp;
90 selection_solvables(Pool *pool, Queue *selection, Queue *pkgs)
95 for (i = 0; i < selection->count; i += 2)
97 Id select = selection->elements[i] & SOLVER_SELECTMASK;
98 Id id = selection->elements[i + 1];
99 if (select == SOLVER_SOLVABLE_ALL)
101 FOR_POOL_SOLVABLES(p)
104 if (select == SOLVER_SOLVABLE_REPO)
107 Repo *repo = pool_id2repo(pool, id);
110 FOR_REPO_SOLVABLES(repo, p, s)
114 else if (select == SOLVER_SOLVABLE)
115 queue_push(pkgs, id);
118 FOR_JOB_SELECT(p, pp, select, id)
125 solv_sort(pkgs->elements, pkgs->count, sizeof(Id), selection_solvables_sortcmp, NULL);
126 lastid = pkgs->elements[0];
127 for (i = j = 1; i < pkgs->count; i++)
128 if (pkgs->elements[i] != lastid)
129 pkgs->elements[j++] = lastid = pkgs->elements[i];
130 queue_truncate(pkgs, j);
134 selection_flatten(Pool *pool, Queue *selection)
138 if (selection->count <= 2)
140 for (i = 0; i < selection->count; i += 2)
141 if ((selection->elements[i] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_ALL)
143 selection->elements[0] = selection->elements[i];
144 selection->elements[1] = selection->elements[i + 1];
145 queue_truncate(selection, 2);
149 selection_solvables(pool, selection, &q);
152 queue_empty(selection);
155 queue_truncate(selection, 2);
158 selection->elements[0] = SOLVER_SOLVABLE_ONE_OF;
159 selection->elements[1] = pool_queuetowhatprovides(pool, &q);
163 selection->elements[0] = SOLVER_SOLVABLE | SOLVER_NOAUTOSET;
164 selection->elements[1] = q.elements[0];
168 /* only supports simple rels plus REL_ARCH */
170 match_nevr_rel(Pool *pool, Solvable *s, Id rflags, Id revr)
172 if (rflags == REL_ARCH)
176 if (revr != ARCH_SRC || s->arch != ARCH_NOSRC)
183 return pool_intersect_evrs(pool, REL_EQ, s->evr, rflags, revr);
186 /* only supports simple rels plus REL_ARCH */
188 selection_filter_rel_noprune(Pool *pool, Queue *selection, Id relflags, Id relevr)
192 if (!selection->count)
195 for (i = 0; i < selection->count; i += 2)
197 Id select = selection->elements[i] & SOLVER_SELECTMASK;
198 Id id = selection->elements[i + 1];
199 if (select == SOLVER_SOLVABLE || select == SOLVER_SOLVABLE_ONE_OF)
201 /* done by selection_addextra, currently implies SELECTION_NAME */
207 FOR_JOB_SELECT(p, pp, select, id)
209 Solvable *s = pool->solvables + p;
210 if (match_nevr_rel(pool, s, relflags, relevr))
219 selection->elements[i] = SOLVER_SOLVABLE | SOLVER_NOAUTOSET;
220 selection->elements[i + 1] = q.elements[0];
224 selection->elements[i] = SOLVER_SOLVABLE_ONE_OF;
225 selection->elements[i + 1] = pool_queuetowhatprovides(pool, &q);
230 else if (select == SOLVER_SOLVABLE_NAME || select == SOLVER_SOLVABLE_PROVIDES)
232 /* don't stack src reldeps */
233 if (relflags == REL_ARCH && (relevr == ARCH_SRC || relevr == ARCH_NOSRC) && ISRELDEP(id))
235 Reldep *rd = GETRELDEP(pool, id);
236 if (rd->flags == REL_ARCH && rd->evr == ARCH_SRC)
239 selection->elements[i + 1] = pool_rel2id(pool, id, relevr, relflags, 1);
242 continue; /* actually cannot happen */
244 /* now add the setflags we gained */
245 if (relflags == REL_ARCH)
246 selection->elements[i] |= SOLVER_SETARCH;
247 if (relflags == REL_EQ && select != SOLVER_SOLVABLE_PROVIDES)
249 if (pool->disttype == DISTTYPE_DEB)
250 selection->elements[i] |= SOLVER_SETEVR; /* debian can't match version only like rpm */
253 const char *rel = strrchr(pool_id2str(pool, relevr), '-');
254 selection->elements[i] |= rel ? SOLVER_SETEVR : SOLVER_SETEV;
260 /* only supports simple rels plus REL_ARCH */
261 /* prunes empty jobs */
263 selection_filter_rel(Pool *pool, Queue *selection, Id relflags, Id relevr)
265 selection_filter_rel_noprune(pool, selection, relflags, relevr);
266 selection_prune(pool, selection);
269 /* limit a selection to to repository */
270 /* prunes empty jobs */
272 selection_filter_repo(Pool *pool, Queue *selection, Repo *repo, int setflags)
277 if (!selection->count)
281 queue_empty(selection);
285 for (i = j = 0; i < selection->count; i += 2)
287 Id select = selection->elements[i] & SOLVER_SELECTMASK;
288 Id id = selection->elements[i + 1];
289 if (select == SOLVER_SOLVABLE_ALL)
291 select = SOLVER_SOLVABLE_REPO;
294 else if (select == SOLVER_SOLVABLE_REPO)
296 if (id != repo->repoid)
299 else if (select == SOLVER_SOLVABLE)
301 if (pool->solvables[id].repo != repo)
309 FOR_JOB_SELECT(p, pp, select, id)
311 if (pool->solvables[p].repo != repo)
322 select = SOLVER_SOLVABLE | SOLVER_NOAUTOSET;
327 select = SOLVER_SOLVABLE_ONE_OF;
328 id = pool_queuetowhatprovides(pool, &q);
332 if (select == SOLVER_SOLVABLE_REPO)
336 FOR_REPO_SOLVABLES(repo, p, s)
339 continue; /* repo is empty */
341 selection->elements[j++] = select | (selection->elements[i] & ~SOLVER_SELECTMASK) | setflags;
342 selection->elements[j++] = id;
344 queue_truncate(selection, j);
350 matchprovides(Pool *pool, Solvable *s, Id dep)
353 idp = s->repo->idarraydata + s->provides;
354 while ((id = *idp++) != 0)
355 if (pool_match_dep(pool, id, dep))
360 /* change a SOLVER_SOLVABLE_NAME/PROVIDES selection to something that also includes
362 * extra packages are: src, badarch, disabled
365 selection_addextra(Pool *pool, Queue *selection, int flags)
369 int i, isextra, haveextra, doprovides;
371 if ((flags & SELECTION_INSTALLED_ONLY) != 0)
372 flags &= ~SELECTION_WITH_SOURCE;
374 if (!(flags & (SELECTION_WITH_SOURCE | SELECTION_WITH_DISABLED | SELECTION_WITH_BADARCH)))
375 return; /* nothing to add */
378 for (i = 0; i < selection->count; i += 2)
380 if (selection->elements[i] == SOLVER_SOLVABLE_NAME)
382 else if (selection->elements[i] == SOLVER_SOLVABLE_PROVIDES)
386 dep = selection->elements[i + 1];
391 /* first put all non-extra packages on the queue */
392 FOR_PROVIDES(p, pp, dep)
394 if ((flags & SELECTION_INSTALLED_ONLY) != 0 && pool->solvables[p].repo != pool->installed)
399 FOR_POOL_SOLVABLES(p)
401 Solvable *s = pool->solvables + p;
402 if (!doprovides && !pool_match_nevr(pool, s, dep))
404 if ((flags & SELECTION_INSTALLED_ONLY) != 0 && s->repo != pool->installed)
407 if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
409 if (!(flags & SELECTION_WITH_SOURCE) && !(flags & SELECTION_SOURCE_ONLY))
411 if (!(flags & SELECTION_SOURCE_ONLY))
413 if (pool_disabled_solvable(pool, s))
415 if (!(flags & SELECTION_WITH_DISABLED))
422 if ((flags & SELECTION_SOURCE_ONLY) != 0)
424 if (s->repo != pool->installed)
426 if (pool_disabled_solvable(pool, s))
428 if (!(flags & SELECTION_WITH_DISABLED))
432 if (pool_badarch_solvable(pool, s))
434 if (!(flags & SELECTION_WITH_BADARCH))
443 continue; /* already done above in FOR_PROVIDES */
444 if (!s->provides || !matchprovides(pool, s, dep))
447 haveextra |= isextra;
450 if (!haveextra || !q.count)
454 selection->elements[i] = (selection->elements[i] & ~SOLVER_SELECTMASK) | SOLVER_SOLVABLE | SOLVER_NOAUTOSET;
455 selection->elements[i + 1] = q.elements[0];
460 solv_sort(q.elements, q.count, sizeof(Id), selection_solvables_sortcmp, NULL);
461 selection->elements[i] = (selection->elements[i] & ~SOLVER_SELECTMASK) | SOLVER_SOLVABLE_ONE_OF;
462 selection->elements[i + 1] = pool_queuetowhatprovides(pool, &q);
468 static inline const char *
469 skipkind(const char *n)
472 for (s = n; *s >= 'a' && *s <= 'z'; s++)
474 if (*s == ':' && s != n)
480 queue_pushunique2(Queue *q, Id id1, Id id2)
483 for (i = 0; i < q->count; i += 2)
484 if (q->elements[i] == id1 && q->elements[i + 1] == id2)
486 queue_push2(q, id1, id2);
490 /***** provides matching *****/
493 selection_addextra_provides(Pool *pool, Queue *selection, const char *name, int flags)
497 int doglob, nocase, globflags;
499 if ((flags & SELECTION_INSTALLED_ONLY) != 0)
500 return 0; /* neither disabled nor badarch nor src */
502 nocase = flags & SELECTION_NOCASE;
503 doglob = (flags & SELECTION_GLOB) != 0 && strpbrk(name, "[*?") != 0;
504 globflags = doglob && nocase ? FNM_CASEFOLD : 0;
506 FOR_POOL_SOLVABLES(p)
509 Solvable *s = pool->solvables + p;
512 if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC) /* no provides */
514 if (s->repo == pool->installed)
516 if (pool_disabled_solvable(pool, s))
518 if (!(flags & SELECTION_WITH_DISABLED))
520 if (!(flags & SELECTION_WITH_BADARCH) && pool_badarch_solvable(pool, s))
523 else if (pool_badarch_solvable(pool, s))
525 if (!(flags & SELECTION_WITH_BADARCH))
530 /* here is an extra solvable we need to consider */
531 idp = s->repo->idarraydata + s->provides;
532 while ((id = *idp++) != 0)
536 Reldep *rd = GETRELDEP(pool, id);
539 if (pool->whatprovides[id] > 1)
540 continue; /* we already did that one in the normal code path */
541 n = pool_id2str(pool, id);
542 if ((doglob ? fnmatch(name, n, globflags) : nocase ? strcasecmp(name, n) : strcmp(name, n)) == 0)
544 queue_pushunique2(selection, SOLVER_SOLVABLE_PROVIDES, id);
552 /* this is the fast path of selection_provides: the id for the name
553 * is known and thus we can use the whatprovides data to quickly
554 * check the existance of a package with that provides */
556 selection_provides_id(Pool *pool, Queue *selection, Id id, int flags)
560 FOR_PROVIDES(p, pp, id)
562 Solvable *s = pool->solvables + p;
563 if ((flags & SELECTION_INSTALLED_ONLY) != 0 && s->repo != pool->installed)
565 queue_push2(selection, SOLVER_SOLVABLE_PROVIDES, id);
566 return SELECTION_PROVIDES;
569 if ((flags & (SELECTION_WITH_BADARCH | SELECTION_WITH_DISABLED)) != 0)
571 /* misuse selection_addextra to test if there is an extra package
572 * that provides the id */
573 queue_push2(selection, SOLVER_SOLVABLE_PROVIDES, id);
574 selection_addextra(pool, selection, flags);
575 if (selection->elements[0] == SOLVER_SOLVABLE_PROVIDES)
576 queue_empty(selection); /* no extra package found */
579 selection->elements[0] = SOLVER_SOLVABLE_PROVIDES;
580 selection->elements[1] = id;
582 return selection->count ? SELECTION_PROVIDES : 0;
588 /* match the provides of a package */
589 /* note that we only return raw SOLVER_SOLVABLE_PROVIDES jobs
590 * so that the selection can be modified later. */
592 selection_provides(Pool *pool, Queue *selection, const char *name, int flags)
601 if ((flags & SELECTION_SOURCE_ONLY) != 0)
602 return 0; /* sources do not have provides */
604 nocase = flags & SELECTION_NOCASE;
607 /* try the fast path first */
608 id = pool_str2id(pool, name, 0);
611 /* the id is known, do the fast id matching */
612 int ret = selection_provides_id(pool, selection, id, flags);
618 doglob = (flags & SELECTION_GLOB) != 0 && strpbrk(name, "[*?") != 0;
619 if (!nocase && !doglob)
621 /* all done above in selection_provides_id */
625 /* looks like a glob or nocase match. really hard work. */
627 globflags = doglob && nocase ? FNM_CASEFOLD : 0;
628 for (id = 1; id < pool->ss.nstrings; id++)
630 /* do we habe packages providing this id? */
631 if ((!pool->whatprovides[id] && pool->addedfileprovides == 2) || pool->whatprovides[id] == 1)
633 n = pool_id2str(pool, id);
634 if ((doglob ? fnmatch(name, n, globflags) : nocase ? strcasecmp(name, n) : strcmp(name, n)) == 0)
636 if ((flags & SELECTION_INSTALLED_ONLY) != 0)
638 FOR_PROVIDES(p, pp, id)
639 if (pool->solvables[p].repo == pool->installed)
644 else if (!pool->whatprovides[id])
646 FOR_PROVIDES(p, pp, id)
651 queue_push2(selection, SOLVER_SOLVABLE_PROVIDES, id);
656 if (flags & (SELECTION_WITH_BADARCH | SELECTION_WITH_DISABLED))
657 match |= selection_addextra_provides(pool, selection, name, flags);
659 return match ? SELECTION_PROVIDES : 0;
662 /***** name matching *****/
664 /* this is the fast path of selection_name: the id for the name
665 * is known and thus we can quickly check the existance of a
666 * package with that name */
668 selection_name_id(Pool *pool, Queue *selection, Id id, int flags)
673 if ((flags & SELECTION_SOURCE_ONLY) != 0)
675 /* sources cannot be installed */
676 if ((flags & SELECTION_INSTALLED_ONLY) != 0)
678 /* add ARCH_SRC to match only sources */
679 matchid = pool_rel2id(pool, id, ARCH_SRC, REL_ARCH, 1);
680 flags &= ~SELECTION_WITH_SOURCE;
683 FOR_PROVIDES(p, pp, matchid)
685 Solvable *s = pool->solvables + p;
688 if ((flags & SELECTION_INSTALLED_ONLY) != 0 && s->repo != pool->installed)
690 /* one match is all we need */
691 queue_push2(selection, SOLVER_SOLVABLE_NAME, matchid);
692 /* add the requested extra packages */
693 if ((flags & (SELECTION_WITH_SOURCE | SELECTION_WITH_BADARCH | SELECTION_WITH_DISABLED)) != 0)
694 selection_addextra(pool, selection, flags);
695 return SELECTION_NAME;
698 if ((flags & (SELECTION_WITH_BADARCH | SELECTION_WITH_DISABLED)) != 0)
700 queue_push2(selection, SOLVER_SOLVABLE_NAME, matchid);
701 selection_addextra(pool, selection, flags);
702 if (selection->elements[0] == SOLVER_SOLVABLE_NAME)
703 queue_empty(selection);
704 return selection->count ? SELECTION_NAME : 0;
707 if ((flags & SELECTION_WITH_SOURCE) != 0 && (flags & SELECTION_INSTALLED_ONLY) == 0)
709 /* WITH_SOURCE case, but we had no match. try SOURCE_ONLY instead */
710 matchid = pool_rel2id(pool, id, ARCH_SRC, REL_ARCH, 1);
711 FOR_PROVIDES(p, pp, matchid)
713 Solvable *s = pool->solvables + p;
716 queue_push2(selection, SOLVER_SOLVABLE_NAME, matchid);
717 return SELECTION_NAME;
723 /* does not check SELECTION_INSTALLED_ONLY, as it is normally done
726 solvable_matches_selection_flags(Pool *pool, Solvable *s, int flags)
728 if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
730 if (!(flags & SELECTION_SOURCE_ONLY) && !(flags & SELECTION_WITH_SOURCE))
732 /* source package are never installed and never have a bad arch */
733 if (!(flags & SELECTION_WITH_DISABLED) && pool_disabled_solvable(pool, s))
738 if ((flags & SELECTION_SOURCE_ONLY) != 0)
740 if (s->repo != pool->installed)
742 if (!(flags & SELECTION_WITH_DISABLED) && pool_disabled_solvable(pool, s))
744 if (!(flags & SELECTION_WITH_BADARCH) && pool_badarch_solvable(pool, s))
751 /* match the name of a package */
752 /* note that for SELECTION_INSTALLED_ONLY the result is not trimmed */
754 selection_name(Pool *pool, Queue *selection, const char *name, int flags)
762 if ((flags & SELECTION_SOURCE_ONLY) != 0)
763 flags &= ~SELECTION_WITH_SOURCE;
765 nocase = flags & SELECTION_NOCASE;
766 if (!nocase && !(flags & SELECTION_SKIP_KIND))
768 /* try the fast path first */
769 id = pool_str2id(pool, name, 0);
772 int ret = selection_name_id(pool, selection, id, flags);
778 doglob = (flags & SELECTION_GLOB) != 0 && strpbrk(name, "[*?") != 0;
779 if (!nocase && !(flags & SELECTION_SKIP_KIND) && !doglob)
780 return 0; /* all done above in selection_name_id */
782 /* do a name match over all packages. hard work. */
784 globflags = doglob && nocase ? FNM_CASEFOLD : 0;
785 FOR_POOL_SOLVABLES(p)
787 Solvable *s = pool->solvables + p;
788 if ((flags & SELECTION_INSTALLED_ONLY) != 0 && s->repo != pool->installed)
790 if (!solvable_matches_selection_flags(pool, s, flags))
793 n = pool_id2str(pool, id);
794 if (flags & SELECTION_SKIP_KIND)
796 if ((doglob ? fnmatch(name, n, globflags) : nocase ? strcasecmp(name, n) : strcmp(name, n)) == 0)
798 if ((flags & SELECTION_SOURCE_ONLY) != 0)
800 if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
802 id = pool_rel2id(pool, id, ARCH_SRC, REL_ARCH, 1);
804 queue_pushunique2(selection, SOLVER_SOLVABLE_NAME, id);
810 /* if there was a match widen the selector to include all extra packages */
811 if ((flags & (SELECTION_WITH_SOURCE | SELECTION_WITH_BADARCH | SELECTION_WITH_DISABLED)) != 0)
812 selection_addextra(pool, selection, flags);
813 return SELECTION_NAME;
819 /***** SELECTION_DOTARCH and SELECTION_REL handling *****/
821 /* like selection_name, but check for a .arch suffix if the match did
822 not work and SELECTION_DOTARCH is used */
824 selection_name_arch(Pool *pool, Queue *selection, const char *name, int flags, int doprovides, int noprune)
831 ret = selection_provides(pool, selection, name, flags);
833 ret = selection_name(pool, selection, name, flags);
836 if (!(flags & SELECTION_DOTARCH))
838 /* check if there is an .arch suffix */
839 if ((r = strrchr(name, '.')) != 0 && r[1] && (archid = str2archid(pool, r + 1)) != 0)
841 char *rname = solv_strdup(name);
843 if (archid == ARCH_SRC || archid == ARCH_NOSRC)
844 flags |= SELECTION_SOURCE_ONLY;
846 ret = selection_provides(pool, selection, rname, flags);
848 ret = selection_name(pool, selection, rname, flags);
851 selection_filter_rel_noprune(pool, selection, REL_ARCH, archid);
853 selection_prune(pool, selection);
856 return ret && selection->count ? ret | SELECTION_DOTARCH : 0;
862 splitrel(char *rname, char *r, int *rflagsp)
864 int nend = r - rname;
866 if (nend && *r == '=' && r[-1] == '!')
870 rflags = REL_LT|REL_GT;
883 while (*r && (*r == ' ' || *r == '\t'))
885 while (nend && (rname[nend - 1] == ' ' || rname[nend - 1] == '\t'))
887 if (nend <= 0 || !*r || !rflags)
894 /* match name/provides, support DOTARCH and REL modifiers
897 selection_name_arch_rel(Pool *pool, Queue *selection, const char *name, int flags, int doprovides)
899 int ret, rflags = 0, noprune;
900 char *r = 0, *rname = 0;
902 /* try to split off an relation part */
903 if ((flags & SELECTION_REL) != 0)
905 if ((r = strpbrk(name, "<=>")) != 0)
907 rname = solv_strdup(name);
908 r = rname + (r - name);
909 if ((r = splitrel(rname, r, &rflags)) == 0)
910 rname = solv_free(rname);
914 /* check if we need to call selection_addextra */
915 noprune = doprovides && (flags & (SELECTION_WITH_DISABLED | SELECTION_WITH_BADARCH));
919 /* could not split off relation */
920 ret = selection_name_arch(pool, selection, name, flags, doprovides, noprune);
923 selection_addextra(pool, selection, flags);
924 selection_prune(pool, selection);
926 return ret && selection->count ? ret : 0;
929 /* we could split of a relation. prune name and then filter rel */
930 ret = selection_name_arch(pool, selection, rname, flags, doprovides, noprune);
933 selection_filter_rel_noprune(pool, selection, rflags, pool_str2id(pool, r, 1));
935 selection_addextra(pool, selection, flags);
936 selection_prune(pool, selection);
939 return ret && selection->count ? ret | SELECTION_REL : 0;
942 /***** filelist matching *****/
945 selection_filelist_sortcmp(const void *ap, const void *bp, void *dp)
948 const Id *a = ap, *b = bp;
950 return strcmp(pool_id2str(pool, a[0]), pool_id2str(pool, b[0]));
955 selection_filelist(Pool *pool, Queue *selection, const char *name, int flags)
963 /* all files in the file list start with a '/' */
966 if (!(flags & SELECTION_GLOB))
968 if (*name != '*' && *name != '[' && *name != '?')
971 type = !(flags & SELECTION_GLOB) || strpbrk(name, "[*?") == 0 ? SEARCH_STRING : SEARCH_GLOB;
972 if ((flags & SELECTION_NOCASE) != 0)
973 type |= SEARCH_NOCASE;
975 dataiterator_init(&di, pool, flags & SELECTION_INSTALLED_ONLY ? pool->installed : 0, 0, SOLVABLE_FILELIST, name, type|SEARCH_FILES);
976 while (dataiterator_step(&di))
978 Solvable *s = pool->solvables + di.solvid;
981 if (!solvable_matches_selection_flags(pool, s, flags))
983 if ((flags & SELECTION_FLAT) != 0)
985 /* don't bother with the complex stuff */
986 queue_push2(selection, SOLVER_SOLVABLE | SOLVER_NOAUTOSET, di.solvid);
987 dataiterator_skip_solvable(&di);
990 id = pool_str2id(pool, di.kv.str, 1);
991 queue_push2(&q, id, di.solvid);
993 dataiterator_free(&di);
994 if ((flags & SELECTION_FLAT) != 0)
997 return selection->count ? SELECTION_FILELIST : 0;
1004 solv_sort(q.elements, q.count / 2, 2 * sizeof(Id), selection_filelist_sortcmp, pool);
1006 queue_push2(&q, 0, 0);
1007 for (i = j = 0; i < q.count; i += 2)
1009 if (q.elements[i] != lastid)
1012 queue_pushunique2(selection, SOLVER_SOLVABLE | SOLVER_NOAUTOSET, q.elements[0]);
1017 /* check if we already have it */
1018 for (k = 0; k < selection->count; k += 2)
1020 if (selection->elements[k] != SOLVER_SOLVABLE_ONE_OF)
1022 idp = pool->whatprovidesdata + selection->elements[k + 1];
1023 if (!memcmp(idp, q.elements, j * sizeof(Id)) && !idp[j])
1026 if (k == selection->count)
1027 queue_push2(selection, SOLVER_SOLVABLE_ONE_OF, pool_ids2whatprovides(pool, q.elements, j));
1029 lastid = q.elements[i];
1032 if (!j || q.elements[j - 1] != q.elements[i])
1033 q.elements[j++] = q.elements[i + 1];
1036 return SELECTION_FILELIST;
1040 /***** canon name matching *****/
1042 #if defined(MULTI_SEMANTICS)
1043 # define EVRCMP_DEPCMP (pool->disttype == DISTTYPE_DEB ? EVRCMP_COMPARE : EVRCMP_MATCH_RELEASE)
1044 #elif defined(DEBIAN)
1045 # define EVRCMP_DEPCMP EVRCMP_COMPARE
1047 # define EVRCMP_DEPCMP EVRCMP_MATCH_RELEASE
1050 /* magic epoch promotion code, works only for SELECTION_NAME selections */
1052 selection_filter_evr(Pool *pool, Queue *selection, const char *evr)
1059 /* do we already have an epoch? */
1060 for (sp = evr; *sp >= '0' && *sp <= '9'; sp++)
1062 if (*sp == ':' && sp != evr)
1064 /* yes, just add the rel filter */
1065 selection_filter_rel(pool, selection, REL_EQ, pool_str2id(pool, evr, 1));
1070 queue_init_buffer(&q, qbuf, sizeof(qbuf)/sizeof(*qbuf));
1071 for (i = j = 0; i < selection->count; i += 2)
1073 Id select = selection->elements[i] & SOLVER_SELECTMASK;
1074 Id id = selection->elements[i + 1];
1076 const char *lastepoch = 0;
1077 int lastepochlen = 0;
1080 FOR_JOB_SELECT(p, pp, select, id)
1082 Solvable *s = pool->solvables + p;
1083 const char *sevr = pool_id2str(pool, s->evr);
1084 for (sp = sevr; *sp >= '0' && *sp <= '9'; sp++)
1088 /* compare vr part */
1089 if (strcmp(evr, sp != sevr ? sp + 1 : sevr) != 0)
1091 int r = pool_evrcmp_str(pool, sp != sevr ? sp + 1 : sevr, evr, EVRCMP_DEPCMP);
1092 if (r == -1 || r == 1)
1093 continue; /* solvable does not match vr */
1098 while (sevr < sp && *sevr == '0') /* normalize epoch */
1104 lastepochlen = sp - sevr;
1106 else if (lastepochlen != sp - sevr || strncmp(lastepoch, sevr, lastepochlen) != 0)
1107 lastepochlen = -1; /* multiple different epochs */
1109 if (!lastepoch || lastepochlen == 0)
1110 id = pool_str2id(pool, evr, 1); /* no match at all or zero epoch */
1111 else if (lastepochlen >= 0)
1113 /* found exactly one epoch, simply prepend */
1114 char *evrx = solv_malloc(strlen(evr) + lastepochlen + 2);
1115 strncpy(evrx, lastepoch, lastepochlen + 1);
1116 strcpy(evrx + lastepochlen + 1, evr);
1117 id = pool_str2id(pool, evrx, 1);
1122 /* multiple epochs in multiple solvables, convert to list of solvables */
1123 selection->elements[j] = (selection->elements[i] & ~SOLVER_SELECTMASK) | SOLVER_SOLVABLE_ONE_OF;
1124 selection->elements[j + 1] = pool_queuetowhatprovides(pool, &q);
1129 queue_push2(&q, selection->elements[i], selection->elements[i + 1]);
1130 selection_filter_rel(pool, &q, REL_EQ, id);
1132 continue; /* oops, no match */
1133 selection->elements[j] = q.elements[0];
1134 selection->elements[j + 1] = q.elements[1];
1137 queue_truncate(selection, j);
1141 /* match the "canonical" name of the package */
1143 selection_canon(Pool *pool, Queue *selection, const char *name, int flags)
1145 char *rname, *r, *r2;
1151 * nameglob-version.arch
1152 * nameglob-version-release
1153 * nameglob-version-release.arch
1155 flags |= SELECTION_NAME;
1156 flags &= ~SELECTION_PROVIDES;
1159 if (pool->disttype == DISTTYPE_CONDA)
1161 Id *wp, id = pool_conda_matchspec(pool, name);
1164 wp = pool_whatprovides_ptr(pool, id); /* check if there is a match */
1167 queue_push2(selection, SOLVER_SOLVABLE_PROVIDES, id);
1168 return SELECTION_CANON;
1171 if (pool->disttype == DISTTYPE_DEB)
1173 if ((r = strchr(name, '_')) == 0)
1175 rname = solv_strdup(name); /* so we can modify it */
1176 r = rname + (r - name);
1178 if ((ret = selection_name(pool, selection, rname, flags)) == 0)
1183 /* is there a vaild arch? */
1184 if ((r2 = strrchr(r, '_')) != 0 && r[1] && (archid = str2archid(pool, r + 1)) != 0)
1186 *r2 = 0; /* split off */
1187 selection_filter_rel(pool, selection, REL_ARCH, archid);
1189 selection_filter_rel(pool, selection, REL_EQ, pool_str2id(pool, r, 1));
1191 return selection->count ? ret | SELECTION_CANON : 0;
1194 if (pool->disttype == DISTTYPE_HAIKU)
1196 if ((r = strchr(name, '-')) == 0)
1198 rname = solv_strdup(name); /* so we can modify it */
1199 r = rname + (r - name);
1201 if ((ret = selection_name(pool, selection, rname, flags)) == 0)
1206 /* is there a vaild arch? */
1207 if ((r2 = strrchr(r, '-')) != 0 && r[1] && (archid = str2archid(pool, r + 1)) != 0)
1209 *r2 = 0; /* split off */
1210 selection_filter_rel(pool, selection, REL_ARCH, archid);
1212 selection_filter_rel(pool, selection, REL_EQ, pool_str2id(pool, r, 1));
1214 return selection->count ? ret | SELECTION_CANON : 0;
1217 if ((r = strrchr(name, '-')) == 0)
1219 rname = solv_strdup(name); /* so we can modify it */
1220 r = rname + (r - name);
1223 /* split off potential arch part from version */
1224 if ((r2 = strrchr(r + 1, '.')) != 0 && r2[1] && (archid = str2archid(pool, r2 + 1)) != 0)
1225 *r2 = 0; /* found valid arch, split it off */
1226 if (archid == ARCH_SRC || archid == ARCH_NOSRC)
1227 flags |= SELECTION_SOURCE_ONLY;
1229 /* try with just the version */
1230 if ((ret = selection_name(pool, selection, rname, flags)) == 0)
1232 /* no luck, try with version-release */
1233 if ((r2 = strrchr(rname, '-')) == 0)
1241 if ((ret = selection_name(pool, selection, rname, flags)) == 0)
1248 selection_filter_rel(pool, selection, REL_ARCH, archid);
1249 selection_filter_evr(pool, selection, r + 1); /* magic epoch promotion */
1251 return selection->count ? ret | SELECTION_CANON : 0;
1254 /* return the needed withbits to match the provided selection */
1256 selection_extrabits(Pool *pool, Queue *selection, int flags)
1258 int i, needflags, isextra;
1264 allflags = flags & (SELECTION_WITH_SOURCE | SELECTION_WITH_DISABLED | SELECTION_WITH_BADARCH);
1265 if (!selection->count)
1267 if (selection->count == 2 && selection->elements[0] == SOLVER_SOLVABLE_ALL)
1268 return allflags; /* don't bother */
1269 queue_init(&qlimit);
1270 selection_solvables(pool, selection, &qlimit);
1272 for (i = 0; i < qlimit.count; i++)
1274 p = qlimit.elements[i];
1275 s = pool->solvables + p;
1276 if ((flags & SELECTION_INSTALLED_ONLY) != 0 && s->repo != pool->installed)
1279 if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
1281 if (!(flags & SELECTION_WITH_SOURCE))
1283 isextra |= SELECTION_WITH_SOURCE;
1284 if (pool_disabled_solvable(pool, s))
1286 if (!(flags & SELECTION_WITH_DISABLED))
1288 isextra |= SELECTION_WITH_DISABLED;
1293 if ((flags & SELECTION_SOURCE_ONLY) != 0)
1295 if (s->repo != pool->installed)
1297 if (pool_disabled_solvable(pool, s))
1299 if (!(flags & SELECTION_WITH_DISABLED))
1301 isextra |= SELECTION_WITH_DISABLED;
1303 if (pool_badarch_solvable(pool, s))
1305 if (!(flags & SELECTION_WITH_BADARCH))
1307 isextra |= SELECTION_WITH_BADARCH;
1313 needflags |= isextra;
1314 if (needflags == allflags)
1318 queue_free(&qlimit);
1323 selection_combine(Pool *pool, Queue *sel1, Queue *sel2, int flags, int ret)
1325 if ((flags & SELECTION_MODEBITS) == SELECTION_ADD)
1326 selection_add(pool, sel1, sel2);
1327 else if ((flags & SELECTION_MODEBITS) == SELECTION_SUBTRACT)
1328 selection_subtract(pool, sel1, sel2);
1329 else if ((flags & SELECTION_MODEBITS) == SELECTION_FILTER)
1331 if (ret || !(flags & SELECTION_FILTER_KEEP_IFEMPTY))
1333 if ((flags & SELECTION_FILTER_SWAPPED) != 0)
1335 selection_filter(pool, sel2, sel1);
1337 queue_init_clone(sel1, sel2);
1340 selection_filter(pool, sel1, sel2);
1343 else /* SELECTION_REPLACE */
1346 queue_init_clone(sel1, sel2);
1353 selection_make(Pool *pool, Queue *selection, const char *name, int flags)
1356 if ((flags & SELECTION_MODEBITS) != SELECTION_REPLACE)
1360 if ((flags & SELECTION_MODEBITS) == SELECTION_SUBTRACT || (flags & SELECTION_MODEBITS) == SELECTION_FILTER)
1362 if (!selection->count)
1364 if ((flags & (SELECTION_WITH_DISABLED | SELECTION_WITH_BADARCH | SELECTION_WITH_SOURCE)) != 0)
1366 /* try to drop expensive extra bits */
1367 flags = (flags & ~(SELECTION_WITH_DISABLED | SELECTION_WITH_BADARCH | SELECTION_WITH_SOURCE)) | selection_extrabits(pool, selection, flags);
1371 ret = selection_make(pool, &q, name, flags & ~SELECTION_MODEBITS);
1372 return selection_combine(pool, selection, &q, flags, ret);
1374 queue_empty(selection);
1375 if ((flags & SELECTION_INSTALLED_ONLY) != 0 && !pool->installed)
1378 /* here come our four selection modes */
1379 if ((flags & SELECTION_FILELIST) != 0)
1380 ret = selection_filelist(pool, selection, name, flags);
1381 if (!ret && (flags & SELECTION_NAME) != 0)
1382 ret = selection_name_arch_rel(pool, selection, name, flags, 0);
1383 if (!ret && (flags & SELECTION_PROVIDES) != 0)
1384 ret = selection_name_arch_rel(pool, selection, name, flags, 1);
1385 if (!ret && (flags & SELECTION_CANON) != 0)
1386 ret = selection_canon(pool, selection, name, flags);
1388 /* now do result filtering */
1389 if (ret && (flags & SELECTION_INSTALLED_ONLY) != 0)
1390 selection_filter_repo(pool, selection, pool->installed, SOLVER_SETREPO);
1392 /* flatten if requested */
1393 if (ret && (flags & SELECTION_FLAT) != 0)
1394 selection_flatten(pool, selection);
1395 return selection->count ? ret : 0;
1399 matchdep_str(const char *pattern, const char *string, int flags)
1401 if (!pattern || !string)
1403 if (flags & SELECTION_GLOB)
1405 int globflags = (flags & SELECTION_NOCASE) != 0 ? FNM_CASEFOLD : 0;
1406 return fnmatch(pattern, string, globflags) == 0 ? 1 : 0;
1408 if (flags & SELECTION_NOCASE)
1409 return strcasecmp(pattern, string) == 0 ? 1 : 0;
1410 return strcmp(pattern, string) == 0 ? 1 : 0;
1413 /* like pool_match_dep but uses matchdep_str to match the name for glob and nocase matching */
1415 matchdep(Pool *pool, Id id, char *rname, int rflags, Id revr, int flags)
1419 Reldep *rd = GETRELDEP(pool, id);
1422 if (rd->flags == REL_AND || rd->flags == REL_OR || rd->flags == REL_WITH || rd->flags == REL_WITHOUT || rd->flags == REL_COND || rd->flags == REL_UNLESS)
1424 if (matchdep(pool, rd->name, rname, rflags, revr, flags))
1426 if ((rd->flags == REL_COND || rd->flags == REL_UNLESS) && ISRELDEP(rd->evr))
1428 rd = GETRELDEP(pool, rd->evr);
1429 if (rd->flags != REL_ELSE)
1432 if (rd->flags != REL_COND && rd->flags != REL_UNLESS && rd->flags != REL_WITHOUT && matchdep(pool, rd->evr, rname, rflags, revr, flags))
1436 if (rd->flags == REL_ARCH)
1437 return matchdep(pool, rd->name, rname, rflags, revr, flags);
1439 if (!matchdep(pool, rd->name, rname, rflags, revr, flags))
1441 if (rflags && !pool_intersect_evrs(pool, rd->flags, rd->evr, rflags, revr))
1445 return matchdep_str(rname, pool_id2str(pool, id), flags);
1449 int start; /* either 2 or repofilter->start */
1450 int end; /* either nsolvables or repofilter->end */
1458 selection_make_matchsolvable_common(Pool *pool, Queue *selection, Queue *solvidq, Id solvid, int flags, int keyname, int marker, struct limiter *limiter)
1466 if ((flags & SELECTION_MODEBITS) != SELECTION_REPLACE)
1471 ret = selection_make_matchsolvable_common(pool, &q, solvidq, solvid, flags & ~SELECTION_MODEBITS, keyname, marker, limiter);
1472 return selection_combine(pool, selection, &q, flags, ret);
1475 queue_empty(selection);
1478 if (!solvidq && !solvid)
1480 if (solvidq && solvid)
1485 map_init(&m, pool->nsolvables);
1486 for (i = 0; i < solvidq->count; i++)
1487 MAPSET(&m, solvidq->elements[i]);
1490 reloff = pool->ss.nstrings;
1491 map_init(&missc, reloff + pool->nrels);
1492 for (li = limiter->start; li < limiter->end; li++)
1495 p = limiter->mapper ? limiter->mapper[li] : li;
1496 if (solvidq && MAPTST(&m, p))
1498 if (!solvidq && p == solvid)
1500 s = pool->solvables + p;
1501 if (!s->repo || (limiter->repofilter && s->repo != limiter->repofilter))
1503 if (!solvable_matches_selection_flags(pool, s, flags))
1505 if (solvable_matchessolvable_int(s, keyname, marker, solvid, solvidq ? &m : 0, &q, &missc, reloff, 0))
1506 queue_push(selection, p);
1513 /* convert package list to selection */
1514 if (!selection->count)
1516 j = selection->count;
1517 queue_insertn(selection, 0, selection->count, 0);
1518 for (i = 0; i < selection->count; i += 2)
1520 selection->elements[i] = SOLVER_SOLVABLE | SOLVER_NOAUTOSET;
1521 selection->elements[i + 1] = selection->elements[j++];
1523 if ((flags & SELECTION_FLAT) != 0)
1524 selection_flatten(pool, selection);
1525 return SELECTION_PROVIDES;
1529 selection_make_matchdeps_common(Pool *pool, Queue *selection, const char *name, Id dep, int flags, int keyname, int marker, struct limiter *limiter)
1533 char *rname = 0, *r = 0;
1539 if ((flags & SELECTION_MODEBITS) != SELECTION_REPLACE)
1543 ret = selection_make_matchdeps_common(pool, &q, name, dep, flags & ~SELECTION_MODEBITS, keyname, marker, limiter);
1544 return selection_combine(pool, selection, &q, flags, ret);
1547 queue_empty(selection);
1555 if ((flags & SELECTION_MATCH_DEPSTR) != 0)
1556 flags &= ~SELECTION_REL;
1560 rname = solv_strdup(name);
1561 if ((flags & SELECTION_REL) != 0)
1563 if ((r = strpbrk(rname, "<=>")) != 0)
1565 if ((r = splitrel(rname, r, &rflags)) == 0)
1571 revr = pool_str2id(pool, r, 1);
1572 ret |= SELECTION_REL;
1574 if ((flags & SELECTION_GLOB) != 0 && strpbrk(rname, "[*?") == 0)
1575 flags &= ~SELECTION_GLOB;
1577 if ((flags & SELECTION_GLOB) == 0 && (flags & SELECTION_NOCASE) == 0 && (flags & SELECTION_MATCH_DEPSTR) == 0)
1579 /* we can use the faster selection_make_matchdepid */
1580 dep = pool_str2id(pool, rname, 1);
1582 dep = pool_rel2id(pool, dep, revr, rflags, 1);
1583 rname = solv_free(rname);
1589 if (keyname == SOLVABLE_NAME && (flags & SELECTION_MATCH_DEPSTR) != 0)
1594 rd = GETRELDEP(pool, dep);
1595 if (!rd->name || rd->flags != REL_EQ)
1604 for (li = limiter->start; li < limiter->end; li++)
1607 p = limiter->mapper ? limiter->mapper[li] : li;
1608 s = pool->solvables + p;
1609 if (!s->repo || (limiter->repofilter && s->repo != limiter->repofilter))
1611 if (!solvable_matches_selection_flags(pool, s, flags))
1613 if (keyname == SOLVABLE_NAME) /* nevr match hack */
1617 if ((flags & SELECTION_MATCH_DEPSTR) != 0)
1619 if (s->name != dep || s->evr != revr)
1624 if (!pool_match_nevr(pool, s, dep))
1630 if ((flags & SELECTION_MATCH_DEPSTR) != 0) /* mis-use */
1632 char *tmp = pool_tmpjoin(pool, pool_id2str(pool, s->name), " = ", pool_id2str(pool, s->evr));
1633 if (!matchdep_str(rname, tmp, flags))
1638 if (!matchdep(pool, s->name, rname, rflags, revr, flags))
1640 if (rflags && !pool_intersect_evrs(pool, rflags, revr, REL_EQ, s->evr))
1644 queue_push(selection, p);
1649 repo_lookup_deparray(s->repo, p, keyname, &q, marker);
1654 if ((flags & SELECTION_MATCH_DEPSTR) != 0) /* mis-use */
1656 for (i = 0; i < q.count; i++)
1657 if (q.elements[i] == dep)
1662 for (i = 0; i < q.count; i++)
1663 if (pool_match_dep(pool, q.elements[i], dep))
1669 if ((flags & SELECTION_MATCH_DEPSTR) != 0)
1671 for (i = 0; i < q.count; i++)
1672 if (matchdep_str(rname, pool_dep2str(pool, q.elements[i]), flags))
1677 for (i = 0; i < q.count; i++)
1678 if (matchdep(pool, q.elements[i], rname, rflags, revr, flags))
1683 queue_push(selection, p);
1688 /* convert package list to selection */
1689 if (!selection->count)
1691 j = selection->count;
1692 queue_insertn(selection, 0, selection->count, 0);
1693 for (i = 0; i < selection->count; i += 2)
1695 selection->elements[i] = SOLVER_SOLVABLE | SOLVER_NOAUTOSET;
1696 selection->elements[i + 1] = selection->elements[j++];
1699 if ((flags & SELECTION_FLAT) != 0)
1700 selection_flatten(pool, selection);
1701 return ret | (keyname == SOLVABLE_NAME ? SELECTION_NAME : SELECTION_PROVIDES);
1705 setup_limiter(Pool *pool, Queue *selection, int flags, struct limiter *limiter)
1708 limiter->end = pool->nsolvables;
1709 limiter->mapper = 0;
1710 limiter->repofilter = 0;
1711 if ((flags & SELECTION_INSTALLED_ONLY) != 0)
1713 Repo *repo = pool->installed;
1714 limiter->repofilter = repo;
1715 limiter->start = repo ? repo->start : 0;
1716 limiter->end = repo ? repo->end : 0;
1718 if ((flags & SELECTION_MODEBITS) != SELECTION_SUBTRACT && (flags & SELECTION_MODEBITS) != SELECTION_FILTER)
1720 /* the result will be limited to the first selection */
1721 if (!selection->count)
1722 limiter->start = limiter->end = 0;
1725 /* check for special cases where we do not need to call selection_solvables() */
1726 if (selection->count == 2 && (selection->elements[0] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_ALL)
1728 if (selection->count == 2 && (selection->elements[0] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_REPO)
1730 Repo *repo = pool_id2repo(pool, selection->elements[1]);
1731 if (limiter->repofilter && repo != limiter->repofilter)
1733 limiter->repofilter = repo;
1734 limiter->start = repo ? repo->start : 0;
1735 limiter->end = repo ? repo->end : 0;
1738 /* convert selection into a package list and use it in the limiter */
1739 queue_init(&limiter->qlimit);
1740 selection_solvables(pool, selection, &limiter->qlimit);
1742 limiter->end = limiter->qlimit.count;
1743 if (!limiter->qlimit.count)
1744 queue_free(&limiter->qlimit);
1746 limiter->mapper = limiter->qlimit.elements;
1750 free_limiter(struct limiter *limiter)
1752 if (limiter->mapper)
1753 queue_free(&limiter->qlimit);
1757 * select against the dependencies in keyname
1758 * like SELECTION_PROVIDES, but with the deps in keyname instead of provides.
1759 * supported match modifiers:
1765 selection_make_matchdeps(Pool *pool, Queue *selection, const char *name, int flags, int keyname, int marker)
1767 struct limiter limiter;
1769 setup_limiter(pool, selection, flags, &limiter);
1770 ret = selection_make_matchdeps_common(pool, selection, name, 0, flags, keyname, marker, &limiter);
1771 free_limiter(&limiter);
1776 * select against the dependency id in keyname
1779 selection_make_matchdepid(Pool *pool, Queue *selection, Id dep, int flags, int keyname, int marker)
1781 struct limiter limiter;
1783 setup_limiter(pool, selection, flags, &limiter);
1784 ret = selection_make_matchdeps_common(pool, selection, 0, dep, flags, keyname, marker, &limiter);
1785 free_limiter(&limiter);
1790 selection_make_matchsolvable(Pool *pool, Queue *selection, Id solvid, int flags, int keyname, int marker)
1792 struct limiter limiter;
1794 setup_limiter(pool, selection, flags, &limiter);
1795 ret = selection_make_matchsolvable_common(pool, selection, 0, solvid, flags, keyname, marker, &limiter);
1796 free_limiter(&limiter);
1801 selection_make_matchsolvablelist(Pool *pool, Queue *selection, Queue *solvidq, int flags, int keyname, int marker)
1803 struct limiter limiter;
1805 setup_limiter(pool, selection, flags, &limiter);
1806 ret = selection_make_matchsolvable_common(pool, selection, solvidq, 0, flags, keyname, marker, &limiter);
1807 free_limiter(&limiter);
1812 pool_is_kind(Pool *pool, Id name, Id kind)
1817 n = pool_id2str(pool, name);
1820 const char *kn = pool_id2str(pool, kind);
1821 int knl = strlen(kn);
1822 return !strncmp(n, kn, knl) && n[knl] == ':' ? 1 : 0;
1828 while(*n >= 'a' && *n <= 'z')
1830 return *n == ':' ? 0 : 1;
1835 selection_filter_map(Pool *pool, Queue *sel, Map *m, int setflags)
1842 for (i = j = 0; i < sel->count; i += 2)
1844 Id select = sel->elements[i] & SOLVER_SELECTMASK;
1845 Id id = sel->elements[i + 1];
1849 if (select == SOLVER_SOLVABLE_ALL)
1851 FOR_POOL_SOLVABLES(p)
1859 else if (select == SOLVER_SOLVABLE_REPO)
1862 Repo *repo = pool_id2repo(pool, id);
1865 FOR_REPO_SOLVABLES(repo, p, s)
1874 else if (select == SOLVER_SOLVABLE)
1876 if (!map_tst(m, id))
1878 sel->elements[j] = sel->elements[i] | setflags;
1879 sel->elements[j + 1] = id;
1885 FOR_JOB_SELECT(p, pp, select, id)
1888 queue_pushunique(&q, p);
1897 sel->elements[j] = sel->elements[i] | setflags;
1898 sel->elements[j + 1] = id;
1900 else if (q.count > 1)
1902 sel->elements[j] = (sel->elements[i] & ~SOLVER_SELECTMASK) | SOLVER_SOLVABLE_ONE_OF | setflags;
1903 sel->elements[j + 1] = pool_queuetowhatprovides(pool, &q);
1907 sel->elements[j] = (sel->elements[i] & ~SOLVER_SELECTMASK) | SOLVER_SOLVABLE | SOLVER_NOAUTOSET | setflags;
1908 sel->elements[j + 1] = q.elements[0];
1912 queue_truncate(sel, j);
1917 selection_filter_int(Pool *pool, Queue *sel1, Queue *sel2, int invert)
1920 Id p, pp, q1filled = 0;
1925 /* handle special cases */
1926 if (!sel1->count || !sel2->count)
1928 if (invert && !sel2->count)
1933 if (sel1->count == 2 && (sel1->elements[0] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_ALL && !invert)
1935 /* XXX: not 100% correct, but very useful */
1936 setflags = sel1->elements[0] & ~(SOLVER_SELECTMASK | SOLVER_SETMASK); /* job & jobflags */
1938 queue_init_clone(sel1, sel2);
1939 for (i = 0; i < sel1->count; i += 2)
1940 sel1->elements[i] = (sel1->elements[i] & (SOLVER_SELECTMASK | SOLVER_SETMASK)) | setflags;
1943 if (sel1->count == 2 && (sel1->elements[0] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_REPO && !invert)
1945 Repo *repo = pool_id2repo(pool, sel1->elements[1]);
1946 setflags = sel1->elements[0] & ~(SOLVER_SELECTMASK | SOLVER_NOAUTOSET); /* job, jobflags, setflags */
1948 queue_init_clone(sel1, sel2);
1949 for (i = 0; i < sel1->count; i += 2)
1950 sel1->elements[i] &= SOLVER_SELECTMASK | SOLVER_SETMASK; /* remove job and jobflags */
1951 selection_filter_repo(pool, sel1, repo, setflags);
1954 if (sel2->count == 2 && (sel2->elements[0] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_ALL)
1960 if (sel2->count == 2 && (sel2->elements[0] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_REPO && !invert)
1962 Repo *repo = pool_id2repo(pool, sel2->elements[1]);
1963 setflags = sel2->elements[0] & (SOLVER_SETMASK & ~SOLVER_NOAUTOSET);
1964 selection_filter_repo(pool, sel1, repo, setflags);
1968 /* convert sel2 into a map */
1970 map_init(&m2, pool->nsolvables);
1971 for (i = 0; i < sel2->count; i += 2)
1973 Id select = sel2->elements[i] & SOLVER_SELECTMASK;
1974 if (select == SOLVER_SOLVABLE_ALL)
1982 if (select == SOLVER_SOLVABLE_REPO)
1985 Repo *repo = pool_id2repo(pool, sel2->elements[i + 1]);
1988 FOR_REPO_SOLVABLES(repo, p, s)
1994 if ((select == SOLVER_SOLVABLE_NAME || select == SOLVER_SOLVABLE_PROVIDES) && ISRELDEP(sel2->elements[i + 1]))
1996 Reldep *rd = GETRELDEP(pool, sel2->elements[i + 1]);
1997 if (rd->flags == REL_ARCH && rd->name == 0)
1999 /* special arch filter */
2001 selection_solvables(pool, sel1, &q1);
2002 for (j = 0; j < q1.count; j++)
2004 Id p = q1.elements[j];
2005 Solvable *s = pool->solvables + p;
2006 if (s->arch == rd->evr || (rd->evr == ARCH_SRC && s->arch == ARCH_NOSRC))
2011 else if (rd->flags == REL_KIND && rd->name == 0)
2013 /* special kind filter */
2015 selection_solvables(pool, sel1, &q1);
2016 for (j = 0; j < q1.count; j++)
2018 Id p = q1.elements[j];
2019 Solvable *s = pool->solvables + p;
2020 if (pool_is_kind(pool, s->name, rd->evr))
2026 FOR_JOB_SELECT(p, pp, select, sel2->elements[i + 1])
2032 /* now filter sel1 with the map */
2035 if (sel2->count == 2)
2036 setflags = sel2->elements[0] & (SOLVER_SETMASK & ~SOLVER_NOAUTOSET);
2037 selection_filter_map(pool, sel1, &m2, setflags);
2042 selection_filter(Pool *pool, Queue *sel1, Queue *sel2)
2044 selection_filter_int(pool, sel1, sel2, 0);
2048 selection_add(Pool *pool, Queue *sel1, Queue *sel2)
2051 queue_insertn(sel1, sel1->count, sel2->count, sel2->elements);
2055 selection_subtract(Pool *pool, Queue *sel1, Queue *sel2)
2057 selection_filter_int(pool, sel1, sel2, 1);
2061 pool_selection2str(Pool *pool, Queue *selection, Id flagmask)
2066 s = pool_tmpjoin(pool, 0, 0, 0);
2067 for (i = 0; i < selection->count; i += 2)
2069 Id how = selection->elements[i];
2071 s = pool_tmpappend(pool, s, " + ", 0);
2072 s2 = solver_select2str(pool, how & SOLVER_SELECTMASK, selection->elements[i + 1]);
2073 s = pool_tmpappend(pool, s, s2, 0);
2074 pool_freetmpspace(pool, s2);
2075 how &= flagmask & SOLVER_SETMASK;
2079 s = pool_tmpappend(pool, s, " ", 0);
2080 if (how & SOLVER_SETEV)
2081 s = pool_tmpappend(pool, s, ",setev", 0);
2082 if (how & SOLVER_SETEVR)
2083 s = pool_tmpappend(pool, s, ",setevr", 0);
2084 if (how & SOLVER_SETARCH)
2085 s = pool_tmpappend(pool, s, ",setarch", 0);
2086 if (how & SOLVER_SETVENDOR)
2087 s = pool_tmpappend(pool, s, ",setvendor", 0);
2088 if (how & SOLVER_SETREPO)
2089 s = pool_tmpappend(pool, s, ",setrepo", 0);
2090 if (how & SOLVER_NOAUTOSET)
2091 s = pool_tmpappend(pool, s, ",noautoset", 0);
2092 if (s[o + 1] != ',')
2093 s = pool_tmpappend(pool, s, ",?", 0);
2095 s = pool_tmpappend(pool, s, "]", 0);