void pool_add_pos_literals_complex_dep(Pool *pool, Id dep, Queue *q, Map *m, int neg) { while (ISRELDEP(dep)) { Reldep *rd = GETRELDEP(pool, dep); if (rd->flags != REL_AND && rd->flags != REL_OR && rd->flags != REL_COND) break; pool_add_pos_literals_complex_dep(pool, rd->name, q, m, neg); dep = rd->evr; if (rd->flags == REL_COND) { neg = !neg; if (ISRELDEP(dep)) { Reldep *rd2 = GETRELDEP(pool, rd->evr); if (rd2->flags == REL_ELSE) { pool_add_pos_literals_complex_dep(pool, rd2->evr, q, m, !neg); dep = rd2->name; } } } } if (!neg) { Id p, pp; FOR_PROVIDES(p, pp, dep) if (!MAPTST(m, p)) queue_push(q, p); }
/* get e:v.r for Id */ const char * pool_id2evr(const Pool *pool, Id id) { Reldep *rd; if (!ISRELDEP(id)) return ""; rd = GETRELDEP(pool, id); if (ISRELDEP(rd->evr)) return "(REL)"; return pool->ss.stringspace + pool->ss.strings[rd->evr]; }
/* Id -> String * for rels (returns name only) and strings */ const char * pool_id2str(const Pool *pool, Id id) { if (ISRELDEP(id)) { Reldep *rd = GETRELDEP(pool, id); if (ISRELDEP(rd->name)) return "REL"; return pool->ss.stringspace + pool->ss.strings[rd->name]; } return pool->ss.stringspace + pool->ss.strings[id]; }
/* get operator for RelId */ const char * pool_id2rel(const Pool *pool, Id id) { Reldep *rd; if (!ISRELDEP(id)) return ""; rd = GETRELDEP(pool, id); switch (rd->flags) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: return rels[rd->flags & 7]; case REL_AND: return " & "; case REL_OR: return " | "; case REL_WITH: return " + "; case REL_NAMESPACE: return " NAMESPACE "; /* actually not used in dep2str */ case REL_ARCH: return "."; case REL_FILECONFLICT: return " FILECONFLICT "; default: break; } return " ??? "; }
int pool_is_complex_dep_rd(Pool *pool, Reldep *rd) { for (;;) { if (rd->flags == REL_AND || rd->flags == REL_COND) /* those two are the complex ones */ return 1; if (rd->flags != REL_OR) return 0; if (ISRELDEP(rd->name) && pool_is_complex_dep_rd(pool, GETRELDEP(pool, rd->name))) return 1; if (!ISRELDEP(rd->evr)) return 0; rd = GETRELDEP(pool, rd->evr); } }
Offset repo_fix_conflicts(Repo *repo, Offset conflicts) { char buf[1024], *p, *dep; Pool *pool = repo->pool; Id id; int i; if (!conflicts) return conflicts; for (i = conflicts; repo->idarraydata[i]; i++) { id = repo->idarraydata[i]; if (ISRELDEP(id)) continue; dep = (char *)pool_id2str(pool, id); if (!strncmp(dep, "otherproviders(", 15) && strlen(dep) < sizeof(buf) - 2) { strcpy(buf, dep + 15); if ((p = strchr(buf, ')')) != 0) *p = 0; id = pool_str2id(pool, buf, 1); id = pool_rel2id(pool, NAMESPACE_OTHERPROVIDERS, id, REL_NAMESPACE, 1); repo->idarraydata[i] = id; } } return conflicts; }
static const char *findKernelFlavor(Parsedata *pd, Solvable *s) { Pool *pool = pd->pool; Id pid, *pidp; if (s->provides) { pidp = pd->repo->idarraydata + s->provides; while ((pid = *pidp++) != 0) { Reldep *prd; const char *depname; if (!ISRELDEP(pid)) continue; /* wrong provides name */ prd = GETRELDEP(pool, pid); depname = pool_id2str(pool, prd->name); if (!strncmp(depname, "kernel-", 7)) return depname + 7; } } if (s->requires) { pidp = pd->repo->idarraydata + s->requires; while ((pid = *pidp++) != 0) { const char *depname; if (!ISRELDEP(pid)) { depname = pool_id2str(pool, pid); } else { Reldep *prd = GETRELDEP(pool, pid); depname = pool_id2str(pool, prd->name); } if (!strncmp(depname, "kernel-", 7)) return depname + 7; } } return 0; }
/* get operator for RelId */ const char * pool_id2rel(const Pool *pool, Id id) { Reldep *rd; if (!ISRELDEP(id)) return ""; rd = GETRELDEP(pool, id); switch (rd->flags) { /* debian special cases < and > */ /* haiku special cases <> (maybe we should use != for the others as well */ case 0: case REL_EQ: case REL_GT | REL_EQ: case REL_LT | REL_EQ: case REL_LT | REL_EQ | REL_GT: #if !defined(DEBIAN) && !defined(MULTI_SEMANTICS) case REL_LT: case REL_GT: #endif #if !defined(HAIKU) && !defined(MULTI_SEMANTICS) case REL_LT | REL_GT: #endif return rels[rd->flags]; #if defined(DEBIAN) || defined(MULTI_SEMANTICS) case REL_GT: return pool->disttype == DISTTYPE_DEB ? " >> " : rels[rd->flags]; case REL_LT: return pool->disttype == DISTTYPE_DEB ? " << " : rels[rd->flags]; #endif #if defined(HAIKU) || defined(MULTI_SEMANTICS) case REL_LT | REL_GT: return pool->disttype == DISTTYPE_HAIKU ? " != " : rels[rd->flags]; #endif case REL_AND: return " & "; case REL_OR: return " | "; case REL_WITH: return " + "; case REL_NAMESPACE: return " NAMESPACE "; /* actually not used in dep2str */ case REL_ARCH: return "."; case REL_MULTIARCH: return ":"; case REL_FILECONFLICT: return " FILECONFLICT "; case REL_COND: return " IF "; case REL_COMPAT: return " compat >= "; case REL_KIND: return " KIND "; case REL_ELSE: return " ELSE "; default: break; } return " ??? "; }
const char * pool_dep2str(Pool *pool, Id id) { char *p; if (!ISRELDEP(id)) return pool->ss.stringspace + pool->ss.strings[id]; p = pool_alloctmpspace(pool, dep2strlen(pool, id) + 1); dep2strcpy(pool, p, id, 0); return p; }
/* Id -> String * for rels (returns name only) and strings */ const char * pool_id2str(const Pool *pool, Id id) { while (ISRELDEP(id)) { Reldep *rd = GETRELDEP(pool, id); id = rd->name; } return pool->ss.stringspace + pool->ss.strings[id]; }
static int dep2strlen(const Pool *pool, Id id) { int l = 0; while (ISRELDEP(id)) { Reldep *rd = GETRELDEP(pool, id); /* add 2 for parens */ l += 2 + dep2strlen(pool, rd->name) + strlen(pool_id2rel(pool, id)); id = rd->evr; } return l + strlen(pool->ss.stringspace + pool->ss.strings[id]); }
/* get operator for RelId */ const char * pool_id2rel(const Pool *pool, Id id) { Reldep *rd; if (!ISRELDEP(id)) return ""; rd = GETRELDEP(pool, id); switch (rd->flags) { case 0: case 2: case 3: case 6: case 7: #if !defined(DEBIAN) && !defined(MULTI_SEMANTICS) case 1: case 4: #endif #if !defined(HAIKU) && !defined(MULTI_SEMANTICS) case 5: #endif return rels[rd->flags]; #if defined(DEBIAN) || defined(MULTI_SEMANTICS) case 1: return pool->disttype == DISTTYPE_DEB ? " >> " : rels[rd->flags]; case 4: return pool->disttype == DISTTYPE_DEB ? " << " : rels[rd->flags]; #endif #if defined(HAIKU) || defined(MULTI_SEMANTICS) case 5: return pool->disttype == DISTTYPE_HAIKU ? " != " : rels[rd->flags]; #endif case REL_AND: return " & "; case REL_OR: return " | "; case REL_WITH: return " + "; case REL_NAMESPACE: return " NAMESPACE "; /* actually not used in dep2str */ case REL_ARCH: return "."; case REL_FILECONFLICT: return " FILECONFLICT "; case REL_COND: return " IF "; case REL_COMPAT: return " compat >= "; default: break; } return " ??? "; }
static void dep2strcpy(const Pool *pool, char *p, Id id, int oldrel) { while (ISRELDEP(id)) { Reldep *rd = GETRELDEP(pool, id); if (oldrel == REL_AND || oldrel == REL_OR || oldrel == REL_WITH) if (rd->flags == REL_AND || rd->flags == REL_OR || rd->flags == REL_WITH) if (oldrel != rd->flags) { *p++ = '('; dep2strcpy(pool, p, rd->name, rd->flags); p += strlen(p); strcpy(p, pool_id2rel(pool, id)); p += strlen(p); dep2strcpy(pool, p, rd->evr, rd->flags); strcat(p, ")"); return; } if (rd->flags == REL_KIND) { dep2strcpy(pool, p, rd->evr, rd->flags); p += strlen(p); *p++ = ':'; id = rd->name; oldrel = rd->flags; continue; } dep2strcpy(pool, p, rd->name, rd->flags); p += strlen(p); if (rd->flags == REL_NAMESPACE) { *p++ = '('; dep2strcpy(pool, p, rd->evr, rd->flags); strcat(p, ")"); return; } if (rd->flags == REL_FILECONFLICT) { *p = 0; return; } strcpy(p, pool_id2rel(pool, id)); p += strlen(p); id = rd->evr; oldrel = rd->flags; } strcpy(p, pool->ss.stringspace + pool->ss.strings[id]); }
/* these packages will never show up installed */ static inline int is_noinst_pseudo_package(Pool *pool, Solvable *s) { const char *n = pool_id2str(pool, s->name); if (!strncmp(n, "patch:", 6)) return 1; if (!strncmp(n, "pattern:", 8)) { #if defined(SUSE) && defined(ENABLE_LINKED_PKGS) /* unlike normal patterns, autopatterns *can* be installed (via the package link), so do not filter them */ if (s->provides) { Id prv, *prvp = s->repo->idarraydata + s->provides; while ((prv = *prvp++) != 0) if (ISRELDEP(prv) && !strcmp(pool_id2str(pool, prv), "autopattern()")) return 0; } #endif return 1; } return 0; }
int repo_add_autopattern(Repo *repo, int flags) { Pool *pool = repo->pool; Repodata *data = 0; Solvable *s, *s2; Queue patq, patq2; Queue prdq, prdq2; Id p; Id pattern_id, product_id; Id autopattern_id = 0, autoproduct_id = 0; int i, j; queue_init(&patq); queue_init(&patq2); queue_init(&prdq); queue_init(&prdq2); pattern_id = pool_str2id(pool, "pattern()", 9); product_id = pool_str2id(pool, "product()", 9); FOR_REPO_SOLVABLES(repo, p, s) { const char *n = pool_id2str(pool, s->name); if (*n == 'p') { if (!strncmp("pattern:", n, 8)) { queue_push(&patq, p); continue; } else if (!strncmp("product:", n, 8)) { queue_push(&prdq, p); continue; } } if (s->provides) { Id prv, *prvp = repo->idarraydata + s->provides; while ((prv = *prvp++) != 0) /* go through all provides */ if (ISRELDEP(prv)) { Reldep *rd = GETRELDEP(pool, prv); if (rd->flags != REL_EQ) continue; if (rd->name == pattern_id) { queue_push2(&patq2, p, rd->evr); break; } if (rd->name == product_id) { queue_push2(&prdq2, p, rd->evr); break; } } } } for (i = 0; i < patq2.count; i += 2) { const char *pn = 0; char *newname; Id name, prv, *prvp; const char *str; unsigned long long num; s = pool->solvables + patq2.elements[i]; /* construct new name */ newname = pool_tmpjoin(pool, "pattern:", pool_id2str(pool, patq2.elements[i + 1]), 0); unescape(newname); name = pool_str2id(pool, newname, 0); if (name) { /* check if we already have that pattern */ for (j = 0; j < patq.count; j++) { s2 = pool->solvables + patq.elements[j]; if (s2->name == name && s2->arch == s->arch && s2->evr == s->evr) break; } if (j < patq.count) continue; /* yes, do not add again */ } /* new pattern */ if (!name) name = pool_str2id(pool, newname, 1); if (!data) { repo_internalize(repo); /* to make that the lookups work */ data = repo_add_repodata(repo, flags); } s2 = pool_id2solvable(pool, repo_add_solvable(repo)); s = pool->solvables + patq2.elements[i]; /* re-calc pointer */ s2->name = name; s2->arch = s->arch; s2->evr = s->evr; s2->vendor = s->vendor; /* add link requires */ s2->requires = repo_addid_dep(repo, s2->requires, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1) , 0); /* add autopattern provides */ if (!autopattern_id) autopattern_id = pool_str2id(pool, "autopattern()", 1); s2->provides = repo_addid_dep(repo, s2->provides, pool_rel2id(pool, autopattern_id, s->name, REL_EQ, 1), 0); /* add self provides */ s2->provides = repo_addid_dep(repo, s2->provides, pool_rel2id(pool, s2->name, s2->evr, REL_EQ, 1), 0); if ((num = solvable_lookup_num(s, SOLVABLE_INSTALLTIME, 0)) != 0) repodata_set_num(data, s2 - pool->solvables, SOLVABLE_INSTALLTIME, num); if ((num = solvable_lookup_num(s, SOLVABLE_BUILDTIME, 0)) != 0) repodata_set_num(data, s2 - pool->solvables, SOLVABLE_BUILDTIME, num); if ((str = solvable_lookup_str(s, SOLVABLE_SUMMARY)) != 0) repodata_set_str(data, s2 - pool->solvables, SOLVABLE_SUMMARY, str); if ((str = solvable_lookup_str(s, SOLVABLE_DESCRIPTION)) != 0) repodata_set_str(data, s2 - pool->solvables, SOLVABLE_DESCRIPTION, str); /* fill in stuff from provides */ prvp = repo->idarraydata + s->provides; while ((prv = *prvp++) != 0) /* go through all provides */ { Id evr = 0; if (ISRELDEP(prv)) { Reldep *rd = GETRELDEP(pool, prv); if (rd->flags != REL_EQ) continue; prv = rd->name; evr = rd->evr; } pn = pool_id2str(pool, prv); if (strncmp("pattern-", pn, 8) != 0) continue; newname = 0; if (evr) { newname = pool_tmpjoin(pool, pool_id2str(pool, evr), 0, 0); unescape(newname); } if (!strncmp(pn, "pattern-category(", 17) && evr) { char lang[9]; int l = strlen(pn); Id langtag; if (l > 17 + 9 || pn[l - 1] != ')') continue; strncpy(lang, pn + 17, l - 17 - 1); lang[l - 17 - 1] = 0; langtag = SOLVABLE_CATEGORY; if (*lang && strcmp(lang, "en") != 0) langtag = pool_id2langid(pool, SOLVABLE_CATEGORY, lang, 1); if (newname[solv_validutf8(newname)] == 0) repodata_set_str(data, s2 - pool->solvables, langtag, newname); else { char *ustr = solv_latin1toutf8(newname); repodata_set_str(data, s2 - pool->solvables, langtag, ustr); solv_free(ustr); } } else if (!strcmp(pn, "pattern-includes()") && evr) repodata_add_poolstr_array(data, s2 - pool->solvables, SOLVABLE_INCLUDES, pool_tmpjoin(pool, "pattern:", newname, 0)); else if (!strcmp(pn, "pattern-extends()") && evr) repodata_add_poolstr_array(data, s2 - pool->solvables, SOLVABLE_EXTENDS, pool_tmpjoin(pool, "pattern:", newname, 0)); else if (!strcmp(pn, "pattern-icon()") && evr) repodata_set_str(data, s2 - pool->solvables, SOLVABLE_ICON, newname); else if (!strcmp(pn, "pattern-order()") && evr) repodata_set_str(data, s2 - pool->solvables, SOLVABLE_ORDER, newname); else if (!strcmp(pn, "pattern-visible()") && !evr) repodata_set_void(data, s2 - pool->solvables, SOLVABLE_ISVISIBLE); } } queue_free(&patq); queue_free(&patq2); if (repo == pool->installed) queue_empty(&prdq2); /* no auto products for installed repos */ for (i = 0; i < prdq2.count; i += 2) { const char *pn = 0; char *newname; Id name, evr = 0, prv, *prvp; const char *str; unsigned long long num; s = pool->solvables + prdq2.elements[i]; /* construct new name */ newname = pool_tmpjoin(pool, "product(", pool_id2str(pool, prdq2.elements[i + 1]), ")"); unescape(newname); name = pool_str2id(pool, newname, 0); if (!name) continue; /* must have it in provides! */ prvp = repo->idarraydata + s->provides; while ((prv = *prvp++) != 0) /* go through all provides */ { if (ISRELDEP(prv)) { Reldep *rd = GETRELDEP(pool, prv); if (rd->name == name && rd->flags == REL_EQ) { evr = rd->evr; break; } } } if (!prv) continue; /* not found in provides */ newname = pool_tmpjoin(pool, "product:", pool_id2str(pool, prdq2.elements[i + 1]), 0); unescape(newname); name = pool_str2id(pool, newname, 0); if (name) { /* check if we already have that product */ for (j = 0; j < prdq.count; j++) { s2 = pool->solvables + prdq.elements[j]; if (s2->name == name && s2->arch == s->arch && s2->evr == evr) break; } if (j < prdq.count) continue; /* yes, do not add again */ } /* new product */ if (!name) name = pool_str2id(pool, newname, 1); if (!data) { repo_internalize(repo); /* to make that the lookups work */ data = repo_add_repodata(repo, flags); } if ((num = solvable_lookup_num(s, SOLVABLE_INSTALLTIME, 0)) != 0) continue; /* eek, not for installed packages, please! */ s2 = pool_id2solvable(pool, repo_add_solvable(repo)); s = pool->solvables + prdq2.elements[i]; /* re-calc pointer */ s2->name = name; s2->arch = s->arch; s2->evr = evr; s2->vendor = s->vendor; /* add link requires */ s2->requires = repo_addid_dep(repo, s2->requires, prv, 0); if (!autoproduct_id) autoproduct_id = pool_str2id(pool, "autoproduct()", 1); s2->provides = repo_addid_dep(repo, s2->provides, pool_rel2id(pool, autoproduct_id, s->name, REL_EQ, 1), 0); /* add self provides */ s2->provides = repo_addid_dep(repo, s2->provides, pool_rel2id(pool, s2->name, s2->evr, REL_EQ, 1), 0); if ((num = solvable_lookup_num(s, SOLVABLE_BUILDTIME, 0)) != 0) repodata_set_num(data, s2 - pool->solvables, SOLVABLE_BUILDTIME, num); if ((str = solvable_lookup_str(s, SOLVABLE_SUMMARY)) != 0) repodata_set_str(data, s2 - pool->solvables, SOLVABLE_SUMMARY, str); if ((str = solvable_lookup_str(s, SOLVABLE_DESCRIPTION)) != 0) repodata_set_str(data, s2 - pool->solvables, SOLVABLE_DESCRIPTION, str); if ((str = solvable_lookup_str(s, SOLVABLE_DISTRIBUTION)) != 0) repodata_set_str(data, s2 - pool->solvables, SOLVABLE_DISTRIBUTION, str); /* fill in stuff from provides */ prvp = repo->idarraydata + s->provides; while ((prv = *prvp++) != 0) /* go through all provides */ { Id evr = 0; if (ISRELDEP(prv)) { Reldep *rd = GETRELDEP(pool, prv); if (rd->flags != REL_EQ) continue; prv = rd->name; evr = rd->evr; } pn = pool_id2str(pool, prv); if (strncmp("product-", pn, 8) != 0) continue; newname = 0; if (evr) { newname = pool_tmpjoin(pool, pool_id2str(pool, evr), 0, 0); unescape(newname); } if (!strcmp(pn, "product-label()") && evr) repodata_set_str(data, s2 - pool->solvables, PRODUCT_SHORTLABEL, newname); else if (!strcmp(pn, "product-type()") && evr) repodata_set_str(data, s2 - pool->solvables, PRODUCT_TYPE, newname); else if (!strcmp(pn, "product-cpeid()") && evr) repodata_set_str(data, s2 - pool->solvables, SOLVABLE_CPEID, newname); else if (!strcmp(pn, "product-flags()") && evr) repodata_add_poolstr_array(data, s2 - pool->solvables, PRODUCT_FLAGS, newname); else if (!strcmp(pn, "product-updates-repoid()") && evr) repodata_add_poolstr_array(data, s2 - pool->solvables, PRODUCT_UPDATES_REPOID, newname); else if (!strncmp(pn, "product-url(", 12) && evr && pn[12] && pn[13] && strlen(pn + 12) < 32) { char type[34]; strcpy(type, pn + 12); type[strlen(type) - 1] = 0; /* closing ) */ repodata_add_poolstr_array(data, s2 - pool->solvables, PRODUCT_URL_TYPE, type); repodata_add_poolstr_array(data, s2 - pool->solvables, PRODUCT_URL, newname); } } } queue_free(&prdq); queue_free(&prdq2); if (data && !(flags & REPO_NO_INTERNALIZE)) repodata_internalize(data); else if (!data && !(flags & REPO_NO_INTERNALIZE)) repo_internalize(repo); return 0; }
static void pool_addfileprovides_dep(Pool *pool, Id *ida, struct searchfiles *sf, struct searchfiles *isf) { Id dep, sid; const char *s; struct searchfiles *csf; while ((dep = *ida++) != 0) { csf = sf; while (ISRELDEP(dep)) { Reldep *rd; sid = pool->ss.nstrings + GETRELID(dep); if (MAPTST(&csf->seen, sid)) { dep = 0; break; } MAPSET(&csf->seen, sid); rd = GETRELDEP(pool, dep); if (rd->flags < 8) dep = rd->name; else if (rd->flags == REL_NAMESPACE) { if (rd->name == NAMESPACE_SPLITPROVIDES) { csf = isf; if (!csf || MAPTST(&csf->seen, sid)) { dep = 0; break; } MAPSET(&csf->seen, sid); } dep = rd->evr; } else if (rd->flags == REL_FILECONFLICT) { dep = 0; break; } else { Id ids[2]; ids[0] = rd->name; ids[1] = 0; pool_addfileprovides_dep(pool, ids, csf, isf); dep = rd->evr; } } if (!dep) continue; if (MAPTST(&csf->seen, dep)) continue; MAPSET(&csf->seen, dep); s = pool_id2str(pool, dep); if (*s != '/') continue; if (csf != isf && pool->addedfileprovides == 1 && !repodata_filelistfilter_matches(0, s)) continue; /* skip non-standard locations csf == isf: installed case */ csf->ids = solv_extend(csf->ids, csf->nfiles, 1, sizeof(Id), SEARCHFILES_BLOCK); csf->ids[csf->nfiles++] = dep; } }
/* warning: does inplace changes */ static void control2solvable(Solvable *s, Repodata *data, char *control) { Repo *repo = s->repo; Pool *pool = repo->pool; char *p, *q, *end, *tag; int x, l; int havesource = 0; char checksum[32 * 2 + 1]; Id checksumtype = 0; Id newtype; p = control; while (*p) { p = strchr(p, '\n'); if (!p) break; if (p[1] == ' ' || p[1] == '\t') { char *q; /* continuation line */ q = p - 1; while (q >= control && *q == ' ' && *q == '\t') q--; l = q + 1 - control; if (l) memmove(p + 1 - l, control, l); control = p + 1 - l; p[1] = '\n'; p += 2; continue; } end = p - 1; if (*p) *p++ = 0; /* strip trailing space */ while (end >= control && (*end == ' ' || *end == '\t')) *end-- = 0; tag = control; control = p; q = strchr(tag, ':'); if (!q || q - tag < 4) continue; *q++ = 0; while (*q == ' ' || *q == '\t') q++; x = '@' + (tag[0] & 0x1f); x = (x << 8) + '@' + (tag[1] & 0x1f); switch(x) { case 'A' << 8 | 'R': if (!strcasecmp(tag, "architecture")) s->arch = pool_str2id(pool, q, 1); break; case 'B' << 8 | 'R': if (!strcasecmp(tag, "breaks")) s->conflicts = makedeps(repo, q, s->conflicts, 0); break; case 'C' << 8 | 'O': if (!strcasecmp(tag, "conflicts")) s->conflicts = makedeps(repo, q, s->conflicts, 0); break; case 'D' << 8 | 'E': if (!strcasecmp(tag, "depends")) s->requires = makedeps(repo, q, s->requires, -SOLVABLE_PREREQMARKER); else if (!strcasecmp(tag, "description")) { char *ld = strchr(q, '\n'); if (ld) { *ld++ = 0; repodata_set_str(data, s - pool->solvables, SOLVABLE_DESCRIPTION, ld); } else repodata_set_str(data, s - pool->solvables, SOLVABLE_DESCRIPTION, q); repodata_set_str(data, s - pool->solvables, SOLVABLE_SUMMARY, q); } break; case 'E' << 8 | 'N': if (!strcasecmp(tag, "enhances")) s->enhances = makedeps(repo, q, s->enhances, 0); break; case 'F' << 8 | 'I': if (!strcasecmp(tag, "filename")) repodata_set_location(data, s - pool->solvables, 0, 0, q); break; case 'H' << 8 | 'O': if (!strcasecmp(tag, "homepage")) repodata_set_str(data, s - pool->solvables, SOLVABLE_URL, q); break; case 'I' << 8 | 'N': if (!strcasecmp(tag, "installed-size")) repodata_set_num(data, s - pool->solvables, SOLVABLE_INSTALLSIZE, strtoull(q, 0, 10) << 10); break; case 'M' << 8 | 'D': if (!strcasecmp(tag, "md5sum") && !checksumtype && strlen(q) == 16 * 2) { strcpy(checksum, q); checksumtype = REPOKEY_TYPE_MD5; } break; case 'P' << 8 | 'A': if (!strcasecmp(tag, "package")) s->name = pool_str2id(pool, q, 1); break; case 'P' << 8 | 'R': if (!strcasecmp(tag, "pre-depends")) s->requires = makedeps(repo, q, s->requires, SOLVABLE_PREREQMARKER); else if (!strcasecmp(tag, "provides")) s->provides = makedeps(repo, q, s->provides, 0); break; case 'R' << 8 | 'E': if (!strcasecmp(tag, "replaces")) s->obsoletes = makedeps(repo, q, s->obsoletes, 0); else if (!strcasecmp(tag, "recommends")) s->recommends = makedeps(repo, q, s->recommends, 0); break; case 'S' << 8 | 'H': newtype = solv_chksum_str2type(tag); if (!newtype || solv_chksum_len(newtype) * 2 != strlen(q)) break; if (!checksumtype || (newtype == REPOKEY_TYPE_SHA1 && checksumtype != REPOKEY_TYPE_SHA256) || newtype == REPOKEY_TYPE_SHA256) { strcpy(checksum, q); checksumtype = newtype; } break; case 'S' << 8 | 'O': if (!strcasecmp(tag, "source")) { char *q2; /* ignore version for now */ for (q2 = q; *q2; q2++) if (*q2 == ' ' || *q2 == '\t') { *q2 = 0; break; } if (s->name && !strcmp(q, pool_id2str(pool, s->name))) repodata_set_void(data, s - pool->solvables, SOLVABLE_SOURCENAME); else repodata_set_id(data, s - pool->solvables, SOLVABLE_SOURCENAME, pool_str2id(pool, q, 1)); havesource = 1; } break; case 'S' << 8 | 'T': if (!strcasecmp(tag, "status")) repodata_set_poolstr(data, s - pool->solvables, SOLVABLE_INSTALLSTATUS, q); break; case 'S' << 8 | 'U': if (!strcasecmp(tag, "suggests")) s->suggests = makedeps(repo, q, s->suggests, 0); break; case 'V' << 8 | 'E': if (!strcasecmp(tag, "version")) s->evr = pool_str2id(pool, q, 1); break; } } if (checksumtype) repodata_set_checksum(data, s - pool->solvables, SOLVABLE_CHECKSUM, checksumtype, checksum); if (!s->arch) s->arch = ARCH_ALL; if (!s->evr) s->evr = ID_EMPTY; if (s->name) s->provides = repo_addid_dep(repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0); if (s->name && !havesource) repodata_set_void(data, s - pool->solvables, SOLVABLE_SOURCENAME); if (s->obsoletes) { /* obsoletes only count when the packages also conflict */ /* XXX: should not transcode here */ int i, j, k; Id d, cid; for (i = j = s->obsoletes; (d = repo->idarraydata[i]) != 0; i++) { if (!s->conflicts) continue; for (k = s->conflicts; (cid = repo->idarraydata[k]) != 0; k++) { if (repo->idarraydata[k] == cid) break; if (ISRELDEP(cid)) { Reldep *rd = GETRELDEP(pool, cid); if (rd->flags < 8 && rd->name == d) break; /* specialize obsoletes */ } } if (cid) repo->idarraydata[j++] = cid; } repo->idarraydata[j] = 0; if (j == s->obsoletes) s->obsoletes = 0; } }
int repo_add_autopattern(Repo *repo, int flags) { Pool *pool = repo->pool; Repodata *data = 0; Solvable *s, *s2; Queue q, q2; Id p; Id pattern_id; Id autopattern_id = 0; int i, j; queue_init(&q); queue_init(&q2); pattern_id = pool_str2id(pool, "pattern()", 9); FOR_REPO_SOLVABLES(repo, p, s) { const char *n = pool_id2str(pool, s->name); if (!strncmp("pattern:", n, 8)) queue_push(&q, p); else if (s->provides) { Id prv, *prvp = repo->idarraydata + s->provides; while ((prv = *prvp++) != 0) /* go through all provides */ if (ISRELDEP(prv)) { Reldep *rd = GETRELDEP(pool, prv); if (rd->name == pattern_id && rd->flags == REL_EQ) { queue_push2(&q2, p, rd->evr); break; } } } } for (i = 0; i < q2.count; i += 2) { const char *pn = 0; char *newname; Id name, prv, *prvp; const char *str; unsigned long long num; s = pool->solvables + q2.elements[i]; /* construct new name */ newname = pool_tmpjoin(pool, "pattern:", pool_id2str(pool, q2.elements[i + 1]), 0); unescape(newname); name = pool_str2id(pool, newname, 0); if (name) { /* check if we already have that pattern */ for (j = 0; j < q.count; j++) { s2 = pool->solvables + q.elements[j]; if (s2->name == name && s2->arch == s->arch && s2->evr == s->evr) break; } if (j < q.count) continue; /* yes, do not add again */ } /* new pattern */ if (!name) name = pool_str2id(pool, newname, 1); if (!data) { repo_internalize(repo); /* to make that the lookups work */ data = repo_add_repodata(repo, flags); } s2 = pool_id2solvable(pool, repo_add_solvable(repo)); s = pool->solvables + q2.elements[i]; /* re-calc pointer */ s2->name = name; s2->arch = s->arch; s2->evr = s->evr; s2->vendor = s->vendor; /* add link requires */ s2->requires = repo_addid_dep(repo, s2->requires, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1) , 0); /* add autopattern provides */ if (!autopattern_id) autopattern_id = pool_str2id(pool, "autopattern()", 1); s2->provides = repo_addid_dep(repo, s2->provides, pool_rel2id(pool, autopattern_id, s->name, REL_EQ, 1), 0); /* add self provides */ s2->provides = repo_addid_dep(repo, s2->provides, pool_rel2id(pool, s2->name, s2->evr, REL_EQ, 1), 0); if ((num = solvable_lookup_num(s, SOLVABLE_INSTALLTIME, 0)) != 0) repodata_set_num(data, s2 - pool->solvables, SOLVABLE_INSTALLTIME, num); if ((num = solvable_lookup_num(s, SOLVABLE_BUILDTIME, 0)) != 0) repodata_set_num(data, s2 - pool->solvables, SOLVABLE_BUILDTIME, num); if ((str = solvable_lookup_str(s, SOLVABLE_SUMMARY)) != 0) repodata_set_str(data, s2 - pool->solvables, SOLVABLE_SUMMARY, str); if ((str = solvable_lookup_str(s, SOLVABLE_DESCRIPTION)) != 0) repodata_set_str(data, s2 - pool->solvables, SOLVABLE_DESCRIPTION, str); /* fill in stuff from provides */ prvp = repo->idarraydata + s->provides; while ((prv = *prvp++) != 0) /* go through all provides */ { Id evr = 0; if (ISRELDEP(prv)) { Reldep *rd = GETRELDEP(pool, prv); if (rd->flags != REL_EQ) continue; prv = rd->name; evr = rd->evr; } pn = pool_id2str(pool, prv); if (strncmp("pattern-", pn, 8) != 0) continue; newname = 0; if (evr) { newname = pool_tmpjoin(pool, pool_id2str(pool, evr), 0, 0); unescape(newname); } if (!strncmp(pn, "pattern-category(", 17) && evr) { char lang[9]; int l = strlen(pn); Id langtag; if (l > 17 + 9 || pn[l - 1] != ')') continue; strncpy(lang, pn + 17, l - 17 - 1); lang[l - 17 - 1] = 0; langtag = SOLVABLE_CATEGORY; if (*lang && strcmp(lang, "en") != 0) langtag = pool_id2langid(pool, SOLVABLE_CATEGORY, lang, 1); repodata_set_str(data, s2 - pool->solvables, langtag, newname); } else if (!strcmp(pn, "pattern-includes()") && evr) repodata_add_poolstr_array(data, s2 - pool->solvables, SOLVABLE_INCLUDES, pool_tmpjoin(pool, "pattern:", newname, 0)); else if (!strcmp(pn, "pattern-extends()") && evr) repodata_add_poolstr_array(data, s2 - pool->solvables, SOLVABLE_EXTENDS, pool_tmpjoin(pool, "pattern:", newname, 0)); else if (!strcmp(pn, "pattern-icon()") && evr) repodata_set_str(data, s2 - pool->solvables, SOLVABLE_ICON, newname); else if (!strcmp(pn, "pattern-order()") && evr) repodata_set_str(data, s2 - pool->solvables, SOLVABLE_ORDER, newname); else if (!strcmp(pn, "pattern-visible()") && !evr) repodata_set_void(data, s2 - pool->solvables, SOLVABLE_ISVISIBLE); } } queue_free(&q); queue_free(&q2); if (data && !(flags & REPO_NO_INTERNALIZE)) repodata_internalize(data); else if (!data && !(flags & REPO_NO_INTERNALIZE)) repo_internalize(repo); return 0; }
Offset repo_fix_supplements(Repo *repo, Offset provides, Offset supplements, Offset freshens) { Pool *pool = repo->pool; Id id, idp, idl; char buf[1024], *p, *dep; int i, l; if (provides) { for (i = provides; repo->idarraydata[i]; i++) { id = repo->idarraydata[i]; if (ISRELDEP(id)) continue; dep = (char *)pool_id2str(pool, id); if (!strncmp(dep, "locale(", 7) && strlen(dep) < sizeof(buf) - 2) { idp = 0; strcpy(buf + 2, dep); dep = buf + 2 + 7; if ((p = strchr(dep, ':')) != 0 && p != dep) { *p++ = 0; idp = pool_str2id(pool, dep, 1); dep = p; } id = 0; while ((p = strchr(dep, ';')) != 0) { if (p == dep) { dep = p + 1; continue; } *p++ = 0; idl = pool_str2id(pool, dep, 1); idl = pool_rel2id(pool, NAMESPACE_LANGUAGE, idl, REL_NAMESPACE, 1); if (id) id = pool_rel2id(pool, id, idl, REL_OR, 1); else id = idl; dep = p; } if (dep[0] && dep[1]) { for (p = dep; *p && *p != ')'; p++) ; *p = 0; idl = pool_str2id(pool, dep, 1); idl = pool_rel2id(pool, NAMESPACE_LANGUAGE, idl, REL_NAMESPACE, 1); if (id) id = pool_rel2id(pool, id, idl, REL_OR, 1); else id = idl; } if (idp) id = pool_rel2id(pool, idp, id, REL_AND, 1); if (id) supplements = repo_addid_dep(repo, supplements, id, 0); } else if ((p = strchr(dep, ':')) != 0 && p != dep && p[1] == '/' && strlen(dep) < sizeof(buf)) { strcpy(buf, dep); p = buf + (p - dep); *p++ = 0; idp = pool_str2id(pool, buf, 1); /* strip trailing slashes */ l = strlen(p); while (l > 1 && p[l - 1] == '/') p[--l] = 0; id = pool_str2id(pool, p, 1); id = pool_rel2id(pool, idp, id, REL_WITH, 1); id = pool_rel2id(pool, NAMESPACE_SPLITPROVIDES, id, REL_NAMESPACE, 1); supplements = repo_addid_dep(repo, supplements, id, 0); } } } if (supplements) { for (i = supplements; repo->idarraydata[i]; i++) { id = repo->idarraydata[i]; if (ISRELDEP(id)) continue; dep = (char *)pool_id2str(pool, id); if (!strncmp(dep, "system:modalias(", 16)) dep += 7; if (!strncmp(dep, "modalias(", 9) && dep[9] && dep[10] && strlen(dep) < sizeof(buf)) { strcpy(buf, dep); p = strchr(buf + 9, ':'); if (p && p != buf + 9 && strchr(p + 1, ':')) { *p++ = 0; idp = pool_str2id(pool, buf + 9, 1); p[strlen(p) - 1] = 0; id = pool_str2id(pool, p, 1); id = pool_rel2id(pool, NAMESPACE_MODALIAS, id, REL_NAMESPACE, 1); id = pool_rel2id(pool, idp, id, REL_AND, 1); } else { p = buf + 9; p[strlen(p) - 1] = 0; id = pool_str2id(pool, p, 1); id = pool_rel2id(pool, NAMESPACE_MODALIAS, id, REL_NAMESPACE, 1); } if (id) repo->idarraydata[i] = id; } else if (!strncmp(dep, "packageand(", 11) && strlen(dep) < sizeof(buf)) { strcpy(buf, dep); id = 0; dep = buf + 11; while ((p = strchr(dep, ':')) != 0) { if (p == dep) { dep = p + 1; continue; } *p++ = 0; idp = pool_str2id(pool, dep, 1); if (id) id = pool_rel2id(pool, id, idp, REL_AND, 1); else id = idp; dep = p; } if (dep[0] && dep[1]) { dep[strlen(dep) - 1] = 0; idp = pool_str2id(pool, dep, 1); if (id) id = pool_rel2id(pool, id, idp, REL_AND, 1); else id = idp; } if (id) repo->idarraydata[i] = id; } else if (!strncmp(dep, "filesystem(", 11) && strlen(dep) < sizeof(buf)) { strcpy(buf, dep + 11); if ((p = strrchr(buf, ')')) != 0) *p = 0; id = pool_str2id(pool, buf, 1); id = pool_rel2id(pool, NAMESPACE_FILESYSTEM, id, REL_NAMESPACE, 1); repo->idarraydata[i] = id; } } } if (freshens && repo->idarraydata[freshens]) { Id idsupp = 0, idfresh = 0; if (!supplements || !repo->idarraydata[supplements]) return freshens; for (i = supplements; repo->idarraydata[i]; i++) { if (!idsupp) idsupp = repo->idarraydata[i]; else idsupp = pool_rel2id(pool, idsupp, repo->idarraydata[i], REL_OR, 1); } for (i = freshens; repo->idarraydata[i]; i++) { if (!idfresh) idfresh = repo->idarraydata[i]; else idfresh = pool_rel2id(pool, idfresh, repo->idarraydata[i], REL_OR, 1); } if (!idsupp) idsupp = idfresh; else idsupp = pool_rel2id(pool, idsupp, idfresh, REL_AND, 1); supplements = repo_addid_dep(repo, 0, idsupp, 0); } return supplements; }
static void XMLCALL endElement(void *userData, const char *name) { Parsedata *pd = (Parsedata *)userData; Pool *pool = pd->pool; Solvable *s = pd->solvable; Id evr; unsigned int t = 0; const char *flavor; if (pd->depth != pd->statedepth) { pd->depth--; /* printf("back from unknown %d %d %d\n", pd->state, pd->depth, pd->statedepth); */ return; } /* ignore deps element */ if (pd->state == STATE_PACKAGE && !strcmp(name, "deps")) return; pd->depth--; pd->statedepth--; switch (pd->state) { case STATE_PACKAGE: /* package complete */ if (name[0] == 's' && name[1] == 'r' && name[2] == 'c' && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC) s->arch = ARCH_SRC; if (!s->arch) /* default to "noarch" */ s->arch = ARCH_NOARCH; if (!s->evr && pd->version) /* set solvable evr */ s->evr = evr2id(pool, pd, pd->epoch ? pd->evrspace + pd->epoch : 0, pd->version ? pd->evrspace + pd->version : 0, pd->release ? pd->evrspace + pd->release : ""); /* ensure self-provides */ if (s->name && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC) s->provides = repo_addid_dep(pd->repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0); s->supplements = repo_fix_supplements(pd->repo, s->provides, s->supplements, pd->freshens); s->conflicts = repo_fix_conflicts(pd->repo, s->conflicts); pd->freshens = 0; /* see bugzilla bnc#190163 */ flavor = findKernelFlavor(pd, s); if (flavor) { char *cflavor = solv_strdup(flavor); /* make pointer safe */ Id npr; Id pid; /* this is either a kernel package or a kmp */ if (s->provides) { Offset prov = s->provides; npr = 0; while ((pid = pd->repo->idarraydata[prov++]) != 0) { const char *depname = 0; Reldep *prd = 0; if (ISRELDEP(pid)) { prd = GETRELDEP(pool, pid); depname = pool_id2str(pool, prd->name); } else { depname = pool_id2str(pool, pid); } if (!strncmp(depname, "kernel(", 7) && !strchr(depname, ':')) { char newdep[100]; snprintf(newdep, sizeof(newdep), "kernel(%s:%s", cflavor, depname + 7); pid = pool_str2id(pool, newdep, 1); if (prd) pid = pool_rel2id(pool, pid, prd->evr, prd->flags, 1); } npr = repo_addid_dep(pd->repo, npr, pid, 0); } s->provides = npr; } #if 1 if (s->requires) { Offset reqs = s->requires; npr = 0; while ((pid = pd->repo->idarraydata[reqs++]) != 0) { const char *depname = 0; Reldep *prd = 0; if (ISRELDEP(pid)) { prd = GETRELDEP(pool, pid); depname = pool_id2str(pool, prd->name); } else { depname = pool_id2str(pool, pid); } if (!strncmp(depname, "kernel(", 7) && !strchr(depname, ':')) { char newdep[100]; snprintf(newdep, sizeof(newdep), "kernel(%s:%s", cflavor, depname + 7); pid = pool_str2id(pool, newdep, 1); if (prd) pid = pool_rel2id(pool, pid, prd->evr, prd->flags, 1); } npr = repo_addid_dep(pd->repo, npr, pid, 0); } s->requires = npr; } #endif free(cflavor); } break; case STATE_NAME: s->name = pool_str2id(pool, pd->content, 1); break; case STATE_VENDOR: s->vendor = pool_str2id(pool, pd->content, 1); break; case STATE_BUILDTIME: t = atoi (pd->content); if (t) repodata_set_num(pd->data, s - pool->solvables, SOLVABLE_BUILDTIME, t); break; case STATE_UPDATE: /* new version, keeping all other metadata */ evr = evr2id(pool, pd, pd->epoch ? pd->evrspace + pd->epoch : 0, pd->version ? pd->evrspace + pd->version : 0, pd->release ? pd->evrspace + pd->release : 0); pd->levrspace = 1; pd->epoch = 0; pd->version = 0; pd->release = 0; /* use highest evr */ if (!s->evr || pool_evrcmp(pool, s->evr, evr, EVRCMP_COMPARE) <= 0) s->evr = evr; break; case STATE_EPOCH: case STATE_VERSION: case STATE_RELEASE: case STATE_PEPOCH: case STATE_PVERSION: case STATE_PRELEASE: /* ensure buffer space */ if (pd->lcontent + 1 + pd->levrspace > pd->aevrspace) { pd->evrspace = (char *)realloc(pd->evrspace, pd->lcontent + 1 + pd->levrspace + 256); pd->aevrspace = pd->lcontent + 1 + pd->levrspace + 256; } memcpy(pd->evrspace + pd->levrspace, pd->content, pd->lcontent + 1); if (pd->state == STATE_EPOCH || pd->state == STATE_PEPOCH) pd->epoch = pd->levrspace; else if (pd->state == STATE_VERSION || pd->state == STATE_PVERSION) pd->version = pd->levrspace; else pd->release = pd->levrspace; pd->levrspace += pd->lcontent + 1; break; case STATE_ARCH: case STATE_PARCH: s->arch = pool_str2id(pool, pd->content, 1); break; default: break; } pd->state = pd->sbtab[pd->state]; pd->docontent = 0; /* printf("back from known %d %d %d\n", pd->state, pd->depth, pd->statedepth); */ }
int repo_add_mdk(Repo *repo, FILE *fp, int flags) { Pool *pool = repo->pool; Repodata *data; Solvable *s; char *buf; int bufa, bufl; data = repo_add_repodata(repo, flags); bufa = 4096; buf = solv_malloc(bufa); bufl = 0; s = 0; while (fgets(buf + bufl, bufa - bufl, fp) > 0) { bufl += strlen(buf + bufl); if (bufl && buf[bufl - 1] != '\n') { if (bufa - bufl < 256) { bufa += 4096; buf = solv_realloc(buf, bufa); } continue; } buf[--bufl] = 0; bufl = 0; if (buf[0] != '@') { pool_debug(pool, SOLV_ERROR, "bad line <%s>\n", buf); continue; } if (!s) s = pool_id2solvable(pool, repo_add_solvable(repo)); if (!strncmp(buf + 1, "filesize@", 9)) repodata_set_num(data, s - pool->solvables, SOLVABLE_DOWNLOADSIZE, strtoull(buf + 10, 0, 10)); else if (!strncmp(buf + 1, "summary@", 8)) repodata_set_str(data, s - pool->solvables, SOLVABLE_SUMMARY, buf + 9); else if (!strncmp(buf + 1, "provides@", 9)) s->provides = parse_deps(s, buf + 10, 0); else if (!strncmp(buf + 1, "requires@", 9)) s->requires = parse_deps(s, buf + 10, SOLVABLE_PREREQMARKER); else if (!strncmp(buf + 1, "suggests@", 9)) s->suggests = parse_deps(s, buf + 10, 0); else if (!strncmp(buf + 1, "obsoletes@", 10)) s->obsoletes = parse_deps(s, buf + 11, 0); else if (!strncmp(buf + 1, "conflicts@", 10)) s->conflicts = parse_deps(s, buf + 11, 0); else if (!strncmp(buf + 1, "info@", 5)) { char *nvra = buf + 6; char *epochstr; char *arch; char *version; char *filename; if ((epochstr = strchr(nvra, '@')) != 0) { char *sizestr; *epochstr++ = 0; if ((sizestr = strchr(epochstr, '@')) != 0) { char *groupstr; *sizestr++ = 0; if ((groupstr = strchr(sizestr, '@')) != 0) { char *n; *groupstr++ = 0; if ((n = strchr(groupstr, '@')) != 0) *n = 0; if (*groupstr) repodata_set_poolstr(data, s - pool->solvables, SOLVABLE_GROUP, groupstr); } repodata_set_num(data, s - pool->solvables, SOLVABLE_INSTALLSIZE, strtoull(sizestr, 0, 10)); } } filename = pool_tmpjoin(pool, nvra, ".rpm", 0); arch = strrchr(nvra, '.'); if (arch) { *arch++ = 0; s->arch = pool_str2id(pool, arch, 1); } /* argh, do we have a distepoch or not, check self-provides */ if (s->provides) { Id id, lastid, *idp = s->repo->idarraydata + s->provides; lastid = 0; for (idp = s->repo->idarraydata + s->provides; (id = *idp) != 0; idp++) { const char *evr, *name; int namel; Reldep *rd; if (!ISRELDEP(id)) continue; rd = GETRELDEP(pool, id); if (rd->flags != REL_EQ) continue; name = pool_id2str(pool, rd->name); namel = strlen(name); if (strncmp(name, nvra, namel) != 0 || nvra[namel] != '-') continue; evr = pool_id2str(pool, rd->evr); evr = strrchr(evr, '-'); if (evr && strchr(evr, ':') != 0) lastid = id; } if (lastid) { /* self provides found, and it contains a distepoch */ /* replace with self-provides distepoch to get rid of the disttag */ char *nvradistepoch = strrchr(nvra, '-'); if (nvradistepoch) { Reldep *rd = GETRELDEP(pool, lastid); const char *evr = pool_id2str(pool, rd->evr); evr = strrchr(evr, '-'); if (evr && (evr = strchr(evr, ':')) != 0) { if (strlen(evr) < strlen(nvradistepoch)) strcpy(nvradistepoch, evr); } } } } version = strrchr(nvra, '-'); if (version) { char *release = version; *release = 0; version = strrchr(nvra, '-'); *release = '-'; if (!version) version = release; *version++ = 0; } else version = ""; s->name = pool_str2id(pool, nvra, 1); if (epochstr && *epochstr && strcmp(epochstr, "0") != 0) { char *evr = pool_tmpjoin(pool, epochstr, ":", version); s->evr = pool_str2id(pool, evr, 1); } else s->evr = pool_str2id(pool, version, 1); repodata_set_location(data, s - pool->solvables, 0, 0, filename); if (s->name && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC) s->provides = repo_addid_dep(s->repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0); s = 0; } else { char *tagend = strchr(buf + 1, '@'); if (tagend) *tagend = 0; pool_debug(pool, SOLV_ERROR, "unknown tag <%s>\n", buf + 1); continue; } } if (s) { pool_debug(pool, SOLV_ERROR, "unclosed package at EOF\n"); repo_free_solvable(s->repo, s - pool->solvables, 1); } solv_free(buf); if (!(flags & REPO_NO_INTERNALIZE)) repodata_internalize(data); return 0; }
/* * returns: * 0: no blocks * 1: matches all * -1: at least one block */ static int normalize_dep(Pool *pool, Id dep, Queue *bq, int flags) { int bqcnt = bq->count; int bqcnt2; int todnf = flags & CPLXDEPS_TODNF ? 1 : 0; Id p, dp; #ifdef CPLXDEBUG printf("normalize_dep %s todnf:%d\n", pool_dep2str(pool, dep), todnf); #endif if (pool_is_complex_dep(pool, dep)) { Reldep *rd = GETRELDEP(pool, dep); if (rd->flags == REL_AND || rd->flags == REL_OR || rd->flags == REL_COND) { int rdflags = rd->flags; Id name = rd->name; Id evr = rd->evr; int r, mode; if (rdflags == REL_COND) { /* check for relly complex ELSE case */ if (ISRELDEP(evr)) { Reldep *rd2 = GETRELDEP(pool, evr); if (rd2->flags == REL_ELSE) { int r2; /* really complex case */ if ((flags & CPLXDEPS_ELSE_MASK) == CPLXDEPS_ELSE_AND_1) { /* A OR ~B */ rdflags = REL_COND; evr = rd2->name; } else if ((flags & CPLXDEPS_ELSE_MASK) == CPLXDEPS_ELSE_AND_2) { /* C OR B */ rdflags = REL_OR; name = rd2->evr; evr = rd2->name; } else if ((flags & CPLXDEPS_ELSE_MASK) == CPLXDEPS_ELSE_OR_1) { /* A AND B */ rdflags = REL_AND; evr = rd2->name; } else if ((flags & CPLXDEPS_ELSE_MASK) == CPLXDEPS_ELSE_OR_2) { /* A AND C */ rdflags = REL_AND; evr = rd2->evr; } else if ((flags & CPLXDEPS_ELSE_MASK) == CPLXDEPS_ELSE_OR_3) { /* C AND ~B */ rdflags = REL_ELSE; name = rd2->evr; evr = rd2->name; } else if (!todnf) { /* we want AND: A IF (B ELSE C) -> (A OR ~B) AND (C OR B) */ r = normalize_dep(pool, dep, bq, flags | CPLXDEPS_ELSE_AND_1); if (r == 0 && (flags & CPLXDEPS_DONTFIX) == 0) return 0; r2 = normalize_dep(pool, dep, bq, flags | CPLXDEPS_ELSE_AND_2); if (r2 == 0 && (flags & CPLXDEPS_DONTFIX) == 0) { queue_truncate(bq, bqcnt); return 0; } if (r == -1 || r2 == -1) return -1; return r == 1 || r2 == 1 ? 1 : 0; } else { int r2, r3; /* we want OR: A IF (B ELSE C) -> (A AND B) OR (A AND C) OR (~B AND C) */ r = normalize_dep(pool, dep, bq, flags | CPLXDEPS_ELSE_OR_1); if (r == 1) return 1; r2 = normalize_dep(pool, dep, bq, flags | CPLXDEPS_ELSE_OR_2); if (r2 == 1) { queue_truncate(bq, bqcnt); return 1; } r3 = normalize_dep(pool, dep, bq, flags | CPLXDEPS_ELSE_OR_3); if (r3 == 1) { queue_truncate(bq, bqcnt); return 1; } if (r == -1 || r2 == -1 || r3 == -1) return -1; return 0; } } } } mode = rdflags == REL_AND || rdflags == REL_ELSE ? 0 : 1; /* get blocks of first argument */ r = normalize_dep(pool, name, bq, flags); if (r == 0) { if (rdflags == REL_ELSE) return 0; if (rdflags == REL_AND && (flags & CPLXDEPS_DONTFIX) == 0) return 0; if (rdflags == REL_COND) { r = normalize_dep(pool, evr, bq, (flags ^ CPLXDEPS_TODNF) & ~CPLXDEPS_DONTFIX); return invert_depblocks(pool, bq, bqcnt, r); /* invert block for COND */ } return normalize_dep(pool, evr, bq, flags); } if (r == 1) { if (rdflags == REL_ELSE) { r = normalize_dep(pool, evr, bq, (flags ^ CPLXDEPS_TODNF) & ~CPLXDEPS_DONTFIX); return invert_depblocks(pool, bq, bqcnt, r); /* invert block for ELSE */ } if (rdflags == REL_OR || rdflags == REL_COND) return 1; return normalize_dep(pool, evr, bq, flags); } /* get blocks of second argument */ bqcnt2 = bq->count; /* COND is OR with NEG on evr block, so we invert the todnf flag in that case */ r = normalize_dep(pool, evr, bq, rdflags == REL_COND || rdflags == REL_ELSE ? ((flags ^ CPLXDEPS_TODNF) & ~CPLXDEPS_DONTFIX) : flags); if (rdflags == REL_COND || rdflags == REL_ELSE) r = invert_depblocks(pool, bq, bqcnt2, r); /* invert 2nd block */ if (r == 0) { if (rdflags == REL_OR) return -1; if (rdflags == REL_AND && (flags & CPLXDEPS_DONTFIX) != 0) return -1; queue_truncate(bq, bqcnt); return 0; } if (r == 1) { if (rdflags == REL_COND || rdflags == REL_OR) { queue_truncate(bq, bqcnt); return 1; } return -1; } if (mode == todnf) { /* simple case: just join em. nothing more to do here. */ #ifdef CPLXDEBUG printf("SIMPLE JOIN %d %d %d\n", bqcnt, bqcnt2, bq->count); #endif return -1; } else { /* complex case: mix em */ int i, j, bqcnt3; #ifdef CPLXDEBUG printf("COMPLEX JOIN %d %d %d\n", bqcnt, bqcnt2, bq->count); #endif bqcnt2 = expand_simpledeps(pool, bq, bqcnt, bqcnt2); bqcnt3 = bq->count; for (i = bqcnt; i < bqcnt2; i++) { for (j = bqcnt2; j < bqcnt3; j++) { int a, b; int bqcnt4 = bq->count; int k = i; /* mix i block with j block, both blocks are sorted */ while (bq->elements[k] && bq->elements[j]) { if (bq->elements[k] < bq->elements[j]) queue_push(bq, bq->elements[k++]); else { if (bq->elements[k] == bq->elements[j]) k++; queue_push(bq, bq->elements[j++]); } } while (bq->elements[j]) queue_push(bq, bq->elements[j++]); while (bq->elements[k]) queue_push(bq, bq->elements[k++]); /* block is finished, check for A + -A */ for (a = bqcnt4, b = bq->count - 1; a < b; ) { if (-bq->elements[a] == bq->elements[b]) break; if (-bq->elements[a] > bq->elements[b]) a++; else b--; } if (a < b) queue_truncate(bq, bqcnt4); /* ignore this block */ else queue_push(bq, 0); /* finish block */ } /* advance to next block */ while (bq->elements[i]) i++; } i = -1; if (bqcnt3 == bq->count) /* ignored all blocks? */ i = todnf ? 0 : 1; queue_deleten(bq, bqcnt, bqcnt3 - bqcnt); return i; } } } /* fallback case: just use package list */ dp = pool_whatprovides(pool, dep); if (dp <= 2 || !pool->whatprovidesdata[dp]) return dp == 2 ? 1 : 0; if (pool->whatprovidesdata[dp] == SYSTEMSOLVABLE) return 1; bqcnt = bq->count; if ((flags & CPLXDEPS_NAME) != 0) { while ((p = pool->whatprovidesdata[dp++]) != 0) { if (!pool_match_nevr(pool, pool->solvables + p, dep)) continue; queue_push(bq, p); if (todnf) queue_push(bq, 0); } } else if (todnf) { while ((p = pool->whatprovidesdata[dp++]) != 0) queue_push2(bq, p, 0); } else queue_push2(bq, pool->nsolvables, dp); /* not yet expanded marker + offset */ if (bq->count == bqcnt) return 0; /* no provider */ if (!todnf) queue_push(bq, 0); /* finish block */ return -1; }