static void set_sourcerpm(Repodata *data, Solvable *s, Id handle, char *sourcerpm) { const char *p, *sevr, *sarch, *name, *evr; Pool *pool; p = strrchr(sourcerpm, '.'); if (!p || strcmp(p, ".rpm") != 0) return; p--; while (p > sourcerpm && *p != '.') p--; if (*p != '.' || p == sourcerpm) return; sarch = p-- + 1; while (p > sourcerpm && *p != '-') p--; if (*p != '-' || p == sourcerpm) return; p--; while (p > sourcerpm && *p != '-') p--; if (*p != '-' || p == sourcerpm) return; sevr = p + 1; pool = s->repo->pool; if (!strcmp(sarch, "src.rpm")) repodata_set_constantid(data, handle, SOLVABLE_SOURCEARCH, ARCH_SRC); else if (!strcmp(sarch, "nosrc.rpm")) repodata_set_constantid(data, handle, SOLVABLE_SOURCEARCH, ARCH_NOSRC); else repodata_set_constantid(data, handle, SOLVABLE_SOURCEARCH, strn2id(pool, sarch, strlen(sarch) - 4, 1)); evr = id2str(pool, s->evr); if (evr && !strncmp(sevr, evr, sarch - sevr - 1) && evr[sarch - sevr - 1] == 0) repodata_set_void(data, handle, SOLVABLE_SOURCEEVR); else repodata_set_id(data, handle, SOLVABLE_SOURCEEVR, strn2id(pool, sevr, sarch - sevr - 1, 1)); name = id2str(pool, s->name); if (name && !strncmp(sourcerpm, name, sevr - sourcerpm - 1) && name[sevr - sourcerpm - 1] == 0) repodata_set_void(data, handle, SOLVABLE_SOURCENAME); else repodata_set_id(data, handle, SOLVABLE_SOURCENAME, strn2id(pool, sourcerpm, sevr - sourcerpm - 1, 1)); }
static void add_source(struct parsedata *pd, char *line, Solvable *s, Id handle) { Pool *pool = s->repo->pool; char *sp[5]; Id name; Id arch; const char *evr, *sevr; if (split(line, sp, 5) != 4) { pd->ret = pool_error(pool, -1, "susetags: line %d: bad source line '%s'\n", pd->lineno, line); return; } name = pool_str2id(pool, sp[0], 1); arch = pool_str2id(pool, sp[3], 1); /* do this before id2str */ evr = join2(&pd->jd, sp[1], "-", sp[2]); sevr = pool_id2str(pool, s->evr); if (sevr) { /* strip epoch */ const char *p; for (p = sevr; *p >= '0' && *p <= '9'; p++) ; if (p != sevr && *p == ':' && p[1]) sevr = p; } if (name == s->name) repodata_set_void(pd->data, handle, SOLVABLE_SOURCENAME); else repodata_set_id(pd->data, handle, SOLVABLE_SOURCENAME, name); if (sevr && !strcmp(sevr, evr)) repodata_set_void(pd->data, handle, SOLVABLE_SOURCEEVR); else repodata_set_id(pd->data, handle, SOLVABLE_SOURCEEVR, pool_str2id(pool, evr, 1)); repodata_set_constantid(pd->data, handle, SOLVABLE_SOURCEARCH, arch); }
static void XMLCALL endElement(void *userData, const char *name) { struct parsedata *pd = userData; Pool *pool = pd->pool; Solvable *s = pd->solvable; Repo *repo = pd->repo; #if 0 fprintf(stderr, "end: %s\n", name); #endif if (pd->depth != pd->statedepth) { pd->depth--; #if 0 fprintf(stderr, "back from unknown %d %d %d\n", pd->state, pd->depth, pd->statedepth); #endif return; } pd->depth--; pd->statedepth--; switch (pd->state) { case STATE_START: break; case STATE_UPDATES: break; case STATE_UPDATE: s->provides = repo_addid_dep(repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0); if (pd->buildtime) { repodata_set_num(pd->data, pd->datanum, SOLVABLE_BUILDTIME, pd->buildtime); pd->buildtime = (time_t)0; } break; case STATE_ID: s->name = pool_str2id(pool, join2(&pd->jd, "patch", ":", pd->content), 1); break; /* <title>imlib-1.9.15-6.fc8</title> */ case STATE_TITLE: while (pd->lcontent > 0 && pd->content[pd->lcontent - 1] == '\n') pd->content[--pd->lcontent] = 0; repodata_set_str(pd->data, pd->datanum, SOLVABLE_SUMMARY, pd->content); break; case STATE_SEVERITY: repodata_set_poolstr(pd->data, pd->datanum, UPDATE_SEVERITY, pd->content); break; case STATE_RIGHTS: repodata_set_poolstr(pd->data, pd->datanum, UPDATE_RIGHTS, pd->content); break; /* * <release>Fedora 8</release> */ case STATE_RELEASE: break; case STATE_ISSUED: break; case STATE_REFERENCES: break; case STATE_REFERENCE: break; /* * <description>This update ...</description> */ case STATE_DESCRIPTION: repodata_set_str(pd->data, pd->datanum, SOLVABLE_DESCRIPTION, pd->content); break; /* * <message>Warning! ...</message> */ case STATE_MESSAGE: repodata_set_str(pd->data, pd->datanum, UPDATE_MESSAGE, pd->content); break; case STATE_PKGLIST: break; case STATE_COLLECTION: break; case STATE_NAME: break; case STATE_PACKAGE: repodata_add_flexarray(pd->data, pd->datanum, UPDATE_COLLECTION, pd->collhandle); pd->collhandle = 0; break; /* <filename>libntlm-0.4.2-1.fc8.x86_64.rpm</filename> */ /* <filename>libntlm-0.4.2-1.fc8.x86_64.rpm</filename> */ case STATE_FILENAME: repodata_set_str(pd->data, pd->collhandle, UPDATE_COLLECTION_FILENAME, pd->content); break; /* <reboot_suggested>True</reboot_suggested> */ case STATE_REBOOT: if (pd->content[0] == 'T' || pd->content[0] == 't'|| pd->content[0] == '1') { /* FIXME: this is per-package, the global flag should be computed at runtime */ repodata_set_void(pd->data, pd->datanum, UPDATE_REBOOT); repodata_set_void(pd->data, pd->collhandle, UPDATE_REBOOT); } break; /* <restart_suggested>True</restart_suggested> */ case STATE_RESTART: if (pd->content[0] == 'T' || pd->content[0] == 't'|| pd->content[0] == '1') { /* FIXME: this is per-package, the global flag should be computed at runtime */ repodata_set_void(pd->data, pd->datanum, UPDATE_RESTART); repodata_set_void(pd->data, pd->collhandle, UPDATE_RESTART); } break; /* <relogin_suggested>True</relogin_suggested> */ case STATE_RELOGIN: if (pd->content[0] == 'T' || pd->content[0] == 't'|| pd->content[0] == '1') { /* FIXME: this is per-package, the global flag should be computed at runtime */ repodata_set_void(pd->data, pd->datanum, UPDATE_RELOGIN); repodata_set_void(pd->data, pd->collhandle, UPDATE_RELOGIN); } break; default: break; } pd->state = pd->sbtab[pd->state]; pd->docontent = 0; }
static void XMLCALL startElement(void *userData, const char *name, const char **atts) { //fprintf(stderr,"+tag: %s\n", name); struct parsedata *pd = userData; Pool *pool = pd->common.pool; Solvable *s = pd->solvable; struct stateswitch *sw; const char *str; Id handle = pd->handle; // fprintf(stderr, "into %s, from %d, depth %d, statedepth %d\n", name, pd->state, pd->depth, pd->statedepth); if (pd->depth != pd->statedepth) { pd->depth++; return; } if (pd->state == STATE_START && !strcmp(name, "patterns")) return; if (pd->state == STATE_START && !strcmp(name, "products")) return; //if (pd->state == STATE_START && !strcmp(name, "metadata")) // return; if (pd->state == STATE_SOLVABLE && !strcmp(name, "format")) return; pd->depth++; if (!pd->swtab[pd->state]) return; for (sw = pd->swtab[pd->state]; sw->from == pd->state; sw++) if (!strcmp(sw->ename, name)) break; if (sw->from != pd->state) { #if 0 fprintf(stderr, "into unknown: %s\n", name); #endif return; } pd->state = sw->to; pd->docontent = sw->docontent; pd->statedepth = pd->depth; pd->lcontent = 0; *pd->content = 0; switch(pd->state) { case STATE_SOLVABLE: pd->kind = 0; if (name[2] == 't' && name[3] == 't') pd->kind = "pattern"; else if (name[1] == 'r') pd->kind = "product"; else if (name[2] == 't' && name[3] == 'c') pd->kind = "patch"; /* to support extension metadata files like others.xml which have the following structure: <otherdata xmlns="http://linux.duke.edu/metadata/other" packages="101"> <package pkgid="b78f8664cd90efe42e09a345e272997ef1b53c18" name="zaptel-kmp-default" arch="i586"><version epoch="0" ver="1.2.10_2.6.22_rc4_git6_2" rel="70"/> ... we need to check if the pkgid is there and if it matches an already seen package, that means we don't need to create a new solvable but just append the attributes to the existing one. */ const char *pkgid; if ((pkgid = find_attr("pkgid", atts)) != NULL) { // look at the checksum cache Id index = stringpool_str2id(&pd->cspool, pkgid, 0); if (!index || index >= pd->ncscache || !pd->cscache[index]) { fprintf(stderr, "error, the repository specifies extra information about package with checksum '%s', which does not exist in the repository.\n", pkgid); exit(1); } pd->solvable = pool_id2solvable(pool, pd->cscache[index]); } else { /* this is a new package */ pd->solvable = pool_id2solvable(pool, repo_add_solvable(pd->common.repo)); pd->freshens = 0; } pd->handle = pd->solvable - pool->solvables; #if 0 fprintf(stderr, "package #%d\n", pd->solvable - pool->solvables); #endif break; case STATE_VERSION: s->evr = makeevr_atts(pool, pd, atts); break; case STATE_PROVIDES: s->provides = 0; break; case STATE_PROVIDESENTRY: s->provides = adddep(pool, pd, s->provides, atts, 0); break; case STATE_REQUIRES: s->requires = 0; break; case STATE_REQUIRESENTRY: s->requires = adddep(pool, pd, s->requires, atts, 1); break; case STATE_OBSOLETES: s->obsoletes = 0; break; case STATE_OBSOLETESENTRY: s->obsoletes = adddep(pool, pd, s->obsoletes, atts, 0); break; case STATE_CONFLICTS: s->conflicts = 0; break; case STATE_CONFLICTSENTRY: s->conflicts = adddep(pool, pd, s->conflicts, atts, 0); break; case STATE_RECOMMENDS: s->recommends = 0; break; case STATE_RECOMMENDSENTRY: s->recommends = adddep(pool, pd, s->recommends, atts, 0); break; case STATE_SUPPLEMENTS: s->supplements= 0; break; case STATE_SUPPLEMENTSENTRY: s->supplements = adddep(pool, pd, s->supplements, atts, 0); break; case STATE_SUGGESTS: s->suggests = 0; break; case STATE_SUGGESTSENTRY: s->suggests = adddep(pool, pd, s->suggests, atts, 0); break; case STATE_ENHANCES: s->enhances = 0; break; case STATE_ENHANCESENTRY: s->enhances = adddep(pool, pd, s->enhances, atts, 0); break; case STATE_FRESHENS: pd->freshens = 0; break; case STATE_FRESHENSENTRY: pd->freshens = adddep(pool, pd, pd->freshens, atts, 0); break; case STATE_EULA: case STATE_SUMMARY: case STATE_CATEGORY: case STATE_DESCRIPTION: pd->tmplang = find_attr("lang", atts); break; case STATE_USERVISIBLE: repodata_set_void(pd->data, handle, SOLVABLE_ISVISIBLE ); break; case STATE_INCLUDESENTRY: { const char *tmp = find_attr("pattern", atts); if (tmp) repodata_add_poolstr_array(pd->data, pd->handle, SOLVABLE_INCLUDES, join2("pattern", ":", tmp)); } break; case STATE_EXTENDSENTRY: { const char *tmp = find_attr("pattern", atts); if (tmp) repodata_add_poolstr_array(pd->data, pd->handle, SOLVABLE_EXTENDS, join2("pattern", ":", tmp)); } break; case STATE_LOCATION: str = find_attr("href", atts); if (str) repodata_set_location(pd->data, handle, 0, 0, str); break; case STATE_CHECKSUM: pd->tmpattr = find_attr("type", atts); break; case STATE_TIME: { unsigned int t; str = find_attr("build", atts); if (str && (t = atoi(str)) != 0) repodata_set_num(pd->data, handle, SOLVABLE_BUILDTIME, t); break; } case STATE_SIZE: { unsigned int k; str = find_attr("installed", atts); if (str && (k = atoi(str)) != 0) repodata_set_num(pd->data, handle, SOLVABLE_INSTALLSIZE, (k + 1023) / 1024); /* XXX the "package" attribute gives the size of the rpm file, i.e. the download size. Except on packman, there it seems to be something else entirely, it has a value near to the other two values, as if the rpm is uncompressed. */ str = find_attr("package", atts); if (str && (k = atoi(str)) != 0) repodata_set_num(pd->data, handle, SOLVABLE_DOWNLOADSIZE, (k + 1023) / 1024); break; } case STATE_HEADERRANGE: { unsigned int end; str = find_attr("end", atts); if (str && (end = atoi(str)) != 0) repodata_set_num(pd->data, handle, SOLVABLE_HEADEREND, end); } /* <diskusage> <dirs> <dir name="/" size="56" count="11"/> <dir name="usr/" size="56" count="11"/> <dir name="usr/bin/" size="38" count="10"/> <dir name="usr/share/" size="18" count="1"/> <dir name="usr/share/doc/" size="18" count="1"/> </dirs> </diskusage> */ case STATE_DISKUSAGE: { /* Really, do nothing, wat for <dir> tag */ break; } case STATE_DIR: { long filesz = 0, filenum = 0; unsigned dirid; if ((str = find_attr("name", atts)) != 0) dirid = repodata_str2dir(pd->data, str, 1); else { fprintf( stderr, "<dir .../> tag without 'name' attribute, atts = %p, *atts = %p\n", (void *)atts, *atts); break; } if ((str = find_attr("size", atts)) != 0) filesz = strtol(str, 0, 0); if ((str = find_attr("count", atts)) != 0) filenum = strtol(str, 0, 0); pd->dirs = sat_extend(pd->dirs, pd->ndirs, 1, sizeof(pd->dirs[0]), 31); pd->dirs[pd->ndirs][0] = dirid; pd->dirs[pd->ndirs][1] = filesz; pd->dirs[pd->ndirs][2] = filenum; pd->ndirs++; break; } default: break; } }
/* 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; }
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; }