+#ifdef ENABLE_LINKED_PKGS
+
+static void
+addlinks(Solver *solv, Solvable *s, Id req, Queue *qr, Id prv, Queue *qp, Map *m, Queue *workq)
+{
+ Pool *pool = solv->pool;
+ int i;
+ if (!qr->count)
+ return;
+#if 0
+ printf("ADDLINKS %s\n -> %s\n", pool_solvable2str(pool, s), pool_dep2str(pool, req));
+ for (i = 0; i < qr->count; i++)
+ printf(" - %s\n", pool_solvid2str(pool, qr->elements[i]));
+ printf(" <- %s\n", pool_dep2str(pool, prv));
+ for (i = 0; i < qp->count; i++)
+ printf(" - %s\n", pool_solvid2str(pool, qp->elements[i]));
+#endif
+
+ if (qr->count == 1)
+ addrpmrule(solv, qr->elements[0], -(s - pool->solvables), SOLVER_RULE_RPM_PACKAGE_REQUIRES, req);
+ else
+ addrpmrule(solv, -(s - pool->solvables), pool_queuetowhatprovides(pool, qr), SOLVER_RULE_RPM_PACKAGE_REQUIRES, req);
+ if (qp->count > 1)
+ {
+ Id d = pool_queuetowhatprovides(pool, qp);
+ for (i = 0; i < qr->count; i++)
+ addrpmrule(solv, -qr->elements[i], d, SOLVER_RULE_RPM_PACKAGE_REQUIRES, prv);
+ }
+ else if (qp->count)
+ {
+ for (i = 0; i < qr->count; i++)
+ addrpmrule(solv, qp->elements[0], -qr->elements[i], SOLVER_RULE_RPM_PACKAGE_REQUIRES, prv);
+ }
+ if (!m)
+ return; /* nothing more to do if called from getrpmruleinfos() */
+ for (i = 0; i < qr->count; i++)
+ if (!MAPTST(m, qr->elements[i]))
+ queue_push(workq, qr->elements[i]);
+ for (i = 0; i < qp->count; i++)
+ if (!MAPTST(m, qp->elements[i]))
+ queue_push(workq, qp->elements[i]);
+ if (solv->installed && s->repo == solv->installed)
+ {
+ Repo *installed = solv->installed;
+ /* record installed buddies */
+ if (!solv->instbuddy)
+ solv->instbuddy = solv_calloc(installed->end - installed->start, sizeof(Id));
+ if (qr->count == 1)
+ solv->instbuddy[s - pool->solvables - installed->start] = qr->elements[0];
+ for (i = 0; i < qp->count; i++)
+ {
+ Id p = qp->elements[i];
+ if (pool->solvables[p].repo != installed)
+ continue; /* huh? */
+ if (qp->count > 1 || (solv->instbuddy[p - installed->start] != 0 && solv->instbuddy[p - installed->start] != s - pool->solvables))
+ solv->instbuddy[p - installed->start] = 1; /* 1: ambiguous buddy */
+ else
+ solv->instbuddy[p - installed->start] = s - pool->solvables;
+ }
+ }
+}
+
+static void
+add_package_link(Solver *solv, Solvable *s, Map *m, Queue *workq)
+{
+ Queue qr, qp;
+ Id req = 0, prv = 0;
+ queue_init(&qr);
+ queue_init(&qp);
+ find_package_link(solv->pool, s, &req, &qr, &prv, &qp);
+ if (qr.count)
+ addlinks(solv, s, req, &qr, prv, &qp, m, workq);
+ queue_free(&qr);
+ queue_free(&qp);
+}
+
+#endif
+
+#ifdef ENABLE_COMPLEX_DEPS
+
+static void
+add_complex_deprules(Solver *solv, Id p, Id dep, int type, int dontfix, Queue *workq, Map *m)
+{
+ Pool *pool = solv->pool;
+ Repo *installed = solv->installed;
+ int i, j;
+ Queue bq;
+
+ queue_init(&bq);
+
+ /* CNF expansion for requires, DNF + INVERT expansion for conflicts */
+ i = pool_normalize_complex_dep(pool, dep, &bq, type == SOLVER_RULE_RPM_PACKAGE_REQUIRES ? 0 : (CPLXDEPS_TODNF | CPLXDEPS_EXPAND | CPLXDEPS_INVERT));
+ /* handle special cases */
+ if (i == 0)
+ {
+ if (dontfix)
+ {
+ POOL_DEBUG(SOLV_DEBUG_RULE_CREATION, "ignoring broken dependency %s of installed package %s\n", pool_dep2str(pool, dep), pool_solvid2str(pool, p));
+ }
+ else
+ {
+ POOL_DEBUG(SOLV_DEBUG_RULE_CREATION, "package %s [%d] is not installable (%s)\n", pool_solvid2str(pool, p), p, pool_dep2str(pool, dep));
+ addrpmrule(solv, -p, 0, type == SOLVER_RULE_RPM_PACKAGE_REQUIRES ? SOLVER_RULE_RPM_NOTHING_PROVIDES_DEP : type, dep);
+ }
+ queue_free(&bq);
+ return;
+ }
+ if (i == 1)
+ {
+ queue_free(&bq);
+ return;
+ }
+
+ /* go through all blocks and add a rule for each block */
+ for (i = 0; i < bq.count; i++)
+ {
+ if (!bq.elements[i])
+ continue; /* huh? */
+ if (bq.elements[i] == pool->nsolvables)
+ {
+ /* conventional requires (cannot be a conflicts as they have been expanded) */
+ Id *dp = pool->whatprovidesdata + bq.elements[i + 1];
+ i += 2;
+ if (dontfix)
+ {
+ for (j = 0; dp[j] != 0; j++)
+ if (pool->solvables[dp[j]].repo == installed)
+ break; /* provider was installed */
+ if (!dp[j])
+ {
+ POOL_DEBUG(SOLV_DEBUG_RULE_CREATION, "ignoring broken requires %s of installed package %s\n", pool_dep2str(pool, dep), pool_solvid2str(pool, p));
+ continue;
+ }
+ }
+ if (!*dp)
+ {
+ /* nothing provides req! */
+ POOL_DEBUG(SOLV_DEBUG_RULE_CREATION, "package %s [%d] is not installable (%s)\n", pool_solvid2str(pool, p), p, pool_dep2str(pool, dep));
+ addrpmrule(solv, -p, 0, SOLVER_RULE_RPM_NOTHING_PROVIDES_DEP, dep);
+ continue;
+ }
+ addrpmrule(solv, -p, dp - pool->whatprovidesdata, SOLVER_RULE_RPM_PACKAGE_REQUIRES, dep);
+ /* push all non-visited providers on the work queue */
+ if (m)
+ for (; *dp; dp++)
+ if (!MAPTST(m, *dp))
+ queue_push(workq, *dp);
+ continue;
+ }
+ if (!bq.elements[i + 1])
+ {
+ Id p2 = bq.elements[i];
+ /* simple rule with just two literals */
+ if (dontfix && p2 < 0 && pool->solvables[-p2].repo == installed)
+ continue;
+ if (dontfix && p2 > 0 && pool->solvables[p2].repo != installed)
+ continue;
+ if (p == p2)
+ continue;
+ if (-p == p2)
+ {
+ if (type == SOLVER_RULE_RPM_PACKAGE_CONFLICT)
+ {
+ if (pool->forbidselfconflicts && !is_otherproviders_dep(pool, dep))
+ addrpmrule(solv, -p, 0, SOLVER_RULE_RPM_SELF_CONFLICT, dep);
+ continue;
+ }
+ addrpmrule(solv, -p, 0, type, dep);
+ continue;
+ }
+ if (p2 > 0)
+ addrpmrule(solv, p2, -p, type, dep); /* hack so that we don't need pool_queuetowhatprovides */
+ else
+ addrpmrule(solv, -p, p2, type, dep);
+ if (m && p2 > 0 && !MAPTST(m, p2))
+ queue_push(workq, p2);
+ }
+ else
+ {
+ Id *qele;
+ int qcnt;
+
+ qele = bq.elements + i;
+ qcnt = i;
+ while (bq.elements[i])
+ i++;
+ qcnt = i - qcnt;
+ if (dontfix)
+ {
+ for (j = 0; j < qcnt; j++)
+ {
+ if (qele[j] > 0 && pool->solvables[qele[j]].repo == installed)
+ break;
+ if (qele[j] < 0 && pool->solvables[-qele[j]].repo != installed)
+ break;
+ }
+ if (j == qcnt)
+ continue;
+ }
+ /* add -p to (ordered) rule (overwriting the trailing zero) */
+ for (j = 0; ; j++)
+ {
+ if (j == qcnt || qele[j] > -p)
+ {
+ if (j < qcnt)
+ memmove(qele + j + 1, qele + j, (qcnt - j) * sizeof(Id));
+ qele[j] = -p;
+ qcnt++;
+ break;
+ }
+ if (qele[j] == -p)
+ break;
+ }
+ /* check if the rule contains both p and -p */
+ for (j = 0; j < qcnt; j++)
+ if (qele[j] == p)
+ break;
+ if (j == qcnt)
+ {
+ /* hack: create fake queue 'q' so that we can call pool_queuetowhatprovides */
+ Queue q;
+ memset(&q, 0, sizeof(q));
+ q.count = qcnt - 1;
+ q.elements = qele + 1;
+ addrpmrule(solv, qele[0], pool_queuetowhatprovides(pool, &q), type, dep);
+ if (m)
+ for (j = 0; j < qcnt; j++)
+ if (qele[j] > 0 && !MAPTST(m, qele[j]))
+ queue_push(workq, qele[j]);
+ }
+ }
+ }
+ queue_free(&bq);
+}
+
+#endif
+