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]);
56 FOR_REPO_SOLVABLES(repo, p, s)
61 FOR_JOB_SELECT(p, pp, select, selection->elements[i + 1])
66 selection->elements[j] = selection->elements[i];
67 selection->elements[j + 1] = selection->elements[i + 1];
70 queue_truncate(selection, j);
75 selection_solvables_sortcmp(const void *ap, const void *bp, void *dp)
77 return *(const Id *)ap - *(const Id *)bp;
81 selection_solvables(Pool *pool, Queue *selection, Queue *pkgs)
86 for (i = 0; i < selection->count; i += 2)
88 Id select = selection->elements[i] & SOLVER_SELECTMASK;
89 if (select == SOLVER_SOLVABLE_ALL)
94 if (select == SOLVER_SOLVABLE_REPO)
97 Repo *repo = pool_id2repo(pool, selection->elements[i + 1]);
99 FOR_REPO_SOLVABLES(repo, p, s)
104 FOR_JOB_SELECT(p, pp, select, selection->elements[i + 1])
111 solv_sort(pkgs->elements, pkgs->count, sizeof(Id), selection_solvables_sortcmp, NULL);
112 lastid = pkgs->elements[0];
113 for (i = j = 1; i < pkgs->count; i++)
114 if (pkgs->elements[i] != lastid)
115 pkgs->elements[j++] = lastid = pkgs->elements[i];
116 queue_truncate(pkgs, j);
120 selection_flatten(Pool *pool, Queue *selection)
124 if (selection->count <= 2)
126 for (i = 0; i < selection->count; i += 2)
127 if ((selection->elements[i] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_ALL)
129 selection->elements[0] = selection->elements[i];
130 selection->elements[1] = selection->elements[i + 1];
131 queue_truncate(selection, 2);
135 selection_solvables(pool, selection, &q);
138 queue_empty(selection);
141 queue_truncate(selection, 2);
144 selection->elements[0] = SOLVER_SOLVABLE_ONE_OF;
145 selection->elements[1] = pool_queuetowhatprovides(pool, &q);
149 selection->elements[0] = SOLVER_SOLVABLE | SOLVER_NOAUTOSET;
150 selection->elements[1] = q.elements[0];
155 selection_filter_rel(Pool *pool, Queue *selection, Id relflags, Id relevr)
159 for (i = 0; i < selection->count; i += 2)
161 Id select = selection->elements[i] & SOLVER_SELECTMASK;
162 Id id = selection->elements[i + 1];
163 if (select == SOLVER_SOLVABLE || select == SOLVER_SOLVABLE_ONE_OF)
165 /* done by selection_addsrc, currently implies SELECTION_NAME */
168 Id rel = 0, relname = 0;
172 FOR_JOB_SELECT(p, pp, select, id)
174 Solvable *s = pool->solvables + p;
175 if (!rel || s->name != relname)
178 rel = pool_rel2id(pool, relname, relevr, relflags, 1);
180 if (pool_match_nevr(pool, s, rel))
189 selection->elements[i] = SOLVER_SOLVABLE | SOLVER_NOAUTOSET;
190 selection->elements[i + 1] = q.elements[0];
194 selection->elements[i] = SOLVER_SOLVABLE_ONE_OF;
195 selection->elements[i + 1] = pool_queuetowhatprovides(pool, &q);
200 else if (select == SOLVER_SOLVABLE_NAME || select == SOLVER_SOLVABLE_PROVIDES)
202 /* don't stack src reldeps */
203 if (relflags == REL_ARCH && (relevr == ARCH_SRC || relevr == ARCH_NOSRC) && ISRELDEP(id))
205 Reldep *rd = GETRELDEP(pool, id);
206 if (rd->flags == REL_ARCH && rd->evr == ARCH_SRC)
209 selection->elements[i + 1] = pool_rel2id(pool, id, relevr, relflags, 1);
212 continue; /* actually internal error */
213 if (relflags == REL_ARCH)
214 selection->elements[i] |= SOLVER_SETARCH;
215 if (relflags == REL_EQ && select != SOLVER_SOLVABLE_PROVIDES)
217 if (pool->disttype == DISTTYPE_DEB)
218 selection->elements[i] |= SOLVER_SETEVR; /* debian can't match version only like rpm */
221 const char *rel = strrchr(pool_id2str(pool, relevr), '-');
222 selection->elements[i] |= rel ? SOLVER_SETEVR : SOLVER_SETEV;
226 selection_prune(pool, selection);
230 selection_filter_installed(Pool *pool, Queue *selection)
235 if (!pool->installed)
236 queue_empty(selection);
238 for (i = j = 0; i < selection->count; i += 2)
240 Id select = selection->elements[i] & SOLVER_SELECTMASK;
241 Id id = selection->elements[i + 1];
242 if (select == SOLVER_SOLVABLE_ALL)
244 select = SOLVER_SOLVABLE_REPO;
245 id = pool->installed->repoid;
247 else if (select == SOLVER_SOLVABLE_REPO)
249 if (id != pool->installed->repoid)
257 FOR_JOB_SELECT(p, pp, select, id)
259 if (pool->solvables[p].repo != pool->installed)
268 else if (q.count == 1)
270 select = SOLVER_SOLVABLE | SOLVER_NOAUTOSET;
275 select = SOLVER_SOLVABLE_ONE_OF;
276 id = pool_queuetowhatprovides(pool, &q);
282 selection->elements[j++] = select | (selection->elements[i] & ~SOLVER_SELECTMASK) | SOLVER_SETREPO;
283 selection->elements[j++] = id;
286 queue_truncate(selection, j);
291 selection_addsrc(Pool *pool, Queue *selection, int flags)
297 if ((flags & SELECTION_INSTALLED_ONLY) != 0)
298 return; /* sources can't be installed */
300 for (i = 0; i < selection->count; i += 2)
302 if (selection->elements[i] != SOLVER_SOLVABLE_NAME)
304 name = selection->elements[i + 1];
307 FOR_POOL_SOLVABLES(p)
309 Solvable *s = pool->solvables + p;
312 if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
314 if (pool_disabled_solvable(pool, s))
318 else if (s->repo != pool->installed && !pool_installable(pool, s))
322 if (!havesrc || !q.count)
326 selection->elements[i] = SOLVER_SOLVABLE | SOLVER_NOAUTOSET;
327 selection->elements[i + 1] = q.elements[0];
331 selection->elements[i] = SOLVER_SOLVABLE_ONE_OF;
332 selection->elements[i + 1] = pool_queuetowhatprovides(pool, &q);
338 static inline const char *
339 skipkind(const char *n)
342 for (s = n; *s >= 'a' && *s <= 'z'; s++)
344 if (*s == ':' && s != n)
350 queue_pushunique2(Queue *q, Id id1, Id id2)
353 for (i = 0; i < q->count; i += 2)
354 if (q->elements[i] == id1 && q->elements[i + 1] == id2)
356 queue_push2(q, id1, id2);
360 selection_depglob_id(Pool *pool, Queue *selection, Id id, int flags)
365 FOR_PROVIDES(p, pp, id)
367 Solvable *s = pool->solvables + p;
368 if ((flags & SELECTION_INSTALLED_ONLY) != 0 && s->repo != pool->installed)
371 if (s->name == id && (flags & SELECTION_NAME) != 0)
373 if ((flags & SELECTION_SOURCE_ONLY) != 0)
374 id = pool_rel2id(pool, id, ARCH_SRC, REL_ARCH, 1);
375 queue_push2(selection, SOLVER_SOLVABLE_NAME, id);
376 if ((flags & SELECTION_WITH_SOURCE) != 0)
377 selection_addsrc(pool, selection, flags);
378 return SELECTION_NAME;
381 if ((flags & (SELECTION_SOURCE_ONLY | SELECTION_WITH_SOURCE)) != 0 && (flags & SELECTION_NAME) != 0)
383 /* src rpms don't have provides, so we must check every solvable */
384 FOR_POOL_SOLVABLES(p) /* slow path */
386 Solvable *s = pool->solvables + p;
387 if (s->name == id && (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC))
389 if ((flags & SELECTION_INSTALLED_ONLY) != 0 && s->repo != pool->installed)
390 continue; /* just in case... src rpms can't be installed */
391 if (pool_disabled_solvable(pool, s))
393 if ((flags & SELECTION_SOURCE_ONLY) != 0)
394 id = pool_rel2id(pool, id, ARCH_SRC, REL_ARCH, 1);
395 queue_push2(selection, SOLVER_SOLVABLE_NAME, id);
396 if ((flags & SELECTION_WITH_SOURCE) != 0)
397 selection_addsrc(pool, selection, flags);
398 return SELECTION_NAME;
402 if (match && (flags & SELECTION_PROVIDES) != 0)
404 queue_push2(selection, SOLVER_SOLVABLE_PROVIDES, id);
405 return SELECTION_PROVIDES;
411 selection_depglob(Pool *pool, Queue *selection, const char *name, int flags)
419 if ((flags & SELECTION_SOURCE_ONLY) != 0)
421 flags &= ~SELECTION_PROVIDES; /* sources don't provide anything */
422 flags &= ~SELECTION_WITH_SOURCE;
425 if (!(flags & (SELECTION_NAME|SELECTION_PROVIDES)))
428 if ((flags & SELECTION_INSTALLED_ONLY) != 0 && !pool->installed)
431 nocase = flags & SELECTION_NOCASE;
432 if (!nocase && !(flags & SELECTION_SKIP_KIND))
434 id = pool_str2id(pool, name, 0);
437 /* the id is know, do the fast id matching using the whatprovides lookup */
438 int ret = selection_depglob_id(pool, selection, id, flags);
444 if ((flags & SELECTION_GLOB) != 0 && strpbrk(name, "[*?") != 0)
447 if (!nocase && !(flags & SELECTION_SKIP_KIND) && !doglob)
448 return 0; /* all done above in depglob_id */
450 if (doglob && nocase)
451 globflags = FNM_CASEFOLD;
453 if ((flags & SELECTION_NAME) != 0)
455 /* looks like a name glob. hard work. */
456 FOR_POOL_SOLVABLES(p)
458 Solvable *s = pool->solvables + p;
460 if (s->repo != pool->installed && !pool_installable(pool, s))
462 if (!(flags & SELECTION_SOURCE_ONLY) || (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC))
464 if (pool_disabled_solvable(pool, s))
467 if ((flags & SELECTION_INSTALLED_ONLY) != 0 && s->repo != pool->installed)
470 n = pool_id2str(pool, id);
471 if (flags & SELECTION_SKIP_KIND)
473 if ((doglob ? fnmatch(name, n, globflags) : nocase ? strcasecmp(name, n) : strcmp(name, n)) == 0)
475 if ((flags & SELECTION_SOURCE_ONLY) != 0)
476 id = pool_rel2id(pool, id, ARCH_SRC, REL_ARCH, 1);
477 queue_pushunique2(selection, SOLVER_SOLVABLE_NAME, id);
483 if ((flags & SELECTION_WITH_SOURCE) != 0)
484 selection_addsrc(pool, selection, flags);
485 return SELECTION_NAME;
489 if ((flags & SELECTION_PROVIDES))
491 /* looks like a dep glob. really hard work. */
492 for (id = 1; id < pool->ss.nstrings; id++)
495 if (!pool->whatprovides[id] || pool->whatprovides[id] == 1)
497 n = pool_id2str(pool, id);
498 if ((doglob ? fnmatch(name, n, globflags) : nocase ? strcasecmp(name, n) : strcmp(name, n)) == 0)
500 if ((flags & SELECTION_INSTALLED_ONLY) != 0)
502 FOR_PROVIDES(p, pp, id)
503 if (pool->solvables[p].repo == pool->installed)
508 queue_push2(selection, SOLVER_SOLVABLE_PROVIDES, id);
513 return SELECTION_PROVIDES;
519 selection_depglob_arch(Pool *pool, Queue *selection, const char *name, int flags)
525 if ((ret = selection_depglob(pool, selection, name, flags)) != 0)
527 if (!(flags & SELECTION_DOTARCH))
529 /* check if there is an .arch suffix */
530 if ((r = strrchr(name, '.')) != 0 && r[1] && (archid = str2archid(pool, r + 1)) != 0)
532 char *rname = solv_strdup(name);
534 if (archid == ARCH_SRC || archid == ARCH_NOSRC)
535 flags |= SELECTION_SOURCE_ONLY;
536 if ((ret = selection_depglob(pool, selection, rname, flags)) != 0)
538 selection_filter_rel(pool, selection, REL_ARCH, archid);
540 return ret | SELECTION_DOTARCH;
548 selection_filelist(Pool *pool, Queue *selection, const char *name, int flags)
554 type = !(flags & SELECTION_GLOB) || strpbrk(name, "[*?") == 0 ? SEARCH_STRING : SEARCH_GLOB;
555 if ((flags & SELECTION_NOCASE) != 0)
556 type |= SEARCH_NOCASE;
558 dataiterator_init(&di, pool, flags & SELECTION_INSTALLED_ONLY ? pool->installed : 0, 0, SOLVABLE_FILELIST, name, type|SEARCH_FILES|SEARCH_COMPLETE_FILELIST);
559 while (dataiterator_step(&di))
561 Solvable *s = pool->solvables + di.solvid;
564 if (s->repo != pool->installed && !pool_installable(pool, s))
566 if (!(flags & SELECTION_SOURCE_ONLY) || (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC))
568 if (pool_disabled_solvable(pool, s))
571 if ((flags & SELECTION_INSTALLED_ONLY) != 0 && s->repo != pool->installed)
573 queue_push(&q, di.solvid);
574 dataiterator_skip_solvable(&di);
576 dataiterator_free(&di);
580 queue_push2(selection, SOLVER_SOLVABLE_ONE_OF, pool_queuetowhatprovides(pool, &q));
582 queue_push2(selection, SOLVER_SOLVABLE | SOLVER_NOAUTOSET, q.elements[0]);
584 return SELECTION_FILELIST;
588 splitrel(char *rname, char *r, int *rflagsp)
590 int nend = r - rname;
592 if (nend && *r == '=' && r[-1] == '!')
596 rflags = REL_LT|REL_GT;
609 while (*r && (*r == ' ' || *r == '\t'))
611 while (nend && (rname[nend - 1] == ' ' || rname[nend - 1] == '\t'))
621 selection_rel(Pool *pool, Queue *selection, const char *name, int flags)
626 /* relation case, support:
630 rname = solv_strdup(name);
631 if ((r = strpbrk(rname, "<=>")) != 0)
633 if ((r = splitrel(rname, r, &rflags)) == 0)
639 if ((ret = selection_depglob_arch(pool, selection, rname, flags)) != 0)
642 selection_filter_rel(pool, selection, rflags, pool_str2id(pool, r, 1));
644 return ret | SELECTION_REL;
650 #if defined(MULTI_SEMANTICS)
651 # define EVRCMP_DEPCMP (pool->disttype == DISTTYPE_DEB ? EVRCMP_COMPARE : EVRCMP_MATCH_RELEASE)
652 #elif defined(DEBIAN)
653 # define EVRCMP_DEPCMP EVRCMP_COMPARE
655 # define EVRCMP_DEPCMP EVRCMP_MATCH_RELEASE
658 /* magic epoch promotion code, works only for SELECTION_NAME selections */
660 selection_filter_evr(Pool *pool, Queue *selection, char *evr)
667 queue_init_buffer(&q, qbuf, sizeof(qbuf)/sizeof(*qbuf));
668 for (i = j = 0; i < selection->count; i += 2)
670 Id select = selection->elements[i] & SOLVER_SELECTMASK;
671 Id id = selection->elements[i + 1];
673 const char *lastepoch = 0;
674 int lastepochlen = 0;
677 FOR_JOB_SELECT(p, pp, select, id)
679 Solvable *s = pool->solvables + p;
680 const char *sevr = pool_id2str(pool, s->evr);
682 for (sp = sevr; *sp >= '0' && *sp <= '9'; sp++)
686 /* compare vr part */
687 if (strcmp(evr, sp != sevr ? sp + 1 : sevr) != 0)
689 int r = pool_evrcmp_str(pool, sp != sevr ? sp + 1 : sevr, evr, EVRCMP_DEPCMP);
690 if (r == -1 || r == 1)
691 continue; /* solvable does not match vr */
696 while (sevr < sp && *sevr == '0') /* normalize epoch */
702 lastepochlen = sp - sevr;
704 else if (lastepochlen != sp - sevr || strncmp(lastepoch, sevr, lastepochlen) != 0)
705 lastepochlen = -1; /* multiple different epochs */
707 if (!lastepoch || lastepochlen == 0)
708 id = pool_str2id(pool, evr, 1); /* no match at all or zero epoch */
709 else if (lastepochlen >= 0)
711 /* found exactly one epoch, simply prepend */
712 char *evrx = solv_malloc(strlen(evr) + lastepochlen + 2);
713 strncpy(evrx, lastepoch, lastepochlen + 1);
714 strcpy(evrx + lastepochlen + 1, evr);
715 id = pool_str2id(pool, evrx, 1);
720 /* multiple epochs in multiple solvables, convert to list of solvables */
721 selection->elements[j] = (selection->elements[i] & ~SOLVER_SELECTMASK) | SOLVER_SOLVABLE_ONE_OF;
722 selection->elements[j + 1] = pool_queuetowhatprovides(pool, &q);
727 queue_push2(&q, selection->elements[i], selection->elements[i + 1]);
728 selection_filter_rel(pool, &q, REL_EQ, id);
730 continue; /* oops, no match */
731 selection->elements[j] = q.elements[0];
732 selection->elements[j + 1] = q.elements[1];
735 queue_truncate(selection, j);
739 /* match the "canonical" name of the package */
741 selection_canon(Pool *pool, Queue *selection, const char *name, int flags)
743 char *rname, *r, *r2;
749 * nameglob-version.arch
750 * nameglob-version-release
751 * nameglob-version-release.arch
753 flags |= SELECTION_NAME;
754 flags &= ~SELECTION_PROVIDES;
756 if (pool->disttype == DISTTYPE_DEB)
758 if ((r = strchr(name, '_')) == 0)
760 rname = solv_strdup(name); /* so we can modify it */
761 r = rname + (r - name);
763 if ((ret = selection_depglob(pool, selection, rname, flags)) == 0)
768 /* is there a vaild arch? */
769 if ((r2 = strrchr(r, '_')) != 0 && r[1] && (archid = str2archid(pool, r + 1)) != 0)
771 *r2 = 0; /* split off */
772 selection_filter_rel(pool, selection, REL_ARCH, archid);
774 selection_filter_rel(pool, selection, REL_EQ, pool_str2id(pool, r, 1));
776 return ret | SELECTION_CANON;
779 if (pool->disttype == DISTTYPE_HAIKU)
781 if ((r = strchr(name, '-')) == 0)
783 rname = solv_strdup(name); /* so we can modify it */
784 r = rname + (r - name);
786 if ((ret = selection_depglob(pool, selection, rname, flags)) == 0)
791 /* is there a vaild arch? */
792 if ((r2 = strrchr(r, '-')) != 0 && r[1] && (archid = str2archid(pool, r + 1)) != 0)
794 *r2 = 0; /* split off */
795 selection_filter_rel(pool, selection, REL_ARCH, archid);
797 selection_filter_rel(pool, selection, REL_EQ, pool_str2id(pool, r, 1));
799 return ret | SELECTION_CANON;
802 if ((r = strrchr(name, '-')) == 0)
804 rname = solv_strdup(name); /* so we can modify it */
805 r = rname + (r - name);
808 /* split off potential arch part from version */
809 if ((r2 = strrchr(r + 1, '.')) != 0 && r2[1] && (archid = str2archid(pool, r2 + 1)) != 0)
810 *r2 = 0; /* found valid arch, split it off */
811 if (archid == ARCH_SRC || archid == ARCH_NOSRC)
812 flags |= SELECTION_SOURCE_ONLY;
814 /* try with just the version */
815 if ((ret = selection_depglob(pool, selection, rname, flags)) == 0)
817 /* no luck, try with version-release */
818 if ((r2 = strrchr(rname, '-')) == 0)
826 if ((ret = selection_depglob(pool, selection, rname, flags)) == 0)
833 selection_filter_rel(pool, selection, REL_ARCH, archid);
834 selection_filter_evr(pool, selection, r + 1); /* magic epoch promotion */
836 return ret | SELECTION_CANON;
840 selection_make(Pool *pool, Queue *selection, const char *name, int flags)
844 queue_empty(selection);
845 if (*name == '/' && (flags & SELECTION_FILELIST))
846 ret = selection_filelist(pool, selection, name, flags);
847 if (!ret && (flags & SELECTION_REL) != 0 && strpbrk(name, "<=>") != 0)
848 ret = selection_rel(pool, selection, name, flags);
850 ret = selection_depglob_arch(pool, selection, name, flags);
851 if (!ret && (flags & SELECTION_CANON) != 0)
852 ret = selection_canon(pool, selection, name, flags);
853 if (selection->count && (flags & SELECTION_INSTALLED_ONLY) != 0)
854 selection_filter_installed(pool, selection);
855 if (ret && !selection->count)
856 ret = 0; /* no match -> always return zero */
857 if (ret && (flags & SELECTION_FLAT) != 0)
858 selection_flatten(pool, selection);
863 matchdep(Pool *pool, Id id, char *rname, int rflags, char *revr, int flags)
867 Reldep *rd = GETRELDEP(pool, id);
868 if (rd->flags == REL_AND || rd->flags == REL_OR || rd->flags == REL_WITH)
870 if (matchdep(pool, rd->name, rname, rflags, revr, flags))
872 if (matchdep(pool, rd->evr, rname, rflags, revr, flags))
876 if (rd->flags == REL_ARCH)
877 return matchdep(pool, rd->name, rname, rflags, revr, flags);
878 if (!matchdep(pool, rd->name, rname, rflags, revr, flags))
882 /* XXX: need pool_match_flags_evr here */
883 if (!pool_match_dep(pool, pool_rel2id(pool, rd->name, pool_str2id(pool, revr, 1), rflags, 1), id))
888 if (flags & SELECTION_GLOB)
890 int globflags = (flags & SELECTION_NOCASE) != 0 ? FNM_CASEFOLD : 0;
891 return fnmatch(rname, pool_id2str(pool, id), globflags) == 0 ? 1 : 0;
893 if (flags & SELECTION_NOCASE)
894 return strcasecmp(rname, pool_id2str(pool, id)) == 0 ? 1 : 0;
895 return strcmp(rname, pool_id2str(pool, id)) == 0 ? 1 : 0;
899 * select against the dependencies in keyname
900 * like SELECTION_REL and SELECTION_PROVIDES, but with the
901 * deps in keyname instead of provides.
904 selection_make_matchdeps(Pool *pool, Queue *selection, const char *name, int flags, int keyname, int marker)
911 queue_empty(selection);
912 rname = solv_strdup(name);
913 if ((r = strpbrk(rname, "<=>")) != 0)
915 if ((r = splitrel(rname, r, &rflags)) == 0)
921 if ((flags & SELECTION_GLOB) != 0 && !strpbrk(name, "[*?") != 0)
922 flags &= ~SELECTION_GLOB;
925 FOR_POOL_SOLVABLES(p)
927 Solvable *s = pool->solvables + p;
930 if (s->repo != pool->installed && !pool_installable(pool, s))
932 if (!(flags & SELECTION_SOURCE_ONLY) || (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC))
934 if (pool_disabled_solvable(pool, s))
937 if ((flags & SELECTION_INSTALLED_ONLY) != 0 && s->repo != pool->installed)
939 if ((s->arch == ARCH_SRC || s->arch == ARCH_NOSRC) && !(flags & SELECTION_SOURCE_ONLY) && !(flags & SELECTION_WITH_SOURCE))
942 repo_lookup_deparray(s->repo, p, keyname, &q, marker);
943 for (i = 0; i < q.count; i++)
945 Id id = q.elements[i];
946 if (matchdep(pool, id, rname, rflags, r, flags))
950 queue_push2(selection, SOLVER_SOLVABLE | SOLVER_NOAUTOSET, p);
954 if (!selection->count)
956 if ((flags & SELECTION_FLAT) != 0)
957 selection_flatten(pool, selection);
958 return SELECTION_PROVIDES;
962 pool_is_kind(Pool *pool, Id name, Id kind)
967 n = pool_id2str(pool, name);
970 const char *kn = pool_id2str(pool, kind);
971 int knl = strlen(kn);
972 return !strncmp(n, kn, knl) && n[knl] == ':' ? 1 : 0;
978 while(*n >= 'a' && *n <= 'z')
980 return *n == ':' ? 0 : 1;
985 selection_filter(Pool *pool, Queue *sel1, Queue *sel2)
988 Id p, pp, q1filled = 0;
993 if (!sel1->count || !sel2->count)
998 if (sel1->count == 2 && (sel1->elements[0] & SOLVER_SELECTMASK) == SOLVER_SOLVABLE_ALL)
1000 /* XXX: not 100% correct, but very useful */
1001 p = sel1->elements[0] & ~(SOLVER_SELECTMASK | SOLVER_SETMASK); /* job & jobflags */
1003 queue_init_clone(sel1, sel2);
1004 for (i = 0; i < sel1->count; i += 2)
1005 sel1->elements[i] = (sel1->elements[i] & (SOLVER_SELECTMASK | SOLVER_SETMASK)) | p ;
1009 map_init(&m2, pool->nsolvables);
1010 for (i = 0; i < sel2->count; i += 2)
1012 Id select = sel2->elements[i] & SOLVER_SELECTMASK;
1013 if (select == SOLVER_SOLVABLE_ALL)
1019 if (select == SOLVER_SOLVABLE_REPO)
1022 Repo *repo = pool_id2repo(pool, sel2->elements[i + 1]);
1024 FOR_REPO_SOLVABLES(repo, p, s)
1029 if ((select == SOLVER_SOLVABLE_NAME || select == SOLVER_SOLVABLE_PROVIDES) && ISRELDEP(sel2->elements[i + 1]))
1031 Reldep *rd = GETRELDEP(pool, sel2->elements[i + 1]);
1032 if (rd->flags == REL_ARCH && rd->name == 0)
1034 /* special arch filter */
1036 selection_solvables(pool, sel1, &q1);
1037 for (j = 0; j < q1.count; j++)
1039 Id p = q1.elements[j];
1040 Solvable *s = pool->solvables + p;
1041 if (s->arch == rd->evr || (rd->evr == ARCH_SRC && s->arch == ARCH_NOSRC))
1046 else if (rd->flags == REL_KIND && rd->name == 0)
1048 /* special kind filter */
1050 selection_solvables(pool, sel1, &q1);
1051 for (j = 0; j < q1.count; j++)
1053 Id p = q1.elements[j];
1054 Solvable *s = pool->solvables + p;
1055 if (pool_is_kind(pool, s->name, rd->evr))
1061 FOR_JOB_SELECT(p, pp, select, sel2->elements[i + 1])
1065 if (sel2->count == 2) /* XXX: AND all setmasks instead? */
1066 setflags = sel2->elements[0] & SOLVER_SETMASK & ~SOLVER_NOAUTOSET;
1067 for (i = j = 0; i < sel1->count; i += 2)
1069 Id select = sel1->elements[i] & SOLVER_SELECTMASK;
1072 if (select == SOLVER_SOLVABLE_ALL)
1074 FOR_POOL_SOLVABLES(p)
1076 if (map_tst(&m2, p))
1082 else if (select == SOLVER_SOLVABLE_REPO)
1085 Repo *repo = pool_id2repo(pool, sel1->elements[i + 1]);
1087 FOR_REPO_SOLVABLES(repo, p, s)
1089 if (map_tst(&m2, p))
1097 FOR_JOB_SELECT(p, pp, select, sel1->elements[i + 1])
1099 if (map_tst(&m2, p))
1100 queue_pushunique(&q1, p);
1109 sel1->elements[j] = sel1->elements[i] | setflags;
1110 sel1->elements[j + 1] = sel1->elements[i + 1];
1112 else if (q1.count > 1)
1114 sel1->elements[j] = (sel1->elements[i] & ~SOLVER_SELECTMASK) | SOLVER_SOLVABLE_ONE_OF | setflags;
1115 sel1->elements[j + 1] = pool_queuetowhatprovides(pool, &q1);
1119 sel1->elements[j] = (sel1->elements[i] & ~SOLVER_SELECTMASK) | SOLVER_SOLVABLE | SOLVER_NOAUTOSET | setflags;
1120 sel1->elements[j + 1] = q1.elements[0];
1124 queue_truncate(sel1, j);
1130 selection_add(Pool *pool, Queue *sel1, Queue *sel2)
1133 for (i = 0; i < sel2->count; i++)
1134 queue_push(sel1, sel2->elements[i]);
1138 pool_selection2str(Pool *pool, Queue *selection, Id flagmask)
1143 s = pool_tmpjoin(pool, 0, 0, 0);
1144 for (i = 0; i < selection->count; i += 2)
1146 Id how = selection->elements[i];
1148 s = pool_tmpappend(pool, s, " + ", 0);
1149 s2 = solver_select2str(pool, how & SOLVER_SELECTMASK, selection->elements[i + 1]);
1150 s = pool_tmpappend(pool, s, s2, 0);
1151 pool_freetmpspace(pool, s2);
1152 how &= flagmask & SOLVER_SETMASK;
1156 s = pool_tmpappend(pool, s, " ", 0);
1157 if (how & SOLVER_SETEV)
1158 s = pool_tmpappend(pool, s, ",setev", 0);
1159 if (how & SOLVER_SETEVR)
1160 s = pool_tmpappend(pool, s, ",setevr", 0);
1161 if (how & SOLVER_SETARCH)
1162 s = pool_tmpappend(pool, s, ",setarch", 0);
1163 if (how & SOLVER_SETVENDOR)
1164 s = pool_tmpappend(pool, s, ",setvendor", 0);
1165 if (how & SOLVER_SETREPO)
1166 s = pool_tmpappend(pool, s, ",setrepo", 0);
1167 if (how & SOLVER_NOAUTOSET)
1168 s = pool_tmpappend(pool, s, ",noautoset", 0);
1169 if (s[o + 1] != ',')
1170 s = pool_tmpappend(pool, s, ",?", 0);
1172 s = pool_tmpappend(pool, s, "]", 0);