summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Schroeder <mls@suse.de>2012-11-15 11:39:19 +0100
committerMichael Schroeder <mls@suse.de>2012-11-15 11:39:19 +0100
commit4b6ae8c6a7047e610a4631884a7a9c7b1f574454 (patch)
tree1179019d3234a9029b2930b7dd8deeac4ed3bff1
parentd4b8348a7d0c37e866195a33f62b032582300c34 (diff)
downloadlibsolv-4b6ae8c6a7047e610a4631884a7a9c7b1f574454.tar.gz
libsolv-4b6ae8c6a7047e610a4631884a7a9c7b1f574454.tar.bz2
libsolv-4b6ae8c6a7047e610a4631884a7a9c7b1f574454.zip
improve magic epoch promotion code to work better when multiple epochs match
-rw-r--r--src/selection.c78
1 files changed, 47 insertions, 31 deletions
diff --git a/src/selection.c b/src/selection.c
index cdf071e..32d4e28 100644
--- a/src/selection.c
+++ b/src/selection.c
@@ -549,16 +549,20 @@ static void
selection_limit_evr(Pool *pool, Queue *selection, char *evr)
{
int i, j;
+ Queue q;
+ Id qbuf[10];
+
+ queue_init(&q);
+ queue_init_buffer(&q, qbuf, sizeof(qbuf)/sizeof(*qbuf));
for (i = j = 0; i < selection->count; i += 2)
{
Id select = selection->elements[i] & SOLVER_SELECTMASK;
Id id = selection->elements[i + 1];
Id p, pp;
- Queue tmpq;
- Id tmpqb[2];
- const char *highest = 0;
- int highestlen = 0;
+ const char *lastepoch = 0;
+ int lastepochlen = 0;
+ queue_empty(&q);
FOR_JOB_SELECT(p, pp, select, id)
{
Solvable *s = pool->solvables + p;
@@ -566,50 +570,62 @@ selection_limit_evr(Pool *pool, Queue *selection, char *evr)
const char *sp;
for (sp = sevr; *sp >= '0' && *sp <= '9'; sp++)
;
- if (sp == sevr || *sp != ':')
- continue;
- /* found epoch, compare vr */
- if (strcmp(sp + 1, evr) != 0)
+ if (*sp != ':')
+ sp = sevr;
+ /* compare vr part */
+ if (strcmp(evr, sp != sevr ? sp + 1 : sevr) != 0)
{
- int r = pool_evrcmp_str(pool, sp + 1, evr, EVRCMP_DEPCMP);
+ int r = pool_evrcmp_str(pool, sp != sevr ? sp + 1 : sevr, evr, EVRCMP_DEPCMP);
if (r == -1 || r == 1)
- continue; /* no match */
+ continue; /* solvable does not match vr */
}
- if (highest)
+ queue_push(&q, p);
+ if (sp > sevr)
{
- if (highestlen == sp - sevr && !strncmp(highest, sevr, highestlen))
- continue;
- if (pool_evrcmp_str(pool, sevr, highest, EVRCMP_COMPARE) <= 0)
- continue;
+ while (sevr < sp && *sevr == '0') /* normalize */
+ sevr++;
}
- highest = sevr;
- highestlen = sp - sevr;
+ if (!lastepoch)
+ {
+ lastepoch = sevr;
+ lastepochlen = sp - sevr;
+ }
+ else if (lastepochlen != sp - sevr || strncmp(lastepoch, sevr, lastepochlen) != 0)
+ lastepochlen = -1; /* multiple different epochs */
}
- if (highest)
+ if (!lastepoch || lastepochlen == 0)
+ id = pool_str2id(pool, evr, 1); /* no match at all or zero epoch */
+ else if (lastepochlen >= 0)
{
- /* found epoch, prepend */
- char *evrx = solv_malloc(strlen(evr) + highestlen + 2);
- strncpy(evrx, highest, highestlen + 1);
- strcpy(evrx + highestlen + 1, evr);
+ /* found exactly one epoch, simlpy prepend */
+ char *evrx = solv_malloc(strlen(evr) + lastepochlen + 2);
+ strncpy(evrx, lastepoch, lastepochlen + 1);
+ strcpy(evrx + lastepochlen + 1, evr);
id = pool_str2id(pool, evrx, 1);
solv_free(evrx);
}
else
- id = pool_str2id(pool, evr, 1);
- queue_init_buffer(&tmpq, tmpqb, sizeof(tmpqb)/sizeof(*tmpqb));
- queue_push2(&tmpq, selection->elements[i], selection->elements[i + 1]);
- selection_limit_rel(pool, &tmpq, REL_EQ, id);
- if (!tmpq.count)
{
- queue_free(&tmpq);
+ /* multiple epochs in multiple solvables, convert to listy of solvables */
+ selection->elements[j] = (selection->elements[i] & ~SOLVER_SELECTMASK) | SOLVER_SOLVABLE_ONE_OF;
+ selection->elements[j + 1] = pool_queuetowhatprovides(pool, &q);
+ j += 2;
+ continue;
+ }
+ queue_empty(&q);
+ queue_push2(&q, selection->elements[i], selection->elements[i + 1]);
+ selection_limit_rel(pool, &q, REL_EQ, id);
+ if (!q.count)
+ {
+ queue_free(&q);
continue; /* oops, no match */
}
- selection->elements[j] = tmpq.elements[0];
- selection->elements[j + 1] = tmpq.elements[1];
- queue_free(&tmpq);
+ selection->elements[j] = q.elements[0];
+ selection->elements[j + 1] = q.elements[1];
j += 2;
}
queue_truncate(selection, j);
+ queue_free(&q);
}
static int