X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=ext%2Frepo_autopattern.c;h=7edfc6ceeb2d71fd9366a02976ae28c3d0006823;hb=0254042972e8b301303ad00678e5388e7722b440;hp=5a663ba862ce9647b9d8b6a032bba5fa21fd1e7e;hpb=a55cde2e9b2692e20dfc8c5bc1770d10410256d1;p=platform%2Fupstream%2Flibsolv.git diff --git a/ext/repo_autopattern.c b/ext/repo_autopattern.c index 5a663ba..7edfc6c 100644 --- a/ext/repo_autopattern.c +++ b/ext/repo_autopattern.c @@ -5,6 +5,9 @@ * for further information */ +#define _GNU_SOURCE +#define _XOPEN_SOURCE +#include #include #include #include @@ -55,43 +58,108 @@ unescape(char *p) *q = 0; } +static time_t +datestr2timestamp(const char *date) +{ + const char *p; + struct tm tm; + + if (!date || !*date) + return 0; + for (p = date; *p >= '0' && *p <= '9'; p++) + ; + if (!*p) + return atoi(date); + memset(&tm, 0, sizeof(tm)); + p = strptime(date, "%F%T", &tm); + if (!p) + { + memset(&tm, 0, sizeof(tm)); + p = strptime(date, "%F", &tm); + if (!p || *p) + return 0; + } + return timegm(&tm); +} + int repo_add_autopattern(Repo *repo, int flags) { Pool *pool = repo->pool; Repodata *data = 0; Solvable *s, *s2; - Queue q, q2; + Queue patq, patq2; + Queue prdq, prdq2; Id p; - Id pattern_id; - Id autopattern_id = 0; + Id pattern_id, product_id; + Id autopattern_id = 0, autoproduct_id = 0; int i, j; - queue_init(&q); - queue_init(&q2); + 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 (!strncmp("pattern:", n, 8)) - queue_push(&q, p); - else if (s->provides) + 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->name == pattern_id && rd->flags == REL_EQ) + if (rd->flags != REL_EQ) + continue; + if (rd->name == pattern_id) { - queue_push2(&q2, p, rd->evr); - break; + 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 < q2.count; i += 2) + for (i = 0; i < patq2.count; i += 2) { const char *pn = 0; char *newname; @@ -99,21 +167,21 @@ repo_add_autopattern(Repo *repo, int flags) const char *str; unsigned long long num; - s = pool->solvables + q2.elements[i]; + s = pool->solvables + patq2.elements[i]; /* construct new name */ - newname = pool_tmpjoin(pool, "pattern:", pool_id2str(pool, q2.elements[i + 1]), 0); + 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 < q.count; j++) + for (j = 0; j < patq.count; j++) { - s2 = pool->solvables + q.elements[j]; + s2 = pool->solvables + patq.elements[j]; if (s2->name == name && s2->arch == s->arch && s2->evr == s->evr) break; } - if (j < q.count) + if (j < patq.count) continue; /* yes, do not add again */ } /* new pattern */ @@ -125,7 +193,7 @@ repo_add_autopattern(Repo *repo, int flags) data = repo_add_repodata(repo, flags); } s2 = pool_id2solvable(pool, repo_add_solvable(repo)); - s = pool->solvables + q2.elements[i]; /* re-calc pointer */ + s = pool->solvables + patq2.elements[i]; /* re-calc pointer */ s2->name = name; s2->arch = s->arch; s2->evr = s->evr; @@ -201,8 +269,147 @@ repo_add_autopattern(Repo *repo, int flags) repodata_set_void(data, s2 - pool->solvables, SOLVABLE_ISVISIBLE); } } - queue_free(&q); - queue_free(&q2); + 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-register-target()") && evr) + repodata_set_str(data, s2 - pool->solvables, PRODUCT_REGISTER_TARGET, newname); + else if (!strcmp(pn, "product-register-flavor()") && evr) + repodata_set_str(data, s2 - pool->solvables, PRODUCT_REGISTER_FLAVOR, 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))