-/*
- * Copyright (c) 2009 - 2017 SUSE Linux Products GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the same terms as Perl itself.
- *
- */
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#define MULTI_SEMANTICS
-#include "solvversion.h"
-#if LIBSOLV_VERSION < 623
-#define LIBSOLVEXT_FEATURE_DEBIAN
-#define LIBSOLVEXT_FEATURE_ARCHREPO
-#endif
-
#include "pool.h"
#include "repo.h"
#include "util.h"
#include "evr.h"
#include "hash.h"
#include "chksum.h"
-#include "testcase.h"
#include "repo_solv.h"
#include "repo_write.h"
#include "repo_rpmdb.h"
-#if defined(LIBSOLVEXT_FEATURE_DEBIAN)
#include "repo_deb.h"
-#endif
-#if defined(LIBSOLVEXT_FEATURE_ARCHREPO)
+#if 1
#include "repo_arch.h"
#endif
-#if defined(LIBSOLV_FEATURE_COMPLEX_DEPS)
-#include "pool_parserpmrichdep.h"
-#endif
-
-#ifndef REL_ERROR
-# define REL_ERROR 27 /* for old libsolv versions */
-#endif
-#ifndef REL_UNLESS
-# define REL_UNLESS 29 /* for old libsolv versions */
-#endif
-
-#define EXPANDER_DEBUG_ALL (1 << 0)
-#define EXPANDER_DEBUG_STDOUT (1 << 1)
-#define EXPANDER_DEBUG_STR (1 << 2)
-
-#define EXPANDER_OPTION_IGNOREIGNORE (1 << 0)
-#define EXPANDER_OPTION_IGNORECONFLICTS (1 << 1)
-#define EXPANDER_OPTION_DORECOMMENDS (1 << 2)
-#define EXPANDER_OPTION_DOSUPPLEMENTS (1 << 3)
-#define EXPANDER_OPTION_USERECOMMENDSFORCHOICES (1 << 4)
-#define EXPANDER_OPTION_USESUPPLEMENTSFORCHOICES (1 << 5)
typedef struct _Expander {
Pool *pool;
Queue conflictsq;
Map conflicts;
+ int debug;
int havefileprovides;
+ int ignoreconflicts;
+ int ignoreignore;
- /* debug support */
- int debug;
char *debugstr;
int debugstrl;
int debugstrf;
-
- /* options */
- int ignoreconflicts;
- int ignoreignore;
int userecommendsforchoices;
- int usesupplementsforchoices;
- int dorecommends;
- int dosupplements;
} Expander;
-typedef struct _ExpanderCtx {
- Pool *pool;
- Expander *xp;
- Queue *out; /* the result */
- Map installed; /* installed packages */
- Map conflicts; /* conflicts from installed packages */
- Queue conflictsinfo; /* source info for the above */
- int cidone; /* conflictsinfo done position */
- Queue todo; /* requires todo list */
- Queue errors; /* expansion errors */
- Queue cplxq; /* complex dep work queue */
- Queue cplxblks; /* complex dep block data, add only */
- Queue todo_cond; /* delayed requires/conflicts */
- Queue pruneq; /* multi purpose queue for pruning packages */
- Map todo_condmap; /* all neg packages in todo_cond blocks */
- Map recommended; /* recommended packages */
- int recdone; /* recommended done position */
-
- /* options */
- int ignoreconflicts;
- int ignoreignore;
- int userecommendsforchoices;
- int usesupplementsforchoices;
- int dorecommends;
- int dosupplements;
-
- /* hacks */
- Solvable *ignore_s; /* small hack: ignore requires of this solvable */
-} ExpanderCtx;
-
-
typedef Pool *BSSolv__pool;
typedef Repo *BSSolv__repo;
typedef Expander *BSSolv__expander;
static Id buildservice_repocookie;
static Id buildservice_external;
static Id buildservice_dodurl;
-static Id buildservice_dodcookie;
-static Id buildservice_dodresources;
-static Id buildservice_annotation;
-static Id buildservice_modules;
static Id expander_directdepsend;
-
-static int genmetaalgo;
-static int depsortsccs;
+static Id buildservice_dodcookie;
/* make sure bit n is usable */
#define MAPEXP(m, n) ((m)->size < (((n) + 8) >> 3) ? map_grow(m, n + 256) : 0)
}
static Id
-dep2id_rec(Pool *pool, char *s)
+dep2id(Pool *pool, char *s)
{
char *n;
Id id;
if ((n = strchr(s, '|')) != 0)
{
- id = dep2id_rec(pool, n + 1);
+ id = dep2id(pool, n + 1);
*n = 0;
- id = pool_rel2id(pool, dep2id_rec(pool, s), id, REL_OR, 1);
+ id = pool_rel2id(pool, dep2id(pool, s), id, REL_OR, 1);
*n = '|';
return id;
}
while (*s == ' ' || *s == '\t')
s++;
n = s;
- if (pool->disttype == DISTTYPE_RPM)
- {
- /* rpm delimits the name by whitespace only */
- while (*s && *s != ' ' && *s != '\t')
- s++;
- }
- else
- {
- while (*s && *s != ' ' && *s != '\t' && *s != '<' && *s != '=' && *s != '>')
- s++;
- }
+ while (*s && *s != ' ' && *s != '\t' && *s != '<' && *s != '=' && *s != '>')
+ s++;
#ifdef REL_MULTIARCH
if (s - n > 4 && s[-4] == ':' && !strncmp(s - 4, ":any", 4))
{
for (;;s++)
{
if (*s == '<')
- flags |= REL_LT;
+ flags |= REL_LT;
else if (*s == '=')
- flags |= REL_EQ;
+ flags |= REL_EQ;
else if (*s == '>')
- flags |= REL_GT;
+ flags |= REL_GT;
else
- break;
+ break;
}
if (!flags)
return id;
return pool_rel2id(pool, id, pool_strn2id(pool, n, s - n, 1), flags, 1);
}
-static Id
-parsedep_error(Pool *pool, const char *s)
-{
- Id id;
- id = pool_str2id(pool, s, 1);
- return pool_rel2id(pool, pool_str2id(pool, "dependency parse error", 1), id, REL_ERROR, 1);
-}
-
-static Id
-dep2id(Pool *pool, char *s)
-{
- Id id;
- if (pool->disttype == DISTTYPE_RPM && *s == '(')
- {
-#if defined(LIBSOLV_FEATURE_COMPLEX_DEPS)
- id = pool_parserpmrichdep(pool, s);
-#else
- id = 0;
-#endif
- }
- else
- id = dep2id_rec(pool, s);
- if (!id)
- id = parsedep_error(pool, s);
- return id;
-}
-
-static Offset
+static inline Offset
importdeps(HV *hv, const char *key, int keyl, Repo *repo)
{
Pool *pool = repo->pool;
- SSize_t i;
+ int i;
AV *av = hvlookupav(hv, key, keyl);
Offset off = 0;
if (av)
{
char *str = avlookupstr(av, i);
if (str)
- {
- Id id = testcase_str2dep(pool, str);
- if (!id)
- id = parsedep_error(pool, str);
- off = repo_addid_dep(repo, off, id, 0);
- }
+ off = repo_addid_dep(repo, off, dep2id(pool, str), 0);
}
}
return off;
}
-static void
+void
exportdeps(HV *hv, const char *key, int keyl, Repo *repo, Offset off, Id skey)
{
Pool *pool = repo->pool;
{
if (id == SOLVABLE_FILEMARKER)
break;
- str = testcase_dep2str(pool, id);
+ str = pool_dep2str(pool, id);
+ if (ISRELDEP(id))
+ {
+ Reldep *rd = GETRELDEP(pool, id);
+ if (skey == SOLVABLE_CONFLICTS && rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_OTHERPROVIDERS)
+ {
+ if (!strncmp(str, "namespace:", 10))
+ str += 10;
+ }
+ if (skey == SOLVABLE_SUPPLEMENTS)
+ {
+ if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_FILESYSTEM)
+ {
+ if (!strncmp(str, "namespace:", 10))
+ str += 10;
+ }
+ else if (rd->flags == REL_NAMESPACE && rd->name == NAMESPACE_MODALIAS)
+ {
+ if (!strncmp(str, "namespace:", 10))
+ str += 10;
+ }
+ else if (rd->flags == REL_AND)
+ {
+ /* either packageand chain or modalias */
+ str = 0;
+ if (ISRELDEP(rd->evr))
+ {
+ Reldep *mrd = GETRELDEP(pool, rd->evr);
+ if (mrd->flags == REL_NAMESPACE && mrd->name == NAMESPACE_MODALIAS)
+ {
+ str = pool_tmpjoin(pool, "modalias(", pool_dep2str(pool, rd->name), ":");
+ str = pool_tmpappend(pool, str, pool_dep2str(pool, mrd->evr), ")");
+ }
+ else if (mrd->flags >= 8)
+ continue;
+ }
+ if (!str)
+ {
+ /* must be and chain */
+ str = pool_dep2str(pool, rd->evr);
+ for (;;)
+ {
+ id = rd->name;
+ if (!ISRELDEP(id))
+ break;
+ rd = GETRELDEP(pool, id);
+ if (rd->flags != REL_AND)
+ break;
+ str = pool_tmpjoin(pool, pool_dep2str(pool, rd->evr), ":", str);
+ }
+ str = pool_tmpjoin(pool, pool_dep2str(pool, id), ":", str);
+ str = pool_tmpjoin(pool, "packageand(", str, ")");
+ }
+ }
+ else if (rd->flags >= 8)
+ continue;
+ }
+ }
if (skey == SOLVABLE_REQUIRES)
{
if (id == SOLVABLE_PREREQMARKER)
(void)hv_store(hv, key, keyl, newRV_noinc((SV*)av), 0);
}
-static int
-data2pkg(Repo *repo, Repodata *data, HV *hv, int isdod)
+void
+data2solvables(Repo *repo, Repodata *data, HV *rhv)
{
Pool *pool = repo->pool;
- char *str;
+ SV *sv;
+ HV *hv;
+ char *str, *key;
+ I32 keyl;
Id p;
Solvable *s;
- AV *av;
- str = hvlookupstr(hv, "name", 4);
- if (!str)
- return 0; /* need to have a name */
- p = repo_add_solvable(repo);
- s = pool_id2solvable(pool, p);
- s->name = pool_str2id(pool, str, 1);
- str = hvlookupstr(hv, "arch", 4);
- if (!str)
- str = ""; /* dummy, need to have arch */
- s->arch = pool_str2id(pool, str, 1);
- s->evr = makeevr(pool, hvlookupstr(hv, "epoch", 5), hvlookupstr(hv, "version", 7), hvlookupstr(hv, "release", 7));
- str = hvlookupstr(hv, "path", 4);
- if (str)
+ hv_iterinit(rhv);
+ while ((sv = hv_iternextsv(rhv, &key, &keyl)) != 0)
{
- char *ss = strrchr(str, '/');
- if (ss)
+ if (!SvROK(sv) || SvTYPE(SvRV(sv)) != SVt_PVHV)
+ continue;
+ hv = (HV *)SvRV(sv);
+ str = hvlookupstr(hv, "name", 4);
+ if (!str)
+ continue; /* need to have a name */
+ p = repo_add_solvable(repo);
+ s = pool_id2solvable(pool, p);
+ s->name = pool_str2id(pool, str, 1);
+ str = hvlookupstr(hv, "arch", 4);
+ if (!str)
+ str = ""; /* dummy, need to have arch */
+ s->arch = pool_str2id(pool, str, 1);
+ s->evr = makeevr(pool, hvlookupstr(hv, "epoch", 5), hvlookupstr(hv, "version", 7), hvlookupstr(hv, "release", 7));
+ str = hvlookupstr(hv, "path", 4);
+ if (str)
{
- *ss = 0;
- repodata_set_str(data, p, SOLVABLE_MEDIADIR, str);
- *ss++ = '/';
+ char *ss = strrchr(str, '/');
+ if (ss)
+ {
+ *ss = 0;
+ repodata_set_str(data, p, SOLVABLE_MEDIADIR, str);
+ *ss++ = '/';
+ }
+ else
+ ss = str;
+ repodata_set_str(data, p, SOLVABLE_MEDIAFILE, ss);
}
- else
- ss = str;
- repodata_set_str(data, p, SOLVABLE_MEDIAFILE, ss);
- }
- if (isdod)
- repodata_set_str(data, p, buildservice_id, "dod");
- else
- {
str = hvlookupstr(hv, "id", 2);
if (str)
repodata_set_str(data, p, buildservice_id, str);
- }
- str = hvlookupstr(hv, "source", 6);
- if (str)
- repodata_set_poolstr(data, p, SOLVABLE_SOURCENAME, str);
- if (isdod)
- {
- static unsigned char dod_pkgid[16] = { 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd0 };
- repodata_set_bin_checksum(data, p, SOLVABLE_PKGID, REPOKEY_TYPE_MD5, dod_pkgid);
- }
- else
- {
+ str = hvlookupstr(hv, "source", 6);
+ if (str)
+ repodata_set_poolstr(data, p, SOLVABLE_SOURCENAME, str);
str = hvlookupstr(hv, "hdrmd5", 6);
if (str && strlen(str) == 32)
repodata_set_checksum(data, p, SOLVABLE_PKGID, REPOKEY_TYPE_MD5, str);
- }
- s->provides = importdeps(hv, "provides", 8, repo);
- s->obsoletes = importdeps(hv, "obsoletes", 9, repo);
- s->conflicts = importdeps(hv, "conflicts", 9, repo);
- s->requires = importdeps(hv, "requires", 8, repo);
- s->recommends = importdeps(hv, "recommends", 10, repo);
- s->suggests = importdeps(hv, "suggests", 8, repo);
- s->supplements = importdeps(hv, "supplements", 11, repo);
- s->enhances = importdeps(hv, "enhances", 8, repo);
- if (!s->evr && s->provides)
- {
- /* look for self provides */
- Id pro, *prop = s->repo->idarraydata + s->provides;
- while ((pro = *prop++) != 0)
- {
- Reldep *rd;
- if (!ISRELDEP(pro))
- continue;
- rd = GETRELDEP(pool, pro);
- if (rd->name == s->name && rd->flags == REL_EQ)
- s->evr = rd->evr;
- }
- }
- if (s->evr && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
- s->provides = repo_addid_dep(repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
- str = hvlookupstr(hv, "checksum", 8);
- if (str)
- {
- char *cp, typebuf[8];
- Id ctype;
- if (*str != ':' && (cp = strchr(str, ':')) != 0 && cp - str < sizeof(typebuf))
- {
- strncpy(typebuf, str, cp - str);
- typebuf[cp - str] = 0;
- ctype = solv_chksum_str2type(typebuf);
- if (ctype)
- repodata_set_checksum(data, p, SOLVABLE_CHECKSUM, ctype, cp + 1);
- }
- }
- str = hvlookupstr(hv, "annotation", 10);
- if (str && strlen(str) < 100000)
- repodata_set_str(data, p, buildservice_annotation, str);
- av = hvlookupav(hv, "modules", 7);
- if (av)
- {
- SSize_t i;
- for (i = 0; i <= av_len(av); i++)
- {
- char *str = avlookupstr(av, i);
- repodata_add_idarray(data, p, buildservice_modules, pool_str2id(pool, str, 1));
- }
- }
- return p;
-}
-
-static void
-data2solvables(Repo *repo, Repodata *data, SV *rsv, int isdod)
-{
- AV *rav = 0;
- SSize_t ravi = 0;
- HV *rhv = 0;
- SV *sv;
- char *key;
- I32 keyl;
-
- if (SvTYPE(rsv) == SVt_PVAV)
- rav = (AV *)rsv;
- else
- rhv = (HV *)rsv;
-
- if (rhv)
- hv_iterinit(rhv);
- for (;;)
- {
- if (rhv)
- {
- sv = hv_iternextsv(rhv, &key, &keyl);
- if (!sv)
- break;
- }
- else
- {
- SV **svp;
- if (ravi > av_len(rav))
- break;
- svp = av_fetch(rav, ravi++, 0);
- if (!svp || !*svp)
- continue;
- sv = *svp;
+ s->provides = importdeps(hv, "provides", 8, repo);
+ s->obsoletes = importdeps(hv, "obsoletes", 9, repo);
+ s->conflicts = importdeps(hv, "conflicts", 9, repo);
+ s->requires = importdeps(hv, "requires", 8, repo);
+ s->recommends = importdeps(hv, "recommends", 10, repo);
+ s->suggests = importdeps(hv, "suggests", 8, repo);
+ s->supplements = importdeps(hv, "supplements", 11, repo);
+ s->enhances = importdeps(hv, "enhances", 8, repo);
+ if (!s->evr && s->provides)
+ {
+ /* look for self provides */
+ Id pro, *prop = s->repo->idarraydata + s->provides;
+ while ((pro = *prop++) != 0)
+ {
+ Reldep *rd;
+ if (!ISRELDEP(pro))
+ continue;
+ rd = GETRELDEP(pool, pro);
+ if (rd->name == s->name && rd->flags == REL_EQ)
+ s->evr = rd->evr;
+ }
}
- if (!SvROK(sv) || SvTYPE(SvRV(sv)) != SVt_PVHV)
- continue;
- data2pkg(repo, data, (HV *)SvRV(sv), isdod);
- }
-
- /* set meta information */
- repodata_set_str(data, SOLVID_META, buildservice_repocookie, REPOCOOKIE);
- if (rhv)
- {
- char *str;
- AV *av;
- str = hvlookupstr(rhv, "/url", 4);
+ if (s->evr)
+ s->provides = repo_addid_dep(repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
+ str = hvlookupstr(hv, "checksum", 8);
if (str)
- repodata_set_str(data, SOLVID_META, buildservice_dodurl, str);
- str = hvlookupstr(rhv, "/dodcookie", 10);
- if (str)
- repodata_set_str(data, SOLVID_META, buildservice_dodcookie, str);
- av = hvlookupav(rhv, "/dodresources", 13);
- if (av)
{
- SSize_t i;
- for (i = 0; i <= av_len(av); i++)
+ char *cp, typebuf[8];
+ Id ctype;
+ if (*str != ':' && (cp = strchr(str, ':')) != 0 && cp - str < sizeof(typebuf))
{
- Id id = pool_str2id(repo->pool, avlookupstr(av, i), 1);
- repodata_add_idarray(data, SOLVID_META, buildservice_dodresources, id);
+ strncpy(typebuf, str, cp - str);
+ typebuf[cp - str] = 0;
+ ctype = solv_chksum_str2type(typebuf);
+ if (ctype)
+ repodata_set_checksum(data, p, SOLVABLE_CHECKSUM, ctype, cp + 1);
}
}
}
+
+ repodata_set_str(data, SOLVID_META, buildservice_repocookie, REPOCOOKIE);
+ str = hvlookupstr(rhv, "/url", 4);
+ if (str)
+ repodata_set_str(data, SOLVID_META, buildservice_dodurl, str);
+ str = hvlookupstr(rhv, "/dodcookie", 10);
+ if (str)
+ repodata_set_str(data, SOLVID_META, buildservice_dodcookie, str);
}
static SV *
return sv;
}
-#define CPLXDEPS_TODNF (1 << 0)
-
-static int
-invert_depblocks(ExpanderCtx *xpctx, Queue *bq, int start, int r)
+static void
+expander_dbg(Expander *xp, const char *format, ...)
{
- int i, j, end;
- if (r == 0 || r == 1)
- return r ? 0 : 1;
- end = bq->count;
- for (i = j = start; i < end; i++)
+ va_list args;
+ char buf[1024];
+ int l;
+ if (!xp->debug)
+ return;
+ va_start(args, format);
+ vsnprintf(buf, sizeof(buf), format, args);
+ va_end(args);
+ printf("%s", buf);
+ l = strlen(buf);
+ if (buf[0] != ' ' || (l && buf[l - 1] == '\n'))
+ fflush(stdout);
+ if (l >= xp->debugstrf) /* >= because of trailing \0 */
{
- if (bq->elements[i])
- {
- bq->elements[i] = -bq->elements[i];
- continue;
- }
- /* end of block reached, reverse */
- if (i - 1 > j)
- {
- int k;
- for (k = i - 1; j < k; j++, k--)
- {
- Id t = bq->elements[j];
- bq->elements[j] = bq->elements[k];
- bq->elements[k] = t;
- }
- }
- j = i + 1;
+ xp->debugstr = solv_realloc(xp->debugstr, xp->debugstrl + l + 1024);
+ xp->debugstrf = l + 1024;
}
- return -1;
+ strcpy(xp->debugstr + xp->debugstrl, buf);
+ xp->debugstrl += l;
+ xp->debugstrf -= l;
}
-static int
-distribute_depblocks(ExpanderCtx *xpctx, Queue *bq, int start, int start2, int flags)
+static const char *
+expander_solvid2name(Expander *xp, Id p)
+{
+ const char *n = pool_id2str(xp->pool, xp->pool->solvables[p].name);
+ Repo *r;
+ if (!xp->debug)
+ return n;
+ r = xp->pool->solvables[p].repo;
+ if (!r)
+ return n;
+ return pool_tmpjoin(xp->pool, n, "@", r->name);
+}
+
+static inline void
+expander_installed(Expander *xp, Id p, Map *installed, Map *conflicts, Queue *conflictsinfo, int *cidone, Queue *out, Queue *todo)
{
- int i, j, end2 = bq->count;
- for (i = start; i < start2; i++)
+ Pool *pool = xp->pool;
+ Solvable *s = pool->solvables + p;
+ Id req, id, *reqp, con, *conp;
+ const char *n;
+
+ MAPSET(installed, p);
+ queue_push(out, p);
+ if (MAPTST(&xp->conflicts, s->name))
{
- for (j = start2; j < end2; j++)
+ int i;
+ for (i = 0; i < xp->conflictsq.count; i++)
{
- int a, b;
- int bqcnt4 = bq->count;
- int k = i;
-
- /* distribute i block with j block, both blocks are sorted */
- while (bq->elements[k] && bq->elements[j])
+ Id p2, pp2;
+ Id id = xp->conflictsq.elements[i];
+ if (id != s->name)
+ continue;
+ id = xp->conflictsq.elements[i ^ 1];
+ FOR_PROVIDES(p2, pp2, id)
{
- if (bq->elements[k] < bq->elements[j])
- queue_push(bq, bq->elements[k++]);
- else
+ if (pool->solvables[p2].name == id)
{
- if (bq->elements[k] == bq->elements[j])
- k++;
- queue_push(bq, bq->elements[j++]);
+ MAPEXP(conflicts, pool->nsolvables);
+ MAPSET(conflicts, p2);
}
}
- while (bq->elements[j])
- queue_push(bq, bq->elements[j++]);
- while (bq->elements[k])
- queue_push(bq, bq->elements[k++]);
-
- /* block is finished, check for A + -A */
- for (a = bqcnt4, b = bq->count - 1; a < b; )
- {
- if (-bq->elements[a] == bq->elements[b])
- break;
- if (-bq->elements[a] > bq->elements[b])
- a++;
- else
- b--;
- }
- if (a < b)
- queue_truncate(bq, bqcnt4); /* ignore this block */
- else
- queue_push(bq, 0); /* finish block */
}
- /* advance to next block */
- while (bq->elements[i])
- i++;
- }
- queue_deleten(bq, start, end2 - start);
- if (start == bq->count)
- return flags & CPLXDEPS_TODNF ? 0 : 1;
- return -1;
-}
-
-#if 0
-static void
-print_depblocks(ExpanderCtx *xpctx, Queue *bq, int start, int r)
-{
- Pool *pool = xpctx->pool;
- int i;
-
- if (r == 0)
- {
- printf("[NONE]\n");
- return;
}
- if (r == 1)
+ if (s->requires)
{
- printf("[ALL]\n");
- return;
+ reqp = s->repo->idarraydata + s->requires;
+ while ((req = *reqp++) != 0)
+ {
+ if (req == SOLVABLE_PREREQMARKER)
+ continue;
+ id = id2name(pool, req);
+ if (!xp->ignoreignore)
+ {
+ if (MAPTST(&xp->ignored, id))
+ continue;
+ if (MAPTST(&xp->ignoredx, id))
+ {
+ Id xid = pool_str2id(pool, pool_tmpjoin(pool, pool_id2str(pool, s->name), ":", pool_id2str(pool, id)), 0);
+ if (xid && MAPTST(&xp->ignored, xid))
+ continue;
+ }
+ }
+ n = pool_id2str(pool, id);
+ if (!strncmp(n, "rpmlib(", 7))
+ {
+ MAPEXP(&xp->ignored, id);
+ MAPSET(&xp->ignored, id);
+ continue;
+ }
+ if (*n == '/')
+ {
+ if (!xp->havefileprovides || pool->whatprovides[id] <= 1)
+ {
+ MAPEXP(&xp->ignored, id);
+ MAPSET(&xp->ignored, id);
+ continue;
+ }
+ }
+ queue_push2(todo, req, p);
+ }
}
- for (i = start; i < bq->count; i++)
- {
- if (bq->elements[i] > 0)
- printf(" %s", pool_solvid2str(pool, bq->elements[i]));
- else if (bq->elements[i] < 0)
- printf(" -%s", pool_solvid2str(pool, -bq->elements[i]));
- else
- printf(" ||");
- }
- printf("\n");
-}
-#endif
-
-
-static int
-pool_is_complex_dep_rd(Pool *pool, Reldep *rd)
-{
- for (;;)
- {
- if (rd->flags == REL_AND || rd->flags == REL_COND || rd->flags == REL_UNLESS) /* those are the complex ones */
- return 1;
- if (rd->flags != REL_OR)
- return 0;
- if (ISRELDEP(rd->name) && pool_is_complex_dep_rd(pool, GETRELDEP(pool, rd->name)))
- return 1;
- if (!ISRELDEP(rd->evr))
- return 0;
- rd = GETRELDEP(pool, rd->evr);
- }
-}
-
-static inline int
-pool_is_complex_dep(Pool *pool, Id dep)
-{
- if (ISRELDEP(dep))
- {
- Reldep *rd = GETRELDEP(pool, dep);
- if (rd->flags >= 8 && pool_is_complex_dep_rd(pool, rd))
- return 1;
- }
- return 0;
-}
-
-static int normalize_dep(ExpanderCtx *xpctx, Id dep, Queue *bq, int flags);
-
-static int
-normalize_dep_or(ExpanderCtx *xpctx, Id dep1, Id dep2, Queue *bq, int flags, int invflags)
-{
- int r1, r2, bqcnt2, bqcnt = bq->count;
- r1 = normalize_dep(xpctx, dep1, bq, flags);
- if (r1 == 1)
- return 1; /* early exit */
- bqcnt2 = bq->count;
- r2 = normalize_dep(xpctx, dep2, bq, flags ^ invflags);
- if (invflags)
- r2 = invert_depblocks(xpctx, bq, bqcnt2, r2);
- if (r1 == 1 || r2 == 1)
- {
- queue_truncate(bq, bqcnt);
- return 1;
- }
- if (r1 == 0)
- return r2;
- if (r2 == 0)
- return r1;
- if ((flags & CPLXDEPS_TODNF) == 0)
- return distribute_depblocks(xpctx, bq, bqcnt, bqcnt2, flags);
- return -1;
-}
-
-static int
-normalize_dep_and(ExpanderCtx *xpctx, Id dep1, Id dep2, Queue *bq, int flags, int invflags)
-{
- int r1, r2, bqcnt2, bqcnt = bq->count;
- r1 = normalize_dep(xpctx, dep1, bq, flags);
- if (r1 == 0)
- return 0; /* early exit */
- bqcnt2 = bq->count;
- r2 = normalize_dep(xpctx, dep2, bq, flags ^ invflags);
- if (invflags)
- r2 = invert_depblocks(xpctx, bq, bqcnt2, r2);
- if (r1 == 0 || r2 == 0)
- {
- queue_truncate(bq, bqcnt);
- return 0;
- }
- if (r1 == 1)
- return r2;
- if (r2 == 1)
- return r1;
- if ((flags & CPLXDEPS_TODNF) != 0)
- return distribute_depblocks(xpctx, bq, bqcnt, bqcnt2, flags);
- return -1;
-}
-
-static int
-normalize_dep_if_else(ExpanderCtx *xpctx, Id dep1, Id dep2, Id dep3, Queue *bq, int flags)
-{
- /* A IF (B ELSE C) -> (A OR ~B) AND (C OR B) */
- int r1, r2, bqcnt2, bqcnt = bq->count;
- r1 = normalize_dep_or(xpctx, dep1, dep2, bq, flags, CPLXDEPS_TODNF);
- if (r1 == 0)
- return 0; /* early exit */
- bqcnt2 = bq->count;
- r2 = normalize_dep_or(xpctx, dep2, dep3, bq, flags, 0);
- if (r1 == 0 || r2 == 0)
- {
- queue_truncate(bq, bqcnt);
- return 0;
- }
- if (r1 == 1)
- return r2;
- if (r2 == 1)
- return r1;
- if ((flags & CPLXDEPS_TODNF) != 0)
- return distribute_depblocks(xpctx, bq, bqcnt, bqcnt2, flags);
- return -1;
-}
-
-static int
-normalize_dep_unless_else(ExpanderCtx *xpctx, Id dep1, Id dep2, Id dep3, Queue *bq, int flags)
-{
- /* A UNLESS (B ELSE C) -> (A AND ~B) OR (C AND B) */
- int r1, r2, bqcnt2, bqcnt = bq->count;
- r1 = normalize_dep_and(xpctx, dep1, dep2, bq, flags, CPLXDEPS_TODNF);
- if (r1 == 1)
- return 1; /* early exit */
- bqcnt2 = bq->count;
- r2 = normalize_dep_and(xpctx, dep2, dep3, bq, flags, 0);
- if (r1 == 1 || r2 == 1)
- {
- queue_truncate(bq, bqcnt);
- return 1;
- }
- if (r1 == 0)
- return r2;
- if (r2 == 0)
- return r1;
- if ((flags & CPLXDEPS_TODNF) == 0)
- return distribute_depblocks(xpctx, bq, bqcnt, bqcnt2, flags);
- return -1;
-}
-
-static int expander_isignored(Expander *xp, Solvable *s, Id req);
-
-static int
-normalize_dep(ExpanderCtx *xpctx, Id dep, Queue *bq, int flags)
-{
- Pool *pool = xpctx->pool;
- Id p, dp;
-
- if (pool_is_complex_dep(pool, dep))
- {
- Reldep *rd = GETRELDEP(pool, dep);
- if (rd->flags == REL_COND)
- {
- Id evr = rd->evr;
- if (ISRELDEP(evr))
- {
- Reldep *rd2 = GETRELDEP(pool, evr);
- if (rd2->flags == REL_ELSE)
- return normalize_dep_if_else(xpctx, rd->name, rd2->name, rd2->evr, bq, flags);
- }
- return normalize_dep_or(xpctx, rd->name, rd->evr, bq, flags, CPLXDEPS_TODNF);
- }
- if (rd->flags == REL_UNLESS)
- {
- Id evr = rd->evr;
- if (ISRELDEP(evr))
- {
- Reldep *rd2 = GETRELDEP(pool, evr);
- if (rd2->flags == REL_ELSE)
- return normalize_dep_unless_else(xpctx, rd->name, rd2->name, rd2->evr, bq, flags);
- }
- return normalize_dep_and(xpctx, rd->name, rd->evr, bq, flags, CPLXDEPS_TODNF);
- }
- if (rd->flags == REL_OR)
- return normalize_dep_or(xpctx, rd->name, rd->evr, bq, flags, 0);
- if (rd->flags == REL_AND)
- return normalize_dep_and(xpctx, rd->name, rd->evr, bq, flags, 0);
- }
-
- if (xpctx->ignore_s && (flags & CPLXDEPS_TODNF) == 0)
- {
- if (expander_isignored(xpctx->xp, xpctx->ignore_s, dep))
- return 1;
- }
-
- dp = pool_whatprovides(pool, dep);
- if (dp == 2)
- return 1;
- if (dp < 2 || !pool->whatprovidesdata[dp])
- return 0;
- if (pool->whatprovidesdata[dp] == SYSTEMSOLVABLE)
- return 1;
- if ((flags & CPLXDEPS_TODNF) != 0)
- {
- while ((p = pool->whatprovidesdata[dp++]) != 0)
- queue_push2(bq, p, 0);
- }
- else
- {
- while ((p = pool->whatprovidesdata[dp++]) != 0)
- queue_push(bq, p);
- queue_push(bq, 0);
- }
- return -1;
-}
-
-#define ISCPLX(pool, d) (ISRELDEP(d) && GETRELID(d) >= pool->nrels)
-#define GETCPLX(pool, d) (GETRELID(d) - pool->nrels)
-#define MAKECPLX(pool, d) (MAKERELDEP(pool->nrels + d))
-
-#define DEPTYPE_REQUIRES 0
-#define DEPTYPE_CONFLICTS 1
-#define DEPTYPE_OBSOLETES 2
-#define DEPTYPE_RECOMMENDS 3
-#define DEPTYPE_PROVIDES 4
-
-#define ERROR_NOPROVIDER 1
-#define ERROR_CHOICE 2
-#define ERROR_CONFLICTINGPROVIDERS 3
-#define ERROR_PROVIDERINFO 4
-#define ERROR_PROVIDERINFO2 5
-#define ERROR_BADDEPENDENCY 6
-#define ERROR_CONFLICT 7
-#define ERROR_CONFLICT2 8
-#define ERROR_ALLCONFLICT 9
-#define ERROR_NOPROVIDERINFO 10
-
-static void
-expander_dbg(Expander *xp, const char *format, ...)
-{
- va_list args;
- char buf[1024];
- int l;
-
- if (!xp->debug)
- return;
- va_start(args, format);
- vsnprintf(buf, sizeof(buf), format, args);
- va_end(args);
- l = strlen(buf);
- if ((xp->debug & (EXPANDER_DEBUG_ALL | EXPANDER_DEBUG_STDOUT)) != 0)
- {
- printf("%s", buf);
- if (buf[0] != ' ' || (l && buf[l - 1] == '\n'))
- fflush(stdout);
- }
- if ((xp->debug & (EXPANDER_DEBUG_ALL | EXPANDER_DEBUG_STR)) != 0)
- {
- if (l >= xp->debugstrf) /* >= because of trailing \0 */
- {
- xp->debugstr = solv_realloc(xp->debugstr, xp->debugstrl + l + 1024);
- xp->debugstrf = l + 1024;
- }
- strcpy(xp->debugstr + xp->debugstrl, buf);
- xp->debugstrl += l;
- xp->debugstrf -= l;
- }
-}
-
-static void
-expander_clrdbg(Expander *xp)
-{
- if (xp->debugstr)
- free(xp->debugstr);
- xp->debugstr = 0;
- xp->debugstrl = xp->debugstrf = 0;
-}
-
-static const char *
-expander_solvid2name(Expander *xp, Id p)
-{
- const char *n = pool_id2str(xp->pool, xp->pool->solvables[p].name);
- Repo *r;
- if (!xp->debug)
- return n;
- r = xp->pool->solvables[p].repo;
- if (!r)
- return n;
- return pool_tmpjoin(xp->pool, n, "@", r->name);
-}
-
-static const char *
-expander_solvid2str(Expander *xp, Id p)
-{
- const char *n = pool_solvid2str(xp->pool, p);
- Repo *r;
- if (!xp->debug)
- return n;
- r = xp->pool->solvables[p].repo;
- if (!r)
- return n;
- return pool_tmpjoin(xp->pool, n, "@", r->name);
-}
-
-static int
-pkgname_sort_cmp(const void *ap, const void *bp, void *dp)
-{
- Pool *pool = (Pool *)dp;
- Id a = *(Id *)ap;
- Id b = *(Id *)bp;
- return strcmp(pool_id2str(pool, pool->solvables[a].name), pool_id2str(pool, pool->solvables[b].name));
-}
-
-static int
-expander_isignored(Expander *xp, Solvable *s, Id req)
-{
- Pool *pool = xp->pool;
- Id id = id2name(pool, req);
- const char *n;
-
- if (!xp->ignoreignore)
- {
- if (MAPTST(&xp->ignored, id))
- return 1;
- if (MAPTST(&xp->ignoredx, id))
- {
- Id xid = pool_str2id(pool, pool_tmpjoin(pool, pool_id2str(pool, s->name), ":", pool_id2str(pool, id)), 0);
- if (xid && MAPTST(&xp->ignored, xid))
- return 1;
- }
- }
- n = pool_id2str(pool, id);
- if (!strncmp(n, "rpmlib(", 7))
- {
- MAPEXP(&xp->ignored, id);
- MAPSET(&xp->ignored, id);
- return 1;
- }
- if (*n == '/')
- {
- if (!xp->havefileprovides || pool->whatprovides[id] <= 1)
- {
- MAPEXP(&xp->ignored, id);
- MAPSET(&xp->ignored, id);
- return 1;
- }
- }
- return 0;
-}
-
-static int
-expander_to_cplxblks(ExpanderCtx *xpctx, Id p, Id dep, int deptype, Id *ptr)
-{
- int blkoff = xpctx->cplxblks.count;
- queue_push(&xpctx->cplxblks, p);
- queue_push(&xpctx->cplxblks, dep);
- queue_push(&xpctx->cplxblks, deptype);
- for (;;)
- {
- Id pp = *ptr++;
- queue_push(&xpctx->cplxblks, pp);
- if (!pp)
- break;
- }
- return blkoff;
-}
-
-static int
-expander_check_cplxblock(ExpanderCtx *xpctx, Id p, Id dep, int deptype, Id *ptr, int blkoff)
-{
- Pool *pool = xpctx->pool;
- int posn = 0, posi = 0, negn = 0, negi = 0;
- Id pp, *ptr2 = ptr;
- Id lastcon = 0;
-
- while ((pp = *ptr2++) != 0)
- {
- if (pp > 0)
- {
- posn++;
- if (MAPTST(&xpctx->installed, pp))
- posi++;
- }
- else
- {
- if (p == -pp)
- continue; /* ignore redundant self-entry */
- negn++;
- if (MAPTST(&xpctx->installed, -pp))
- negi++;
- else
- lastcon = -pp;
- }
- }
-#if 0
- printf("expander_check_cplxblock pos: %d,%d neg: %d,%d\n", posn, posi, negn, negi);
-#endif
- if (posi)
- return -1;
- if (!posn && deptype == DEPTYPE_RECOMMENDS)
- return -1;
- if (negi == negn)
- {
- /* all neg installed */
- if (posn)
- {
- /* posn > 0 and all neg installed, add to todo */
- if (blkoff < 0)
- blkoff = expander_to_cplxblks(xpctx, p, dep, deptype, ptr);
-#if 0
- printf("put on todo, blkoff = %d\n", blkoff);
-#endif
- queue_push2(&xpctx->todo, MAKECPLX(pool, blkoff), p);
- }
- else
- {
- /* no posn, conflict */
- for (ptr2 = ptr; (pp = *ptr2++) != 0; )
- {
- if (p == -pp)
- continue; /* ignore redundant self-entry */
- if (deptype == DEPTYPE_REQUIRES)
- {
- /* do not report a requires as conflicts */
- queue_push(&xpctx->errors, ERROR_NOPROVIDER);
- queue_push2(&xpctx->errors, dep, p);
- break;
- }
- queue_push(&xpctx->errors, ERROR_CONFLICT);
- queue_push2(&xpctx->errors, p, -pp);
- }
- }
- return -1;
- }
- else if (!posn && negn && negi == negn - 1)
- {
- /* add conflict */
-#if 0
- printf("add conflict %d %d\n", lastcon, p);
-#endif
- MAPEXP(&xpctx->conflicts, pool->nsolvables);
- MAPSET(&xpctx->conflicts, lastcon);
- if (p)
- queue_push2(&xpctx->conflictsinfo, lastcon, p); /* always do this for rich deps */
- return -1;
- }
- else
- {
-#ifdef DEBUG_COND
- printf("put/stay on cond queue, blkoff = %d\n", blkoff);
-#endif
- /* either posn > 0 and 1 neg not installed or more than 1 neg not installed */
- if (blkoff < 0)
- blkoff = expander_to_cplxblks(xpctx, p, dep, deptype, ptr);
- return blkoff;
- }
-}
-
-static void
-expander_installed_complexdep(ExpanderCtx *xpctx, Id p, Id dep, int deptype)
-{
- Queue *cplxq = &xpctx->cplxq;
- int r, i, start = cplxq->count, blkoff;
-
-#if 0
- printf("expander_installed_complexdep %s type %d\n", pool_dep2str(xpctx->pool, dep), deptype);
-#endif
- if (deptype == DEPTYPE_CONFLICTS)
- {
- r = normalize_dep(xpctx, dep, cplxq, CPLXDEPS_TODNF);
- r = invert_depblocks(xpctx, cplxq, start, r);
- }
- else
- r = normalize_dep(xpctx, dep, cplxq, 0);
-#if 0
- print_depblocks(xpctx, cplxq, start, r);
-#endif
- if (r == 1)
- return;
- if (r == 0)
- {
- if (deptype == DEPTYPE_CONFLICTS)
- {
- queue_push(&xpctx->errors, ERROR_ALLCONFLICT);
- queue_push2(&xpctx->errors, dep, p);
- }
- else if (deptype != DEPTYPE_RECOMMENDS)
- {
- queue_push(&xpctx->errors, ERROR_NOPROVIDER);
- queue_push2(&xpctx->errors, dep, p);
- }
- return;
- }
- while (start < cplxq->count)
- {
- /* find end */
- for (i = start; cplxq->elements[i] != 0; i++)
- ;
- blkoff = expander_check_cplxblock(xpctx, p, dep, deptype, cplxq->elements + start, -1);
- if (blkoff >= 0)
- {
- Pool *pool = xpctx->pool;
- Id p;
- MAPEXP(&xpctx->todo_condmap, pool->nsolvables);
- for (i = start; (p = cplxq->elements[i]) != 0; i++)
- if (p < 0)
- MAPSET(&xpctx->todo_condmap, -p);
- queue_push(&xpctx->todo_cond, blkoff);
- }
- start = i + 1;
- }
- queue_truncate(cplxq, start);
-}
-
-static int
-expander_checkconflicts_complexdep(ExpanderCtx *xpctx, Id p, Id dep, int deptype, int recorderrors)
-{
- Queue *cplxq = &xpctx->cplxq;
- int r, i, start = cplxq->count;
- Id pp;
- int ret = 0;
-
-#if 0
- printf("expander_checkconflicts_complexdep %s type %d\n", pool_dep2str(xpctx->pool, dep), deptype);
-#endif
- if (deptype == DEPTYPE_CONFLICTS)
- {
- r = normalize_dep(xpctx, dep, cplxq, CPLXDEPS_TODNF);
- r = invert_depblocks(xpctx, cplxq, start, r);
- }
- else
- r = normalize_dep(xpctx, dep, cplxq, 0);
-#if 0
- print_depblocks(xpctx, cplxq, start, r);
-#endif
- /* r == 0: conflict with everything. Ignore here, pick error up when package gets installed */
- if (r == 0 || r == 1)
- return 0;
- while (start < cplxq->count)
- {
- for (i = start; (pp = cplxq->elements[i]) != 0; i++)
- if (pp > 0 || (pp < 0 && !MAPTST(&xpctx->installed, -pp)))
- break;
- if (pp == 0)
- {
- /* no pos and all neg installed -> conflict */
- for (i = start; (pp = cplxq->elements[i]) != 0; i++)
- {
- pp = -cplxq->elements[i];
- if (recorderrors)
- {
- queue_push(&xpctx->errors, recorderrors == 2 ? ERROR_CONFLICT : ERROR_PROVIDERINFO);
- queue_push2(&xpctx->errors, p, pp);
- }
- else if (xpctx->xp->debug)
- {
- Pool *pool = xpctx->pool;
- expander_dbg(xpctx->xp, "ignoring provider %s because it conflicts with installed %s\n", pool_solvid2str(pool, p), pool_solvid2str(pool, pp));
- }
- ret = ret ? 1 : pp;
- }
- }
- for (; cplxq->elements[i] != 0; i++)
- ;
- start = i + 1;
- }
- queue_truncate(cplxq, start);
- return ret;
-}
-
-static void
-updateconflictsinfo(ExpanderCtx *xpctx)
-{
- int i;
- Pool *pool = xpctx->pool;
- Queue *out = xpctx->out;
- Queue *conflictsinfo = &xpctx->conflictsinfo;
-
- if (xpctx->ignoreconflicts)
- return;
- for (i = xpctx->cidone; i < out->count; i++)
- {
- Id p, p2, pp2;
- Id con, *conp;
- Solvable *s;
- p = out->elements[i];
- s = pool->solvables + p;
- /* keep in sync with expander_installed! */
- if (s->conflicts)
- {
- conp = s->repo->idarraydata + s->conflicts;
- while ((con = *conp++) != 0)
- {
- if (pool_is_complex_dep(pool, con))
- continue; /* already pushed */
- FOR_PROVIDES(p2, pp2, con)
- {
- if (p2 == p)
- continue;
- queue_push2(conflictsinfo, p2, p);
- }
- }
- }
- if (s->obsoletes)
- {
- conp = s->repo->idarraydata + s->obsoletes;
- while ((con = *conp++) != 0)
- {
- FOR_PROVIDES(p2, pp2, con)
- {
- if (p2 == p || !pool_match_nevr(pool, pool->solvables + p2, con))
- continue;
- queue_push2(conflictsinfo, p2, -p);
- }
- }
- }
- }
- xpctx->cidone = out->count;
-}
-
-static int
-findconflictsinfo(ExpanderCtx *xpctx, Id p, int recorderrors)
-{
- Queue *conflictsinfo = &xpctx->conflictsinfo;
- int i, ret = 0;
-
- if (xpctx->cidone < xpctx->out->count)
- updateconflictsinfo(xpctx);
-
- for (i = 0; i < conflictsinfo->count; i++)
- if (conflictsinfo->elements[i] == p)
- {
- ret = conflictsinfo->elements[i + 1];
- if (recorderrors)
- {
- queue_push(&xpctx->errors, recorderrors == 2 ? ERROR_CONFLICT2 : ERROR_PROVIDERINFO2);
- queue_push2(&xpctx->errors, p, ret);
- }
- else if (xpctx->xp->debug)
- {
- Pool *pool = xpctx->pool;
- expander_dbg(xpctx->xp, "ignoring provider %s because installed %s %s it\n", pool_solvid2str(pool, p), pool_solvid2str(pool, ret > 0 ? ret : -ret), ret > 0 ? "conflicts with" : "obsoletes");
- }
- }
- if (!ret)
- {
- /* conflict from our job, i.e. a !xxx dep */
- if (recorderrors)
- {
- queue_push(&xpctx->errors, recorderrors == 2 ? ERROR_CONFLICT2 : ERROR_PROVIDERINFO2);
- queue_push2(&xpctx->errors, p, 0);
- }
- else if (xpctx->xp->debug)
- {
- Pool *pool = xpctx->pool;
- expander_dbg(xpctx->xp, "ignoring conflicted provider %s\n", pool_solvid2str(pool, p));
- }
- }
- return ret;
-}
-
-
-static void
-recheck_conddeps(ExpanderCtx *xpctx)
-{
- int i;
- for (i = 0; i < xpctx->todo_cond.count; i++)
- {
- int blkoff = xpctx->todo_cond.elements[i];
-#ifdef DEBUG_COND
- printf("todo_cond %d\n", blkoff);
-#endif
- Id *ptr = xpctx->cplxblks.elements + blkoff;
- if (expander_check_cplxblock(xpctx, ptr[0], ptr[1], ptr[2], ptr + 3, blkoff) < 0)
- {
-#ifdef DEBUG_COND
- printf("remove no longer needed cond entry\n");
-#endif
- queue_delete(&xpctx->todo_cond, i);
- i--;
- }
- }
-}
-
-/* install a single package */
-static void
-expander_installed(ExpanderCtx *xpctx, Id p)
-{
- Pool *pool = xpctx->pool;
- Expander *xp = xpctx->xp;
- Solvable *s = pool->solvables + p;
- Id req, *reqp, con, *conp;
-
-#if 0
-printf("expander_installed %s\n", pool_solvid2str(pool, p));
-#endif
- MAPSET(&xpctx->installed, p);
- queue_push(xpctx->out, p);
-
- if (xpctx->conflicts.size && MAPTST(&xpctx->conflicts, p))
- findconflictsinfo(xpctx, p, 2);
-
- /* add synthetic conflicts from the project config */
- if (MAPTST(&xp->conflicts, s->name))
- {
- int i;
- for (i = 0; i < xp->conflictsq.count; i++)
- {
- Id p2, pp2;
- Id id = xp->conflictsq.elements[i];
- if (id != s->name)
- continue;
- id = xp->conflictsq.elements[i ^ 1];
- FOR_PROVIDES(p2, pp2, id)
- {
- if (pool->solvables[p2].name != id)
- continue;
- if (MAPTST(&xpctx->installed, p2))
- {
- queue_push(&xpctx->errors, ERROR_CONFLICT);
- queue_push2(&xpctx->errors, p, p2);
- continue;
- }
- MAPEXP(&xpctx->conflicts, pool->nsolvables);
- MAPSET(&xpctx->conflicts, p2);
- queue_push2(&xpctx->conflictsinfo, p2, p);
- }
- }
- }
-
- if (s->requires)
- {
- reqp = s->repo->idarraydata + s->requires;
- while ((req = *reqp++) != 0)
- {
- if (req == SOLVABLE_PREREQMARKER)
- continue;
- if (ISRELDEP(req) && GETRELDEP(pool, req)->flags == REL_ERROR)
- {
- queue_push(&xpctx->errors, ERROR_BADDEPENDENCY);
- queue_push2(&xpctx->errors, GETRELDEP(pool, req)->evr, p);
- continue;
- }
- if (pool_is_complex_dep(pool, req))
- {
- xpctx->ignore_s = s;
- expander_installed_complexdep(xpctx, p, req, DEPTYPE_REQUIRES);
- xpctx->ignore_s = 0;
- continue;
- }
- if (expander_isignored(xp, s, req))
- continue;
- queue_push2(&xpctx->todo, req, p);
- }
- }
- if (!xpctx->ignoreconflicts)
+ if (!xp->ignoreconflicts)
{
if (s->conflicts)
{
while ((con = *conp++) != 0)
{
Id p2, pp2;
- if (ISRELDEP(con) && GETRELDEP(pool, con)->flags == REL_ERROR)
- {
- queue_push(&xpctx->errors, ERROR_BADDEPENDENCY);
- queue_push2(&xpctx->errors, GETRELDEP(pool, con)->evr, p);
- continue;
- }
- if (pool_is_complex_dep(pool, con))
- {
- expander_installed_complexdep(xpctx, p, con, DEPTYPE_CONFLICTS);
- continue;
- }
FOR_PROVIDES(p2, pp2, con)
{
if (p2 == p)
continue;
- if (MAPTST(&xpctx->installed, p2))
- {
- queue_push(&xpctx->errors, ERROR_CONFLICT);
- queue_push2(&xpctx->errors, p, p2);
- continue;
- }
- MAPEXP(&xpctx->conflicts, pool->nsolvables);
- MAPSET(&xpctx->conflicts, p2);
+ MAPEXP(conflicts, pool->nsolvables);
+ MAPSET(conflicts, p2);
if (xp->debug)
- queue_push2(&xpctx->conflictsinfo, p2, p);
+ queue_push2(conflictsinfo, p2, p);
}
}
}
{
if (p2 == p || !pool_match_nevr(pool, pool->solvables + p2, con))
continue;
- if (MAPTST(&xpctx->installed, p2))
- {
- queue_push(&xpctx->errors, ERROR_CONFLICT);
- queue_push2(&xpctx->errors, p, -p2);
- continue;
- }
- MAPEXP(&xpctx->conflicts, pool->nsolvables);
- MAPSET(&xpctx->conflicts, p2);
+ MAPEXP(conflicts, pool->nsolvables);
+ MAPSET(conflicts, p2);
if (xp->debug)
- queue_push2(&xpctx->conflictsinfo, p2, -p);
+ queue_push2(conflictsinfo, p2, -p);
}
}
}
if (xp->debug)
- xpctx->cidone = xpctx->out->count;
+ *cidone = out->count;
}
- if (xpctx->todo_condmap.size && MAPTST(&xpctx->todo_condmap, p))
- recheck_conddeps(xpctx);
}
-/* same as expander_installed, but install multiple packages
- * in one block */
-static void
-expander_installed_multiple(ExpanderCtx *xpctx, Queue *toinstall)
-{
- int i, j, havecond = 0;
-
- /* unify */
- for (i = j = 0; i < toinstall->count; i++)
- {
- Id p = toinstall->elements[i];
- if (MAPTST(&xpctx->installed, p))
- continue; /* already seen */
- MAPSET(&xpctx->installed, p);
- toinstall->elements[j++] = p;
- if (xpctx->todo_condmap.size && MAPTST(&xpctx->todo_condmap, p))
- {
- havecond = 1;
- MAPCLR(&xpctx->todo_condmap, p); /* no longer needed */
- }
- }
- queue_truncate(toinstall, j);
-
- /* run conditionals first */
- if (havecond)
- recheck_conddeps(xpctx);
-
- if (!xpctx->errors.count)
- for (i = 0; i < toinstall->count; i++)
- expander_installed(xpctx, toinstall->elements[i]);
- queue_empty(toinstall);
-}
-
-static int
-expander_checkconflicts(ExpanderCtx *xpctx, Id p, Id *conflicts, int isobsoletes, int recorderrors)
+static inline int
+expander_checkconflicts(Expander *xp, Id p, Map *installed, Id *conflicts, int isobsoletes)
{
- Map *installed = &xpctx->installed;
- Pool *pool = xpctx->pool;
+ Pool *pool = xp->pool;
Id con, p2, pp2;
- int ret = 0;
- if (xpctx->ignoreconflicts)
+ if (xp->ignoreconflicts)
return 0;
while ((con = *conflicts++) != 0)
{
- if (!isobsoletes && pool_is_complex_dep(pool, con))
- {
- p2 = expander_checkconflicts_complexdep(xpctx, p, con, DEPTYPE_CONFLICTS, recorderrors);
- ret = ret ? 1 : p2;
- continue;
- }
FOR_PROVIDES(p2, pp2, con)
{
if (p == p2)
if (isobsoletes && !pool_match_nevr(pool, pool->solvables + p2, con))
continue;
if (MAPTST(installed, p2))
- {
- if (recorderrors)
- {
- queue_push(&xpctx->errors, recorderrors == 2 ? ERROR_CONFLICT : ERROR_PROVIDERINFO);
- queue_push2(&xpctx->errors, p, isobsoletes ? -p2 : p2);
- }
- else if (xpctx->xp->debug)
- {
- if (isobsoletes)
- expander_dbg(xpctx->xp, "ignoring provider %s because it obsoletes installed %s\n", pool_solvid2str(pool, p), pool_solvid2str(pool, p2));
- else
- expander_dbg(xpctx->xp, "ignoring provider %s because it conflicts with installed %s\n", pool_solvid2str(pool, p), pool_solvid2str(pool, p2));
- }
- ret = ret ? 1 : p2;
- }
+ return p2;
}
}
- return ret;
+ return 0;
}
static void
-expander_updaterecommendedmap(ExpanderCtx *xpctx)
+expander_updateconflictsinfo(Expander *xp, Queue *conflictsinfo, int *cidone, Queue *out)
{
- Pool *pool = xpctx->pool;
- Queue *out = xpctx->out;
- Map *recommended = &xpctx->recommended;
-
+ Pool *pool = xp->pool;
int i;
- Id p, pp, rec, *recp;
- for (i = xpctx->recdone; i < out->count; i++)
+ if (xp->ignoreconflicts)
+ return;
+ for (i = *cidone; i < out->count; i++)
{
+ Id p, p2, pp2;
+ Id con, *conp;
Solvable *s;
- s = pool->solvables + out->elements[i];
- if (s->recommends)
- {
- MAPEXP(recommended, pool->nsolvables);
- for (recp = s->repo->idarraydata + s->recommends; (rec = *recp++) != 0; )
- FOR_PROVIDES(p, pp, rec)
- MAPSET(recommended, p);
- }
- }
- xpctx->recdone = out->count;
-}
-
-static int
-expander_dep_fulfilled(ExpanderCtx *xpctx, Id dep)
-{
- Pool *pool = xpctx->pool;
- Id p, pp;
-
- if (ISRELDEP(dep))
- {
- Reldep *rd = GETRELDEP(pool, dep);
- if (rd->flags == REL_COND)
+ p = out->elements[i];
+ s = pool->solvables + p;
+ /* keep in sync with expander_installed! */
+ if (s->conflicts)
{
- if (ISRELDEP(rd->evr))
+ conp = s->repo->idarraydata + s->conflicts;
+ while ((con = *conp++) != 0)
{
- Reldep *rd2 = GETRELDEP(pool, rd->evr);
- if (rd2->flags == REL_ELSE)
+ FOR_PROVIDES(p2, pp2, con)
{
- if (expander_dep_fulfilled(xpctx, rd2->name))
- return expander_dep_fulfilled(xpctx, rd->name);
- return expander_dep_fulfilled(xpctx, rd2->evr);
+ if (p2 == p)
+ continue;
+ queue_push2(conflictsinfo, p2, p);
}
}
- if (expander_dep_fulfilled(xpctx, rd->name)) /* A OR ~B */
- return 1;
- return !expander_dep_fulfilled(xpctx, rd->evr);
}
- if (rd->flags == REL_UNLESS)
+ if (s->obsoletes)
{
- if (ISRELDEP(rd->evr))
+ conp = s->repo->idarraydata + s->obsoletes;
+ while ((con = *conp++) != 0)
{
- Reldep *rd2 = GETRELDEP(pool, rd->evr);
- if (rd2->flags == REL_ELSE)
+ FOR_PROVIDES(p2, pp2, con)
{
- if (!expander_dep_fulfilled(xpctx, rd2->name))
- return expander_dep_fulfilled(xpctx, rd->name);
- return expander_dep_fulfilled(xpctx, rd2->evr);
+ if (p2 == p || !pool_match_nevr(pool, pool->solvables + p2, con))
+ continue;
+ queue_push2(conflictsinfo, p2, -p);
}
}
- if (!expander_dep_fulfilled(xpctx, rd->name)) /* A AND ~B */
- return 0;
- return !expander_dep_fulfilled(xpctx, rd->evr);
- }
- if (rd->flags == REL_AND)
- {
- if (!expander_dep_fulfilled(xpctx, rd->name))
- return 0;
- return expander_dep_fulfilled(xpctx, rd->evr);
- }
- if (rd->flags == REL_OR)
- {
- if (expander_dep_fulfilled(xpctx, rd->name))
- return 1;
- return expander_dep_fulfilled(xpctx, rd->evr);
- }
- }
- FOR_PROVIDES(p, pp, dep)
- {
- if (MAPTST(&xpctx->installed, p))
- return 1;
- }
- return 0;
-}
-
-static int
-prune_neg_prefers(ExpanderCtx *xpctx, Id who, Id *e, int n)
-{
- Expander *xp = xpctx->xp;
- Pool *pool = xpctx->pool;
- Id whon = who ? pool->solvables[who].name : 0;
- int i, j;
- for (i = j = 0; i < n; i++)
- {
- Id p = e[i];
- Id pn = pool->solvables[p].name;
- if (MAPTST(&xp->preferneg, pn))
- continue;
- if (who && MAPTST(&xp->prefernegx, pn))
- {
- Id xid = pool_str2id(pool, pool_tmpjoin(pool, pool_id2str(pool, whon), ":", pool_id2str(pool, pn)), 0);
- if (xid && MAPTST(&xp->preferneg, xid))
- continue;
- }
- e[j++] = p;
- }
- return j ? j : n;
-}
-
-static int
-prune_pos_prefers(ExpanderCtx *xpctx, Id who, Id *e, int n, int domulti)
-{
- Expander *xp = xpctx->xp;
- Queue *pruneq = &xpctx->pruneq;
- Pool *pool = xpctx->pool;
- Id whon = who ? pool->solvables[who].name : 0;
- int i, j;
-
- if (pruneq->count)
- queue_empty(pruneq);
- for (i = j = 0; i < n; i++)
- {
- Id p = e[i];
- Id pn = pool->solvables[p].name;
- if (MAPTST(&xp->preferpos, pn))
- queue_push2(pruneq, pn, p);
- else if (who && MAPTST(&xp->preferposx, pn))
- {
- Id xid = pool_str2id(pool, pool_tmpjoin(pool, pool_id2str(pool, whon), ":", pool_id2str(pool, pn)), 0);
- if (xid && MAPTST(&xp->preferpos, xid))
- queue_push2(pruneq, xid, p);
- }
- }
- if (!pruneq->count)
- return n;
- if (pruneq->count > 2)
- {
- if (!domulti)
- return n;
- /* pos prefers are ordered, the first one wins */
- for (i = 0; i < xp->preferposq.count; i++)
- {
- Id xid = xp->preferposq.elements[i];
- for (j = 0; j < pruneq->count; j += 2)
- if (pruneq->elements[j] == xid)
- {
- e[0] = pruneq->elements[j + 1];
- return 1;
- }
}
}
- e[0] = pruneq->elements[1]; /* simple case, just one prefer */
- return 1;
-}
-
-static int
-prune_or_dep(ExpanderCtx *xpctx, Id dep, Id *e, int n)
-{
- Pool *pool = xpctx->pool;
- int i, j;
- Id p, pp;
-
- for (;;)
- {
- Reldep *rd = 0;
- if (ISRELDEP(dep))
- {
- rd = GETRELDEP(pool, dep);
- if (rd->flags != REL_OR)
- rd = 0;
- }
- if (rd)
- dep = rd->name;
- i = j = 0;
- /* both sets are ordered */
- FOR_PROVIDES(p, pp, dep)
- {
- if (p < e[i])
- continue;
- while (i < n && p > e[i])
- i++;
- if (i == n)
- break;
- if (p == e[i])
- e[j++] = p;
- }
- if (j)
- return j;
- if (rd)
- dep = rd->evr;
- else
- break;
- }
- return n;
-}
-
-static int
-prune_supplemented(ExpanderCtx *xpctx, Id *e, int n)
-{
- Pool *pool = xpctx->pool;
- int i, j;
- Id sup, *supp;
-
- for (i = j = 0; i < n; i++)
- {
- Id p = e[i];
- Solvable *s = pool->solvables + p;
- if (!s->supplements)
- continue;
- supp = s->repo->idarraydata + s->supplements;
- while ((sup = *supp++) != 0)
- if (expander_dep_fulfilled(xpctx, sup))
- break;
- if (sup)
- e[j++] = p;
- }
- return j ? j : n;
+ *cidone = out->count;
}
static void
-add_recommended_packages(ExpanderCtx *xpctx, Solvable *s)
+expander_updaterecommendedmap(Expander *xp, Map *recommended, int *recdone, Queue *out)
{
- Pool *pool = xpctx->pool;
+ Pool *pool = xp->pool;
+
+ int i;
Id p, pp, rec, *recp;
- for (recp = s->repo->idarraydata + s->recommends; (rec = *recp++) != 0; )
+ for (i = *recdone; i < out->count; i++)
{
- int haveone = 0;
- if (pool_is_complex_dep(pool, rec))
- {
- expander_installed_complexdep(xpctx, s - pool->solvables, rec, DEPTYPE_RECOMMENDS);
- continue;
- }
- FOR_PROVIDES(p, pp, rec)
- {
- if (MAPTST(&xpctx->installed, p))
- break;
- if (haveone)
- continue;
- if (xpctx->conflicts.size && MAPTST(&xpctx->conflicts, p))
- continue;
- if (pool->solvables[p].conflicts && expander_checkconflicts(xpctx, p, pool->solvables[p].repo->idarraydata + pool->solvables[p].conflicts, 0, 0) != 0)
- continue;
- if (pool->solvables[p].obsoletes && expander_checkconflicts(xpctx, p, pool->solvables[p].repo->idarraydata + pool->solvables[p].obsoletes, 1, 0) != 0)
- continue;
- haveone = 1;
- }
- if (p)
- continue; /* already fulfilled */
- if (haveone)
- queue_push2(&xpctx->todo, rec, s - pool->solvables);
+ Solvable *s;
+ s = pool->solvables + out->elements[i];
+ if (s->recommends)
+ {
+ MAPEXP(recommended, pool->nsolvables);
+ for (recp = s->repo->idarraydata + s->recommends; (rec = *recp++) != 0; )
+ FOR_PROVIDES(p, pp, rec)
+ MAPSET(recommended, p);
+ }
}
+ *recdone = out->count;
}
-static void
-expander_growmaps(Expander *xp)
+static inline int
+findconflictsinfo(Queue *conflictsinfo, Id p)
{
- Pool *pool = xp->pool;
- MAPEXP(&xp->ignored, pool->ss.nstrings);
- MAPEXP(&xp->ignoredx, pool->ss.nstrings);
- MAPEXP(&xp->preferpos, pool->ss.nstrings);
- MAPEXP(&xp->preferposx, pool->ss.nstrings);
- MAPEXP(&xp->preferneg, pool->ss.nstrings);
- MAPEXP(&xp->prefernegx, pool->ss.nstrings);
- MAPEXP(&xp->conflicts, pool->ss.nstrings);
-}
+ int i;
-static Id
-str2id_dup(Pool *pool, const char *str)
-{
- char buf[256];
- size_t l = strlen(str);
- if (l < 256) {
- memcpy(buf, str, l + 1);
- return pool_str2id(pool, buf, 1);
- } else {
- return pool_str2id(pool, pool_tmpjoin(pool, str, 0, 0), 1);
- }
+ for (i = 0; i < conflictsinfo->count; i++)
+ if (conflictsinfo->elements[i] == p)
+ return conflictsinfo->elements[i + 1];
+ return 0;
}
-static void
-add_noproviderinfo(ExpanderCtx *xpctx, Id dep, Id who)
-{
- Pool *pool = xpctx->pool;
- Reldep *rd, *prd;
- Id p, pp, prov, *provp;
- int nprovinfo;
+#define ERROR_NOPROVIDER 1
+#define ERROR_CHOICE 2
+#define ERROR_CONFLICTINGPROVIDER 3
+#define ERROR_CONFLICTINGPROVIDERS 4
+#define ERROR_PROVIDERINFO 5
+#define ERROR_PROVIDERINFO2 6
- if (xpctx->xp->debug)
- {
- if (who)
- expander_dbg(xpctx->xp, "nothing provides %s needed by %s\n", pool_dep2str(pool, dep), expander_solvid2str(xpctx->xp, who));
- else
- expander_dbg(xpctx->xp, "nothing provides %s\n", pool_dep2str(pool, dep));
- }
- if (!ISRELDEP(dep))
- return;
- rd = GETRELDEP(pool, dep);
- if (rd->flags >= 8 || ISRELDEP(rd->name) || ISRELDEP(rd->evr))
- return;
- nprovinfo = 0;
- FOR_PROVIDES(p, pp, rd->name)
- {
- Solvable *s = pool->solvables + p;
- if (!s->repo || !s->provides)
- continue;
- for (provp = s->repo->idarraydata + s->provides; (prov = *provp++) != 0; )
- {
- if (!ISRELDEP(prov))
- continue;
- prd = GETRELDEP(pool, prov);
- if (prd->name != rd->name || ISRELDEP(prd->evr))
- continue;
- queue_push(&xpctx->errors, ERROR_NOPROVIDERINFO);
- if (prd->name == s->name && prd->evr == s->evr)
- {
- if (xpctx->xp->debug)
- expander_dbg(xpctx->xp, "%s has version %s\n", expander_solvid2str(xpctx->xp, p), pool_id2str(pool, prd->evr));
- queue_push2(&xpctx->errors, prd->evr, 0);
- }
- else
- {
- if (xpctx->xp->debug)
- expander_dbg(xpctx->xp, "%s provides version %s\n", expander_solvid2str(xpctx->xp, p), pool_id2str(pool, prd->evr));
- queue_push2(&xpctx->errors, prd->evr, p);
- }
- if (++nprovinfo >= 4)
- return; /* only show the first 4 providers */
- }
- }
-}
-static int
-expander_expand(Expander *xp, Queue *in, Queue *indep, Queue *out, Queue *ignoreq, int options)
+int
+expander_expand(Expander *xp, Queue *in, Queue *out, Queue *inconfl)
{
- ExpanderCtx xpctx;
Pool *pool = xp->pool;
- Queue toinstall;
- Queue qq, choices;
+ Queue todo, errors, cerrors, qq, posfoundq;
+ Map installed;
+ Map conflicts;
+ Map recommended;
+ Queue conflictsinfo;
+ int cidone;
+ int recdone;
Solvable *s;
Id q, p, pp;
- int i, j, nerrors;
- int ti, tj, tc;
- Id todoid, id, who, whon;
- Id conflprovpc;
- int pass;
- Queue revertignore;
- int oldignoreignore = xp->ignoreignore;
- Map oldignored, oldignoredx;
- int ignoremapssaved = 0;
- int dorecstart = 0;
-
- memset(&xpctx, 0, sizeof(xpctx));
- xpctx.xp = xp;
- xpctx.pool = pool;
- xpctx.out = out;
- xpctx.ignoreignore = options & EXPANDER_OPTION_IGNOREIGNORE ? 1 : xp->ignoreignore;
- xpctx.ignoreconflicts = options & EXPANDER_OPTION_IGNORECONFLICTS ? 1 : xp->ignoreconflicts;
- xpctx.userecommendsforchoices = options & EXPANDER_OPTION_USERECOMMENDSFORCHOICES ? 1 : xp->userecommendsforchoices;
- xpctx.usesupplementsforchoices = options & EXPANDER_OPTION_USESUPPLEMENTSFORCHOICES ? 1 : xp->usesupplementsforchoices;
- xpctx.dorecommends = options & EXPANDER_OPTION_DORECOMMENDS ? 1 : xp->dorecommends;
- xpctx.dosupplements = options & EXPANDER_OPTION_DOSUPPLEMENTS ? 1 : xp->dosupplements;
- map_init(&xpctx.installed, pool->nsolvables);
- map_init(&xpctx.conflicts, 0);
- map_init(&xpctx.recommended, 0);
- queue_init(&xpctx.conflictsinfo);
- queue_init(&xpctx.todo);
- queue_init(&xpctx.todo_cond);
- map_init(&xpctx.todo_condmap, 0);
- queue_init(&xpctx.errors);
- queue_init(&xpctx.cplxq);
- queue_init(&xpctx.cplxblks);
- queue_init(&xpctx.pruneq);
-
- queue_init(&toinstall);
+ int i, j, nerrors, doamb, ambcnt;
+ Id id, who, whon, pn;
+ Id conflprov, conflprovpc;
+ int haverecommended = 0;
+ int haverecommended_done = 0;
+
+ map_init(&installed, pool->nsolvables);
+ map_init(&conflicts, 0);
+ map_init(&recommended, 0);
+ queue_init(&conflictsinfo);
+ queue_init(&todo);
queue_init(&qq);
- queue_init(&choices);
- queue_init(&revertignore);
+ queue_init(&errors);
+ queue_init(&cerrors);
+ queue_init(&posfoundq);
queue_empty(out);
-
- /* process ignored. hack: we mess with the ignore config in xp */
- xp->ignoreignore = 0;
- if (xpctx.ignoreignore && ignoreq->count)
- {
- /* bad: have direct ignores and we need to zero the project config ignores */
- oldignored = xp->ignored;
- oldignoredx = xp->ignoredx;
- ignoremapssaved = 1;
- /* clear project config maps */
- memset(&xp->ignored, 0, sizeof(xp->ignored));
- memset(&xp->ignoredx, 0, sizeof(xp->ignoredx));
- }
- if (ignoreq->count)
+ cidone = 0;
+ recdone = 0;
+ if (inconfl)
{
- /* mix direct ignores with ignores from project config */
- for (i = 0; i < ignoreq->count; i++)
+ for (i = 0; i < inconfl->count; i += 2)
{
- const char *ss;
- id = ignoreq->elements[i];
- MAPEXP(&xp->ignored, id);
- if (MAPTST(&xp->ignored, id))
- continue;
- MAPSET(&xp->ignored, id);
- queue_push(&revertignore, id);
- if ((ss = strchr(pool_id2str(pool, id), ':')) != 0)
+ Id con = inconfl->elements[i];
+ FOR_PROVIDES(p, pp, con)
{
- id = str2id_dup(pool, ss + 1);
- MAPEXP(&xp->ignoredx, id);
- if (MAPTST(&xp->ignoredx, id))
+ if (inconfl->elements[i + 1] && !pool_match_nevr(pool, pool->solvables + p, con))
continue;
- MAPSET(&xp->ignoredx, id);
- queue_push(&revertignore, -id);
- }
- }
- }
- else if (xpctx.ignoreignore)
- {
- /* no direct ignores, ignore project config ignores.
- * easy: just disable ignore processing */
- xp->ignoreignore = 1;
- }
-
- /* grow maps to make bit tests cheaper */
- expander_growmaps(xp);
-
- /* process standard dependencies */
- if (indep)
- {
- for (i = 0; i < indep->count; i += 2)
- {
- int deptype = indep->elements[i];
- Id dep = indep->elements[i + 1];
- if (ISRELDEP(dep) && GETRELDEP(pool, dep)->flags == REL_ERROR)
- {
- queue_push(&xpctx.errors, ERROR_BADDEPENDENCY);
- queue_push2(&xpctx.errors, GETRELDEP(pool, dep)->evr, 0);
- continue;
- }
- if ((deptype == DEPTYPE_REQUIRES || deptype == DEPTYPE_CONFLICTS) && pool_is_complex_dep(pool, dep))
- {
- expander_installed_complexdep(&xpctx, 0, dep, deptype);
- continue;
- }
- if (deptype == DEPTYPE_REQUIRES)
- {
- queue_push2(&xpctx.todo, dep, 0);
- }
- else if (deptype == DEPTYPE_CONFLICTS || deptype == DEPTYPE_OBSOLETES)
- {
- FOR_PROVIDES(p, pp, dep)
- {
- if (deptype == DEPTYPE_OBSOLETES && !pool_match_nevr(pool, pool->solvables + p, dep))
- continue;
- MAPEXP(&xpctx.conflicts, pool->nsolvables);
- MAPSET(&xpctx.conflicts, p);
- }
+ MAPEXP(&conflicts, pool->nsolvables);
+ MAPSET(&conflicts, p);
}
}
}
- /* process direct dependencies */
+ /* do direct expands */
for (i = 0; i < in->count; i++)
{
id = in->elements[i];
- if (ISRELDEP(id) && GETRELDEP(pool, id)->flags == REL_ERROR)
+ if (id == expander_directdepsend)
{
- queue_push(&xpctx.errors, ERROR_BADDEPENDENCY);
- queue_push2(&xpctx.errors, GETRELDEP(pool, id)->evr, 0);
- continue;
- }
- if (pool_is_complex_dep(pool, id))
- {
- expander_installed_complexdep(&xpctx, 0, id, DEPTYPE_REQUIRES);
- continue;
+ for (i = i + 1; i < in->count; i++)
+ if (in->elements[i] != expander_directdepsend)
+ queue_push2(&todo, in->elements[i], 0);
+ break;
}
q = 0;
FOR_PROVIDES(p, pp, id)
}
if (!q)
{
- queue_push2(&xpctx.todo, id, 0); /* unclear, resolve later */
+ /* unclear, resolve later */
+ queue_push2(&todo, id, 0);
continue;
}
- if (xp->debug)
- expander_dbg(xp, "added %s because of %s (direct dep)\n", expander_solvid2name(xp, q), pool_dep2str(pool, id));
- queue_push(&toinstall, q);
- }
-
- /* unify toinstall, check against conflicts */
- for (i = 0; i < toinstall.count; i++)
- {
- p = toinstall.elements[i];
- MAPSET(&xpctx.installed, p);
- }
- for (i = j = 0; i < toinstall.count; i++)
- {
- p = toinstall.elements[i];
- if (!MAPTST(&xpctx.installed, p))
+ if (MAPTST(&installed, q))
continue;
- MAPCLR(&xpctx.installed, p);
- toinstall.elements[j++] = p;
- }
- queue_truncate(&toinstall, j);
- if (xpctx.conflicts.size)
- {
- for (i = 0; i < toinstall.count; i++)
+ if (conflicts.size && MAPTST(&conflicts, q))
+ {
+ queue_push(&errors, ERROR_CONFLICTINGPROVIDER);
+ queue_push2(&errors, id, 0);
+ if (cidone < out->count)
+ expander_updateconflictsinfo(xp, &conflictsinfo, &cidone, out);
+ queue_push(&errors, ERROR_PROVIDERINFO2);
+ queue_push2(&errors, q, findconflictsinfo(&conflictsinfo, q));
+ continue;
+ }
+ if (pool->solvables[q].conflicts && (pp = expander_checkconflicts(xp, q, &installed, pool->solvables[q].repo->idarraydata + pool->solvables[q].conflicts, 0)) != 0)
{
- p = toinstall.elements[i];
- if (MAPTST(&xpctx.conflicts, p))
- findconflictsinfo(&xpctx, p, 2);
+ queue_push(&errors, ERROR_CONFLICTINGPROVIDER);
+ queue_push2(&errors, id, 0);
+ queue_push(&errors, ERROR_PROVIDERINFO);
+ queue_push2(&errors, q, pp);
+ continue;
}
- }
-
- /* here is the big expansion loop */
- pass = 0;
- while (!xpctx.errors.count)
- {
- if (toinstall.count)
+ if (pool->solvables[q].obsoletes && (pp = expander_checkconflicts(xp, q, &installed, pool->solvables[q].repo->idarraydata + pool->solvables[q].obsoletes, 1)) != 0)
{
- expander_installed_multiple(&xpctx, &toinstall);
- pass = 0;
+ queue_push(&errors, ERROR_CONFLICTINGPROVIDER);
+ queue_push2(&errors, id, 0);
+ queue_push(&errors, ERROR_PROVIDERINFO);
+ queue_push2(&errors, q, -pp);
continue;
}
-
- if (!xpctx.todo.count)
+ if (xp->debug)
+ expander_dbg(xp, "added %s because of %s (direct dep)\n", expander_solvid2name(xp, q), pool_dep2str(pool, id));
+ expander_installed(xp, q, &installed, &conflicts, &conflictsinfo, &cidone, out, &todo); /* unique match! */
+ }
+
+ doamb = 0;
+ ambcnt = todo.count;
+ while (todo.count)
+ {
+ id = queue_shift(&todo);
+ who = queue_shift(&todo);
+ if (ambcnt == 0)
+ {
+ if (doamb >= 2)
+ break; /* amb pass had no progress, stop */
+ doamb = xp->userecommendsforchoices ? doamb + 1 : 3;
+ if (doamb == 1 && !haverecommended)
+ {
+ for (i = haverecommended_done; i < out->count; i++)
+ if (pool->solvables[out->elements[i]].recommends)
+ haverecommended = 1;
+ haverecommended_done = out->count;
+ if (!haverecommended)
+ doamb = 3;
+ }
+ if (xp->debug)
+ {
+ if (doamb == 2)
+ expander_dbg(xp, "now doing undecided dependencies with recommends\n");
+ else
+ expander_dbg(xp, "now doing undecided dependencies\n");
+ }
+ ambcnt = todo.count;
+ }
+ else
+ ambcnt -= 2;
+// printf("todo %s %s ambcnt %d\n", pool_id2str(pool, pool->solvables[who].name), pool_dep2str(pool, id), ambcnt);
+// fflush(stdout);
+ whon = who ? pool->solvables[who].name : 0;
+ queue_empty(&qq);
+ conflprov = 0;
+ conflprovpc = 0;
+ FOR_PROVIDES(p, pp, id)
{
- /* almost finished. now do weak deps if requested */
- pass = 0;
- if (xpctx.dorecommends)
+ Id pc;
+ if (MAPTST(&installed, p))
+ break;
+ if (who && !xp->ignoreignore)
{
- expander_dbg(xp, "--- now doing recommended packages\n");
- for (; dorecstart < out->count; dorecstart++)
+ Id pn = pool->solvables[p].name;
+ if (MAPTST(&xp->ignored, pn))
+ break;
+ if (MAPTST(&xp->ignoredx, pn))
{
- s = pool->solvables + out->elements[dorecstart];
- if (s->recommends)
- add_recommended_packages(&xpctx, s);
+ Id xid = pool_str2id(pool, pool_tmpjoin(pool, pool_id2str(pool, whon), ":", pool_id2str(pool, pn)), 0);
+ if (xid && MAPTST(&xp->ignored, xid))
+ break;
}
- if (xpctx.todo.count)
- continue;
}
- if (xpctx.dosupplements)
+ if (conflicts.size && MAPTST(&conflicts, p))
{
- Id sup, *supp;
- expander_dbg(xp, "--- now doing supplemented packages\n");
- for (p = 1; p < pool->nsolvables; p++)
+ if (xp->debug)
{
- s = pool->solvables + p;
- if (!s->supplements || !s->repo)
- continue;
- if (MAPTST(&xpctx.installed, p))
- continue;
- if (!pool_installable(pool, s))
- continue;
- if (xpctx.conflicts.size && MAPTST(&xpctx.conflicts, p))
- continue;
- if (s->conflicts && expander_checkconflicts(&xpctx, p, s->repo->idarraydata + s->conflicts, 0, 0) != 0)
- continue;
- if (s->obsoletes && expander_checkconflicts(&xpctx, p, s->repo->idarraydata + s->obsoletes, 1, 0) != 0)
- continue;
- supp = s->repo->idarraydata + s->supplements;
- while ((sup = *supp++) != 0)
- if (expander_dep_fulfilled(&xpctx, sup))
- break;
- if (!sup)
- continue;
- expander_dbg(xp, "added %s because it supplements %s\n", expander_solvid2name(xp, p), pool_dep2str(pool, sup));
- queue_push(&toinstall, p);
+ Id pc = findconflictsinfo(&conflictsinfo, p);
+ if (pc)
+ expander_dbg(xp, "ignoring provider %s of %s because installed %s %s it\n", pool_solvid2str(pool, p), pool_dep2str(pool, id), pool_solvid2str(pool, pc > 0 ? pc : -pc), pc > 0 ? "conflicts with" : "obsoletes");
+ else
+ expander_dbg(xp, "ignoring conflicted provider %s of %s\n", pool_solvid2str(pool, p), pool_dep2str(pool, id));
}
- if (toinstall.count)
- continue;
+ conflprov = conflprov ? 1 : p;
+ conflprovpc = 0;
+ continue;
}
- /* no new stuff to do, we're finished! */
- break;
- }
-
- expander_dbg(xp, "--- now doing normal dependencies\n");
-
- if (pass == 1)
- queue_empty(&choices);
-
- for (ti = tj = 0; ti < xpctx.todo.count; ti += 2)
- {
- int deptype = DEPTYPE_REQUIRES;
- todoid = id = xpctx.todo.elements[ti];
- who = xpctx.todo.elements[ti + 1];
- if (!id) /* deleted entry? */
- continue;
- queue_empty(&qq);
- if (ISCPLX(pool, id))
+ if (pool->solvables[p].conflicts && (pc = expander_checkconflicts(xp, p, &installed, pool->solvables[p].repo->idarraydata + pool->solvables[p].conflicts, 0)) != 0)
{
- pp = GETCPLX(pool, id); /* p, dep, deptype, ids... */
- id = xpctx.cplxblks.elements[pp + 1];
- deptype = xpctx.cplxblks.elements[pp + 2];
- pp += 3;
- while ((p = xpctx.cplxblks.elements[pp++]))
- if (p > 0)
- queue_push(&qq, p);
+ expander_dbg(xp, "ignoring provider %s of %s because it conflicts with installed %s\n", pool_solvid2str(pool, p), pool_dep2str(pool, id), pool_solvid2str(pool, pc));
+ conflprov = conflprov ? 1 : p;
+ conflprovpc = pc;
+ continue;
}
- else
+ if (pool->solvables[p].obsoletes && (pc = expander_checkconflicts(xp, p, &installed, pool->solvables[p].repo->idarraydata + pool->solvables[p].obsoletes, 1)) != 0)
{
- FOR_PROVIDES(p, pp, id)
- queue_push(&qq, p);
+ expander_dbg(xp, "ignoring provider %s of %s because it obsoletes installed %s\n", pool_solvid2str(pool, p), pool_dep2str(pool, id), pool_solvid2str(pool, pc));
+ conflprov = conflprov ? 1 : p;
+ conflprovpc = -pc;
+ continue;
}
-
- if (qq.count == 0)
+ queue_push(&qq, p);
+ }
+ if (p)
+ continue;
+ if (qq.count == 0)
+ {
+ if (!conflprov)
{
- if (deptype == DEPTYPE_RECOMMENDS)
- continue;
- queue_push(&xpctx.errors, ERROR_NOPROVIDER);
- queue_push2(&xpctx.errors, id, who);
- add_noproviderinfo(&xpctx, id, who);
+ queue_push(&errors, ERROR_NOPROVIDER);
+ queue_push2(&errors, id, who);
continue;
}
-
- /* check installed and ignores */
- whon = who ? pool->solvables[who].name : 0;
- for (i = 0; i < qq.count; i++)
+ /* more work for conflicts */
+ if (conflprov != 1)
{
- p = qq.elements[i];
- if (MAPTST(&xpctx.installed, p))
- break;
- if (who && deptype == DEPTYPE_REQUIRES && !xp->ignoreignore)
+ /* nice, just one provider */
+ queue_push(&errors, ERROR_CONFLICTINGPROVIDER);
+ queue_push2(&errors, id, who);
+ if (!conflprovpc)
{
- Id pn = pool->solvables[p].name;
- if (MAPTST(&xp->ignored, pn))
- break;
- if (MAPTST(&xp->ignoredx, pn))
- {
- Id xid = pool_str2id(pool, pool_tmpjoin(pool, pool_id2str(pool, whon), ":", pool_id2str(pool, pn)), 0);
- if (xid && MAPTST(&xp->ignored, xid))
- break;
- }
+ if (cidone < out->count)
+ expander_updateconflictsinfo(xp, &conflictsinfo, &cidone, out);
+ conflprovpc = findconflictsinfo(&conflictsinfo, conflprov);
+ queue_push(&errors, ERROR_PROVIDERINFO2);
+ queue_push2(&errors, conflprov, conflprovpc);
+ }
+ else
+ {
+ queue_push(&errors, ERROR_PROVIDERINFO);
+ queue_push2(&errors, conflprov, conflprovpc);
}
- }
- if (i < qq.count)
- continue; /* ignored dependency or fulfilled */
-
- if (pass == 0 && qq.count > 1)
- {
- xpctx.todo.elements[tj++] = todoid;
- xpctx.todo.elements[tj++] = who;
continue;
}
-
- /* do conflict pruning */
- conflprovpc = 0;
- for (i = j = 0; i < qq.count; i++)
+ /* even more work if all providers conflict */
+ queue_push(&errors, ERROR_CONFLICTINGPROVIDERS);
+ queue_push2(&errors, id, who);
+ if (cidone < out->count)
+ expander_updateconflictsinfo(xp, &conflictsinfo, &cidone, out);
+ FOR_PROVIDES(p, pp, id)
{
Id pc;
- p = qq.elements[i];
- if (xpctx.conflicts.size && MAPTST(&xpctx.conflicts, p))
- {
- if (xp->debug)
- findconflictsinfo(&xpctx, p, 0);
- conflprovpc = 0;
- continue;
- }
- if (pool->solvables[p].conflicts && (pc = expander_checkconflicts(&xpctx, p, pool->solvables[p].repo->idarraydata + pool->solvables[p].conflicts, 0, 0)) != 0)
+ if (conflicts.size && MAPTST(&conflicts, p))
{
- conflprovpc = pc;
+ pc = findconflictsinfo(&conflictsinfo, p);
+ queue_push(&errors, ERROR_PROVIDERINFO2);
+ queue_push2(&errors, p, pc);
continue;
}
- if (pool->solvables[p].obsoletes && (pc = expander_checkconflicts(&xpctx, p, pool->solvables[p].repo->idarraydata + pool->solvables[p].obsoletes, 1, 0)) != 0)
+ if (pool->solvables[p].conflicts && (pc = expander_checkconflicts(xp, p, &installed, pool->solvables[p].repo->idarraydata + pool->solvables[p].conflicts, 0)) != 0)
{
- conflprovpc = -pc;
+ queue_push(&errors, ERROR_PROVIDERINFO);
+ queue_push2(&errors, p, pc);
continue;
}
- qq.elements[j++] = p;
- }
- if (j == 0)
- {
- if (deptype == DEPTYPE_RECOMMENDS)
- continue;
- queue_push(&xpctx.errors, ERROR_CONFLICTINGPROVIDERS);
- queue_push2(&xpctx.errors, id, who);
- if (qq.count == 1 && conflprovpc != 1 && conflprovpc != -1)
+ if (pool->solvables[p].obsoletes && (pc = expander_checkconflicts(xp, p, &installed, pool->solvables[p].repo->idarraydata + pool->solvables[p].obsoletes, 1)) != 0)
{
- p = qq.elements[0];
- if (conflprovpc)
- {
- queue_push(&xpctx.errors, ERROR_PROVIDERINFO);
- queue_push2(&xpctx.errors, p, conflprovpc);
- continue;
- }
- findconflictsinfo(&xpctx, p, 1);
+ queue_push(&errors, ERROR_PROVIDERINFO);
+ queue_push2(&errors, p, -pc);
continue;
}
- /* even more work if all providers conflict */
- for (j = 0; j < qq.count; j++)
- {
- p = qq.elements[j];
- if (xpctx.conflicts.size && MAPTST(&xpctx.conflicts, p))
- findconflictsinfo(&xpctx, p, 1);
- if (pool->solvables[p].conflicts)
- expander_checkconflicts(&xpctx, p, pool->solvables[p].repo->idarraydata + pool->solvables[p].conflicts, 0, 1);
- if (pool->solvables[p].obsoletes)
- expander_checkconflicts(&xpctx, p, pool->solvables[p].repo->idarraydata + pool->solvables[p].obsoletes, 1, 1);
- }
- continue;
- }
- queue_truncate(&qq, j);
- if (qq.count == 1)
- {
- p = qq.elements[0];
- if (xp->debug)
- expander_dbg(xp, "added %s because of %s:%s\n", expander_solvid2name(xp, p), whon ? pool_id2str(pool, whon) : "(direct)", pool_dep2str(pool, id));
- queue_push(&toinstall, p);
- continue;
}
- /* pass is == 1 and we have multiple choices */
+ continue;
+ }
+ if (qq.count > 1 && !doamb)
+ {
+ /* try again later */
+ queue_push2(&todo, id, who);
if (xp->debug)
{
expander_dbg(xp, "undecided about %s:%s:", whon ? pool_id2str(pool, whon) : "(direct)", pool_dep2str(pool, id));
for (i = 0; i < qq.count; i++)
- expander_dbg(xp, " %s", expander_solvid2name(xp, qq.elements[i]));
- expander_dbg(xp, "\n");
+ expander_dbg(xp, " %s", expander_solvid2name(xp, qq.elements[i]));
+ expander_dbg(xp, "\n");
}
- queue_push2(&choices, qq.count + 3, id);
- queue_push(&choices, qq.count);
- queue_insertn(&choices, choices.count, qq.count, qq.elements);
- xpctx.todo.elements[tj++] = todoid;
- xpctx.todo.elements[tj++] = who;
- }
- queue_truncate(&xpctx.todo, tj);
-
- if (toinstall.count)
- continue;
-
- if (!xpctx.todo.count)
- continue;
-
- /* did not find a package to install, only choices left on todo list */
- if (pass == 0)
- {
- pass = 1; /* now do conflict pruning */
continue;
}
- expander_dbg(xp, "--- now doing undecided dependencies\n");
-
- /* prune prefers */
- for (ti = tc = 0; ti < xpctx.todo.count; ti += 2)
+ /* prune neg prefers */
+ if (qq.count > 1)
{
- Id who = xpctx.todo.elements[ti + 1];
- Id *qe = choices.elements + tc + 3;
- Id id = choices.elements[tc + 1];
- int qn = choices.elements[tc + 2];
- whon = who ? pool->solvables[who].name : 0;
- if (qn > 1)
- qn = prune_neg_prefers(&xpctx, who, qe, qn);
- if (qn > 1)
- qn = prune_pos_prefers(&xpctx, who, qe, qn, 0);
- if (qn == 1)
+ for (i = j = 0; i < qq.count; i++)
{
- p = qe[0];
- if (xp->debug)
- expander_dbg(xp, "added %s because of %s:%s\n", expander_solvid2name(xp, p), whon ? pool_id2str(pool, whon) : "(direct)", pool_dep2str(pool, id));
- queue_push(&toinstall, p);
- xpctx.todo.elements[ti] = 0; /* kill entry */
+ p = qq.elements[i];
+ pn = pool->solvables[p].name;
+ if (MAPTST(&xp->preferneg, pn))
+ continue;
+ if (who && MAPTST(&xp->prefernegx, pn))
+ {
+ Id xid = pool_str2id(pool, pool_tmpjoin(pool, pool_id2str(pool, whon), ":", pool_id2str(pool, pn)), 0);
+ if (xid && MAPTST(&xp->preferneg, xid))
+ continue;
+ }
+ qq.elements[j++] = p;
}
- choices.elements[tc + 2] = qn;
- tc += choices.elements[tc];
+ if (j)
+ queue_truncate(&qq, j);
}
- if (toinstall.count)
- continue;
- /* prune pos prefers with domulti and debian or */
- for (ti = tc = 0; ti < xpctx.todo.count; ti += 2)
+ /* prune pos prefers */
+ if (qq.count > 1)
{
- Id who = xpctx.todo.elements[ti + 1];
- Id *qe = choices.elements + tc + 3;
- Id id = choices.elements[tc + 1];
- int qn = choices.elements[tc + 2];
- whon = who ? pool->solvables[who].name : 0;
- if (qn > 1)
- qn = prune_pos_prefers(&xpctx, who, qe, qn, 1);
- if (qn > 1 && pool->disttype != DISTTYPE_RPM)
+ queue_empty(&posfoundq);
+ for (i = j = 0; i < qq.count; i++)
{
- if (ISRELDEP(id) && GETRELDEP(pool, id)->flags == REL_OR)
- qn = prune_or_dep(&xpctx, id, qe, qn);
+ p = qq.elements[i];
+ pn = pool->solvables[p].name;
+ if (MAPTST(&xp->preferpos, pn))
+ {
+ queue_push2(&posfoundq, pn, p);
+ qq.elements[j++] = p;
+ continue;
+ }
+ if (who && MAPTST(&xp->preferposx, pn))
+ {
+ Id xid = pool_str2id(pool, pool_tmpjoin(pool, pool_id2str(pool, whon), ":", pool_id2str(pool, pn)), 0);
+ if (xid && MAPTST(&xp->preferpos, xid))
+ {
+ queue_push2(&posfoundq, xid, p);
+ qq.elements[j++] = p;
+ continue;
+ }
+ }
}
- if (qn == 1)
+ if (posfoundq.count == 2)
{
- p = qe[0];
- if (xp->debug)
- expander_dbg(xp, "added %s because of %s:%s\n", expander_solvid2name(xp, p), whon ? pool_id2str(pool, whon) : "(direct)", pool_dep2str(pool, id));
- queue_push(&toinstall, p);
- xpctx.todo.elements[ti] = 0; /* kill entry */
+ queue_empty(&qq);
+ queue_push(&qq, posfoundq.elements[1]);
}
- choices.elements[tc + 2] = qn;
- tc += choices.elements[tc];
- }
- if (toinstall.count)
- continue;
-
- /* prune recommended packages */
- if (xpctx.userecommendsforchoices)
- expander_updaterecommendedmap(&xpctx);
- if (xpctx.recommended.size)
- {
- expander_dbg(xp, "now doing undecided dependencies with recommends\n");
- for (ti = tc = 0; ti < xpctx.todo.count; ti += 2)
+ else if (posfoundq.count)
{
- Id who = xpctx.todo.elements[ti + 1];
- Id *qe = choices.elements + tc + 3;
- Id id = choices.elements[tc + 1];
- int qn = choices.elements[tc + 2];
- whon = who ? pool->solvables[who].name : 0;
- for (i = j = 0; i < qn; i++)
- if (MAPTST(&xpctx.recommended, qe[i]))
- qe[j++] = qe[i];
- if (j)
- qn = j;
- if (qn == 1)
+ /* found a pos prefer, now find first hit */
+ /* (prefers are ordered) */
+ for (i = 0; i < xp->preferposq.count; i++)
{
- p = qe[0];
- if (xp->debug)
- expander_dbg(xp, "added %s because of %s:%s\n", expander_solvid2name(xp, p), whon ? pool_id2str(pool, whon) : "(direct)", pool_dep2str(pool, id));
- queue_push(&toinstall, p);
- xpctx.todo.elements[ti] = 0; /* kill entry */
+ Id xid = xp->preferposq.elements[i];
+ for (j = 0; j < posfoundq.count; j += 2)
+ if (posfoundq.elements[j] == xid)
+ break;
+ if (j < posfoundq.count)
+ {
+ queue_empty(&qq);
+ queue_push(&qq, posfoundq.elements[j + 1]);
+ break;
+ }
}
- choices.elements[tc + 2] = qn;
- tc += choices.elements[tc];
}
- if (toinstall.count)
- continue;
}
- if (xpctx.usesupplementsforchoices)
+
+ /* prune OR deps */
+ if (qq.count > 1 && ISRELDEP(id) && GETRELDEP(pool, id)->flags == REL_OR)
{
- expander_dbg(xp, "now doing undecided dependencies with supplements\n");
- for (ti = tc = 0; ti < xpctx.todo.count; ti += 2)
+ Id rid = id;
+ for (;;)
{
- Id who = xpctx.todo.elements[ti + 1];
- Id *qe = choices.elements + tc + 3;
- Id id = choices.elements[tc + 1];
- int qn = choices.elements[tc + 2];
- whon = who ? pool->solvables[who].name : 0;
- qn = prune_supplemented(&xpctx, qe, qn);
- if (qn == 1)
+ Reldep *rd = 0;
+ if (ISRELDEP(rid))
{
- p = qe[0];
- if (xp->debug)
- expander_dbg(xp, "added %s because of %s:%s\n", expander_solvid2name(xp, p), whon ? pool_id2str(pool, whon) : "(direct)", pool_dep2str(pool, id));
- queue_push(&toinstall, p);
- xpctx.todo.elements[ti] = 0; /* kill entry */
+ rd = GETRELDEP(pool, rid);
+ if (rd->flags != REL_OR)
+ rd = 0;
}
- choices.elements[tc + 2] = qn;
- tc += choices.elements[tc];
+ if (rd)
+ rid = rd->name;
+ queue_empty(&qq);
+ FOR_PROVIDES(p, pp, rid)
+ queue_push(&qq, p);
+ if (qq.count)
+ break;
+ if (rd)
+ rid = rd->evr;
+ else
+ break;
}
- if (toinstall.count)
- continue;
}
- /* nothing more to prune. record errors. */
- for (ti = tc = 0; ti < xpctx.todo.count; ti += 2)
- {
- Id who = xpctx.todo.elements[ti + 1];
- Id *qe = choices.elements + tc + 3;
- Id id = choices.elements[tc + 1];
- int qn = choices.elements[tc + 2];
- queue_push(&xpctx.errors, ERROR_CHOICE);
- queue_push2(&xpctx.errors, id, who);
- for (i = 0; i < qn; i++)
- queue_push(&xpctx.errors, qe[i]);
- queue_push(&xpctx.errors, 0);
- tc += choices.elements[tc];
- }
- }
+ if (qq.count > 1 && doamb == 1)
+ {
+ queue_push2(&todo, id, who);
+ continue;
+ }
- /* free data */
- map_free(&xpctx.installed);
- map_free(&xpctx.conflicts);
- map_free(&xpctx.recommended);
- map_free(&xpctx.todo_condmap);
- queue_free(&xpctx.conflictsinfo);
- queue_free(&xpctx.todo_cond);
- queue_free(&xpctx.todo);
- queue_free(&toinstall);
- queue_free(&qq);
- queue_free(&choices);
- queue_free(&xpctx.pruneq);
- queue_free(&xpctx.cplxq);
- queue_free(&xpctx.cplxblks);
-
- /* revert ignores */
- xp->ignoreignore = oldignoreignore;
- if (ignoremapssaved)
- {
- map_free(&xp->ignored);
- map_free(&xp->ignoredx);
- xp->ignored = oldignored;
- xp->ignoredx = oldignoredx;
- }
- else
- {
- for (i = 0; i < revertignore.count; i++)
+ /* prioritize recommended packages. */
+ if (qq.count > 1 && doamb == 2)
+ {
+ expander_updaterecommendedmap(xp, &recommended, &recdone, out);
+ if (recommended.size)
+ {
+ for (i = j = 0; i < qq.count; i++)
+ if (MAPTST(&recommended, qq.elements[i]))
+ qq.elements[j++] = qq.elements[i];
+ if (j)
+ queue_truncate(&qq, j);
+ }
+ }
+
+
+ if (qq.count > 1)
{
- id = revertignore.elements[i];
- if (id > 0)
- MAPCLR(&xp->ignored, id);
- else
- MAPCLR(&xp->ignoredx, -id);
+ queue_push(&cerrors, ERROR_CHOICE);
+ queue_push2(&cerrors, id, who);
+ for (i = 0; i < qq.count; i++)
+ queue_push(&cerrors, qq.elements[i]);
+ queue_push(&cerrors, 0);
+ /* try again later */
+ queue_push2(&todo, id, who);
+ continue;
}
- }
- queue_free(&revertignore);
-
- /* finish return queue, count errors */
+ if (xp->debug)
+ expander_dbg(xp, "added %s because of %s:%s\n", expander_solvid2name(xp, qq.elements[0]), whon ? pool_id2str(pool, whon) : "(direct)", pool_dep2str(pool, id));
+ expander_installed(xp, qq.elements[0], &installed, &conflicts, &conflictsinfo, &cidone, out, &todo);
+ doamb = 0;
+ ambcnt = todo.count;
+ queue_empty(&cerrors);
+ }
+ map_free(&installed);
+ map_free(&conflicts);
+ map_free(&recommended);
+ queue_free(&conflictsinfo);
nerrors = 0;
- if (xpctx.errors.count)
+ if (errors.count || cerrors.count)
{
queue_empty(out);
- queue_insertn(out, 0, xpctx.errors.count, xpctx.errors.elements);
- for (i = 0; i < out->count; i += 3)
+ for (i = 0; i < errors.count; i += 3)
{
+ queue_push(out, errors.elements[i]);
+ queue_push(out, errors.elements[i + 1]);
+ queue_push(out, errors.elements[i + 2]);
nerrors++;
- if (out->elements[i] == ERROR_CHOICE)
- while (out->elements[i + 3])
- i++;
}
- }
- queue_free(&xpctx.errors);
- return nerrors;
-}
-
-static Expander *
-expander_create(Pool *pool, Queue *preferpos, Queue *preferneg, Queue *ignore, Queue *conflict, Queue *fileprovides, int debug, int options)
-{
- Expander *xp;
- int i, j;
- Id id, id2;
- const char *str;
- Queue q;
-
- xp = calloc(sizeof(Expander), 1);
- xp->pool = pool;
- xp->debug = debug;
- xp->ignoreignore = options & EXPANDER_OPTION_IGNOREIGNORE ? 1 : 0;
- xp->ignoreconflicts = options & EXPANDER_OPTION_IGNORECONFLICTS ? 1 : 0;
- xp->userecommendsforchoices = options & EXPANDER_OPTION_USERECOMMENDSFORCHOICES ? 1 : 0;
- xp->usesupplementsforchoices = options & EXPANDER_OPTION_USESUPPLEMENTSFORCHOICES ? 1 : 0;
- xp->dorecommends = options & EXPANDER_OPTION_DORECOMMENDS ? 1 : 0;
- xp->dosupplements = options & EXPANDER_OPTION_DOSUPPLEMENTS ? 1 : 0;
-
- queue_init(&xp->preferposq);
- for (i = 0; i < preferpos->count; i++)
- {
- id = preferpos->elements[i];
- queue_push(&xp->preferposq, id);
- MAPEXP(&xp->preferpos, id);
- MAPSET(&xp->preferpos, id);
- if ((str = strchr(pool_id2str(pool, id), ':')) != 0)
- {
- id = str2id_dup(pool, str + 1);
- MAPEXP(&xp->preferposx, id);
- MAPSET(&xp->preferposx, id);
- }
- }
- for (i = 0; i < preferneg->count; i++)
- {
- id = preferneg->elements[i];
- MAPEXP(&xp->preferneg, id);
- MAPSET(&xp->preferneg, id);
- if ((str = strchr(pool_id2str(pool, id), ':')) != 0)
- {
- id = str2id_dup(pool, str + 1);
- MAPEXP(&xp->prefernegx, id);
- MAPSET(&xp->prefernegx, id);
- }
- }
-
- for (i = 0; i < ignore->count; i++)
- {
- id = ignore->elements[i];
- MAPEXP(&xp->ignored, id);
- MAPSET(&xp->ignored, id);
- if ((str = strchr(pool_id2str(pool, id), ':')) != 0)
- {
- id = str2id_dup(pool, str + 1);
- MAPEXP(&xp->ignoredx, id);
- MAPSET(&xp->ignoredx, id);
- }
- }
-
- queue_init(&xp->conflictsq);
- for (i = 0; i < conflict->count; i += 2)
- {
- id = conflict->elements[i];
- id2 = conflict->elements[i + 1];
- queue_push2(&xp->conflictsq, id, id2);
- MAPEXP(&xp->conflicts, id);
- MAPSET(&xp->conflicts, id);
- MAPEXP(&xp->conflicts, id2);
- MAPSET(&xp->conflicts, id2);
- }
-
- if (fileprovides->count)
- xp->havefileprovides = 1;
- queue_init(&q);
- for (i = 0; i < fileprovides->count; i++)
- {
- Id p, pp;
- id = fileprovides->elements[i];
- int havenew = 0;
-
- /* XXX: this modifies the pool, which is somewhat unclean! */
- /* get old providers */
- queue_empty(&q);
- FOR_PROVIDES(p, pp, id)
- queue_push(&q, p);
- for (j = i + 1; j < fileprovides->count && (id2 = fileprovides->elements[j]) != 0; j++)
+ for (i = 0; i < cerrors.count; )
{
- FOR_PROVIDES(p, pp, id2)
+ queue_push(out, cerrors.elements[i]);
+ queue_push(out, cerrors.elements[i + 1]);
+ queue_push(out, cerrors.elements[i + 2]);
+ i += 3;
+ while (cerrors.elements[i])
{
- int k;
- if (pool->solvables[p].name != id2)
- continue; /* match name only */
- /* insert sorted */
- for (k = 0; ; k++)
- {
- if (k == q.count || q.elements[k] > p)
- {
- queue_insert(&q, k, p);
- havenew = 1;
- break;
- }
- if (q.elements[k] == p)
- break;
- }
+ queue_push(out, cerrors.elements[i]);
+ i++;
}
+ queue_push(out, 0);
+ i++;
+ nerrors++;
}
- if (havenew)
- pool->whatprovides[id] = pool_queuetowhatprovides(pool, &q);
- i = j;
- }
- queue_free(&q);
- return xp;
-}
-
-static void
-expander_free(Expander *xp)
-{
- map_free(&xp->ignored);
- map_free(&xp->ignoredx);
- queue_free(&xp->preferposq);
- map_free(&xp->preferpos);
- map_free(&xp->preferposx);
- map_free(&xp->preferneg);
- map_free(&xp->prefernegx);
- queue_free(&xp->conflictsq);
- map_free(&xp->conflicts);
- solv_free(xp->debugstr);
- solv_free(xp);
-}
-
-
-
-static void
-set_disttype(Pool *pool, int disttype)
-{
- pool_setdisttype(pool, disttype);
-#ifdef POOL_FLAG_HAVEDISTEPOCH
- /* make newer mandriva work, hopefully there are no ill effects... */
- pool_set_flag(pool, POOL_FLAG_HAVEDISTEPOCH, disttype == DISTTYPE_RPM ? 1 : 0);
-#endif
-}
-
-static void
-set_disttype_from_location(Pool *pool, Solvable *so)
-{
- unsigned int medianr;
- const char *s = solvable_get_location(so, &medianr);
- int disttype = -1;
- int sl;
- if (!s)
- return;
- sl = strlen(s);
- if (disttype < 0 && sl >= 4 && !strcmp(s + sl - 4, ".rpm"))
- disttype = DISTTYPE_RPM;
-#ifdef DISTTYPE_DEB
- if (disttype < 0 && sl >= 4 && !strcmp(s + sl - 4, ".deb"))
- disttype = DISTTYPE_DEB;
-#endif
-#ifdef DISTTYPE_ARCH
- if (disttype < 0 && sl >= 12 && (!strcmp(s + sl - 11, ".pkg.tar.gz") || !strcmp(s + sl - 11, ".pkg.tar.xz") || !strcmp(s + sl - 12, ".pkg.tar.zst")))
- disttype = DISTTYPE_ARCH;
-#endif
- if (disttype >= 0 && pool->disttype != disttype)
- set_disttype(pool, disttype);
-}
-
-static inline const char *
-solvid2name(Pool *pool, Id p)
-{
- return pool_id2str(pool, pool->solvables[p].name);
-}
-
-#define ISNOARCH(arch) (arch == ARCH_NOARCH || arch == ARCH_ALL || arch == ARCH_ANY)
-
-static int
-has_keyname(Repo *repo, Id keyname)
-{
- Repodata *data;
- int rdid;
- FOR_REPODATAS(repo, rdid, data)
- if (repodata_has_keyname(data, keyname))
- return 1;
- return 0;
-}
-
-static inline int
-match_modules_req(Pool *pool, Id id)
-{
- const char *dep = pool_id2str(pool, id);
- Id *modules;
- if (strncmp(dep, "platform", 8) == 0 && (dep[8] == 0 || dep[8] == '-'))
- return 1;
- for (modules = pool->appdata; *modules; modules++)
- {
- const char *name, *rname;
- if (*modules == id)
- return 1;
- name = pool_id2str(pool, *modules);
- if ((rname = strrchr(name, '-')) == 0 || rname == name)
- continue;
- if (!strncmp(dep, rname, rname - name) && dep[rname - name] == 0)
- return 1;
- }
- return 0;
-}
-
-static void
-create_module_map(Repo *repo, Map *modulemap, Queue *modulemapq)
-{
- Pool *pool = repo->pool;
- Id *modules = pool->appdata;
- int i, have_moduleinfo = 0;
- Id id, p, *pp;
- Solvable *s;
-
- if (!modulemap->size)
- map_grow(modulemap, pool->ss.nstrings);
- if (!modules)
- return;
- if (!*modules)
- {
- map_setall(modulemap);
- return;
- }
- /* clear old bits */
- if (modulemapq->count)
- {
- for (i = 0; i < modulemapq->count; i++)
- MAPCLR(modulemap, modulemapq->elements[i]);
- queue_empty(modulemapq);
}
- for (modules = pool->appdata; *modules; modules++)
- MAPSET(modulemap, *modules);
- /* look for module information stored in "buildservice:modules" solvables */
- FOR_REPO_SOLVABLES(repo, p, s)
+ else
{
- if (s->name != buildservice_modules || s->arch != ARCH_SRC)
- continue;
- have_moduleinfo = 1;
- if (s->evr >= 1 && s->evr < pool->ss.nstrings && MAPTST(modulemap, s->evr))
+ if (todo.count)
{
- queue_push(modulemapq, s->evr); /* directly addressed */
- continue;
+ fprintf(stderr, "Internal expansion error!\n");
+ queue_empty(out);
+ queue_push(out, ERROR_NOPROVIDER);
+ queue_push(out, 0);
+ queue_push(out, 0);
}
- id = s->repo->idarraydata[s->provides];
- if (id < 1 || id >= pool->ss.nstrings || !MAPTST(modulemap, id))
- continue; /* not what we're looking for */
- for (pp = s->repo->idarraydata + s->requires; (id = *pp) != 0; pp++)
- {
- /* check if the dep is fulfilled by any module in the list */
- if (id < 1 || id >= pool->ss.nstrings)
- break; /* hey! */
- if (!MAPTST(modulemap, id) && !match_modules_req(pool, id))
- break; /* could not fulfil requires */
- }
- if (id)
- continue; /* could not fulfil one of the requires, ignore module */
- queue_push(modulemapq, s->evr);
- }
- if (!have_moduleinfo)
- {
- /* old style repo with no moduleinfo at all. simple use the unexpanded ids */
- for (modules = pool->appdata; *modules; modules++)
- queue_push(modulemapq, *modules);
- return;
}
- for (modules = pool->appdata; *modules; modules++)
- MAPCLR(modulemap, *modules);
- for (i = 0; i < modulemapq->count; i++)
- MAPSET(modulemap, modulemapq->elements[i]);
+ queue_free(&todo);
+ queue_free(&qq);
+ queue_free(&errors);
+ queue_free(&cerrors);
+ queue_free(&posfoundq);
+ return nerrors;
}
-static int
-in_module_map(Pool *pool, Map *modulemap, Queue *modules)
+static void
+set_disttype(Pool *pool, int disttype)
{
- int i;
- for (i = 0; i < modules->count; i++)
- {
- Id id = modules->elements[i];
- if (id > 1 && id < pool->ss.nstrings && MAPTST(modulemap, id))
- return 1;
- }
- return 0;
+ pool_setdisttype(pool, disttype);
+#ifdef POOL_FLAG_HAVEDISTEPOCH
+ /* make newer mandriva work, hopefully there are no ill effects... */
+ pool_set_flag(pool, POOL_FLAG_HAVEDISTEPOCH, disttype == DISTTYPE_RPM ? 1 : 0);
+#endif
}
-
static void
-create_considered(Pool *pool, Repo *repoonly, Map *considered, int unorderedrepos)
+set_disttype_from_location(Pool *pool, Solvable *so)
+{
+ unsigned int medianr;
+ const char *s = solvable_get_location(so, &medianr);
+ int disttype = -1;
+ int sl;
+ if (!s)
+ return;
+ sl = strlen(s);
+ if (disttype < 0 && sl >= 4 && !strcmp(s + sl - 4, ".rpm"))
+ disttype = DISTTYPE_RPM;
+#ifdef DISTTYPE_DEB
+ if (disttype < 0 && sl >= 4 && !strcmp(s + sl - 4, ".deb"))
+ disttype = DISTTYPE_DEB;
+#endif
+#ifdef DISTTYPE_ARCH
+ if (disttype < 0 && sl >= 12 && (!strcmp(s + sl - 11, ".pkg.tar.gz") || !strcmp(s + sl - 11, ".pkg.tar.xz") || !strcmp(s + sl - 12, ".pkg.tar.zst")))
+ disttype = DISTTYPE_ARCH;
+#endif
+ if (disttype >= 0 && pool->disttype != disttype)
+ set_disttype(pool, disttype);
+}
+
+void
+create_considered(Pool *pool, Repo *repoonly, Map *considered)
{
Id p, pb,*best;
Solvable *s, *sb;
Repo *repo;
int olddisttype = -1;
int dodrepo;
- int mayhave_modules;
- Queue modules;
- Map modulemap;
- Queue modulemapq;
- int modulemap_uptodate;
map_init(considered, pool->nsolvables);
best = solv_calloc(sizeof(Id), pool->ss.nstrings);
- queue_init(&modules);
- map_init(&modulemap, 0);
- queue_init(&modulemapq);
FOR_REPOS(ridx, repo)
{
if (repoonly && repo != repoonly)
continue;
dodrepo = repo_lookup_str(repo, SOLVID_META, buildservice_dodurl) != 0;
- mayhave_modules = has_keyname(repo, buildservice_modules) ? 1 : 0;
- modulemap_uptodate = 0;
FOR_REPO_SOLVABLES(repo, p, s)
{
- int inmodule = 0;
if (s->arch == ARCH_SRC || s->arch == ARCH_NOSRC)
continue;
pb = best[s->name];
- sb = pb ? pool->solvables + pb : 0;
- if (mayhave_modules)
- {
- solvable_lookup_idarray(s, buildservice_modules, &modules);
- inmodule = modules.count ? 1 : 0;
- if (inmodule)
- {
- if (!modulemap_uptodate)
- {
- create_module_map(repo, &modulemap, &modulemapq);
- modulemap_uptodate = 1;
- }
- if (!in_module_map(pool, &modulemap, &modules))
- continue; /* nope, ignore package */
- }
- }
- if (unorderedrepos && sb && s->repo->priority != sb->repo->priority)
- {
- if (s->repo->priority < sb->repo->priority)
- continue; /* lower prio, ignore */
- }
- else if (sb)
+ if (pb)
{
- int sbinmodule = 0;
- /* we already have that name. decide which one to take */
- if (!unorderedrepos && s->repo != sb->repo)
+ sb = pool->solvables + pb;
+ if (s->repo != sb->repo)
continue; /* first repo wins */
-
- if (s->repo == sb->repo && mayhave_modules)
- sbinmodule = solvable_lookup_type(sb, buildservice_modules) ? 1 : 0;
-
- if (inmodule != sbinmodule)
+ if (s->arch != sb->arch)
{
- if (inmodule < sbinmodule)
+ int r;
+ if (s->arch == ARCH_NOARCH || s->arch == ARCH_ALL || s->arch == ARCH_ANY)
continue;
+ if (sb->arch != ARCH_NOARCH && sb->arch != ARCH_ALL && sb->arch != ARCH_ANY)
+ {
+ /* the strcmp is kind of silly, but works for most archs */
+ r = strcmp(pool_id2str(pool, sb->arch), pool_id2str(pool, s->arch));
+ if (r >= 0)
+ continue;
+ }
}
else if (s->evr != sb->evr)
{
- /* check versions */
+ /* same repo, check versions */
int r;
if (olddisttype < 0)
{
set_disttype_from_location(pool, s);
}
r = pool_evrcmp(pool, sb->evr, s->evr, EVRCMP_COMPARE);
- if (r == 0)
- r = strcmp(pool_id2str(pool, sb->evr), pool_id2str(pool, s->evr));
- if (r >= 0)
- continue;
- }
- else if (s->arch != sb->arch)
- {
- /* same versions, check arch */
- if (ISNOARCH(sb->arch) && !ISNOARCH(s->arch))
+ if (r > 0)
continue;
- if (ISNOARCH(sb->arch) || !ISNOARCH(s->arch))
+ else if (r == 0)
{
- int r;
- /* the strcmp is kind of silly, but works for most archs */
- r = strcmp(pool_id2str(pool, sb->arch), pool_id2str(pool, s->arch));
+ r = strcmp(pool_id2str(pool, sb->evr), pool_id2str(pool, s->evr));
if (r >= 0)
continue;
}
}
}
-
if (dodrepo)
{
/* we only consider dod packages */
best[s->name] = p;
MAPSET(considered, p);
}
- /* dodrepos have a second pass: replace dod entries with identical downloaded ones */
+ /* dodrepos have a second pass: replace dod entries with downloaded ones */
if (dodrepo)
{
const char *bsid;
}
}
solv_free(best);
- queue_free(&modules);
- map_free(&modulemap);
- queue_free(&modulemapq);
if (olddisttype >= 0 && pool->disttype != olddisttype)
set_disttype(pool, olddisttype);
}
struct metaline {
- char *l; /* pointer to line */
- int lastoff; /* line offset of last path element */
- int nslash; /* number of slashes */
- int killed; /* 1: line has been killed. 2: because of a cycle package */
+ char *l;
+ int lastoff;
+ int nslash;
+ int killed;
};
static int metacmp(const void *ap, const void *bp)
return a - b;
}
-static char *
-slurp(FILE *fp, int *lenp)
-{
- int l, ll;
- char *buf = 0;
- int bufl = 0;
-
- for (l = 0; ; l += ll)
- {
- if (bufl - l < 4096)
- {
- bufl += 4096;
- if (bufl < 0)
- {
- buf = solv_free(buf);
- l = 0;
- break;
- }
- buf = solv_realloc(buf, bufl);
- }
- ll = fread(buf + l, 1, bufl - l, fp);
- if (ll < 0)
- {
- buf = solv_free(buf);
- l = 0;
- break;
- }
- if (ll == 0)
- {
- buf[l] = 0; /* always zero-terminate */
- break;
- }
- }
- if (lenp)
- *lenp = l;
- return buf;
-}
-
-
-Id
-repo_add_obsbinlnk(Repo *repo, const char *path, int flags)
-{
- Repodata *data;
- FILE *fp;
- char *buf;
- int len;
- SV *sv;
- unsigned char *src;
- STRLEN srcl;
- Id p;
-
- if ((fp = fopen(path, "r")) == 0)
- return 0;
- buf = slurp(fp, &len);
- fclose(fp);
- if (!buf || len <= 0)
- return 0;
- src = (unsigned char *)buf;
- srcl = len;
- sv = 0;
- if (srcl >= 7 && src[0] == 'p' && src[1] == 's' && src[2] == 't' && src[3] == '0' && (src[4] & 1) == 1 && src[4] >= 5) {
- src += 6;
- srcl -= 6;
- sv = retrieve(&src, &srcl, 0);
- }
- free(buf);
- if (!sv)
- return 0;
- if (SvTYPE(sv) != SVt_PVHV)
- {
- SvREFCNT_dec(sv);
- return 0;
- }
- data = repo_add_repodata(repo, flags);
- p = data2pkg(repo, data, (HV *)sv, 0);
- SvREFCNT_dec(sv);
- if (!(flags & REPO_NO_INTERNALIZE))
- repodata_internalize(data);
- return p;
-}
-
#ifndef REPO_NO_LOCATION
# define REPO_NO_LOCATION 0
#endif
path = solv_dupjoin(prefix, "/", s);
if (sl >= 4 && !strcmp(s + sl - 4, ".rpm"))
p = repo_add_rpm(data->repo, (const char *)path, REPO_REUSE_REPODATA|REPO_NO_INTERNALIZE|REPO_NO_LOCATION|RPM_ADD_WITH_PKGID|RPM_ADD_NO_FILELIST|RPM_ADD_NO_RPMLIBREQS);
-#if defined(LIBSOLVEXT_FEATURE_DEBIAN)
else if (sl >= 4 && !strcmp(s + sl - 4, ".deb"))
p = repo_add_deb(data->repo, (const char *)path, REPO_REUSE_REPODATA|REPO_NO_INTERNALIZE|REPO_NO_LOCATION|DEBS_ADD_WITH_PKGID);
-#endif
- else if (sl >= 10 && !strcmp(s + sl - 10, ".obsbinlnk"))
- {
- p = repo_add_obsbinlnk(data->repo, (const char *)path, REPO_REUSE_REPODATA|REPO_NO_INTERNALIZE|REPO_NO_LOCATION);
- /* do not overwrite location from obsbinlnk file */
- solv_free(path);
- if (p)
- repodata_set_str(data, p, buildservice_id, sid);
- return p;
- }
-#if defined(LIBSOLVEXT_FEATURE_ARCHREPO) && defined(ARCH_ADD_WITH_PKGID)
+#ifdef ARCH_ADD_WITH_PKGID
else if (sl >= 12 && (!strcmp(s + sl - 11, ".pkg.tar.gz") || !strcmp(s + sl - 11, ".pkg.tar.xz") || !strcmp(s + sl - 12, ".pkg.tar.zst")))
p = repo_add_arch_pkg(data->repo, (const char *)path, REPO_REUSE_REPODATA|REPO_NO_INTERNALIZE|REPO_NO_LOCATION|ARCH_ADD_WITH_PKGID);
#endif
printf("stats file_size %lld\n", (unsigned long long)ftell(fp));
}
-static int
-unifymodules_cmp(const void *ap, const void *bp, void *dp)
-{
- return *(Id *)ap - *(Id *)bp;
-}
-
-static int
-missingmodules_cmp(const void *ap, const void *bp, void *dp)
-{
- const Id *a = ap;
- const Id *b = bp;
- if (a[0] != b[0])
- return a[0] - b[0];
- if (!a[1] && b[1])
- return -1;
- if (!b[1] && a[1])
- return 1;
- return a[1] - b[1];
-}
-
-static int
-is_dod_package(Solvable *s)
-{
- const char *str = solvable_lookup_str(s, buildservice_id);
- return str && !strcmp(str, "dod") ? 1 : 0;
-}
-
-static Solvable *
-find_corresponding_dod(Solvable *s)
-{
- Repo *repo = s->repo;
- Id p2;
- Solvable *s2;
-
- if (!repo)
- return 0;
- FOR_REPO_SOLVABLES(repo, p2, s2)
- {
- if (s->name == s2->name && s->evr == s2->evr && s->arch == s2->arch && s != s2 && is_dod_package(s2))
- return s2;
- }
- return 0;
-}
-
-struct scc_data {
- Id *edata;
- Id *vedge;
- Queue *sccs;
- int *stack;
- int nstack;
- int *low;
- int idx;
-};
-
-static void
-scc_collect(struct scc_data *scc, int node)
-{
- int *low = scc->low;
- Id *e;
- queue_push(scc->sccs, node);
- low[node] = -1;
- for (e = scc->edata + scc->vedge[node]; *e; e++)
- if (*e != -1 && low[*e] > 0)
- scc_collect(scc, *e);
-}
-
-/* Tarjan's SCC algorithm */
-static int
-scc_visit(struct scc_data *scc, int node)
-{
- int l, myidx, *low = scc->low, nontrivial = 0;
- Id *e;
- low[node] = myidx = scc->idx++;
- for (e = scc->edata + scc->vedge[node]; *e; e++)
- {
- if (*e == -1 || *e == node)
- continue;
- if (!(l = low[*e]))
- l = scc_visit(scc, *e);
- if (l > 0)
- nontrivial = 1;
- if (l > 0 && l < low[node])
- low[node] = l;
- }
- if (low[node] != myidx)
- return low[node];
- low[node] = -1;
- if (nontrivial)
- {
- scc_collect(scc, node);
- queue_push(scc->sccs, 0);
- }
- return -1;
-}
-
-static void
-find_sccs(Queue *edata, Queue *vedge, Queue *sccs)
-{
- struct scc_data scc;
- int i;
- scc.edata = edata->elements;
- scc.vedge = vedge->elements;
- scc.sccs = sccs;
- scc.low = solv_calloc(vedge->count, sizeof(int));
- scc.idx = 1;
- for (i = 1; i < vedge->count; i++)
- if (!scc.edata[vedge->elements[i]])
- scc.low[i] = -1;
- for (i = 1; i < vedge->count; i++)
- if (!scc.low[i])
- scc_visit(&scc, i);
- solv_free(scc.low);
-}
-
-
MODULE = BSSolv PACKAGE = BSSolv
void
depsort(HV *deps, SV *mapp, SV *cycp, ...)
- ALIAS:
- depsort2 = 1
PPCODE:
{
int i, j, k, cy, cycstart, nv;
- int pkgstart = 3;
SV *sv, **svp;
- SV *pkg2srcp = 0;
Id id, *e;
Id *mark;
char **names;
- char **depnames;
Hashtable ht;
Hashval h, hh, hm;
HV *mhv = 0;
- HV *pkg2srchv = 0;
Queue edata;
Queue vedge;
Queue todo;
Queue cycles;
- Map edgeunifymap;
- int didsccs = 0;
- if (ix)
- {
- /* called as depsort2 */
- if (items < 4)
- XSRETURN_EMPTY; /* nothing to sort */
- pkgstart = 4;
- pkg2srcp = cycp;
- cycp = ST(3);
- }
- if (items == pkgstart)
+ if (items == 3)
XSRETURN_EMPTY; /* nothing to sort */
- if (items == pkgstart + 1)
+ if (items == 4)
{
/* only one item */
- char *s = SvPV_nolen(ST(pkgstart));
+ char *s = SvPV_nolen(ST(3));
EXTEND(SP, 1);
sv = newSVpv(s, 0);
PUSHs(sv_2mortal(sv));
XSRETURN(1); /* nothing to sort */
}
- if (pkg2srcp && SvROK(pkg2srcp) && SvTYPE(SvRV(pkg2srcp)) == SVt_PVHV)
- pkg2srchv = (HV *)SvRV(pkg2srcp);
-
if (mapp && SvROK(mapp) && SvTYPE(SvRV(mapp)) == SVt_PVHV)
mhv = (HV *)SvRV(mapp);
hm = mkmask(items);
ht = solv_calloc(hm + 1, sizeof(*ht));
- names = depnames = solv_calloc(items, sizeof(char *));
-
- /* create pkgname -> edge hash, store edge -> pkgname data */
+ names = solv_calloc(items, sizeof(char *));
nv = 1;
- for (i = pkgstart; i < items; i++)
+ for (i = 3; i < items; i++)
{
char *s = SvPV_nolen(ST(i));
h = strhash(s) & hm;
names[id] = s;
}
- if (pkg2srchv)
- {
- /* redo the hash with src names instead of pkg names */
- depnames = solv_calloc(nv, sizeof(char *));
- memset(ht, 0, (hm + 1) * sizeof(*ht));
- for (i = 1; i < nv; i++)
- {
- char *s = names[i];
- svp = hv_fetch(pkg2srchv, s, strlen(s), 0);
- if (svp)
- {
- char *ns = SvPV_nolen(*svp);
- if (ns)
- s = ns;
- }
- depnames[i] = s;
- h = strhash(s) & hm;
- hh = HASHCHAIN_START;
- while ((id = ht[h]) != 0)
- h = HASHCHAIN_NEXT(h, hh, hm);
- ht[h] = i;
- }
- }
-
/* we now know all vertices, create edges */
queue_push(&vedge, 0);
queue_push(&edata, 0);
- map_init(&edgeunifymap, nv);
for (i = 1; i < nv; i++)
{
- int edgestart = edata.count;
svp = hv_fetch(deps, names[i], strlen(names[i]), 0);
sv = svp ? *svp : 0;
- queue_push(&vedge, edgestart);
+ queue_push(&vedge, edata.count);
if (sv && SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVAV)
{
AV *av = (AV *)SvRV(sv);
hh = HASHCHAIN_START;
while ((id = ht[h]) != 0)
{
- if (!strcmp(depnames[id], s))
- {
- if (id != i && !MAPTST(&edgeunifymap, id))
- {
- MAPSET(&edgeunifymap, id);
- queue_push(&edata, id);
- }
- if (names == depnames)
- break; /* no other entry with same name */
- }
+ if (!strcmp(names[id], s))
+ break;
h = HASHCHAIN_NEXT(h, hh, hm);
}
+ if (!id)
+ continue; /* not known, ignore */
+ if (id == i)
+ continue; /* no self edge */
+ queue_push(&edata, id);
}
}
- for (j = edgestart; j < edata.count; j++)
- {
-#ifdef MAPCLR_AT
- MAPCLR_AT(&edgeunifymap, edata.elements[j]);
-#else
- MAPCLR(&edgeunifymap, edata.elements[j]);
-#endif
- }
- queue_push(&edata, 0); /* terminate edge array */
+ queue_push(&edata, 0);
}
- /* free no longer needed stuff */
- map_free(&edgeunifymap);
solv_free(ht);
- if (depnames != names)
- depnames = solv_free(depnames);
if (0)
{
continue;
}
/* oh no, we found a cycle, record and break it */
- if (depsortsccs && !didsccs && cycp)
- {
- /* use Tarjan's SCC algorithm */
- find_sccs(&edata, &vedge, &cycles);
- queue_push(&cycles, 0);
- didsccs = cycles.count;
- }
cy = cycles.count;
for (j = todo.count - 1; j >= 0; j--)
if (todo.elements[j] == -i)
todo.count = cycstart + 1;
}
- if (didsccs && depsortsccs != 2)
- queue_truncate(&cycles, didsccs - 1);
-
- /* record cycles */
+ /* recored cycles */
if (cycles.count && cycp && SvROK(cycp) && SvTYPE(SvRV(cycp)) == SVt_PVAV)
{
AV *av = (AV *)SvRV(cycp);
solv_free(names);
}
-int
-setdepsortsccs(int flag)
- CODE:
- depsortsccs = flag;
- RETVAL = flag;
- OUTPUT:
- RETVAL
-
-int
-setgenmetaalgo(int algo)
- CODE:
- if (algo < 0)
- algo = 1;
- if (algo > 1)
- croak("BSSolv::setgenmetaalgo: unsupported algo %d\n", algo);
- genmetaalgo = algo;
- RETVAL = algo;
- OUTPUT:
- RETVAL
-
-
void
gen_meta(AV *subp, ...)
PPCODE:
}
if (cycle)
{
- lp->killed = 1; /* killed because line includes a subpackage */
+ lp->killed = 1;
if (cycle > 1) /* ignore self cycles */
queue_push(&cycles, i);
}
char *cycledata = 0;
int cycledatalen = 0;
- /* create hash of cycle packages */
cycledata = solv_extend(cycledata, cycledatalen, 1, 1, 255);
- cycledata[cycledatalen++] = 0;
+ cycledata[0] = 0;
+ cycledatalen += 1;
hm = mkmask(cycles.count);
ht = solv_calloc(hm + 1, sizeof(*ht));
for (i = 0; i < cycles.count; i++)
break;
h = HASHCHAIN_NEXT(h, hh, hm);
}
- if (!id)
- {
- int l = strlen(s);
- cycledata = solv_extend(cycledata, cycledatalen, l + 1, 1, 255);
- ht[h] = cycledatalen; /* point to name */
- strcpy(cycledata + cycledatalen, s);
- cycledatalen += l + 1;
- }
+ if (id)
+ continue;
+ cycledata = solv_extend(cycledata, cycledatalen, strlen(s) + 1, 1, 255);
+ ht[h] = cycledatalen;
+ strcpy(cycledata + cycledatalen, s);
+ cycledatalen += strlen(s) + 1;
if (se)
*se = '/';
}
-
for (i = 0, lp = lines; i < nlines; i++, lp++)
{
- if (!lp->nslash)
- continue;
- if (lp->killed && genmetaalgo == 0)
+ if (lp->killed || !lp->nslash)
continue;
lo = strchr(lp->l + 34, '/') + 1;
for (s2 = lo; *s2; s2++)
*s2 = '/';
if (id)
{
- lp->killed = 2; /* killed because it containes a cycle package */
+ lp->killed = 1;
break;
}
lo = s2 + 1;
}
- if (lp->killed == 2)
+ if (lp->killed)
continue;
h = strhash(lo) & hm;
hh = HASHCHAIN_START;
h = HASHCHAIN_NEXT(h, hh, hm);
}
if (id)
- lp->killed = 2; /* killed because it containes a cycle package */
+ {
+ lp->killed = 1;
+ }
}
solv_free(ht);
cycledata = solv_free(cycledata);
+ queue_free(&cycles);
}
- queue_free(&cycles);
/* cycles are pruned, now sort array */
if (nlines > 1)
for (i = 0, lp = lines; i < nlines; i++, lp++)
{
if (lp->killed)
- {
- if (genmetaalgo == 0 || lp->killed != 2)
- continue;
- }
+ continue;
s = lp->l;
h = strnhash(s, 10);
h = strhash_cont(s + lp->lastoff, h) & hm;
break;
h = HASHCHAIN_NEXT(h, hh, hm);
}
- if (id && genmetaalgo == 1 && lp->killed == 2)
- {
- /* also kill old line of same level */
- struct metaline *lp2 = lines + (id - 1);
- if (!lp2->killed && lp2->nslash == lp->nslash)
- lp2->killed = 1;
- }
if (id)
lp->killed = 1;
else
solv_free(lines);
}
-void
-add_meta(AV *new_meta, SV *sv, const char *bin, const char *packid = 0)
- PPCODE:
- {
- const char *p, *np;
- char *buf;
- size_t l, bufl, binl, packidl;
- int first = 1;
- if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVAV) {
- AV *av = (AV *)SvRV(sv);
- SV **svp = av_fetch(av, 0, 0);
- sv = svp ? *svp : 0;
- }
- if (!sv)
- XSRETURN_EMPTY;
- p = SvPV_nolen(sv);
- binl = strlen(bin);
- bufl = binl + 256;
- buf = malloc(bufl);
- if (!buf) {
- croak("out of mem\n");
- XSRETURN_EMPTY;
- }
- packidl = packid ? strlen(packid) : 0;
- for (;;) {
- np = strchr(p, '\n');
- l = np ? np - p : strlen(p);
- if (l > 34) {
- if (l + binl + 1 + 1 > bufl) {
- bufl = l + binl + 256;
- buf = realloc(buf, bufl);
- if (!buf) {
- croak("out of mem\n");
- XSRETURN_EMPTY;
- }
- }
- strncpy(buf, p, 34);
- strcpy(buf + 34, bin);
- buf[34 + binl] = '/';
- strncpy(buf + 34 + binl + 1, p + 34, l - 34);
- l += binl + 1;
- buf[l] = 0;
- if (first) {
- if (packidl && l > packidl + 1 && buf[l - packidl - 1] == '/' && !strcmp(buf + l - packidl, packid)) {
- free(buf);
- XSRETURN_EMPTY;
- }
- l = 34 + binl;
- buf[l] = 0;
- first = 0;
- }
- av_push(new_meta, newSVpvn(buf, l));
- }
- if (!np)
- break;
- p = np + 1;
- }
- free(buf);
- }
-
SV *
thawcache(SV *sv)
CODE:
buildservice_dodurl = pool_str2id(pool, "buildservice:dodurl", 1);
expander_directdepsend = pool_str2id(pool, "-directdepsend--", 1);
buildservice_dodcookie = pool_str2id(pool, "buildservice:dodcookie", 1);
- buildservice_dodresources = pool_str2id(pool, "buildservice:dodresources", 1);
- buildservice_annotation = pool_str2id(pool, "buildservice:annotation", 1);
- buildservice_modules = pool_str2id(pool, "buildservice:modules", 1);
pool_freeidhashes(pool);
RETVAL = pool;
}
continue;
if (strcmp(s + sl - 4, ".rpm")
&& strcmp(s + sl - 4, ".deb")
- && (sl < 10 || strcmp(s + sl - 10, ".obsbinlnk"))
#ifdef ARCH_ADD_WITH_PKGID
&& (sl < 11 || strcmp(s + sl - 11, ".pkg.tar.gz"))
&& (sl < 11 || strcmp(s + sl - 11, ".pkg.tar.xz"))
RETVAL
BSSolv::repo
-repofromdata(BSSolv::pool pool, char *name, SV *rv)
+repofromdata(BSSolv::pool pool, char *name, HV *rhv)
CODE:
{
Repo *repo;
Repodata *data;
- if (!SvROK(rv) || (SvTYPE(SvRV(rv)) != SVt_PVHV && SvTYPE(SvRV(rv)) != SVt_PVAV))
- croak("BSSolv::pool::repofromdata: rv is not a HASH or ARRAY reference");
repo = repo_create(pool, name);
data = repo_add_repodata(repo, 0);
- data2solvables(repo, data, SvRV(rv), 0);
+ data2solvables(repo, data, rhv);
if (name && !strcmp(name, "/external/"))
repodata_set_void(data, SOLVID_META, buildservice_external);
repo_internalize(repo);
RETVAL
void
-createwhatprovides(BSSolv::pool pool, int unorderedrepos = 0)
+createwhatprovides(BSSolv::pool pool)
CODE:
if (pool->considered)
{
solv_free(pool->considered);
}
pool->considered = solv_calloc(sizeof(Map), 1);
- create_considered(pool, 0, pool->considered, unorderedrepos);
+ create_considered(pool, 0, pool->considered);
pool_createwhatprovides(pool);
void
PPCODE:
{
Id p, pp, id;
- id = testcase_str2dep(pool, str);
+ id = dep2id(pool, str);
if (id)
FOR_PROVIDES(p, pp, id)
XPUSHs(sv_2mortal(newSViv((IV)p)));
Id p, id;
Id *pp;
Solvable *s;
- id = testcase_str2dep(pool, str);
+ id = dep2id(pool, str);
if (id)
{
for (p = 2; p < pool->nsolvables; p++)
OUTPUT:
RETVAL
-const char *
-pkg2evr(BSSolv::pool pool, int p)
- CODE:
- RETVAL = pool_id2str(pool, pool->solvables[p].evr);
- OUTPUT:
- RETVAL
-
-const char *
-pkg2arch(BSSolv::pool pool, int p)
- CODE:
- RETVAL = pool_id2str(pool, pool->solvables[p].arch);
- OUTPUT:
- RETVAL
-
const char *
pkg2srcname(BSSolv::pool pool, int p)
CODE:
OUTPUT:
RETVAL
-int
-pkg2inmodule(BSSolv::pool pool, int p)
- CODE:
- RETVAL = solvable_lookup_type(pool->solvables + p, buildservice_modules) != 0;
- OUTPUT:
- RETVAL
-
-void
-pkg2modules(BSSolv::pool pool, int p)
- PPCODE:
- {
- Solvable *s = pool->solvables + p;
- Queue modules;
- int i;
- queue_init(&modules);
- solvable_lookup_idarray(s, buildservice_modules, &modules);
- if (!modules.count && !is_dod_package(s))
- {
- Solvable *s2 = find_corresponding_dod(s);
- if (s2)
- solvable_lookup_idarray(s2, buildservice_modules, &modules);
- }
- for (i = 0; i < modules.count; i++)
- XPUSHs(sv_2mortal(newSVpv(pool_id2str(pool, modules.elements[i]), 0)));
- queue_free(&modules);
- }
-
int
verifypkgchecksum(BSSolv::pool pool, int p, char *path)
CODE:
ss = solvable_lookup_str(s, buildservice_id);
if (ss)
(void)hv_store(RETVAL, "id", 2, newSVpv(ss, 0), 0);
- ss = solvable_lookup_str(s, buildservice_annotation);
- if (ss)
- (void)hv_store(RETVAL, "annotation", 10, newSVpv(ss, 0), 0);
- if (solvable_lookup_type(s, buildservice_modules))
- {
- Queue modules;
- int i;
- queue_init(&modules);
- solvable_lookup_idarray(s, buildservice_modules, &modules);
- if (modules.count)
- {
- AV *av = newAV();
- for (i = 0; i < modules.count; i++)
- av_push(av, newSVpv(pool_id2str(pool, modules.elements[i]), 0));
- (void)hv_store(RETVAL, "modules", 7, newRV_noinc((SV*)av), 0);
- }
- }
}
OUTPUT:
RETVAL
-const char *
-pkg2annotation(BSSolv::pool pool, int p)
- CODE:
- RETVAL = solvable_lookup_str(pool->solvables + p, buildservice_annotation);
- OUTPUT:
- RETVAL
-
void
repos(BSSolv::pool pool)
PPCODE:
sv = newRV_noinc((SV *)notready);
PUSHs(sv_2mortal(sv));
sv = newRV_noinc((SV *)subpacks);
- PUSHs(sv_2mortal(sv));
- }
-
-void
-setmodules(BSSolv::pool pool, AV *modulesav)
- CODE:
- {
- SSize_t i, n = av_len(modulesav);
- pool->appdata = solv_free(pool->appdata);
- if (n >= 0 && n < 1000000)
- {
- Id *modules = pool->appdata = solv_calloc(n + 2, sizeof(Id));
- for (i = 0; i <= n; i++)
- modules[i] = pool_str2id(pool, avlookupstr(modulesav, i), 1);
- modules[i] = 0;
- }
+ PUSHs(sv_2mortal(sv));
}
-void
-getmodules(BSSolv::pool pool)
- PPCODE:
- if (pool->appdata)
- {
- Id *modules = pool->appdata;
- int i;
- for (i = 0; modules[i]; i++)
- XPUSHs(sv_2mortal(newSVpv(pool_id2str(pool, modules[i]), 0)));
- }
-
void
DESTROY(BSSolv::pool pool)
CODE:
map_free(pool->considered);
pool->considered = solv_free(pool->considered);
}
- pool->appdata = solv_free(pool->appdata);
pool_free(pool);
MODULE = BSSolv PACKAGE = BSSolv::repo PREFIX = repo
-void
-freerepo(BSSolv::repo repo)
- CODE:
- {
- repo_free(repo, 1);
- }
-
-void
-allpackages(BSSolv::repo repo)
- PPCODE:
- {
- Id p;
- Solvable *s;
- EXTEND(SP, repo->nsolvables);
- FOR_REPO_SOLVABLES(repo, p, s)
- PUSHs(sv_2mortal(newSViv(p)));
- }
-
void
pkgnames(BSSolv::repo repo)
PPCODE:
Id p;
Solvable *s;
Map c;
-
- create_considered(pool, repo, &c, 0);
+
+ create_considered(pool, repo, &c);
EXTEND(SP, 2 * repo->nsolvables);
FOR_REPO_SOLVABLES(repo, p, s)
{
const char *str;
unsigned int medianr;
- create_considered(pool, repo, &c, 0);
+ create_considered(pool, repo, &c);
EXTEND(SP, 2 * repo->nsolvables);
FOR_REPO_SOLVABLES(repo, p, s)
{
continue;
h = strhash(str) & hm;
hh = HASHCHAIN_START;
- while (ht[h])
+ while ((id = ht[h]) != 0)
h = HASHCHAIN_NEXT(h, hh, hm);
ht[h] = p;
}
continue;
if (strcmp(s + sl - 4, ".rpm")
&& strcmp(s + sl - 4, ".deb")
- && (sl < 10 || strcmp(s + sl - 10, ".obsbinlnk"))
#ifdef ARCH_ADD_WITH_PKGID
&& (sl < 11 || strcmp(s + sl - 11, ".pkg.tar.gz"))
&& (sl < 11 || strcmp(s + sl - 11, ".pkg.tar.xz"))
&& (sl < 12 || strcmp(s + sl - 12, ".pkg.tar.zst"))
#endif
)
- continue;
if (sl > 10 && !strcmp(s + sl - 10, ".patch.rpm"))
continue;
if (sl > 10 && !strcmp(s + sl - 10, ".nosrc.rpm"))
const char *str = solvable_lookup_str(pool->solvables + id, buildservice_id);
if (!strcmp(str, sid))
{
- /* check location (unless it's a obsbinlnk where the location comes from the content) */
+ /* check location */
unsigned int medianr;
str = solvable_get_location(pool->solvables + id, &medianr);
if (str[0] == '.' && str[1] == '/')
str += 2;
- if (!strcmp(str, s) || (sl >= 10 && !strcmp(s + sl - 10, ".obsbinlnk")))
+ if (!strcmp(str, s))
break;
}
h = HASHCHAIN_NEXT(h, hh, hm);
OUTPUT:
RETVAL
-void
-modulesfrombins(BSSolv::repo repo, ...)
- PPCODE:
- {
- Pool *pool = repo->pool;
- Hashtable ht;
- Hashval h, hh, hm;
- Queue modules;
- Queue collectedmodules;
- Id p, lastid;
- Solvable *s;
- int i, j;
-
- queue_init(&collectedmodules);
- queue_init(&modules);
- hm = mkmask(2 * repo->nsolvables + 1);
- ht = solv_calloc(hm + 1, sizeof(*ht));
- FOR_REPO_SOLVABLES(repo, p, s)
- {
- const char *bsid = solvable_lookup_str(s, buildservice_id);
- if (!bsid)
- continue;
- if (!strcmp(bsid, "dod"))
- h = s->name + s->evr * 37 + s->arch * 129;
- else
- h = strhash(bsid);
- h &= hm;
- hh = HASHCHAIN_START;
- while (ht[h])
- h = HASHCHAIN_NEXT(h, hh, hm);
- ht[h] = p;
- }
-
- for (i = 1; i + 1 < items; i += 2)
- {
- const char *bsid = SvPV_nolen(ST(i + 1));
- h = strhash(bsid) & hm;
- hh = HASHCHAIN_START;
- while ((p = ht[h]) != 0)
- {
- const char *bsid2 = solvable_lookup_str(pool->solvables + p, buildservice_id);
- if (!strcmp(bsid, bsid2))
- break;
- h = HASHCHAIN_NEXT(h, hh, hm);
- }
- if (!p)
- continue;
- s = pool->solvables + p;
- h = (s->name + s->evr * 37 + s->arch * 129) & hm;
- hh = HASHCHAIN_START;
- while ((p = ht[h]) != 0)
- {
- Solvable *s2 = pool->solvables + p;
- if (s->name == s2->name && s->evr == s2->evr && s->arch == s2->arch)
- {
- lastid = collectedmodules.count ? collectedmodules.elements[collectedmodules.count - 1] : 0;
- solvable_lookup_idarray(s2, buildservice_modules, &modules);
- for (j = 0; j < modules.count; j++)
- if (modules.elements[j] != lastid)
- queue_push(&collectedmodules, modules.elements[j]);
- }
- h = HASHCHAIN_NEXT(h, hh, hm);
- }
- }
- solv_free(ht);
- queue_free(&modules);
- /* sort and unify */
- solv_sort(collectedmodules.elements, collectedmodules.count, sizeof(Id), unifymodules_cmp, 0);
- lastid = -1;
- for (i = 0; i < collectedmodules.count; i++)
- {
- if (collectedmodules.elements[i] == lastid)
- continue;
- lastid = collectedmodules.elements[i];
- XPUSHs(sv_2mortal(newSVpv(pool_id2str(pool, lastid), 0)));
- }
- queue_free(&collectedmodules);
- }
-
-void
-missingmodules(BSSolv::repo repo, ...)
- PPCODE:
- {
- Pool *pool = repo->pool;
- Id p, *pp, *modules, id, req, lastid1, lastid2;
- Solvable *s;
- Queue missingq;
- int i, missing;
-
- queue_init(&missingq);
- if (pool->appdata && ((Id *)pool->appdata)[0] && has_keyname(repo, buildservice_modules))
- {
- FOR_REPO_SOLVABLES(repo, p, s)
- {
- if (s->name != buildservice_modules || s->arch != ARCH_SRC || !s->requires)
- continue;
- id = s->repo->idarraydata[s->provides];
- for (modules = pool->appdata; *modules; modules++)
- if (id == *modules)
- break;
- if (!*modules)
- continue;
- missing = 0;
- for (pp = s->repo->idarraydata + s->requires; (req = *pp) != 0; pp++)
- if (!match_modules_req(pool, req))
- {
- missing = 1;
- queue_push2(&missingq, id, req);
- }
- if (!missing) /* we're good */
- queue_push2(&missingq, id, 0);
- }
- /* sort and unify */
- solv_sort(missingq.elements, missingq.count / 2, sizeof(Id) * 2, missingmodules_cmp, 0);
- lastid1 = lastid2 = -1;
- for (i = 0; i < missingq.count; i += 2)
- {
- if (missingq.elements[i] == lastid1 && missingq.elements[i + 1] == lastid2)
- continue;
- if (missingq.elements[i] != lastid1)
- {
- lastid1 = missingq.elements[i];
- lastid2 = missingq.elements[i + 1];
- }
- if (!lastid2)
- continue;
- lastid2 = missingq.elements[i + 1];
- XPUSHs(sv_2mortal(newSVpv(pool_id2str(pool, lastid1), 0)));
- XPUSHs(sv_2mortal(newSVpv(pool_id2str(pool, lastid2), 0)));
- }
- queue_free(&missingq);
- }
- }
void
getpathid(BSSolv::repo repo)
unsigned int medianr;
const char *str;
str = solvable_get_location(s, &medianr);
- /* We need to special case .obsbinlink here where the location
- * points back into the package. We currently assume that
- * the name in the full tree is always <name>.obsbinlnk */
- if (!strncmp(str, "../", 3))
- str = pool_tmpjoin(repo->pool, pool_id2str(repo->pool, s->name), ".obsbinlnk", 0);
PUSHs(sv_2mortal(newSVpv(str, 0)));
str = solvable_lookup_str(s, buildservice_id);
PUSHs(sv_2mortal(newSVpv(str, 0)));
OUTPUT:
RETVAL
-void
-dodresources(BSSolv::repo repo)
- PPCODE:
- {
- Pool *pool = repo->pool;
- Queue dodresources;
- int i;
-
- queue_init(&dodresources);
- repo_lookup_idarray(repo, SOLVID_META, buildservice_dodresources, &dodresources);
- for (i = 0; i < dodresources.count; i++)
- XPUSHs(sv_2mortal(newSVpv(pool_id2str(pool, dodresources.elements[i]), 0)));
- queue_free(&dodresources);
- }
-
void
updatedoddata(BSSolv::repo repo, HV *rhv = 0)
CODE:
data = repo_add_repodata(repo, REPO_REUSE_REPODATA);
repodata_unset(data, SOLVID_META, buildservice_dodurl);
repodata_unset(data, SOLVID_META, buildservice_dodcookie);
- repodata_unset(data, SOLVID_META, buildservice_dodresources);
/* add new data */
if (rhv)
- data2solvables(repo, data, (SV *)rhv, 1);
+ data2solvables(repo, data, rhv);
repo_internalize(repo);
}
-void
-setpriority(BSSolv::repo repo, int priority)
- PPCODE:
- repo->priority = priority;
-
-int
-mayhavemodules(BSSolv::repo repo)
- CODE:
- RETVAL = has_keyname(repo, buildservice_modules);
- OUTPUT:
- RETVAL
-
-void
-getmodules(BSSolv::repo repo)
- PPCODE:
- if (has_keyname(repo, buildservice_modules))
- {
- Pool *pool = repo->pool;
- Id p, lastid = -1;
- Solvable *s;
- Queue collectedmodules;
- int i;
-
- queue_init(&collectedmodules);
- FOR_REPO_SOLVABLES(repo, p, s)
- if (s->name == buildservice_modules && s->arch == ARCH_SRC && s->repo->idarraydata[s->provides])
- queue_push(&collectedmodules, s->repo->idarraydata[s->provides]);
- if (!collectedmodules.count)
- {
- Queue modules;
- queue_init(&modules);
- FOR_REPO_SOLVABLES(repo, p, s)
- {
- solvable_lookup_idarray(pool->solvables + p, buildservice_modules, &modules);
- for (i = 0; i < modules.count; i++)
- {
- if (modules.elements[i] == lastid)
- continue;
- lastid = modules.elements[i];
- queue_push(&collectedmodules, modules.elements[i]);
- }
- }
- queue_free(&modules);
- }
- /* sort and unify */
- solv_sort(collectedmodules.elements, collectedmodules.count, sizeof(Id), unifymodules_cmp, 0);
- lastid = -1;
- for (i = 0; i < collectedmodules.count; i++)
- {
- if (collectedmodules.elements[i] == lastid)
- continue;
- lastid = collectedmodules.elements[i];
- XPUSHs(sv_2mortal(newSVpv(pool_id2str(pool, lastid), 0)));
- }
- queue_free(&collectedmodules);
- }
-
-void
-getdodblobs(BSSolv::repo repo)
- PPCODE:
- {
- Pool *pool = repo->pool;
- int i;
- Id p;
- Solvable *s;
- Stringpool ss;
- stringpool_init_empty(&ss);
- FOR_REPO_SOLVABLES(repo, p, s)
- {
- const char *str = solvable_lookup_str(s, buildservice_id);
- unsigned int medianr;
- const char *s, *se;
- if (!str || strcmp(str, "dod") != 0)
- continue;
- s = solvable_get_location(pool->solvables + p, &medianr);
- if ((s = strrchr(s, '?')) == 0)
- continue;
- for (++s; s; s = se ? se + 1 : 0)
- {
- se = strchr(s, ',');
- if (se)
- stringpool_strn2id(&ss, s, se - s, 1);
- else
- stringpool_str2id(&ss, s, 1);
- }
- }
- for (i = 2; i < ss.nstrings; i++)
- {
- XPUSHs(sv_2mortal(newSVpv(stringpool_id2str(&ss, i), 0)));
- }
- stringpool_free(&ss);
- }
-
MODULE = BSSolv PACKAGE = BSSolv::expander PREFIX = expander
+
BSSolv::expander
new(char *packname = "BSSolv::expander", BSSolv::pool pool, HV *config)
CODE:
{
SV *sv, **svp;
- char *str, *p;
- int i;
- Id id;
+ char *str;
+ int i, neg;
+ Id id, id2;
Expander *xp;
- Queue preferpos;
- Queue preferneg;
- Queue ignore;
- Queue conflict;
- Queue fileprovides;
- int debug = 0;
- int options = 0;
-
- queue_init(&preferpos);
- queue_init(&preferneg);
- queue_init(&ignore);
- queue_init(&conflict);
- queue_init(&fileprovides);
+
+ xp = calloc(sizeof(Expander), 1);
+ xp->pool = pool;
svp = hv_fetch(config, "prefer", 6, 0);
sv = svp ? *svp : 0;
if (sv && SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVAV)
str = SvPV_nolen(sv);
if (!str)
continue;
+ neg = 0;
if (*str == '-')
- queue_push(&preferneg, pool_str2id(pool, str + 1, 1));
+ {
+ neg = 1;
+ str++;
+ }
+ id = pool_str2id(pool, str, 1);
+ id2 = 0;
+ if ((str = strchr(str, ':')) != 0)
+ id2 = pool_str2id(pool, str + 1, 1);
+ if (neg)
+ {
+ MAPEXP(&xp->preferneg, id);
+ MAPSET(&xp->preferneg, id);
+ if (id2)
+ {
+ MAPEXP(&xp->prefernegx, id2);
+ MAPSET(&xp->prefernegx, id2);
+ }
+ }
else
- queue_push(&preferpos, pool_str2id(pool, str, 1));
+ {
+ queue_push(&xp->preferposq, id);
+ MAPEXP(&xp->preferpos, id);
+ MAPSET(&xp->preferpos, id);
+ if (id2)
+ {
+ MAPEXP(&xp->preferposx, id2);
+ MAPSET(&xp->preferposx, id2);
+ }
+ }
}
}
svp = hv_fetch(config, "ignoreh", 7, 0);
{
HV *hv = (HV *)SvRV(sv);
HE *he;
+
hv_iterinit(hv);
while ((he = hv_iternext(hv)) != 0)
{
str = hv_iterkey(he, &strl);
if (!str)
continue;
- queue_push(&ignore, pool_str2id(pool, str, 1));
+
+ id = pool_str2id(pool, str, 1);
+ id2 = 0;
+ if ((str = strchr(str, ':')) != 0)
+ id2 = pool_str2id(pool, str + 1, 1);
+ MAPEXP(&xp->ignored, id);
+ MAPSET(&xp->ignored, id);
+ if (id2)
+ {
+ MAPEXP(&xp->ignoredx, id2);
+ MAPSET(&xp->ignoredx, id2);
+ }
}
}
svp = hv_fetch(config, "conflict", 8, 0);
AV *av = (AV *)SvRV(sv);
for (i = 0; i <= av_len(av); i++)
{
+ char *p;
+ Id id2;
+
svp = av_fetch(av, i, 0);
if (!svp)
continue;
str = p + 1;
while ((p = strchr(str, ',')) != 0)
{
- queue_push2(&conflict, id, pool_strn2id(pool, str, p - str, 1));
+ id2 = pool_strn2id(pool, str, p - str, 1);
+ queue_push2(&xp->conflictsq, id, id2);
+ MAPEXP(&xp->conflicts, id);
+ MAPSET(&xp->conflicts, id);
+ MAPEXP(&xp->conflicts, id2);
+ MAPSET(&xp->conflicts, id2);
str = p + 1;
}
- queue_push2(&conflict, id, pool_str2id(pool, str, 1));
+ id2 = pool_str2id(pool, str, 1);
+ queue_push2(&xp->conflictsq, id, id2);
+ MAPEXP(&xp->conflicts, id);
+ MAPSET(&xp->conflicts, id);
+ MAPEXP(&xp->conflicts, id2);
+ MAPSET(&xp->conflicts, id2);
}
}
+ /* XXX: this modifies the pool, which is a bit unclean! */
svp = hv_fetch(config, "fileprovides", 12, 0);
sv = svp ? *svp : 0;
if (sv && SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVHV)
{
HV *hv = (HV *)SvRV(sv);
I32 strl;
+ Queue q;
+ xp->havefileprovides = 1;
hv_iterinit(hv);
+ queue_init(&q);
while ((sv = hv_iternextsv(hv, &str, &strl)) != 0)
{
AV *av;
- Id id2;
+ Id p, pp;
+ int havenew = 0;
if (!SvROK(sv) || SvTYPE(SvRV(sv)) != SVt_PVAV)
continue;
id = pool_str2id(pool, str, 1);
+ queue_empty(&q);
+ FOR_PROVIDES(p, pp, id)
+ queue_push(&q, p);
av = (AV *)SvRV(sv);
for (i = 0; i <= av_len(av); i++)
{
if (!str)
continue;
id2 = pool_str2id(pool, str, 0);
- if (!id2)
- continue;
- if (id)
+ FOR_PROVIDES(p, pp, id2)
{
- queue_push(&fileprovides, id); /* start name block */
- id = 0;
+ int j;
+ for (j = 0; j < q.count; j++)
+ {
+ if (q.elements[j] == p)
+ break;
+ if (q.elements[j] > p)
+ {
+ queue_insert(&q, j, p);
+ havenew = 1;
+ break;
+ }
+ }
+ if (j == q.count)
+ {
+ queue_push(&q, p);
+ havenew = 1;
+ }
}
- queue_push(&fileprovides, id2);
}
- if (id == 0)
- queue_push(&fileprovides, 0); /* had at least one entry, finish name block */
+ if (havenew)
+ pool->whatprovides[id] = pool_queuetowhatprovides(pool, &q);
}
+ queue_free(&q);
}
- options |= EXPANDER_OPTION_USERECOMMENDSFORCHOICES;
svp = hv_fetch(config, "expandflags:ignoreconflicts", 27, 0);
sv = svp ? *svp : 0;
if (sv && SvTRUE(sv))
- options |= EXPANDER_OPTION_IGNORECONFLICTS;
- svp = hv_fetch(config, "expandflags:dorecommends", 24, 0);
+ xp->ignoreconflicts = 1;
+ svp = hv_fetch(config, "expand_dbg", 10, 0);
sv = svp ? *svp : 0;
if (sv && SvTRUE(sv))
- options |= EXPANDER_OPTION_DORECOMMENDS;
- svp = hv_fetch(config, "expandflags:dosupplements", 25, 0);
- sv = svp ? *svp : 0;
+ xp->debug = 1;
+ sv = get_sv("Build::expand_dbg", FALSE);
if (sv && SvTRUE(sv))
- options |= EXPANDER_OPTION_DOSUPPLEMENTS | EXPANDER_OPTION_USESUPPLEMENTSFORCHOICES;
- svp = hv_fetch(config, "expand_dbg", 10, 0);
- sv = svp ? *svp : 0;
- if (sv && SvOK(sv))
- debug = SvIV(sv);
- else
- {
- sv = get_sv("Build::expand_dbg", FALSE);
- if (sv && SvOK(sv))
- debug = SvIV(sv);
- }
- xp = expander_create(pool, &preferpos, &preferneg, &ignore, &conflict, &fileprovides, debug, options);
- queue_free(&preferpos);
- queue_free(&preferneg);
- queue_free(&ignore);
- queue_free(&conflict);
- queue_free(&fileprovides);
+ xp->debug = 1;
+ xp->userecommendsforchoices = 1;
RETVAL = xp;
}
OUTPUT:
{
Pool *pool;
int i, nerrors;
- Id id, who, indepbuf[64];
- Queue ignoreq, in, out, indep;
- int directdepsend = 0;
- int options = 0;
-
- queue_init(&ignoreq);
+ Id id, who, conflbuf[16];
+ Queue revertignore, in, out, confl;
+ int oldignoreignore = xp->ignoreignore;
+ int ignoreignore = 0;
+ Map oldignored, oldignoredx;
+ int ignoremapssaved = 0;
+
+ queue_init(&revertignore);
queue_init(&in);
queue_init(&out);
- queue_init_buffer(&indep, indepbuf, sizeof(indepbuf)/sizeof(*indepbuf));
+ queue_init_buffer(&confl, conflbuf, sizeof(conflbuf)/sizeof(*conflbuf));
pool = xp->pool;
if (xp->debug)
expander_dbg(xp, "expand args:");
for (i = 1; i < items; i++)
{
char *s = SvPV_nolen(ST(i));
- int deptype = DEPTYPE_REQUIRES;
-
if (xp->debug)
expander_dbg(xp, " %s", s);
- if (*s == '-' && s[1] == '-')
- {
- /* expand option */
- if (!strcmp(s, "--ignoreignore--"))
- options |= EXPANDER_OPTION_IGNOREIGNORE;
- else if (!strcmp(s, "--directdepsend--"))
- directdepsend = 1;
- else if (!strcmp(s, "--dorecommends--"))
- options |= EXPANDER_OPTION_DORECOMMENDS;
- else if (!strcmp(s, "--dosupplements--"))
- options |= EXPANDER_OPTION_DOSUPPLEMENTS | EXPANDER_OPTION_USESUPPLEMENTSFORCHOICES;
- else if (!strcmp(s, "--ignoreconflicts--"))
- options |= EXPANDER_OPTION_IGNORECONFLICTS;
- continue;
- }
if (*s == '-')
{
- /* ignore dependency */
+ Id id;
+ if (s[1] == '-' && !strcmp(s, "--ignoreignore--"))
+ {
+ ignoreignore = 1;
+ continue;
+ }
id = pool_str2id(pool, s + 1, 1);
- queue_push(&ignoreq, id);
- continue;
- }
- if (*s == '!')
- {
- deptype = DEPTYPE_CONFLICTS;
- s++;
- if (*s == '!')
+ if (id == expander_directdepsend)
{
- deptype = DEPTYPE_OBSOLETES;
- s++;
+ queue_push(&in, id);
+ continue;
}
+ queue_push(&revertignore, id);
+ }
+ else if (*s == '!')
+ {
+ Id id = dep2id(pool, s + (s[1] == '!' ? 2 : 1));
+ queue_push2(&confl, id, s[1] == '!' ? 1 : 0);
}
- id = dep2id(pool, s);
- if (deptype == DEPTYPE_REQUIRES && !directdepsend)
- queue_push(&in, id);
else
- queue_push2(&indep, deptype, id);
+ {
+ Id id = dep2id(pool, s);
+ queue_push(&in, id);
+ }
}
if (xp->debug)
expander_dbg(xp, "\n");
- nerrors = expander_expand(xp, &in, &indep, &out, &ignoreq, options);
+ if (ignoreignore && revertignore.count)
+ {
+ /* bad: have direct ignores and project config ignores */
+ oldignored = xp->ignored;
+ oldignoredx = xp->ignoredx;
+ ignoremapssaved = 1;
+ /* clear project config maps */
+ memset(&xp->ignored, 0, sizeof(xp->ignored));
+ memset(&xp->ignoredx, 0, sizeof(xp->ignoredx));
+ }
+
+ if (revertignore.count)
+ {
+ /* mix direct ignores with ignores from project config */
+ int revertcnt = revertignore.count;
+ for (i = 0; i < revertcnt; i++)
+ {
+ const char *ss;
+ id = revertignore.elements[i];
+ MAPEXP(&xp->ignored, id);
+ if (MAPTST(&xp->ignored, id))
+ continue;
+ MAPSET(&xp->ignored, id);
+ queue_push(&revertignore, id);
+ if ((ss = strchr(pool_id2str(pool, id), ':')) != 0)
+ {
+ id = pool_str2id(pool, ss + 1, 1);
+ MAPEXP(&xp->ignoredx, id);
+ if (MAPTST(&xp->ignoredx, id))
+ continue;
+ MAPSET(&xp->ignoredx, id);
+ queue_push(&revertignore, -id);
+ }
+ }
+ queue_deleten(&revertignore, 0, revertcnt);
+ }
+ else if (ignoreignore)
+ {
+ /* no direct ignores, disable ignore processing */
+ xp->ignoreignore = 1;
+ }
+
+ MAPEXP(&xp->ignored, pool->ss.nstrings);
+ MAPEXP(&xp->ignoredx, pool->ss.nstrings);
+ MAPEXP(&xp->preferpos, pool->ss.nstrings);
+ MAPEXP(&xp->preferposx, pool->ss.nstrings);
+ MAPEXP(&xp->preferneg, pool->ss.nstrings);
+ MAPEXP(&xp->prefernegx, pool->ss.nstrings);
+ MAPEXP(&xp->conflicts, pool->ss.nstrings);
+
+ nerrors = expander_expand(xp, &in, &out, &confl);
+
+ /* revert ignores */
+ xp->ignoreignore = oldignoreignore;
+ if (ignoremapssaved)
+ {
+ map_free(&xp->ignored);
+ map_free(&xp->ignoredx);
+ xp->ignored = oldignored;
+ xp->ignoredx = oldignoredx;
+ }
+ else
+ {
+ for (i = 0; i < revertignore.count; i++)
+ {
+ id = revertignore.elements[i];
+ if (id > 0)
+ MAPCLR(&xp->ignored, id);
+ else
+ MAPCLR(&xp->ignoredx, -id);
+ }
+ }
+ queue_free(&revertignore);
queue_free(&in);
- queue_free(&indep);
- queue_free(&ignoreq);
+ queue_free(&confl);
if (nerrors)
{
id = out.elements[i + 1];
who = out.elements[i + 2];
if (who)
- sv = newSVpvf("nothing provides %s needed by %s", pool_dep2str(pool, id), solvid2name(pool, who));
+ sv = newSVpvf("nothing provides %s needed by %s", pool_dep2str(pool, id), pool_id2str(pool, pool->solvables[who].name));
else
sv = newSVpvf("nothing provides %s", pool_dep2str(pool, id));
i += 3;
}
- else if (type == ERROR_ALLCONFLICT)
+ else if (type == ERROR_CONFLICTINGPROVIDER)
{
id = out.elements[i + 1];
who = out.elements[i + 2];
if (who)
- sv = newSVpvf("%s conflicts with always true %s", solvid2name(pool, who), pool_dep2str(pool, id));
- else
- sv = newSVpvf("conflict with always true %s", pool_dep2str(pool, id));
- i += 3;
- }
- else if (type == ERROR_CONFLICT)
- {
- Id who2 = out.elements[i + 2];
- who = out.elements[i + 1];
- if (!who && who2 >= 0)
- sv = newSVpvf("conflicts with %s", solvid2name(pool, who2));
- else if (who2 < 0)
- sv = newSVpvf("%s obsoletes %s", solvid2name(pool, who), solvid2name(pool, -who2));
- else
- sv = newSVpvf("%s conflicts with %s", solvid2name(pool, who), solvid2name(pool, who2));
- i += 3;
- }
- else if (type == ERROR_CONFLICT2)
- {
- Id who2 = out.elements[i + 2];
- who = out.elements[i + 1];
- if (who2 < 0)
- sv = newSVpvf("%s is obsoleted by %s", solvid2name(pool, who), solvid2name(pool, -who2));
- else if (who2 > 0)
- sv = newSVpvf("%s is in conflict with %s", solvid2name(pool, who), solvid2name(pool, who2));
+ sv = newSVpvf("conflict for provider of %s needed by %s", pool_dep2str(pool, id), pool_id2str(pool, pool->solvables[who].name));
else
- sv = newSVpvf("%s is in conflict", solvid2name(pool, who));
+ sv = newSVpvf("conflict for provider of %s", pool_dep2str(pool, id));
i += 3;
}
else if (type == ERROR_CONFLICTINGPROVIDERS)
id = out.elements[i + 1];
who = out.elements[i + 2];
if (who)
- sv = newSVpvf("conflict for providers of %s needed by %s", pool_dep2str(pool, id), solvid2name(pool, who));
+ sv = newSVpvf("conflict for all providers of %s needed by %s", pool_dep2str(pool, id), pool_id2str(pool, pool->solvables[who].name));
else
- sv = newSVpvf("conflict for providers of %s", pool_dep2str(pool, id));
+ sv = newSVpvf("conflict for all providers of %s", pool_dep2str(pool, id));
i += 3;
}
else if (type == ERROR_PROVIDERINFO)
Id who2 = out.elements[i + 2];
who = out.elements[i + 1];
if (who2 < 0)
- sv = newSVpvf("(provider %s obsoletes %s)", solvid2name(pool, who), solvid2name(pool, -who2));
+ sv = newSVpvf("(provider %s obsoletes installed %s)", pool_id2str(pool, pool->solvables[who].name), pool_id2str(pool, pool->solvables[-who2].name));
else
- sv = newSVpvf("(provider %s conflicts with %s)", solvid2name(pool, who), solvid2name(pool, who2));
+ sv = newSVpvf("(provider %s conflicts with installed %s)", pool_id2str(pool, pool->solvables[who].name), pool_id2str(pool, pool->solvables[who2].name));
i += 3;
}
else if (type == ERROR_PROVIDERINFO2)
Id who2 = out.elements[i + 2];
who = out.elements[i + 1];
if (who2 < 0)
- sv = newSVpvf("(provider %s is obsoleted by %s)", solvid2name(pool, who), solvid2name(pool, -who2));
+ sv = newSVpvf("(provider %s is obsoleted by installed %s)", pool_id2str(pool, pool->solvables[who].name), pool_id2str(pool, pool->solvables[-who2].name));
else if (who2 > 0)
- sv = newSVpvf("(provider %s is in conflict with %s)", solvid2name(pool, who), solvid2name(pool, who2));
+ sv = newSVpvf("(provider %s is conflicted by installed %s)", pool_id2str(pool, pool->solvables[who].name), pool_id2str(pool, pool->solvables[who2].name));
else
- sv = newSVpvf("(provider %s is in conflict)", solvid2name(pool, who));
+ sv = newSVpvf("(provider %s is conflicted by the build config)", pool_id2str(pool, pool->solvables[who].name));
i += 3;
}
else if (type == ERROR_CHOICE)
{
int j;
char *str = "";
- for (j = i + 3; out.elements[j]; j++)
- ;
- solv_sort(out.elements + i + 3, j - (i + 3), sizeof(Id), pkgname_sort_cmp, pool);
for (j = i + 3; out.elements[j]; j++)
{
Solvable *s = pool->solvables + out.elements[j];
id = out.elements[i + 1];
who = out.elements[i + 2];
if (who)
- sv = newSVpvf("have choice for %s needed by %s: %s", pool_dep2str(pool, id), solvid2name(pool, who), str);
+ sv = newSVpvf("have choice for %s needed by %s: %s", pool_dep2str(pool, id), pool_id2str(pool, pool->solvables[who].name), str);
else
sv = newSVpvf("have choice for %s: %s", pool_dep2str(pool, id), str);
i = j + 1;
}
- else if (type == ERROR_BADDEPENDENCY)
- {
- id = out.elements[i + 1];
- who = out.elements[i + 2];
- if (who)
- sv = newSVpvf("cannot parse dependency %s from %s", pool_dep2str(pool, id), solvid2name(pool, who));
- else
- sv = newSVpvf("cannot parse dependency %s", pool_dep2str(pool, id));
- i += 3;
- }
- else if (type == ERROR_NOPROVIDERINFO)
- {
- id = out.elements[i + 1];
- who = out.elements[i + 2];
- if (who)
- sv = newSVpvf("(got version %s provided by %s)", pool_id2str(pool, id), solvid2name(pool, who));
- else
- sv = newSVpvf("(got version %s)", pool_id2str(pool, id));
- i += 3;
- }
else
croak("expander: bad error type\n");
PUSHs(sv_2mortal(sv));
queue_free(&out);
}
-void
-debug(BSSolv::expander xp, const char *str)
- CODE:
- expander_dbg(xp, "%s", str);
-
-
const char *
debugstr(BSSolv::expander xp)
CODE:
- RETVAL = xp->debugstr ? xp->debugstr : "";
+ if (!xp->debugstr)
+ xp->debugstr = calloc(1, 1);
+ RETVAL = xp->debugstr;
OUTPUT:
RETVAL
-const char *
-debugstrclr(BSSolv::expander xp)
-
- CODE:
- RETVAL = xp->debugstr ? xp->debugstr : "";
- OUTPUT:
- RETVAL
- CLEANUP:
- expander_clrdbg(xp);
void
DESTROY(BSSolv::expander xp)
CODE:
- expander_free(xp);
-
+ map_free(&xp->ignored);
+ map_free(&xp->ignoredx);
+ queue_free(&xp->preferposq);
+ map_free(&xp->preferpos);
+ map_free(&xp->preferposx);
+ map_free(&xp->preferneg);
+ map_free(&xp->prefernegx);
+ queue_free(&xp->conflictsq);
+ map_free(&xp->conflicts);
+ solv_free(xp->debugstr);
+ solv_free(xp);