1 |
commit: f162c6a9219deacfe23c8e21b732f8594a938130 |
2 |
Author: Mike Frysinger <vapier <AT> gentoo <DOT> org> |
3 |
AuthorDate: Fri Nov 27 19:04:10 2015 +0000 |
4 |
Commit: Mike Frysinger <vapier <AT> gentoo <DOT> org> |
5 |
CommitDate: Fri Nov 27 19:04:10 2015 +0000 |
6 |
URL: https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=f162c6a9 |
7 |
|
8 |
qsearch: add multiple overlay support |
9 |
|
10 |
We ractor some of the main code into helper funcs to make iterating |
11 |
over the overlays easier to manage. |
12 |
|
13 |
URL: https://bugs.gentoo.org/553260 |
14 |
|
15 |
qsearch.c | 268 +++++++++++++++++++++++++++++++++++--------------------------- |
16 |
1 file changed, 152 insertions(+), 116 deletions(-) |
17 |
|
18 |
diff --git a/qsearch.c b/qsearch.c |
19 |
index 02d43ca..b7c992e 100644 |
20 |
--- a/qsearch.c |
21 |
+++ b/qsearch.c |
22 |
@@ -31,18 +31,114 @@ static const char * const qsearch_opts_help[] = { |
23 |
}; |
24 |
#define qsearch_usage(ret) usage(ret, QSEARCH_FLAGS, qsearch_long_opts, qsearch_opts_help, lookup_applet_idx("qsearch")) |
25 |
|
26 |
-int qsearch_main(int argc, char **argv) |
27 |
+#define LAST_BUF_SIZE 256 |
28 |
+ |
29 |
+/* Search an ebuild's details via the metadata cache. */ |
30 |
+static void |
31 |
+qsearch_ebuild_metadata(_q_unused_ int overlay_fd, const char *ebuild, const char *search_me, char *last, |
32 |
+ bool search_desc, bool search_all, _q_unused_ bool search_name, bool show_name_only, bool show_homepage) |
33 |
+{ |
34 |
+ portage_cache *pcache = cache_read_file(ebuild); |
35 |
+ |
36 |
+ if (pcache == NULL) { |
37 |
+ if (!reinitialize) |
38 |
+ warnf("(cache update pending) %s", ebuild); |
39 |
+ reinitialize = 1; |
40 |
+ return; |
41 |
+ } |
42 |
+ |
43 |
+ if (strcmp(pcache->atom->PN, last) != 0) { |
44 |
+ strncpy(last, pcache->atom->PN, LAST_BUF_SIZE); |
45 |
+ if (search_all || rematch(search_me, (search_desc ? pcache->DESCRIPTION : ebuild), REG_EXTENDED | REG_ICASE) == 0) |
46 |
+ printf("%s%s/%s%s%s %s\n", BOLD, pcache->atom->CATEGORY, BLUE, |
47 |
+ pcache->atom->PN, NORM, |
48 |
+ (show_name_only ? "" : |
49 |
+ (show_homepage ? pcache->HOMEPAGE : pcache->DESCRIPTION))); |
50 |
+ } |
51 |
+ cache_free(pcache); |
52 |
+} |
53 |
+ |
54 |
+/* Search an ebuild's details via the ebuild cache. */ |
55 |
+static void |
56 |
+qsearch_ebuild_ebuild(int overlay_fd, const char *ebuild, const char *search_me, char *last, |
57 |
+ _q_unused_ bool search_desc, bool search_all, bool search_name, bool show_name_only, _q_unused_ bool show_homepage) |
58 |
{ |
59 |
- FILE *fp; |
60 |
- char *ebuild = NULL; |
61 |
- char last[126] = ""; |
62 |
+ const char * const search_vars[] = { "DESCRIPTION=", "HOMEPAGE=" }; |
63 |
+ const char *search_var = search_vars[show_homepage ? 1 : 0]; |
64 |
+ size_t search_len = strlen(search_var); |
65 |
char *p, *q, *str; |
66 |
+ |
67 |
+ FILE *ebuildfp; |
68 |
+ str = xstrdup(ebuild); |
69 |
+ p = dirname(str); |
70 |
+ |
71 |
+ if (strcmp(p, last) == 0) |
72 |
+ goto no_cache_ebuild_match; |
73 |
+ |
74 |
+ bool show_it = false; |
75 |
+ strncpy(last, p, LAST_BUF_SIZE); |
76 |
+ if (search_name) { |
77 |
+ if (rematch(search_me, basename(last), REG_EXTENDED | REG_ICASE) != 0) { |
78 |
+ goto no_cache_ebuild_match; |
79 |
+ } else { |
80 |
+ q = NULL; |
81 |
+ show_it = true; |
82 |
+ } |
83 |
+ } |
84 |
+ |
85 |
+ int fd = openat(overlay_fd, ebuild, O_RDONLY|O_CLOEXEC); |
86 |
+ if (fd != -1) { |
87 |
+ ebuildfp = fdopen(fd, "r"); |
88 |
+ if (ebuildfp == NULL) { |
89 |
+ close(fd); |
90 |
+ goto no_cache_ebuild_match; |
91 |
+ } |
92 |
+ } else { |
93 |
+ if (!reinitialize) |
94 |
+ warnfp("(cache update pending) %s", ebuild); |
95 |
+ reinitialize = 1; |
96 |
+ goto no_cache_ebuild_match; |
97 |
+ } |
98 |
+ |
99 |
+ char *buf = NULL; |
100 |
+ size_t buflen, linelen; |
101 |
+ while ((linelen = getline(&buf, &buflen, ebuildfp)) != -1) { |
102 |
+ if (linelen <= search_len) |
103 |
+ continue; |
104 |
+ if (strncmp(buf, search_var, search_len) != 0) |
105 |
+ continue; |
106 |
+ if ((q = strrchr(buf, '"')) != NULL) |
107 |
+ *q = 0; |
108 |
+ if (strlen(buf) <= search_len) |
109 |
+ break; |
110 |
+ q = buf + search_len + 1; |
111 |
+ if (!search_all && !search_name && rematch(search_me, q, REG_EXTENDED | REG_ICASE) != 0) |
112 |
+ break; |
113 |
+ show_it = true; |
114 |
+ break; |
115 |
+ } |
116 |
+ |
117 |
+ if (show_it) { |
118 |
+ printf("%s%s/%s%s%s %s\n", |
119 |
+ BOLD, dirname(p), BLUE, basename(p), NORM, |
120 |
+ (show_name_only ? "" : q ? : "<no DESCRIPTION found>")); |
121 |
+ } |
122 |
+ |
123 |
+ free(buf); |
124 |
+ fclose(ebuildfp); |
125 |
+ no_cache_ebuild_match: |
126 |
+ free(str); |
127 |
+} |
128 |
+ |
129 |
+int qsearch_main(int argc, char **argv) |
130 |
+{ |
131 |
+ char last[LAST_BUF_SIZE]; |
132 |
char *search_me = NULL; |
133 |
- char show_homepage = 0, show_name_only = 0; |
134 |
- char search_desc = 0, search_all = 0, search_name = 1, search_cache = CACHE_EBUILD; |
135 |
- const char *search_vars[] = { "DESCRIPTION=", "HOMEPAGE=" }; |
136 |
- size_t search_len, ebuild_len, linelen; |
137 |
- int i, idx=0; |
138 |
+ bool show_homepage = false, show_name_only = false; |
139 |
+ bool search_desc = false, search_all = false, search_name = true; |
140 |
+ int search_cache = CACHE_EBUILD; |
141 |
+ int i; |
142 |
+ void (*search_func)(int, const char *, const char *, char *last, bool, bool, bool, bool, bool); |
143 |
|
144 |
DBG("argc=%d argv[0]=%s argv[1]=%s", |
145 |
argc, argv[0], argc > 1 ? argv[1] : "NULL?"); |
146 |
@@ -50,132 +146,72 @@ int qsearch_main(int argc, char **argv) |
147 |
while ((i = GETOPT_LONG(QSEARCH, qsearch, "")) != -1) { |
148 |
switch (i) { |
149 |
COMMON_GETOPTS_CASES(qsearch) |
150 |
- case 'a': search_all = 1; break; |
151 |
+ case 'a': search_all = true; break; |
152 |
case 'c': search_cache = CACHE_METADATA; break; |
153 |
case 'e': search_cache = CACHE_EBUILD; break; |
154 |
- case 's': search_desc = 0; search_name = 1; break; |
155 |
- case 'S': search_desc = 1; search_name = 0; break; |
156 |
- case 'N': show_name_only = 1; break; |
157 |
- case 'H': show_homepage = 1, idx = 1; break; |
158 |
+ case 's': search_desc = false; search_name = true; break; |
159 |
+ case 'S': search_desc = true; search_name = false; break; |
160 |
+ case 'N': show_name_only = true; break; |
161 |
+ case 'H': show_homepage = true; break; |
162 |
} |
163 |
} |
164 |
|
165 |
+ switch (search_cache) { |
166 |
+ case CACHE_METADATA: |
167 |
+ search_func = qsearch_ebuild_metadata; |
168 |
+ break; |
169 |
+ case CACHE_EBUILD: |
170 |
+ search_func = qsearch_ebuild_ebuild; |
171 |
+ break; |
172 |
+ default: |
173 |
+ err("unknown cache %i", search_cache); |
174 |
+ } |
175 |
+ |
176 |
if (search_all) { |
177 |
- search_desc = 1; |
178 |
- search_name = 0; |
179 |
+ search_desc = true; |
180 |
+ search_name = false; |
181 |
} else { |
182 |
if (argc == optind) |
183 |
qsearch_usage(EXIT_FAILURE); |
184 |
search_me = argv[optind]; |
185 |
} |
186 |
last[0] = 0; |
187 |
- fp = fopen(initialize_flat(portdir, search_cache, false), "r"); |
188 |
- if (!fp) |
189 |
- return 1; |
190 |
- |
191 |
- int portdir_fd = open(portdir, O_RDONLY|O_CLOEXEC|O_PATH); |
192 |
- if (portdir_fd < 0) |
193 |
- errp("open(%s) failed", portdir); |
194 |
- |
195 |
- q = NULL; /* Silence a gcc warning. */ |
196 |
- search_len = strlen(search_vars[idx]); |
197 |
|
198 |
- while ((linelen = getline(&ebuild, &ebuild_len, fp)) != -1) { |
199 |
- rmspace_len(ebuild, linelen); |
200 |
- if (!ebuild[0]) |
201 |
+ int ret = 0; |
202 |
+ size_t n; |
203 |
+ const char *overlay; |
204 |
+ array_for_each(overlays, n, overlay) { |
205 |
+ FILE *fp = fopen(initialize_flat(overlay, search_cache, false), "r"); |
206 |
+ if (!fp) { |
207 |
+ warnp("opening cache for %s failed", overlay); |
208 |
+ ret = 1; |
209 |
continue; |
210 |
+ } |
211 |
|
212 |
- switch (search_cache) { |
213 |
- |
214 |
- case CACHE_METADATA: { |
215 |
- portage_cache *pcache; |
216 |
- if ((pcache = cache_read_file(ebuild)) != NULL) { |
217 |
- if (strcmp(pcache->atom->PN, last) != 0) { |
218 |
- strncpy(last, pcache->atom->PN, sizeof(last)); |
219 |
- if ((rematch(search_me, (search_desc ? pcache->DESCRIPTION : ebuild), REG_EXTENDED | REG_ICASE) == 0) || search_all) |
220 |
- printf("%s%s/%s%s%s %s\n", BOLD, pcache->atom->CATEGORY, BLUE, |
221 |
- pcache->atom->PN, NORM, |
222 |
- (show_name_only ? "" : |
223 |
- (show_homepage ? pcache->HOMEPAGE : pcache->DESCRIPTION))); |
224 |
- } |
225 |
- cache_free(pcache); |
226 |
- } else { |
227 |
- if (!reinitialize) |
228 |
- warnf("(cache update pending) %s", ebuild); |
229 |
- reinitialize = 1; |
230 |
- } |
231 |
- break; |
232 |
+ int overlay_fd = open(overlay, O_RDONLY|O_CLOEXEC|O_PATH); |
233 |
+ if (overlay_fd < 0) { |
234 |
+ fclose(fp); |
235 |
+ warnp("open failed: %s", overlay); |
236 |
+ ret = 1; |
237 |
+ continue; |
238 |
} |
239 |
|
240 |
- case CACHE_EBUILD: { |
241 |
- FILE *ebuildfp; |
242 |
- str = xstrdup(ebuild); |
243 |
- p = dirname(str); |
244 |
- |
245 |
- if (strcmp(p, last) != 0) { |
246 |
- bool show_it = false; |
247 |
- strncpy(last, p, sizeof(last)); |
248 |
- if (search_name) { |
249 |
- if (rematch(search_me, basename(last), REG_EXTENDED | REG_ICASE) != 0) { |
250 |
- goto no_cache_ebuild_match; |
251 |
- } else { |
252 |
- q = NULL; |
253 |
- show_it = true; |
254 |
- } |
255 |
- } |
256 |
- |
257 |
- int fd = openat(portdir_fd, ebuild, O_RDONLY|O_CLOEXEC); |
258 |
- if (fd != -1) { |
259 |
- ebuildfp = fdopen(fd, "r"); |
260 |
- if (ebuildfp == NULL) { |
261 |
- close(fd); |
262 |
- continue; |
263 |
- } |
264 |
- } else { |
265 |
- if (!reinitialize) |
266 |
- warnfp("(cache update pending) %s", ebuild); |
267 |
- reinitialize = 1; |
268 |
- goto no_cache_ebuild_match; |
269 |
- } |
270 |
- |
271 |
- char *buf = NULL; |
272 |
- size_t buflen; |
273 |
- while ((linelen = getline(&buf, &buflen, ebuildfp)) != -1) { |
274 |
- if (linelen <= search_len) |
275 |
- continue; |
276 |
- if (strncmp(buf, search_vars[idx], search_len) != 0) |
277 |
- continue; |
278 |
- if ((q = strrchr(buf, '"')) != NULL) |
279 |
- *q = 0; |
280 |
- if (strlen(buf) <= search_len) |
281 |
- break; |
282 |
- q = buf + search_len + 1; |
283 |
- if (!search_all && !search_name && rematch(search_me, q, REG_EXTENDED | REG_ICASE) != 0) |
284 |
- break; |
285 |
- show_it = true; |
286 |
- break; |
287 |
- } |
288 |
- |
289 |
- if (show_it) { |
290 |
- printf("%s%s/%s%s%s %s\n", |
291 |
- BOLD, dirname(p), BLUE, basename(p), NORM, |
292 |
- (show_name_only ? "" : q ? : "<no DESCRIPTION found>")); |
293 |
- } |
294 |
- |
295 |
- free(buf); |
296 |
- fclose(ebuildfp); |
297 |
- } |
298 |
-no_cache_ebuild_match: |
299 |
- free(str); |
300 |
+ size_t buflen, linelen; |
301 |
+ char *buf = NULL; |
302 |
+ while ((linelen = getline(&buf, &buflen, fp)) != -1) { |
303 |
+ rmspace_len(buf, linelen); |
304 |
+ if (!buf[0]) |
305 |
+ continue; |
306 |
|
307 |
- break; |
308 |
- } /* case CACHE_EBUILD */ |
309 |
- } /* switch (search_cache) */ |
310 |
+ search_func(overlay_fd, buf, search_me, last, search_desc, |
311 |
+ search_all, search_name, show_name_only, show_homepage); |
312 |
+ } |
313 |
+ free(buf); |
314 |
+ close(overlay_fd); |
315 |
+ fclose(fp); |
316 |
} |
317 |
- free(ebuild); |
318 |
- close(portdir_fd); |
319 |
- fclose(fp); |
320 |
- return EXIT_SUCCESS; |
321 |
+ |
322 |
+ return ret; |
323 |
} |
324 |
|
325 |
#else |