]>
Commit | Line | Data |
---|---|---|
28d3fe2c JR |
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 | |
2d94f8f7 JR |
4 | @@ -58,6 +58,22 @@ |
5 | char _buff[0]; /* for evr, first byte is always '\0' */ | |
6 | }; | |
7 | ||
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) | |
15 | + | |
16 | +struct boolean_req { | |
17 | + uint16_t op; // and, or, ir (else), with, without, unless (else) | |
18 | + struct capreq* req; | |
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; | |
22 | +}; | |
23 | + | |
24 | /* CAUTION: side effects! */ | |
25 | #define capreq_name(cr) (cr)->name | |
26 | #define capreq_name_len(cr) (cr)->namelen | |
28d3fe2c JR |
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 | |
2d94f8f7 JR |
30 | @@ -16,13 +16,163 @@ |
31 | ||
32 | #include "ictx.h" | |
33 | ||
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)", | |
37 | - capreq_stra(cr)); | |
38 | - return 1; | |
39 | +static struct BooleanOpComp { | |
40 | + const char *n; | |
41 | + int l; | |
42 | + uint16_t op; | |
43 | +} BooleanOps[] = { | |
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 }, | |
50 | + { NULL, 0, 0}, | |
51 | +}; | |
52 | + | |
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; | |
57 | + uint16_t op; | |
58 | + | |
59 | + cap = q = strdup(req); | |
60 | + DBGF("dep: %s", q); | |
61 | + // skip whitespace | |
62 | + while (*q == ' ') | |
63 | + q++; | |
64 | + DBGF("ltrim: %s", q); | |
65 | + name = q; | |
66 | + // look for the end of normal dep | |
67 | + while (*q != ' ') | |
68 | + q++; | |
69 | + name_len = q - name; | |
70 | + DBGF("to parse: %s, name: %s, name_len: %d", q, name, name_len); | |
71 | + while (*q == ' ') | |
72 | + q++; | |
73 | + DBGF("ltrim: %s", q); | |
74 | + op = 0; | |
75 | + while (*q != ' ') { | |
76 | + if (*q == '<') | |
77 | + op |= REL_LT; | |
78 | + else if (*q == '=') | |
79 | + op |= REL_EQ; | |
80 | + else if (*q == '>') | |
81 | + op |= REL_GT; | |
82 | + else | |
83 | + break; | |
84 | + q++; | |
85 | + } | |
86 | + DBGF("to parse: %s, op: %d", q, op); | |
87 | + while (*q == ' ') | |
88 | + q++; | |
89 | + DBGF("ltrim: %s", q); | |
90 | + if (op) { | |
91 | + evr = q; | |
92 | + while (*q != ' ' && *q != ')') | |
93 | + q++; | |
94 | + evr_len = q - evr; | |
95 | + DBGF("to parse: evr: %s, evr_len: %d", evr, evr_len); | |
96 | + } | |
97 | + DBGF("to parse: %s", q); | |
98 | + while (*q == ' ') | |
99 | + q++; | |
100 | + DBGF("ltrim: %s", q); | |
101 | + *len = q - cap; | |
102 | + *(name + name_len) = '\0'; | |
103 | + DBGF("name: %s, name_len: %d", name, name_len); | |
104 | + if (evr) { | |
105 | + *(evr + evr_len) = '\0'; | |
106 | + DBGF("evr: %s, evr_len: %d", evr, evr_len); | |
107 | + } | |
108 | + cr = capreq_new_evr(NULL, name, evr, op, 0); | |
109 | + free(cap); | |
110 | + return cr; | |
111 | +} | |
112 | + | |
113 | +static struct boolean_req* parse_boolean_dep(const char *strreq, uint16_t op, int* len) { | |
114 | + char *p, *q, *cap; | |
115 | + struct boolean_req *breq; | |
116 | + int parsed_len; | |
117 | + struct BooleanOpComp *o; | |
118 | + | |
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) { | |
122 | + if (*p != '(') | |
123 | + return NULL; | |
124 | + p++; | |
125 | + } | |
126 | + DBGF("breq: %s", p); | |
127 | + breq = malloc(sizeof(struct boolean_req)); | |
128 | + bzero(breq, sizeof(struct boolean_req)); | |
129 | + // skip whitespace | |
130 | + while (*p == ' ') | |
131 | + p++; | |
132 | + DBGF("breq ltrim: %s", p); | |
133 | + // nested dep | |
134 | + q = p; | |
135 | + if (*p == '(') | |
136 | + breq->left = parse_boolean_dep(p, 0, &parsed_len); | |
137 | + else | |
138 | + breq->req = parse_single_dep(p, &parsed_len); | |
139 | + q += parsed_len; | |
140 | + DBGF("breq to parse: %s", q); | |
141 | + if (*q == ')') { | |
142 | + if (len) | |
143 | + *len = q - cap; | |
144 | + return breq; | |
28d3fe2c JR |
145 | } |
146 | - return 0; | |
2d94f8f7 JR |
147 | + |
148 | + for (o = BooleanOps; o->n; o++) | |
149 | + if (!strncmp(q, o->n, o->l)) | |
150 | + break; | |
151 | + breq->op = o->op; | |
152 | + if (!breq->op) { | |
153 | + DBGF("fail no-op"); | |
154 | + return NULL; | |
155 | + } | |
156 | + q += o->l; | |
157 | + while (*q == ' ') | |
158 | + q++; | |
159 | + if (*q == '(') | |
160 | + breq->right = parse_boolean_dep(q, breq->op, &parsed_len); | |
161 | + else { | |
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); | |
165 | + } | |
166 | + q += parsed_len; | |
167 | + if (*q == ')') { | |
168 | + if (len) | |
169 | + *len = q - cap; | |
170 | + return breq; | |
171 | + } | |
172 | + | |
173 | + if (breq->op == CAPREQ_BOOL_OP_IF || breq->op == CAPREQ_BOOL_OP_UNLESS) { | |
174 | + if (!strncmp(q, "else", 4)) { | |
175 | + q += 4; | |
176 | + while (*q == ' ') | |
177 | + q++; | |
178 | + if (*q == '(') | |
179 | + breq->leftn = parse_boolean_dep(q, breq->op, &parsed_len); | |
180 | + else { | |
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); | |
184 | + } | |
185 | + } | |
28d3fe2c | 186 | + } |
2d94f8f7 JR |
187 | + while (*q == ' ') |
188 | + q++; | |
189 | + if (*q != ')' && op != CAPREQ_BOOL_OP_AND && op != CAPREQ_BOOL_OP_OR) { | |
190 | + DBGF("fail no closing paren"); | |
191 | + return NULL; | |
192 | + } | |
193 | + | |
194 | + if (len) | |
195 | + *len = q - cap; | |
196 | + return breq; | |
197 | } | |
198 | ||
199 | static | |
28d3fe2c | 200 | @@ -553,8 +703,11 @@ |
2d94f8f7 JR |
201 | |
202 | } | |
203 | ||
204 | + | |
205 | +// i3pkg - package to be installed | |
206 | +// req - dependency we are looking for | |
207 | static int process_req(int indent, struct i3ctx *ictx, | |
28d3fe2c JR |
208 | - struct i3pkg *i3pkg, const struct capreq *req) |
209 | + struct i3pkg *i3pkg, const struct capreq *req, int boolean) | |
2d94f8f7 | 210 | { |
28d3fe2c JR |
211 | struct poldek_ts *ts = ictx->ts; /* just for short */ |
212 | struct pkg *pkg, *tomark = NULL; | |
213 | @@ -644,7 +797,8 @@ | |
214 | else | |
215 | errfmt = _("%s: req %s not found"); | |
216 | ||
217 | - i3_error(ictx, pkg, I3ERR_NOTFOUND, errfmt, pkg_id(pkg), strreq); | |
218 | + if (boolean == 0) | |
219 | + i3_error(ictx, pkg, I3ERR_NOTFOUND, errfmt, pkg_id(pkg), strreq); | |
220 | rc = 0; | |
221 | ||
222 | l_end: | |
223 | @@ -653,6 +807,49 @@ | |
2d94f8f7 JR |
224 | return rc; |
225 | } | |
226 | ||
227 | +static int process_boolean_req(int indent, struct i3ctx *ictx, | |
228 | + struct i3pkg *i3pkg, const struct boolean_req *breq) | |
229 | +{ | |
230 | + int rcl, rcr, rce; | |
231 | + if (breq->req) | |
28d3fe2c | 232 | + rcl = process_req(indent, ictx, i3pkg, breq->req, 1); |
2d94f8f7 JR |
233 | + else |
234 | + rcl = process_boolean_req(indent, ictx, i3pkg, breq->left); | |
c6ad8d0d JR |
235 | + if (breq->op != CAPREQ_BOOL_OP_OR) |
236 | + if (breq->right) | |
237 | + rcr = process_boolean_req(indent, ictx, i3pkg, breq->right); | |
238 | + else | |
239 | + return rcl; | |
2d94f8f7 JR |
240 | + switch (breq->op) { |
241 | + case CAPREQ_BOOL_OP_AND: | |
242 | + return (rcl > 0 && rcr > 0) ? 1 : -1; | |
243 | + case CAPREQ_BOOL_OP_OR: | |
c6ad8d0d JR |
244 | + if (rcl <= 0 && breq->right) |
245 | + return process_boolean_req(indent, ictx, i3pkg, breq->right); | |
246 | + return rcl; | |
2d94f8f7 JR |
247 | + case CAPREQ_BOOL_OP_IF: |
248 | + if (rcr > 0) | |
249 | + return rcl; | |
250 | + if (breq->leftn) | |
251 | + return process_boolean_req(indent, ictx, i3pkg, breq->leftn); | |
c6ad8d0d | 252 | + return 1; |
2d94f8f7 JR |
253 | + case CAPREQ_BOOL_OP_UNLESS: |
254 | + if (rcr <= 0) | |
255 | + return rcl; | |
256 | + if (breq->leftn) | |
257 | + return process_boolean_req(indent, ictx, i3pkg, breq->leftn); | |
c6ad8d0d | 258 | + return 1; |
2d94f8f7 JR |
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; | |
265 | + default: | |
266 | + return -1; | |
267 | + } | |
268 | + return -1; | |
269 | +} | |
270 | ||
271 | static tn_array *with_suggests(int indent, struct i3ctx *ictx, struct pkg *pkg) | |
272 | { | |
28d3fe2c | 273 | @@ -660,6 +857,7 @@ |
2d94f8f7 JR |
274 | struct pkg *oldpkg = NULL; |
275 | char *autochoice = NULL; /* testing only */ | |
276 | int i; | |
277 | + struct boolean_req* breq; | |
278 | ||
279 | if (pkg->sugs == NULL) | |
280 | return NULL; | |
28d3fe2c | 281 | @@ -693,8 +891,14 @@ |
2d94f8f7 JR |
282 | |
283 | //trace(indent, "%d) suggested %s", i, reqstr); | |
284 | ||
285 | - if (skip_boolean_dep(req)) | |
286 | + if (capreq_is_boolean(req)) { | |
287 | + logn(LOGWARN, "%s: skipping boolean dependency (weak deps not supported yet)", | |
288 | + capreq_stra(req)); | |
289 | + // TODO | |
290 | + // breq = parse_boolean_dep(capreq_name(req), 0, NULL); | |
291 | + // process_boolean_req(indent, ictx, i3pkg, breq); | |
292 | continue; | |
293 | + } | |
294 | ||
295 | if (iset_provides(ictx->inset, req)) { | |
296 | trace(indent, "- %s: already marked", reqstr); | |
28d3fe2c | 297 | @@ -791,6 +995,7 @@ |
2d94f8f7 JR |
298 | const struct capreq *req = NULL; |
299 | unsigned itflags = PKG_ITER_REQIN; | |
300 | int nerrors = 0, backtrack = 0; | |
301 | + struct boolean_req* breq; | |
302 | ||
303 | pkg = i3pkg->pkg; | |
304 | n_assert(pkg); | |
28d3fe2c | 305 | @@ -806,10 +1011,18 @@ |
2d94f8f7 JR |
306 | while ((req = pkg_req_iter_get(it))) { |
307 | int rc; | |
308 | ||
309 | - if (skip_boolean_dep(req)) | |
310 | - continue; | |
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); | |
28d3fe2c JR |
316 | + if (rc <= 0) |
317 | + i3_error(ictx, i3pkg->pkg, I3ERR_NOTFOUND, _("%s: req %s not found"), pkg_id(i3pkg->pkg), capreq_stra(req)); | |
2d94f8f7 | 318 | + } else { |
28d3fe2c | 319 | + rc = process_req(indent, ictx, i3pkg, req, 0); |
2d94f8f7 JR |
320 | + } |
321 | ||
322 | - if ((rc = process_req(indent, ictx, i3pkg, req)) <= 0) { | |
323 | + if (rc <= 0) { | |
324 | nerrors++; | |
325 | if (rc < 0) { | |
326 | backtrack = 1; | |
28d3fe2c JR |
327 | @@ -836,7 +1049,7 @@ |
328 | ||
329 | req = n_array_nth(suggests, i); | |
330 | ||
331 | - if ((rc = process_req(indent, ictx, i3pkg, req)) <= 0) { | |
332 | + if ((rc = process_req(indent, ictx, i3pkg, req, 0)) <= 0) { | |
333 | nerrors++; | |
334 | if (rc < 0) { | |
335 | backtrack = 1; |