1 |
commit: 5d0261aabae596a7beb9b6879201c43a064be800 |
2 |
Author: Fabian Groffen <grobian <AT> gentoo <DOT> org> |
3 |
AuthorDate: Thu Jan 2 14:59:24 2020 +0000 |
4 |
Commit: Fabian Groffen <grobian <AT> gentoo <DOT> org> |
5 |
CommitDate: Thu Jan 2 14:59:24 2020 +0000 |
6 |
URL: https://gitweb.gentoo.org/proj/portage-utils.git/commit/?id=5d0261aa |
7 |
|
8 |
qpkg: make use of tree being able to traverse binpkg trees |
9 |
|
10 |
Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org> |
11 |
|
12 |
qpkg.c | 172 ++++++++++++++++++++++++++--------------------------------------- |
13 |
1 file changed, 69 insertions(+), 103 deletions(-) |
14 |
|
15 |
diff --git a/qpkg.c b/qpkg.c |
16 |
index 771241c..b210b09 100644 |
17 |
--- a/qpkg.c |
18 |
+++ b/qpkg.c |
19 |
@@ -54,115 +54,79 @@ extern char pretend; |
20 |
static char *qpkg_bindir = NULL; |
21 |
static int eclean = 0; |
22 |
|
23 |
-/* checks to make sure this is a .tbz2 file. used by scandir() */ |
24 |
-static int |
25 |
-filter_tbz2(const struct dirent *dentry) |
26 |
-{ |
27 |
- if (dentry->d_name[0] == '.') |
28 |
- return 0; |
29 |
- if (strlen(dentry->d_name) < 6) |
30 |
- return 0; |
31 |
- return !strcmp(".tbz2", dentry->d_name + strlen(dentry->d_name) - 5); |
32 |
-} |
33 |
- |
34 |
-/* process a single dir for cleaning. dir can be a $PKGDIR, $PKGDIR/All/, $PKGDIR/$CAT */ |
35 |
-static uint64_t |
36 |
-qpkg_clean_dir(char *dirp, set *vdb) |
37 |
-{ |
38 |
- set *ll = NULL; |
39 |
- struct dirent **fnames; |
40 |
- int i, count; |
41 |
- char buf[_Q_PATH_MAX * 2]; |
42 |
- struct stat st; |
43 |
- uint64_t num_all_bytes = 0; |
44 |
- size_t disp_units = 0; |
45 |
- char **t; |
46 |
- bool ignore; |
47 |
- |
48 |
- if (dirp == NULL) |
49 |
- return 0; |
50 |
- if (chdir(dirp) != 0) |
51 |
- return 0; |
52 |
- if ((count = scandir(".", &fnames, filter_tbz2, alphasort)) < 0) |
53 |
- return 0; |
54 |
- |
55 |
- /* create copy of vdb with only basenames */ |
56 |
- for ((void)list_set(vdb, &t); *t != NULL; t++) |
57 |
- ll = add_set_unique(basename(*t), ll, &ignore); |
58 |
- |
59 |
- for (i = 0; i < count; i++) { |
60 |
- fnames[i]->d_name[strlen(fnames[i]->d_name)-5] = 0; |
61 |
- if (contains_set(fnames[i]->d_name, ll)) |
62 |
- continue; |
63 |
- snprintf(buf, sizeof(buf), "%s.tbz2", fnames[i]->d_name); |
64 |
- if (lstat(buf, &st) != -1) { |
65 |
- if (S_ISREG(st.st_mode)) { |
66 |
- disp_units = KILOBYTE; |
67 |
- if ((st.st_size / KILOBYTE) > 1000) |
68 |
- disp_units = MEGABYTE; |
69 |
- num_all_bytes += st.st_size; |
70 |
- qprintf(" %s[%s %3s %s %s] %s%s%s\n", |
71 |
- DKBLUE, GREEN, |
72 |
- make_human_readable_str(st.st_size, 1, disp_units), |
73 |
- disp_units == MEGABYTE ? "MiB" : "KiB", |
74 |
- DKBLUE, BLUE, fnames[i]->d_name, NORM); |
75 |
- } |
76 |
- if (!pretend) |
77 |
- unlink(buf); |
78 |
- } |
79 |
- } |
80 |
- |
81 |
- free_set(ll); |
82 |
- scandir_free(fnames, count); |
83 |
- |
84 |
- return num_all_bytes; |
85 |
-} |
86 |
- |
87 |
/* figure out what dirs we want to process for cleaning and display results. */ |
88 |
static int |
89 |
qpkg_clean(char *dirp) |
90 |
{ |
91 |
- int i, count; |
92 |
+ size_t n; |
93 |
size_t disp_units = 0; |
94 |
- uint64_t num_all_bytes; |
95 |
- struct dirent **dnames; |
96 |
- set *vdb = NULL; |
97 |
+ uint64_t num_all_bytes = 0; |
98 |
+ set *known_pkgs = NULL; |
99 |
+ set *bin_pkgs = NULL; |
100 |
+ DECLARE_ARRAY(bins); |
101 |
tree_ctx *t; |
102 |
+ tree_ctx *pkgs; |
103 |
+ char *binatomstr; |
104 |
+ depend_atom *atom; |
105 |
+ char buf[_Q_PATH_MAX]; |
106 |
+ struct stat st; |
107 |
|
108 |
- if (chdir(dirp) != 0) |
109 |
- return 1; |
110 |
- if ((count = scandir(".", &dnames, filter_hidden, alphasort)) < 0) |
111 |
+ pkgs = tree_open_binpkg(portroot, dirp); |
112 |
+ if (pkgs == NULL) |
113 |
return 1; |
114 |
|
115 |
+ bin_pkgs = tree_get_atoms(pkgs, true, bin_pkgs); |
116 |
+ array_set(bin_pkgs, bins); |
117 |
+ |
118 |
if (eclean) { |
119 |
- size_t n; |
120 |
const char *overlay; |
121 |
|
122 |
array_for_each(overlays, n, overlay) { |
123 |
t = tree_open(portroot, overlay); |
124 |
if (t != NULL) { |
125 |
- vdb = tree_get_atoms(t, true, vdb); |
126 |
+ known_pkgs = tree_get_atoms(t, true, known_pkgs); |
127 |
tree_close(t); |
128 |
} |
129 |
} |
130 |
} else { |
131 |
t = tree_open_vdb(portroot, portvdb); |
132 |
if (t != NULL) { |
133 |
- vdb = tree_get_atoms(t, true, vdb); |
134 |
+ known_pkgs = tree_get_atoms(t, true, known_pkgs); |
135 |
tree_close(t); |
136 |
} |
137 |
} |
138 |
|
139 |
- num_all_bytes = qpkg_clean_dir(dirp, vdb); |
140 |
+ /* check which binpkgs exist in the known_pkgs (vdb or trees), such |
141 |
+ * that the remainder is what we would clean */ |
142 |
+ array_for_each(bins, n, binatomstr) { |
143 |
+ if (contains_set(binatomstr, known_pkgs)) |
144 |
+ xarraydelete_ptr(bins, n--); |
145 |
+ } |
146 |
+ |
147 |
+ free_set(known_pkgs); |
148 |
|
149 |
- for (i = 0; i < count; i++) { |
150 |
- char buf[_Q_PATH_MAX * 2]; |
151 |
- snprintf(buf, sizeof(buf), "%s/%s", dirp, dnames[i]->d_name); |
152 |
- num_all_bytes += qpkg_clean_dir(buf, vdb); |
153 |
+ array_for_each(bins, n, binatomstr) { |
154 |
+ snprintf(buf, sizeof(buf), "%s/%s.tbz2", dirp, binatomstr); |
155 |
+ atom = atom_explode(binatomstr); |
156 |
+ if (lstat(buf, &st) != -1) { |
157 |
+ if (S_ISREG(st.st_mode)) { |
158 |
+ disp_units = KILOBYTE; |
159 |
+ if ((st.st_size / KILOBYTE) > 1000) |
160 |
+ disp_units = MEGABYTE; |
161 |
+ num_all_bytes += st.st_size; |
162 |
+ qprintf(" %s[%s %3s %s %s]%s %s\n", |
163 |
+ DKBLUE, GREEN, |
164 |
+ make_human_readable_str(st.st_size, 1, disp_units), |
165 |
+ disp_units == MEGABYTE ? "MiB" : "KiB", |
166 |
+ DKBLUE, NORM, atom_format("%[CAT]/%[PF]", atom)); |
167 |
+ } |
168 |
+ if (!pretend) |
169 |
+ unlink(buf); |
170 |
+ } |
171 |
} |
172 |
- scandir_free(dnames, count); |
173 |
|
174 |
- free_set(vdb); |
175 |
+ xarrayfree_int(bins); |
176 |
+ free_set(bin_pkgs); |
177 |
|
178 |
disp_units = KILOBYTE; |
179 |
if ((num_all_bytes / KILOBYTE) > 1000) |
180 |
@@ -328,15 +292,23 @@ qpkg_make(depend_atom *atom) |
181 |
return 0; |
182 |
} |
183 |
|
184 |
+static int |
185 |
+qpkg_cb(tree_pkg_ctx *pkg, void *priv) |
186 |
+{ |
187 |
+ size_t *pkgs_made = priv; |
188 |
+ |
189 |
+ if (qpkg_make(tree_get_atom(pkg, false)) == 0) |
190 |
+ (*pkgs_made)++; |
191 |
+ |
192 |
+ return 0; |
193 |
+} |
194 |
+ |
195 |
int qpkg_main(int argc, char **argv) |
196 |
{ |
197 |
tree_ctx *ctx; |
198 |
- tree_cat_ctx *cat_ctx; |
199 |
- tree_pkg_ctx *pkg_ctx; |
200 |
size_t s, pkgs_made; |
201 |
int i; |
202 |
struct stat st; |
203 |
- char buf[BUFSIZE]; |
204 |
depend_atom *atom; |
205 |
int restrict_chmod = 0; |
206 |
int qclean = 0; |
207 |
@@ -417,27 +389,21 @@ int qpkg_main(int argc, char **argv) |
208 |
if (!ctx) |
209 |
return EXIT_FAILURE; |
210 |
|
211 |
- /* scan all the categories */ |
212 |
- while ((cat_ctx = tree_next_cat(ctx))) { |
213 |
- /* scan all the packages in this category */ |
214 |
- while ((pkg_ctx = tree_next_pkg(cat_ctx))) { |
215 |
- /* see if user wants any of these packages */ |
216 |
- atom = tree_get_atom(pkg_ctx, false); |
217 |
- snprintf(buf, sizeof(buf), "%s/%s", atom->CATEGORY, atom->PN); |
218 |
- for (i = optind; i < argc; ++i) { |
219 |
- if (argv[i] == NULL) |
220 |
- continue; |
221 |
- |
222 |
- if (!strcmp(argv[i], atom->PN) || |
223 |
- !strcmp(argv[i], atom->P) || |
224 |
- !strcmp(argv[i], buf) || |
225 |
- !strcmp(argv[i], "world")) |
226 |
- if (!qpkg_make(atom)) |
227 |
- ++pkgs_made; |
228 |
- } |
229 |
- tree_close_pkg(pkg_ctx); |
230 |
+ for (i = optind; i < argc; ++i) { |
231 |
+ if (argv[i] == NULL) |
232 |
+ continue; |
233 |
+ if (strcmp(argv[i], "world") == 0) { |
234 |
+ /* we're basically done, this means all */ |
235 |
+ tree_foreach_pkg_fast(ctx, qpkg_cb, &pkgs_made, NULL); |
236 |
} |
237 |
+ atom = atom_explode(argv[i]); |
238 |
+ if (atom == NULL) |
239 |
+ continue; |
240 |
+ |
241 |
+ tree_foreach_pkg_fast(ctx, qpkg_cb, &pkgs_made, atom); |
242 |
+ atom_implode(atom); |
243 |
} |
244 |
+ tree_close(ctx); |
245 |
|
246 |
if (pkgs_made) |
247 |
qprintf(" %s*%s Packages can be found in %s\n", |