1 |
commit: 9fe091668c8a1d988c02c849ac1bece6eb764d0b |
2 |
Author: John Helmert III <ajak <AT> gentoo <DOT> org> |
3 |
AuthorDate: Wed Feb 9 20:52:08 2022 +0000 |
4 |
Commit: Sam James <sam <AT> gentoo <DOT> org> |
5 |
CommitDate: Mon Feb 21 03:50:50 2022 +0000 |
6 |
URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=9fe09166 |
7 |
|
8 |
Blacken previously missed Python files |
9 |
|
10 |
Signed-off-by: John Helmert III <ajak <AT> gentoo.org> |
11 |
Signed-off-by: Sam James <sam <AT> gentoo.org> |
12 |
|
13 |
bin/archive-conf | 44 +- |
14 |
bin/binhost-snapshot | 262 +++--- |
15 |
bin/clean_locks | 56 +- |
16 |
bin/dispatch-conf | 345 ++++--- |
17 |
bin/ebuild | 512 ++++++----- |
18 |
bin/egencache | 2435 ++++++++++++++++++++++++++----------------------- |
19 |
bin/emaint | 43 +- |
20 |
bin/emerge | 128 +-- |
21 |
bin/emirrordist | 18 +- |
22 |
bin/env-update | 44 +- |
23 |
bin/fixpackages | 40 +- |
24 |
bin/glsa-check | 703 +++++++++------ |
25 |
bin/pid-ns-init | 42 +- |
26 |
bin/portageq | 2447 +++++++++++++++++++++++++++----------------------- |
27 |
bin/quickpkg | 734 ++++++++------- |
28 |
bin/regenworld | 207 +++-- |
29 |
bin/shelve-utils | 38 +- |
30 |
repoman/bin/repoman | 6 +- |
31 |
repoman/runtests | 113 +-- |
32 |
runtests | 110 +-- |
33 |
20 files changed, 4568 insertions(+), 3759 deletions(-) |
34 |
|
35 |
diff --git a/bin/archive-conf b/bin/archive-conf |
36 |
index 3b31ebe1a..beb4fcd23 100755 |
37 |
--- a/bin/archive-conf |
38 |
+++ b/bin/archive-conf |
39 |
@@ -12,18 +12,25 @@ |
40 |
import sys |
41 |
|
42 |
from os import path as osp |
43 |
-if osp.isfile(osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), ".portage_not_installed")): |
44 |
- sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "lib")) |
45 |
+ |
46 |
+if osp.isfile( |
47 |
+ osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), ".portage_not_installed") |
48 |
+): |
49 |
+ sys.path.insert( |
50 |
+ 0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "lib") |
51 |
+ ) |
52 |
import portage |
53 |
+ |
54 |
portage._internal_caller = True |
55 |
|
56 |
import portage.dispatch_conf |
57 |
from portage import os |
58 |
from portage.checksum import perform_md5 |
59 |
|
60 |
-FIND_EXTANT_CONTENTS = "find %s -name CONTENTS" |
61 |
+FIND_EXTANT_CONTENTS = "find %s -name CONTENTS" |
62 |
+ |
63 |
+MANDATORY_OPTS = ["archive-dir"] |
64 |
|
65 |
-MANDATORY_OPTS = [ 'archive-dir' ] |
66 |
|
67 |
def archive_conf(): |
68 |
args = [] |
69 |
@@ -35,12 +42,15 @@ def archive_conf(): |
70 |
for conf in sys.argv[1:]: |
71 |
if not os.path.isabs(conf): |
72 |
conf = os.path.abspath(conf) |
73 |
- args += [ conf ] |
74 |
- md5_match_hash[conf] = '' |
75 |
+ args += [conf] |
76 |
+ md5_match_hash[conf] = "" |
77 |
|
78 |
# Find all the CONTENT files in VDB_PATH. |
79 |
- with os.popen(FIND_EXTANT_CONTENTS % (os.path.join(portage.settings['EROOT'], portage.VDB_PATH))) as f: |
80 |
- content_files += f.readlines() |
81 |
+ with os.popen( |
82 |
+ FIND_EXTANT_CONTENTS |
83 |
+ % (os.path.join(portage.settings["EROOT"], portage.VDB_PATH)) |
84 |
+ ) as f: |
85 |
+ content_files += f.readlines() |
86 |
|
87 |
# Search for the saved md5 checksum of all the specified config files |
88 |
# and see if the current file is unmodified or not. |
89 |
@@ -51,12 +61,15 @@ def archive_conf(): |
90 |
try: |
91 |
contents = open(filename, "r") |
92 |
except IOError as e: |
93 |
- print('archive-conf: Unable to open %s: %s' % (filename, e), file=sys.stderr) |
94 |
+ print( |
95 |
+ "archive-conf: Unable to open %s: %s" % (filename, e), |
96 |
+ file=sys.stderr, |
97 |
+ ) |
98 |
sys.exit(1) |
99 |
lines = contents.readlines() |
100 |
for line in lines: |
101 |
items = line.split() |
102 |
- if items[0] == 'obj': |
103 |
+ if items[0] == "obj": |
104 |
for conf in args: |
105 |
if items[1] == conf: |
106 |
stored = items[2].lower() |
107 |
@@ -70,18 +83,19 @@ def archive_conf(): |
108 |
pass |
109 |
|
110 |
for conf in args: |
111 |
- archive = os.path.join(options['archive-dir'], conf.lstrip('/')) |
112 |
- if options['use-rcs'] == 'yes': |
113 |
- portage.dispatch_conf.rcs_archive(archive, conf, md5_match_hash[conf], '') |
114 |
+ archive = os.path.join(options["archive-dir"], conf.lstrip("/")) |
115 |
+ if options["use-rcs"] == "yes": |
116 |
+ portage.dispatch_conf.rcs_archive(archive, conf, md5_match_hash[conf], "") |
117 |
if md5_match_hash[conf]: |
118 |
portage.dispatch_conf.rcs_archive_post_process(archive) |
119 |
else: |
120 |
- portage.dispatch_conf.file_archive(archive, conf, md5_match_hash[conf], '') |
121 |
+ portage.dispatch_conf.file_archive(archive, conf, md5_match_hash[conf], "") |
122 |
if md5_match_hash[conf]: |
123 |
portage.dispatch_conf.file_archive_post_process(archive) |
124 |
|
125 |
+ |
126 |
# run |
127 |
if len(sys.argv) > 1: |
128 |
archive_conf() |
129 |
else: |
130 |
- print('Usage: archive-conf /CONFIG/FILE [/CONFIG/FILE...]', file=sys.stderr) |
131 |
+ print("Usage: archive-conf /CONFIG/FILE [/CONFIG/FILE...]", file=sys.stderr) |
132 |
|
133 |
diff --git a/bin/binhost-snapshot b/bin/binhost-snapshot |
134 |
index 2201781d6..3461a301c 100755 |
135 |
--- a/bin/binhost-snapshot |
136 |
+++ b/bin/binhost-snapshot |
137 |
@@ -11,128 +11,156 @@ import textwrap |
138 |
from urllib.parse import urlparse |
139 |
|
140 |
from os import path as osp |
141 |
-if osp.isfile(osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), ".portage_not_installed")): |
142 |
- sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "lib")) |
143 |
+ |
144 |
+if osp.isfile( |
145 |
+ osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), ".portage_not_installed") |
146 |
+): |
147 |
+ sys.path.insert( |
148 |
+ 0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "lib") |
149 |
+ ) |
150 |
import portage |
151 |
+ |
152 |
portage._internal_caller = True |
153 |
|
154 |
+ |
155 |
def parse_args(argv): |
156 |
- prog_name = os.path.basename(argv[0]) |
157 |
- usage = prog_name + ' [options] ' + \ |
158 |
- '<src_pkg_dir> <snapshot_dir> <snapshot_uri> <binhost_dir>' |
159 |
- |
160 |
- prog_desc = "This program will copy src_pkg_dir to snapshot_dir " + \ |
161 |
- "and inside binhost_dir it will create a Packages index file " + \ |
162 |
- "which refers to snapshot_uri. This is intended to solve race " + \ |
163 |
- "conditions on binhosts as described at http://crosbug.com/3225." |
164 |
- |
165 |
- usage += "\n\n" |
166 |
- for line in textwrap.wrap(prog_desc, 70): |
167 |
- usage += line + "\n" |
168 |
- |
169 |
- usage += "\n" |
170 |
- usage += "Required Arguments:\n\n" |
171 |
- usage += " src_pkg_dir - the source $PKGDIR\n" |
172 |
- usage += " snapshot_dir - destination snapshot " + \ |
173 |
- "directory (must not exist)\n" |
174 |
- usage += " snapshot_uri - URI which refers to " + \ |
175 |
- "snapshot_dir from the\n" + \ |
176 |
- " client side\n" |
177 |
- usage += " binhost_dir - directory in which to " + \ |
178 |
- "write Packages index with\n" + \ |
179 |
- " snapshot_uri" |
180 |
- |
181 |
- parser = argparse.ArgumentParser(usage=usage) |
182 |
- parser.add_argument('--hardlinks', |
183 |
- help='create hardlinks (y or n, default is y)', |
184 |
- choices=('y', 'n'), |
185 |
- default='y') |
186 |
- options, args = parser.parse_known_args(argv[1:]) |
187 |
- |
188 |
- if len(args) != 4: |
189 |
- parser.error("Required 4 arguments, got %d" % (len(args),)) |
190 |
- |
191 |
- return parser, options, args |
192 |
+ prog_name = os.path.basename(argv[0]) |
193 |
+ usage = ( |
194 |
+ prog_name |
195 |
+ + " [options] " |
196 |
+ + "<src_pkg_dir> <snapshot_dir> <snapshot_uri> <binhost_dir>" |
197 |
+ ) |
198 |
+ |
199 |
+ prog_desc = ( |
200 |
+ "This program will copy src_pkg_dir to snapshot_dir " |
201 |
+ + "and inside binhost_dir it will create a Packages index file " |
202 |
+ + "which refers to snapshot_uri. This is intended to solve race " |
203 |
+ + "conditions on binhosts as described at http://crosbug.com/3225." |
204 |
+ ) |
205 |
+ |
206 |
+ usage += "\n\n" |
207 |
+ for line in textwrap.wrap(prog_desc, 70): |
208 |
+ usage += line + "\n" |
209 |
+ |
210 |
+ usage += "\n" |
211 |
+ usage += "Required Arguments:\n\n" |
212 |
+ usage += " src_pkg_dir - the source $PKGDIR\n" |
213 |
+ usage += " snapshot_dir - destination snapshot " + "directory (must not exist)\n" |
214 |
+ usage += ( |
215 |
+ " snapshot_uri - URI which refers to " |
216 |
+ + "snapshot_dir from the\n" |
217 |
+ + " client side\n" |
218 |
+ ) |
219 |
+ usage += ( |
220 |
+ " binhost_dir - directory in which to " |
221 |
+ + "write Packages index with\n" |
222 |
+ + " snapshot_uri" |
223 |
+ ) |
224 |
+ |
225 |
+ parser = argparse.ArgumentParser(usage=usage) |
226 |
+ parser.add_argument( |
227 |
+ "--hardlinks", |
228 |
+ help="create hardlinks (y or n, default is y)", |
229 |
+ choices=("y", "n"), |
230 |
+ default="y", |
231 |
+ ) |
232 |
+ options, args = parser.parse_known_args(argv[1:]) |
233 |
+ |
234 |
+ if len(args) != 4: |
235 |
+ parser.error("Required 4 arguments, got %d" % (len(args),)) |
236 |
+ |
237 |
+ return parser, options, args |
238 |
+ |
239 |
|
240 |
def main(argv): |
241 |
- parser, options, args = parse_args(argv) |
242 |
- |
243 |
- src_pkg_dir, snapshot_dir, snapshot_uri, binhost_dir = args |
244 |
- src_pkgs_index = os.path.join(src_pkg_dir, 'Packages') |
245 |
- |
246 |
- if not os.path.isdir(src_pkg_dir): |
247 |
- parser.error("src_pkg_dir is not a directory: '%s'" % (src_pkg_dir,)) |
248 |
- |
249 |
- if not os.path.isfile(src_pkgs_index): |
250 |
- parser.error("src_pkg_dir does not contain a " + \ |
251 |
- "'Packages' index: '%s'" % (src_pkg_dir,)) |
252 |
- |
253 |
- parse_result = urlparse(snapshot_uri) |
254 |
- if not (parse_result.scheme and parse_result.netloc and parse_result.path): |
255 |
- parser.error("snapshot_uri is not a valid URI: '%s'" % (snapshot_uri,)) |
256 |
- |
257 |
- if os.path.isdir(snapshot_dir): |
258 |
- parser.error("snapshot_dir already exists: '%s'" % snapshot_dir) |
259 |
- |
260 |
- try: |
261 |
- os.makedirs(os.path.dirname(snapshot_dir)) |
262 |
- except OSError: |
263 |
- pass |
264 |
- if not os.path.isdir(os.path.dirname(snapshot_dir)): |
265 |
- parser.error("snapshot_dir parent could not be created: '%s'" % \ |
266 |
- os.path.dirname(snapshot_dir)) |
267 |
- |
268 |
- try: |
269 |
- os.makedirs(binhost_dir) |
270 |
- except OSError: |
271 |
- pass |
272 |
- if not os.path.isdir(binhost_dir): |
273 |
- parser.error("binhost_dir could not be created: '%s'" % binhost_dir) |
274 |
- |
275 |
- cp_opts = 'RP' |
276 |
- if options.hardlinks == 'n': |
277 |
- cp_opts += 'p' |
278 |
- else: |
279 |
- cp_opts += 'l' |
280 |
- |
281 |
- cp_cmd = 'cp -%s %s %s' % ( |
282 |
- cp_opts, |
283 |
- portage._shell_quote(src_pkg_dir), |
284 |
- portage._shell_quote(snapshot_dir) |
285 |
- ) |
286 |
- |
287 |
- ret = os.system(cp_cmd) |
288 |
- if not (os.WIFEXITED(ret) and os.WEXITSTATUS(ret) == os.EX_OK): |
289 |
- return 1 |
290 |
- |
291 |
- infile = io.open(portage._unicode_encode(src_pkgs_index, |
292 |
- encoding=portage._encodings['fs'], errors='strict'), |
293 |
- mode='r', encoding=portage._encodings['repo.content'], |
294 |
- errors='strict') |
295 |
- |
296 |
- outfile = portage.util.atomic_ofstream( |
297 |
- os.path.join(binhost_dir, "Packages"), |
298 |
- encoding=portage._encodings['repo.content'], |
299 |
- errors='strict') |
300 |
- |
301 |
- for line in infile: |
302 |
- if line[:4] == 'URI:': |
303 |
- # skip existing URI line |
304 |
- pass |
305 |
- else: |
306 |
- if not line.strip(): |
307 |
- # end of header |
308 |
- outfile.write("URI: %s\n\n" % snapshot_uri) |
309 |
- break |
310 |
- outfile.write(line) |
311 |
- |
312 |
- for line in infile: |
313 |
- outfile.write(line) |
314 |
- |
315 |
- infile.close() |
316 |
- outfile.close() |
317 |
- |
318 |
- return os.EX_OK |
319 |
+ parser, options, args = parse_args(argv) |
320 |
+ |
321 |
+ src_pkg_dir, snapshot_dir, snapshot_uri, binhost_dir = args |
322 |
+ src_pkgs_index = os.path.join(src_pkg_dir, "Packages") |
323 |
+ |
324 |
+ if not os.path.isdir(src_pkg_dir): |
325 |
+ parser.error("src_pkg_dir is not a directory: '%s'" % (src_pkg_dir,)) |
326 |
+ |
327 |
+ if not os.path.isfile(src_pkgs_index): |
328 |
+ parser.error( |
329 |
+ "src_pkg_dir does not contain a " |
330 |
+ + "'Packages' index: '%s'" % (src_pkg_dir,) |
331 |
+ ) |
332 |
+ |
333 |
+ parse_result = urlparse(snapshot_uri) |
334 |
+ if not (parse_result.scheme and parse_result.netloc and parse_result.path): |
335 |
+ parser.error("snapshot_uri is not a valid URI: '%s'" % (snapshot_uri,)) |
336 |
+ |
337 |
+ if os.path.isdir(snapshot_dir): |
338 |
+ parser.error("snapshot_dir already exists: '%s'" % snapshot_dir) |
339 |
+ |
340 |
+ try: |
341 |
+ os.makedirs(os.path.dirname(snapshot_dir)) |
342 |
+ except OSError: |
343 |
+ pass |
344 |
+ if not os.path.isdir(os.path.dirname(snapshot_dir)): |
345 |
+ parser.error( |
346 |
+ "snapshot_dir parent could not be created: '%s'" |
347 |
+ % os.path.dirname(snapshot_dir) |
348 |
+ ) |
349 |
+ |
350 |
+ try: |
351 |
+ os.makedirs(binhost_dir) |
352 |
+ except OSError: |
353 |
+ pass |
354 |
+ if not os.path.isdir(binhost_dir): |
355 |
+ parser.error("binhost_dir could not be created: '%s'" % binhost_dir) |
356 |
+ |
357 |
+ cp_opts = "RP" |
358 |
+ if options.hardlinks == "n": |
359 |
+ cp_opts += "p" |
360 |
+ else: |
361 |
+ cp_opts += "l" |
362 |
+ |
363 |
+ cp_cmd = "cp -%s %s %s" % ( |
364 |
+ cp_opts, |
365 |
+ portage._shell_quote(src_pkg_dir), |
366 |
+ portage._shell_quote(snapshot_dir), |
367 |
+ ) |
368 |
+ |
369 |
+ ret = os.system(cp_cmd) |
370 |
+ if not (os.WIFEXITED(ret) and os.WEXITSTATUS(ret) == os.EX_OK): |
371 |
+ return 1 |
372 |
+ |
373 |
+ infile = io.open( |
374 |
+ portage._unicode_encode( |
375 |
+ src_pkgs_index, encoding=portage._encodings["fs"], errors="strict" |
376 |
+ ), |
377 |
+ mode="r", |
378 |
+ encoding=portage._encodings["repo.content"], |
379 |
+ errors="strict", |
380 |
+ ) |
381 |
+ |
382 |
+ outfile = portage.util.atomic_ofstream( |
383 |
+ os.path.join(binhost_dir, "Packages"), |
384 |
+ encoding=portage._encodings["repo.content"], |
385 |
+ errors="strict", |
386 |
+ ) |
387 |
+ |
388 |
+ for line in infile: |
389 |
+ if line[:4] == "URI:": |
390 |
+ # skip existing URI line |
391 |
+ pass |
392 |
+ else: |
393 |
+ if not line.strip(): |
394 |
+ # end of header |
395 |
+ outfile.write("URI: %s\n\n" % snapshot_uri) |
396 |
+ break |
397 |
+ outfile.write(line) |
398 |
+ |
399 |
+ for line in infile: |
400 |
+ outfile.write(line) |
401 |
+ |
402 |
+ infile.close() |
403 |
+ outfile.close() |
404 |
+ |
405 |
+ return os.EX_OK |
406 |
+ |
407 |
|
408 |
if __name__ == "__main__": |
409 |
- sys.exit(main(sys.argv)) |
410 |
+ sys.exit(main(sys.argv)) |
411 |
|
412 |
diff --git a/bin/clean_locks b/bin/clean_locks |
413 |
index 6618f58da..88e1b3325 100755 |
414 |
--- a/bin/clean_locks |
415 |
+++ b/bin/clean_locks |
416 |
@@ -5,38 +5,44 @@ |
417 |
import errno |
418 |
import sys |
419 |
from os import path as osp |
420 |
-if osp.isfile(osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), ".portage_not_installed")): |
421 |
- sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "lib")) |
422 |
+ |
423 |
+if osp.isfile( |
424 |
+ osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), ".portage_not_installed") |
425 |
+): |
426 |
+ sys.path.insert( |
427 |
+ 0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "lib") |
428 |
+ ) |
429 |
import portage |
430 |
+ |
431 |
portage._internal_caller = True |
432 |
|
433 |
if not sys.argv[1:] or "--help" in sys.argv or "-h" in sys.argv: |
434 |
- print() |
435 |
- print("You must specify directories with hardlink-locks to clean.") |
436 |
- print("You may optionally specify --force, which will remove all") |
437 |
- print("of the locks, even if we can't establish if they are in use.") |
438 |
- print("Please attempt cleaning without force first.") |
439 |
- print() |
440 |
- print("%s %s/.locks" % (sys.argv[0], portage.settings["DISTDIR"])) |
441 |
- print("%s --force %s/.locks" % (sys.argv[0], portage.settings["DISTDIR"])) |
442 |
- print() |
443 |
- sys.exit(1) |
444 |
+ print() |
445 |
+ print("You must specify directories with hardlink-locks to clean.") |
446 |
+ print("You may optionally specify --force, which will remove all") |
447 |
+ print("of the locks, even if we can't establish if they are in use.") |
448 |
+ print("Please attempt cleaning without force first.") |
449 |
+ print() |
450 |
+ print("%s %s/.locks" % (sys.argv[0], portage.settings["DISTDIR"])) |
451 |
+ print("%s --force %s/.locks" % (sys.argv[0], portage.settings["DISTDIR"])) |
452 |
+ print() |
453 |
+ sys.exit(1) |
454 |
|
455 |
force = False |
456 |
if "--force" in sys.argv[1:]: |
457 |
- force=True |
458 |
+ force = True |
459 |
|
460 |
for x in sys.argv[1:]: |
461 |
- if x == "--force": |
462 |
- continue |
463 |
- try: |
464 |
- for y in portage.locks.hardlock_cleanup(x, remove_all_locks=force): |
465 |
- print(y) |
466 |
- print() |
467 |
+ if x == "--force": |
468 |
+ continue |
469 |
+ try: |
470 |
+ for y in portage.locks.hardlock_cleanup(x, remove_all_locks=force): |
471 |
+ print(y) |
472 |
+ print() |
473 |
|
474 |
- except OSError as e: |
475 |
- if e.errno in (errno.ENOENT, errno.ENOTDIR): |
476 |
- print("!!! %s is not a directory or does not exist" % x) |
477 |
- else: |
478 |
- raise |
479 |
- sys.exit(e.errno) |
480 |
+ except OSError as e: |
481 |
+ if e.errno in (errno.ENOENT, errno.ENOTDIR): |
482 |
+ print("!!! %s is not a directory or does not exist" % x) |
483 |
+ else: |
484 |
+ raise |
485 |
+ sys.exit(e.errno) |
486 |
|
487 |
diff --git a/bin/dispatch-conf b/bin/dispatch-conf |
488 |
index a4ca80ba9..c0e7ffc1e 100755 |
489 |
--- a/bin/dispatch-conf |
490 |
+++ b/bin/dispatch-conf |
491 |
@@ -23,28 +23,39 @@ from stat import ST_GID, ST_MODE, ST_UID |
492 |
from random import random |
493 |
|
494 |
try: |
495 |
- import curses |
496 |
+ import curses |
497 |
except ImportError: |
498 |
- curses = None |
499 |
+ curses = None |
500 |
|
501 |
from os import path as osp |
502 |
-if osp.isfile(osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), ".portage_not_installed")): |
503 |
- sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "lib")) |
504 |
+ |
505 |
+if osp.isfile( |
506 |
+ osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), ".portage_not_installed") |
507 |
+): |
508 |
+ sys.path.insert( |
509 |
+ 0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "lib") |
510 |
+ ) |
511 |
import portage |
512 |
+ |
513 |
portage._internal_caller = True |
514 |
from portage import os, shutil |
515 |
from portage import _encodings, _unicode_decode |
516 |
-from portage.dispatch_conf import (diffstatusoutput, diff_mixed_wrapper, |
517 |
- perform_conf_update_hooks, perform_conf_update_session_hooks) |
518 |
+from portage.dispatch_conf import ( |
519 |
+ diffstatusoutput, |
520 |
+ diff_mixed_wrapper, |
521 |
+ perform_conf_update_hooks, |
522 |
+ perform_conf_update_session_hooks, |
523 |
+) |
524 |
from portage.process import find_binary, spawn |
525 |
from portage.util import writemsg, writemsg_stdout |
526 |
|
527 |
-FIND_EXTANT_CONFIGS = "find '%s' %s -name '._cfg????_%s' ! -name '.*~' ! -iname '.*.bak' -print" |
528 |
-DIFF_CONTENTS = "diff -Nu '%s' '%s'" |
529 |
+FIND_EXTANT_CONFIGS = ( |
530 |
+ "find '%s' %s -name '._cfg????_%s' ! -name '.*~' ! -iname '.*.bak' -print" |
531 |
+) |
532 |
+DIFF_CONTENTS = "diff -Nu '%s' '%s'" |
533 |
|
534 |
if "case-insensitive-fs" in portage.settings.features: |
535 |
- FIND_EXTANT_CONFIGS = FIND_EXTANT_CONFIGS.replace( |
536 |
- "-name '._cfg", "-iname '._cfg") |
537 |
+ FIND_EXTANT_CONFIGS = FIND_EXTANT_CONFIGS.replace("-name '._cfg", "-iname '._cfg") |
538 |
|
539 |
# We need a secure scratch dir and python does silly verbose errors on the use of tempnam |
540 |
oldmask = os.umask(0o077) |
541 |
@@ -52,13 +63,13 @@ SCRATCH_DIR = None |
542 |
while SCRATCH_DIR is None: |
543 |
try: |
544 |
mydir = "/tmp/dispatch-conf." |
545 |
- for x in range(0,8): |
546 |
+ for x in range(0, 8): |
547 |
if int(random() * 3) == 0: |
548 |
- mydir += chr(int(65+random()*26.0)) |
549 |
+ mydir += chr(int(65 + random() * 26.0)) |
550 |
elif int(random() * 2) == 0: |
551 |
- mydir += chr(int(97+random()*26.0)) |
552 |
+ mydir += chr(int(97 + random() * 26.0)) |
553 |
else: |
554 |
- mydir += chr(int(48+random()*10.0)) |
555 |
+ mydir += chr(int(48 + random() * 10.0)) |
556 |
if os.path.exists(mydir): |
557 |
continue |
558 |
os.mkdir(mydir) |
559 |
@@ -71,9 +82,12 @@ os.umask(oldmask) |
560 |
# Ensure the scratch dir is deleted |
561 |
def cleanup(mydir=SCRATCH_DIR): |
562 |
shutil.rmtree(mydir) |
563 |
+ |
564 |
+ |
565 |
atexit.register(cleanup) |
566 |
|
567 |
-MANDATORY_OPTS = [ 'archive-dir', 'diff', 'replace-cvs', 'replace-wscomments', 'merge' ] |
568 |
+MANDATORY_OPTS = ["archive-dir", "diff", "replace-cvs", "replace-wscomments", "merge"] |
569 |
+ |
570 |
|
571 |
def cmd_var_is_valid(cmd): |
572 |
""" |
573 |
@@ -89,12 +103,14 @@ def cmd_var_is_valid(cmd): |
574 |
|
575 |
return find_binary(cmd[0]) is not None |
576 |
|
577 |
+ |
578 |
diff = diff_mixed_wrapper(diffstatusoutput, DIFF_CONTENTS) |
579 |
|
580 |
+ |
581 |
class dispatch: |
582 |
options = {} |
583 |
|
584 |
- def grind (self, config_paths): |
585 |
+ def grind(self, config_paths): |
586 |
confs = [] |
587 |
count = 0 |
588 |
|
589 |
@@ -105,10 +121,11 @@ class dispatch: |
590 |
|
591 |
if "log-file" in self.options: |
592 |
if os.path.isfile(self.options["log-file"]): |
593 |
- shutil.copy(self.options["log-file"], self.options["log-file"] + '.old') |
594 |
- if os.path.isfile(self.options["log-file"]) \ |
595 |
- or not os.path.exists(self.options["log-file"]): |
596 |
- open(self.options["log-file"], 'w').close() # Truncate it |
597 |
+ shutil.copy(self.options["log-file"], self.options["log-file"] + ".old") |
598 |
+ if os.path.isfile(self.options["log-file"]) or not os.path.exists( |
599 |
+ self.options["log-file"] |
600 |
+ ): |
601 |
+ open(self.options["log-file"], "w").close() # Truncate it |
602 |
os.chmod(self.options["log-file"], 0o600) |
603 |
|
604 |
pager = self.options.get("pager") |
605 |
@@ -134,7 +151,8 @@ class dispatch: |
606 |
|
607 |
for path in config_paths: |
608 |
path = portage.normalize_path( |
609 |
- os.path.join(config_root, path.lstrip(os.sep))) |
610 |
+ os.path.join(config_root, path.lstrip(os.sep)) |
611 |
+ ) |
612 |
|
613 |
# Protect files that don't exist (bug #523684). If the |
614 |
# parent directory doesn't exist, we can safely skip it. |
615 |
@@ -148,32 +166,38 @@ class dispatch: |
616 |
find_opts = "-maxdepth 1" |
617 |
|
618 |
try: |
619 |
- path_list = _unicode_decode(subprocess.check_output( |
620 |
- portage.util.shlex_split(FIND_EXTANT_CONFIGS % |
621 |
- (path, find_opts, basename))), |
622 |
- errors='strict').splitlines() |
623 |
+ path_list = _unicode_decode( |
624 |
+ subprocess.check_output( |
625 |
+ portage.util.shlex_split( |
626 |
+ FIND_EXTANT_CONFIGS % (path, find_opts, basename) |
627 |
+ ) |
628 |
+ ), |
629 |
+ errors="strict", |
630 |
+ ).splitlines() |
631 |
except subprocess.CalledProcessError: |
632 |
pass |
633 |
else: |
634 |
confs.extend(self.massage(path_list)) |
635 |
|
636 |
- if self.options['use-rcs'] == 'yes': |
637 |
+ if self.options["use-rcs"] == "yes": |
638 |
for rcs_util in ("rcs", "ci", "co", "rcsmerge"): |
639 |
if not find_binary(rcs_util): |
640 |
- print('dispatch-conf: Error finding all RCS utils and " + \ |
641 |
- "use-rcs=yes in config; fatal', file=sys.stderr) |
642 |
+ print( |
643 |
+ 'dispatch-conf: Error finding all RCS utils and " + \ |
644 |
+ "use-rcs=yes in config; fatal', |
645 |
+ file=sys.stderr, |
646 |
+ ) |
647 |
return False |
648 |
|
649 |
- |
650 |
# config file freezing support |
651 |
frozen_files = set(self.options.get("frozen-files", "").split()) |
652 |
auto_zapped = [] |
653 |
protect_obj = portage.util.ConfigProtect( |
654 |
- config_root, config_paths, |
655 |
- portage.util.shlex_split( |
656 |
- portage.settings.get('CONFIG_PROTECT_MASK', '')), |
657 |
- case_insensitive=("case-insensitive-fs" |
658 |
- in portage.settings.features)) |
659 |
+ config_root, |
660 |
+ config_paths, |
661 |
+ portage.util.shlex_split(portage.settings.get("CONFIG_PROTECT_MASK", "")), |
662 |
+ case_insensitive=("case-insensitive-fs" in portage.settings.features), |
663 |
+ ) |
664 |
|
665 |
# |
666 |
# Remove new configs identical to current |
667 |
@@ -183,36 +207,44 @@ class dispatch: |
668 |
# or c) in paths now unprotected by CONFIG_PROTECT_MASK, |
669 |
# |
670 |
|
671 |
- def f (conf): |
672 |
- mrgconf = re.sub(r'\._cfg', '._mrg', conf['new']) |
673 |
- archive = os.path.join(self.options['archive-dir'], conf['current'].lstrip('/')) |
674 |
- if self.options['use-rcs'] == 'yes': |
675 |
- mrgfail = portage.dispatch_conf.rcs_archive(archive, conf['current'], conf['new'], mrgconf) |
676 |
+ def f(conf): |
677 |
+ mrgconf = re.sub(r"\._cfg", "._mrg", conf["new"]) |
678 |
+ archive = os.path.join( |
679 |
+ self.options["archive-dir"], conf["current"].lstrip("/") |
680 |
+ ) |
681 |
+ if self.options["use-rcs"] == "yes": |
682 |
+ mrgfail = portage.dispatch_conf.rcs_archive( |
683 |
+ archive, conf["current"], conf["new"], mrgconf |
684 |
+ ) |
685 |
else: |
686 |
- mrgfail = portage.dispatch_conf.file_archive(archive, conf['current'], conf['new'], mrgconf) |
687 |
- if os.path.lexists(archive + '.dist'): |
688 |
- unmodified = len(diff(conf['current'], archive + '.dist')[1]) == 0 |
689 |
+ mrgfail = portage.dispatch_conf.file_archive( |
690 |
+ archive, conf["current"], conf["new"], mrgconf |
691 |
+ ) |
692 |
+ if os.path.lexists(archive + ".dist"): |
693 |
+ unmodified = len(diff(conf["current"], archive + ".dist")[1]) == 0 |
694 |
else: |
695 |
unmodified = 0 |
696 |
if os.path.exists(mrgconf): |
697 |
- if mrgfail or len(diff(conf['new'], mrgconf)[1]) == 0: |
698 |
+ if mrgfail or len(diff(conf["new"], mrgconf)[1]) == 0: |
699 |
os.unlink(mrgconf) |
700 |
- newconf = conf['new'] |
701 |
+ newconf = conf["new"] |
702 |
else: |
703 |
newconf = mrgconf |
704 |
else: |
705 |
- newconf = conf['new'] |
706 |
- |
707 |
- if newconf == mrgconf and \ |
708 |
- self.options.get('ignore-previously-merged') != 'yes' and \ |
709 |
- os.path.lexists(archive+'.dist') and \ |
710 |
- len(diff(archive+'.dist', conf['new'])[1]) == 0: |
711 |
+ newconf = conf["new"] |
712 |
+ |
713 |
+ if ( |
714 |
+ newconf == mrgconf |
715 |
+ and self.options.get("ignore-previously-merged") != "yes" |
716 |
+ and os.path.lexists(archive + ".dist") |
717 |
+ and len(diff(archive + ".dist", conf["new"])[1]) == 0 |
718 |
+ ): |
719 |
# The current update is identical to the archived .dist |
720 |
# version that has previously been merged. |
721 |
os.unlink(mrgconf) |
722 |
- newconf = conf['new'] |
723 |
+ newconf = conf["new"] |
724 |
|
725 |
- mystatus, myoutput = diff(conf['current'], newconf) |
726 |
+ mystatus, myoutput = diff(conf["current"], newconf) |
727 |
myoutput_len = len(myoutput) |
728 |
same_file = 0 == myoutput_len |
729 |
if mystatus >> 8 == 2: |
730 |
@@ -221,49 +253,53 @@ class dispatch: |
731 |
same_wsc = False |
732 |
else: |
733 |
# Extract all the normal diff lines (ignore the headers). |
734 |
- mylines = re.findall('^[+-][^\n+-].*$', myoutput, re.MULTILINE) |
735 |
+ mylines = re.findall("^[+-][^\n+-].*$", myoutput, re.MULTILINE) |
736 |
|
737 |
# Filter out all the cvs headers |
738 |
- cvs_header = re.compile('# [$]Header:') |
739 |
+ cvs_header = re.compile("# [$]Header:") |
740 |
cvs_lines = list(filter(cvs_header.search, mylines)) |
741 |
same_cvs = len(mylines) == len(cvs_lines) |
742 |
|
743 |
# Filter out comments and whitespace-only changes. |
744 |
# Note: be nice to also ignore lines that only differ in whitespace... |
745 |
wsc_lines = [] |
746 |
- for x in [r'^[-+]\s*#', r'^[-+]\s*$']: |
747 |
- wsc_lines += list(filter(re.compile(x).match, mylines)) |
748 |
+ for x in [r"^[-+]\s*#", r"^[-+]\s*$"]: |
749 |
+ wsc_lines += list(filter(re.compile(x).match, mylines)) |
750 |
same_wsc = len(mylines) == len(wsc_lines) |
751 |
|
752 |
# Do options permit? |
753 |
- same_cvs = same_cvs and self.options['replace-cvs'] == 'yes' |
754 |
- same_wsc = same_wsc and self.options['replace-wscomments'] == 'yes' |
755 |
- unmodified = unmodified and self.options['replace-unmodified'] == 'yes' |
756 |
+ same_cvs = same_cvs and self.options["replace-cvs"] == "yes" |
757 |
+ same_wsc = same_wsc and self.options["replace-wscomments"] == "yes" |
758 |
+ unmodified = unmodified and self.options["replace-unmodified"] == "yes" |
759 |
|
760 |
if same_file: |
761 |
- os.unlink (conf ['new']) |
762 |
- self.post_process(conf['current']) |
763 |
+ os.unlink(conf["new"]) |
764 |
+ self.post_process(conf["current"]) |
765 |
if os.path.exists(mrgconf): |
766 |
os.unlink(mrgconf) |
767 |
return False |
768 |
- elif conf['current'] in frozen_files: |
769 |
+ elif conf["current"] in frozen_files: |
770 |
"""Frozen files are automatically zapped. The new config has |
771 |
already been archived with a .new suffix. When zapped, it is |
772 |
left with the .new suffix (post_process is skipped), since it |
773 |
hasn't been merged into the current config.""" |
774 |
- auto_zapped.append(conf['current']) |
775 |
- os.unlink(conf['new']) |
776 |
+ auto_zapped.append(conf["current"]) |
777 |
+ os.unlink(conf["new"]) |
778 |
try: |
779 |
os.unlink(mrgconf) |
780 |
except OSError: |
781 |
pass |
782 |
return False |
783 |
- elif unmodified or same_cvs or same_wsc or \ |
784 |
- not protect_obj.isprotected(conf['current']): |
785 |
- self.replace(newconf, conf['current']) |
786 |
- self.post_process(conf['current']) |
787 |
+ elif ( |
788 |
+ unmodified |
789 |
+ or same_cvs |
790 |
+ or same_wsc |
791 |
+ or not protect_obj.isprotected(conf["current"]) |
792 |
+ ): |
793 |
+ self.replace(newconf, conf["current"]) |
794 |
+ self.post_process(conf["current"]) |
795 |
if newconf == mrgconf: |
796 |
- os.unlink(conf['new']) |
797 |
+ os.unlink(conf["new"]) |
798 |
elif os.path.exists(mrgconf): |
799 |
os.unlink(mrgconf) |
800 |
return False |
801 |
@@ -279,7 +315,7 @@ class dispatch: |
802 |
valid_input = "qhtnmlezu" |
803 |
|
804 |
def diff_pager(file1, file2): |
805 |
- cmd = self.options['diff'] % (file1, file2) |
806 |
+ cmd = self.options["diff"] % (file1, file2) |
807 |
cmd += pager |
808 |
spawn_shell(cmd) |
809 |
|
810 |
@@ -288,8 +324,8 @@ class dispatch: |
811 |
for conf in confs: |
812 |
count = count + 1 |
813 |
|
814 |
- newconf = conf['new'] |
815 |
- mrgconf = re.sub(r'\._cfg', '._mrg', newconf) |
816 |
+ newconf = conf["new"] |
817 |
+ mrgconf = re.sub(r"\._cfg", "._mrg", newconf) |
818 |
if os.path.exists(mrgconf): |
819 |
newconf = mrgconf |
820 |
show_new_diff = 0 |
821 |
@@ -297,14 +333,20 @@ class dispatch: |
822 |
while 1: |
823 |
clear_screen() |
824 |
if show_new_diff: |
825 |
- diff_pager(conf['new'], mrgconf) |
826 |
+ diff_pager(conf["new"], mrgconf) |
827 |
show_new_diff = 0 |
828 |
else: |
829 |
- diff_pager(conf['current'], newconf) |
830 |
+ diff_pager(conf["current"], newconf) |
831 |
|
832 |
print() |
833 |
- writemsg_stdout('>> (%i of %i) -- %s\n' % (count, len(confs), conf['current']), noiselevel=-1) |
834 |
- print('>> q quit, h help, n next, e edit-new, z zap-new, u use-new\n m merge, t toggle-merge, l look-merge: ', end=' ') |
835 |
+ writemsg_stdout( |
836 |
+ ">> (%i of %i) -- %s\n" % (count, len(confs), conf["current"]), |
837 |
+ noiselevel=-1, |
838 |
+ ) |
839 |
+ print( |
840 |
+ ">> q quit, h help, n next, e edit-new, z zap-new, u use-new\n m merge, t toggle-merge, l look-merge: ", |
841 |
+ end=" ", |
842 |
+ ) |
843 |
|
844 |
# In some cases getch() will return some spurious characters |
845 |
# that do not represent valid input. If we don't validate the |
846 |
@@ -315,28 +357,30 @@ class dispatch: |
847 |
while True: |
848 |
c = getch() |
849 |
if c in valid_input: |
850 |
- sys.stdout.write('\n') |
851 |
+ sys.stdout.write("\n") |
852 |
sys.stdout.flush() |
853 |
break |
854 |
|
855 |
- if c == 'q': |
856 |
+ if c == "q": |
857 |
perform_conf_update_session_hooks("post-session") |
858 |
- sys.exit (0) |
859 |
- if c == 'h': |
860 |
- self.do_help () |
861 |
+ sys.exit(0) |
862 |
+ if c == "h": |
863 |
+ self.do_help() |
864 |
continue |
865 |
- elif c == 't': |
866 |
+ elif c == "t": |
867 |
if newconf == mrgconf: |
868 |
- newconf = conf['new'] |
869 |
+ newconf = conf["new"] |
870 |
elif os.path.exists(mrgconf): |
871 |
newconf = mrgconf |
872 |
continue |
873 |
- elif c == 'n': |
874 |
+ elif c == "n": |
875 |
break |
876 |
- elif c == 'm': |
877 |
- merged = SCRATCH_DIR+"/"+os.path.basename(conf['current']) |
878 |
+ elif c == "m": |
879 |
+ merged = SCRATCH_DIR + "/" + os.path.basename(conf["current"]) |
880 |
print() |
881 |
- ret = os.system (self.options['merge'] % (merged, conf ['current'], newconf)) |
882 |
+ ret = os.system( |
883 |
+ self.options["merge"] % (merged, conf["current"], newconf) |
884 |
+ ) |
885 |
ret = os.WEXITSTATUS(ret) |
886 |
if ret < 2: |
887 |
ret = 0 |
888 |
@@ -345,29 +389,29 @@ class dispatch: |
889 |
continue |
890 |
shutil.copyfile(merged, mrgconf) |
891 |
os.remove(merged) |
892 |
- mystat = os.lstat(conf['new']) |
893 |
+ mystat = os.lstat(conf["new"]) |
894 |
os.chmod(mrgconf, mystat[ST_MODE]) |
895 |
os.chown(mrgconf, mystat[ST_UID], mystat[ST_GID]) |
896 |
newconf = mrgconf |
897 |
continue |
898 |
- elif c == 'l': |
899 |
+ elif c == "l": |
900 |
show_new_diff = 1 |
901 |
continue |
902 |
- elif c == 'e': |
903 |
- if 'EDITOR' not in os.environ: |
904 |
- os.environ['EDITOR']='nano' |
905 |
- os.system(os.environ['EDITOR'] + ' ' + newconf) |
906 |
+ elif c == "e": |
907 |
+ if "EDITOR" not in os.environ: |
908 |
+ os.environ["EDITOR"] = "nano" |
909 |
+ os.system(os.environ["EDITOR"] + " " + newconf) |
910 |
continue |
911 |
- elif c == 'z': |
912 |
- os.unlink(conf['new']) |
913 |
+ elif c == "z": |
914 |
+ os.unlink(conf["new"]) |
915 |
if os.path.exists(mrgconf): |
916 |
os.unlink(mrgconf) |
917 |
break |
918 |
- elif c == 'u': |
919 |
- self.replace(newconf, conf ['current']) |
920 |
- self.post_process(conf['current']) |
921 |
+ elif c == "u": |
922 |
+ self.replace(newconf, conf["current"]) |
923 |
+ self.post_process(conf["current"]) |
924 |
if newconf == mrgconf: |
925 |
- os.unlink(conf['new']) |
926 |
+ os.unlink(conf["new"]) |
927 |
elif os.path.exists(mrgconf): |
928 |
os.unlink(mrgconf) |
929 |
break |
930 |
@@ -384,13 +428,14 @@ class dispatch: |
931 |
|
932 |
perform_conf_update_session_hooks("post-session") |
933 |
|
934 |
- def replace (self, newconf, curconf): |
935 |
+ def replace(self, newconf, curconf): |
936 |
"""Replace current config with the new/merged version. Also logs |
937 |
the diff of what changed into the configured log file.""" |
938 |
if "log-file" in self.options: |
939 |
status, output = diff(curconf, newconf) |
940 |
- with io.open(self.options["log-file"], mode="a", |
941 |
- encoding=_encodings["stdio"]) as f: |
942 |
+ with io.open( |
943 |
+ self.options["log-file"], mode="a", encoding=_encodings["stdio"] |
944 |
+ ) as f: |
945 |
f.write(output + "\n") |
946 |
|
947 |
perform_conf_update_hooks("pre-update", curconf) |
948 |
@@ -398,22 +443,23 @@ class dispatch: |
949 |
try: |
950 |
os.rename(newconf, curconf) |
951 |
except (IOError, os.error) as why: |
952 |
- writemsg('dispatch-conf: Error renaming %s to %s: %s; fatal\n' % \ |
953 |
- (newconf, curconf, str(why)), noiselevel=-1) |
954 |
+ writemsg( |
955 |
+ "dispatch-conf: Error renaming %s to %s: %s; fatal\n" |
956 |
+ % (newconf, curconf, str(why)), |
957 |
+ noiselevel=-1, |
958 |
+ ) |
959 |
return |
960 |
|
961 |
perform_conf_update_hooks("post-update", curconf) |
962 |
|
963 |
- |
964 |
def post_process(self, curconf): |
965 |
- archive = os.path.join(self.options['archive-dir'], curconf.lstrip('/')) |
966 |
- if self.options['use-rcs'] == 'yes': |
967 |
+ archive = os.path.join(self.options["archive-dir"], curconf.lstrip("/")) |
968 |
+ if self.options["use-rcs"] == "yes": |
969 |
portage.dispatch_conf.rcs_archive_post_process(archive) |
970 |
else: |
971 |
portage.dispatch_conf.file_archive_post_process(archive) |
972 |
|
973 |
- |
974 |
- def massage (self, newconfigs): |
975 |
+ def massage(self, newconfigs): |
976 |
"""Sort, rstrip, remove old versions, break into triad hash. |
977 |
|
978 |
Triad is dictionary of current (/etc/make.conf), new (/etc/._cfg0003_make.conf) |
979 |
@@ -423,25 +469,25 @@ class dispatch: |
980 |
""" |
981 |
h = {} |
982 |
configs = [] |
983 |
- newconfigs.sort () |
984 |
+ newconfigs.sort() |
985 |
|
986 |
for nconf in newconfigs: |
987 |
# Use strict mode here, because we want to know if it fails, |
988 |
# and portage only merges files with valid UTF-8 encoding. |
989 |
- nconf = _unicode_decode(nconf, errors='strict').rstrip() |
990 |
- conf = re.sub (r'\._cfg\d+_', '', nconf) |
991 |
- dirname = os.path.dirname(nconf) |
992 |
- conf_map = { |
993 |
- 'current' : conf, |
994 |
- 'dir' : dirname, |
995 |
- 'new' : nconf, |
996 |
+ nconf = _unicode_decode(nconf, errors="strict").rstrip() |
997 |
+ conf = re.sub(r"\._cfg\d+_", "", nconf) |
998 |
+ dirname = os.path.dirname(nconf) |
999 |
+ conf_map = { |
1000 |
+ "current": conf, |
1001 |
+ "dir": dirname, |
1002 |
+ "new": nconf, |
1003 |
} |
1004 |
|
1005 |
if conf in h: |
1006 |
- mrgconf = re.sub(r'\._cfg', '._mrg', h[conf]['new']) |
1007 |
+ mrgconf = re.sub(r"\._cfg", "._mrg", h[conf]["new"]) |
1008 |
if os.path.exists(mrgconf): |
1009 |
os.unlink(mrgconf) |
1010 |
- os.unlink(h[conf]['new']) |
1011 |
+ os.unlink(h[conf]["new"]) |
1012 |
h[conf].update(conf_map) |
1013 |
else: |
1014 |
h[conf] = conf_map |
1015 |
@@ -449,27 +495,27 @@ class dispatch: |
1016 |
|
1017 |
return configs |
1018 |
|
1019 |
- |
1020 |
- def do_help (self): |
1021 |
+ def do_help(self): |
1022 |
print() |
1023 |
print() |
1024 |
|
1025 |
- print(' u -- update current config with new config and continue') |
1026 |
- print(' z -- zap (delete) new config and continue') |
1027 |
- print(' n -- skip to next config, leave all intact') |
1028 |
- print(' e -- edit new config') |
1029 |
- print(' m -- interactively merge current and new configs') |
1030 |
- print(' l -- look at diff between pre-merged and merged configs') |
1031 |
- print(' t -- toggle new config between merged and pre-merged state') |
1032 |
- print(' h -- this screen') |
1033 |
- print(' q -- quit') |
1034 |
+ print(" u -- update current config with new config and continue") |
1035 |
+ print(" z -- zap (delete) new config and continue") |
1036 |
+ print(" n -- skip to next config, leave all intact") |
1037 |
+ print(" e -- edit new config") |
1038 |
+ print(" m -- interactively merge current and new configs") |
1039 |
+ print(" l -- look at diff between pre-merged and merged configs") |
1040 |
+ print(" t -- toggle new config between merged and pre-merged state") |
1041 |
+ print(" h -- this screen") |
1042 |
+ print(" q -- quit") |
1043 |
|
1044 |
- print(); print('press any key to return to diff...', end=' ') |
1045 |
+ print() |
1046 |
+ print("press any key to return to diff...", end=" ") |
1047 |
|
1048 |
- getch () |
1049 |
+ getch() |
1050 |
|
1051 |
|
1052 |
-def getch (): |
1053 |
+def getch(): |
1054 |
# from ASPN - Danny Yoo |
1055 |
# |
1056 |
|
1057 |
@@ -482,6 +528,7 @@ def getch (): |
1058 |
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) |
1059 |
return ch |
1060 |
|
1061 |
+ |
1062 |
def clear_screen(): |
1063 |
if curses is not None: |
1064 |
try: |
1065 |
@@ -493,40 +540,48 @@ def clear_screen(): |
1066 |
pass |
1067 |
os.system("clear 2>/dev/null") |
1068 |
|
1069 |
+ |
1070 |
shell = os.environ.get("SHELL") |
1071 |
if not shell or not os.access(shell, os.EX_OK): |
1072 |
shell = find_binary("sh") |
1073 |
|
1074 |
+ |
1075 |
def spawn_shell(cmd): |
1076 |
if shell: |
1077 |
sys.__stdout__.flush() |
1078 |
sys.__stderr__.flush() |
1079 |
- spawn([shell, "-c", cmd], env=os.environ, |
1080 |
- fd_pipes = { 0 : portage._get_stdin().fileno(), |
1081 |
- 1 : sys.__stdout__.fileno(), |
1082 |
- 2 : sys.__stderr__.fileno()}) |
1083 |
+ spawn( |
1084 |
+ [shell, "-c", cmd], |
1085 |
+ env=os.environ, |
1086 |
+ fd_pipes={ |
1087 |
+ 0: portage._get_stdin().fileno(), |
1088 |
+ 1: sys.__stdout__.fileno(), |
1089 |
+ 2: sys.__stderr__.fileno(), |
1090 |
+ }, |
1091 |
+ ) |
1092 |
else: |
1093 |
os.system(cmd) |
1094 |
|
1095 |
+ |
1096 |
def usage(argv): |
1097 |
- print('dispatch-conf: sane configuration file update\n') |
1098 |
- print('Usage: dispatch-conf [config dirs]\n') |
1099 |
- print('See the dispatch-conf(1) man page for more details') |
1100 |
+ print("dispatch-conf: sane configuration file update\n") |
1101 |
+ print("Usage: dispatch-conf [config dirs]\n") |
1102 |
+ print("See the dispatch-conf(1) man page for more details") |
1103 |
sys.exit(os.EX_OK) |
1104 |
|
1105 |
+ |
1106 |
for x in sys.argv: |
1107 |
- if x in ('-h', '--help'): |
1108 |
+ if x in ("-h", "--help"): |
1109 |
usage(sys.argv) |
1110 |
- elif x in ('--version',): |
1111 |
+ elif x in ("--version",): |
1112 |
print("Portage", portage.VERSION) |
1113 |
sys.exit(os.EX_OK) |
1114 |
|
1115 |
# run |
1116 |
-d = dispatch () |
1117 |
+d = dispatch() |
1118 |
|
1119 |
if len(sys.argv) > 1: |
1120 |
# for testing |
1121 |
d.grind(sys.argv[1:]) |
1122 |
else: |
1123 |
- d.grind(portage.util.shlex_split( |
1124 |
- portage.settings.get('CONFIG_PROTECT', ''))) |
1125 |
+ d.grind(portage.util.shlex_split(portage.settings.get("CONFIG_PROTECT", ""))) |
1126 |
|
1127 |
diff --git a/bin/ebuild b/bin/ebuild |
1128 |
index 3ad589008..bdedab9cb 100755 |
1129 |
--- a/bin/ebuild |
1130 |
+++ b/bin/ebuild |
1131 |
@@ -11,45 +11,58 @@ import textwrap |
1132 |
# This block ensures that ^C interrupts are handled quietly. |
1133 |
try: |
1134 |
|
1135 |
- def exithandler(signum, _frame): |
1136 |
- signal.signal(signal.SIGINT, signal.SIG_IGN) |
1137 |
- signal.signal(signal.SIGTERM, signal.SIG_IGN) |
1138 |
- sys.exit(128 + signum) |
1139 |
+ def exithandler(signum, _frame): |
1140 |
+ signal.signal(signal.SIGINT, signal.SIG_IGN) |
1141 |
+ signal.signal(signal.SIGTERM, signal.SIG_IGN) |
1142 |
+ sys.exit(128 + signum) |
1143 |
|
1144 |
- signal.signal(signal.SIGINT, exithandler) |
1145 |
- signal.signal(signal.SIGTERM, exithandler) |
1146 |
- # Prevent "[Errno 32] Broken pipe" exceptions when |
1147 |
- # writing to a pipe. |
1148 |
- signal.signal(signal.SIGPIPE, signal.SIG_DFL) |
1149 |
+ signal.signal(signal.SIGINT, exithandler) |
1150 |
+ signal.signal(signal.SIGTERM, exithandler) |
1151 |
+ # Prevent "[Errno 32] Broken pipe" exceptions when |
1152 |
+ # writing to a pipe. |
1153 |
+ signal.signal(signal.SIGPIPE, signal.SIG_DFL) |
1154 |
|
1155 |
except KeyboardInterrupt: |
1156 |
- sys.exit(128 + signal.SIGINT) |
1157 |
+ sys.exit(128 + signal.SIGINT) |
1158 |
+ |
1159 |
|
1160 |
def debug_signal(_signum, _frame): |
1161 |
- import pdb |
1162 |
- pdb.set_trace() |
1163 |
+ import pdb |
1164 |
+ |
1165 |
+ pdb.set_trace() |
1166 |
|
1167 |
-if platform.python_implementation() == 'Jython': |
1168 |
- debug_signum = signal.SIGUSR2 # bug #424259 |
1169 |
+ |
1170 |
+if platform.python_implementation() == "Jython": |
1171 |
+ debug_signum = signal.SIGUSR2 # bug #424259 |
1172 |
else: |
1173 |
- debug_signum = signal.SIGUSR1 |
1174 |
+ debug_signum = signal.SIGUSR1 |
1175 |
|
1176 |
signal.signal(debug_signum, debug_signal) |
1177 |
|
1178 |
import io |
1179 |
import os |
1180 |
from os import path as osp |
1181 |
-if osp.isfile(osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), ".portage_not_installed")): |
1182 |
- sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "lib")) |
1183 |
+ |
1184 |
+if osp.isfile( |
1185 |
+ osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), ".portage_not_installed") |
1186 |
+): |
1187 |
+ sys.path.insert( |
1188 |
+ 0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "lib") |
1189 |
+ ) |
1190 |
import portage |
1191 |
+ |
1192 |
portage._internal_caller = True |
1193 |
from portage import os |
1194 |
from portage import _encodings |
1195 |
from portage import _shell_quote |
1196 |
from portage import _unicode_encode |
1197 |
from portage.const import VDB_PATH |
1198 |
-from portage.exception import PermissionDenied, PortageKeyError, \ |
1199 |
- PortagePackageException, UnsupportedAPIException |
1200 |
+from portage.exception import ( |
1201 |
+ PermissionDenied, |
1202 |
+ PortageKeyError, |
1203 |
+ PortagePackageException, |
1204 |
+ UnsupportedAPIException, |
1205 |
+) |
1206 |
from portage.localization import _ |
1207 |
import portage.util |
1208 |
from portage.util._eventloop.global_event_loop import global_event_loop |
1209 |
@@ -63,65 +76,73 @@ description = "See the ebuild(1) man page for more info" |
1210 |
usage = "Usage: ebuild <ebuild file> <command> [command] ..." |
1211 |
parser = argparse.ArgumentParser(description=description, usage=usage) |
1212 |
|
1213 |
-force_help = "When used together with the digest or manifest " + \ |
1214 |
- "command, this option forces regeneration of digests for all " + \ |
1215 |
- "distfiles associated with the current ebuild. Any distfiles " + \ |
1216 |
- "that do not already exist in ${DISTDIR} will be automatically fetched." |
1217 |
+force_help = ( |
1218 |
+ "When used together with the digest or manifest " |
1219 |
+ + "command, this option forces regeneration of digests for all " |
1220 |
+ + "distfiles associated with the current ebuild. Any distfiles " |
1221 |
+ + "that do not already exist in ${DISTDIR} will be automatically fetched." |
1222 |
+) |
1223 |
|
1224 |
parser.add_argument("--force", help=force_help, action="store_true") |
1225 |
-parser.add_argument("--color", help="enable or disable color output", |
1226 |
- choices=("y", "n")) |
1227 |
-parser.add_argument("--debug", help="show debug output", |
1228 |
- action="store_true") |
1229 |
-parser.add_argument("--version", help="show version and exit", |
1230 |
- action="store_true") |
1231 |
-parser.add_argument("--ignore-default-opts", |
1232 |
- action="store_true", |
1233 |
- help="do not use the EBUILD_DEFAULT_OPTS environment variable") |
1234 |
-parser.add_argument("--skip-manifest", help="skip all manifest checks", |
1235 |
- action="store_true") |
1236 |
+parser.add_argument( |
1237 |
+ "--color", help="enable or disable color output", choices=("y", "n") |
1238 |
+) |
1239 |
+parser.add_argument("--debug", help="show debug output", action="store_true") |
1240 |
+parser.add_argument("--version", help="show version and exit", action="store_true") |
1241 |
+parser.add_argument( |
1242 |
+ "--ignore-default-opts", |
1243 |
+ action="store_true", |
1244 |
+ help="do not use the EBUILD_DEFAULT_OPTS environment variable", |
1245 |
+) |
1246 |
+parser.add_argument( |
1247 |
+ "--skip-manifest", help="skip all manifest checks", action="store_true" |
1248 |
+) |
1249 |
|
1250 |
opts, pargs = parser.parse_known_args(args=sys.argv[1:]) |
1251 |
|
1252 |
+ |
1253 |
def err(txt): |
1254 |
- portage.writemsg('ebuild: %s\n' % (txt,), noiselevel=-1) |
1255 |
- sys.exit(1) |
1256 |
+ portage.writemsg("ebuild: %s\n" % (txt,), noiselevel=-1) |
1257 |
+ sys.exit(1) |
1258 |
+ |
1259 |
|
1260 |
if opts.version: |
1261 |
- print("Portage", portage.VERSION) |
1262 |
- sys.exit(os.EX_OK) |
1263 |
+ print("Portage", portage.VERSION) |
1264 |
+ sys.exit(os.EX_OK) |
1265 |
|
1266 |
if len(pargs) < 2: |
1267 |
- parser.error("missing required args") |
1268 |
+ parser.error("missing required args") |
1269 |
|
1270 |
if not opts.ignore_default_opts: |
1271 |
- default_opts = portage.util.shlex_split( |
1272 |
- portage.settings.get("EBUILD_DEFAULT_OPTS", "")) |
1273 |
- opts, pargs = parser.parse_known_args(default_opts + sys.argv[1:]) |
1274 |
+ default_opts = portage.util.shlex_split( |
1275 |
+ portage.settings.get("EBUILD_DEFAULT_OPTS", "") |
1276 |
+ ) |
1277 |
+ opts, pargs = parser.parse_known_args(default_opts + sys.argv[1:]) |
1278 |
|
1279 |
debug = opts.debug |
1280 |
force = opts.force |
1281 |
|
1282 |
if debug: |
1283 |
- # Ensure that all config instances have this setting, |
1284 |
- # including the one that's used by portdbapi for aux_get. |
1285 |
- os.environ['PORTAGE_DEBUG'] = '1' |
1286 |
- portage._reset_legacy_globals() |
1287 |
+ # Ensure that all config instances have this setting, |
1288 |
+ # including the one that's used by portdbapi for aux_get. |
1289 |
+ os.environ["PORTAGE_DEBUG"] = "1" |
1290 |
+ portage._reset_legacy_globals() |
1291 |
|
1292 |
# do this _after_ 'import portage' to prevent unnecessary tracing |
1293 |
if debug and "python-trace" in portage.features: |
1294 |
- portage.debug.set_trace(True) |
1295 |
- |
1296 |
-if not opts.color == 'y' and \ |
1297 |
- (opts.color == 'n' or \ |
1298 |
- portage.settings.get('NOCOLOR') in ('yes', 'true') or \ |
1299 |
- portage.settings.get('TERM') == 'dumb' or \ |
1300 |
- not sys.stdout.isatty()): |
1301 |
- portage.output.nocolor() |
1302 |
- portage.settings.unlock() |
1303 |
- portage.settings['NOCOLOR'] = 'true' |
1304 |
- portage.settings.backup_changes('NOCOLOR') |
1305 |
- portage.settings.lock() |
1306 |
+ portage.debug.set_trace(True) |
1307 |
+ |
1308 |
+if not opts.color == "y" and ( |
1309 |
+ opts.color == "n" |
1310 |
+ or portage.settings.get("NOCOLOR") in ("yes", "true") |
1311 |
+ or portage.settings.get("TERM") == "dumb" |
1312 |
+ or not sys.stdout.isatty() |
1313 |
+): |
1314 |
+ portage.output.nocolor() |
1315 |
+ portage.settings.unlock() |
1316 |
+ portage.settings["NOCOLOR"] = "true" |
1317 |
+ portage.settings.backup_changes("NOCOLOR") |
1318 |
+ portage.settings.lock() |
1319 |
|
1320 |
apply_priorities(portage.settings) |
1321 |
|
1322 |
@@ -129,118 +150,140 @@ ebuild = pargs.pop(0) |
1323 |
|
1324 |
pf = None |
1325 |
if ebuild.endswith(".ebuild"): |
1326 |
- pf = os.path.basename(ebuild)[:-7] |
1327 |
+ pf = os.path.basename(ebuild)[:-7] |
1328 |
|
1329 |
if pf is None: |
1330 |
- err("%s: does not end with '.ebuild'" % (ebuild,)) |
1331 |
+ err("%s: does not end with '.ebuild'" % (ebuild,)) |
1332 |
|
1333 |
if not os.path.isabs(ebuild): |
1334 |
- mycwd = os.getcwd() |
1335 |
- # Try to get the non-canonical path from the PWD evironment variable, since |
1336 |
- # the canonical path returned from os.getcwd() may may be unusable in |
1337 |
- # cases where the directory stucture is built from symlinks. |
1338 |
- pwd = os.environ.get('PWD', '') |
1339 |
- if pwd and pwd != mycwd and \ |
1340 |
- os.path.realpath(pwd) == mycwd: |
1341 |
- mycwd = portage.normalize_path(pwd) |
1342 |
- ebuild = os.path.join(mycwd, ebuild) |
1343 |
+ mycwd = os.getcwd() |
1344 |
+ # Try to get the non-canonical path from the PWD evironment variable, since |
1345 |
+ # the canonical path returned from os.getcwd() may may be unusable in |
1346 |
+ # cases where the directory stucture is built from symlinks. |
1347 |
+ pwd = os.environ.get("PWD", "") |
1348 |
+ if pwd and pwd != mycwd and os.path.realpath(pwd) == mycwd: |
1349 |
+ mycwd = portage.normalize_path(pwd) |
1350 |
+ ebuild = os.path.join(mycwd, ebuild) |
1351 |
ebuild = portage.normalize_path(ebuild) |
1352 |
# portdbapi uses the canonical path for the base of the ebuild repository, but |
1353 |
# subdirectories of the base can be built from symlinks (like crossdev does). |
1354 |
ebuild_portdir = os.path.realpath( |
1355 |
- os.path.dirname(os.path.dirname(os.path.dirname(ebuild)))) |
1356 |
+ os.path.dirname(os.path.dirname(os.path.dirname(ebuild))) |
1357 |
+) |
1358 |
ebuild = os.path.join(ebuild_portdir, *ebuild.split(os.path.sep)[-3:]) |
1359 |
-vdb_path = os.path.realpath(os.path.join(portage.settings['EROOT'], VDB_PATH)) |
1360 |
+vdb_path = os.path.realpath(os.path.join(portage.settings["EROOT"], VDB_PATH)) |
1361 |
|
1362 |
# Make sure that portdb.findname() returns the correct ebuild. |
1363 |
-if ebuild_portdir != vdb_path and \ |
1364 |
- ebuild_portdir not in portage.portdb.porttrees: |
1365 |
- portdir_overlay = portage.settings.get("PORTDIR_OVERLAY", "") |
1366 |
- os.environ["PORTDIR_OVERLAY"] = ( |
1367 |
- portdir_overlay + " " + _shell_quote(ebuild_portdir)) |
1368 |
+if ebuild_portdir != vdb_path and ebuild_portdir not in portage.portdb.porttrees: |
1369 |
+ portdir_overlay = portage.settings.get("PORTDIR_OVERLAY", "") |
1370 |
+ os.environ["PORTDIR_OVERLAY"] = portdir_overlay + " " + _shell_quote(ebuild_portdir) |
1371 |
|
1372 |
- print("Appending %s to PORTDIR_OVERLAY..." % ebuild_portdir) |
1373 |
- portage._reset_legacy_globals() |
1374 |
+ print("Appending %s to PORTDIR_OVERLAY..." % ebuild_portdir) |
1375 |
+ portage._reset_legacy_globals() |
1376 |
|
1377 |
myrepo = None |
1378 |
if ebuild_portdir != vdb_path: |
1379 |
- myrepo = portage.portdb.getRepositoryName(ebuild_portdir) |
1380 |
+ myrepo = portage.portdb.getRepositoryName(ebuild_portdir) |
1381 |
|
1382 |
if not os.path.exists(ebuild): |
1383 |
- err('%s: does not exist' % (ebuild,)) |
1384 |
+ err("%s: does not exist" % (ebuild,)) |
1385 |
|
1386 |
ebuild_split = ebuild.split("/") |
1387 |
cpv = "%s/%s" % (ebuild_split[-3], pf) |
1388 |
|
1389 |
-with io.open(_unicode_encode(ebuild, encoding=_encodings['fs'], errors='strict'), |
1390 |
- mode='r', encoding=_encodings['repo.content'], errors='replace') as f: |
1391 |
- eapi = portage._parse_eapi_ebuild_head(f)[0] |
1392 |
+with io.open( |
1393 |
+ _unicode_encode(ebuild, encoding=_encodings["fs"], errors="strict"), |
1394 |
+ mode="r", |
1395 |
+ encoding=_encodings["repo.content"], |
1396 |
+ errors="replace", |
1397 |
+) as f: |
1398 |
+ eapi = portage._parse_eapi_ebuild_head(f)[0] |
1399 |
if eapi is None: |
1400 |
- eapi = "0" |
1401 |
+ eapi = "0" |
1402 |
if not portage.catpkgsplit(cpv, eapi=eapi): |
1403 |
- err('%s: %s: does not follow correct package syntax' % (ebuild, cpv)) |
1404 |
+ err("%s: %s: does not follow correct package syntax" % (ebuild, cpv)) |
1405 |
|
1406 |
if ebuild.startswith(vdb_path): |
1407 |
- mytree = "vartree" |
1408 |
- pkg_type = "installed" |
1409 |
+ mytree = "vartree" |
1410 |
+ pkg_type = "installed" |
1411 |
|
1412 |
- portage_ebuild = portage.db[portage.root][mytree].dbapi.findname(cpv, myrepo=myrepo) |
1413 |
+ portage_ebuild = portage.db[portage.root][mytree].dbapi.findname(cpv, myrepo=myrepo) |
1414 |
|
1415 |
- if os.path.realpath(portage_ebuild) != ebuild: |
1416 |
- err('Portage seems to think that %s is at %s' % (cpv, portage_ebuild)) |
1417 |
+ if os.path.realpath(portage_ebuild) != ebuild: |
1418 |
+ err("Portage seems to think that %s is at %s" % (cpv, portage_ebuild)) |
1419 |
|
1420 |
else: |
1421 |
- mytree = "porttree" |
1422 |
- pkg_type = "ebuild" |
1423 |
+ mytree = "porttree" |
1424 |
+ pkg_type = "ebuild" |
1425 |
|
1426 |
- portage_ebuild = portage.portdb.findname(cpv, myrepo=myrepo) |
1427 |
+ portage_ebuild = portage.portdb.findname(cpv, myrepo=myrepo) |
1428 |
|
1429 |
- if not portage_ebuild or portage_ebuild != ebuild: |
1430 |
- err('%s: does not seem to have a valid PORTDIR structure' % (ebuild,)) |
1431 |
+ if not portage_ebuild or portage_ebuild != ebuild: |
1432 |
+ err("%s: does not seem to have a valid PORTDIR structure" % (ebuild,)) |
1433 |
|
1434 |
if len(pargs) > 1 and "config" in pargs: |
1435 |
- other_phases = set(pargs) |
1436 |
- other_phases.difference_update( |
1437 |
- ("clean", "config", "digest", "manifest")) |
1438 |
- if other_phases: |
1439 |
- err('"config" must not be called with any other phase') |
1440 |
+ other_phases = set(pargs) |
1441 |
+ other_phases.difference_update(("clean", "config", "digest", "manifest")) |
1442 |
+ if other_phases: |
1443 |
+ err('"config" must not be called with any other phase') |
1444 |
+ |
1445 |
|
1446 |
def discard_digests(myebuild, mysettings, mydbapi): |
1447 |
- """Discard all distfiles digests for the given ebuild. This is useful when |
1448 |
- upstream has changed the identity of the distfiles and the user would |
1449 |
- otherwise have to manually remove the Manifest and files/digest-* files in |
1450 |
- order to ensure correct results.""" |
1451 |
- try: |
1452 |
- portage._doebuild_manifest_exempt_depend += 1 |
1453 |
- pkgdir = os.path.dirname(myebuild) |
1454 |
- fetchlist_dict = portage.FetchlistDict(pkgdir, mysettings, mydbapi) |
1455 |
- mf = mysettings.repositories.get_repo_for_location( |
1456 |
- os.path.dirname(os.path.dirname(pkgdir))) |
1457 |
- mf = mf.load_manifest(pkgdir, mysettings["DISTDIR"], |
1458 |
- fetchlist_dict=fetchlist_dict) |
1459 |
- mf.create(requiredDistfiles=None, |
1460 |
- assumeDistHashesSometimes=True, assumeDistHashesAlways=True) |
1461 |
- distfiles = fetchlist_dict[cpv] |
1462 |
- for myfile in distfiles: |
1463 |
- try: |
1464 |
- del mf.fhashdict["DIST"][myfile] |
1465 |
- except KeyError: |
1466 |
- pass |
1467 |
- mf.write() |
1468 |
- finally: |
1469 |
- portage._doebuild_manifest_exempt_depend -= 1 |
1470 |
- |
1471 |
-portage.settings.validate() # generate warning messages if necessary |
1472 |
- |
1473 |
-build_dir_phases = set(["setup", "unpack", "prepare", "configure", "compile", |
1474 |
- "test", "install", "package", "rpm", "merge", "qmerge"]) |
1475 |
+ """Discard all distfiles digests for the given ebuild. This is useful when |
1476 |
+ upstream has changed the identity of the distfiles and the user would |
1477 |
+ otherwise have to manually remove the Manifest and files/digest-* files in |
1478 |
+ order to ensure correct results.""" |
1479 |
+ try: |
1480 |
+ portage._doebuild_manifest_exempt_depend += 1 |
1481 |
+ pkgdir = os.path.dirname(myebuild) |
1482 |
+ fetchlist_dict = portage.FetchlistDict(pkgdir, mysettings, mydbapi) |
1483 |
+ mf = mysettings.repositories.get_repo_for_location( |
1484 |
+ os.path.dirname(os.path.dirname(pkgdir)) |
1485 |
+ ) |
1486 |
+ mf = mf.load_manifest( |
1487 |
+ pkgdir, mysettings["DISTDIR"], fetchlist_dict=fetchlist_dict |
1488 |
+ ) |
1489 |
+ mf.create( |
1490 |
+ requiredDistfiles=None, |
1491 |
+ assumeDistHashesSometimes=True, |
1492 |
+ assumeDistHashesAlways=True, |
1493 |
+ ) |
1494 |
+ distfiles = fetchlist_dict[cpv] |
1495 |
+ for myfile in distfiles: |
1496 |
+ try: |
1497 |
+ del mf.fhashdict["DIST"][myfile] |
1498 |
+ except KeyError: |
1499 |
+ pass |
1500 |
+ mf.write() |
1501 |
+ finally: |
1502 |
+ portage._doebuild_manifest_exempt_depend -= 1 |
1503 |
+ |
1504 |
+ |
1505 |
+portage.settings.validate() # generate warning messages if necessary |
1506 |
+ |
1507 |
+build_dir_phases = set( |
1508 |
+ [ |
1509 |
+ "setup", |
1510 |
+ "unpack", |
1511 |
+ "prepare", |
1512 |
+ "configure", |
1513 |
+ "compile", |
1514 |
+ "test", |
1515 |
+ "install", |
1516 |
+ "package", |
1517 |
+ "rpm", |
1518 |
+ "merge", |
1519 |
+ "qmerge", |
1520 |
+ ] |
1521 |
+) |
1522 |
|
1523 |
# If the current metadata is invalid then force the ebuild to be |
1524 |
# sourced again even if $T/environment already exists. |
1525 |
ebuild_changed = False |
1526 |
if mytree == "porttree" and build_dir_phases.intersection(pargs): |
1527 |
- ebuild_changed = \ |
1528 |
- portage.portdb._pull_valid_cache(cpv, ebuild, ebuild_portdir)[0] is None |
1529 |
+ ebuild_changed = ( |
1530 |
+ portage.portdb._pull_valid_cache(cpv, ebuild, ebuild_portdir)[0] is None |
1531 |
+ ) |
1532 |
|
1533 |
# Make configuration adjustments to portage.portdb.doebuild_settings, |
1534 |
# in order to enforce consistency for EBUILD_FORCE_TEST support |
1535 |
@@ -251,35 +294,37 @@ tmpsettings["PORTAGE_VERBOSE"] = "1" |
1536 |
tmpsettings.backup_changes("PORTAGE_VERBOSE") |
1537 |
|
1538 |
if opts.skip_manifest: |
1539 |
- tmpsettings["EBUILD_SKIP_MANIFEST"] = "1" |
1540 |
- tmpsettings.backup_changes("EBUILD_SKIP_MANIFEST") |
1541 |
+ tmpsettings["EBUILD_SKIP_MANIFEST"] = "1" |
1542 |
+ tmpsettings.backup_changes("EBUILD_SKIP_MANIFEST") |
1543 |
|
1544 |
-if opts.skip_manifest or \ |
1545 |
- "digest" in tmpsettings.features or \ |
1546 |
- "digest" in pargs or \ |
1547 |
- "manifest" in pargs: |
1548 |
- portage._doebuild_manifest_exempt_depend += 1 |
1549 |
+if ( |
1550 |
+ opts.skip_manifest |
1551 |
+ or "digest" in tmpsettings.features |
1552 |
+ or "digest" in pargs |
1553 |
+ or "manifest" in pargs |
1554 |
+): |
1555 |
+ portage._doebuild_manifest_exempt_depend += 1 |
1556 |
|
1557 |
if "test" in pargs: |
1558 |
- # This variable is a signal to config.regenerate() to |
1559 |
- # indicate that the test phase should be enabled regardless |
1560 |
- # of problems such as masked "test" USE flag. |
1561 |
- tmpsettings["EBUILD_FORCE_TEST"] = "1" |
1562 |
- tmpsettings.backup_changes("EBUILD_FORCE_TEST") |
1563 |
- tmpsettings.features.add("test") |
1564 |
- portage.writemsg(_("Forcing test.\n"), noiselevel=-1) |
1565 |
+ # This variable is a signal to config.regenerate() to |
1566 |
+ # indicate that the test phase should be enabled regardless |
1567 |
+ # of problems such as masked "test" USE flag. |
1568 |
+ tmpsettings["EBUILD_FORCE_TEST"] = "1" |
1569 |
+ tmpsettings.backup_changes("EBUILD_FORCE_TEST") |
1570 |
+ tmpsettings.features.add("test") |
1571 |
+ portage.writemsg(_("Forcing test.\n"), noiselevel=-1) |
1572 |
|
1573 |
tmpsettings.features.discard("fail-clean") |
1574 |
|
1575 |
if "merge" in pargs and "noauto" in tmpsettings.features: |
1576 |
- print("Disabling noauto in features... merge disables it. (qmerge doesn't)") |
1577 |
- tmpsettings.features.discard("noauto") |
1578 |
+ print("Disabling noauto in features... merge disables it. (qmerge doesn't)") |
1579 |
+ tmpsettings.features.discard("noauto") |
1580 |
|
1581 |
-if 'digest' in tmpsettings.features: |
1582 |
- if pargs and pargs[0] not in ("digest", "manifest"): |
1583 |
- pargs = ['digest'] + pargs |
1584 |
- # We only need to build digests on the first pass. |
1585 |
- tmpsettings.features.discard('digest') |
1586 |
+if "digest" in tmpsettings.features: |
1587 |
+ if pargs and pargs[0] not in ("digest", "manifest"): |
1588 |
+ pargs = ["digest"] + pargs |
1589 |
+ # We only need to build digests on the first pass. |
1590 |
+ tmpsettings.features.discard("digest") |
1591 |
|
1592 |
# Now that configuration adjustments are complete, create a clone of |
1593 |
# tmpsettings. The current instance refers to portdb.doebuild_settings, |
1594 |
@@ -287,25 +332,35 @@ if 'digest' in tmpsettings.features: |
1595 |
tmpsettings = portage.config(clone=tmpsettings) |
1596 |
|
1597 |
try: |
1598 |
- metadata = dict(zip(Package.metadata_keys, |
1599 |
- portage.db[portage.settings['EROOT']][mytree].dbapi.aux_get( |
1600 |
- cpv, Package.metadata_keys, myrepo=myrepo))) |
1601 |
+ metadata = dict( |
1602 |
+ zip( |
1603 |
+ Package.metadata_keys, |
1604 |
+ portage.db[portage.settings["EROOT"]][mytree].dbapi.aux_get( |
1605 |
+ cpv, Package.metadata_keys, myrepo=myrepo |
1606 |
+ ), |
1607 |
+ ) |
1608 |
+ ) |
1609 |
except PortageKeyError: |
1610 |
- # aux_get failure, message should have been shown on stderr. |
1611 |
- sys.exit(1) |
1612 |
- |
1613 |
-root_config = RootConfig(portage.settings, |
1614 |
- portage.db[portage.settings['EROOT']], None) |
1615 |
- |
1616 |
-cpv = portage.versions._pkg_str(cpv, |
1617 |
- metadata=metadata, |
1618 |
- settings=portage.settings, |
1619 |
- db=portage.db[portage.settings['EROOT']][mytree].dbapi) |
1620 |
- |
1621 |
-pkg = Package(built=(pkg_type != "ebuild"), cpv=cpv, |
1622 |
- installed=(pkg_type=="installed"), |
1623 |
- metadata=metadata, root_config=root_config, |
1624 |
- type_name=pkg_type) |
1625 |
+ # aux_get failure, message should have been shown on stderr. |
1626 |
+ sys.exit(1) |
1627 |
+ |
1628 |
+root_config = RootConfig(portage.settings, portage.db[portage.settings["EROOT"]], None) |
1629 |
+ |
1630 |
+cpv = portage.versions._pkg_str( |
1631 |
+ cpv, |
1632 |
+ metadata=metadata, |
1633 |
+ settings=portage.settings, |
1634 |
+ db=portage.db[portage.settings["EROOT"]][mytree].dbapi, |
1635 |
+) |
1636 |
+ |
1637 |
+pkg = Package( |
1638 |
+ built=(pkg_type != "ebuild"), |
1639 |
+ cpv=cpv, |
1640 |
+ installed=(pkg_type == "installed"), |
1641 |
+ metadata=metadata, |
1642 |
+ root_config=root_config, |
1643 |
+ type_name=pkg_type, |
1644 |
+) |
1645 |
|
1646 |
# Apply package.env and repo-level settings. This allows per-package |
1647 |
# FEATURES and other variables (possibly PORTAGE_TMPDIR) to be |
1648 |
@@ -315,63 +370,76 @@ pkg = Package(built=(pkg_type != "ebuild"), cpv=cpv, |
1649 |
# portdb.porttrees in order to accomplish this). |
1650 |
tmpsettings.setcpv(pkg) |
1651 |
|
1652 |
+ |
1653 |
def stale_env_warning(): |
1654 |
- if "clean" not in pargs and \ |
1655 |
- "noauto" not in tmpsettings.features and \ |
1656 |
- build_dir_phases.intersection(pargs): |
1657 |
- portage.doebuild_environment(ebuild, "setup", portage.root, |
1658 |
- tmpsettings, debug, 1, portage.portdb) |
1659 |
- env_filename = os.path.join(tmpsettings["T"], "environment") |
1660 |
- if os.path.exists(env_filename): |
1661 |
- msg = ("Existing ${T}/environment for '%s' will be sourced. " + \ |
1662 |
- "Run 'clean' to start with a fresh environment.") % \ |
1663 |
- (tmpsettings["PF"], ) |
1664 |
- msg = textwrap.wrap(msg, 70) |
1665 |
- for x in msg: |
1666 |
- portage.writemsg(">>> %s\n" % x) |
1667 |
- |
1668 |
- if ebuild_changed: |
1669 |
- open(os.path.join(tmpsettings['PORTAGE_BUILDDIR'], |
1670 |
- '.ebuild_changed'), 'w').close() |
1671 |
+ if ( |
1672 |
+ "clean" not in pargs |
1673 |
+ and "noauto" not in tmpsettings.features |
1674 |
+ and build_dir_phases.intersection(pargs) |
1675 |
+ ): |
1676 |
+ portage.doebuild_environment( |
1677 |
+ ebuild, "setup", portage.root, tmpsettings, debug, 1, portage.portdb |
1678 |
+ ) |
1679 |
+ env_filename = os.path.join(tmpsettings["T"], "environment") |
1680 |
+ if os.path.exists(env_filename): |
1681 |
+ msg = ( |
1682 |
+ "Existing ${T}/environment for '%s' will be sourced. " |
1683 |
+ + "Run 'clean' to start with a fresh environment." |
1684 |
+ ) % (tmpsettings["PF"],) |
1685 |
+ msg = textwrap.wrap(msg, 70) |
1686 |
+ for x in msg: |
1687 |
+ portage.writemsg(">>> %s\n" % x) |
1688 |
+ |
1689 |
+ if ebuild_changed: |
1690 |
+ open( |
1691 |
+ os.path.join(tmpsettings["PORTAGE_BUILDDIR"], ".ebuild_changed"), |
1692 |
+ "w", |
1693 |
+ ).close() |
1694 |
+ |
1695 |
|
1696 |
checked_for_stale_env = False |
1697 |
|
1698 |
for arg in pargs: |
1699 |
- try: |
1700 |
- if not checked_for_stale_env and arg not in ("digest","manifest"): |
1701 |
- # This has to go after manifest generation since otherwise |
1702 |
- # aux_get() might fail due to invalid ebuild digests. |
1703 |
- stale_env_warning() |
1704 |
- checked_for_stale_env = True |
1705 |
- |
1706 |
- if arg in ("digest", "manifest") and force: |
1707 |
- discard_digests(ebuild, tmpsettings, portage.portdb) |
1708 |
- a = portage.doebuild(ebuild, arg, settings=tmpsettings, |
1709 |
- debug=debug, tree=mytree, |
1710 |
- vartree=portage.db[portage.root]['vartree']) |
1711 |
- except KeyboardInterrupt: |
1712 |
- print("Interrupted.") |
1713 |
- a = 1 |
1714 |
- except PortageKeyError: |
1715 |
- # aux_get error |
1716 |
- a = 1 |
1717 |
- except UnsupportedAPIException as e: |
1718 |
- msg = textwrap.wrap(str(e), 70) |
1719 |
- del e |
1720 |
- for x in msg: |
1721 |
- portage.writemsg("!!! %s\n" % x, noiselevel=-1) |
1722 |
- a = 1 |
1723 |
- except PortagePackageException as e: |
1724 |
- portage.writemsg("!!! %s\n" % (e,), noiselevel=-1) |
1725 |
- a = 1 |
1726 |
- except PermissionDenied as e: |
1727 |
- portage.writemsg("!!! Permission Denied: %s\n" % (e,), noiselevel=-1) |
1728 |
- a = 1 |
1729 |
- if a == None: |
1730 |
- print("Could not run the required binary?") |
1731 |
- a = 127 |
1732 |
- if a: |
1733 |
- global_event_loop().close() |
1734 |
- sys.exit(a) |
1735 |
+ try: |
1736 |
+ if not checked_for_stale_env and arg not in ("digest", "manifest"): |
1737 |
+ # This has to go after manifest generation since otherwise |
1738 |
+ # aux_get() might fail due to invalid ebuild digests. |
1739 |
+ stale_env_warning() |
1740 |
+ checked_for_stale_env = True |
1741 |
+ |
1742 |
+ if arg in ("digest", "manifest") and force: |
1743 |
+ discard_digests(ebuild, tmpsettings, portage.portdb) |
1744 |
+ a = portage.doebuild( |
1745 |
+ ebuild, |
1746 |
+ arg, |
1747 |
+ settings=tmpsettings, |
1748 |
+ debug=debug, |
1749 |
+ tree=mytree, |
1750 |
+ vartree=portage.db[portage.root]["vartree"], |
1751 |
+ ) |
1752 |
+ except KeyboardInterrupt: |
1753 |
+ print("Interrupted.") |
1754 |
+ a = 1 |
1755 |
+ except PortageKeyError: |
1756 |
+ # aux_get error |
1757 |
+ a = 1 |
1758 |
+ except UnsupportedAPIException as e: |
1759 |
+ msg = textwrap.wrap(str(e), 70) |
1760 |
+ del e |
1761 |
+ for x in msg: |
1762 |
+ portage.writemsg("!!! %s\n" % x, noiselevel=-1) |
1763 |
+ a = 1 |
1764 |
+ except PortagePackageException as e: |
1765 |
+ portage.writemsg("!!! %s\n" % (e,), noiselevel=-1) |
1766 |
+ a = 1 |
1767 |
+ except PermissionDenied as e: |
1768 |
+ portage.writemsg("!!! Permission Denied: %s\n" % (e,), noiselevel=-1) |
1769 |
+ a = 1 |
1770 |
+ if a == None: |
1771 |
+ print("Could not run the required binary?") |
1772 |
+ a = 127 |
1773 |
+ if a: |
1774 |
+ global_event_loop().close() |
1775 |
+ sys.exit(a) |
1776 |
|
1777 |
global_event_loop().close() |
1778 |
|
1779 |
diff --git a/bin/egencache b/bin/egencache |
1780 |
index b590a5529..2b523c7b3 100755 |
1781 |
--- a/bin/egencache |
1782 |
+++ b/bin/egencache |
1783 |
@@ -11,25 +11,28 @@ import sys |
1784 |
# This block ensures that ^C interrupts are handled quietly. |
1785 |
try: |
1786 |
|
1787 |
- def exithandler(signum, _frame): |
1788 |
- signal.signal(signal.SIGINT, signal.SIG_IGN) |
1789 |
- signal.signal(signal.SIGTERM, signal.SIG_IGN) |
1790 |
- sys.exit(128 + signum) |
1791 |
+ def exithandler(signum, _frame): |
1792 |
+ signal.signal(signal.SIGINT, signal.SIG_IGN) |
1793 |
+ signal.signal(signal.SIGTERM, signal.SIG_IGN) |
1794 |
+ sys.exit(128 + signum) |
1795 |
|
1796 |
- signal.signal(signal.SIGINT, exithandler) |
1797 |
- signal.signal(signal.SIGTERM, exithandler) |
1798 |
+ signal.signal(signal.SIGINT, exithandler) |
1799 |
+ signal.signal(signal.SIGTERM, exithandler) |
1800 |
|
1801 |
except KeyboardInterrupt: |
1802 |
- sys.exit(128 + signal.SIGINT) |
1803 |
+ sys.exit(128 + signal.SIGINT) |
1804 |
+ |
1805 |
|
1806 |
def debug_signal(_signum, _frame): |
1807 |
- import pdb |
1808 |
- pdb.set_trace() |
1809 |
+ import pdb |
1810 |
+ |
1811 |
+ pdb.set_trace() |
1812 |
+ |
1813 |
|
1814 |
-if platform.python_implementation() == 'Jython': |
1815 |
- debug_signum = signal.SIGUSR2 # bug #424259 |
1816 |
+if platform.python_implementation() == "Jython": |
1817 |
+ debug_signum = signal.SIGUSR2 # bug #424259 |
1818 |
else: |
1819 |
- debug_signum = signal.SIGUSR1 |
1820 |
+ debug_signum = signal.SIGUSR1 |
1821 |
|
1822 |
signal.signal(debug_signum, debug_signal) |
1823 |
|
1824 |
@@ -42,17 +45,28 @@ import textwrap |
1825 |
import re |
1826 |
|
1827 |
from os import path as osp |
1828 |
-if osp.isfile(osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), ".portage_not_installed")): |
1829 |
- sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "lib")) |
1830 |
+ |
1831 |
+if osp.isfile( |
1832 |
+ osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), ".portage_not_installed") |
1833 |
+): |
1834 |
+ sys.path.insert( |
1835 |
+ 0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "lib") |
1836 |
+ ) |
1837 |
import portage |
1838 |
+ |
1839 |
portage._internal_caller = True |
1840 |
from portage import os, _encodings, _unicode_encode, _unicode_decode |
1841 |
from portage.cache.cache_errors import CacheError, StatCollision |
1842 |
-from portage.cache.index.pkg_desc_index import pkg_desc_index_line_format, pkg_desc_index_line_read |
1843 |
+from portage.cache.index.pkg_desc_index import ( |
1844 |
+ pkg_desc_index_line_format, |
1845 |
+ pkg_desc_index_line_read, |
1846 |
+) |
1847 |
from portage.const import TIMESTAMP_FORMAT |
1848 |
from portage.dep import _repo_separator |
1849 |
from portage.output import colorize, EOutput |
1850 |
-from portage.package.ebuild._parallel_manifest.ManifestScheduler import ManifestScheduler |
1851 |
+from portage.package.ebuild._parallel_manifest.ManifestScheduler import ( |
1852 |
+ ManifestScheduler, |
1853 |
+) |
1854 |
from portage.util import cmp_sort_key, writemsg_level |
1855 |
from portage.util._async.AsyncFunction import AsyncFunction |
1856 |
from portage.util._async.run_main_scheduler import run_main_scheduler |
1857 |
@@ -65,1125 +79,1326 @@ from portage.versions import vercmp |
1858 |
from _emerge.MetadataRegen import MetadataRegen |
1859 |
|
1860 |
try: |
1861 |
- from xml.etree import ElementTree |
1862 |
+ from xml.etree import ElementTree |
1863 |
except ImportError: |
1864 |
- pass |
1865 |
+ pass |
1866 |
else: |
1867 |
- try: |
1868 |
- from xml.parsers.expat import ExpatError |
1869 |
- except ImportError: |
1870 |
- pass |
1871 |
- else: |
1872 |
- from portage.xml.metadata import parse_metadata_use # pylint: disable=ungrouped-imports |
1873 |
+ try: |
1874 |
+ from xml.parsers.expat import ExpatError |
1875 |
+ except ImportError: |
1876 |
+ pass |
1877 |
+ else: |
1878 |
+ from portage.xml.metadata import ( # pylint: disable=ungrouped-imports |
1879 |
+ parse_metadata_use, |
1880 |
+ ) |
1881 |
|
1882 |
|
1883 |
def parse_args(args): |
1884 |
- usage = "egencache [options] <action> ... [atom] ..." |
1885 |
- parser = argparse.ArgumentParser(usage=usage) |
1886 |
- |
1887 |
- actions = parser.add_argument_group('Actions') |
1888 |
- actions.add_argument("--update", |
1889 |
- action="store_true", |
1890 |
- help="update metadata/md5-cache/ (generate as necessary)") |
1891 |
- actions.add_argument("--update-use-local-desc", |
1892 |
- action="store_true", |
1893 |
- help="update the use.local.desc file from metadata.xml") |
1894 |
- actions.add_argument("--update-changelogs", |
1895 |
- action="store_true", |
1896 |
- help="update the ChangeLog files from SCM logs") |
1897 |
- actions.add_argument("--update-pkg-desc-index", |
1898 |
- action="store_true", |
1899 |
- help="update package description index") |
1900 |
- actions.add_argument("--update-manifests", |
1901 |
- action="store_true", |
1902 |
- help="update manifests") |
1903 |
- |
1904 |
- common = parser.add_argument_group('Common options') |
1905 |
- common.add_argument("--repo", |
1906 |
- action="store", |
1907 |
- help="name of repo to operate on") |
1908 |
- common.add_argument("--config-root", |
1909 |
- help="location of portage config files", |
1910 |
- dest="portage_configroot") |
1911 |
- common.add_argument("--external-cache-only", |
1912 |
- action="store_true", |
1913 |
- help="Output only to the external cache (not the repository itself)") |
1914 |
- common.add_argument("--gpg-dir", |
1915 |
- help="override the PORTAGE_GPG_DIR variable", |
1916 |
- dest="gpg_dir") |
1917 |
- common.add_argument("--gpg-key", |
1918 |
- help="override the PORTAGE_GPG_KEY variable", |
1919 |
- dest="gpg_key") |
1920 |
- common.add_argument("--repositories-configuration", |
1921 |
- help="override configuration of repositories (in format of repos.conf)", |
1922 |
- dest="repositories_configuration") |
1923 |
- common.add_argument("--sign-manifests", |
1924 |
- choices=('y', 'n'), |
1925 |
- metavar="<y|n>", |
1926 |
- help="manually override layout.conf sign-manifests setting") |
1927 |
- common.add_argument("--strict-manifests", |
1928 |
- choices=('y', 'n'), |
1929 |
- metavar="<y|n>", |
1930 |
- help="manually override \"strict\" FEATURES setting") |
1931 |
- common.add_argument("--thin-manifests", |
1932 |
- choices=('y', 'n'), |
1933 |
- metavar="<y|n>", |
1934 |
- help="manually override layout.conf thin-manifests setting") |
1935 |
- common.add_argument("--tolerant", |
1936 |
- action="store_true", |
1937 |
- help="exit successfully if only minor errors occurred") |
1938 |
- common.add_argument("--ignore-default-opts", |
1939 |
- action="store_true", |
1940 |
- help="do not use the EGENCACHE_DEFAULT_OPTS environment variable") |
1941 |
- common.add_argument("-v", "--verbose", |
1942 |
- action="count", default=0, |
1943 |
- help="increase verbosity") |
1944 |
- common.add_argument("--write-timestamp", |
1945 |
- action="store_true", |
1946 |
- help="write metadata/timestamp.chk as required for rsync repositories") |
1947 |
- |
1948 |
- update = parser.add_argument_group('--update options') |
1949 |
- update.add_argument("--cache-dir", |
1950 |
- help="location of the metadata cache", |
1951 |
- dest="cache_dir") |
1952 |
- update.add_argument("-j", "--jobs", |
1953 |
- type=int, |
1954 |
- action="store", |
1955 |
- help="max ebuild processes to spawn") |
1956 |
- update.add_argument("--load-average", |
1957 |
- type=float, |
1958 |
- action="store", |
1959 |
- help="max load allowed when spawning multiple jobs", |
1960 |
- dest="load_average") |
1961 |
- update.add_argument("--rsync", |
1962 |
- action="store_true", |
1963 |
- help="enable rsync stat collision workaround " + \ |
1964 |
- "for bug 139134 (use with --update)") |
1965 |
- |
1966 |
- uld = parser.add_argument_group('--update-use-local-desc options') |
1967 |
- uld.add_argument("--preserve-comments", |
1968 |
- action="store_true", |
1969 |
- help="preserve the comments from the existing use.local.desc file") |
1970 |
- uld.add_argument("--use-local-desc-output", |
1971 |
- help="output file for use.local.desc data (or '-' for stdout)", |
1972 |
- dest="uld_output") |
1973 |
- |
1974 |
- uc = parser.add_argument_group('--update-changelogs options') |
1975 |
- uc.add_argument("--changelog-reversed", |
1976 |
- action="store_true", |
1977 |
- help="log commits in reverse order (oldest first)") |
1978 |
- uc.add_argument("--changelog-output", |
1979 |
- help="output filename for change logs", |
1980 |
- dest="changelog_output", |
1981 |
- default="ChangeLog") |
1982 |
- |
1983 |
- options, args = parser.parse_known_args(args) |
1984 |
- |
1985 |
- if options.jobs: |
1986 |
- jobs = None |
1987 |
- try: |
1988 |
- jobs = int(options.jobs) |
1989 |
- except ValueError: |
1990 |
- jobs = -1 |
1991 |
- |
1992 |
- if jobs < 1: |
1993 |
- parser.error("Invalid: --jobs='%s'" % \ |
1994 |
- (options.jobs,)) |
1995 |
- |
1996 |
- options.jobs = jobs |
1997 |
- |
1998 |
- else: |
1999 |
- options.jobs = None |
2000 |
- |
2001 |
- if options.load_average: |
2002 |
- try: |
2003 |
- load_average = float(options.load_average) |
2004 |
- except ValueError: |
2005 |
- load_average = 0.0 |
2006 |
- |
2007 |
- if load_average <= 0.0: |
2008 |
- parser.error("Invalid: --load-average='%s'" % \ |
2009 |
- (options.load_average,)) |
2010 |
- |
2011 |
- options.load_average = load_average |
2012 |
- |
2013 |
- else: |
2014 |
- options.load_average = None |
2015 |
- |
2016 |
- options.config_root = options.portage_configroot |
2017 |
- if options.config_root is not None and \ |
2018 |
- not os.path.isdir(options.config_root): |
2019 |
- parser.error("Not a directory: --config-root='%s'" % \ |
2020 |
- (options.config_root,)) |
2021 |
- |
2022 |
- if options.cache_dir is not None: |
2023 |
- if not os.path.isdir(options.cache_dir): |
2024 |
- parser.error("Not a directory: --cache-dir='%s'" % \ |
2025 |
- (options.cache_dir,)) |
2026 |
- if not os.access(options.cache_dir, os.W_OK): |
2027 |
- parser.error("Write access denied: --cache-dir='%s'" % \ |
2028 |
- (options.cache_dir,)) |
2029 |
- |
2030 |
- for atom in args: |
2031 |
- try: |
2032 |
- atom = portage.dep.Atom(atom) |
2033 |
- except portage.exception.InvalidAtom: |
2034 |
- parser.error('Invalid atom: %s' % (atom,)) |
2035 |
- |
2036 |
- if not isjustname(atom): |
2037 |
- parser.error('Atom is too specific: %s' % (atom,)) |
2038 |
- |
2039 |
- if options.update_use_local_desc: |
2040 |
- try: |
2041 |
- ElementTree |
2042 |
- ExpatError |
2043 |
- except NameError: |
2044 |
- parser.error('--update-use-local-desc requires python with USE=xml!') |
2045 |
- |
2046 |
- if options.uld_output == '-' and options.preserve_comments: |
2047 |
- parser.error('--preserve-comments can not be used when outputting to stdout') |
2048 |
- |
2049 |
- return parser, options, args |
2050 |
+ usage = "egencache [options] <action> ... [atom] ..." |
2051 |
+ parser = argparse.ArgumentParser(usage=usage) |
2052 |
+ |
2053 |
+ actions = parser.add_argument_group("Actions") |
2054 |
+ actions.add_argument( |
2055 |
+ "--update", |
2056 |
+ action="store_true", |
2057 |
+ help="update metadata/md5-cache/ (generate as necessary)", |
2058 |
+ ) |
2059 |
+ actions.add_argument( |
2060 |
+ "--update-use-local-desc", |
2061 |
+ action="store_true", |
2062 |
+ help="update the use.local.desc file from metadata.xml", |
2063 |
+ ) |
2064 |
+ actions.add_argument( |
2065 |
+ "--update-changelogs", |
2066 |
+ action="store_true", |
2067 |
+ help="update the ChangeLog files from SCM logs", |
2068 |
+ ) |
2069 |
+ actions.add_argument( |
2070 |
+ "--update-pkg-desc-index", |
2071 |
+ action="store_true", |
2072 |
+ help="update package description index", |
2073 |
+ ) |
2074 |
+ actions.add_argument( |
2075 |
+ "--update-manifests", action="store_true", help="update manifests" |
2076 |
+ ) |
2077 |
+ |
2078 |
+ common = parser.add_argument_group("Common options") |
2079 |
+ common.add_argument("--repo", action="store", help="name of repo to operate on") |
2080 |
+ common.add_argument( |
2081 |
+ "--config-root", |
2082 |
+ help="location of portage config files", |
2083 |
+ dest="portage_configroot", |
2084 |
+ ) |
2085 |
+ common.add_argument( |
2086 |
+ "--external-cache-only", |
2087 |
+ action="store_true", |
2088 |
+ help="Output only to the external cache (not the repository itself)", |
2089 |
+ ) |
2090 |
+ common.add_argument( |
2091 |
+ "--gpg-dir", help="override the PORTAGE_GPG_DIR variable", dest="gpg_dir" |
2092 |
+ ) |
2093 |
+ common.add_argument( |
2094 |
+ "--gpg-key", help="override the PORTAGE_GPG_KEY variable", dest="gpg_key" |
2095 |
+ ) |
2096 |
+ common.add_argument( |
2097 |
+ "--repositories-configuration", |
2098 |
+ help="override configuration of repositories (in format of repos.conf)", |
2099 |
+ dest="repositories_configuration", |
2100 |
+ ) |
2101 |
+ common.add_argument( |
2102 |
+ "--sign-manifests", |
2103 |
+ choices=("y", "n"), |
2104 |
+ metavar="<y|n>", |
2105 |
+ help="manually override layout.conf sign-manifests setting", |
2106 |
+ ) |
2107 |
+ common.add_argument( |
2108 |
+ "--strict-manifests", |
2109 |
+ choices=("y", "n"), |
2110 |
+ metavar="<y|n>", |
2111 |
+ help='manually override "strict" FEATURES setting', |
2112 |
+ ) |
2113 |
+ common.add_argument( |
2114 |
+ "--thin-manifests", |
2115 |
+ choices=("y", "n"), |
2116 |
+ metavar="<y|n>", |
2117 |
+ help="manually override layout.conf thin-manifests setting", |
2118 |
+ ) |
2119 |
+ common.add_argument( |
2120 |
+ "--tolerant", |
2121 |
+ action="store_true", |
2122 |
+ help="exit successfully if only minor errors occurred", |
2123 |
+ ) |
2124 |
+ common.add_argument( |
2125 |
+ "--ignore-default-opts", |
2126 |
+ action="store_true", |
2127 |
+ help="do not use the EGENCACHE_DEFAULT_OPTS environment variable", |
2128 |
+ ) |
2129 |
+ common.add_argument( |
2130 |
+ "-v", "--verbose", action="count", default=0, help="increase verbosity" |
2131 |
+ ) |
2132 |
+ common.add_argument( |
2133 |
+ "--write-timestamp", |
2134 |
+ action="store_true", |
2135 |
+ help="write metadata/timestamp.chk as required for rsync repositories", |
2136 |
+ ) |
2137 |
+ |
2138 |
+ update = parser.add_argument_group("--update options") |
2139 |
+ update.add_argument( |
2140 |
+ "--cache-dir", help="location of the metadata cache", dest="cache_dir" |
2141 |
+ ) |
2142 |
+ update.add_argument( |
2143 |
+ "-j", "--jobs", type=int, action="store", help="max ebuild processes to spawn" |
2144 |
+ ) |
2145 |
+ update.add_argument( |
2146 |
+ "--load-average", |
2147 |
+ type=float, |
2148 |
+ action="store", |
2149 |
+ help="max load allowed when spawning multiple jobs", |
2150 |
+ dest="load_average", |
2151 |
+ ) |
2152 |
+ update.add_argument( |
2153 |
+ "--rsync", |
2154 |
+ action="store_true", |
2155 |
+ help="enable rsync stat collision workaround " |
2156 |
+ + "for bug 139134 (use with --update)", |
2157 |
+ ) |
2158 |
+ |
2159 |
+ uld = parser.add_argument_group("--update-use-local-desc options") |
2160 |
+ uld.add_argument( |
2161 |
+ "--preserve-comments", |
2162 |
+ action="store_true", |
2163 |
+ help="preserve the comments from the existing use.local.desc file", |
2164 |
+ ) |
2165 |
+ uld.add_argument( |
2166 |
+ "--use-local-desc-output", |
2167 |
+ help="output file for use.local.desc data (or '-' for stdout)", |
2168 |
+ dest="uld_output", |
2169 |
+ ) |
2170 |
+ |
2171 |
+ uc = parser.add_argument_group("--update-changelogs options") |
2172 |
+ uc.add_argument( |
2173 |
+ "--changelog-reversed", |
2174 |
+ action="store_true", |
2175 |
+ help="log commits in reverse order (oldest first)", |
2176 |
+ ) |
2177 |
+ uc.add_argument( |
2178 |
+ "--changelog-output", |
2179 |
+ help="output filename for change logs", |
2180 |
+ dest="changelog_output", |
2181 |
+ default="ChangeLog", |
2182 |
+ ) |
2183 |
+ |
2184 |
+ options, args = parser.parse_known_args(args) |
2185 |
+ |
2186 |
+ if options.jobs: |
2187 |
+ jobs = None |
2188 |
+ try: |
2189 |
+ jobs = int(options.jobs) |
2190 |
+ except ValueError: |
2191 |
+ jobs = -1 |
2192 |
+ |
2193 |
+ if jobs < 1: |
2194 |
+ parser.error("Invalid: --jobs='%s'" % (options.jobs,)) |
2195 |
+ |
2196 |
+ options.jobs = jobs |
2197 |
+ |
2198 |
+ else: |
2199 |
+ options.jobs = None |
2200 |
+ |
2201 |
+ if options.load_average: |
2202 |
+ try: |
2203 |
+ load_average = float(options.load_average) |
2204 |
+ except ValueError: |
2205 |
+ load_average = 0.0 |
2206 |
+ |
2207 |
+ if load_average <= 0.0: |
2208 |
+ parser.error("Invalid: --load-average='%s'" % (options.load_average,)) |
2209 |
+ |
2210 |
+ options.load_average = load_average |
2211 |
+ |
2212 |
+ else: |
2213 |
+ options.load_average = None |
2214 |
+ |
2215 |
+ options.config_root = options.portage_configroot |
2216 |
+ if options.config_root is not None and not os.path.isdir(options.config_root): |
2217 |
+ parser.error("Not a directory: --config-root='%s'" % (options.config_root,)) |
2218 |
+ |
2219 |
+ if options.cache_dir is not None: |
2220 |
+ if not os.path.isdir(options.cache_dir): |
2221 |
+ parser.error("Not a directory: --cache-dir='%s'" % (options.cache_dir,)) |
2222 |
+ if not os.access(options.cache_dir, os.W_OK): |
2223 |
+ parser.error("Write access denied: --cache-dir='%s'" % (options.cache_dir,)) |
2224 |
+ |
2225 |
+ for atom in args: |
2226 |
+ try: |
2227 |
+ atom = portage.dep.Atom(atom) |
2228 |
+ except portage.exception.InvalidAtom: |
2229 |
+ parser.error("Invalid atom: %s" % (atom,)) |
2230 |
+ |
2231 |
+ if not isjustname(atom): |
2232 |
+ parser.error("Atom is too specific: %s" % (atom,)) |
2233 |
+ |
2234 |
+ if options.update_use_local_desc: |
2235 |
+ try: |
2236 |
+ ElementTree |
2237 |
+ ExpatError |
2238 |
+ except NameError: |
2239 |
+ parser.error("--update-use-local-desc requires python with USE=xml!") |
2240 |
+ |
2241 |
+ if options.uld_output == "-" and options.preserve_comments: |
2242 |
+ parser.error("--preserve-comments can not be used when outputting to stdout") |
2243 |
+ |
2244 |
+ return parser, options, args |
2245 |
+ |
2246 |
|
2247 |
class GenCache: |
2248 |
- def __init__(self, portdb, cp_iter=None, max_jobs=None, max_load=None, |
2249 |
- rsync=False, external_cache_only=False): |
2250 |
- # The caller must set portdb.porttrees in order to constrain |
2251 |
- # findname, cp_list, and cpv_list to the desired tree. |
2252 |
- tree = portdb.porttrees[0] |
2253 |
- self._portdb = portdb |
2254 |
- self._eclass_db = portdb.repositories.get_repo_for_location(tree).eclass_db |
2255 |
- self._auxdbkeys = portdb._known_keys |
2256 |
- # We can globally cleanse stale cache only if we |
2257 |
- # iterate over every single cp. |
2258 |
- self._global_cleanse = cp_iter is None |
2259 |
- if cp_iter is not None: |
2260 |
- self._cp_set = set(cp_iter) |
2261 |
- cp_iter = iter(self._cp_set) |
2262 |
- self._cp_missing = self._cp_set.copy() |
2263 |
- else: |
2264 |
- self._cp_set = None |
2265 |
- self._cp_missing = set() |
2266 |
- write_auxdb = external_cache_only or "metadata-transfer" in portdb.settings.features |
2267 |
- self._regen = MetadataRegen(portdb, cp_iter=cp_iter, |
2268 |
- consumer=self._metadata_callback, |
2269 |
- max_jobs=max_jobs, max_load=max_load, |
2270 |
- write_auxdb=write_auxdb, main=True) |
2271 |
- self.returncode = os.EX_OK |
2272 |
- conf = portdb.repositories.get_repo_for_location(tree) |
2273 |
- if external_cache_only: |
2274 |
- self._trg_caches = () |
2275 |
- else: |
2276 |
- self._trg_caches = tuple(conf.iter_pregenerated_caches( |
2277 |
- self._auxdbkeys, force=True, readonly=False)) |
2278 |
- if not self._trg_caches: |
2279 |
- raise Exception("cache formats '%s' aren't supported" % |
2280 |
- (" ".join(conf.cache_formats),)) |
2281 |
- |
2282 |
- if rsync: |
2283 |
- for trg_cache in self._trg_caches: |
2284 |
- if hasattr(trg_cache, 'raise_stat_collision'): |
2285 |
- trg_cache.raise_stat_collision = True |
2286 |
- # Make _metadata_callback write this cache first, in case |
2287 |
- # it raises a StatCollision and triggers mtime |
2288 |
- # modification. |
2289 |
- self._trg_caches = tuple([trg_cache] + |
2290 |
- [x for x in self._trg_caches if x is not trg_cache]) |
2291 |
- |
2292 |
- self._existing_nodes = set() |
2293 |
- |
2294 |
- def _metadata_callback(self, cpv, repo_path, metadata, |
2295 |
- ebuild_hash, eapi_supported): |
2296 |
- self._existing_nodes.add(cpv) |
2297 |
- self._cp_missing.discard(cpv_getkey(cpv)) |
2298 |
- |
2299 |
- # Since we're supposed to be able to efficiently obtain the |
2300 |
- # EAPI from _parse_eapi_ebuild_head, we don't write cache |
2301 |
- # entries for unsupported EAPIs. |
2302 |
- if metadata is not None and eapi_supported: |
2303 |
- for trg_cache in self._trg_caches: |
2304 |
- self._write_cache(trg_cache, |
2305 |
- cpv, repo_path, metadata, ebuild_hash) |
2306 |
- |
2307 |
- def _write_cache(self, trg_cache, cpv, repo_path, metadata, ebuild_hash): |
2308 |
- |
2309 |
- if not hasattr(trg_cache, 'raise_stat_collision'): |
2310 |
- # This cache does not avoid redundant writes automatically, |
2311 |
- # so check for an identical existing entry before writing. |
2312 |
- # This prevents unnecessary disk writes and can also prevent |
2313 |
- # unnecessary rsync transfers. |
2314 |
- try: |
2315 |
- dest = trg_cache[cpv] |
2316 |
- except (KeyError, CacheError): |
2317 |
- pass |
2318 |
- else: |
2319 |
- if trg_cache.validate_entry(dest, |
2320 |
- ebuild_hash, self._eclass_db): |
2321 |
- identical = True |
2322 |
- for k in self._auxdbkeys: |
2323 |
- if dest.get(k, '') != metadata.get(k, ''): |
2324 |
- identical = False |
2325 |
- break |
2326 |
- if identical: |
2327 |
- return |
2328 |
- |
2329 |
- try: |
2330 |
- chf = trg_cache.validation_chf |
2331 |
- metadata['_%s_' % chf] = getattr(ebuild_hash, chf) |
2332 |
- try: |
2333 |
- trg_cache[cpv] = metadata |
2334 |
- except StatCollision as sc: |
2335 |
- # If the content of a cache entry changes and neither the |
2336 |
- # file mtime nor size changes, it will prevent rsync from |
2337 |
- # detecting changes. Cache backends may raise this |
2338 |
- # exception from _setitem() if they detect this type of stat |
2339 |
- # collision. These exceptions are handled by bumping the |
2340 |
- # mtime on the ebuild (and the corresponding cache entry). |
2341 |
- # See bug #139134. It is convenient to include checks for |
2342 |
- # redundant writes along with the internal StatCollision |
2343 |
- # detection code, so for caches with the |
2344 |
- # raise_stat_collision attribute, we do not need to |
2345 |
- # explicitly check for redundant writes like we do for the |
2346 |
- # other cache types above. |
2347 |
- max_mtime = sc.mtime |
2348 |
- for _ec, ec_hash in metadata['_eclasses_'].items(): |
2349 |
- if max_mtime < ec_hash.mtime: |
2350 |
- max_mtime = ec_hash.mtime |
2351 |
- if max_mtime == sc.mtime: |
2352 |
- max_mtime += 1 |
2353 |
- max_mtime = int(max_mtime) |
2354 |
- try: |
2355 |
- os.utime(ebuild_hash.location, (max_mtime, max_mtime)) |
2356 |
- except OSError as e: |
2357 |
- self.returncode |= 1 |
2358 |
- writemsg_level( |
2359 |
- "%s writing target: %s\n" % (cpv, e), |
2360 |
- level=logging.ERROR, noiselevel=-1) |
2361 |
- else: |
2362 |
- ebuild_hash.mtime = max_mtime |
2363 |
- metadata['_mtime_'] = max_mtime |
2364 |
- trg_cache[cpv] = metadata |
2365 |
- self._portdb.auxdb[repo_path][cpv] = metadata |
2366 |
- |
2367 |
- except CacheError as ce: |
2368 |
- self.returncode |= 1 |
2369 |
- writemsg_level( |
2370 |
- "%s writing target: %s\n" % (cpv, ce), |
2371 |
- level=logging.ERROR, noiselevel=-1) |
2372 |
- |
2373 |
- def run(self): |
2374 |
- signum = run_main_scheduler(self._regen) |
2375 |
- if signum is not None: |
2376 |
- sys.exit(128 + signum) |
2377 |
- |
2378 |
- self.returncode |= self._regen.returncode |
2379 |
- |
2380 |
- for trg_cache in self._trg_caches: |
2381 |
- self._cleanse_cache(trg_cache) |
2382 |
- |
2383 |
- def _cleanse_cache(self, trg_cache): |
2384 |
- cp_missing = self._cp_missing |
2385 |
- dead_nodes = set() |
2386 |
- if self._global_cleanse: |
2387 |
- try: |
2388 |
- for cpv in trg_cache: |
2389 |
- cp = cpv_getkey(cpv) |
2390 |
- if cp is None: |
2391 |
- self.returncode |= 1 |
2392 |
- writemsg_level( |
2393 |
- "Unable to parse cp for '%s'\n" % (cpv,), |
2394 |
- level=logging.ERROR, noiselevel=-1) |
2395 |
- else: |
2396 |
- dead_nodes.add(cpv) |
2397 |
- except CacheError as ce: |
2398 |
- self.returncode |= 1 |
2399 |
- writemsg_level( |
2400 |
- "Error listing cache entries for " + \ |
2401 |
- "'%s': %s, continuing...\n" % \ |
2402 |
- (trg_cache.location, ce), |
2403 |
- level=logging.ERROR, noiselevel=-1) |
2404 |
- |
2405 |
- else: |
2406 |
- cp_set = self._cp_set |
2407 |
- try: |
2408 |
- for cpv in trg_cache: |
2409 |
- cp = cpv_getkey(cpv) |
2410 |
- if cp is None: |
2411 |
- self.returncode |= 1 |
2412 |
- writemsg_level( |
2413 |
- "Unable to parse cp for '%s'\n" % (cpv,), |
2414 |
- level=logging.ERROR, noiselevel=-1) |
2415 |
- else: |
2416 |
- cp_missing.discard(cp) |
2417 |
- if cp in cp_set: |
2418 |
- dead_nodes.add(cpv) |
2419 |
- except CacheError as ce: |
2420 |
- self.returncode |= 1 |
2421 |
- writemsg_level( |
2422 |
- "Error listing cache entries for " + \ |
2423 |
- "'%s': %s, continuing...\n" % \ |
2424 |
- (trg_cache.location, ce), |
2425 |
- level=logging.ERROR, noiselevel=-1) |
2426 |
- |
2427 |
- if cp_missing: |
2428 |
- self.returncode |= 1 |
2429 |
- for cp in sorted(cp_missing): |
2430 |
- writemsg_level( |
2431 |
- "No ebuilds or cache entries found for '%s'\n" % (cp,), |
2432 |
- level=logging.ERROR, noiselevel=-1) |
2433 |
- |
2434 |
- if dead_nodes: |
2435 |
- dead_nodes.difference_update(self._existing_nodes) |
2436 |
- for k in dead_nodes: |
2437 |
- try: |
2438 |
- del trg_cache[k] |
2439 |
- except KeyError: |
2440 |
- pass |
2441 |
- except CacheError as ce: |
2442 |
- self.returncode |= 1 |
2443 |
- writemsg_level( |
2444 |
- "%s deleting stale cache: %s\n" % (k, ce), |
2445 |
- level=logging.ERROR, noiselevel=-1) |
2446 |
- |
2447 |
- if not trg_cache.autocommits: |
2448 |
- try: |
2449 |
- trg_cache.commit() |
2450 |
- except CacheError as ce: |
2451 |
- self.returncode |= 1 |
2452 |
- writemsg_level( |
2453 |
- "committing target: %s\n" % (ce,), |
2454 |
- level=logging.ERROR, noiselevel=-1) |
2455 |
- |
2456 |
- if hasattr(trg_cache, '_prune_empty_dirs'): |
2457 |
- trg_cache._prune_empty_dirs() |
2458 |
+ def __init__( |
2459 |
+ self, |
2460 |
+ portdb, |
2461 |
+ cp_iter=None, |
2462 |
+ max_jobs=None, |
2463 |
+ max_load=None, |
2464 |
+ rsync=False, |
2465 |
+ external_cache_only=False, |
2466 |
+ ): |
2467 |
+ # The caller must set portdb.porttrees in order to constrain |
2468 |
+ # findname, cp_list, and cpv_list to the desired tree. |
2469 |
+ tree = portdb.porttrees[0] |
2470 |
+ self._portdb = portdb |
2471 |
+ self._eclass_db = portdb.repositories.get_repo_for_location(tree).eclass_db |
2472 |
+ self._auxdbkeys = portdb._known_keys |
2473 |
+ # We can globally cleanse stale cache only if we |
2474 |
+ # iterate over every single cp. |
2475 |
+ self._global_cleanse = cp_iter is None |
2476 |
+ if cp_iter is not None: |
2477 |
+ self._cp_set = set(cp_iter) |
2478 |
+ cp_iter = iter(self._cp_set) |
2479 |
+ self._cp_missing = self._cp_set.copy() |
2480 |
+ else: |
2481 |
+ self._cp_set = None |
2482 |
+ self._cp_missing = set() |
2483 |
+ write_auxdb = ( |
2484 |
+ external_cache_only or "metadata-transfer" in portdb.settings.features |
2485 |
+ ) |
2486 |
+ self._regen = MetadataRegen( |
2487 |
+ portdb, |
2488 |
+ cp_iter=cp_iter, |
2489 |
+ consumer=self._metadata_callback, |
2490 |
+ max_jobs=max_jobs, |
2491 |
+ max_load=max_load, |
2492 |
+ write_auxdb=write_auxdb, |
2493 |
+ main=True, |
2494 |
+ ) |
2495 |
+ self.returncode = os.EX_OK |
2496 |
+ conf = portdb.repositories.get_repo_for_location(tree) |
2497 |
+ if external_cache_only: |
2498 |
+ self._trg_caches = () |
2499 |
+ else: |
2500 |
+ self._trg_caches = tuple( |
2501 |
+ conf.iter_pregenerated_caches( |
2502 |
+ self._auxdbkeys, force=True, readonly=False |
2503 |
+ ) |
2504 |
+ ) |
2505 |
+ if not self._trg_caches: |
2506 |
+ raise Exception( |
2507 |
+ "cache formats '%s' aren't supported" |
2508 |
+ % (" ".join(conf.cache_formats),) |
2509 |
+ ) |
2510 |
+ |
2511 |
+ if rsync: |
2512 |
+ for trg_cache in self._trg_caches: |
2513 |
+ if hasattr(trg_cache, "raise_stat_collision"): |
2514 |
+ trg_cache.raise_stat_collision = True |
2515 |
+ # Make _metadata_callback write this cache first, in case |
2516 |
+ # it raises a StatCollision and triggers mtime |
2517 |
+ # modification. |
2518 |
+ self._trg_caches = tuple( |
2519 |
+ [trg_cache] |
2520 |
+ + [x for x in self._trg_caches if x is not trg_cache] |
2521 |
+ ) |
2522 |
+ |
2523 |
+ self._existing_nodes = set() |
2524 |
+ |
2525 |
+ def _metadata_callback(self, cpv, repo_path, metadata, ebuild_hash, eapi_supported): |
2526 |
+ self._existing_nodes.add(cpv) |
2527 |
+ self._cp_missing.discard(cpv_getkey(cpv)) |
2528 |
+ |
2529 |
+ # Since we're supposed to be able to efficiently obtain the |
2530 |
+ # EAPI from _parse_eapi_ebuild_head, we don't write cache |
2531 |
+ # entries for unsupported EAPIs. |
2532 |
+ if metadata is not None and eapi_supported: |
2533 |
+ for trg_cache in self._trg_caches: |
2534 |
+ self._write_cache(trg_cache, cpv, repo_path, metadata, ebuild_hash) |
2535 |
+ |
2536 |
+ def _write_cache(self, trg_cache, cpv, repo_path, metadata, ebuild_hash): |
2537 |
+ |
2538 |
+ if not hasattr(trg_cache, "raise_stat_collision"): |
2539 |
+ # This cache does not avoid redundant writes automatically, |
2540 |
+ # so check for an identical existing entry before writing. |
2541 |
+ # This prevents unnecessary disk writes and can also prevent |
2542 |
+ # unnecessary rsync transfers. |
2543 |
+ try: |
2544 |
+ dest = trg_cache[cpv] |
2545 |
+ except (KeyError, CacheError): |
2546 |
+ pass |
2547 |
+ else: |
2548 |
+ if trg_cache.validate_entry(dest, ebuild_hash, self._eclass_db): |
2549 |
+ identical = True |
2550 |
+ for k in self._auxdbkeys: |
2551 |
+ if dest.get(k, "") != metadata.get(k, ""): |
2552 |
+ identical = False |
2553 |
+ break |
2554 |
+ if identical: |
2555 |
+ return |
2556 |
+ |
2557 |
+ try: |
2558 |
+ chf = trg_cache.validation_chf |
2559 |
+ metadata["_%s_" % chf] = getattr(ebuild_hash, chf) |
2560 |
+ try: |
2561 |
+ trg_cache[cpv] = metadata |
2562 |
+ except StatCollision as sc: |
2563 |
+ # If the content of a cache entry changes and neither the |
2564 |
+ # file mtime nor size changes, it will prevent rsync from |
2565 |
+ # detecting changes. Cache backends may raise this |
2566 |
+ # exception from _setitem() if they detect this type of stat |
2567 |
+ # collision. These exceptions are handled by bumping the |
2568 |
+ # mtime on the ebuild (and the corresponding cache entry). |
2569 |
+ # See bug #139134. It is convenient to include checks for |
2570 |
+ # redundant writes along with the internal StatCollision |
2571 |
+ # detection code, so for caches with the |
2572 |
+ # raise_stat_collision attribute, we do not need to |
2573 |
+ # explicitly check for redundant writes like we do for the |
2574 |
+ # other cache types above. |
2575 |
+ max_mtime = sc.mtime |
2576 |
+ for _ec, ec_hash in metadata["_eclasses_"].items(): |
2577 |
+ if max_mtime < ec_hash.mtime: |
2578 |
+ max_mtime = ec_hash.mtime |
2579 |
+ if max_mtime == sc.mtime: |
2580 |
+ max_mtime += 1 |
2581 |
+ max_mtime = int(max_mtime) |
2582 |
+ try: |
2583 |
+ os.utime(ebuild_hash.location, (max_mtime, max_mtime)) |
2584 |
+ except OSError as e: |
2585 |
+ self.returncode |= 1 |
2586 |
+ writemsg_level( |
2587 |
+ "%s writing target: %s\n" % (cpv, e), |
2588 |
+ level=logging.ERROR, |
2589 |
+ noiselevel=-1, |
2590 |
+ ) |
2591 |
+ else: |
2592 |
+ ebuild_hash.mtime = max_mtime |
2593 |
+ metadata["_mtime_"] = max_mtime |
2594 |
+ trg_cache[cpv] = metadata |
2595 |
+ self._portdb.auxdb[repo_path][cpv] = metadata |
2596 |
+ |
2597 |
+ except CacheError as ce: |
2598 |
+ self.returncode |= 1 |
2599 |
+ writemsg_level( |
2600 |
+ "%s writing target: %s\n" % (cpv, ce), |
2601 |
+ level=logging.ERROR, |
2602 |
+ noiselevel=-1, |
2603 |
+ ) |
2604 |
+ |
2605 |
+ def run(self): |
2606 |
+ signum = run_main_scheduler(self._regen) |
2607 |
+ if signum is not None: |
2608 |
+ sys.exit(128 + signum) |
2609 |
+ |
2610 |
+ self.returncode |= self._regen.returncode |
2611 |
+ |
2612 |
+ for trg_cache in self._trg_caches: |
2613 |
+ self._cleanse_cache(trg_cache) |
2614 |
+ |
2615 |
+ def _cleanse_cache(self, trg_cache): |
2616 |
+ cp_missing = self._cp_missing |
2617 |
+ dead_nodes = set() |
2618 |
+ if self._global_cleanse: |
2619 |
+ try: |
2620 |
+ for cpv in trg_cache: |
2621 |
+ cp = cpv_getkey(cpv) |
2622 |
+ if cp is None: |
2623 |
+ self.returncode |= 1 |
2624 |
+ writemsg_level( |
2625 |
+ "Unable to parse cp for '%s'\n" % (cpv,), |
2626 |
+ level=logging.ERROR, |
2627 |
+ noiselevel=-1, |
2628 |
+ ) |
2629 |
+ else: |
2630 |
+ dead_nodes.add(cpv) |
2631 |
+ except CacheError as ce: |
2632 |
+ self.returncode |= 1 |
2633 |
+ writemsg_level( |
2634 |
+ "Error listing cache entries for " |
2635 |
+ + "'%s': %s, continuing...\n" % (trg_cache.location, ce), |
2636 |
+ level=logging.ERROR, |
2637 |
+ noiselevel=-1, |
2638 |
+ ) |
2639 |
+ |
2640 |
+ else: |
2641 |
+ cp_set = self._cp_set |
2642 |
+ try: |
2643 |
+ for cpv in trg_cache: |
2644 |
+ cp = cpv_getkey(cpv) |
2645 |
+ if cp is None: |
2646 |
+ self.returncode |= 1 |
2647 |
+ writemsg_level( |
2648 |
+ "Unable to parse cp for '%s'\n" % (cpv,), |
2649 |
+ level=logging.ERROR, |
2650 |
+ noiselevel=-1, |
2651 |
+ ) |
2652 |
+ else: |
2653 |
+ cp_missing.discard(cp) |
2654 |
+ if cp in cp_set: |
2655 |
+ dead_nodes.add(cpv) |
2656 |
+ except CacheError as ce: |
2657 |
+ self.returncode |= 1 |
2658 |
+ writemsg_level( |
2659 |
+ "Error listing cache entries for " |
2660 |
+ + "'%s': %s, continuing...\n" % (trg_cache.location, ce), |
2661 |
+ level=logging.ERROR, |
2662 |
+ noiselevel=-1, |
2663 |
+ ) |
2664 |
+ |
2665 |
+ if cp_missing: |
2666 |
+ self.returncode |= 1 |
2667 |
+ for cp in sorted(cp_missing): |
2668 |
+ writemsg_level( |
2669 |
+ "No ebuilds or cache entries found for '%s'\n" % (cp,), |
2670 |
+ level=logging.ERROR, |
2671 |
+ noiselevel=-1, |
2672 |
+ ) |
2673 |
+ |
2674 |
+ if dead_nodes: |
2675 |
+ dead_nodes.difference_update(self._existing_nodes) |
2676 |
+ for k in dead_nodes: |
2677 |
+ try: |
2678 |
+ del trg_cache[k] |
2679 |
+ except KeyError: |
2680 |
+ pass |
2681 |
+ except CacheError as ce: |
2682 |
+ self.returncode |= 1 |
2683 |
+ writemsg_level( |
2684 |
+ "%s deleting stale cache: %s\n" % (k, ce), |
2685 |
+ level=logging.ERROR, |
2686 |
+ noiselevel=-1, |
2687 |
+ ) |
2688 |
+ |
2689 |
+ if not trg_cache.autocommits: |
2690 |
+ try: |
2691 |
+ trg_cache.commit() |
2692 |
+ except CacheError as ce: |
2693 |
+ self.returncode |= 1 |
2694 |
+ writemsg_level( |
2695 |
+ "committing target: %s\n" % (ce,), |
2696 |
+ level=logging.ERROR, |
2697 |
+ noiselevel=-1, |
2698 |
+ ) |
2699 |
+ |
2700 |
+ if hasattr(trg_cache, "_prune_empty_dirs"): |
2701 |
+ trg_cache._prune_empty_dirs() |
2702 |
+ |
2703 |
|
2704 |
class GenPkgDescIndex: |
2705 |
- def __init__(self, repo_config, portdb, output_file, verbose=False): |
2706 |
- self.returncode = os.EX_OK |
2707 |
- self._repo_config = repo_config |
2708 |
- self._portdb = portdb |
2709 |
- self._output_file = output_file |
2710 |
- self._verbose = verbose |
2711 |
- |
2712 |
- def run(self): |
2713 |
- |
2714 |
- display_updates = self._verbose > 0 |
2715 |
- old = {} |
2716 |
- new = {} |
2717 |
- if display_updates: |
2718 |
- try: |
2719 |
- with open(self._output_file, 'rt', encoding=_encodings["repo.content"]) as f: |
2720 |
- for line in f: |
2721 |
- pkg_desc = pkg_desc_index_line_read(line) |
2722 |
- old[pkg_desc.cp] = pkg_desc |
2723 |
- except FileNotFoundError: |
2724 |
- pass |
2725 |
- |
2726 |
- portage.util.ensure_dirs(os.path.dirname(self._output_file)) |
2727 |
- f = portage.util.atomic_ofstream(self._output_file, |
2728 |
- encoding=_encodings["repo.content"]) |
2729 |
- |
2730 |
- portdb = self._portdb |
2731 |
- for cp in portdb.cp_all(): |
2732 |
- pkgs = portdb.cp_list(cp) |
2733 |
- if not pkgs: |
2734 |
- continue |
2735 |
- desc, = portdb.aux_get(pkgs[-1], ["DESCRIPTION"]) |
2736 |
- |
2737 |
- line = pkg_desc_index_line_format(cp, pkgs, desc) |
2738 |
- f.write(line) |
2739 |
- if display_updates: |
2740 |
- new[cp] = pkg_desc_index_line_read(line) |
2741 |
- |
2742 |
- f.close() |
2743 |
- |
2744 |
- if display_updates: |
2745 |
- out = EOutput() |
2746 |
- out.einfo("Searching for changes") |
2747 |
- print("") |
2748 |
- items = sorted(new.values(), key=lambda pkg_desc: pkg_desc.cp) |
2749 |
- haspkgs = False |
2750 |
- for pkg_desc in items: |
2751 |
- masked = False |
2752 |
- version = self._portdb.xmatch("bestmatch-visible", |
2753 |
- Atom("{}{}{}".format(pkg_desc.cp, _repo_separator, self._repo_config.name))) |
2754 |
- if not version: |
2755 |
- version = pkg_desc.cpv_list[-1] |
2756 |
- masked = True |
2757 |
- old_versions = old.get(pkg_desc.cp) |
2758 |
- if old_versions is None or version not in old_versions.cpv_list: |
2759 |
- prefix0 = " " |
2760 |
- prefix1 = " " |
2761 |
- |
2762 |
- if old_versions is None: |
2763 |
- color = functools.partial(colorize, "darkgreen") |
2764 |
- prefix1 = "N" |
2765 |
- else: |
2766 |
- color = functools.partial(colorize, "turquoise") |
2767 |
- prefix1 = "U" |
2768 |
- |
2769 |
- if masked: |
2770 |
- prefix0 = "M" |
2771 |
- |
2772 |
- print(" [%s%s] %s (%s): %s" % ( |
2773 |
- colorize("red", prefix0), |
2774 |
- color(prefix1), |
2775 |
- colorize("bold", pkg_desc.cp), |
2776 |
- color(version[len(pkg_desc.cp)+1:]), |
2777 |
- pkg_desc.desc)) |
2778 |
- haspkgs = True |
2779 |
- |
2780 |
- if not haspkgs: |
2781 |
- out.einfo("No updates found") |
2782 |
+ def __init__(self, repo_config, portdb, output_file, verbose=False): |
2783 |
+ self.returncode = os.EX_OK |
2784 |
+ self._repo_config = repo_config |
2785 |
+ self._portdb = portdb |
2786 |
+ self._output_file = output_file |
2787 |
+ self._verbose = verbose |
2788 |
+ |
2789 |
+ def run(self): |
2790 |
+ |
2791 |
+ display_updates = self._verbose > 0 |
2792 |
+ old = {} |
2793 |
+ new = {} |
2794 |
+ if display_updates: |
2795 |
+ try: |
2796 |
+ with open( |
2797 |
+ self._output_file, "rt", encoding=_encodings["repo.content"] |
2798 |
+ ) as f: |
2799 |
+ for line in f: |
2800 |
+ pkg_desc = pkg_desc_index_line_read(line) |
2801 |
+ old[pkg_desc.cp] = pkg_desc |
2802 |
+ except FileNotFoundError: |
2803 |
+ pass |
2804 |
+ |
2805 |
+ portage.util.ensure_dirs(os.path.dirname(self._output_file)) |
2806 |
+ f = portage.util.atomic_ofstream( |
2807 |
+ self._output_file, encoding=_encodings["repo.content"] |
2808 |
+ ) |
2809 |
+ |
2810 |
+ portdb = self._portdb |
2811 |
+ for cp in portdb.cp_all(): |
2812 |
+ pkgs = portdb.cp_list(cp) |
2813 |
+ if not pkgs: |
2814 |
+ continue |
2815 |
+ (desc,) = portdb.aux_get(pkgs[-1], ["DESCRIPTION"]) |
2816 |
+ |
2817 |
+ line = pkg_desc_index_line_format(cp, pkgs, desc) |
2818 |
+ f.write(line) |
2819 |
+ if display_updates: |
2820 |
+ new[cp] = pkg_desc_index_line_read(line) |
2821 |
+ |
2822 |
+ f.close() |
2823 |
+ |
2824 |
+ if display_updates: |
2825 |
+ out = EOutput() |
2826 |
+ out.einfo("Searching for changes") |
2827 |
+ print("") |
2828 |
+ items = sorted(new.values(), key=lambda pkg_desc: pkg_desc.cp) |
2829 |
+ haspkgs = False |
2830 |
+ for pkg_desc in items: |
2831 |
+ masked = False |
2832 |
+ version = self._portdb.xmatch( |
2833 |
+ "bestmatch-visible", |
2834 |
+ Atom( |
2835 |
+ "{}{}{}".format( |
2836 |
+ pkg_desc.cp, _repo_separator, self._repo_config.name |
2837 |
+ ) |
2838 |
+ ), |
2839 |
+ ) |
2840 |
+ if not version: |
2841 |
+ version = pkg_desc.cpv_list[-1] |
2842 |
+ masked = True |
2843 |
+ old_versions = old.get(pkg_desc.cp) |
2844 |
+ if old_versions is None or version not in old_versions.cpv_list: |
2845 |
+ prefix0 = " " |
2846 |
+ prefix1 = " " |
2847 |
+ |
2848 |
+ if old_versions is None: |
2849 |
+ color = functools.partial(colorize, "darkgreen") |
2850 |
+ prefix1 = "N" |
2851 |
+ else: |
2852 |
+ color = functools.partial(colorize, "turquoise") |
2853 |
+ prefix1 = "U" |
2854 |
+ |
2855 |
+ if masked: |
2856 |
+ prefix0 = "M" |
2857 |
+ |
2858 |
+ print( |
2859 |
+ " [%s%s] %s (%s): %s" |
2860 |
+ % ( |
2861 |
+ colorize("red", prefix0), |
2862 |
+ color(prefix1), |
2863 |
+ colorize("bold", pkg_desc.cp), |
2864 |
+ color(version[len(pkg_desc.cp) + 1 :]), |
2865 |
+ pkg_desc.desc, |
2866 |
+ ) |
2867 |
+ ) |
2868 |
+ haspkgs = True |
2869 |
+ |
2870 |
+ if not haspkgs: |
2871 |
+ out.einfo("No updates found") |
2872 |
+ |
2873 |
|
2874 |
class GenUseLocalDesc: |
2875 |
- def __init__(self, portdb, output=None, |
2876 |
- preserve_comments=False): |
2877 |
- self.returncode = os.EX_OK |
2878 |
- self._portdb = portdb |
2879 |
- self._output = output |
2880 |
- self._preserve_comments = preserve_comments |
2881 |
- |
2882 |
- def run(self): |
2883 |
- repo_path = self._portdb.porttrees[0] |
2884 |
- ops = {'<':0, '<=':1, '=':2, '>=':3, '>':4} |
2885 |
- prev_mtime = None |
2886 |
- prev_md5 = None |
2887 |
- |
2888 |
- if self._output is None or self._output != '-': |
2889 |
- if self._output is None: |
2890 |
- prof_path = os.path.join(repo_path, 'profiles') |
2891 |
- desc_path = os.path.join(prof_path, 'use.local.desc') |
2892 |
- try: |
2893 |
- os.mkdir(prof_path) |
2894 |
- except OSError: |
2895 |
- pass |
2896 |
- else: |
2897 |
- desc_path = self._output |
2898 |
- |
2899 |
- try: |
2900 |
- prev_md5 = portage.checksum.perform_md5(desc_path) |
2901 |
- prev_mtime = os.stat(desc_path)[stat.ST_MTIME] |
2902 |
- except (portage.exception.FileNotFound, OSError): |
2903 |
- pass |
2904 |
- |
2905 |
- try: |
2906 |
- if self._preserve_comments: |
2907 |
- # Probe in binary mode, in order to avoid |
2908 |
- # potential character encoding issues. |
2909 |
- output = open(_unicode_encode(desc_path, |
2910 |
- encoding=_encodings['fs'], errors='strict'), 'r+b') |
2911 |
- else: |
2912 |
- output = io.open(_unicode_encode(desc_path, |
2913 |
- encoding=_encodings['fs'], errors='strict'), |
2914 |
- mode='w', encoding=_encodings['repo.content'], |
2915 |
- errors='backslashreplace') |
2916 |
- except IOError as e: |
2917 |
- if not self._preserve_comments or \ |
2918 |
- os.path.isfile(desc_path): |
2919 |
- writemsg_level( |
2920 |
- "ERROR: failed to open output file %s: %s\n" \ |
2921 |
- % (desc_path, e), level=logging.ERROR, noiselevel=-1) |
2922 |
- self.returncode |= 2 |
2923 |
- return |
2924 |
- |
2925 |
- # Open in r+b mode failed because the file doesn't |
2926 |
- # exist yet. We can probably recover if we disable |
2927 |
- # preserve_comments mode now. |
2928 |
- writemsg_level( |
2929 |
- "WARNING: --preserve-comments enabled, but " + \ |
2930 |
- "output file not found: %s\n" % (desc_path,), |
2931 |
- level=logging.WARNING, noiselevel=-1) |
2932 |
- self._preserve_comments = False |
2933 |
- try: |
2934 |
- output = io.open(_unicode_encode(desc_path, |
2935 |
- encoding=_encodings['fs'], errors='strict'), |
2936 |
- mode='w', encoding=_encodings['repo.content'], |
2937 |
- errors='backslashreplace') |
2938 |
- except IOError as e: |
2939 |
- writemsg_level( |
2940 |
- "ERROR: failed to open output file %s: %s\n" \ |
2941 |
- % (desc_path, e), level=logging.ERROR, noiselevel=-1) |
2942 |
- self.returncode |= 2 |
2943 |
- return |
2944 |
- else: |
2945 |
- output = sys.stdout |
2946 |
- |
2947 |
- if self._preserve_comments: |
2948 |
- while True: |
2949 |
- pos = output.tell() |
2950 |
- if not output.readline().startswith(b'#'): |
2951 |
- break |
2952 |
- output.seek(pos) |
2953 |
- output.truncate() |
2954 |
- output.close() |
2955 |
- |
2956 |
- # Finished probing comments in binary mode, now append |
2957 |
- # in text mode. |
2958 |
- output = io.open(_unicode_encode(desc_path, |
2959 |
- encoding=_encodings['fs'], errors='strict'), |
2960 |
- mode='a', encoding=_encodings['repo.content'], |
2961 |
- errors='backslashreplace') |
2962 |
- output.write('\n') |
2963 |
- else: |
2964 |
- output.write(textwrap.dedent('''\ |
2965 |
+ def __init__(self, portdb, output=None, preserve_comments=False): |
2966 |
+ self.returncode = os.EX_OK |
2967 |
+ self._portdb = portdb |
2968 |
+ self._output = output |
2969 |
+ self._preserve_comments = preserve_comments |
2970 |
+ |
2971 |
+ def run(self): |
2972 |
+ repo_path = self._portdb.porttrees[0] |
2973 |
+ ops = {"<": 0, "<=": 1, "=": 2, ">=": 3, ">": 4} |
2974 |
+ prev_mtime = None |
2975 |
+ prev_md5 = None |
2976 |
+ |
2977 |
+ if self._output is None or self._output != "-": |
2978 |
+ if self._output is None: |
2979 |
+ prof_path = os.path.join(repo_path, "profiles") |
2980 |
+ desc_path = os.path.join(prof_path, "use.local.desc") |
2981 |
+ try: |
2982 |
+ os.mkdir(prof_path) |
2983 |
+ except OSError: |
2984 |
+ pass |
2985 |
+ else: |
2986 |
+ desc_path = self._output |
2987 |
+ |
2988 |
+ try: |
2989 |
+ prev_md5 = portage.checksum.perform_md5(desc_path) |
2990 |
+ prev_mtime = os.stat(desc_path)[stat.ST_MTIME] |
2991 |
+ except (portage.exception.FileNotFound, OSError): |
2992 |
+ pass |
2993 |
+ |
2994 |
+ try: |
2995 |
+ if self._preserve_comments: |
2996 |
+ # Probe in binary mode, in order to avoid |
2997 |
+ # potential character encoding issues. |
2998 |
+ output = open( |
2999 |
+ _unicode_encode( |
3000 |
+ desc_path, encoding=_encodings["fs"], errors="strict" |
3001 |
+ ), |
3002 |
+ "r+b", |
3003 |
+ ) |
3004 |
+ else: |
3005 |
+ output = io.open( |
3006 |
+ _unicode_encode( |
3007 |
+ desc_path, encoding=_encodings["fs"], errors="strict" |
3008 |
+ ), |
3009 |
+ mode="w", |
3010 |
+ encoding=_encodings["repo.content"], |
3011 |
+ errors="backslashreplace", |
3012 |
+ ) |
3013 |
+ except IOError as e: |
3014 |
+ if not self._preserve_comments or os.path.isfile(desc_path): |
3015 |
+ writemsg_level( |
3016 |
+ "ERROR: failed to open output file %s: %s\n" % (desc_path, e), |
3017 |
+ level=logging.ERROR, |
3018 |
+ noiselevel=-1, |
3019 |
+ ) |
3020 |
+ self.returncode |= 2 |
3021 |
+ return |
3022 |
+ |
3023 |
+ # Open in r+b mode failed because the file doesn't |
3024 |
+ # exist yet. We can probably recover if we disable |
3025 |
+ # preserve_comments mode now. |
3026 |
+ writemsg_level( |
3027 |
+ "WARNING: --preserve-comments enabled, but " |
3028 |
+ + "output file not found: %s\n" % (desc_path,), |
3029 |
+ level=logging.WARNING, |
3030 |
+ noiselevel=-1, |
3031 |
+ ) |
3032 |
+ self._preserve_comments = False |
3033 |
+ try: |
3034 |
+ output = io.open( |
3035 |
+ _unicode_encode( |
3036 |
+ desc_path, encoding=_encodings["fs"], errors="strict" |
3037 |
+ ), |
3038 |
+ mode="w", |
3039 |
+ encoding=_encodings["repo.content"], |
3040 |
+ errors="backslashreplace", |
3041 |
+ ) |
3042 |
+ except IOError as e: |
3043 |
+ writemsg_level( |
3044 |
+ "ERROR: failed to open output file %s: %s\n" % (desc_path, e), |
3045 |
+ level=logging.ERROR, |
3046 |
+ noiselevel=-1, |
3047 |
+ ) |
3048 |
+ self.returncode |= 2 |
3049 |
+ return |
3050 |
+ else: |
3051 |
+ output = sys.stdout |
3052 |
+ |
3053 |
+ if self._preserve_comments: |
3054 |
+ while True: |
3055 |
+ pos = output.tell() |
3056 |
+ if not output.readline().startswith(b"#"): |
3057 |
+ break |
3058 |
+ output.seek(pos) |
3059 |
+ output.truncate() |
3060 |
+ output.close() |
3061 |
+ |
3062 |
+ # Finished probing comments in binary mode, now append |
3063 |
+ # in text mode. |
3064 |
+ output = io.open( |
3065 |
+ _unicode_encode(desc_path, encoding=_encodings["fs"], errors="strict"), |
3066 |
+ mode="a", |
3067 |
+ encoding=_encodings["repo.content"], |
3068 |
+ errors="backslashreplace", |
3069 |
+ ) |
3070 |
+ output.write("\n") |
3071 |
+ else: |
3072 |
+ output.write( |
3073 |
+ textwrap.dedent( |
3074 |
+ """\ |
3075 |
# This file is deprecated as per GLEP 56 in favor of metadata.xml. Please add |
3076 |
# your descriptions to your package's metadata.xml ONLY. |
3077 |
# * generated automatically using egencache * |
3078 |
|
3079 |
- ''')) |
3080 |
- |
3081 |
- # The cmp function no longer exists in python3, so we'll |
3082 |
- # implement our own here under a slightly different name |
3083 |
- # since we don't want any confusion given that we never |
3084 |
- # want to rely on the builtin cmp function. |
3085 |
- def cmp_func(a, b): |
3086 |
- if a is None or b is None: |
3087 |
- # None can't be compared with other types in python3. |
3088 |
- if a is None and b is None: |
3089 |
- return 0 |
3090 |
- elif a is None: |
3091 |
- return -1 |
3092 |
- else: |
3093 |
- return 1 |
3094 |
- return (a > b) - (a < b) |
3095 |
- |
3096 |
- class _MetadataTreeBuilder(ElementTree.TreeBuilder): |
3097 |
- """ |
3098 |
- Implements doctype() as required to avoid deprecation warnings |
3099 |
- since Python >=2.7 |
3100 |
- """ |
3101 |
- def doctype(self, name, pubid, system): |
3102 |
- pass |
3103 |
- |
3104 |
- for cp in self._portdb.cp_all(): |
3105 |
- metadata_path = os.path.join(repo_path, cp, 'metadata.xml') |
3106 |
- try: |
3107 |
- metadata = ElementTree.parse(_unicode_encode(metadata_path, |
3108 |
- encoding=_encodings['fs'], errors='strict'), |
3109 |
- parser=ElementTree.XMLParser( |
3110 |
- target=_MetadataTreeBuilder())) |
3111 |
- except IOError: |
3112 |
- pass |
3113 |
- except (ExpatError, EnvironmentError) as e: |
3114 |
- writemsg_level( |
3115 |
- "ERROR: failed parsing %s/metadata.xml: %s\n" % (cp, e), |
3116 |
- level=logging.ERROR, noiselevel=-1) |
3117 |
- self.returncode |= 1 |
3118 |
- else: |
3119 |
- try: |
3120 |
- usedict = parse_metadata_use(metadata) |
3121 |
- except portage.exception.ParseError as e: |
3122 |
- writemsg_level( |
3123 |
- "ERROR: failed parsing %s/metadata.xml: %s\n" % (cp, e), |
3124 |
- level=logging.ERROR, noiselevel=-1) |
3125 |
- self.returncode |= 1 |
3126 |
- else: |
3127 |
- for flag in sorted(usedict): |
3128 |
- def atomcmp(atoma, atomb): |
3129 |
- # None is better than an atom, that's why we reverse the args |
3130 |
- if atoma is None or atomb is None: |
3131 |
- return cmp_func(atomb, atoma) |
3132 |
- # Same for plain PNs (.operator is None then) |
3133 |
- elif atoma.operator is None or atomb.operator is None: |
3134 |
- return cmp_func(atomb.operator, atoma.operator) |
3135 |
- # Version matching |
3136 |
- elif atoma.cpv != atomb.cpv: |
3137 |
- return vercmp(atoma.version, atomb.version) |
3138 |
- # Versions match, let's fallback to operator matching |
3139 |
- else: |
3140 |
- return cmp_func(ops.get(atoma.operator, -1), |
3141 |
- ops.get(atomb.operator, -1)) |
3142 |
- |
3143 |
- def _Atom(key): |
3144 |
- if key is not None: |
3145 |
- return Atom(key) |
3146 |
- return None |
3147 |
- |
3148 |
- resdict = usedict[flag] |
3149 |
- if len(resdict) == 1: |
3150 |
- resdesc = next(iter(resdict.items()))[1] |
3151 |
- else: |
3152 |
- try: |
3153 |
- reskeys = dict((_Atom(k), k) for k in resdict) |
3154 |
- except portage.exception.InvalidAtom as e: |
3155 |
- writemsg_level( |
3156 |
- "ERROR: failed parsing %s/metadata.xml: %s\n" % (cp, e), |
3157 |
- level=logging.ERROR, noiselevel=-1) |
3158 |
- self.returncode |= 1 |
3159 |
- resdesc = next(iter(resdict.items()))[1] |
3160 |
- else: |
3161 |
- resatoms = sorted(reskeys, key=cmp_sort_key(atomcmp)) |
3162 |
- resdesc = resdict[reskeys[resatoms[-1]]] |
3163 |
- |
3164 |
- output.write('%s:%s - %s\n' % (cp, flag, resdesc)) |
3165 |
- |
3166 |
- output.close() |
3167 |
- if (prev_mtime is not None and |
3168 |
- prev_md5 == portage.checksum.perform_md5(desc_path)): |
3169 |
- # Preserve mtime for rsync. |
3170 |
- mtime = prev_mtime |
3171 |
- else: |
3172 |
- # For portability, and consistency with the mtime preservation |
3173 |
- # code, set mtime to an exact integer value. |
3174 |
- mtime = int(time.time()) |
3175 |
- |
3176 |
- os.utime(desc_path, (mtime, mtime)) |
3177 |
+ """ |
3178 |
+ ) |
3179 |
+ ) |
3180 |
+ |
3181 |
+ # The cmp function no longer exists in python3, so we'll |
3182 |
+ # implement our own here under a slightly different name |
3183 |
+ # since we don't want any confusion given that we never |
3184 |
+ # want to rely on the builtin cmp function. |
3185 |
+ def cmp_func(a, b): |
3186 |
+ if a is None or b is None: |
3187 |
+ # None can't be compared with other types in python3. |
3188 |
+ if a is None and b is None: |
3189 |
+ return 0 |
3190 |
+ elif a is None: |
3191 |
+ return -1 |
3192 |
+ else: |
3193 |
+ return 1 |
3194 |
+ return (a > b) - (a < b) |
3195 |
+ |
3196 |
+ class _MetadataTreeBuilder(ElementTree.TreeBuilder): |
3197 |
+ """ |
3198 |
+ Implements doctype() as required to avoid deprecation warnings |
3199 |
+ since Python >=2.7 |
3200 |
+ """ |
3201 |
+ |
3202 |
+ def doctype(self, name, pubid, system): |
3203 |
+ pass |
3204 |
+ |
3205 |
+ for cp in self._portdb.cp_all(): |
3206 |
+ metadata_path = os.path.join(repo_path, cp, "metadata.xml") |
3207 |
+ try: |
3208 |
+ metadata = ElementTree.parse( |
3209 |
+ _unicode_encode( |
3210 |
+ metadata_path, encoding=_encodings["fs"], errors="strict" |
3211 |
+ ), |
3212 |
+ parser=ElementTree.XMLParser(target=_MetadataTreeBuilder()), |
3213 |
+ ) |
3214 |
+ except IOError: |
3215 |
+ pass |
3216 |
+ except (ExpatError, EnvironmentError) as e: |
3217 |
+ writemsg_level( |
3218 |
+ "ERROR: failed parsing %s/metadata.xml: %s\n" % (cp, e), |
3219 |
+ level=logging.ERROR, |
3220 |
+ noiselevel=-1, |
3221 |
+ ) |
3222 |
+ self.returncode |= 1 |
3223 |
+ else: |
3224 |
+ try: |
3225 |
+ usedict = parse_metadata_use(metadata) |
3226 |
+ except portage.exception.ParseError as e: |
3227 |
+ writemsg_level( |
3228 |
+ "ERROR: failed parsing %s/metadata.xml: %s\n" % (cp, e), |
3229 |
+ level=logging.ERROR, |
3230 |
+ noiselevel=-1, |
3231 |
+ ) |
3232 |
+ self.returncode |= 1 |
3233 |
+ else: |
3234 |
+ for flag in sorted(usedict): |
3235 |
+ |
3236 |
+ def atomcmp(atoma, atomb): |
3237 |
+ # None is better than an atom, that's why we reverse the args |
3238 |
+ if atoma is None or atomb is None: |
3239 |
+ return cmp_func(atomb, atoma) |
3240 |
+ # Same for plain PNs (.operator is None then) |
3241 |
+ elif atoma.operator is None or atomb.operator is None: |
3242 |
+ return cmp_func(atomb.operator, atoma.operator) |
3243 |
+ # Version matching |
3244 |
+ elif atoma.cpv != atomb.cpv: |
3245 |
+ return vercmp(atoma.version, atomb.version) |
3246 |
+ # Versions match, let's fallback to operator matching |
3247 |
+ else: |
3248 |
+ return cmp_func( |
3249 |
+ ops.get(atoma.operator, -1), |
3250 |
+ ops.get(atomb.operator, -1), |
3251 |
+ ) |
3252 |
+ |
3253 |
+ def _Atom(key): |
3254 |
+ if key is not None: |
3255 |
+ return Atom(key) |
3256 |
+ return None |
3257 |
+ |
3258 |
+ resdict = usedict[flag] |
3259 |
+ if len(resdict) == 1: |
3260 |
+ resdesc = next(iter(resdict.items()))[1] |
3261 |
+ else: |
3262 |
+ try: |
3263 |
+ reskeys = dict((_Atom(k), k) for k in resdict) |
3264 |
+ except portage.exception.InvalidAtom as e: |
3265 |
+ writemsg_level( |
3266 |
+ "ERROR: failed parsing %s/metadata.xml: %s\n" |
3267 |
+ % (cp, e), |
3268 |
+ level=logging.ERROR, |
3269 |
+ noiselevel=-1, |
3270 |
+ ) |
3271 |
+ self.returncode |= 1 |
3272 |
+ resdesc = next(iter(resdict.items()))[1] |
3273 |
+ else: |
3274 |
+ resatoms = sorted(reskeys, key=cmp_sort_key(atomcmp)) |
3275 |
+ resdesc = resdict[reskeys[resatoms[-1]]] |
3276 |
+ |
3277 |
+ output.write("%s:%s - %s\n" % (cp, flag, resdesc)) |
3278 |
+ |
3279 |
+ output.close() |
3280 |
+ if prev_mtime is not None and prev_md5 == portage.checksum.perform_md5( |
3281 |
+ desc_path |
3282 |
+ ): |
3283 |
+ # Preserve mtime for rsync. |
3284 |
+ mtime = prev_mtime |
3285 |
+ else: |
3286 |
+ # For portability, and consistency with the mtime preservation |
3287 |
+ # code, set mtime to an exact integer value. |
3288 |
+ mtime = int(time.time()) |
3289 |
+ |
3290 |
+ os.utime(desc_path, (mtime, mtime)) |
3291 |
|
3292 |
|
3293 |
class GenChangeLogs: |
3294 |
- def __init__(self, portdb, changelog_output, changelog_reversed, |
3295 |
- max_jobs=None, max_load=None): |
3296 |
- self.returncode = os.EX_OK |
3297 |
- self._portdb = portdb |
3298 |
- self._wrapper = textwrap.TextWrapper( |
3299 |
- width = 78, |
3300 |
- initial_indent = ' ', |
3301 |
- subsequent_indent = ' ' |
3302 |
- ) |
3303 |
- self._changelog_output = changelog_output |
3304 |
- self._changelog_reversed = changelog_reversed |
3305 |
- self._max_jobs = max_jobs |
3306 |
- self._max_load = max_load |
3307 |
- self._repo_path = self._portdb.porttrees[0] |
3308 |
- # --work-tree=... must be passed to Git if GIT_DIR is used |
3309 |
- # and GIT_DIR is not a child of the root of the checkout |
3310 |
- # eg: |
3311 |
- # GIT_DIR=$parent/work/.git/ |
3312 |
- # work-tree=$parent/staging/ |
3313 |
- # If work-tree is not passed, Git tries to use the shared |
3314 |
- # parent of the current directory and the $GIT_DIR, which can |
3315 |
- # be outside the root of the checkout. |
3316 |
- self._work_tree = '--work-tree=%s' % self._repo_path |
3317 |
- |
3318 |
- @staticmethod |
3319 |
- def grab(cmd): |
3320 |
- p = subprocess.Popen(cmd, stdout=subprocess.PIPE) |
3321 |
- return _unicode_decode(p.communicate()[0], |
3322 |
- encoding=_encodings['stdio'], errors='strict') |
3323 |
- |
3324 |
- def generate_changelog(self, cp): |
3325 |
- |
3326 |
- os.chdir(os.path.join(self._repo_path, cp)) |
3327 |
- # Determine whether ChangeLog is up-to-date by comparing |
3328 |
- # the newest commit timestamp with the ChangeLog timestamp. |
3329 |
- lmod = self.grab(['git', self._work_tree, 'log', '--format=%ct', '-1', '.']) |
3330 |
- if not lmod: |
3331 |
- # This cp has not been added to the repo. |
3332 |
- return |
3333 |
- |
3334 |
- lmod = int(lmod) |
3335 |
- |
3336 |
- try: |
3337 |
- cmod = os.stat('ChangeLog')[stat.ST_MTIME] |
3338 |
- except OSError: |
3339 |
- cmod = 0 |
3340 |
- |
3341 |
- # Use exact comparison, since commit times are |
3342 |
- # not necessarily ordered. |
3343 |
- if cmod == lmod: |
3344 |
- return |
3345 |
- |
3346 |
- try: |
3347 |
- output = io.open(self._changelog_output, |
3348 |
- mode='w', encoding=_encodings['repo.content'], |
3349 |
- errors='backslashreplace') |
3350 |
- except IOError as e: |
3351 |
- writemsg_level( |
3352 |
- "ERROR: failed to open ChangeLog for %s: %s\n" % (cp,e,), |
3353 |
- level=logging.ERROR, noiselevel=-1) |
3354 |
- self.returncode |= 2 |
3355 |
- return |
3356 |
- |
3357 |
- output.write(textwrap.dedent('''\ |
3358 |
+ def __init__( |
3359 |
+ self, portdb, changelog_output, changelog_reversed, max_jobs=None, max_load=None |
3360 |
+ ): |
3361 |
+ self.returncode = os.EX_OK |
3362 |
+ self._portdb = portdb |
3363 |
+ self._wrapper = textwrap.TextWrapper( |
3364 |
+ width=78, initial_indent=" ", subsequent_indent=" " |
3365 |
+ ) |
3366 |
+ self._changelog_output = changelog_output |
3367 |
+ self._changelog_reversed = changelog_reversed |
3368 |
+ self._max_jobs = max_jobs |
3369 |
+ self._max_load = max_load |
3370 |
+ self._repo_path = self._portdb.porttrees[0] |
3371 |
+ # --work-tree=... must be passed to Git if GIT_DIR is used |
3372 |
+ # and GIT_DIR is not a child of the root of the checkout |
3373 |
+ # eg: |
3374 |
+ # GIT_DIR=$parent/work/.git/ |
3375 |
+ # work-tree=$parent/staging/ |
3376 |
+ # If work-tree is not passed, Git tries to use the shared |
3377 |
+ # parent of the current directory and the $GIT_DIR, which can |
3378 |
+ # be outside the root of the checkout. |
3379 |
+ self._work_tree = "--work-tree=%s" % self._repo_path |
3380 |
+ |
3381 |
+ @staticmethod |
3382 |
+ def grab(cmd): |
3383 |
+ p = subprocess.Popen(cmd, stdout=subprocess.PIPE) |
3384 |
+ return _unicode_decode( |
3385 |
+ p.communicate()[0], encoding=_encodings["stdio"], errors="strict" |
3386 |
+ ) |
3387 |
+ |
3388 |
+ def generate_changelog(self, cp): |
3389 |
+ |
3390 |
+ os.chdir(os.path.join(self._repo_path, cp)) |
3391 |
+ # Determine whether ChangeLog is up-to-date by comparing |
3392 |
+ # the newest commit timestamp with the ChangeLog timestamp. |
3393 |
+ lmod = self.grab(["git", self._work_tree, "log", "--format=%ct", "-1", "."]) |
3394 |
+ if not lmod: |
3395 |
+ # This cp has not been added to the repo. |
3396 |
+ return |
3397 |
+ |
3398 |
+ lmod = int(lmod) |
3399 |
+ |
3400 |
+ try: |
3401 |
+ cmod = os.stat("ChangeLog")[stat.ST_MTIME] |
3402 |
+ except OSError: |
3403 |
+ cmod = 0 |
3404 |
+ |
3405 |
+ # Use exact comparison, since commit times are |
3406 |
+ # not necessarily ordered. |
3407 |
+ if cmod == lmod: |
3408 |
+ return |
3409 |
+ |
3410 |
+ try: |
3411 |
+ output = io.open( |
3412 |
+ self._changelog_output, |
3413 |
+ mode="w", |
3414 |
+ encoding=_encodings["repo.content"], |
3415 |
+ errors="backslashreplace", |
3416 |
+ ) |
3417 |
+ except IOError as e: |
3418 |
+ writemsg_level( |
3419 |
+ "ERROR: failed to open ChangeLog for %s: %s\n" |
3420 |
+ % ( |
3421 |
+ cp, |
3422 |
+ e, |
3423 |
+ ), |
3424 |
+ level=logging.ERROR, |
3425 |
+ noiselevel=-1, |
3426 |
+ ) |
3427 |
+ self.returncode |= 2 |
3428 |
+ return |
3429 |
+ |
3430 |
+ output.write( |
3431 |
+ textwrap.dedent( |
3432 |
+ """\ |
3433 |
# ChangeLog for %s |
3434 |
# Copyright 1999-%s Gentoo Foundation; Distributed under the GPL v2 |
3435 |
# (auto-generated from git log) |
3436 |
|
3437 |
- ''' % (cp, time.strftime('%Y')))) |
3438 |
- |
3439 |
- # now grab all the commits |
3440 |
- revlist_cmd = ['git', self._work_tree, 'rev-list'] |
3441 |
- if self._changelog_reversed: |
3442 |
- revlist_cmd.append('--reverse') |
3443 |
- revlist_cmd.extend(['HEAD', '--', '.']) |
3444 |
- commits = self.grab(revlist_cmd).split() |
3445 |
- |
3446 |
- for c in commits: |
3447 |
- # Explaining the arguments: |
3448 |
- # --name-status to get a list of added/removed files |
3449 |
- # --no-renames to avoid getting more complex records on the list |
3450 |
- # --format to get the timestamp, author and commit description |
3451 |
- # --root to make it work fine even with the initial commit |
3452 |
- # --relative=$cp to get paths relative to ebuilddir |
3453 |
- # -r (recursive) to get per-file changes |
3454 |
- # then the commit-id and path. |
3455 |
- |
3456 |
- cinfo = self.grab(['git', self._work_tree, 'diff-tree', |
3457 |
- '--name-status', |
3458 |
- '--no-renames', |
3459 |
- '--format=%ct %cN <%cE>%n%B', |
3460 |
- '--root', |
3461 |
- '--relative=%s' % (cp, ), |
3462 |
- '-r', |
3463 |
- c, '--', '.']).rstrip('\n').split('\n') |
3464 |
- |
3465 |
- # Expected output: |
3466 |
- # timestamp Author Name <author@email> |
3467 |
- # commit message l1 |
3468 |
- # ... |
3469 |
- # commit message ln |
3470 |
- # |
3471 |
- # status1 filename1 |
3472 |
- # ... |
3473 |
- # statusn filenamen |
3474 |
- |
3475 |
- changed = [] |
3476 |
- for n, l in enumerate(reversed(cinfo)): |
3477 |
- if not l: |
3478 |
- body = cinfo[1:-n-1] |
3479 |
- break |
3480 |
- else: |
3481 |
- f = l.split() |
3482 |
- if f[1] == 'Manifest': |
3483 |
- pass # XXX: remanifest commits? |
3484 |
- elif f[1].startswith('ChangeLog'): |
3485 |
- pass |
3486 |
- elif f[0].startswith('A'): |
3487 |
- changed.append(ChangeLogTypeSort("+", f[1])) |
3488 |
- elif f[0].startswith('D'): |
3489 |
- changed.append(ChangeLogTypeSort("-", f[1])) |
3490 |
- elif f[0].startswith('M'): |
3491 |
- changed.append(ChangeLogTypeSort("", f[1])) |
3492 |
- else: |
3493 |
- writemsg_level( |
3494 |
- "ERROR: unexpected git file status for %s: %s\n" % (cp,f,), |
3495 |
- level=logging.ERROR, noiselevel=-1) |
3496 |
- self.returncode |= 1 |
3497 |
- |
3498 |
- if not changed: |
3499 |
- continue |
3500 |
- |
3501 |
- (ts, author) = cinfo[0].split(' ', 1) |
3502 |
- date = time.strftime('%d %b %Y', time.gmtime(float(ts))) |
3503 |
- |
3504 |
- changed = [str(x) for x in sorted(changed)] |
3505 |
- |
3506 |
- wroteheader = False |
3507 |
- # Reverse the sort order for headers. |
3508 |
- for c in reversed(changed): |
3509 |
- if c.startswith('+') and c.endswith('.ebuild'): |
3510 |
- output.write('*%s (%s)\n' % (c[1:-7], date)) |
3511 |
- wroteheader = True |
3512 |
- if wroteheader: |
3513 |
- output.write('\n') |
3514 |
- |
3515 |
- # strip '<cp>: ', '[<cp>] ', and similar |
3516 |
- body[0] = re.sub(r'^\W*' + re.escape(cp) + r'\W+', '', body[0]) |
3517 |
- # strip trailing newline |
3518 |
- if not body[-1]: |
3519 |
- body = body[:-1] |
3520 |
- # strip git-svn id |
3521 |
- if body[-1].startswith('git-svn-id:') and not body[-2]: |
3522 |
- body = body[:-2] |
3523 |
- # strip the repoman version/manifest note |
3524 |
- if body[-1] == ' (Signed Manifest commit)' or body[-1] == ' (Unsigned Manifest commit)': |
3525 |
- body = body[:-1] |
3526 |
- if body[-1].startswith('(Portage version:') and body[-1].endswith(')'): |
3527 |
- body = body[:-1] |
3528 |
- if not body[-1]: |
3529 |
- body = body[:-1] |
3530 |
- |
3531 |
- # don't break filenames on hyphens |
3532 |
- self._wrapper.break_on_hyphens = False |
3533 |
- output.write(self._wrapper.fill( |
3534 |
- '%s; %s %s:' % (date, author, ', '.join(changed)))) |
3535 |
- # but feel free to break commit messages there |
3536 |
- self._wrapper.break_on_hyphens = True |
3537 |
- output.write( |
3538 |
- '\n%s\n\n' % '\n'.join(self._wrapper.fill(x) for x in body)) |
3539 |
- |
3540 |
- output.close() |
3541 |
- os.utime(self._changelog_output, (lmod, lmod)) |
3542 |
- |
3543 |
- def _task_iter(self): |
3544 |
- if not os.path.isdir(os.environ.get('GIT_DIR', os.path.join(self._repo_path, '.git'))): |
3545 |
- writemsg_level( |
3546 |
- "ERROR: --update-changelogs supported only in git repos\n", |
3547 |
- level=logging.ERROR, noiselevel=-1) |
3548 |
- self.returncode = 127 |
3549 |
- return |
3550 |
- |
3551 |
- for cp in self._portdb.cp_all(): |
3552 |
- yield AsyncFunction(target=self.generate_changelog, args=[cp]) |
3553 |
- |
3554 |
- def run(self): |
3555 |
- return run_main_scheduler( |
3556 |
- TaskScheduler(self._task_iter(), event_loop=global_event_loop(), |
3557 |
- max_jobs=self._max_jobs, max_load=self._max_load)) |
3558 |
+ """ |
3559 |
+ % (cp, time.strftime("%Y")) |
3560 |
+ ) |
3561 |
+ ) |
3562 |
+ |
3563 |
+ # now grab all the commits |
3564 |
+ revlist_cmd = ["git", self._work_tree, "rev-list"] |
3565 |
+ if self._changelog_reversed: |
3566 |
+ revlist_cmd.append("--reverse") |
3567 |
+ revlist_cmd.extend(["HEAD", "--", "."]) |
3568 |
+ commits = self.grab(revlist_cmd).split() |
3569 |
+ |
3570 |
+ for c in commits: |
3571 |
+ # Explaining the arguments: |
3572 |
+ # --name-status to get a list of added/removed files |
3573 |
+ # --no-renames to avoid getting more complex records on the list |
3574 |
+ # --format to get the timestamp, author and commit description |
3575 |
+ # --root to make it work fine even with the initial commit |
3576 |
+ # --relative=$cp to get paths relative to ebuilddir |
3577 |
+ # -r (recursive) to get per-file changes |
3578 |
+ # then the commit-id and path. |
3579 |
+ |
3580 |
+ cinfo = ( |
3581 |
+ self.grab( |
3582 |
+ [ |
3583 |
+ "git", |
3584 |
+ self._work_tree, |
3585 |
+ "diff-tree", |
3586 |
+ "--name-status", |
3587 |
+ "--no-renames", |
3588 |
+ "--format=%ct %cN <%cE>%n%B", |
3589 |
+ "--root", |
3590 |
+ "--relative=%s" % (cp,), |
3591 |
+ "-r", |
3592 |
+ c, |
3593 |
+ "--", |
3594 |
+ ".", |
3595 |
+ ] |
3596 |
+ ) |
3597 |
+ .rstrip("\n") |
3598 |
+ .split("\n") |
3599 |
+ ) |
3600 |
+ |
3601 |
+ # Expected output: |
3602 |
+ # timestamp Author Name <author@email> |
3603 |
+ # commit message l1 |
3604 |
+ # ... |
3605 |
+ # commit message ln |
3606 |
+ # |
3607 |
+ # status1 filename1 |
3608 |
+ # ... |
3609 |
+ # statusn filenamen |
3610 |
+ |
3611 |
+ changed = [] |
3612 |
+ for n, l in enumerate(reversed(cinfo)): |
3613 |
+ if not l: |
3614 |
+ body = cinfo[1 : -n - 1] |
3615 |
+ break |
3616 |
+ else: |
3617 |
+ f = l.split() |
3618 |
+ if f[1] == "Manifest": |
3619 |
+ pass # XXX: remanifest commits? |
3620 |
+ elif f[1].startswith("ChangeLog"): |
3621 |
+ pass |
3622 |
+ elif f[0].startswith("A"): |
3623 |
+ changed.append(ChangeLogTypeSort("+", f[1])) |
3624 |
+ elif f[0].startswith("D"): |
3625 |
+ changed.append(ChangeLogTypeSort("-", f[1])) |
3626 |
+ elif f[0].startswith("M"): |
3627 |
+ changed.append(ChangeLogTypeSort("", f[1])) |
3628 |
+ else: |
3629 |
+ writemsg_level( |
3630 |
+ "ERROR: unexpected git file status for %s: %s\n" |
3631 |
+ % ( |
3632 |
+ cp, |
3633 |
+ f, |
3634 |
+ ), |
3635 |
+ level=logging.ERROR, |
3636 |
+ noiselevel=-1, |
3637 |
+ ) |
3638 |
+ self.returncode |= 1 |
3639 |
+ |
3640 |
+ if not changed: |
3641 |
+ continue |
3642 |
+ |
3643 |
+ (ts, author) = cinfo[0].split(" ", 1) |
3644 |
+ date = time.strftime("%d %b %Y", time.gmtime(float(ts))) |
3645 |
+ |
3646 |
+ changed = [str(x) for x in sorted(changed)] |
3647 |
+ |
3648 |
+ wroteheader = False |
3649 |
+ # Reverse the sort order for headers. |
3650 |
+ for c in reversed(changed): |
3651 |
+ if c.startswith("+") and c.endswith(".ebuild"): |
3652 |
+ output.write("*%s (%s)\n" % (c[1:-7], date)) |
3653 |
+ wroteheader = True |
3654 |
+ if wroteheader: |
3655 |
+ output.write("\n") |
3656 |
+ |
3657 |
+ # strip '<cp>: ', '[<cp>] ', and similar |
3658 |
+ body[0] = re.sub(r"^\W*" + re.escape(cp) + r"\W+", "", body[0]) |
3659 |
+ # strip trailing newline |
3660 |
+ if not body[-1]: |
3661 |
+ body = body[:-1] |
3662 |
+ # strip git-svn id |
3663 |
+ if body[-1].startswith("git-svn-id:") and not body[-2]: |
3664 |
+ body = body[:-2] |
3665 |
+ # strip the repoman version/manifest note |
3666 |
+ if ( |
3667 |
+ body[-1] == " (Signed Manifest commit)" |
3668 |
+ or body[-1] == " (Unsigned Manifest commit)" |
3669 |
+ ): |
3670 |
+ body = body[:-1] |
3671 |
+ if body[-1].startswith("(Portage version:") and body[-1].endswith(")"): |
3672 |
+ body = body[:-1] |
3673 |
+ if not body[-1]: |
3674 |
+ body = body[:-1] |
3675 |
+ |
3676 |
+ # don't break filenames on hyphens |
3677 |
+ self._wrapper.break_on_hyphens = False |
3678 |
+ output.write( |
3679 |
+ self._wrapper.fill("%s; %s %s:" % (date, author, ", ".join(changed))) |
3680 |
+ ) |
3681 |
+ # but feel free to break commit messages there |
3682 |
+ self._wrapper.break_on_hyphens = True |
3683 |
+ output.write("\n%s\n\n" % "\n".join(self._wrapper.fill(x) for x in body)) |
3684 |
+ |
3685 |
+ output.close() |
3686 |
+ os.utime(self._changelog_output, (lmod, lmod)) |
3687 |
+ |
3688 |
+ def _task_iter(self): |
3689 |
+ if not os.path.isdir( |
3690 |
+ os.environ.get("GIT_DIR", os.path.join(self._repo_path, ".git")) |
3691 |
+ ): |
3692 |
+ writemsg_level( |
3693 |
+ "ERROR: --update-changelogs supported only in git repos\n", |
3694 |
+ level=logging.ERROR, |
3695 |
+ noiselevel=-1, |
3696 |
+ ) |
3697 |
+ self.returncode = 127 |
3698 |
+ return |
3699 |
+ |
3700 |
+ for cp in self._portdb.cp_all(): |
3701 |
+ yield AsyncFunction(target=self.generate_changelog, args=[cp]) |
3702 |
+ |
3703 |
+ def run(self): |
3704 |
+ return run_main_scheduler( |
3705 |
+ TaskScheduler( |
3706 |
+ self._task_iter(), |
3707 |
+ event_loop=global_event_loop(), |
3708 |
+ max_jobs=self._max_jobs, |
3709 |
+ max_load=self._max_load, |
3710 |
+ ) |
3711 |
+ ) |
3712 |
+ |
3713 |
|
3714 |
def egencache_main(args): |
3715 |
|
3716 |
- # The calling environment is ignored, so the program is |
3717 |
- # completely controlled by commandline arguments. |
3718 |
- env = {} |
3719 |
- |
3720 |
- if (not sys.stdout.isatty() or |
3721 |
- os.environ.get('NOCOLOR', '').lower() in ('yes', 'true')): |
3722 |
- portage.output.nocolor() |
3723 |
- env['NOCOLOR'] = 'true' |
3724 |
+ # The calling environment is ignored, so the program is |
3725 |
+ # completely controlled by commandline arguments. |
3726 |
+ env = {} |
3727 |
+ |
3728 |
+ if not sys.stdout.isatty() or os.environ.get("NOCOLOR", "").lower() in ( |
3729 |
+ "yes", |
3730 |
+ "true", |
3731 |
+ ): |
3732 |
+ portage.output.nocolor() |
3733 |
+ env["NOCOLOR"] = "true" |
3734 |
+ |
3735 |
+ parser, options, atoms = parse_args(args) |
3736 |
+ |
3737 |
+ config_root = options.config_root |
3738 |
+ |
3739 |
+ if options.repositories_configuration is not None: |
3740 |
+ env["PORTAGE_REPOSITORIES"] = options.repositories_configuration |
3741 |
+ |
3742 |
+ if options.cache_dir is not None: |
3743 |
+ env["PORTAGE_DEPCACHEDIR"] = options.cache_dir |
3744 |
+ |
3745 |
+ settings = portage.config(config_root=config_root, local_config=False, env=env) |
3746 |
+ |
3747 |
+ default_opts = None |
3748 |
+ if not options.ignore_default_opts: |
3749 |
+ default_opts = portage.util.shlex_split( |
3750 |
+ settings.get("EGENCACHE_DEFAULT_OPTS", "") |
3751 |
+ ) |
3752 |
+ |
3753 |
+ if default_opts: |
3754 |
+ parser, options, args = parse_args(default_opts + args) |
3755 |
+ |
3756 |
+ if options.cache_dir is not None: |
3757 |
+ env["PORTAGE_DEPCACHEDIR"] = options.cache_dir |
3758 |
+ |
3759 |
+ settings = portage.config(config_root=config_root, local_config=False, env=env) |
3760 |
+ |
3761 |
+ if not ( |
3762 |
+ options.update |
3763 |
+ or options.update_use_local_desc |
3764 |
+ or options.update_changelogs |
3765 |
+ or options.update_manifests |
3766 |
+ or options.update_pkg_desc_index |
3767 |
+ ): |
3768 |
+ parser.error("No action specified") |
3769 |
+ return 1 |
3770 |
+ |
3771 |
+ if options.repo is None: |
3772 |
+ if len(settings.repositories.prepos) == 2: |
3773 |
+ for repo in settings.repositories: |
3774 |
+ if repo.name != "DEFAULT": |
3775 |
+ options.repo = repo.name |
3776 |
+ break |
3777 |
+ |
3778 |
+ if options.repo is None: |
3779 |
+ parser.error("--repo option is required") |
3780 |
+ |
3781 |
+ repo_path = settings.repositories.treemap.get(options.repo) |
3782 |
+ if repo_path is None: |
3783 |
+ parser.error("Unable to locate repository named '%s'" % (options.repo,)) |
3784 |
+ return 1 |
3785 |
+ |
3786 |
+ repo_config = settings.repositories.get_repo_for_location(repo_path) |
3787 |
+ |
3788 |
+ if options.strict_manifests is not None: |
3789 |
+ if options.strict_manifests == "y": |
3790 |
+ settings.features.add("strict") |
3791 |
+ else: |
3792 |
+ settings.features.discard("strict") |
3793 |
+ |
3794 |
+ if options.update and "metadata-transfer" not in settings.features: |
3795 |
+ # Forcibly enable metadata-transfer if portdbapi has a pregenerated |
3796 |
+ # cache that does not support eclass validation. |
3797 |
+ cache = repo_config.get_pregenerated_cache( |
3798 |
+ portage.dbapi.dbapi._known_keys, readonly=True |
3799 |
+ ) |
3800 |
+ if cache is not None and not cache.complete_eclass_entries: |
3801 |
+ settings.features.add("metadata-transfer") |
3802 |
+ cache = None |
3803 |
+ |
3804 |
+ settings.lock() |
3805 |
+ |
3806 |
+ portdb = portage.portdbapi(mysettings=settings) |
3807 |
+ |
3808 |
+ # Limit ebuilds to the specified repo. |
3809 |
+ portdb.porttrees = [repo_path] |
3810 |
+ |
3811 |
+ if options.update: |
3812 |
+ if options.cache_dir is not None: |
3813 |
+ # already validated earlier |
3814 |
+ pass |
3815 |
+ else: |
3816 |
+ # We check write access after the portdbapi constructor |
3817 |
+ # has had an opportunity to create it. This ensures that |
3818 |
+ # we don't use the cache in the "volatile" mode which is |
3819 |
+ # undesirable for egencache. |
3820 |
+ if not os.access(settings["PORTAGE_DEPCACHEDIR"], os.W_OK): |
3821 |
+ writemsg_level( |
3822 |
+ "ecachegen: error: " |
3823 |
+ + "write access denied: %s\n" % (settings["PORTAGE_DEPCACHEDIR"],), |
3824 |
+ level=logging.ERROR, |
3825 |
+ noiselevel=-1, |
3826 |
+ ) |
3827 |
+ return 1 |
3828 |
+ |
3829 |
+ if options.sign_manifests is not None: |
3830 |
+ repo_config.sign_manifest = options.sign_manifests == "y" |
3831 |
+ |
3832 |
+ if options.thin_manifests is not None: |
3833 |
+ repo_config.thin_manifest = options.thin_manifests == "y" |
3834 |
+ |
3835 |
+ gpg_cmd = None |
3836 |
+ gpg_vars = None |
3837 |
+ force_sign_key = None |
3838 |
+ |
3839 |
+ if options.update_manifests: |
3840 |
+ if repo_config.sign_manifest: |
3841 |
+ |
3842 |
+ sign_problem = False |
3843 |
+ gpg_dir = None |
3844 |
+ gpg_cmd = settings.get("PORTAGE_GPG_SIGNING_COMMAND") |
3845 |
+ if gpg_cmd is None: |
3846 |
+ writemsg_level( |
3847 |
+ "egencache: error: " |
3848 |
+ "PORTAGE_GPG_SIGNING_COMMAND is unset! " |
3849 |
+ "Is make.globals missing?\n", |
3850 |
+ level=logging.ERROR, |
3851 |
+ noiselevel=-1, |
3852 |
+ ) |
3853 |
+ sign_problem = True |
3854 |
+ elif ( |
3855 |
+ "${PORTAGE_GPG_KEY}" in gpg_cmd |
3856 |
+ and options.gpg_key is None |
3857 |
+ and "PORTAGE_GPG_KEY" not in settings |
3858 |
+ ): |
3859 |
+ writemsg_level( |
3860 |
+ "egencache: error: " "PORTAGE_GPG_KEY is unset!\n", |
3861 |
+ level=logging.ERROR, |
3862 |
+ noiselevel=-1, |
3863 |
+ ) |
3864 |
+ sign_problem = True |
3865 |
+ elif "${PORTAGE_GPG_DIR}" in gpg_cmd: |
3866 |
+ if options.gpg_dir is not None: |
3867 |
+ gpg_dir = options.gpg_dir |
3868 |
+ elif "PORTAGE_GPG_DIR" not in settings: |
3869 |
+ gpg_dir = os.path.expanduser("~/.gnupg") |
3870 |
+ else: |
3871 |
+ gpg_dir = os.path.expanduser(settings["PORTAGE_GPG_DIR"]) |
3872 |
+ if not os.access(gpg_dir, os.X_OK): |
3873 |
+ writemsg_level( |
3874 |
+ ( |
3875 |
+ "egencache: error: " |
3876 |
+ "Unable to access directory: " |
3877 |
+ "PORTAGE_GPG_DIR='%s'\n" |
3878 |
+ ) |
3879 |
+ % gpg_dir, |
3880 |
+ level=logging.ERROR, |
3881 |
+ noiselevel=-1, |
3882 |
+ ) |
3883 |
+ sign_problem = True |
3884 |
+ |
3885 |
+ if sign_problem: |
3886 |
+ writemsg_level( |
3887 |
+ "egencache: You may disable manifest " |
3888 |
+ "signatures with --sign-manifests=n or by setting " |
3889 |
+ '"sign-manifests = false" in metadata/layout.conf\n', |
3890 |
+ level=logging.ERROR, |
3891 |
+ noiselevel=-1, |
3892 |
+ ) |
3893 |
+ return 1 |
3894 |
+ |
3895 |
+ gpg_vars = {} |
3896 |
+ if gpg_dir is not None: |
3897 |
+ gpg_vars["PORTAGE_GPG_DIR"] = gpg_dir |
3898 |
+ gpg_var_names = [] |
3899 |
+ if options.gpg_key is None: |
3900 |
+ gpg_var_names.append("PORTAGE_GPG_KEY") |
3901 |
+ else: |
3902 |
+ gpg_vars["PORTAGE_GPG_KEY"] = options.gpg_key |
3903 |
+ |
3904 |
+ for k in gpg_var_names: |
3905 |
+ v = settings.get(k) |
3906 |
+ if v is not None: |
3907 |
+ gpg_vars[k] = v |
3908 |
+ |
3909 |
+ force_sign_key = gpg_vars.get("PORTAGE_GPG_KEY") |
3910 |
+ |
3911 |
+ ret = [os.EX_OK] |
3912 |
+ |
3913 |
+ if options.update: |
3914 |
+ cp_iter = None |
3915 |
+ if atoms: |
3916 |
+ cp_iter = iter(atoms) |
3917 |
+ |
3918 |
+ gen_cache = GenCache( |
3919 |
+ portdb, |
3920 |
+ cp_iter=cp_iter, |
3921 |
+ max_jobs=options.jobs, |
3922 |
+ max_load=options.load_average, |
3923 |
+ rsync=options.rsync, |
3924 |
+ external_cache_only=options.external_cache_only, |
3925 |
+ ) |
3926 |
+ gen_cache.run() |
3927 |
+ if options.tolerant: |
3928 |
+ ret.append(os.EX_OK) |
3929 |
+ else: |
3930 |
+ ret.append(gen_cache.returncode) |
3931 |
+ |
3932 |
+ if options.update_pkg_desc_index: |
3933 |
+ if not options.external_cache_only and repo_config.writable: |
3934 |
+ writable_location = repo_config.location |
3935 |
+ else: |
3936 |
+ writable_location = os.path.join( |
3937 |
+ portdb.depcachedir, repo_config.location.lstrip(os.sep) |
3938 |
+ ) |
3939 |
+ if not options.external_cache_only: |
3940 |
+ msg = [ |
3941 |
+ "WARNING: Repository is not writable: %s" % (repo_config.location,), |
3942 |
+ " Using cache directory instead: %s" % (writable_location,), |
3943 |
+ ] |
3944 |
+ msg = "".join(line + "\n" for line in msg) |
3945 |
+ writemsg_level(msg, level=logging.WARNING, noiselevel=-1) |
3946 |
+ |
3947 |
+ gen_index = GenPkgDescIndex( |
3948 |
+ repo_config, |
3949 |
+ portdb, |
3950 |
+ os.path.join(writable_location, "metadata", "pkg_desc_index"), |
3951 |
+ verbose=options.verbose, |
3952 |
+ ) |
3953 |
+ gen_index.run() |
3954 |
+ ret.append(gen_index.returncode) |
3955 |
+ |
3956 |
+ if options.update_use_local_desc: |
3957 |
+ gen_desc = GenUseLocalDesc( |
3958 |
+ portdb, |
3959 |
+ output=options.uld_output, |
3960 |
+ preserve_comments=options.preserve_comments, |
3961 |
+ ) |
3962 |
+ gen_desc.run() |
3963 |
+ ret.append(gen_desc.returncode) |
3964 |
+ |
3965 |
+ if options.update_changelogs: |
3966 |
+ gen_clogs = GenChangeLogs( |
3967 |
+ portdb, |
3968 |
+ changelog_output=options.changelog_output, |
3969 |
+ changelog_reversed=options.changelog_reversed, |
3970 |
+ max_jobs=options.jobs, |
3971 |
+ max_load=options.load_average, |
3972 |
+ ) |
3973 |
+ signum = gen_clogs.run() |
3974 |
+ if signum is not None: |
3975 |
+ sys.exit(128 + signum) |
3976 |
+ ret.append(gen_clogs.returncode) |
3977 |
+ |
3978 |
+ if options.update_manifests: |
3979 |
+ |
3980 |
+ cp_iter = None |
3981 |
+ if atoms: |
3982 |
+ cp_iter = iter(atoms) |
3983 |
+ |
3984 |
+ event_loop = global_event_loop() |
3985 |
+ scheduler = ManifestScheduler( |
3986 |
+ portdb, |
3987 |
+ cp_iter=cp_iter, |
3988 |
+ gpg_cmd=gpg_cmd, |
3989 |
+ gpg_vars=gpg_vars, |
3990 |
+ force_sign_key=force_sign_key, |
3991 |
+ max_jobs=options.jobs, |
3992 |
+ max_load=options.load_average, |
3993 |
+ event_loop=event_loop, |
3994 |
+ ) |
3995 |
+ |
3996 |
+ signum = run_main_scheduler(scheduler) |
3997 |
+ if signum is not None: |
3998 |
+ sys.exit(128 + signum) |
3999 |
+ |
4000 |
+ if options.tolerant: |
4001 |
+ ret.append(os.EX_OK) |
4002 |
+ else: |
4003 |
+ ret.append(scheduler.returncode) |
4004 |
+ |
4005 |
+ if options.write_timestamp: |
4006 |
+ timestamp_path = os.path.join(repo_path, "metadata", "timestamp.chk") |
4007 |
+ try: |
4008 |
+ portage.util.write_atomic( |
4009 |
+ timestamp_path, time.strftime("%s\n" % TIMESTAMP_FORMAT, time.gmtime()) |
4010 |
+ ) |
4011 |
+ except (EnvironmentError, portage.exception.PortageException): |
4012 |
+ ret.append(os.EX_IOERR) |
4013 |
+ else: |
4014 |
+ ret.append(os.EX_OK) |
4015 |
+ |
4016 |
+ return max(ret) |
4017 |
|
4018 |
- parser, options, atoms = parse_args(args) |
4019 |
- |
4020 |
- config_root = options.config_root |
4021 |
- |
4022 |
- if options.repositories_configuration is not None: |
4023 |
- env['PORTAGE_REPOSITORIES'] = options.repositories_configuration |
4024 |
- |
4025 |
- if options.cache_dir is not None: |
4026 |
- env['PORTAGE_DEPCACHEDIR'] = options.cache_dir |
4027 |
- |
4028 |
- settings = portage.config(config_root=config_root, |
4029 |
- local_config=False, env=env) |
4030 |
- |
4031 |
- default_opts = None |
4032 |
- if not options.ignore_default_opts: |
4033 |
- default_opts = portage.util.shlex_split( |
4034 |
- settings.get('EGENCACHE_DEFAULT_OPTS', '')) |
4035 |
- |
4036 |
- if default_opts: |
4037 |
- parser, options, args = parse_args(default_opts + args) |
4038 |
- |
4039 |
- if options.cache_dir is not None: |
4040 |
- env['PORTAGE_DEPCACHEDIR'] = options.cache_dir |
4041 |
- |
4042 |
- settings = portage.config(config_root=config_root, |
4043 |
- local_config=False, env=env) |
4044 |
- |
4045 |
- if not (options.update or options.update_use_local_desc or |
4046 |
- options.update_changelogs or options.update_manifests or |
4047 |
- options.update_pkg_desc_index): |
4048 |
- parser.error('No action specified') |
4049 |
- return 1 |
4050 |
- |
4051 |
- if options.repo is None: |
4052 |
- if len(settings.repositories.prepos) == 2: |
4053 |
- for repo in settings.repositories: |
4054 |
- if repo.name != "DEFAULT": |
4055 |
- options.repo = repo.name |
4056 |
- break |
4057 |
- |
4058 |
- if options.repo is None: |
4059 |
- parser.error("--repo option is required") |
4060 |
- |
4061 |
- repo_path = settings.repositories.treemap.get(options.repo) |
4062 |
- if repo_path is None: |
4063 |
- parser.error("Unable to locate repository named '%s'" % (options.repo,)) |
4064 |
- return 1 |
4065 |
- |
4066 |
- repo_config = settings.repositories.get_repo_for_location(repo_path) |
4067 |
- |
4068 |
- if options.strict_manifests is not None: |
4069 |
- if options.strict_manifests == "y": |
4070 |
- settings.features.add("strict") |
4071 |
- else: |
4072 |
- settings.features.discard("strict") |
4073 |
- |
4074 |
- if options.update and 'metadata-transfer' not in settings.features: |
4075 |
- # Forcibly enable metadata-transfer if portdbapi has a pregenerated |
4076 |
- # cache that does not support eclass validation. |
4077 |
- cache = repo_config.get_pregenerated_cache( |
4078 |
- portage.dbapi.dbapi._known_keys, readonly=True) |
4079 |
- if cache is not None and not cache.complete_eclass_entries: |
4080 |
- settings.features.add('metadata-transfer') |
4081 |
- cache = None |
4082 |
- |
4083 |
- settings.lock() |
4084 |
- |
4085 |
- portdb = portage.portdbapi(mysettings=settings) |
4086 |
- |
4087 |
- # Limit ebuilds to the specified repo. |
4088 |
- portdb.porttrees = [repo_path] |
4089 |
- |
4090 |
- if options.update: |
4091 |
- if options.cache_dir is not None: |
4092 |
- # already validated earlier |
4093 |
- pass |
4094 |
- else: |
4095 |
- # We check write access after the portdbapi constructor |
4096 |
- # has had an opportunity to create it. This ensures that |
4097 |
- # we don't use the cache in the "volatile" mode which is |
4098 |
- # undesirable for egencache. |
4099 |
- if not os.access(settings["PORTAGE_DEPCACHEDIR"], os.W_OK): |
4100 |
- writemsg_level("ecachegen: error: " + \ |
4101 |
- "write access denied: %s\n" % (settings["PORTAGE_DEPCACHEDIR"],), |
4102 |
- level=logging.ERROR, noiselevel=-1) |
4103 |
- return 1 |
4104 |
- |
4105 |
- if options.sign_manifests is not None: |
4106 |
- repo_config.sign_manifest = options.sign_manifests == 'y' |
4107 |
- |
4108 |
- if options.thin_manifests is not None: |
4109 |
- repo_config.thin_manifest = options.thin_manifests == 'y' |
4110 |
- |
4111 |
- gpg_cmd = None |
4112 |
- gpg_vars = None |
4113 |
- force_sign_key = None |
4114 |
- |
4115 |
- if options.update_manifests: |
4116 |
- if repo_config.sign_manifest: |
4117 |
- |
4118 |
- sign_problem = False |
4119 |
- gpg_dir = None |
4120 |
- gpg_cmd = settings.get("PORTAGE_GPG_SIGNING_COMMAND") |
4121 |
- if gpg_cmd is None: |
4122 |
- writemsg_level("egencache: error: " |
4123 |
- "PORTAGE_GPG_SIGNING_COMMAND is unset! " |
4124 |
- "Is make.globals missing?\n", |
4125 |
- level=logging.ERROR, noiselevel=-1) |
4126 |
- sign_problem = True |
4127 |
- elif "${PORTAGE_GPG_KEY}" in gpg_cmd and \ |
4128 |
- options.gpg_key is None and \ |
4129 |
- "PORTAGE_GPG_KEY" not in settings: |
4130 |
- writemsg_level("egencache: error: " |
4131 |
- "PORTAGE_GPG_KEY is unset!\n", |
4132 |
- level=logging.ERROR, noiselevel=-1) |
4133 |
- sign_problem = True |
4134 |
- elif "${PORTAGE_GPG_DIR}" in gpg_cmd: |
4135 |
- if options.gpg_dir is not None: |
4136 |
- gpg_dir = options.gpg_dir |
4137 |
- elif "PORTAGE_GPG_DIR" not in settings: |
4138 |
- gpg_dir = os.path.expanduser("~/.gnupg") |
4139 |
- else: |
4140 |
- gpg_dir = os.path.expanduser(settings["PORTAGE_GPG_DIR"]) |
4141 |
- if not os.access(gpg_dir, os.X_OK): |
4142 |
- writemsg_level(("egencache: error: " |
4143 |
- "Unable to access directory: " |
4144 |
- "PORTAGE_GPG_DIR='%s'\n") % gpg_dir, |
4145 |
- level=logging.ERROR, noiselevel=-1) |
4146 |
- sign_problem = True |
4147 |
- |
4148 |
- if sign_problem: |
4149 |
- writemsg_level("egencache: You may disable manifest " |
4150 |
- "signatures with --sign-manifests=n or by setting " |
4151 |
- "\"sign-manifests = false\" in metadata/layout.conf\n", |
4152 |
- level=logging.ERROR, noiselevel=-1) |
4153 |
- return 1 |
4154 |
- |
4155 |
- gpg_vars = {} |
4156 |
- if gpg_dir is not None: |
4157 |
- gpg_vars["PORTAGE_GPG_DIR"] = gpg_dir |
4158 |
- gpg_var_names = [] |
4159 |
- if options.gpg_key is None: |
4160 |
- gpg_var_names.append("PORTAGE_GPG_KEY") |
4161 |
- else: |
4162 |
- gpg_vars["PORTAGE_GPG_KEY"] = options.gpg_key |
4163 |
- |
4164 |
- for k in gpg_var_names: |
4165 |
- v = settings.get(k) |
4166 |
- if v is not None: |
4167 |
- gpg_vars[k] = v |
4168 |
- |
4169 |
- force_sign_key = gpg_vars.get("PORTAGE_GPG_KEY") |
4170 |
- |
4171 |
- ret = [os.EX_OK] |
4172 |
- |
4173 |
- if options.update: |
4174 |
- cp_iter = None |
4175 |
- if atoms: |
4176 |
- cp_iter = iter(atoms) |
4177 |
- |
4178 |
- gen_cache = GenCache(portdb, cp_iter=cp_iter, |
4179 |
- max_jobs=options.jobs, |
4180 |
- max_load=options.load_average, |
4181 |
- rsync=options.rsync, |
4182 |
- external_cache_only=options.external_cache_only) |
4183 |
- gen_cache.run() |
4184 |
- if options.tolerant: |
4185 |
- ret.append(os.EX_OK) |
4186 |
- else: |
4187 |
- ret.append(gen_cache.returncode) |
4188 |
- |
4189 |
- if options.update_pkg_desc_index: |
4190 |
- if not options.external_cache_only and repo_config.writable: |
4191 |
- writable_location = repo_config.location |
4192 |
- else: |
4193 |
- writable_location = os.path.join(portdb.depcachedir, |
4194 |
- repo_config.location.lstrip(os.sep)) |
4195 |
- if not options.external_cache_only: |
4196 |
- msg = [ |
4197 |
- "WARNING: Repository is not writable: %s" % ( |
4198 |
- repo_config.location,), |
4199 |
- " Using cache directory instead: %s" % ( |
4200 |
- writable_location,) |
4201 |
- ] |
4202 |
- msg = "".join(line + '\n' for line in msg) |
4203 |
- writemsg_level(msg, |
4204 |
- level=logging.WARNING, noiselevel=-1) |
4205 |
- |
4206 |
- gen_index = GenPkgDescIndex(repo_config, portdb, os.path.join( |
4207 |
- writable_location, "metadata", "pkg_desc_index"), |
4208 |
- verbose=options.verbose) |
4209 |
- gen_index.run() |
4210 |
- ret.append(gen_index.returncode) |
4211 |
- |
4212 |
- if options.update_use_local_desc: |
4213 |
- gen_desc = GenUseLocalDesc(portdb, |
4214 |
- output=options.uld_output, |
4215 |
- preserve_comments=options.preserve_comments) |
4216 |
- gen_desc.run() |
4217 |
- ret.append(gen_desc.returncode) |
4218 |
- |
4219 |
- if options.update_changelogs: |
4220 |
- gen_clogs = GenChangeLogs(portdb, |
4221 |
- changelog_output=options.changelog_output, |
4222 |
- changelog_reversed=options.changelog_reversed, |
4223 |
- max_jobs=options.jobs, |
4224 |
- max_load=options.load_average) |
4225 |
- signum = gen_clogs.run() |
4226 |
- if signum is not None: |
4227 |
- sys.exit(128 + signum) |
4228 |
- ret.append(gen_clogs.returncode) |
4229 |
- |
4230 |
- if options.update_manifests: |
4231 |
- |
4232 |
- cp_iter = None |
4233 |
- if atoms: |
4234 |
- cp_iter = iter(atoms) |
4235 |
- |
4236 |
- event_loop = global_event_loop() |
4237 |
- scheduler = ManifestScheduler(portdb, cp_iter=cp_iter, |
4238 |
- gpg_cmd=gpg_cmd, gpg_vars=gpg_vars, |
4239 |
- force_sign_key=force_sign_key, |
4240 |
- max_jobs=options.jobs, |
4241 |
- max_load=options.load_average, |
4242 |
- event_loop=event_loop) |
4243 |
- |
4244 |
- signum = run_main_scheduler(scheduler) |
4245 |
- if signum is not None: |
4246 |
- sys.exit(128 + signum) |
4247 |
- |
4248 |
- if options.tolerant: |
4249 |
- ret.append(os.EX_OK) |
4250 |
- else: |
4251 |
- ret.append(scheduler.returncode) |
4252 |
- |
4253 |
- if options.write_timestamp: |
4254 |
- timestamp_path = os.path.join(repo_path, 'metadata', 'timestamp.chk') |
4255 |
- try: |
4256 |
- portage.util.write_atomic(timestamp_path, |
4257 |
- time.strftime('%s\n' % TIMESTAMP_FORMAT, time.gmtime())) |
4258 |
- except (EnvironmentError, portage.exception.PortageException): |
4259 |
- ret.append(os.EX_IOERR) |
4260 |
- else: |
4261 |
- ret.append(os.EX_OK) |
4262 |
- |
4263 |
- return max(ret) |
4264 |
|
4265 |
if __name__ == "__main__": |
4266 |
- portage._disable_legacy_globals() |
4267 |
- portage.util.noiselimit = -1 |
4268 |
- try: |
4269 |
- sys.exit(egencache_main(sys.argv[1:])) |
4270 |
- finally: |
4271 |
- global_event_loop().close() |
4272 |
+ portage._disable_legacy_globals() |
4273 |
+ portage.util.noiselimit = -1 |
4274 |
+ try: |
4275 |
+ sys.exit(egencache_main(sys.argv[1:])) |
4276 |
+ finally: |
4277 |
+ global_event_loop().close() |
4278 |
|
4279 |
diff --git a/bin/emaint b/bin/emaint |
4280 |
index feef8d7e8..bd7b9083c 100755 |
4281 |
--- a/bin/emaint |
4282 |
+++ b/bin/emaint |
4283 |
@@ -7,37 +7,44 @@ |
4284 |
|
4285 |
import sys |
4286 |
import errno |
4287 |
+ |
4288 |
# This block ensures that ^C interrupts are handled quietly. |
4289 |
try: |
4290 |
- import signal |
4291 |
+ import signal |
4292 |
|
4293 |
- def exithandler(signum, _frame): |
4294 |
- signal.signal(signal.SIGINT, signal.SIG_IGN) |
4295 |
- signal.signal(signal.SIGTERM, signal.SIG_IGN) |
4296 |
- sys.exit(128 + signum) |
4297 |
+ def exithandler(signum, _frame): |
4298 |
+ signal.signal(signal.SIGINT, signal.SIG_IGN) |
4299 |
+ signal.signal(signal.SIGTERM, signal.SIG_IGN) |
4300 |
+ sys.exit(128 + signum) |
4301 |
|
4302 |
- signal.signal(signal.SIGINT, exithandler) |
4303 |
- signal.signal(signal.SIGTERM, exithandler) |
4304 |
- signal.signal(signal.SIGPIPE, signal.SIG_DFL) |
4305 |
+ signal.signal(signal.SIGINT, exithandler) |
4306 |
+ signal.signal(signal.SIGTERM, exithandler) |
4307 |
+ signal.signal(signal.SIGPIPE, signal.SIG_DFL) |
4308 |
|
4309 |
except KeyboardInterrupt: |
4310 |
- sys.exit(1) |
4311 |
+ sys.exit(1) |
4312 |
|
4313 |
from os import path as osp |
4314 |
-if osp.isfile(osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), ".portage_not_installed")): |
4315 |
- sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "lib")) |
4316 |
+ |
4317 |
+if osp.isfile( |
4318 |
+ osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), ".portage_not_installed") |
4319 |
+): |
4320 |
+ sys.path.insert( |
4321 |
+ 0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "lib") |
4322 |
+ ) |
4323 |
import portage |
4324 |
+ |
4325 |
portage._internal_caller = True |
4326 |
from portage.emaint.main import emaint_main |
4327 |
from portage.util._eventloop.global_event_loop import global_event_loop |
4328 |
|
4329 |
try: |
4330 |
- emaint_main(sys.argv[1:]) |
4331 |
+ emaint_main(sys.argv[1:]) |
4332 |
except IOError as e: |
4333 |
- if e.errno == errno.EACCES: |
4334 |
- print("\nemaint: Need superuser access") |
4335 |
- sys.exit(1) |
4336 |
- else: |
4337 |
- raise |
4338 |
+ if e.errno == errno.EACCES: |
4339 |
+ print("\nemaint: Need superuser access") |
4340 |
+ sys.exit(1) |
4341 |
+ else: |
4342 |
+ raise |
4343 |
finally: |
4344 |
- global_event_loop().close() |
4345 |
+ global_event_loop().close() |
4346 |
|
4347 |
diff --git a/bin/emerge b/bin/emerge |
4348 |
index 33ece427c..a407b9d6c 100755 |
4349 |
--- a/bin/emerge |
4350 |
+++ b/bin/emerge |
4351 |
@@ -14,71 +14,81 @@ import sys |
4352 |
global_event_loop = None |
4353 |
try: |
4354 |
|
4355 |
- def exithandler(signum, _frame): |
4356 |
- signal.signal(signal.SIGTERM, signal.SIG_IGN) |
4357 |
- sys.exit(128 + signum) |
4358 |
+ def exithandler(signum, _frame): |
4359 |
+ signal.signal(signal.SIGTERM, signal.SIG_IGN) |
4360 |
+ sys.exit(128 + signum) |
4361 |
|
4362 |
- signal.signal(signal.SIGTERM, exithandler) |
4363 |
- # Prevent "[Errno 32] Broken pipe" exceptions when |
4364 |
- # writing to a pipe. |
4365 |
- signal.signal(signal.SIGPIPE, signal.SIG_DFL) |
4366 |
+ signal.signal(signal.SIGTERM, exithandler) |
4367 |
+ # Prevent "[Errno 32] Broken pipe" exceptions when |
4368 |
+ # writing to a pipe. |
4369 |
+ signal.signal(signal.SIGPIPE, signal.SIG_DFL) |
4370 |
|
4371 |
- def debug_signal(_signum, _frame): |
4372 |
- import pdb |
4373 |
- pdb.set_trace() |
4374 |
+ def debug_signal(_signum, _frame): |
4375 |
+ import pdb |
4376 |
|
4377 |
- if platform.python_implementation() == 'Jython': |
4378 |
- debug_signum = signal.SIGUSR2 # bug #424259 |
4379 |
- else: |
4380 |
- debug_signum = signal.SIGUSR1 |
4381 |
+ pdb.set_trace() |
4382 |
|
4383 |
- signal.signal(debug_signum, debug_signal) |
4384 |
+ if platform.python_implementation() == "Jython": |
4385 |
+ debug_signum = signal.SIGUSR2 # bug #424259 |
4386 |
+ else: |
4387 |
+ debug_signum = signal.SIGUSR1 |
4388 |
|
4389 |
- from os import path as osp |
4390 |
- if osp.isfile(osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), ".portage_not_installed")): |
4391 |
- sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "lib")) |
4392 |
- import portage |
4393 |
- portage._internal_caller = True |
4394 |
- portage._disable_legacy_globals() |
4395 |
- from portage.elog import mod_echo |
4396 |
- from portage.exception import IsADirectory, ParseError, PermissionDenied |
4397 |
- from portage.util._eventloop.global_event_loop import global_event_loop |
4398 |
- from _emerge.main import emerge_main |
4399 |
+ signal.signal(debug_signum, debug_signal) |
4400 |
|
4401 |
- if __name__ == "__main__": |
4402 |
- portage.process.sanitize_fds() |
4403 |
- try: |
4404 |
- retval = emerge_main() |
4405 |
- except PermissionDenied as e: |
4406 |
- sys.stderr.write("Permission denied: '%s'\n" % str(e)) |
4407 |
- sys.exit(e.errno) |
4408 |
- except IsADirectory as e: |
4409 |
- sys.stderr.write("'%s' is a directory, but should be a file!\n" |
4410 |
- "See portage man page for information on " |
4411 |
- "which files may be directories.\n" % |
4412 |
- str(e)) |
4413 |
- sys.exit(e.errno) |
4414 |
- except ParseError as e: |
4415 |
- sys.stderr.write("%s\n" % str(e)) |
4416 |
- sys.exit(1) |
4417 |
- except (KeyboardInterrupt, SystemExit): |
4418 |
- raise |
4419 |
- except Exception: |
4420 |
- # If an unexpected exception occurs then we don't want the |
4421 |
- # mod_echo output to obscure the traceback, so dump the |
4422 |
- # mod_echo output before showing the traceback. |
4423 |
- import traceback |
4424 |
- tb_str = traceback.format_exc() |
4425 |
- mod_echo.finalize() |
4426 |
- sys.stderr.write(tb_str) |
4427 |
- sys.exit(1) |
4428 |
- sys.exit(retval) |
4429 |
+ from os import path as osp |
4430 |
+ |
4431 |
+ if osp.isfile( |
4432 |
+ osp.join( |
4433 |
+ osp.dirname(osp.dirname(osp.realpath(__file__))), ".portage_not_installed" |
4434 |
+ ) |
4435 |
+ ): |
4436 |
+ sys.path.insert( |
4437 |
+ 0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "lib") |
4438 |
+ ) |
4439 |
+ import portage |
4440 |
+ |
4441 |
+ portage._internal_caller = True |
4442 |
+ portage._disable_legacy_globals() |
4443 |
+ from portage.elog import mod_echo |
4444 |
+ from portage.exception import IsADirectory, ParseError, PermissionDenied |
4445 |
+ from portage.util._eventloop.global_event_loop import global_event_loop |
4446 |
+ from _emerge.main import emerge_main |
4447 |
+ |
4448 |
+ if __name__ == "__main__": |
4449 |
+ portage.process.sanitize_fds() |
4450 |
+ try: |
4451 |
+ retval = emerge_main() |
4452 |
+ except PermissionDenied as e: |
4453 |
+ sys.stderr.write("Permission denied: '%s'\n" % str(e)) |
4454 |
+ sys.exit(e.errno) |
4455 |
+ except IsADirectory as e: |
4456 |
+ sys.stderr.write( |
4457 |
+ "'%s' is a directory, but should be a file!\n" |
4458 |
+ "See portage man page for information on " |
4459 |
+ "which files may be directories.\n" % str(e) |
4460 |
+ ) |
4461 |
+ sys.exit(e.errno) |
4462 |
+ except ParseError as e: |
4463 |
+ sys.stderr.write("%s\n" % str(e)) |
4464 |
+ sys.exit(1) |
4465 |
+ except (KeyboardInterrupt, SystemExit): |
4466 |
+ raise |
4467 |
+ except Exception: |
4468 |
+ # If an unexpected exception occurs then we don't want the |
4469 |
+ # mod_echo output to obscure the traceback, so dump the |
4470 |
+ # mod_echo output before showing the traceback. |
4471 |
+ import traceback |
4472 |
+ |
4473 |
+ tb_str = traceback.format_exc() |
4474 |
+ mod_echo.finalize() |
4475 |
+ sys.stderr.write(tb_str) |
4476 |
+ sys.exit(1) |
4477 |
+ sys.exit(retval) |
4478 |
|
4479 |
except KeyboardInterrupt: |
4480 |
- sys.stderr.write("\n\nExiting on signal %(signal)s\n" % |
4481 |
- {"signal": signal.SIGINT}) |
4482 |
- sys.stderr.flush() |
4483 |
- sys.exit(128 + signal.SIGINT) |
4484 |
+ sys.stderr.write("\n\nExiting on signal %(signal)s\n" % {"signal": signal.SIGINT}) |
4485 |
+ sys.stderr.flush() |
4486 |
+ sys.exit(128 + signal.SIGINT) |
4487 |
finally: |
4488 |
- if global_event_loop is not None: |
4489 |
- global_event_loop().close() |
4490 |
+ if global_event_loop is not None: |
4491 |
+ global_event_loop().close() |
4492 |
|
4493 |
diff --git a/bin/emirrordist b/bin/emirrordist |
4494 |
index 626a055e7..35060213f 100755 |
4495 |
--- a/bin/emirrordist |
4496 |
+++ b/bin/emirrordist |
4497 |
@@ -6,6 +6,7 @@ import signal |
4498 |
import sys |
4499 |
|
4500 |
import portage |
4501 |
+ |
4502 |
portage._internal_caller = True |
4503 |
portage._disable_legacy_globals() |
4504 |
from portage._emirrordist.main import emirrordist_main |
4505 |
@@ -13,13 +14,14 @@ from portage.util._eventloop.global_event_loop import global_event_loop |
4506 |
|
4507 |
if __name__ == "__main__": |
4508 |
|
4509 |
- def debug_signal(_signum, _frame): |
4510 |
- import pdb |
4511 |
- pdb.set_trace() |
4512 |
+ def debug_signal(_signum, _frame): |
4513 |
+ import pdb |
4514 |
+ |
4515 |
+ pdb.set_trace() |
4516 |
|
4517 |
- signal.signal(signal.SIGUSR1, debug_signal) |
4518 |
+ signal.signal(signal.SIGUSR1, debug_signal) |
4519 |
|
4520 |
- try: |
4521 |
- sys.exit(emirrordist_main(sys.argv[1:])) |
4522 |
- finally: |
4523 |
- global_event_loop().close() |
4524 |
+ try: |
4525 |
+ sys.exit(emirrordist_main(sys.argv[1:])) |
4526 |
+ finally: |
4527 |
+ global_event_loop().close() |
4528 |
|
4529 |
diff --git a/bin/env-update b/bin/env-update |
4530 |
index f3851afaf..c0de199e6 100755 |
4531 |
--- a/bin/env-update |
4532 |
+++ b/bin/env-update |
4533 |
@@ -5,35 +5,43 @@ |
4534 |
import errno |
4535 |
import sys |
4536 |
|
4537 |
+ |
4538 |
def usage(status): |
4539 |
- print("Usage: env-update [--no-ldconfig]") |
4540 |
- print("") |
4541 |
- print("See the env-update(1) man page for more info") |
4542 |
- sys.exit(status) |
4543 |
+ print("Usage: env-update [--no-ldconfig]") |
4544 |
+ print("") |
4545 |
+ print("See the env-update(1) man page for more info") |
4546 |
+ sys.exit(status) |
4547 |
+ |
4548 |
|
4549 |
if "-h" in sys.argv or "--help" in sys.argv: |
4550 |
- usage(0) |
4551 |
+ usage(0) |
4552 |
|
4553 |
-makelinks=1 |
4554 |
+makelinks = 1 |
4555 |
if "--no-ldconfig" in sys.argv: |
4556 |
- makelinks=0 |
4557 |
- sys.argv.pop(sys.argv.index("--no-ldconfig")) |
4558 |
+ makelinks = 0 |
4559 |
+ sys.argv.pop(sys.argv.index("--no-ldconfig")) |
4560 |
|
4561 |
if len(sys.argv) > 1: |
4562 |
- print("!!! Invalid command line options!\n") |
4563 |
- usage(1) |
4564 |
+ print("!!! Invalid command line options!\n") |
4565 |
+ usage(1) |
4566 |
|
4567 |
from os import path as osp |
4568 |
-if osp.isfile(osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), ".portage_not_installed")): |
4569 |
- sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "lib")) |
4570 |
+ |
4571 |
+if osp.isfile( |
4572 |
+ osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), ".portage_not_installed") |
4573 |
+): |
4574 |
+ sys.path.insert( |
4575 |
+ 0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "lib") |
4576 |
+ ) |
4577 |
import portage |
4578 |
+ |
4579 |
portage._internal_caller = True |
4580 |
|
4581 |
try: |
4582 |
- portage.env_update(makelinks) |
4583 |
+ portage.env_update(makelinks) |
4584 |
except IOError as e: |
4585 |
- if e.errno == errno.EACCES: |
4586 |
- print("env-update: Need superuser access") |
4587 |
- sys.exit(1) |
4588 |
- else: |
4589 |
- raise |
4590 |
+ if e.errno == errno.EACCES: |
4591 |
+ print("env-update: Need superuser access") |
4592 |
+ sys.exit(1) |
4593 |
+ else: |
4594 |
+ raise |
4595 |
|
4596 |
diff --git a/bin/fixpackages b/bin/fixpackages |
4597 |
index eab4b3959..34aaa786e 100755 |
4598 |
--- a/bin/fixpackages |
4599 |
+++ b/bin/fixpackages |
4600 |
@@ -7,14 +7,21 @@ import os |
4601 |
import sys |
4602 |
|
4603 |
from os import path as osp |
4604 |
-if osp.isfile(osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), ".portage_not_installed")): |
4605 |
- sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "lib")) |
4606 |
+ |
4607 |
+if osp.isfile( |
4608 |
+ osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), ".portage_not_installed") |
4609 |
+): |
4610 |
+ sys.path.insert( |
4611 |
+ 0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "lib") |
4612 |
+ ) |
4613 |
import portage |
4614 |
+ |
4615 |
portage._internal_caller = True |
4616 |
from portage import os |
4617 |
from portage.output import EOutput |
4618 |
from textwrap import wrap |
4619 |
from portage._global_updates import _global_updates |
4620 |
+ |
4621 |
mysettings = portage.settings |
4622 |
mytrees = portage.db |
4623 |
mtimedb = portage.mtimedb |
4624 |
@@ -26,22 +33,25 @@ description = " ".join(description.split()) |
4625 |
parser = argparse.ArgumentParser(description=description) |
4626 |
parser.parse_args() |
4627 |
|
4628 |
-if mysettings['ROOT'] != "/": |
4629 |
- out = EOutput() |
4630 |
- msg = "The fixpackages program is not intended for use with " + \ |
4631 |
- "ROOT != \"/\". Instead use `emaint --fix movebin` and/or " + \ |
4632 |
- "`emaint --fix moveinst." |
4633 |
- for line in wrap(msg, 72): |
4634 |
- out.eerror(line) |
4635 |
- sys.exit(1) |
4636 |
+if mysettings["ROOT"] != "/": |
4637 |
+ out = EOutput() |
4638 |
+ msg = ( |
4639 |
+ "The fixpackages program is not intended for use with " |
4640 |
+ + 'ROOT != "/". Instead use `emaint --fix movebin` and/or ' |
4641 |
+ + "`emaint --fix moveinst." |
4642 |
+ ) |
4643 |
+ for line in wrap(msg, 72): |
4644 |
+ out.eerror(line) |
4645 |
+ sys.exit(1) |
4646 |
|
4647 |
try: |
4648 |
- os.nice(int(mysettings.get("PORTAGE_NICENESS", "0"))) |
4649 |
+ os.nice(int(mysettings.get("PORTAGE_NICENESS", "0"))) |
4650 |
except (OSError, ValueError) as e: |
4651 |
- portage.writemsg("!!! Failed to change nice value to '%s'\n" % \ |
4652 |
- mysettings["PORTAGE_NICENESS"]) |
4653 |
- portage.writemsg("!!! %s\n" % str(e)) |
4654 |
- del e |
4655 |
+ portage.writemsg( |
4656 |
+ "!!! Failed to change nice value to '%s'\n" % mysettings["PORTAGE_NICENESS"] |
4657 |
+ ) |
4658 |
+ portage.writemsg("!!! %s\n" % str(e)) |
4659 |
+ del e |
4660 |
|
4661 |
_global_updates(mytrees, mtimedb["updates"], if_mtime_changed=False) |
4662 |
|
4663 |
|
4664 |
diff --git a/bin/glsa-check b/bin/glsa-check |
4665 |
index 165123fd0..93d9efe18 100755 |
4666 |
--- a/bin/glsa-check |
4667 |
+++ b/bin/glsa-check |
4668 |
@@ -10,9 +10,15 @@ from functools import reduce |
4669 |
import operator |
4670 |
|
4671 |
from os import path as osp |
4672 |
-if osp.isfile(osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), ".portage_not_installed")): |
4673 |
- sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "lib")) |
4674 |
+ |
4675 |
+if osp.isfile( |
4676 |
+ osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), ".portage_not_installed") |
4677 |
+): |
4678 |
+ sys.path.insert( |
4679 |
+ 0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "lib") |
4680 |
+ ) |
4681 |
import portage |
4682 |
+ |
4683 |
portage._internal_caller = True |
4684 |
from portage import os |
4685 |
from portage.glsa import match |
4686 |
@@ -23,62 +29,123 @@ __author__ = "Marius Mauch <genone@g.o>" |
4687 |
__version__ = "1.0.1" |
4688 |
|
4689 |
# option parsing |
4690 |
-epilog = "glsa-list can contain an arbitrary number of GLSA ids," \ |
4691 |
- " filenames containing GLSAs or the special identifiers" \ |
4692 |
- " 'all' and 'affected'" |
4693 |
-parser = argparse.ArgumentParser(usage=__program__ + " <option> [glsa-id | all | new | affected]", |
4694 |
- epilog=epilog) |
4695 |
+epilog = ( |
4696 |
+ "glsa-list can contain an arbitrary number of GLSA ids," |
4697 |
+ " filenames containing GLSAs or the special identifiers" |
4698 |
+ " 'all' and 'affected'" |
4699 |
+) |
4700 |
+parser = argparse.ArgumentParser( |
4701 |
+ usage=__program__ + " <option> [glsa-id | all | new | affected]", epilog=epilog |
4702 |
+) |
4703 |
|
4704 |
modes = parser.add_argument_group("Modes") |
4705 |
-modes.add_argument("-l", "--list", action="store_const", |
4706 |
- const="list", dest="mode", |
4707 |
- help="List a summary for the given GLSA(s) or set and whether they affect the system") |
4708 |
-modes.add_argument("-d", "--dump", action="store_const", |
4709 |
- const="dump", dest="mode", |
4710 |
- help="Show all information about the GLSA(s) or set") |
4711 |
-modes.add_argument("--print", action="store_const", |
4712 |
- const="dump", dest="mode", |
4713 |
- help="Alias for --dump") |
4714 |
-modes.add_argument("-t", "--test", action="store_const", |
4715 |
- const="test", dest="mode", |
4716 |
- help="Test if this system is affected by the GLSA(s) or set and output the GLSA ID(s)") |
4717 |
-modes.add_argument("-p", "--pretend", action="store_const", |
4718 |
- const="pretend", dest="mode", |
4719 |
- help="Show the necessary steps to remediate the system") |
4720 |
-modes.add_argument("-f", "--fix", action="store_const", |
4721 |
- const="fix", dest="mode", |
4722 |
- help="(experimental) Attempt to remediate the system based on the instructions given in the GLSA(s) or set. This will only upgrade (when an upgrade path exists) or remove packages") |
4723 |
-modes.add_argument("-i", "--inject", action="store_const", |
4724 |
- const="inject", dest="mode", |
4725 |
- help="Inject the given GLSA(s) into the glsa_injected file") |
4726 |
-modes.add_argument("-m", "--mail", action="store_const", |
4727 |
- const="mail", dest="mode", |
4728 |
- help="Send a mail with the given GLSAs to the administrator") |
4729 |
-parser.add_argument("-V", "--version", action="store_true", |
4730 |
- help="Show information about glsa-check") |
4731 |
-parser.add_argument("-q", "--quiet", action="store_true", dest="quiet", |
4732 |
- help="Be less verbose and do not send empty mail") |
4733 |
-parser.add_argument("-v", "--verbose", action="store_true", dest="verbose", |
4734 |
- help="Print more messages") |
4735 |
-parser.add_argument("-n", "--nocolor", action="store_true", |
4736 |
- help="Removes color from output") |
4737 |
-parser.add_argument("-e", "--emergelike", action="store_false", dest="least_change", |
4738 |
- help="Upgrade to latest version (not least-change)") |
4739 |
-parser.add_argument("-c", "--cve", action="store_true", dest="list_cve", |
4740 |
- help="Show CVE IDs in listing mode") |
4741 |
-parser.add_argument("-r", "--reverse", action="store_true", dest="reverse", |
4742 |
- help="List GLSAs in reverse order") |
4743 |
+modes.add_argument( |
4744 |
+ "-l", |
4745 |
+ "--list", |
4746 |
+ action="store_const", |
4747 |
+ const="list", |
4748 |
+ dest="mode", |
4749 |
+ help="List a summary for the given GLSA(s) or set and whether they affect the system", |
4750 |
+) |
4751 |
+modes.add_argument( |
4752 |
+ "-d", |
4753 |
+ "--dump", |
4754 |
+ action="store_const", |
4755 |
+ const="dump", |
4756 |
+ dest="mode", |
4757 |
+ help="Show all information about the GLSA(s) or set", |
4758 |
+) |
4759 |
+modes.add_argument( |
4760 |
+ "--print", action="store_const", const="dump", dest="mode", help="Alias for --dump" |
4761 |
+) |
4762 |
+modes.add_argument( |
4763 |
+ "-t", |
4764 |
+ "--test", |
4765 |
+ action="store_const", |
4766 |
+ const="test", |
4767 |
+ dest="mode", |
4768 |
+ help="Test if this system is affected by the GLSA(s) or set and output the GLSA ID(s)", |
4769 |
+) |
4770 |
+modes.add_argument( |
4771 |
+ "-p", |
4772 |
+ "--pretend", |
4773 |
+ action="store_const", |
4774 |
+ const="pretend", |
4775 |
+ dest="mode", |
4776 |
+ help="Show the necessary steps to remediate the system", |
4777 |
+) |
4778 |
+modes.add_argument( |
4779 |
+ "-f", |
4780 |
+ "--fix", |
4781 |
+ action="store_const", |
4782 |
+ const="fix", |
4783 |
+ dest="mode", |
4784 |
+ help="(experimental) Attempt to remediate the system based on the instructions given in the GLSA(s) or set. This will only upgrade (when an upgrade path exists) or remove packages", |
4785 |
+) |
4786 |
+modes.add_argument( |
4787 |
+ "-i", |
4788 |
+ "--inject", |
4789 |
+ action="store_const", |
4790 |
+ const="inject", |
4791 |
+ dest="mode", |
4792 |
+ help="Inject the given GLSA(s) into the glsa_injected file", |
4793 |
+) |
4794 |
+modes.add_argument( |
4795 |
+ "-m", |
4796 |
+ "--mail", |
4797 |
+ action="store_const", |
4798 |
+ const="mail", |
4799 |
+ dest="mode", |
4800 |
+ help="Send a mail with the given GLSAs to the administrator", |
4801 |
+) |
4802 |
+parser.add_argument( |
4803 |
+ "-V", "--version", action="store_true", help="Show information about glsa-check" |
4804 |
+) |
4805 |
+parser.add_argument( |
4806 |
+ "-q", |
4807 |
+ "--quiet", |
4808 |
+ action="store_true", |
4809 |
+ dest="quiet", |
4810 |
+ help="Be less verbose and do not send empty mail", |
4811 |
+) |
4812 |
+parser.add_argument( |
4813 |
+ "-v", "--verbose", action="store_true", dest="verbose", help="Print more messages" |
4814 |
+) |
4815 |
+parser.add_argument( |
4816 |
+ "-n", "--nocolor", action="store_true", help="Removes color from output" |
4817 |
+) |
4818 |
+parser.add_argument( |
4819 |
+ "-e", |
4820 |
+ "--emergelike", |
4821 |
+ action="store_false", |
4822 |
+ dest="least_change", |
4823 |
+ help="Upgrade to latest version (not least-change)", |
4824 |
+) |
4825 |
+parser.add_argument( |
4826 |
+ "-c", |
4827 |
+ "--cve", |
4828 |
+ action="store_true", |
4829 |
+ dest="list_cve", |
4830 |
+ help="Show CVE IDs in listing mode", |
4831 |
+) |
4832 |
+parser.add_argument( |
4833 |
+ "-r", |
4834 |
+ "--reverse", |
4835 |
+ action="store_true", |
4836 |
+ dest="reverse", |
4837 |
+ help="List GLSAs in reverse order", |
4838 |
+) |
4839 |
|
4840 |
options, params = parser.parse_known_args() |
4841 |
|
4842 |
if options.nocolor: |
4843 |
- nocolor() |
4844 |
+ nocolor() |
4845 |
|
4846 |
if options.version: |
4847 |
- sys.stderr.write("\n"+ __program__ + ", version " + __version__ + "\n") |
4848 |
- sys.stderr.write("Author: " + __author__ + "\n") |
4849 |
- sys.stderr.write("This program is licensed under the GPL, version 2\n\n") |
4850 |
- sys.exit(0) |
4851 |
+ sys.stderr.write("\n" + __program__ + ", version " + __version__ + "\n") |
4852 |
+ sys.stderr.write("Author: " + __author__ + "\n") |
4853 |
+ sys.stderr.write("This program is licensed under the GPL, version 2\n\n") |
4854 |
+ sys.exit(0) |
4855 |
|
4856 |
mode = options.mode |
4857 |
least_change = options.least_change |
4858 |
@@ -88,27 +155,34 @@ verbose = options.verbose |
4859 |
|
4860 |
# Sanity checking |
4861 |
if mode is None: |
4862 |
- sys.stderr.write("No mode given: what should I do?\n") |
4863 |
- parser.print_help() |
4864 |
- sys.exit(1) |
4865 |
+ sys.stderr.write("No mode given: what should I do?\n") |
4866 |
+ parser.print_help() |
4867 |
+ sys.exit(1) |
4868 |
elif mode != "list" and not params: |
4869 |
- sys.stderr.write("\nno GLSA given, so we'll do nothing for now. \n") |
4870 |
- sys.stderr.write("If you want to run on all GLSA please tell me so \n") |
4871 |
- sys.stderr.write("(specify \"all\" as parameter)\n\n") |
4872 |
- parser.print_help() |
4873 |
- sys.exit(1) |
4874 |
+ sys.stderr.write("\nno GLSA given, so we'll do nothing for now. \n") |
4875 |
+ sys.stderr.write("If you want to run on all GLSA please tell me so \n") |
4876 |
+ sys.stderr.write('(specify "all" as parameter)\n\n') |
4877 |
+ parser.print_help() |
4878 |
+ sys.exit(1) |
4879 |
elif mode in ["fix", "inject"] and os.geteuid() != 0: |
4880 |
- # we need root privileges for write access |
4881 |
- sys.stderr.write("\nThis tool needs root access to "+options.mode+" this GLSA\n\n") |
4882 |
- sys.exit(2) |
4883 |
+ # we need root privileges for write access |
4884 |
+ sys.stderr.write( |
4885 |
+ "\nThis tool needs root access to " + options.mode + " this GLSA\n\n" |
4886 |
+ ) |
4887 |
+ sys.exit(2) |
4888 |
elif mode == "list" and not params: |
4889 |
- params.append("affected") |
4890 |
+ params.append("affected") |
4891 |
|
4892 |
# delay this for speed increase |
4893 |
-from portage.glsa import (Glsa, GlsaTypeException, GlsaFormatException, |
4894 |
- get_applied_glsas, get_glsa_list) |
4895 |
- |
4896 |
-eroot = portage.settings['EROOT'] |
4897 |
+from portage.glsa import ( |
4898 |
+ Glsa, |
4899 |
+ GlsaTypeException, |
4900 |
+ GlsaFormatException, |
4901 |
+ get_applied_glsas, |
4902 |
+ get_glsa_list, |
4903 |
+) |
4904 |
+ |
4905 |
+eroot = portage.settings["EROOT"] |
4906 |
vardb = portage.db[eroot]["vartree"].dbapi |
4907 |
portdb = portage.db[eroot]["porttree"].dbapi |
4908 |
|
4909 |
@@ -120,254 +194,299 @@ todolist = [e for e in completelist if e not in checklist] |
4910 |
|
4911 |
glsalist = [] |
4912 |
if "new" in params: |
4913 |
- params.remove("new") |
4914 |
- sys.stderr.write("Warning: The 'new' glsa-list target has been removed, using 'affected'.\n") |
4915 |
- params.append("affected") |
4916 |
+ params.remove("new") |
4917 |
+ sys.stderr.write( |
4918 |
+ "Warning: The 'new' glsa-list target has been removed, using 'affected'.\n" |
4919 |
+ ) |
4920 |
+ params.append("affected") |
4921 |
|
4922 |
if "all" in params: |
4923 |
- glsalist = completelist |
4924 |
- params.remove("all") |
4925 |
+ glsalist = completelist |
4926 |
+ params.remove("all") |
4927 |
|
4928 |
if "affected" in params: |
4929 |
- for x in todolist: |
4930 |
- try: |
4931 |
- myglsa = Glsa(x, portage.settings, vardb, portdb) |
4932 |
- except (GlsaTypeException, GlsaFormatException) as e: |
4933 |
- if verbose: |
4934 |
- sys.stderr.write(("invalid GLSA: %s (error message was: %s)\n" % (x, e))) |
4935 |
- continue |
4936 |
- if myglsa.isVulnerable(): |
4937 |
- glsalist.append(x) |
4938 |
- params.remove("affected") |
4939 |
+ for x in todolist: |
4940 |
+ try: |
4941 |
+ myglsa = Glsa(x, portage.settings, vardb, portdb) |
4942 |
+ except (GlsaTypeException, GlsaFormatException) as e: |
4943 |
+ if verbose: |
4944 |
+ sys.stderr.write( |
4945 |
+ ("invalid GLSA: %s (error message was: %s)\n" % (x, e)) |
4946 |
+ ) |
4947 |
+ continue |
4948 |
+ if myglsa.isVulnerable(): |
4949 |
+ glsalist.append(x) |
4950 |
+ params.remove("affected") |
4951 |
|
4952 |
# remove invalid parameters |
4953 |
for p in params[:]: |
4954 |
- if not (p in completelist or os.path.exists(p)): |
4955 |
- sys.stderr.write(("(removing %s from parameter list as it isn't a valid GLSA specification)\n" % p)) |
4956 |
- params.remove(p) |
4957 |
+ if not (p in completelist or os.path.exists(p)): |
4958 |
+ sys.stderr.write( |
4959 |
+ ( |
4960 |
+ "(removing %s from parameter list as it isn't a valid GLSA specification)\n" |
4961 |
+ % p |
4962 |
+ ) |
4963 |
+ ) |
4964 |
+ params.remove(p) |
4965 |
|
4966 |
glsalist.extend([g for g in params if g not in glsalist]) |
4967 |
|
4968 |
+ |
4969 |
def summarylist(myglsalist, fd1=sys.stdout, fd2=sys.stderr, encoding="utf-8"): |
4970 |
- # Get to the raw streams in py3k before wrapping them with an encoded writer |
4971 |
- # to avoid writing bytes to a text stream (stdout/stderr are text streams |
4972 |
- # by default in py3k) |
4973 |
- if hasattr(fd1, "buffer"): |
4974 |
- fd1 = fd1.buffer |
4975 |
- if hasattr(fd2, "buffer"): |
4976 |
- fd2 = fd2.buffer |
4977 |
- fd1 = codecs.getwriter(encoding)(fd1) |
4978 |
- fd2 = codecs.getwriter(encoding)(fd2) |
4979 |
- if not quiet: |
4980 |
- fd2.write(white("[A]")+" means this GLSA was marked as applied (injected),\n") |
4981 |
- fd2.write(green("[U]")+" means the system is not affected and\n") |
4982 |
- fd2.write(red("[N]")+" indicates that the system might be affected.\n\n") |
4983 |
- |
4984 |
- for myid in sorted(myglsalist, reverse=options.reverse): |
4985 |
- try: |
4986 |
- myglsa = Glsa(myid, portage.settings, vardb, portdb) |
4987 |
- except (GlsaTypeException, GlsaFormatException) as e: |
4988 |
- if verbose: |
4989 |
- fd2.write(("invalid GLSA: %s (error message was: %s)\n" % (myid, e))) |
4990 |
- continue |
4991 |
- if myglsa.isInjected(): |
4992 |
- status = "[A]" |
4993 |
- color = white |
4994 |
- elif myglsa.isVulnerable(): |
4995 |
- status = "[N]" |
4996 |
- color = red |
4997 |
- else: |
4998 |
- status = "[U]" |
4999 |
- color = green |
5000 |
- |
5001 |
- if verbose: |
5002 |
- access = ("[%-8s] " % myglsa.access) |
5003 |
- else: |
5004 |
- access = "" |
5005 |
- |
5006 |
- fd1.write(color(myglsa.nr) + " " + color(status) + " " + color(access) + myglsa.title + " (") |
5007 |
- if not verbose: |
5008 |
- for pkg in list(myglsa.packages)[:3]: |
5009 |
- fd1.write(" " + pkg + " ") |
5010 |
- if len(myglsa.packages) > 3: |
5011 |
- fd1.write("... ") |
5012 |
- else: |
5013 |
- for cpv in myglsa.packages.keys(): |
5014 |
- pkg = myglsa.packages[cpv] |
5015 |
- for path in pkg: |
5016 |
- v_installed = reduce(operator.add, [match(v, vardb) for v in path["vul_atoms"]], []) |
5017 |
- u_installed = reduce(operator.add, [match(u, vardb) for u in path["unaff_atoms"]], []) |
5018 |
- mylist = sorted(set(v_installed).difference(set(u_installed))) |
5019 |
- if len(mylist) > 0: |
5020 |
- cpv = color(" ".join(mylist)) |
5021 |
- fd1.write(" " + cpv + " ") |
5022 |
- |
5023 |
- fd1.write(")") |
5024 |
- if list_cve: |
5025 |
- cve_ids = [] |
5026 |
- for r in myglsa.references: |
5027 |
- m = re.search(r'(CAN|CVE)-[\d-]+', r) |
5028 |
- if m is not None: |
5029 |
- cve_ids.append(m.group(0)) |
5030 |
- if cve_ids: |
5031 |
- fd1.write(" "+(",".join(cve_ids))) |
5032 |
- fd1.write("\n") |
5033 |
- return 0 |
5034 |
+ # Get to the raw streams in py3k before wrapping them with an encoded writer |
5035 |
+ # to avoid writing bytes to a text stream (stdout/stderr are text streams |
5036 |
+ # by default in py3k) |
5037 |
+ if hasattr(fd1, "buffer"): |
5038 |
+ fd1 = fd1.buffer |
5039 |
+ if hasattr(fd2, "buffer"): |
5040 |
+ fd2 = fd2.buffer |
5041 |
+ fd1 = codecs.getwriter(encoding)(fd1) |
5042 |
+ fd2 = codecs.getwriter(encoding)(fd2) |
5043 |
+ if not quiet: |
5044 |
+ fd2.write(white("[A]") + " means this GLSA was marked as applied (injected),\n") |
5045 |
+ fd2.write(green("[U]") + " means the system is not affected and\n") |
5046 |
+ fd2.write(red("[N]") + " indicates that the system might be affected.\n\n") |
5047 |
+ |
5048 |
+ for myid in sorted(myglsalist, reverse=options.reverse): |
5049 |
+ try: |
5050 |
+ myglsa = Glsa(myid, portage.settings, vardb, portdb) |
5051 |
+ except (GlsaTypeException, GlsaFormatException) as e: |
5052 |
+ if verbose: |
5053 |
+ fd2.write(("invalid GLSA: %s (error message was: %s)\n" % (myid, e))) |
5054 |
+ continue |
5055 |
+ if myglsa.isInjected(): |
5056 |
+ status = "[A]" |
5057 |
+ color = white |
5058 |
+ elif myglsa.isVulnerable(): |
5059 |
+ status = "[N]" |
5060 |
+ color = red |
5061 |
+ else: |
5062 |
+ status = "[U]" |
5063 |
+ color = green |
5064 |
+ |
5065 |
+ if verbose: |
5066 |
+ access = "[%-8s] " % myglsa.access |
5067 |
+ else: |
5068 |
+ access = "" |
5069 |
+ |
5070 |
+ fd1.write( |
5071 |
+ color(myglsa.nr) |
5072 |
+ + " " |
5073 |
+ + color(status) |
5074 |
+ + " " |
5075 |
+ + color(access) |
5076 |
+ + myglsa.title |
5077 |
+ + " (" |
5078 |
+ ) |
5079 |
+ if not verbose: |
5080 |
+ for pkg in list(myglsa.packages)[:3]: |
5081 |
+ fd1.write(" " + pkg + " ") |
5082 |
+ if len(myglsa.packages) > 3: |
5083 |
+ fd1.write("... ") |
5084 |
+ else: |
5085 |
+ for cpv in myglsa.packages.keys(): |
5086 |
+ pkg = myglsa.packages[cpv] |
5087 |
+ for path in pkg: |
5088 |
+ v_installed = reduce( |
5089 |
+ operator.add, [match(v, vardb) for v in path["vul_atoms"]], [] |
5090 |
+ ) |
5091 |
+ u_installed = reduce( |
5092 |
+ operator.add, [match(u, vardb) for u in path["unaff_atoms"]], [] |
5093 |
+ ) |
5094 |
+ mylist = sorted(set(v_installed).difference(set(u_installed))) |
5095 |
+ if len(mylist) > 0: |
5096 |
+ cpv = color(" ".join(mylist)) |
5097 |
+ fd1.write(" " + cpv + " ") |
5098 |
+ |
5099 |
+ fd1.write(")") |
5100 |
+ if list_cve: |
5101 |
+ cve_ids = [] |
5102 |
+ for r in myglsa.references: |
5103 |
+ m = re.search(r"(CAN|CVE)-[\d-]+", r) |
5104 |
+ if m is not None: |
5105 |
+ cve_ids.append(m.group(0)) |
5106 |
+ if cve_ids: |
5107 |
+ fd1.write(" " + (",".join(cve_ids))) |
5108 |
+ fd1.write("\n") |
5109 |
+ return 0 |
5110 |
+ |
5111 |
|
5112 |
if mode == "list": |
5113 |
- sys.exit(summarylist(glsalist)) |
5114 |
+ sys.exit(summarylist(glsalist)) |
5115 |
|
5116 |
# dump, fix, inject and fix are nearly the same code, only the glsa method call differs |
5117 |
if mode in ["dump", "fix", "inject", "pretend"]: |
5118 |
- for myid in glsalist: |
5119 |
- try: |
5120 |
- myglsa = Glsa(myid, portage.settings, vardb, portdb) |
5121 |
- except (GlsaTypeException, GlsaFormatException) as e: |
5122 |
- if verbose: |
5123 |
- sys.stderr.write(("invalid GLSA: %s (error message was: %s)\n" % (myid, e))) |
5124 |
- continue |
5125 |
- if mode == "dump": |
5126 |
- myglsa.dump() |
5127 |
- elif mode == "fix": |
5128 |
- if not quiet: |
5129 |
- sys.stdout.write("Fixing GLSA "+myid+"\n") |
5130 |
- if not myglsa.isVulnerable(): |
5131 |
- if not quiet: |
5132 |
- sys.stdout.write(">>> no vulnerable packages installed\n") |
5133 |
- else: |
5134 |
- if quiet: |
5135 |
- sys.stdout.write("Fixing GLSA "+myid+"\n") |
5136 |
- mergelist = myglsa.getMergeList(least_change=least_change) |
5137 |
- if mergelist == []: |
5138 |
- sys.stdout.write(">>> cannot fix GLSA, no unaffected packages available\n") |
5139 |
- sys.exit(2) |
5140 |
- for pkg in mergelist: |
5141 |
- sys.stdout.write(">>> merging "+pkg+"\n") |
5142 |
- # using emerge for the actual merging as it contains the dependency |
5143 |
- # code and we want to be consistent in behaviour. Also this functionality |
5144 |
- # will be integrated in emerge later, so it shouldn't hurt much. |
5145 |
- emergecmd = "emerge --oneshot" + (" --quiet" if quiet else "") + " =" + pkg |
5146 |
- if verbose: |
5147 |
- sys.stderr.write(emergecmd+"\n") |
5148 |
- exitcode = os.system(emergecmd) |
5149 |
- # system() returns the exitcode in the high byte of a 16bit integer |
5150 |
- if exitcode >= 1 << 8: |
5151 |
- exitcode >>= 8 |
5152 |
- if exitcode: |
5153 |
- sys.exit(exitcode) |
5154 |
- if len(mergelist): |
5155 |
- sys.stdout.write("\n") |
5156 |
- elif mode == "pretend": |
5157 |
- if not quiet: |
5158 |
- sys.stdout.write("Checking GLSA "+myid+"\n") |
5159 |
- if not myglsa.isVulnerable(): |
5160 |
- if not quiet: |
5161 |
- sys.stdout.write(">>> no vulnerable packages installed\n") |
5162 |
- else: |
5163 |
- if quiet: |
5164 |
- sys.stdout.write("Checking GLSA "+myid+"\n") |
5165 |
- mergedict = {} |
5166 |
- for (vuln, update) in myglsa.getAffectionTable(least_change=least_change): |
5167 |
- mergedict.setdefault(update, []).append(vuln) |
5168 |
- |
5169 |
- # first, extract the atoms that cannot be upgraded (where key == "") |
5170 |
- no_upgrades = [] |
5171 |
- sys.stdout.write(">>> The following updates will be performed for this GLSA:\n") |
5172 |
- if "" in mergedict: |
5173 |
- no_upgrades = mergedict[""] |
5174 |
- del mergedict[""] |
5175 |
- |
5176 |
- # see if anything is left that can be upgraded |
5177 |
- if mergedict: |
5178 |
- sys.stdout.write(">>> Updates that will be performed:\n") |
5179 |
- for (upd, vuln) in mergedict.items(): |
5180 |
- sys.stdout.write(" " + green(upd) + " (vulnerable: " + red(", ".join(vuln)) + ")\n") |
5181 |
- |
5182 |
- if no_upgrades: |
5183 |
- sys.stdout.write(">>> No upgrade path exists for these packages:\n") |
5184 |
- sys.stdout.write(" " + red(", ".join(no_upgrades)) + "\n") |
5185 |
- sys.stdout.write("\n") |
5186 |
- elif mode == "inject": |
5187 |
- sys.stdout.write("injecting " + myid + "\n") |
5188 |
- myglsa.inject() |
5189 |
- if not quiet: |
5190 |
- sys.stdout.write("\n") |
5191 |
- sys.exit(0) |
5192 |
+ for myid in glsalist: |
5193 |
+ try: |
5194 |
+ myglsa = Glsa(myid, portage.settings, vardb, portdb) |
5195 |
+ except (GlsaTypeException, GlsaFormatException) as e: |
5196 |
+ if verbose: |
5197 |
+ sys.stderr.write( |
5198 |
+ ("invalid GLSA: %s (error message was: %s)\n" % (myid, e)) |
5199 |
+ ) |
5200 |
+ continue |
5201 |
+ if mode == "dump": |
5202 |
+ myglsa.dump() |
5203 |
+ elif mode == "fix": |
5204 |
+ if not quiet: |
5205 |
+ sys.stdout.write("Fixing GLSA " + myid + "\n") |
5206 |
+ if not myglsa.isVulnerable(): |
5207 |
+ if not quiet: |
5208 |
+ sys.stdout.write(">>> no vulnerable packages installed\n") |
5209 |
+ else: |
5210 |
+ if quiet: |
5211 |
+ sys.stdout.write("Fixing GLSA " + myid + "\n") |
5212 |
+ mergelist = myglsa.getMergeList(least_change=least_change) |
5213 |
+ if mergelist == []: |
5214 |
+ sys.stdout.write( |
5215 |
+ ">>> cannot fix GLSA, no unaffected packages available\n" |
5216 |
+ ) |
5217 |
+ sys.exit(2) |
5218 |
+ for pkg in mergelist: |
5219 |
+ sys.stdout.write(">>> merging " + pkg + "\n") |
5220 |
+ # using emerge for the actual merging as it contains the dependency |
5221 |
+ # code and we want to be consistent in behaviour. Also this functionality |
5222 |
+ # will be integrated in emerge later, so it shouldn't hurt much. |
5223 |
+ emergecmd = ( |
5224 |
+ "emerge --oneshot" + (" --quiet" if quiet else "") + " =" + pkg |
5225 |
+ ) |
5226 |
+ if verbose: |
5227 |
+ sys.stderr.write(emergecmd + "\n") |
5228 |
+ exitcode = os.system(emergecmd) |
5229 |
+ # system() returns the exitcode in the high byte of a 16bit integer |
5230 |
+ if exitcode >= 1 << 8: |
5231 |
+ exitcode >>= 8 |
5232 |
+ if exitcode: |
5233 |
+ sys.exit(exitcode) |
5234 |
+ if len(mergelist): |
5235 |
+ sys.stdout.write("\n") |
5236 |
+ elif mode == "pretend": |
5237 |
+ if not quiet: |
5238 |
+ sys.stdout.write("Checking GLSA " + myid + "\n") |
5239 |
+ if not myglsa.isVulnerable(): |
5240 |
+ if not quiet: |
5241 |
+ sys.stdout.write(">>> no vulnerable packages installed\n") |
5242 |
+ else: |
5243 |
+ if quiet: |
5244 |
+ sys.stdout.write("Checking GLSA " + myid + "\n") |
5245 |
+ mergedict = {} |
5246 |
+ for (vuln, update) in myglsa.getAffectionTable( |
5247 |
+ least_change=least_change |
5248 |
+ ): |
5249 |
+ mergedict.setdefault(update, []).append(vuln) |
5250 |
+ |
5251 |
+ # first, extract the atoms that cannot be upgraded (where key == "") |
5252 |
+ no_upgrades = [] |
5253 |
+ sys.stdout.write( |
5254 |
+ ">>> The following updates will be performed for this GLSA:\n" |
5255 |
+ ) |
5256 |
+ if "" in mergedict: |
5257 |
+ no_upgrades = mergedict[""] |
5258 |
+ del mergedict[""] |
5259 |
+ |
5260 |
+ # see if anything is left that can be upgraded |
5261 |
+ if mergedict: |
5262 |
+ sys.stdout.write(">>> Updates that will be performed:\n") |
5263 |
+ for (upd, vuln) in mergedict.items(): |
5264 |
+ sys.stdout.write( |
5265 |
+ " " |
5266 |
+ + green(upd) |
5267 |
+ + " (vulnerable: " |
5268 |
+ + red(", ".join(vuln)) |
5269 |
+ + ")\n" |
5270 |
+ ) |
5271 |
+ |
5272 |
+ if no_upgrades: |
5273 |
+ sys.stdout.write(">>> No upgrade path exists for these packages:\n") |
5274 |
+ sys.stdout.write(" " + red(", ".join(no_upgrades)) + "\n") |
5275 |
+ sys.stdout.write("\n") |
5276 |
+ elif mode == "inject": |
5277 |
+ sys.stdout.write("injecting " + myid + "\n") |
5278 |
+ myglsa.inject() |
5279 |
+ if not quiet: |
5280 |
+ sys.stdout.write("\n") |
5281 |
+ sys.exit(0) |
5282 |
|
5283 |
# test is a bit different as Glsa.test() produces no output |
5284 |
if mode == "test": |
5285 |
- outputlist = [] |
5286 |
- for myid in glsalist: |
5287 |
- try: |
5288 |
- myglsa = Glsa(myid, portage.settings, vardb, portdb) |
5289 |
- except (GlsaTypeException, GlsaFormatException) as e: |
5290 |
- if verbose: |
5291 |
- sys.stderr.write(("invalid GLSA: %s (error message was: %s)\n" % (myid, e))) |
5292 |
- continue |
5293 |
- if myglsa.isVulnerable(): |
5294 |
- outputlist.append(str(myglsa.nr)) |
5295 |
- if len(outputlist) > 0: |
5296 |
- sys.stderr.write("This system is affected by the following GLSAs:\n") |
5297 |
- if verbose: |
5298 |
- summarylist(outputlist) |
5299 |
- else: |
5300 |
- sys.stdout.write("\n".join(outputlist)+"\n") |
5301 |
- sys.exit(6) |
5302 |
- else: |
5303 |
- sys.stderr.write("This system is not affected by any of the listed GLSAs\n") |
5304 |
- sys.exit(0) |
5305 |
+ outputlist = [] |
5306 |
+ for myid in glsalist: |
5307 |
+ try: |
5308 |
+ myglsa = Glsa(myid, portage.settings, vardb, portdb) |
5309 |
+ except (GlsaTypeException, GlsaFormatException) as e: |
5310 |
+ if verbose: |
5311 |
+ sys.stderr.write( |
5312 |
+ ("invalid GLSA: %s (error message was: %s)\n" % (myid, e)) |
5313 |
+ ) |
5314 |
+ continue |
5315 |
+ if myglsa.isVulnerable(): |
5316 |
+ outputlist.append(str(myglsa.nr)) |
5317 |
+ if len(outputlist) > 0: |
5318 |
+ sys.stderr.write("This system is affected by the following GLSAs:\n") |
5319 |
+ if verbose: |
5320 |
+ summarylist(outputlist) |
5321 |
+ else: |
5322 |
+ sys.stdout.write("\n".join(outputlist) + "\n") |
5323 |
+ sys.exit(6) |
5324 |
+ else: |
5325 |
+ sys.stderr.write("This system is not affected by any of the listed GLSAs\n") |
5326 |
+ sys.exit(0) |
5327 |
|
5328 |
# mail mode as requested by solar |
5329 |
if mode == "mail": |
5330 |
- import socket |
5331 |
- from io import BytesIO |
5332 |
- from email.mime.text import MIMEText |
5333 |
- import portage.mail |
5334 |
- |
5335 |
- # color doesn't make any sense for mail |
5336 |
- nocolor() |
5337 |
- |
5338 |
- if "PORTAGE_ELOG_MAILURI" in portage.settings: |
5339 |
- myrecipient = portage.settings["PORTAGE_ELOG_MAILURI"].split()[0] |
5340 |
- else: |
5341 |
- myrecipient = "root@localhost" |
5342 |
- |
5343 |
- if "PORTAGE_ELOG_MAILFROM" in portage.settings: |
5344 |
- myfrom = portage.settings["PORTAGE_ELOG_MAILFROM"] |
5345 |
- else: |
5346 |
- myfrom = "glsa-check" |
5347 |
- |
5348 |
- mysubject = "[glsa-check] Summary for %s" % socket.getfqdn() |
5349 |
- |
5350 |
- # need a file object for summarylist() |
5351 |
- myfd = BytesIO() |
5352 |
- line = "GLSA Summary report for host %s\n" % socket.getfqdn() |
5353 |
- myfd.write(line.encode("utf-8")) |
5354 |
- line = "(Command was: %s)\n\n" % " ".join(sys.argv) |
5355 |
- myfd.write(line.encode("utf-8")) |
5356 |
- summarylist(glsalist, fd1=myfd, fd2=myfd) |
5357 |
- summary = myfd.getvalue().decode("utf-8") |
5358 |
- myfd.close() |
5359 |
- |
5360 |
- myattachments = [] |
5361 |
- for myid in glsalist: |
5362 |
- try: |
5363 |
- myglsa = Glsa(myid, portage.settings, vardb, portdb) |
5364 |
- except (GlsaTypeException, GlsaFormatException) as e: |
5365 |
- if verbose: |
5366 |
- sys.stderr.write(("invalid GLSA: %s (error message was: %s)\n" % (myid, e))) |
5367 |
- continue |
5368 |
- myfd = BytesIO() |
5369 |
- myglsa.dump(outstream=myfd) |
5370 |
- attachment = myfd.getvalue().decode("utf-8") |
5371 |
- myattachments.append(MIMEText(attachment, _charset="utf8")) |
5372 |
- myfd.close() |
5373 |
- |
5374 |
- if glsalist or not quiet: |
5375 |
- mymessage = portage.mail.create_message(myfrom, myrecipient, mysubject, summary, myattachments) |
5376 |
- portage.mail.send_mail(portage.settings, mymessage) |
5377 |
- |
5378 |
- sys.exit(0) |
5379 |
+ import socket |
5380 |
+ from io import BytesIO |
5381 |
+ from email.mime.text import MIMEText |
5382 |
+ import portage.mail |
5383 |
+ |
5384 |
+ # color doesn't make any sense for mail |
5385 |
+ nocolor() |
5386 |
+ |
5387 |
+ if "PORTAGE_ELOG_MAILURI" in portage.settings: |
5388 |
+ myrecipient = portage.settings["PORTAGE_ELOG_MAILURI"].split()[0] |
5389 |
+ else: |
5390 |
+ myrecipient = "root@localhost" |
5391 |
+ |
5392 |
+ if "PORTAGE_ELOG_MAILFROM" in portage.settings: |
5393 |
+ myfrom = portage.settings["PORTAGE_ELOG_MAILFROM"] |
5394 |
+ else: |
5395 |
+ myfrom = "glsa-check" |
5396 |
+ |
5397 |
+ mysubject = "[glsa-check] Summary for %s" % socket.getfqdn() |
5398 |
+ |
5399 |
+ # need a file object for summarylist() |
5400 |
+ myfd = BytesIO() |
5401 |
+ line = "GLSA Summary report for host %s\n" % socket.getfqdn() |
5402 |
+ myfd.write(line.encode("utf-8")) |
5403 |
+ line = "(Command was: %s)\n\n" % " ".join(sys.argv) |
5404 |
+ myfd.write(line.encode("utf-8")) |
5405 |
+ summarylist(glsalist, fd1=myfd, fd2=myfd) |
5406 |
+ summary = myfd.getvalue().decode("utf-8") |
5407 |
+ myfd.close() |
5408 |
+ |
5409 |
+ myattachments = [] |
5410 |
+ for myid in glsalist: |
5411 |
+ try: |
5412 |
+ myglsa = Glsa(myid, portage.settings, vardb, portdb) |
5413 |
+ except (GlsaTypeException, GlsaFormatException) as e: |
5414 |
+ if verbose: |
5415 |
+ sys.stderr.write( |
5416 |
+ ("invalid GLSA: %s (error message was: %s)\n" % (myid, e)) |
5417 |
+ ) |
5418 |
+ continue |
5419 |
+ myfd = BytesIO() |
5420 |
+ myglsa.dump(outstream=myfd) |
5421 |
+ attachment = myfd.getvalue().decode("utf-8") |
5422 |
+ myattachments.append(MIMEText(attachment, _charset="utf8")) |
5423 |
+ myfd.close() |
5424 |
+ |
5425 |
+ if glsalist or not quiet: |
5426 |
+ mymessage = portage.mail.create_message( |
5427 |
+ myfrom, myrecipient, mysubject, summary, myattachments |
5428 |
+ ) |
5429 |
+ portage.mail.send_mail(portage.settings, mymessage) |
5430 |
+ |
5431 |
+ sys.exit(0) |
5432 |
|
5433 |
# something wrong here, all valid paths are covered with sys.exit() |
5434 |
sys.stderr.write("nothing more to do\n") |
5435 |
|
5436 |
diff --git a/bin/pid-ns-init b/bin/pid-ns-init |
5437 |
index b9bf56a7b..6bac5961c 100644 |
5438 |
--- a/bin/pid-ns-init |
5439 |
+++ b/bin/pid-ns-init |
5440 |
@@ -57,20 +57,22 @@ def preexec_fn(uid, gid, groups, umask): |
5441 |
os.umask(umask) |
5442 |
|
5443 |
# CPython >= 3 subprocess.Popen handles this internally. |
5444 |
- if platform.python_implementation() != 'CPython': |
5445 |
+ if platform.python_implementation() != "CPython": |
5446 |
for signum in ( |
5447 |
- signal.SIGHUP, |
5448 |
- signal.SIGINT, |
5449 |
- signal.SIGPIPE, |
5450 |
- signal.SIGQUIT, |
5451 |
- signal.SIGTERM, |
5452 |
+ signal.SIGHUP, |
5453 |
+ signal.SIGINT, |
5454 |
+ signal.SIGPIPE, |
5455 |
+ signal.SIGQUIT, |
5456 |
+ signal.SIGTERM, |
5457 |
): |
5458 |
signal.signal(signum, signal.SIG_DFL) |
5459 |
|
5460 |
|
5461 |
def main(argv): |
5462 |
if len(argv) < 2: |
5463 |
- return 'Usage: {} <main-child-pid> or <uid> <gid> <groups> <umask> <pass_fds> <binary> <argv0> [arg]..'.format(argv[0]) |
5464 |
+ return "Usage: {} <main-child-pid> or <uid> <gid> <groups> <umask> <pass_fds> <binary> <argv0> [arg]..".format( |
5465 |
+ argv[0] |
5466 |
+ ) |
5467 |
|
5468 |
if len(argv) == 2: |
5469 |
# The child process is init (pid 1) in a child pid namespace, and |
5470 |
@@ -82,15 +84,23 @@ def main(argv): |
5471 |
proc = None |
5472 |
else: |
5473 |
# The current process is init (pid 1) in a child pid namespace. |
5474 |
- uid, gid, groups, umask, pass_fds, binary, args = argv[1], argv[2], argv[3], argv[4], tuple(int(fd) for fd in argv[5].split(',')), argv[6], argv[7:] |
5475 |
+ uid, gid, groups, umask, pass_fds, binary, args = ( |
5476 |
+ argv[1], |
5477 |
+ argv[2], |
5478 |
+ argv[3], |
5479 |
+ argv[4], |
5480 |
+ tuple(int(fd) for fd in argv[5].split(",")), |
5481 |
+ argv[6], |
5482 |
+ argv[7:], |
5483 |
+ ) |
5484 |
uid = int(uid) if uid else None |
5485 |
gid = int(gid) if gid else None |
5486 |
- groups = tuple(int(group) for group in groups.split(',')) if groups else None |
5487 |
+ groups = tuple(int(group) for group in groups.split(",")) if groups else None |
5488 |
umask = int(umask) if umask else None |
5489 |
|
5490 |
popen_kwargs = { |
5491 |
- 'preexec_fn': functools.partial(preexec_fn, uid, gid, groups, umask), |
5492 |
- 'pass_fds': pass_fds, |
5493 |
+ "preexec_fn": functools.partial(preexec_fn, uid, gid, groups, umask), |
5494 |
+ "pass_fds": pass_fds, |
5495 |
} |
5496 |
|
5497 |
# Obtain the current nice value, which will be potentially be |
5498 |
@@ -128,12 +138,16 @@ def main(argv): |
5499 |
|
5500 |
# If setsid has been called, use kill(0, signum) to |
5501 |
# forward signals to the entire process group. |
5502 |
- sig_handler = functools.partial(forward_kill_signal, 0 if setsid else main_child_pid) |
5503 |
+ sig_handler = functools.partial( |
5504 |
+ forward_kill_signal, 0 if setsid else main_child_pid |
5505 |
+ ) |
5506 |
for signum in KILL_SIGNALS: |
5507 |
signal.signal(signum, sig_handler) |
5508 |
|
5509 |
# For correct operation of Ctrl+Z, forward SIGTSTP and SIGCONT. |
5510 |
- sigtstp_sigcont_handler = functools.partial(forward_sigtstp_sigcont, 0 if setsid else main_child_pid) |
5511 |
+ sigtstp_sigcont_handler = functools.partial( |
5512 |
+ forward_sigtstp_sigcont, 0 if setsid else main_child_pid |
5513 |
+ ) |
5514 |
for signum in SIGTSTP_SIGCONT: |
5515 |
signal.signal(signum, sigtstp_sigcont_handler) |
5516 |
|
5517 |
@@ -163,5 +177,5 @@ def main(argv): |
5518 |
return 127 |
5519 |
|
5520 |
|
5521 |
-if __name__ == '__main__': |
5522 |
+if __name__ == "__main__": |
5523 |
sys.exit(main(sys.argv)) |
5524 |
|
5525 |
diff --git a/bin/portageq b/bin/portageq |
5526 |
index 1c7e27a99..8338d4e14 100755 |
5527 |
--- a/bin/portageq |
5528 |
+++ b/bin/portageq |
5529 |
@@ -5,79 +5,95 @@ |
5530 |
import argparse |
5531 |
import signal |
5532 |
import sys |
5533 |
+ |
5534 |
# This block ensures that ^C interrupts are handled quietly. |
5535 |
try: |
5536 |
|
5537 |
- def exithandler(signum, _frame): |
5538 |
- signal.signal(signal.SIGINT, signal.SIG_IGN) |
5539 |
- signal.signal(signal.SIGTERM, signal.SIG_IGN) |
5540 |
- sys.exit(128 + signum) |
5541 |
+ def exithandler(signum, _frame): |
5542 |
+ signal.signal(signal.SIGINT, signal.SIG_IGN) |
5543 |
+ signal.signal(signal.SIGTERM, signal.SIG_IGN) |
5544 |
+ sys.exit(128 + signum) |
5545 |
|
5546 |
- signal.signal(signal.SIGINT, exithandler) |
5547 |
- signal.signal(signal.SIGTERM, exithandler) |
5548 |
+ signal.signal(signal.SIGINT, exithandler) |
5549 |
+ signal.signal(signal.SIGTERM, exithandler) |
5550 |
|
5551 |
except KeyboardInterrupt: |
5552 |
- sys.exit(128 + signal.SIGINT) |
5553 |
+ sys.exit(128 + signal.SIGINT) |
5554 |
|
5555 |
import os |
5556 |
import types |
5557 |
|
5558 |
-if os.path.isfile(os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), ".portage_not_installed")): |
5559 |
- pym_paths = [os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), "lib")] |
5560 |
- sys.path.insert(0, pym_paths[0]) |
5561 |
+if os.path.isfile( |
5562 |
+ os.path.join( |
5563 |
+ os.path.dirname(os.path.dirname(os.path.realpath(__file__))), |
5564 |
+ ".portage_not_installed", |
5565 |
+ ) |
5566 |
+): |
5567 |
+ pym_paths = [ |
5568 |
+ os.path.join( |
5569 |
+ os.path.dirname(os.path.dirname(os.path.realpath(__file__))), "lib" |
5570 |
+ ) |
5571 |
+ ] |
5572 |
+ sys.path.insert(0, pym_paths[0]) |
5573 |
else: |
5574 |
- import sysconfig |
5575 |
- pym_paths = [ |
5576 |
- os.path.join(sysconfig.get_path("purelib"), x) for x in ("_emerge", "portage") |
5577 |
- ] |
5578 |
+ import sysconfig |
5579 |
+ |
5580 |
+ pym_paths = [ |
5581 |
+ os.path.join(sysconfig.get_path("purelib"), x) for x in ("_emerge", "portage") |
5582 |
+ ] |
5583 |
# Avoid sandbox violations after Python upgrade. |
5584 |
if os.environ.get("SANDBOX_ON") == "1": |
5585 |
- sandbox_write = os.environ.get("SANDBOX_WRITE", "").split(":") |
5586 |
- for pym_path in pym_paths: |
5587 |
- if pym_path not in sandbox_write: |
5588 |
- sandbox_write.append(pym_path) |
5589 |
- os.environ["SANDBOX_WRITE"] = ":".join(filter(None, sandbox_write)) |
5590 |
- del pym_path, sandbox_write |
5591 |
+ sandbox_write = os.environ.get("SANDBOX_WRITE", "").split(":") |
5592 |
+ for pym_path in pym_paths: |
5593 |
+ if pym_path not in sandbox_write: |
5594 |
+ sandbox_write.append(pym_path) |
5595 |
+ os.environ["SANDBOX_WRITE"] = ":".join(filter(None, sandbox_write)) |
5596 |
+ del pym_path, sandbox_write |
5597 |
del pym_paths |
5598 |
|
5599 |
import portage |
5600 |
+ |
5601 |
portage._internal_caller = True |
5602 |
from portage import os |
5603 |
from portage.eapi import eapi_has_repo_deps |
5604 |
from portage.util import writemsg, writemsg_stdout |
5605 |
-portage.proxy.lazyimport.lazyimport(globals(), |
5606 |
- 're', |
5607 |
- 'subprocess', |
5608 |
- '_emerge.Package:Package', |
5609 |
- '_emerge.RootConfig:RootConfig', |
5610 |
- '_emerge.is_valid_package_atom:insert_category_into_atom', |
5611 |
- 'portage.dbapi._expand_new_virt:expand_new_virt', |
5612 |
- 'portage._sets.base:InternalPackageSet', |
5613 |
- 'portage.util._eventloop.global_event_loop:global_event_loop', |
5614 |
- 'portage.xml.metadata:MetaDataXML' |
5615 |
+ |
5616 |
+portage.proxy.lazyimport.lazyimport( |
5617 |
+ globals(), |
5618 |
+ "re", |
5619 |
+ "subprocess", |
5620 |
+ "_emerge.Package:Package", |
5621 |
+ "_emerge.RootConfig:RootConfig", |
5622 |
+ "_emerge.is_valid_package_atom:insert_category_into_atom", |
5623 |
+ "portage.dbapi._expand_new_virt:expand_new_virt", |
5624 |
+ "portage._sets.base:InternalPackageSet", |
5625 |
+ "portage.util._eventloop.global_event_loop:global_event_loop", |
5626 |
+ "portage.xml.metadata:MetaDataXML", |
5627 |
) |
5628 |
|
5629 |
+ |
5630 |
def eval_atom_use(atom): |
5631 |
- if 'USE' in os.environ: |
5632 |
- use = frozenset(os.environ['USE'].split()) |
5633 |
- atom = atom.evaluate_conditionals(use) |
5634 |
- return atom |
5635 |
+ if "USE" in os.environ: |
5636 |
+ use = frozenset(os.environ["USE"].split()) |
5637 |
+ atom = atom.evaluate_conditionals(use) |
5638 |
+ return atom |
5639 |
|
5640 |
|
5641 |
def uses_configroot(function): |
5642 |
- function.uses_configroot = True |
5643 |
- return function |
5644 |
+ function.uses_configroot = True |
5645 |
+ return function |
5646 |
|
5647 |
|
5648 |
def uses_eroot(function): |
5649 |
- function.uses_eroot = True |
5650 |
- return function |
5651 |
+ function.uses_eroot = True |
5652 |
+ return function |
5653 |
+ |
5654 |
|
5655 |
# global to hold all function docstrings to be used for argparse help. |
5656 |
# Avoids python compilation level 2 optimization troubles. |
5657 |
docstrings = {} |
5658 |
|
5659 |
-#----------------------------------------------------------------------------- |
5660 |
+# ----------------------------------------------------------------------------- |
5661 |
# |
5662 |
# To add functionality to this tool, add a function below. |
5663 |
# |
5664 |
@@ -100,573 +116,615 @@ docstrings = {} |
5665 |
# and will automaticly add a command by the same name as the function! |
5666 |
# |
5667 |
|
5668 |
+ |
5669 |
@uses_eroot |
5670 |
def has_version(argv): |
5671 |
- if len(argv) < 2: |
5672 |
- print("ERROR: insufficient parameters!") |
5673 |
- return 3 |
5674 |
- |
5675 |
- warnings = [] |
5676 |
- |
5677 |
- allow_repo = atom_validate_strict is False or eapi_has_repo_deps(eapi) |
5678 |
- try: |
5679 |
- atom = portage.dep.Atom(argv[1], allow_repo=allow_repo) |
5680 |
- except portage.exception.InvalidAtom: |
5681 |
- if atom_validate_strict: |
5682 |
- portage.writemsg("ERROR: Invalid atom: '%s'\n" % argv[1], |
5683 |
- noiselevel=-1) |
5684 |
- return 2 |
5685 |
- else: |
5686 |
- atom = argv[1] |
5687 |
- else: |
5688 |
- if atom_validate_strict: |
5689 |
- try: |
5690 |
- atom = portage.dep.Atom(argv[1], allow_repo=allow_repo, eapi=eapi) |
5691 |
- except portage.exception.InvalidAtom as e: |
5692 |
- warnings.append("QA Notice: %s: %s" % ('has_version', e)) |
5693 |
- atom = eval_atom_use(atom) |
5694 |
- |
5695 |
- if warnings: |
5696 |
- elog('eqawarn', warnings) |
5697 |
- |
5698 |
- try: |
5699 |
- mylist = portage.db[argv[0]]["vartree"].dbapi.match(atom) |
5700 |
- if mylist: |
5701 |
- return 0 |
5702 |
- else: |
5703 |
- return 1 |
5704 |
- except KeyError: |
5705 |
- return 1 |
5706 |
- except portage.exception.InvalidAtom: |
5707 |
- portage.writemsg("ERROR: Invalid atom: '%s'\n" % argv[1], |
5708 |
- noiselevel=-1) |
5709 |
- return 2 |
5710 |
- |
5711 |
-docstrings['has_version'] = """<eroot> <category/package> |
5712 |
+ if len(argv) < 2: |
5713 |
+ print("ERROR: insufficient parameters!") |
5714 |
+ return 3 |
5715 |
+ |
5716 |
+ warnings = [] |
5717 |
+ |
5718 |
+ allow_repo = atom_validate_strict is False or eapi_has_repo_deps(eapi) |
5719 |
+ try: |
5720 |
+ atom = portage.dep.Atom(argv[1], allow_repo=allow_repo) |
5721 |
+ except portage.exception.InvalidAtom: |
5722 |
+ if atom_validate_strict: |
5723 |
+ portage.writemsg("ERROR: Invalid atom: '%s'\n" % argv[1], noiselevel=-1) |
5724 |
+ return 2 |
5725 |
+ else: |
5726 |
+ atom = argv[1] |
5727 |
+ else: |
5728 |
+ if atom_validate_strict: |
5729 |
+ try: |
5730 |
+ atom = portage.dep.Atom(argv[1], allow_repo=allow_repo, eapi=eapi) |
5731 |
+ except portage.exception.InvalidAtom as e: |
5732 |
+ warnings.append("QA Notice: %s: %s" % ("has_version", e)) |
5733 |
+ atom = eval_atom_use(atom) |
5734 |
+ |
5735 |
+ if warnings: |
5736 |
+ elog("eqawarn", warnings) |
5737 |
+ |
5738 |
+ try: |
5739 |
+ mylist = portage.db[argv[0]]["vartree"].dbapi.match(atom) |
5740 |
+ if mylist: |
5741 |
+ return 0 |
5742 |
+ else: |
5743 |
+ return 1 |
5744 |
+ except KeyError: |
5745 |
+ return 1 |
5746 |
+ except portage.exception.InvalidAtom: |
5747 |
+ portage.writemsg("ERROR: Invalid atom: '%s'\n" % argv[1], noiselevel=-1) |
5748 |
+ return 2 |
5749 |
+ |
5750 |
+ |
5751 |
+docstrings[ |
5752 |
+ "has_version" |
5753 |
+] = """<eroot> <category/package> |
5754 |
Return code 0 if it's available, 1 otherwise. |
5755 |
""" |
5756 |
-has_version.__doc__ = docstrings['has_version'] |
5757 |
+has_version.__doc__ = docstrings["has_version"] |
5758 |
|
5759 |
|
5760 |
@uses_eroot |
5761 |
def best_version(argv): |
5762 |
- if len(argv) < 2: |
5763 |
- print("ERROR: insufficient parameters!") |
5764 |
- return 3 |
5765 |
- |
5766 |
- warnings = [] |
5767 |
- |
5768 |
- allow_repo = atom_validate_strict is False or eapi_has_repo_deps(eapi) |
5769 |
- try: |
5770 |
- atom = portage.dep.Atom(argv[1], allow_repo=allow_repo) |
5771 |
- except portage.exception.InvalidAtom: |
5772 |
- if atom_validate_strict: |
5773 |
- portage.writemsg("ERROR: Invalid atom: '%s'\n" % argv[1], |
5774 |
- noiselevel=-1) |
5775 |
- return 2 |
5776 |
- else: |
5777 |
- atom = argv[1] |
5778 |
- else: |
5779 |
- if atom_validate_strict: |
5780 |
- try: |
5781 |
- atom = portage.dep.Atom(argv[1], allow_repo=allow_repo, eapi=eapi) |
5782 |
- except portage.exception.InvalidAtom as e: |
5783 |
- warnings.append("QA Notice: %s: %s" % ('best_version', e)) |
5784 |
- atom = eval_atom_use(atom) |
5785 |
- |
5786 |
- if warnings: |
5787 |
- elog('eqawarn', warnings) |
5788 |
- |
5789 |
- try: |
5790 |
- mylist = portage.db[argv[0]]["vartree"].dbapi.match(atom) |
5791 |
- print(portage.best(mylist)) |
5792 |
- except KeyError: |
5793 |
- return 1 |
5794 |
- |
5795 |
-docstrings['best_version'] = """<eroot> <category/package> |
5796 |
+ if len(argv) < 2: |
5797 |
+ print("ERROR: insufficient parameters!") |
5798 |
+ return 3 |
5799 |
+ |
5800 |
+ warnings = [] |
5801 |
+ |
5802 |
+ allow_repo = atom_validate_strict is False or eapi_has_repo_deps(eapi) |
5803 |
+ try: |
5804 |
+ atom = portage.dep.Atom(argv[1], allow_repo=allow_repo) |
5805 |
+ except portage.exception.InvalidAtom: |
5806 |
+ if atom_validate_strict: |
5807 |
+ portage.writemsg("ERROR: Invalid atom: '%s'\n" % argv[1], noiselevel=-1) |
5808 |
+ return 2 |
5809 |
+ else: |
5810 |
+ atom = argv[1] |
5811 |
+ else: |
5812 |
+ if atom_validate_strict: |
5813 |
+ try: |
5814 |
+ atom = portage.dep.Atom(argv[1], allow_repo=allow_repo, eapi=eapi) |
5815 |
+ except portage.exception.InvalidAtom as e: |
5816 |
+ warnings.append("QA Notice: %s: %s" % ("best_version", e)) |
5817 |
+ atom = eval_atom_use(atom) |
5818 |
+ |
5819 |
+ if warnings: |
5820 |
+ elog("eqawarn", warnings) |
5821 |
+ |
5822 |
+ try: |
5823 |
+ mylist = portage.db[argv[0]]["vartree"].dbapi.match(atom) |
5824 |
+ print(portage.best(mylist)) |
5825 |
+ except KeyError: |
5826 |
+ return 1 |
5827 |
+ |
5828 |
+ |
5829 |
+docstrings[ |
5830 |
+ "best_version" |
5831 |
+] = """<eroot> <category/package> |
5832 |
Returns highest installed matching category/package-version (without .ebuild). |
5833 |
""" |
5834 |
-best_version.__doc__ = docstrings['best_version'] |
5835 |
+best_version.__doc__ = docstrings["best_version"] |
5836 |
|
5837 |
|
5838 |
@uses_eroot |
5839 |
def mass_best_version(argv): |
5840 |
- if len(argv) < 2: |
5841 |
- print("ERROR: insufficient parameters!") |
5842 |
- return 2 |
5843 |
- try: |
5844 |
- for pack in argv[1:]: |
5845 |
- mylist = portage.db[argv[0]]['vartree'].dbapi.match(pack) |
5846 |
- print('%s:%s' % (pack, portage.best(mylist))) |
5847 |
- except KeyError: |
5848 |
- return 1 |
5849 |
- |
5850 |
-docstrings['mass_best_version'] = """<eroot> [<category/package>]+ |
5851 |
+ if len(argv) < 2: |
5852 |
+ print("ERROR: insufficient parameters!") |
5853 |
+ return 2 |
5854 |
+ try: |
5855 |
+ for pack in argv[1:]: |
5856 |
+ mylist = portage.db[argv[0]]["vartree"].dbapi.match(pack) |
5857 |
+ print("%s:%s" % (pack, portage.best(mylist))) |
5858 |
+ except KeyError: |
5859 |
+ return 1 |
5860 |
+ |
5861 |
+ |
5862 |
+docstrings[ |
5863 |
+ "mass_best_version" |
5864 |
+] = """<eroot> [<category/package>]+ |
5865 |
Returns category/package-version (without .ebuild). |
5866 |
""" |
5867 |
-mass_best_version.__doc__ = docstrings['mass_best_version'] |
5868 |
+mass_best_version.__doc__ = docstrings["mass_best_version"] |
5869 |
|
5870 |
|
5871 |
@uses_eroot |
5872 |
def metadata(argv): |
5873 |
- if len(argv) < 4: |
5874 |
- print('ERROR: insufficient parameters!', file=sys.stderr) |
5875 |
- return 2 |
5876 |
- |
5877 |
- eroot, pkgtype, pkgspec = argv[0:3] |
5878 |
- metakeys = argv[3:] |
5879 |
- type_map = { |
5880 |
- 'ebuild': 'porttree', |
5881 |
- 'binary': 'bintree', |
5882 |
- 'installed': 'vartree' |
5883 |
- } |
5884 |
- if pkgtype not in type_map: |
5885 |
- print("Unrecognized package type: '%s'" % pkgtype, file=sys.stderr) |
5886 |
- return 1 |
5887 |
- trees = portage.db |
5888 |
- repo = portage.dep.dep_getrepo(pkgspec) |
5889 |
- pkgspec = portage.dep.remove_slot(pkgspec) |
5890 |
- try: |
5891 |
- values = trees[eroot][type_map[pkgtype]].dbapi.aux_get( |
5892 |
- pkgspec, metakeys, myrepo=repo) |
5893 |
- writemsg_stdout(''.join('%s\n' % x for x in values), noiselevel=-1) |
5894 |
- except KeyError: |
5895 |
- print("Package not found: '%s'" % pkgspec, file=sys.stderr) |
5896 |
- return 1 |
5897 |
- |
5898 |
-docstrings['metadata'] = """ |
5899 |
+ if len(argv) < 4: |
5900 |
+ print("ERROR: insufficient parameters!", file=sys.stderr) |
5901 |
+ return 2 |
5902 |
+ |
5903 |
+ eroot, pkgtype, pkgspec = argv[0:3] |
5904 |
+ metakeys = argv[3:] |
5905 |
+ type_map = {"ebuild": "porttree", "binary": "bintree", "installed": "vartree"} |
5906 |
+ if pkgtype not in type_map: |
5907 |
+ print("Unrecognized package type: '%s'" % pkgtype, file=sys.stderr) |
5908 |
+ return 1 |
5909 |
+ trees = portage.db |
5910 |
+ repo = portage.dep.dep_getrepo(pkgspec) |
5911 |
+ pkgspec = portage.dep.remove_slot(pkgspec) |
5912 |
+ try: |
5913 |
+ values = trees[eroot][type_map[pkgtype]].dbapi.aux_get( |
5914 |
+ pkgspec, metakeys, myrepo=repo |
5915 |
+ ) |
5916 |
+ writemsg_stdout("".join("%s\n" % x for x in values), noiselevel=-1) |
5917 |
+ except KeyError: |
5918 |
+ print("Package not found: '%s'" % pkgspec, file=sys.stderr) |
5919 |
+ return 1 |
5920 |
+ |
5921 |
+ |
5922 |
+docstrings[ |
5923 |
+ "metadata" |
5924 |
+] = """ |
5925 |
<eroot> <pkgtype> <category/package> [<key>]+ |
5926 |
Returns metadata values for the specified package. |
5927 |
Available keys: %s |
5928 |
-""" % ','.join(sorted(x for x in portage.auxdbkeys)) |
5929 |
-metadata.__doc__ = docstrings['metadata'] |
5930 |
+""" % ",".join( |
5931 |
+ sorted(x for x in portage.auxdbkeys) |
5932 |
+) |
5933 |
+metadata.__doc__ = docstrings["metadata"] |
5934 |
|
5935 |
|
5936 |
@uses_eroot |
5937 |
def contents(argv): |
5938 |
- if len(argv) != 2: |
5939 |
- print("ERROR: expected 2 parameters, got %d!" % len(argv)) |
5940 |
- return 2 |
5941 |
- |
5942 |
- root, cpv = argv |
5943 |
- vartree = portage.db[root]["vartree"] |
5944 |
- if not vartree.dbapi.cpv_exists(cpv): |
5945 |
- sys.stderr.write("Package not found: '%s'\n" % cpv) |
5946 |
- return 1 |
5947 |
- cat, pkg = portage.catsplit(cpv) |
5948 |
- db = portage.dblink(cat, pkg, root, vartree.settings, |
5949 |
- treetype="vartree", vartree=vartree) |
5950 |
- writemsg_stdout(''.join('%s\n' % x for x in sorted(db.getcontents())), |
5951 |
- noiselevel=-1) |
5952 |
- |
5953 |
-docstrings['contents'] = """<eroot> <category/package> |
5954 |
+ if len(argv) != 2: |
5955 |
+ print("ERROR: expected 2 parameters, got %d!" % len(argv)) |
5956 |
+ return 2 |
5957 |
+ |
5958 |
+ root, cpv = argv |
5959 |
+ vartree = portage.db[root]["vartree"] |
5960 |
+ if not vartree.dbapi.cpv_exists(cpv): |
5961 |
+ sys.stderr.write("Package not found: '%s'\n" % cpv) |
5962 |
+ return 1 |
5963 |
+ cat, pkg = portage.catsplit(cpv) |
5964 |
+ db = portage.dblink( |
5965 |
+ cat, pkg, root, vartree.settings, treetype="vartree", vartree=vartree |
5966 |
+ ) |
5967 |
+ writemsg_stdout( |
5968 |
+ "".join("%s\n" % x for x in sorted(db.getcontents())), noiselevel=-1 |
5969 |
+ ) |
5970 |
+ |
5971 |
+ |
5972 |
+docstrings[ |
5973 |
+ "contents" |
5974 |
+] = """<eroot> <category/package> |
5975 |
List the files that are installed for a given package, with |
5976 |
one file listed on each line. All file names will begin with |
5977 |
<eroot>. |
5978 |
""" |
5979 |
-contents.__doc__ = docstrings['contents'] |
5980 |
+contents.__doc__ = docstrings["contents"] |
5981 |
|
5982 |
|
5983 |
@uses_eroot |
5984 |
def owners(argv): |
5985 |
- if len(argv) < 2: |
5986 |
- sys.stderr.write("ERROR: insufficient parameters!\n") |
5987 |
- sys.stderr.flush() |
5988 |
- return 2 |
5989 |
- |
5990 |
- eroot = argv[0] |
5991 |
- vardb = portage.db[eroot]["vartree"].dbapi |
5992 |
- root = portage.settings['ROOT'] |
5993 |
- |
5994 |
- cwd = None |
5995 |
- try: |
5996 |
- cwd = os.getcwd() |
5997 |
- except OSError: |
5998 |
- pass |
5999 |
- |
6000 |
- files = [] |
6001 |
- orphan_abs_paths = set() |
6002 |
- orphan_basenames = set() |
6003 |
- for f in argv[1:]: |
6004 |
- f = portage.normalize_path(f) |
6005 |
- is_basename = os.sep not in f |
6006 |
- if not is_basename and f[:1] != os.sep: |
6007 |
- if cwd is None: |
6008 |
- sys.stderr.write("ERROR: cwd does not exist!\n") |
6009 |
- sys.stderr.flush() |
6010 |
- return 2 |
6011 |
- f = os.path.join(cwd, f) |
6012 |
- f = portage.normalize_path(f) |
6013 |
- if not is_basename and not f.startswith(eroot): |
6014 |
- sys.stderr.write("ERROR: file paths must begin with <eroot>!\n") |
6015 |
- sys.stderr.flush() |
6016 |
- return 2 |
6017 |
- if is_basename: |
6018 |
- files.append(f) |
6019 |
- orphan_basenames.add(f) |
6020 |
- else: |
6021 |
- files.append(f[len(root)-1:]) |
6022 |
- orphan_abs_paths.add(f) |
6023 |
- |
6024 |
- owners = vardb._owners.get_owners(files) |
6025 |
- |
6026 |
- msg = [] |
6027 |
- for pkg, owned_files in owners.items(): |
6028 |
- cpv = pkg.mycpv |
6029 |
- msg.append("%s\n" % cpv) |
6030 |
- for f in sorted(owned_files): |
6031 |
- f_abs = os.path.join(root, f.lstrip(os.path.sep)) |
6032 |
- msg.append("\t%s\n" % (f_abs,)) |
6033 |
- orphan_abs_paths.discard(f_abs) |
6034 |
- if orphan_basenames: |
6035 |
- orphan_basenames.discard(os.path.basename(f_abs)) |
6036 |
- |
6037 |
- writemsg_stdout(''.join(msg), noiselevel=-1) |
6038 |
- |
6039 |
- if orphan_abs_paths or orphan_basenames: |
6040 |
- orphans = [] |
6041 |
- orphans.extend(orphan_abs_paths) |
6042 |
- orphans.extend(orphan_basenames) |
6043 |
- orphans.sort() |
6044 |
- msg = [] |
6045 |
- msg.append("None of the installed packages claim these files:\n") |
6046 |
- for f in orphans: |
6047 |
- msg.append("\t%s\n" % (f,)) |
6048 |
- sys.stderr.write("".join(msg)) |
6049 |
- sys.stderr.flush() |
6050 |
- |
6051 |
- if owners: |
6052 |
- return 0 |
6053 |
- return 1 |
6054 |
- |
6055 |
-docstrings['owners'] = """<eroot> [<filename>]+ |
6056 |
+ if len(argv) < 2: |
6057 |
+ sys.stderr.write("ERROR: insufficient parameters!\n") |
6058 |
+ sys.stderr.flush() |
6059 |
+ return 2 |
6060 |
+ |
6061 |
+ eroot = argv[0] |
6062 |
+ vardb = portage.db[eroot]["vartree"].dbapi |
6063 |
+ root = portage.settings["ROOT"] |
6064 |
+ |
6065 |
+ cwd = None |
6066 |
+ try: |
6067 |
+ cwd = os.getcwd() |
6068 |
+ except OSError: |
6069 |
+ pass |
6070 |
+ |
6071 |
+ files = [] |
6072 |
+ orphan_abs_paths = set() |
6073 |
+ orphan_basenames = set() |
6074 |
+ for f in argv[1:]: |
6075 |
+ f = portage.normalize_path(f) |
6076 |
+ is_basename = os.sep not in f |
6077 |
+ if not is_basename and f[:1] != os.sep: |
6078 |
+ if cwd is None: |
6079 |
+ sys.stderr.write("ERROR: cwd does not exist!\n") |
6080 |
+ sys.stderr.flush() |
6081 |
+ return 2 |
6082 |
+ f = os.path.join(cwd, f) |
6083 |
+ f = portage.normalize_path(f) |
6084 |
+ if not is_basename and not f.startswith(eroot): |
6085 |
+ sys.stderr.write("ERROR: file paths must begin with <eroot>!\n") |
6086 |
+ sys.stderr.flush() |
6087 |
+ return 2 |
6088 |
+ if is_basename: |
6089 |
+ files.append(f) |
6090 |
+ orphan_basenames.add(f) |
6091 |
+ else: |
6092 |
+ files.append(f[len(root) - 1 :]) |
6093 |
+ orphan_abs_paths.add(f) |
6094 |
+ |
6095 |
+ owners = vardb._owners.get_owners(files) |
6096 |
+ |
6097 |
+ msg = [] |
6098 |
+ for pkg, owned_files in owners.items(): |
6099 |
+ cpv = pkg.mycpv |
6100 |
+ msg.append("%s\n" % cpv) |
6101 |
+ for f in sorted(owned_files): |
6102 |
+ f_abs = os.path.join(root, f.lstrip(os.path.sep)) |
6103 |
+ msg.append("\t%s\n" % (f_abs,)) |
6104 |
+ orphan_abs_paths.discard(f_abs) |
6105 |
+ if orphan_basenames: |
6106 |
+ orphan_basenames.discard(os.path.basename(f_abs)) |
6107 |
+ |
6108 |
+ writemsg_stdout("".join(msg), noiselevel=-1) |
6109 |
+ |
6110 |
+ if orphan_abs_paths or orphan_basenames: |
6111 |
+ orphans = [] |
6112 |
+ orphans.extend(orphan_abs_paths) |
6113 |
+ orphans.extend(orphan_basenames) |
6114 |
+ orphans.sort() |
6115 |
+ msg = [] |
6116 |
+ msg.append("None of the installed packages claim these files:\n") |
6117 |
+ for f in orphans: |
6118 |
+ msg.append("\t%s\n" % (f,)) |
6119 |
+ sys.stderr.write("".join(msg)) |
6120 |
+ sys.stderr.flush() |
6121 |
+ |
6122 |
+ if owners: |
6123 |
+ return 0 |
6124 |
+ return 1 |
6125 |
+ |
6126 |
+ |
6127 |
+docstrings[ |
6128 |
+ "owners" |
6129 |
+] = """<eroot> [<filename>]+ |
6130 |
Given a list of files, print the packages that own the files and which |
6131 |
files belong to each package. Files owned by a package are listed on |
6132 |
the lines below it, indented by a single tab character (\\t). All file |
6133 |
paths must either start with <eroot> or be a basename alone. |
6134 |
Returns 1 if no owners could be found, and 0 otherwise. |
6135 |
""" |
6136 |
-owners.__doc__ = docstrings['owners'] |
6137 |
+owners.__doc__ = docstrings["owners"] |
6138 |
|
6139 |
|
6140 |
@uses_eroot |
6141 |
def is_protected(argv): |
6142 |
- if len(argv) != 2: |
6143 |
- sys.stderr.write("ERROR: expected 2 parameters, got %d!\n" % len(argv)) |
6144 |
- sys.stderr.flush() |
6145 |
- return 2 |
6146 |
- |
6147 |
- root, filename = argv |
6148 |
- |
6149 |
- err = sys.stderr |
6150 |
- cwd = None |
6151 |
- try: |
6152 |
- cwd = os.getcwd() |
6153 |
- except OSError: |
6154 |
- pass |
6155 |
- |
6156 |
- f = portage.normalize_path(filename) |
6157 |
- if not f.startswith(os.path.sep): |
6158 |
- if cwd is None: |
6159 |
- err.write("ERROR: cwd does not exist!\n") |
6160 |
- err.flush() |
6161 |
- return 2 |
6162 |
- f = os.path.join(cwd, f) |
6163 |
- f = portage.normalize_path(f) |
6164 |
- |
6165 |
- if not f.startswith(root): |
6166 |
- err.write("ERROR: file paths must begin with <eroot>!\n") |
6167 |
- err.flush() |
6168 |
- return 2 |
6169 |
- |
6170 |
- from portage.util import ConfigProtect |
6171 |
- |
6172 |
- settings = portage.settings |
6173 |
- protect = portage.util.shlex_split(settings.get("CONFIG_PROTECT", "")) |
6174 |
- protect_mask = portage.util.shlex_split( |
6175 |
- settings.get("CONFIG_PROTECT_MASK", "")) |
6176 |
- protect_obj = ConfigProtect(root, protect, protect_mask, |
6177 |
- case_insensitive=("case-insensitive-fs" in settings.features)) |
6178 |
- if protect_obj.isprotected(f): |
6179 |
- return 0 |
6180 |
- return 1 |
6181 |
- |
6182 |
-docstrings['is_protected'] = """<eroot> <filename> |
6183 |
+ if len(argv) != 2: |
6184 |
+ sys.stderr.write("ERROR: expected 2 parameters, got %d!\n" % len(argv)) |
6185 |
+ sys.stderr.flush() |
6186 |
+ return 2 |
6187 |
+ |
6188 |
+ root, filename = argv |
6189 |
+ |
6190 |
+ err = sys.stderr |
6191 |
+ cwd = None |
6192 |
+ try: |
6193 |
+ cwd = os.getcwd() |
6194 |
+ except OSError: |
6195 |
+ pass |
6196 |
+ |
6197 |
+ f = portage.normalize_path(filename) |
6198 |
+ if not f.startswith(os.path.sep): |
6199 |
+ if cwd is None: |
6200 |
+ err.write("ERROR: cwd does not exist!\n") |
6201 |
+ err.flush() |
6202 |
+ return 2 |
6203 |
+ f = os.path.join(cwd, f) |
6204 |
+ f = portage.normalize_path(f) |
6205 |
+ |
6206 |
+ if not f.startswith(root): |
6207 |
+ err.write("ERROR: file paths must begin with <eroot>!\n") |
6208 |
+ err.flush() |
6209 |
+ return 2 |
6210 |
+ |
6211 |
+ from portage.util import ConfigProtect |
6212 |
+ |
6213 |
+ settings = portage.settings |
6214 |
+ protect = portage.util.shlex_split(settings.get("CONFIG_PROTECT", "")) |
6215 |
+ protect_mask = portage.util.shlex_split(settings.get("CONFIG_PROTECT_MASK", "")) |
6216 |
+ protect_obj = ConfigProtect( |
6217 |
+ root, |
6218 |
+ protect, |
6219 |
+ protect_mask, |
6220 |
+ case_insensitive=("case-insensitive-fs" in settings.features), |
6221 |
+ ) |
6222 |
+ if protect_obj.isprotected(f): |
6223 |
+ return 0 |
6224 |
+ return 1 |
6225 |
+ |
6226 |
+ |
6227 |
+docstrings[ |
6228 |
+ "is_protected" |
6229 |
+] = """<eroot> <filename> |
6230 |
Given a single filename, return code 0 if it's protected, 1 otherwise. |
6231 |
The filename must begin with <eroot>. |
6232 |
""" |
6233 |
-is_protected.__doc__ = docstrings['is_protected'] |
6234 |
+is_protected.__doc__ = docstrings["is_protected"] |
6235 |
|
6236 |
|
6237 |
@uses_eroot |
6238 |
def filter_protected(argv): |
6239 |
- if len(argv) != 1: |
6240 |
- sys.stderr.write("ERROR: expected 1 parameter, got %d!\n" % len(argv)) |
6241 |
- sys.stderr.flush() |
6242 |
- return 2 |
6243 |
- |
6244 |
- root, = argv |
6245 |
- out = sys.stdout |
6246 |
- err = sys.stderr |
6247 |
- cwd = None |
6248 |
- try: |
6249 |
- cwd = os.getcwd() |
6250 |
- except OSError: |
6251 |
- pass |
6252 |
- |
6253 |
- from portage.util import ConfigProtect |
6254 |
- |
6255 |
- settings = portage.settings |
6256 |
- protect = portage.util.shlex_split(settings.get("CONFIG_PROTECT", "")) |
6257 |
- protect_mask = portage.util.shlex_split( |
6258 |
- settings.get("CONFIG_PROTECT_MASK", "")) |
6259 |
- protect_obj = ConfigProtect(root, protect, protect_mask, |
6260 |
- case_insensitive=("case-insensitive-fs" in settings.features)) |
6261 |
- |
6262 |
- errors = 0 |
6263 |
- |
6264 |
- for line in sys.stdin: |
6265 |
- filename = line.rstrip("\n") |
6266 |
- f = portage.normalize_path(filename) |
6267 |
- if not f.startswith(os.path.sep): |
6268 |
- if cwd is None: |
6269 |
- err.write("ERROR: cwd does not exist!\n") |
6270 |
- err.flush() |
6271 |
- errors += 1 |
6272 |
- continue |
6273 |
- f = os.path.join(cwd, f) |
6274 |
- f = portage.normalize_path(f) |
6275 |
- |
6276 |
- if not f.startswith(root): |
6277 |
- err.write("ERROR: file paths must begin with <eroot>!\n") |
6278 |
- err.flush() |
6279 |
- errors += 1 |
6280 |
- continue |
6281 |
- |
6282 |
- if protect_obj.isprotected(f): |
6283 |
- out.write("%s\n" % filename) |
6284 |
- out.flush() |
6285 |
- |
6286 |
- if errors: |
6287 |
- return 2 |
6288 |
- |
6289 |
- return 0 |
6290 |
- |
6291 |
-docstrings['filter_protected'] = """<eroot> |
6292 |
+ if len(argv) != 1: |
6293 |
+ sys.stderr.write("ERROR: expected 1 parameter, got %d!\n" % len(argv)) |
6294 |
+ sys.stderr.flush() |
6295 |
+ return 2 |
6296 |
+ |
6297 |
+ (root,) = argv |
6298 |
+ out = sys.stdout |
6299 |
+ err = sys.stderr |
6300 |
+ cwd = None |
6301 |
+ try: |
6302 |
+ cwd = os.getcwd() |
6303 |
+ except OSError: |
6304 |
+ pass |
6305 |
+ |
6306 |
+ from portage.util import ConfigProtect |
6307 |
+ |
6308 |
+ settings = portage.settings |
6309 |
+ protect = portage.util.shlex_split(settings.get("CONFIG_PROTECT", "")) |
6310 |
+ protect_mask = portage.util.shlex_split(settings.get("CONFIG_PROTECT_MASK", "")) |
6311 |
+ protect_obj = ConfigProtect( |
6312 |
+ root, |
6313 |
+ protect, |
6314 |
+ protect_mask, |
6315 |
+ case_insensitive=("case-insensitive-fs" in settings.features), |
6316 |
+ ) |
6317 |
+ |
6318 |
+ errors = 0 |
6319 |
+ |
6320 |
+ for line in sys.stdin: |
6321 |
+ filename = line.rstrip("\n") |
6322 |
+ f = portage.normalize_path(filename) |
6323 |
+ if not f.startswith(os.path.sep): |
6324 |
+ if cwd is None: |
6325 |
+ err.write("ERROR: cwd does not exist!\n") |
6326 |
+ err.flush() |
6327 |
+ errors += 1 |
6328 |
+ continue |
6329 |
+ f = os.path.join(cwd, f) |
6330 |
+ f = portage.normalize_path(f) |
6331 |
+ |
6332 |
+ if not f.startswith(root): |
6333 |
+ err.write("ERROR: file paths must begin with <eroot>!\n") |
6334 |
+ err.flush() |
6335 |
+ errors += 1 |
6336 |
+ continue |
6337 |
+ |
6338 |
+ if protect_obj.isprotected(f): |
6339 |
+ out.write("%s\n" % filename) |
6340 |
+ out.flush() |
6341 |
+ |
6342 |
+ if errors: |
6343 |
+ return 2 |
6344 |
+ |
6345 |
+ return 0 |
6346 |
+ |
6347 |
+ |
6348 |
+docstrings[ |
6349 |
+ "filter_protected" |
6350 |
+] = """<eroot> |
6351 |
Read filenames from stdin and write them to stdout if they are protected. |
6352 |
All filenames are delimited by \\n and must begin with <eroot>. |
6353 |
""" |
6354 |
-filter_protected.__doc__ = docstrings['filter_protected'] |
6355 |
+filter_protected.__doc__ = docstrings["filter_protected"] |
6356 |
|
6357 |
|
6358 |
@uses_eroot |
6359 |
def best_visible(argv): |
6360 |
- if len(argv) < 2: |
6361 |
- writemsg("ERROR: insufficient parameters!\n", noiselevel=-1) |
6362 |
- return 2 |
6363 |
- |
6364 |
- pkgtype = "ebuild" |
6365 |
- if len(argv) > 2: |
6366 |
- pkgtype = argv[1] |
6367 |
- atom = argv[2] |
6368 |
- else: |
6369 |
- atom = argv[1] |
6370 |
- |
6371 |
- type_map = { |
6372 |
- "ebuild":"porttree", |
6373 |
- "binary":"bintree", |
6374 |
- "installed":"vartree"} |
6375 |
- |
6376 |
- if pkgtype not in type_map: |
6377 |
- writemsg("Unrecognized package type: '%s'\n" % pkgtype, |
6378 |
- noiselevel=-1) |
6379 |
- return 2 |
6380 |
- |
6381 |
- eroot = argv[0] |
6382 |
- db = portage.db[eroot][type_map[pkgtype]].dbapi |
6383 |
- |
6384 |
- try: |
6385 |
- atom = portage.dep_expand(atom, mydb=db, settings=portage.settings) |
6386 |
- except portage.exception.InvalidAtom: |
6387 |
- writemsg("ERROR: Invalid atom: '%s'\n" % atom, |
6388 |
- noiselevel=-1) |
6389 |
- return 2 |
6390 |
- |
6391 |
- root_config = RootConfig(portage.settings, portage.db[eroot], None) |
6392 |
- |
6393 |
- if hasattr(db, "xmatch"): |
6394 |
- cpv_list = db.xmatch("match-all-cpv-only", atom) |
6395 |
- else: |
6396 |
- cpv_list = db.match(atom) |
6397 |
- |
6398 |
- if cpv_list: |
6399 |
- # reversed, for descending order |
6400 |
- cpv_list.reverse() |
6401 |
- # verify match, since the atom may match the package |
6402 |
- # for a given cpv from one repo but not another, and |
6403 |
- # we can use match-all-cpv-only to avoid redundant |
6404 |
- # metadata access. |
6405 |
- atom_set = InternalPackageSet(initial_atoms=(atom,)) |
6406 |
- |
6407 |
- if atom.repo is None and hasattr(db, "getRepositories"): |
6408 |
- repo_list = db.getRepositories() |
6409 |
- else: |
6410 |
- repo_list = [atom.repo] |
6411 |
- |
6412 |
- for cpv in cpv_list: |
6413 |
- for repo in repo_list: |
6414 |
- try: |
6415 |
- metadata = dict(zip(Package.metadata_keys, |
6416 |
- db.aux_get(cpv, Package.metadata_keys, myrepo=repo))) |
6417 |
- except KeyError: |
6418 |
- continue |
6419 |
- pkg = Package(built=(pkgtype != "ebuild"), cpv=cpv, |
6420 |
- installed=(pkgtype=="installed"), metadata=metadata, |
6421 |
- root_config=root_config, type_name=pkgtype) |
6422 |
- if not atom_set.findAtomForPackage(pkg): |
6423 |
- continue |
6424 |
- |
6425 |
- if pkg.visible: |
6426 |
- writemsg_stdout("%s\n" % (pkg.cpv,), noiselevel=-1) |
6427 |
- return os.EX_OK |
6428 |
- |
6429 |
- # No package found, write out an empty line. |
6430 |
- writemsg_stdout("\n", noiselevel=-1) |
6431 |
- |
6432 |
- return 1 |
6433 |
- |
6434 |
-docstrings['best_visible'] = """<eroot> [pkgtype] <atom> |
6435 |
+ if len(argv) < 2: |
6436 |
+ writemsg("ERROR: insufficient parameters!\n", noiselevel=-1) |
6437 |
+ return 2 |
6438 |
+ |
6439 |
+ pkgtype = "ebuild" |
6440 |
+ if len(argv) > 2: |
6441 |
+ pkgtype = argv[1] |
6442 |
+ atom = argv[2] |
6443 |
+ else: |
6444 |
+ atom = argv[1] |
6445 |
+ |
6446 |
+ type_map = {"ebuild": "porttree", "binary": "bintree", "installed": "vartree"} |
6447 |
+ |
6448 |
+ if pkgtype not in type_map: |
6449 |
+ writemsg("Unrecognized package type: '%s'\n" % pkgtype, noiselevel=-1) |
6450 |
+ return 2 |
6451 |
+ |
6452 |
+ eroot = argv[0] |
6453 |
+ db = portage.db[eroot][type_map[pkgtype]].dbapi |
6454 |
+ |
6455 |
+ try: |
6456 |
+ atom = portage.dep_expand(atom, mydb=db, settings=portage.settings) |
6457 |
+ except portage.exception.InvalidAtom: |
6458 |
+ writemsg("ERROR: Invalid atom: '%s'\n" % atom, noiselevel=-1) |
6459 |
+ return 2 |
6460 |
+ |
6461 |
+ root_config = RootConfig(portage.settings, portage.db[eroot], None) |
6462 |
+ |
6463 |
+ if hasattr(db, "xmatch"): |
6464 |
+ cpv_list = db.xmatch("match-all-cpv-only", atom) |
6465 |
+ else: |
6466 |
+ cpv_list = db.match(atom) |
6467 |
+ |
6468 |
+ if cpv_list: |
6469 |
+ # reversed, for descending order |
6470 |
+ cpv_list.reverse() |
6471 |
+ # verify match, since the atom may match the package |
6472 |
+ # for a given cpv from one repo but not another, and |
6473 |
+ # we can use match-all-cpv-only to avoid redundant |
6474 |
+ # metadata access. |
6475 |
+ atom_set = InternalPackageSet(initial_atoms=(atom,)) |
6476 |
+ |
6477 |
+ if atom.repo is None and hasattr(db, "getRepositories"): |
6478 |
+ repo_list = db.getRepositories() |
6479 |
+ else: |
6480 |
+ repo_list = [atom.repo] |
6481 |
+ |
6482 |
+ for cpv in cpv_list: |
6483 |
+ for repo in repo_list: |
6484 |
+ try: |
6485 |
+ metadata = dict( |
6486 |
+ zip( |
6487 |
+ Package.metadata_keys, |
6488 |
+ db.aux_get(cpv, Package.metadata_keys, myrepo=repo), |
6489 |
+ ) |
6490 |
+ ) |
6491 |
+ except KeyError: |
6492 |
+ continue |
6493 |
+ pkg = Package( |
6494 |
+ built=(pkgtype != "ebuild"), |
6495 |
+ cpv=cpv, |
6496 |
+ installed=(pkgtype == "installed"), |
6497 |
+ metadata=metadata, |
6498 |
+ root_config=root_config, |
6499 |
+ type_name=pkgtype, |
6500 |
+ ) |
6501 |
+ if not atom_set.findAtomForPackage(pkg): |
6502 |
+ continue |
6503 |
+ |
6504 |
+ if pkg.visible: |
6505 |
+ writemsg_stdout("%s\n" % (pkg.cpv,), noiselevel=-1) |
6506 |
+ return os.EX_OK |
6507 |
+ |
6508 |
+ # No package found, write out an empty line. |
6509 |
+ writemsg_stdout("\n", noiselevel=-1) |
6510 |
+ |
6511 |
+ return 1 |
6512 |
+ |
6513 |
+ |
6514 |
+docstrings[ |
6515 |
+ "best_visible" |
6516 |
+] = """<eroot> [pkgtype] <atom> |
6517 |
Returns category/package-version (without .ebuild). |
6518 |
The pkgtype argument defaults to "ebuild" if unspecified, |
6519 |
otherwise it must be one of ebuild, binary, or installed. |
6520 |
""" |
6521 |
-best_visible.__doc__ = docstrings['best_visible'] |
6522 |
+best_visible.__doc__ = docstrings["best_visible"] |
6523 |
|
6524 |
|
6525 |
@uses_eroot |
6526 |
def mass_best_visible(argv): |
6527 |
- type_map = { |
6528 |
- "ebuild":"porttree", |
6529 |
- "binary":"bintree", |
6530 |
- "installed":"vartree"} |
6531 |
- |
6532 |
- if len(argv) < 2: |
6533 |
- print("ERROR: insufficient parameters!") |
6534 |
- return 2 |
6535 |
- try: |
6536 |
- root = argv.pop(0) |
6537 |
- pkgtype = "ebuild" |
6538 |
- if argv[0] in type_map: |
6539 |
- pkgtype = argv.pop(0) |
6540 |
- for pack in argv: |
6541 |
- writemsg_stdout("%s:" % pack, noiselevel=-1) |
6542 |
- best_visible([root, pkgtype, pack]) |
6543 |
- except KeyError: |
6544 |
- return 1 |
6545 |
- |
6546 |
-docstrings['mass_best_visible'] = """<eroot> [<type>] [<category/package>]+ |
6547 |
+ type_map = {"ebuild": "porttree", "binary": "bintree", "installed": "vartree"} |
6548 |
+ |
6549 |
+ if len(argv) < 2: |
6550 |
+ print("ERROR: insufficient parameters!") |
6551 |
+ return 2 |
6552 |
+ try: |
6553 |
+ root = argv.pop(0) |
6554 |
+ pkgtype = "ebuild" |
6555 |
+ if argv[0] in type_map: |
6556 |
+ pkgtype = argv.pop(0) |
6557 |
+ for pack in argv: |
6558 |
+ writemsg_stdout("%s:" % pack, noiselevel=-1) |
6559 |
+ best_visible([root, pkgtype, pack]) |
6560 |
+ except KeyError: |
6561 |
+ return 1 |
6562 |
+ |
6563 |
+ |
6564 |
+docstrings[ |
6565 |
+ "mass_best_visible" |
6566 |
+] = """<eroot> [<type>] [<category/package>]+ |
6567 |
Returns category/package-version (without .ebuild). |
6568 |
The pkgtype argument defaults to "ebuild" if unspecified, |
6569 |
otherwise it must be one of ebuild, binary, or installed. |
6570 |
""" |
6571 |
-mass_best_visible.__doc__ = docstrings['mass_best_visible'] |
6572 |
+mass_best_visible.__doc__ = docstrings["mass_best_visible"] |
6573 |
|
6574 |
|
6575 |
@uses_eroot |
6576 |
def all_best_visible(argv): |
6577 |
- if len(argv) < 1: |
6578 |
- sys.stderr.write("ERROR: insufficient parameters!\n") |
6579 |
- sys.stderr.flush() |
6580 |
- return 2 |
6581 |
- |
6582 |
- #print portage.db[argv[0]]["porttree"].dbapi.cp_all() |
6583 |
- for pkg in portage.db[argv[0]]["porttree"].dbapi.cp_all(): |
6584 |
- mybest=portage.best(portage.db[argv[0]]["porttree"].dbapi.match(pkg)) |
6585 |
- if mybest: |
6586 |
- print(mybest) |
6587 |
- |
6588 |
-docstrings['all_best_visible'] = """<eroot> |
6589 |
+ if len(argv) < 1: |
6590 |
+ sys.stderr.write("ERROR: insufficient parameters!\n") |
6591 |
+ sys.stderr.flush() |
6592 |
+ return 2 |
6593 |
+ |
6594 |
+ # print portage.db[argv[0]]["porttree"].dbapi.cp_all() |
6595 |
+ for pkg in portage.db[argv[0]]["porttree"].dbapi.cp_all(): |
6596 |
+ mybest = portage.best(portage.db[argv[0]]["porttree"].dbapi.match(pkg)) |
6597 |
+ if mybest: |
6598 |
+ print(mybest) |
6599 |
+ |
6600 |
+ |
6601 |
+docstrings[ |
6602 |
+ "all_best_visible" |
6603 |
+] = """<eroot> |
6604 |
Returns all best_visible packages (without .ebuild). |
6605 |
""" |
6606 |
-all_best_visible.__doc__ = docstrings['all_best_visible'] |
6607 |
+all_best_visible.__doc__ = docstrings["all_best_visible"] |
6608 |
|
6609 |
|
6610 |
@uses_eroot |
6611 |
def match(argv): |
6612 |
- if len(argv) != 2: |
6613 |
- print("ERROR: expected 2 parameters, got %d!" % len(argv)) |
6614 |
- return 2 |
6615 |
- root, atom = argv |
6616 |
- if not atom: |
6617 |
- atom = "*/*" |
6618 |
- |
6619 |
- vardb = portage.db[root]["vartree"].dbapi |
6620 |
- try: |
6621 |
- atom = portage.dep.Atom(atom, allow_wildcard=True, allow_repo=True) |
6622 |
- except portage.exception.InvalidAtom: |
6623 |
- # maybe it's valid but missing category |
6624 |
- atom = portage.dep_expand(atom, mydb=vardb, settings=vardb.settings) |
6625 |
- |
6626 |
- if atom.extended_syntax: |
6627 |
- if atom == "*/*": |
6628 |
- results = vardb.cpv_all() |
6629 |
- else: |
6630 |
- results = [] |
6631 |
- require_metadata = atom.slot or atom.repo |
6632 |
- for cpv in vardb.cpv_all(): |
6633 |
- |
6634 |
- if not portage.match_from_list(atom, [cpv]): |
6635 |
- continue |
6636 |
- |
6637 |
- if require_metadata: |
6638 |
- try: |
6639 |
- cpv = vardb._pkg_str(cpv, atom.repo) |
6640 |
- except (KeyError, portage.exception.InvalidData): |
6641 |
- continue |
6642 |
- if not portage.match_from_list(atom, [cpv]): |
6643 |
- continue |
6644 |
- |
6645 |
- results.append(cpv) |
6646 |
- |
6647 |
- results.sort() |
6648 |
- else: |
6649 |
- results = vardb.match(atom) |
6650 |
- for cpv in results: |
6651 |
- print(cpv) |
6652 |
- |
6653 |
-docstrings['match'] = """<eroot> <atom> |
6654 |
+ if len(argv) != 2: |
6655 |
+ print("ERROR: expected 2 parameters, got %d!" % len(argv)) |
6656 |
+ return 2 |
6657 |
+ root, atom = argv |
6658 |
+ if not atom: |
6659 |
+ atom = "*/*" |
6660 |
+ |
6661 |
+ vardb = portage.db[root]["vartree"].dbapi |
6662 |
+ try: |
6663 |
+ atom = portage.dep.Atom(atom, allow_wildcard=True, allow_repo=True) |
6664 |
+ except portage.exception.InvalidAtom: |
6665 |
+ # maybe it's valid but missing category |
6666 |
+ atom = portage.dep_expand(atom, mydb=vardb, settings=vardb.settings) |
6667 |
+ |
6668 |
+ if atom.extended_syntax: |
6669 |
+ if atom == "*/*": |
6670 |
+ results = vardb.cpv_all() |
6671 |
+ else: |
6672 |
+ results = [] |
6673 |
+ require_metadata = atom.slot or atom.repo |
6674 |
+ for cpv in vardb.cpv_all(): |
6675 |
+ |
6676 |
+ if not portage.match_from_list(atom, [cpv]): |
6677 |
+ continue |
6678 |
+ |
6679 |
+ if require_metadata: |
6680 |
+ try: |
6681 |
+ cpv = vardb._pkg_str(cpv, atom.repo) |
6682 |
+ except (KeyError, portage.exception.InvalidData): |
6683 |
+ continue |
6684 |
+ if not portage.match_from_list(atom, [cpv]): |
6685 |
+ continue |
6686 |
+ |
6687 |
+ results.append(cpv) |
6688 |
+ |
6689 |
+ results.sort() |
6690 |
+ else: |
6691 |
+ results = vardb.match(atom) |
6692 |
+ for cpv in results: |
6693 |
+ print(cpv) |
6694 |
+ |
6695 |
+ |
6696 |
+docstrings[ |
6697 |
+ "match" |
6698 |
+] = """<eroot> <atom> |
6699 |
Returns a \\n separated list of category/package-version. |
6700 |
When given an empty string, all installed packages will |
6701 |
be listed. |
6702 |
""" |
6703 |
-match.__doc__ = docstrings['match'] |
6704 |
+match.__doc__ = docstrings["match"] |
6705 |
|
6706 |
|
6707 |
@uses_eroot |
6708 |
def expand_virtual(argv): |
6709 |
- if len(argv) != 2: |
6710 |
- writemsg("ERROR: expected 2 parameters, got %d!\n" % len(argv), |
6711 |
- noiselevel=-1) |
6712 |
- return 2 |
6713 |
+ if len(argv) != 2: |
6714 |
+ writemsg("ERROR: expected 2 parameters, got %d!\n" % len(argv), noiselevel=-1) |
6715 |
+ return 2 |
6716 |
+ |
6717 |
+ root, atom = argv |
6718 |
|
6719 |
- root, atom = argv |
6720 |
+ try: |
6721 |
+ results = list(expand_new_virt(portage.db[root]["vartree"].dbapi, atom)) |
6722 |
+ except portage.exception.InvalidAtom: |
6723 |
+ writemsg("ERROR: Invalid atom: '%s'\n" % atom, noiselevel=-1) |
6724 |
+ return 2 |
6725 |
|
6726 |
- try: |
6727 |
- results = list(expand_new_virt( |
6728 |
- portage.db[root]["vartree"].dbapi, atom)) |
6729 |
- except portage.exception.InvalidAtom: |
6730 |
- writemsg("ERROR: Invalid atom: '%s'\n" % atom, |
6731 |
- noiselevel=-1) |
6732 |
- return 2 |
6733 |
+ results.sort() |
6734 |
+ for x in results: |
6735 |
+ if not x.blocker: |
6736 |
+ writemsg_stdout("%s\n" % (x,)) |
6737 |
|
6738 |
- results.sort() |
6739 |
- for x in results: |
6740 |
- if not x.blocker: |
6741 |
- writemsg_stdout("%s\n" % (x,)) |
6742 |
+ return os.EX_OK |
6743 |
|
6744 |
- return os.EX_OK |
6745 |
|
6746 |
-docstrings['expand_virtual'] = """<eroot> <atom> |
6747 |
+docstrings[ |
6748 |
+ "expand_virtual" |
6749 |
+] = """<eroot> <atom> |
6750 |
Returns a \\n separated list of atoms expanded from a |
6751 |
given virtual atom (GLEP 37 virtuals only), |
6752 |
excluding blocker atoms. Satisfied |
6753 |
@@ -677,802 +735,911 @@ docstrings['expand_virtual'] = """<eroot> <atom> |
6754 |
resolve the returned atoms to specific installed |
6755 |
packages. |
6756 |
""" |
6757 |
-expand_virtual.__doc__ = docstrings['expand_virtual'] |
6758 |
+expand_virtual.__doc__ = docstrings["expand_virtual"] |
6759 |
|
6760 |
|
6761 |
def vdb_path(_argv): |
6762 |
- out = sys.stdout |
6763 |
- out.write(os.path.join(portage.settings["EROOT"], portage.VDB_PATH) + "\n") |
6764 |
- out.flush() |
6765 |
- return os.EX_OK |
6766 |
+ out = sys.stdout |
6767 |
+ out.write(os.path.join(portage.settings["EROOT"], portage.VDB_PATH) + "\n") |
6768 |
+ out.flush() |
6769 |
+ return os.EX_OK |
6770 |
|
6771 |
-docstrings['vdb_path'] = """ |
6772 |
+ |
6773 |
+docstrings[ |
6774 |
+ "vdb_path" |
6775 |
+] = """ |
6776 |
Returns the path used for the var(installed) package database for the |
6777 |
set environment/configuration options. |
6778 |
""" |
6779 |
-vdb_path.__doc__ = docstrings['vdb_path'] |
6780 |
+vdb_path.__doc__ = docstrings["vdb_path"] |
6781 |
|
6782 |
|
6783 |
def gentoo_mirrors(_argv): |
6784 |
- print(portage.settings["GENTOO_MIRRORS"]) |
6785 |
+ print(portage.settings["GENTOO_MIRRORS"]) |
6786 |
+ |
6787 |
|
6788 |
-docstrings['gentoo_mirrors'] = """ |
6789 |
+docstrings[ |
6790 |
+ "gentoo_mirrors" |
6791 |
+] = """ |
6792 |
Returns the mirrors set to use in the portage configuration. |
6793 |
""" |
6794 |
-gentoo_mirrors.__doc__ = docstrings['gentoo_mirrors'] |
6795 |
+gentoo_mirrors.__doc__ = docstrings["gentoo_mirrors"] |
6796 |
|
6797 |
|
6798 |
@uses_configroot |
6799 |
@uses_eroot |
6800 |
def repositories_configuration(argv): |
6801 |
- if len(argv) < 1: |
6802 |
- print("ERROR: insufficient parameters!", file=sys.stderr) |
6803 |
- return 3 |
6804 |
- sys.stdout.write(portage.db[argv[0]]["vartree"].settings.repositories.config_string()) |
6805 |
- sys.stdout.flush() |
6806 |
- |
6807 |
-docstrings['repositories_configuration'] = """<eroot> |
6808 |
+ if len(argv) < 1: |
6809 |
+ print("ERROR: insufficient parameters!", file=sys.stderr) |
6810 |
+ return 3 |
6811 |
+ sys.stdout.write( |
6812 |
+ portage.db[argv[0]]["vartree"].settings.repositories.config_string() |
6813 |
+ ) |
6814 |
+ sys.stdout.flush() |
6815 |
+ |
6816 |
+ |
6817 |
+docstrings[ |
6818 |
+ "repositories_configuration" |
6819 |
+] = """<eroot> |
6820 |
Returns the configuration of repositories. |
6821 |
""" |
6822 |
-repositories_configuration.__doc__ = docstrings['repositories_configuration'] |
6823 |
+repositories_configuration.__doc__ = docstrings["repositories_configuration"] |
6824 |
|
6825 |
|
6826 |
@uses_configroot |
6827 |
@uses_eroot |
6828 |
def repos_config(argv): |
6829 |
- return repositories_configuration(argv) |
6830 |
+ return repositories_configuration(argv) |
6831 |
+ |
6832 |
|
6833 |
-docstrings['repos_config'] = """ |
6834 |
+docstrings[ |
6835 |
+ "repos_config" |
6836 |
+] = """ |
6837 |
<eroot> |
6838 |
This is an alias for the repositories_configuration command. |
6839 |
""" |
6840 |
-repos_config.__doc__ = docstrings['repos_config'] |
6841 |
+repos_config.__doc__ = docstrings["repos_config"] |
6842 |
|
6843 |
|
6844 |
def portdir(_argv): |
6845 |
- print("WARNING: 'portageq portdir' is deprecated. Use the get_repo_path " |
6846 |
- "command instead. eg: " |
6847 |
- "'portageq get_repo_path / gentoo' instead.", file=sys.stderr) |
6848 |
- print(portage.settings["PORTDIR"]) |
6849 |
- |
6850 |
-docstrings['portdir'] = """ |
6851 |
+ print( |
6852 |
+ "WARNING: 'portageq portdir' is deprecated. Use the get_repo_path " |
6853 |
+ "command instead. eg: " |
6854 |
+ "'portageq get_repo_path / gentoo' instead.", |
6855 |
+ file=sys.stderr, |
6856 |
+ ) |
6857 |
+ print(portage.settings["PORTDIR"]) |
6858 |
+ |
6859 |
+ |
6860 |
+docstrings[ |
6861 |
+ "portdir" |
6862 |
+] = """ |
6863 |
Returns the PORTDIR path. |
6864 |
Deprecated in favor of get_repo_path command. |
6865 |
""" |
6866 |
-portdir.__doc__ = docstrings['portdir'] |
6867 |
+portdir.__doc__ = docstrings["portdir"] |
6868 |
|
6869 |
|
6870 |
def config_protect(_argv): |
6871 |
- print(portage.settings["CONFIG_PROTECT"]) |
6872 |
+ print(portage.settings["CONFIG_PROTECT"]) |
6873 |
+ |
6874 |
|
6875 |
-docstrings['config_protect'] = """ |
6876 |
+docstrings[ |
6877 |
+ "config_protect" |
6878 |
+] = """ |
6879 |
Returns the CONFIG_PROTECT paths. |
6880 |
""" |
6881 |
-config_protect.__doc__ = docstrings['config_protect'] |
6882 |
+config_protect.__doc__ = docstrings["config_protect"] |
6883 |
|
6884 |
|
6885 |
def config_protect_mask(_argv): |
6886 |
- print(portage.settings["CONFIG_PROTECT_MASK"]) |
6887 |
+ print(portage.settings["CONFIG_PROTECT_MASK"]) |
6888 |
|
6889 |
-docstrings['config_protect_mask'] = """ |
6890 |
+ |
6891 |
+docstrings[ |
6892 |
+ "config_protect_mask" |
6893 |
+] = """ |
6894 |
Returns the CONFIG_PROTECT_MASK paths. |
6895 |
""" |
6896 |
-config_protect_mask.__doc__ = docstrings['config_protect_mask'] |
6897 |
+config_protect_mask.__doc__ = docstrings["config_protect_mask"] |
6898 |
|
6899 |
-def portdir_overlay(_argv): |
6900 |
- print("WARNING: 'portageq portdir_overlay' is deprecated. Use the get_repos" |
6901 |
- " and get_repo_path commands or the repos_config command instead. eg: " |
6902 |
- "'portageq repos_config /'", file=sys.stderr) |
6903 |
- print(portage.settings["PORTDIR_OVERLAY"]) |
6904 |
|
6905 |
-docstrings['portdir_overlay'] = """ |
6906 |
+def portdir_overlay(_argv): |
6907 |
+ print( |
6908 |
+ "WARNING: 'portageq portdir_overlay' is deprecated. Use the get_repos" |
6909 |
+ " and get_repo_path commands or the repos_config command instead. eg: " |
6910 |
+ "'portageq repos_config /'", |
6911 |
+ file=sys.stderr, |
6912 |
+ ) |
6913 |
+ print(portage.settings["PORTDIR_OVERLAY"]) |
6914 |
+ |
6915 |
+ |
6916 |
+docstrings[ |
6917 |
+ "portdir_overlay" |
6918 |
+] = """ |
6919 |
Returns the PORTDIR_OVERLAY path. |
6920 |
Deprecated in favor of get_repos & get_repo_path or repos_config commands. |
6921 |
""" |
6922 |
-portdir_overlay.__doc__ = docstrings['portdir_overlay'] |
6923 |
+portdir_overlay.__doc__ = docstrings["portdir_overlay"] |
6924 |
|
6925 |
|
6926 |
def pkgdir(_argv): |
6927 |
- print(portage.settings["PKGDIR"]) |
6928 |
+ print(portage.settings["PKGDIR"]) |
6929 |
|
6930 |
-docstrings['pkgdir'] = """ |
6931 |
+ |
6932 |
+docstrings[ |
6933 |
+ "pkgdir" |
6934 |
+] = """ |
6935 |
Returns the PKGDIR path. |
6936 |
""" |
6937 |
-pkgdir.__doc__ = docstrings['pkgdir'] |
6938 |
+pkgdir.__doc__ = docstrings["pkgdir"] |
6939 |
|
6940 |
|
6941 |
def distdir(_argv): |
6942 |
- print(portage.settings["DISTDIR"]) |
6943 |
+ print(portage.settings["DISTDIR"]) |
6944 |
+ |
6945 |
|
6946 |
-docstrings['distdir'] = """ |
6947 |
+docstrings[ |
6948 |
+ "distdir" |
6949 |
+] = """ |
6950 |
Returns the DISTDIR path. |
6951 |
""" |
6952 |
-distdir.__doc__ = docstrings['distdir'] |
6953 |
+distdir.__doc__ = docstrings["distdir"] |
6954 |
|
6955 |
|
6956 |
def colormap(_argv): |
6957 |
- print(portage.output.colormap()) |
6958 |
+ print(portage.output.colormap()) |
6959 |
|
6960 |
-docstrings['colormap'] = """ |
6961 |
+ |
6962 |
+docstrings[ |
6963 |
+ "colormap" |
6964 |
+] = """ |
6965 |
Display the color.map as environment variables. |
6966 |
""" |
6967 |
-colormap.__doc__ = docstrings['colormap'] |
6968 |
+colormap.__doc__ = docstrings["colormap"] |
6969 |
|
6970 |
|
6971 |
def envvar(argv): |
6972 |
- verbose = "-v" in argv |
6973 |
- if verbose: |
6974 |
- argv.pop(argv.index("-v")) |
6975 |
+ verbose = "-v" in argv |
6976 |
+ if verbose: |
6977 |
+ argv.pop(argv.index("-v")) |
6978 |
+ |
6979 |
+ if len(argv) == 0: |
6980 |
+ print("ERROR: insufficient parameters!") |
6981 |
+ return 2 |
6982 |
|
6983 |
- if len(argv) == 0: |
6984 |
- print("ERROR: insufficient parameters!") |
6985 |
- return 2 |
6986 |
+ exit_status = 0 |
6987 |
|
6988 |
- exit_status = 0 |
6989 |
+ for arg in argv: |
6990 |
+ if arg in ("PORTDIR", "PORTDIR_OVERLAY", "SYNC"): |
6991 |
+ print( |
6992 |
+ "WARNING: 'portageq envvar %s' is deprecated. Use any of " |
6993 |
+ "'get_repos, get_repo_path, repos_config' instead." % arg, |
6994 |
+ file=sys.stderr, |
6995 |
+ ) |
6996 |
|
6997 |
- for arg in argv: |
6998 |
- if arg in ("PORTDIR", "PORTDIR_OVERLAY", "SYNC"): |
6999 |
- print("WARNING: 'portageq envvar %s' is deprecated. Use any of " |
7000 |
- "'get_repos, get_repo_path, repos_config' instead." |
7001 |
- % arg, file=sys.stderr) |
7002 |
+ value = portage.settings.get(arg) |
7003 |
+ if value is None: |
7004 |
+ value = "" |
7005 |
+ exit_status = 1 |
7006 |
|
7007 |
- value = portage.settings.get(arg) |
7008 |
- if value is None: |
7009 |
- value = "" |
7010 |
- exit_status = 1 |
7011 |
+ if verbose: |
7012 |
+ print(arg + "=" + portage._shell_quote(value)) |
7013 |
+ else: |
7014 |
+ print(value) |
7015 |
|
7016 |
- if verbose: |
7017 |
- print(arg + "=" + portage._shell_quote(value)) |
7018 |
- else: |
7019 |
- print(value) |
7020 |
+ return exit_status |
7021 |
|
7022 |
- return exit_status |
7023 |
|
7024 |
-docstrings['envvar'] = """<variable>+ |
7025 |
+docstrings[ |
7026 |
+ "envvar" |
7027 |
+] = """<variable>+ |
7028 |
Returns a specific environment variable as exists prior to ebuild.sh. |
7029 |
Similar to: emerge --verbose --info | egrep '^<variable>=' |
7030 |
""" |
7031 |
-envvar.__doc__ = docstrings['envvar'] |
7032 |
+envvar.__doc__ = docstrings["envvar"] |
7033 |
|
7034 |
|
7035 |
@uses_configroot |
7036 |
@uses_eroot |
7037 |
def get_repos(argv): |
7038 |
- if len(argv) < 1: |
7039 |
- print("ERROR: insufficient parameters!") |
7040 |
- return 2 |
7041 |
- print(" ".join(reversed(portage.db[argv[0]]["vartree"].settings.repositories.prepos_order))) |
7042 |
- |
7043 |
-docstrings['get_repos'] = """<eroot> |
7044 |
+ if len(argv) < 1: |
7045 |
+ print("ERROR: insufficient parameters!") |
7046 |
+ return 2 |
7047 |
+ print( |
7048 |
+ " ".join( |
7049 |
+ reversed(portage.db[argv[0]]["vartree"].settings.repositories.prepos_order) |
7050 |
+ ) |
7051 |
+ ) |
7052 |
+ |
7053 |
+ |
7054 |
+docstrings[ |
7055 |
+ "get_repos" |
7056 |
+] = """<eroot> |
7057 |
Returns all repos with names (repo_name file) argv[0] = $EROOT |
7058 |
""" |
7059 |
-get_repos.__doc__ = docstrings['get_repos'] |
7060 |
+get_repos.__doc__ = docstrings["get_repos"] |
7061 |
|
7062 |
|
7063 |
@uses_configroot |
7064 |
@uses_eroot |
7065 |
def master_repositories(argv): |
7066 |
- if len(argv) < 2: |
7067 |
- print("ERROR: insufficient parameters!", file=sys.stderr) |
7068 |
- return 3 |
7069 |
- for arg in argv[1:]: |
7070 |
- if portage.dep._repo_name_re.match(arg) is None: |
7071 |
- print("ERROR: invalid repository: %s" % arg, file=sys.stderr) |
7072 |
- return 2 |
7073 |
- try: |
7074 |
- repo = portage.db[argv[0]]["vartree"].settings.repositories[arg] |
7075 |
- except KeyError: |
7076 |
- print("") |
7077 |
- return 1 |
7078 |
- else: |
7079 |
- print(" ".join(x.name for x in repo.masters)) |
7080 |
- |
7081 |
-docstrings['master_repositories'] = """<eroot> <repo_id>+ |
7082 |
+ if len(argv) < 2: |
7083 |
+ print("ERROR: insufficient parameters!", file=sys.stderr) |
7084 |
+ return 3 |
7085 |
+ for arg in argv[1:]: |
7086 |
+ if portage.dep._repo_name_re.match(arg) is None: |
7087 |
+ print("ERROR: invalid repository: %s" % arg, file=sys.stderr) |
7088 |
+ return 2 |
7089 |
+ try: |
7090 |
+ repo = portage.db[argv[0]]["vartree"].settings.repositories[arg] |
7091 |
+ except KeyError: |
7092 |
+ print("") |
7093 |
+ return 1 |
7094 |
+ else: |
7095 |
+ print(" ".join(x.name for x in repo.masters)) |
7096 |
+ |
7097 |
+ |
7098 |
+docstrings[ |
7099 |
+ "master_repositories" |
7100 |
+] = """<eroot> <repo_id>+ |
7101 |
Returns space-separated list of master repositories for specified repository. |
7102 |
""" |
7103 |
-master_repositories.__doc__ = docstrings['master_repositories'] |
7104 |
+master_repositories.__doc__ = docstrings["master_repositories"] |
7105 |
|
7106 |
|
7107 |
@uses_configroot |
7108 |
@uses_eroot |
7109 |
def master_repos(argv): |
7110 |
- return master_repositories(argv) |
7111 |
+ return master_repositories(argv) |
7112 |
+ |
7113 |
|
7114 |
-docstrings['master_repos'] = """<eroot> <repo_id>+ |
7115 |
+docstrings[ |
7116 |
+ "master_repos" |
7117 |
+] = """<eroot> <repo_id>+ |
7118 |
This is an alias for the master_repositories command. |
7119 |
""" |
7120 |
-master_repos.__doc__ = docstrings['master_repos'] |
7121 |
+master_repos.__doc__ = docstrings["master_repos"] |
7122 |
|
7123 |
|
7124 |
@uses_configroot |
7125 |
@uses_eroot |
7126 |
def get_repo_path(argv): |
7127 |
|
7128 |
- if len(argv) < 2: |
7129 |
- print("ERROR: insufficient parameters!", file=sys.stderr) |
7130 |
- return 3 |
7131 |
- for arg in argv[1:]: |
7132 |
- if portage.dep._repo_name_re.match(arg) is None: |
7133 |
- print("ERROR: invalid repository: %s" % arg, file=sys.stderr) |
7134 |
- return 2 |
7135 |
- path = portage.db[argv[0]]["vartree"].settings.repositories.treemap.get(arg) |
7136 |
- if path is None: |
7137 |
- print("") |
7138 |
- return 1 |
7139 |
- print(path) |
7140 |
- |
7141 |
-docstrings['get_repo_path'] = """<eroot> <repo_id>+ |
7142 |
+ if len(argv) < 2: |
7143 |
+ print("ERROR: insufficient parameters!", file=sys.stderr) |
7144 |
+ return 3 |
7145 |
+ for arg in argv[1:]: |
7146 |
+ if portage.dep._repo_name_re.match(arg) is None: |
7147 |
+ print("ERROR: invalid repository: %s" % arg, file=sys.stderr) |
7148 |
+ return 2 |
7149 |
+ path = portage.db[argv[0]]["vartree"].settings.repositories.treemap.get(arg) |
7150 |
+ if path is None: |
7151 |
+ print("") |
7152 |
+ return 1 |
7153 |
+ print(path) |
7154 |
+ |
7155 |
+ |
7156 |
+docstrings[ |
7157 |
+ "get_repo_path" |
7158 |
+] = """<eroot> <repo_id>+ |
7159 |
Returns the path to the repo named argv[1], argv[0] = $EROOT |
7160 |
""" |
7161 |
-get_repo_path.__doc__ = docstrings['get_repo_path'] |
7162 |
+get_repo_path.__doc__ = docstrings["get_repo_path"] |
7163 |
|
7164 |
|
7165 |
@uses_eroot |
7166 |
def available_eclasses(argv): |
7167 |
- if len(argv) < 2: |
7168 |
- print("ERROR: insufficient parameters!", file=sys.stderr) |
7169 |
- return 3 |
7170 |
- for arg in argv[1:]: |
7171 |
- if portage.dep._repo_name_re.match(arg) is None: |
7172 |
- print("ERROR: invalid repository: %s" % arg, file=sys.stderr) |
7173 |
- return 2 |
7174 |
- try: |
7175 |
- repo = portage.db[argv[0]]["vartree"].settings.repositories[arg] |
7176 |
- except KeyError: |
7177 |
- print("") |
7178 |
- return 1 |
7179 |
- else: |
7180 |
- print(" ".join(sorted(repo.eclass_db.eclasses))) |
7181 |
- |
7182 |
-docstrings['available_eclasses'] = """<eroot> <repo_id>+ |
7183 |
+ if len(argv) < 2: |
7184 |
+ print("ERROR: insufficient parameters!", file=sys.stderr) |
7185 |
+ return 3 |
7186 |
+ for arg in argv[1:]: |
7187 |
+ if portage.dep._repo_name_re.match(arg) is None: |
7188 |
+ print("ERROR: invalid repository: %s" % arg, file=sys.stderr) |
7189 |
+ return 2 |
7190 |
+ try: |
7191 |
+ repo = portage.db[argv[0]]["vartree"].settings.repositories[arg] |
7192 |
+ except KeyError: |
7193 |
+ print("") |
7194 |
+ return 1 |
7195 |
+ else: |
7196 |
+ print(" ".join(sorted(repo.eclass_db.eclasses))) |
7197 |
+ |
7198 |
+ |
7199 |
+docstrings[ |
7200 |
+ "available_eclasses" |
7201 |
+] = """<eroot> <repo_id>+ |
7202 |
Returns space-separated list of available eclasses for specified repository. |
7203 |
""" |
7204 |
-available_eclasses.__doc__ = docstrings['available_eclasses'] |
7205 |
+available_eclasses.__doc__ = docstrings["available_eclasses"] |
7206 |
|
7207 |
|
7208 |
@uses_eroot |
7209 |
def eclass_path(argv): |
7210 |
- if len(argv) < 3: |
7211 |
- print("ERROR: insufficient parameters!", file=sys.stderr) |
7212 |
- return 3 |
7213 |
- if portage.dep._repo_name_re.match(argv[1]) is None: |
7214 |
- print("ERROR: invalid repository: %s" % argv[1], file=sys.stderr) |
7215 |
- return 2 |
7216 |
- try: |
7217 |
- repo = portage.db[argv[0]]["vartree"].settings.repositories[argv[1]] |
7218 |
- except KeyError: |
7219 |
- print("") |
7220 |
- return 1 |
7221 |
- else: |
7222 |
- retval = 0 |
7223 |
- for arg in argv[2:]: |
7224 |
- try: |
7225 |
- eclass = repo.eclass_db.eclasses[arg] |
7226 |
- except KeyError: |
7227 |
- print("") |
7228 |
- retval = 1 |
7229 |
- else: |
7230 |
- print(eclass.location) |
7231 |
- return retval |
7232 |
- |
7233 |
-docstrings['eclass_path'] = """<eroot> <repo_id> <eclass>+ |
7234 |
+ if len(argv) < 3: |
7235 |
+ print("ERROR: insufficient parameters!", file=sys.stderr) |
7236 |
+ return 3 |
7237 |
+ if portage.dep._repo_name_re.match(argv[1]) is None: |
7238 |
+ print("ERROR: invalid repository: %s" % argv[1], file=sys.stderr) |
7239 |
+ return 2 |
7240 |
+ try: |
7241 |
+ repo = portage.db[argv[0]]["vartree"].settings.repositories[argv[1]] |
7242 |
+ except KeyError: |
7243 |
+ print("") |
7244 |
+ return 1 |
7245 |
+ else: |
7246 |
+ retval = 0 |
7247 |
+ for arg in argv[2:]: |
7248 |
+ try: |
7249 |
+ eclass = repo.eclass_db.eclasses[arg] |
7250 |
+ except KeyError: |
7251 |
+ print("") |
7252 |
+ retval = 1 |
7253 |
+ else: |
7254 |
+ print(eclass.location) |
7255 |
+ return retval |
7256 |
+ |
7257 |
+ |
7258 |
+docstrings[ |
7259 |
+ "eclass_path" |
7260 |
+] = """<eroot> <repo_id> <eclass>+ |
7261 |
Returns the path to specified eclass for specified repository. |
7262 |
""" |
7263 |
-eclass_path.__doc__ = docstrings['eclass_path'] |
7264 |
+eclass_path.__doc__ = docstrings["eclass_path"] |
7265 |
|
7266 |
|
7267 |
@uses_eroot |
7268 |
def license_path(argv): |
7269 |
- if len(argv) < 3: |
7270 |
- print("ERROR: insufficient parameters!", file=sys.stderr) |
7271 |
- return 3 |
7272 |
- if portage.dep._repo_name_re.match(argv[1]) is None: |
7273 |
- print("ERROR: invalid repository: %s" % argv[1], file=sys.stderr) |
7274 |
- return 2 |
7275 |
- try: |
7276 |
- repo = portage.db[argv[0]]["vartree"].settings.repositories[argv[1]] |
7277 |
- except KeyError: |
7278 |
- print("") |
7279 |
- return 1 |
7280 |
- else: |
7281 |
- retval = 0 |
7282 |
- for arg in argv[2:]: |
7283 |
- eclass_path = "" |
7284 |
- paths = reversed([os.path.join(x.location, 'licenses', arg) for x in list(repo.masters) + [repo]]) |
7285 |
- for path in paths: |
7286 |
- if os.path.exists(path): |
7287 |
- eclass_path = path |
7288 |
- break |
7289 |
- if eclass_path == "": |
7290 |
- retval = 1 |
7291 |
- print(eclass_path) |
7292 |
- return retval |
7293 |
- |
7294 |
-docstrings['license_path'] = """<eroot> <repo_id> <license>+ |
7295 |
+ if len(argv) < 3: |
7296 |
+ print("ERROR: insufficient parameters!", file=sys.stderr) |
7297 |
+ return 3 |
7298 |
+ if portage.dep._repo_name_re.match(argv[1]) is None: |
7299 |
+ print("ERROR: invalid repository: %s" % argv[1], file=sys.stderr) |
7300 |
+ return 2 |
7301 |
+ try: |
7302 |
+ repo = portage.db[argv[0]]["vartree"].settings.repositories[argv[1]] |
7303 |
+ except KeyError: |
7304 |
+ print("") |
7305 |
+ return 1 |
7306 |
+ else: |
7307 |
+ retval = 0 |
7308 |
+ for arg in argv[2:]: |
7309 |
+ eclass_path = "" |
7310 |
+ paths = reversed( |
7311 |
+ [ |
7312 |
+ os.path.join(x.location, "licenses", arg) |
7313 |
+ for x in list(repo.masters) + [repo] |
7314 |
+ ] |
7315 |
+ ) |
7316 |
+ for path in paths: |
7317 |
+ if os.path.exists(path): |
7318 |
+ eclass_path = path |
7319 |
+ break |
7320 |
+ if eclass_path == "": |
7321 |
+ retval = 1 |
7322 |
+ print(eclass_path) |
7323 |
+ return retval |
7324 |
+ |
7325 |
+ |
7326 |
+docstrings[ |
7327 |
+ "license_path" |
7328 |
+] = """<eroot> <repo_id> <license>+ |
7329 |
Returns the path to specified license for specified repository. |
7330 |
""" |
7331 |
-license_path.__doc__ = docstrings['license_path'] |
7332 |
+license_path.__doc__ = docstrings["license_path"] |
7333 |
|
7334 |
|
7335 |
@uses_eroot |
7336 |
def list_preserved_libs(argv): |
7337 |
- if len(argv) != 1: |
7338 |
- print("ERROR: wrong number of arguments") |
7339 |
- return 2 |
7340 |
- mylibs = portage.db[argv[0]]["vartree"].dbapi._plib_registry.getPreservedLibs() |
7341 |
- rValue = 1 |
7342 |
- msg = [] |
7343 |
- for cpv in sorted(mylibs): |
7344 |
- msg.append(cpv) |
7345 |
- for path in mylibs[cpv]: |
7346 |
- msg.append(' ' + path) |
7347 |
- rValue = 0 |
7348 |
- msg.append('\n') |
7349 |
- writemsg_stdout(''.join(msg), noiselevel=-1) |
7350 |
- return rValue |
7351 |
- |
7352 |
-docstrings['list_preserved_libs'] = """<eroot> |
7353 |
+ if len(argv) != 1: |
7354 |
+ print("ERROR: wrong number of arguments") |
7355 |
+ return 2 |
7356 |
+ mylibs = portage.db[argv[0]]["vartree"].dbapi._plib_registry.getPreservedLibs() |
7357 |
+ rValue = 1 |
7358 |
+ msg = [] |
7359 |
+ for cpv in sorted(mylibs): |
7360 |
+ msg.append(cpv) |
7361 |
+ for path in mylibs[cpv]: |
7362 |
+ msg.append(" " + path) |
7363 |
+ rValue = 0 |
7364 |
+ msg.append("\n") |
7365 |
+ writemsg_stdout("".join(msg), noiselevel=-1) |
7366 |
+ return rValue |
7367 |
+ |
7368 |
+ |
7369 |
+docstrings[ |
7370 |
+ "list_preserved_libs" |
7371 |
+] = """<eroot> |
7372 |
Print a list of libraries preserved during a package update in the form |
7373 |
package: path. Returns 1 if no preserved libraries could be found, |
7374 |
0 otherwise. |
7375 |
""" |
7376 |
-list_preserved_libs.__doc__ = docstrings['list_preserved_libs'] |
7377 |
+list_preserved_libs.__doc__ = docstrings["list_preserved_libs"] |
7378 |
|
7379 |
|
7380 |
class MaintainerEmailMatcher: |
7381 |
- def __init__(self, maintainer_emails): |
7382 |
- self._re = re.compile("^(%s)$" % "|".join(maintainer_emails), re.I) |
7383 |
- |
7384 |
- def __call__(self, metadata_xml): |
7385 |
- match = False |
7386 |
- matcher = self._re.match |
7387 |
- for x in metadata_xml.maintainers(): |
7388 |
- if x.email is not None and matcher(x.email) is not None: |
7389 |
- match = True |
7390 |
- break |
7391 |
- return match |
7392 |
+ def __init__(self, maintainer_emails): |
7393 |
+ self._re = re.compile("^(%s)$" % "|".join(maintainer_emails), re.I) |
7394 |
+ |
7395 |
+ def __call__(self, metadata_xml): |
7396 |
+ match = False |
7397 |
+ matcher = self._re.match |
7398 |
+ for x in metadata_xml.maintainers(): |
7399 |
+ if x.email is not None and matcher(x.email) is not None: |
7400 |
+ match = True |
7401 |
+ break |
7402 |
+ return match |
7403 |
+ |
7404 |
|
7405 |
# Match if metadata.xml contains no maintainer (orphaned package) |
7406 |
def match_orphaned(metadata_xml): |
7407 |
- if not metadata_xml.maintainers(): |
7408 |
- return True |
7409 |
- else: |
7410 |
- return False |
7411 |
+ if not metadata_xml.maintainers(): |
7412 |
+ return True |
7413 |
+ else: |
7414 |
+ return False |
7415 |
+ |
7416 |
|
7417 |
def pquery(parser, opts, args): |
7418 |
- portdb = portage.db[portage.root]['porttree'].dbapi |
7419 |
- root_config = RootConfig(portdb.settings, |
7420 |
- portage.db[portage.root], None) |
7421 |
- |
7422 |
- def _pkg(cpv, repo_name): |
7423 |
- try: |
7424 |
- metadata = dict(zip( |
7425 |
- Package.metadata_keys, |
7426 |
- portdb.aux_get(cpv, |
7427 |
- Package.metadata_keys, |
7428 |
- myrepo=repo_name))) |
7429 |
- except KeyError: |
7430 |
- raise portage.exception.PackageNotFound(cpv) |
7431 |
- return Package(built=False, cpv=cpv, |
7432 |
- installed=False, metadata=metadata, |
7433 |
- root_config=root_config, |
7434 |
- type_name="ebuild") |
7435 |
- |
7436 |
- need_metadata = False |
7437 |
- atoms = [] |
7438 |
- for arg in args: |
7439 |
- if "/" not in arg.split(":")[0]: |
7440 |
- atom = insert_category_into_atom(arg, '*') |
7441 |
- if atom is None: |
7442 |
- writemsg("ERROR: Invalid atom: '%s'\n" % arg, |
7443 |
- noiselevel=-1) |
7444 |
- return 2 |
7445 |
- else: |
7446 |
- atom = arg |
7447 |
- |
7448 |
- try: |
7449 |
- atom = portage.dep.Atom(atom, allow_wildcard=True, allow_repo=True) |
7450 |
- except portage.exception.InvalidAtom: |
7451 |
- writemsg("ERROR: Invalid atom: '%s'\n" % arg, |
7452 |
- noiselevel=-1) |
7453 |
- return 2 |
7454 |
- |
7455 |
- if atom.slot is not None: |
7456 |
- need_metadata = True |
7457 |
- |
7458 |
- atoms.append(atom) |
7459 |
- |
7460 |
- if "*/*" in atoms: |
7461 |
- del atoms[:] |
7462 |
- need_metadata = False |
7463 |
- |
7464 |
- if not opts.no_filters: |
7465 |
- need_metadata = True |
7466 |
- |
7467 |
- xml_matchers = [] |
7468 |
- if opts.maintainer_email: |
7469 |
- maintainer_emails = [] |
7470 |
- for x in opts.maintainer_email: |
7471 |
- maintainer_emails.extend(x.split(",")) |
7472 |
- if opts.no_regex: # Escape regex-special characters for an exact match |
7473 |
- maintainer_emails = [re.escape(x) for x in maintainer_emails] |
7474 |
- xml_matchers.append(MaintainerEmailMatcher(maintainer_emails)) |
7475 |
- if opts.orphaned: |
7476 |
- xml_matchers.append(match_orphaned) |
7477 |
- |
7478 |
- if opts.repo is not None: |
7479 |
- repos = [portdb.repositories[opts.repo]] |
7480 |
- else: |
7481 |
- repos = list(portdb.repositories) |
7482 |
- |
7483 |
- if not atoms: |
7484 |
- names = None |
7485 |
- categories = list(portdb.categories) |
7486 |
- else: |
7487 |
- category_wildcard = False |
7488 |
- name_wildcard = False |
7489 |
- categories = [] |
7490 |
- names = [] |
7491 |
- for atom in atoms: |
7492 |
- category, name = portage.catsplit(atom.cp) |
7493 |
- categories.append(category) |
7494 |
- names.append(name) |
7495 |
- if "*" in category: |
7496 |
- category_wildcard = True |
7497 |
- if "*" in name: |
7498 |
- name_wildcard = True |
7499 |
- |
7500 |
- if category_wildcard: |
7501 |
- categories = list(portdb.categories) |
7502 |
- else: |
7503 |
- categories = list(set(categories)) |
7504 |
- |
7505 |
- if name_wildcard: |
7506 |
- names = None |
7507 |
- else: |
7508 |
- names = sorted(set(names)) |
7509 |
- |
7510 |
- no_version = opts.no_version |
7511 |
- categories.sort() |
7512 |
- |
7513 |
- for category in categories: |
7514 |
- if names is None: |
7515 |
- cp_list = portdb.cp_all(categories=(category,)) |
7516 |
- else: |
7517 |
- cp_list = [category + "/" + name for name in names] |
7518 |
- for cp in cp_list: |
7519 |
- matches = [] |
7520 |
- for repo in repos: |
7521 |
- match = True |
7522 |
- if xml_matchers: |
7523 |
- metadata_xml_path = os.path.join( |
7524 |
- repo.location, cp, 'metadata.xml') |
7525 |
- try: |
7526 |
- metadata_xml = MetaDataXML(metadata_xml_path, None) |
7527 |
- except (EnvironmentError, SyntaxError): |
7528 |
- match = False |
7529 |
- else: |
7530 |
- for matcher in xml_matchers: |
7531 |
- if not matcher(metadata_xml): |
7532 |
- match = False |
7533 |
- break |
7534 |
- if not match: |
7535 |
- continue |
7536 |
- cpv_list = portdb.cp_list(cp, mytree=[repo.location]) |
7537 |
- if atoms: |
7538 |
- for cpv in cpv_list: |
7539 |
- pkg = None |
7540 |
- for atom in atoms: |
7541 |
- if atom.repo is not None and \ |
7542 |
- atom.repo != repo.name: |
7543 |
- continue |
7544 |
- if not portage.match_from_list(atom, [cpv]): |
7545 |
- continue |
7546 |
- if need_metadata: |
7547 |
- if pkg is None: |
7548 |
- try: |
7549 |
- pkg = _pkg(cpv, repo.name) |
7550 |
- except portage.exception.PackageNotFound: |
7551 |
- continue |
7552 |
- |
7553 |
- if not (opts.no_filters or pkg.visible): |
7554 |
- continue |
7555 |
- if not portage.match_from_list(atom, [pkg]): |
7556 |
- continue |
7557 |
- matches.append(cpv) |
7558 |
- break |
7559 |
- if no_version and matches: |
7560 |
- break |
7561 |
- elif opts.no_filters: |
7562 |
- matches.extend(cpv_list) |
7563 |
- else: |
7564 |
- for cpv in cpv_list: |
7565 |
- try: |
7566 |
- pkg = _pkg(cpv, repo.name) |
7567 |
- except portage.exception.PackageNotFound: |
7568 |
- continue |
7569 |
- else: |
7570 |
- if pkg.visible: |
7571 |
- matches.append(cpv) |
7572 |
- if no_version: |
7573 |
- break |
7574 |
- |
7575 |
- if no_version and matches: |
7576 |
- break |
7577 |
- |
7578 |
- if not matches: |
7579 |
- continue |
7580 |
- |
7581 |
- if no_version: |
7582 |
- writemsg_stdout("%s\n" % (cp,), noiselevel=-1) |
7583 |
- else: |
7584 |
- matches = list(set(matches)) |
7585 |
- portdb._cpv_sort_ascending(matches) |
7586 |
- for cpv in matches: |
7587 |
- writemsg_stdout("%s\n" % (cpv,), noiselevel=-1) |
7588 |
- |
7589 |
- return os.EX_OK |
7590 |
- |
7591 |
-docstrings['pquery'] = """[options] [atom]+ |
7592 |
+ portdb = portage.db[portage.root]["porttree"].dbapi |
7593 |
+ root_config = RootConfig(portdb.settings, portage.db[portage.root], None) |
7594 |
+ |
7595 |
+ def _pkg(cpv, repo_name): |
7596 |
+ try: |
7597 |
+ metadata = dict( |
7598 |
+ zip( |
7599 |
+ Package.metadata_keys, |
7600 |
+ portdb.aux_get(cpv, Package.metadata_keys, myrepo=repo_name), |
7601 |
+ ) |
7602 |
+ ) |
7603 |
+ except KeyError: |
7604 |
+ raise portage.exception.PackageNotFound(cpv) |
7605 |
+ return Package( |
7606 |
+ built=False, |
7607 |
+ cpv=cpv, |
7608 |
+ installed=False, |
7609 |
+ metadata=metadata, |
7610 |
+ root_config=root_config, |
7611 |
+ type_name="ebuild", |
7612 |
+ ) |
7613 |
+ |
7614 |
+ need_metadata = False |
7615 |
+ atoms = [] |
7616 |
+ for arg in args: |
7617 |
+ if "/" not in arg.split(":")[0]: |
7618 |
+ atom = insert_category_into_atom(arg, "*") |
7619 |
+ if atom is None: |
7620 |
+ writemsg("ERROR: Invalid atom: '%s'\n" % arg, noiselevel=-1) |
7621 |
+ return 2 |
7622 |
+ else: |
7623 |
+ atom = arg |
7624 |
+ |
7625 |
+ try: |
7626 |
+ atom = portage.dep.Atom(atom, allow_wildcard=True, allow_repo=True) |
7627 |
+ except portage.exception.InvalidAtom: |
7628 |
+ writemsg("ERROR: Invalid atom: '%s'\n" % arg, noiselevel=-1) |
7629 |
+ return 2 |
7630 |
+ |
7631 |
+ if atom.slot is not None: |
7632 |
+ need_metadata = True |
7633 |
+ |
7634 |
+ atoms.append(atom) |
7635 |
+ |
7636 |
+ if "*/*" in atoms: |
7637 |
+ del atoms[:] |
7638 |
+ need_metadata = False |
7639 |
+ |
7640 |
+ if not opts.no_filters: |
7641 |
+ need_metadata = True |
7642 |
+ |
7643 |
+ xml_matchers = [] |
7644 |
+ if opts.maintainer_email: |
7645 |
+ maintainer_emails = [] |
7646 |
+ for x in opts.maintainer_email: |
7647 |
+ maintainer_emails.extend(x.split(",")) |
7648 |
+ if opts.no_regex: # Escape regex-special characters for an exact match |
7649 |
+ maintainer_emails = [re.escape(x) for x in maintainer_emails] |
7650 |
+ xml_matchers.append(MaintainerEmailMatcher(maintainer_emails)) |
7651 |
+ if opts.orphaned: |
7652 |
+ xml_matchers.append(match_orphaned) |
7653 |
+ |
7654 |
+ if opts.repo is not None: |
7655 |
+ repos = [portdb.repositories[opts.repo]] |
7656 |
+ else: |
7657 |
+ repos = list(portdb.repositories) |
7658 |
+ |
7659 |
+ if not atoms: |
7660 |
+ names = None |
7661 |
+ categories = list(portdb.categories) |
7662 |
+ else: |
7663 |
+ category_wildcard = False |
7664 |
+ name_wildcard = False |
7665 |
+ categories = [] |
7666 |
+ names = [] |
7667 |
+ for atom in atoms: |
7668 |
+ category, name = portage.catsplit(atom.cp) |
7669 |
+ categories.append(category) |
7670 |
+ names.append(name) |
7671 |
+ if "*" in category: |
7672 |
+ category_wildcard = True |
7673 |
+ if "*" in name: |
7674 |
+ name_wildcard = True |
7675 |
+ |
7676 |
+ if category_wildcard: |
7677 |
+ categories = list(portdb.categories) |
7678 |
+ else: |
7679 |
+ categories = list(set(categories)) |
7680 |
+ |
7681 |
+ if name_wildcard: |
7682 |
+ names = None |
7683 |
+ else: |
7684 |
+ names = sorted(set(names)) |
7685 |
+ |
7686 |
+ no_version = opts.no_version |
7687 |
+ categories.sort() |
7688 |
+ |
7689 |
+ for category in categories: |
7690 |
+ if names is None: |
7691 |
+ cp_list = portdb.cp_all(categories=(category,)) |
7692 |
+ else: |
7693 |
+ cp_list = [category + "/" + name for name in names] |
7694 |
+ for cp in cp_list: |
7695 |
+ matches = [] |
7696 |
+ for repo in repos: |
7697 |
+ match = True |
7698 |
+ if xml_matchers: |
7699 |
+ metadata_xml_path = os.path.join(repo.location, cp, "metadata.xml") |
7700 |
+ try: |
7701 |
+ metadata_xml = MetaDataXML(metadata_xml_path, None) |
7702 |
+ except (EnvironmentError, SyntaxError): |
7703 |
+ match = False |
7704 |
+ else: |
7705 |
+ for matcher in xml_matchers: |
7706 |
+ if not matcher(metadata_xml): |
7707 |
+ match = False |
7708 |
+ break |
7709 |
+ if not match: |
7710 |
+ continue |
7711 |
+ cpv_list = portdb.cp_list(cp, mytree=[repo.location]) |
7712 |
+ if atoms: |
7713 |
+ for cpv in cpv_list: |
7714 |
+ pkg = None |
7715 |
+ for atom in atoms: |
7716 |
+ if atom.repo is not None and atom.repo != repo.name: |
7717 |
+ continue |
7718 |
+ if not portage.match_from_list(atom, [cpv]): |
7719 |
+ continue |
7720 |
+ if need_metadata: |
7721 |
+ if pkg is None: |
7722 |
+ try: |
7723 |
+ pkg = _pkg(cpv, repo.name) |
7724 |
+ except portage.exception.PackageNotFound: |
7725 |
+ continue |
7726 |
+ |
7727 |
+ if not (opts.no_filters or pkg.visible): |
7728 |
+ continue |
7729 |
+ if not portage.match_from_list(atom, [pkg]): |
7730 |
+ continue |
7731 |
+ matches.append(cpv) |
7732 |
+ break |
7733 |
+ if no_version and matches: |
7734 |
+ break |
7735 |
+ elif opts.no_filters: |
7736 |
+ matches.extend(cpv_list) |
7737 |
+ else: |
7738 |
+ for cpv in cpv_list: |
7739 |
+ try: |
7740 |
+ pkg = _pkg(cpv, repo.name) |
7741 |
+ except portage.exception.PackageNotFound: |
7742 |
+ continue |
7743 |
+ else: |
7744 |
+ if pkg.visible: |
7745 |
+ matches.append(cpv) |
7746 |
+ if no_version: |
7747 |
+ break |
7748 |
+ |
7749 |
+ if no_version and matches: |
7750 |
+ break |
7751 |
+ |
7752 |
+ if not matches: |
7753 |
+ continue |
7754 |
+ |
7755 |
+ if no_version: |
7756 |
+ writemsg_stdout("%s\n" % (cp,), noiselevel=-1) |
7757 |
+ else: |
7758 |
+ matches = list(set(matches)) |
7759 |
+ portdb._cpv_sort_ascending(matches) |
7760 |
+ for cpv in matches: |
7761 |
+ writemsg_stdout("%s\n" % (cpv,), noiselevel=-1) |
7762 |
+ |
7763 |
+ return os.EX_OK |
7764 |
+ |
7765 |
+ |
7766 |
+docstrings[ |
7767 |
+ "pquery" |
7768 |
+] = """[options] [atom]+ |
7769 |
Emulates a subset of Pkgcore's pquery tool. |
7770 |
""" |
7771 |
-pquery.__doc__ = docstrings['pquery'] |
7772 |
+pquery.__doc__ = docstrings["pquery"] |
7773 |
|
7774 |
|
7775 |
-#----------------------------------------------------------------------------- |
7776 |
+# ----------------------------------------------------------------------------- |
7777 |
# |
7778 |
# DO NOT CHANGE CODE BEYOND THIS POINT - IT'S NOT NEEDED! |
7779 |
# |
7780 |
|
7781 |
-non_commands = frozenset(['elog', 'eval_atom_use', 'exithandler', 'match_orphaned', 'main', 'usage', 'uses_eroot']) |
7782 |
-commands = sorted(k for k, v in globals().items() \ |
7783 |
- if k not in non_commands and isinstance(v, types.FunctionType) and v.__module__ == "__main__") |
7784 |
+non_commands = frozenset( |
7785 |
+ [ |
7786 |
+ "elog", |
7787 |
+ "eval_atom_use", |
7788 |
+ "exithandler", |
7789 |
+ "match_orphaned", |
7790 |
+ "main", |
7791 |
+ "usage", |
7792 |
+ "uses_eroot", |
7793 |
+ ] |
7794 |
+) |
7795 |
+commands = sorted( |
7796 |
+ k |
7797 |
+ for k, v in globals().items() |
7798 |
+ if k not in non_commands |
7799 |
+ and isinstance(v, types.FunctionType) |
7800 |
+ and v.__module__ == "__main__" |
7801 |
+) |
7802 |
|
7803 |
|
7804 |
def add_pquery_arguments(parser): |
7805 |
- pquery_option_groups = ( |
7806 |
- ( |
7807 |
- 'Repository matching options', |
7808 |
- ( |
7809 |
- { |
7810 |
- "longopt": "--no-filters", |
7811 |
- "action": "store_true", |
7812 |
- "help": "no visibility filters (ACCEPT_KEYWORDS, package masking, etc)" |
7813 |
- }, |
7814 |
- { |
7815 |
- "longopt": "--repo", |
7816 |
- "help": "repository to use (all repositories are used by default)" |
7817 |
- }, |
7818 |
- ) |
7819 |
- ), |
7820 |
- ( |
7821 |
- 'Package matching options', |
7822 |
- ( |
7823 |
- { |
7824 |
- "longopt": "--maintainer-email", |
7825 |
- "action": "append", |
7826 |
- "help": "comma-separated list of maintainer email regexes to search for" |
7827 |
- }, |
7828 |
- { |
7829 |
- "longopt": "--no-regex", |
7830 |
- "action": "store_true", |
7831 |
- "help": "Use exact matching instead of regex matching for --maintainer-email" |
7832 |
- }, |
7833 |
- { |
7834 |
- "longopt": "--orphaned", |
7835 |
- "action": "store_true", |
7836 |
- "help": "match only orphaned (maintainer-needed) packages" |
7837 |
- } |
7838 |
- ) |
7839 |
- ), |
7840 |
- ( |
7841 |
- 'Output formatting', |
7842 |
- ( |
7843 |
- { |
7844 |
- "shortopt": "-n", |
7845 |
- "longopt": "--no-version", |
7846 |
- "action": "store_true", |
7847 |
- "help": "collapse multiple matching versions together" |
7848 |
- }, |
7849 |
- ) |
7850 |
- ), |
7851 |
- ) |
7852 |
- |
7853 |
- for group_title, opt_data in pquery_option_groups: |
7854 |
- arg_group = parser.add_argument_group(group_title) |
7855 |
- for opt_info in opt_data: |
7856 |
- pargs = [] |
7857 |
- try: |
7858 |
- pargs.append(opt_info["shortopt"]) |
7859 |
- except KeyError: |
7860 |
- pass |
7861 |
- try: |
7862 |
- pargs.append(opt_info["longopt"]) |
7863 |
- except KeyError: |
7864 |
- pass |
7865 |
- |
7866 |
- kwargs = {} |
7867 |
- try: |
7868 |
- kwargs["action"] = opt_info["action"] |
7869 |
- except KeyError: |
7870 |
- pass |
7871 |
- try: |
7872 |
- kwargs["help"] = opt_info["help"] |
7873 |
- except KeyError: |
7874 |
- pass |
7875 |
- arg_group.add_argument(*pargs, **kwargs) |
7876 |
+ pquery_option_groups = ( |
7877 |
+ ( |
7878 |
+ "Repository matching options", |
7879 |
+ ( |
7880 |
+ { |
7881 |
+ "longopt": "--no-filters", |
7882 |
+ "action": "store_true", |
7883 |
+ "help": "no visibility filters (ACCEPT_KEYWORDS, package masking, etc)", |
7884 |
+ }, |
7885 |
+ { |
7886 |
+ "longopt": "--repo", |
7887 |
+ "help": "repository to use (all repositories are used by default)", |
7888 |
+ }, |
7889 |
+ ), |
7890 |
+ ), |
7891 |
+ ( |
7892 |
+ "Package matching options", |
7893 |
+ ( |
7894 |
+ { |
7895 |
+ "longopt": "--maintainer-email", |
7896 |
+ "action": "append", |
7897 |
+ "help": "comma-separated list of maintainer email regexes to search for", |
7898 |
+ }, |
7899 |
+ { |
7900 |
+ "longopt": "--no-regex", |
7901 |
+ "action": "store_true", |
7902 |
+ "help": "Use exact matching instead of regex matching for --maintainer-email", |
7903 |
+ }, |
7904 |
+ { |
7905 |
+ "longopt": "--orphaned", |
7906 |
+ "action": "store_true", |
7907 |
+ "help": "match only orphaned (maintainer-needed) packages", |
7908 |
+ }, |
7909 |
+ ), |
7910 |
+ ), |
7911 |
+ ( |
7912 |
+ "Output formatting", |
7913 |
+ ( |
7914 |
+ { |
7915 |
+ "shortopt": "-n", |
7916 |
+ "longopt": "--no-version", |
7917 |
+ "action": "store_true", |
7918 |
+ "help": "collapse multiple matching versions together", |
7919 |
+ }, |
7920 |
+ ), |
7921 |
+ ), |
7922 |
+ ) |
7923 |
+ |
7924 |
+ for group_title, opt_data in pquery_option_groups: |
7925 |
+ arg_group = parser.add_argument_group(group_title) |
7926 |
+ for opt_info in opt_data: |
7927 |
+ pargs = [] |
7928 |
+ try: |
7929 |
+ pargs.append(opt_info["shortopt"]) |
7930 |
+ except KeyError: |
7931 |
+ pass |
7932 |
+ try: |
7933 |
+ pargs.append(opt_info["longopt"]) |
7934 |
+ except KeyError: |
7935 |
+ pass |
7936 |
+ |
7937 |
+ kwargs = {} |
7938 |
+ try: |
7939 |
+ kwargs["action"] = opt_info["action"] |
7940 |
+ except KeyError: |
7941 |
+ pass |
7942 |
+ try: |
7943 |
+ kwargs["help"] = opt_info["help"] |
7944 |
+ except KeyError: |
7945 |
+ pass |
7946 |
+ arg_group.add_argument(*pargs, **kwargs) |
7947 |
|
7948 |
|
7949 |
def usage(argv): |
7950 |
- print(">>> Portage information query tool") |
7951 |
- print(">>> %s" % portage.VERSION) |
7952 |
- print(">>> Usage: portageq <command> [<option> ...]") |
7953 |
- print("") |
7954 |
- print("Available commands:") |
7955 |
- |
7956 |
- # |
7957 |
- # Show our commands -- we do this by scanning the functions in this |
7958 |
- # file, and formatting each functions documentation. |
7959 |
- # |
7960 |
- help_mode = '--help' in argv |
7961 |
- for name in commands: |
7962 |
- doc = docstrings.get(name) |
7963 |
- if doc == None: |
7964 |
- print(" " + name) |
7965 |
- print(" MISSING DOCUMENTATION!") |
7966 |
- print("") |
7967 |
- continue |
7968 |
- |
7969 |
- lines = doc.lstrip("\n").split("\n") |
7970 |
- print(" " + name + " " + lines[0].strip()) |
7971 |
- if len(argv) > 1: |
7972 |
- if not help_mode: |
7973 |
- lines = lines[:-1] |
7974 |
- for line in lines[1:]: |
7975 |
- print(" " + line.strip()) |
7976 |
- |
7977 |
- print() |
7978 |
- print('Pkgcore pquery compatible options:') |
7979 |
- print() |
7980 |
- parser = argparse.ArgumentParser(add_help=False, |
7981 |
- usage='portageq pquery [options] [atom ...]') |
7982 |
- add_pquery_arguments(parser) |
7983 |
- parser.print_help() |
7984 |
- |
7985 |
- if len(argv) == 1: |
7986 |
- print("\nRun portageq with --help for info") |
7987 |
+ print(">>> Portage information query tool") |
7988 |
+ print(">>> %s" % portage.VERSION) |
7989 |
+ print(">>> Usage: portageq <command> [<option> ...]") |
7990 |
+ print("") |
7991 |
+ print("Available commands:") |
7992 |
+ |
7993 |
+ # |
7994 |
+ # Show our commands -- we do this by scanning the functions in this |
7995 |
+ # file, and formatting each functions documentation. |
7996 |
+ # |
7997 |
+ help_mode = "--help" in argv |
7998 |
+ for name in commands: |
7999 |
+ doc = docstrings.get(name) |
8000 |
+ if doc == None: |
8001 |
+ print(" " + name) |
8002 |
+ print(" MISSING DOCUMENTATION!") |
8003 |
+ print("") |
8004 |
+ continue |
8005 |
+ |
8006 |
+ lines = doc.lstrip("\n").split("\n") |
8007 |
+ print(" " + name + " " + lines[0].strip()) |
8008 |
+ if len(argv) > 1: |
8009 |
+ if not help_mode: |
8010 |
+ lines = lines[:-1] |
8011 |
+ for line in lines[1:]: |
8012 |
+ print(" " + line.strip()) |
8013 |
+ |
8014 |
+ print() |
8015 |
+ print("Pkgcore pquery compatible options:") |
8016 |
+ print() |
8017 |
+ parser = argparse.ArgumentParser( |
8018 |
+ add_help=False, usage="portageq pquery [options] [atom ...]" |
8019 |
+ ) |
8020 |
+ add_pquery_arguments(parser) |
8021 |
+ parser.print_help() |
8022 |
+ |
8023 |
+ if len(argv) == 1: |
8024 |
+ print("\nRun portageq with --help for info") |
8025 |
+ |
8026 |
|
8027 |
atom_validate_strict = "EBUILD_PHASE" in os.environ |
8028 |
eapi = None |
8029 |
if atom_validate_strict: |
8030 |
- eapi = os.environ.get('EAPI') |
8031 |
+ eapi = os.environ.get("EAPI") |
8032 |
|
8033 |
- def elog(elog_funcname, lines): |
8034 |
- cmd = "source '%s/isolated-functions.sh' ; " % \ |
8035 |
- os.environ["PORTAGE_BIN_PATH"] |
8036 |
- for line in lines: |
8037 |
- cmd += "%s %s ; " % (elog_funcname, portage._shell_quote(line)) |
8038 |
- subprocess.call([portage.const.BASH_BINARY, "-c", cmd]) |
8039 |
+ def elog(elog_funcname, lines): |
8040 |
+ cmd = "source '%s/isolated-functions.sh' ; " % os.environ["PORTAGE_BIN_PATH"] |
8041 |
+ for line in lines: |
8042 |
+ cmd += "%s %s ; " % (elog_funcname, portage._shell_quote(line)) |
8043 |
+ subprocess.call([portage.const.BASH_BINARY, "-c", cmd]) |
8044 |
|
8045 |
else: |
8046 |
- def elog(elog_funcname, lines): |
8047 |
- pass |
8048 |
+ |
8049 |
+ def elog(elog_funcname, lines): |
8050 |
+ pass |
8051 |
+ |
8052 |
|
8053 |
def main(argv): |
8054 |
|
8055 |
- argv = portage._decode_argv(argv) |
8056 |
- |
8057 |
- nocolor = os.environ.get('NOCOLOR') |
8058 |
- if nocolor in ('yes', 'true'): |
8059 |
- portage.output.nocolor() |
8060 |
- |
8061 |
- parser = argparse.ArgumentParser(add_help=False) |
8062 |
- |
8063 |
- # used by envvar |
8064 |
- parser.add_argument("-v", dest="verbose", action="store_true") |
8065 |
- |
8066 |
- actions = parser.add_argument_group('Actions') |
8067 |
- actions.add_argument("-h", "--help", action="store_true") |
8068 |
- actions.add_argument("--version", action="store_true") |
8069 |
- |
8070 |
- add_pquery_arguments(parser) |
8071 |
- |
8072 |
- opts, args = parser.parse_known_args(argv[1:]) |
8073 |
- |
8074 |
- if opts.help: |
8075 |
- usage(argv) |
8076 |
- return os.EX_OK |
8077 |
- elif opts.version: |
8078 |
- print("Portage", portage.VERSION) |
8079 |
- return os.EX_OK |
8080 |
- |
8081 |
- cmd = None |
8082 |
- if args and args[0] in commands: |
8083 |
- cmd = args[0] |
8084 |
- |
8085 |
- if cmd == 'pquery': |
8086 |
- cmd = None |
8087 |
- args = args[1:] |
8088 |
- |
8089 |
- if cmd is None: |
8090 |
- return pquery(parser, opts, args) |
8091 |
- |
8092 |
- if opts.verbose: |
8093 |
- # used by envvar |
8094 |
- args.append("-v") |
8095 |
- |
8096 |
- argv = argv[:1] + args |
8097 |
- |
8098 |
- if len(argv) < 2: |
8099 |
- usage(argv) |
8100 |
- sys.exit(os.EX_USAGE) |
8101 |
- |
8102 |
- function = globals()[cmd] |
8103 |
- uses_eroot = getattr(function, "uses_eroot", False) and len(argv) > 2 |
8104 |
- if uses_eroot: |
8105 |
- if not os.path.isdir(argv[2]): |
8106 |
- sys.stderr.write("Not a directory: '%s'\n" % argv[2]) |
8107 |
- sys.stderr.write("Run portageq with --help for info\n") |
8108 |
- sys.stderr.flush() |
8109 |
- sys.exit(os.EX_USAGE) |
8110 |
- # Calculate EPREFIX and ROOT that will be used to construct |
8111 |
- # portage.settings later. It's tempting to use |
8112 |
- # portage.settings["EPREFIX"] here, but that would force |
8113 |
- # instantiation of portage.settings, which we don't want to do |
8114 |
- # until after we've calculated ROOT (see bug #529200). |
8115 |
- eprefix = portage.data._target_eprefix() |
8116 |
- eroot = portage.util.normalize_path(argv[2]) |
8117 |
- |
8118 |
- if eprefix: |
8119 |
- if not eroot.endswith(eprefix): |
8120 |
- sys.stderr.write("ERROR: This version of portageq" |
8121 |
- " only supports <eroot>s ending in" |
8122 |
- " '%s'. The provided <eroot>, '%s'," |
8123 |
- " doesn't.\n" % (eprefix, eroot)) |
8124 |
- sys.stderr.flush() |
8125 |
- sys.exit(os.EX_USAGE) |
8126 |
- root = eroot[:1 - len(eprefix)] |
8127 |
- else: |
8128 |
- root = eroot |
8129 |
- |
8130 |
- os.environ["ROOT"] = root |
8131 |
- |
8132 |
- if getattr(function, "uses_configroot", False): |
8133 |
- os.environ["PORTAGE_CONFIGROOT"] = eroot |
8134 |
- # Disable RepoConfigLoader location validation, allowing raw |
8135 |
- # configuration to pass through, since repo locations are not |
8136 |
- # necessarily expected to exist if the configuration comes |
8137 |
- # from a chroot. |
8138 |
- portage._sync_mode = True |
8139 |
- |
8140 |
- args = argv[2:] |
8141 |
- |
8142 |
- try: |
8143 |
- if uses_eroot: |
8144 |
- args[0] = portage.settings['EROOT'] |
8145 |
- retval = function(args) |
8146 |
- if retval: |
8147 |
- sys.exit(retval) |
8148 |
- except portage.exception.PermissionDenied as e: |
8149 |
- sys.stderr.write("Permission denied: '%s'\n" % str(e)) |
8150 |
- sys.exit(e.errno) |
8151 |
- except portage.exception.ParseError as e: |
8152 |
- sys.stderr.write("%s\n" % str(e)) |
8153 |
- sys.exit(1) |
8154 |
- except portage.exception.AmbiguousPackageName as e: |
8155 |
- # Multiple matches thrown from cpv_expand |
8156 |
- pkgs = e.args[0] |
8157 |
- # An error has occurred so we writemsg to stderr and exit nonzero. |
8158 |
- portage.writemsg("You specified an unqualified atom that matched multiple packages:\n", noiselevel=-1) |
8159 |
- for pkg in pkgs: |
8160 |
- portage.writemsg("* %s\n" % pkg, noiselevel=-1) |
8161 |
- portage.writemsg("\nPlease use a more specific atom.\n", noiselevel=-1) |
8162 |
- sys.exit(1) |
8163 |
- |
8164 |
-if __name__ == '__main__': |
8165 |
- try: |
8166 |
- sys.exit(main(sys.argv)) |
8167 |
- finally: |
8168 |
- global_event_loop().close() |
8169 |
- |
8170 |
-#----------------------------------------------------------------------------- |
8171 |
+ argv = portage._decode_argv(argv) |
8172 |
+ |
8173 |
+ nocolor = os.environ.get("NOCOLOR") |
8174 |
+ if nocolor in ("yes", "true"): |
8175 |
+ portage.output.nocolor() |
8176 |
+ |
8177 |
+ parser = argparse.ArgumentParser(add_help=False) |
8178 |
+ |
8179 |
+ # used by envvar |
8180 |
+ parser.add_argument("-v", dest="verbose", action="store_true") |
8181 |
+ |
8182 |
+ actions = parser.add_argument_group("Actions") |
8183 |
+ actions.add_argument("-h", "--help", action="store_true") |
8184 |
+ actions.add_argument("--version", action="store_true") |
8185 |
+ |
8186 |
+ add_pquery_arguments(parser) |
8187 |
+ |
8188 |
+ opts, args = parser.parse_known_args(argv[1:]) |
8189 |
+ |
8190 |
+ if opts.help: |
8191 |
+ usage(argv) |
8192 |
+ return os.EX_OK |
8193 |
+ elif opts.version: |
8194 |
+ print("Portage", portage.VERSION) |
8195 |
+ return os.EX_OK |
8196 |
+ |
8197 |
+ cmd = None |
8198 |
+ if args and args[0] in commands: |
8199 |
+ cmd = args[0] |
8200 |
+ |
8201 |
+ if cmd == "pquery": |
8202 |
+ cmd = None |
8203 |
+ args = args[1:] |
8204 |
+ |
8205 |
+ if cmd is None: |
8206 |
+ return pquery(parser, opts, args) |
8207 |
+ |
8208 |
+ if opts.verbose: |
8209 |
+ # used by envvar |
8210 |
+ args.append("-v") |
8211 |
+ |
8212 |
+ argv = argv[:1] + args |
8213 |
+ |
8214 |
+ if len(argv) < 2: |
8215 |
+ usage(argv) |
8216 |
+ sys.exit(os.EX_USAGE) |
8217 |
+ |
8218 |
+ function = globals()[cmd] |
8219 |
+ uses_eroot = getattr(function, "uses_eroot", False) and len(argv) > 2 |
8220 |
+ if uses_eroot: |
8221 |
+ if not os.path.isdir(argv[2]): |
8222 |
+ sys.stderr.write("Not a directory: '%s'\n" % argv[2]) |
8223 |
+ sys.stderr.write("Run portageq with --help for info\n") |
8224 |
+ sys.stderr.flush() |
8225 |
+ sys.exit(os.EX_USAGE) |
8226 |
+ # Calculate EPREFIX and ROOT that will be used to construct |
8227 |
+ # portage.settings later. It's tempting to use |
8228 |
+ # portage.settings["EPREFIX"] here, but that would force |
8229 |
+ # instantiation of portage.settings, which we don't want to do |
8230 |
+ # until after we've calculated ROOT (see bug #529200). |
8231 |
+ eprefix = portage.data._target_eprefix() |
8232 |
+ eroot = portage.util.normalize_path(argv[2]) |
8233 |
+ |
8234 |
+ if eprefix: |
8235 |
+ if not eroot.endswith(eprefix): |
8236 |
+ sys.stderr.write( |
8237 |
+ "ERROR: This version of portageq" |
8238 |
+ " only supports <eroot>s ending in" |
8239 |
+ " '%s'. The provided <eroot>, '%s'," |
8240 |
+ " doesn't.\n" % (eprefix, eroot) |
8241 |
+ ) |
8242 |
+ sys.stderr.flush() |
8243 |
+ sys.exit(os.EX_USAGE) |
8244 |
+ root = eroot[: 1 - len(eprefix)] |
8245 |
+ else: |
8246 |
+ root = eroot |
8247 |
+ |
8248 |
+ os.environ["ROOT"] = root |
8249 |
+ |
8250 |
+ if getattr(function, "uses_configroot", False): |
8251 |
+ os.environ["PORTAGE_CONFIGROOT"] = eroot |
8252 |
+ # Disable RepoConfigLoader location validation, allowing raw |
8253 |
+ # configuration to pass through, since repo locations are not |
8254 |
+ # necessarily expected to exist if the configuration comes |
8255 |
+ # from a chroot. |
8256 |
+ portage._sync_mode = True |
8257 |
+ |
8258 |
+ args = argv[2:] |
8259 |
+ |
8260 |
+ try: |
8261 |
+ if uses_eroot: |
8262 |
+ args[0] = portage.settings["EROOT"] |
8263 |
+ retval = function(args) |
8264 |
+ if retval: |
8265 |
+ sys.exit(retval) |
8266 |
+ except portage.exception.PermissionDenied as e: |
8267 |
+ sys.stderr.write("Permission denied: '%s'\n" % str(e)) |
8268 |
+ sys.exit(e.errno) |
8269 |
+ except portage.exception.ParseError as e: |
8270 |
+ sys.stderr.write("%s\n" % str(e)) |
8271 |
+ sys.exit(1) |
8272 |
+ except portage.exception.AmbiguousPackageName as e: |
8273 |
+ # Multiple matches thrown from cpv_expand |
8274 |
+ pkgs = e.args[0] |
8275 |
+ # An error has occurred so we writemsg to stderr and exit nonzero. |
8276 |
+ portage.writemsg( |
8277 |
+ "You specified an unqualified atom that matched multiple packages:\n", |
8278 |
+ noiselevel=-1, |
8279 |
+ ) |
8280 |
+ for pkg in pkgs: |
8281 |
+ portage.writemsg("* %s\n" % pkg, noiselevel=-1) |
8282 |
+ portage.writemsg("\nPlease use a more specific atom.\n", noiselevel=-1) |
8283 |
+ sys.exit(1) |
8284 |
+ |
8285 |
+ |
8286 |
+if __name__ == "__main__": |
8287 |
+ try: |
8288 |
+ sys.exit(main(sys.argv)) |
8289 |
+ finally: |
8290 |
+ global_event_loop().close() |
8291 |
+ |
8292 |
+# ----------------------------------------------------------------------------- |
8293 |
|
8294 |
diff --git a/bin/quickpkg b/bin/quickpkg |
8295 |
index 7a3304ca4..a4a3584da 100755 |
8296 |
--- a/bin/quickpkg |
8297 |
+++ b/bin/quickpkg |
8298 |
@@ -10,19 +10,32 @@ import subprocess |
8299 |
import sys |
8300 |
|
8301 |
from os import path as osp |
8302 |
-if osp.isfile(osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), ".portage_not_installed")): |
8303 |
- sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "lib")) |
8304 |
+ |
8305 |
+if osp.isfile( |
8306 |
+ osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), ".portage_not_installed") |
8307 |
+): |
8308 |
+ sys.path.insert( |
8309 |
+ 0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "lib") |
8310 |
+ ) |
8311 |
import portage |
8312 |
+ |
8313 |
portage._internal_caller = True |
8314 |
from portage import os |
8315 |
from portage import xpak, gpkg |
8316 |
from portage.const import SUPPORTED_GENTOO_BINPKG_FORMATS |
8317 |
from portage.dbapi.dep_expand import dep_expand |
8318 |
from portage.dep import Atom, use_reduce |
8319 |
-from portage.exception import (AmbiguousPackageName, InvalidAtom, InvalidData, |
8320 |
- InvalidBinaryPackageFormat, InvalidDependString, PackageSetNotFound, |
8321 |
- PermissionDenied) |
8322 |
+from portage.exception import ( |
8323 |
+ AmbiguousPackageName, |
8324 |
+ InvalidAtom, |
8325 |
+ InvalidData, |
8326 |
+ InvalidBinaryPackageFormat, |
8327 |
+ InvalidDependString, |
8328 |
+ PackageSetNotFound, |
8329 |
+ PermissionDenied, |
8330 |
+) |
8331 |
from portage.util import ensure_dirs, shlex_split, varexpand, _xattr |
8332 |
+ |
8333 |
xattr = _xattr.xattr |
8334 |
from portage._sets import load_default_config, SETPREFIX |
8335 |
from portage.process import find_binary |
8336 |
@@ -32,358 +45,391 @@ from portage.gpg import GPG |
8337 |
|
8338 |
|
8339 |
def quickpkg_atom(options, infos, arg, eout): |
8340 |
- settings = portage.settings |
8341 |
- eroot = portage.settings['EROOT'] |
8342 |
- trees = portage.db[eroot] |
8343 |
- vartree = trees["vartree"] |
8344 |
- vardb = vartree.dbapi |
8345 |
- bintree = trees["bintree"] |
8346 |
- |
8347 |
- include_config = options.include_config == "y" |
8348 |
- include_unmodified_config = options.include_unmodified_config == "y" |
8349 |
- fix_metadata_keys = ["PF", "CATEGORY"] |
8350 |
- |
8351 |
- try: |
8352 |
- atom = dep_expand(arg, mydb=vardb, settings=vartree.settings) |
8353 |
- except AmbiguousPackageName as e: |
8354 |
- # Multiple matches thrown from cpv_expand |
8355 |
- eout.eerror("Please use a more specific atom: %s" % \ |
8356 |
- " ".join(e.args[0])) |
8357 |
- del e |
8358 |
- infos["missing"].append(arg) |
8359 |
- return 1 |
8360 |
- except (InvalidAtom, InvalidData): |
8361 |
- eout.eerror("Invalid atom: %s" % (arg,)) |
8362 |
- infos["missing"].append(arg) |
8363 |
- return 1 |
8364 |
- if atom[:1] == '=' and arg[:1] != '=': |
8365 |
- # dep_expand() allows missing '=' but it's really invalid |
8366 |
- eout.eerror("Invalid atom: %s" % (arg,)) |
8367 |
- infos["missing"].append(arg) |
8368 |
- return 1 |
8369 |
- |
8370 |
- matches = vardb.match(atom) |
8371 |
- pkgs_for_arg = 0 |
8372 |
- retval = 0 |
8373 |
- for cpv in matches: |
8374 |
- excluded_config_files = [] |
8375 |
- dblnk = vardb._dblink(cpv) |
8376 |
- have_lock = False |
8377 |
- |
8378 |
- if "__PORTAGE_INHERIT_VARDB_LOCK" not in settings: |
8379 |
- try: |
8380 |
- dblnk.lockdb() |
8381 |
- have_lock = True |
8382 |
- except PermissionDenied: |
8383 |
- pass |
8384 |
- |
8385 |
- try: |
8386 |
- if not dblnk.exists(): |
8387 |
- # unmerged by a concurrent process |
8388 |
- continue |
8389 |
- iuse, use, restrict = vardb.aux_get(cpv, |
8390 |
- ["IUSE","USE","RESTRICT"]) |
8391 |
- iuse = [ x.lstrip("+-") for x in iuse.split() ] |
8392 |
- use = use.split() |
8393 |
- try: |
8394 |
- restrict = use_reduce(restrict, uselist=use, flat=True) |
8395 |
- except InvalidDependString as e: |
8396 |
- eout.eerror("Invalid RESTRICT metadata " + \ |
8397 |
- "for '%s': %s; skipping" % (cpv, str(e))) |
8398 |
- del e |
8399 |
- continue |
8400 |
- if "bindist" in iuse and "bindist" not in use: |
8401 |
- eout.ewarn("%s: package was emerged with USE=-bindist!" % cpv) |
8402 |
- eout.ewarn("%s: it might not be legal to redistribute this." % cpv) |
8403 |
- elif "bindist" in restrict: |
8404 |
- eout.ewarn("%s: package has RESTRICT=bindist!" % cpv) |
8405 |
- eout.ewarn("%s: it might not be legal to redistribute this." % cpv) |
8406 |
- eout.ebegin("Building package for %s" % cpv) |
8407 |
- pkgs_for_arg += 1 |
8408 |
- existing_metadata = dict(zip(fix_metadata_keys, |
8409 |
- vardb.aux_get(cpv, fix_metadata_keys))) |
8410 |
- category, pf = portage.catsplit(cpv) |
8411 |
- required_metadata = {} |
8412 |
- required_metadata["CATEGORY"] = category |
8413 |
- required_metadata["PF"] = pf |
8414 |
- update_metadata = {} |
8415 |
- for k, v in required_metadata.items(): |
8416 |
- if v != existing_metadata[k]: |
8417 |
- update_metadata[k] = v |
8418 |
- if update_metadata: |
8419 |
- vardb.aux_update(cpv, update_metadata) |
8420 |
- |
8421 |
- binpkg_format = settings.get("BINPKG_FORMAT", SUPPORTED_GENTOO_BINPKG_FORMATS[0]) |
8422 |
- if binpkg_format == "xpak": |
8423 |
- xpdata = xpak.xpak(dblnk.dbdir) |
8424 |
- binpkg_tmpfile = os.path.join(bintree.pkgdir, |
8425 |
- cpv + ".tbz2." + str(portage.getpid())) |
8426 |
- ensure_dirs(os.path.dirname(binpkg_tmpfile)) |
8427 |
- binpkg_compression = settings.get("BINPKG_COMPRESS", "bzip2") |
8428 |
- try: |
8429 |
- compression = _compressors[binpkg_compression] |
8430 |
- except KeyError as e: |
8431 |
- if binpkg_compression: |
8432 |
- eout.eerror("Invalid or unsupported compression method: %s" % e.args[0]) |
8433 |
- return 1 |
8434 |
- # Empty BINPKG_COMPRESS disables compression. |
8435 |
- binpkg_compression = 'none' |
8436 |
- compression = { |
8437 |
- 'compress': 'cat', |
8438 |
- 'package': 'sys-apps/coreutils', |
8439 |
- } |
8440 |
- try: |
8441 |
- compression_binary = shlex_split(varexpand(compression["compress"], mydict=settings))[0] |
8442 |
- except IndexError as e: |
8443 |
- eout.eerror("Invalid or unsupported compression method: %s" % e.args[0]) |
8444 |
- return 1 |
8445 |
- if find_binary(compression_binary) is None: |
8446 |
- missing_package = compression["package"] |
8447 |
- eout.eerror("File compression unsupported %s. Missing package: %s" % (binpkg_compression, missing_package)) |
8448 |
- return 1 |
8449 |
- cmd = [varexpand(x, mydict=settings) for x in shlex_split(compression["compress"])] |
8450 |
- # Filter empty elements that make Popen fail |
8451 |
- cmd = [x for x in cmd if x != ""] |
8452 |
- with open(binpkg_tmpfile, "wb") as fobj: |
8453 |
- proc = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=fobj) |
8454 |
- excluded_config_files = dblnk.quickpkg(proc.stdin, |
8455 |
- include_config=include_config, |
8456 |
- include_unmodified_config=include_unmodified_config) |
8457 |
- proc.stdin.close() |
8458 |
- if proc.wait() != os.EX_OK: |
8459 |
- eout.eend(1) |
8460 |
- eout.eerror("Compressor failed for package %s" % cpv) |
8461 |
- retval |= 1 |
8462 |
- try: |
8463 |
- os.unlink(binpkg_tmpfile) |
8464 |
- except OSError as e: |
8465 |
- if e.errno not in (errno.ENOENT, errno.ESTALE): |
8466 |
- raise |
8467 |
- continue |
8468 |
- xpak.tbz2(binpkg_tmpfile).recompose_mem(xpdata) |
8469 |
- elif binpkg_format == "gpkg": |
8470 |
- metadata = gpkg.gpkg(settings)._generate_metadata_from_dir(dblnk.dbdir) |
8471 |
- binpkg_tmpfile = os.path.join(bintree.pkgdir, |
8472 |
- cpv + ".gpkg.tar." + str(os.getpid())) |
8473 |
- ensure_dirs(os.path.dirname(binpkg_tmpfile)) |
8474 |
- excluded_config_files = dblnk.quickpkg(binpkg_tmpfile, |
8475 |
- metadata, |
8476 |
- include_config=include_config, |
8477 |
- include_unmodified_config=include_unmodified_config) |
8478 |
- else: |
8479 |
- raise InvalidBinaryPackageFormat(binpkg_format) |
8480 |
- finally: |
8481 |
- if have_lock: |
8482 |
- dblnk.unlockdb() |
8483 |
- pkg_info = bintree.inject(cpv, filename=binpkg_tmpfile) |
8484 |
- # The pkg_info value ensures that the following getname call |
8485 |
- # returns the correct path when FEATURES=binpkg-multi-instance |
8486 |
- # is enabled, but fallback to cpv in case the inject call |
8487 |
- # returned None due to some kind of failure. |
8488 |
- binpkg_path = bintree.getname(pkg_info or cpv) |
8489 |
- try: |
8490 |
- s = os.stat(binpkg_path) |
8491 |
- except OSError: |
8492 |
- s = None |
8493 |
- |
8494 |
- if s is None or pkg_info is None: |
8495 |
- # Sanity check, shouldn't happen normally. |
8496 |
- eout.eend(1) |
8497 |
- eout.eerror("Failed to create package: '%s'" % binpkg_path) |
8498 |
- retval |= 1 |
8499 |
- else: |
8500 |
- eout.eend(0) |
8501 |
- infos["successes"].append((cpv, s.st_size)) |
8502 |
- infos["config_files_excluded"] += len(excluded_config_files) |
8503 |
- for filename in excluded_config_files: |
8504 |
- eout.ewarn("Excluded config: '%s'" % filename) |
8505 |
- if not pkgs_for_arg: |
8506 |
- eout.eerror("Could not find anything " + \ |
8507 |
- "to match '%s'; skipping" % arg) |
8508 |
- infos["missing"].append(arg) |
8509 |
- retval |= 1 |
8510 |
- return retval |
8511 |
+ settings = portage.settings |
8512 |
+ eroot = portage.settings["EROOT"] |
8513 |
+ trees = portage.db[eroot] |
8514 |
+ vartree = trees["vartree"] |
8515 |
+ vardb = vartree.dbapi |
8516 |
+ bintree = trees["bintree"] |
8517 |
+ |
8518 |
+ include_config = options.include_config == "y" |
8519 |
+ include_unmodified_config = options.include_unmodified_config == "y" |
8520 |
+ fix_metadata_keys = ["PF", "CATEGORY"] |
8521 |
+ |
8522 |
+ try: |
8523 |
+ atom = dep_expand(arg, mydb=vardb, settings=vartree.settings) |
8524 |
+ except AmbiguousPackageName as e: |
8525 |
+ # Multiple matches thrown from cpv_expand |
8526 |
+ eout.eerror("Please use a more specific atom: %s" % " ".join(e.args[0])) |
8527 |
+ del e |
8528 |
+ infos["missing"].append(arg) |
8529 |
+ return 1 |
8530 |
+ except (InvalidAtom, InvalidData): |
8531 |
+ eout.eerror("Invalid atom: %s" % (arg,)) |
8532 |
+ infos["missing"].append(arg) |
8533 |
+ return 1 |
8534 |
+ if atom[:1] == "=" and arg[:1] != "=": |
8535 |
+ # dep_expand() allows missing '=' but it's really invalid |
8536 |
+ eout.eerror("Invalid atom: %s" % (arg,)) |
8537 |
+ infos["missing"].append(arg) |
8538 |
+ return 1 |
8539 |
+ |
8540 |
+ matches = vardb.match(atom) |
8541 |
+ pkgs_for_arg = 0 |
8542 |
+ retval = 0 |
8543 |
+ for cpv in matches: |
8544 |
+ excluded_config_files = [] |
8545 |
+ dblnk = vardb._dblink(cpv) |
8546 |
+ have_lock = False |
8547 |
+ |
8548 |
+ if "__PORTAGE_INHERIT_VARDB_LOCK" not in settings: |
8549 |
+ try: |
8550 |
+ dblnk.lockdb() |
8551 |
+ have_lock = True |
8552 |
+ except PermissionDenied: |
8553 |
+ pass |
8554 |
+ |
8555 |
+ try: |
8556 |
+ if not dblnk.exists(): |
8557 |
+ # unmerged by a concurrent process |
8558 |
+ continue |
8559 |
+ iuse, use, restrict = vardb.aux_get(cpv, ["IUSE", "USE", "RESTRICT"]) |
8560 |
+ iuse = [x.lstrip("+-") for x in iuse.split()] |
8561 |
+ use = use.split() |
8562 |
+ try: |
8563 |
+ restrict = use_reduce(restrict, uselist=use, flat=True) |
8564 |
+ except InvalidDependString as e: |
8565 |
+ eout.eerror( |
8566 |
+ "Invalid RESTRICT metadata " |
8567 |
+ + "for '%s': %s; skipping" % (cpv, str(e)) |
8568 |
+ ) |
8569 |
+ del e |
8570 |
+ continue |
8571 |
+ if "bindist" in iuse and "bindist" not in use: |
8572 |
+ eout.ewarn("%s: package was emerged with USE=-bindist!" % cpv) |
8573 |
+ eout.ewarn("%s: it might not be legal to redistribute this." % cpv) |
8574 |
+ elif "bindist" in restrict: |
8575 |
+ eout.ewarn("%s: package has RESTRICT=bindist!" % cpv) |
8576 |
+ eout.ewarn("%s: it might not be legal to redistribute this." % cpv) |
8577 |
+ eout.ebegin("Building package for %s" % cpv) |
8578 |
+ pkgs_for_arg += 1 |
8579 |
+ existing_metadata = dict( |
8580 |
+ zip(fix_metadata_keys, vardb.aux_get(cpv, fix_metadata_keys)) |
8581 |
+ ) |
8582 |
+ category, pf = portage.catsplit(cpv) |
8583 |
+ required_metadata = {} |
8584 |
+ required_metadata["CATEGORY"] = category |
8585 |
+ required_metadata["PF"] = pf |
8586 |
+ update_metadata = {} |
8587 |
+ for k, v in required_metadata.items(): |
8588 |
+ if v != existing_metadata[k]: |
8589 |
+ update_metadata[k] = v |
8590 |
+ if update_metadata: |
8591 |
+ vardb.aux_update(cpv, update_metadata) |
8592 |
+ |
8593 |
+ binpkg_format = settings.get( |
8594 |
+ "BINPKG_FORMAT", SUPPORTED_GENTOO_BINPKG_FORMATS[0] |
8595 |
+ ) |
8596 |
+ if binpkg_format == "xpak": |
8597 |
+ xpdata = xpak.xpak(dblnk.dbdir) |
8598 |
+ binpkg_tmpfile = os.path.join( |
8599 |
+ bintree.pkgdir, cpv + ".tbz2." + str(portage.getpid()) |
8600 |
+ ) |
8601 |
+ ensure_dirs(os.path.dirname(binpkg_tmpfile)) |
8602 |
+ binpkg_compression = settings.get("BINPKG_COMPRESS", "bzip2") |
8603 |
+ try: |
8604 |
+ compression = _compressors[binpkg_compression] |
8605 |
+ except KeyError as e: |
8606 |
+ if binpkg_compression: |
8607 |
+ eout.eerror( |
8608 |
+ "Invalid or unsupported compression method: %s" % e.args[0] |
8609 |
+ ) |
8610 |
+ return 1 |
8611 |
+ # Empty BINPKG_COMPRESS disables compression. |
8612 |
+ binpkg_compression = "none" |
8613 |
+ compression = { |
8614 |
+ "compress": "cat", |
8615 |
+ "package": "sys-apps/coreutils", |
8616 |
+ } |
8617 |
+ try: |
8618 |
+ compression_binary = shlex_split( |
8619 |
+ varexpand(compression["compress"], mydict=settings) |
8620 |
+ )[0] |
8621 |
+ except IndexError as e: |
8622 |
+ eout.eerror( |
8623 |
+ "Invalid or unsupported compression method: %s" % e.args[0] |
8624 |
+ ) |
8625 |
+ return 1 |
8626 |
+ if find_binary(compression_binary) is None: |
8627 |
+ missing_package = compression["package"] |
8628 |
+ eout.eerror( |
8629 |
+ "File compression unsupported %s. Missing package: %s" |
8630 |
+ % (binpkg_compression, missing_package) |
8631 |
+ ) |
8632 |
+ return 1 |
8633 |
+ cmd = [ |
8634 |
+ varexpand(x, mydict=settings) |
8635 |
+ for x in shlex_split(compression["compress"]) |
8636 |
+ ] |
8637 |
+ # Filter empty elements that make Popen fail |
8638 |
+ cmd = [x for x in cmd if x != ""] |
8639 |
+ with open(binpkg_tmpfile, "wb") as fobj: |
8640 |
+ proc = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=fobj) |
8641 |
+ excluded_config_files = dblnk.quickpkg( |
8642 |
+ proc.stdin, |
8643 |
+ include_config=include_config, |
8644 |
+ include_unmodified_config=include_unmodified_config, |
8645 |
+ ) |
8646 |
+ proc.stdin.close() |
8647 |
+ if proc.wait() != os.EX_OK: |
8648 |
+ eout.eend(1) |
8649 |
+ eout.eerror("Compressor failed for package %s" % cpv) |
8650 |
+ retval |= 1 |
8651 |
+ try: |
8652 |
+ os.unlink(binpkg_tmpfile) |
8653 |
+ except OSError as e: |
8654 |
+ if e.errno not in (errno.ENOENT, errno.ESTALE): |
8655 |
+ raise |
8656 |
+ continue |
8657 |
+ xpak.tbz2(binpkg_tmpfile).recompose_mem(xpdata) |
8658 |
+ elif binpkg_format == "gpkg": |
8659 |
+ metadata = gpkg.gpkg(settings)._generate_metadata_from_dir(dblnk.dbdir) |
8660 |
+ binpkg_tmpfile = os.path.join( |
8661 |
+ bintree.pkgdir, cpv + ".gpkg.tar." + str(os.getpid()) |
8662 |
+ ) |
8663 |
+ ensure_dirs(os.path.dirname(binpkg_tmpfile)) |
8664 |
+ excluded_config_files = dblnk.quickpkg( |
8665 |
+ binpkg_tmpfile, |
8666 |
+ metadata, |
8667 |
+ include_config=include_config, |
8668 |
+ include_unmodified_config=include_unmodified_config, |
8669 |
+ ) |
8670 |
+ else: |
8671 |
+ raise InvalidBinaryPackageFormat(binpkg_format) |
8672 |
+ finally: |
8673 |
+ if have_lock: |
8674 |
+ dblnk.unlockdb() |
8675 |
+ pkg_info = bintree.inject(cpv, filename=binpkg_tmpfile) |
8676 |
+ # The pkg_info value ensures that the following getname call |
8677 |
+ # returns the correct path when FEATURES=binpkg-multi-instance |
8678 |
+ # is enabled, but fallback to cpv in case the inject call |
8679 |
+ # returned None due to some kind of failure. |
8680 |
+ binpkg_path = bintree.getname(pkg_info or cpv) |
8681 |
+ try: |
8682 |
+ s = os.stat(binpkg_path) |
8683 |
+ except OSError: |
8684 |
+ s = None |
8685 |
+ |
8686 |
+ if s is None or pkg_info is None: |
8687 |
+ # Sanity check, shouldn't happen normally. |
8688 |
+ eout.eend(1) |
8689 |
+ eout.eerror("Failed to create package: '%s'" % binpkg_path) |
8690 |
+ retval |= 1 |
8691 |
+ else: |
8692 |
+ eout.eend(0) |
8693 |
+ infos["successes"].append((cpv, s.st_size)) |
8694 |
+ infos["config_files_excluded"] += len(excluded_config_files) |
8695 |
+ for filename in excluded_config_files: |
8696 |
+ eout.ewarn("Excluded config: '%s'" % filename) |
8697 |
+ if not pkgs_for_arg: |
8698 |
+ eout.eerror("Could not find anything " + "to match '%s'; skipping" % arg) |
8699 |
+ infos["missing"].append(arg) |
8700 |
+ retval |= 1 |
8701 |
+ return retval |
8702 |
+ |
8703 |
|
8704 |
def quickpkg_set(options, infos, arg, eout): |
8705 |
- eroot = portage.settings['EROOT'] |
8706 |
- trees = portage.db[eroot] |
8707 |
- vartree = trees["vartree"] |
8708 |
- |
8709 |
- settings = vartree.settings |
8710 |
- settings._init_dirs() |
8711 |
- setconfig = load_default_config(settings, trees) |
8712 |
- sets = setconfig.getSets() |
8713 |
- |
8714 |
- set_name = arg[1:] |
8715 |
- if not set_name in sets: |
8716 |
- eout.eerror("Package set not found: '%s'; skipping" % (arg,)) |
8717 |
- infos["missing"].append(arg) |
8718 |
- return 1 |
8719 |
- |
8720 |
- try: |
8721 |
- atoms = setconfig.getSetAtoms(set_name) |
8722 |
- except PackageSetNotFound as e: |
8723 |
- eout.eerror("Failed to process package set '%s' because " % set_name + |
8724 |
- "it contains the non-existent package set '%s'; skipping" % e) |
8725 |
- infos["missing"].append(arg) |
8726 |
- return 1 |
8727 |
- retval = os.EX_OK |
8728 |
- for atom in atoms: |
8729 |
- retval |= quickpkg_atom(options, infos, atom, eout) |
8730 |
- return retval |
8731 |
+ eroot = portage.settings["EROOT"] |
8732 |
+ trees = portage.db[eroot] |
8733 |
+ vartree = trees["vartree"] |
8734 |
+ |
8735 |
+ settings = vartree.settings |
8736 |
+ settings._init_dirs() |
8737 |
+ setconfig = load_default_config(settings, trees) |
8738 |
+ sets = setconfig.getSets() |
8739 |
+ |
8740 |
+ set_name = arg[1:] |
8741 |
+ if not set_name in sets: |
8742 |
+ eout.eerror("Package set not found: '%s'; skipping" % (arg,)) |
8743 |
+ infos["missing"].append(arg) |
8744 |
+ return 1 |
8745 |
+ |
8746 |
+ try: |
8747 |
+ atoms = setconfig.getSetAtoms(set_name) |
8748 |
+ except PackageSetNotFound as e: |
8749 |
+ eout.eerror( |
8750 |
+ "Failed to process package set '%s' because " % set_name |
8751 |
+ + "it contains the non-existent package set '%s'; skipping" % e |
8752 |
+ ) |
8753 |
+ infos["missing"].append(arg) |
8754 |
+ return 1 |
8755 |
+ retval = os.EX_OK |
8756 |
+ for atom in atoms: |
8757 |
+ retval |= quickpkg_atom(options, infos, atom, eout) |
8758 |
+ return retval |
8759 |
|
8760 |
|
8761 |
def quickpkg_extended_atom(options, infos, atom, eout): |
8762 |
- eroot = portage.settings['EROOT'] |
8763 |
- trees = portage.db[eroot] |
8764 |
- vartree = trees["vartree"] |
8765 |
- vardb = vartree.dbapi |
8766 |
+ eroot = portage.settings["EROOT"] |
8767 |
+ trees = portage.db[eroot] |
8768 |
+ vartree = trees["vartree"] |
8769 |
+ vardb = vartree.dbapi |
8770 |
|
8771 |
- require_metadata = atom.slot or atom.repo |
8772 |
- atoms = [] |
8773 |
- for cpv in vardb.cpv_all(): |
8774 |
- cpv_atom = Atom("=%s" % cpv) |
8775 |
+ require_metadata = atom.slot or atom.repo |
8776 |
+ atoms = [] |
8777 |
+ for cpv in vardb.cpv_all(): |
8778 |
+ cpv_atom = Atom("=%s" % cpv) |
8779 |
|
8780 |
- if atom == "*/*": |
8781 |
- atoms.append(cpv_atom) |
8782 |
- continue |
8783 |
+ if atom == "*/*": |
8784 |
+ atoms.append(cpv_atom) |
8785 |
+ continue |
8786 |
|
8787 |
- if not portage.match_from_list(atom, [cpv]): |
8788 |
- continue |
8789 |
+ if not portage.match_from_list(atom, [cpv]): |
8790 |
+ continue |
8791 |
|
8792 |
- if require_metadata: |
8793 |
- try: |
8794 |
- cpv = vardb._pkg_str(cpv, atom.repo) |
8795 |
- except (KeyError, InvalidData): |
8796 |
- continue |
8797 |
- if not portage.match_from_list(atom, [cpv]): |
8798 |
- continue |
8799 |
+ if require_metadata: |
8800 |
+ try: |
8801 |
+ cpv = vardb._pkg_str(cpv, atom.repo) |
8802 |
+ except (KeyError, InvalidData): |
8803 |
+ continue |
8804 |
+ if not portage.match_from_list(atom, [cpv]): |
8805 |
+ continue |
8806 |
|
8807 |
- atoms.append(cpv_atom) |
8808 |
+ atoms.append(cpv_atom) |
8809 |
|
8810 |
- for atom in atoms: |
8811 |
- quickpkg_atom(options, infos, atom, eout) |
8812 |
+ for atom in atoms: |
8813 |
+ quickpkg_atom(options, infos, atom, eout) |
8814 |
|
8815 |
|
8816 |
def quickpkg_main(options, args, eout): |
8817 |
- eroot = portage.settings['EROOT'] |
8818 |
- trees = portage.db[eroot] |
8819 |
- bintree = trees["bintree"] |
8820 |
- |
8821 |
- try: |
8822 |
- ensure_dirs(bintree.pkgdir) |
8823 |
- except portage.exception.PortageException: |
8824 |
- pass |
8825 |
- if not os.access(bintree.pkgdir, os.W_OK): |
8826 |
- eout.eerror("No write access to '%s'" % bintree.pkgdir) |
8827 |
- return errno.EACCES |
8828 |
- |
8829 |
- if 'xattr' in portage.settings.features and not _xattr.XATTRS_WORKS: |
8830 |
- eout.eerror("No xattr support library was found, " |
8831 |
- "so xattrs will not be preserved!") |
8832 |
- portage.settings.unlock() |
8833 |
- portage.settings.features.remove('xattr') |
8834 |
- portage.settings.lock() |
8835 |
- |
8836 |
- if portage.settings.get("BINPKG_GPG_SIGNING_KEY", None): |
8837 |
- gpg = GPG(portage.settings) |
8838 |
- gpg.unlock() |
8839 |
- |
8840 |
- infos = {} |
8841 |
- infos["successes"] = [] |
8842 |
- infos["missing"] = [] |
8843 |
- infos["config_files_excluded"] = 0 |
8844 |
- for arg in args: |
8845 |
- if arg[0] == SETPREFIX: |
8846 |
- quickpkg_set(options, infos, arg, eout) |
8847 |
- continue |
8848 |
- try: |
8849 |
- atom = Atom(arg, allow_wildcard=True, allow_repo=True) |
8850 |
- except (InvalidAtom, InvalidData): |
8851 |
- # maybe it's valid but missing category (requires dep_expand) |
8852 |
- quickpkg_atom(options, infos, arg, eout) |
8853 |
- else: |
8854 |
- if atom.extended_syntax: |
8855 |
- quickpkg_extended_atom(options, infos, atom, eout) |
8856 |
- else: |
8857 |
- quickpkg_atom(options, infos, atom, eout) |
8858 |
- |
8859 |
- if not infos["successes"]: |
8860 |
- eout.eerror("No packages found") |
8861 |
- return 1 |
8862 |
- print() |
8863 |
- eout.einfo("Packages now in '%s':" % bintree.pkgdir) |
8864 |
- units = {10:'K', 20:'M', 30:'G', 40:'T', |
8865 |
- 50:'P', 60:'E', 70:'Z', 80:'Y'} |
8866 |
- for cpv, size in infos["successes"]: |
8867 |
- if not size: |
8868 |
- # avoid OverflowError in math.log() |
8869 |
- size_str = "0" |
8870 |
- else: |
8871 |
- power_of_2 = math.log(size, 2) |
8872 |
- power_of_2 = 10*(power_of_2//10) |
8873 |
- unit = units.get(power_of_2) |
8874 |
- if unit: |
8875 |
- size = float(size)/(2**power_of_2) |
8876 |
- size_str = "%.1f" % size |
8877 |
- if len(size_str) > 4: |
8878 |
- # emulate `du -h`, don't show too many sig figs |
8879 |
- size_str = str(int(size)) |
8880 |
- size_str += unit |
8881 |
- else: |
8882 |
- size_str = str(size) |
8883 |
- eout.einfo("%s: %s" % (cpv, size_str)) |
8884 |
- if infos["config_files_excluded"]: |
8885 |
- print() |
8886 |
- eout.ewarn("Excluded config files: %d" % infos["config_files_excluded"]) |
8887 |
- eout.ewarn("See --help if you would like to include config files.") |
8888 |
- if infos["missing"]: |
8889 |
- print() |
8890 |
- eout.ewarn("The following packages could not be found:") |
8891 |
- eout.ewarn(" ".join(infos["missing"])) |
8892 |
- return 2 |
8893 |
- return os.EX_OK |
8894 |
+ eroot = portage.settings["EROOT"] |
8895 |
+ trees = portage.db[eroot] |
8896 |
+ bintree = trees["bintree"] |
8897 |
+ |
8898 |
+ try: |
8899 |
+ ensure_dirs(bintree.pkgdir) |
8900 |
+ except portage.exception.PortageException: |
8901 |
+ pass |
8902 |
+ if not os.access(bintree.pkgdir, os.W_OK): |
8903 |
+ eout.eerror("No write access to '%s'" % bintree.pkgdir) |
8904 |
+ return errno.EACCES |
8905 |
+ |
8906 |
+ if "xattr" in portage.settings.features and not _xattr.XATTRS_WORKS: |
8907 |
+ eout.eerror( |
8908 |
+ "No xattr support library was found, " "so xattrs will not be preserved!" |
8909 |
+ ) |
8910 |
+ portage.settings.unlock() |
8911 |
+ portage.settings.features.remove("xattr") |
8912 |
+ portage.settings.lock() |
8913 |
+ |
8914 |
+ if portage.settings.get("BINPKG_GPG_SIGNING_KEY", None): |
8915 |
+ gpg = GPG(portage.settings) |
8916 |
+ gpg.unlock() |
8917 |
+ |
8918 |
+ infos = {} |
8919 |
+ infos["successes"] = [] |
8920 |
+ infos["missing"] = [] |
8921 |
+ infos["config_files_excluded"] = 0 |
8922 |
+ for arg in args: |
8923 |
+ if arg[0] == SETPREFIX: |
8924 |
+ quickpkg_set(options, infos, arg, eout) |
8925 |
+ continue |
8926 |
+ try: |
8927 |
+ atom = Atom(arg, allow_wildcard=True, allow_repo=True) |
8928 |
+ except (InvalidAtom, InvalidData): |
8929 |
+ # maybe it's valid but missing category (requires dep_expand) |
8930 |
+ quickpkg_atom(options, infos, arg, eout) |
8931 |
+ else: |
8932 |
+ if atom.extended_syntax: |
8933 |
+ quickpkg_extended_atom(options, infos, atom, eout) |
8934 |
+ else: |
8935 |
+ quickpkg_atom(options, infos, atom, eout) |
8936 |
+ |
8937 |
+ if not infos["successes"]: |
8938 |
+ eout.eerror("No packages found") |
8939 |
+ return 1 |
8940 |
+ print() |
8941 |
+ eout.einfo("Packages now in '%s':" % bintree.pkgdir) |
8942 |
+ units = {10: "K", 20: "M", 30: "G", 40: "T", 50: "P", 60: "E", 70: "Z", 80: "Y"} |
8943 |
+ for cpv, size in infos["successes"]: |
8944 |
+ if not size: |
8945 |
+ # avoid OverflowError in math.log() |
8946 |
+ size_str = "0" |
8947 |
+ else: |
8948 |
+ power_of_2 = math.log(size, 2) |
8949 |
+ power_of_2 = 10 * (power_of_2 // 10) |
8950 |
+ unit = units.get(power_of_2) |
8951 |
+ if unit: |
8952 |
+ size = float(size) / (2**power_of_2) |
8953 |
+ size_str = "%.1f" % size |
8954 |
+ if len(size_str) > 4: |
8955 |
+ # emulate `du -h`, don't show too many sig figs |
8956 |
+ size_str = str(int(size)) |
8957 |
+ size_str += unit |
8958 |
+ else: |
8959 |
+ size_str = str(size) |
8960 |
+ eout.einfo("%s: %s" % (cpv, size_str)) |
8961 |
+ if infos["config_files_excluded"]: |
8962 |
+ print() |
8963 |
+ eout.ewarn("Excluded config files: %d" % infos["config_files_excluded"]) |
8964 |
+ eout.ewarn("See --help if you would like to include config files.") |
8965 |
+ if infos["missing"]: |
8966 |
+ print() |
8967 |
+ eout.ewarn("The following packages could not be found:") |
8968 |
+ eout.ewarn(" ".join(infos["missing"])) |
8969 |
+ return 2 |
8970 |
+ return os.EX_OK |
8971 |
+ |
8972 |
|
8973 |
if __name__ == "__main__": |
8974 |
- usage = "quickpkg [options] <list of package atoms or package sets>" |
8975 |
- parser = argparse.ArgumentParser(usage=usage) |
8976 |
- parser.add_argument("--umask", |
8977 |
- default="0077", |
8978 |
- help="umask used during package creation (default is 0077)") |
8979 |
- parser.add_argument("--ignore-default-opts", |
8980 |
- action="store_true", |
8981 |
- help="do not use the QUICKPKG_DEFAULT_OPTS environment variable") |
8982 |
- parser.add_argument("--include-config", |
8983 |
- choices=["y","n"], |
8984 |
- default="n", |
8985 |
- metavar="<y|n>", |
8986 |
- help="include all files protected by CONFIG_PROTECT (as a security precaution, default is 'n')") |
8987 |
- parser.add_argument("--include-unmodified-config", |
8988 |
- choices=["y","n"], |
8989 |
- default="n", |
8990 |
- metavar="<y|n>", |
8991 |
- help="include files protected by CONFIG_PROTECT that have not been modified since installation (as a security precaution, default is 'n')") |
8992 |
- options, args = parser.parse_known_args(sys.argv[1:]) |
8993 |
- if not options.ignore_default_opts: |
8994 |
- default_opts = shlex_split( |
8995 |
- portage.settings.get("QUICKPKG_DEFAULT_OPTS", "")) |
8996 |
- options, args = parser.parse_known_args(default_opts + sys.argv[1:]) |
8997 |
- if not args: |
8998 |
- parser.error("no packages atoms given") |
8999 |
- try: |
9000 |
- umask = int(options.umask, 8) |
9001 |
- except ValueError: |
9002 |
- parser.error("invalid umask: %s" % options.umask) |
9003 |
- # We need to ensure a sane umask for the packages that will be created. |
9004 |
- old_umask = os.umask(umask) |
9005 |
- eout = portage.output.EOutput() |
9006 |
- def sigwinch_handler(signum, frame): |
9007 |
- lines, eout.term_columns = portage.output.get_term_size() |
9008 |
- signal.signal(signal.SIGWINCH, sigwinch_handler) |
9009 |
- try: |
9010 |
- retval = quickpkg_main(options, args, eout) |
9011 |
- finally: |
9012 |
- os.umask(old_umask) |
9013 |
- signal.signal(signal.SIGWINCH, signal.SIG_DFL) |
9014 |
- global_event_loop().close() |
9015 |
- sys.exit(retval) |
9016 |
+ usage = "quickpkg [options] <list of package atoms or package sets>" |
9017 |
+ parser = argparse.ArgumentParser(usage=usage) |
9018 |
+ parser.add_argument( |
9019 |
+ "--umask", |
9020 |
+ default="0077", |
9021 |
+ help="umask used during package creation (default is 0077)", |
9022 |
+ ) |
9023 |
+ parser.add_argument( |
9024 |
+ "--ignore-default-opts", |
9025 |
+ action="store_true", |
9026 |
+ help="do not use the QUICKPKG_DEFAULT_OPTS environment variable", |
9027 |
+ ) |
9028 |
+ parser.add_argument( |
9029 |
+ "--include-config", |
9030 |
+ choices=["y", "n"], |
9031 |
+ default="n", |
9032 |
+ metavar="<y|n>", |
9033 |
+ help="include all files protected by CONFIG_PROTECT (as a security precaution, default is 'n')", |
9034 |
+ ) |
9035 |
+ parser.add_argument( |
9036 |
+ "--include-unmodified-config", |
9037 |
+ choices=["y", "n"], |
9038 |
+ default="n", |
9039 |
+ metavar="<y|n>", |
9040 |
+ help="include files protected by CONFIG_PROTECT that have not been modified since installation (as a security precaution, default is 'n')", |
9041 |
+ ) |
9042 |
+ options, args = parser.parse_known_args(sys.argv[1:]) |
9043 |
+ if not options.ignore_default_opts: |
9044 |
+ default_opts = shlex_split(portage.settings.get("QUICKPKG_DEFAULT_OPTS", "")) |
9045 |
+ options, args = parser.parse_known_args(default_opts + sys.argv[1:]) |
9046 |
+ if not args: |
9047 |
+ parser.error("no packages atoms given") |
9048 |
+ try: |
9049 |
+ umask = int(options.umask, 8) |
9050 |
+ except ValueError: |
9051 |
+ parser.error("invalid umask: %s" % options.umask) |
9052 |
+ # We need to ensure a sane umask for the packages that will be created. |
9053 |
+ old_umask = os.umask(umask) |
9054 |
+ eout = portage.output.EOutput() |
9055 |
+ |
9056 |
+ def sigwinch_handler(signum, frame): |
9057 |
+ lines, eout.term_columns = portage.output.get_term_size() |
9058 |
+ |
9059 |
+ signal.signal(signal.SIGWINCH, sigwinch_handler) |
9060 |
+ try: |
9061 |
+ retval = quickpkg_main(options, args, eout) |
9062 |
+ finally: |
9063 |
+ os.umask(old_umask) |
9064 |
+ signal.signal(signal.SIGWINCH, signal.SIG_DFL) |
9065 |
+ global_event_loop().close() |
9066 |
+ sys.exit(retval) |
9067 |
|
9068 |
diff --git a/bin/regenworld b/bin/regenworld |
9069 |
index e3577a103..fd11ed14a 100755 |
9070 |
--- a/bin/regenworld |
9071 |
+++ b/bin/regenworld |
9072 |
@@ -4,9 +4,15 @@ |
9073 |
|
9074 |
import sys |
9075 |
from os import path as osp |
9076 |
-if osp.isfile(osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), ".portage_not_installed")): |
9077 |
- sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "lib")) |
9078 |
+ |
9079 |
+if osp.isfile( |
9080 |
+ osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), ".portage_not_installed") |
9081 |
+): |
9082 |
+ sys.path.insert( |
9083 |
+ 0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "lib") |
9084 |
+ ) |
9085 |
import portage |
9086 |
+ |
9087 |
portage._internal_caller = True |
9088 |
from portage import os |
9089 |
from portage._sets.files import StaticFileSet, WorldSelectedPackagesSet |
9090 |
@@ -16,129 +22,138 @@ import tempfile |
9091 |
import textwrap |
9092 |
|
9093 |
__candidatematcher__ = re.compile("^[0-9]+: \\*\\*\\* emerge ") |
9094 |
-__noncandidatematcher__ = re.compile(" sync( |$)| clean( |$)| search( |$)|--oneshot|--fetchonly| unmerge( |$)") |
9095 |
+__noncandidatematcher__ = re.compile( |
9096 |
+ " sync( |$)| clean( |$)| search( |$)|--oneshot|--fetchonly| unmerge( |$)" |
9097 |
+) |
9098 |
+ |
9099 |
|
9100 |
def issyspkg(pkgline): |
9101 |
- return pkgline[0] == "*" |
9102 |
+ return pkgline[0] == "*" |
9103 |
+ |
9104 |
|
9105 |
def iscandidate(logline): |
9106 |
- return (__candidatematcher__.match(logline) |
9107 |
- and not __noncandidatematcher__.search(logline)) |
9108 |
+ return __candidatematcher__.match(logline) and not __noncandidatematcher__.search( |
9109 |
+ logline |
9110 |
+ ) |
9111 |
+ |
9112 |
|
9113 |
def getpkginfo(logline): |
9114 |
- logline = re.sub("^[0-9]+: \\*\\*\\* emerge ", "", logline) |
9115 |
- logline = logline.strip() |
9116 |
- logline = re.sub("(\\S+\\.(ebuild|tbz2))|(--\\S+)|inject ", "", logline) |
9117 |
- return logline.strip() |
9118 |
+ logline = re.sub("^[0-9]+: \\*\\*\\* emerge ", "", logline) |
9119 |
+ logline = logline.strip() |
9120 |
+ logline = re.sub("(\\S+\\.(ebuild|tbz2))|(--\\S+)|inject ", "", logline) |
9121 |
+ return logline.strip() |
9122 |
+ |
9123 |
|
9124 |
__uniqlist__ = [] |
9125 |
+ |
9126 |
+ |
9127 |
def isunwanted(pkgline): |
9128 |
- if pkgline in ["world", "system", "depclean", "info", "regen", ""]: |
9129 |
- return False |
9130 |
- elif pkgline in __uniqlist__: |
9131 |
- return False |
9132 |
- elif not re.search("^[a-zA-Z<>=~]", pkgline): |
9133 |
- return False |
9134 |
- else: |
9135 |
- __uniqlist__.append(pkgline) |
9136 |
- return True |
9137 |
- |
9138 |
-eroot = portage.settings['EROOT'] |
9139 |
+ if pkgline in ["world", "system", "depclean", "info", "regen", ""]: |
9140 |
+ return False |
9141 |
+ elif pkgline in __uniqlist__: |
9142 |
+ return False |
9143 |
+ elif not re.search("^[a-zA-Z<>=~]", pkgline): |
9144 |
+ return False |
9145 |
+ else: |
9146 |
+ __uniqlist__.append(pkgline) |
9147 |
+ return True |
9148 |
+ |
9149 |
+ |
9150 |
+eroot = portage.settings["EROOT"] |
9151 |
world_file = os.path.join(eroot, portage.WORLD_FILE) |
9152 |
|
9153 |
# show a little description if we have arguments |
9154 |
if len(sys.argv) >= 2 and sys.argv[1] in ["-h", "--help"]: |
9155 |
- print("This script regenerates the portage world file by checking the portage") |
9156 |
- print("logfile for all actions that you've done in the past. It ignores any") |
9157 |
- print("arguments except --help. It is recommended that you make a backup of") |
9158 |
- print("your existing world file (%s) before using this tool." % world_file) |
9159 |
- sys.exit(0) |
9160 |
+ print("This script regenerates the portage world file by checking the portage") |
9161 |
+ print("logfile for all actions that you've done in the past. It ignores any") |
9162 |
+ print("arguments except --help. It is recommended that you make a backup of") |
9163 |
+ print("your existing world file (%s) before using this tool." % world_file) |
9164 |
+ sys.exit(0) |
9165 |
|
9166 |
worldlist = portage.grabfile(world_file) |
9167 |
syslist = [x for x in portage.settings.packages if issyspkg(x)] |
9168 |
|
9169 |
if portage.settings.get("EMERGE_LOG_DIR"): |
9170 |
- logfile = portage.grabfile( |
9171 |
- os.path.join(portage.settings["EMERGE_LOG_DIR"], "emerge.log") |
9172 |
- ) |
9173 |
+ logfile = portage.grabfile( |
9174 |
+ os.path.join(portage.settings["EMERGE_LOG_DIR"], "emerge.log") |
9175 |
+ ) |
9176 |
else: |
9177 |
- logfile = portage.grabfile(os.path.join(eroot, "var/log/emerge.log")) |
9178 |
+ logfile = portage.grabfile(os.path.join(eroot, "var/log/emerge.log")) |
9179 |
biglist = [getpkginfo(x) for x in logfile if iscandidate(x)] |
9180 |
tmplist = [] |
9181 |
for l in biglist: |
9182 |
- tmplist += l.split() |
9183 |
+ tmplist += l.split() |
9184 |
biglist = [x for x in tmplist if isunwanted(x)] |
9185 |
-#for p in biglist: |
9186 |
-# print(p) |
9187 |
-#sys.exit(0) |
9188 |
+# for p in biglist: |
9189 |
+# print(p) |
9190 |
+# sys.exit(0) |
9191 |
|
9192 |
# resolving virtuals |
9193 |
realsyslist = [] |
9194 |
for mykey in syslist: |
9195 |
- # drop the asterix |
9196 |
- mykey = mykey[1:] |
9197 |
- #print("candidate:",mykey) |
9198 |
- mylist = portage.db[eroot]["vartree"].dbapi.match(mykey) |
9199 |
- if mylist: |
9200 |
- mykey=portage.cpv_getkey(mylist[0]) |
9201 |
- if mykey not in realsyslist: |
9202 |
- realsyslist.append(mykey) |
9203 |
+ # drop the asterix |
9204 |
+ mykey = mykey[1:] |
9205 |
+ # print("candidate:",mykey) |
9206 |
+ mylist = portage.db[eroot]["vartree"].dbapi.match(mykey) |
9207 |
+ if mylist: |
9208 |
+ mykey = portage.cpv_getkey(mylist[0]) |
9209 |
+ if mykey not in realsyslist: |
9210 |
+ realsyslist.append(mykey) |
9211 |
|
9212 |
for mykey in biglist: |
9213 |
- #print("checking:",mykey) |
9214 |
- try: |
9215 |
- mylist = portage.db[eroot]["vartree"].dbapi.match(mykey) |
9216 |
- except (portage.exception.InvalidAtom, KeyError): |
9217 |
- if "--debug" in sys.argv: |
9218 |
- print("* ignoring broken log entry for %s (likely injected)" % mykey) |
9219 |
- except ValueError as e: |
9220 |
- try: |
9221 |
- print("* %s is an ambiguous package name, candidates are:\n%s" % (mykey, e)) |
9222 |
- except AttributeError: |
9223 |
- # FIXME: Find out what causes this (bug #344845). |
9224 |
- print("* %s is an ambiguous package name" % (mykey,)) |
9225 |
- continue |
9226 |
- if mylist: |
9227 |
- #print "mylist:",mylist |
9228 |
- myfavkey=portage.cpv_getkey(mylist[0]) |
9229 |
- if (myfavkey not in realsyslist) and (myfavkey not in worldlist): |
9230 |
- print("add to world:",myfavkey) |
9231 |
- worldlist.append(myfavkey) |
9232 |
+ # print("checking:",mykey) |
9233 |
+ try: |
9234 |
+ mylist = portage.db[eroot]["vartree"].dbapi.match(mykey) |
9235 |
+ except (portage.exception.InvalidAtom, KeyError): |
9236 |
+ if "--debug" in sys.argv: |
9237 |
+ print("* ignoring broken log entry for %s (likely injected)" % mykey) |
9238 |
+ except ValueError as e: |
9239 |
+ try: |
9240 |
+ print("* %s is an ambiguous package name, candidates are:\n%s" % (mykey, e)) |
9241 |
+ except AttributeError: |
9242 |
+ # FIXME: Find out what causes this (bug #344845). |
9243 |
+ print("* %s is an ambiguous package name" % (mykey,)) |
9244 |
+ continue |
9245 |
+ if mylist: |
9246 |
+ # print "mylist:",mylist |
9247 |
+ myfavkey = portage.cpv_getkey(mylist[0]) |
9248 |
+ if (myfavkey not in realsyslist) and (myfavkey not in worldlist): |
9249 |
+ print("add to world:", myfavkey) |
9250 |
+ worldlist.append(myfavkey) |
9251 |
|
9252 |
if not worldlist: |
9253 |
- pass |
9254 |
+ pass |
9255 |
else: |
9256 |
- existing_set = WorldSelectedPackagesSet(eroot) |
9257 |
- existing_set.load() |
9258 |
- |
9259 |
- if not existing_set: |
9260 |
- existing_set.replace(worldlist) |
9261 |
- else: |
9262 |
- old_world = existing_set._filename |
9263 |
- fd, tmp_filename = tempfile.mkstemp(suffix=".tmp", |
9264 |
- prefix=os.path.basename(old_world) + ".", |
9265 |
- dir=os.path.dirname(old_world)) |
9266 |
- os.close(fd) |
9267 |
- |
9268 |
- new_set = StaticFileSet(tmp_filename) |
9269 |
- new_set.update(worldlist) |
9270 |
- |
9271 |
- if existing_set.getAtoms() == new_set.getAtoms(): |
9272 |
- os.unlink(tmp_filename) |
9273 |
- else: |
9274 |
- new_set.write() |
9275 |
- |
9276 |
- msg = "Please review differences between old and new files, " + \ |
9277 |
- "and replace the old file if desired." |
9278 |
- |
9279 |
- portage.util.writemsg_stdout("\n", |
9280 |
- noiselevel=-1) |
9281 |
- for line in textwrap.wrap(msg, 65): |
9282 |
- portage.util.writemsg_stdout("%s\n" % line, |
9283 |
- noiselevel=-1) |
9284 |
- portage.util.writemsg_stdout("\n", |
9285 |
- noiselevel=-1) |
9286 |
- portage.util.writemsg_stdout(" old: %s\n\n" % old_world, |
9287 |
- noiselevel=-1) |
9288 |
- portage.util.writemsg_stdout(" new: %s\n\n" % tmp_filename, |
9289 |
- noiselevel=-1) |
9290 |
+ existing_set = WorldSelectedPackagesSet(eroot) |
9291 |
+ existing_set.load() |
9292 |
+ |
9293 |
+ if not existing_set: |
9294 |
+ existing_set.replace(worldlist) |
9295 |
+ else: |
9296 |
+ old_world = existing_set._filename |
9297 |
+ fd, tmp_filename = tempfile.mkstemp( |
9298 |
+ suffix=".tmp", |
9299 |
+ prefix=os.path.basename(old_world) + ".", |
9300 |
+ dir=os.path.dirname(old_world), |
9301 |
+ ) |
9302 |
+ os.close(fd) |
9303 |
+ |
9304 |
+ new_set = StaticFileSet(tmp_filename) |
9305 |
+ new_set.update(worldlist) |
9306 |
+ |
9307 |
+ if existing_set.getAtoms() == new_set.getAtoms(): |
9308 |
+ os.unlink(tmp_filename) |
9309 |
+ else: |
9310 |
+ new_set.write() |
9311 |
+ |
9312 |
+ msg = ( |
9313 |
+ "Please review differences between old and new files, " |
9314 |
+ + "and replace the old file if desired." |
9315 |
+ ) |
9316 |
+ |
9317 |
+ portage.util.writemsg_stdout("\n", noiselevel=-1) |
9318 |
+ for line in textwrap.wrap(msg, 65): |
9319 |
+ portage.util.writemsg_stdout("%s\n" % line, noiselevel=-1) |
9320 |
+ portage.util.writemsg_stdout("\n", noiselevel=-1) |
9321 |
+ portage.util.writemsg_stdout(" old: %s\n\n" % old_world, noiselevel=-1) |
9322 |
+ portage.util.writemsg_stdout(" new: %s\n\n" % tmp_filename, noiselevel=-1) |
9323 |
|
9324 |
diff --git a/bin/shelve-utils b/bin/shelve-utils |
9325 |
index 6cfa36a81..3c513bd17 100755 |
9326 |
--- a/bin/shelve-utils |
9327 |
+++ b/bin/shelve-utils |
9328 |
@@ -6,31 +6,37 @@ import argparse |
9329 |
import sys |
9330 |
|
9331 |
from os import path as osp |
9332 |
-if osp.isfile(osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), ".portage_not_installed")): |
9333 |
- sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "lib")) |
9334 |
+ |
9335 |
+if osp.isfile( |
9336 |
+ osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), ".portage_not_installed") |
9337 |
+): |
9338 |
+ sys.path.insert( |
9339 |
+ 0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "lib") |
9340 |
+ ) |
9341 |
import portage |
9342 |
+ |
9343 |
portage._internal_caller = True |
9344 |
from portage.util.shelve import dump, restore |
9345 |
|
9346 |
|
9347 |
def main(argv=None): |
9348 |
- parser = argparse.ArgumentParser(prog="shelve-utils") |
9349 |
- subparsers = parser.add_subparsers(help="sub-command help") |
9350 |
+ parser = argparse.ArgumentParser(prog="shelve-utils") |
9351 |
+ subparsers = parser.add_subparsers(help="sub-command help") |
9352 |
|
9353 |
- dump_command = subparsers.add_parser("dump", help="dump shelve database") |
9354 |
- dump_command.add_argument("src", help="input shelve file") |
9355 |
- dump_command.add_argument("dest", help="output pickle file") |
9356 |
- dump_command.set_defaults(func=dump) |
9357 |
+ dump_command = subparsers.add_parser("dump", help="dump shelve database") |
9358 |
+ dump_command.add_argument("src", help="input shelve file") |
9359 |
+ dump_command.add_argument("dest", help="output pickle file") |
9360 |
+ dump_command.set_defaults(func=dump) |
9361 |
|
9362 |
- restore_command = subparsers.add_parser("restore", help="restore shelve database") |
9363 |
- restore_command.add_argument("src", help="input pickle file") |
9364 |
- restore_command.add_argument("dest", help="output shelve file") |
9365 |
- restore_command.set_defaults(func=restore) |
9366 |
+ restore_command = subparsers.add_parser("restore", help="restore shelve database") |
9367 |
+ restore_command.add_argument("src", help="input pickle file") |
9368 |
+ restore_command.add_argument("dest", help="output shelve file") |
9369 |
+ restore_command.set_defaults(func=restore) |
9370 |
|
9371 |
- args = parser.parse_args(args=portage._decode_argv(argv or sys.argv)[1:]) |
9372 |
- args.func(args) |
9373 |
+ args = parser.parse_args(args=portage._decode_argv(argv or sys.argv)[1:]) |
9374 |
+ args.func(args) |
9375 |
|
9376 |
|
9377 |
if __name__ == "__main__": |
9378 |
- portage.util.initialize_logger() |
9379 |
- main(argv=sys.argv) |
9380 |
+ portage.util.initialize_logger() |
9381 |
+ main(argv=sys.argv) |
9382 |
|
9383 |
diff --git a/repoman/bin/repoman b/repoman/bin/repoman |
9384 |
index 427cb3162..beaf8147a 100755 |
9385 |
--- a/repoman/bin/repoman |
9386 |
+++ b/repoman/bin/repoman |
9387 |
@@ -25,17 +25,21 @@ except KeyboardInterrupt: |
9388 |
sys.exit(1) |
9389 |
|
9390 |
from os import path as osp |
9391 |
+ |
9392 |
here = osp.realpath(__file__) |
9393 |
if osp.isfile(osp.join(osp.dirname(osp.dirname(here)), ".repoman_not_installed")): |
9394 |
# Add the repoman subpkg |
9395 |
pym_path = osp.join(osp.dirname(osp.dirname(here)), "lib") |
9396 |
sys.path.insert(0, pym_path) |
9397 |
- if osp.isfile(osp.join(osp.dirname(osp.dirname(osp.dirname(here))), ".portage_not_installed")): |
9398 |
+ if osp.isfile( |
9399 |
+ osp.join(osp.dirname(osp.dirname(osp.dirname(here))), ".portage_not_installed") |
9400 |
+ ): |
9401 |
# Add the base portage pkg |
9402 |
pym_path = osp.join(osp.dirname(osp.dirname(osp.dirname(here))), "lib") |
9403 |
sys.path.insert(0, pym_path) |
9404 |
|
9405 |
import portage |
9406 |
+ |
9407 |
portage._internal_caller = True |
9408 |
from portage.util._eventloop.global_event_loop import global_event_loop |
9409 |
from repoman.main import repoman_main |
9410 |
|
9411 |
diff --git a/repoman/runtests b/repoman/runtests |
9412 |
index 5b1306e59..f02bfe875 100755 |
9413 |
--- a/repoman/runtests |
9414 |
+++ b/repoman/runtests |
9415 |
@@ -20,62 +20,53 @@ import tempfile |
9416 |
|
9417 |
|
9418 |
# These are the versions we fully support and require to pass tests. |
9419 |
-PYTHON_SUPPORTED_VERSIONS = [ |
9420 |
- '2.7', |
9421 |
- '3.6', |
9422 |
- '3.7', |
9423 |
- '3.8', |
9424 |
- '3.9' |
9425 |
-] |
9426 |
+PYTHON_SUPPORTED_VERSIONS = ["2.7", "3.6", "3.7", "3.8", "3.9"] |
9427 |
# The rest are just "nice to have". |
9428 |
-PYTHON_NICE_VERSIONS = [ |
9429 |
- 'pypy3', |
9430 |
- '3.10' |
9431 |
-] |
9432 |
+PYTHON_NICE_VERSIONS = ["pypy3", "3.10"] |
9433 |
|
9434 |
-EPREFIX = os.environ.get('PORTAGE_OVERRIDE_EPREFIX', '/') |
9435 |
+EPREFIX = os.environ.get("PORTAGE_OVERRIDE_EPREFIX", "/") |
9436 |
|
9437 |
|
9438 |
class Colors(object): |
9439 |
"""Simple object holding color constants.""" |
9440 |
|
9441 |
- _COLORS_YES = ('y', 'yes', 'true') |
9442 |
- _COLORS_NO = ('n', 'no', 'false') |
9443 |
+ _COLORS_YES = ("y", "yes", "true") |
9444 |
+ _COLORS_NO = ("n", "no", "false") |
9445 |
|
9446 |
- WARN = GOOD = BAD = NORMAL = '' |
9447 |
+ WARN = GOOD = BAD = NORMAL = "" |
9448 |
|
9449 |
def __init__(self, colorize=None): |
9450 |
if colorize is None: |
9451 |
- nocolors = os.environ.get('NOCOLOR', 'false') |
9452 |
+ nocolors = os.environ.get("NOCOLOR", "false") |
9453 |
# Ugh, look away, for here we invert the world! |
9454 |
if nocolors in self._COLORS_YES: |
9455 |
colorize = False |
9456 |
elif nocolors in self._COLORS_NO: |
9457 |
colorize = True |
9458 |
else: |
9459 |
- raise ValueError('$NOCOLORS is invalid: %s' % nocolors) |
9460 |
+ raise ValueError("$NOCOLORS is invalid: %s" % nocolors) |
9461 |
else: |
9462 |
if colorize in self._COLORS_YES: |
9463 |
colorize = True |
9464 |
elif colorize in self._COLORS_NO: |
9465 |
colorize = False |
9466 |
else: |
9467 |
- raise ValueError('--colors is invalid: %s' % colorize) |
9468 |
+ raise ValueError("--colors is invalid: %s" % colorize) |
9469 |
|
9470 |
if colorize: |
9471 |
- self.WARN = '\033[1;33m' |
9472 |
- self.GOOD = '\033[1;32m' |
9473 |
- self.BAD = '\033[1;31m' |
9474 |
- self.NORMAL = '\033[0m' |
9475 |
+ self.WARN = "\033[1;33m" |
9476 |
+ self.GOOD = "\033[1;32m" |
9477 |
+ self.BAD = "\033[1;31m" |
9478 |
+ self.NORMAL = "\033[0m" |
9479 |
|
9480 |
|
9481 |
def get_python_executable(ver): |
9482 |
"""Find the right python executable for |ver|""" |
9483 |
- if ver in ('pypy', 'pypy3'): |
9484 |
+ if ver in ("pypy", "pypy3"): |
9485 |
prog = ver |
9486 |
else: |
9487 |
- prog = 'python' + ver |
9488 |
- return os.path.join(EPREFIX, 'usr', 'bin', prog) |
9489 |
+ prog = "python" + ver |
9490 |
+ return os.path.join(EPREFIX, "usr", "bin", prog) |
9491 |
|
9492 |
|
9493 |
def get_parser(): |
9494 |
@@ -93,13 +84,25 @@ $ %(prog)s lib/portage/tests/xpak/test_decodeint.py |
9495 |
parser = argparse.ArgumentParser( |
9496 |
description=__doc__, |
9497 |
formatter_class=argparse.RawDescriptionHelpFormatter, |
9498 |
- epilog=epilog) |
9499 |
- parser.add_argument('--keep-temp', default=False, action='store_true', |
9500 |
- help='Do not delete the temporary directory when exiting') |
9501 |
- parser.add_argument('--color', type=str, default=None, |
9502 |
- help='Whether to use colorized output (default is auto)') |
9503 |
- parser.add_argument('--python-versions', action='append', |
9504 |
- help='Versions of python to test (default is test available)') |
9505 |
+ epilog=epilog, |
9506 |
+ ) |
9507 |
+ parser.add_argument( |
9508 |
+ "--keep-temp", |
9509 |
+ default=False, |
9510 |
+ action="store_true", |
9511 |
+ help="Do not delete the temporary directory when exiting", |
9512 |
+ ) |
9513 |
+ parser.add_argument( |
9514 |
+ "--color", |
9515 |
+ type=str, |
9516 |
+ default=None, |
9517 |
+ help="Whether to use colorized output (default is auto)", |
9518 |
+ ) |
9519 |
+ parser.add_argument( |
9520 |
+ "--python-versions", |
9521 |
+ action="append", |
9522 |
+ help="Versions of python to test (default is test available)", |
9523 |
+ ) |
9524 |
return parser |
9525 |
|
9526 |
|
9527 |
@@ -116,67 +119,71 @@ def main(argv): |
9528 |
ignore_missing = False |
9529 |
pyversions = [] |
9530 |
for ver in opts.python_versions: |
9531 |
- if ver == 'supported': |
9532 |
+ if ver == "supported": |
9533 |
pyversions.extend(PYTHON_SUPPORTED_VERSIONS) |
9534 |
else: |
9535 |
pyversions.extend(ver.split()) |
9536 |
|
9537 |
here = os.path.dirname(__file__) |
9538 |
- run_path = os.path.join(here, 'lib/repoman/tests/runTests.py') |
9539 |
+ run_path = os.path.join(here, "lib/repoman/tests/runTests.py") |
9540 |
tempdir = None |
9541 |
try: |
9542 |
# Set up a single tempdir for all the tests to use. |
9543 |
# This way we know the tests won't leak things on us. |
9544 |
- tempdir = tempfile.mkdtemp(prefix='repoman.runtests.') |
9545 |
- os.environ['TMPDIR'] = tempdir |
9546 |
+ tempdir = tempfile.mkdtemp(prefix="repoman.runtests.") |
9547 |
+ os.environ["TMPDIR"] = tempdir |
9548 |
|
9549 |
# Actually test those versions now. |
9550 |
statuses = [] |
9551 |
for ver in pyversions: |
9552 |
prog = get_python_executable(ver) |
9553 |
- cmd = [prog, '-b', '-Wd', run_path] + args |
9554 |
+ cmd = [prog, "-b", "-Wd", run_path] + args |
9555 |
if os.access(prog, os.X_OK): |
9556 |
- print('%sTesting with Python %s...%s' % |
9557 |
- (colors.GOOD, ver, colors.NORMAL)) |
9558 |
+ print( |
9559 |
+ "%sTesting with Python %s...%s" % (colors.GOOD, ver, colors.NORMAL) |
9560 |
+ ) |
9561 |
statuses.append((ver, subprocess.call(cmd))) |
9562 |
elif not ignore_missing: |
9563 |
- print('%sCould not find requested Python %s%s' % |
9564 |
- (colors.BAD, ver, colors.NORMAL)) |
9565 |
+ print( |
9566 |
+ "%sCould not find requested Python %s%s" |
9567 |
+ % (colors.BAD, ver, colors.NORMAL) |
9568 |
+ ) |
9569 |
statuses.append((ver, 1)) |
9570 |
else: |
9571 |
- print('%sSkip Python %s...%s' % |
9572 |
- (colors.WARN, ver, colors.NORMAL)) |
9573 |
+ print("%sSkip Python %s...%s" % (colors.WARN, ver, colors.NORMAL)) |
9574 |
print() |
9575 |
finally: |
9576 |
if tempdir is not None: |
9577 |
if opts.keep_temp: |
9578 |
- print('Temporary directory left behind:\n%s' % tempdir) |
9579 |
+ print("Temporary directory left behind:\n%s" % tempdir) |
9580 |
else: |
9581 |
# Nuke our tempdir and anything that might be under it. |
9582 |
shutil.rmtree(tempdir, True) |
9583 |
|
9584 |
# Then summarize it all. |
9585 |
- print('\nSummary:\n') |
9586 |
+ print("\nSummary:\n") |
9587 |
width = 10 |
9588 |
- header = '| %-*s | %s' % (width, 'Version', 'Status') |
9589 |
- print('%s\n|%s' % (header, '-' * (len(header) - 1))) |
9590 |
+ header = "| %-*s | %s" % (width, "Version", "Status") |
9591 |
+ print("%s\n|%s" % (header, "-" * (len(header) - 1))) |
9592 |
exit_status = 0 |
9593 |
for ver, status in statuses: |
9594 |
exit_status += status |
9595 |
if status: |
9596 |
color = colors.BAD |
9597 |
- msg = 'FAIL' |
9598 |
+ msg = "FAIL" |
9599 |
else: |
9600 |
color = colors.GOOD |
9601 |
- msg = 'PASS' |
9602 |
- print('| %s%-*s%s | %s%s%s' % |
9603 |
- (color, width, ver, colors.NORMAL, color, msg, colors.NORMAL)) |
9604 |
+ msg = "PASS" |
9605 |
+ print( |
9606 |
+ "| %s%-*s%s | %s%s%s" |
9607 |
+ % (color, width, ver, colors.NORMAL, color, msg, colors.NORMAL) |
9608 |
+ ) |
9609 |
exit(exit_status) |
9610 |
|
9611 |
|
9612 |
-if __name__ == '__main__': |
9613 |
+if __name__ == "__main__": |
9614 |
try: |
9615 |
main(sys.argv[1:]) |
9616 |
except KeyboardInterrupt: |
9617 |
- print('interrupted ...', file=sys.stderr) |
9618 |
+ print("interrupted ...", file=sys.stderr) |
9619 |
exit(1) |
9620 |
|
9621 |
diff --git a/runtests b/runtests |
9622 |
index bc3105026..2a653e3d4 100755 |
9623 |
--- a/runtests |
9624 |
+++ b/runtests |
9625 |
@@ -20,61 +20,53 @@ import tempfile |
9626 |
|
9627 |
|
9628 |
# These are the versions we fully support and require to pass tests. |
9629 |
-PYTHON_SUPPORTED_VERSIONS = [ |
9630 |
- '3.6', |
9631 |
- '3.7', |
9632 |
- '3.8', |
9633 |
- '3.9' |
9634 |
-] |
9635 |
+PYTHON_SUPPORTED_VERSIONS = ["3.6", "3.7", "3.8", "3.9"] |
9636 |
# The rest are just "nice to have". |
9637 |
-PYTHON_NICE_VERSIONS = [ |
9638 |
- 'pypy3', |
9639 |
- '3.10' |
9640 |
-] |
9641 |
+PYTHON_NICE_VERSIONS = ["pypy3", "3.10"] |
9642 |
|
9643 |
-EPREFIX = os.environ.get('PORTAGE_OVERRIDE_EPREFIX', '/') |
9644 |
+EPREFIX = os.environ.get("PORTAGE_OVERRIDE_EPREFIX", "/") |
9645 |
|
9646 |
|
9647 |
class Colors: |
9648 |
"""Simple object holding color constants.""" |
9649 |
|
9650 |
- _COLORS_YES = ('y', 'yes', 'true') |
9651 |
- _COLORS_NO = ('n', 'no', 'false') |
9652 |
+ _COLORS_YES = ("y", "yes", "true") |
9653 |
+ _COLORS_NO = ("n", "no", "false") |
9654 |
|
9655 |
- WARN = GOOD = BAD = NORMAL = '' |
9656 |
+ WARN = GOOD = BAD = NORMAL = "" |
9657 |
|
9658 |
def __init__(self, colorize=None): |
9659 |
if colorize is None: |
9660 |
- nocolors = os.environ.get('NOCOLOR', 'false') |
9661 |
+ nocolors = os.environ.get("NOCOLOR", "false") |
9662 |
# Ugh, look away, for here we invert the world! |
9663 |
if nocolors in self._COLORS_YES: |
9664 |
colorize = False |
9665 |
elif nocolors in self._COLORS_NO: |
9666 |
colorize = True |
9667 |
else: |
9668 |
- raise ValueError('$NOCOLORS is invalid: %s' % nocolors) |
9669 |
+ raise ValueError("$NOCOLORS is invalid: %s" % nocolors) |
9670 |
else: |
9671 |
if colorize in self._COLORS_YES: |
9672 |
colorize = True |
9673 |
elif colorize in self._COLORS_NO: |
9674 |
colorize = False |
9675 |
else: |
9676 |
- raise ValueError('--colors is invalid: %s' % colorize) |
9677 |
+ raise ValueError("--colors is invalid: %s" % colorize) |
9678 |
|
9679 |
if colorize: |
9680 |
- self.WARN = '\033[1;33m' |
9681 |
- self.GOOD = '\033[1;32m' |
9682 |
- self.BAD = '\033[1;31m' |
9683 |
- self.NORMAL = '\033[0m' |
9684 |
+ self.WARN = "\033[1;33m" |
9685 |
+ self.GOOD = "\033[1;32m" |
9686 |
+ self.BAD = "\033[1;31m" |
9687 |
+ self.NORMAL = "\033[0m" |
9688 |
|
9689 |
|
9690 |
def get_python_executable(ver): |
9691 |
"""Find the right python executable for |ver|""" |
9692 |
- if ver in ('pypy', 'pypy3'): |
9693 |
+ if ver in ("pypy", "pypy3"): |
9694 |
prog = ver |
9695 |
else: |
9696 |
- prog = 'python' + ver |
9697 |
- return os.path.join(EPREFIX, 'usr', 'bin', prog) |
9698 |
+ prog = "python" + ver |
9699 |
+ return os.path.join(EPREFIX, "usr", "bin", prog) |
9700 |
|
9701 |
|
9702 |
def get_parser(): |
9703 |
@@ -92,13 +84,25 @@ $ %(prog)s lib/portage/tests/xpak/test_decodeint.py |
9704 |
parser = argparse.ArgumentParser( |
9705 |
description=__doc__, |
9706 |
formatter_class=argparse.RawDescriptionHelpFormatter, |
9707 |
- epilog=epilog) |
9708 |
- parser.add_argument('--keep-temp', default=False, action='store_true', |
9709 |
- help='Do not delete the temporary directory when exiting') |
9710 |
- parser.add_argument('--color', type=str, default=None, |
9711 |
- help='Whether to use colorized output (default is auto)') |
9712 |
- parser.add_argument('--python-versions', action='append', |
9713 |
- help='Versions of python to test (default is test available)') |
9714 |
+ epilog=epilog, |
9715 |
+ ) |
9716 |
+ parser.add_argument( |
9717 |
+ "--keep-temp", |
9718 |
+ default=False, |
9719 |
+ action="store_true", |
9720 |
+ help="Do not delete the temporary directory when exiting", |
9721 |
+ ) |
9722 |
+ parser.add_argument( |
9723 |
+ "--color", |
9724 |
+ type=str, |
9725 |
+ default=None, |
9726 |
+ help="Whether to use colorized output (default is auto)", |
9727 |
+ ) |
9728 |
+ parser.add_argument( |
9729 |
+ "--python-versions", |
9730 |
+ action="append", |
9731 |
+ help="Versions of python to test (default is test available)", |
9732 |
+ ) |
9733 |
return parser |
9734 |
|
9735 |
|
9736 |
@@ -115,7 +119,7 @@ def main(argv): |
9737 |
ignore_missing = False |
9738 |
pyversions = [] |
9739 |
for ver in opts.python_versions: |
9740 |
- if ver == 'supported': |
9741 |
+ if ver == "supported": |
9742 |
pyversions.extend(PYTHON_SUPPORTED_VERSIONS) |
9743 |
else: |
9744 |
pyversions.extend(ver.split()) |
9745 |
@@ -124,56 +128,60 @@ def main(argv): |
9746 |
try: |
9747 |
# Set up a single tempdir for all the tests to use. |
9748 |
# This way we know the tests won't leak things on us. |
9749 |
- tempdir = tempfile.mkdtemp(prefix='portage.runtests.') |
9750 |
- os.environ['TMPDIR'] = tempdir |
9751 |
+ tempdir = tempfile.mkdtemp(prefix="portage.runtests.") |
9752 |
+ os.environ["TMPDIR"] = tempdir |
9753 |
|
9754 |
# Actually test those versions now. |
9755 |
statuses = [] |
9756 |
for ver in pyversions: |
9757 |
prog = get_python_executable(ver) |
9758 |
- cmd = [prog, '-b', '-Wd', 'lib/portage/tests/runTests.py'] + args |
9759 |
+ cmd = [prog, "-b", "-Wd", "lib/portage/tests/runTests.py"] + args |
9760 |
if os.access(prog, os.X_OK): |
9761 |
- print('%sTesting with Python %s...%s' % |
9762 |
- (colors.GOOD, ver, colors.NORMAL)) |
9763 |
+ print( |
9764 |
+ "%sTesting with Python %s...%s" % (colors.GOOD, ver, colors.NORMAL) |
9765 |
+ ) |
9766 |
statuses.append((ver, subprocess.call(cmd))) |
9767 |
elif not ignore_missing: |
9768 |
- print('%sCould not find requested Python %s%s' % |
9769 |
- (colors.BAD, ver, colors.NORMAL)) |
9770 |
+ print( |
9771 |
+ "%sCould not find requested Python %s%s" |
9772 |
+ % (colors.BAD, ver, colors.NORMAL) |
9773 |
+ ) |
9774 |
statuses.append((ver, 1)) |
9775 |
else: |
9776 |
- print('%sSkip Python %s...%s' % |
9777 |
- (colors.WARN, ver, colors.NORMAL)) |
9778 |
+ print("%sSkip Python %s...%s" % (colors.WARN, ver, colors.NORMAL)) |
9779 |
print() |
9780 |
finally: |
9781 |
if tempdir is not None: |
9782 |
if opts.keep_temp: |
9783 |
- print('Temporary directory left behind:\n%s' % tempdir) |
9784 |
+ print("Temporary directory left behind:\n%s" % tempdir) |
9785 |
else: |
9786 |
# Nuke our tempdir and anything that might be under it. |
9787 |
shutil.rmtree(tempdir, True) |
9788 |
|
9789 |
# Then summarize it all. |
9790 |
- print('\nSummary:\n') |
9791 |
+ print("\nSummary:\n") |
9792 |
width = 10 |
9793 |
- header = '| %-*s | %s' % (width, 'Version', 'Status') |
9794 |
- print('%s\n|%s' % (header, '-' * (len(header) - 1))) |
9795 |
+ header = "| %-*s | %s" % (width, "Version", "Status") |
9796 |
+ print("%s\n|%s" % (header, "-" * (len(header) - 1))) |
9797 |
exit_status = 0 |
9798 |
for ver, status in statuses: |
9799 |
exit_status += status |
9800 |
if status: |
9801 |
color = colors.BAD |
9802 |
- msg = 'FAIL' |
9803 |
+ msg = "FAIL" |
9804 |
else: |
9805 |
color = colors.GOOD |
9806 |
- msg = 'PASS' |
9807 |
- print('| %s%-*s%s | %s%s%s' % |
9808 |
- (color, width, ver, colors.NORMAL, color, msg, colors.NORMAL)) |
9809 |
+ msg = "PASS" |
9810 |
+ print( |
9811 |
+ "| %s%-*s%s | %s%s%s" |
9812 |
+ % (color, width, ver, colors.NORMAL, color, msg, colors.NORMAL) |
9813 |
+ ) |
9814 |
exit(exit_status) |
9815 |
|
9816 |
|
9817 |
-if __name__ == '__main__': |
9818 |
+if __name__ == "__main__": |
9819 |
try: |
9820 |
main(sys.argv[1:]) |
9821 |
except KeyboardInterrupt: |
9822 |
- print('interrupted ...', file=sys.stderr) |
9823 |
+ print("interrupted ...", file=sys.stderr) |
9824 |
exit(1) |