]> git.pld-linux.org Git - packages/poldek.git/blob - boolean-deps.patch
Release 19 (by relup.sh)
[packages/poldek.git] / boolean-deps.patch
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
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
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
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;
145      }
146 -    return 0;
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 +       }
186 +    }
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
200 @@ -553,8 +703,11 @@
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,
208 -                       struct i3pkg *i3pkg, const struct capreq *req)
209 +                       struct i3pkg *i3pkg, const struct capreq *req, int boolean)
210  {
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 @@
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)
232 +        rcl = process_req(indent, ictx, i3pkg, breq->req, 1);
233 +    else
234 +        rcl = process_boolean_req(indent, ictx, i3pkg, breq->left);
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;
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);
246 +            return rcl;
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);
252 +            return 1;
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);
258 +            return 1;
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  {
273 @@ -660,6 +857,7 @@
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;
281 @@ -693,8 +891,14 @@
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);
297 @@ -791,6 +995,7 @@
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);
305 @@ -806,10 +1011,18 @@
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);
316 +            if (rc <= 0)
317 +                i3_error(ictx, i3pkg->pkg, I3ERR_NOTFOUND, _("%s: req %s not found"), pkg_id(i3pkg->pkg), capreq_stra(req));
318 +        } else {
319 +            rc = process_req(indent, ictx, i3pkg, req, 0);
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;
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;
This page took 0.062826 seconds and 3 git commands to generate.