X-Git-Url: https://git.tld-linux.org/?p=packages%2Fpoldek.git;a=blobdiff_plain;f=boolean-deps.patch;fp=boolean-deps.patch;h=325d1c7a7fea3130c5b967a083accfcab5809105;hp=0000000000000000000000000000000000000000;hb=6885e3f24ac122b1f5fa08f9349d967235a5a96d;hpb=4681641f45fcd4d3a57510e44ecb002ec390ae22 diff --git a/boolean-deps.patch b/boolean-deps.patch new file mode 100644 index 0000000..325d1c7 --- /dev/null +++ b/boolean-deps.patch @@ -0,0 +1,335 @@ +diff -ur poldek-0.42.2/capreq.h poldek-0.42.2-boolean-deps/capreq.h +--- poldek-0.42.2/capreq.h 2020-01-25 22:59:59.000000000 +0100 ++++ poldek-0.42.2-boolean-deps/capreq.h 2022-06-08 20:48:12.797280673 +0200 +@@ -58,6 +58,22 @@ + char _buff[0]; /* for evr, first byte is always '\0' */ + }; + ++#define CAPREQ_BOOL_OP_AND (1 << 0) ++#define CAPREQ_BOOL_OP_OR (1 << 1) ++#define CAPREQ_BOOL_OP_IF (1 << 2) ++#define CAPREQ_BOOL_OP_UNLESS (1 << 3) ++#define CAPREQ_BOOL_OP_ELSE (1 << 4) ++#define CAPREQ_BOOL_OP_WITH (1 << 5) ++#define CAPREQ_BOOL_OP_WITHOUT (1 << 6) ++ ++struct boolean_req { ++ uint16_t op; // and, or, ir (else), with, without, unless (else) ++ struct capreq* req; ++ struct boolean_req* left; // left (and|or|with|without) right ++ struct boolean_req* leftn; // left (if|unless) right (else leftn) ++ struct boolean_req* right; ++}; ++ + /* CAUTION: side effects! */ + #define capreq_name(cr) (cr)->name + #define capreq_name_len(cr) (cr)->namelen +diff -ur poldek-0.42.2/install3/requirements.c poldek-0.42.2-boolean-deps/install3/requirements.c +--- poldek-0.42.2/install3/requirements.c 2020-04-06 14:24:18.000000000 +0200 ++++ poldek-0.42.2-boolean-deps/install3/requirements.c 2022-06-08 20:48:12.797280673 +0200 +@@ -16,13 +16,163 @@ + + #include "ictx.h" + +-static int skip_boolean_dep(const struct capreq *cr) { +- if (capreq_is_boolean(cr)) { +- logn(LOGWARN, "%s: skipping boolean dependency (not supported yet)", +- capreq_stra(cr)); +- return 1; ++static struct BooleanOpComp { ++ const char *n; ++ int l; ++ uint16_t op; ++} BooleanOps[] = { ++ { "and", 3, CAPREQ_BOOL_OP_AND }, ++ { "or", 2, CAPREQ_BOOL_OP_OR }, ++ { "if", 2, CAPREQ_BOOL_OP_IF }, ++ { "unless", 6, CAPREQ_BOOL_OP_UNLESS }, ++ { "with", 4, CAPREQ_BOOL_OP_WITH }, ++ { "without", 7, CAPREQ_BOOL_OP_WITHOUT }, ++ { NULL, 0, 0}, ++}; ++ ++static struct capreq* parse_single_dep(char *req, int *len) { ++ char *q, *cap, *name, *evr = NULL; ++ int name_len, evr_len; ++ struct capreq* cr = NULL; ++ uint16_t op; ++ ++ cap = q = strdup(req); ++ DBGF("dep: %s", q); ++ // skip whitespace ++ while (*q == ' ') ++ q++; ++ DBGF("ltrim: %s", q); ++ name = q; ++ // look for the end of normal dep ++ while (*q != ' ') ++ q++; ++ name_len = q - name; ++ DBGF("to parse: %s, name: %s, name_len: %d", q, name, name_len); ++ while (*q == ' ') ++ q++; ++ DBGF("ltrim: %s", q); ++ op = 0; ++ while (*q != ' ') { ++ if (*q == '<') ++ op |= REL_LT; ++ else if (*q == '=') ++ op |= REL_EQ; ++ else if (*q == '>') ++ op |= REL_GT; ++ else ++ break; ++ q++; ++ } ++ DBGF("to parse: %s, op: %d", q, op); ++ while (*q == ' ') ++ q++; ++ DBGF("ltrim: %s", q); ++ if (op) { ++ evr = q; ++ while (*q != ' ' && *q != ')') ++ q++; ++ evr_len = q - evr; ++ DBGF("to parse: evr: %s, evr_len: %d", evr, evr_len); ++ } ++ DBGF("to parse: %s", q); ++ while (*q == ' ') ++ q++; ++ DBGF("ltrim: %s", q); ++ *len = q - cap; ++ *(name + name_len) = '\0'; ++ DBGF("name: %s, name_len: %d", name, name_len); ++ if (evr) { ++ *(evr + evr_len) = '\0'; ++ DBGF("evr: %s, evr_len: %d", evr, evr_len); ++ } ++ cr = capreq_new_evr(NULL, name, evr, op, 0); ++ free(cap); ++ return cr; ++} ++ ++static struct boolean_req* parse_boolean_dep(const char *strreq, uint16_t op, int* len) { ++ char *p, *q, *cap; ++ struct boolean_req *breq; ++ int parsed_len; ++ struct BooleanOpComp *o; ++ ++ cap = p = strdup(strreq); ++ // boolean dep must start with '(' except if we're chaining 'and' or 'or' ++ if (op != CAPREQ_BOOL_OP_AND && op != CAPREQ_BOOL_OP_OR) { ++ if (*p != '(') ++ return NULL; ++ p++; ++ } ++ DBGF("breq: %s", p); ++ breq = malloc(sizeof(struct boolean_req)); ++ bzero(breq, sizeof(struct boolean_req)); ++ // skip whitespace ++ while (*p == ' ') ++ p++; ++ DBGF("breq ltrim: %s", p); ++ // nested dep ++ q = p; ++ if (*p == '(') ++ breq->left = parse_boolean_dep(p, 0, &parsed_len); ++ else ++ breq->req = parse_single_dep(p, &parsed_len); ++ q += parsed_len; ++ DBGF("breq to parse: %s", q); ++ if (*q == ')') { ++ if (len) ++ *len = q - cap; ++ return breq; + } +- return 0; ++ ++ for (o = BooleanOps; o->n; o++) ++ if (!strncmp(q, o->n, o->l)) ++ break; ++ breq->op = o->op; ++ if (!breq->op) { ++ DBGF("fail no-op"); ++ return NULL; ++ } ++ q += o->l; ++ while (*q == ' ') ++ q++; ++ if (*q == '(') ++ breq->right = parse_boolean_dep(q, breq->op, &parsed_len); ++ else { ++ breq->right = malloc(sizeof(struct boolean_req)); ++ bzero(breq->right, sizeof(struct boolean_req)); ++ breq->right->req = parse_single_dep(q, &parsed_len); ++ } ++ q += parsed_len; ++ if (*q == ')') { ++ if (len) ++ *len = q - cap; ++ return breq; ++ } ++ ++ if (breq->op == CAPREQ_BOOL_OP_IF || breq->op == CAPREQ_BOOL_OP_UNLESS) { ++ if (!strncmp(q, "else", 4)) { ++ q += 4; ++ while (*q == ' ') ++ q++; ++ if (*q == '(') ++ breq->leftn = parse_boolean_dep(q, breq->op, &parsed_len); ++ else { ++ breq->leftn = malloc(sizeof(struct boolean_req)); ++ bzero(breq->leftn, sizeof(struct boolean_req)); ++ breq->leftn->req = parse_single_dep(q, &parsed_len); ++ } ++ } ++ } ++ while (*q == ' ') ++ q++; ++ if (*q != ')' && op != CAPREQ_BOOL_OP_AND && op != CAPREQ_BOOL_OP_OR) { ++ DBGF("fail no closing paren"); ++ return NULL; ++ } ++ ++ if (len) ++ *len = q - cap; ++ return breq; + } + + static +@@ -553,8 +703,11 @@ + + } + ++ ++// i3pkg - package to be installed ++// req - dependency we are looking for + static int process_req(int indent, struct i3ctx *ictx, +- struct i3pkg *i3pkg, const struct capreq *req) ++ struct i3pkg *i3pkg, const struct capreq *req, int boolean) + { + struct poldek_ts *ts = ictx->ts; /* just for short */ + struct pkg *pkg, *tomark = NULL; +@@ -644,7 +797,8 @@ + else + errfmt = _("%s: req %s not found"); + +- i3_error(ictx, pkg, I3ERR_NOTFOUND, errfmt, pkg_id(pkg), strreq); ++ if (boolean == 0) ++ i3_error(ictx, pkg, I3ERR_NOTFOUND, errfmt, pkg_id(pkg), strreq); + rc = 0; + + l_end: +@@ -653,6 +807,49 @@ + return rc; + } + ++static int process_boolean_req(int indent, struct i3ctx *ictx, ++ struct i3pkg *i3pkg, const struct boolean_req *breq) ++{ ++ int rcl, rcr, rce; ++ if (breq->req) ++ rcl = process_req(indent, ictx, i3pkg, breq->req, 1); ++ else ++ rcl = process_boolean_req(indent, ictx, i3pkg, breq->left); ++ if (breq->op != CAPREQ_BOOL_OP_OR) ++ if (breq->right) ++ rcr = process_boolean_req(indent, ictx, i3pkg, breq->right); ++ else ++ return rcl; ++ switch (breq->op) { ++ case CAPREQ_BOOL_OP_AND: ++ return (rcl > 0 && rcr > 0) ? 1 : -1; ++ case CAPREQ_BOOL_OP_OR: ++ if (rcl <= 0 && breq->right) ++ return process_boolean_req(indent, ictx, i3pkg, breq->right); ++ return rcl; ++ case CAPREQ_BOOL_OP_IF: ++ if (rcr > 0) ++ return rcl; ++ if (breq->leftn) ++ return process_boolean_req(indent, ictx, i3pkg, breq->leftn); ++ return 1; ++ case CAPREQ_BOOL_OP_UNLESS: ++ if (rcr <= 0) ++ return rcl; ++ if (breq->leftn) ++ return process_boolean_req(indent, ictx, i3pkg, breq->leftn); ++ return 1; ++ case CAPREQ_BOOL_OP_WITH: ++ // TODO: check that both deps are stisfied by the same package ++ return (rcl > 0 && rcr > 0) ? 1 : -1; ++ case CAPREQ_BOOL_OP_WITHOUT: ++ // TODO: check that both deps are stisfied by the same package ++ return (rcl > 0 && rcr <= 0) ? 1 : -1; ++ default: ++ return -1; ++ } ++ return -1; ++} + + static tn_array *with_suggests(int indent, struct i3ctx *ictx, struct pkg *pkg) + { +@@ -660,6 +857,7 @@ + struct pkg *oldpkg = NULL; + char *autochoice = NULL; /* testing only */ + int i; ++ struct boolean_req* breq; + + if (pkg->sugs == NULL) + return NULL; +@@ -693,8 +891,14 @@ + + //trace(indent, "%d) suggested %s", i, reqstr); + +- if (skip_boolean_dep(req)) ++ if (capreq_is_boolean(req)) { ++ logn(LOGWARN, "%s: skipping boolean dependency (weak deps not supported yet)", ++ capreq_stra(req)); ++ // TODO ++ // breq = parse_boolean_dep(capreq_name(req), 0, NULL); ++ // process_boolean_req(indent, ictx, i3pkg, breq); + continue; ++ } + + if (iset_provides(ictx->inset, req)) { + trace(indent, "- %s: already marked", reqstr); +@@ -791,6 +995,7 @@ + const struct capreq *req = NULL; + unsigned itflags = PKG_ITER_REQIN; + int nerrors = 0, backtrack = 0; ++ struct boolean_req* breq; + + pkg = i3pkg->pkg; + n_assert(pkg); +@@ -806,10 +1011,18 @@ + while ((req = pkg_req_iter_get(it))) { + int rc; + +- if (skip_boolean_dep(req)) +- continue; ++ if (capreq_is_boolean(req)) { ++ msgn_i(1, indent, "%s required by %s", ++ capreq_stra(req), pkg->name ? pkg->name : "(null)"); ++ breq = parse_boolean_dep(capreq_name(req), 0, NULL); ++ rc = process_boolean_req(indent + 2, ictx, i3pkg, breq); ++ if (rc <= 0) ++ i3_error(ictx, i3pkg->pkg, I3ERR_NOTFOUND, _("%s: req %s not found"), pkg_id(i3pkg->pkg), capreq_stra(req)); ++ } else { ++ rc = process_req(indent, ictx, i3pkg, req, 0); ++ } + +- if ((rc = process_req(indent, ictx, i3pkg, req)) <= 0) { ++ if (rc <= 0) { + nerrors++; + if (rc < 0) { + backtrack = 1; +@@ -836,7 +1049,7 @@ + + req = n_array_nth(suggests, i); + +- if ((rc = process_req(indent, ictx, i3pkg, req)) <= 0) { ++ if ((rc = process_req(indent, ictx, i3pkg, req, 0)) <= 0) { + nerrors++; + if (rc < 0) { + backtrack = 1;