X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=tools%2Frepo_rpmmd.c;h=44ab8eee32c979345eb61a89346682fae714d42f;hb=d4a38c4b2394d728afd0344f5b03b173123278ef;hp=57aec0957220f5e37815670400706231f429fb7c;hpb=2c6eada18db721a3cd2500dfaa360aae1688b4d3;p=platform%2Fupstream%2Flibsolv.git diff --git a/tools/repo_rpmmd.c b/tools/repo_rpmmd.c index 57aec09..44ab8ee 100644 --- a/tools/repo_rpmmd.c +++ b/tools/repo_rpmmd.c @@ -22,11 +22,9 @@ enum state { STATE_START, - STATE_METADATA, + STATE_SOLVABLE, - STATE_PRODUCT, - STATE_PATTERN, - STATE_PATCH, + STATE_NAME, STATE_ARCH, STATE_VERSION, @@ -51,7 +49,14 @@ enum state { STATE_DOWNLOADSIZE, STATE_INSTALLTIME, STATE_INSTALLONLY, - + + /* Novell/SUSE extended attributes */ + STATE_EULA, + STATE_KEYWORD, + STATE_DISKUSAGE, + STATE_DIRS, + STATE_DIR, + /* patch */ STATE_ID, STATE_TIMESTAMP, @@ -76,8 +81,6 @@ enum state { STATE_UPDATEURL, STATE_OPTIONALURL, STATE_FLAG, - STATE_FLAVOR, - STATE_REFERENCES, /* rpm-md dependencies inside the format tag */ @@ -105,12 +108,6 @@ enum state { STATE_FILE, - STATE_DISKUSAGE, - STATE_TRANSLATIONS, - STATE_DUINFO, - STATE_DIRS, - STATE_DIR, - // general NUMSTATES }; @@ -123,14 +120,20 @@ struct stateswitch { }; static struct stateswitch stateswitches[] = { + /** fake tag used to enclose 2 different xml files in one **/ + { STATE_START, "rpmmd", STATE_START, 0 }, + + /** tags for different package data, we just ignore the tag **/ + { STATE_START, "metadata", STATE_START, 0 }, + { STATE_START, "otherdata", STATE_START, 0 }, + { STATE_START, "diskusagedata", STATE_START, 0 }, + { STATE_START, "susedata", STATE_START, 0 }, { STATE_START, "product", STATE_SOLVABLE, 0 }, { STATE_START, "pattern", STATE_SOLVABLE, 0 }, { STATE_START, "patch", STATE_SOLVABLE, 0 }, { STATE_START, "package", STATE_SOLVABLE, 0 }, - { STATE_START, "diskusage", STATE_DISKUSAGE, 0 }, - { STATE_START, "translations", STATE_TRANSLATIONS, 0 }, - + { STATE_SOLVABLE, "name", STATE_NAME, 1 }, { STATE_SOLVABLE, "arch", STATE_ARCH, 1 }, { STATE_SOLVABLE, "version", STATE_VERSION, 0 }, @@ -138,7 +141,7 @@ static struct stateswitch stateswitches[] = { // package attributes rpm-md { STATE_SOLVABLE, "location", STATE_LOCATION, 0 }, { STATE_SOLVABLE, "checksum", STATE_CHECKSUM, 1 }, - + /* resobject attributes */ { STATE_SOLVABLE, "summary", STATE_SUMMARY, 1 }, @@ -155,6 +158,11 @@ static struct stateswitch stateswitches[] = { { STATE_SOLVABLE, "install-only", STATE_INSTALLONLY, 1 }, { STATE_SOLVABLE, "time", STATE_TIME, 0 }, + /* extended Novell/SUSE attributes (susedata.xml) */ + { STATE_SOLVABLE, "eula", STATE_EULA, 1 }, + { STATE_SOLVABLE, "keyword", STATE_KEYWORD, 1 }, + { STATE_SOLVABLE, "diskusage", STATE_DISKUSAGE, 0 }, + // pattern attribute { STATE_SOLVABLE, "script", STATE_SCRIPT, 1 }, { STATE_SOLVABLE, "icon", STATE_ICON, 1 }, @@ -169,14 +177,12 @@ static struct stateswitch stateswitches[] = { { STATE_SOLVABLE, "update-url", STATE_UPDATEURL, 1 }, { STATE_SOLVABLE, "optional-url", STATE_OPTIONALURL, 1 }, { STATE_SOLVABLE, "flag", STATE_FLAG, 1 }, - { STATE_SOLVABLE, "flavor", STATE_FLAVOR, 1 }, - { STATE_SOLVABLE, "references", STATE_REFERENCES, 1 }, { STATE_SOLVABLE, "rpm:vendor", STATE_VENDOR, 1 }, { STATE_SOLVABLE, "rpm:group", STATE_RPM_GROUP, 1 }, { STATE_SOLVABLE, "rpm:license", STATE_RPM_LICENSE, 1 }, - /* rpm-md dependencies */ + /* rpm-md dependencies */ { STATE_SOLVABLE, "rpm:provides", STATE_PROVIDES, 0 }, { STATE_SOLVABLE, "rpm:requires", STATE_REQUIRES, 0 }, { STATE_SOLVABLE, "rpm:obsoletes", STATE_OBSOLETES, 0 }, @@ -189,7 +195,11 @@ static struct stateswitch stateswitches[] = { { STATE_SOLVABLE, "rpm:sourcerpm", STATE_SOURCERPM, 1 }, { STATE_SOLVABLE, "rpm:header-range", STATE_HEADERRANGE, 0 }, { STATE_SOLVABLE, "file", STATE_FILE, 1 }, - + + /* extended Novell/SUSE diskusage attributes (susedata.xml) */ + { STATE_DISKUSAGE, "dirs", STATE_DIRS, 0 }, + { STATE_DIRS, "dir", STATE_DIR, 0 }, + { STATE_PROVIDES, "rpm:entry", STATE_PROVIDESENTRY, 0 }, { STATE_REQUIRES, "rpm:entry", STATE_REQUIRESENTRY, 0 }, { STATE_OBSOLETES, "rpm:entry", STATE_OBSOLETESENTRY, 0 }, @@ -200,14 +210,13 @@ static struct stateswitch stateswitches[] = { { STATE_ENHANCES, "rpm:entry", STATE_ENHANCESENTRY, 0 }, { STATE_FRESHENS, "rpm:entry", STATE_FRESHENSENTRY, 0 }, - /* diskusage.xml */ - { STATE_DISKUSAGE, "duinfo", STATE_DUINFO, 0 }, - { STATE_DUINFO, "dirs", STATE_DIRS, 0 }, - { STATE_DIRS, "dir", STATE_DIR, 0 }, - { NUMSTATES} }; +/* maxmum initial size of + the checksum cache */ +#define MAX_CSCACHE 32768 +#define CSREALLOC_STEP 1024 struct parsedata { struct parsedata_common common; @@ -223,7 +232,8 @@ struct parsedata { Offset freshens; struct stateswitch *swtab[NUMSTATES]; enum state sbtab[NUMSTATES]; - const char *lang; + /* temporal to store attribute tag language */ + const char *tmplang; const char *capkind; // used to store tmp attributes // while the tag ends @@ -234,13 +244,102 @@ struct parsedata { Id (*dirs)[3]; // dirid, size, nfiles int ndirs; Id langcache[ID_NUM_INTERNAL]; + /** system language */ + const char *language; + + /** Hash to maps checksums to solv */ + Stringpool cspool; + /** Cache of known checksums to solvable id */ + Id *cscache; + /* the current longest index in the table */ + int ncscache; }; +static Id +langtag(struct parsedata *pd, Id tag, const char *language) +{ + if (language && !language[0]) + language = 0; + if (!language || tag >= ID_NUM_INTERNAL) + return pool_id2langid(pd->common.repo->pool, tag, language, 1); + return pool_id2langid(pd->common.repo->pool, tag, language, 1); + if (!pd->langcache[tag]) + pd->langcache[tag] = pool_id2langid(pd->common.repo->pool, tag, language, 1); + return pd->langcache[tag]; +} + +static int +id3_cmp (const void *v1, const void *v2) +{ + Id *i1 = (Id*)v1; + Id *i2 = (Id*)v2; + return i1[0] - i2[0]; +} + +static void +commit_diskusage (struct parsedata *pd, unsigned handle) +{ + unsigned i; + Dirpool *dp = &pd->data->dirpool; + /* Now sort in dirid order. This ensures that parents come before + their children. */ + if (pd->ndirs > 1) + qsort(pd->dirs, pd->ndirs, sizeof (pd->dirs[0]), id3_cmp); + /* Substract leaf numbers from all parents to make the numbers + non-cumulative. This must be done post-order (i.e. all leafs + adjusted before parents). We ensure this by starting at the end of + the array moving to the start, hence seeing leafs before parents. */ + for (i = pd->ndirs; i--;) + { + unsigned p = dirpool_parent(dp, pd->dirs[i][0]); + unsigned j = i; + for (; p; p = dirpool_parent(dp, p)) + { + for (; j--;) + if (pd->dirs[j][0] == p) + break; + if (j < pd->ndirs) + { + if (pd->dirs[j][1] < pd->dirs[i][1]) + pd->dirs[j][1] = 0; + else + pd->dirs[j][1] -= pd->dirs[i][1]; + if (pd->dirs[j][2] < pd->dirs[i][2]) + pd->dirs[j][2] = 0; + else + pd->dirs[j][2] -= pd->dirs[i][2]; + } + else + /* Haven't found this parent in the list, look further if + we maybe find the parents parent. */ + j = i; + } + } +#if 0 + char sbuf[1024]; + char *buf = sbuf; + unsigned slen = sizeof (sbuf); + for (i = 0; i < pd->ndirs; i++) + { + dir2str (attr, pd->dirs[i][0], &buf, &slen); + fprintf (stderr, "have dir %d %d %d %s\n", pd->dirs[i][0], pd->dirs[i][1], pd->dirs[i][2], buf); + } + if (buf != sbuf) + free (buf); +#endif + for (i = 0; i < pd->ndirs; i++) + if (pd->dirs[i][1] || pd->dirs[i][2]) + { + repodata_add_dirnumnum(pd->data, handle, SOLVABLE_DISKUSAGE, pd->dirs[i][0], pd->dirs[i][1], pd->dirs[i][2]); + } + pd->ndirs = 0; +} + /* * makeevr_atts * parse 'epoch', 'ver' and 'rel', return evr Id - * + * */ static Id @@ -315,7 +414,7 @@ makeevr_atts(Pool *pool, struct parsedata *pd, const char **atts) * I: txt, name of attribute * I: atts, list of key/value attributes * O: pointer to value of matching key, or NULL - * + * */ static inline const char * @@ -347,7 +446,7 @@ static char *flagtab[] = { /* * adddep * parse attributes to reldep Id - * + * */ static unsigned int @@ -382,8 +481,8 @@ adddep(Pool *pool, struct parsedata *pd, unsigned int olddeps, const char **atts pd->content = sat_realloc(pd->content, l + 256); pd->acontent = l + 256; } - sprintf(pd->content, "%s:%s", k, n); - name = str2id(pool, pd->content, 1); + sprintf(pd->content, "%s:%s", k, n); + name = str2id(pool, pd->content, 1); } else name = str2id(pool, (char *)n, 1); @@ -419,27 +518,27 @@ set_desciption_author(Repodata *data, Id handle, char *str) if (!str || !*str) return; for (aut = str; (aut = strchr(aut, '\n')) != 0; aut++) - if (!strncmp(aut, "\nAuthors:\n--------\n", 19)) + if (!strncmp(aut, "\nAuthors:\n--------\n", 19)) break; if (aut) { /* oh my, found SUSE special author section */ - int l = aut - str; - str[l] = 0; + int l = aut - str; + str[l] = 0; while (l > 0 && str[l - 1] == '\n') - str[--l] = 0; + str[--l] = 0; if (l) repodata_set_str(data, handle, SOLVABLE_DESCRIPTION, str); p = aut + 19; aut = str; /* copy over */ while (*p == ' ' || *p == '\n') p++; - while (*p) + while (*p) { if (*p == '\n') { *aut++ = *p++; - while (*p == ' ') + while (*p == ' ') p++; continue; } @@ -447,7 +546,7 @@ set_desciption_author(Repodata *data, Id handle, char *str) } while (aut != str && aut[-1] == '\n') aut--; - *aut = 0; + *aut = 0; if (*str) repodata_set_str(data, handle, SOLVABLE_AUTHORS, str); } @@ -458,7 +557,7 @@ set_desciption_author(Repodata *data, Id handle, char *str) /* * set_sourcerpm - * + * */ static void @@ -512,7 +611,7 @@ set_sourcerpm(Repodata *data, Solvable *s, Id handle, char *sourcerpm) /* * startElement * XML callback - * + * */ static void XMLCALL @@ -536,12 +635,14 @@ startElement(void *userData, const char *name, const char **atts) if (pd->state == STATE_START && !strcmp(name, "patterns")) return; - if (pd->state == STATE_START && !strcmp(name, "metadata")) - return; + //if (pd->state == STATE_START && !strcmp(name, "metadata")) + // return; if (pd->state == STATE_SOLVABLE && !strcmp(name, "format")) return; pd->depth++; + if (!pd->swtab[pd->state]) + return; for (sw = pd->swtab[pd->state]; sw->from == pd->state; sw++) if (!strcmp(sw->ename, name)) break; @@ -567,16 +668,46 @@ startElement(void *userData, const char *name, const char **atts) pd->kind = "product"; else if (name[2] == 't' && name[3] == 'c') pd->kind = "patch"; - - /* this is a new package */ - /*fprintf(stderr, "new package\n");*/ - pd->solvable = pool_id2solvable(pool, repo_add_solvable(pd->common.repo)); - pd->freshens = 0; - repodata_extend(pd->data, pd->solvable - pool->solvables); - pd->handle = repodata_get_handle(pd->data, (pd->solvable - pool->solvables) - pd->data->start); + + /* to support extension metadata files like others.xml which + have the following structure: + + + + ... + + we need to check if the pkgid is there and if it matches + an already seen package, that means we don't need to create + a new solvable but just append the attributes to the existing + one. + */ + const char *pkgid; + if ((pkgid = find_attr("pkgid", atts)) != NULL) + { + // look at the checksum cache + Id index = stringpool_str2id(&pd->cspool, pkgid, 0); + if (!index || index >= pd->ncscache || !pd->cscache[index]) + { + fprintf(stderr, "error, the repository specifies extra information about package with checksum '%s', which does not exist in the repository.\n", pkgid); + exit(1); + } + pd->solvable = pool_id2solvable(pool, pd->cscache[index]); + } + else + { + /* this is a new package */ + pd->solvable = pool_id2solvable(pool, repo_add_solvable(pd->common.repo)); + pd->freshens = 0; + } + pd->handle = pd->solvable - pool->solvables; #if 0 fprintf(stderr, "package #%d\n", pd->solvable - pool->solvables); #endif + break; case STATE_VERSION: s->evr = makeevr_atts(pool, pd, atts); @@ -637,24 +768,12 @@ startElement(void *userData, const char *name, const char **atts) break; case STATE_SUMMARY: case STATE_DESCRIPTION: - pd->lang = find_attr("lang", atts); + pd->tmplang = find_attr("lang", atts); break; case STATE_LOCATION: str = find_attr("href", atts); if (str) - { - const char *str2 = strrchr(str, '/'); - if (str2) - { - char *str3 = strdup(str); - str3[str2 - str] = 0; - repodata_set_poolstr(pd->data, handle, SOLVABLE_MEDIADIR, str3); - free(str3); - repodata_set_str(pd->data, handle, SOLVABLE_MEDIAFILE, str2 + 1); - } - else - repodata_set_str(pd->data, handle, SOLVABLE_MEDIAFILE, str); - } + repodata_set_location(pd->data, handle, 0, 0, str); break; case STATE_CHECKSUM: pd->tmpattr = find_attr("type", atts); @@ -689,12 +808,50 @@ startElement(void *userData, const char *name, const char **atts) if (str && (end = atoi(str)) != 0) repodata_set_num(pd->data, handle, SOLVABLE_HEADEREND, end); } + /* + + + + + + + + + + */ case STATE_DISKUSAGE: - case STATE_TRANSLATIONS: - case STATE_DUINFO: - case STATE_DIRS: + { + /* Really, do nothing, wat for tag */ + break; + } case STATE_DIR: - + { + long filesz = 0, filenum = 0; + unsigned dirid; + if ( (str = find_attr("name", atts)) ) + { + dirid = repodata_str2dir(pd->data, str, 1); + } + else + { + fprintf( stderr, " tag without 'name' attribute, atts = %p, *atts = %p\n", atts, *atts); + break; + } + if ( (str = find_attr("size", atts)) ) + { + filesz = strtol (str, 0, 0); + } + if ( (str = find_attr("count", atts)) ) + { + filenum = strtol (str, 0, 0); + } + pd->dirs = sat_extend(pd->dirs, pd->ndirs, 1, sizeof(pd->dirs[0]), 31); + pd->dirs[pd->ndirs][0] = dirid; + pd->dirs[pd->ndirs][1] = filesz; + pd->dirs[pd->ndirs][2] = filenum; + pd->ndirs++; + break; + } default: break; } @@ -704,7 +861,7 @@ startElement(void *userData, const char *name, const char **atts) /* * endElement * XML callback - * + * */ static void XMLCALL @@ -729,8 +886,8 @@ endElement(void *userData, const char *name) /* ignore patterns & metadata */ if (pd->state == STATE_START && !strcmp(name, "patterns")) return; - if (pd->state == STATE_START && !strcmp(name, "metadata")) - return; + //if (pd->state == STATE_START && !strcmp(name, "metadata")) + // return; if (pd->state == STATE_SOLVABLE && !strcmp(name, "format")) return; @@ -738,8 +895,6 @@ endElement(void *userData, const char *name) pd->statedepth--; switch (pd->state) { - case STATE_PATTERN: - case STATE_PRODUCT: case STATE_SOLVABLE: if (!s->arch) s->arch = ARCH_NOARCH; @@ -747,7 +902,8 @@ endElement(void *userData, const char *name) s->evr = ID_EMPTY; /* some patterns have this */ if (s->arch != ARCH_SRC && s->arch != ARCH_NOSRC) s->provides = repo_addid_dep(repo, s->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0); - s->supplements = repo_fix_legacy(repo, s->provides, s->supplements, pd->freshens); + s->supplements = repo_fix_supplements(repo, s->provides, s->supplements, pd->freshens); + s->conflicts = repo_fix_conflicts(repo, s->conflicts); pd->freshens = 0; pd->kind = 0; break; @@ -770,9 +926,9 @@ endElement(void *userData, const char *name) repodata_set_poolstr(pd->data, handle, SOLVABLE_LICENSE, pd->content); break; case STATE_CHECKSUM: - { + { int l; - Id type; + Id type, index; if (!strcasecmp (pd->tmpattr, "sha") || !strcasecmp (pd->tmpattr, "sha1")) l = SIZEOF_SHA1 * 2, type = REPOKEY_TYPE_SHA1; else if (!strcasecmp (pd->tmpattr, "md5")) @@ -788,8 +944,18 @@ endElement(void *userData, const char *name) exit(1); } repodata_set_checksum(pd->data, handle, SOLVABLE_CHECKSUM, type, pd->content); + /* we save the checksum to solvable id relationship for extended + metadata */ + index = stringpool_str2id(&pd->cspool, pd->content, 1 /* create it */); + if (index >= pd->ncscache) + { + pd->cscache = sat_zextend(pd->cscache, pd->ncscache, index + 1 - pd->ncscache, sizeof(Id), 255); + pd->ncscache = index + 1; + } + /* add the checksum to the cache */ + pd->cscache[index] = s - pool->solvables; + break; } - break; case STATE_FILE: #if 0 id = str2id(pool, pd->content, 1); @@ -810,11 +976,11 @@ endElement(void *userData, const char *name) repodata_add_dirstr(pd->data, handle, SOLVABLE_FILELIST, id, p); break; case STATE_SUMMARY: - pd->lang = 0; + pd->tmplang = 0; repodata_set_str(pd->data, handle, SOLVABLE_SUMMARY, pd->content); break; case STATE_DESCRIPTION: - pd->lang = 0; + pd->tmplang = 0; set_desciption_author(pd->data, handle, pd->content); break; case STATE_DISTRIBUTION: @@ -833,27 +999,40 @@ endElement(void *userData, const char *name) break; case STATE_RELNOTESURL: if (pd->content[0]) - repodata_set_poolstr(pd->data, handle, PRODUCT_RELNOTESURL, pd->content); + { + repodata_add_poolstr_array(pd->data, pd->handle, PRODUCT_URL, pd->content); + repodata_add_idarray(pd->data, pd->handle, PRODUCT_URL_TYPE, str2id(pool, "releasenotes", 1)); + } break; case STATE_UPDATEURL: if (pd->content[0]) - repodata_set_poolstr(pd->data, handle, PRODUCT_EXTRAURLS, pd->content); + { + repodata_add_poolstr_array(pd->data, pd->handle, PRODUCT_URL, pd->content); + repodata_add_idarray(pd->data, pd->handle, PRODUCT_URL_TYPE, str2id(pool, "update", 1)); + } break; case STATE_OPTIONALURL: if (pd->content[0]) - repodata_set_poolstr(pd->data, handle, PRODUCT_OPTIONALURLS, pd->content); + { + repodata_add_poolstr_array(pd->data, pd->handle, PRODUCT_URL, pd->content); + repodata_add_idarray(pd->data, pd->handle, PRODUCT_URL_TYPE, str2id(pool, "optional", 1)); + } break; case STATE_FLAG: if (pd->content[0]) repodata_set_poolstr(pd->data, handle, PRODUCT_FLAGS, pd->content); break; - case STATE_FLAVOR: + case STATE_EULA: if (pd->content[0]) - repodata_set_str(pd->data, handle, PRODUCT_FLAVOR, pd->content); + repodata_set_str(pd->data, handle, langtag(pd, SOLVABLE_EULA, pd->language), pd->content); break; - case STATE_REFERENCES: + case STATE_KEYWORD: if (pd->content[0]) - repodata_set_str(pd->data, handle, PRODUCT_REFERENCES, pd->content); + repodata_add_poolstr_array(pd->data, pd->handle, SOLVABLE_KEYWORDS, pd->content); + break; + case STATE_DISKUSAGE: + if (pd->ndirs) + commit_diskusage (pd, pd->handle); break; default: break; @@ -867,7 +1046,7 @@ endElement(void *userData, const char *name) /* * characterData * XML callback - * + * */ static void XMLCALL @@ -900,18 +1079,26 @@ characterData(void *userData, const XML_Char *s, int len) /* * repo_add_rpmmd - * parse rpm-md metadata (primary, others, diskusage, translations) - * + * parse rpm-md metadata (primary, others) + * */ void -repo_add_rpmmd(Repo *repo, FILE *fp, int flags) +repo_add_rpmmd(Repo *repo, FILE *fp, const char *language, int flags) { Pool *pool = repo->pool; struct parsedata pd; char buf[BUFF_SIZE]; int i, l; struct stateswitch *sw; + Repodata *data; + unsigned int now; + + now = sat_timems(0); + if (!(flags & REPO_REUSE_REPODATA)) + data = repo_add_repodata(repo, 0); + else + data = repo_last_repodata(repo); memset(&pd, 0, sizeof(pd)); for (i = 0, sw = stateswitches; sw->from != NUMSTATES; i++, sw++) @@ -923,7 +1110,7 @@ repo_add_rpmmd(Repo *repo, FILE *fp, int flags) pd.common.pool = pool; pd.common.repo = repo; - pd.data = repo_add_repodata(repo, 0); + pd.data = data; pd.content = sat_malloc(256); pd.acontent = 256; @@ -931,6 +1118,13 @@ repo_add_rpmmd(Repo *repo, FILE *fp, int flags) pd.common.tmp = 0; pd.common.tmpl = 0; pd.kind = 0; + pd.language = language; + + /* initialize the string pool where we will store + the package checksums we know about, to get an Id + we can use in a cache */ + stringpool_init_empty(&pd.cspool); + XML_Parser parser = XML_ParserCreate(NULL); XML_SetUserData(parser, &pd); pd.parser = &parser; @@ -948,9 +1142,13 @@ repo_add_rpmmd(Repo *repo, FILE *fp, int flags) break; } XML_ParserFree(parser); - - if (pd.data) - repodata_internalize(pd.data); sat_free(pd.content); 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)); + POOL_DEBUG(SAT_DEBUG_STATS, "repo size: %d solvables\n", repo->nsolvables); + POOL_DEBUG(SAT_DEBUG_STATS, "repo memory used: %ld K incore, %ld K idarray\n", (unsigned long)data->incoredatalen/1024, (unsigned long)repo->idarraysize / (1024/sizeof(Id))); }