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); if (repo == pool->installed) flags |= ADD_NO_AUTOPRODUCTS; /* no auto products for installed repos */ 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) { const char *evrstr = pool_id2str(pool, rd->evr); if (evrstr[0] == '.') /* hack to allow provides that do not create a pattern */ continue; if (patq2.count && patq2.elements[patq2.count - 2] == p) { /* hmm, two provides. choose by evrstr */ if (strcmp(evrstr, pool_id2str(pool, patq2.elements[patq2.count - 1])) >= 0) continue; patq2.count -= 2; } queue_push2(&patq2, p, rd->evr); } if (rd->name == product_id) { const char *evrstr = pool_id2str(pool, rd->evr); if (prdq2.count && prdq2.elements[prdq2.count - 2] == p) { /* hmm, two provides. choose by evrstr */ if (strcmp(evrstr, pool_id2str(pool, prdq2.elements[prdq2.count - 1])) >= 0) continue; prdq2.count -= 2; } queue_push2(&prdq2, p, rd->evr); } } } } 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 ((flags & ADD_NO_AUTOPRODUCTS) != 0) queue_empty(&prdq2); 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) { Id h = repodata_new_handle(data); repodata_set_str(data, h, PRODUCT_UPDATES_REPOID, newname); repodata_add_flexarray(data, s2 - pool->solvables, PRODUCT_UPDATES, h); } else if (!strcmp(pn, "product-endoflife()") && evr) { time_t t = datestr2timestamp(newname); if (t) repodata_set_num(data, s2 - pool->solvables, PRODUCT_ENDOFLIFE, t); } 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 XMLCALL startElement(void *userData, const char *name, const char **atts) { struct parsedata *pd = userData; Pool *pool = pd->pool; Solvable *solvable = pd->solvable; struct stateswitch *sw; /*const char *str; */ #if 0 fprintf(stderr, "start: [%d]%s\n", pd->state, name); #endif if (pd->depth != pd->statedepth) { pd->depth++; return; } pd->depth++; if (!pd->swtab[pd->state]) return; for (sw = pd->swtab[pd->state]; sw->from == pd->state; sw++) /* find name in statetable */ if (!strcmp(sw->ename, name)) break; if (sw->from != pd->state) { #if 0 fprintf(stderr, "into unknown: %s (from: %d)\n", name, pd->state); exit( 1 ); #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_START: break; case STATE_UPDATES: break; /* * <update from="*****@*****.**" * status="stable" * type="bugfix" (enhancement, security) * version="1.4"> */ case STATE_UPDATE: { const char *from = 0, *type = 0, *version = 0; for (; *atts; atts += 2) { if (!strcmp(*atts, "from")) from = atts[1]; else if (!strcmp(*atts, "type")) type = atts[1]; else if (!strcmp(*atts, "version")) version = atts[1]; } solvable = pd->solvable = pool_id2solvable(pool, repo_add_solvable(pd->repo)); pd->datanum = pd->solvable - pool->solvables; solvable->vendor = pool_str2id(pool, from, 1); solvable->evr = pool_str2id(pool, version, 1); solvable->arch = ARCH_NOARCH; if (type) repodata_set_str(pd->data, pd->datanum, SOLVABLE_PATCHCATEGORY, type); pd->buildtime = (time_t)0; } break; /* <id>FEDORA-2007-4594</id> */ case STATE_ID: break; /* <title>imlib-1.9.15-6.fc8</title> */ case STATE_TITLE: break; /* <release>Fedora 8</release> */ case STATE_RELEASE: break; /* <issued date="2008-03-21 21:36:55"/> */ case STATE_ISSUED: case STATE_UPDATED: { const char *date = 0; for (; *atts; atts += 2) { if (!strcmp(*atts, "date")) date = atts[1]; } if (date) { time_t t = datestr2timestamp(date); if (t && t > pd->buildtime) pd->buildtime = t; } } break; case STATE_REFERENCES: break; /* <reference href="https://bugzilla.redhat.com/show_bug.cgi?id=330471" * id="330471" * title="LDAP schema file missing for dhcpd" * type="bugzilla"/> */ case STATE_REFERENCE: { const char *href = 0, *id = 0, *title = 0, *type = 0; Id handle; for (; *atts; atts += 2) { if (!strcmp(*atts, "href")) href = atts[1]; else if (!strcmp(*atts, "id")) id = atts[1]; else if (!strcmp(*atts, "title")) title = atts[1]; else if (!strcmp(*atts, "type")) type = atts[1]; } handle = repodata_new_handle(pd->data); if (href) repodata_set_str(pd->data, handle, UPDATE_REFERENCE_HREF, href); if (id) repodata_set_str(pd->data, handle, UPDATE_REFERENCE_ID, id); if (title) repodata_set_str(pd->data, handle, UPDATE_REFERENCE_TITLE, title); if (type) repodata_set_poolstr(pd->data, handle, UPDATE_REFERENCE_TYPE, type); repodata_add_flexarray(pd->data, pd->datanum, UPDATE_REFERENCE, handle); } break; /* <description>This update ...</description> */ case STATE_DESCRIPTION: break; /* <message type="confirm">This update ...</message> */ case STATE_MESSAGE: break; case STATE_PKGLIST: break; /* <collection short="F8" */ case STATE_COLLECTION: break; /* <name>Fedora 8</name> */ case STATE_NAME: break; /* <package arch="ppc64" name="imlib-debuginfo" release="6.fc8" * src="http://download.fedoraproject.org/pub/fedora/linux/updates/8/ppc64/imlib-debuginfo-1.9.15-6.fc8.ppc64.rpm" * version="1.9.15"> * * * -> patch.conflicts: {name} < {version}.{release} */ case STATE_PACKAGE: { const char *arch = 0, *name = 0; Id evr = makeevr_atts(pool, pd, atts); /* parse "epoch", "version", "release" */ Id n, a = 0; Id rel_id; for (; *atts; atts += 2) { if (!strcmp(*atts, "arch")) arch = atts[1]; else if (!strcmp(*atts, "name")) name = atts[1]; } /* generated Id for name */ n = pool_str2id(pool, name, 1); rel_id = n; if (arch) { /* generate Id for arch and combine with name */ a = pool_str2id(pool, arch, 1); rel_id = pool_rel2id(pool, n, a, REL_ARCH, 1); } rel_id = pool_rel2id(pool, rel_id, evr, REL_LT, 1); solvable->conflicts = repo_addid_dep(pd->repo, solvable->conflicts, rel_id, 0); /* who needs the collection anyway? */ pd->collhandle = repodata_new_handle(pd->data); repodata_set_id(pd->data, pd->collhandle, UPDATE_COLLECTION_NAME, n); repodata_set_id(pd->data, pd->collhandle, UPDATE_COLLECTION_EVR, evr); repodata_set_id(pd->data, pd->collhandle, UPDATE_COLLECTION_ARCH, a); 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: break; /* <reboot_suggested>True</reboot_suggested> */ case STATE_REBOOT: break; /* <restart_suggested>True</restart_suggested> */ case STATE_RESTART: break; /* <relogin_suggested>True</relogin_suggested> */ case STATE_RELOGIN: break; default: break; } return; }
static void XMLCALL endElement(void *userData, const char *name) { struct parsedata *pd = userData; Solvable *s = pd->solvable; #if 0 fprintf(stderr, "end: [%d]%s\n", pd->state, 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_PRODUCT: /* product done, finish solvable */ if (pd->ctime) repodata_set_num(pd->data, pd->handle, SOLVABLE_INSTALLTIME, pd->ctime); if (pd->basename) repodata_set_str(pd->data, pd->handle, PRODUCT_REFERENCEFILE, pd->basename); /* this is where <productsdir>/baseproduct points to */ if (pd->currentproduct == pd->baseproduct) repodata_set_str(pd->data, pd->handle, PRODUCT_TYPE, "base"); if (pd->tmprel) { if (pd->tmpvers) s->evr = makeevr(pd->pool, join2(&pd->jd, pd->tmpvers, "-", pd->tmprel)); else { fprintf(stderr, "Seen <release> but no <version>\n"); } } else if (pd->tmpvers) s->evr = makeevr(pd->pool, pd->tmpvers); /* just version, no release */ pd->tmpvers = solv_free((void *)pd->tmpvers); pd->tmprel = solv_free((void *)pd->tmprel); if (!s->arch) s->arch = ARCH_NOARCH; if (!s->evr) s->evr = ID_EMPTY; if (s->name && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC) s->provides = repo_addid_dep(pd->repo, s->provides, pool_rel2id(pd->pool, s->name, s->evr, REL_EQ, 1), 0); pd->solvable = 0; break; case STATE_VENDOR: s->vendor = pool_str2id(pd->pool, pd->content, 1); break; case STATE_NAME: s->name = pool_str2id(pd->pool, join2(&pd->jd, "product", ":", pd->content), 1); break; case STATE_VERSION: pd->tmpvers = solv_strdup(pd->content); break; case STATE_RELEASE: pd->tmprel = solv_strdup(pd->content); break; case STATE_ARCH: s->arch = pool_str2id(pd->pool, pd->content, 1); break; case STATE_PRODUCTLINE: repodata_set_str(pd->data, pd->handle, PRODUCT_PRODUCTLINE, pd->content); break; case STATE_UPDATEREPOKEY: /** obsolete **/ break; case STATE_SUMMARY: repodata_set_str(pd->data, pd->handle, pool_id2langid(pd->pool, SOLVABLE_SUMMARY, pd->tmplang, 1), pd->content); break; case STATE_SHORTSUMMARY: repodata_set_str(pd->data, pd->handle, PRODUCT_SHORTLABEL, pd->content); break; case STATE_DESCRIPTION: repodata_set_str(pd->data, pd->handle, pool_id2langid(pd->pool, SOLVABLE_DESCRIPTION, pd->tmplang, 1), pd->content); break; case STATE_URL: if (pd->urltype) { repodata_add_poolstr_array(pd->data, pd->handle, PRODUCT_URL, pd->content); repodata_add_idarray(pd->data, pd->handle, PRODUCT_URL_TYPE, pd->urltype); } break; case STATE_TARGET: repodata_set_str(pd->data, pd->handle, PRODUCT_REGISTER_TARGET, pd->content); break; case STATE_REGRELEASE: repodata_set_str(pd->data, pd->handle, PRODUCT_REGISTER_RELEASE, pd->content); break; case STATE_CPEID: if (*pd->content) repodata_set_str(pd->data, pd->handle, SOLVABLE_CPEID, pd->content); break; case STATE_ENDOFLIFE: if (*pd->content) { time_t t = datestr2timestamp(pd->content); if (t) repodata_set_num(pd->data, pd->handle, PRODUCT_ENDOFLIFE, (unsigned long long)t); } break; default: break; } pd->state = pd->sbtab[pd->state]; pd->docontent = 0; #if 0 fprintf(stderr, "end: [%s] -> %d\n", name, pd->state); #endif }