@@ -0,0 +1,2027 @@
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+
+#define MULTI_SEMANTICS
+
+#include "pool.h"
+#include "repo.h"
+#include "util.h"
+#include "evr.h"
+#include "hash.h"
+#include "repo_solv.h"
+#include "repo_write.h"
+#include "repo_rpmdb.h"
+#include "repo_deb.h"
+
+typedef struct _Expander {
+ Pool *pool;
+
+ Map ignored;
+ Map ignoredx;
+
+ Queue preferposq;
+ Map preferpos;
+ Map preferposx;
+
+ Map preferneg;
+ Map prefernegx;
+
+ Queue conflictsq;
+ Map conflicts;
+
+ int debug;
+} Expander;
+
+typedef Pool *BSSolv__pool;
+typedef Repo *BSSolv__repo;
+typedef Expander *BSSolv__expander;
+
+static Id buildservice_id;
+static Id buildservice_repocookie;
+static Id buildservice_external;
+
+/* make sure bit n is usable */
+#define MAPEXP(m, n) ((m)->size < (((n) + 8) >> 3) ? map_grow(m, n + 256) : 0)
+
+#define REPOCOOKIE "buildservice repo 1.0"
+
+static int
+myrepowritefilter(Repo *repo, Repokey *key, void *kfdata)
+{
+ int i;
+ if (key->name == SOLVABLE_URL)
+ return KEY_STORAGE_DROPPED;
+ if (key->name == SOLVABLE_HEADEREND)
+ return KEY_STORAGE_DROPPED;
+ if (key->name == SOLVABLE_PACKAGER)
+ return KEY_STORAGE_DROPPED;
+ if (key->name == SOLVABLE_GROUP)
+ return KEY_STORAGE_DROPPED;
+ if (key->name == SOLVABLE_LICENSE)
+ return KEY_STORAGE_DROPPED;
+ i = repo_write_stdkeyfilter(repo, key, kfdata);
+ if (i == KEY_STORAGE_VERTICAL_OFFSET)
+ return KEY_STORAGE_DROPPED;
+ return i;
+}
+
+static inline char *
+hvlookupstr(HV *hv, const char *key, int keyl)
+{
+ SV **svp = hv_fetch(hv, key, keyl, 0);
+ if (!svp)
+ return 0;
+ return SvPV_nolen(*svp);
+}
+
+static inline AV *
+hvlookupav(HV *hv, const char *key, int keyl)
+{
+ SV *sv, **svp = hv_fetch(hv, key, keyl, 0);
+ if (!svp)
+ return 0;
+ sv = *svp;
+ if (!sv || !SvROK(sv) || SvTYPE(SvRV(sv)) != SVt_PVAV)
+ return 0;
+ return (AV *)SvRV(sv);
+}
+
+static Id
+makeevr(Pool *pool, char *e, char *v, char *r)
+{
+ char *s;
+
+ if (!v)
+ return 0;
+ if (e && !strcmp(e, "0"))
+ e = 0;
+ if (e)
+ s = pool_tmpjoin(pool, e, ":", v);
+ else
+ s = v;
+ if (r)
+ s = pool_tmpjoin(pool, s, "-", r);
+ return str2id(pool, s, 1);
+}
+
+static inline char *
+avlookupstr(AV *av, int n)
+{
+ SV **svp = av_fetch(av, n, 0);
+ if (!svp)
+ return 0;
+ return SvPV_nolen(*svp);
+}
+
+static inline Id
+id2name(Pool *pool, Id id)
+{
+ while (ISRELDEP(id))
+ {
+ Reldep *rd = GETRELDEP(pool, id);
+ id = rd->name;
+ }
+ return id;
+}
+
+static Id
+dep2id(Pool *pool, char *s)
+{
+ char *n;
+ Id id;
+ int flags;
+
+ if ((n = strchr(s, '|')) != 0)
+ {
+ id = dep2id(pool, n + 1);
+ *n = 0;
+ id = rel2id(pool, dep2id(pool, s), id, REL_OR, 1);
+ *n = '|';
+ return id;
+ }
+ while (*s == ' ' || *s == '\t')
+ s++;
+ n = s;
+ while (*s && *s != ' ' && *s != '\t' && *s != '<' && *s != '=' && *s != '>')
+ s++;
+ id = strn2id(pool, n, s - n, 1);
+ if (!*s)
+ return id;
+ while (*s == ' ' || *s == '\t')
+ s++;
+ flags = 0;
+ for (;;s++)
+ {
+ if (*s == '<')
+ flags |= REL_LT;
+ else if (*s == '=')
+ flags |= REL_EQ;
+ else if (*s == '>')
+ flags |= REL_GT;
+ else
+ break;
+ }
+ if (!flags)
+ return id;
+ while (*s == ' ' || *s == '\t')
+ s++;
+ return rel2id(pool, id, str2id(pool, s, 1), flags, 1);
+}
+
+static inline void
+expander_installed(Expander *xp, Id p, Map *installed, Map *conflicts, Queue *out, Queue *todo)
+{
+ Pool *pool = xp->pool;
+ Solvable *s = pool->solvables + p;
+ Id req, id, *reqp;
+ const char *n;
+
+ MAPSET(installed, p);
+ queue_push(out, p);
+ 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)
+ {
|