continue;
}
if (!datamatcher_match(&di->matcher, di->kv.str))
- continue;
+ continue;
}
/* found something! */
return 1;
solv->pool = pool;
solv->installed = pool->installed;
+ queue_init(&solv->transaction);
+ queue_init(&solv->transaction_info);
queue_init(&solv->ruletojob);
queue_init(&solv->decisionq);
queue_init(&solv->decisionq_why);
void
solver_free(Solver *solv)
{
+ queue_free(&solv->transaction);
+ queue_free(&solv->transaction_info);
queue_free(&solv->job);
queue_free(&solv->ruletojob);
queue_free(&solv->decisionq);
map_free(&obsmap);
}
+
+Solver *obsq_sortcmp_data;
+
+static int
+obsq_sortcmp(const void *ap, const void *bp)
+{
+ Id a, b, oa, ob;
+ Solver *solv = obsq_sortcmp_data;
+ Pool *pool = solv->pool;
+ Solvable *s, *oas, *obs;
+ int r;
+
+ a = ((Id *)ap)[0];
+ oa = ((Id *)ap)[1];
+ b = ((Id *)bp)[0];
+ ob = ((Id *)bp)[1];
+ if (a != b)
+ return a - b;
+ if (oa == ob)
+ return 0;
+ s = pool->solvables + a;
+ oas = pool->solvables + oa;
+ obs = pool->solvables + ob;
+ if (oas->name != obs->name)
+ {
+ if (oas->name == s->name)
+ return -1;
+ if (obs->name == s->name)
+ return 1;
+ return strcmp(id2str(pool, oas->name), id2str(pool, obs->name));
+ }
+ r = evrcmp(pool, oas->evr, obs->evr, EVRCMP_COMPARE);
+ if (r)
+ return -r; /* highest version first */
+ return oa - ob;
+}
+
+void
+solver_transaction_info(Solver *solv, Id p, Queue *out)
+{
+ Pool *pool = solv->pool;
+ Solvable *s = pool->solvables + p;
+ Queue *ti = &solv->transaction_info;
+ int i;
+
+ queue_empty(out);
+ if (p <= 0 || !s->repo)
+ return;
+ if (s->repo == solv->installed)
+ {
+ /* find which packages obsolete us */
+ for (i = 0; i < ti->count; i += 2)
+ if (ti->elements[i + 1] == p)
+ {
+ queue_push(out, p);
+ queue_push(out, ti->elements[i]);
+ }
+ if (out->count > 2)
+ {
+ /* sort obsoleters */
+ obsq_sortcmp_data = solv;
+ qsort(out->elements, out->count / 2, 2 * sizeof(Id), obsq_sortcmp);
+ }
+ for (i = 0; i < out->count; i += 2)
+ out->elements[i] = out->elements[i / 2 + 1];
+ out->count /= 2;
+ }
+ else
+ {
+ /* find the packages we obsolete */
+ for (i = 0; i < ti->count; i += 2)
+ {
+ if (ti->elements[i] == p)
+ queue_push(out, ti->elements[i + 1]);
+ else if (out->count)
+ break;
+ }
+ }
+}
+
+Id
+solver_transaction_pkg(Solver *solv, Id p)
+{
+ Queue ti;
+ Id tibuf[5];
+
+ queue_init_buffer(&ti, tibuf, sizeof(tibuf)/sizeof(*tibuf));
+ solver_transaction_info(solv, p, &ti);
+ p = ti.count ? ti.elements[0] : 0;
+ queue_free(&ti);
+ return p;
+}
+
+static void
+create_transaction(Solver *solv)
+{
+ Pool *pool = solv->pool;
+ Repo *installed = solv->installed;
+ Queue *ti = &solv->transaction_info;
+ int i, j, r, noobs;
+ Id p, p2, pp2;
+ Solvable *s, *s2;
+
+ queue_empty(&solv->transaction);
+ queue_empty(ti);
+
+ /* first create obsoletes index */
+ if (installed)
+ {
+ for (i = 0; i < solv->decisionq.count; i++)
+ {
+ p = solv->decisionq.elements[i];
+ if (p <= 0 || p == SYSTEMSOLVABLE)
+ continue;
+ s = pool->solvables + p;
+ if (s->repo == installed)
+ continue;
+ noobs = solv->noobsoletes.size && MAPTST(&solv->noobsoletes, p);
+ FOR_PROVIDES(p2, pp2, s->name)
+ {
+ if (solv->decisionmap[p2] > 0)
+ continue;
+ s2 = pool->solvables + p2;
+ if (s2->repo != installed)
+ continue;
+ if (noobs && (s->name != s2->name || s->evr != s2->evr || s->arch != s2->arch))
+ continue;
+ if (!solv->implicitobsoleteusesprovides && s->name != s2->name)
+ continue;
+ queue_push(ti, p);
+ queue_push(ti, p2);
+ }
+ if (s->obsoletes && !noobs)
+ {
+ Id obs, *obsp = s->repo->idarraydata + s->obsoletes;
+ while ((obs = *obsp++) != 0)
+ {
+ FOR_PROVIDES(p2, pp2, obs)
+ {
+ s2 = pool->solvables + p2;
+ if (s2->repo != installed)
+ continue;
+ if (!solv->obsoleteusesprovides && !pool_match_nevr(pool, pool->solvables + p2, obs))
+ continue;
+ queue_push(ti, p);
+ queue_push(ti, p2);
+ }
+ }
+ }
+ }
+ obsq_sortcmp_data = solv;
+ qsort(ti->elements, ti->count / 2, 2 * sizeof(Id), obsq_sortcmp);
+ /* now unify */
+ for (i = j = 0; i < ti->count; i += 2)
+ {
+ if (j && ti->elements[i] == ti->elements[j - 2] && ti->elements[i + 1] == ti->elements[j - 1])
+ continue;
+ ti->elements[j++] = ti->elements[i];
+ ti->elements[j++] = ti->elements[i + 1];
+ }
+ ti->count = j;
+ }
+
+ if (installed)
+ {
+ FOR_REPO_SOLVABLES(installed, p, s)
+ {
+ if (solv->decisionmap[p] > 0)
+ continue;
+ p2 = solver_transaction_pkg(solv, p);
+ if (!p2)
+ queue_push(&solv->transaction, SOLVER_TRANSACTION_ERASE);
+ else
+ {
+ s2 = pool->solvables + p2;
+ if (s->name == s2->name)
+ {
+ if (s->evr == s2->evr && solvable_identical(s, s2))
+ queue_push(&solv->transaction, SOLVER_TRANSACTION_REINSTALLED);
+ else
+ {
+ r = evrcmp(pool, s->evr, s2->evr, EVRCMP_COMPARE);
+ if (r < 0)
+ queue_push(&solv->transaction, SOLVER_TRANSACTION_UPGRADED);
+ else if (r > 0)
+ queue_push(&solv->transaction, SOLVER_TRANSACTION_DOWNGRADED);
+ else
+ queue_push(&solv->transaction, SOLVER_TRANSACTION_CHANGED);
+ }
+ }
+ else
+ queue_push(&solv->transaction, SOLVER_TRANSACTION_OBSOLETED);
+ }
+ queue_push(&solv->transaction, p);
+ }
+ }
+ for (i = 0; i < solv->decisionq.count; i++)
+ {
+ p = solv->decisionq.elements[i];
+ if (p < 0 || p == SYSTEMSOLVABLE)
+ continue;
+ s = pool->solvables + p;
+ if (solv->installed && s->repo == solv->installed)
+ continue;
+ noobs = solv->noobsoletes.size && MAPTST(&solv->noobsoletes, p);
+ p2 = solver_transaction_pkg(solv, p);
+ if (noobs)
+ queue_push(&solv->transaction, p2 ? SOLVER_TRANSACTION_MULTIREINSTALL : SOLVER_TRANSACTION_MULTIINSTALL);
+ else if (!p2)
+ queue_push(&solv->transaction, SOLVER_TRANSACTION_INSTALL);
+ else
+ {
+ s2 = pool->solvables + p2;
+ if (s->name == s2->name)
+ {
+ if (s->evr == s2->evr && solvable_identical(s, s2))
+ queue_push(&solv->transaction, SOLVER_TRANSACTION_REINSTALL);
+ else
+ {
+ r = evrcmp(pool, s->evr, s2->evr, EVRCMP_COMPARE);
+ if (r > 0)
+ queue_push(&solv->transaction, SOLVER_TRANSACTION_UPGRADE);
+ else if (r < 0)
+ queue_push(&solv->transaction, SOLVER_TRANSACTION_DOWNGRADE);
+ else
+ queue_push(&solv->transaction, SOLVER_TRANSACTION_CHANGE);
+ }
+ }
+ else
+ queue_push(&solv->transaction, SOLVER_TRANSACTION_RENAME);
+ }
+ queue_push(&solv->transaction, p);
+ }
+}
+
/*
*
* solve job queue
}
solv->problems.count = j;
}
+
+ /*
+ * finally prepare transaction info
+ */
+ create_transaction(solv);
+
POOL_DEBUG(SAT_DEBUG_STATS, "final solver statistics: %d problems, %d learned rules, %d unsolvable\n", solv->problems.count / 2, solv->stats_learned, solv->stats_unsolvable);
POOL_DEBUG(SAT_DEBUG_STATS, "solver_solve took %d ms\n", sat_timems(solve_start));
}
Pool *pool;
Queue job; /* copy of the job we're solving */
+ Queue transaction; /* solver result */
+ Queue transaction_info; /* transaction obsoletes info */
+
Repo *installed; /* copy of pool->installed */
/* list of rules, ordered
#define SOLVER_SOLUTION_DISTUPGRADE (-1)
#define SOLVER_SOLUTION_INFARCH (-2)
+#define SOLVER_TRANSACTION_ERASE 0x10
+#define SOLVER_TRANSACTION_REINSTALLED 0x11
+#define SOLVER_TRANSACTION_DOWNGRADED 0x12
+#define SOLVER_TRANSACTION_CHANGED 0x13
+#define SOLVER_TRANSACTION_UPGRADED 0x14
+#define SOLVER_TRANSACTION_OBSOLETED 0x15
+
+#define SOLVER_TRANSACTION_INSTALL 0x20
+#define SOLVER_TRANSACTION_REINSTALL 0x21
+#define SOLVER_TRANSACTION_DOWNGRADE 0x22
+#define SOLVER_TRANSACTION_CHANGE 0x23
+#define SOLVER_TRANSACTION_UPGRADE 0x24
+#define SOLVER_TRANSACTION_RENAME 0x25
+
+#define SOLVER_TRANSACTION_MULTIINSTALL 0x30
+#define SOLVER_TRANSACTION_MULTIREINSTALL 0x31
+
+
extern Solver *solver_create(Pool *pool);
extern void solver_free(Solver *solv);
extern void solver_solve(Solver *solv, Queue *job);
+extern void solver_transaction_info(Solver *solv, Id p, Queue *info);
+extern Id solver_transaction_pkg(Solver *solv, Id p);
+
extern int solver_dep_installed(Solver *solv, Id dep);
extern int solver_splitprovides(Solver *solv, Id dep);
{
Pool *pool = solv->pool;
Repo *installed = solv->installed;
- Id p, *obsoletesmap = solver_create_decisions_obsoletesmap(solv);
- int i;
+ Id p;
+ int i, j;
Solvable *s;
+ Queue iq;
IF_POOLDEBUG (SAT_DEBUG_SCHUBI)
{
POOL_DEBUG(SAT_DEBUG_RESULT, "\n");
POOL_DEBUG(SAT_DEBUG_RESULT, "transaction:\n");
- /* print solvables to be erased */
-
- if (installed)
- {
- FOR_REPO_SOLVABLES(installed, p, s)
- {
- if (solv->decisionmap[p] > 0)
- continue;
- if (obsoletesmap[p])
- continue;
- POOL_DEBUG(SAT_DEBUG_RESULT, " erase %s\n", solvable2str(pool, s));
- }
- }
-
- /* print solvables to be installed */
-
- for (i = 0; i < solv->decisionq.count; i++)
+ queue_init(&iq);
+ for (i = 0; i < solv->transaction.count; i += 2)
{
- int j;
- p = solv->decisionq.elements[i];
- if (p < 0)
- continue;
- if (p == SYSTEMSOLVABLE)
- continue;
- s = pool->solvables + p;
- if (installed && s->repo == installed)
- continue;
-
- if (!obsoletesmap[p])
+ s = pool->solvables + solv->transaction.elements[i + 1];
+ switch(solv->transaction.elements[i])
{
+ case SOLVER_TRANSACTION_MULTI_INSTALL:
+ POOL_DEBUG(SAT_DEBUG_RESULT, " multi install %s", solvable2str(pool, s));
+ break;
+ case SOLVER_TRANSACTION_MULTI_REINSTALL:
+ POOL_DEBUG(SAT_DEBUG_RESULT, " multi reinstall %s", solvable2str(pool, s));
+ break;
+ case SOLVER_TRANSACTION_INSTALL:
POOL_DEBUG(SAT_DEBUG_RESULT, " install %s", solvable2str(pool, s));
+ break;
+ case SOLVER_TRANSACTION_REINSTALL:
+ POOL_DEBUG(SAT_DEBUG_RESULT, " reinstall %s", solvable2str(pool, s));
+ break;
+ case SOLVER_TRANSACTION_DOWNGRADE:
+ POOL_DEBUG(SAT_DEBUG_RESULT, " downgrade %s", solvable2str(pool, s));
+ break;
+ case SOLVER_TRANSACTION_CHANGE:
+ POOL_DEBUG(SAT_DEBUG_RESULT, " change %s", solvable2str(pool, s));
+ break;
+ case SOLVER_TRANSACTION_UPGRADE:
+ case SOLVER_TRANSACTION_RENAME:
+ POOL_DEBUG(SAT_DEBUG_RESULT, " upgrade %s", solvable2str(pool, s));
+ break;
+ case SOLVER_TRANSACTION_ERASE:
+ POOL_DEBUG(SAT_DEBUG_RESULT, " erase %s", solvable2str(pool, s));
+ break;
+ default:
+ break;
}
- else
- {
- Id xp, xpp;
- FOR_PROVIDES(xp, xpp, s->name)
+ switch(solv->transaction.elements[i])
+ {
+ case SOLVER_TRANSACTION_INSTALL:
+ case SOLVER_TRANSACTION_ERASE:
+ POOL_DEBUG(SAT_DEBUG_RESULT, "\n");
+ break;
+ case SOLVER_TRANSACTION_REINSTALL:
+ case SOLVER_TRANSACTION_DOWNGRADE:
+ case SOLVER_TRANSACTION_CHANGE:
+ case SOLVER_TRANSACTION_UPGRADE:
+ case SOLVER_TRANSACTION_RENAME:
+ solver_transaction_info(solv, solv->transaction.elements[i + 1], &iq);
+ if (iq.count)
{
- Solvable *s2 = pool->solvables + xp;
- if (s2->name != s->name)
- continue;
- if (evrcmp(pool, s->evr, s2->evr, EVRCMP_MATCH_RELEASE) < 0)
- break;
+ POOL_DEBUG(SAT_DEBUG_RESULT, " (obsoletes");
+ for (j = 0; j < iq.count; j++)
+ POOL_DEBUG(SAT_DEBUG_RESULT, " %s", solvable2str(pool, pool->solvables + iq.elements[j]));
+ POOL_DEBUG(SAT_DEBUG_RESULT, ")");
}
- if (xp)
- POOL_DEBUG(SAT_DEBUG_RESULT, " downgrade %s", solvable2str(pool, s));
- else
- POOL_DEBUG(SAT_DEBUG_RESULT, " upgrade %s", solvable2str(pool, s));
- POOL_DEBUG(SAT_DEBUG_RESULT, " (obsoletes");
- for (j = installed->start; j < installed->end; j++)
- if (obsoletesmap[j] == p)
- POOL_DEBUG(SAT_DEBUG_RESULT, " %s", solvable2str(pool, pool->solvables + j));
- POOL_DEBUG(SAT_DEBUG_RESULT, ")");
+ POOL_DEBUG(SAT_DEBUG_RESULT, "\n");
+ break;
+ default:
+ break;
}
- POOL_DEBUG(SAT_DEBUG_RESULT, "\n");
}
- POOL_DEBUG(SAT_DEBUG_RESULT, "\n");
+ queue_free(&iq);
- sat_free(obsoletesmap);
+ POOL_DEBUG(SAT_DEBUG_RESULT, "\n");
if (solv->recommendations.count)
{
return;
sevr = p + 1;
pool = s->repo->pool;
- name = id2str(pool, s->name);
- evr = id2str(pool, s->evr);
if (!strcmp(sarch, "src.rpm"))
repodata_set_constantid(data, handle, SOLVABLE_SOURCEARCH, ARCH_SRC);
else if (!strcmp(sarch, "nosrc.rpm"))
repodata_set_constantid(data, handle, SOLVABLE_SOURCEARCH, ARCH_NOSRC);
else
repodata_set_constantid(data, handle, SOLVABLE_SOURCEARCH, strn2id(pool, sarch, strlen(sarch) - 4, 1));
+ evr = id2str(pool, s->evr);
if (evr && !strncmp(sevr, evr, sarch - sevr - 1) && evr[sarch - sevr - 1] == 0)
repodata_set_void(data, handle, SOLVABLE_SOURCEEVR);
else
repodata_set_id(data, handle, SOLVABLE_SOURCEEVR, strn2id(pool, sevr, sarch - sevr - 1, 1));
+ name = id2str(pool, s->name);
if (name && !strncmp(sourcerpm, name, sevr - sourcerpm - 1) && name[sevr - sourcerpm - 1] == 0)
repodata_set_void(data, handle, SOLVABLE_SOURCENAME);
else