#define TYPE_RPMMD 2
#define TYPE_PLAINDIR 3
+static int
+read_repoinfos_sort(const void *ap, const void *bp)
+{
+ const struct repoinfo *a = ap;
+ const struct repoinfo *b = bp;
+ return strcmp(a->alias, b->alias);
+}
+
struct repoinfo *
read_repoinfos(Pool *pool, const char *reposdir, int *nrepoinfosp)
{
cinfo = 0;
}
closedir(dir);
+ qsort(repoinfos, nrepoinfos, sizeof(*repoinfos), read_repoinfos_sort);
*nrepoinfosp = nrepoinfos;
return repoinfos;
}
FILE **newpkgsfps;
struct fcstate fcstate;
- if (!strcmp(argv[1], "install") || !strcmp(argv[1], "in"))
+ argc--;
+ argv++;
+ if (!strcmp(argv[0], "install") || !strcmp(argv[0], "in"))
mode = SOLVER_INSTALL;
- else if (!strcmp(argv[1], "erase") || !strcmp(argv[1], "rm"))
+ else if (!strcmp(argv[0], "erase") || !strcmp(argv[0], "rm"))
mode = SOLVER_ERASE;
- else if (!strcmp(argv[1], "show"))
+ else if (!strcmp(argv[0], "show"))
mode = 0;
- else if (!strcmp(argv[1], "update") || !strcmp(argv[1], "up"))
+ else if (!strcmp(argv[0], "update") || !strcmp(argv[0], "up"))
mode = SOLVER_UPDATE;
else
{
pool_createwhatprovides(pool);
queue_init(&job);
- for (i = 2; i < argc; i++)
+ for (i = 1; i < argc; i++)
mkselect(pool, argv[i], 0, &job);
if (!job.count && mode == SOLVER_UPDATE)
updateall = 1;
#define TAG_ENHANCESVERSION 1160
#define TAG_ENHANCESFLAGS 1161
+#define SIGTAG_SIZE 1000
+#define SIGTAG_PGP 1002 /* RSA signature */
+#define SIGTAG_MD5 1004 /* header+payload md5 checksum */
+#define SIGTAG_GPG 1005 /* DSA signature */
+
#define DEP_LESS (1 << 1)
#define DEP_GREATER (1 << 2)
#define DEP_EQUAL (1 << 3)
unsigned char data[1];
} RpmHead;
-static int
-headexists(RpmHead *h, int tag)
+
+static inline unsigned char *
+headfindtag(RpmHead *h, int tag)
{
unsigned int i;
unsigned char *d, taga[4];
-
d = h->dp - 16;
taga[0] = tag >> 24;
taga[1] = tag >> 16;
taga[3] = tag;
for (i = 0; i < h->cnt; i++, d -= 16)
if (d[3] == taga[3] && d[2] == taga[2] && d[1] == taga[1] && d[0] == taga[0])
- return 1;
+ return d;
return 0;
}
+static int
+headexists(RpmHead *h, int tag)
+{
+ return headfindtag(h, tag) ? 1 : 0;
+}
+
static unsigned int *
headint32array(RpmHead *h, int tag, int *cnt)
{
unsigned int i, o, *r;
- unsigned char *d, taga[4];
+ unsigned char *d = headfindtag(h, tag);
- d = h->dp - 16;
- taga[0] = tag >> 24;
- taga[1] = tag >> 16;
- taga[2] = tag >> 8;
- taga[3] = tag;
- for (i = 0; i < h->cnt; i++, d -= 16)
- if (d[3] == taga[3] && d[2] == taga[2] && d[1] == taga[1] && d[0] == taga[0])
- break;
- if (i >= h->cnt)
- return 0;
- if (d[4] != 0 || d[5] != 0 || d[6] != 0 || d[7] != 4)
+ if (!d || d[4] != 0 || d[5] != 0 || d[6] != 0 || d[7] != 4)
return 0;
o = d[8] << 24 | d[9] << 16 | d[10] << 8 | d[11];
i = d[12] << 24 | d[13] << 16 | d[14] << 8 | d[15];
return r;
}
+/* returns the first entry of an integer array */
static unsigned int
headint32(RpmHead *h, int tag)
{
unsigned int i, o;
- unsigned char *d, taga[4];
+ unsigned char *d = headfindtag(h, tag);
- d = h->dp - 16;
- taga[0] = tag >> 24;
- taga[1] = tag >> 16;
- taga[2] = tag >> 8;
- taga[3] = tag;
- for (i = 0; i < h->cnt; i++, d -= 16)
- if (d[3] == taga[3] && d[2] == taga[2] && d[1] == taga[1] && d[0] == taga[0])
- break;
- if (i >= h->cnt)
- return 0;
- if (d[4] != 0 || d[5] != 0 || d[6] != 0 || d[7] != 4)
+ if (!d || d[4] != 0 || d[5] != 0 || d[6] != 0 || d[7] != 4)
return 0;
o = d[8] << 24 | d[9] << 16 | d[10] << 8 | d[11];
i = d[12] << 24 | d[13] << 16 | d[14] << 8 | d[15];
headint16array(RpmHead *h, int tag, int *cnt)
{
unsigned int i, o, *r;
- unsigned char *d, taga[4];
+ unsigned char *d = headfindtag(h, tag);
- d = h->dp - 16;
- taga[0] = tag >> 24;
- taga[1] = tag >> 16;
- taga[2] = tag >> 8;
- taga[3] = tag;
- for (i = 0; i < h->cnt; i++, d -= 16)
- if (d[3] == taga[3] && d[2] == taga[2] && d[1] == taga[1] && d[0] == taga[0])
- break;
- if (i >= h->cnt)
- return 0;
- if (d[4] != 0 || d[5] != 0 || d[6] != 0 || d[7] != 3)
+ if (!d || d[4] != 0 || d[5] != 0 || d[6] != 0 || d[7] != 3)
return 0;
o = d[8] << 24 | d[9] << 16 | d[10] << 8 | d[11];
i = d[12] << 24 | d[13] << 16 | d[14] << 8 | d[15];
static char *
headstring(RpmHead *h, int tag)
{
- unsigned int i, o;
- unsigned char *d, taga[4];
- d = h->dp - 16;
- taga[0] = tag >> 24;
- taga[1] = tag >> 16;
- taga[2] = tag >> 8;
- taga[3] = tag;
- for (i = 0; i < h->cnt; i++, d -= 16)
- if (d[3] == taga[3] && d[2] == taga[2] && d[1] == taga[1] && d[0] == taga[0])
- break;
- if (i >= h->cnt)
- return 0;
+ unsigned int o;
+ unsigned char *d = headfindtag(h, tag);
/* 6: STRING, 9: I18NSTRING */
- if (d[4] != 0 || d[5] != 0 || d[6] != 0 || (d[7] != 6 && d[7] != 9))
+ if (!d || d[4] != 0 || d[5] != 0 || d[6] != 0 || (d[7] != 6 && d[7] != 9))
return 0;
o = d[8] << 24 | d[9] << 16 | d[10] << 8 | d[11];
+ if (o >= h->dcnt)
+ return 0;
return (char *)h->dp + o;
}
headstringarray(RpmHead *h, int tag, int *cnt)
{
unsigned int i, o;
- unsigned char *d, taga[4];
+ unsigned char *d = headfindtag(h, tag);
char **r;
- d = h->dp - 16;
- taga[0] = tag >> 24;
- taga[1] = tag >> 16;
- taga[2] = tag >> 8;
- taga[3] = tag;
- for (i = 0; i < h->cnt; i++, d -= 16)
- if (d[3] == taga[3] && d[2] == taga[2] && d[1] == taga[1] && d[0] == taga[0])
- break;
- if (i >= h->cnt)
- return 0;
- if (d[4] != 0 || d[5] != 0 || d[6] != 0 || d[7] != 8)
+ if (!d || d[4] != 0 || d[5] != 0 || d[6] != 0 || d[7] != 8)
return 0;
o = d[8] << 24 | d[9] << 16 | d[10] << 8 | d[11];
i = d[12] << 24 | d[13] << 16 | d[14] << 8 | d[15];
return r;
}
+static unsigned char *
+headbinary(RpmHead *h, int tag, unsigned int *sizep)
+{
+ unsigned int i, o;
+ unsigned char *d = headfindtag(h, tag);
+ if (!d || d[4] != 0 || d[5] != 0 || d[6] != 0 || d[7] != 7)
+ return 0;
+ o = d[8] << 24 | d[9] << 16 | d[10] << 8 | d[11];
+ i = d[12] << 24 | d[13] << 16 | d[14] << 8 | d[15];
+ if (o > h->dcnt || o + i < o || o + i > h->dcnt)
+ return 0;
+ if (sizep)
+ *sizep = i;
+ return h->dp + o;
+}
+
static char *headtoevr(RpmHead *h)
{
unsigned int epoch;
sat_free(buf);
}
+
+#define MAKEDEPS_FILTER_WEAK (1 << 0)
+#define MAKEDEPS_FILTER_STRONG (1 << 1)
+#define MAKEDEPS_NO_RPMLIB (1 << 2)
+
+/*
+ * strong: 0: ignore strongness
+ * 1: filter to strong
+ * 2: filter to weak
+ */
static unsigned int
-makedeps(Pool *pool, Repo *repo, RpmHead *rpmhead, int tagn, int tagv, int tagf, int strong)
+makedeps(Pool *pool, Repo *repo, RpmHead *rpmhead, int tagn, int tagv, int tagf, int flags)
{
char **n, **v;
unsigned int *f;
int i, cc, nc, vc, fc;
- int haspre = 0;
+ int haspre;
unsigned int olddeps;
Id *ida;
+ int strong;
+ strong = flags & (MAKEDEPS_FILTER_STRONG|MAKEDEPS_FILTER_WEAK);
n = headstringarray(rpmhead, tagn, &nc);
if (!n)
return 0;
}
cc = nc;
- if (strong)
+ haspre = 0; /* add no prereq marker */
+ if (flags)
{
+ /* we do filtering */
cc = 0;
for (i = 0; i < nc; i++)
- if ((f[i] & DEP_STRONG) == (strong == 1 ? 0 : DEP_STRONG))
- {
- cc++;
- if ((f[i] & DEP_PRE) != 0)
- haspre = 1;
- }
+ {
+ if (strong && (f[i] & DEP_STRONG) != (strong == MAKEDEPS_FILTER_WEAK ? 0 : DEP_STRONG))
+ continue;
+ if ((flags & MAKEDEPS_NO_RPMLIB) != 0)
+ if (!strncmp(n[i], "rpmlib(", 7))
+ continue;
+ if ((f[i] & DEP_PRE) != 0)
+ haspre = 1;
+ cc++;
+ }
}
- else
+ else if (tagn == TAG_REQUIRENAME)
{
+ /* no filtering, just look for the first prereq */
for (i = 0; i < nc; i++)
if ((f[i] & DEP_PRE) != 0)
{
break;
}
}
- if (tagn != TAG_REQUIRENAME)
- haspre = 0;
if (cc == 0)
{
sat_free(n);
{
if (haspre != 1)
break;
- haspre = 2;
+ haspre = 2; /* pass two: prereqs */
i = 0;
*ida++ = SOLVABLE_PREREQMARKER;
}
- if (strong && (f[i] & DEP_STRONG) != (strong == 1 ? 0 : DEP_STRONG))
+ if (strong && (f[i] & DEP_STRONG) != (strong == MAKEDEPS_FILTER_WEAK ? 0 : DEP_STRONG))
continue;
if (haspre == 1 && (f[i] & DEP_PRE) != 0)
continue;
if (haspre == 2 && (f[i] & DEP_PRE) == 0)
continue;
+ if ((flags & MAKEDEPS_NO_RPMLIB) != 0)
+ if (!strncmp(n[i], "rpmlib(", 7))
+ continue;
if (f[i] & (DEP_LESS|DEP_GREATER|DEP_EQUAL))
{
Id name, evr;
}
static int
-rpm2solv(Pool *pool, Repo *repo, Repodata *data, Solvable *s, RpmHead *rpmhead)
+rpm2solv(Pool *pool, Repo *repo, Repodata *data, Solvable *s, RpmHead *rpmhead, int flags)
{
char *name;
char *evr;
s->vendor = str2id(pool, headstring(rpmhead, TAG_VENDOR), 1);
s->provides = makedeps(pool, repo, rpmhead, TAG_PROVIDENAME, TAG_PROVIDEVERSION, TAG_PROVIDEFLAGS, 0);
- s->provides = addfileprovides(pool, repo, data, s, rpmhead, s->provides);
+ if ((flags & RPM_ADD_NO_FILELIST) == 0)
+ s->provides = addfileprovides(pool, repo, data, s, rpmhead, s->provides);
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->requires = makedeps(pool, repo, rpmhead, TAG_REQUIRENAME, TAG_REQUIREVERSION, TAG_REQUIREFLAGS, 0);
+ s->requires = makedeps(pool, repo, rpmhead, TAG_REQUIRENAME, TAG_REQUIREVERSION, TAG_REQUIREFLAGS, (flags & RPM_ADD_NO_RPMLIBREQS) ? MAKEDEPS_NO_RPMLIB : 0);
s->conflicts = makedeps(pool, repo, rpmhead, TAG_CONFLICTNAME, TAG_CONFLICTVERSION, TAG_CONFLICTFLAGS, 0);
s->obsoletes = makedeps(pool, repo, rpmhead, TAG_OBSOLETENAME, TAG_OBSOLETEVERSION, TAG_OBSOLETEFLAGS, 0);
- s->recommends = makedeps(pool, repo, rpmhead, TAG_SUGGESTSNAME, TAG_SUGGESTSVERSION, TAG_SUGGESTSFLAGS, 2);
- s->suggests = makedeps(pool, repo, rpmhead, TAG_SUGGESTSNAME, TAG_SUGGESTSVERSION, TAG_SUGGESTSFLAGS, 1);
- s->supplements = makedeps(pool, repo, rpmhead, TAG_ENHANCESNAME, TAG_ENHANCESVERSION, TAG_ENHANCESFLAGS, 2);
- s->enhances = makedeps(pool, repo, rpmhead, TAG_ENHANCESNAME, TAG_ENHANCESVERSION, TAG_ENHANCESFLAGS, 1);
+ s->recommends = makedeps(pool, repo, rpmhead, TAG_SUGGESTSNAME, TAG_SUGGESTSVERSION, TAG_SUGGESTSFLAGS, MAKEDEPS_FILTER_STRONG);
+ s->suggests = makedeps(pool, repo, rpmhead, TAG_SUGGESTSNAME, TAG_SUGGESTSVERSION, TAG_SUGGESTSFLAGS, MAKEDEPS_FILTER_WEAK);
+ s->supplements = makedeps(pool, repo, rpmhead, TAG_ENHANCESNAME, TAG_ENHANCESVERSION, TAG_ENHANCESFLAGS, MAKEDEPS_FILTER_STRONG);
+ s->enhances = makedeps(pool, repo, rpmhead, TAG_ENHANCESNAME, TAG_ENHANCESVERSION, TAG_ENHANCESFLAGS, MAKEDEPS_FILTER_WEAK);
s->supplements = repo_fix_supplements(repo, s->provides, s->supplements, 0);
s->conflicts = repo_fix_conflicts(repo, s->conflicts);
memcpy(rpmhead->data, (unsigned char *)dbdata.data + 8, rpmhead->cnt * 16 + rpmhead->dcnt);
rpmhead->dp = rpmhead->data + rpmhead->cnt * 16;
repo->rpmdbid[(s - pool->solvables) - repo->start] = dbid;
- if (rpm2solv(pool, repo, data, s, rpmhead))
+ if (rpm2solv(pool, repo, data, s, rpmhead, flags))
{
i++;
s = 0;
memcpy(rpmhead->data, (unsigned char *)dbdata.data + 8, rpmhead->cnt * 16 + rpmhead->dcnt);
rpmhead->dp = rpmhead->data + rpmhead->cnt * 16;
- rpm2solv(pool, repo, data, s, rpmhead);
+ rpm2solv(pool, repo, data, s, rpmhead, flags);
if ((flags & RPMDB_REPORT_PROGRESS) != 0)
{
if (done < count)
int headerstart, headerend;
struct stat stb;
Repodata *data;
+ unsigned char pkgid[16];
+ int gotpkgid;
if (!(flags & REPO_REUSE_REPODATA))
data = repo_add_repodata(repo, 0);
sigdsize += sigcnt * 16;
sigdsize = (sigdsize + 7) & ~7;
headerstart = 96 + 16 + sigdsize;
- while (sigdsize)
+ gotpkgid = 0;
+ if ((flags & RPM_ADD_WITH_PKGID) != 0)
{
- l = sigdsize > 4096 ? 4096 : sigdsize;
- if (fread(lead, l, 1, fp) != 1)
+ unsigned char *chksum;
+ unsigned int chksumsize;
+ /* extract pkgid from the signature header */
+ if (sigdsize > rpmheadsize)
+ {
+ rpmheadsize = sigdsize + 128;
+ rpmhead = sat_realloc(rpmhead, sizeof(*rpmhead) + rpmheadsize);
+ }
+ if (fread(rpmhead->data, sigdsize, 1, fp) != 1)
{
fprintf(stderr, "%s: unexpected EOF\n", rpms[i]);
fclose(fp);
continue;
}
- sigdsize -= l;
+ rpmhead->cnt = sigcnt;
+ rpmhead->dcnt = sigdsize - sigcnt * 16;
+ rpmhead->dp = rpmhead->data + rpmhead->cnt * 16;
+ chksum = headbinary(rpmhead, SIGTAG_MD5, &chksumsize);
+ if (chksum && chksumsize == 16)
+ {
+ gotpkgid = 1;
+ memcpy(pkgid, chksum, 16);
+ }
+ }
+ else
+ {
+ /* just skip the signature header */
+ while (sigdsize)
+ {
+ l = sigdsize > 4096 ? 4096 : sigdsize;
+ if (fread(lead, l, 1, fp) != 1)
+ {
+ fprintf(stderr, "%s: unexpected EOF\n", rpms[i]);
+ fclose(fp);
+ continue;
+ }
+ sigdsize -= l;
+ }
}
if (fread(lead, 16, 1, fp) != 1)
{
}
fclose(fp);
s = pool_id2solvable(pool, repo_add_solvable(repo));
- rpm2solv(pool, repo, data, s, rpmhead);
+ rpm2solv(pool, repo, data, s, rpmhead, flags);
if (data)
{
Id handle = s - pool->solvables;
repodata_set_location(data, handle, 0, 0, rpms[i]);
repodata_set_num(data, handle, SOLVABLE_DOWNLOADSIZE, (unsigned int)((stb.st_size + 1023) / 1024));
repodata_set_num(data, handle, SOLVABLE_HEADEREND, headerend);
+ if (gotpkgid)
+ repodata_set_bin_checksum(data, handle, SOLVABLE_PKGID, REPOKEY_TYPE_MD5, pkgid);
}
}
if (rpmhead)
extern void repo_add_rpmdb(Repo *repo, Repo *ref, const char *rootdir, int flags);
extern void repo_add_rpms(Repo *repo, const char **rpms, int nrpms, int flags);
-#define RPMDB_REPORT_PROGRESS (1 << 8)
+#define RPMDB_REPORT_PROGRESS (1 << 8)
+#define RPM_ADD_WITH_PKGID (1 << 9)
+#define RPM_ADD_NO_FILELIST (1 << 10)
+#define RPM_ADD_NO_RPMLIBREQS (1 << 11)
#define RPM_ITERATE_FILELIST_ONLYDIRS (1 << 0)
#define RPM_ITERATE_FILELIST_WITHMD5 (1 << 1)
}
/*
- * add Id to repo
- * olddeps = old array to extend
+ * remove repo from pool, zero out (i.e. free) solvables
*
*/
+void
+repo_free(Repo *repo, int reuseids)
+{
+ Pool *pool = repo->pool;
+ Solvable *s;
+ int i;
+
+ pool_freewhatprovides(pool);
+ if (repo == pool->installed)
+ pool->installed = 0;
+
+ if (reuseids && repo->end == pool->nsolvables)
+ {
+ /* it's ok to reuse the ids. As this is the last repo, we can
+ just shrink the solvable array */
+ for (i = repo->end - 1, s = pool->solvables + i; i >= repo->start; i--, s--)
+ if (s->repo != repo)
+ break;
+ repo->end = i + 1;
+ pool->nsolvables = i + 1;
+ }
+ /* zero out (i.e. free) solvables belonging to this repo */
+ for (i = repo->start, s = pool->solvables + i; i < repo->end; i++, s++)
+ if (s->repo == repo)
+ memset(s, 0, sizeof(*s));
+ for (i = 0; i < pool->nrepos; i++) /* find repo in pool */
+ if (pool->repos[i] == repo)
+ break;
+ if (i == pool->nrepos) /* repo not in pool, return */
+ return;
+ if (i < pool->nrepos - 1)
+ {
+ memmove(pool->repos + i, pool->repos + i + 1, (pool->nrepos - 1 - i) * sizeof(Repo *));
+ /* fix repo ids */
+ for (; i < pool->nrepos - 1; i++)
+ pool->repos[i]->repoid = i + 1;
+ }
+ pool->nrepos--;
+ repo_freedata(repo);
+}
+
+void
+repo_freeallrepos(Pool *pool, int reuseids)
+{
+ int i;
+
+ pool_freewhatprovides(pool);
+ for (i = 0; i < pool->nrepos; i++)
+ repo_freedata(pool->repos[i]);
+ pool->repos = sat_free(pool->repos);
+ pool->nrepos = 0;
+ /* the first two solvables don't belong to a repo */
+ pool_free_solvable_block(pool, 2, pool->nsolvables - 2, reuseids);
+}
+
+
+/* repository sidedata is solvable data allocated on demand.
+ * It is used for data that is normally not present
+ * in the solvable like the rpmdbid.
+ * The solvable allocation funcions need to make sure that
+ * the sidedata gets extended if new solvables get added.
+ */
+
+#define REPO_SIDEDATA_BLOCK 63
+
+void *
+repo_sidedata_create(Repo *repo, size_t size)
+{
+ return sat_calloc_block(repo->end - repo->start, size, REPO_SIDEDATA_BLOCK);
+}
+
+void *
+repo_sidedata_extend(Repo *repo, void *b, size_t size, Id p, int count)
+{
+ int n = repo->end - repo->start;
+ if (p < repo->start)
+ {
+ int d = repo->start - p;
+ b = sat_extend(b, n, d, size, REPO_SIDEDATA_BLOCK);
+ memmove((char *)b + d * size, b, n * size);
+ memset(b, 0, d * size);
+ n += d;
+ }
+ if (p + count > repo->end)
+ {
+ int d = p + count - repo->end;
+ b = sat_extend(b, n, d, size, REPO_SIDEDATA_BLOCK);
+ memset((char *)b + n * size, 0, d * size);
+ }
+ return b;
+}
+
+/*
+ * add Id to idarraydata used to store dependencies
+ * olddeps: old array offset to extend
+ * returns new array offset
+ */
+
Offset
repo_addid(Repo *repo, Offset olddeps, Id id)
{
* marker= 0 for normal dep
* marker > 0 add dep after marker
* marker < 0 add dep after -marker
- *
+ * returns new start of dependency array
*/
Offset
repo_addid_dep(Repo *repo, Offset olddeps, Id id, Id marker)
/*
* reserve Ids
* make space for 'num' more dependencies
+ * returns new start of dependency array
+ *
+ * reserved ids will always begin at offset idarraysize
*/
Offset
}
-/*
- * remove repo from pool, zero out solvables
- *
- */
-
-void
-repo_free(Repo *repo, int reuseids)
-{
- Pool *pool = repo->pool;
- Solvable *s;
- int i;
-
- pool_freewhatprovides(pool);
- if (repo == pool->installed)
- pool->installed = 0;
-
- if (reuseids && repo->end == pool->nsolvables)
- {
- /* it's ok to reuse the ids. As this is the last repo, we can
- just shrink the solvable array */
- for (i = repo->end - 1, s = pool->solvables + i; i >= repo->start; i--, s--)
- if (s->repo != repo)
- break;
- repo->end = i + 1;
- pool->nsolvables = i + 1;
- }
- /* zero out solvables belonging to this repo */
- for (i = repo->start, s = pool->solvables + i; i < repo->end; i++, s++)
- if (s->repo == repo)
- memset(s, 0, sizeof(*s));
- for (i = 0; i < pool->nrepos; i++) /* find repo in pool */
- if (pool->repos[i] == repo)
- break;
- if (i == pool->nrepos) /* repo not in pool, return */
- return;
- if (i < pool->nrepos - 1)
- {
- memmove(pool->repos + i, pool->repos + i + 1, (pool->nrepos - 1 - i) * sizeof(Repo *));
- /* fix repo ids */
- for (; i < pool->nrepos - 1; i++)
- pool->repos[i]->repoid = i + 1;
- }
- pool->nrepos--;
- repo_freedata(repo);
-}
-
-void
-repo_freeallrepos(Pool *pool, int reuseids)
-{
- int i;
-
- pool_freewhatprovides(pool);
- for (i = 0; i < pool->nrepos; i++)
- repo_freedata(pool->repos[i]);
- pool->repos = sat_free(pool->repos);
- pool->nrepos = 0;
- /* the first two solvables don't belong to a repo */
- pool_free_solvable_block(pool, 2, pool->nsolvables - 2, reuseids);
-}
-
-
-#define REPO_SIDEDATA_BLOCK 63
-
-void *
-repo_sidedata_create(Repo *repo, size_t size)
-{
- return sat_calloc_block(repo->end - repo->start, size, REPO_SIDEDATA_BLOCK);
-}
-
-void *
-repo_sidedata_extend(Repo *repo, void *b, size_t size, Id p, int count)
-{
- int n = repo->end - repo->start;
- if (p < repo->start)
- {
- int d = repo->start - p;
- b = sat_extend(b, n, d, size, REPO_SIDEDATA_BLOCK);
- memmove((char *)b + d * size, b, n * size);
- memset(b, 0, d * size);
- n += d;
- }
- if (p + count > repo->end)
- {
- int d = p + count - repo->end;
- b = sat_extend(b, n, d, size, REPO_SIDEDATA_BLOCK);
- memset((char *)b + n * size, 0, d * size);
- }
- return b;
-}
Offset
repo_fix_supplements(Repo *repo, Offset provides, Offset supplements, Offset freshens)
{
Id id = repodata_lookup_id(data, entry, keyname);
if (id)
- {
- if (data->localpool)
- id = repodata_globalize_id(data, id);
- return id;
- }
+ return data->localpool ? repodata_globalize_id(data, id, 1) : id;
}
}
}
}
else
{
- if (repo->rpmdbid)
- repo->rpmdbid = (Id *)repo_sidedata_extend(repo, repo->rpmdbid, sizeof(Id), p, 1);
if (p < repo->start)
repo->start = p;
if (p + 1 > repo->end)
repo->end = p + 1;
}
+ if (repo->rpmdbid)
+ repo->rpmdbid = (Id *)repo_sidedata_extend(repo, repo->rpmdbid, sizeof(Id), p, 1);
repo->nsolvables++;
repo->pool->solvables[p].repo = repo;
return p;
}
else
{
- if (repo->rpmdbid)
- repo->rpmdbid = (Id *)repo_sidedata_extend(repo, repo->rpmdbid, sizeof(Id), p, count);
if (p < repo->start)
repo->start = p;
if (p + count > repo->end)
repo->end = p + count;
}
+ if (repo->rpmdbid)
+ repo->rpmdbid = (Id *)repo_sidedata_extend(repo, repo->rpmdbid, sizeof(Id), p, count);
repo->nsolvables += count;
for (s = repo->pool->solvables + p; count--; s++)
s->repo = repo;
*
* Manage data coming from one repository
*
+ * a repository can contain multiple repodata entries, consisting of
+ * different sets of keys and different sets of solvables
*/
#define _GNU_SOURCE
return id;
}
+Id
+repodata_globalize_id(Repodata *data, Id id, int create)
+{
+ if (!id || !data || !data->localpool)
+ return id;
+ return str2id(data->repo->pool, stringpool_id2str(&data->spool, id), create);
+}
+
const char *
repodata_lookup_str(Repodata *data, Id solvid, Id keyname)
{
}
}
+/* extend repodata so that it includes solvables from start to start + num - 1 */
void
repodata_extend_block(Repodata *data, Id start, Id num)
{
data->attrdatalen += l;
}
+/* add an array element consisting of entrysize Ids to the repodata. modifies attriddata
+ * so that the caller can append the new element there */
static void
repodata_add_array(Repodata *data, Id handle, Id keyname, Id keytype, int entrysize)
{
int i;
for (i = 0; i < buflen; i++)
{
-#define c2h(c) (((c)>='0' && (c)<='9') ? ((c)-'0') \
- : ((c)>='a' && (c)<='f') ? ((c)-'a'+10) \
- : ((c)>='A' && (c)<='F') ? ((c)-'A'+10) \
+#define c2h(c) (((c)>='0' && (c)<='9') ? ((c)-'0') \
+ : ((c)>='a' && (c)<='f') ? ((c)-('a'-10)) \
+ : ((c)>='A' && (c)<='F') ? ((c)-('A'-10)) \
: -1)
int v = c2h(*str);
str++;
return str;
}
+/* rpm filenames don't contain the epoch, so strip it */
static inline const char *
evrid2vrstr(Pool *pool, Id evrid)
{
repodata_set_str(data, solvid, SOLVABLE_MEDIAFILE, file);
}
-Id
-repodata_globalize_id(Repodata *data, Id id)
-{
- if (!data || !data->localpool)
- return id;
- return str2id(data->repo->pool, stringpool_id2str(&data->spool, id), 1);
-}
-
void
repodata_add_dirnumnum(Repodata *data, Id solvid, Id keyname, Id dir, Id num, Id num2)
{
data->attriddata[data->attriddatalen++] = 0;
}
+/* add all attrs from src to dest */
void
repodata_merge_attrs(Repodata *data, Id dest, Id src)
{
schemaid = repodata_schema2id(data, schema, 1);
else if (schemaid != repodata_schema2id(data, schema, 0))
{
- pool_debug(data->repo->pool, SAT_FATAL, "substructs with different schemas\n");
+ pool_debug(data->repo->pool, SAT_FATAL, "fixarray substructs with different schemas\n");
exit(1);
}
#if 0
void repodata_disable_paging(Repodata *data);
/* helper functions */
-Id repodata_globalize_id(Repodata *data, Id id);
+Id repodata_globalize_id(Repodata *data, Id id, int create);
Id repodata_str2dir(Repodata *data, const char *dir, int create);
const char *repodata_dir2str(Repodata *data, Id did, const char *suf);
const char *repodata_chk2str(Repodata *data, Id type, const unsigned char *buf);
/*
* repopage.c
*
- * Pageing and compression functions for the vertical repository data
- *
+ * Paging and compression functions for the vertical repository data.
+ * Vertical data is grouped by key, normal data is grouped by solvable.
+ * This makes searching for a string in vertical data fast as there's
+ * no need to skip over data if keys we're not interested in.
+ *
+ * The vertical data is split into pages, each page is compressed with a fast
+ * compression algorithm. These pages are read in on demand, not recently used
+ * pages automatically get dropped.
*/
#define _XOPEN_SOURCE 500
POOL_DEBUG(SAT_DEBUG_RESULT, "upgraded packages (%d):\n", cnt);
break;
case SOLVER_TRANSACTION_VENDORCHANGE:
- POOL_DEBUG(SAT_DEBUG_RESULT, "vendor change from %s to %s (%d):\n", id2strnone(pool, classes.elements[i + 2]), id2strnone(pool, classes.elements[i + 3]), cnt);
+ POOL_DEBUG(SAT_DEBUG_RESULT, "vendor change from '%s' to '%s' (%d):\n", id2strnone(pool, classes.elements[i + 2]), id2strnone(pool, classes.elements[i + 3]), cnt);
break;
case SOLVER_TRANSACTION_ARCHCHANGE:
POOL_DEBUG(SAT_DEBUG_RESULT, "arch change from %s to %s (%d):\n", id2str(pool, classes.elements[i + 2]), id2str(pool, classes.elements[i + 3]), cnt);
for (i = 1, te = od->tes + i; i < od->ntes; i++, te++)
{
Solvable *s = pool->solvables + te->p;
- POOL_DEBUG(SAT_WARN, "TE %4d: %c%s\n", i, s->repo == pool->installed ? '-' : '+', solvable2str(pool, s));
+ POOL_DEBUG(SAT_DEBUG_RESULT, "TE %4d: %c%s\n", i, s->repo == pool->installed ? '-' : '+', solvable2str(pool, s));
if (s->repo != pool->installed)
{
queue_empty(&obsq);
transaction_all_obs_pkgs(od->trans, te->p, &obsq);
for (j = 0; j < obsq.count; j++)
- POOL_DEBUG(SAT_WARN, " -%s\n", solvid2str(pool, obsq.elements[j]));
+ POOL_DEBUG(SAT_DEBUG_RESULT, " -%s\n", solvid2str(pool, obsq.elements[j]));
}
for (j = te->edges; od->edgedata[j]; j += 2)
{
te2 = od->tes + od->edgedata[j];
- POOL_DEBUG(SAT_WARN, " --%x--> TE %4d: %s\n", od->edgedata[j + 1], od->edgedata[j], solvid2str(pool, te2->p));
+ if ((od->edgedata[j + 1] & TYPE_BROKEN) == 0)
+ POOL_DEBUG(SAT_DEBUG_RESULT, " --%x--> TE %4d: %s\n", od->edgedata[j + 1], od->edgedata[j], solvid2str(pool, te2->p));
+ else
+ POOL_DEBUG(SAT_DEBUG_RESULT, " ##%x##> TE %4d: %s\n", od->edgedata[j + 1], od->edgedata[j], solvid2str(pool, te2->p));
}
}
}
}
POOL_DEBUG(SAT_DEBUG_STATS, "cycle edge creation took %d ms\n", sat_timems(now));
+ dump_tes(&od);
/* all edges are finally set up and there are no cycles, now the easy part.
* Create an ordered transaction */
now = sat_timems(0);
}
if (!good)
{
- POOL_DEBUG(SAT_WARN, " %c%s: nothing provides %s needed by %c%s\n", pool->solvables[tepkg].repo == pool->installed ? '-' : '+', solvid2str(pool, tepkg), dep2str(pool, req), s->repo == pool->installed ? '-' : '+', solvable2str(pool, s));
+ POOL_DEBUG(SAT_DEBUG_RESULT, " %c%s: nothing provides %s needed by %c%s\n", pool->solvables[tepkg].repo == pool->installed ? '-' : '+', solvid2str(pool, tepkg), dep2str(pool, req), s->repo == pool->installed ? '-' : '+', solvable2str(pool, s));
}
}
}