Gentoo Archives: gentoo-commits

From: Fabian Groffen <grobian@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/portage-utils:master commit in: /, tests/atom_explode/, libq/
Date: Wed, 01 Jan 2020 12:51:47
Message-Id: 1577883018.c6537da04a6695656d655bf4e48813fb041ec010.grobian@gentoo
1 commit: c6537da04a6695656d655bf4e48813fb041ec010
2 Author: Fabian Groffen <grobian <AT> gentoo <DOT> org>
3 AuthorDate: Wed Jan 1 12:50:18 2020 +0000
4 Commit: Fabian Groffen <grobian <AT> gentoo <DOT> org>
5 CommitDate: Wed Jan 1 12:50:18 2020 +0000
6 URL: https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=c6537da0
7
8 libq/atom: stick to PMS for PVR
9
10 rework allocations somewhat, and make sure PVR does NOT include -r0, in
11 addition add PF to the structure, so this one can be grabbed more easily
12
13 Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org>
14
15 TODO.md | 9 +--
16 libq/atom.c | 149 ++++++++++++++++++++++++++--------------------
17 libq/atom.h | 1 +
18 tests/atom_explode/test.c | 22 +++++--
19 4 files changed, 107 insertions(+), 74 deletions(-)
20
21 diff --git a/TODO.md b/TODO.md
22 index dffaa91..cd4f2b2 100644
23 --- a/TODO.md
24 +++ b/TODO.md
25 @@ -22,13 +22,8 @@
26 - replace all strtok by strtok\_r, because the latter is already used,
27 so we can
28
29 -# Atoms
30 -
31 -- only 32bit values are supported for revision (-r#)
32 -- only 64bit values are supported in any individual version component
33 - foo-(1234)\_alpha(56789)
34 -- these limits should not be an issue for all practical purposes
35 -- make PVR match PMS https://dev.gentoo.org/~ulm/pms/head/pms.html#x1-10800011
36 +- parse package.accept\_keywords such that we can provide the latest
37 + "available" version like Portage
38
39 # qmerge
40
41
42 diff --git a/libq/atom.c b/libq/atom.c
43 index 05b138c..6f70847 100644
44 --- a/libq/atom.c
45 +++ b/libq/atom.c
46 @@ -1,5 +1,5 @@
47 /*
48 - * Copyright 2005-2019 Gentoo Foundation
49 + * Copyright 2005-2020 Gentoo Foundation
50 * Distributed under the terms of the GNU General Public License v2
51 *
52 * Copyright 2005-2008 Ned Ludd - <solar@g.o>
53 @@ -39,6 +39,9 @@ const char * const atom_op_str[] = {
54
55 const char * const booga[] = {"!!!", "!=", "==", ">", "<"};
56
57 +/* split string into individual components, known as an atom
58 + * for a definition of which variable contains what, see:
59 + * https://dev.gentoo.org/~ulm/pms/head/pms.html#x1-10800011 */
60 depend_atom *
61 atom_explode(const char *atom)
62 {
63 @@ -48,18 +51,33 @@ atom_explode(const char *atom)
64 size_t slen;
65 size_t idx;
66 size_t sidx;
67 -
68 - /* we allocate mem for atom struct and two strings (strlen(atom)).
69 - * the first string is for CAT/PN/PV while the second is for PVR.
70 - * PVR needs 3 extra bytes for possible implicit '-r0'. */
71 - slen = strlen(atom);
72 - len = sizeof(*ret) + (slen + 1) * sizeof(*atom) * 3 + 3;
73 + char *lastpv = NULL;
74 + char *pv;
75 +
76 + /* PMS 11.1 recap:
77 + * CAT The package’s category app-editors
78 + * PF Package name, version, and revision (if any) vim-7.0.174-r1
79 + * PVR Package version and revision (if any) 7.0.174-r1
80 + * P Package name and version, without the revision part vim-7.0.174
81 + * PV Package version, with no revision 7.0.174
82 + * PN Package name vim
83 + * PR Package revision, or r0 if none exists r1
84 + *
85 + * Thus, CAT/PF is the full allocation of the input string, for the
86 + * rest (P, PN, PV, PR, PVR) we need copies. We represent PR as an
87 + * integer, which leaves the set to PN, P and PV.
88 + * PVR is an offset inside PF, likewise, PV is an offset inside P.
89 + * We allocate memory for atom struct, one string for CAT/PF + PVR,
90 + * another to cover PN and a final one for P + PV. */
91 + slen = strlen(atom) + 1;
92 + len = sizeof(*ret) + (slen * 3);
93 ret = xmalloc(len);
94 memset(ret, '\0', sizeof(*ret));
95 - ptr = (char *)ret;
96 - ret->P = ptr + sizeof(*ret);
97 - ret->PVR = ret->P + slen + 1;
98 - ret->CATEGORY = ret->PVR + slen + 1 + 3;
99 +
100 + /* assign pointers to the three storage containers */
101 + ret->CATEGORY = (char *)ret + sizeof(*ret); /* CAT PF PVR */
102 + ret->P = ret->CATEGORY + slen; /* P PV */
103 + ret->PN = ret->P + slen; /* PN */
104
105 /* check for blocker operators */
106 ret->blocker = ATOM_BL_NONE;
107 @@ -95,13 +113,15 @@ atom_explode(const char *atom)
108 ret->pfx_op += ATOM_OP_EQUAL;
109 atom++;
110 }
111 +
112 + /* fill in full block */
113 strcpy(ret->CATEGORY, atom);
114
115 /* eat file name crap when given an (autocompleted) path */
116 if ((ptr = strstr(ret->CATEGORY, ".ebuild")) != NULL)
117 *ptr = '\0';
118
119 - /* chip off the trailing [::REPO] as needed */
120 + /* chip off the trailing ::REPO as needed */
121 if ((ptr = strstr(ret->CATEGORY, "::")) != NULL) {
122 ret->REPO = ptr + 2;
123 *ptr = '\0';
124 @@ -172,7 +192,7 @@ atom_explode(const char *atom)
125 *ptr++ = '\0';
126 }
127
128 - /* chip off the trailing [:SLOT] as needed */
129 + /* chip off the trailing :SLOT as needed */
130 if ((ptr = strrchr(ret->CATEGORY, ':')) != NULL) {
131 *ptr++ = '\0';
132 ret->SLOT = ptr;
133 @@ -205,14 +225,14 @@ atom_explode(const char *atom)
134 *ptr = '\0';
135 }
136
137 - /* break up the CATEGORY and PVR */
138 + /* break up the CATEGORY, PF and PVR */
139 if ((ptr = strrchr(ret->CATEGORY, '/')) != NULL) {
140 - ret->PN = ptr + 1;
141 - *ptr = '\0';
142 + *ptr++ = '\0';
143 + ret->PF = ptr;
144
145 /* set PN to NULL if there's nothing */
146 - if (ret->PN[0] == '\0')
147 - ret->PN = NULL;
148 + if (ret->PF[0] == '\0')
149 + ret->PF = NULL;
150
151 /* eat extra crap in case it exists, this is a feature to allow
152 * /path/to/pkg.ebuild, doesn't work with prefix operators
153 @@ -220,75 +240,81 @@ atom_explode(const char *atom)
154 if ((ptr = strrchr(ret->CATEGORY, '/')) != NULL)
155 ret->CATEGORY = ptr + 1;
156 } else {
157 - ret->PN = ret->CATEGORY;
158 + ret->PF = ret->CATEGORY;
159 ret->CATEGORY = NULL;
160 }
161
162 - if (ret->PN == NULL) {
163 + if (ret->PF == NULL) {
164 /* atom has no name, this is it */
165 ret->P = NULL;
166 + ret->PN = NULL;
167 ret->PVR = NULL;
168 +
169 return ret;
170 }
171
172 - /* CATEGORY should be all set here, PN contains everything up to
173 + /* CATEGORY should be all set here, PF contains everything up to
174 * SLOT, REPO or '*'
175 - * PN must not end in a hyphen followed by anything matching version
176 - * syntax, version syntax starts with a number, so "-[0-9]" is a
177 - * separator from PN to PV* -- except it doesn't when the thing
178 - * doesn't validate as version :( */
179 -
180 - ptr = ret->PN;
181 - {
182 - char *lastpv = NULL;
183 - char *pv;
184 -
185 - while ((ptr = strchr(ptr, '-')) != NULL) {
186 - ptr++;
187 - if (!isdigit(*ptr))
188 - continue;
189 + * PMS 3.1.2 says PN must not end in a hyphen followed by
190 + * anything matching version syntax. PMS 3.2 version syntax
191 + * starts with a number, so "-[0-9]" is a separator from PN to
192 + * PV* -- except it doesn't when the thing doesn't validate as
193 + * version :( */
194 +
195 + ptr = ret->PF;
196 + while ((ptr = strchr(ptr, '-')) != NULL) {
197 + ptr++;
198 + if (!isdigit(*ptr))
199 + continue;
200
201 - /* so we should have something like "-2" here, see if this
202 - * checks out as valid version string */
203 - pv = ptr;
204 - while (*++ptr != '\0') {
205 - if (*ptr != '.' && !isdigit(*ptr))
206 - break;
207 - }
208 - /* allow for 1 optional suffix letter */
209 - if (*ptr >= 'a' && *ptr <= 'z')
210 - ret->letter = *ptr++;
211 - if (*ptr == '_' || *ptr == '-' || *ptr == '\0') {
212 - lastpv = pv;
213 - continue; /* valid, keep searching */
214 - }
215 - ret->letter = '\0';
216 + /* so we should have something like "-2" here, see if this
217 + * checks out as valid version string */
218 + pv = ptr;
219 + while (*++ptr != '\0') {
220 + if (*ptr != '.' && !isdigit(*ptr))
221 + break;
222 + }
223 + /* allow for 1 optional suffix letter */
224 + if (*ptr >= 'a' && *ptr <= 'z')
225 + ret->letter = *ptr++;
226 + if (*ptr == '_' || *ptr == '-' || *ptr == '\0') {
227 + lastpv = pv;
228 + continue; /* valid, keep searching */
229 }
230 - ptr = lastpv;
231 + ret->letter = '\0';
232 }
233 + ptr = lastpv;
234
235 if (ptr == NULL) {
236 /* atom has no version, this is it */
237 - strcpy(ret->P, ret->PN);
238 - ret->PVR = NULL;
239 + ret->P = ret->PN = ret->PF;
240 + ret->PV = ret->PVR = NULL;
241 +
242 return ret;
243 }
244 - ret->PV = ptr;
245 +
246 + ret->PVR = ptr;
247 + snprintf(ret->PN, slen, "%.*s", (int)(ret->PVR - 1 - ret->PF), ret->PF);
248
249 /* find -r# */
250 - ptr = ret->PV + strlen(ret->PV) - 1;
251 - while (*ptr && ptr > ret->PV) {
252 - if (!isdigit(*ptr)) {
253 + pv = NULL;
254 + ptr = ret->PVR + strlen(ret->PVR) - 1;
255 + while (*ptr && ptr > ret->PVR) {
256 + if (!isdigit((int)*ptr)) {
257 if (ptr[0] == 'r' && ptr[-1] == '-') {
258 ret->PR_int = atoi(ptr + 1);
259 - ptr[-1] = '\0';
260 + pv = &ptr[-1];
261 }
262 break;
263 }
264 ptr--;
265 }
266 - strcpy(ret->P, ret->PN);
267 - ret->PV[-1] = '\0';
268 + if (pv != NULL) {
269 + snprintf(ret->P, slen, "%.*s", (int)(pv - ret->PF), ret->PF);
270 + } else {
271 + ret->P = ret->PF;
272 + }
273 + ret->PV = ret->P + (ret->PVR - ret->PF);
274
275 /* break out all the suffixes */
276 sidx = 0;
277 @@ -325,9 +351,6 @@ atom_explode(const char *atom)
278 ret->suffixes[idx] = t;
279 }
280
281 - /* size is malloced above with the required space in mind */
282 - sprintf(ret->PVR, "%s-r%i", ret->PV, ret->PR_int);
283 -
284 return ret;
285 }
286
287
288 diff --git a/libq/atom.h b/libq/atom.h
289 index a5175b0..1548dd9 100644
290 --- a/libq/atom.h
291 +++ b/libq/atom.h
292 @@ -74,6 +74,7 @@ typedef struct {
293 char *CATEGORY;
294 char *PN;
295 char *PV;
296 + char *PF;
297 unsigned int PR_int;
298 char letter;
299 atom_suffix *suffixes;
300
301 diff --git a/tests/atom_explode/test.c b/tests/atom_explode/test.c
302 index 21a5f1d..b794d3b 100644
303 --- a/tests/atom_explode/test.c
304 +++ b/tests/atom_explode/test.c
305 @@ -1,5 +1,5 @@
306 /*
307 - * Copyright 2005-2019 Gentoo Foundation
308 + * Copyright 2005-2020 Gentoo Foundation
309 * Distributed under the terms of the GNU General Public License v2
310 *
311 * Copyright 2005-2008 Ned Ludd - <solar@g.o>
312 @@ -19,9 +19,23 @@ FILE *warnout;
313
314 static inline void boom(depend_atom *a, char *s)
315 {
316 - printf("%s -> %s / [%s] %s - %s [%s] [r%i]\n",
317 - s, (a->CATEGORY?:"null"), a->P, a->PN,
318 - a->PVR, a->PV, a->PR_int);
319 + /* python code:
320 + * CATEGORY = cpv[0]
321 + * PN = cpv[1]
322 + * PV = cpv[2]
323 + * PR_int = cpv[3]
324 + * P = PN + "-" + PV
325 + * PVR = PV + "-" + cpv[3]
326 + * print(a+" -> "+CATEGORY+" / ["+P+"] "+PN+" - "+PVR+" ["+PV+"] ["+PR_int+"]")
327 + * this most notably doesn't test PVR in compliance with PMS */
328 + printf("%s -> %s / [%s] %s - %s%s [%s] [r%i]\n",
329 + s,
330 + (a->CATEGORY ? a->CATEGORY : "null"),
331 + a->P,
332 + a->PN,
333 + a->PVR, (a->PVR != NULL && a->PR_int == 0) ? "-r0" : "",
334 + a->PV,
335 + a->PR_int);
336 }
337
338 int main(int argc, char *argv[])