int gpgcheck;
int priority;
int keeppackages;
+
+ unsigned char extcookie[32];
};
#ifdef FEDORA
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 = '_';
}
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)
{
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;
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);
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);
}
}
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;
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)
{
int i;
FILE *fp;
FILE *sigfp;
- Dataiterator di;
const char *filename;
const unsigned char *filechksum;
Id filechksumtype;
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
{
#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))
}
if (!done)
repo_add_rpmdb(repo, 0, 0, REPO_REUSE_REPODATA);
- writecachedrepo(repo, cookie);
+ writecachedrepo(repo, 0, 0, cookie);
}
pool_set_installed(pool, repo);
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");
break;
}
calc_checksum_fp(fp, REPOKEY_TYPE_SHA256, cookie);
- if (usecachedrepo(repo, cookie))
+ if (usecachedrepo(repo, 0, cookie))
{
printf(" cached\n");
fclose(fp);
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)
break;
}
calc_checksum_fp(fp, REPOKEY_TYPE_SHA256, cookie);
- if (usecachedrepo(repo, cookie))
+ if (usecachedrepo(repo, 0, cookie))
{
printf(" cached\n");
fclose(fp);
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);
}
pool = pool_create();
+ pool_setloadcallback(pool, load_stub, 0);
pool->nscallback = nscallback;
// pool_setdebuglevel(pool, 2);
setarch(pool);
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);
solver_free(solv);
solv = 0;
}
- if (!solv->trans.steps.count)
+
+ trans = &solv->trans;
+ if (!trans->steps.count)
{
printf("Nothing to do.\n");
exit(1);
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;
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))
{
#define DISABLE_SPLIT
#include "tools_util.h"
#include "repo_rpmmd.h"
+#include "chksum.h"
enum state {
/** 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 },
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);
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));
#include "pool.h"
#include "repo.h"
+#include "hash.h"
#include "tools_util.h"
#include "repo_susetags.h"
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
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);
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)
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
solvables. */
if (indesc >= 2 && !s)
{
+#if 0
pool_debug(pool, SAT_ERROR, "susetags: huh %d: %s?\n", pd.lineno, line);
+#endif
continue;
}
switch (tag)
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);
free(pd.share_with);
}
+ sat_free(joinhash);
if (!(flags & REPO_NO_INTERNALIZE))
repodata_internalize(data);
* if <attrname> given, write attributes as '<attrname>.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);
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;
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;
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;
/* 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;
if (p >= data->start)
break;
}
- if (i == s->repo->nrepodata)
+ if (i == repo->nrepodata)
data = nextdata; /* no direct hit, use next repodata */
if (data)
{
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);
}
}
void *debugcallbackdata;
/* load callback */
- FILE * (*loadcallback)(struct _Pool *, struct _Repodata *, void *);
+ int (*loadcallback)(struct _Pool *, struct _Repodata *, void *);
void *loadcallbackdata;
/* search position */
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;
void pool_clear_pos(Pool *pool);
-typedef struct _duchanges {
+typedef struct _DUChanges {
const char *path;
int kbytes;
int files;
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;
+ }
}
}
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;
#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)
#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);
static Pool *mypool; /* for pool_debug... */
-static void repodata_load_stub(Repodata *data);
-
/*******************************************************************************
* functions to extract data from a file handle
/*******************************************************************************
- * 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;
int hh;
Id *hashtbl;
Id name, evr, did;
- int flags;
+ int relflags;
Reldep *ran;
unsigned int size_idarray;
Id *idarraydatap, *idarraydataend;
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;
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 *****************************************/
* alloc buffers
*/
- if (!parent)
+ if (!(flags & REPO_LOCALPOOL))
spool = &pool->ss;
else
{
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;
{
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);
}
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 */
}
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)
{
{
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
if (parent)
{
/* overwrite stub repodata */
- repodata_free(parent);
+ repodata_freedata(parent);
*parent = data;
}
else
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);
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);
}
#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
}
case REPODATA_ERROR:
return 0;
case REPODATA_AVAILABLE:
+ case REPODATA_LOADING:
return 1;
default:
data->state = REPODATA_ERROR;
}
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;
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);
if (di->repoid >= 0)
{
di->repoid++;
+ di->repodataid = 0;
if (di->repoid < di->pool->nrepos)
{
di->repo = di->pool->repos[di->repoid];
}
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)
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);
}
/*
#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 *);
* 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);
*/
void repodata_merge_attrs(Repodata *data, Id dest, Id src);
+void repodata_create_stubs(Repodata *data);
void repodata_join(Repodata *data, Id joinkey);
/*
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 */
#include "bitmap.h"
struct _Pool;
+struct _DUChanges;
struct _TransactionOrderdata;
typedef struct _Transaction {
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);
#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;
}
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