1 |
commit: e5ff6caad2f4b848f77e6de82c866fa42aba30ae |
2 |
Author: Fabian Groffen <grobian <AT> gentoo <DOT> org> |
3 |
AuthorDate: Sat Dec 14 16:56:39 2019 +0000 |
4 |
Commit: Fabian Groffen <grobian <AT> gentoo <DOT> org> |
5 |
CommitDate: Sat Dec 14 16:56:39 2019 +0000 |
6 |
URL: https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=e5ff6caa |
7 |
|
8 |
qkeyword: add modes to list just list latest stable/testing |
9 |
|
10 |
This functionality combined with -F allows usage with e.g. Puppet |
11 |
providers. |
12 |
|
13 |
Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org> |
14 |
|
15 |
man/qkeyword.1 | 23 +++++++++++----- |
16 |
qkeyword.c | 84 +++++++++++++++++++++++++++++++++++++++++++++------------- |
17 |
2 files changed, 81 insertions(+), 26 deletions(-) |
18 |
|
19 |
diff --git a/man/qkeyword.1 b/man/qkeyword.1 |
20 |
index c43fa61..34beb18 100644 |
21 |
--- a/man/qkeyword.1 |
22 |
+++ b/man/qkeyword.1 |
23 |
@@ -1,5 +1,5 @@ |
24 |
.\" generated by mkman.py, please do NOT edit! |
25 |
-.TH qkeyword "1" "Nov 2019" "Gentoo Foundation" "qkeyword" |
26 |
+.TH qkeyword "1" "Dec 2019" "Gentoo Foundation" "qkeyword" |
27 |
.SH NAME |
28 |
qkeyword \- list packages based on keywords |
29 |
.SH SYNOPSIS |
30 |
@@ -32,22 +32,31 @@ match catname. |
31 |
match maintainer email from metadata.xml (slow). |
32 |
.TP |
33 |
\fB\-i\fR, \fB\-\-imlate\fR |
34 |
-list packages that can be marked stable on a given arch. |
35 |
+list packages that can be marked stable for <arch>. |
36 |
.TP |
37 |
\fB\-d\fR, \fB\-\-dropped\fR |
38 |
-list packages that have dropped keywords on a version bump on a given arch. |
39 |
+list packages that have dropped keywords for <arch>. |
40 |
.TP |
41 |
-\fB\-t\fR, \fB\-\-testing\fR |
42 |
-list packages that have ~arch versions, but no stable versions on a given arch. |
43 |
+\fB\-t\fR, \fB\-\-needsstable\fR |
44 |
+list packages that have ~arch versions, but no stable versions for <arch>. |
45 |
.TP |
46 |
\fB\-s\fR, \fB\-\-stats\fR |
47 |
display statistics about the portage tree. |
48 |
.TP |
49 |
\fB\-a\fR, \fB\-\-all\fR |
50 |
-list packages that have at least one version keyworded for on a given arch. |
51 |
+list packages that have at least one version keyworded for <arch>. |
52 |
.TP |
53 |
\fB\-n\fR, \fB\-\-not\fR |
54 |
-list packages that aren't keyworded on a given arch. |
55 |
+list packages that aren't keyworded for <arch>. |
56 |
+.TP |
57 |
+\fB\-S\fR, \fB\-\-stable\fR |
58 |
+list latest stable version per package for <arch>. |
59 |
+.TP |
60 |
+\fB\-T\fR, \fB\-\-testing\fR |
61 |
+list latest testing version per package for <arch>. |
62 |
+.TP |
63 |
+\fB\-F\fR \fI<arg>\fR, \fB\-\-format\fR \fI<arg>\fR |
64 |
+Print latest atom using given format string. |
65 |
.TP |
66 |
\fB\-\-root\fR \fI<arg>\fR |
67 |
Set the ROOT env var. |
68 |
|
69 |
diff --git a/qkeyword.c b/qkeyword.c |
70 |
index 4c6c759..4a55b6a 100644 |
71 |
--- a/qkeyword.c |
72 |
+++ b/qkeyword.c |
73 |
@@ -28,29 +28,35 @@ |
74 |
/* Required portage-utils stuff */ |
75 |
/********************************************************************/ |
76 |
|
77 |
-#define QKEYWORD_FLAGS "p:c:m:idtans" COMMON_FLAGS |
78 |
+#define QKEYWORD_FLAGS "p:c:m:idtsanSTF:" COMMON_FLAGS |
79 |
static struct option const qkeyword_long_opts[] = { |
80 |
- {"matchpkg", a_argument, NULL, 'p'}, |
81 |
- {"matchcat", a_argument, NULL, 'c'}, |
82 |
- {"matchmaint", a_argument, NULL, 'm'}, |
83 |
- {"imlate", no_argument, NULL, 'i'}, |
84 |
- {"dropped", no_argument, NULL, 'd'}, |
85 |
- {"testing", no_argument, NULL, 't'}, |
86 |
- {"stats", no_argument, NULL, 's'}, |
87 |
- {"all", no_argument, NULL, 'a'}, |
88 |
- {"not", no_argument, NULL, 'n'}, |
89 |
+ {"matchpkg", a_argument, NULL, 'p'}, |
90 |
+ {"matchcat", a_argument, NULL, 'c'}, |
91 |
+ {"matchmaint", a_argument, NULL, 'm'}, |
92 |
+ {"imlate", no_argument, NULL, 'i'}, |
93 |
+ {"dropped", no_argument, NULL, 'd'}, |
94 |
+ {"needsstable", no_argument, NULL, 't'}, |
95 |
+ {"stats", no_argument, NULL, 's'}, |
96 |
+ {"all", no_argument, NULL, 'a'}, |
97 |
+ {"not", no_argument, NULL, 'n'}, |
98 |
+ {"stable", no_argument, NULL, 'S'}, |
99 |
+ {"testing", no_argument, NULL, 'T'}, |
100 |
+ {"format", a_argument, NULL, 'F'}, |
101 |
COMMON_LONG_OPTS |
102 |
}; |
103 |
static const char * const qkeyword_opts_help[] = { |
104 |
"match pkgname", |
105 |
"match catname", |
106 |
"match maintainer email from metadata.xml (slow)", |
107 |
- "list packages that can be marked stable on a given arch", |
108 |
- "list packages that have dropped keywords on a version bump on a given arch", |
109 |
- "list packages that have ~arch versions, but no stable versions on a given arch", |
110 |
+ "list packages that can be marked stable for <arch>", |
111 |
+ "list packages that have dropped keywords for <arch>", |
112 |
+ "list packages that have ~arch versions, but no stable versions for <arch>", |
113 |
"display statistics about the portage tree", |
114 |
- "list packages that have at least one version keyworded for on a given arch", |
115 |
- "list packages that aren't keyworded on a given arch.", |
116 |
+ "list packages that have at least one version keyworded for <arch>", |
117 |
+ "list packages that aren't keyworded for <arch>", |
118 |
+ "list latest stable version per package for <arch>", |
119 |
+ "list latest testing version per package for <arch>", |
120 |
+ "Print latest atom using given format string", |
121 |
COMMON_OPTS_HELP |
122 |
}; |
123 |
#define qkeyword_usage(ret) usage(ret, QKEYWORD_FLAGS, qkeyword_long_opts, qkeyword_opts_help, NULL, lookup_applet_idx("qkeyword")) |
124 |
@@ -63,6 +69,7 @@ typedef struct { |
125 |
size_t keywordsbuflen; |
126 |
const char *arch; |
127 |
tree_pkg_cb *runfunc; |
128 |
+ const char *fmt; |
129 |
} qkeyword_data; |
130 |
|
131 |
static set *archs = NULL; |
132 |
@@ -218,6 +225,34 @@ qkeyword_imlate(tree_pkg_ctx *pkg_ctx, void *priv) |
133 |
return EXIT_FAILURE; |
134 |
} |
135 |
|
136 |
+static int |
137 |
+qkeyword_lstable(tree_pkg_ctx *pkg_ctx, void *priv) |
138 |
+{ |
139 |
+ qkeyword_data *data = (qkeyword_data *)priv; |
140 |
+ |
141 |
+ if (data->keywordsbuf[qkeyword_test_arch] == stable) |
142 |
+ { |
143 |
+ printf("%s", atom_format(data->fmt, tree_get_atom(pkg_ctx, true))); |
144 |
+ return EXIT_SUCCESS; |
145 |
+ } |
146 |
+ |
147 |
+ return EXIT_FAILURE; |
148 |
+} |
149 |
+ |
150 |
+static int |
151 |
+qkeyword_ltesting(tree_pkg_ctx *pkg_ctx, void *priv) |
152 |
+{ |
153 |
+ qkeyword_data *data = (qkeyword_data *)priv; |
154 |
+ |
155 |
+ if (data->keywordsbuf[qkeyword_test_arch] == testing) |
156 |
+ { |
157 |
+ printf("%s\n", atom_format(data->fmt, tree_get_atom(pkg_ctx, true))); |
158 |
+ return EXIT_SUCCESS; |
159 |
+ } |
160 |
+ |
161 |
+ return EXIT_FAILURE; |
162 |
+} |
163 |
+ |
164 |
static int |
165 |
qkeyword_not(tree_pkg_ctx *pkg_ctx, void *priv) |
166 |
{ |
167 |
@@ -658,7 +693,6 @@ keyword_sort(const void *l, const void *r) |
168 |
char *ld = strchr(*ls, '-'); |
169 |
char *rd = strchr(*rs, '-'); |
170 |
|
171 |
- printf("%s vs %s\n", *ls, *rs); |
172 |
if (ld == NULL && rd != NULL) |
173 |
return -1; |
174 |
else if (ld != NULL && rd == NULL) |
175 |
@@ -729,7 +763,7 @@ qkeyword_traverse(tree_pkg_cb func, void *priv) |
176 |
const char *overlay; |
177 |
qkeyword_data *data = (qkeyword_data *)priv; |
178 |
|
179 |
- /* Preload all the arches. Not entirely correctly (as arches are bound |
180 |
+ /* Preload all the arches. Not entirely correct (as arches are bound |
181 |
* to overlays if set), but oh well. */ |
182 |
array_for_each(overlays, n, overlay) |
183 |
qkeyword_load_arches(overlay); |
184 |
@@ -767,6 +801,7 @@ int qkeyword_main(int argc, char **argv) |
185 |
char *cat = NULL; |
186 |
char *maint = NULL; |
187 |
|
188 |
+ data.fmt = NULL; |
189 |
while ((i = GETOPT_LONG(QKEYWORD, qkeyword, "")) != -1) { |
190 |
switch (i) { |
191 |
case 'p': pkg = optarg; break; |
192 |
@@ -778,11 +813,16 @@ int qkeyword_main(int argc, char **argv) |
193 |
case 's': |
194 |
case 'a': |
195 |
case 'n': |
196 |
- if (action) |
197 |
+ case 'S': |
198 |
+ case 'T': |
199 |
+ /* trying to use more than 1 action */ |
200 |
+ if (action != '\0') |
201 |
qkeyword_usage(EXIT_FAILURE); |
202 |
- /* trying to use more than 1 action */ |
203 |
action = i; |
204 |
break; |
205 |
+ case 'F': |
206 |
+ data.fmt = optarg; |
207 |
+ break; |
208 |
|
209 |
COMMON_GETOPTS_CASES(qkeyword) |
210 |
} |
211 |
@@ -815,6 +855,10 @@ int qkeyword_main(int argc, char **argv) |
212 |
data.qatom = NULL; |
213 |
} |
214 |
|
215 |
+ /* set format if none given */ |
216 |
+ if ((action == 'S' || action == 'T') && data.fmt == NULL) |
217 |
+ data.fmt = "%[CATEGORY]%[PF]"; |
218 |
+ |
219 |
archs = create_set(); |
220 |
archlist_count = 0; |
221 |
arch_longest_len = 0; |
222 |
@@ -834,6 +878,8 @@ int qkeyword_main(int argc, char **argv) |
223 |
i = qkeyword_stats(NULL, NULL); break; |
224 |
case 'a': i = qkeyword_traverse(qkeyword_all, &data); break; |
225 |
case 'n': i = qkeyword_traverse(qkeyword_not, &data); break; |
226 |
+ case 'S': i = qkeyword_traverse(qkeyword_lstable, &data); break; |
227 |
+ case 'T': i = qkeyword_traverse(qkeyword_ltesting, &data); break; |
228 |
default: i = -2; break; |
229 |
} |