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 && (id > pool->lastarch || !pool->id2arch[id]))
41 selection_prune(Pool *pool, Queue *selection)
45 for (i = j = 0; i < selection->count; i += 2)
47 Id select = selection->elements[i] & SOLVER_SELECTMASK;
49 if (select == SOLVER_SOLVABLE_ALL)
51 else if (select == SOLVER_SOLVABLE_REPO)
54 Repo *repo = pool_id2repo(pool, selection->elements[i + 1]);
57 FOR_REPO_SOLVABLES(repo, p, s)
63 FOR_JOB_SELECT(p, pp, select, selection->elements[i + 1])
68 selection->elements[j] = selection->elements[i];
69 selection->elements[j + 1] = selection->elements[i + 1];
72 queue_truncate(selection, j);
77 selection_solvables_sortcmp(const void *ap, const void *bp, void *dp)
79 return *(const Id *)ap - *(const Id *)bp;
83 selection_solvables(Pool *pool, Queue *selection, Queue *pkgs)
88 for (i = 0; i < selection->count; i += 2)
90 Id select = selection->elements[i] & SOLVER_SELECTMASK;
91 if (select == SOLVER_SOLVABLE_ALL)
96 if (select == SOLVER_SOLVABLE_REPO)
99 Repo *repo = pool_id2repo(pool, selection->elements[i + 1]);
102 FOR_REPO_SOLVABLES(repo, p, s)
108 FOR_JOB_SELECT(p, pp, select, selection->elements[i + 1])
115 solv_sort(pkgs->elements, pkgs->count, sizeof(Id), selection_solvables_sortcmp, NULL);
116 lastid = pkgs->elements[0];
117 for (i = j = 1; i < pkgs->count; i++)
118 if (pkgs->elements[i] != lastid)
119 pkgs->elements[j++] = lastid = pkgs->elements[i];
120 queue_truncate(pkgs, j);
124 selection_flatten(Pool *pool, Queue *selection)
128 if (selection->count <= 2)
130 for (i = 0; i < selection->count; i += 2)
131 if ((selection->elements[i] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_ALL)
133 selection->elements[0] = selection->elements[i];
134 selection->elements[1] = selection->elements[i + 1];
135 queue_truncate(selection, 2);
139 selection_solvables(pool, selection, &q);
142 queue_empty(selection);
145 queue_truncate(selection, 2);
148 selection->elements[0] = SOLVER_SOLVABLE_ONE_OF;
149 selection->elements[1] = pool_queuetowhatprovides(pool, &q);
153 selection->elements[0] = SOLVER_SOLVABLE | SOLVER_NOAUTOSET;
154 selection->elements[1] = q.elements[0];
159 selection_filter_rel(Pool *pool, Queue *selection, Id relflags, Id relevr)
163 for (i = 0; i < selection->count; i += 2)
165 Id select = selection->elements[i] & SOLVER_SELECTMASK;
166 Id id = selection->elements[i + 1];
167 if (select == SOLVER_SOLVABLE || select == SOLVER_SOLVABLE_ONE_OF)
169 /* done by selection_addsrc, currently implies SELECTION_NAME */
172 Id rel = 0, relname = 0;
176 FOR_JOB_SELECT(p, pp, select, id)
178 Solvable *s = pool->solvables + p;
179 if (!rel || s->name != relname)
182 rel = pool_rel2id(pool, relname, relevr, relflags, 1);
184 if (pool_match_nevr(pool, s, rel))
193 selection->elements[i] = SOLVER_SOLVABLE | SOLVER_NOAUTOSET;
194 selection->elements[i + 1] = q.elements[0];
198 selection->elements[i] = SOLVER_SOLVABLE_ONE_OF;
199 selection->elements[i + 1] = pool_queuetowhatprovides(pool, &q);
204 else if (select == SOLVER_SOLVABLE_NAME || select == SOLVER_SOLVABLE_PROVIDES)
206 /* don't stack src reldeps */
207 if (relflags == REL_ARCH && (relevr == ARCH_SRC || relevr == ARCH_NOSRC) && ISRELDEP(id))
209 Reldep *rd = GETRELDEP(pool, id);
210 if (rd->flags == REL_ARCH && rd->evr == ARCH_SRC)
213 selection->elements[i + 1] = pool_rel2id(pool, id, relevr, relflags, 1);
216 continue; /* actually internal error */
217 if (relflags == REL_ARCH)
218 selection->elements[i] |= SOLVER_SETARCH;
219 if (relflags == REL_EQ && select != SOLVER_SOLVABLE_PROVIDES)
221 if (pool->disttype == DISTTYPE_DEB)
222 selection->elements[i] |= SOLVER_SETEVR; /* debian can't match version only like rpm */
225 const char *rel = strrchr(pool_id2str(pool, relevr), '-');
226 selection->elements[i] |= rel ? SOLVER_SETEVR : SOLVER_SETEV;
230 selection_prune(pool, selection);
234 selection_filter_installed(Pool *pool, Queue *selection)
239 if (!pool->installed)
240 queue_empty(selection);
242 for (i = j = 0; i < selection->count; i += 2)
244 Id select = selection->elements[i] & SOLVER_SELECTMASK;
245 Id id = selection->elements[i + 1];
246 if (select == SOLVER_SOLVABLE_ALL)
248 select = SOLVER_SOLVABLE_REPO;
249 id = pool->installed->repoid;
251 else if (select == SOLVER_SOLVABLE_REPO)
253 if (id != pool->installed->repoid)
261 FOR_JOB_SELECT(p, pp, select, id)
263 if (pool->solvables[p].repo != pool->installed)
272 else if (q.count == 1)
274 select = SOLVER_SOLVABLE | SOLVER_NOAUTOSET;
279 select = SOLVER_SOLVABLE_ONE_OF;
280 id = pool_queuetowhatprovides(pool, &q);
286 selection->elements[j++] = select | (selection->elements[i] & ~SOLVER_SELECTMASK) | SOLVER_SETREPO;
287 selection->elements[j++] = id;
290 queue_truncate(selection, j);
295 selection_addsrc(Pool *pool, Queue *selection, int flags)
301 if ((flags & SELECTION_INSTALLED_ONLY) != 0)
302 return; /* sources can't be installed */
304 for (i = 0; i < selection->count; i += 2)
306 if (selection->elements[i] != SOLVER_SOLVABLE_NAME)
308 name = selection->elements[i + 1];
311 FOR_POOL_SOLVABLES(p)
313 Solvable *s = pool->solvables + p;
316 if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
318 if (pool_disabled_solvable(pool, s))
322 else if (s->repo != pool->installed && !pool_installable(pool, s))
326 if (!havesrc || !q.count)
330 selection->elements[i] = SOLVER_SOLVABLE | SOLVER_NOAUTOSET;
331 selection->elements[i + 1] = q.elements[0];
335 selection->elements[i] = SOLVER_SOLVABLE_ONE_OF;
336 selection->elements[i + 1] = pool_queuetowhatprovides(pool, &q);
342 static inline const char *
343 skipkind(const char *n)
346 for (s = n; *s >= 'a' && *s <= 'z'; s++)
348 if (*s == ':' && s != n)
354 queue_pushunique2(Queue *q, Id id1, Id id2)
357 for (i = 0; i < q->count; i += 2)
358 if (q->elements[i] == id1 && q->elements[i + 1] == id2)
360 queue_push2(q, id1, id2);
364 selection_depglob_id(Pool *pool, Queue *selection, Id id, int flags)
369 FOR_PROVIDES(p, pp, id)
371 Solvable *s = pool->solvables + p;
372 if ((flags & SELECTION_INSTALLED_ONLY) != 0 && s->repo != pool->installed)
375 if (s->name == id && (flags & SELECTION_NAME) != 0)
377 if ((flags & SELECTION_SOURCE_ONLY) != 0)
378 id = pool_rel2id(pool, id, ARCH_SRC, REL_ARCH, 1);
379 queue_push2(selection, SOLVER_SOLVABLE_NAME, id);
380 if ((flags & SELECTION_WITH_SOURCE) != 0)
381 selection_addsrc(pool, selection, flags);
382 return SELECTION_NAME;
385 if ((flags & (SELECTION_SOURCE_ONLY | SELECTION_WITH_SOURCE)) != 0 && (flags & SELECTION_NAME) != 0)
387 /* src rpms don't have provides, so we must check every solvable */
388 FOR_POOL_SOLVABLES(p) /* slow path */
390 Solvable *s = pool->solvables + p;
391 if (s->name == id && (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC))
393 if ((flags & SELECTION_INSTALLED_ONLY) != 0 && s->repo != pool->installed)
394 continue; /* just in case... src rpms can't be installed */
395 if (pool_disabled_solvable(pool, s))
397 if ((flags & SELECTION_SOURCE_ONLY) != 0)
398 id = pool_rel2id(pool, id, ARCH_SRC, REL_ARCH, 1);
399 queue_push2(selection, SOLVER_SOLVABLE_NAME, id);
400 if ((flags & SELECTION_WITH_SOURCE) != 0)
401 selection_addsrc(pool, selection, flags);
402 return SELECTION_NAME;
406 if (match && (flags & SELECTION_PROVIDES) != 0)
408 queue_push2(selection, SOLVER_SOLVABLE_PROVIDES, id);
409 return SELECTION_PROVIDES;
415 selection_depglob(Pool *pool, Queue *selection, const char *name, int flags)
423 if ((flags & SELECTION_SOURCE_ONLY) != 0)
425 flags &= ~SELECTION_PROVIDES; /* sources don't provide anything */
426 flags &= ~SELECTION_WITH_SOURCE;
429 if (!(flags & (SELECTION_NAME|SELECTION_PROVIDES)))
432 if ((flags & SELECTION_INSTALLED_ONLY) != 0 && !pool->installed)
435 nocase = flags & SELECTION_NOCASE;
436 if (!nocase && !(flags & SELECTION_SKIP_KIND))
438 id = pool_str2id(pool, name, 0);
441 /* the id is know, do the fast id matching using the whatprovides lookup */
442 int ret = selection_depglob_id(pool, selection, id, flags);
448 if ((flags & SELECTION_GLOB) != 0 && strpbrk(name, "[*?") != 0)
451 if (!nocase && !(flags & SELECTION_SKIP_KIND) && !doglob)
452 return 0; /* all done above in depglob_id */
454 if (doglob && nocase)
455 globflags = FNM_CASEFOLD;
457 if ((flags & SELECTION_NAME) != 0)
459 /* looks like a name glob. hard work. */
460 FOR_POOL_SOLVABLES(p)
462 Solvable *s = pool->solvables + p;
464 if (s->repo != pool->installed && !pool_installable(pool, s))
466 if (!(flags & SELECTION_SOURCE_ONLY) || (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC))
468 if (pool_disabled_solvable(pool, s))
471 if ((flags & SELECTION_INSTALLED_ONLY) != 0 && s->repo != pool->installed)
474 n = pool_id2str(pool, id);
475 if (flags & SELECTION_SKIP_KIND)
477 if ((doglob ? fnmatch(name, n, globflags) : nocase ? strcasecmp(name, n) : strcmp(name, n)) == 0)
479 if ((flags & SELECTION_SOURCE_ONLY) != 0)
480 id = pool_rel2id(pool, id, ARCH_SRC, REL_ARCH, 1);
481 queue_pushunique2(selection, SOLVER_SOLVABLE_NAME, id);
487 if ((flags & SELECTION_WITH_SOURCE) != 0)
488 selection_addsrc(pool, selection, flags);
489 return SELECTION_NAME;
493 if ((flags & SELECTION_PROVIDES))
495 /* looks like a dep glob. really hard work. */
496 for (id = 1; id < pool->ss.nstrings; id++)
499 if (!pool->whatprovides[id] || pool->whatprovides[id] == 1)
501 n = pool_id2str(pool, id);
502 if ((doglob ? fnmatch(name, n, globflags) : nocase ? strcasecmp(name, n) : strcmp(name, n)) == 0)
504 if ((flags & SELECTION_INSTALLED_ONLY) != 0)
506 FOR_PROVIDES(p, pp, id)
507 if (pool->solvables[p].repo == pool->installed)
512 queue_push2(selection, SOLVER_SOLVABLE_PROVIDES, id);
517 return SELECTION_PROVIDES;
523 selection_depglob_arch(Pool *pool, Queue *selection, const char *name, int flags)
529 if ((ret = selection_depglob(pool, selection, name, flags)) != 0)
531 if (!(flags & SELECTION_DOTARCH))
533 /* check if there is an .arch suffix */
534 if ((r = strrchr(name, '.')) != 0 && r[1] && (archid = str2archid(pool, r + 1)) != 0)
536 char *rname = solv_strdup(name);
538 if (archid == ARCH_SRC || archid == ARCH_NOSRC)
539 flags |= SELECTION_SOURCE_ONLY;
540 if ((ret = selection_depglob(pool, selection, rname, flags)) != 0)
542 selection_filter_rel(pool, selection, REL_ARCH, archid);
544 return ret | SELECTION_DOTARCH;
552 selection_filelist(Pool *pool, Queue *selection, const char *name, int flags)
558 /* all files in the file list start with a '/' */
561 if (!(flags & SELECTION_GLOB))
563 if (*name != '*' && *name != '[' && *name != '?')
566 type = !(flags & SELECTION_GLOB) || strpbrk(name, "[*?") == 0 ? SEARCH_STRING : SEARCH_GLOB;
567 if ((flags & SELECTION_NOCASE) != 0)
568 type |= SEARCH_NOCASE;
570 dataiterator_init(&di, pool, flags & SELECTION_INSTALLED_ONLY ? pool->installed : 0, 0, SOLVABLE_FILELIST, name, type|SEARCH_FILES|SEARCH_COMPLETE_FILELIST);
571 while (dataiterator_step(&di))
573 Solvable *s = pool->solvables + di.solvid;
576 if (s->repo != pool->installed && !pool_installable(pool, s))
578 if (!(flags & SELECTION_SOURCE_ONLY) || (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC))
580 if (pool_disabled_solvable(pool, s))
583 if ((flags & SELECTION_INSTALLED_ONLY) != 0 && s->repo != pool->installed)
585 queue_push(&q, di.solvid);
586 dataiterator_skip_solvable(&di);
588 dataiterator_free(&di);
592 queue_push2(selection, SOLVER_SOLVABLE_ONE_OF, pool_queuetowhatprovides(pool, &q));
594 queue_push2(selection, SOLVER_SOLVABLE | SOLVER_NOAUTOSET, q.elements[0]);
596 return SELECTION_FILELIST;
600 splitrel(char *rname, char *r, int *rflagsp)
602 int nend = r - rname;
604 if (nend && *r == '=' && r[-1] == '!')
608 rflags = REL_LT|REL_GT;
621 while (*r && (*r == ' ' || *r == '\t'))
623 while (nend && (rname[nend - 1] == ' ' || rname[nend - 1] == '\t'))
633 selection_rel(Pool *pool, Queue *selection, const char *name, int flags)
638 /* relation case, support:
642 rname = solv_strdup(name);
643 if ((r = strpbrk(rname, "<=>")) != 0)
645 if ((r = splitrel(rname, r, &rflags)) == 0)
651 if ((ret = selection_depglob_arch(pool, selection, rname, flags)) != 0)
654 selection_filter_rel(pool, selection, rflags, pool_str2id(pool, r, 1));
656 return ret | SELECTION_REL;
662 #if defined(MULTI_SEMANTICS)
663 # define EVRCMP_DEPCMP (pool->disttype == DISTTYPE_DEB ? EVRCMP_COMPARE : EVRCMP_MATCH_RELEASE)
664 #elif defined(DEBIAN)
665 # define EVRCMP_DEPCMP EVRCMP_COMPARE
667 # define EVRCMP_DEPCMP EVRCMP_MATCH_RELEASE
670 /* magic epoch promotion code, works only for SELECTION_NAME selections */
672 selection_filter_evr(Pool *pool, Queue *selection, char *evr)
679 queue_init_buffer(&q, qbuf, sizeof(qbuf)/sizeof(*qbuf));
680 for (i = j = 0; i < selection->count; i += 2)
682 Id select = selection->elements[i] & SOLVER_SELECTMASK;
683 Id id = selection->elements[i + 1];
685 const char *lastepoch = 0;
686 int lastepochlen = 0;
689 FOR_JOB_SELECT(p, pp, select, id)
691 Solvable *s = pool->solvables + p;
692 const char *sevr = pool_id2str(pool, s->evr);
694 for (sp = sevr; *sp >= '0' && *sp <= '9'; sp++)
698 /* compare vr part */
699 if (strcmp(evr, sp != sevr ? sp + 1 : sevr) != 0)
701 int r = pool_evrcmp_str(pool, sp != sevr ? sp + 1 : sevr, evr, EVRCMP_DEPCMP);
702 if (r == -1 || r == 1)
703 continue; /* solvable does not match vr */
708 while (sevr < sp && *sevr == '0') /* normalize epoch */
714 lastepochlen = sp - sevr;
716 else if (lastepochlen != sp - sevr || strncmp(lastepoch, sevr, lastepochlen) != 0)
717 lastepochlen = -1; /* multiple different epochs */
719 if (!lastepoch || lastepochlen == 0)
720 id = pool_str2id(pool, evr, 1); /* no match at all or zero epoch */
721 else if (lastepochlen >= 0)
723 /* found exactly one epoch, simply prepend */
724 char *evrx = solv_malloc(strlen(evr) + lastepochlen + 2);
725 strncpy(evrx, lastepoch, lastepochlen + 1);
726 strcpy(evrx + lastepochlen + 1, evr);
727 id = pool_str2id(pool, evrx, 1);
732 /* multiple epochs in multiple solvables, convert to list of solvables */
733 selection->elements[j] = (selection->elements[i] & ~SOLVER_SELECTMASK) | SOLVER_SOLVABLE_ONE_OF;
734 selection->elements[j + 1] = pool_queuetowhatprovides(pool, &q);
739 queue_push2(&q, selection->elements[i], selection->elements[i + 1]);
740 selection_filter_rel(pool, &q, REL_EQ, id);
742 continue; /* oops, no match */
743 selection->elements[j] = q.elements[0];
744 selection->elements[j + 1] = q.elements[1];
747 queue_truncate(selection, j);
751 /* match the "canonical" name of the package */
753 selection_canon(Pool *pool, Queue *selection, const char *name, int flags)
755 char *rname, *r, *r2;
761 * nameglob-version.arch
762 * nameglob-version-release
763 * nameglob-version-release.arch
765 flags |= SELECTION_NAME;
766 flags &= ~SELECTION_PROVIDES;
768 if (pool->disttype == DISTTYPE_DEB)
770 if ((r = strchr(name, '_')) == 0)
772 rname = solv_strdup(name); /* so we can modify it */
773 r = rname + (r - name);
775 if ((ret = selection_depglob(pool, selection, rname, flags)) == 0)
780 /* is there a vaild arch? */
781 if ((r2 = strrchr(r, '_')) != 0 && r[1] && (archid = str2archid(pool, r + 1)) != 0)
783 *r2 = 0; /* split off */
784 selection_filter_rel(pool, selection, REL_ARCH, archid);
786 selection_filter_rel(pool, selection, REL_EQ, pool_str2id(pool, r, 1));
788 return ret | SELECTION_CANON;
791 if (pool->disttype == DISTTYPE_HAIKU)
793 if ((r = strchr(name, '-')) == 0)
795 rname = solv_strdup(name); /* so we can modify it */
796 r = rname + (r - name);
798 if ((ret = selection_depglob(pool, selection, rname, flags)) == 0)
803 /* is there a vaild arch? */
804 if ((r2 = strrchr(r, '-')) != 0 && r[1] && (archid = str2archid(pool, r + 1)) != 0)
806 *r2 = 0; /* split off */
807 selection_filter_rel(pool, selection, REL_ARCH, archid);
809 selection_filter_rel(pool, selection, REL_EQ, pool_str2id(pool, r, 1));
811 return ret | SELECTION_CANON;
814 if ((r = strrchr(name, '-')) == 0)
816 rname = solv_strdup(name); /* so we can modify it */
817 r = rname + (r - name);
820 /* split off potential arch part from version */
821 if ((r2 = strrchr(r + 1, '.')) != 0 && r2[1] && (archid = str2archid(pool, r2 + 1)) != 0)
822 *r2 = 0; /* found valid arch, split it off */
823 if (archid == ARCH_SRC || archid == ARCH_NOSRC)
824 flags |= SELECTION_SOURCE_ONLY;
826 /* try with just the version */
827 if ((ret = selection_depglob(pool, selection, rname, flags)) == 0)
829 /* no luck, try with version-release */
830 if ((r2 = strrchr(rname, '-')) == 0)
838 if ((ret = selection_depglob(pool, selection, rname, flags)) == 0)
845 selection_filter_rel(pool, selection, REL_ARCH, archid);
846 selection_filter_evr(pool, selection, r + 1); /* magic epoch promotion */
848 return ret | SELECTION_CANON;
852 selection_make(Pool *pool, Queue *selection, const char *name, int flags)
856 queue_empty(selection);
857 if ((flags & SELECTION_FILELIST) != 0)
858 ret = selection_filelist(pool, selection, name, flags);
859 if (!ret && (flags & SELECTION_REL) != 0 && strpbrk(name, "<=>") != 0)
860 ret = selection_rel(pool, selection, name, flags);
862 ret = selection_depglob_arch(pool, selection, name, flags);
863 if (!ret && (flags & SELECTION_CANON) != 0)
864 ret = selection_canon(pool, selection, name, flags);
865 if (selection->count && (flags & SELECTION_INSTALLED_ONLY) != 0)
866 selection_filter_installed(pool, selection);
867 if (ret && !selection->count)
868 ret = 0; /* no match -> always return zero */
869 if (ret && (flags & SELECTION_FLAT) != 0)
870 selection_flatten(pool, selection);
875 matchdep_str(const char *pattern, const char *string, int flags)
877 if (flags & SELECTION_GLOB)
879 int globflags = (flags & SELECTION_NOCASE) != 0 ? FNM_CASEFOLD : 0;
880 return fnmatch(pattern, string, globflags) == 0 ? 1 : 0;
882 if (flags & SELECTION_NOCASE)
883 return strcasecmp(pattern, string) == 0 ? 1 : 0;
884 return strcmp(pattern, string) == 0 ? 1 : 0;
888 matchdep(Pool *pool, Id id, char *rname, int rflags, char *revr, int flags)
892 Reldep *rd = GETRELDEP(pool, id);
893 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)
895 if (matchdep(pool, rd->name, rname, rflags, revr, flags))
897 if ((rd->flags == REL_COND || rd->flags == REL_UNLESS) && ISRELDEP(rd->evr))
899 rd = GETRELDEP(pool, rd->evr);
900 if (rd->flags != REL_ELSE)
903 if (rd->flags != REL_COND && rd->flags != REL_UNLESS && rd->flags != REL_WITHOUT && matchdep(pool, rd->evr, rname, rflags, revr, flags))
907 if (rd->flags == REL_ARCH)
908 return matchdep(pool, rd->name, rname, rflags, revr, flags);
909 if (!matchdep(pool, rd->name, rname, rflags, revr, flags))
913 /* XXX: need pool_match_flags_evr here */
914 if (!pool_match_dep(pool, pool_rel2id(pool, rd->name, pool_str2id(pool, revr, 1), rflags, 1), id))
919 return matchdep_str(rname, pool_id2str(pool, id), flags);
923 * select against the dependencies in keyname
924 * like SELECTION_REL and SELECTION_PROVIDES, but with the
925 * deps in keyname instead of provides.
928 selection_make_matchdeps(Pool *pool, Queue *selection, const char *name, int flags, int keyname, int marker)
935 queue_empty(selection);
936 rname = solv_strdup(name);
937 if (!(flags & SELECTION_MATCH_DEPSTR))
939 if ((r = strpbrk(rname, "<=>")) != 0)
941 if ((r = splitrel(rname, r, &rflags)) == 0)
948 if ((flags & SELECTION_GLOB) != 0 && !strpbrk(rname, "[*?") != 0)
949 flags &= ~SELECTION_GLOB;
952 FOR_POOL_SOLVABLES(p)
954 Solvable *s = pool->solvables + p;
957 if (s->repo != pool->installed && !pool_installable(pool, s))
959 if (!(flags & SELECTION_SOURCE_ONLY) || (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC))
961 if (pool_disabled_solvable(pool, s))
964 if ((flags & SELECTION_INSTALLED_ONLY) != 0 && s->repo != pool->installed)
966 if ((s->arch == ARCH_SRC || s->arch == ARCH_NOSRC) && !(flags & SELECTION_SOURCE_ONLY) && !(flags & SELECTION_WITH_SOURCE))
969 repo_lookup_deparray(s->repo, p, keyname, &q, marker);
970 for (i = 0; i < q.count; i++)
972 Id id = q.elements[i];
973 if ((flags & SELECTION_MATCH_DEPSTR) != 0)
975 if (matchdep_str(rname, pool_dep2str(pool, id), flags))
979 if (matchdep(pool, id, rname, rflags, r, flags))
983 queue_push2(selection, SOLVER_SOLVABLE | SOLVER_NOAUTOSET, p);
987 if (!selection->count)
989 if ((flags & SELECTION_FLAT) != 0)
990 selection_flatten(pool, selection);
991 return SELECTION_PROVIDES;
995 selection_make_matchdepid(Pool *pool, Queue *selection, Id dep, int flags, int keyname, int marker)
1000 queue_empty(selection);
1004 FOR_POOL_SOLVABLES(p)
1006 Solvable *s = pool->solvables + p;
1009 if (s->repo != pool->installed && !pool_installable(pool, s))
1011 if (!(flags & SELECTION_SOURCE_ONLY) || (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC))
1013 if (pool_disabled_solvable(pool, s))
1016 if ((flags & SELECTION_INSTALLED_ONLY) != 0 && s->repo != pool->installed)
1018 if ((s->arch == ARCH_SRC || s->arch == ARCH_NOSRC) && !(flags & SELECTION_SOURCE_ONLY) && !(flags & SELECTION_WITH_SOURCE))
1021 repo_lookup_deparray(s->repo, p, keyname, &q, marker);
1022 for (i = 0; i < q.count; i++)
1024 if ((flags & SELECTION_MATCH_DEPSTR) != 0) /* mis-use */
1026 if (q.elements[i] == dep)
1030 if (pool_match_dep(pool, q.elements[i], dep))
1034 queue_push2(selection, SOLVER_SOLVABLE | SOLVER_NOAUTOSET, p);
1037 if (!selection->count)
1039 if ((flags & SELECTION_FLAT) != 0)
1040 selection_flatten(pool, selection);
1041 return SELECTION_PROVIDES;
1045 pool_is_kind(Pool *pool, Id name, Id kind)
1050 n = pool_id2str(pool, name);
1053 const char *kn = pool_id2str(pool, kind);
1054 int knl = strlen(kn);
1055 return !strncmp(n, kn, knl) && n[knl] == ':' ? 1 : 0;
1061 while(*n >= 'a' && *n <= 'z')
1063 return *n == ':' ? 0 : 1;
1068 selection_filter(Pool *pool, Queue *sel1, Queue *sel2)
1071 Id p, pp, q1filled = 0;
1076 if (!sel1->count || !sel2->count)
1081 if (sel1->count == 2 && (sel1->elements[0] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_ALL)
1083 /* XXX: not 100% correct, but very useful */
1084 p = sel1->elements[0] & ~(SOLVER_SELECTMASK | SOLVER_SETMASK); /* job & jobflags */
1086 queue_init_clone(sel1, sel2);
1087 for (i = 0; i < sel1->count; i += 2)
1088 sel1->elements[i] = (sel1->elements[i] & (SOLVER_SELECTMASK | SOLVER_SETMASK)) | p ;
1092 map_init(&m2, pool->nsolvables);
1093 for (i = 0; i < sel2->count; i += 2)
1095 Id select = sel2->elements[i] & SOLVER_SELECTMASK;
1096 if (select == SOLVER_SOLVABLE_ALL)
1102 if (select == SOLVER_SOLVABLE_REPO)
1105 Repo *repo = pool_id2repo(pool, sel2->elements[i + 1]);
1108 FOR_REPO_SOLVABLES(repo, p, s)
1114 if ((select == SOLVER_SOLVABLE_NAME || select == SOLVER_SOLVABLE_PROVIDES) && ISRELDEP(sel2->elements[i + 1]))
1116 Reldep *rd = GETRELDEP(pool, sel2->elements[i + 1]);
1117 if (rd->flags == REL_ARCH && rd->name == 0)
1119 /* special arch filter */
1121 selection_solvables(pool, sel1, &q1);
1122 for (j = 0; j < q1.count; j++)
1124 Id p = q1.elements[j];
1125 Solvable *s = pool->solvables + p;
1126 if (s->arch == rd->evr || (rd->evr == ARCH_SRC && s->arch == ARCH_NOSRC))
1131 else if (rd->flags == REL_KIND && rd->name == 0)
1133 /* special kind filter */
1135 selection_solvables(pool, sel1, &q1);
1136 for (j = 0; j < q1.count; j++)
1138 Id p = q1.elements[j];
1139 Solvable *s = pool->solvables + p;
1140 if (pool_is_kind(pool, s->name, rd->evr))
1146 FOR_JOB_SELECT(p, pp, select, sel2->elements[i + 1])
1150 if (sel2->count == 2) /* XXX: AND all setmasks instead? */
1151 setflags = sel2->elements[0] & SOLVER_SETMASK & ~SOLVER_NOAUTOSET;
1152 for (i = j = 0; i < sel1->count; i += 2)
1154 Id select = sel1->elements[i] & SOLVER_SELECTMASK;
1157 if (select == SOLVER_SOLVABLE_ALL)
1159 FOR_POOL_SOLVABLES(p)
1161 if (map_tst(&m2, p))
1167 else if (select == SOLVER_SOLVABLE_REPO)
1170 Repo *repo = pool_id2repo(pool, sel1->elements[i + 1]);
1173 FOR_REPO_SOLVABLES(repo, p, s)
1175 if (map_tst(&m2, p))
1184 FOR_JOB_SELECT(p, pp, select, sel1->elements[i + 1])
1186 if (map_tst(&m2, p))
1187 queue_pushunique(&q1, p);
1196 sel1->elements[j] = sel1->elements[i] | setflags;
1197 sel1->elements[j + 1] = sel1->elements[i + 1];
1199 else if (q1.count > 1)
1201 sel1->elements[j] = (sel1->elements[i] & ~SOLVER_SELECTMASK) | SOLVER_SOLVABLE_ONE_OF | setflags;
1202 sel1->elements[j + 1] = pool_queuetowhatprovides(pool, &q1);
1206 sel1->elements[j] = (sel1->elements[i] & ~SOLVER_SELECTMASK) | SOLVER_SOLVABLE | SOLVER_NOAUTOSET | setflags;
1207 sel1->elements[j + 1] = q1.elements[0];
1211 queue_truncate(sel1, j);
1217 selection_add(Pool *pool, Queue *sel1, Queue *sel2)
1220 for (i = 0; i < sel2->count; i++)
1221 queue_push(sel1, sel2->elements[i]);
1225 pool_selection2str(Pool *pool, Queue *selection, Id flagmask)
1230 s = pool_tmpjoin(pool, 0, 0, 0);
1231 for (i = 0; i < selection->count; i += 2)
1233 Id how = selection->elements[i];
1235 s = pool_tmpappend(pool, s, " + ", 0);
1236 s2 = solver_select2str(pool, how & SOLVER_SELECTMASK, selection->elements[i + 1]);
1237 s = pool_tmpappend(pool, s, s2, 0);
1238 pool_freetmpspace(pool, s2);
1239 how &= flagmask & SOLVER_SETMASK;
1243 s = pool_tmpappend(pool, s, " ", 0);
1244 if (how & SOLVER_SETEV)
1245 s = pool_tmpappend(pool, s, ",setev", 0);
1246 if (how & SOLVER_SETEVR)
1247 s = pool_tmpappend(pool, s, ",setevr", 0);
1248 if (how & SOLVER_SETARCH)
1249 s = pool_tmpappend(pool, s, ",setarch", 0);
1250 if (how & SOLVER_SETVENDOR)
1251 s = pool_tmpappend(pool, s, ",setvendor", 0);
1252 if (how & SOLVER_SETREPO)
1253 s = pool_tmpappend(pool, s, ",setrepo", 0);
1254 if (how & SOLVER_NOAUTOSET)
1255 s = pool_tmpappend(pool, s, ",noautoset", 0);
1256 if (s[o + 1] != ',')
1257 s = pool_tmpappend(pool, s, ",?", 0);
1259 s = pool_tmpappend(pool, s, "]", 0);