pax_global_header00006660000000000000000000000064125646423120014517gustar00rootroot0000000000000052 comment=22dae2ba2cfb066a442e60ad0ff4f7fe4ff42ce0 perl-BSSolv-0.05/000077500000000000000000000000001256464231200135535ustar00rootroot00000000000000perl-BSSolv-0.05/BSSolv.pm000066400000000000000000000002651256464231200152640ustar00rootroot00000000000000package BSSolv; use strict; require Exporter; our @ISA = qw(Exporter); our $VERSION = '0.05'; require XSLoader; XSLoader::load('BSSolv', $VERSION); package BSSolv::repo; 1; perl-BSSolv-0.05/BSSolv.xs000066400000000000000000002201061256464231200153000ustar00rootroot00000000000000#ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #define MULTI_SEMANTICS #include "pool.h" #include "repo.h" #include "util.h" #include "evr.h" #include "hash.h" #include "chksum.h" #include "repo_solv.h" #include "repo_write.h" #include "repo_rpmdb.h" #include "repo_deb.h" #if 1 #include "repo_arch.h" #endif typedef struct _Expander { Pool *pool; Map ignored; Map ignoredx; Queue preferposq; Map preferpos; Map preferposx; Map preferneg; Map prefernegx; Queue conflictsq; Map conflicts; int debug; int havefileprovides; int ignoreconflicts; int ignoreignore; char *debugstr; int debugstrl; int debugstrf; } Expander; typedef Pool *BSSolv__pool; typedef Repo *BSSolv__repo; typedef Expander *BSSolv__expander; static Id buildservice_id; static Id buildservice_repocookie; static Id buildservice_external; static Id buildservice_dodurl; static Id expander_directdepsend; static Id buildservice_dodcookie; /* make sure bit n is usable */ #define MAPEXP(m, n) ((m)->size < (((n) + 8) >> 3) ? map_grow(m, n + 256) : 0) #define REPOCOOKIE "buildservice repo 1.1" static int myrepowritefilter(Repo *repo, Repokey *key, void *kfdata) { int i; if (key->name == SOLVABLE_URL) return KEY_STORAGE_DROPPED; if (key->name == SOLVABLE_HEADEREND) return KEY_STORAGE_DROPPED; if (key->name == SOLVABLE_PACKAGER) return KEY_STORAGE_DROPPED; if (key->name == SOLVABLE_GROUP) return KEY_STORAGE_DROPPED; if (key->name == SOLVABLE_LICENSE) return KEY_STORAGE_DROPPED; if (key->name == SOLVABLE_PKGID) return KEY_STORAGE_INCORE; if (key->name == SOLVABLE_CHECKSUM) return KEY_STORAGE_INCORE; i = repo_write_stdkeyfilter(repo, key, kfdata); if (i == KEY_STORAGE_VERTICAL_OFFSET) return KEY_STORAGE_DROPPED; return i; } static inline char * hvlookupstr(HV *hv, const char *key, int keyl) { SV **svp = hv_fetch(hv, key, keyl, 0); if (!svp) return 0; return SvPV_nolen(*svp); } static inline AV * hvlookupav(HV *hv, const char *key, int keyl) { SV *sv, **svp = hv_fetch(hv, key, keyl, 0); if (!svp) return 0; sv = *svp; if (!sv || !SvROK(sv) || SvTYPE(SvRV(sv)) != SVt_PVAV) return 0; return (AV *)SvRV(sv); } static Id makeevr(Pool *pool, char *e, char *v, char *r) { char *s; if (!v) return 0; if (e && !strcmp(e, "0")) e = 0; if (e) s = pool_tmpjoin(pool, e, ":", v); else s = v; if (r) s = pool_tmpjoin(pool, s, "-", r); return pool_str2id(pool, s, 1); } static inline char * avlookupstr(AV *av, int n) { SV **svp = av_fetch(av, n, 0); if (!svp) return 0; return SvPV_nolen(*svp); } static inline Id id2name(Pool *pool, Id id) { while (ISRELDEP(id)) { Reldep *rd = GETRELDEP(pool, id); id = rd->name; } return id; } static Id dep2id(Pool *pool, char *s) { char *n; Id id; int flags; if ((n = strchr(s, '|')) != 0) { id = dep2id(pool, n + 1); *n = 0; id = pool_rel2id(pool, dep2id(pool, s), id, REL_OR, 1); *n = '|'; return id; } while (*s == ' ' || *s == '\t') s++; n = s; while (*s && *s != ' ' && *s != '\t' && *s != '<' && *s != '=' && *s != '>') s++; #ifdef REL_MULTIARCH if (s - n > 4 && s[-4] == ':' && !strncmp(s - 4, ":any", 4)) { id = pool_strn2id(pool, n, s - n - 4, 1); id = pool_rel2id(pool, id, ARCH_ANY, REL_MULTIARCH, 1); } else #endif id = pool_strn2id(pool, n, s - n, 1); if (!*s) return id; while (*s == ' ' || *s == '\t') s++; flags = 0; for (;;s++) { if (*s == '<') flags |= REL_LT; else if (*s == '=') flags |= REL_EQ; else if (*s == '>') flags |= REL_GT; else break; } if (!flags) return id; while (*s == ' ' || *s == '\t') s++; n = s; while (*s && *s != ' ' && *s != '\t') s++; return pool_rel2id(pool, id, pool_strn2id(pool, n, s - n, 1), flags, 1); } static inline Offset importdeps(HV *hv, const char *key, int keyl, Repo *repo) { Pool *pool = repo->pool; int i; AV *av = hvlookupav(hv, key, keyl); Offset off = 0; if (av) { for (i = 0; i <= av_len(av); i++) { char *str = avlookupstr(av, i); if (str) off = repo_addid_dep(repo, off, dep2id(pool, str), 0); } } return off; } void exportdeps(HV *hv, const char *key, int keyl, Repo *repo, Offset off, Id skey) { Pool *pool = repo->pool; AV *av; Id id, *pp; const char *str; if (!off || !repo->idarraydata[off]) return; pp = repo->idarraydata + off; av = 0; while ((id = *pp++)) { if (id == SOLVABLE_FILEMARKER) break; str = pool_dep2str(pool, id); if (ISRELDEP(id)) { Reldep *rd = GETRELDEP(pool, id); if (skey == SOLVABLE_CONFLICTS && rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_OTHERPROVIDERS) { if (!strncmp(str, "namespace:", 10)) str += 10; } if (skey == SOLVABLE_SUPPLEMENTS) { if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_FILESYSTEM) { if (!strncmp(str, "namespace:", 10)) str += 10; } else if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_MODALIAS) { if (!strncmp(str, "namespace:", 10)) str += 10; } else if (rd->flags == REL_AND) { /* either packageand chain or modalias */ str = 0; if (ISRELDEP(rd->evr)) { Reldep *mrd = GETRELDEP(pool, rd->evr); if (mrd->flags == REL_NAMESPACE && mrd->name == NAMESPACE_MODALIAS) { str = pool_tmpjoin(pool, "modalias(", pool_dep2str(pool, rd->name), ":"); str = pool_tmpappend(pool, str, pool_dep2str(pool, mrd->evr), ")"); } else if (mrd->flags >= 8) continue; } if (!str) { /* must be and chain */ str = pool_dep2str(pool, rd->evr); for (;;) { id = rd->name; if (!ISRELDEP(id)) break; rd = GETRELDEP(pool, id); if (rd->flags != REL_AND) break; str = pool_tmpjoin(pool, pool_dep2str(pool, rd->evr), ":", str); } str = pool_tmpjoin(pool, pool_dep2str(pool, id), ":", str); str = pool_tmpjoin(pool, "packageand(", str, ")"); } } else if (rd->flags >= 8) continue; } } if (skey == SOLVABLE_REQUIRES) { if (id == SOLVABLE_PREREQMARKER) continue; if (*str == 'r' && !strncmp(str, "rpmlib(", 7)) continue; } if (!av) av = newAV(); av_push(av, newSVpv(str, 0)); } if (av) (void)hv_store(hv, key, keyl, newRV_noinc((SV*)av), 0); } void data2solvables(Repo *repo, Repodata *data, HV *rhv) { Pool *pool = repo->pool; SV *sv; HV *hv; char *str, *key; I32 keyl; Id p; Solvable *s; hv_iterinit(rhv); while ((sv = hv_iternextsv(rhv, &key, &keyl)) != 0) { if (!SvROK(sv) || SvTYPE(SvRV(sv)) != SVt_PVHV) continue; hv = (HV *)SvRV(sv); str = hvlookupstr(hv, "name", 4); if (!str) continue; /* need to have a name */ p = repo_add_solvable(repo); s = pool_id2solvable(pool, p); s->name = pool_str2id(pool, str, 1); str = hvlookupstr(hv, "arch", 4); if (!str) str = ""; /* dummy, need to have arch */ s->arch = pool_str2id(pool, str, 1); s->evr = makeevr(pool, hvlookupstr(hv, "epoch", 5), hvlookupstr(hv, "version", 7), hvlookupstr(hv, "release", 7)); str = hvlookupstr(hv, "path", 4); if (str) { char *ss = strrchr(str, '/'); if (ss) { *ss = 0; repodata_set_str(data, p, SOLVABLE_MEDIADIR, str); *ss++ = '/'; } else ss = str; repodata_set_str(data, p, SOLVABLE_MEDIAFILE, ss); } str = hvlookupstr(hv, "id", 2); if (str) repodata_set_str(data, p, buildservice_id, str); str = hvlookupstr(hv, "source", 6); if (str) repodata_set_poolstr(data, p, SOLVABLE_SOURCENAME, str); str = hvlookupstr(hv, "hdrmd5", 6); if (str && strlen(str) == 32) repodata_set_checksum(data, p, SOLVABLE_PKGID, REPOKEY_TYPE_MD5, str); s->provides = importdeps(hv, "provides", 8, repo); s->obsoletes = importdeps(hv, "obsoletes", 9, repo); s->conflicts = importdeps(hv, "conflicts", 9, repo); s->requires = importdeps(hv, "requires", 8, repo); s->recommends = importdeps(hv, "recommends", 10, repo); s->suggests = importdeps(hv, "suggests", 8, repo); s->supplements = importdeps(hv, "supplements", 11, repo); s->enhances = importdeps(hv, "enhances", 8, repo); if (!s->evr && s->provides) { /* look for self provides */ Id pro, *prop = s->repo->idarraydata + s->provides; while ((pro = *prop++) != 0) { Reldep *rd; if (!ISRELDEP(pro)) continue; rd = GETRELDEP(pool, pro); if (rd->name == s->name && rd->flags == REL_EQ) s->evr = rd->evr; } } if (s->evr) s->provides = repo_addid_dep(repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0); str = hvlookupstr(hv, "checksum", 8); if (str) { char *cp, typebuf[8]; Id ctype; if (*str != ':' && (cp = strchr(str, ':')) != 0 && cp - str < sizeof(typebuf)) { strncpy(typebuf, str, cp - str); typebuf[cp - str] = 0; ctype = solv_chksum_str2type(typebuf); if (ctype) repodata_set_checksum(data, p, SOLVABLE_CHECKSUM, ctype, cp + 1); } } } repodata_set_str(data, SOLVID_META, buildservice_repocookie, REPOCOOKIE); str = hvlookupstr(rhv, "/url", 4); if (str) repodata_set_str(data, SOLVID_META, buildservice_dodurl, str); str = hvlookupstr(rhv, "/dodcookie", 10); if (str) repodata_set_str(data, SOLVID_META, buildservice_dodcookie, str); } static SV * retrieve(unsigned char **srcp, STRLEN *srclp, int depth) { SV *sv, *rv; AV *av; HV *hv; unsigned char *src = *srcp; STRLEN srcl = *srclp; int type; unsigned int i, len; STRLEN size; if (depth > 10) return 0; if (srcl-- == 0) return 0; type = *src++; switch (type) { case 1: if (srcl < 4) return 0; size = src[0] << 24 | src[1] << 16 | src[2] << 8 | src[3]; srcl -= 4; src += 4; if (srcl < size) return 0; sv = NEWSV(10002, size); sv_setpvn(sv, (char *)src, size); srcl -= size; src += size; break; case 2: if (srcl < 4) return 0; len = src[0] << 24 | src[1] << 16 | src[2] << 8 | src[3]; srcl -= 4; src += 4; if (len > srcl) return 0; av = newAV(); if (len) av_extend(av, len); for (i = 0; i < len; i++) { sv = retrieve(&src, &srcl, depth + 1); if (!sv) return 0; if (av_store(av, i, sv) == 0) return 0; } sv = (SV *)av; break; case 3: if (srcl < 4) return 0; len = src[0] << 24 | src[1] << 16 | src[2] << 8 | src[3]; srcl -= 4; src += 4; if (len > srcl) return 0; hv = newHV(); if (len) hv_ksplit(hv, len + 1); for (i = 0; i < len; i++) { sv = retrieve(&src, &srcl, depth + 1); if (!sv) return 0; if (srcl < 4) return 0; size = src[0] << 24 | src[1] << 16 | src[2] << 8 | src[3]; srcl -= 4; src += 4; if (srcl < size) return 0; if (hv_store(hv, (char *)src, (U32)size, sv, 0) == 0) return 0; srcl -= size; src += size; } sv = (SV *)hv; break; case 4: rv = NEWSV(10002, 0); sv = retrieve(&src, &srcl, depth + 1); if (!sv) return 0; sv_upgrade(rv, SVt_RV); SvRV_set(rv, sv); SvROK_on(rv); sv = rv; break; case 10: if (srcl-- == 0) return 0; size = *src++; if (srcl < size) return 0; sv = NEWSV(10002, size); sv_setpvn(sv, (char *)src, size); srcl -= size; src += size; break; default: /* fprintf(stderr, "unknown tag %d\n", type); */ return 0; } *srcp = src; *srclp = srcl; return sv; } static void expander_dbg(Expander *xp, const char *format, ...) { va_list args; char buf[1024]; int l; if (!xp->debug) return; va_start(args, format); vsnprintf(buf, sizeof(buf), format, args); va_end(args); printf("%s", buf); l = strlen(buf); if (buf[0] != ' ' || (l && buf[l - 1] == '\n')) fflush(stdout); if (l >= xp->debugstrf) /* >= because of trailing \0 */ { xp->debugstr = solv_realloc(xp->debugstr, xp->debugstrl + l + 1024); xp->debugstrf = l + 1024; } strcpy(xp->debugstr + xp->debugstrl, buf); xp->debugstrl += l; xp->debugstrf -= l; } static const char * expander_solvid2name(Expander *xp, Id p) { const char *n = pool_id2str(xp->pool, xp->pool->solvables[p].name); Repo *r; if (!xp->debug) return n; r = xp->pool->solvables[p].repo; if (!r) return n; return pool_tmpjoin(xp->pool, n, "@", r->name); } static inline void expander_installed(Expander *xp, Id p, Map *installed, Map *conflicts, Queue *conflictsinfo, int *cidone, Queue *out, Queue *todo) { Pool *pool = xp->pool; Solvable *s = pool->solvables + p; Id req, id, *reqp, con, *conp; const char *n; MAPSET(installed, p); queue_push(out, p); if (MAPTST(&xp->conflicts, s->name)) { int i; for (i = 0; i < xp->conflictsq.count; i++) { Id p2, pp2; Id id = xp->conflictsq.elements[i]; if (id != s->name) continue; id = xp->conflictsq.elements[i ^ 1]; FOR_PROVIDES(p2, pp2, id) { if (pool->solvables[p2].name == id) { MAPEXP(conflicts, pool->nsolvables); MAPSET(conflicts, p2); } } } } if (s->requires) { reqp = s->repo->idarraydata + s->requires; while ((req = *reqp++) != 0) { if (req == SOLVABLE_PREREQMARKER) continue; id = id2name(pool, req); if (!xp->ignoreignore) { if (MAPTST(&xp->ignored, id)) continue; if (MAPTST(&xp->ignoredx, id)) { Id xid = pool_str2id(pool, pool_tmpjoin(pool, pool_id2str(pool, s->name), ":", pool_id2str(pool, id)), 0); if (xid && MAPTST(&xp->ignored, xid)) continue; } } n = pool_id2str(pool, id); if (!strncmp(n, "rpmlib(", 7)) { MAPEXP(&xp->ignored, id); MAPSET(&xp->ignored, id); continue; } if (*n == '/') { if (!xp->havefileprovides || pool->whatprovides[id] <= 1) { MAPEXP(&xp->ignored, id); MAPSET(&xp->ignored, id); continue; } } queue_push2(todo, req, p); } } if (!xp->ignoreconflicts) { if (s->conflicts) { conp = s->repo->idarraydata + s->conflicts; while ((con = *conp++) != 0) { Id p2, pp2; FOR_PROVIDES(p2, pp2, con) { if (p2 == p) continue; MAPEXP(conflicts, pool->nsolvables); MAPSET(conflicts, p2); if (xp->debug) queue_push2(conflictsinfo, p2, p); } } } if (s->obsoletes) { conp = s->repo->idarraydata + s->obsoletes; while ((con = *conp++) != 0) { Id p2, pp2; FOR_PROVIDES(p2, pp2, con) { if (p2 == p || !pool_match_nevr(pool, pool->solvables + p2, con)) continue; MAPEXP(conflicts, pool->nsolvables); MAPSET(conflicts, p2); if (xp->debug) queue_push2(conflictsinfo, p2, -p); } } } if (xp->debug) *cidone = out->count; } } static inline int expander_checkconflicts(Expander *xp, Id p, Map *installed, Id *conflicts, int isobsoletes) { Pool *pool = xp->pool; Id con, p2, pp2; if (xp->ignoreconflicts) return 0; while ((con = *conflicts++) != 0) { FOR_PROVIDES(p2, pp2, con) { if (p == p2) continue; if (isobsoletes && !pool_match_nevr(pool, pool->solvables + p2, con)) continue; if (MAPTST(installed, p2)) return p2; } } return 0; } static void expander_updateconflictsinfo(Expander *xp, Queue *conflictsinfo, int *cidone, Queue *out) { Pool *pool = xp->pool; int i; if (xp->ignoreconflicts) return; for (i = *cidone; i < out->count; i++) { Id p, p2, pp2; Id con, *conp; Solvable *s; p = out->elements[i]; s = pool->solvables + p; /* keep in sync with expander_installed! */ if (s->conflicts) { conp = s->repo->idarraydata + s->conflicts; while ((con = *conp++) != 0) { FOR_PROVIDES(p2, pp2, con) { if (p2 == p) continue; queue_push2(conflictsinfo, p2, p); } } } if (s->obsoletes) { conp = s->repo->idarraydata + s->obsoletes; while ((con = *conp++) != 0) { FOR_PROVIDES(p2, pp2, con) { if (p2 == p || !pool_match_nevr(pool, pool->solvables + p2, con)) continue; queue_push2(conflictsinfo, p2, -p); } } } } *cidone = out->count; } static inline int findconflictsinfo(Queue *conflictsinfo, Id p) { int i; for (i = 0; i < conflictsinfo->count; i++) if (conflictsinfo->elements[i] == p) return conflictsinfo->elements[i + 1]; return 0; } #define ERROR_NOPROVIDER 1 #define ERROR_CHOICE 2 #define ERROR_CONFLICTINGPROVIDER 3 #define ERROR_CONFLICTINGPROVIDERS 4 #define ERROR_PROVIDERINFO 5 #define ERROR_PROVIDERINFO2 6 int expander_expand(Expander *xp, Queue *in, Queue *out, Queue *inconfl) { Pool *pool = xp->pool; Queue todo, errors, cerrors, qq, posfoundq; Map installed; Map conflicts; Queue conflictsinfo; int cidone; Solvable *s; Id q, p, pp; int i, j, nerrors, doamb, ambcnt; Id id, who, whon, pn; Id conflprov, conflprovpc; map_init(&installed, pool->nsolvables); map_init(&conflicts, 0); queue_init(&conflictsinfo); queue_init(&todo); queue_init(&qq); queue_init(&errors); queue_init(&cerrors); queue_init(&posfoundq); queue_empty(out); cidone = 0; if (inconfl) { for (i = 0; i < inconfl->count; i += 2) { Id con = inconfl->elements[i]; FOR_PROVIDES(p, pp, con) { if (inconfl->elements[i + 1] && !pool_match_nevr(pool, pool->solvables + p, con)) continue; MAPEXP(&conflicts, pool->nsolvables); MAPSET(&conflicts, p); } } } /* do direct expands */ for (i = 0; i < in->count; i++) { id = in->elements[i]; if (id == expander_directdepsend) { for (i = i + 1; i < in->count; i++) if (in->elements[i] != expander_directdepsend) queue_push2(&todo, in->elements[i], 0); break; } q = 0; FOR_PROVIDES(p, pp, id) { s = pool->solvables + p; if (!pool_match_nevr(pool, s, id)) continue; if (q) { q = 0; break; } q = p; } if (!q) { /* unclear, resolve later */ queue_push2(&todo, id, 0); continue; } if (MAPTST(&installed, q)) continue; if (conflicts.size && MAPTST(&conflicts, q)) { queue_push(&errors, ERROR_CONFLICTINGPROVIDER); queue_push2(&errors, id, 0); if (cidone < out->count) expander_updateconflictsinfo(xp, &conflictsinfo, &cidone, out); queue_push(&errors, ERROR_PROVIDERINFO2); queue_push2(&errors, q, findconflictsinfo(&conflictsinfo, q)); continue; } if (pool->solvables[q].conflicts && (pp = expander_checkconflicts(xp, q, &installed, pool->solvables[q].repo->idarraydata + pool->solvables[q].conflicts, 0)) != 0) { queue_push(&errors, ERROR_CONFLICTINGPROVIDER); queue_push2(&errors, id, 0); queue_push(&errors, ERROR_PROVIDERINFO); queue_push2(&errors, q, pp); continue; } if (pool->solvables[q].obsoletes && (pp = expander_checkconflicts(xp, q, &installed, pool->solvables[q].repo->idarraydata + pool->solvables[q].obsoletes, 1)) != 0) { queue_push(&errors, ERROR_CONFLICTINGPROVIDER); queue_push2(&errors, id, 0); queue_push(&errors, ERROR_PROVIDERINFO); queue_push2(&errors, q, -pp); continue; } if (xp->debug) expander_dbg(xp, "added %s because of %s (direct dep)\n", expander_solvid2name(xp, q), pool_dep2str(pool, id)); expander_installed(xp, q, &installed, &conflicts, &conflictsinfo, &cidone, out, &todo); /* unique match! */ } doamb = 0; ambcnt = todo.count; while (todo.count) { id = queue_shift(&todo); who = queue_shift(&todo); if (ambcnt == 0) { if (doamb) break; /* amb pass had no progress, stop */ if (xp->debug) expander_dbg(xp, "now doing undecided dependencies\n"); doamb = 1; /* start amb pass */ ambcnt = todo.count; } else ambcnt -= 2; // printf("todo %s %s ambcnt %d\n", pool_id2str(pool, pool->solvables[who].name), pool_dep2str(pool, id), ambcnt); // fflush(stdout); whon = who ? pool->solvables[who].name : 0; queue_empty(&qq); conflprov = 0; conflprovpc = 0; FOR_PROVIDES(p, pp, id) { Id pc; if (MAPTST(&installed, p)) break; if (who && !xp->ignoreignore) { Id pn = pool->solvables[p].name; if (MAPTST(&xp->ignored, pn)) break; if (MAPTST(&xp->ignoredx, pn)) { Id xid = pool_str2id(pool, pool_tmpjoin(pool, pool_id2str(pool, whon), ":", pool_id2str(pool, pn)), 0); if (xid && MAPTST(&xp->ignored, xid)) break; } } if (conflicts.size && MAPTST(&conflicts, p)) { if (xp->debug) { Id pc = findconflictsinfo(&conflictsinfo, p); if (pc) expander_dbg(xp, "ignoring provider %s of %s because installed %s %s it\n", pool_solvid2str(pool, p), pool_dep2str(pool, id), pool_solvid2str(pool, pc > 0 ? pc : -pc), pc > 0 ? "conflicts with" : "obsoletes"); else expander_dbg(xp, "ignoring conflicted provider %s of %s\n", pool_solvid2str(pool, p), pool_dep2str(pool, id)); } conflprov = conflprov ? 1 : p; conflprovpc = 0; continue; } if (pool->solvables[p].conflicts && (pc = expander_checkconflicts(xp, p, &installed, pool->solvables[p].repo->idarraydata + pool->solvables[p].conflicts, 0)) != 0) { expander_dbg(xp, "ignoring provider %s of %s because it conflicts with installed %s\n", pool_solvid2str(pool, p), pool_dep2str(pool, id), pool_solvid2str(pool, pc)); conflprov = conflprov ? 1 : p; conflprovpc = pc; continue; } if (pool->solvables[p].obsoletes && (pc = expander_checkconflicts(xp, p, &installed, pool->solvables[p].repo->idarraydata + pool->solvables[p].obsoletes, 1)) != 0) { expander_dbg(xp, "ignoring provider %s of %s because it obsoletes installed %s\n", pool_solvid2str(pool, p), pool_dep2str(pool, id), pool_solvid2str(pool, pc)); conflprov = conflprov ? 1 : p; conflprovpc = -pc; continue; } queue_push(&qq, p); } if (p) continue; if (qq.count == 0) { if (!conflprov) { queue_push(&errors, ERROR_NOPROVIDER); queue_push2(&errors, id, who); continue; } /* more work for conflicts */ if (conflprov != 1) { /* nice, just one provider */ queue_push(&errors, ERROR_CONFLICTINGPROVIDER); queue_push2(&errors, id, who); if (!conflprovpc) { if (cidone < out->count) expander_updateconflictsinfo(xp, &conflictsinfo, &cidone, out); conflprovpc = findconflictsinfo(&conflictsinfo, conflprov); queue_push(&errors, ERROR_PROVIDERINFO2); queue_push2(&errors, conflprov, conflprovpc); } else { queue_push(&errors, ERROR_PROVIDERINFO); queue_push2(&errors, conflprov, conflprovpc); } continue; } /* even more work if all providers conflict */ queue_push(&errors, ERROR_CONFLICTINGPROVIDERS); queue_push2(&errors, id, who); if (cidone < out->count) expander_updateconflictsinfo(xp, &conflictsinfo, &cidone, out); FOR_PROVIDES(p, pp, id) { Id pc; if (conflicts.size && MAPTST(&conflicts, p)) { pc = findconflictsinfo(&conflictsinfo, p); queue_push(&errors, ERROR_PROVIDERINFO2); queue_push2(&errors, p, pc); continue; } if (pool->solvables[p].conflicts && (pc = expander_checkconflicts(xp, p, &installed, pool->solvables[p].repo->idarraydata + pool->solvables[p].conflicts, 0)) != 0) { queue_push(&errors, ERROR_PROVIDERINFO); queue_push2(&errors, p, pc); continue; } if (pool->solvables[p].obsoletes && (pc = expander_checkconflicts(xp, p, &installed, pool->solvables[p].repo->idarraydata + pool->solvables[p].obsoletes, 1)) != 0) { queue_push(&errors, ERROR_PROVIDERINFO); queue_push2(&errors, p, -pc); continue; } } continue; } if (qq.count > 1 && !doamb) { /* try again later */ queue_push2(&todo, id, who); if (xp->debug) { expander_dbg(xp, "undecided about %s:%s:", whon ? pool_id2str(pool, whon) : "(direct)", pool_dep2str(pool, id)); for (i = 0; i < qq.count; i++) expander_dbg(xp, " %s", expander_solvid2name(xp, qq.elements[i])); expander_dbg(xp, "\n"); } continue; } /* prune neg prefers */ if (qq.count > 1) { for (i = j = 0; i < qq.count; i++) { p = qq.elements[i]; pn = pool->solvables[p].name; if (MAPTST(&xp->preferneg, pn)) continue; if (who && MAPTST(&xp->prefernegx, pn)) { Id xid = pool_str2id(pool, pool_tmpjoin(pool, pool_id2str(pool, whon), ":", pool_id2str(pool, pn)), 0); if (xid && MAPTST(&xp->preferneg, xid)) continue; } qq.elements[j++] = p; } if (j) queue_truncate(&qq, j); } /* prune pos prefers */ if (qq.count > 1) { queue_empty(&posfoundq); for (i = j = 0; i < qq.count; i++) { p = qq.elements[i]; pn = pool->solvables[p].name; if (MAPTST(&xp->preferpos, pn)) { queue_push2(&posfoundq, pn, p); qq.elements[j++] = p; continue; } if (who && MAPTST(&xp->preferposx, pn)) { Id xid = pool_str2id(pool, pool_tmpjoin(pool, pool_id2str(pool, whon), ":", pool_id2str(pool, pn)), 0); if (xid && MAPTST(&xp->preferpos, xid)) { queue_push2(&posfoundq, xid, p); qq.elements[j++] = p; continue; } } } if (posfoundq.count == 2) { queue_empty(&qq); queue_push(&qq, posfoundq.elements[1]); } else if (posfoundq.count) { /* found a pos prefer, now find first hit */ /* (prefers are ordered) */ for (i = 0; i < xp->preferposq.count; i++) { Id xid = xp->preferposq.elements[i]; for (j = 0; j < posfoundq.count; j += 2) if (posfoundq.elements[j] == xid) break; if (j < posfoundq.count) { queue_empty(&qq); queue_push(&qq, posfoundq.elements[j + 1]); break; } } } } /* prune OR deps */ if (qq.count > 1 && ISRELDEP(id) && GETRELDEP(pool, id)->flags == REL_OR) { Id rid = id; for (;;) { Reldep *rd = 0; if (ISRELDEP(rid)) { rd = GETRELDEP(pool, rid); if (rd->flags != REL_OR) rd = 0; } if (rd) rid = rd->name; queue_empty(&qq); FOR_PROVIDES(p, pp, rid) queue_push(&qq, p); if (qq.count) break; if (rd) rid = rd->evr; else break; } } if (qq.count > 1) { queue_push(&cerrors, ERROR_CHOICE); queue_push2(&cerrors, id, who); for (i = 0; i < qq.count; i++) queue_push(&cerrors, qq.elements[i]); queue_push(&cerrors, 0); /* try again later */ queue_push2(&todo, id, who); continue; } if (xp->debug) expander_dbg(xp, "added %s because of %s:%s\n", expander_solvid2name(xp, qq.elements[0]), whon ? pool_id2str(pool, whon) : "(direct)", pool_dep2str(pool, id)); expander_installed(xp, qq.elements[0], &installed, &conflicts, &conflictsinfo, &cidone, out, &todo); doamb = 0; ambcnt = todo.count; queue_empty(&cerrors); } map_free(&installed); map_free(&conflicts); queue_free(&conflictsinfo); nerrors = 0; if (errors.count || cerrors.count) { queue_empty(out); for (i = 0; i < errors.count; i += 3) { queue_push(out, errors.elements[i]); queue_push(out, errors.elements[i + 1]); queue_push(out, errors.elements[i + 2]); nerrors++; } for (i = 0; i < cerrors.count; ) { queue_push(out, cerrors.elements[i]); queue_push(out, cerrors.elements[i + 1]); queue_push(out, cerrors.elements[i + 2]); i += 3; while (cerrors.elements[i]) { queue_push(out, cerrors.elements[i]); i++; } queue_push(out, 0); i++; nerrors++; } } else { if (todo.count) { fprintf(stderr, "Internal expansion error!\n"); queue_empty(out); queue_push(out, ERROR_NOPROVIDER); queue_push(out, 0); queue_push(out, 0); } } queue_free(&todo); queue_free(&qq); queue_free(&errors); queue_free(&cerrors); queue_free(&posfoundq); return nerrors; } static void set_disttype(Pool *pool, int disttype) { pool_setdisttype(pool, disttype); #ifdef POOL_FLAG_HAVEDISTEPOCH /* make newer mandriva work, hopefully there are no ill effects... */ pool_set_flag(pool, POOL_FLAG_HAVEDISTEPOCH, disttype == DISTTYPE_RPM ? 1 : 0); #endif } static void set_disttype_from_location(Pool *pool, Solvable *so) { unsigned int medianr; const char *s = solvable_get_location(so, &medianr); int disttype = -1; int sl; if (!s) return; sl = strlen(s); if (disttype < 0 && sl >= 4 && !strcmp(s + sl - 4, ".rpm")) disttype = DISTTYPE_RPM; #ifdef DISTTYPE_DEB if (disttype < 0 && sl >= 4 && !strcmp(s + sl - 4, ".deb")) disttype = DISTTYPE_DEB; #endif #ifdef DISTTYPE_ARCH if (disttype < 0 && sl >= 11 && (!strcmp(s + sl - 11, ".pkg.tar.gz") || !strcmp(s + sl - 11, ".pkg.tar.xz"))) disttype = DISTTYPE_ARCH; #endif if (disttype >= 0 && pool->disttype != disttype) set_disttype(pool, disttype); } void create_considered(Pool *pool, Repo *repoonly, Map *considered) { Id p, pb,*best; Solvable *s, *sb; int ridx; Repo *repo; int olddisttype = -1; int dodrepo; map_init(considered, pool->nsolvables); best = solv_calloc(sizeof(Id), pool->ss.nstrings); FOR_REPOS(ridx, repo) { if (repoonly && repo != repoonly) continue; dodrepo = repo_lookup_str(repo, SOLVID_META, buildservice_dodurl) != 0; FOR_REPO_SOLVABLES(repo, p, s) { if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC) continue; pb = best[s->name]; if (pb) { sb = pool->solvables + pb; if (s->repo != sb->repo) continue; /* first repo wins */ if (s->arch != sb->arch) { int r; if (s->arch == ARCH_NOARCH || s->arch == ARCH_ALL || s->arch == ARCH_ANY) continue; if (sb->arch != ARCH_NOARCH && sb->arch != ARCH_ALL && sb->arch != ARCH_ANY) { /* the strcmp is kind of silly, but works for most archs */ r = strcmp(pool_id2str(pool, sb->arch), pool_id2str(pool, s->arch)); if (r >= 0) continue; } } else if (s->evr != sb->evr) { /* same repo, check versions */ int r; if (olddisttype < 0) { olddisttype = pool->disttype; set_disttype_from_location(pool, s); } r = pool_evrcmp(pool, sb->evr, s->evr, EVRCMP_COMPARE); if (r > 0) continue; else if (r == 0) { r = strcmp(pool_id2str(pool, sb->evr), pool_id2str(pool, s->evr)); if (r >= 0) continue; } } } if (dodrepo) { /* we only consider dod packages */ const char *bsid = solvable_lookup_str(s, buildservice_id); if (!bsid || strcmp(bsid, "dod") != 0) continue; } if (pb) MAPCLR(considered, pb); best[s->name] = p; MAPSET(considered, p); } /* dodrepos have a second pass: replace dod entries with downloaded ones */ if (dodrepo) { const char *bsid; FOR_REPO_SOLVABLES(repo, p, s) { if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC) continue; pb = best[s->name]; if (!pb || pb == p) continue; sb = pool->solvables + pb; if (sb->repo != s->repo || sb->name != s->name || sb->arch != s->arch || sb->evr != s->evr) continue; bsid = solvable_lookup_str(s, buildservice_id); if (bsid && strcmp(bsid, "dod") == 0) continue; /* not downloaded */ MAPCLR(considered, pb); best[s->name] = p; MAPSET(considered, p); } } } solv_free(best); if (olddisttype >= 0 && pool->disttype != olddisttype) set_disttype(pool, olddisttype); } struct metaline { char *l; int lastoff; int nslash; int killed; }; static int metacmp(const void *ap, const void *bp) { const struct metaline *a, *b; int r; a = ap; b = bp; r = a->nslash - b->nslash; if (r) return r; r = strcmp(a->l + 34, b->l + 34); if (r) return r; r = strcmp(a->l, b->l); if (r) return r; return a - b; } #ifndef REPO_NO_LOCATION # define REPO_NO_LOCATION 0 #endif Id repodata_addbin(Repodata *data, char *prefix, char *s, int sl, char *sid) { Id p = 0; char *path; #if REPO_NO_LOCATION == 0 char *sp; #endif path = solv_dupjoin(prefix, "/", s); if (sl >= 4 && !strcmp(s + sl - 4, ".rpm")) p = repo_add_rpm(data->repo, (const char *)path, REPO_REUSE_REPODATA|REPO_NO_INTERNALIZE|REPO_NO_LOCATION|RPM_ADD_WITH_PKGID|RPM_ADD_NO_FILELIST|RPM_ADD_NO_RPMLIBREQS); else if (sl >= 4 && !strcmp(s + sl - 4, ".deb")) p = repo_add_deb(data->repo, (const char *)path, REPO_REUSE_REPODATA|REPO_NO_INTERNALIZE|REPO_NO_LOCATION|DEBS_ADD_WITH_PKGID); #ifdef ARCH_ADD_WITH_PKGID else if (sl >= 11 && (!strcmp(s + sl - 11, ".pkg.tar.gz") || !strcmp(s + sl - 11, ".pkg.tar.xz"))) p = repo_add_arch_pkg(data->repo, (const char *)path, REPO_REUSE_REPODATA|REPO_NO_INTERNALIZE|REPO_NO_LOCATION|ARCH_ADD_WITH_PKGID); #endif solv_free(path); if (!p) return 0; #if REPO_NO_LOCATION != 0 repodata_set_location(data, p, 0, 0, s); #else if ((sp = strrchr(s, '/')) != 0) { *sp = 0; repodata_set_str(data, p, SOLVABLE_MEDIADIR, s); *sp = '/'; } else repodata_delete_uninternalized(data, p, SOLVABLE_MEDIADIR); #endif repodata_set_str(data, p, buildservice_id, sid); return p; } MODULE = BSSolv PACKAGE = BSSolv void depsort(HV *deps, SV *mapp, SV *cycp, ...) PPCODE: { int i, j, k, cy, cycstart, nv; SV *sv, **svp; Id id, *e; Id *mark; char **names; Hashtable ht; Hashval h, hh, hm; HV *mhv = 0; Queue edata; Queue vedge; Queue todo; Queue cycles; if (items == 3) XSRETURN_EMPTY; /* nothing to sort */ if (items == 4) { /* only one item */ char *s = SvPV_nolen(ST(2)); EXTEND(SP, 1); sv = newSVpv(s, 0); PUSHs(sv_2mortal(sv)); XSRETURN(1); /* nothing to sort */ } if (mapp && SvROK(mapp) && SvTYPE(SvRV(mapp)) == SVt_PVHV) mhv = (HV *)SvRV(mapp); queue_init(&edata); queue_init(&vedge); queue_init(&todo); queue_init(&cycles); hm = mkmask(items); ht = solv_calloc(hm + 1, sizeof(*ht)); names = solv_calloc(items, sizeof(char *)); nv = 1; for (i = 3; i < items; i++) { char *s = SvPV_nolen(ST(i)); h = strhash(s) & hm; hh = HASHCHAIN_START; while ((id = ht[h]) != 0) { if (!strcmp(names[id], s)) break; h = HASHCHAIN_NEXT(h, hh, hm); } if (id) continue; /* had that one before, ignore */ id = nv++; ht[h] = id; names[id] = s; } /* we now know all vertices, create edges */ queue_push(&vedge, 0); queue_push(&edata, 0); for (i = 1; i < nv; i++) { svp = hv_fetch(deps, names[i], strlen(names[i]), 0); sv = svp ? *svp : 0; queue_push(&vedge, edata.count); if (sv && SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVAV) { AV *av = (AV *)SvRV(sv); for (j = 0; j <= av_len(av); j++) { char *s; STRLEN slen; svp = av_fetch(av, j, 0); if (!svp) continue; sv = *svp; s = SvPV(sv, slen); if (!s) continue; if (mhv) { /* look up in dep map */ svp = hv_fetch(mhv, s, slen, 0); if (svp) { s = SvPV(*svp, slen); if (!s) continue; } } /* look up in hash */ h = strhash(s) & hm; hh = HASHCHAIN_START; while ((id = ht[h]) != 0) { if (!strcmp(names[id], s)) break; h = HASHCHAIN_NEXT(h, hh, hm); } if (!id) continue; /* not known, ignore */ if (id == i) continue; /* no self edge */ queue_push(&edata, id); } } queue_push(&edata, 0); } solv_free(ht); if (0) { printf("vertexes: %d\n", vedge.count - 1); for (i = 1; i < vedge.count; i++) { printf("%d %s:", i, names[i]); Id *e = edata.elements + vedge.elements[i]; for (; *e; e++) printf(" %d", *e); printf("\n"); } } /* now everything is set up, sort em! */ mark = solv_calloc(vedge.count, sizeof(Id)); for (i = vedge.count - 1; i; i--) queue_push(&todo, i); EXTEND(SP, vedge.count - 1); while (todo.count) { i = queue_pop(&todo); // printf("check %d\n", i); if (i < 0) { i = -i; mark[i] = 2; sv = newSVpv(names[i], 0); PUSHs(sv_2mortal(sv)); continue; } if (mark[i] == 2) continue; if (mark[i] == 0) { int edgestovisit = 0; Id *e = edata.elements + vedge.elements[i]; for (; *e; e++) { if (*e == -1) continue; /* broken */ if (mark[*e] == 2) continue; if (!edgestovisit++) queue_push(&todo, -i); queue_push(&todo, *e); } if (!edgestovisit) { mark[i] = 2; sv = newSVpv(names[i], 0); PUSHs(sv_2mortal(sv)); } else mark[i] = 1; continue; } /* oh no, we found a cycle, record and break it */ cy = cycles.count; for (j = todo.count - 1; j >= 0; j--) if (todo.elements[j] == -i) break; cycstart = j; // printf("cycle:\n"); for (j = cycstart; j < todo.count; j++) if (todo.elements[j] < 0) { k = -todo.elements[j]; mark[k] = 0; queue_push(&cycles, k); // printf(" %d\n", k); } queue_push(&cycles, 0); todo.elements[cycstart] = i; /* break it */ for (k = cy; cycles.elements[k]; k++) ; if (!cycles.elements[k]) k = cy; j = cycles.elements[k + 1] ? cycles.elements[k + 1] : cycles.elements[cy]; k = cycles.elements[k]; /* breaking edge from k -> j */ // printf("break %d -> %d\n", k, j); e = edata.elements + vedge.elements[k]; for (; *e; e++) if (*e == j) break; if (!*e) abort(); *e = -1; todo.count = cycstart + 1; } /* recored cycles */ if (cycles.count && cycp && SvROK(cycp) && SvTYPE(SvRV(cycp)) == SVt_PVAV) { AV *av = (AV *)SvRV(cycp); for (i = 0; i < cycles.count;) { AV *av2 = newAV(); for (; cycles.elements[i]; i++) { SV *sv = newSVpv(names[cycles.elements[i]], 0); av_push(av2, sv); } av_push(av, newRV_noinc((SV*)av2)); i++; } } queue_free(&cycles); queue_free(&edata); queue_free(&vedge); queue_free(&todo); solv_free(mark); solv_free(names); } void gen_meta(AV *subp, ...) PPCODE: { Hashtable ht; Hashval h, hh, hm; char **subpacks; struct metaline *lines, *lp; int nlines; int i, j, cycle, ns; char *s, *s2, *lo; Id id; Queue cycles; Id cycles_buf[64]; if (items == 1) XSRETURN_EMPTY; /* nothing to generate */ queue_init_buffer(&cycles, cycles_buf, sizeof(cycles_buf)/sizeof(*cycles_buf)); hm = mkmask(av_len(subp) + 2); ht = solv_calloc(hm + 1, sizeof(*ht)); subpacks = solv_calloc(av_len(subp) + 2, sizeof(char *)); for (j = 0; j <= av_len(subp); j++) { SV **svp = av_fetch(subp, j, 0); if (!svp) continue; s = SvPV_nolen(*svp); h = strhash(s) & hm; hh = HASHCHAIN_START; while ((id = ht[h]) != 0) h = HASHCHAIN_NEXT(h, hh, hm); ht[h] = j + 1; subpacks[j + 1] = s; } lines = solv_calloc(items - 1, sizeof(*lines)); nlines = items - 1; /* lines are of the form "md5sum pkg/pkg..." */ for (i = 0, lp = lines; i < nlines; i++, lp++) { s = SvPV_nolen(ST(i + 1)); if (strlen(s) < 35 || s[32] != ' ' || s[33] != ' ') croak("gen_meta: bad line %s\n", s); /* count '/' */ lp->l = s; ns = 0; cycle = 0; lo = s + 34; for (s2 = lo; *s2; s2++) if (*s2 == '/') { if (!cycle) { *s2 = 0; h = strhash(lo) & hm; hh = HASHCHAIN_START; while ((id = ht[h]) != 0) { if (!strcmp(lo, subpacks[id])) break; h = HASHCHAIN_NEXT(h, hh, hm); } *s2 = '/'; if (id) cycle = 1 + ns; } ns++; lo = s2 + 1; } if (!cycle) { h = strhash(lo) & hm; hh = HASHCHAIN_START; while ((id = ht[h]) != 0) { if (!strcmp(lo, subpacks[id])) break; h = HASHCHAIN_NEXT(h, hh, hm); } if (id) cycle = 1 + ns; } if (cycle) { lp->killed = 1; if (cycle > 1) /* ignore self cycles */ queue_push(&cycles, i); } lp->nslash = ns; lp->lastoff = lo - s; } solv_free(ht); solv_free(subpacks); /* if we found cycles, prune em */ if (cycles.count) { char *cycledata = 0; int cycledatalen = 0; cycledata = solv_extend(cycledata, cycledatalen, 1, 1, 255); cycledata[0] = 0; cycledatalen += 1; hm = mkmask(cycles.count); ht = solv_calloc(hm + 1, sizeof(*ht)); for (i = 0; i < cycles.count; i++) { char *se; s = lines[cycles.elements[i]].l + 34; se = strchr(s, '/'); if (se) *se = 0; h = strhash(s) & hm; hh = HASHCHAIN_START; while ((id = ht[h]) != 0) { if (!strcmp(s, cycledata + id)) break; h = HASHCHAIN_NEXT(h, hh, hm); } if (id) continue; cycledata = solv_extend(cycledata, cycledatalen, strlen(s) + 1, 1, 255); ht[h] = cycledatalen; strcpy(cycledata + cycledatalen, s); cycledatalen += strlen(s) + 1; if (se) *se = '/'; } for (i = 0, lp = lines; i < nlines; i++, lp++) { if (lp->killed || !lp->nslash) continue; lo = strchr(lp->l + 34, '/') + 1; for (s2 = lo; *s2; s2++) if (*s2 == '/') { *s2 = 0; h = strhash(lo) & hm; hh = HASHCHAIN_START; while ((id = ht[h]) != 0) { if (!strcmp(lo, cycledata + id)) break; h = HASHCHAIN_NEXT(h, hh, hm); } *s2 = '/'; if (id) { lp->killed = 1; break; } lo = s2 + 1; } if (lp->killed) continue; h = strhash(lo) & hm; hh = HASHCHAIN_START; while ((id = ht[h]) != 0) { if (!strcmp(lo, cycledata + id)) break; h = HASHCHAIN_NEXT(h, hh, hm); } if (id) { lp->killed = 1; } } solv_free(ht); cycledata = solv_free(cycledata); queue_free(&cycles); } /* cycles are pruned, now sort array */ if (nlines > 1) qsort(lines, nlines, sizeof(*lines), metacmp); hm = mkmask(nlines); ht = solv_calloc(hm + 1, sizeof(*ht)); for (i = 0, lp = lines; i < nlines; i++, lp++) { if (lp->killed) continue; s = lp->l; h = strnhash(s, 10); h = strhash_cont(s + lp->lastoff, h) & hm; hh = HASHCHAIN_START; while ((id = ht[h]) != 0) { struct metaline *lp2 = lines + (id - 1); if (!strncmp(lp->l, lp2->l, 32) && !strcmp(lp->l + lp->lastoff, lp2->l + lp2->lastoff)) break; h = HASHCHAIN_NEXT(h, hh, hm); } if (id) lp->killed = 1; else ht[h] = i + 1; } solv_free(ht); j = 0; for (i = 0, lp = lines; i < nlines; i++, lp++) if (!lp->killed) j++; EXTEND(SP, j); for (i = 0, lp = lines; i < nlines; i++, lp++) { SV *sv; if (lp->killed) continue; sv = newSVpv(lp->l, 0); PUSHs(sv_2mortal(sv)); } solv_free(lines); } SV * thawcache(SV *sv) CODE: unsigned char *src; STRLEN srcl; if (!SvPOK(sv)) { croak("thaw: argument is not a string\n"); XSRETURN_UNDEF; } src = (unsigned char *)SvPV(sv, srcl); if (srcl < 7 || src[0] != 'p' || src[1] != 's' || src[2] != 't' || src[3] != '0') { croak("thaw: argument is not a perl storable\n"); XSRETURN_UNDEF; } if ((src[4] & 1) != 1) { croak("thaw: argument is not a perl storable in network order\n"); XSRETURN_UNDEF; } if (src[4] < 5) { croak("thaw: argument is a perl storable with a too old version\n"); XSRETURN_UNDEF; } src += 6; srcl -= 6; sv = retrieve(&src, &srcl, 0); if (sv == 0 || srcl) { croak("thaw: corrupt storable\n"); XSRETURN_UNDEF; } RETVAL = newRV_noinc(sv); OUTPUT: RETVAL MODULE = BSSolv PACKAGE = BSSolv::pool PREFIX = pool PROTOTYPES: ENABLE BSSolv::pool new(char *packname = "BSSolv::pool") CODE: { Pool *pool = pool_create(); set_disttype(pool, DISTTYPE_RPM); buildservice_id = pool_str2id(pool, "buildservice:id", 1); buildservice_repocookie= pool_str2id(pool, "buildservice:repocookie", 1); buildservice_external = pool_str2id(pool, "buildservice:external", 1); buildservice_dodurl = pool_str2id(pool, "buildservice:dodurl", 1); expander_directdepsend = pool_str2id(pool, "-directdepsend--", 1); buildservice_dodcookie = pool_str2id(pool, "buildservice:dodcookie", 1); pool_freeidhashes(pool); RETVAL = pool; } OUTPUT: RETVAL void settype(BSSolv::pool pool, char *type) CODE: if (!strcmp(type, "rpm")) set_disttype(pool, DISTTYPE_RPM); #ifdef DISTTYPE_DEB else if (!strcmp(type, "deb")) set_disttype(pool, DISTTYPE_DEB); #endif #ifdef DISTTYPE_ARCH else if (!strcmp(type, "arch")) set_disttype(pool, DISTTYPE_ARCH); #endif else croak("settype: unknown type '%s'\n", type); BSSolv::repo repofromfile(BSSolv::pool pool, char *name, char *filename) CODE: FILE *fp; fp = fopen(filename, "r"); if (!fp) { croak("%s: %s\n", filename, Strerror(errno)); XSRETURN_UNDEF; } RETVAL = repo_create(pool, name); repo_add_solv(RETVAL, fp, 0); fclose(fp); OUTPUT: RETVAL BSSolv::repo repofromstr(BSSolv::pool pool, char *name, SV *sv) CODE: FILE *fp; STRLEN len; char *buf; buf = SvPV(sv, len); if (!buf) croak("repofromstr: undef string\n"); fp = fmemopen(buf, len, "r"); if (!fp) { croak("fmemopen failed\n"); XSRETURN_UNDEF; } RETVAL = repo_create(pool, name); repo_add_solv(RETVAL, fp, 0); fclose(fp); OUTPUT: RETVAL BSSolv::repo repofrombins(BSSolv::pool pool, char *name, char *dir, ...) CODE: { int i; Repo *repo; Repodata *data; repo = repo_create(pool, name); data = repo_add_repodata(repo, 0); for (i = 3; i + 1 < items; i += 2) { STRLEN sl; char *s = SvPV(ST(i), sl); char *sid = SvPV_nolen(ST(i + 1)); if (sl < 4) continue; if (strcmp(s + sl - 4, ".rpm") && strcmp(s + sl - 4, ".deb") #ifdef ARCH_ADD_WITH_PKGID && (sl < 11 || strcmp(s + sl - 11, ".pkg.tar.gz")) && (sl < 11 || strcmp(s + sl - 11, ".pkg.tar.xz")) #endif ) continue; if (sl >= 10 && !strcmp(s + sl - 10, ".patch.rpm")) continue; if (sl >= 10 && !strcmp(s + sl - 10, ".nosrc.rpm")) continue; if (sl >= 8 && !strcmp(s + sl - 8, ".src.rpm")) continue; repodata_addbin(data, dir, s, (int)sl, sid); } repo_set_str(repo, SOLVID_META, buildservice_repocookie, REPOCOOKIE); repo_internalize(repo); RETVAL = repo; } OUTPUT: RETVAL BSSolv::repo repofromdata(BSSolv::pool pool, char *name, HV *rhv) CODE: { Repo *repo; Repodata *data; repo = repo_create(pool, name); data = repo_add_repodata(repo, 0); data2solvables(repo, data, rhv); if (name && !strcmp(name, "/external/")) repodata_set_void(data, SOLVID_META, buildservice_external); repo_internalize(repo); RETVAL = repo; } OUTPUT: RETVAL void createwhatprovides(BSSolv::pool pool) CODE: if (pool->considered) { map_free(pool->considered); solv_free(pool->considered); } pool->considered = solv_calloc(sizeof(Map), 1); create_considered(pool, 0, pool->considered); pool_createwhatprovides(pool); void setdebuglevel(BSSolv::pool pool, int level) CODE: pool_setdebuglevel(pool, level); void whatprovides(BSSolv::pool pool, char *str) PPCODE: { Id p, pp, id; id = dep2id(pool, str); if (id) FOR_PROVIDES(p, pp, id) XPUSHs(sv_2mortal(newSViv((IV)p))); } void whatrequires(BSSolv::pool pool, char *str) PPCODE: { Id p, id; Id *pp; Solvable *s; id = dep2id(pool, str); if (id) { for (p = 2; p < pool->nsolvables; p++) { if (!MAPTST(pool->considered, p)) continue; s = pool->solvables + p; if (!s->requires) continue; for (pp = s->repo->idarraydata + s->requires; *pp; pp++) if (pool_match_dep(pool, id, *pp)) break; if (*pp) XPUSHs(sv_2mortal(newSViv((IV)p))); } } } void consideredpackages(BSSolv::pool pool) PPCODE: { int p, nsolv = 0; for (p = 2; p < pool->nsolvables; p++) if (MAPTST(pool->considered, p)) nsolv++; EXTEND(SP, nsolv); for (p = 2; p < pool->nsolvables; p++) if (MAPTST(pool->considered, p)) PUSHs(sv_2mortal(newSViv((IV)p))); } void allpackages(BSSolv::pool pool) PPCODE: { int p, nsolv = 0; for (p = 2; p < pool->nsolvables; p++) if (pool->solvables[p].repo) nsolv++; EXTEND(SP, nsolv); for (p = 2; p < pool->nsolvables; p++) if (pool->solvables[p].repo) PUSHs(sv_2mortal(newSViv((IV)p))); } const char * pkg2name(BSSolv::pool pool, int p) CODE: RETVAL = pool_id2str(pool, pool->solvables[p].name); OUTPUT: RETVAL const char * pkg2srcname(BSSolv::pool pool, int p) CODE: if (solvable_lookup_void(pool->solvables + p, SOLVABLE_SOURCENAME)) RETVAL = pool_id2str(pool, pool->solvables[p].name); else RETVAL = solvable_lookup_str(pool->solvables + p, SOLVABLE_SOURCENAME); OUTPUT: RETVAL const char * pkg2pkgid(BSSolv::pool pool, int p) CODE: { Id type; const char *s = solvable_lookup_checksum(pool->solvables + p, SOLVABLE_PKGID, &type); RETVAL = s; } OUTPUT: RETVAL const char * pkg2bsid(BSSolv::pool pool, int p) CODE: RETVAL = solvable_lookup_str(pool->solvables + p, buildservice_id); OUTPUT: RETVAL const char * pkg2reponame(BSSolv::pool pool, int p) CODE: { Repo *repo = pool->solvables[p].repo; RETVAL = repo ? repo->name : 0; } OUTPUT: RETVAL const char * pkg2path(BSSolv::pool pool, int p) CODE: { unsigned int medianr; RETVAL = solvable_get_location(pool->solvables + p, &medianr); } OUTPUT: RETVAL const char * pkg2fullpath(BSSolv::pool pool, int p, char *myarch) CODE: { unsigned int medianr; const char *s = solvable_get_location(pool->solvables + p, &medianr); Repo *repo = pool->solvables[p].repo; s = pool_tmpjoin(pool, myarch, "/:full/", s); RETVAL = pool_tmpjoin(pool, repo->name, "/", s); } OUTPUT: RETVAL int pkg2sizek(BSSolv::pool pool, int p) CODE: #ifdef SOLV_KV_NUM64 RETVAL = solvable_lookup_sizek(pool->solvables + p, SOLVABLE_DOWNLOADSIZE, 0); #else RETVAL = solvable_lookup_num(pool->solvables + p, SOLVABLE_DOWNLOADSIZE, 0); #endif OUTPUT: RETVAL const char * pkg2checksum(BSSolv::pool pool, int p) CODE: { Id type; const char *s = solvable_lookup_checksum(pool->solvables + p, SOLVABLE_CHECKSUM, &type); if (s) s = pool_tmpjoin(pool, solv_chksum_type2str(type), ":", s); RETVAL = s; } OUTPUT: RETVAL int verifypkgchecksum(BSSolv::pool pool, int p, char *path) CODE: { Id type; const unsigned char *cin, *cout; FILE *fp; void *cs; int cslen; char buf[4096]; size_t len; int res = 0; if ((cin = solvable_lookup_bin_checksum(pool->solvables + p, SOLVABLE_CHECKSUM, &type)) != 0) { if ((fp = fopen(path, "r")) != 0) { if ((cs = solv_chksum_create(type)) != 0) { while ((len = fread(buf, 1, sizeof(buf), fp)) > 0) solv_chksum_add(cs, buf, len); if ((cout = solv_chksum_get(cs, &cslen)) != 0 && cslen && !memcmp(cin, cout, cslen)) res = 1; solv_chksum_free(cs, 0); } fclose(fp); } } RETVAL = res; } OUTPUT: RETVAL HV * pkg2data(BSSolv::pool pool, int p) CODE: { Solvable *s = pool->solvables + p; Id id; const char *ss, *se; unsigned int medianr; if (!s->repo) XSRETURN_EMPTY; RETVAL = newHV(); sv_2mortal((SV*)RETVAL); (void)hv_store(RETVAL, "name", 4, newSVpv(pool_id2str(pool, s->name), 0), 0); ss = pool_id2str(pool, s->evr); se = ss; while (*se >= '0' && *se <= '9') se++; if (se != ss && *se == ':' && se[1]) { (void)hv_store(RETVAL, "epoch", 5, newSVpvn(ss, se - ss), 0); ss = se + 1; } se = strrchr(ss, '-'); if (se) { (void)hv_store(RETVAL, "version", 7, newSVpvn(ss, se - ss), 0); (void)hv_store(RETVAL, "release", 7, newSVpv(se + 1, 0), 0); } else (void)hv_store(RETVAL, "version", 7, newSVpv(ss, 0), 0); (void)hv_store(RETVAL, "arch", 4, newSVpv(pool_id2str(pool, s->arch), 0), 0); exportdeps(RETVAL, "provides", 8, s->repo, s->provides, SOLVABLE_PROVIDES); exportdeps(RETVAL, "obsoletes", 9, s->repo, s->obsoletes, SOLVABLE_OBSOLETES); exportdeps(RETVAL, "conflicts", 9, s->repo, s->conflicts, SOLVABLE_CONFLICTS); exportdeps(RETVAL, "requires", 8, s->repo, s->requires, SOLVABLE_REQUIRES); exportdeps(RETVAL, "recommends", 10, s->repo, s->recommends, SOLVABLE_RECOMMENDS); exportdeps(RETVAL, "suggests", 8, s->repo, s->suggests, SOLVABLE_SUGGESTS); exportdeps(RETVAL, "supplements", 11, s->repo, s->supplements, SOLVABLE_SUPPLEMENTS); exportdeps(RETVAL, "enhances", 8, s->repo, s->enhances, SOLVABLE_ENHANCES); if (solvable_lookup_void(s, SOLVABLE_SOURCENAME)) ss = pool_id2str(pool, s->name); else ss = solvable_lookup_str(s, SOLVABLE_SOURCENAME); if (ss) (void)hv_store(RETVAL, "source", 6, newSVpv(ss, 0), 0); ss = solvable_get_location(s, &medianr); if (ss) (void)hv_store(RETVAL, "path", 4, newSVpv(ss, 0), 0); ss = solvable_lookup_checksum(s, SOLVABLE_PKGID, &id); if (ss && id == REPOKEY_TYPE_MD5) (void)hv_store(RETVAL, "hdrmd5", 6, newSVpv(ss, 0), 0); ss = solvable_lookup_str(s, buildservice_id); if (ss) (void)hv_store(RETVAL, "id", 2, newSVpv(ss, 0), 0); } OUTPUT: RETVAL void repos(BSSolv::pool pool) PPCODE: { int ridx; Repo *repo; EXTEND(SP, pool->nrepos); FOR_REPOS(ridx, repo) { SV *sv = sv_newmortal(); sv_setref_pv(sv, "BSSolv::repo", (void *)repo); PUSHs(sv); } } void DESTROY(BSSolv::pool pool) CODE: if (pool->considered) { map_free(pool->considered); pool->considered = solv_free(pool->considered); } pool_free(pool); MODULE = BSSolv PACKAGE = BSSolv::repo PREFIX = repo void pkgnames(BSSolv::repo repo) PPCODE: { Pool *pool = repo->pool; Id p; Solvable *s; Map c; create_considered(pool, repo, &c); EXTEND(SP, 2 * repo->nsolvables); FOR_REPO_SOLVABLES(repo, p, s) { if (!MAPTST(&c, p)) continue; PUSHs(sv_2mortal(newSVpv(pool_id2str(pool, s->name), 0))); PUSHs(sv_2mortal(newSViv(p))); } map_free(&c); } void pkgpaths(BSSolv::repo repo) PPCODE: { Pool *pool = repo->pool; Id p; Solvable *s; Map c; const char *str; unsigned int medianr; create_considered(pool, repo, &c); EXTEND(SP, 2 * repo->nsolvables); FOR_REPO_SOLVABLES(repo, p, s) { if (!MAPTST(&c, p)) continue; /* ignore dod packages */ str = solvable_lookup_str(s, buildservice_id); if (str && !strcmp(str, "dod")) continue; str = solvable_get_location(pool->solvables + p, &medianr); if (!str) continue; PUSHs(sv_2mortal(newSVpv(str, 0))); PUSHs(sv_2mortal(newSViv(p))); } map_free(&c); } void tofile(BSSolv::repo repo, char *filename) CODE: { FILE *fp; fp = fopen(filename, "w"); if (fp == 0) croak("%s: %s\n", filename, Strerror(errno)); repo_write_filtered(repo, fp, myrepowritefilter, 0, 0); if (fclose(fp)) croak("fclose: %s\n", Strerror(errno)); } void tofile_fd(BSSolv::repo repo, int fd) CODE: { FILE *fp; int fd2; fd2 = dup(fd); if (fd2 == -1) croak("dup: %s\n", Strerror(errno)); fp = fdopen(fd2, "w"); if (fp == 0) { int e = errno; close(fd2); croak("fdopen: %s\n", Strerror(e)); } repo_write_filtered(repo, fp, myrepowritefilter, 0, 0); if (fclose(fp)) { int e = errno; close(fd2); croak("fclose: %s\n", Strerror(e)); } } SV * tostr(BSSolv::repo repo) CODE: { FILE *fp; char *buf; size_t len; fp = open_memstream(&buf, &len); if (fp == 0) croak("open_memstream: %s\n", Strerror(errno)); repo_write_filtered(repo, fp, myrepowritefilter, 0, 0); if (fclose(fp)) croak("fclose: %s\n", Strerror(errno)); RETVAL = newSVpvn(buf, len); free(buf); } OUTPUT: RETVAL int updatefrombins(BSSolv::repo repo, char *dir, ...) CODE: { Pool *pool = repo->pool; int i; Repodata *data = 0; Hashtable ht; Hashval h, hh, hm; int dirty = 0; Map reused; int oldend = 0; Id p, id; Solvable *s; STRLEN sl; const char *oldcookie; map_init(&reused, repo->end - repo->start); if (repo_lookup_str(repo, SOLVID_META, buildservice_dodurl)) { /* this is a dod repo. keep all dod packages. */ FOR_REPO_SOLVABLES(repo, p, s) { const char *str = solvable_lookup_str(s, buildservice_id); if (str && !strcmp(str, "dod")) MAPSET(&reused, p - repo->start); } } hm = mkmask(2 * repo->nsolvables + 1); ht = solv_calloc(hm + 1, sizeof(*ht)); oldcookie = repo_lookup_str(repo, SOLVID_META, buildservice_repocookie); if (oldcookie && !strcmp(oldcookie, REPOCOOKIE)) { FOR_REPO_SOLVABLES(repo, p, s) { const char *str = solvable_lookup_str(s, buildservice_id); if (!str || !strcmp(str, "dod")) continue; h = strhash(str) & hm; hh = HASHCHAIN_START; while ((id = ht[h]) != 0) h = HASHCHAIN_NEXT(h, hh, hm); ht[h] = p; } } if (repo->end != repo->start) oldend = repo->end; for (i = 2; i + 1 < items; i += 2) { char *s = SvPV(ST(i), sl); char *sid = SvPV_nolen(ST(i + 1)); if (sl < 4) continue; if (strcmp(s + sl - 4, ".rpm") && strcmp(s + sl - 4, ".deb") #ifdef ARCH_ADD_WITH_PKGID && (sl < 11 || strcmp(s + sl - 11, ".pkg.tar.gz")) && (sl < 11 || strcmp(s + sl - 11, ".pkg.tar.xz")) #endif ) if (sl > 10 && !strcmp(s + sl - 10, ".patch.rpm")) continue; if (sl > 10 && !strcmp(s + sl - 10, ".nosrc.rpm")) continue; if (sl > 8 && !strcmp(s + sl - 8, ".src.rpm")) continue; h = strhash(sid) & hm; hh = HASHCHAIN_START; while ((id = ht[h]) != 0) { const char *str = solvable_lookup_str(pool->solvables + id, buildservice_id); if (!strcmp(str, sid)) { /* check location */ unsigned int medianr; str = solvable_get_location(pool->solvables + id, &medianr); if (str[0] == '.' && str[1] == '/') str += 2; if (!strcmp(str, s)) break; } h = HASHCHAIN_NEXT(h, hh, hm); } if (id) { /* same id and location, reuse old entry */ MAPSET(&reused, id - repo->start); } else { /* add new entry */ dirty++; if (!data) data = repo_add_repodata(repo, 0); repodata_addbin(data, dir, s, (int)sl, sid); } } solv_free(ht); if (oldcookie) { if (strcmp(oldcookie, REPOCOOKIE) != 0) { Repodata *firstrepodata = repo_id2repodata(repo, 1); if (data && data != firstrepodata) repodata_internalize(data); data = firstrepodata; repodata_set_str(data, SOLVID_META, buildservice_repocookie, REPOCOOKIE); } } else { if (!data) data = repo_add_repodata(repo, 0); repodata_set_str(data, SOLVID_META, buildservice_repocookie, REPOCOOKIE); } if (data) repodata_internalize(data); if (oldend) { for (i = repo->start; i < oldend; i++) { if (pool->solvables[i].repo != repo) continue; if (MAPTST(&reused, i - repo->start)) continue; if (dirty <= 0) dirty--; repo_free_solvable_block(repo, i, 1, 0); } } map_free(&reused); RETVAL = dirty; } OUTPUT: RETVAL void getpathid(BSSolv::repo repo) PPCODE: { Id p; Solvable *s; EXTEND(SP, repo->nsolvables * 2); FOR_REPO_SOLVABLES(repo, p, s) { unsigned int medianr; const char *str; str = solvable_get_location(s, &medianr); PUSHs(sv_2mortal(newSVpv(str, 0))); str = solvable_lookup_str(s, buildservice_id); PUSHs(sv_2mortal(newSVpv(str, 0))); } } const char * name(BSSolv::repo repo) CODE: RETVAL = repo->name; OUTPUT: RETVAL int isexternal(BSSolv::repo repo) CODE: RETVAL = repo_lookup_void(repo, SOLVID_META, buildservice_external) ? 1 : 0; OUTPUT: RETVAL const char * dodurl(BSSolv::repo repo) CODE: RETVAL = repo_lookup_str(repo, SOLVID_META, buildservice_dodurl); OUTPUT: RETVAL const char * dodcookie(BSSolv::repo repo) CODE: RETVAL = repo_lookup_str(repo, SOLVID_META, buildservice_dodcookie); OUTPUT: RETVAL void updatedoddata(BSSolv::repo repo, HV *rhv = 0) CODE: { Id p; Solvable *s; Repodata *data; /* delete old dod data */ FOR_REPO_SOLVABLES(repo, p, s) { const char *str = solvable_lookup_str(s, buildservice_id); if (!str || !strcmp(str, "dod")) repo_free_solvable(repo, p, 1); } data = repo_add_repodata(repo, REPO_REUSE_REPODATA); repodata_unset(data, SOLVID_META, buildservice_dodurl); repodata_unset(data, SOLVID_META, buildservice_dodcookie); /* add new data */ if (rhv) data2solvables(repo, data, rhv); repo_internalize(repo); } MODULE = BSSolv PACKAGE = BSSolv::expander PREFIX = expander BSSolv::expander new(char *packname = "BSSolv::expander", BSSolv::pool pool, HV *config) CODE: { SV *sv, **svp; char *str; int i, neg; Id id, id2; Expander *xp; xp = calloc(sizeof(Expander), 1); xp->pool = pool; svp = hv_fetch(config, "prefer", 6, 0); sv = svp ? *svp : 0; if (sv && SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVAV) { AV *av = (AV *)SvRV(sv); for (i = 0; i <= av_len(av); i++) { svp = av_fetch(av, i, 0); if (!svp) continue; sv = *svp; str = SvPV_nolen(sv); if (!str) continue; neg = 0; if (*str == '-') { neg = 1; str++; } id = pool_str2id(pool, str, 1); id2 = 0; if ((str = strchr(str, ':')) != 0) id2 = pool_str2id(pool, str + 1, 1); if (neg) { MAPEXP(&xp->preferneg, id); MAPSET(&xp->preferneg, id); if (id2) { MAPEXP(&xp->prefernegx, id2); MAPSET(&xp->prefernegx, id2); } } else { queue_push(&xp->preferposq, id); MAPEXP(&xp->preferpos, id); MAPSET(&xp->preferpos, id); if (id2) { MAPEXP(&xp->preferposx, id2); MAPSET(&xp->preferposx, id2); } } } } svp = hv_fetch(config, "ignoreh", 7, 0); sv = svp ? *svp : 0; if (sv && SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVHV) { HV *hv = (HV *)SvRV(sv); HE *he; hv_iterinit(hv); while ((he = hv_iternext(hv)) != 0) { I32 strl; str = hv_iterkey(he, &strl); if (!str) continue; id = pool_str2id(pool, str, 1); id2 = 0; if ((str = strchr(str, ':')) != 0) id2 = pool_str2id(pool, str + 1, 1); MAPEXP(&xp->ignored, id); MAPSET(&xp->ignored, id); if (id2) { MAPEXP(&xp->ignoredx, id2); MAPSET(&xp->ignoredx, id2); } } } svp = hv_fetch(config, "conflict", 8, 0); sv = svp ? *svp : 0; if (sv && SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVAV) { AV *av = (AV *)SvRV(sv); for (i = 0; i <= av_len(av); i++) { char *p; Id id2; svp = av_fetch(av, i, 0); if (!svp) continue; sv = *svp; str = SvPV_nolen(sv); if (!str) continue; p = strchr(str, ':'); if (!p) continue; id = pool_strn2id(pool, str, p - str, 1); str = p + 1; while ((p = strchr(str, ',')) != 0) { id2 = pool_strn2id(pool, str, p - str, 1); queue_push2(&xp->conflictsq, id, id2); MAPEXP(&xp->conflicts, id); MAPSET(&xp->conflicts, id); MAPEXP(&xp->conflicts, id2); MAPSET(&xp->conflicts, id2); str = p + 1; } id2 = pool_str2id(pool, str, 1); queue_push2(&xp->conflictsq, id, id2); MAPEXP(&xp->conflicts, id); MAPSET(&xp->conflicts, id); MAPEXP(&xp->conflicts, id2); MAPSET(&xp->conflicts, id2); } } /* XXX: this modifies the pool, which is a bit unclean! */ svp = hv_fetch(config, "fileprovides", 12, 0); sv = svp ? *svp : 0; if (sv && SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVHV) { HV *hv = (HV *)SvRV(sv); I32 strl; Queue q; xp->havefileprovides = 1; hv_iterinit(hv); queue_init(&q); while ((sv = hv_iternextsv(hv, &str, &strl)) != 0) { AV *av; Id p, pp; int havenew = 0; if (!SvROK(sv) || SvTYPE(SvRV(sv)) != SVt_PVAV) continue; id = pool_str2id(pool, str, 1); queue_empty(&q); FOR_PROVIDES(p, pp, id) queue_push(&q, p); av = (AV *)SvRV(sv); for (i = 0; i <= av_len(av); i++) { svp = av_fetch(av, i, 0); if (!svp) continue; sv = *svp; str = SvPV_nolen(sv); if (!str) continue; id2 = pool_str2id(pool, str, 0); FOR_PROVIDES(p, pp, id2) { int j; for (j = 0; j < q.count; j++) { if (q.elements[j] == p) break; if (q.elements[j] > p) { queue_insert(&q, j, p); havenew = 1; break; } } if (j == q.count) { queue_push(&q, p); havenew = 1; } } } if (havenew) pool->whatprovides[id] = pool_queuetowhatprovides(pool, &q); } queue_free(&q); } svp = hv_fetch(config, "expandflags:ignoreconflicts", 27, 0); sv = svp ? *svp : 0; if (sv && SvTRUE(sv)) xp->ignoreconflicts = 1; svp = hv_fetch(config, "expand_dbg", 10, 0); sv = svp ? *svp : 0; if (sv && SvTRUE(sv)) xp->debug = 1; sv = get_sv("Build::expand_dbg", FALSE); if (sv && SvTRUE(sv)) xp->debug = 1; RETVAL = xp; } OUTPUT: RETVAL void expand(BSSolv::expander xp, ...) PPCODE: { Pool *pool; int i, nerrors; Id id, who, conflbuf[16]; Queue revertignore, in, out, confl; int oldignoreignore = xp->ignoreignore; queue_init(&revertignore); queue_init(&in); queue_init(&out); queue_init_buffer(&confl, conflbuf, sizeof(conflbuf)/sizeof(*conflbuf)); pool = xp->pool; if (xp->debug) expander_dbg(xp, "expand args:"); for (i = 1; i < items; i++) { char *s = SvPV_nolen(ST(i)); if (xp->debug) expander_dbg(xp, " %s", s); if (*s == '-') { Id id; if (s[1] == '-' && !strcmp(s, "--ignoreignore--")) { xp->ignoreignore = 1; continue; } id = pool_str2id(pool, s + 1, 1); if (id == expander_directdepsend) { queue_push(&in, id); continue; } MAPEXP(&xp->ignored, id); if (MAPTST(&xp->ignored, id)) continue; MAPSET(&xp->ignored, id); queue_push(&revertignore, id); if ((s = strchr(s + 1, ':')) != 0) { id = pool_str2id(pool, s + 1, 1); MAPEXP(&xp->ignoredx, id); if (MAPTST(&xp->ignoredx, id)) continue; MAPSET(&xp->ignoredx, id); queue_push(&revertignore, -id); } } else if (*s == '!') { Id id = dep2id(pool, s + (s[1] == '!' ? 2 : 1)); queue_push2(&confl, id, s[1] == '!' ? 1 : 0); } else { Id id = dep2id(pool, s); queue_push(&in, id); } } if (xp->debug) expander_dbg(xp, "\n"); MAPEXP(&xp->ignored, pool->ss.nstrings); MAPEXP(&xp->ignoredx, pool->ss.nstrings); MAPEXP(&xp->preferpos, pool->ss.nstrings); MAPEXP(&xp->preferposx, pool->ss.nstrings); MAPEXP(&xp->preferneg, pool->ss.nstrings); MAPEXP(&xp->prefernegx, pool->ss.nstrings); MAPEXP(&xp->conflicts, pool->ss.nstrings); nerrors = expander_expand(xp, &in, &out, &confl); /* revert ignores */ xp->ignoreignore = oldignoreignore; for (i = 0; i < revertignore.count; i++) { id = revertignore.elements[i]; if (id > 0) MAPCLR(&xp->ignored, id); else MAPCLR(&xp->ignoredx, -id); } queue_free(&revertignore); queue_free(&in); queue_free(&confl); if (nerrors) { EXTEND(SP, nerrors + 1); PUSHs(sv_2mortal(newSV(0))); for (i = 0; i < out.count; ) { SV *sv; Id type = out.elements[i]; if (type == ERROR_NOPROVIDER) { id = out.elements[i + 1]; who = out.elements[i + 2]; if (who) sv = newSVpvf("nothing provides %s needed by %s", pool_dep2str(pool, id), pool_id2str(pool, pool->solvables[who].name)); else sv = newSVpvf("nothing provides %s", pool_dep2str(pool, id)); i += 3; } else if (type == ERROR_CONFLICTINGPROVIDER) { id = out.elements[i + 1]; who = out.elements[i + 2]; if (who) sv = newSVpvf("conflict for provider of %s needed by %s", pool_dep2str(pool, id), pool_id2str(pool, pool->solvables[who].name)); else sv = newSVpvf("conflict for provider of %s", pool_dep2str(pool, id)); i += 3; } else if (type == ERROR_CONFLICTINGPROVIDERS) { id = out.elements[i + 1]; who = out.elements[i + 2]; if (who) sv = newSVpvf("conflict for all providers of %s needed by %s", pool_dep2str(pool, id), pool_id2str(pool, pool->solvables[who].name)); else sv = newSVpvf("conflict for all providers of %s", pool_dep2str(pool, id)); i += 3; } else if (type == ERROR_PROVIDERINFO) { Id who2 = out.elements[i + 2]; who = out.elements[i + 1]; if (who2 < 0) sv = newSVpvf("(provider %s obsoletes installed %s)", pool_id2str(pool, pool->solvables[who].name), pool_id2str(pool, pool->solvables[-who2].name)); else sv = newSVpvf("(provider %s conflicts with installed %s)", pool_id2str(pool, pool->solvables[who].name), pool_id2str(pool, pool->solvables[who2].name)); i += 3; } else if (type == ERROR_PROVIDERINFO2) { Id who2 = out.elements[i + 2]; who = out.elements[i + 1]; if (who2 < 0) sv = newSVpvf("(provider %s is obsoleted by installed %s)", pool_id2str(pool, pool->solvables[who].name), pool_id2str(pool, pool->solvables[-who2].name)); else if (who2 > 0) sv = newSVpvf("(provider %s is conflicted by installed %s)", pool_id2str(pool, pool->solvables[who].name), pool_id2str(pool, pool->solvables[who2].name)); else sv = newSVpvf("(provider %s is conflicted by the build config)", pool_id2str(pool, pool->solvables[who].name)); i += 3; } else if (type == ERROR_CHOICE) { int j; char *str = ""; for (j = i + 3; out.elements[j]; j++) { Solvable *s = pool->solvables + out.elements[j]; str = pool_tmpjoin(pool, str, " ", pool_id2str(pool, s->name)); } if (*str) str++; /* skip starting ' ' */ id = out.elements[i + 1]; who = out.elements[i + 2]; if (who) sv = newSVpvf("have choice for %s needed by %s: %s", pool_dep2str(pool, id), pool_id2str(pool, pool->solvables[who].name), str); else sv = newSVpvf("have choice for %s: %s", pool_dep2str(pool, id), str); i = j + 1; } else croak("expander: bad error type\n"); PUSHs(sv_2mortal(sv)); } } else { EXTEND(SP, out.count + 1); PUSHs(sv_2mortal(newSViv((IV)1))); for (i = 0; i < out.count; i++) { Solvable *s = pool->solvables + out.elements[i]; PUSHs(sv_2mortal(newSVpv(pool_id2str(pool, s->name), 0))); } } queue_free(&out); } const char * debugstr(BSSolv::expander xp) CODE: if (!xp->debugstr) xp->debugstr = calloc(1, 1); RETVAL = xp->debugstr; OUTPUT: RETVAL void DESTROY(BSSolv::expander xp) CODE: map_free(&xp->ignored); map_free(&xp->ignoredx); queue_free(&xp->preferposq); map_free(&xp->preferpos); map_free(&xp->preferposx); map_free(&xp->preferneg); map_free(&xp->prefernegx); queue_free(&xp->conflictsq); map_free(&xp->conflicts); solv_free(xp->debugstr); solv_free(xp); perl-BSSolv-0.05/MANIFEST000066400000000000000000000003241256464231200147030ustar00rootroot00000000000000BSSolv.pm BSSolv.xs Makefile.PL MANIFEST META.yml README dist/debian.changelog dist/debian.compat dist/debian.control dist/debian.rules dist/perl-BSSolv.changes dist/perl-BSSolv.dsc dist/perl-BSSolv.spec typemap perl-BSSolv-0.05/META.yml000066400000000000000000000005071256464231200150260ustar00rootroot00000000000000--- #YAML:1.0 name: BSSolv version: 0.05 abstract: Support perl module for the OBS backend license: perl author: - Michael Schroeder, mls@suse.de provides: BSSolv: file: BSSolv.pm version: 0.05 meta-spec: version: 1.3 url: http://module-build.sourceforge.net/META-spec-v1.3.html generated_by: Michael Schroeder perl-BSSolv-0.05/Makefile.PL000066400000000000000000000007271256464231200155330ustar00rootroot00000000000000use ExtUtils::MakeMaker; my $solvprefix = '/usr'; my $inc = "-I$solvprefix/include/solv"; my $lib = ''; if (grep {$_ eq '--bundled-libsolv'} @ARGV) { my $builddir = 'libsolv'; $inc = "-I$builddir/src -I$builddir/ext"; $lib = "-L$builddir/src -L$builddir/ext"; } $lib = ($lib ? "$lib " : '') . '-lsolvext -lsolv -lz -llzma'; WriteMakefile( NAME => 'BSSolv', VERSION_FROM => 'BSSolv.pm', INC => $inc, LIBS => [ $lib ], ) perl-BSSolv-0.05/README000066400000000000000000000014561256464231200144410ustar00rootroot00000000000000BSSolv version 0.02 =================== This is a support perl module for the OBS backend. It contains functions for repository management, dependency solving, package ordering, and meta file creation. INSTALLATION To install this module type the following: perl Makefile.PL [options] make make install The Makefile.PL options are: --bundled-libsolv : build against a not-installed libsolv library built in a 'libsolv' subdir DEPENDENCIES The libsolv library COPYRIGHT AND LICENSE Copyright (C) 2009-2014 Michael Schroeder This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself. Please refer to the Perl Artistic License for details: http://search.cpan.org/perldoc?perlartistic perl-BSSolv-0.05/dist/000077500000000000000000000000001256464231200145165ustar00rootroot00000000000000perl-BSSolv-0.05/dist/debian.changelog000066400000000000000000000020631256464231200176120ustar00rootroot00000000000000libbssolv-perl (0.4.0-5) unstable; urgency=low * make checksums pass our writefilter -- Michael Schroeder Tue, 18 Aug 2015 16:41:51 +0200 libbssolv-perl (0.4.0-4) unstable; urgency=low * allow setting of the dodcookie without a dodurl -- Michael Schroeder Tue, 18 Aug 2015 16:35:51 +0200 libbssolv-perl (0.4.0-3) unstable; urgency=low * implement download on demand data updating -- Michael Schroeder Thu, 30 Jul 2015 15:55:51 +0200 libbssolv-perl (0.4.0-2) unstable; urgency=low * update to git #a93b6ed8 -- Michael Schroeder Thu, 18 Sep 2014 18:08:58 +0200 libbssolv-perl (0.4.0-1) unstable; urgency=low * update to libsolv-0.4.0 -- Michael Schroeder Fri, 18 Oct 2013 12:08:58 +0200 libbssolv-perl (0.2.4-1) unstable; urgency=low * update to libsolv-0.2.4 -- Michael Schroeder Wed, 6 Feb 2013 15:45:06 +0100 libbssolv-perl (0.2.0-1) unstable; urgency=low * Initial Release -- Michael Schroeder Mon, 10 Oct 2011 19:30:22 +0200 perl-BSSolv-0.05/dist/debian.compat000066400000000000000000000000021256464231200171350ustar00rootroot000000000000007 perl-BSSolv-0.05/dist/debian.control000066400000000000000000000006061256464231200173440ustar00rootroot00000000000000Source: libbssolv-perl Section: perl Priority: optional Build-Depends: debhelper (>= 7), perl (>= 5.6.10-12), cmake, libexpat1-dev, libz-dev, liblzma-dev, librpm-dev Maintainer: Stephan Kulow Standards-Version: 3.8.0 Package: libbssolv-perl Architecture: any Depends: ${perl:Depends} Description: Using a Satisfyability Solver to compute package dependencies. Fancy stuff perl-BSSolv-0.05/dist/debian.rules000066400000000000000000000005241256464231200170150ustar00rootroot00000000000000#!/usr/bin/make -f override_dh_auto_configure: ln -s . libsolv cmake -DFEDORA=1 -DDISABLE_SHARED=1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_SKIP_RPATH=1 -DENABLE_RPMDB=1 -DENABLE_DEBIAN=1 -DENABLE_ARCHREPO=1 -DENABLE_LZMA_COMPRESSION=1 -DMULTI_SEMANTICS=1 -DCMAKE_INSTALL_PREFIX=/usr make dh_auto_configure -- --bundled-libsolv %: dh $@ perl-BSSolv-0.05/dist/perl-BSSolv.changes000066400000000000000000000155211256464231200201640ustar00rootroot00000000000000------------------------------------------------------------------- Tue Aug 18 16:43:22 CEST 2015 - mls@suse.de - update to version 0.25.0 (perl module 0.05 version) * make checksums pass our writefilter ------------------------------------------------------------------- Tue Aug 18 16:35:36 CEST 2015 - mls@suse.de - update to version 0.24.0 (perl module 0.04 version) * allow setting of the dodcookie without a dodurl ------------------------------------------------------------------- Thu Jul 30 15:54:33 CEST 2015 - mls@suse.de - update to version 0.23.0 (perl module 0.03 version) * implement download on demand data updating ------------------------------------------------------------------- Thu Jun 11 08:08:32 UTC 2015 - adrian@suse.de - update to version 0.22.0 (perl module 0.02 version) * implement handling of conflicts (aka '!') deps in expander * treat ARCH_ANY like ARCH_ALL * improve conflictsinfo handling * support --ignoreignore-- flag * improved debug output ------------------------------------------------------------------- Thu Sep 18 11:32:58 CEST 2014 - ro@suse.de - update to BSSolv.xs from GIT ------------------------------------------------------------------- Fri Oct 18 12:10:47 CEST 2013 - mls@suse.de - update to libsolv-0.4.0 to get REL_MULTIARCH support ------------------------------------------------------------------- Wed Feb 6 15:42:59 CET 2013 - mls@suse.de - update to libsolv-0.2.4 ------------------------------------------------------------------- Wed Nov 14 14:18:55 CET 2012 - mls@suse.de - update BSSolv.xs to get debugstr support ------------------------------------------------------------------- Tue Nov 13 17:56:54 CET 2012 - mls@suse.de - support 'ignoreconflicts' expandflag ------------------------------------------------------------------- Tue Nov 13 12:11:54 CET 2012 - mls@suse.de - use REPO_NO_LOCATION ------------------------------------------------------------------- Mon Nov 12 14:58:14 CET 2012 - mls@suse.de - update libsolv to current version to fix deb parsing - bump repocookie ------------------------------------------------------------------- Mon Oct 15 17:46:37 CEST 2012 - mls@suse.de - update libsolv and BSSolv.xs to current version * export all dependencies * obey package conflicts when expanding ------------------------------------------------------------------- Fri Apr 27 14:40:10 CEST 2012 - mls@suse.de - update BSSolv.xs so that the worker caches binaries again ------------------------------------------------------------------- Wed Apr 25 16:11:09 CEST 2012 - mls@suse.de - bump version to 0.18.2 - update to libsolv-0.1.0 to fix opensuse 11.4 builds ------------------------------------------------------------------- Wed Apr 4 14:58:11 CEST 2012 - mls@suse.de - bump version to 0.18.1 - update to current libsolv - enable arch linux support ------------------------------------------------------------------- Wed Nov 30 14:44:14 UTC 2011 - adrian@suse.de - bump version to 0.18.0 - base package on libsolv tar ball ------------------------------------------------------------------- Wed Nov 30 13:20:12 CET 2011 - mls@suse.de - update BSSolv.xs: * fix prefer order handling bug * add repo->tofile_fd ------------------------------------------------------------------- Wed Nov 16 14:55:55 CET 2011 - mls@suse.de - fix debian control file extraction, thanks djszapi! ------------------------------------------------------------------- Thu Aug 25 12:49:06 CEST 2011 - mls@suse.de - fix debian dependency compare function ------------------------------------------------------------------- Tue Jun 28 18:55:12 UTC 2011 - coolo@novell.com - add requires to correct perl version ------------------------------------------------------------------- Tue Feb 15 13:49:35 CET 2011 - mls@suse.de - define USE_OWN_QSORT instead of using glib ------------------------------------------------------------------- Mon Feb 14 16:44:24 UTC 2011 - adrian@suse.de - update to 0.16.4 ------------------------------------------------------------------- Thu Dec 9 10:06:40 UTC 2010 - adrian@suse.de - update to 0.16.2 - fix build for Factory ------------------------------------------------------------------- Fri Oct 29 07:29:16 UTC 2010 - adrian@suse.de - follow the version of satsolver for this package ------------------------------------------------------------------- Sat Oct 23 09:53:11 UTC 2010 - mrdocs@opensuse.org - fix the build with the correct source version ------------------------------------------------------------------- Tue Oct 19 10:05:03 UTC 2010 - adrian@suse.de - adapt spec to version 0.16.0 ------------------------------------------------------------------- Fri Jul 23 13:13:27 UTC 2010 - adrian@suse.de - update BSSolv.xs from current build-service git repo ------------------------------------------------------------------- Fri May 14 12:53:24 UTC 2010 - adrian@suse.de - adapt spec to version 0.15.0 ------------------------------------------------------------------- Wed Apr 7 17:17:37 CEST 2010 - mls@suse.de - adapt spec to version 0.14.17 ------------------------------------------------------------------- Mon Mar 15 14:20:51 UTC 2010 - chris@computersalat.de - fix spec o new version 0.14.16 (zypp:Head) ------------------------------------------------------------------- Tue Mar 2 12:48:19 UTC 2010 - chris@computersalat.de - hmm, cause of undocumented SOURCE changes (satsolver-0.14.15 from zypp:Head), util patch (SLES 10 fix) now obsolete o hence removed ------------------------------------------------------------------- Sun Feb 28 21:05:00 UTC 2010 - adrian@suse.de - fixed SLES 10 fix ------------------------------------------------------------------- Mon Feb 22 22:59:44 UTC 2010 - chris@computersalat.de - fix spec o new version 0.14.15 (zypp:Head) - reworked patch for SLE_10 ------------------------------------------------------------------- Fri Feb 12 21:26:07 UTC 2010 - chris@computersalat.de - spec mods o added header o fixed source version - fix build for SLE_10 o added satsolver-0.14.14-util.patch - BuildReq ruby-devel > 1.8.4 o /usr/bin/ruby: no such file to load -- vendor-specific (LoadError) ------------------------------------------------------------------- Mon Dec 21 17:26:47 CET 2009 - mls@suse.de - add dod changes - fix bug in debian dep parsing - add support for whatprovides/whatrequires ------------------------------------------------------------------- Fri Oct 23 12:02:40 CEST 2009 - mls@suse.de - strip trailing spaces in dep2id ------------------------------------------------------------------- Wed Oct 21 11:11:52 CEST 2009 - mls@suse.de - add pkg2sizek ------------------------------------------------------------------- Wed Oct 7 10:17:38 CEST 2009 - mls@suse.de - update BSSolv.xs ------------------------------------------------------------------- Tue Oct 6 12:19:38 CEST 2009 - mls@suse.de - initial version perl-BSSolv-0.05/dist/perl-BSSolv.dsc000066400000000000000000000004661256464231200173270ustar00rootroot00000000000000Format: 1.0 Source: libbssolv-perl Binary: libbssolv-perl Version: 0.4.0-5 Maintainer: Stephan Kulow Standards-Version: 3.8.0 Build-Depends: debhelper (>= 7), perl (>= 5.6.10-12), cmake, libexpat1-dev, libz-dev, liblzma-dev, librpm-dev Debtransform-Files: BSSolv.pm BSSolv.xs Makefile.PL typemap perl-BSSolv-0.05/dist/perl-BSSolv.spec000066400000000000000000000067031256464231200175100ustar00rootroot00000000000000# # spec file for package perl-BSSolv # # Copyright (c) 2015 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed # upon. The license for this file, and modifications and additions to the # file, is the same license as for the pristine package itself (unless the # license for the pristine package is not an Open Source License, in which # case the license is the MIT License). An "Open Source License" is a # license that conforms to the Open Source Definition (Version 1.9) # published by the Open Source Initiative. # Please submit bugfixes or comments via http://bugs.opensuse.org/ # Name: perl-BSSolv Version: 0.25.0 Release: 0 Url: https://github.com/openSUSE/perl-BSSolv Source: libsolv-0.4.0.tar.bz2 Source1: Makefile.PL Source2: BSSolv.pm Source3: BSSolv.xs Source4: typemap BuildRoot: %{_tmppath}/%{name}-%{version}-build %if 0%{?mandriva_version} # force this version on mandriva BuildRequires: libneon0.26-devel %endif %if 0%{?fedora_version} BuildRequires: db4-devel BuildRequires: perl-devel %endif %if 0%{?suse_version} Requires: perl = %perl_version %if 0%{?suse_version} < 1030 BuildRequires: expat %else BuildRequires: libexpat-devel %endif %else BuildRequires: expat-devel %endif %if 0%{?rhel_version} || 0%{?centos_version} BuildRequires: db4-devel %endif BuildRequires: cmake BuildRequires: gcc-c++ BuildRequires: perl BuildRequires: rpm-devel BuildRequires: xz-devel BuildRequires: zlib-devel #RHEL6 moved ExtUtils::MakeMaker outside the main perl package BuildRequires: perl(ExtUtils::MakeMaker) # the testsuite uses the check framework BuildRequires: check-devel Summary: A new approach to package dependency solving License: BSD-3-Clause Group: Development/Libraries/C and C++ # probably needed for rhel/centos on x86_64 %if 0%{!?perl_vendorarch} %define perl_vendorarch %(eval "`%{__perl} -V:installvendorarch`"; echo $installvendorarch) %endif %description Using a Satisfyability Solver to compute package dependencies. %prep %setup -c ln -s libsolv-* libsolv cp %{SOURCE1} %{SOURCE2} %{SOURCE3} %{SOURCE4} . pushd libsolv popd %build export CFLAGS="$RPM_OPT_FLAGS" export CXXFLAGS="$CFLAGS" CMAKE_FLAGS= %if 0%{?fedora_version} || 0%{?rhel_version} || 0%{?centos_version} CMAKE_FLAGS="-DFEDORA=1" %endif %if 0%{?rhel_version} || 0%{?centos_version} CFLAGS="$CFLAGS -DUSE_OWN_QSORT" %endif pushd libsolv cmake $CMAKE_FLAGS \ -DDISABLE_SHARED=1 \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_SKIP_RPATH=1 \ -DENABLE_RPMDB=1 \ -DENABLE_DEBIAN=1 \ -DENABLE_ARCHREPO=1 \ -DENABLE_LZMA_COMPRESSION=1 \ -DMULTI_SEMANTICS=1 pushd src ; make ; popd pushd ext ; make ; popd popd perl Makefile.PL --bundled-libsolv make %install make DESTDIR=$RPM_BUILD_ROOT install_vendor %if 0%{?suse_version} %perl_process_packlist %else find $RPM_BUILD_ROOT -type f -name perllocal.pod -exec rm -f {} \; find $RPM_BUILD_ROOT -type f -name .packlist -exec rm -f {} \; find $RPM_BUILD_ROOT -type f -name '*.bs' -a -size 0 -exec rm -f {} ';' find $RPM_BUILD_ROOT -depth -type d -exec rmdir {} 2>/dev/null \; %{_fixperms} $RPM_BUILD_ROOT/* %endif %files %defattr(-,root,root) %{perl_vendorarch}/BSSolv.pm %{perl_vendorarch}/auto/BSSolv %if 0%{?suse_version} %if 0%{?suse_version} < 1140 /var/adm/perl-modules/* %endif %endif %changelog perl-BSSolv-0.05/typemap000066400000000000000000000001111256464231200151460ustar00rootroot00000000000000BSSolv::pool T_PTROBJ BSSolv::repo T_PTROBJ BSSolv::expander T_PTROBJ