From 560f20469f373bc8779587b8692b9949f38fc4bb Mon Sep 17 00:00:00 2001 From: Michael Schroeder Date: Tue, 14 Jul 2009 18:34:49 +0200 Subject: [PATCH] - add new flags for the load functions: REPO_LOCALPOOL - create local pool REPO_EXTEND_SOLVABLES - extend existing solvables instead of creating new ones REPO_USE_LOADING - replace repodata in state loading - add repo_add_solv_flags to make repo_add_solv use flags - make repo_add_solv obey the flags instead of using defaults if this is a subload - change loadcallback definition to return a boolean, the callback is now responsible for the loading - change repo_write so that the keyfilter can select which repodata to use (hack) - change pool_addfileprovides to load the complete filelist if needed - add SEARCH_COMPLETE_FILELIST flag to searches - add transaction_create_installedmap/transaction_calc_installsizechange --- examples/solv.c | 418 ++++++++++++++++++++++++++++++++++++++++++---------- ext/repo_rpmmd.c | 26 ++++ ext/repo_susetags.c | 143 +++++++++++------- ext/repo_susetags.h | 4 +- ext/repo_write.c | 11 ++ src/pool.c | 40 ++++- src/pool.h | 6 +- src/repo.c | 26 +++- src/repo.h | 3 + src/repo_solv.c | 177 ++++------------------ src/repo_solv.h | 1 + src/repodata.c | 206 +++++++++++++++++--------- src/repodata.h | 5 + src/transaction.c | 47 ++++++ src/transaction.h | 4 + tools/dumpsolv.c | 20 ++- tools/mergesolv.c | 22 ++- 17 files changed, 786 insertions(+), 373 deletions(-) diff --git a/examples/solv.c b/examples/solv.c index 15878e4..e04221c 100644 --- a/examples/solv.c +++ b/examples/solv.c @@ -72,6 +72,8 @@ struct repoinfo { int gpgcheck; int priority; int keeppackages; + + unsigned char extcookie[32]; }; #ifdef FEDORA @@ -556,10 +558,16 @@ setarch(Pool *pool) pool_setarch(pool, un.machine); } -char *calccachepath(Repo *repo) +char *calccachepath(Repo *repo, const char *repoext) { char *q, *p = pool_tmpjoin(repo->pool, SOLVCACHE_PATH, "/", repo->name); - p = pool_tmpjoin(repo->pool, p, ".solv", 0); + if (repoext) + { + p = pool_tmpjoin(repo->pool, p, "_", repoext); + p = pool_tmpjoin(repo->pool, p, ".solvx", 0); + } + else + p = pool_tmpjoin(repo->pool, p, ".solv", 0); q = p + strlen(SOLVCACHE_PATH) + 1; if (*q == '.') *q = '_'; @@ -570,12 +578,15 @@ char *calccachepath(Repo *repo) } int -usecachedrepo(Repo *repo, unsigned char *cookie) +usecachedrepo(Repo *repo, const char *repoext, unsigned char *cookie) { FILE *fp; unsigned char mycookie[32]; + struct repoinfo *cinfo; + int flags = 0; - if (!(fp = fopen(calccachepath(repo), "r"))) + cinfo = repo->appdata; + if (!(fp = fopen(calccachepath(repo, repoext), "r"))) return 0; if (fseek(fp, -sizeof(mycookie), SEEK_END) || fread(mycookie, sizeof(mycookie), 1, fp) != 1) { @@ -588,28 +599,53 @@ usecachedrepo(Repo *repo, unsigned char *cookie) return 0; } rewind(fp); - if (repo_add_solv(repo, fp)) + if (repoext && !strcmp(repoext, "DL")) + flags = REPO_USE_LOADING|REPO_EXTEND_SOLVABLES; + else if (repoext) + flags = REPO_USE_LOADING|REPO_LOCALPOOL|REPO_EXTEND_SOLVABLES; + + if (repo_add_solv_flags(repo, fp, flags)) { fclose(fp); return 0; } + if (!repoext && cinfo) + { + struct stat stb; + if (!fstat(fileno(fp), &stb)) + calc_checksum_stat(&stb, REPOKEY_TYPE_SHA256, cinfo->extcookie); + } fclose(fp); return 1; } -void -writecachedrepo(Repo *repo, unsigned char *cookie) +int +myrepodatafilter(Repo *repo, Repokey *key, void *kfdata) +{ + Repodata *data = kfdata; + + if (key->name == 1 && key->size != data - repo->repodata) + return -1; + if (key->storage == KEY_STORAGE_SOLVABLE) + return KEY_STORAGE_DROPPED; + return repo_write_stdkeyfilter(repo, key, kfdata); +} + +static void +writecachedrepo(Repo *repo, Repodata *info, const char *repoext, unsigned char *cookie) { Id *addedfileprovides = 0; FILE *fp; int i, fd; char *tmpl; - Repodata *info; + int myinfo = 0; + struct repoinfo *cinfo; + cinfo = repo->appdata; mkdir(SOLVCACHE_PATH, 0755); tmpl = sat_dupjoin(SOLVCACHE_PATH, "/", ".newsolv-XXXXXX"); fd = mkstemp(tmpl); - if (!fd) + if (fd < 0) { free(tmpl); return; @@ -622,17 +658,27 @@ writecachedrepo(Repo *repo, unsigned char *cookie) free(tmpl); return; } - info = repo_add_repodata(repo, 0); - pool_addfileprovides_ids(repo->pool, 0, &addedfileprovides); - if (addedfileprovides && *addedfileprovides) + if (!repoext) { - for (i = 0; addedfileprovides[i]; i++) - repodata_add_idarray(info, SOLVID_META, REPOSITORY_ADDEDFILEPROVIDES, addedfileprovides[i]); + if (!info) + { + info = repo_add_repodata(repo, 0); + myinfo = 1; + } + pool_addfileprovides_ids(repo->pool, 0, &addedfileprovides); + if (addedfileprovides && *addedfileprovides) + { + for (i = 0; addedfileprovides[i]; i++) + repodata_add_idarray(info, SOLVID_META, REPOSITORY_ADDEDFILEPROVIDES, addedfileprovides[i]); + } + sat_free(addedfileprovides); + repodata_internalize(info); + repo_write(repo, fp, repo_write_stdkeyfilter, 0, 0); } - sat_free(addedfileprovides); - repodata_internalize(info); - repo_write(repo, fp, 0, 0, 0); - repodata_free(info); + else + repo_write(repo, fp, myrepodatafilter, info, 0); + if (myinfo) + repodata_free(info); if (fwrite(cookie, 32, 1, fp) != 1) { fclose(fp); @@ -646,7 +692,13 @@ writecachedrepo(Repo *repo, unsigned char *cookie) free(tmpl); return; } - if (!rename(tmpl, calccachepath(repo))) + if (!repoext && cinfo) + { + struct stat stb; + if (!stat(tmpl, &stb)) + calc_checksum_stat(&stb, REPOKEY_TYPE_SHA256, cinfo->extcookie); + } + if (!rename(tmpl, calccachepath(repo, repoext))) unlink(tmpl); free(tmpl); } @@ -668,7 +720,7 @@ iscompressed(const char *name) } static inline const char * -findinrepomd(Repo *repo, const char *what, const unsigned char **chksump, Id *chksumtypep) +repomd_find(Repo *repo, const char *what, const unsigned char **chksump, Id *chksumtypep) { Pool *pool = repo->pool; Dataiterator di; @@ -694,6 +746,228 @@ findinrepomd(Repo *repo, const char *what, const unsigned char **chksump, Id *ch return filename; } +int +repomd_add_ext(Repo *repo, Repodata *data, const char *what) +{ + Pool *pool = repo->pool; + Dataiterator di; + Id chksumtype, handle; + const unsigned char *chksum; + const char *filename; + + dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_REPOMD_TYPE, what, SEARCH_STRING); + dataiterator_prepend_keyname(&di, REPOSITORY_REPOMD); + if (!dataiterator_step(&di)) + { + dataiterator_free(&di); + return 0; + } + if (!strcmp(what, "prestodelta")) + what = "deltainfo"; + dataiterator_setpos_parent(&di); + filename = pool_lookup_str(pool, SOLVID_POS, REPOSITORY_REPOMD_LOCATION); + chksum = pool_lookup_bin_checksum(pool, SOLVID_POS, REPOSITORY_REPOMD_CHECKSUM, &chksumtype); + if (!filename || !chksum) + { + dataiterator_free(&di); + return 0; + } + handle = repodata_new_handle(data); + repodata_set_poolstr(data, handle, REPOSITORY_REPOMD_TYPE, what); + repodata_set_str(data, handle, REPOSITORY_REPOMD_LOCATION, filename); + if (chksumtype) + repodata_set_bin_checksum(data, handle, REPOSITORY_REPOMD_CHECKSUM, chksumtype, chksum); + if (!strcmp(what, "deltainfo")) + { + repodata_add_idarray(data, handle, REPOSITORY_KEYS, REPOSITORY_DELTAINFO); + repodata_add_idarray(data, handle, REPOSITORY_KEYS, REPOKEY_TYPE_FLEXARRAY); + repodata_add_idarray(data, handle, REPOSITORY_KEYS, DELTA_PACKAGE_NAME); + repodata_add_idarray(data, handle, REPOSITORY_KEYS, REPOKEY_TYPE_ID); + repodata_add_idarray(data, handle, REPOSITORY_KEYS, DELTA_PACKAGE_EVR); + repodata_add_idarray(data, handle, REPOSITORY_KEYS, REPOKEY_TYPE_ID); + repodata_add_idarray(data, handle, REPOSITORY_KEYS, DELTA_PACKAGE_ARCH); + repodata_add_idarray(data, handle, REPOSITORY_KEYS, REPOKEY_TYPE_ID); + repodata_add_idarray(data, handle, REPOSITORY_KEYS, DELTA_BASE_EVR); + repodata_add_idarray(data, handle, REPOSITORY_KEYS, REPOKEY_TYPE_ID); + } + if (!strcmp(what, "filelists")) + { + repodata_add_idarray(data, handle, REPOSITORY_KEYS, SOLVABLE_FILELIST); + repodata_add_idarray(data, handle, REPOSITORY_KEYS, REPOKEY_TYPE_DIRSTRARRAY); + } + dataiterator_free(&di); + repodata_add_flexarray(data, SOLVID_META, REPOSITORY_EXTERNAL, handle); + return 1; +} + +static inline const char * +susetags_find(Repo *repo, const char *what, const unsigned char **chksump, Id *chksumtypep) +{ + Pool *pool = repo->pool; + Dataiterator di; + const char *filename; + + filename = 0; + *chksump = 0; + *chksumtypep = 0; + dataiterator_init(&di, pool, repo, SOLVID_META, SUSETAGS_FILE_NAME, what, SEARCH_STRING); + dataiterator_prepend_keyname(&di, SUSETAGS_FILE); + if (dataiterator_step(&di)) + { + dataiterator_setpos_parent(&di); + *chksump = pool_lookup_bin_checksum(pool, SOLVID_POS, SUSETAGS_FILE_CHECKSUM, chksumtypep); + filename = what; + } + dataiterator_free(&di); + if (filename && !*chksumtypep) + { + printf("no %s file checksum!\n", what); + filename = 0; + } + return filename; +} + + +int +load_stub(Pool *pool, Repodata *data, void *dp) +{ + const char *filename, *descrdir, *repomdtype; + const unsigned char *filechksum; + Id filechksumtype; + struct repoinfo *cinfo; + FILE *fp; + Id defvendor; + char ext[3]; + + cinfo = data->repo->appdata; + + filename = repodata_lookup_str(data, SOLVID_META, SUSETAGS_FILE_NAME); + if (filename) + { + /* susetags load */ + ext[0] = filename[9]; + ext[1] = filename[10]; + ext[2] = 0; +#if 1 + printf("[%s:%s", data->repo->name, ext); +#endif + if (usecachedrepo(data->repo, ext, cinfo->extcookie)) + { + printf(" cached]"); fflush(stdout); + return 1; + } +#if 1 + printf(" loading]"); fflush(stdout); +#endif + defvendor = repo_lookup_id(data->repo, SOLVID_META, SUSETAGS_DEFAULTVENDOR); + descrdir = repo_lookup_str(data->repo, SOLVID_META, SUSETAGS_DESCRDIR); + if (!descrdir) + descrdir = "suse/setup/descr"; + filechksumtype = 0; + filechksum = repodata_lookup_bin_checksum(data, SOLVID_META, SUSETAGS_FILE_CHECKSUM, &filechksumtype); + if ((fp = curlfopen(cinfo, pool_tmpjoin(pool, descrdir, "/", filename), iscompressed(filename), filechksum, filechksumtype)) == 0) + return 0; + repo_add_susetags(data->repo, fp, defvendor, ext, REPO_USE_LOADING|REPO_EXTEND_SOLVABLES); + fclose(fp); + writecachedrepo(data->repo, data, ext, cinfo->extcookie); + return 1; + } + + repomdtype = repodata_lookup_str(data, SOLVID_META, REPOSITORY_REPOMD_TYPE); + if (repomdtype) + { + if (!strcmp(repomdtype, "filelists")) + strcpy(ext, "FL"); + else if (!strcmp(repomdtype, "deltainfo")) + strcpy(ext, "DL"); + else + return 0; +#if 1 + printf("[%s:%s", data->repo->name, ext); +#endif + if (usecachedrepo(data->repo, ext, cinfo->extcookie)) + { + printf(" cached]");fflush(stdout); + return 1; + } + printf(" loading]"); fflush(stdout); + filename = repodata_lookup_str(data, SOLVID_META, REPOSITORY_REPOMD_LOCATION); + filechksumtype = 0; + filechksum = repodata_lookup_bin_checksum(data, SOLVID_META, SUSETAGS_FILE_CHECKSUM, &filechksumtype); + if ((fp = curlfopen(cinfo, filename, iscompressed(filename), filechksum, filechksumtype)) == 0) + return 0; + if (!strcmp(ext, "FL")) + repo_add_rpmmd(data->repo, fp, ext, REPO_USE_LOADING|REPO_EXTEND_SOLVABLES); + else if (!strcmp(ext, "DL")) + repo_add_deltainfoxml(data->repo, fp, REPO_USE_LOADING); + fclose(fp); + writecachedrepo(data->repo, data, ext, cinfo->extcookie); + return 1; + } + + return 0; +} + +Id susetags_langtags[] = { + SOLVABLE_SUMMARY, REPOKEY_TYPE_STR, + SOLVABLE_DESCRIPTION, REPOKEY_TYPE_STR, + SOLVABLE_EULA, REPOKEY_TYPE_STR, + SOLVABLE_MESSAGEINS, REPOKEY_TYPE_STR, + SOLVABLE_MESSAGEDEL, REPOKEY_TYPE_STR, + SOLVABLE_CATEGORY, REPOKEY_TYPE_ID, + 0, 0 +}; + +void +susetags_add_ext(Repo *repo, Repodata *data) +{ + Pool *pool = repo->pool; + Dataiterator di; + char ext[3]; + Id handle, filechksumtype; + const unsigned char *filechksum; + int i; + + dataiterator_init(&di, pool, repo, SOLVID_META, SUSETAGS_FILE_NAME, 0, 0); + dataiterator_prepend_keyname(&di, SUSETAGS_FILE); + while (dataiterator_step(&di)) + { + if (strncmp(di.kv.str, "packages.", 9) != 0) + continue; + if (!di.kv.str[9] || !di.kv.str[10] || (di.kv.str[11] && di.kv.str[11] != '.')) + continue; + ext[0] = di.kv.str[9]; + ext[1] = di.kv.str[10]; + ext[2] = 0; + if (!susetags_find(repo, di.kv.str, &filechksum, &filechksumtype)) + continue; + handle = repodata_new_handle(data); + repodata_set_str(data, handle, SUSETAGS_FILE_NAME, di.kv.str); + if (filechksumtype) + repodata_set_bin_checksum(data, handle, SUSETAGS_FILE_CHECKSUM, filechksumtype, filechksum); + if (!strcmp(ext, "DU")) + { + repodata_add_idarray(data, handle, REPOSITORY_KEYS, SOLVABLE_DISKUSAGE); + repodata_add_idarray(data, handle, REPOSITORY_KEYS, REPOKEY_TYPE_DIRNUMNUMARRAY); + } + if (!strcmp(ext, "FL")) + { + repodata_add_idarray(data, handle, REPOSITORY_KEYS, SOLVABLE_FILELIST); + repodata_add_idarray(data, handle, REPOSITORY_KEYS, REPOKEY_TYPE_DIRSTRARRAY); + } + else + { + for (i = 0; susetags_langtags[i]; i += 2) + { + repodata_add_idarray(data, handle, REPOSITORY_KEYS, pool_id2langid(pool, susetags_langtags[i], ext, 1)); + repodata_add_idarray(data, handle, REPOSITORY_KEYS, susetags_langtags[i + 1]); + } + } + repodata_add_flexarray(data, SOLVID_META, REPOSITORY_EXTERNAL, handle); + } + dataiterator_free(&di); +} + void read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos) { @@ -702,7 +976,6 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos) int i; FILE *fp; FILE *sigfp; - Dataiterator di; const char *filename; const unsigned char *filechksum; Id filechksumtype; @@ -711,13 +984,14 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos) struct stat stb; unsigned char cookie[32]; Pool *sigpool = 0; + Repodata *data; repo = repo_create(pool, "@System"); printf("rpm database:"); if (stat("/var/lib/rpm/Packages", &stb)) memset(&stb, 0, sizeof(&stb)); calc_checksum_stat(&stb, REPOKEY_TYPE_SHA256, cookie); - if (usecachedrepo(repo, cookie)) + if (usecachedrepo(repo, 0, cookie)) printf(" cached\n"); else { @@ -728,7 +1002,7 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos) #ifdef PRODUCTS_PATH repo_add_products(repo, PRODUCTS_PATH, 0, REPO_NO_INTERNALIZE); #endif - if ((ofp = fopen(calccachepath(repo), "r")) != 0) + if ((ofp = fopen(calccachepath(repo, 0), "r")) != 0) { Repo *ref = repo_create(pool, "@System.old"); if (!repo_add_solv(ref, ofp)) @@ -741,7 +1015,7 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos) } if (!done) repo_add_rpmdb(repo, 0, 0, REPO_REUSE_REPODATA); - writecachedrepo(repo, cookie); + writecachedrepo(repo, 0, 0, cookie); } pool_set_installed(pool, repo); @@ -756,7 +1030,7 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos) repo->appdata = cinfo; repo->priority = 99 - cinfo->priority; - if (!cinfo->autorefresh && usecachedrepo(repo, 0)) + if (!cinfo->autorefresh && usecachedrepo(repo, 0, 0)) { printf("repo '%s':", cinfo->alias); printf(" cached\n"); @@ -775,7 +1049,7 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos) break; } calc_checksum_fp(fp, REPOKEY_TYPE_SHA256, cookie); - if (usecachedrepo(repo, cookie)) + if (usecachedrepo(repo, 0, cookie)) { printf(" cached\n"); fclose(fp); @@ -806,39 +1080,32 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos) repo_add_repomdxml(repo, fp, 0); fclose(fp); printf(" reading\n"); - filename = findinrepomd(repo, "primary", &filechksum, &filechksumtype); + filename = repomd_find(repo, "primary", &filechksum, &filechksumtype); if (filename && (fp = curlfopen(cinfo, filename, iscompressed(filename), filechksum, filechksumtype)) != 0) { repo_add_rpmmd(repo, fp, 0, 0); fclose(fp); } - filename = findinrepomd(repo, "updateinfo", &filechksum, &filechksumtype); + filename = repomd_find(repo, "updateinfo", &filechksum, &filechksumtype); if (filename && (fp = curlfopen(cinfo, filename, iscompressed(filename), filechksum, filechksumtype)) != 0) { repo_add_updateinfoxml(repo, fp, 0); fclose(fp); } - filename = findinrepomd(repo, "deltainfo", &filechksum, &filechksumtype); - if (!filename) - filename = findinrepomd(repo, "prestodelta", &filechksum, &filechksumtype); - if (filename && (fp = curlfopen(cinfo, filename, iscompressed(filename), filechksum, filechksumtype)) != 0) - { - repo_add_deltainfoxml(repo, fp, 0); - fclose(fp); - } - - writecachedrepo(repo, cookie); + data = repo_last_repodata(repo); + if (!repomd_add_ext(repo, data, "deltainfo")) + repomd_add_ext(repo, data, "prestodelta"); + repomd_add_ext(repo, data, "filelists"); + repodata_internalize(data); + writecachedrepo(repo, data, 0, cookie); + repodata_create_stubs(data); break; case TYPE_SUSETAGS: printf("susetags repo '%s':", cinfo->alias); fflush(stdout); - repo = repo_create(pool, cinfo->alias); - cinfo->repo = repo; - repo->appdata = cinfo; - repo->priority = 99 - cinfo->priority; descrdir = 0; defvendor = 0; if ((fp = curlfopen(cinfo, "content", 0, 0, 0)) == 0) @@ -849,7 +1116,7 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos) break; } calc_checksum_fp(fp, REPOKEY_TYPE_SHA256, cookie); - if (usecachedrepo(repo, cookie)) + if (usecachedrepo(repo, 0, cookie)) { printf(" cached\n"); fclose(fp); @@ -881,44 +1148,24 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos) descrdir = repo_lookup_str(repo, SOLVID_META, SUSETAGS_DESCRDIR); if (!descrdir) descrdir = "suse/setup/descr"; - filename = 0; - dataiterator_init(&di, pool, repo, SOLVID_META, SUSETAGS_FILE_NAME, "packages.gz", SEARCH_STRING); - dataiterator_prepend_keyname(&di, SUSETAGS_FILE); - if (dataiterator_step(&di)) - { - dataiterator_setpos_parent(&di); - filechksum = pool_lookup_bin_checksum(pool, SOLVID_POS, SUSETAGS_FILE_CHECKSUM, &filechksumtype); - filename = "packages.gz"; - } - dataiterator_free(&di); - if (!filename) - { - dataiterator_init(&di, pool, repo, SOLVID_META, SUSETAGS_FILE_NAME, "packages", SEARCH_STRING); - dataiterator_prepend_keyname(&di, SUSETAGS_FILE); - if (dataiterator_step(&di)) - { - dataiterator_setpos_parent(&di); - filechksum = pool_lookup_bin_checksum(pool, SOLVID_POS, SUSETAGS_FILE_CHECKSUM, &filechksumtype); - filename = "packages"; - } - dataiterator_free(&di); - } + filename = susetags_find(repo, "packages.gz", &filechksum, &filechksumtype); + if (!filename) + filename = susetags_find(repo, "packages", &filechksum, &filechksumtype); if (!filename) { printf(" no packages file entry, skipped\n"); break; } - if (!filechksumtype) - { - printf(" no packages file checksum, skipped\n"); - break; - } printf(" reading\n"); if ((fp = curlfopen(cinfo, pool_tmpjoin(pool, descrdir, "/", filename), iscompressed(filename), filechksum, filechksumtype)) == 0) break; repo_add_susetags(repo, fp, defvendor, 0, 0); fclose(fp); - writecachedrepo(repo, cookie); + data = repo_last_repodata(repo); + susetags_add_ext(repo, data); + repodata_internalize(data); + writecachedrepo(repo, data, 0, cookie); + repodata_create_stubs(data); break; default: printf("unsupported repo '%s': skipped\n", cinfo->alias); @@ -1184,6 +1431,7 @@ main(int argc, char **argv) } pool = pool_create(); + pool_setloadcallback(pool, load_stub, 0); pool->nscallback = nscallback; // pool_setdebuglevel(pool, 2); setarch(pool); @@ -1213,7 +1461,10 @@ main(int argc, char **argv) FOR_JOB_SELECT(p, pp, job.elements[i], job.elements[i + 1]) { Solvable *s = pool_id2solvable(pool, p); + const char *sum = solvable_lookup_str_lang(s, SOLVABLE_SUMMARY, "de"); printf(" - %s [%s]\n", solvable2str(pool, s), s->repo->name); + if (sum) + printf(" %s\n", sum); } } exit(0); @@ -1352,7 +1603,9 @@ rerunsolver: solver_free(solv); solv = 0; } - if (!solv->trans.steps.count) + + trans = &solv->trans; + if (!trans->steps.count) { printf("Nothing to do.\n"); exit(1); @@ -1360,13 +1613,30 @@ rerunsolver: printf("\n"); printf("Transaction summary:\n\n"); solver_printtransaction(solv); + +#if 1 + if (1) + { + DUChanges duc[4]; + int i; + + duc[0].path = "/"; + duc[1].path = "/usr/share/man"; + duc[2].path = "/sbin"; + duc[3].path = "/etc"; + transaction_calc_duchanges(trans, duc, 4); + for (i = 0; i < 4; i++) + printf("duchanges %s: %d K %d\n", duc[i].path, duc[i].kbytes, duc[i].files); + printf("install size change: %d K\n", transaction_calc_installsizechange(trans)); + } +#endif + if (!yesno("OK to continue (y/n)? ")) { printf("Abort.\n"); exit(1); } - trans = &solv->trans; queue_init(&checkq); newpkgs = transaction_installedresult(trans, &checkq); newpkgsfps = 0; @@ -1400,7 +1670,7 @@ rerunsolver: if (pool->installed && pool->installed->nsolvables) { /* try a delta first */ - dataiterator_init(&di, pool, 0, SOLVID_META, DELTA_PACKAGE_NAME, id2str(pool, s->name), SEARCH_STRING); + dataiterator_init(&di, pool, s->repo, SOLVID_META, DELTA_PACKAGE_NAME, id2str(pool, s->name), SEARCH_STRING); dataiterator_prepend_keyname(&di, REPOSITORY_DELTAINFO); while (dataiterator_step(&di)) { diff --git a/ext/repo_rpmmd.c b/ext/repo_rpmmd.c index 10dbf4e..8c97ab2 100644 --- a/ext/repo_rpmmd.c +++ b/ext/repo_rpmmd.c @@ -18,6 +18,7 @@ #define DISABLE_SPLIT #include "tools_util.h" #include "repo_rpmmd.h" +#include "chksum.h" enum state { @@ -126,6 +127,7 @@ static struct stateswitch stateswitches[] = { /** tags for different package data, we just ignore the tag **/ { STATE_START, "metadata", STATE_START, 0 }, { STATE_START, "otherdata", STATE_START, 0 }, + { STATE_START, "filelists", STATE_START, 0 }, { STATE_START, "diskusagedata", STATE_START, 0 }, { STATE_START, "susedata", STATE_START, 0 }, @@ -1125,6 +1127,29 @@ repo_add_rpmmd(Repo *repo, FILE *fp, const char *language, int flags) the package checksums we know about, to get an Id we can use in a cache */ stringpool_init_empty(&pd.cspool); + if ((flags & REPO_EXTEND_SOLVABLES) != 0) + { + /* setup join data */ + Dataiterator di; + dataiterator_init(&di, pool, repo, 0, SOLVABLE_CHECKSUM, 0, 0); + while (dataiterator_step(&di)) + { + const char *str; + int index; + + if (!sat_chksum_len(di.key->type)) + continue; + str = repodata_chk2str(di.data, di.key->type, (const unsigned char *)di.kv.str); + index = stringpool_str2id(&pd.cspool, str, 1); + if (index >= pd.ncscache) + { + pd.cscache = sat_zextend(pd.cscache, pd.ncscache, index + 1 - pd.ncscache, sizeof(Id), 255); + pd.ncscache = index + 1; + } + pd.cscache[index] = di.solvid; + } + dataiterator_free(&di); + } XML_Parser parser = XML_ParserCreate(NULL); XML_SetUserData(parser, &pd); @@ -1147,6 +1172,7 @@ repo_add_rpmmd(Repo *repo, FILE *fp, const char *language, int flags) join_freemem(); stringpool_free(&pd.cspool); sat_free(pd.cscache); + if (!(flags & REPO_NO_INTERNALIZE)) repodata_internalize(data); POOL_DEBUG(SAT_DEBUG_STATS, "repo_add_rpmmd took %d ms\n", sat_timems(now)); diff --git a/ext/repo_susetags.c b/ext/repo_susetags.c index a7b0a51..e73afed 100644 --- a/ext/repo_susetags.c +++ b/ext/repo_susetags.c @@ -14,6 +14,7 @@ #include "pool.h" #include "repo.h" +#include "hash.h" #include "tools_util.h" #include "repo_susetags.h" @@ -394,6 +395,46 @@ finish_solvable(struct parsedata *pd, Solvable *s, Id handle, Offset freshens) commit_diskusage(pd, handle); } +static Hashtable +joinhash_init(Repo *repo, Hashmask *hmp) +{ + Hashmask hm = mkmask(repo->nsolvables); + Hashtable ht = sat_calloc(hm + 1, sizeof(*ht)); + Hashval h, hh; + Solvable *s; + int i; + + FOR_REPO_SOLVABLES(repo, i, s) + { + hh = HASHCHAIN_START; + h = s->name & hm; + while (ht[h]) + h = HASHCHAIN_NEXT(h, hh, hm); + ht[h] = i; + } + *hmp = hm; + return ht; +} + +static Solvable * +joinhash_lookup(Repo *repo, Hashtable ht, Hashmask hm, Id name, Id evr, Id arch) +{ + Hashval h, hh; + + if (!name || !arch || !evr) + return 0; + hh = HASHCHAIN_START; + h = name & hm; + while (ht[h]) + { + Solvable *s = repo->pool->solvables + ht[h]; + if (s->name == name && s->evr == evr && s->arch == arch) + return s; + h = HASHCHAIN_NEXT(h, hh, hm); + } + return 0; +} + /* * parse susetags @@ -420,9 +461,14 @@ repo_add_susetags(Repo *repo, FILE *fp, Id defvendor, const char *language, int struct parsedata pd; Repodata *data = 0; Id handle = 0; + Hashtable joinhash = 0; + Hashmask joinhashm = 0; - if ((flags & SUSETAGS_EXTEND) && repo->nrepodata) - indesc = 1; + if ((flags & (SUSETAGS_EXTEND|REPO_EXTEND_SOLVABLES)) != 0 && repo->nrepodata) + { + joinhash = joinhash_init(repo, &joinhashm); + indesc = 1; + } data = repo_add_repodata(repo, flags); @@ -566,7 +612,6 @@ repo_add_susetags(Repo *repo, FILE *fp, Id defvendor, const char *language, int if ((tag == CTAG('=', 'P', 'k', 'g') || tag == CTAG('=', 'P', 'a', 't'))) { - Id name, evr, arch; /* If we have an old solvable, complete it by filling in some default stuff. */ if (s) @@ -589,66 +634,49 @@ repo_add_susetags(Repo *repo, FILE *fp, Id defvendor, const char *language, int pool_debug(pool, SAT_FATAL, "susetags: bad line: %d: %s\n", pd.lineno, line); exit(1); } - /* Lookup (but don't construct) the name and arch. */ - if (pd.kind) - name = str2id(pool, join2(pd.kind, ":", sp[0]), 0); - else - name = str2id(pool, sp[0], 0); - arch = str2id(pool, sp[3], 0); - evr = makeevr(pool, join2(sp[1], "-", sp[2])); - s = 0; freshens = 0; - /* Now see if we know this solvable already. If we found neither - the name nor the arch at all in this repo - there's no chance of finding the exact solvable either. */ - if (name && arch && (indesc >= 2)) - { - int n, nn; - /* Now look for a solvable with the given name,evr,arch. - Our input is structured so, that the second set of =Pkg - lines comes in roughly the same order as the first set, so we - have a hint at where to start our search, namely were we found - the last entry. */ - for (n = repo->start, nn = n + last_found_pack; n < repo->end; n++, nn++) - { - if (nn >= repo->end) - nn = repo->start; - s = pool->solvables + nn; - if (s->repo == repo && s->name == name && s->evr == evr && s->arch == arch) - break; - } - if (n == repo->end) - s = 0; - else - { - last_found_pack = nn - repo->start; - handle = nn; - } - } - - - /* And if we still don't have a solvable, create a new one. */ - if (!s) + if (!joinhash) { + /* normal operation. create a new solvable. */ s = pool_id2solvable(pool, repo_add_solvable(repo)); - last_found_pack = (s - pool->solvables) - repo->start; - if (data) - handle = s - pool->solvables; - if (name) - s->name = name; - else if (pd.kind) + if (pd.kind) s->name = str2id(pool, join2(pd.kind, ":", sp[0]), 1); else s->name = str2id(pool, sp[0], 1); - s->evr = evr; - if (arch) - s->arch = arch; - else - s->arch = str2id(pool, sp[3], 1); + s->evr = makeevr(pool, join2(sp[1], "-", sp[2])); + s->arch = str2id(pool, sp[3], 1); s->vendor = defvendor; } + else + { + /* data join operation. find solvable matching name/arch/evr and + * add data to it */ + Id name, evr, arch; + /* we don't use the create flag here as a simple pre-check for existance */ + if (pd.kind) + name = str2id(pool, join2(pd.kind, ":", sp[0]), 0); + else + name = str2id(pool, sp[0], 0); + evr = makeevr(pool, join2(sp[1], "-", sp[2])); + arch = str2id(pool, sp[3], 0); + if (!name || !arch) + continue; /* ids didn't exist */ + if (repo->start + last_found_pack + 1 < repo->end) + { + s = pool->solvables + repo->start + last_found_pack + 1; + if (s->repo != repo || s->name != name || s->evr != evr || s->arch != arch) + s = 0; + } + if (!s) + s = joinhash_lookup(repo, joinhash, joinhashm, name, evr, arch); + if (!s) + continue; + } + last_found_pack = (s - pool->solvables) - repo->start; + if (data) + handle = s - pool->solvables; } /* If we have no current solvable to add to, ignore all further lines @@ -656,7 +684,9 @@ repo_add_susetags(Repo *repo, FILE *fp, Id defvendor, const char *language, int solvables. */ if (indesc >= 2 && !s) { +#if 0 pool_debug(pool, SAT_ERROR, "susetags: huh %d: %s?\n", pd.lineno, line); +#endif continue; } switch (tag) @@ -745,6 +775,12 @@ repo_add_susetags(Repo *repo, FILE *fp, Id defvendor, const char *language, int last_found_pack = 0; handle = 0; indesc++; + if (indesc > 1) + { + sat_free(joinhash); + repodata_internalize(data); + joinhash = joinhash_init(repo, &joinhashm); + } continue; case CTAG('=', 'V', 'n', 'd'): /* vendor */ s->vendor = str2id(pool, line + 6, 1); @@ -943,6 +979,7 @@ repo_add_susetags(Repo *repo, FILE *fp, Id defvendor, const char *language, int free(pd.share_with); } + sat_free(joinhash); if (!(flags & REPO_NO_INTERNALIZE)) repodata_internalize(data); diff --git a/ext/repo_susetags.h b/ext/repo_susetags.h index 57acaeb..91acd2a 100644 --- a/ext/repo_susetags.h +++ b/ext/repo_susetags.h @@ -9,7 +9,7 @@ * if given, write attributes as '.attr' */ -#define SUSETAGS_KINDS_SEPARATELY (1 << 2) -#define SUSETAGS_EXTEND (1 << 3) +#define SUSETAGS_KINDS_SEPARATELY (1 << 8) +#define SUSETAGS_EXTEND (1 << 9) extern void repo_add_susetags(Repo *repo, FILE *fp, Id defvendor, const char *language, int flags); diff --git a/ext/repo_write.c b/ext/repo_write.c index 46dfbdb..c17ead4 100644 --- a/ext/repo_write.c +++ b/ext/repo_write.c @@ -1120,6 +1120,17 @@ repo_write(Repo *repo, FILE *fp, int (*keyfilter)(Repo *repo, Repokey *key, void cbdata.keymap[n++] = 0; /* key 0 */ idused = 0; dirused = 0; + if (keyfilter) + { + Repokey zerokey; + /* check if we want this repodata */ + memset(&zerokey, 0, sizeof(zerokey)); + zerokey.name = 1; + zerokey.type = 1; + zerokey.size = i; + if (keyfilter(repo, &zerokey, kfdata) == -1) + continue; + } for (j = 1; j < data->nkeys; j++, n++) { key = data->keys + j; diff --git a/src/pool.c b/src/pool.c index 4988b0a..ad1e8cb 100644 --- a/src/pool.c +++ b/src/pool.c @@ -926,10 +926,11 @@ pool_addfileprovides_search(Pool *pool, struct addfileprovides_cbdata *cbd, stru Id p, start, end; Solvable *s; Repodata *data = 0, *nextdata; - Repo *oldrepo = 0; + Repo *repo, *oldrepo = 0; int dataincludes = 0; - int i, j; + int i, j, flags; Map providedids; + Repodata *ffldata = 0; cbd->nfiles = sf->nfiles; cbd->ids = sf->ids; @@ -947,12 +948,14 @@ pool_addfileprovides_search(Pool *pool, struct addfileprovides_cbdata *cbd, stru start = 2; /* skip system solvable */ end = pool->nsolvables; } + flags = 0; for (p = start, s = pool->solvables + p; p < end; p++, s++) { - if (!s->repo || (repoonly && s->repo != repoonly)) + repo = s->repo; + if (!repo || (repoonly && repo != repoonly)) continue; /* check if p is in (oldrepo,data) */ - if (s->repo != oldrepo || (data && p >= data->end)) + if (repo != oldrepo || (data && p >= data->end)) { data = 0; oldrepo = 0; @@ -962,7 +965,7 @@ pool_addfileprovides_search(Pool *pool, struct addfileprovides_cbdata *cbd, stru /* nope, find new repo/repodata */ /* if we don't find a match, set data to the next repodata */ nextdata = 0; - for (i = 0, data = s->repo->repodata; i < s->repo->nrepodata; i++, data++) + for (i = 0, data = repo->repodata; i < repo->nrepodata; i++, data++) { if (p >= data->end) continue; @@ -979,7 +982,7 @@ pool_addfileprovides_search(Pool *pool, struct addfileprovides_cbdata *cbd, stru if (p >= data->start) break; } - if (i == s->repo->nrepodata) + if (i == repo->nrepodata) data = nextdata; /* no direct hit, use next repodata */ if (data) { @@ -991,11 +994,32 @@ pool_addfileprovides_search(Pool *pool, struct addfileprovides_cbdata *cbd, stru map_free(&providedids); dataincludes = i == cbd->nfiles; } - oldrepo = s->repo; + oldrepo = repo; } if (data && p >= data->start && dataincludes) continue; - repo_search(s->repo, p, SOLVABLE_FILELIST, 0, 0, addfileprovides_cb, cbd); + if (ffldata == 0 || p < ffldata->start || p >= ffldata->end) + { + for (i = 0, ffldata = repo->repodata; i < repo->nrepodata; i++, ffldata++) + if (p >= ffldata->start && p < ffldata->end) + break; + if (i == repo->nrepodata) + ffldata = 0; + flags = 0; + if (ffldata) + { + for (i = 0; i < cbd->nfiles; i++) + if (!repodata_filelistfilter_matches(ffldata, id2str(pool, cbd->ids[i]))) + { +#if 0 + printf("Need the complete filelist in repo %s because of %s\n", repo->name, id2str(pool, cbd->ids[i])); +#endif + flags = SEARCH_COMPLETE_FILELIST; + break; + } + } + } + repo_search(repo, p, SOLVABLE_FILELIST, 0, flags, addfileprovides_cb, cbd); } } diff --git a/src/pool.h b/src/pool.h index 365bd66..347c7f3 100644 --- a/src/pool.h +++ b/src/pool.h @@ -117,7 +117,7 @@ struct _Pool { void *debugcallbackdata; /* load callback */ - FILE * (*loadcallback)(struct _Pool *, struct _Repodata *, void *); + int (*loadcallback)(struct _Pool *, struct _Repodata *, void *); void *loadcallbackdata; /* search position */ @@ -276,7 +276,7 @@ static inline void pool_setdebugmask(Pool *pool, int mask) pool->debugmask = mask; } -static inline void pool_setloadcallback(Pool *pool, FILE *(*cb)(struct _Pool *, struct _Repodata *, void *), void *loadcbdata) +static inline void pool_setloadcallback(Pool *pool, int (*cb)(struct _Pool *, struct _Repodata *, void *), void *loadcbdata) { pool->loadcallback = cb; pool->loadcallbackdata = loadcbdata; @@ -292,7 +292,7 @@ void pool_search(Pool *pool, Id p, Id key, const char *match, int flags, int (*c void pool_clear_pos(Pool *pool); -typedef struct _duchanges { +typedef struct _DUChanges { const char *path; int kbytes; int files; diff --git a/src/repo.c b/src/repo.c index 943a1c1..bfac9f3 100644 --- a/src/repo.c +++ b/src/repo.c @@ -805,6 +805,13 @@ repo_search_md(Repo *repo, Id p, Id keyname, struct matchdata *md) repodata_search(data, p, keyname, md->flags, repo_matchvalue, md); if (md->stop > SEARCH_NEXT_KEY) break; + if (keyname == SOLVABLE_FILELIST) + { + if (!(md->flags & SEARCH_COMPLETE_FILELIST)) + break; + if (md->matcher.match && (md->flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) == SEARCH_STRING && repodata_filelistfilter_matches(data, md->matcher.match)) + break; + } } } @@ -985,9 +992,26 @@ repo_lookup_void(Repo *repo, Id entry, Id keyname) Repodata * repo_add_repodata(Repo *repo, int flags) { + int i; + if ((flags & REPO_USE_LOADING) != 0) + { + for (i = repo->nrepodata - 1; i >= 0; i--) + if (repo->repodata[i].state == REPODATA_LOADING) + { + Repodata *data = repo->repodata + i; + /* re-init */ + /* hack: we mis-use REPO_REUSE_REPODATA here */ + if (!(flags & REPO_REUSE_REPODATA)) + { + repodata_freedata(data); + repodata_initdata(data, repo, (flags & REPO_LOCALPOOL) ? 1 : 0); + } + return data; + } + return 0; /* must not create a new repodata! */ + } if ((flags & REPO_REUSE_REPODATA) != 0) { - int i; for (i = repo->nrepodata - 1; i >= 0; i--) if (repo->repodata[i].state != REPODATA_STUB) return repo->repodata + i; diff --git a/src/repo.h b/src/repo.h index 65114b7..2f7c49a 100644 --- a/src/repo.h +++ b/src/repo.h @@ -166,6 +166,7 @@ typedef struct _KeyValue { #define SEARCH_SUB (1<<9) #define SEARCH_ARRAYSENTINEL (1<<10) #define SEARCH_DISABLED_REPOS (1<<11) +#define SEARCH_COMPLETE_FILELIST (1<<12) /* stringification flags */ #define SEARCH_SKIP_KIND (1<<16) @@ -183,6 +184,8 @@ typedef struct _KeyValue { #define REPO_REUSE_REPODATA (1 << 0) #define REPO_NO_INTERNALIZE (1 << 1) #define REPO_LOCALPOOL (1 << 2) +#define REPO_USE_LOADING (1 << 3) +#define REPO_EXTEND_SOLVABLES (1 << 4) Repodata *repo_add_repodata(Repo *repo, int flags); Repodata *repo_last_repodata(Repo *repo); diff --git a/src/repo_solv.c b/src/repo_solv.c index 813d3c4..3be8dd6 100644 --- a/src/repo_solv.c +++ b/src/repo_solv.c @@ -42,8 +42,6 @@ static Pool *mypool; /* for pool_debug... */ -static void repodata_load_stub(Repodata *data); - /******************************************************************************* * functions to extract data from a file handle @@ -408,101 +406,15 @@ incore_add_u8(Repodata *data, unsigned int x) /******************************************************************************* - * callback to create our stub sub-repodatas from the incore data - */ - -struct create_stub_data { - Repodata *data; - Id xkeyname; -}; - -static int -create_stub_cb(void *cbdata, Solvable *s, Repodata *data, Repokey *key, KeyValue *kv) -{ - struct create_stub_data *stubdata = cbdata; - if (key->name == REPOSITORY_EXTERNAL && key->type == REPOKEY_TYPE_FLEXARRAY) - { - if (stubdata->data) - { - repodata_internalize(stubdata->data); - if (data->start != data->end) - { - repodata_extend(stubdata->data, data->start); - repodata_extend(stubdata->data, data->end - 1); - } - stubdata->data = 0; - } - if (kv->eof == 2) - return SEARCH_NEXT_SOLVABLE; - stubdata->data = repo_add_repodata(data->repo, 0); - stubdata->data->state = REPODATA_STUB; - stubdata->data->loadcallback = repodata_load_stub; - return SEARCH_ENTERSUB; - } - if (!stubdata->data) - return SEARCH_NEXT_KEY; - switch(key->type) - { - case REPOKEY_TYPE_ID: - repodata_set_id(stubdata->data, SOLVID_META, key->name, kv->id); - break; - case REPOKEY_TYPE_CONSTANTID: - repodata_set_constantid(stubdata->data, SOLVID_META, key->name, kv->id); - break; - case REPOKEY_TYPE_STR: - repodata_set_str(stubdata->data, SOLVID_META, key->name, kv->str); - break; - case REPOKEY_TYPE_VOID: - repodata_set_void(stubdata->data, SOLVID_META, key->name); - break; - case REPOKEY_TYPE_NUM: - repodata_set_num(stubdata->data, SOLVID_META, key->name, kv->num); - break; - case REPOKEY_TYPE_IDARRAY: - repodata_add_idarray(stubdata->data, SOLVID_META, key->name, kv->id); - if (key->name == REPOSITORY_KEYS) - { - if (!stubdata->xkeyname) - stubdata->xkeyname = kv->id; - else - { - Repokey xkey; - - xkey.name = stubdata->xkeyname; - xkey.type = kv->id; - xkey.storage = KEY_STORAGE_INCORE; - xkey.size = 0; - repodata_key2id(stubdata->data, &xkey, 1); - stubdata->xkeyname = 0; - } - if (kv->eof) - stubdata->xkeyname = 0; - } - break; - case REPOKEY_TYPE_MD5: - case REPOKEY_TYPE_SHA1: - case REPOKEY_TYPE_SHA256: - repodata_set_checksum(stubdata->data, SOLVID_META, key->name, key->type, kv->str); - break; - default: - return SEARCH_NEXT_KEY; - } - return 0; -} - - -/******************************************************************************* * our main function */ /* * read repo from .solv file and add it to pool - * if stubdata is set, substitute it with read data - * (this is used to replace a repodata stub with the real data) */ -static int -repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent) +int +repo_add_solv_flags(Repo *repo, FILE *fp, int flags) { Pool *pool = repo->pool; int i, l; @@ -519,7 +431,7 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent) int hh; Id *hashtbl; Id name, evr, did; - int flags; + int relflags; Reldep *ran; unsigned int size_idarray; Id *idarraydatap, *idarraydataend; @@ -541,10 +453,18 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent) struct _Stringpool *spool; + Repodata *parent = 0; Repodata data; now = sat_timems(0); + if ((flags & REPO_USE_LOADING) != 0) + { + /* this is a stub replace operation */ + flags |= REPO_EXTEND_SOLVABLES; + parent = repo_add_repodata(repo, flags | REPO_REUSE_REPODATA); + } + memset(&data, 0, sizeof(data)); data.repo = repo; data.fp = fp; @@ -583,18 +503,15 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent) return SOLV_ERROR_CORRUPT; } - if (parent) + if (numrel && (flags & REPO_LOCALPOOL) != 0) { - if (numrel) - { - pool_debug(pool, SAT_ERROR, "relations are forbidden in a sub-repository\n"); - return SOLV_ERROR_CORRUPT; - } - if (parent->end - parent->start != numsolv) - { - pool_debug(pool, SAT_ERROR, "sub-repository solvable number doesn't match main repository (%d - %d)\n", parent->end - parent->start, numsolv); - return SOLV_ERROR_CORRUPT; - } + pool_debug(pool, SAT_ERROR, "relations are forbidden in a local pool\n"); + return SOLV_ERROR_CORRUPT; + } + if (parent && numsolv && parent->end - parent->start != numsolv) + { + pool_debug(pool, SAT_ERROR, "sub-repository solvable number doesn't match main repository (%d - %d)\n", parent->end - parent->start, numsolv); + return SOLV_ERROR_CORRUPT; } /******* Part 1: string IDs *****************************************/ @@ -611,7 +528,7 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent) * alloc buffers */ - if (!parent) + if (!(flags & REPO_LOCALPOOL)) spool = &pool->ss; else { @@ -690,7 +607,7 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent) strsp[sizeid] = 0; /* make string space \0 terminated */ sp = strsp; - if (parent) + if ((flags & REPO_LOCALPOOL) != 0) { /* no shared pool, thus no idmap and no unification */ idmap = 0; @@ -841,17 +758,17 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent) { name = read_id(&data, i + numid); /* read (repo relative) Ids */ evr = read_id(&data, i + numid); - flags = read_u8(&data); + relflags = read_u8(&data); name = idmap[name]; /* map to (pool relative) Ids */ evr = idmap[evr]; - h = relhash(name, evr, flags) & hashmask; + h = relhash(name, evr, relflags) & hashmask; hh = HASHCHAIN_START; for (;;) { id = hashtbl[h]; if (id == ID_NULL) /* end of hash chain */ break; - if (ran[id].name == name && ran[id].evr == evr && ran[id].flags == flags) + if (ran[id].name == name && ran[id].evr == evr && ran[id].flags == relflags) break; h = HASHCHAIN_NEXT(h, hh, hashmask); } @@ -861,7 +778,7 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent) hashtbl[h] = id; ran[id].name = name; ran[id].evr = evr; - ran[id].flags = flags; + ran[id].flags = relflags; } idmap[i + numid] = MAKERELDEP(id); /* fill Id map */ } @@ -898,12 +815,12 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent) id = read_id(&data, numid); if (idmap) id = idmap[id]; - else if (parent) + else if ((flags & REPO_LOCALPOOL) != 0) id = str2id(pool, stringpool_id2str(spool, id), 1); type = read_id(&data, numid); if (idmap) type = idmap[type]; - else if (parent) + else if ((flags & REPO_LOCALPOOL) != 0) type = str2id(pool, stringpool_id2str(spool, type), 1); if (type < REPOKEY_TYPE_VOID || type > REPOKEY_TYPE_FLEXARRAY) { @@ -923,7 +840,7 @@ repo_add_solv_parent(Repo *repo, FILE *fp, Repodata *parent) { if (idmap) keys[i].size = idmap[keys[i].size]; - else if (parent) + else if ((flags & REPO_LOCALPOOL) != 0) keys[i].size = str2id(pool, stringpool_id2str(spool, keys[i].size), 1); } #if 0 @@ -1345,7 +1262,7 @@ printf("=> %s %s %p\n", id2str(pool, keys[key].name), id2str(pool, keys[key].typ if (parent) { /* overwrite stub repodata */ - repodata_free(parent); + repodata_freedata(parent); *parent = data; } else @@ -1359,13 +1276,8 @@ printf("=> %s %s %p\n", id2str(pool, keys[key].name), id2str(pool, keys[key].typ for (key = 1 ; key < data.nkeys; key++) if (data.keys[key].name == REPOSITORY_EXTERNAL && data.keys[key].type == REPOKEY_TYPE_FLEXARRAY) break; - if (key < data.nkeys) - { - struct create_stub_data stubdata; - /* got some */ - memset(&stubdata, 0, sizeof(stubdata)); - repodata_search(&data, SOLVID_META, REPOSITORY_EXTERNAL, SEARCH_ARRAYSENTINEL, create_stub_cb, &stubdata); - } + if (key < data.nkeys && !parent) + repodata_create_stubs(&data); POOL_DEBUG(SAT_DEBUG_STATS, "repo_add_solv took %d ms\n", sat_timems(now)); POOL_DEBUG(SAT_DEBUG_STATS, "repo size: %d solvables\n", repo->nsolvables); @@ -1376,30 +1288,5 @@ printf("=> %s %s %p\n", id2str(pool, keys[key].name), id2str(pool, keys[key].typ int repo_add_solv(Repo *repo, FILE *fp) { - return repo_add_solv_parent(repo, fp, 0); -} - -static void -repodata_load_stub(Repodata *data) -{ - FILE *fp; - Pool *pool = data->repo->pool; - if (!pool->loadcallback) - { - data->state = REPODATA_ERROR; - return; - } - /* so that we can retrieve meta data */ - data->state = REPODATA_AVAILABLE; - fp = pool->loadcallback(pool, data, pool->loadcallbackdata); - if (!fp) - { - data->state = REPODATA_ERROR; - return; - } - if (repo_add_solv_parent(data->repo, fp, data)) - data->state = REPODATA_ERROR; - else - data->state = REPODATA_AVAILABLE; - fclose(fp); + return repo_add_solv_flags(repo, fp, 0); } diff --git a/src/repo_solv.h b/src/repo_solv.h index 3127258..e3e63a5 100644 --- a/src/repo_solv.h +++ b/src/repo_solv.h @@ -23,6 +23,7 @@ extern "C" { #include "repo.h" extern int repo_add_solv(Repo *repo, FILE *fp); +extern int repo_add_solv_flags(Repo *repo, FILE *fp, int flags); #ifdef __cplusplus } diff --git a/src/repodata.c b/src/repodata.c index 13b4922..0879eaa 100644 --- a/src/repodata.c +++ b/src/repodata.c @@ -472,6 +472,7 @@ maybe_load_repodata(Repodata *data, Id keyname) case REPODATA_ERROR: return 0; case REPODATA_AVAILABLE: + case REPODATA_LOADING: return 1; default: data->state = REPODATA_ERROR; @@ -1133,6 +1134,47 @@ dataiterator_find_keyname(Dataiterator *di, Id keyname) } int +repodata_filelistfilter_matches(Repodata *data, const char *str) +{ + /* '.*bin\/.*', '^\/etc\/.*', '^\/usr\/lib\/sendmail$' */ + /* for now hardcoded */ + if (strstr(str, "bin/")) + return 1; + if (!strncmp(str, "/etc/", 5)) + return 1; + if (!strcmp(str, "/usr/bin/sendmail")) + return 1; + return 0; +} + +static int +dataiterator_filelistcheck(Dataiterator *di) +{ + int i; + Repodata *data = di->data; + if (data->state != REPODATA_AVAILABLE) + return 1; + if (!repodata_precheck_keyname(data, REPOSITORY_EXTERNAL)) + return 1; + for (i = 0; i < data->nkeys; i++) + if (data->keys[i].name == REPOSITORY_EXTERNAL) + break; + if (i == data->nkeys) + return 1; + if (!(di->matcher.flags & SEARCH_COMPLETE_FILELIST)) + { + di->repodataid = -1; /* do not look somewhere else */ + return 1; + } + if (di->matcher.match && (di->matcher.flags & (SEARCH_STRINGMASK|SEARCH_NOCASE)) == SEARCH_STRING && repodata_filelistfilter_matches(di->data, di->matcher.match)) + { + di->repodataid = -1; /* do not look somewhere else */ + return 1; + } + return 1; +} + +int dataiterator_step(Dataiterator *di) { Id schema; @@ -1173,6 +1215,8 @@ dataiterator_step(Dataiterator *di) goto di_nextsolvable; di->data = di->repo->repodata + di->repodataid; } + if (di->repodataid >= 0 && di->keyname == SOLVABLE_FILELIST && !dataiterator_filelistcheck(di)) + goto di_nextrepodata; if (!maybe_load_repodata(di->data, di->keyname)) goto di_nextrepodata; di->dp = solvid2data(di->data, di->solvid, &schema); @@ -1247,6 +1291,7 @@ dataiterator_step(Dataiterator *di) if (di->repoid >= 0) { di->repoid++; + di->repodataid = 0; if (di->repoid < di->pool->nrepos) { di->repo = di->pool->repos[di->repoid]; @@ -2500,7 +2545,7 @@ fprintf(stderr, "schemadata %p\n", data->schemadata); } key = data->keys + *keyp; #if 0 - fprintf(stderr, "internalize %d:%s:%s\n", entry, id2str(data->repo->pool, key->name), id2str(data->repo->pool, key->type)); + fprintf(stderr, "internalize %d(%d):%s:%s\n", entry, entry + data->start, id2str(data->repo->pool, key->name), id2str(data->repo->pool, key->type)); #endif ndp = dp; if (oldcount) @@ -2573,96 +2618,113 @@ repodata_disable_paging(Repodata *data) repopagestore_disable_paging(&data->store); } -static inline Hashval -repodata_join_hash(Solvable *s, Id joinkey) +static void +repodata_load_stub(Repodata *data) { - if (joinkey == SOLVABLE_NAME) - return s->name; - if (joinkey == SOLVABLE_CHECKSUM) - { - Id type; - const unsigned char *chk = solvable_lookup_bin_checksum(s, joinkey, &type); - if (chk) - return 1 << 31 | chk[0] << 24 | chk[1] << 16 | chk[2] << 7 | chk[3]; - } - return 0; -} + Repo *repo = data->repo; + Pool *pool = repo->pool; + int r; -static inline int -repodata_join_match(Solvable *s1, Solvable *s2, Id joinkey) -{ - if (joinkey == SOLVABLE_NAME) - return s1->name == s2->name && s1->evr == s2->evr && s1->arch == s2->arch ? 1 : 0; - if (joinkey == SOLVABLE_CHECKSUM) + if (!pool->loadcallback) { - const unsigned char *chk1, *chk2; - Id type1, type2; - chk1 = solvable_lookup_bin_checksum(s1, joinkey, &type1); - if (!chk1) - return 0; - chk2 = solvable_lookup_bin_checksum(s2, joinkey, &type2); - if (!chk2 || type1 != type2) - return 0; - return memcmp(chk1, chk2, sat_chksum_len(type1)) ? 0 : 1; + data->state = REPODATA_ERROR; + return; } - return 0; + data->state = REPODATA_LOADING; + r = pool->loadcallback(pool, data, pool->loadcallbackdata); + if (!r) + data->state = REPODATA_ERROR; } void -repodata_join(Repodata *data, Id joinkey) +repodata_create_stubs(Repodata *data) { Repo *repo = data->repo; Pool *pool = repo->pool; - Hashmask hm = mkmask(repo->nsolvables); - Hashtable ht = sat_calloc(hm + 1, sizeof(*ht)); - Hashval h, hh; - int i, datastart, dataend; - Solvable *s; - - datastart = data->start; - dataend = data->end; - if (datastart == dataend || repo->start == repo->end) + Repodata *sdata; + int *stubdataids; + Dataiterator di; + Id xkeyname = 0; + int i, cnt = 0; + + dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0); + while (dataiterator_step(&di)) + cnt++; + dataiterator_free(&di); + if (!cnt) return; - FOR_REPO_SOLVABLES(repo, i, s) + stubdataids = sat_calloc(cnt, sizeof(*stubdataids)); + for (i = 0; i < cnt; i++) { - if (i >= datastart && i < dataend) - continue; - h = repodata_join_hash(s, joinkey); - if (!h) - continue; - h &= hm; - hh = HASHCHAIN_START; - while (ht[h]) - h = HASHCHAIN_NEXT(h, hh, hm); - ht[h] = i; + sdata = repo_add_repodata(repo, 0); + if (data->end > data->start) + { + repodata_extend(sdata, data->start); + repodata_extend(sdata, data->end - 1); + } + stubdataids[i] = sdata - repo->repodata; + sdata->state = REPODATA_STUB; + sdata->loadcallback = repodata_load_stub; } - for (i = datastart; i < dataend; i++) + i = 0; + dataiterator_init(&di, pool, repo, SOLVID_META, REPOSITORY_EXTERNAL, 0, 0); + sdata = 0; + while (dataiterator_step(&di)) { - Solvable *s = pool->solvables + i; - if (s->repo != data->repo) - continue; - if (!data->attrs[i - data->start]) - continue; - h = repodata_join_hash(s, joinkey); - if (!h) - continue; - h &= hm; - hh = HASHCHAIN_START; - while (ht[h]) + if (di.key->name == REPOSITORY_EXTERNAL && !di.nparents) + { + dataiterator_entersub(&di); + sdata = repo->repodata + stubdataids[i++]; + xkeyname = 0; + continue; + } + switch (di.key->type) { - Solvable *s2 = pool->solvables + ht[h]; - if (repodata_join_match(s, s2, joinkey)) + case REPOKEY_TYPE_ID: + repodata_set_id(sdata, SOLVID_META, di.key->name, di.kv.id); + break; + case REPOKEY_TYPE_CONSTANTID: + repodata_set_constantid(sdata, SOLVID_META, di.key->name, di.kv.id); + break; + case REPOKEY_TYPE_STR: + repodata_set_str(sdata, SOLVID_META, di.key->name, di.kv.str); + break; + case REPOKEY_TYPE_VOID: + repodata_set_void(sdata, SOLVID_META, di.key->name); + break; + case REPOKEY_TYPE_NUM: + repodata_set_num(sdata, SOLVID_META, di.key->name, di.kv.num); + break; + case REPOKEY_TYPE_MD5: + case REPOKEY_TYPE_SHA1: + case REPOKEY_TYPE_SHA256: + repodata_set_checksum(sdata, SOLVID_META, di.key->name, di.key->type, di.kv.str); + break; + case REPOKEY_TYPE_IDARRAY: + repodata_add_idarray(sdata, SOLVID_META, di.key->name, di.kv.id); + if (di.key->name == REPOSITORY_KEYS) { - /* a match! move data over */ - repodata_extend(data, ht[h]); - repodata_merge_attrs(data, ht[h], i); + Repokey xkey; + + if (!xkeyname) + { + if (!di.kv.eof) + xkeyname = di.kv.id; + continue; + } + xkey.name = xkeyname; + xkey.type = di.kv.id; + xkey.storage = KEY_STORAGE_INCORE; + xkey.size = 0; + repodata_key2id(sdata, &xkey, 1); + xkeyname = 0; } - h = HASHCHAIN_NEXT(h, hh, hm); } } - sat_free(ht); - /* all done! now free solvables */ - repo_free_solvable_block(repo, datastart, dataend - datastart, 1); + dataiterator_free(&di); + for (i = 0; i < cnt; i++) + repodata_internalize(repo->repodata + stubdataids[i]); + sat_free(stubdataids); } /* diff --git a/src/repodata.h b/src/repodata.h index ed3c474..527043d 100644 --- a/src/repodata.h +++ b/src/repodata.h @@ -47,6 +47,8 @@ typedef struct _Repodata { #define REPODATA_STUB 1 #define REPODATA_ERROR 2 #define REPODATA_STORE 3 +#define REPODATA_LOADING 4 + int state; /* available, stub or error */ void (*loadcallback)(struct _Repodata *); @@ -161,6 +163,8 @@ void repodata_search(Repodata *data, Id solvid, Id keyname, int flags, int (*cal * if not possible */ int repodata_stringify(Pool *pool, Repodata *data, Repokey *key, struct _KeyValue *kv, int flags); +int repodata_filelistfilter_matches(Repodata *data, const char *str); + /* lookup functions */ Id repodata_lookup_id(Repodata *data, Id solvid, Id keyname); @@ -228,6 +232,7 @@ void repodata_add_flexarray(Repodata *data, Id solvid, Id keyname, Id ghandle); */ void repodata_merge_attrs(Repodata *data, Id dest, Id src); +void repodata_create_stubs(Repodata *data); void repodata_join(Repodata *data, Id joinkey); /* diff --git a/src/transaction.c b/src/transaction.c index 7d67a55..914e94b 100644 --- a/src/transaction.c +++ b/src/transaction.c @@ -705,6 +705,53 @@ transaction_installedresult(Transaction *trans, Queue *installedq) return cutoff; } +static void +transaction_create_installedmap(Transaction *trans, Map *installedmap) +{ + Pool *pool = trans->pool; + Repo *installed = pool->installed; + Solvable *s; + Id p; + int i; + + map_init(installedmap, pool->nsolvables); + for (i = 0; i < trans->steps.count; i++) + { + p = trans->steps.elements[i]; + s = pool->solvables + p; + if (!installed || s->repo != installed) + MAPSET(installedmap, p); + } + if (installed) + { + FOR_REPO_SOLVABLES(installed, p, s) + if (!MAPTST(&trans->transactsmap, p)) + MAPSET(installedmap, p); + } +} + +int +transaction_calc_installsizechange(Transaction *trans) +{ + Map installedmap; + int change; + + transaction_create_installedmap(trans, &installedmap); + change = pool_calc_installsizechange(trans->pool, &installedmap); + map_free(&installedmap); + return change; +} + +void +transaction_calc_duchanges(Transaction *trans, DUChanges *mps, int nmps) +{ + Map installedmap; + + transaction_create_installedmap(trans, &installedmap); + pool_calc_duchanges(trans->pool, &installedmap, mps, nmps); + map_free(&installedmap); +} + struct _TransactionElement { Id p; /* solvable id */ Id edges; /* pointer into edges data */ diff --git a/src/transaction.h b/src/transaction.h index 8bd1ebd..c929520 100644 --- a/src/transaction.h +++ b/src/transaction.h @@ -22,6 +22,7 @@ extern "C" { #include "bitmap.h" struct _Pool; +struct _DUChanges; struct _TransactionOrderdata; typedef struct _Transaction { @@ -103,6 +104,9 @@ extern void transaction_classify_pkgs(Transaction *trans, int mode, Id type, Id packages is returned */ extern int transaction_installedresult(Transaction *trans, Queue *installedq); +int transaction_calc_installsizechange(Transaction *trans); +void transaction_calc_duchanges(Transaction *trans, struct _DUChanges *mps, int nmps); + /* order a transaction */ extern void transaction_order(Transaction *trans, int flags); diff --git a/tools/dumpsolv.c b/tools/dumpsolv.c index cc6ce94..95a5730 100644 --- a/tools/dumpsolv.c +++ b/tools/dumpsolv.c @@ -169,21 +169,27 @@ dump_some_attrs(Repo *repo, Solvable *s) #endif -static FILE * +static int loadcallback (Pool *pool, Repodata *data, void *vdata) { FILE *fp = 0; + int r; + printf("LOADCALLBACK\n"); const char *location = repodata_lookup_str(data, SOLVID_META, REPOSITORY_LOCATION); printf("loc %s\n", location); - if (location && with_attr) + if (!location || !with_attr) + return 0; + fprintf (stderr, "Loading SOLV file %s\n", location); + fp = fopen (location, "r"); + if (!fp) { - fprintf (stderr, "Loading SOLV file %s\n", location); - fp = fopen (location, "r"); - if (!fp) - perror(location); + perror(location); + return 0; } - return fp; + r = repo_add_solv_flags(data->repo, fp, REPO_USE_LOADING|REPO_LOCALPOOL); + fclose(fp); + return !r ? 1 : 0; } diff --git a/tools/mergesolv.c b/tools/mergesolv.c index 87a3295..653de47 100644 --- a/tools/mergesolv.c +++ b/tools/mergesolv.c @@ -33,19 +33,25 @@ usage() exit(0); } -static FILE * +static int loadcallback (Pool *pool, Repodata *data, void *vdata) { - FILE *fp = 0; + FILE *fp; const char *location = repodata_lookup_str(data, SOLVID_META, REPOSITORY_LOCATION); - if (location) + int r; + + if (!location) + return 0; + fprintf(stderr, "Loading SOLV file %s\n", location); + fp = fopen (location, "r"); + if (!fp) { - fprintf(stderr, "Loading SOLV file %s\n", location); - fp = fopen (location, "r"); - if (!fp) - perror(location); + perror(location); + return 0; } - return fp; + r = repo_add_solv_flags(data->repo, fp, REPO_USE_LOADING|REPO_LOCALPOOL); + fclose(fp); + return r ? 0 : 1; } int -- 2.7.4