#include <string.h>
#include "pool.h"
+#include "poolvendor.h"
#include "repo.h"
#include "poolid.h"
#include "poolid_private.h"
memset(pool->solvables, 0, 2 * sizeof(Solvable));
queue_init(&pool->vendormap);
+ queue_init(&pool->pooljobs);
+ queue_init(&pool->lazywhatprovidesq);
#if defined(DEBIAN)
pool->disttype = DISTTYPE_DEB;
#elif defined(ARCHLINUX)
pool->disttype = DISTTYPE_ARCH;
pool->noarchid = ARCH_ANY;
+#elif defined(HAIKU)
+ pool->disttype = DISTTYPE_HAIKU;
+ pool->noarchid = ARCH_ANY;
+ pool->obsoleteusesprovides = 1;
#else
pool->disttype = DISTTYPE_RPM;
pool->noarchid = ARCH_NOARCH;
pool->debugmask = SOLV_DEBUG_RESULT; /* FIXME */
#ifdef FEDORA
- pool->obsoleteusescolors = 1;
+ pool->implicitobsoleteusescolors = 1;
#endif
#ifdef RPM5
+ pool->noobsoletesmultiversion = 1;
pool->forbidselfconflicts = 1;
pool->obsoleteusesprovides = 1;
pool->implicitobsoleteusesprovides = 1;
pool_setvendorclasses(pool, 0);
queue_free(&pool->vendormap);
queue_free(&pool->pooljobs);
+ queue_free(&pool->lazywhatprovidesq);
for (i = 0; i < POOL_TMPSPACEBUF; i++)
solv_free(pool->tmpspace.buf[i]);
for (i = 0; i < pool->nlanguages; i++)
pool->noarchid = ARCH_ALL;
if (disttype == DISTTYPE_ARCH)
pool->noarchid = ARCH_ANY;
+ if (disttype == DISTTYPE_HAIKU)
+ pool->noarchid = ARCH_ANY;
pool->solvables[SYSTEMSOLVABLE].arch = pool->noarchid;
}
#endif
return pool->implicitobsoleteusesprovides;
case POOL_FLAG_OBSOLETEUSESCOLORS:
return pool->obsoleteusescolors;
+ case POOL_FLAG_IMPLICITOBSOLETEUSESCOLORS:
+ return pool->implicitobsoleteusescolors;
case POOL_FLAG_NOINSTALLEDOBSOLETES:
return pool->noinstalledobsoletes;
case POOL_FLAG_HAVEDISTEPOCH:
return pool->havedistepoch;
+ case POOL_FLAG_NOOBSOLETESMULTIVERSION:
+ return pool->noobsoletesmultiversion;
+ case POOL_FLAG_ADDFILEPROVIDESFILTERED:
+ return pool->addfileprovidesfiltered;
default:
break;
}
case POOL_FLAG_OBSOLETEUSESCOLORS:
pool->obsoleteusescolors = value;
break;
+ case POOL_FLAG_IMPLICITOBSOLETEUSESCOLORS:
+ pool->implicitobsoleteusescolors = value;
+ break;
case POOL_FLAG_NOINSTALLEDOBSOLETES:
pool->noinstalledobsoletes = value;
break;
case POOL_FLAG_HAVEDISTEPOCH:
pool->havedistepoch = value;
break;
+ case POOL_FLAG_NOOBSOLETESMULTIVERSION:
+ pool->noobsoletesmultiversion = value;
+ break;
+ case POOL_FLAG_ADDFILEPROVIDESFILTERED:
+ pool->addfileprovidesfiltered = value;
+ break;
default:
break;
}
for (i = 0, idp = whatprovides; i < num; i++, idp++)
{
n = *idp;
- if (!n) /* no providers */
- continue;
- off += n; /* make space for all providers */
- *idp = off++; /* now idp points to terminating zero */
- np++; /* inc # of provider 'slots' for stats */
+ if (!n) /* no providers */
+ {
+ *idp = 1; /* offset for empty list */
+ continue;
+ }
+ off += n; /* make space for all providers */
+ *idp = off++; /* now idp points to terminating zero */
+ np++; /* inc # of provider 'slots' for stats */
}
POOL_DEBUG(SOLV_DEBUG_STATS, "provide ids: %d\n", np);
pool->whatprovidesdataleft = extra;
pool_shrink_whatprovides(pool);
POOL_DEBUG(SOLV_DEBUG_STATS, "whatprovides memory used: %d K id array, %d K data\n", (pool->ss.nstrings + pool->nrels + WHATPROVIDES_BLOCK) / (int)(1024/sizeof(Id)), (pool->whatprovidesdataoff + pool->whatprovidesdataleft) / (int)(1024/sizeof(Id)));
+
+ queue_empty(&pool->lazywhatprovidesq);
+ if ((!pool->addedfileprovides && pool->disttype == DISTTYPE_RPM) || pool->addedfileprovides == 1)
+ {
+ if (!pool->addedfileprovides)
+ POOL_DEBUG(SOLV_DEBUG_STATS, "WARNING: pool_addfileprovides was not called, this may result in slow operation\n");
+ /* lazyly add file provides */
+ for (i = 1; i < num; i++)
+ {
+ const char *str = pool->ss.stringspace + pool->ss.strings[i];
+ if (str[0] != '/')
+ continue;
+ if (pool->addedfileprovides == 1 && repodata_filelistfilter_matches(0, str))
+ continue;
+ /* setup lazy adding, but remember old value */
+ if (pool->whatprovides[i] > 1)
+ queue_push2(&pool->lazywhatprovidesq, i, pool->whatprovides[i]);
+ pool->whatprovides[i] = 0;
+ }
+ POOL_DEBUG(SOLV_DEBUG_STATS, "lazywhatprovidesq size: %d entries\n", pool->lazywhatprovidesq.count / 2);
+ }
+
POOL_DEBUG(SOLV_DEBUG_STATS, "createwhatprovides took %d ms\n", solv_timems(now));
}
#endif
/* check if a package's nevr matches a dependency */
+/* semi-private, called from public pool_match_nevr */
int
pool_match_nevr_rel(Pool *pool, Solvable *s, Id d)
return 0;
}
+#if defined(HAIKU) || defined(MULTI_SEMANTICS)
+/* forward declaration */
+static int pool_match_flags_evr_rel_compat(Pool *pool, Reldep *range, int flags, int evr);
+#endif
+
/* match (flags, evr) against provider (pflags, pevr) */
static inline int
pool_match_flags_evr(Pool *pool, int pflags, Id pevr, int flags, int evr)
return 1; /* both rels show in the same direction */
if (pevr == evr)
return (flags & pflags & REL_EQ) ? 1 : 0;
+#if defined(HAIKU) || defined(MULTI_SEMANTICS)
+ if (ISRELDEP(pevr))
+ {
+ Reldep *rd = GETRELDEP(pool, pevr);
+ if (rd->flags == REL_COMPAT)
+ return pool_match_flags_evr_rel_compat(pool, rd, flags, evr);
+ }
+#endif
switch (pool_evrcmp(pool, pevr, evr, EVRCMP_DEPCMP))
{
case -2:
return 0;
}
+#if defined(HAIKU) || defined(MULTI_SEMANTICS)
+static int
+pool_match_flags_evr_rel_compat(Pool *pool, Reldep *range, int flags, int evr)
+{
+ /* range->name is the actual version, range->evr the backwards compatibility
+ version. If flags are '>=' or '>', we match the compatibility version
+ as well, otherwise only the actual version. */
+ if (!(flags & REL_GT) || (flags & REL_LT))
+ return pool_match_flags_evr(pool, REL_EQ, range->name, flags, evr);
+ return pool_match_flags_evr(pool, REL_LT | REL_EQ, range->name, flags, evr) &&
+ pool_match_flags_evr(pool, REL_GT | REL_EQ, range->evr, REL_EQ, evr);
+}
+#endif
+
+/* public (i.e. not inlined) version of pool_match_flags_evr */
+int
+pool_intersect_evrs(Pool *pool, int pflags, Id pevr, int flags, int evr)
+{
+ return pool_match_flags_evr(pool, pflags, pevr, flags, evr);
+}
+
/* match two dependencies (d1 = provider) */
int
if (!pool_match_dep(pool, rd1->name, rd2->name))
return 0;
/* name matches, check flags and evr */
- return pool_match_flags_evr(pool, rd1->flags, rd1->evr, rd2->flags, rd2->evr);
+ return pool_intersect_evrs(pool, rd1->flags, rd1->evr, rd2->flags, rd2->evr);
+}
+
+Id
+pool_searchlazywhatprovidesq(Pool *pool, Id d)
+{
+ int start = 0;
+ int end = pool->lazywhatprovidesq.count;
+ Id *elements;
+ if (!end)
+ return 0;
+ elements = pool->lazywhatprovidesq.elements;
+ while (end - start > 16)
+ {
+ int mid = (start + end) / 2 & ~1;
+ if (elements[mid] == d)
+ return elements[mid + 1];
+ if (elements[mid] < d)
+ start = mid + 2;
+ else
+ end = mid;
+ }
+ for (; start < end; start += 2)
+ if (elements[start] == d)
+ return elements[start + 1];
+ return 0;
}
/*
+ * addstdproviders
+ *
+ * lazy populating of the whatprovides array, non relation case
+ */
+static Id
+pool_addstdproviders(Pool *pool, Id d)
+{
+ const char *str;
+ Queue q;
+ Id qbuf[16];
+ Dataiterator di;
+ Id oldoffset;
+
+ if (pool->addedfileprovides == 2)
+ {
+ pool->whatprovides[d] = 1;
+ return 1;
+ }
+ str = pool->ss.stringspace + pool->ss.strings[d];
+ if (*str != '/')
+ {
+ pool->whatprovides[d] = 1;
+ return 1;
+ }
+ queue_init_buffer(&q, qbuf, sizeof(qbuf)/sizeof(*qbuf));
+ dataiterator_init(&di, pool, 0, 0, SOLVABLE_FILELIST, str, SEARCH_STRING|SEARCH_FILES|SEARCH_COMPLETE_FILELIST);
+ for (; dataiterator_step(&di); dataiterator_skip_solvable(&di))
+ {
+ Solvable *s = pool->solvables + di.solvid;
+ /* XXX: maybe should add a provides dependency to the solvables
+ * OTOH this is only needed for rel deps that filter the provides,
+ * and those should not use filelist entries */
+ if (s->repo->disabled)
+ continue;
+ if (s->repo != pool->installed && !pool_installable(pool, s))
+ continue;
+ queue_push(&q, di.solvid);
+ }
+ dataiterator_free(&di);
+ oldoffset = pool_searchlazywhatprovidesq(pool, d);
+ if (!q.count)
+ pool->whatprovides[d] = oldoffset ? oldoffset : 1;
+ else
+ {
+ if (oldoffset)
+ {
+ Id *oo = pool->whatprovidesdata + oldoffset;
+ int i;
+ /* unify both queues. easy, as we know both are sorted */
+ for (i = 0; i < q.count; i++)
+ {
+ if (*oo > q.elements[i])
+ continue;
+ if (*oo < q.elements[i])
+ queue_insert(&q, i, *oo);
+ oo++;
+ if (!*oo)
+ break;
+ }
+ while (*oo)
+ queue_push(&q, *oo++);
+ if (q.count == oo - (pool->whatprovidesdata + oldoffset))
+ {
+ /* end result has same size as oldoffset -> no new entries */
+ queue_free(&q);
+ pool->whatprovides[d] = oldoffset;
+ return oldoffset;
+ }
+ }
+ pool->whatprovides[d] = pool_queuetowhatprovides(pool, &q);
+ }
+ queue_free(&q);
+ return pool->whatprovides[d];
+}
+
+
+/*
* addrelproviders
*
* add packages fulfilling the relation to whatprovides array
- * no exact providers, do range match
*
*/
-
Id
pool_addrelproviders(Pool *pool, Id d)
{
- Reldep *rd = GETRELDEP(pool, d);
+ Reldep *rd;
Reldep *prd;
Queue plist;
Id buf[16];
- Id name = rd->name;
- Id evr = rd->evr;
- int flags = rd->flags;
+ Id name, evr, flags;
Id pid, *pidp;
Id p, *pp;
+ if (!ISRELDEP(d))
+ return pool_addstdproviders(pool, d);
+ rd = GETRELDEP(pool, d);
+ name = rd->name;
+ evr = rd->evr;
+ flags = rd->flags;
d = GETRELID(d);
queue_init_buffer(&plist, buf, sizeof(buf)/sizeof(*buf));
return pool->whatprovides_rel[d];
}
+void
+pool_flush_namespaceproviders(Pool *pool, Id ns, Id evr)
+{
+ int nrels = pool->nrels;
+ Id d;
+ Reldep *rd;
+
+ if (!pool->whatprovides_rel)
+ return;
+ for (d = 1, rd = pool->rels + d; d < nrels; d++, rd++)
+ {
+ if (rd->flags != REL_NAMESPACE || rd->name == NAMESPACE_OTHERPROVIDERS)
+ continue;
+ if (ns && rd->name != ns)
+ continue;
+ if (evr && rd->evr != evr)
+ continue;
+ pool->whatprovides_rel[d] = 0;
+ }
+}
+
+/* intersect dependencies in keyname with dep, return list of matching packages */
+void
+pool_whatmatchesdep(Pool *pool, Id keyname, Id dep, Queue *q, int marker)
+{
+ Id p;
+
+ queue_empty(q);
+ FOR_POOL_SOLVABLES(p)
+ {
+ Solvable *s = pool->solvables + p;
+ if (s->repo->disabled)
+ continue;
+ if (s->repo != pool->installed && !pool_installable(pool, s))
+ continue;
+ if (solvable_matchesdep(s, keyname, dep, marker))
+ queue_push(q, p);
+ }
+}
+
/*************************************************************************/
void
pool->loadcallbackdata = loadcbdata;
}
+void pool_setnamespacecallback(Pool *pool, Id (*cb)(struct _Pool *, void *, Id, Id), void *nscbdata)
+{
+ pool->nscallback = cb;
+ pool->nscallbackdata = nscbdata;
+}
+
/*************************************************************************/
struct searchfiles {
s = pool_id2str(pool, dep);
if (*s != '/')
continue;
+ if (csf != isf && pool->addedfileprovides == 1 && !repodata_filelistfilter_matches(0, s))
+ continue; /* skip non-standard locations csf == isf: installed case */
csf->ids = solv_extend(csf->ids, csf->nfiles, 1, sizeof(Id), SEARCHFILES_BLOCK);
csf->dirs = solv_extend(csf->dirs, csf->nfiles, 1, sizeof(const char *), SEARCHFILES_BLOCK);
csf->names = solv_extend(csf->names, csf->nfiles, 1, sizeof(const char *), SEARCHFILES_BLOCK);
map_init(&sf.seen, pool->ss.nstrings + pool->nrels);
memset(&isf, 0, sizeof(isf));
map_init(&isf.seen, pool->ss.nstrings + pool->nrels);
+ pool->addedfileprovides = pool->addfileprovidesfiltered ? 1 : 2;
if (idq)
queue_empty(idq);
pool_lookup_str(Pool *pool, Id entry, Id keyname)
{
if (entry == SOLVID_POS && pool->pos.repo)
- return repodata_lookup_str(pool->pos.repo->repodata + pool->pos.repodataid, SOLVID_POS, keyname);
+ return repo_lookup_str(pool->pos.repo, pool->pos.repodataid ? entry : pool->pos.solvid, keyname);
if (entry <= 0)
return 0;
return solvable_lookup_str(pool->solvables + entry, keyname);
pool_lookup_id(Pool *pool, Id entry, Id keyname)
{
if (entry == SOLVID_POS && pool->pos.repo)
- {
- Repodata *data = pool->pos.repo->repodata + pool->pos.repodataid;
- Id id = repodata_lookup_id(data, SOLVID_POS, keyname);
- return data->localpool ? repodata_globalize_id(data, id, 1) : id;
- }
+ return repo_lookup_id(pool->pos.repo, pool->pos.repodataid ? entry : pool->pos.solvid, keyname);
if (entry <= 0)
return 0;
return solvable_lookup_id(pool->solvables + entry, keyname);
pool_lookup_num(Pool *pool, Id entry, Id keyname, unsigned long long notfound)
{
if (entry == SOLVID_POS && pool->pos.repo)
- {
- unsigned long long value;
- if (repodata_lookup_num(pool->pos.repo->repodata + pool->pos.repodataid, SOLVID_POS, keyname, &value))
- return value;
- return notfound;
- }
+ return repo_lookup_num(pool->pos.repo, pool->pos.repodataid ? entry : pool->pos.solvid, keyname, notfound);
if (entry <= 0)
return notfound;
return solvable_lookup_num(pool->solvables + entry, keyname, notfound);
pool_lookup_void(Pool *pool, Id entry, Id keyname)
{
if (entry == SOLVID_POS && pool->pos.repo)
- return repodata_lookup_void(pool->pos.repo->repodata + pool->pos.repodataid, SOLVID_POS, keyname);
+ return repo_lookup_void(pool->pos.repo, pool->pos.repodataid ? entry : pool->pos.solvid, keyname);
if (entry <= 0)
return 0;
return solvable_lookup_void(pool->solvables + entry, keyname);
pool_lookup_bin_checksum(Pool *pool, Id entry, Id keyname, Id *typep)
{
if (entry == SOLVID_POS && pool->pos.repo)
- return repodata_lookup_bin_checksum(pool->pos.repo->repodata + pool->pos.repodataid, SOLVID_POS, keyname, typep);
+ return repo_lookup_bin_checksum(pool->pos.repo, pool->pos.repodataid ? entry : pool->pos.solvid, keyname, typep);
if (entry <= 0)
return 0;
return solvable_lookup_bin_checksum(pool->solvables + entry, keyname, typep);
pool_lookup_checksum(Pool *pool, Id entry, Id keyname, Id *typep)
{
if (entry == SOLVID_POS && pool->pos.repo)
- {
- const unsigned char *chk = repodata_lookup_bin_checksum(pool->pos.repo->repodata + pool->pos.repodataid, SOLVID_POS, keyname, typep);
- return chk ? repodata_chk2str(pool->pos.repo->repodata + pool->pos.repodataid, *typep, chk) : 0;
- }
+ return repo_lookup_checksum(pool->pos.repo, pool->pos.repodataid ? entry : pool->pos.solvid, keyname, typep);
if (entry <= 0)
return 0;
return solvable_lookup_checksum(pool->solvables + entry, keyname, typep);
}
+int
+pool_lookup_idarray(Pool *pool, Id entry, Id keyname, Queue *q)
+{
+ if (entry == SOLVID_POS && pool->pos.repo)
+ return repo_lookup_idarray(pool->pos.repo, pool->pos.repodataid ? entry : pool->pos.solvid, keyname, q);
+ if (entry <= 0)
+ return 0;
+ return solvable_lookup_idarray(pool->solvables + entry, keyname, q);
+}
+
const char *
pool_lookup_deltalocation(Pool *pool, Id entry, unsigned int *medianrp)
{
if (!conflicts->count)
return;
- for (i = 0; i < conflicts->count; i += 5)
+ for (i = 0; i < conflicts->count; i += 6)
{
fn = conflicts->elements[i];
p = conflicts->elements[i + 1];
md5 = conflicts->elements[i + 2];
- q = conflicts->elements[i + 3];
+ q = conflicts->elements[i + 4];
id = pool_rel2id(pool, fn, md5, REL_FILECONFLICT, 1);
s = pool->solvables + p;
if (!s->repo)