summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/depends.c36
-rw-r--r--lib/order.c2
-rw-r--r--lib/rpmdb.c4
-rw-r--r--lib/rpmds.c5
-rw-r--r--lib/rpmds.h3
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 {