1 |
commit: 47c13a275a7b76d77e5ac3e3ada5024bfc5372bd |
2 |
Author: Fabian Groffen <grobian <AT> gentoo <DOT> org> |
3 |
AuthorDate: Fri May 3 08:47:26 2019 +0000 |
4 |
Commit: Fabian Groffen <grobian <AT> gentoo <DOT> org> |
5 |
CommitDate: Fri May 3 08:47:26 2019 +0000 |
6 |
URL: https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=47c13a27 |
7 |
|
8 |
quse: make -v output faster, format and introduce --repo |
9 |
|
10 |
- improve performance for -v output (listing all use-flags with |
11 |
descriptions per package match) |
12 |
- add -R/--repo flag to print repository next to atom |
13 |
- align USE-flags in -v mode per package |
14 |
|
15 |
Bug: https://bugs.gentoo.org/656550 |
16 |
Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org> |
17 |
|
18 |
TODO.md | 1 - |
19 |
man/quse.1 | 3 ++ |
20 |
quse.c | 171 +++++++++++++++++++++++++++++++++++++++++++++---------------- |
21 |
3 files changed, 131 insertions(+), 44 deletions(-) |
22 |
|
23 |
diff --git a/TODO.md b/TODO.md |
24 |
index 349170f..b70dffc 100644 |
25 |
--- a/TODO.md |
26 |
+++ b/TODO.md |
27 |
@@ -88,5 +88,4 @@ |
28 |
package X |
29 |
|
30 |
# quse |
31 |
-- make -v faster by calling searcg funcs once per package match |
32 |
- make -v only print requested USE-flag when flags given |
33 |
|
34 |
diff --git a/man/quse.1 b/man/quse.1 |
35 |
index 6f0d8d3..ef17c10 100644 |
36 |
--- a/man/quse.1 |
37 |
+++ b/man/quse.1 |
38 |
@@ -25,6 +25,9 @@ Describe the USE flag. |
39 |
\fB\-p\fR \fI<arg>\fR, \fB\-\-package\fR \fI<arg>\fR |
40 |
Restrict matching to package or category. |
41 |
.TP |
42 |
+\fB\-R\fR, \fB\-\-repo\fR |
43 |
+Show repository the ebuild originates from. |
44 |
+.TP |
45 |
\fB\-\-root\fR \fI<arg>\fR |
46 |
Set the ROOT env var. |
47 |
.TP |
48 |
|
49 |
diff --git a/quse.c b/quse.c |
50 |
index fbf61cf..604efdf 100644 |
51 |
--- a/quse.c |
52 |
+++ b/quse.c |
53 |
@@ -26,13 +26,14 @@ |
54 |
#include "xarray.h" |
55 |
#include "xregex.h" |
56 |
|
57 |
-#define QUSE_FLAGS "eaLDp:" COMMON_FLAGS |
58 |
+#define QUSE_FLAGS "eaLDp:R" COMMON_FLAGS |
59 |
static struct option const quse_long_opts[] = { |
60 |
{"exact", no_argument, NULL, 'e'}, |
61 |
{"all", no_argument, NULL, 'a'}, |
62 |
{"license", no_argument, NULL, 'L'}, |
63 |
{"describe", no_argument, NULL, 'D'}, |
64 |
{"package", a_argument, NULL, 'p'}, |
65 |
+ {"repo", no_argument, NULL, 'R'}, |
66 |
COMMON_LONG_OPTS |
67 |
}; |
68 |
static const char * const quse_opts_help[] = { |
69 |
@@ -41,6 +42,7 @@ static const char * const quse_opts_help[] = { |
70 |
"Use the LICENSE vs IUSE", |
71 |
"Describe the USE flag", |
72 |
"Restrict matching to package or category", |
73 |
+ "Show repository the ebuild originates from", |
74 |
COMMON_OPTS_HELP |
75 |
}; |
76 |
#define quse_usage(ret) usage(ret, QUSE_FLAGS, quse_long_opts, quse_opts_help, NULL, lookup_applet_idx("quse")) |
77 |
@@ -48,12 +50,14 @@ static const char * const quse_opts_help[] = { |
78 |
struct quse_state { |
79 |
int argc; |
80 |
char **argv; |
81 |
+ char **retv; |
82 |
const char *overlay; |
83 |
bool do_all:1; |
84 |
bool do_regex:1; |
85 |
bool do_describe:1; |
86 |
bool do_licence:1; |
87 |
bool do_list:1; |
88 |
+ bool do_repo:1; |
89 |
depend_atom *match; |
90 |
regex_t *pregv; |
91 |
}; |
92 |
@@ -110,6 +114,9 @@ quse_search_use_local_desc(int portdirfd, struct quse_state *state) |
93 |
|
94 |
match = false; |
95 |
for (i = 0; i < state->argc; i++) { |
96 |
+ if (state->do_list && state->retv[i] != NULL) |
97 |
+ continue; |
98 |
+ |
99 |
if (state->do_regex) { |
100 |
if (regexec(&state->pregv[i], p, 0, NULL, 0) != 0) |
101 |
continue; |
102 |
@@ -128,13 +135,14 @@ quse_search_use_local_desc(int portdirfd, struct quse_state *state) |
103 |
if (state->match == NULL || |
104 |
atom_compare(atom, state->match) == EQUAL) |
105 |
{ |
106 |
- if (state->do_list) |
107 |
- printf(" %s%s%s %s\n", MAGENTA, p, NORM, q); |
108 |
- else |
109 |
+ if (state->do_list) { |
110 |
+ state->retv[i] = xstrdup(q); |
111 |
+ } else { |
112 |
printf("%s%s/%s%s%s[%s%s%s] %s\n", |
113 |
BOLD, atom->CATEGORY, |
114 |
BLUE, atom->PN, NORM, |
115 |
MAGENTA, p, NORM, q); |
116 |
+ } |
117 |
} |
118 |
|
119 |
atom_implode(atom); |
120 |
@@ -142,6 +150,16 @@ quse_search_use_local_desc(int portdirfd, struct quse_state *state) |
121 |
} |
122 |
} while (1); |
123 |
|
124 |
+ if (state->do_list && ret) { |
125 |
+ /* check if all requested flags are retrieved */ |
126 |
+ ret = true; |
127 |
+ for (i = 0; i < state->argc; i++) |
128 |
+ if (state->retv[i] == NULL) |
129 |
+ break; |
130 |
+ if (i < state->argc) |
131 |
+ ret = false; |
132 |
+ } |
133 |
+ |
134 |
fclose(f); |
135 |
return ret; |
136 |
} |
137 |
@@ -186,6 +204,9 @@ quse_search_use_desc(int portdirfd, struct quse_state *state) |
138 |
|
139 |
match = false; |
140 |
for (i = 0; i < state->argc; i++) { |
141 |
+ if (state->do_list && state->retv[i] != NULL) |
142 |
+ continue; |
143 |
+ |
144 |
if (state->do_regex) { |
145 |
if (regexec(&state->pregv[i], buf, 0, NULL, 0) != 0) |
146 |
continue; |
147 |
@@ -198,16 +219,27 @@ quse_search_use_desc(int portdirfd, struct quse_state *state) |
148 |
} |
149 |
|
150 |
if (match) { |
151 |
- if (state->do_list) |
152 |
- printf(" %s%s%s %s\n", MAGENTA, buf, NORM, p); |
153 |
- else |
154 |
+ if (state->do_list) { |
155 |
+ state->retv[i] = xstrdup(p); |
156 |
+ } else { |
157 |
printf("%sglobal%s[%s%s%s] %s\n", |
158 |
BOLD, NORM, MAGENTA, buf, NORM, p); |
159 |
+ } |
160 |
|
161 |
ret = true; |
162 |
} |
163 |
} while (1); |
164 |
|
165 |
+ if (state->do_list && ret) { |
166 |
+ /* check if all requested flags are retrieved */ |
167 |
+ ret = true; |
168 |
+ for (i = 0; i < state->argc; i++) |
169 |
+ if (state->retv[i] == NULL) |
170 |
+ break; |
171 |
+ if (i < state->argc) |
172 |
+ ret = false; |
173 |
+ } |
174 |
+ |
175 |
fclose(f); |
176 |
return ret; |
177 |
} |
178 |
@@ -287,6 +319,9 @@ quse_search_profiles_desc( |
179 |
|
180 |
match = false; |
181 |
for (i = 0; i < state->argc; i++) { |
182 |
+ if (state->do_list && state->retv[i] != NULL) |
183 |
+ continue; |
184 |
+ |
185 |
arglen = strlen(state->argv[i]); |
186 |
if (arglen > namelen) { |
187 |
/* nginx_modules_http_lua = NGINX_MODULES_HTTP[lua] */ |
188 |
@@ -312,17 +347,18 @@ quse_search_profiles_desc( |
189 |
} |
190 |
|
191 |
if (match) { |
192 |
- const char *r = de->d_name; |
193 |
- char *s = ubuf; |
194 |
- do { |
195 |
- *s++ = (char)toupper((int)*r); |
196 |
- } while (++r < (de->d_name + namelen)); |
197 |
- *s = '\0'; |
198 |
- if (state->do_list) |
199 |
- printf(" %s=%s%s%s %s\n", ubuf, MAGENTA, buf, NORM, p); |
200 |
- else |
201 |
+ if (state->do_list) { |
202 |
+ state->retv[i] = xstrdup(p); |
203 |
+ } else { |
204 |
+ const char *r = de->d_name; |
205 |
+ char *s = ubuf; |
206 |
+ do { |
207 |
+ *s++ = (char)toupper((int)*r); |
208 |
+ } while (++r < (de->d_name + namelen)); |
209 |
+ *s = '\0'; |
210 |
printf("%s%s%s[%s%s%s] %s\n", |
211 |
BOLD, ubuf, NORM, MAGENTA, buf, NORM, p); |
212 |
+ } |
213 |
|
214 |
ret = true; |
215 |
} |
216 |
@@ -332,6 +368,16 @@ quse_search_profiles_desc( |
217 |
} |
218 |
closedir(d); |
219 |
|
220 |
+ if (state->do_list && ret) { |
221 |
+ /* check if all requested flags are retrieved */ |
222 |
+ ret = true; |
223 |
+ for (i = 0; i < state->argc; i++) |
224 |
+ if (state->retv[i] == NULL) |
225 |
+ break; |
226 |
+ if (i < state->argc) |
227 |
+ ret = false; |
228 |
+ } |
229 |
+ |
230 |
return ret; |
231 |
} |
232 |
|
233 |
@@ -369,6 +415,8 @@ quse_results_cb(cache_pkg_ctx *pkg_ctx, void *priv) |
234 |
char *w; |
235 |
int i; |
236 |
int len; |
237 |
+ int maxlen; |
238 |
+ int cnt; |
239 |
int portdirfd = -1; /* pacify compiler */ |
240 |
|
241 |
if (state->match || verbose) { |
242 |
@@ -402,13 +450,15 @@ quse_results_cb(cache_pkg_ctx *pkg_ctx, void *priv) |
243 |
return 0; |
244 |
} |
245 |
|
246 |
+ maxlen = 0; |
247 |
+ cnt = 0; |
248 |
match = false; |
249 |
q = p = state->do_licence ? meta->LICENSE : meta->IUSE; |
250 |
buf[0] = '\0'; |
251 |
v = buf; |
252 |
w = buf + sizeof(buf); |
253 |
|
254 |
- if (state->do_all) { |
255 |
+ if (state->do_all && !verbose) { |
256 |
match = true; |
257 |
v = q; |
258 |
} else { |
259 |
@@ -423,7 +473,10 @@ quse_results_cb(cache_pkg_ctx *pkg_ctx, void *priv) |
260 |
s = q; |
261 |
if (*q == '-' || *q == '+' || *q == '@') |
262 |
q++; |
263 |
- if (state->do_regex) { |
264 |
+ if (state->do_all) { |
265 |
+ i = 0; |
266 |
+ match = true; |
267 |
+ } else if (state->do_regex) { |
268 |
char r; |
269 |
for (i = 0; i < state->argc; i++) { |
270 |
r = *p; |
271 |
@@ -452,6 +505,11 @@ quse_results_cb(cache_pkg_ctx *pkg_ctx, void *priv) |
272 |
} |
273 |
if (i == state->argc) |
274 |
v += snprintf(v, w - v, "%.*s%c", (int)(p - s), s, *p); |
275 |
+ |
276 |
+ if (maxlen < p - q) |
277 |
+ maxlen = p - q; |
278 |
+ cnt++; |
279 |
+ |
280 |
q = p + 1; |
281 |
} |
282 |
} while (*p++ != '\0' && v < w); |
283 |
@@ -459,57 +517,82 @@ quse_results_cb(cache_pkg_ctx *pkg_ctx, void *priv) |
284 |
} |
285 |
|
286 |
if (match) { |
287 |
+ char *repo = state->do_repo ? pkg_ctx->repo : NULL; |
288 |
+ |
289 |
if (quiet) { |
290 |
- printf("%s%s/%s%s%s\n", BOLD, pkg_ctx->cat_ctx->name, |
291 |
- BLUE, pkg_ctx->name, NORM); |
292 |
- } else if (verbose) { |
293 |
+ printf("%s%s/%s%s%s%s%s%s\n", BOLD, pkg_ctx->cat_ctx->name, |
294 |
+ BLUE, pkg_ctx->name, |
295 |
+ repo ? RED : "", repo ? "::" : "", repo ? repo : "", |
296 |
+ NORM); |
297 |
+ } else if (verbose && !state->do_licence) { |
298 |
/* multi-line result, printing USE-flags with their descs */ |
299 |
struct quse_state us = { |
300 |
.do_regex = false, |
301 |
.do_describe = false, |
302 |
.do_list = true, |
303 |
.match = atom, |
304 |
- .argc = 1, |
305 |
- .argv = NULL, |
306 |
+ .argc = cnt, |
307 |
+ .argv = xmalloc(sizeof(char *) * cnt), |
308 |
+ .retv = xzalloc(sizeof(char *) * cnt), |
309 |
.overlay = NULL, |
310 |
}; |
311 |
|
312 |
- printf("%s%s/%s%s%s:\n", BOLD, pkg_ctx->cat_ctx->name, |
313 |
- BLUE, pkg_ctx->name, NORM); |
314 |
+ printf("%s%s/%s%s%s%s%s%s\n", BOLD, pkg_ctx->cat_ctx->name, |
315 |
+ BLUE, pkg_ctx->name, |
316 |
+ repo ? RED : "", repo ? "::" : "", repo ? repo : "", |
317 |
+ NORM); |
318 |
|
319 |
- q = p = state->do_licence ? meta->LICENSE : meta->IUSE; |
320 |
+ q = p = meta->IUSE; |
321 |
buf[0] = '\0'; |
322 |
+ v = buf; |
323 |
+ w = buf + sizeof(buf); |
324 |
+ i = 0; |
325 |
do { |
326 |
if (*p == ' ' || *p == '\0') { |
327 |
s = q; |
328 |
if (*q == '-' || *q == '+' || *q == '@') |
329 |
q++; |
330 |
|
331 |
- snprintf(buf, sizeof(buf), "%.*s", (int)(p - q), q); |
332 |
- v = buf; |
333 |
- us.argv = &v; |
334 |
- |
335 |
- /* print at most one match for each flag, this is |
336 |
- * why we can't setup all flags in argc/argv, |
337 |
- * because then we either print way to few, or way |
338 |
- * too many, possible opt: when argv would be |
339 |
- * modified by search funcs so they remove what they |
340 |
- * matched */ |
341 |
- if (!quse_search_use_local_desc(portdirfd, &us)) |
342 |
- if (!quse_search_use_desc(portdirfd, &us)) |
343 |
- quse_search_profiles_desc(portdirfd, &us); |
344 |
+ /* pre-padd everything such that we always refer to |
345 |
+ * the char before the USE-flag */ |
346 |
+ us.argv[i++] = v + 1; |
347 |
+ v += snprintf(v, w - v, "%c%.*s", |
348 |
+ s == q ? ' ' : *s, (int)(p - q), q) + 1; |
349 |
|
350 |
q = p + 1; |
351 |
} |
352 |
- } while (*p++ != '\0'); |
353 |
+ } while (*p++ != '\0' && i < cnt && v < w); |
354 |
+ |
355 |
+ /* harvest descriptions for USE-flags */ |
356 |
+ if (!quse_search_use_local_desc(portdirfd, &us)) |
357 |
+ if (!quse_search_use_desc(portdirfd, &us)) |
358 |
+ quse_search_profiles_desc(portdirfd, &us); |
359 |
+ |
360 |
+ for (i = 0; i < cnt; i++) { |
361 |
+ printf(" %c%s%s%s%*s %s\n", |
362 |
+ us.argv[i][-1], |
363 |
+ /* selected ? RED : NORM */ MAGENTA, |
364 |
+ us.argv[i], |
365 |
+ NORM, |
366 |
+ (int)(maxlen - strlen(us.argv[i])), "", |
367 |
+ us.retv[i] == NULL ? "<no description found>" : |
368 |
+ us.retv[i]); |
369 |
+ if (us.retv[i] != NULL) |
370 |
+ free(us.retv[i]); |
371 |
+ } |
372 |
+ |
373 |
+ free(us.retv); |
374 |
+ free(us.argv); |
375 |
} else { |
376 |
- printf("%s%s/%s%s%s: %s\n", BOLD, pkg_ctx->cat_ctx->name, |
377 |
- BLUE, pkg_ctx->name, NORM, v); |
378 |
+ printf("%s%s/%s%s%s%s%s%s: %s\n", BOLD, pkg_ctx->cat_ctx->name, |
379 |
+ BLUE, pkg_ctx->name, |
380 |
+ repo ? RED : "", repo ? "::" : "", repo ? repo : "", |
381 |
+ NORM, v); |
382 |
} |
383 |
} |
384 |
|
385 |
cache_close_meta(meta); |
386 |
- if (state->match || verbose) |
387 |
+ if (state->match && verbose) |
388 |
atom_implode(atom); |
389 |
if (verbose) |
390 |
close(portdirfd); |
391 |
@@ -528,6 +611,7 @@ int quse_main(int argc, char **argv) |
392 |
.do_regex = true, |
393 |
.do_describe = false, |
394 |
.do_licence = false, |
395 |
+ .do_repo = false, |
396 |
.match = NULL, |
397 |
.overlay = NULL, |
398 |
}; |
399 |
@@ -538,6 +622,7 @@ int quse_main(int argc, char **argv) |
400 |
case 'a': state.do_all = true; break; |
401 |
case 'L': state.do_licence = true; break; |
402 |
case 'D': state.do_describe = true; break; |
403 |
+ case 'R': state.do_repo = true; break; |
404 |
case 'p': match = optarg; break; |
405 |
COMMON_GETOPTS_CASES(quse) |
406 |
} |