1 diff -ur poldek-0.42.2/capreq.h poldek-0.42.2-boolean-deps/capreq.h
2 --- poldek-0.42.2/capreq.h 2020-01-25 22:59:59.000000000 +0100
3 +++ poldek-0.42.2-boolean-deps/capreq.h 2022-06-08 20:48:12.797280673 +0200
5 char _buff[0]; /* for evr, first byte is always '\0' */
8 +#define CAPREQ_BOOL_OP_AND (1 << 0)
9 +#define CAPREQ_BOOL_OP_OR (1 << 1)
10 +#define CAPREQ_BOOL_OP_IF (1 << 2)
11 +#define CAPREQ_BOOL_OP_UNLESS (1 << 3)
12 +#define CAPREQ_BOOL_OP_ELSE (1 << 4)
13 +#define CAPREQ_BOOL_OP_WITH (1 << 5)
14 +#define CAPREQ_BOOL_OP_WITHOUT (1 << 6)
17 + uint16_t op; // and, or, ir (else), with, without, unless (else)
19 + struct boolean_req* left; // left (and|or|with|without) right
20 + struct boolean_req* leftn; // left (if|unless) right (else leftn)
21 + struct boolean_req* right;
24 /* CAUTION: side effects! */
25 #define capreq_name(cr) (cr)->name
26 #define capreq_name_len(cr) (cr)->namelen
27 diff -ur poldek-0.42.2/install3/requirements.c poldek-0.42.2-boolean-deps/install3/requirements.c
28 --- poldek-0.42.2/install3/requirements.c 2020-04-06 14:24:18.000000000 +0200
29 +++ poldek-0.42.2-boolean-deps/install3/requirements.c 2022-06-08 20:48:12.797280673 +0200
34 -static int skip_boolean_dep(const struct capreq *cr) {
35 - if (capreq_is_boolean(cr)) {
36 - logn(LOGWARN, "%s: skipping boolean dependency (not supported yet)",
39 +static struct BooleanOpComp {
44 + { "and", 3, CAPREQ_BOOL_OP_AND },
45 + { "or", 2, CAPREQ_BOOL_OP_OR },
46 + { "if", 2, CAPREQ_BOOL_OP_IF },
47 + { "unless", 6, CAPREQ_BOOL_OP_UNLESS },
48 + { "with", 4, CAPREQ_BOOL_OP_WITH },
49 + { "without", 7, CAPREQ_BOOL_OP_WITHOUT },
53 +static struct capreq* parse_single_dep(char *req, int *len) {
54 + char *q, *cap, *name, *evr = NULL;
55 + int name_len, evr_len;
56 + struct capreq* cr = NULL;
59 + cap = q = strdup(req);
64 + DBGF("ltrim: %s", q);
66 + // look for the end of normal dep
69 + name_len = q - name;
70 + DBGF("to parse: %s, name: %s, name_len: %d", q, name, name_len);
73 + DBGF("ltrim: %s", q);
86 + DBGF("to parse: %s, op: %d", q, op);
89 + DBGF("ltrim: %s", q);
92 + while (*q != ' ' && *q != ')')
95 + DBGF("to parse: evr: %s, evr_len: %d", evr, evr_len);
97 + DBGF("to parse: %s", q);
100 + DBGF("ltrim: %s", q);
102 + *(name + name_len) = '\0';
103 + DBGF("name: %s, name_len: %d", name, name_len);
105 + *(evr + evr_len) = '\0';
106 + DBGF("evr: %s, evr_len: %d", evr, evr_len);
108 + cr = capreq_new_evr(NULL, name, evr, op, 0);
113 +static struct boolean_req* parse_boolean_dep(const char *strreq, uint16_t op, int* len) {
115 + struct boolean_req *breq;
117 + struct BooleanOpComp *o;
119 + cap = p = strdup(strreq);
120 + // boolean dep must start with '(' except if we're chaining 'and' or 'or'
121 + if (op != CAPREQ_BOOL_OP_AND && op != CAPREQ_BOOL_OP_OR) {
126 + DBGF("breq: %s", p);
127 + breq = malloc(sizeof(struct boolean_req));
128 + bzero(breq, sizeof(struct boolean_req));
132 + DBGF("breq ltrim: %s", p);
136 + breq->left = parse_boolean_dep(p, 0, &parsed_len);
138 + breq->req = parse_single_dep(p, &parsed_len);
140 + DBGF("breq to parse: %s", q);
148 + for (o = BooleanOps; o->n; o++)
149 + if (!strncmp(q, o->n, o->l))
153 + DBGF("fail no-op");
160 + breq->right = parse_boolean_dep(q, breq->op, &parsed_len);
162 + breq->right = malloc(sizeof(struct boolean_req));
163 + bzero(breq->right, sizeof(struct boolean_req));
164 + breq->right->req = parse_single_dep(q, &parsed_len);
173 + if (breq->op == CAPREQ_BOOL_OP_IF || breq->op == CAPREQ_BOOL_OP_UNLESS) {
174 + if (!strncmp(q, "else", 4)) {
179 + breq->leftn = parse_boolean_dep(q, breq->op, &parsed_len);
181 + breq->leftn = malloc(sizeof(struct boolean_req));
182 + bzero(breq->leftn, sizeof(struct boolean_req));
183 + breq->leftn->req = parse_single_dep(q, &parsed_len);
189 + if (*q != ')' && op != CAPREQ_BOOL_OP_AND && op != CAPREQ_BOOL_OP_OR) {
190 + DBGF("fail no closing paren");
205 +// i3pkg - package to be installed
206 +// req - dependency we are looking for
207 static int process_req(int indent, struct i3ctx *ictx,
208 - struct i3pkg *i3pkg, const struct capreq *req)
209 + struct i3pkg *i3pkg, const struct capreq *req, int boolean)
211 struct poldek_ts *ts = ictx->ts; /* just for short */
212 struct pkg *pkg, *tomark = NULL;
215 errfmt = _("%s: req %s not found");
217 - i3_error(ictx, pkg, I3ERR_NOTFOUND, errfmt, pkg_id(pkg), strreq);
219 + i3_error(ictx, pkg, I3ERR_NOTFOUND, errfmt, pkg_id(pkg), strreq);
227 +static int process_boolean_req(int indent, struct i3ctx *ictx,
228 + struct i3pkg *i3pkg, const struct boolean_req *breq)
232 + rcl = process_req(indent, ictx, i3pkg, breq->req, 1);
234 + rcl = process_boolean_req(indent, ictx, i3pkg, breq->left);
235 + if (breq->op != CAPREQ_BOOL_OP_OR)
237 + rcr = process_boolean_req(indent, ictx, i3pkg, breq->right);
240 + switch (breq->op) {
241 + case CAPREQ_BOOL_OP_AND:
242 + return (rcl > 0 && rcr > 0) ? 1 : -1;
243 + case CAPREQ_BOOL_OP_OR:
244 + if (rcl <= 0 && breq->right)
245 + return process_boolean_req(indent, ictx, i3pkg, breq->right);
247 + case CAPREQ_BOOL_OP_IF:
251 + return process_boolean_req(indent, ictx, i3pkg, breq->leftn);
253 + case CAPREQ_BOOL_OP_UNLESS:
257 + return process_boolean_req(indent, ictx, i3pkg, breq->leftn);
259 + case CAPREQ_BOOL_OP_WITH:
260 + // TODO: check that both deps are stisfied by the same package
261 + return (rcl > 0 && rcr > 0) ? 1 : -1;
262 + case CAPREQ_BOOL_OP_WITHOUT:
263 + // TODO: check that both deps are stisfied by the same package
264 + return (rcl > 0 && rcr <= 0) ? 1 : -1;
271 static tn_array *with_suggests(int indent, struct i3ctx *ictx, struct pkg *pkg)
274 struct pkg *oldpkg = NULL;
275 char *autochoice = NULL; /* testing only */
277 + struct boolean_req* breq;
279 if (pkg->sugs == NULL)
283 //trace(indent, "%d) suggested %s", i, reqstr);
285 - if (skip_boolean_dep(req))
286 + if (capreq_is_boolean(req)) {
287 + logn(LOGWARN, "%s: skipping boolean dependency (weak deps not supported yet)",
290 + // breq = parse_boolean_dep(capreq_name(req), 0, NULL);
291 + // process_boolean_req(indent, ictx, i3pkg, breq);
295 if (iset_provides(ictx->inset, req)) {
296 trace(indent, "- %s: already marked", reqstr);
298 const struct capreq *req = NULL;
299 unsigned itflags = PKG_ITER_REQIN;
300 int nerrors = 0, backtrack = 0;
301 + struct boolean_req* breq;
305 @@ -806,10 +1011,18 @@
306 while ((req = pkg_req_iter_get(it))) {
309 - if (skip_boolean_dep(req))
311 + if (capreq_is_boolean(req)) {
312 + msgn_i(1, indent, "%s required by %s",
313 + capreq_stra(req), pkg->name ? pkg->name : "(null)");
314 + breq = parse_boolean_dep(capreq_name(req), 0, NULL);
315 + rc = process_boolean_req(indent + 2, ictx, i3pkg, breq);
317 + i3_error(ictx, i3pkg->pkg, I3ERR_NOTFOUND, _("%s: req %s not found"), pkg_id(i3pkg->pkg), capreq_stra(req));
319 + rc = process_req(indent, ictx, i3pkg, req, 0);
322 - if ((rc = process_req(indent, ictx, i3pkg, req)) <= 0) {
329 req = n_array_nth(suggests, i);
331 - if ((rc = process_req(indent, ictx, i3pkg, req)) <= 0) {
332 + if ((rc = process_req(indent, ictx, i3pkg, req, 0)) <= 0) {