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"
27 str2archid(Pool *pool, const char *arch)
32 id = pool_str2id(pool, arch, 0);
33 if (!id || id == ARCH_SRC || id == ARCH_NOSRC || id == ARCH_NOARCH)
35 if (pool->id2arch && pool_arch2score(pool, id) == 0)
40 /* remove empty jobs from the selection */
42 selection_prune(Pool *pool, Queue *selection)
46 for (i = j = 0; i < selection->count; i += 2)
48 Id select = selection->elements[i] & SOLVER_SELECTMASK;
50 if (select == SOLVER_SOLVABLE_ALL)
52 else if (select == SOLVER_SOLVABLE_REPO)
55 Repo *repo = pool_id2repo(pool, selection->elements[i + 1]);
58 FOR_REPO_SOLVABLES(repo, p, s)
64 FOR_JOB_SELECT(p, pp, select, selection->elements[i + 1])
69 selection->elements[j] = selection->elements[i];
70 selection->elements[j + 1] = selection->elements[i + 1];
73 queue_truncate(selection, j);
78 selection_solvables_sortcmp(const void *ap, const void *bp, void *dp)
80 return *(const Id *)ap - *(const Id *)bp;
84 selection_solvables(Pool *pool, Queue *selection, Queue *pkgs)
89 for (i = 0; i < selection->count; i += 2)
91 Id select = selection->elements[i] & SOLVER_SELECTMASK;
92 if (select == SOLVER_SOLVABLE_ALL)
97 if (select == SOLVER_SOLVABLE_REPO)
100 Repo *repo = pool_id2repo(pool, selection->elements[i + 1]);
103 FOR_REPO_SOLVABLES(repo, p, s)
109 FOR_JOB_SELECT(p, pp, select, selection->elements[i + 1])
116 solv_sort(pkgs->elements, pkgs->count, sizeof(Id), selection_solvables_sortcmp, NULL);
117 lastid = pkgs->elements[0];
118 for (i = j = 1; i < pkgs->count; i++)
119 if (pkgs->elements[i] != lastid)
120 pkgs->elements[j++] = lastid = pkgs->elements[i];
121 queue_truncate(pkgs, j);
125 selection_flatten(Pool *pool, Queue *selection)
129 if (selection->count <= 2)
131 for (i = 0; i < selection->count; i += 2)
132 if ((selection->elements[i] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_ALL)
134 selection->elements[0] = selection->elements[i];
135 selection->elements[1] = selection->elements[i + 1];
136 queue_truncate(selection, 2);
140 selection_solvables(pool, selection, &q);
143 queue_empty(selection);
146 queue_truncate(selection, 2);
149 selection->elements[0] = SOLVER_SOLVABLE_ONE_OF;
150 selection->elements[1] = pool_queuetowhatprovides(pool, &q);
154 selection->elements[0] = SOLVER_SOLVABLE | SOLVER_NOAUTOSET;
155 selection->elements[1] = q.elements[0];
159 /* only supports simple rels plus REL_ARCH */
161 match_nevr_rel(Pool *pool, Solvable *s, Id rflags, Id revr)
163 if (rflags == REL_ARCH)
167 if (revr != ARCH_SRC || s->arch != ARCH_NOSRC)
174 return pool_intersect_evrs(pool, REL_EQ, s->evr, rflags, revr);
177 /* only supports simple rels plus REL_ARCH */
179 selection_filter_rel_noprune(Pool *pool, Queue *selection, Id relflags, Id relevr)
183 if (!selection->count)
186 for (i = 0; i < selection->count; i += 2)
188 Id select = selection->elements[i] & SOLVER_SELECTMASK;
189 Id id = selection->elements[i + 1];
190 if (select == SOLVER_SOLVABLE || select == SOLVER_SOLVABLE_ONE_OF)
192 /* done by selection_addextra, currently implies SELECTION_NAME */
198 FOR_JOB_SELECT(p, pp, select, id)
200 Solvable *s = pool->solvables + p;
201 if (match_nevr_rel(pool, s, relflags, relevr))
210 selection->elements[i] = SOLVER_SOLVABLE | SOLVER_NOAUTOSET;
211 selection->elements[i + 1] = q.elements[0];
215 selection->elements[i] = SOLVER_SOLVABLE_ONE_OF;
216 selection->elements[i + 1] = pool_queuetowhatprovides(pool, &q);
221 else if (select == SOLVER_SOLVABLE_NAME || select == SOLVER_SOLVABLE_PROVIDES)
223 /* don't stack src reldeps */
224 if (relflags == REL_ARCH && (relevr == ARCH_SRC || relevr == ARCH_NOSRC) && ISRELDEP(id))
226 Reldep *rd = GETRELDEP(pool, id);
227 if (rd->flags == REL_ARCH && rd->evr == ARCH_SRC)
230 selection->elements[i + 1] = pool_rel2id(pool, id, relevr, relflags, 1);
233 continue; /* actually cannot happen */
235 /* now add the setflags we gained */
236 if (relflags == REL_ARCH)
237 selection->elements[i] |= SOLVER_SETARCH;
238 if (relflags == REL_EQ && select != SOLVER_SOLVABLE_PROVIDES)
240 if (pool->disttype == DISTTYPE_DEB)
241 selection->elements[i] |= SOLVER_SETEVR; /* debian can't match version only like rpm */
244 const char *rel = strrchr(pool_id2str(pool, relevr), '-');
245 selection->elements[i] |= rel ? SOLVER_SETEVR : SOLVER_SETEV;
251 /* only supports simple rels plus REL_ARCH */
252 /* prunes empty jobs */
254 selection_filter_rel(Pool *pool, Queue *selection, Id relflags, Id relevr)
256 selection_filter_rel_noprune(pool, selection, relflags, relevr);
257 selection_prune(pool, selection);
260 /* limit a selection to to repository */
261 /* prunes empty jobs */
263 selection_filter_repo(Pool *pool, Queue *selection, Repo *repo)
268 if (!selection->count)
272 queue_empty(selection);
276 for (i = j = 0; i < selection->count; i += 2)
278 Id select = selection->elements[i] & SOLVER_SELECTMASK;
279 Id id = selection->elements[i + 1];
280 if (select == SOLVER_SOLVABLE_ALL)
282 select = SOLVER_SOLVABLE_REPO;
285 else if (select == SOLVER_SOLVABLE_REPO)
287 if (id != repo->repoid)
295 FOR_JOB_SELECT(p, pp, select, id)
297 if (pool->solvables[p].repo != repo)
305 select = 0; /* prune empty jobs */
306 else if (q.count == 1)
308 select = SOLVER_SOLVABLE | SOLVER_NOAUTOSET;
313 select = SOLVER_SOLVABLE_ONE_OF;
314 id = pool_queuetowhatprovides(pool, &q);
319 continue; /* job is now empty */
320 if (select == SOLVER_SOLVABLE_REPO)
324 FOR_REPO_SOLVABLES(repo, p, s)
327 continue; /* repo is empty */
329 selection->elements[j++] = select | (selection->elements[i] & ~SOLVER_SELECTMASK) | SOLVER_SETREPO;
330 selection->elements[j++] = id;
332 queue_truncate(selection, j);
338 matchprovides(Pool *pool, Solvable *s, Id dep)
341 idp = s->repo->idarraydata + s->provides;
342 while ((id = *idp++) != 0)
343 if (pool_match_dep(pool, id, dep))
348 /* change a SOLVER_SOLVABLE_NAME/PROVIDES selection to something that also includes
350 * extra packages are: src, badarch, disabled
353 selection_addextra(Pool *pool, Queue *selection, int flags)
357 int i, isextra, haveextra, doprovides;
359 if ((flags & SELECTION_INSTALLED_ONLY) != 0)
360 flags &= ~SELECTION_WITH_SOURCE;
362 if (!(flags & (SELECTION_WITH_SOURCE | SELECTION_WITH_DISABLED | SELECTION_WITH_BADARCH)))
363 return; /* nothing to add */
366 for (i = 0; i < selection->count; i += 2)
368 if (selection->elements[i] == SOLVER_SOLVABLE_NAME)
370 else if (selection->elements[i] == SOLVER_SOLVABLE_PROVIDES)
374 dep = selection->elements[i + 1];
379 /* first put all non-extra packages on the queue */
380 FOR_PROVIDES(p, pp, dep)
382 if ((flags & SELECTION_INSTALLED_ONLY) != 0 && pool->solvables[p].repo != pool->installed)
387 FOR_POOL_SOLVABLES(p)
389 Solvable *s = pool->solvables + p;
390 if (!doprovides && !pool_match_nevr(pool, s, dep))
392 if ((flags & SELECTION_INSTALLED_ONLY) != 0 && s->repo != pool->installed)
395 if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
397 if (!(flags & SELECTION_WITH_SOURCE) && !(flags & SELECTION_SOURCE_ONLY))
399 if (!(flags & SELECTION_SOURCE_ONLY))
401 if (pool_disabled_solvable(pool, s))
403 if (!(flags & SELECTION_WITH_DISABLED))
410 if ((flags & SELECTION_SOURCE_ONLY) != 0)
412 if (s->repo != pool->installed)
414 if (pool_disabled_solvable(pool, s))
416 if (!(flags & SELECTION_WITH_DISABLED))
420 if (pool_badarch_solvable(pool, s))
422 if (!(flags & SELECTION_WITH_BADARCH))
431 continue; /* already done above in FOR_PROVIDES */
432 if (!s->provides || !matchprovides(pool, s, dep))
435 haveextra |= isextra;
438 if (!haveextra || !q.count)
442 selection->elements[i] = (selection->elements[i] & ~SOLVER_SELECTMASK) | SOLVER_SOLVABLE | SOLVER_NOAUTOSET;
443 selection->elements[i + 1] = q.elements[0];
448 solv_sort(q.elements, q.count, sizeof(Id), selection_solvables_sortcmp, NULL);
449 selection->elements[i] = (selection->elements[i] & ~SOLVER_SELECTMASK) | SOLVER_SOLVABLE_ONE_OF;
450 selection->elements[i + 1] = pool_queuetowhatprovides(pool, &q);
456 static inline const char *
457 skipkind(const char *n)
460 for (s = n; *s >= 'a' && *s <= 'z'; s++)
462 if (*s == ':' && s != n)
468 queue_pushunique2(Queue *q, Id id1, Id id2)
471 for (i = 0; i < q->count; i += 2)
472 if (q->elements[i] == id1 && q->elements[i + 1] == id2)
474 queue_push2(q, id1, id2);
478 /***** provides matching *****/
481 selection_addextra_provides(Pool *pool, Queue *selection, const char *name, int flags)
485 int doglob, nocase, globflags;
487 if ((flags & SELECTION_INSTALLED_ONLY) != 0)
488 return 0; /* neither disabled nor badarch nor src */
490 nocase = flags & SELECTION_NOCASE;
491 doglob = (flags & SELECTION_GLOB) != 0 && strpbrk(name, "[*?") != 0;
492 globflags = doglob && nocase ? FNM_CASEFOLD : 0;
494 FOR_POOL_SOLVABLES(p)
497 Solvable *s = pool->solvables + p;
500 if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC) /* no provides */
502 if (s->repo == pool->installed)
504 if (pool_disabled_solvable(pool, s))
506 if (!(flags & SELECTION_WITH_DISABLED))
508 if (!(flags & SELECTION_WITH_BADARCH) && pool_badarch_solvable(pool, s))
511 else if (pool_badarch_solvable(pool, s))
513 if (!(flags & SELECTION_WITH_BADARCH))
518 /* here is an extra solvable we need to consider */
519 idp = s->repo->idarraydata + s->provides;
520 while ((id = *idp++) != 0)
524 Reldep *rd = GETRELDEP(pool, id);
527 if (pool->whatprovides[id] > 1)
528 continue; /* we already did that one in the normal code path */
529 n = pool_id2str(pool, id);
530 if ((doglob ? fnmatch(name, n, globflags) : nocase ? strcasecmp(name, n) : strcmp(name, n)) == 0)
532 queue_pushunique2(selection, SOLVER_SOLVABLE_PROVIDES, id);
540 /* this is the fast path of selection_provides: the id for the name
541 * is known and thus we can quickly check the existance of a
542 * package with that provides */
544 selection_provides_id(Pool *pool, Queue *selection, Id id, int flags)
548 FOR_PROVIDES(p, pp, id)
550 Solvable *s = pool->solvables + p;
551 if ((flags & SELECTION_INSTALLED_ONLY) != 0 && s->repo != pool->installed)
557 queue_push2(selection, SOLVER_SOLVABLE_PROVIDES, id);
558 return SELECTION_PROVIDES;
561 if ((flags & (SELECTION_WITH_BADARCH | SELECTION_WITH_DISABLED)) != 0)
563 queue_push2(selection, SOLVER_SOLVABLE_PROVIDES, id);
564 selection_addextra(pool, selection, flags);
565 if (selection->elements[0] == SOLVER_SOLVABLE_PROVIDES)
566 queue_empty(selection);
569 selection->elements[0] = SOLVER_SOLVABLE_PROVIDES;
570 selection->elements[1] = id;
572 return selection->count ? SELECTION_PROVIDES : 0;
578 /* add missing provides matchers to the selection */
579 /* match the provides of a package */
580 /* note that we only return raw SOLVER_SOLVABLE_PROVIDES jobs
581 * so that the selection can be modified later. */
583 selection_provides(Pool *pool, Queue *selection, const char *name, int flags)
592 if ((flags & SELECTION_SOURCE_ONLY) != 0)
593 return 0; /* sources do not have provides */
595 nocase = flags & SELECTION_NOCASE;
598 /* try the fast path first */
599 id = pool_str2id(pool, name, 0);
602 /* the id is known, do the fast id matching */
603 int ret = selection_provides_id(pool, selection, id, flags);
609 doglob = (flags & SELECTION_GLOB) != 0 && strpbrk(name, "[*?") != 0;
610 if (!nocase && !doglob)
612 /* all done above in selection_provides_id */
616 /* looks like a glob or nocase match. really hard work. */
618 globflags = doglob && nocase ? FNM_CASEFOLD : 0;
619 for (id = 1; id < pool->ss.nstrings; id++)
621 /* do we habe packages providing this id? */
622 if (!pool->whatprovides[id] || pool->whatprovides[id] == 1)
624 n = pool_id2str(pool, id);
625 if ((doglob ? fnmatch(name, n, globflags) : nocase ? strcasecmp(name, n) : strcmp(name, n)) == 0)
627 if ((flags & SELECTION_INSTALLED_ONLY) != 0)
629 FOR_PROVIDES(p, pp, id)
630 if (pool->solvables[p].repo == pool->installed)
635 queue_push2(selection, SOLVER_SOLVABLE_PROVIDES, id);
640 if (flags & (SELECTION_WITH_BADARCH | SELECTION_WITH_DISABLED))
641 match |= selection_addextra_provides(pool, selection, name, flags);
643 return match ? SELECTION_PROVIDES : 0;
646 /***** name matching *****/
648 /* this is the fast path of selection_name: the id for the name
649 * is known and thus we can quickly check the existance of a
650 * package with that name */
652 selection_name_id(Pool *pool, Queue *selection, Id id, int flags)
657 if ((flags & SELECTION_SOURCE_ONLY) != 0)
659 /* sources cannot be installed */
660 if ((flags & SELECTION_INSTALLED_ONLY) != 0)
662 /* add ARCH_SRC to match only sources */
663 matchid = pool_rel2id(pool, id, ARCH_SRC, REL_ARCH, 1);
664 flags &= ~SELECTION_WITH_SOURCE;
667 FOR_PROVIDES(p, pp, matchid)
669 Solvable *s = pool->solvables + p;
672 if ((flags & SELECTION_INSTALLED_ONLY) != 0 && s->repo != pool->installed)
674 /* one match is all we need */
675 queue_push2(selection, SOLVER_SOLVABLE_NAME, matchid);
676 /* add the requested extra packages */
677 if ((flags & (SELECTION_WITH_SOURCE | SELECTION_WITH_BADARCH | SELECTION_WITH_DISABLED)) != 0)
678 selection_addextra(pool, selection, flags);
679 return SELECTION_NAME;
682 if ((flags & (SELECTION_WITH_BADARCH | SELECTION_WITH_DISABLED)) != 0)
684 queue_push2(selection, SOLVER_SOLVABLE_NAME, matchid);
685 selection_addextra(pool, selection, flags);
686 if (selection->elements[0] == SOLVER_SOLVABLE_NAME)
687 queue_empty(selection);
688 return selection->count ? SELECTION_NAME : 0;
691 if ((flags & SELECTION_WITH_SOURCE) != 0 && (flags & SELECTION_INSTALLED_ONLY) == 0)
693 /* WITH_SOURCE case, but we had no match. try SOURCE_ONLY instead */
694 matchid = pool_rel2id(pool, id, ARCH_SRC, REL_ARCH, 1);
695 FOR_PROVIDES(p, pp, matchid)
697 Solvable *s = pool->solvables + p;
700 queue_push2(selection, SOLVER_SOLVABLE_NAME, matchid);
701 return SELECTION_NAME;
707 /* match the name of a package */
708 /* note that for SELECTION_INSTALLED_ONLY the result is not trimmed */
710 selection_name(Pool *pool, Queue *selection, const char *name, int flags)
718 if ((flags & SELECTION_SOURCE_ONLY) != 0)
719 flags &= ~SELECTION_WITH_SOURCE;
721 nocase = flags & SELECTION_NOCASE;
722 if (!nocase && !(flags & SELECTION_SKIP_KIND))
724 /* try the fast path first */
725 id = pool_str2id(pool, name, 0);
728 int ret = selection_name_id(pool, selection, id, flags);
734 doglob = (flags & SELECTION_GLOB) != 0 && strpbrk(name, "[*?") != 0;
735 if (!nocase && !(flags & SELECTION_SKIP_KIND) && !doglob)
736 return 0; /* all done above in selection_name_id */
738 /* do a name match over all packages. hard work. */
740 globflags = doglob && nocase ? FNM_CASEFOLD : 0;
741 FOR_POOL_SOLVABLES(p)
743 Solvable *s = pool->solvables + p;
744 if ((flags & SELECTION_INSTALLED_ONLY) != 0 && s->repo != pool->installed)
746 if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
748 if (!(flags & SELECTION_SOURCE_ONLY) && !(flags & SELECTION_WITH_SOURCE))
750 if (!(flags & SELECTION_WITH_DISABLED) && pool_disabled_solvable(pool, s))
753 else if (s->repo != pool->installed)
755 if (!(flags & SELECTION_WITH_DISABLED) && pool_disabled_solvable(pool, s))
757 if (!(flags & SELECTION_WITH_BADARCH) && pool_badarch_solvable(pool, s))
761 n = pool_id2str(pool, id);
762 if (flags & SELECTION_SKIP_KIND)
764 if ((doglob ? fnmatch(name, n, globflags) : nocase ? strcasecmp(name, n) : strcmp(name, n)) == 0)
766 if ((flags & SELECTION_SOURCE_ONLY) != 0)
768 if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
770 id = pool_rel2id(pool, id, ARCH_SRC, REL_ARCH, 1);
772 queue_pushunique2(selection, SOLVER_SOLVABLE_NAME, id);
778 /* if there was a match widen the selector to include all extra packages */
779 if ((flags & (SELECTION_WITH_SOURCE | SELECTION_WITH_BADARCH | SELECTION_WITH_DISABLED)) != 0)
780 selection_addextra(pool, selection, flags);
781 return SELECTION_NAME;
787 /***** SELECTION_DOTARCH and SELECTION_REL handling *****/
789 /* like selection_name, but check for a .arch suffix if the match did
790 not work and SELECTION_DOTARCH is used */
792 selection_name_arch(Pool *pool, Queue *selection, const char *name, int flags, int doprovides, int noprune)
799 ret = selection_provides(pool, selection, name, flags);
801 ret = selection_name(pool, selection, name, flags);
804 if (!(flags & SELECTION_DOTARCH))
806 /* check if there is an .arch suffix */
807 if ((r = strrchr(name, '.')) != 0 && r[1] && (archid = str2archid(pool, r + 1)) != 0)
809 char *rname = solv_strdup(name);
811 if (archid == ARCH_SRC || archid == ARCH_NOSRC)
812 flags |= SELECTION_SOURCE_ONLY;
814 ret = selection_provides(pool, selection, rname, flags);
816 ret = selection_name(pool, selection, rname, flags);
819 selection_filter_rel_noprune(pool, selection, REL_ARCH, archid);
821 selection_prune(pool, selection);
824 return ret && selection->count ? ret | SELECTION_DOTARCH : 0;
830 splitrel(char *rname, char *r, int *rflagsp)
832 int nend = r - rname;
834 if (nend && *r == '=' && r[-1] == '!')
838 rflags = REL_LT|REL_GT;
851 while (*r && (*r == ' ' || *r == '\t'))
853 while (nend && (rname[nend - 1] == ' ' || rname[nend - 1] == '\t'))
855 if (nend <= 0 || !*r || !rflags)
862 /* match name/provides, support DOTARCH and REL modifiers
865 selection_name_arch_rel(Pool *pool, Queue *selection, const char *name, int flags, int doprovides)
867 int ret, rflags = 0, noprune;
868 char *r = 0, *rname = 0;
870 /* try to split off an relation part */
871 if ((flags & SELECTION_REL) != 0)
873 if ((r = strpbrk(name, "<=>")) != 0)
875 rname = solv_strdup(name);
876 r = rname + (r - name);
877 if ((r = splitrel(rname, r, &rflags)) == 0)
878 rname = solv_free(rname);
882 /* check if we need to call selection_addextra */
883 noprune = doprovides && (flags & (SELECTION_WITH_DISABLED | SELECTION_WITH_BADARCH));
887 /* could not split off relation */
888 ret = selection_name_arch(pool, selection, name, flags, doprovides, noprune);
891 selection_addextra(pool, selection, flags);
892 selection_prune(pool, selection);
894 return ret && selection->count ? ret : 0;
897 /* we could split of a relation. prune name and then filter rel */
898 ret = selection_name_arch(pool, selection, rname, flags, doprovides, noprune);
901 selection_filter_rel_noprune(pool, selection, rflags, pool_str2id(pool, r, 1));
903 selection_addextra(pool, selection, flags);
904 selection_prune(pool, selection);
907 return ret && selection->count ? ret | SELECTION_REL : 0;
910 /***** filelist matching *****/
913 selection_filelist_sortcmp(const void *ap, const void *bp, void *dp)
916 const Id *a = ap, *b = bp;
918 return strcmp(pool_id2str(pool, a[0]), pool_id2str(pool, b[0]));
923 selection_filelist(Pool *pool, Queue *selection, const char *name, int flags)
931 /* all files in the file list start with a '/' */
934 if (!(flags & SELECTION_GLOB))
936 if (*name != '*' && *name != '[' && *name != '?')
939 type = !(flags & SELECTION_GLOB) || strpbrk(name, "[*?") == 0 ? SEARCH_STRING : SEARCH_GLOB;
940 if ((flags & SELECTION_NOCASE) != 0)
941 type |= SEARCH_NOCASE;
943 dataiterator_init(&di, pool, flags & SELECTION_INSTALLED_ONLY ? pool->installed : 0, 0, SOLVABLE_FILELIST, name, type|SEARCH_FILES|SEARCH_COMPLETE_FILELIST);
944 while (dataiterator_step(&di))
946 Solvable *s = pool->solvables + di.solvid;
949 if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
951 if (!(flags & SELECTION_SOURCE_ONLY) && !(flags & SELECTION_WITH_SOURCE))
953 if (!(flags & SELECTION_WITH_DISABLED) && pool_disabled_solvable(pool, s))
958 if ((flags & SELECTION_SOURCE_ONLY) != 0)
960 if (s->repo != pool->installed)
962 if (!(flags & SELECTION_WITH_DISABLED) && pool_disabled_solvable(pool, s))
964 if (!(flags & SELECTION_WITH_BADARCH) && pool_badarch_solvable(pool, s))
968 if ((flags & SELECTION_FLAT) != 0)
970 /* don't bother with the complex stuff */
971 queue_push2(selection, SOLVER_SOLVABLE | SOLVER_NOAUTOSET, di.solvid);
972 dataiterator_skip_solvable(&di);
975 id = pool_str2id(pool, di.kv.str, 1);
976 queue_push2(&q, id, di.solvid);
978 dataiterator_free(&di);
979 if ((flags & SELECTION_FLAT) != 0)
982 return selection->count ? SELECTION_FILELIST : 0;
989 solv_sort(q.elements, q.count / 2, 2 * sizeof(Id), selection_filelist_sortcmp, pool);
991 queue_push2(&q, 0, 0);
992 for (i = j = 0; i < q.count; i += 2)
994 if (q.elements[i] != lastid)
997 queue_pushunique2(selection, SOLVER_SOLVABLE | SOLVER_NOAUTOSET, q.elements[0]);
1002 /* check if we already have it */
1003 for (k = 0; k < selection->count; k += 2)
1005 if (selection->elements[k] != SOLVER_SOLVABLE_ONE_OF)
1007 idp = pool->whatprovidesdata + selection->elements[k + 1];
1008 if (!memcmp(idp, q.elements, j * sizeof(Id)) && !idp[j])
1011 if (k == selection->count)
1012 queue_push2(selection, SOLVER_SOLVABLE_ONE_OF, pool_ids2whatprovides(pool, q.elements, j));
1014 lastid = q.elements[i];
1017 if (!j || q.elements[j - 1] != q.elements[i])
1018 q.elements[j++] = q.elements[i + 1];
1021 return SELECTION_FILELIST;
1025 /***** canon name matching *****/
1027 #if defined(MULTI_SEMANTICS)
1028 # define EVRCMP_DEPCMP (pool->disttype == DISTTYPE_DEB ? EVRCMP_COMPARE : EVRCMP_MATCH_RELEASE)
1029 #elif defined(DEBIAN)
1030 # define EVRCMP_DEPCMP EVRCMP_COMPARE
1032 # define EVRCMP_DEPCMP EVRCMP_MATCH_RELEASE
1035 /* magic epoch promotion code, works only for SELECTION_NAME selections */
1037 selection_filter_evr(Pool *pool, Queue *selection, const char *evr)
1044 /* do we already have an epoch? */
1045 for (sp = evr; *sp >= '0' && *sp <= '9'; sp++)
1047 if (*sp == ':' && sp != evr)
1049 /* yes, just add the rel filter */
1050 selection_filter_rel(pool, selection, REL_EQ, pool_str2id(pool, evr, 1));
1055 queue_init_buffer(&q, qbuf, sizeof(qbuf)/sizeof(*qbuf));
1056 for (i = j = 0; i < selection->count; i += 2)
1058 Id select = selection->elements[i] & SOLVER_SELECTMASK;
1059 Id id = selection->elements[i + 1];
1061 const char *lastepoch = 0;
1062 int lastepochlen = 0;
1065 FOR_JOB_SELECT(p, pp, select, id)
1067 Solvable *s = pool->solvables + p;
1068 const char *sevr = pool_id2str(pool, s->evr);
1069 for (sp = sevr; *sp >= '0' && *sp <= '9'; sp++)
1073 /* compare vr part */
1074 if (strcmp(evr, sp != sevr ? sp + 1 : sevr) != 0)
1076 int r = pool_evrcmp_str(pool, sp != sevr ? sp + 1 : sevr, evr, EVRCMP_DEPCMP);
1077 if (r == -1 || r == 1)
1078 continue; /* solvable does not match vr */
1083 while (sevr < sp && *sevr == '0') /* normalize epoch */
1089 lastepochlen = sp - sevr;
1091 else if (lastepochlen != sp - sevr || strncmp(lastepoch, sevr, lastepochlen) != 0)
1092 lastepochlen = -1; /* multiple different epochs */
1094 if (!lastepoch || lastepochlen == 0)
1095 id = pool_str2id(pool, evr, 1); /* no match at all or zero epoch */
1096 else if (lastepochlen >= 0)
1098 /* found exactly one epoch, simply prepend */
1099 char *evrx = solv_malloc(strlen(evr) + lastepochlen + 2);
1100 strncpy(evrx, lastepoch, lastepochlen + 1);
1101 strcpy(evrx + lastepochlen + 1, evr);
1102 id = pool_str2id(pool, evrx, 1);
1107 /* multiple epochs in multiple solvables, convert to list of solvables */
1108 selection->elements[j] = (selection->elements[i] & ~SOLVER_SELECTMASK) | SOLVER_SOLVABLE_ONE_OF;
1109 selection->elements[j + 1] = pool_queuetowhatprovides(pool, &q);
1114 queue_push2(&q, selection->elements[i], selection->elements[i + 1]);
1115 selection_filter_rel(pool, &q, REL_EQ, id);
1117 continue; /* oops, no match */
1118 selection->elements[j] = q.elements[0];
1119 selection->elements[j + 1] = q.elements[1];
1122 queue_truncate(selection, j);
1126 /* match the "canonical" name of the package */
1128 selection_canon(Pool *pool, Queue *selection, const char *name, int flags)
1130 char *rname, *r, *r2;
1136 * nameglob-version.arch
1137 * nameglob-version-release
1138 * nameglob-version-release.arch
1140 flags |= SELECTION_NAME;
1141 flags &= ~SELECTION_PROVIDES;
1143 if (pool->disttype == DISTTYPE_DEB)
1145 if ((r = strchr(name, '_')) == 0)
1147 rname = solv_strdup(name); /* so we can modify it */
1148 r = rname + (r - name);
1150 if ((ret = selection_name(pool, selection, rname, flags)) == 0)
1155 /* is there a vaild arch? */
1156 if ((r2 = strrchr(r, '_')) != 0 && r[1] && (archid = str2archid(pool, r + 1)) != 0)
1158 *r2 = 0; /* split off */
1159 selection_filter_rel(pool, selection, REL_ARCH, archid);
1161 selection_filter_rel(pool, selection, REL_EQ, pool_str2id(pool, r, 1));
1163 return selection->count ? ret | SELECTION_CANON : 0;
1166 if (pool->disttype == DISTTYPE_HAIKU)
1168 if ((r = strchr(name, '-')) == 0)
1170 rname = solv_strdup(name); /* so we can modify it */
1171 r = rname + (r - name);
1173 if ((ret = selection_name(pool, selection, rname, flags)) == 0)
1178 /* is there a vaild arch? */
1179 if ((r2 = strrchr(r, '-')) != 0 && r[1] && (archid = str2archid(pool, r + 1)) != 0)
1181 *r2 = 0; /* split off */
1182 selection_filter_rel(pool, selection, REL_ARCH, archid);
1184 selection_filter_rel(pool, selection, REL_EQ, pool_str2id(pool, r, 1));
1186 return selection->count ? ret | SELECTION_CANON : 0;
1189 if ((r = strrchr(name, '-')) == 0)
1191 rname = solv_strdup(name); /* so we can modify it */
1192 r = rname + (r - name);
1195 /* split off potential arch part from version */
1196 if ((r2 = strrchr(r + 1, '.')) != 0 && r2[1] && (archid = str2archid(pool, r2 + 1)) != 0)
1197 *r2 = 0; /* found valid arch, split it off */
1198 if (archid == ARCH_SRC || archid == ARCH_NOSRC)
1199 flags |= SELECTION_SOURCE_ONLY;
1201 /* try with just the version */
1202 if ((ret = selection_name(pool, selection, rname, flags)) == 0)
1204 /* no luck, try with version-release */
1205 if ((r2 = strrchr(rname, '-')) == 0)
1213 if ((ret = selection_name(pool, selection, rname, flags)) == 0)
1220 selection_filter_rel(pool, selection, REL_ARCH, archid);
1221 selection_filter_evr(pool, selection, r + 1); /* magic epoch promotion */
1223 return selection->count ? ret | SELECTION_CANON : 0;
1226 /* return the needed withbits to match the provided selection */
1228 selection_extrabits(Pool *pool, Queue *selection, int flags)
1230 int i, needflags, isextra;
1236 allflags = flags & (SELECTION_WITH_SOURCE | SELECTION_WITH_DISABLED | SELECTION_WITH_BADARCH);
1237 if (!selection->count)
1239 if (selection->count == 2 && selection->elements[0] == SOLVER_SOLVABLE_ALL)
1240 return allflags; /* don't bother */
1241 queue_init(&qlimit);
1242 selection_solvables(pool, selection, &qlimit);
1244 for (i = 0; i < qlimit.count; i++)
1246 p = qlimit.elements[i];
1247 s = pool->solvables + p;
1248 if ((flags & SELECTION_INSTALLED_ONLY) != 0 && s->repo != pool->installed)
1251 if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
1253 if (!(flags & SELECTION_WITH_SOURCE))
1255 isextra |= SELECTION_WITH_SOURCE;
1256 if (pool_disabled_solvable(pool, s))
1258 if (!(flags & SELECTION_WITH_DISABLED))
1260 isextra |= SELECTION_WITH_DISABLED;
1265 if ((flags & SELECTION_SOURCE_ONLY) != 0)
1267 if (s->repo != pool->installed)
1269 if (pool_disabled_solvable(pool, s))
1271 if (!(flags & SELECTION_WITH_DISABLED))
1273 isextra |= SELECTION_WITH_DISABLED;
1275 if (pool_badarch_solvable(pool, s))
1277 if (!(flags & SELECTION_WITH_BADARCH))
1279 isextra |= SELECTION_WITH_BADARCH;
1285 needflags |= isextra;
1286 if (needflags == allflags)
1290 queue_free(&qlimit);
1295 selection_make(Pool *pool, Queue *selection, const char *name, int flags)
1298 if ((flags & SELECTION_MODEBITS) != 0)
1303 if ((flags & SELECTION_MODEBITS) == SELECTION_SUBTRACT || (flags & SELECTION_MODEBITS) == SELECTION_FILTER)
1305 if (!selection->count)
1310 if ((flags & (SELECTION_WITH_DISABLED | SELECTION_WITH_BADARCH | SELECTION_WITH_SOURCE)) != 0)
1312 /* try to drop expensive extra bits */
1313 flags = (flags & ~(SELECTION_WITH_DISABLED | SELECTION_WITH_BADARCH | SELECTION_WITH_SOURCE)) | selection_extrabits(pool, selection, flags);
1316 ret = selection_make(pool, &q, name, flags & ~SELECTION_MODEBITS);
1317 if ((flags & SELECTION_MODEBITS) == SELECTION_ADD)
1318 selection_add(pool, selection, &q);
1319 else if ((flags & SELECTION_MODEBITS) == SELECTION_SUBTRACT)
1320 selection_subtract(pool, selection, &q);
1321 else if (ret || !(flags & SELECTION_FILTER_KEEP_IFEMPTY))
1323 if ((flags & SELECTION_FILTER_SWAPPED) != 0)
1325 selection_filter(pool, &q, selection);
1326 queue_free(selection);
1327 queue_init_clone(selection, &q);
1330 selection_filter(pool, selection, &q);
1335 queue_empty(selection);
1336 if ((flags & SELECTION_INSTALLED_ONLY) != 0 && !pool->installed)
1339 /* here come our four selection modes */
1340 if ((flags & SELECTION_FILELIST) != 0)
1341 ret = selection_filelist(pool, selection, name, flags);
1342 if (!ret && (flags & SELECTION_NAME) != 0)
1343 ret = selection_name_arch_rel(pool, selection, name, flags, 0);
1344 if (!ret && (flags & SELECTION_PROVIDES) != 0)
1345 ret = selection_name_arch_rel(pool, selection, name, flags, 1);
1346 if (!ret && (flags & SELECTION_CANON) != 0)
1347 ret = selection_canon(pool, selection, name, flags);
1349 /* now do result filtering */
1350 if (ret && (flags & SELECTION_INSTALLED_ONLY) != 0)
1351 selection_filter_repo(pool, selection, pool->installed);
1353 /* flatten if requested */
1354 if (ret && (flags & SELECTION_FLAT) != 0)
1355 selection_flatten(pool, selection);
1356 return selection->count ? ret : 0;
1360 int start; /* either 2 or repofilter->start */
1361 int end; /* either nsolvables or repofilter->end */
1366 /* add matching src packages to simple SOLVABLE_NAME selections */
1368 setup_limiter(Pool *pool, int flags, struct limiter *limiter)
1371 limiter->end = pool->nsolvables;
1372 limiter->mapper = 0;
1373 limiter->repofilter = 0;
1374 if ((flags & SELECTION_INSTALLED_ONLY) != 0)
1376 Repo *repo = pool->installed;
1377 limiter->repofilter = repo;
1378 limiter->start = repo ? repo->start : 0;
1379 limiter->end = repo ? repo->end : 0;
1384 matchdep_str(const char *pattern, const char *string, int flags)
1386 if (!pattern || !string)
1388 if (flags & SELECTION_GLOB)
1390 int globflags = (flags & SELECTION_NOCASE) != 0 ? FNM_CASEFOLD : 0;
1391 return fnmatch(pattern, string, globflags) == 0 ? 1 : 0;
1393 if (flags & SELECTION_NOCASE)
1394 return strcasecmp(pattern, string) == 0 ? 1 : 0;
1395 return strcmp(pattern, string) == 0 ? 1 : 0;
1398 /* like pool_match_dep but uses matchdep_str to match the name for glob and nocase matching */
1400 matchdep(Pool *pool, Id id, char *rname, int rflags, Id revr, int flags)
1404 Reldep *rd = GETRELDEP(pool, id);
1407 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)
1409 if (matchdep(pool, rd->name, rname, rflags, revr, flags))
1411 if ((rd->flags == REL_COND || rd->flags == REL_UNLESS) && ISRELDEP(rd->evr))
1413 rd = GETRELDEP(pool, rd->evr);
1414 if (rd->flags != REL_ELSE)
1417 if (rd->flags != REL_COND && rd->flags != REL_UNLESS && rd->flags != REL_WITHOUT && matchdep(pool, rd->evr, rname, rflags, revr, flags))
1421 if (rd->flags == REL_ARCH)
1422 return matchdep(pool, rd->name, rname, rflags, revr, flags);
1424 if (!matchdep(pool, rd->name, rname, rflags, revr, flags))
1426 if (rflags && !pool_intersect_evrs(pool, rd->flags, rd->evr, rflags, revr))
1430 return matchdep_str(rname, pool_id2str(pool, id), flags);
1434 selection_make_matchdeps_common_limited(Pool *pool, Queue *selection, const char *name, Id dep, int flags, int keyname, int marker, struct limiter *limiter)
1438 char *rname = 0, *r = 0;
1444 queue_empty(selection);
1452 if ((flags & SELECTION_MATCH_DEPSTR) != 0)
1453 flags &= ~SELECTION_REL;
1457 rname = solv_strdup(name);
1458 if ((flags & SELECTION_REL) != 0)
1460 if ((r = strpbrk(rname, "<=>")) != 0)
1462 if ((r = splitrel(rname, r, &rflags)) == 0)
1468 revr = pool_str2id(pool, r, 1);
1469 ret |= SELECTION_REL;
1471 if ((flags & SELECTION_GLOB) != 0 && !strpbrk(rname, "[*?") != 0)
1472 flags &= ~SELECTION_GLOB;
1474 if ((flags & SELECTION_GLOB) == 0 && (flags & SELECTION_NOCASE) == 0 && (flags & SELECTION_MATCH_DEPSTR) == 0)
1476 /* we can use the faster selection_make_matchdepid */
1477 dep = pool_str2id(pool, rname, 1);
1479 dep = pool_rel2id(pool, dep, revr, rflags, 1);
1480 rname = solv_free(rname);
1486 if (keyname == SOLVABLE_NAME && (flags & SELECTION_MATCH_DEPSTR) != 0)
1491 rd = GETRELDEP(pool, dep);
1492 if (!rd->name || rd->flags != REL_EQ)
1501 for (li = limiter->start; li < limiter->end; li++)
1504 p = limiter->mapper ? limiter->mapper[li] : li;
1505 s = pool->solvables + p;
1506 if (!s->repo || (limiter->repofilter && s->repo != limiter->repofilter))
1508 if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
1510 if (!(flags & SELECTION_SOURCE_ONLY) && !(flags & SELECTION_WITH_SOURCE))
1512 if (!(flags & SELECTION_WITH_DISABLED) && pool_disabled_solvable(pool, s))
1517 if ((flags & SELECTION_SOURCE_ONLY) != 0)
1519 if (s->repo != pool->installed)
1521 if (!(flags & SELECTION_WITH_DISABLED) && pool_disabled_solvable(pool, s))
1523 if (!(flags & SELECTION_WITH_BADARCH) && pool_badarch_solvable(pool, s))
1527 if (keyname == SOLVABLE_NAME) /* nevr match hack */
1531 if ((flags & SELECTION_MATCH_DEPSTR) != 0)
1533 if (s->name != dep || s->evr != revr)
1538 if (!pool_match_nevr(pool, s, dep))
1544 if ((flags & SELECTION_MATCH_DEPSTR) != 0) /* mis-use */
1546 char *tmp = pool_tmpjoin(pool, pool_id2str(pool, s->name), " = ", pool_id2str(pool, s->evr));
1547 if (!matchdep_str(rname, tmp, flags))
1552 if (!matchdep(pool, s->name, rname, rflags, revr, flags))
1554 if (rflags && !pool_intersect_evrs(pool, rflags, revr, REL_EQ, s->evr))
1558 queue_push(selection, p);
1562 repo_lookup_deparray(s->repo, p, keyname, &q, marker);
1567 if ((flags & SELECTION_MATCH_DEPSTR) != 0) /* mis-use */
1569 for (i = 0; i < q.count; i++)
1570 if (q.elements[i] == dep)
1575 for (i = 0; i < q.count; i++)
1576 if (pool_match_dep(pool, q.elements[i], dep))
1582 if ((flags & SELECTION_MATCH_DEPSTR) != 0)
1584 for (i = 0; i < q.count; i++)
1585 if (matchdep_str(rname, pool_dep2str(pool, q.elements[i]), flags))
1590 for (i = 0; i < q.count; i++)
1591 if (matchdep(pool, q.elements[i], rname, rflags, revr, flags))
1596 queue_push(selection, p);
1600 if (!selection->count)
1603 /* convert package list to selection */
1604 j = selection->count;
1605 queue_insertn(selection, 0, selection->count, 0);
1606 for (i = 0; i < selection->count; )
1608 selection->elements[i++] = SOLVER_SOLVABLE | SOLVER_NOAUTOSET;
1609 selection->elements[i++] = selection->elements[j++];
1612 if ((flags & SELECTION_FLAT) != 0)
1613 selection_flatten(pool, selection);
1614 return ret | (keyname == SOLVABLE_NAME ? SELECTION_NAME : SELECTION_PROVIDES);
1618 selection_make_matchdeps_common(Pool *pool, Queue *selection, const char *name, Id dep, int flags, int keyname, int marker)
1620 struct limiter limiter;
1622 setup_limiter(pool, flags, &limiter);
1623 if ((flags & SELECTION_MODEBITS) != SELECTION_REPLACE)
1628 queue_init(&qlimit);
1629 /* deal with special filter cases */
1630 if ((flags & SELECTION_MODEBITS) == SELECTION_FILTER && selection->count == 2 && limiter.end)
1632 if ((selection->elements[0] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_ALL)
1633 flags = (flags & ~SELECTION_MODEBITS) | SELECTION_REPLACE;
1634 else if ((selection->elements[0] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_REPO)
1636 Repo *repo = pool_id2repo(pool, selection->elements[1]);
1637 if (limiter.repofilter && repo != limiter.repofilter)
1639 limiter.repofilter = repo;
1640 limiter.start = repo ? repo->start : 0;
1641 limiter.end = repo ? repo->end : 0;
1642 flags = (flags & ~SELECTION_MODEBITS) | SELECTION_REPLACE;
1645 if (limiter.end && ((flags & SELECTION_MODEBITS) == SELECTION_SUBTRACT || (flags & SELECTION_MODEBITS) == SELECTION_FILTER))
1647 selection_solvables(pool, selection, &qlimit);
1649 limiter.end = qlimit.count;
1650 limiter.mapper = qlimit.elements;
1652 ret = selection_make_matchdeps_common_limited(pool, &q, name, dep, flags & ~SELECTION_MODEBITS, keyname, marker, &limiter);
1653 queue_free(&qlimit);
1654 if ((flags & SELECTION_MODEBITS) == SELECTION_ADD)
1655 selection_add(pool, selection, &q);
1656 else if ((flags & SELECTION_MODEBITS) == SELECTION_SUBTRACT)
1657 selection_subtract(pool, selection, &q);
1658 else if ((flags & SELECTION_MODEBITS) == SELECTION_FILTER)
1660 if (ret || !(flags & SELECTION_FILTER_KEEP_IFEMPTY))
1662 if ((flags & SELECTION_FILTER_SWAPPED) != 0)
1664 selection_filter(pool, &q, selection);
1665 queue_free(selection);
1666 queue_init_clone(selection, &q);
1669 selection_filter(pool, selection, &q);
1672 else if (ret || !(flags & SELECTION_FILTER_KEEP_IFEMPTY))
1674 /* special filter case from above */
1676 Id f = selection->elements[0] & ~(SOLVER_SELECTMASK|SOLVER_NOAUTOSET); /* job, jobflags, setflags */
1677 queue_free(selection);
1678 queue_init_clone(selection, &q);
1679 for (i = 0; i < selection->count; i += 2)
1680 selection->elements[i] = (selection->elements[i] & (SOLVER_SELECTMASK | SOLVER_SETMASK)) | f;
1685 return selection_make_matchdeps_common_limited(pool, selection, name, dep, flags, keyname, marker, &limiter);
1689 * select against the dependencies in keyname
1690 * like SELECTION_PROVIDES, but with the deps in keyname instead of provides.
1691 * supported match modifiers:
1697 selection_make_matchdeps(Pool *pool, Queue *selection, const char *name, int flags, int keyname, int marker)
1699 return selection_make_matchdeps_common(pool, selection, name, 0, flags, keyname, marker);
1703 * select against the dependency id in keyname
1706 selection_make_matchdepid(Pool *pool, Queue *selection, Id dep, int flags, int keyname, int marker)
1708 return selection_make_matchdeps_common(pool, selection, 0, dep, flags, keyname, marker);
1712 pool_is_kind(Pool *pool, Id name, Id kind)
1717 n = pool_id2str(pool, name);
1720 const char *kn = pool_id2str(pool, kind);
1721 int knl = strlen(kn);
1722 return !strncmp(n, kn, knl) && n[knl] == ':' ? 1 : 0;
1728 while(*n >= 'a' && *n <= 'z')
1730 return *n == ':' ? 0 : 1;
1735 selection_filter_map(Pool *pool, Queue *sel, Map *m, int setflags)
1742 for (i = j = 0; i < sel->count; i += 2)
1744 Id select = sel->elements[i] & SOLVER_SELECTMASK;
1747 if (select == SOLVER_SOLVABLE_ALL)
1749 FOR_POOL_SOLVABLES(p)
1757 else if (select == SOLVER_SOLVABLE_REPO)
1760 Repo *repo = pool_id2repo(pool, sel->elements[i + 1]);
1763 FOR_REPO_SOLVABLES(repo, p, s)
1774 FOR_JOB_SELECT(p, pp, select, sel->elements[i + 1])
1777 queue_pushunique(&q, p);
1786 sel->elements[j] = sel->elements[i] | setflags;
1787 sel->elements[j + 1] = sel->elements[i + 1];
1789 else if (q.count > 1)
1791 sel->elements[j] = (sel->elements[i] & ~SOLVER_SELECTMASK) | SOLVER_SOLVABLE_ONE_OF | setflags;
1792 sel->elements[j + 1] = pool_queuetowhatprovides(pool, &q);
1796 sel->elements[j] = (sel->elements[i] & ~SOLVER_SELECTMASK) | SOLVER_SOLVABLE | SOLVER_NOAUTOSET | setflags;
1797 sel->elements[j + 1] = q.elements[0];
1801 queue_truncate(sel, j);
1806 selection_filter_int(Pool *pool, Queue *sel1, Queue *sel2, int invert)
1809 Id p, pp, q1filled = 0;
1814 if (!sel1->count || !sel2->count)
1816 if (invert && !sel2->count)
1821 if (sel1->count == 2 && (sel1->elements[0] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_ALL && !invert)
1823 /* XXX: not 100% correct, but very useful */
1824 p = sel1->elements[0] & ~(SOLVER_SELECTMASK | SOLVER_SETMASK); /* job & jobflags */
1826 queue_init_clone(sel1, sel2);
1827 for (i = 0; i < sel1->count; i += 2)
1828 sel1->elements[i] = (sel1->elements[i] & (SOLVER_SELECTMASK | SOLVER_SETMASK)) | p ;
1832 /* convert sel2 into a map */
1834 map_init(&m2, pool->nsolvables);
1835 for (i = 0; i < sel2->count; i += 2)
1837 Id select = sel2->elements[i] & SOLVER_SELECTMASK;
1838 if (select == SOLVER_SOLVABLE_ALL)
1846 if (select == SOLVER_SOLVABLE_REPO)
1849 Repo *repo = pool_id2repo(pool, sel2->elements[i + 1]);
1852 FOR_REPO_SOLVABLES(repo, p, s)
1858 if ((select == SOLVER_SOLVABLE_NAME || select == SOLVER_SOLVABLE_PROVIDES) && ISRELDEP(sel2->elements[i + 1]))
1860 Reldep *rd = GETRELDEP(pool, sel2->elements[i + 1]);
1861 if (rd->flags == REL_ARCH && rd->name == 0)
1863 /* special arch filter */
1865 selection_solvables(pool, sel1, &q1);
1866 for (j = 0; j < q1.count; j++)
1868 Id p = q1.elements[j];
1869 Solvable *s = pool->solvables + p;
1870 if (s->arch == rd->evr || (rd->evr == ARCH_SRC && s->arch == ARCH_NOSRC))
1875 else if (rd->flags == REL_KIND && rd->name == 0)
1877 /* special kind filter */
1879 selection_solvables(pool, sel1, &q1);
1880 for (j = 0; j < q1.count; j++)
1882 Id p = q1.elements[j];
1883 Solvable *s = pool->solvables + p;
1884 if (pool_is_kind(pool, s->name, rd->evr))
1890 FOR_JOB_SELECT(p, pp, select, sel2->elements[i + 1])
1896 /* now filter sel1 with the map */
1899 if (sel2->count == 2)
1900 setflags = sel2->elements[0] & SOLVER_SETMASK & ~SOLVER_NOAUTOSET;
1901 selection_filter_map(pool, sel1, &m2, setflags);
1906 selection_filter(Pool *pool, Queue *sel1, Queue *sel2)
1908 selection_filter_int(pool, sel1, sel2, 0);
1912 selection_add(Pool *pool, Queue *sel1, Queue *sel2)
1915 queue_insertn(sel1, sel1->count, sel2->count, sel2->elements);
1919 selection_subtract(Pool *pool, Queue *sel1, Queue *sel2)
1921 selection_filter_int(pool, sel1, sel2, 1);
1925 pool_selection2str(Pool *pool, Queue *selection, Id flagmask)
1930 s = pool_tmpjoin(pool, 0, 0, 0);
1931 for (i = 0; i < selection->count; i += 2)
1933 Id how = selection->elements[i];
1935 s = pool_tmpappend(pool, s, " + ", 0);
1936 s2 = solver_select2str(pool, how & SOLVER_SELECTMASK, selection->elements[i + 1]);
1937 s = pool_tmpappend(pool, s, s2, 0);
1938 pool_freetmpspace(pool, s2);
1939 how &= flagmask & SOLVER_SETMASK;
1943 s = pool_tmpappend(pool, s, " ", 0);
1944 if (how & SOLVER_SETEV)
1945 s = pool_tmpappend(pool, s, ",setev", 0);
1946 if (how & SOLVER_SETEVR)
1947 s = pool_tmpappend(pool, s, ",setevr", 0);
1948 if (how & SOLVER_SETARCH)
1949 s = pool_tmpappend(pool, s, ",setarch", 0);
1950 if (how & SOLVER_SETVENDOR)
1951 s = pool_tmpappend(pool, s, ",setvendor", 0);
1952 if (how & SOLVER_SETREPO)
1953 s = pool_tmpappend(pool, s, ",setrepo", 0);
1954 if (how & SOLVER_NOAUTOSET)
1955 s = pool_tmpappend(pool, s, ",noautoset", 0);
1956 if (s[o + 1] != ',')
1957 s = pool_tmpappend(pool, s, ",?", 0);
1959 s = pool_tmpappend(pool, s, "]", 0);