+/* installed packages involed in a dup operation can only be kept
+ * if they are identical to a non-installed one */
+static void
+solver_prune_installed_dup_packages(Solver *solv, Queue *plist)
+{
+ Pool *pool = solv->pool;
+ int i, j, bestprio = 0;
+
+ /* find bestprio (again) */
+ for (i = 0; i < plist->count; i++)
+ {
+ Solvable *s = pool->solvables + plist->elements[i];
+ if (s->repo != pool->installed)
+ {
+ bestprio = s->repo->priority;
+ break;
+ }
+ }
+ if (i == plist->count)
+ return; /* only installed packages, could not find prio */
+ for (i = j = 0; i < plist->count; i++)
+ {
+ Id p = plist->elements[i];
+ Solvable *s = pool->solvables + p;
+ if (s->repo != pool->installed && s->repo->priority < bestprio)
+ continue;
+ if (s->repo == pool->installed && (solv->dupmap_all || (solv->dupinvolvedmap.size && MAPTST(&solv->dupinvolvedmap, p))))
+ {
+ Id p2, pp2;
+ int keepit = 0;
+ FOR_PROVIDES(p2, pp2, s->name)
+ {
+ Solvable *s2 = pool->solvables + p2;
+ if (s2->repo == pool->installed || s2->evr != s->evr || s2->repo->priority < bestprio)
+ continue;
+ if (!solvable_identical(s, s2))
+ continue;
+ keepit = 1;
+ if (s2->repo->priority > bestprio)
+ {
+ /* new max prio! */
+ bestprio = s2->repo->priority;
+ j = 0;
+ }
+ }
+ if (!keepit)
+ continue; /* no identical package found, ignore installed package */
+ }
+ plist->elements[j++] = p;
+ }
+ if (j)
+ plist->count = j;
+}
+
+/*
+ * like prune_to_highest_prio, but calls solver prune_installed_dup_packages
+ * when there are dup packages
+ */
+static inline void
+solver_prune_to_highest_prio(Solver *solv, Queue *plist)
+{
+ prune_to_highest_prio(solv->pool, plist);
+ if (plist->count > 1 && solv->pool->installed && (solv->dupmap_all || solv->dupinvolvedmap.size))
+ solver_prune_installed_dup_packages(solv, plist);
+}
+
+
+static void
+solver_prune_to_highest_prio_per_name(Solver *solv, Queue *plist)
+{
+ Pool *pool = solv->pool;
+ Queue pq;
+ int i, j, k;
+ Id name;
+
+ queue_init(&pq);
+ solv_sort(plist->elements, plist->count, sizeof(Id), prune_to_best_version_sortcmp, pool);
+ queue_push(&pq, plist->elements[0]);
+ name = pool->solvables[pq.elements[0]].name;
+ for (i = 1, j = 0; i < plist->count; i++)
+ {
+ if (pool->solvables[plist->elements[i]].name != name)
+ {
+ if (pq.count > 2)
+ solver_prune_to_highest_prio(solv, &pq);
+ for (k = 0; k < pq.count; k++)
+ plist->elements[j++] = pq.elements[k];
+ queue_empty(&pq);
+ queue_push(&pq, plist->elements[i]);
+ name = pool->solvables[pq.elements[0]].name;
+ }
+ }
+ if (pq.count > 2)
+ solver_prune_to_highest_prio(solv, &pq);
+ for (k = 0; k < pq.count; k++)
+ plist->elements[j++] = pq.elements[k];
+ queue_free(&pq);
+ plist->count = j;
+}
+
+
+#ifdef ENABLE_COMPLEX_DEPS
+
+static void
+check_complex_dep(Solver *solv, Id dep, Map *m, Queue **cqp)
+{
+ Pool *pool = solv->pool;
+ Queue q;
+ queue_init(&q);
+ Id p;
+ int i, qcnt;
+
+#if 0
+ printf("check_complex_dep %s\n", pool_dep2str(pool, dep));
+#endif
+ i = pool_normalize_complex_dep(pool, dep, &q, CPLXDEPS_EXPAND);
+ if (i == 0 || i == 1)
+ {
+ queue_free(&q);
+ return;
+ }
+ qcnt = q.count;
+ for (i = 0; i < qcnt; i++)
+ {
+ for (; (p = q.elements[i]) != 0; i++)
+ {
+ if (p < 0)
+ {
+ if (solv->decisionmap[-p] > 0)
+ continue;
+ if (solv->decisionmap[-p] < 0)
+ break;
+ queue_push(&q, -p);
+ }
+ if (p > 0 && qcnt == q.count)
+ MAPSET(m, p);
+ }
+ if (q.elements[i])
+ {
+#if 0
+ printf("complex dep block cannot be true\n");
+#endif
+ while (q.elements[i])
+ i++;
+ if (qcnt != q.count)
+ queue_truncate(&q, qcnt);
+ }
+ else if (qcnt != q.count)
+ {
+ int j, k;
+ Queue *cq = *cqp;
+#if 0
+ printf("add new complex dep block\n");
+ for (j = qcnt; j < q.count; j++)
+ printf(" - %s\n", pool_solvid2str(pool, q.elements[j]));
+#endif
+ if (!cq)
+ {
+ cq = solv_calloc(1, sizeof(Queue));
+ queue_init(cq);
+ *cqp = cq;
+ queue_insertn(cq, 0, 256, 0);
+ }
+ for (j = qcnt; j < q.count; j++)
+ {
+ p = q.elements[j];
+ for (k = 256; k < cq->count; k += 2)
+ if (cq->elements[k + 1] == dep && cq->elements[k] == p)
+ break;
+ if (k == cq->count)
+ {
+ queue_push2(cq, p, dep);
+ cq->elements[p & 255] |= (1 << (p >> 8 & 31));
+ }
+ }
+ queue_truncate(&q, qcnt);
+ }
+ }
+ queue_free(&q);
+}
+
+static void
+recheck_complex_dep(Solver *solv, Id p, Map *m, Queue **cqp)
+{
+ Queue *cq = *cqp;
+ int i;
+#if 0
+ printf("recheck_complex_dep for package %s\n", pool_solvid2str(solv->pool, p));
+#endif
+ for (i = 256; i < cq->count; i += 2)
+ if (cq->elements[i] == p)
+ break;
+ if (i == cq->count)
+ return; /* false alert */
+ if (solv->decisionmap[p] <= 0)
+ return; /* just in case... */
+ memset(cq->elements, 0, sizeof(Id) * 256);
+ for (i = 256; i < cq->count; i += 2)
+ if (cq->elements[i] == p)
+ {
+ Id dep = cq->elements[i + 1];
+ queue_deleten(cq, i, 2);
+ i -= 2;
+ check_complex_dep(solv, dep, m, &cq);
+ }
+ else
+ {
+ Id pp = cq->elements[i];
+ cq->elements[pp & 255] |= (1 << (pp >> 8 & 31));
+ }
+}
+
+#endif
+