diff options
-rw-r--r-- | lib/depends.c | 36 | ||||
-rw-r--r-- | lib/order.c | 2 | ||||
-rw-r--r-- | lib/rpmdb.c | 4 | ||||
-rw-r--r-- | lib/rpmds.c | 5 | ||||
-rw-r--r-- | lib/rpmds.h | 3 |
5 files changed, 31 insertions, 19 deletions
diff --git a/lib/depends.c b/lib/depends.c index c73e64953..94842f961 100644 --- a/lib/depends.c +++ b/lib/depends.c @@ -733,30 +733,38 @@ retry: rpmdsNotify(dep, "(rich)", rc); goto exit; } - if (op == RPMRICHOP_IF) { + if (op == RPMRICHOP_IF || op == RPMRICHOP_UNLESS) { + /* A IF B -> A OR NOT(B) */ + /* A UNLESS B -> A AND NOT(B) */ if (rpmdsIsRich(ds2)) { - /* check if this is a IF...ELSE combination */ + /* check if this has an ELSE clause */ rpmds ds21 = NULL, ds22 = NULL; rpmrichOp op2; if (rpmdsParseRichDep(ds2, &ds21, &ds22, &op2, NULL) == RPMRC_OK && op2 == RPMRICHOP_ELSE) { - rc = unsatisfiedDepend(ts, dcache, ds21); - if (rc) { - rpmdsFree(ds1); - ds1 = ds22; - ds22 = NULL; + /* A IF B ELSE C -> (A OR NOT(B)) AND (C OR B) */ + /* A UNLESS B ELSE C -> (A AND NOT(B)) OR (C AND B) */ + rc = !unsatisfiedDepend(ts, dcache, ds21); /* NOT(B) */ + if ((rc && op == RPMRICHOP_IF) || (!rc && op == RPMRICHOP_UNLESS)) { + rc = unsatisfiedDepend(ts, dcache, ds1); /* A */ + } else { + rc = unsatisfiedDepend(ts, dcache, ds22); /* C */ } - rc = 1; + rpmdsFree(ds21); + rpmdsFree(ds22); + goto exitrich; } rpmdsFree(ds21); rpmdsFree(ds22); } - if (!rc) - rc = !unsatisfiedDepend(ts, dcache, ds2); - } - if (op != RPMRICHOP_IF || rc) + rc = !unsatisfiedDepend(ts, dcache, ds2); /* NOT(B) */ + if ((rc && op == RPMRICHOP_IF) || (!rc && op == RPMRICHOP_UNLESS)) + rc = unsatisfiedDepend(ts, dcache, ds1); + } else { rc = unsatisfiedDepend(ts, dcache, ds1); - if ((rc && op == RPMRICHOP_OR) || (!rc && op == RPMRICHOP_AND)) - rc = unsatisfiedDepend(ts, dcache, ds2); + if ((rc && op == RPMRICHOP_OR) || (!rc && op == RPMRICHOP_AND)) + rc = unsatisfiedDepend(ts, dcache, ds2); + } +exitrich: ds1 = rpmdsFree(ds1); ds2 = rpmdsFree(ds2); rpmdsNotify(dep, "(rich)", rc); diff --git a/lib/order.c b/lib/order.c index 854f37e98..50fde30aa 100644 --- a/lib/order.c +++ b/lib/order.c @@ -159,7 +159,7 @@ static inline int addRelation(rpmts ts, if (rpmdsParseRichDep(requires, &ds1, &ds2, &op, NULL) == RPMRC_OK) { if (op != RPMRICHOP_ELSE) addRelation(ts, al, p, ds1); - if (op == RPMRICHOP_IF) { + if (op == RPMRICHOP_IF || op == RPMRICHOP_UNLESS) { rpmds ds21, ds22; rpmrichOp op2; if (rpmdsParseRichDep(requires, &ds21, &ds22, &op2, NULL) == RPMRC_OK && op2 == RPMRICHOP_ELSE) { diff --git a/lib/rpmdb.c b/lib/rpmdb.c index 9469ede33..a17a89f20 100644 --- a/lib/rpmdb.c +++ b/lib/rpmdb.c @@ -2194,7 +2194,7 @@ static rpmRC updateRichDepCB(void *cbdata, rpmrichParseType type, data->nargv++; _free(name); } - if (type == RPMRICH_PARSE_OP && op == RPMRICHOP_IF) { + if (type == RPMRICH_PARSE_OP && (op == RPMRICHOP_IF || op == RPMRICHOP_UNLESS)) { /* save nargv in case of ELSE */ data->nargv_level[data->level - 1] = data->nargv; data->neg ^= 1; @@ -2211,7 +2211,7 @@ static rpmRC updateRichDepCB(void *cbdata, rpmrichParseType type, } data->neg ^= 1; } - if (type == RPMRICH_PARSE_LEAVE && op == RPMRICHOP_IF) { + if (type == RPMRICH_PARSE_LEAVE && (op == RPMRICHOP_IF || op == RPMRICHOP_UNLESS)) { data->neg ^= 1; } return RPMRC_OK; diff --git a/lib/rpmds.c b/lib/rpmds.c index be788d7e2..c57ac1f7f 100644 --- a/lib/rpmds.c +++ b/lib/rpmds.c @@ -1357,6 +1357,7 @@ static struct RichOpComp { { "and", RPMRICHOP_AND}, { "or", RPMRICHOP_OR}, { "if", RPMRICHOP_IF}, + { "unless", RPMRICHOP_UNLESS}, { "else", RPMRICHOP_ELSE}, { "with", RPMRICHOP_WITH}, { "without", RPMRICHOP_WITHOUT}, @@ -1397,6 +1398,8 @@ const char *rpmrichOpStr(rpmrichOp op) return "or"; if (op == RPMRICHOP_IF) return "if"; + if (op == RPMRICHOP_UNLESS) + return "unless"; if (op == RPMRICHOP_ELSE) return "else"; if (op == RPMRICHOP_WITH) @@ -1492,7 +1495,7 @@ static rpmRC rpmrichParseInternal(const char **dstrp, char **emsg, rpmrichParseF pe = p; if (parseRichDepOp(&pe, &op, emsg) != RPMRC_OK) return RPMRC_FAIL; - if (op == RPMRICHOP_ELSE && chainop == RPMRICHOP_IF) + if (op == RPMRICHOP_ELSE && (chainop == RPMRICHOP_IF || chainop == RPMRICHOP_UNLESS)) chainop = 0; if (chainop && op != chainop) { if (emsg) diff --git a/lib/rpmds.h b/lib/rpmds.h index 8f1c0c3ef..b1a587dfa 100644 --- a/lib/rpmds.h +++ b/lib/rpmds.h @@ -470,7 +470,8 @@ typedef enum rpmrichOp_e { RPMRICHOP_IF = 4, RPMRICHOP_ELSE = 5, RPMRICHOP_WITH = 6, - RPMRICHOP_WITHOUT = 7 + RPMRICHOP_WITHOUT = 7, + RPMRICHOP_UNLESS = 8 } rpmrichOp; typedef enum rpmrichParseType_e { |