1 |
Author: grobian |
2 |
Date: 2009-06-28 13:36:35 +0000 (Sun, 28 Jun 2009) |
3 |
New Revision: 13719 |
4 |
|
5 |
Added: |
6 |
main/branches/prefix/pym/_emerge/main.py |
7 |
Removed: |
8 |
main/branches/prefix/pym/_emerge/__init__.py |
9 |
Log: |
10 |
manually replay r13697 and pray that nothing was changed in the file at the same time |
11 |
|
12 |
Deleted: main/branches/prefix/pym/_emerge/__init__.py |
13 |
=================================================================== |
14 |
--- main/branches/prefix/pym/_emerge/__init__.py 2009-06-28 13:10:08 UTC (rev 13718) |
15 |
+++ main/branches/prefix/pym/_emerge/__init__.py 2009-06-28 13:36:35 UTC (rev 13719) |
16 |
@@ -1,1295 +0,0 @@ |
17 |
-# Copyright 1999-2009 Gentoo Foundation |
18 |
-# Distributed under the terms of the GNU General Public License v2 |
19 |
-# $Id$ |
20 |
- |
21 |
-import logging |
22 |
-import shlex |
23 |
-import signal |
24 |
-import sys |
25 |
-import textwrap |
26 |
-import os |
27 |
-import platform |
28 |
- |
29 |
-# Portage module path logic (Prefix way) |
30 |
-# In principle we don't want to be dependant on the environment |
31 |
-# (PYTHONPATH) and/or python hardcoded default search path. |
32 |
-# (PYTHONPATH). Since Gentoo patches Python to include Portage's python |
33 |
-# modules in the default search path, any Gentoo python interpreter is |
34 |
-# an enemy for Portage once it is not installed in the path hardcoded |
35 |
-# during Python compilation. This is the case when bootstrapping |
36 |
-# Prefix Portage on a Gentoo Linux system, or when bootstrapping Prefix |
37 |
-# Portage using another Prefix instance on the same system. For this |
38 |
-# reason we ignore the entire search path, and allow a backdoor for |
39 |
-# developers via the PORTAGE_PYTHONPATH variable. |
40 |
-import os |
41 |
-import sys |
42 |
-if os.environ.__contains__("PORTAGE_PYTHONPATH"): |
43 |
- sys.path.insert(0, os.environ["PORTAGE_PYTHONPATH"]) |
44 |
-else: |
45 |
- sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), "pym")) |
46 |
-import portage |
47 |
- |
48 |
-import _emerge.help |
49 |
-import portage.xpak, commands, errno, re, time |
50 |
-from portage.output import colorize, xtermTitleReset |
51 |
-from portage.output import create_color_func |
52 |
-good = create_color_func("GOOD") |
53 |
-bad = create_color_func("BAD") |
54 |
- |
55 |
-import portage.elog |
56 |
-import portage.dep |
57 |
-portage.dep._dep_check_strict = True |
58 |
-import portage.util |
59 |
-import portage.locks |
60 |
-import portage.exception |
61 |
-from portage.const import EPREFIX, BPREFIX, EPREFIX_LSTRIP |
62 |
-from portage.data import secpass |
63 |
-from portage.util import normalize_path as normpath |
64 |
-from portage.util import writemsg, writemsg_level |
65 |
-from portage.sets import SETPREFIX |
66 |
- |
67 |
-from _emerge.actions import action_config, action_sync, action_metadata, \ |
68 |
- action_regen, action_search, action_uninstall, action_info, action_build, \ |
69 |
- adjust_config, chk_updated_cfg_files, display_missing_pkg_set, \ |
70 |
- display_news_notification, getportageversion, load_emerge_config |
71 |
-from _emerge.emergelog import emergelog |
72 |
-from _emerge._flush_elog_mod_echo import _flush_elog_mod_echo |
73 |
-from _emerge.is_valid_package_atom import is_valid_package_atom |
74 |
-from _emerge.stdout_spinner import stdout_spinner |
75 |
- |
76 |
-options=[ |
77 |
-"--ask", "--alphabetical", |
78 |
-"--buildpkg", "--buildpkgonly", |
79 |
-"--changelog", "--columns", |
80 |
-"--complete-graph", |
81 |
-"--debug", "--deep", |
82 |
-"--digest", |
83 |
-"--emptytree", |
84 |
-"--fetchonly", "--fetch-all-uri", |
85 |
-"--getbinpkg", "--getbinpkgonly", |
86 |
-"--help", "--ignore-default-opts", |
87 |
-"--keep-going", |
88 |
-"--noconfmem", |
89 |
-"--newuse", |
90 |
-"--nodeps", "--noreplace", |
91 |
-"--nospinner", "--oneshot", |
92 |
-"--onlydeps", "--pretend", |
93 |
-"--quiet", "--resume", |
94 |
-"--searchdesc", "--selective", |
95 |
-"--skipfirst", |
96 |
-"--tree", |
97 |
-"--update", |
98 |
-"--usepkg", "--usepkgonly", |
99 |
-"--verbose", |
100 |
-] |
101 |
- |
102 |
-shortmapping={ |
103 |
-"1":"--oneshot", |
104 |
-"a":"--ask", |
105 |
-"b":"--buildpkg", "B":"--buildpkgonly", |
106 |
-"c":"--clean", "C":"--unmerge", |
107 |
-"d":"--debug", "D":"--deep", |
108 |
-"e":"--emptytree", |
109 |
-"f":"--fetchonly", "F":"--fetch-all-uri", |
110 |
-"g":"--getbinpkg", "G":"--getbinpkgonly", |
111 |
-"h":"--help", |
112 |
-"k":"--usepkg", "K":"--usepkgonly", |
113 |
-"l":"--changelog", |
114 |
-"n":"--noreplace", "N":"--newuse", |
115 |
-"o":"--onlydeps", "O":"--nodeps", |
116 |
-"p":"--pretend", "P":"--prune", |
117 |
-"q":"--quiet", |
118 |
-"s":"--search", "S":"--searchdesc", |
119 |
-"t":"--tree", |
120 |
-"u":"--update", |
121 |
-"v":"--verbose", "V":"--version" |
122 |
-} |
123 |
- |
124 |
-def chk_updated_info_files(root, infodirs, prev_mtimes, retval): |
125 |
- |
126 |
- if os.path.exists(EPREFIX + "/usr/bin/install-info"): |
127 |
- out = portage.output.EOutput() |
128 |
- regen_infodirs=[] |
129 |
- for z in infodirs: |
130 |
- if z=='': |
131 |
- continue |
132 |
- inforoot=normpath(root+z) |
133 |
- if os.path.isdir(inforoot): |
134 |
- infomtime = long(os.stat(inforoot).st_mtime) |
135 |
- if inforoot not in prev_mtimes or \ |
136 |
- prev_mtimes[inforoot] != infomtime: |
137 |
- regen_infodirs.append(inforoot) |
138 |
- |
139 |
- if not regen_infodirs: |
140 |
- portage.writemsg_stdout("\n") |
141 |
- out.einfo("GNU info directory index is up-to-date.") |
142 |
- else: |
143 |
- portage.writemsg_stdout("\n") |
144 |
- out.einfo("Regenerating GNU info directory index...") |
145 |
- |
146 |
- dir_extensions = ("", ".gz", ".bz2") |
147 |
- icount=0 |
148 |
- badcount=0 |
149 |
- errmsg = "" |
150 |
- for inforoot in regen_infodirs: |
151 |
- if inforoot=='': |
152 |
- continue |
153 |
- |
154 |
- if not os.path.isdir(inforoot) or \ |
155 |
- not os.access(inforoot, os.W_OK): |
156 |
- continue |
157 |
- |
158 |
- file_list = os.listdir(inforoot) |
159 |
- file_list.sort() |
160 |
- dir_file = os.path.join(inforoot, "dir") |
161 |
- moved_old_dir = False |
162 |
- processed_count = 0 |
163 |
- for x in file_list: |
164 |
- if x.startswith(".") or \ |
165 |
- os.path.isdir(os.path.join(inforoot, x)): |
166 |
- continue |
167 |
- if x.startswith("dir"): |
168 |
- skip = False |
169 |
- for ext in dir_extensions: |
170 |
- if x == "dir" + ext or \ |
171 |
- x == "dir" + ext + ".old": |
172 |
- skip = True |
173 |
- break |
174 |
- if skip: |
175 |
- continue |
176 |
- if processed_count == 0: |
177 |
- for ext in dir_extensions: |
178 |
- try: |
179 |
- os.rename(dir_file + ext, dir_file + ext + ".old") |
180 |
- moved_old_dir = True |
181 |
- except EnvironmentError, e: |
182 |
- if e.errno != errno.ENOENT: |
183 |
- raise |
184 |
- del e |
185 |
- processed_count += 1 |
186 |
- myso=commands.getstatusoutput("LANG=C LANGUAGE=C " + EPREFIX + "/usr/bin/install-info --dir-file="+inforoot+"/dir "+inforoot+"/"+x)[1] |
187 |
- existsstr="already exists, for file `" |
188 |
- if myso!="": |
189 |
- if re.search(existsstr,myso): |
190 |
- # Already exists... Don't increment the count for this. |
191 |
- pass |
192 |
- elif myso[:44]=="install-info: warning: no info dir entry in ": |
193 |
- # This info file doesn't contain a DIR-header: install-info produces this |
194 |
- # (harmless) warning (the --quiet switch doesn't seem to work). |
195 |
- # Don't increment the count for this. |
196 |
- pass |
197 |
- else: |
198 |
- badcount=badcount+1 |
199 |
- errmsg += myso + "\n" |
200 |
- icount=icount+1 |
201 |
- |
202 |
- if moved_old_dir and not os.path.exists(dir_file): |
203 |
- # We didn't generate a new dir file, so put the old file |
204 |
- # back where it was originally found. |
205 |
- for ext in dir_extensions: |
206 |
- try: |
207 |
- os.rename(dir_file + ext + ".old", dir_file + ext) |
208 |
- except EnvironmentError, e: |
209 |
- if e.errno != errno.ENOENT: |
210 |
- raise |
211 |
- del e |
212 |
- |
213 |
- # Clean dir.old cruft so that they don't prevent |
214 |
- # unmerge of otherwise empty directories. |
215 |
- for ext in dir_extensions: |
216 |
- try: |
217 |
- os.unlink(dir_file + ext + ".old") |
218 |
- except EnvironmentError, e: |
219 |
- if e.errno != errno.ENOENT: |
220 |
- raise |
221 |
- del e |
222 |
- |
223 |
- #update mtime so we can potentially avoid regenerating. |
224 |
- prev_mtimes[inforoot] = long(os.stat(inforoot).st_mtime) |
225 |
- |
226 |
- if badcount: |
227 |
- out.eerror("Processed %d info files; %d errors." % \ |
228 |
- (icount, badcount)) |
229 |
- writemsg_level(errmsg, level=logging.ERROR, noiselevel=-1) |
230 |
- else: |
231 |
- if icount > 0: |
232 |
- out.einfo("Processed %d info files." % (icount,)) |
233 |
- |
234 |
- |
235 |
-def display_preserved_libs(vardbapi): |
236 |
- MAX_DISPLAY = 3 |
237 |
- |
238 |
- # Ensure the registry is consistent with existing files. |
239 |
- vardbapi.plib_registry.pruneNonExisting() |
240 |
- |
241 |
- if vardbapi.plib_registry.hasEntries(): |
242 |
- print |
243 |
- print colorize("WARN", "!!!") + " existing preserved libs:" |
244 |
- plibdata = vardbapi.plib_registry.getPreservedLibs() |
245 |
- linkmap = vardbapi.linkmap |
246 |
- consumer_map = {} |
247 |
- owners = {} |
248 |
- linkmap_broken = False |
249 |
- |
250 |
- try: |
251 |
- linkmap.rebuild() |
252 |
- except portage.exception.CommandNotFound, e: |
253 |
- writemsg_level("!!! Command Not Found: %s\n" % (e,), |
254 |
- level=logging.ERROR, noiselevel=-1) |
255 |
- del e |
256 |
- linkmap_broken = True |
257 |
- else: |
258 |
- search_for_owners = set() |
259 |
- for cpv in plibdata: |
260 |
- internal_plib_keys = set(linkmap._obj_key(f) \ |
261 |
- for f in plibdata[cpv]) |
262 |
- for f in plibdata[cpv]: |
263 |
- if f in consumer_map: |
264 |
- continue |
265 |
- consumers = [] |
266 |
- for c in linkmap.findConsumers(f): |
267 |
- # Filter out any consumers that are also preserved libs |
268 |
- # belonging to the same package as the provider. |
269 |
- if linkmap._obj_key(c) not in internal_plib_keys: |
270 |
- consumers.append(c) |
271 |
- consumers.sort() |
272 |
- consumer_map[f] = consumers |
273 |
- search_for_owners.update(consumers[:MAX_DISPLAY+1]) |
274 |
- |
275 |
- owners = vardbapi._owners.getFileOwnerMap(search_for_owners) |
276 |
- |
277 |
- for cpv in plibdata: |
278 |
- print colorize("WARN", ">>>") + " package: %s" % cpv |
279 |
- samefile_map = {} |
280 |
- for f in plibdata[cpv]: |
281 |
- obj_key = linkmap._obj_key(f) |
282 |
- alt_paths = samefile_map.get(obj_key) |
283 |
- if alt_paths is None: |
284 |
- alt_paths = set() |
285 |
- samefile_map[obj_key] = alt_paths |
286 |
- alt_paths.add(f) |
287 |
- |
288 |
- for alt_paths in samefile_map.itervalues(): |
289 |
- alt_paths = sorted(alt_paths) |
290 |
- for p in alt_paths: |
291 |
- print colorize("WARN", " * ") + " - %s" % (p,) |
292 |
- f = alt_paths[0] |
293 |
- consumers = consumer_map.get(f, []) |
294 |
- for c in consumers[:MAX_DISPLAY]: |
295 |
- print colorize("WARN", " * ") + " used by %s (%s)" % \ |
296 |
- (c, ", ".join(x.mycpv for x in owners.get(c, []))) |
297 |
- if len(consumers) == MAX_DISPLAY + 1: |
298 |
- print colorize("WARN", " * ") + " used by %s (%s)" % \ |
299 |
- (consumers[MAX_DISPLAY], ", ".join(x.mycpv \ |
300 |
- for x in owners.get(consumers[MAX_DISPLAY], []))) |
301 |
- elif len(consumers) > MAX_DISPLAY: |
302 |
- print colorize("WARN", " * ") + " used by %d other files" % (len(consumers) - MAX_DISPLAY) |
303 |
- print "Use " + colorize("GOOD", "emerge @preserved-rebuild") + " to rebuild packages using these libraries" |
304 |
- |
305 |
- |
306 |
-def post_emerge(root_config, myopts, mtimedb, retval): |
307 |
- """ |
308 |
- Misc. things to run at the end of a merge session. |
309 |
- |
310 |
- Update Info Files |
311 |
- Update Config Files |
312 |
- Update News Items |
313 |
- Commit mtimeDB |
314 |
- Display preserved libs warnings |
315 |
- Exit Emerge |
316 |
- |
317 |
- @param trees: A dictionary mapping each ROOT to it's package databases |
318 |
- @type trees: dict |
319 |
- @param mtimedb: The mtimeDB to store data needed across merge invocations |
320 |
- @type mtimedb: MtimeDB class instance |
321 |
- @param retval: Emerge's return value |
322 |
- @type retval: Int |
323 |
- @rype: None |
324 |
- @returns: |
325 |
- 1. Calls sys.exit(retval) |
326 |
- """ |
327 |
- |
328 |
- target_root = root_config.root |
329 |
- trees = { target_root : root_config.trees } |
330 |
- vardbapi = trees[target_root]["vartree"].dbapi |
331 |
- settings = vardbapi.settings |
332 |
- info_mtimes = mtimedb["info"] |
333 |
- |
334 |
- # Load the most current variables from ${ROOT}/etc/profile.env |
335 |
- settings.unlock() |
336 |
- settings.reload() |
337 |
- settings.regenerate() |
338 |
- settings.lock() |
339 |
- |
340 |
- config_protect = settings.get("CONFIG_PROTECT","").split() |
341 |
- infodirs = settings.get("INFOPATH","").split(":") + \ |
342 |
- settings.get("INFODIR","").split(":") |
343 |
- |
344 |
- os.chdir("/") |
345 |
- |
346 |
- if retval == os.EX_OK: |
347 |
- exit_msg = " *** exiting successfully." |
348 |
- else: |
349 |
- exit_msg = " *** exiting unsuccessfully with status '%s'." % retval |
350 |
- emergelog("notitles" not in settings.features, exit_msg) |
351 |
- |
352 |
- _flush_elog_mod_echo() |
353 |
- |
354 |
- counter_hash = settings.get("PORTAGE_COUNTER_HASH") |
355 |
- if "--pretend" in myopts or (counter_hash is not None and \ |
356 |
- counter_hash == vardbapi._counter_hash()): |
357 |
- display_news_notification(root_config, myopts) |
358 |
- # If vdb state has not changed then there's nothing else to do. |
359 |
- sys.exit(retval) |
360 |
- |
361 |
- vdb_path = os.path.join(target_root, portage.VDB_PATH) |
362 |
- portage.util.ensure_dirs(vdb_path) |
363 |
- vdb_lock = None |
364 |
- if os.access(vdb_path, os.W_OK) and not "--pretend" in myopts: |
365 |
- vdb_lock = portage.locks.lockdir(vdb_path) |
366 |
- |
367 |
- if vdb_lock: |
368 |
- try: |
369 |
- if "noinfo" not in settings.features: |
370 |
- chk_updated_info_files(target_root + EPREFIX, |
371 |
- infodirs, info_mtimes, retval) |
372 |
- mtimedb.commit() |
373 |
- finally: |
374 |
- if vdb_lock: |
375 |
- portage.locks.unlockdir(vdb_lock) |
376 |
- |
377 |
- chk_updated_cfg_files(target_root + EPREFIX, config_protect) |
378 |
- |
379 |
- display_news_notification(root_config, myopts) |
380 |
- if retval in (None, os.EX_OK) or (not "--pretend" in myopts): |
381 |
- display_preserved_libs(vardbapi) |
382 |
- |
383 |
- sys.exit(retval) |
384 |
- |
385 |
- |
386 |
-def multiple_actions(action1, action2): |
387 |
- sys.stderr.write("\n!!! Multiple actions requested... Please choose one only.\n") |
388 |
- sys.stderr.write("!!! '%s' or '%s'\n\n" % (action1, action2)) |
389 |
- sys.exit(1) |
390 |
- |
391 |
-def insert_optional_args(args): |
392 |
- """ |
393 |
- Parse optional arguments and insert a value if one has |
394 |
- not been provided. This is done before feeding the args |
395 |
- to the optparse parser since that parser does not support |
396 |
- this feature natively. |
397 |
- """ |
398 |
- |
399 |
- new_args = [] |
400 |
- jobs_opts = ("-j", "--jobs") |
401 |
- default_arg_opts = { |
402 |
- '--deselect' : ('n',), |
403 |
- '--root-deps' : ('rdeps',), |
404 |
- } |
405 |
- arg_stack = args[:] |
406 |
- arg_stack.reverse() |
407 |
- while arg_stack: |
408 |
- arg = arg_stack.pop() |
409 |
- |
410 |
- default_arg_choices = default_arg_opts.get(arg) |
411 |
- if default_arg_choices is not None: |
412 |
- new_args.append(arg) |
413 |
- if arg_stack and arg_stack[-1] in default_arg_choices: |
414 |
- new_args.append(arg_stack.pop()) |
415 |
- else: |
416 |
- # insert default argument |
417 |
- new_args.append('True') |
418 |
- continue |
419 |
- |
420 |
- short_job_opt = bool("j" in arg and arg[:1] == "-" and arg[:2] != "--") |
421 |
- if not (short_job_opt or arg in jobs_opts): |
422 |
- new_args.append(arg) |
423 |
- continue |
424 |
- |
425 |
- # Insert an empty placeholder in order to |
426 |
- # satisfy the requirements of optparse. |
427 |
- |
428 |
- new_args.append("--jobs") |
429 |
- job_count = None |
430 |
- saved_opts = None |
431 |
- if short_job_opt and len(arg) > 2: |
432 |
- if arg[:2] == "-j": |
433 |
- try: |
434 |
- job_count = int(arg[2:]) |
435 |
- except ValueError: |
436 |
- saved_opts = arg[2:] |
437 |
- else: |
438 |
- job_count = "True" |
439 |
- saved_opts = arg[1:].replace("j", "") |
440 |
- |
441 |
- if job_count is None and arg_stack: |
442 |
- try: |
443 |
- job_count = int(arg_stack[-1]) |
444 |
- except ValueError: |
445 |
- pass |
446 |
- else: |
447 |
- # Discard the job count from the stack |
448 |
- # since we're consuming it here. |
449 |
- arg_stack.pop() |
450 |
- |
451 |
- if job_count is None: |
452 |
- # unlimited number of jobs |
453 |
- new_args.append("True") |
454 |
- else: |
455 |
- new_args.append(str(job_count)) |
456 |
- |
457 |
- if saved_opts is not None: |
458 |
- new_args.append("-" + saved_opts) |
459 |
- |
460 |
- return new_args |
461 |
- |
462 |
-def parse_opts(tmpcmdline, silent=False): |
463 |
- myaction=None |
464 |
- myopts = {} |
465 |
- myfiles=[] |
466 |
- |
467 |
- global options, shortmapping |
468 |
- |
469 |
- actions = frozenset([ |
470 |
- "clean", "config", "depclean", |
471 |
- "info", "list-sets", "metadata", |
472 |
- "prune", "regen", "search", |
473 |
- "sync", "unmerge", "version", |
474 |
- ]) |
475 |
- |
476 |
- longopt_aliases = {"--cols":"--columns", "--skip-first":"--skipfirst"} |
477 |
- argument_options = { |
478 |
- "--config-root": { |
479 |
- "help":"specify the location for portage configuration files", |
480 |
- "action":"store" |
481 |
- }, |
482 |
- "--color": { |
483 |
- "help":"enable or disable color output", |
484 |
- "type":"choice", |
485 |
- "choices":("y", "n") |
486 |
- }, |
487 |
- |
488 |
- "--deselect": { |
489 |
- "help" : "remove atoms from the world file", |
490 |
- "type" : "choice", |
491 |
- "choices" : ("True", "n") |
492 |
- }, |
493 |
- |
494 |
- "--jobs": { |
495 |
- |
496 |
- "help" : "Specifies the number of packages to build " + \ |
497 |
- "simultaneously.", |
498 |
- |
499 |
- "action" : "store" |
500 |
- }, |
501 |
- |
502 |
- "--load-average": { |
503 |
- |
504 |
- "help" :"Specifies that no new builds should be started " + \ |
505 |
- "if there are other builds running and the load average " + \ |
506 |
- "is at least LOAD (a floating-point number).", |
507 |
- |
508 |
- "action" : "store" |
509 |
- }, |
510 |
- |
511 |
- "--with-bdeps": { |
512 |
- "help":"include unnecessary build time dependencies", |
513 |
- "type":"choice", |
514 |
- "choices":("y", "n") |
515 |
- }, |
516 |
- "--reinstall": { |
517 |
- "help":"specify conditions to trigger package reinstallation", |
518 |
- "type":"choice", |
519 |
- "choices":["changed-use"] |
520 |
- }, |
521 |
- "--root": { |
522 |
- "help" : "specify the target root filesystem for merging packages", |
523 |
- "action" : "store" |
524 |
- }, |
525 |
- |
526 |
- "--root-deps": { |
527 |
- "help" : "modify interpretation of depedencies", |
528 |
- "type" : "choice", |
529 |
- "choices" :("True", "rdeps") |
530 |
- }, |
531 |
- } |
532 |
- |
533 |
- from optparse import OptionParser |
534 |
- parser = OptionParser() |
535 |
- if parser.has_option("--help"): |
536 |
- parser.remove_option("--help") |
537 |
- |
538 |
- for action_opt in actions: |
539 |
- parser.add_option("--" + action_opt, action="store_true", |
540 |
- dest=action_opt.replace("-", "_"), default=False) |
541 |
- for myopt in options: |
542 |
- parser.add_option(myopt, action="store_true", |
543 |
- dest=myopt.lstrip("--").replace("-", "_"), default=False) |
544 |
- for shortopt, longopt in shortmapping.iteritems(): |
545 |
- parser.add_option("-" + shortopt, action="store_true", |
546 |
- dest=longopt.lstrip("--").replace("-", "_"), default=False) |
547 |
- for myalias, myopt in longopt_aliases.iteritems(): |
548 |
- parser.add_option(myalias, action="store_true", |
549 |
- dest=myopt.lstrip("--").replace("-", "_"), default=False) |
550 |
- |
551 |
- for myopt, kwargs in argument_options.iteritems(): |
552 |
- parser.add_option(myopt, |
553 |
- dest=myopt.lstrip("--").replace("-", "_"), **kwargs) |
554 |
- |
555 |
- tmpcmdline = insert_optional_args(tmpcmdline) |
556 |
- |
557 |
- myoptions, myargs = parser.parse_args(args=tmpcmdline) |
558 |
- |
559 |
- if myoptions.deselect == "True": |
560 |
- myoptions.deselect = True |
561 |
- |
562 |
- if myoptions.root_deps == "True": |
563 |
- myoptions.root_deps = True |
564 |
- |
565 |
- if myoptions.jobs: |
566 |
- jobs = None |
567 |
- if myoptions.jobs == "True": |
568 |
- jobs = True |
569 |
- else: |
570 |
- try: |
571 |
- jobs = int(myoptions.jobs) |
572 |
- except ValueError: |
573 |
- jobs = -1 |
574 |
- |
575 |
- if jobs is not True and \ |
576 |
- jobs < 1: |
577 |
- jobs = None |
578 |
- if not silent: |
579 |
- writemsg("!!! Invalid --jobs parameter: '%s'\n" % \ |
580 |
- (myoptions.jobs,), noiselevel=-1) |
581 |
- |
582 |
- myoptions.jobs = jobs |
583 |
- |
584 |
- if myoptions.load_average: |
585 |
- try: |
586 |
- load_average = float(myoptions.load_average) |
587 |
- except ValueError: |
588 |
- load_average = 0.0 |
589 |
- |
590 |
- if load_average <= 0.0: |
591 |
- load_average = None |
592 |
- if not silent: |
593 |
- writemsg("!!! Invalid --load-average parameter: '%s'\n" % \ |
594 |
- (myoptions.load_average,), noiselevel=-1) |
595 |
- |
596 |
- myoptions.load_average = load_average |
597 |
- |
598 |
- for myopt in options: |
599 |
- v = getattr(myoptions, myopt.lstrip("--").replace("-", "_")) |
600 |
- if v: |
601 |
- myopts[myopt] = True |
602 |
- |
603 |
- for myopt in argument_options: |
604 |
- v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"), None) |
605 |
- if v is not None: |
606 |
- myopts[myopt] = v |
607 |
- |
608 |
- if myoptions.searchdesc: |
609 |
- myoptions.search = True |
610 |
- |
611 |
- for action_opt in actions: |
612 |
- v = getattr(myoptions, action_opt.replace("-", "_")) |
613 |
- if v: |
614 |
- if myaction: |
615 |
- multiple_actions(myaction, action_opt) |
616 |
- sys.exit(1) |
617 |
- myaction = action_opt |
618 |
- |
619 |
- if myaction is None and myoptions.deselect is True: |
620 |
- myaction = 'deselect' |
621 |
- |
622 |
- myfiles += myargs |
623 |
- |
624 |
- return myaction, myopts, myfiles |
625 |
- |
626 |
-def validate_ebuild_environment(trees): |
627 |
- for myroot in trees: |
628 |
- settings = trees[myroot]["vartree"].settings |
629 |
- settings.validate() |
630 |
- |
631 |
-def apply_priorities(settings): |
632 |
- ionice(settings) |
633 |
- nice(settings) |
634 |
- |
635 |
-def nice(settings): |
636 |
- try: |
637 |
- os.nice(int(settings.get("PORTAGE_NICENESS", "0"))) |
638 |
- except (OSError, ValueError), e: |
639 |
- out = portage.output.EOutput() |
640 |
- out.eerror("Failed to change nice value to '%s'" % \ |
641 |
- settings["PORTAGE_NICENESS"]) |
642 |
- out.eerror("%s\n" % str(e)) |
643 |
- |
644 |
-def ionice(settings): |
645 |
- |
646 |
- ionice_cmd = settings.get("PORTAGE_IONICE_COMMAND") |
647 |
- if ionice_cmd: |
648 |
- ionice_cmd = shlex.split(ionice_cmd) |
649 |
- if not ionice_cmd: |
650 |
- return |
651 |
- |
652 |
- from portage.util import varexpand |
653 |
- variables = {"PID" : str(os.getpid())} |
654 |
- cmd = [varexpand(x, mydict=variables) for x in ionice_cmd] |
655 |
- |
656 |
- try: |
657 |
- rval = portage.process.spawn(cmd, env=os.environ) |
658 |
- except portage.exception.CommandNotFound: |
659 |
- # The OS kernel probably doesn't support ionice, |
660 |
- # so return silently. |
661 |
- return |
662 |
- |
663 |
- if rval != os.EX_OK: |
664 |
- out = portage.output.EOutput() |
665 |
- out.eerror("PORTAGE_IONICE_COMMAND returned %d" % (rval,)) |
666 |
- out.eerror("See the make.conf(5) man page for PORTAGE_IONICE_COMMAND usage instructions.") |
667 |
- |
668 |
-def expand_set_arguments(myfiles, myaction, root_config): |
669 |
- retval = os.EX_OK |
670 |
- setconfig = root_config.setconfig |
671 |
- |
672 |
- sets = setconfig.getSets() |
673 |
- |
674 |
- # In order to know exactly which atoms/sets should be added to the |
675 |
- # world file, the depgraph performs set expansion later. It will get |
676 |
- # confused about where the atoms came from if it's not allowed to |
677 |
- # expand them itself. |
678 |
- do_not_expand = (None, ) |
679 |
- newargs = [] |
680 |
- for a in myfiles: |
681 |
- if a in ("system", "world"): |
682 |
- newargs.append(SETPREFIX+a) |
683 |
- else: |
684 |
- newargs.append(a) |
685 |
- myfiles = newargs |
686 |
- del newargs |
687 |
- newargs = [] |
688 |
- |
689 |
- # separators for set arguments |
690 |
- ARG_START = "{" |
691 |
- ARG_END = "}" |
692 |
- |
693 |
- # WARNING: all operators must be of equal length |
694 |
- IS_OPERATOR = "/@" |
695 |
- DIFF_OPERATOR = "-@" |
696 |
- UNION_OPERATOR = "+@" |
697 |
- |
698 |
- for i in range(0, len(myfiles)): |
699 |
- if myfiles[i].startswith(SETPREFIX): |
700 |
- start = 0 |
701 |
- end = 0 |
702 |
- x = myfiles[i][len(SETPREFIX):] |
703 |
- newset = "" |
704 |
- while x: |
705 |
- start = x.find(ARG_START) |
706 |
- end = x.find(ARG_END) |
707 |
- if start > 0 and start < end: |
708 |
- namepart = x[:start] |
709 |
- argpart = x[start+1:end] |
710 |
- |
711 |
- # TODO: implement proper quoting |
712 |
- args = argpart.split(",") |
713 |
- options = {} |
714 |
- for a in args: |
715 |
- if "=" in a: |
716 |
- k, v = a.split("=", 1) |
717 |
- options[k] = v |
718 |
- else: |
719 |
- options[a] = "True" |
720 |
- setconfig.update(namepart, options) |
721 |
- newset += (x[:start-len(namepart)]+namepart) |
722 |
- x = x[end+len(ARG_END):] |
723 |
- else: |
724 |
- newset += x |
725 |
- x = "" |
726 |
- myfiles[i] = SETPREFIX+newset |
727 |
- |
728 |
- sets = setconfig.getSets() |
729 |
- |
730 |
- # display errors that occured while loading the SetConfig instance |
731 |
- for e in setconfig.errors: |
732 |
- print colorize("BAD", "Error during set creation: %s" % e) |
733 |
- |
734 |
- # emerge relies on the existance of sets with names "world" and "system" |
735 |
- required_sets = ("world", "system") |
736 |
- missing_sets = [] |
737 |
- |
738 |
- for s in required_sets: |
739 |
- if s not in sets: |
740 |
- missing_sets.append(s) |
741 |
- if missing_sets: |
742 |
- if len(missing_sets) > 2: |
743 |
- missing_sets_str = ", ".join('"%s"' % s for s in missing_sets[:-1]) |
744 |
- missing_sets_str += ', and "%s"' % missing_sets[-1] |
745 |
- elif len(missing_sets) == 2: |
746 |
- missing_sets_str = '"%s" and "%s"' % tuple(missing_sets) |
747 |
- else: |
748 |
- missing_sets_str = '"%s"' % missing_sets[-1] |
749 |
- msg = ["emerge: incomplete set configuration, " + \ |
750 |
- "missing set(s): %s" % missing_sets_str] |
751 |
- if sets: |
752 |
- msg.append(" sets defined: %s" % ", ".join(sets)) |
753 |
- msg.append(" This usually means that '%s'" % \ |
754 |
- (os.path.join(portage.const.GLOBAL_CONFIG_PATH, "sets.conf"),)) |
755 |
- msg.append(" is missing or corrupt.") |
756 |
- for line in msg: |
757 |
- writemsg_level(line + "\n", level=logging.ERROR, noiselevel=-1) |
758 |
- return (None, 1) |
759 |
- unmerge_actions = ("unmerge", "prune", "clean", "depclean") |
760 |
- |
761 |
- for a in myfiles: |
762 |
- if a.startswith(SETPREFIX): |
763 |
- # support simple set operations (intersection, difference and union) |
764 |
- # on the commandline. Expressions are evaluated strictly left-to-right |
765 |
- if IS_OPERATOR in a or DIFF_OPERATOR in a or UNION_OPERATOR in a: |
766 |
- expression = a[len(SETPREFIX):] |
767 |
- expr_sets = [] |
768 |
- expr_ops = [] |
769 |
- while IS_OPERATOR in expression or DIFF_OPERATOR in expression or UNION_OPERATOR in expression: |
770 |
- is_pos = expression.rfind(IS_OPERATOR) |
771 |
- diff_pos = expression.rfind(DIFF_OPERATOR) |
772 |
- union_pos = expression.rfind(UNION_OPERATOR) |
773 |
- op_pos = max(is_pos, diff_pos, union_pos) |
774 |
- s1 = expression[:op_pos] |
775 |
- s2 = expression[op_pos+len(IS_OPERATOR):] |
776 |
- op = expression[op_pos:op_pos+len(IS_OPERATOR)] |
777 |
- if not s2 in sets: |
778 |
- display_missing_pkg_set(root_config, s2) |
779 |
- return (None, 1) |
780 |
- expr_sets.insert(0, s2) |
781 |
- expr_ops.insert(0, op) |
782 |
- expression = s1 |
783 |
- if not expression in sets: |
784 |
- display_missing_pkg_set(root_config, expression) |
785 |
- return (None, 1) |
786 |
- expr_sets.insert(0, expression) |
787 |
- result = set(setconfig.getSetAtoms(expression)) |
788 |
- for i in range(0, len(expr_ops)): |
789 |
- s2 = setconfig.getSetAtoms(expr_sets[i+1]) |
790 |
- if expr_ops[i] == IS_OPERATOR: |
791 |
- result.intersection_update(s2) |
792 |
- elif expr_ops[i] == DIFF_OPERATOR: |
793 |
- result.difference_update(s2) |
794 |
- elif expr_ops[i] == UNION_OPERATOR: |
795 |
- result.update(s2) |
796 |
- else: |
797 |
- raise NotImplementedError("unknown set operator %s" % expr_ops[i]) |
798 |
- newargs.extend(result) |
799 |
- else: |
800 |
- s = a[len(SETPREFIX):] |
801 |
- if s not in sets: |
802 |
- display_missing_pkg_set(root_config, s) |
803 |
- return (None, 1) |
804 |
- setconfig.active.append(s) |
805 |
- try: |
806 |
- set_atoms = setconfig.getSetAtoms(s) |
807 |
- except portage.exception.PackageSetNotFound, e: |
808 |
- writemsg_level(("emerge: the given set '%s' " + \ |
809 |
- "contains a non-existent set named '%s'.\n") % \ |
810 |
- (s, e), level=logging.ERROR, noiselevel=-1) |
811 |
- return (None, 1) |
812 |
- if myaction in unmerge_actions and \ |
813 |
- not sets[s].supportsOperation("unmerge"): |
814 |
- sys.stderr.write("emerge: the given set '%s' does " % s + \ |
815 |
- "not support unmerge operations\n") |
816 |
- retval = 1 |
817 |
- elif not set_atoms: |
818 |
- print "emerge: '%s' is an empty set" % s |
819 |
- elif myaction not in do_not_expand: |
820 |
- newargs.extend(set_atoms) |
821 |
- else: |
822 |
- newargs.append(SETPREFIX+s) |
823 |
- for e in sets[s].errors: |
824 |
- print e |
825 |
- else: |
826 |
- newargs.append(a) |
827 |
- return (newargs, retval) |
828 |
- |
829 |
-def repo_name_check(trees): |
830 |
- missing_repo_names = set() |
831 |
- for root, root_trees in trees.iteritems(): |
832 |
- if "porttree" in root_trees: |
833 |
- portdb = root_trees["porttree"].dbapi |
834 |
- missing_repo_names.update(portdb.porttrees) |
835 |
- repos = portdb.getRepositories() |
836 |
- for r in repos: |
837 |
- missing_repo_names.discard(portdb.getRepositoryPath(r)) |
838 |
- if portdb.porttree_root in missing_repo_names and \ |
839 |
- not os.path.exists(os.path.join( |
840 |
- portdb.porttree_root, "profiles")): |
841 |
- # This is normal if $PORTDIR happens to be empty, |
842 |
- # so don't warn about it. |
843 |
- missing_repo_names.remove(portdb.porttree_root) |
844 |
- |
845 |
- if missing_repo_names: |
846 |
- msg = [] |
847 |
- msg.append("WARNING: One or more repositories " + \ |
848 |
- "have missing repo_name entries:") |
849 |
- msg.append("") |
850 |
- for p in missing_repo_names: |
851 |
- msg.append("\t%s/profiles/repo_name" % (p,)) |
852 |
- msg.append("") |
853 |
- msg.extend(textwrap.wrap("NOTE: Each repo_name entry " + \ |
854 |
- "should be a plain text file containing a unique " + \ |
855 |
- "name for the repository on the first line.", 70)) |
856 |
- writemsg_level("".join("%s\n" % l for l in msg), |
857 |
- level=logging.WARNING, noiselevel=-1) |
858 |
- |
859 |
- return bool(missing_repo_names) |
860 |
- |
861 |
-def repo_name_duplicate_check(trees): |
862 |
- ignored_repos = {} |
863 |
- for root, root_trees in trees.iteritems(): |
864 |
- if 'porttree' in root_trees: |
865 |
- portdb = root_trees['porttree'].dbapi |
866 |
- if portdb.mysettings.get('PORTAGE_REPO_DUPLICATE_WARN') != '0': |
867 |
- for repo_name, paths in portdb._ignored_repos: |
868 |
- k = (root, repo_name, portdb.getRepositoryPath(repo_name)) |
869 |
- ignored_repos.setdefault(k, []).extend(paths) |
870 |
- |
871 |
- if ignored_repos: |
872 |
- msg = [] |
873 |
- msg.append('WARNING: One or more repositories ' + \ |
874 |
- 'have been ignored due to duplicate') |
875 |
- msg.append(' profiles/repo_name entries:') |
876 |
- msg.append('') |
877 |
- for k in sorted(ignored_repos): |
878 |
- msg.append(' %s overrides' % (k,)) |
879 |
- for path in ignored_repos[k]: |
880 |
- msg.append(' %s' % (path,)) |
881 |
- msg.append('') |
882 |
- msg.extend(' ' + x for x in textwrap.wrap( |
883 |
- "All profiles/repo_name entries must be unique in order " + \ |
884 |
- "to avoid having duplicates ignored. " + \ |
885 |
- "Set PORTAGE_REPO_DUPLICATE_WARN=\"0\" in " + \ |
886 |
- "/etc/make.conf if you would like to disable this warning.")) |
887 |
- writemsg_level(''.join('%s\n' % l for l in msg), |
888 |
- level=logging.WARNING, noiselevel=-1) |
889 |
- |
890 |
- return bool(ignored_repos) |
891 |
- |
892 |
-def config_protect_check(trees): |
893 |
- for root, root_trees in trees.iteritems(): |
894 |
- if not root_trees["root_config"].settings.get("CONFIG_PROTECT"): |
895 |
- msg = "!!! CONFIG_PROTECT is empty" |
896 |
- if root != "/": |
897 |
- msg += " for '%s'" % root |
898 |
- writemsg_level(msg, level=logging.WARN, noiselevel=-1) |
899 |
- |
900 |
-def profile_check(trees, myaction, myopts): |
901 |
- if myaction in ("info", "sync"): |
902 |
- return os.EX_OK |
903 |
- elif "--version" in myopts or "--help" in myopts: |
904 |
- return os.EX_OK |
905 |
- for root, root_trees in trees.iteritems(): |
906 |
- if root_trees["root_config"].settings.profiles: |
907 |
- continue |
908 |
- # generate some profile related warning messages |
909 |
- validate_ebuild_environment(trees) |
910 |
- msg = "If you have just changed your profile configuration, you " + \ |
911 |
- "should revert back to the previous configuration. Due to " + \ |
912 |
- "your current profile being invalid, allowed actions are " + \ |
913 |
- "limited to --help, --info, --sync, and --version." |
914 |
- writemsg_level("".join("!!! %s\n" % l for l in textwrap.wrap(msg, 70)), |
915 |
- level=logging.ERROR, noiselevel=-1) |
916 |
- return 1 |
917 |
- return os.EX_OK |
918 |
- |
919 |
-def emerge_main(): |
920 |
- global portage # NFC why this is necessary now - genone |
921 |
- portage._disable_legacy_globals() |
922 |
- # Disable color until we're sure that it should be enabled (after |
923 |
- # EMERGE_DEFAULT_OPTS has been parsed). |
924 |
- portage.output.havecolor = 0 |
925 |
- # This first pass is just for options that need to be known as early as |
926 |
- # possible, such as --config-root. They will be parsed again later, |
927 |
- # together with EMERGE_DEFAULT_OPTS (which may vary depending on the |
928 |
- # the value of --config-root). |
929 |
- myaction, myopts, myfiles = parse_opts(sys.argv[1:], silent=True) |
930 |
- if "--debug" in myopts: |
931 |
- os.environ["PORTAGE_DEBUG"] = "1" |
932 |
- if "--config-root" in myopts: |
933 |
- os.environ["PORTAGE_CONFIGROOT"] = myopts["--config-root"] |
934 |
- if "--root" in myopts: |
935 |
- os.environ["ROOT"] = myopts["--root"] |
936 |
- |
937 |
- # Portage needs to ensure a sane umask for the files it creates. |
938 |
- os.umask(022) |
939 |
- settings, trees, mtimedb = load_emerge_config() |
940 |
- portdb = trees[settings["ROOT"]]["porttree"].dbapi |
941 |
- rval = profile_check(trees, myaction, myopts) |
942 |
- if rval != os.EX_OK: |
943 |
- return rval |
944 |
- |
945 |
- if portage._global_updates(trees, mtimedb["updates"]): |
946 |
- mtimedb.commit() |
947 |
- # Reload the whole config from scratch. |
948 |
- settings, trees, mtimedb = load_emerge_config(trees=trees) |
949 |
- portdb = trees[settings["ROOT"]]["porttree"].dbapi |
950 |
- |
951 |
- xterm_titles = "notitles" not in settings.features |
952 |
- |
953 |
- tmpcmdline = [] |
954 |
- if "--ignore-default-opts" not in myopts: |
955 |
- tmpcmdline.extend(settings["EMERGE_DEFAULT_OPTS"].split()) |
956 |
- tmpcmdline.extend(sys.argv[1:]) |
957 |
- myaction, myopts, myfiles = parse_opts(tmpcmdline) |
958 |
- |
959 |
- if "--digest" in myopts: |
960 |
- os.environ["FEATURES"] = os.environ.get("FEATURES","") + " digest" |
961 |
- # Reload the whole config from scratch so that the portdbapi internal |
962 |
- # config is updated with new FEATURES. |
963 |
- settings, trees, mtimedb = load_emerge_config(trees=trees) |
964 |
- portdb = trees[settings["ROOT"]]["porttree"].dbapi |
965 |
- |
966 |
- for myroot in trees: |
967 |
- mysettings = trees[myroot]["vartree"].settings |
968 |
- mysettings.unlock() |
969 |
- adjust_config(myopts, mysettings) |
970 |
- if '--pretend' not in myopts and myaction in \ |
971 |
- (None, 'clean', 'depclean', 'prune', 'unmerge'): |
972 |
- mysettings["PORTAGE_COUNTER_HASH"] = \ |
973 |
- trees[myroot]["vartree"].dbapi._counter_hash() |
974 |
- mysettings.backup_changes("PORTAGE_COUNTER_HASH") |
975 |
- mysettings.lock() |
976 |
- del myroot, mysettings |
977 |
- |
978 |
- apply_priorities(settings) |
979 |
- |
980 |
- spinner = stdout_spinner() |
981 |
- if "candy" in settings.features: |
982 |
- spinner.update = spinner.update_scroll |
983 |
- |
984 |
- if "--quiet" not in myopts: |
985 |
- portage.deprecated_profile_check(settings=settings) |
986 |
- repo_name_check(trees) |
987 |
- repo_name_duplicate_check(trees) |
988 |
- config_protect_check(trees) |
989 |
- |
990 |
- for mytrees in trees.itervalues(): |
991 |
- mydb = mytrees["porttree"].dbapi |
992 |
- # Freeze the portdbapi for performance (memoize all xmatch results). |
993 |
- mydb.freeze() |
994 |
- del mytrees, mydb |
995 |
- |
996 |
- if "moo" in myfiles: |
997 |
- print """ |
998 |
- |
999 |
- Larry loves Gentoo (""" + platform.system() + """) |
1000 |
- |
1001 |
- _______________________ |
1002 |
-< Have you mooed today? > |
1003 |
- ----------------------- |
1004 |
- \ ^__^ |
1005 |
- \ (oo)\_______ |
1006 |
- (__)\ )\/\ |
1007 |
- ||----w | |
1008 |
- || || |
1009 |
- |
1010 |
-""" |
1011 |
- |
1012 |
- for x in myfiles: |
1013 |
- ext = os.path.splitext(x)[1] |
1014 |
- if (ext == ".ebuild" or ext == ".tbz2") and os.path.exists(os.path.abspath(x)): |
1015 |
- print colorize("BAD", "\n*** emerging by path is broken and may not always work!!!\n") |
1016 |
- break |
1017 |
- |
1018 |
- root_config = trees[settings["ROOT"]]["root_config"] |
1019 |
- if myaction == "list-sets": |
1020 |
- sys.stdout.write("".join("%s\n" % s for s in sorted(root_config.sets))) |
1021 |
- sys.stdout.flush() |
1022 |
- return os.EX_OK |
1023 |
- |
1024 |
- # only expand sets for actions taking package arguments |
1025 |
- oldargs = myfiles[:] |
1026 |
- if myaction in ("clean", "config", "depclean", "info", "prune", "unmerge", None): |
1027 |
- myfiles, retval = expand_set_arguments(myfiles, myaction, root_config) |
1028 |
- if retval != os.EX_OK: |
1029 |
- return retval |
1030 |
- |
1031 |
- # Need to handle empty sets specially, otherwise emerge will react |
1032 |
- # with the help message for empty argument lists |
1033 |
- if oldargs and not myfiles: |
1034 |
- print "emerge: no targets left after set expansion" |
1035 |
- return 0 |
1036 |
- |
1037 |
- if ("--tree" in myopts) and ("--columns" in myopts): |
1038 |
- print "emerge: can't specify both of \"--tree\" and \"--columns\"." |
1039 |
- return 1 |
1040 |
- |
1041 |
- if ("--quiet" in myopts): |
1042 |
- spinner.update = spinner.update_quiet |
1043 |
- portage.util.noiselimit = -1 |
1044 |
- |
1045 |
- # Always create packages if FEATURES=buildpkg |
1046 |
- # Imply --buildpkg if --buildpkgonly |
1047 |
- if ("buildpkg" in settings.features) or ("--buildpkgonly" in myopts): |
1048 |
- if "--buildpkg" not in myopts: |
1049 |
- myopts["--buildpkg"] = True |
1050 |
- |
1051 |
- # Always try and fetch binary packages if FEATURES=getbinpkg |
1052 |
- if ("getbinpkg" in settings.features): |
1053 |
- myopts["--getbinpkg"] = True |
1054 |
- |
1055 |
- if "--buildpkgonly" in myopts: |
1056 |
- # --buildpkgonly will not merge anything, so |
1057 |
- # it cancels all binary package options. |
1058 |
- for opt in ("--getbinpkg", "--getbinpkgonly", |
1059 |
- "--usepkg", "--usepkgonly"): |
1060 |
- myopts.pop(opt, None) |
1061 |
- |
1062 |
- if "--fetch-all-uri" in myopts: |
1063 |
- myopts["--fetchonly"] = True |
1064 |
- |
1065 |
- if "--skipfirst" in myopts and "--resume" not in myopts: |
1066 |
- myopts["--resume"] = True |
1067 |
- |
1068 |
- if ("--getbinpkgonly" in myopts) and not ("--usepkgonly" in myopts): |
1069 |
- myopts["--usepkgonly"] = True |
1070 |
- |
1071 |
- if ("--getbinpkgonly" in myopts) and not ("--getbinpkg" in myopts): |
1072 |
- myopts["--getbinpkg"] = True |
1073 |
- |
1074 |
- if ("--getbinpkg" in myopts) and not ("--usepkg" in myopts): |
1075 |
- myopts["--usepkg"] = True |
1076 |
- |
1077 |
- # Also allow -K to apply --usepkg/-k |
1078 |
- if ("--usepkgonly" in myopts) and not ("--usepkg" in myopts): |
1079 |
- myopts["--usepkg"] = True |
1080 |
- |
1081 |
- # Allow -p to remove --ask |
1082 |
- if "--pretend" in myopts: |
1083 |
- myopts.pop("--ask", None) |
1084 |
- |
1085 |
- # forbid --ask when not in a terminal |
1086 |
- # note: this breaks `emerge --ask | tee logfile`, but that doesn't work anyway. |
1087 |
- if ("--ask" in myopts) and (not sys.stdin.isatty()): |
1088 |
- portage.writemsg("!!! \"--ask\" should only be used in a terminal. Exiting.\n", |
1089 |
- noiselevel=-1) |
1090 |
- return 1 |
1091 |
- |
1092 |
- if settings.get("PORTAGE_DEBUG", "") == "1": |
1093 |
- spinner.update = spinner.update_quiet |
1094 |
- portage.debug=1 |
1095 |
- if "python-trace" in settings.features: |
1096 |
- import portage.debug |
1097 |
- portage.debug.set_trace(True) |
1098 |
- |
1099 |
- if not ("--quiet" in myopts): |
1100 |
- if not sys.stdout.isatty() or ("--nospinner" in myopts): |
1101 |
- spinner.update = spinner.update_basic |
1102 |
- |
1103 |
- if myaction == 'version': |
1104 |
- print getportageversion(settings["PORTDIR"], settings["ROOT"], |
1105 |
- settings.profile_path, settings["CHOST"], |
1106 |
- trees[settings["ROOT"]]["vartree"].dbapi) |
1107 |
- return 0 |
1108 |
- elif "--help" in myopts: |
1109 |
- _emerge.help.help(myaction, myopts, portage.output.havecolor) |
1110 |
- return 0 |
1111 |
- |
1112 |
- if "--debug" in myopts: |
1113 |
- print "myaction", myaction |
1114 |
- print "myopts", myopts |
1115 |
- |
1116 |
- if not myaction and not myfiles and "--resume" not in myopts: |
1117 |
- _emerge.help.help(myaction, myopts, portage.output.havecolor) |
1118 |
- return 1 |
1119 |
- |
1120 |
- pretend = "--pretend" in myopts |
1121 |
- fetchonly = "--fetchonly" in myopts or "--fetch-all-uri" in myopts |
1122 |
- buildpkgonly = "--buildpkgonly" in myopts |
1123 |
- |
1124 |
- # check if root user is the current user for the actions where emerge needs this |
1125 |
- if portage.secpass < 2: |
1126 |
- # We've already allowed "--version" and "--help" above. |
1127 |
- if "--pretend" not in myopts and myaction not in ("search","info"): |
1128 |
- need_superuser = myaction in ('clean', 'depclean', 'deselect', |
1129 |
- 'prune', 'unmerge') or not \ |
1130 |
- (fetchonly or \ |
1131 |
- (buildpkgonly and secpass >= 1) or \ |
1132 |
- myaction in ("metadata", "regen") or \ |
1133 |
- (myaction == "sync" and os.access(settings["PORTDIR"], os.W_OK))) |
1134 |
- if portage.secpass < 1 or \ |
1135 |
- need_superuser: |
1136 |
- if need_superuser: |
1137 |
- access_desc = "superuser" |
1138 |
- else: |
1139 |
- access_desc = "portage group" |
1140 |
- # Always show portage_group_warning() when only portage group |
1141 |
- # access is required but the user is not in the portage group. |
1142 |
- from portage.data import portage_group_warning |
1143 |
- if "--ask" in myopts: |
1144 |
- myopts["--pretend"] = True |
1145 |
- del myopts["--ask"] |
1146 |
- print ("%s access is required... " + \ |
1147 |
- "adding --pretend to options\n") % access_desc |
1148 |
- if portage.secpass < 1 and not need_superuser: |
1149 |
- portage_group_warning() |
1150 |
- else: |
1151 |
- sys.stderr.write(("emerge: %s access is required\n") \ |
1152 |
- % access_desc) |
1153 |
- if portage.secpass < 1 and not need_superuser: |
1154 |
- portage_group_warning() |
1155 |
- return 1 |
1156 |
- |
1157 |
- disable_emergelog = False |
1158 |
- for x in ("--pretend", "--fetchonly", "--fetch-all-uri"): |
1159 |
- if x in myopts: |
1160 |
- disable_emergelog = True |
1161 |
- break |
1162 |
- if myaction in ("search", "info"): |
1163 |
- disable_emergelog = True |
1164 |
- if disable_emergelog: |
1165 |
- """ Disable emergelog for everything except build or unmerge |
1166 |
- operations. This helps minimize parallel emerge.log entries that can |
1167 |
- confuse log parsers. We especially want it disabled during |
1168 |
- parallel-fetch, which uses --resume --fetchonly.""" |
1169 |
- global emergelog |
1170 |
- def emergelog(*pargs, **kargs): |
1171 |
- pass |
1172 |
- |
1173 |
- else: |
1174 |
- if 'EMERGE_LOG_DIR' in settings: |
1175 |
- try: |
1176 |
- # At least the parent needs to exist for the lock file. |
1177 |
- portage.util.ensure_dirs(settings['EMERGE_LOG_DIR']) |
1178 |
- except portage.exception.PortageException, e: |
1179 |
- writemsg_level("!!! Error creating directory for " + \ |
1180 |
- "EMERGE_LOG_DIR='%s':\n!!! %s\n" % \ |
1181 |
- (settings['EMERGE_LOG_DIR'], e), |
1182 |
- noiselevel=-1, level=logging.ERROR) |
1183 |
- else: |
1184 |
- global _emerge_log_dir |
1185 |
- _emerge_log_dir = settings['EMERGE_LOG_DIR'] |
1186 |
- |
1187 |
- if not "--pretend" in myopts: |
1188 |
- emergelog(xterm_titles, "Started emerge on: "+\ |
1189 |
- time.strftime("%b %d, %Y %H:%M:%S", time.localtime())) |
1190 |
- myelogstr="" |
1191 |
- if myopts: |
1192 |
- myelogstr=" ".join(myopts) |
1193 |
- if myaction: |
1194 |
- myelogstr+=" "+myaction |
1195 |
- if myfiles: |
1196 |
- myelogstr += " " + " ".join(oldargs) |
1197 |
- emergelog(xterm_titles, " *** emerge " + myelogstr) |
1198 |
- del oldargs |
1199 |
- |
1200 |
- def emergeexitsig(signum, frame): |
1201 |
- signal.signal(signal.SIGINT, signal.SIG_IGN) |
1202 |
- signal.signal(signal.SIGTERM, signal.SIG_IGN) |
1203 |
- portage.util.writemsg("\n\nExiting on signal %(signal)s\n" % {"signal":signum}) |
1204 |
- sys.exit(100+signum) |
1205 |
- signal.signal(signal.SIGINT, emergeexitsig) |
1206 |
- signal.signal(signal.SIGTERM, emergeexitsig) |
1207 |
- |
1208 |
- def emergeexit(): |
1209 |
- """This gets out final log message in before we quit.""" |
1210 |
- if "--pretend" not in myopts: |
1211 |
- emergelog(xterm_titles, " *** terminating.") |
1212 |
- if "notitles" not in settings.features: |
1213 |
- xtermTitleReset() |
1214 |
- portage.atexit_register(emergeexit) |
1215 |
- |
1216 |
- if myaction in ("config", "metadata", "regen", "sync"): |
1217 |
- if "--pretend" in myopts: |
1218 |
- sys.stderr.write(("emerge: The '%s' action does " + \ |
1219 |
- "not support '--pretend'.\n") % myaction) |
1220 |
- return 1 |
1221 |
- |
1222 |
- if "sync" == myaction: |
1223 |
- return action_sync(settings, trees, mtimedb, myopts, myaction) |
1224 |
- elif "metadata" == myaction: |
1225 |
- action_metadata(settings, portdb, myopts) |
1226 |
- elif myaction=="regen": |
1227 |
- validate_ebuild_environment(trees) |
1228 |
- return action_regen(settings, portdb, myopts.get("--jobs"), |
1229 |
- myopts.get("--load-average")) |
1230 |
- # HELP action |
1231 |
- elif "config"==myaction: |
1232 |
- validate_ebuild_environment(trees) |
1233 |
- action_config(settings, trees, myopts, myfiles) |
1234 |
- |
1235 |
- # SEARCH action |
1236 |
- elif "search"==myaction: |
1237 |
- validate_ebuild_environment(trees) |
1238 |
- action_search(trees[settings["ROOT"]]["root_config"], |
1239 |
- myopts, myfiles, spinner) |
1240 |
- |
1241 |
- elif myaction in ('clean', 'depclean', 'deselect', 'prune', 'unmerge'): |
1242 |
- validate_ebuild_environment(trees) |
1243 |
- rval = action_uninstall(settings, trees, mtimedb["ldpath"], |
1244 |
- myopts, myaction, myfiles, spinner) |
1245 |
- if not (myaction == 'deselect' or buildpkgonly or fetchonly or pretend): |
1246 |
- post_emerge(root_config, myopts, mtimedb, rval) |
1247 |
- return rval |
1248 |
- |
1249 |
- elif myaction == 'info': |
1250 |
- |
1251 |
- # Ensure atoms are valid before calling unmerge(). |
1252 |
- vardb = trees[settings["ROOT"]]["vartree"].dbapi |
1253 |
- valid_atoms = [] |
1254 |
- for x in myfiles: |
1255 |
- if is_valid_package_atom(x): |
1256 |
- try: |
1257 |
- valid_atoms.append( |
1258 |
- portage.dep_expand(x, mydb=vardb, settings=settings)) |
1259 |
- except portage.exception.AmbiguousPackageName, e: |
1260 |
- msg = "The short ebuild name \"" + x + \ |
1261 |
- "\" is ambiguous. Please specify " + \ |
1262 |
- "one of the following " + \ |
1263 |
- "fully-qualified ebuild names instead:" |
1264 |
- for line in textwrap.wrap(msg, 70): |
1265 |
- writemsg_level("!!! %s\n" % (line,), |
1266 |
- level=logging.ERROR, noiselevel=-1) |
1267 |
- for i in e[0]: |
1268 |
- writemsg_level(" %s\n" % colorize("INFORM", i), |
1269 |
- level=logging.ERROR, noiselevel=-1) |
1270 |
- writemsg_level("\n", level=logging.ERROR, noiselevel=-1) |
1271 |
- return 1 |
1272 |
- continue |
1273 |
- msg = [] |
1274 |
- msg.append("'%s' is not a valid package atom." % (x,)) |
1275 |
- msg.append("Please check ebuild(5) for full details.") |
1276 |
- writemsg_level("".join("!!! %s\n" % line for line in msg), |
1277 |
- level=logging.ERROR, noiselevel=-1) |
1278 |
- return 1 |
1279 |
- |
1280 |
- return action_info(settings, trees, myopts, valid_atoms) |
1281 |
- |
1282 |
- # "update", "system", or just process files: |
1283 |
- else: |
1284 |
- validate_ebuild_environment(trees) |
1285 |
- |
1286 |
- for x in myfiles: |
1287 |
- if x.startswith(SETPREFIX) or \ |
1288 |
- is_valid_package_atom(x): |
1289 |
- continue |
1290 |
- if x[:1] == os.sep: |
1291 |
- continue |
1292 |
- try: |
1293 |
- os.lstat(x) |
1294 |
- continue |
1295 |
- except OSError: |
1296 |
- pass |
1297 |
- msg = [] |
1298 |
- msg.append("'%s' is not a valid package atom." % (x,)) |
1299 |
- msg.append("Please check ebuild(5) for full details.") |
1300 |
- writemsg_level("".join("!!! %s\n" % line for line in msg), |
1301 |
- level=logging.ERROR, noiselevel=-1) |
1302 |
- return 1 |
1303 |
- |
1304 |
- if "--pretend" not in myopts: |
1305 |
- display_news_notification(root_config, myopts) |
1306 |
- retval = action_build(settings, trees, mtimedb, |
1307 |
- myopts, myaction, myfiles, spinner) |
1308 |
- root_config = trees[settings["ROOT"]]["root_config"] |
1309 |
- post_emerge(root_config, myopts, mtimedb, retval) |
1310 |
- |
1311 |
- return retval |
1312 |
|
1313 |
Copied: main/branches/prefix/pym/_emerge/main.py (from rev 13715, main/branches/prefix/pym/_emerge/__init__.py) |
1314 |
=================================================================== |
1315 |
--- main/branches/prefix/pym/_emerge/main.py (rev 0) |
1316 |
+++ main/branches/prefix/pym/_emerge/main.py 2009-06-28 13:36:35 UTC (rev 13719) |
1317 |
@@ -0,0 +1,1295 @@ |
1318 |
+# Copyright 1999-2009 Gentoo Foundation |
1319 |
+# Distributed under the terms of the GNU General Public License v2 |
1320 |
+# $Id$ |
1321 |
+ |
1322 |
+import logging |
1323 |
+import shlex |
1324 |
+import signal |
1325 |
+import sys |
1326 |
+import textwrap |
1327 |
+import os |
1328 |
+import platform |
1329 |
+ |
1330 |
+# Portage module path logic (Prefix way) |
1331 |
+# In principle we don't want to be dependant on the environment |
1332 |
+# (PYTHONPATH) and/or python hardcoded default search path. |
1333 |
+# (PYTHONPATH). Since Gentoo patches Python to include Portage's python |
1334 |
+# modules in the default search path, any Gentoo python interpreter is |
1335 |
+# an enemy for Portage once it is not installed in the path hardcoded |
1336 |
+# during Python compilation. This is the case when bootstrapping |
1337 |
+# Prefix Portage on a Gentoo Linux system, or when bootstrapping Prefix |
1338 |
+# Portage using another Prefix instance on the same system. For this |
1339 |
+# reason we ignore the entire search path, and allow a backdoor for |
1340 |
+# developers via the PORTAGE_PYTHONPATH variable. |
1341 |
+import os |
1342 |
+import sys |
1343 |
+if os.environ.__contains__("PORTAGE_PYTHONPATH"): |
1344 |
+ sys.path.insert(0, os.environ["PORTAGE_PYTHONPATH"]) |
1345 |
+else: |
1346 |
+ sys.path.insert(0, os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), "pym")) |
1347 |
+import portage |
1348 |
+ |
1349 |
+import _emerge.help |
1350 |
+import portage.xpak, commands, errno, re, time |
1351 |
+from portage.output import colorize, xtermTitleReset |
1352 |
+from portage.output import create_color_func |
1353 |
+good = create_color_func("GOOD") |
1354 |
+bad = create_color_func("BAD") |
1355 |
+ |
1356 |
+import portage.elog |
1357 |
+import portage.dep |
1358 |
+portage.dep._dep_check_strict = True |
1359 |
+import portage.util |
1360 |
+import portage.locks |
1361 |
+import portage.exception |
1362 |
+from portage.const import EPREFIX, BPREFIX, EPREFIX_LSTRIP |
1363 |
+from portage.data import secpass |
1364 |
+from portage.util import normalize_path as normpath |
1365 |
+from portage.util import writemsg, writemsg_level |
1366 |
+from portage.sets import SETPREFIX |
1367 |
+ |
1368 |
+from _emerge.actions import action_config, action_sync, action_metadata, \ |
1369 |
+ action_regen, action_search, action_uninstall, action_info, action_build, \ |
1370 |
+ adjust_config, chk_updated_cfg_files, display_missing_pkg_set, \ |
1371 |
+ display_news_notification, getportageversion, load_emerge_config |
1372 |
+from _emerge.emergelog import emergelog |
1373 |
+from _emerge._flush_elog_mod_echo import _flush_elog_mod_echo |
1374 |
+from _emerge.is_valid_package_atom import is_valid_package_atom |
1375 |
+from _emerge.stdout_spinner import stdout_spinner |
1376 |
+ |
1377 |
+options=[ |
1378 |
+"--ask", "--alphabetical", |
1379 |
+"--buildpkg", "--buildpkgonly", |
1380 |
+"--changelog", "--columns", |
1381 |
+"--complete-graph", |
1382 |
+"--debug", "--deep", |
1383 |
+"--digest", |
1384 |
+"--emptytree", |
1385 |
+"--fetchonly", "--fetch-all-uri", |
1386 |
+"--getbinpkg", "--getbinpkgonly", |
1387 |
+"--help", "--ignore-default-opts", |
1388 |
+"--keep-going", |
1389 |
+"--noconfmem", |
1390 |
+"--newuse", |
1391 |
+"--nodeps", "--noreplace", |
1392 |
+"--nospinner", "--oneshot", |
1393 |
+"--onlydeps", "--pretend", |
1394 |
+"--quiet", "--resume", |
1395 |
+"--searchdesc", "--selective", |
1396 |
+"--skipfirst", |
1397 |
+"--tree", |
1398 |
+"--update", |
1399 |
+"--usepkg", "--usepkgonly", |
1400 |
+"--verbose", |
1401 |
+] |
1402 |
+ |
1403 |
+shortmapping={ |
1404 |
+"1":"--oneshot", |
1405 |
+"a":"--ask", |
1406 |
+"b":"--buildpkg", "B":"--buildpkgonly", |
1407 |
+"c":"--clean", "C":"--unmerge", |
1408 |
+"d":"--debug", "D":"--deep", |
1409 |
+"e":"--emptytree", |
1410 |
+"f":"--fetchonly", "F":"--fetch-all-uri", |
1411 |
+"g":"--getbinpkg", "G":"--getbinpkgonly", |
1412 |
+"h":"--help", |
1413 |
+"k":"--usepkg", "K":"--usepkgonly", |
1414 |
+"l":"--changelog", |
1415 |
+"n":"--noreplace", "N":"--newuse", |
1416 |
+"o":"--onlydeps", "O":"--nodeps", |
1417 |
+"p":"--pretend", "P":"--prune", |
1418 |
+"q":"--quiet", |
1419 |
+"s":"--search", "S":"--searchdesc", |
1420 |
+"t":"--tree", |
1421 |
+"u":"--update", |
1422 |
+"v":"--verbose", "V":"--version" |
1423 |
+} |
1424 |
+ |
1425 |
+def chk_updated_info_files(root, infodirs, prev_mtimes, retval): |
1426 |
+ |
1427 |
+ if os.path.exists(EPREFIX + "/usr/bin/install-info"): |
1428 |
+ out = portage.output.EOutput() |
1429 |
+ regen_infodirs=[] |
1430 |
+ for z in infodirs: |
1431 |
+ if z=='': |
1432 |
+ continue |
1433 |
+ inforoot=normpath(root+z) |
1434 |
+ if os.path.isdir(inforoot): |
1435 |
+ infomtime = long(os.stat(inforoot).st_mtime) |
1436 |
+ if inforoot not in prev_mtimes or \ |
1437 |
+ prev_mtimes[inforoot] != infomtime: |
1438 |
+ regen_infodirs.append(inforoot) |
1439 |
+ |
1440 |
+ if not regen_infodirs: |
1441 |
+ portage.writemsg_stdout("\n") |
1442 |
+ out.einfo("GNU info directory index is up-to-date.") |
1443 |
+ else: |
1444 |
+ portage.writemsg_stdout("\n") |
1445 |
+ out.einfo("Regenerating GNU info directory index...") |
1446 |
+ |
1447 |
+ dir_extensions = ("", ".gz", ".bz2") |
1448 |
+ icount=0 |
1449 |
+ badcount=0 |
1450 |
+ errmsg = "" |
1451 |
+ for inforoot in regen_infodirs: |
1452 |
+ if inforoot=='': |
1453 |
+ continue |
1454 |
+ |
1455 |
+ if not os.path.isdir(inforoot) or \ |
1456 |
+ not os.access(inforoot, os.W_OK): |
1457 |
+ continue |
1458 |
+ |
1459 |
+ file_list = os.listdir(inforoot) |
1460 |
+ file_list.sort() |
1461 |
+ dir_file = os.path.join(inforoot, "dir") |
1462 |
+ moved_old_dir = False |
1463 |
+ processed_count = 0 |
1464 |
+ for x in file_list: |
1465 |
+ if x.startswith(".") or \ |
1466 |
+ os.path.isdir(os.path.join(inforoot, x)): |
1467 |
+ continue |
1468 |
+ if x.startswith("dir"): |
1469 |
+ skip = False |
1470 |
+ for ext in dir_extensions: |
1471 |
+ if x == "dir" + ext or \ |
1472 |
+ x == "dir" + ext + ".old": |
1473 |
+ skip = True |
1474 |
+ break |
1475 |
+ if skip: |
1476 |
+ continue |
1477 |
+ if processed_count == 0: |
1478 |
+ for ext in dir_extensions: |
1479 |
+ try: |
1480 |
+ os.rename(dir_file + ext, dir_file + ext + ".old") |
1481 |
+ moved_old_dir = True |
1482 |
+ except EnvironmentError, e: |
1483 |
+ if e.errno != errno.ENOENT: |
1484 |
+ raise |
1485 |
+ del e |
1486 |
+ processed_count += 1 |
1487 |
+ myso=commands.getstatusoutput("LANG=C LANGUAGE=C " + EPREFIX + "/usr/bin/install-info --dir-file="+inforoot+"/dir "+inforoot+"/"+x)[1] |
1488 |
+ existsstr="already exists, for file `" |
1489 |
+ if myso!="": |
1490 |
+ if re.search(existsstr,myso): |
1491 |
+ # Already exists... Don't increment the count for this. |
1492 |
+ pass |
1493 |
+ elif myso[:44]=="install-info: warning: no info dir entry in ": |
1494 |
+ # This info file doesn't contain a DIR-header: install-info produces this |
1495 |
+ # (harmless) warning (the --quiet switch doesn't seem to work). |
1496 |
+ # Don't increment the count for this. |
1497 |
+ pass |
1498 |
+ else: |
1499 |
+ badcount=badcount+1 |
1500 |
+ errmsg += myso + "\n" |
1501 |
+ icount=icount+1 |
1502 |
+ |
1503 |
+ if moved_old_dir and not os.path.exists(dir_file): |
1504 |
+ # We didn't generate a new dir file, so put the old file |
1505 |
+ # back where it was originally found. |
1506 |
+ for ext in dir_extensions: |
1507 |
+ try: |
1508 |
+ os.rename(dir_file + ext + ".old", dir_file + ext) |
1509 |
+ except EnvironmentError, e: |
1510 |
+ if e.errno != errno.ENOENT: |
1511 |
+ raise |
1512 |
+ del e |
1513 |
+ |
1514 |
+ # Clean dir.old cruft so that they don't prevent |
1515 |
+ # unmerge of otherwise empty directories. |
1516 |
+ for ext in dir_extensions: |
1517 |
+ try: |
1518 |
+ os.unlink(dir_file + ext + ".old") |
1519 |
+ except EnvironmentError, e: |
1520 |
+ if e.errno != errno.ENOENT: |
1521 |
+ raise |
1522 |
+ del e |
1523 |
+ |
1524 |
+ #update mtime so we can potentially avoid regenerating. |
1525 |
+ prev_mtimes[inforoot] = long(os.stat(inforoot).st_mtime) |
1526 |
+ |
1527 |
+ if badcount: |
1528 |
+ out.eerror("Processed %d info files; %d errors." % \ |
1529 |
+ (icount, badcount)) |
1530 |
+ writemsg_level(errmsg, level=logging.ERROR, noiselevel=-1) |
1531 |
+ else: |
1532 |
+ if icount > 0: |
1533 |
+ out.einfo("Processed %d info files." % (icount,)) |
1534 |
+ |
1535 |
+ |
1536 |
+def display_preserved_libs(vardbapi): |
1537 |
+ MAX_DISPLAY = 3 |
1538 |
+ |
1539 |
+ # Ensure the registry is consistent with existing files. |
1540 |
+ vardbapi.plib_registry.pruneNonExisting() |
1541 |
+ |
1542 |
+ if vardbapi.plib_registry.hasEntries(): |
1543 |
+ print |
1544 |
+ print colorize("WARN", "!!!") + " existing preserved libs:" |
1545 |
+ plibdata = vardbapi.plib_registry.getPreservedLibs() |
1546 |
+ linkmap = vardbapi.linkmap |
1547 |
+ consumer_map = {} |
1548 |
+ owners = {} |
1549 |
+ linkmap_broken = False |
1550 |
+ |
1551 |
+ try: |
1552 |
+ linkmap.rebuild() |
1553 |
+ except portage.exception.CommandNotFound, e: |
1554 |
+ writemsg_level("!!! Command Not Found: %s\n" % (e,), |
1555 |
+ level=logging.ERROR, noiselevel=-1) |
1556 |
+ del e |
1557 |
+ linkmap_broken = True |
1558 |
+ else: |
1559 |
+ search_for_owners = set() |
1560 |
+ for cpv in plibdata: |
1561 |
+ internal_plib_keys = set(linkmap._obj_key(f) \ |
1562 |
+ for f in plibdata[cpv]) |
1563 |
+ for f in plibdata[cpv]: |
1564 |
+ if f in consumer_map: |
1565 |
+ continue |
1566 |
+ consumers = [] |
1567 |
+ for c in linkmap.findConsumers(f): |
1568 |
+ # Filter out any consumers that are also preserved libs |
1569 |
+ # belonging to the same package as the provider. |
1570 |
+ if linkmap._obj_key(c) not in internal_plib_keys: |
1571 |
+ consumers.append(c) |
1572 |
+ consumers.sort() |
1573 |
+ consumer_map[f] = consumers |
1574 |
+ search_for_owners.update(consumers[:MAX_DISPLAY+1]) |
1575 |
+ |
1576 |
+ owners = vardbapi._owners.getFileOwnerMap(search_for_owners) |
1577 |
+ |
1578 |
+ for cpv in plibdata: |
1579 |
+ print colorize("WARN", ">>>") + " package: %s" % cpv |
1580 |
+ samefile_map = {} |
1581 |
+ for f in plibdata[cpv]: |
1582 |
+ obj_key = linkmap._obj_key(f) |
1583 |
+ alt_paths = samefile_map.get(obj_key) |
1584 |
+ if alt_paths is None: |
1585 |
+ alt_paths = set() |
1586 |
+ samefile_map[obj_key] = alt_paths |
1587 |
+ alt_paths.add(f) |
1588 |
+ |
1589 |
+ for alt_paths in samefile_map.itervalues(): |
1590 |
+ alt_paths = sorted(alt_paths) |
1591 |
+ for p in alt_paths: |
1592 |
+ print colorize("WARN", " * ") + " - %s" % (p,) |
1593 |
+ f = alt_paths[0] |
1594 |
+ consumers = consumer_map.get(f, []) |
1595 |
+ for c in consumers[:MAX_DISPLAY]: |
1596 |
+ print colorize("WARN", " * ") + " used by %s (%s)" % \ |
1597 |
+ (c, ", ".join(x.mycpv for x in owners.get(c, []))) |
1598 |
+ if len(consumers) == MAX_DISPLAY + 1: |
1599 |
+ print colorize("WARN", " * ") + " used by %s (%s)" % \ |
1600 |
+ (consumers[MAX_DISPLAY], ", ".join(x.mycpv \ |
1601 |
+ for x in owners.get(consumers[MAX_DISPLAY], []))) |
1602 |
+ elif len(consumers) > MAX_DISPLAY: |
1603 |
+ print colorize("WARN", " * ") + " used by %d other files" % (len(consumers) - MAX_DISPLAY) |
1604 |
+ print "Use " + colorize("GOOD", "emerge @preserved-rebuild") + " to rebuild packages using these libraries" |
1605 |
+ |
1606 |
+ |
1607 |
+def post_emerge(root_config, myopts, mtimedb, retval): |
1608 |
+ """ |
1609 |
+ Misc. things to run at the end of a merge session. |
1610 |
+ |
1611 |
+ Update Info Files |
1612 |
+ Update Config Files |
1613 |
+ Update News Items |
1614 |
+ Commit mtimeDB |
1615 |
+ Display preserved libs warnings |
1616 |
+ Exit Emerge |
1617 |
+ |
1618 |
+ @param trees: A dictionary mapping each ROOT to it's package databases |
1619 |
+ @type trees: dict |
1620 |
+ @param mtimedb: The mtimeDB to store data needed across merge invocations |
1621 |
+ @type mtimedb: MtimeDB class instance |
1622 |
+ @param retval: Emerge's return value |
1623 |
+ @type retval: Int |
1624 |
+ @rype: None |
1625 |
+ @returns: |
1626 |
+ 1. Calls sys.exit(retval) |
1627 |
+ """ |
1628 |
+ |
1629 |
+ target_root = root_config.root |
1630 |
+ trees = { target_root : root_config.trees } |
1631 |
+ vardbapi = trees[target_root]["vartree"].dbapi |
1632 |
+ settings = vardbapi.settings |
1633 |
+ info_mtimes = mtimedb["info"] |
1634 |
+ |
1635 |
+ # Load the most current variables from ${ROOT}/etc/profile.env |
1636 |
+ settings.unlock() |
1637 |
+ settings.reload() |
1638 |
+ settings.regenerate() |
1639 |
+ settings.lock() |
1640 |
+ |
1641 |
+ config_protect = settings.get("CONFIG_PROTECT","").split() |
1642 |
+ infodirs = settings.get("INFOPATH","").split(":") + \ |
1643 |
+ settings.get("INFODIR","").split(":") |
1644 |
+ |
1645 |
+ os.chdir("/") |
1646 |
+ |
1647 |
+ if retval == os.EX_OK: |
1648 |
+ exit_msg = " *** exiting successfully." |
1649 |
+ else: |
1650 |
+ exit_msg = " *** exiting unsuccessfully with status '%s'." % retval |
1651 |
+ emergelog("notitles" not in settings.features, exit_msg) |
1652 |
+ |
1653 |
+ _flush_elog_mod_echo() |
1654 |
+ |
1655 |
+ counter_hash = settings.get("PORTAGE_COUNTER_HASH") |
1656 |
+ if "--pretend" in myopts or (counter_hash is not None and \ |
1657 |
+ counter_hash == vardbapi._counter_hash()): |
1658 |
+ display_news_notification(root_config, myopts) |
1659 |
+ # If vdb state has not changed then there's nothing else to do. |
1660 |
+ sys.exit(retval) |
1661 |
+ |
1662 |
+ vdb_path = os.path.join(target_root, portage.VDB_PATH) |
1663 |
+ portage.util.ensure_dirs(vdb_path) |
1664 |
+ vdb_lock = None |
1665 |
+ if os.access(vdb_path, os.W_OK) and not "--pretend" in myopts: |
1666 |
+ vdb_lock = portage.locks.lockdir(vdb_path) |
1667 |
+ |
1668 |
+ if vdb_lock: |
1669 |
+ try: |
1670 |
+ if "noinfo" not in settings.features: |
1671 |
+ chk_updated_info_files(target_root + EPREFIX, |
1672 |
+ infodirs, info_mtimes, retval) |
1673 |
+ mtimedb.commit() |
1674 |
+ finally: |
1675 |
+ if vdb_lock: |
1676 |
+ portage.locks.unlockdir(vdb_lock) |
1677 |
+ |
1678 |
+ chk_updated_cfg_files(target_root + EPREFIX, config_protect) |
1679 |
+ |
1680 |
+ display_news_notification(root_config, myopts) |
1681 |
+ if retval in (None, os.EX_OK) or (not "--pretend" in myopts): |
1682 |
+ display_preserved_libs(vardbapi) |
1683 |
+ |
1684 |
+ sys.exit(retval) |
1685 |
+ |
1686 |
+ |
1687 |
+def multiple_actions(action1, action2): |
1688 |
+ sys.stderr.write("\n!!! Multiple actions requested... Please choose one only.\n") |
1689 |
+ sys.stderr.write("!!! '%s' or '%s'\n\n" % (action1, action2)) |
1690 |
+ sys.exit(1) |
1691 |
+ |
1692 |
+def insert_optional_args(args): |
1693 |
+ """ |
1694 |
+ Parse optional arguments and insert a value if one has |
1695 |
+ not been provided. This is done before feeding the args |
1696 |
+ to the optparse parser since that parser does not support |
1697 |
+ this feature natively. |
1698 |
+ """ |
1699 |
+ |
1700 |
+ new_args = [] |
1701 |
+ jobs_opts = ("-j", "--jobs") |
1702 |
+ default_arg_opts = { |
1703 |
+ '--deselect' : ('n',), |
1704 |
+ '--root-deps' : ('rdeps',), |
1705 |
+ } |
1706 |
+ arg_stack = args[:] |
1707 |
+ arg_stack.reverse() |
1708 |
+ while arg_stack: |
1709 |
+ arg = arg_stack.pop() |
1710 |
+ |
1711 |
+ default_arg_choices = default_arg_opts.get(arg) |
1712 |
+ if default_arg_choices is not None: |
1713 |
+ new_args.append(arg) |
1714 |
+ if arg_stack and arg_stack[-1] in default_arg_choices: |
1715 |
+ new_args.append(arg_stack.pop()) |
1716 |
+ else: |
1717 |
+ # insert default argument |
1718 |
+ new_args.append('True') |
1719 |
+ continue |
1720 |
+ |
1721 |
+ short_job_opt = bool("j" in arg and arg[:1] == "-" and arg[:2] != "--") |
1722 |
+ if not (short_job_opt or arg in jobs_opts): |
1723 |
+ new_args.append(arg) |
1724 |
+ continue |
1725 |
+ |
1726 |
+ # Insert an empty placeholder in order to |
1727 |
+ # satisfy the requirements of optparse. |
1728 |
+ |
1729 |
+ new_args.append("--jobs") |
1730 |
+ job_count = None |
1731 |
+ saved_opts = None |
1732 |
+ if short_job_opt and len(arg) > 2: |
1733 |
+ if arg[:2] == "-j": |
1734 |
+ try: |
1735 |
+ job_count = int(arg[2:]) |
1736 |
+ except ValueError: |
1737 |
+ saved_opts = arg[2:] |
1738 |
+ else: |
1739 |
+ job_count = "True" |
1740 |
+ saved_opts = arg[1:].replace("j", "") |
1741 |
+ |
1742 |
+ if job_count is None and arg_stack: |
1743 |
+ try: |
1744 |
+ job_count = int(arg_stack[-1]) |
1745 |
+ except ValueError: |
1746 |
+ pass |
1747 |
+ else: |
1748 |
+ # Discard the job count from the stack |
1749 |
+ # since we're consuming it here. |
1750 |
+ arg_stack.pop() |
1751 |
+ |
1752 |
+ if job_count is None: |
1753 |
+ # unlimited number of jobs |
1754 |
+ new_args.append("True") |
1755 |
+ else: |
1756 |
+ new_args.append(str(job_count)) |
1757 |
+ |
1758 |
+ if saved_opts is not None: |
1759 |
+ new_args.append("-" + saved_opts) |
1760 |
+ |
1761 |
+ return new_args |
1762 |
+ |
1763 |
+def parse_opts(tmpcmdline, silent=False): |
1764 |
+ myaction=None |
1765 |
+ myopts = {} |
1766 |
+ myfiles=[] |
1767 |
+ |
1768 |
+ global options, shortmapping |
1769 |
+ |
1770 |
+ actions = frozenset([ |
1771 |
+ "clean", "config", "depclean", |
1772 |
+ "info", "list-sets", "metadata", |
1773 |
+ "prune", "regen", "search", |
1774 |
+ "sync", "unmerge", "version", |
1775 |
+ ]) |
1776 |
+ |
1777 |
+ longopt_aliases = {"--cols":"--columns", "--skip-first":"--skipfirst"} |
1778 |
+ argument_options = { |
1779 |
+ "--config-root": { |
1780 |
+ "help":"specify the location for portage configuration files", |
1781 |
+ "action":"store" |
1782 |
+ }, |
1783 |
+ "--color": { |
1784 |
+ "help":"enable or disable color output", |
1785 |
+ "type":"choice", |
1786 |
+ "choices":("y", "n") |
1787 |
+ }, |
1788 |
+ |
1789 |
+ "--deselect": { |
1790 |
+ "help" : "remove atoms from the world file", |
1791 |
+ "type" : "choice", |
1792 |
+ "choices" : ("True", "n") |
1793 |
+ }, |
1794 |
+ |
1795 |
+ "--jobs": { |
1796 |
+ |
1797 |
+ "help" : "Specifies the number of packages to build " + \ |
1798 |
+ "simultaneously.", |
1799 |
+ |
1800 |
+ "action" : "store" |
1801 |
+ }, |
1802 |
+ |
1803 |
+ "--load-average": { |
1804 |
+ |
1805 |
+ "help" :"Specifies that no new builds should be started " + \ |
1806 |
+ "if there are other builds running and the load average " + \ |
1807 |
+ "is at least LOAD (a floating-point number).", |
1808 |
+ |
1809 |
+ "action" : "store" |
1810 |
+ }, |
1811 |
+ |
1812 |
+ "--with-bdeps": { |
1813 |
+ "help":"include unnecessary build time dependencies", |
1814 |
+ "type":"choice", |
1815 |
+ "choices":("y", "n") |
1816 |
+ }, |
1817 |
+ "--reinstall": { |
1818 |
+ "help":"specify conditions to trigger package reinstallation", |
1819 |
+ "type":"choice", |
1820 |
+ "choices":["changed-use"] |
1821 |
+ }, |
1822 |
+ "--root": { |
1823 |
+ "help" : "specify the target root filesystem for merging packages", |
1824 |
+ "action" : "store" |
1825 |
+ }, |
1826 |
+ |
1827 |
+ "--root-deps": { |
1828 |
+ "help" : "modify interpretation of depedencies", |
1829 |
+ "type" : "choice", |
1830 |
+ "choices" :("True", "rdeps") |
1831 |
+ }, |
1832 |
+ } |
1833 |
+ |
1834 |
+ from optparse import OptionParser |
1835 |
+ parser = OptionParser() |
1836 |
+ if parser.has_option("--help"): |
1837 |
+ parser.remove_option("--help") |
1838 |
+ |
1839 |
+ for action_opt in actions: |
1840 |
+ parser.add_option("--" + action_opt, action="store_true", |
1841 |
+ dest=action_opt.replace("-", "_"), default=False) |
1842 |
+ for myopt in options: |
1843 |
+ parser.add_option(myopt, action="store_true", |
1844 |
+ dest=myopt.lstrip("--").replace("-", "_"), default=False) |
1845 |
+ for shortopt, longopt in shortmapping.iteritems(): |
1846 |
+ parser.add_option("-" + shortopt, action="store_true", |
1847 |
+ dest=longopt.lstrip("--").replace("-", "_"), default=False) |
1848 |
+ for myalias, myopt in longopt_aliases.iteritems(): |
1849 |
+ parser.add_option(myalias, action="store_true", |
1850 |
+ dest=myopt.lstrip("--").replace("-", "_"), default=False) |
1851 |
+ |
1852 |
+ for myopt, kwargs in argument_options.iteritems(): |
1853 |
+ parser.add_option(myopt, |
1854 |
+ dest=myopt.lstrip("--").replace("-", "_"), **kwargs) |
1855 |
+ |
1856 |
+ tmpcmdline = insert_optional_args(tmpcmdline) |
1857 |
+ |
1858 |
+ myoptions, myargs = parser.parse_args(args=tmpcmdline) |
1859 |
+ |
1860 |
+ if myoptions.deselect == "True": |
1861 |
+ myoptions.deselect = True |
1862 |
+ |
1863 |
+ if myoptions.root_deps == "True": |
1864 |
+ myoptions.root_deps = True |
1865 |
+ |
1866 |
+ if myoptions.jobs: |
1867 |
+ jobs = None |
1868 |
+ if myoptions.jobs == "True": |
1869 |
+ jobs = True |
1870 |
+ else: |
1871 |
+ try: |
1872 |
+ jobs = int(myoptions.jobs) |
1873 |
+ except ValueError: |
1874 |
+ jobs = -1 |
1875 |
+ |
1876 |
+ if jobs is not True and \ |
1877 |
+ jobs < 1: |
1878 |
+ jobs = None |
1879 |
+ if not silent: |
1880 |
+ writemsg("!!! Invalid --jobs parameter: '%s'\n" % \ |
1881 |
+ (myoptions.jobs,), noiselevel=-1) |
1882 |
+ |
1883 |
+ myoptions.jobs = jobs |
1884 |
+ |
1885 |
+ if myoptions.load_average: |
1886 |
+ try: |
1887 |
+ load_average = float(myoptions.load_average) |
1888 |
+ except ValueError: |
1889 |
+ load_average = 0.0 |
1890 |
+ |
1891 |
+ if load_average <= 0.0: |
1892 |
+ load_average = None |
1893 |
+ if not silent: |
1894 |
+ writemsg("!!! Invalid --load-average parameter: '%s'\n" % \ |
1895 |
+ (myoptions.load_average,), noiselevel=-1) |
1896 |
+ |
1897 |
+ myoptions.load_average = load_average |
1898 |
+ |
1899 |
+ for myopt in options: |
1900 |
+ v = getattr(myoptions, myopt.lstrip("--").replace("-", "_")) |
1901 |
+ if v: |
1902 |
+ myopts[myopt] = True |
1903 |
+ |
1904 |
+ for myopt in argument_options: |
1905 |
+ v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"), None) |
1906 |
+ if v is not None: |
1907 |
+ myopts[myopt] = v |
1908 |
+ |
1909 |
+ if myoptions.searchdesc: |
1910 |
+ myoptions.search = True |
1911 |
+ |
1912 |
+ for action_opt in actions: |
1913 |
+ v = getattr(myoptions, action_opt.replace("-", "_")) |
1914 |
+ if v: |
1915 |
+ if myaction: |
1916 |
+ multiple_actions(myaction, action_opt) |
1917 |
+ sys.exit(1) |
1918 |
+ myaction = action_opt |
1919 |
+ |
1920 |
+ if myaction is None and myoptions.deselect is True: |
1921 |
+ myaction = 'deselect' |
1922 |
+ |
1923 |
+ myfiles += myargs |
1924 |
+ |
1925 |
+ return myaction, myopts, myfiles |
1926 |
+ |
1927 |
+def validate_ebuild_environment(trees): |
1928 |
+ for myroot in trees: |
1929 |
+ settings = trees[myroot]["vartree"].settings |
1930 |
+ settings.validate() |
1931 |
+ |
1932 |
+def apply_priorities(settings): |
1933 |
+ ionice(settings) |
1934 |
+ nice(settings) |
1935 |
+ |
1936 |
+def nice(settings): |
1937 |
+ try: |
1938 |
+ os.nice(int(settings.get("PORTAGE_NICENESS", "0"))) |
1939 |
+ except (OSError, ValueError), e: |
1940 |
+ out = portage.output.EOutput() |
1941 |
+ out.eerror("Failed to change nice value to '%s'" % \ |
1942 |
+ settings["PORTAGE_NICENESS"]) |
1943 |
+ out.eerror("%s\n" % str(e)) |
1944 |
+ |
1945 |
+def ionice(settings): |
1946 |
+ |
1947 |
+ ionice_cmd = settings.get("PORTAGE_IONICE_COMMAND") |
1948 |
+ if ionice_cmd: |
1949 |
+ ionice_cmd = shlex.split(ionice_cmd) |
1950 |
+ if not ionice_cmd: |
1951 |
+ return |
1952 |
+ |
1953 |
+ from portage.util import varexpand |
1954 |
+ variables = {"PID" : str(os.getpid())} |
1955 |
+ cmd = [varexpand(x, mydict=variables) for x in ionice_cmd] |
1956 |
+ |
1957 |
+ try: |
1958 |
+ rval = portage.process.spawn(cmd, env=os.environ) |
1959 |
+ except portage.exception.CommandNotFound: |
1960 |
+ # The OS kernel probably doesn't support ionice, |
1961 |
+ # so return silently. |
1962 |
+ return |
1963 |
+ |
1964 |
+ if rval != os.EX_OK: |
1965 |
+ out = portage.output.EOutput() |
1966 |
+ out.eerror("PORTAGE_IONICE_COMMAND returned %d" % (rval,)) |
1967 |
+ out.eerror("See the make.conf(5) man page for PORTAGE_IONICE_COMMAND usage instructions.") |
1968 |
+ |
1969 |
+def expand_set_arguments(myfiles, myaction, root_config): |
1970 |
+ retval = os.EX_OK |
1971 |
+ setconfig = root_config.setconfig |
1972 |
+ |
1973 |
+ sets = setconfig.getSets() |
1974 |
+ |
1975 |
+ # In order to know exactly which atoms/sets should be added to the |
1976 |
+ # world file, the depgraph performs set expansion later. It will get |
1977 |
+ # confused about where the atoms came from if it's not allowed to |
1978 |
+ # expand them itself. |
1979 |
+ do_not_expand = (None, ) |
1980 |
+ newargs = [] |
1981 |
+ for a in myfiles: |
1982 |
+ if a in ("system", "world"): |
1983 |
+ newargs.append(SETPREFIX+a) |
1984 |
+ else: |
1985 |
+ newargs.append(a) |
1986 |
+ myfiles = newargs |
1987 |
+ del newargs |
1988 |
+ newargs = [] |
1989 |
+ |
1990 |
+ # separators for set arguments |
1991 |
+ ARG_START = "{" |
1992 |
+ ARG_END = "}" |
1993 |
+ |
1994 |
+ # WARNING: all operators must be of equal length |
1995 |
+ IS_OPERATOR = "/@" |
1996 |
+ DIFF_OPERATOR = "-@" |
1997 |
+ UNION_OPERATOR = "+@" |
1998 |
+ |
1999 |
+ for i in range(0, len(myfiles)): |
2000 |
+ if myfiles[i].startswith(SETPREFIX): |
2001 |
+ start = 0 |
2002 |
+ end = 0 |
2003 |
+ x = myfiles[i][len(SETPREFIX):] |
2004 |
+ newset = "" |
2005 |
+ while x: |
2006 |
+ start = x.find(ARG_START) |
2007 |
+ end = x.find(ARG_END) |
2008 |
+ if start > 0 and start < end: |
2009 |
+ namepart = x[:start] |
2010 |
+ argpart = x[start+1:end] |
2011 |
+ |
2012 |
+ # TODO: implement proper quoting |
2013 |
+ args = argpart.split(",") |
2014 |
+ options = {} |
2015 |
+ for a in args: |
2016 |
+ if "=" in a: |
2017 |
+ k, v = a.split("=", 1) |
2018 |
+ options[k] = v |
2019 |
+ else: |
2020 |
+ options[a] = "True" |
2021 |
+ setconfig.update(namepart, options) |
2022 |
+ newset += (x[:start-len(namepart)]+namepart) |
2023 |
+ x = x[end+len(ARG_END):] |
2024 |
+ else: |
2025 |
+ newset += x |
2026 |
+ x = "" |
2027 |
+ myfiles[i] = SETPREFIX+newset |
2028 |
+ |
2029 |
+ sets = setconfig.getSets() |
2030 |
+ |
2031 |
+ # display errors that occured while loading the SetConfig instance |
2032 |
+ for e in setconfig.errors: |
2033 |
+ print colorize("BAD", "Error during set creation: %s" % e) |
2034 |
+ |
2035 |
+ # emerge relies on the existance of sets with names "world" and "system" |
2036 |
+ required_sets = ("world", "system") |
2037 |
+ missing_sets = [] |
2038 |
+ |
2039 |
+ for s in required_sets: |
2040 |
+ if s not in sets: |
2041 |
+ missing_sets.append(s) |
2042 |
+ if missing_sets: |
2043 |
+ if len(missing_sets) > 2: |
2044 |
+ missing_sets_str = ", ".join('"%s"' % s for s in missing_sets[:-1]) |
2045 |
+ missing_sets_str += ', and "%s"' % missing_sets[-1] |
2046 |
+ elif len(missing_sets) == 2: |
2047 |
+ missing_sets_str = '"%s" and "%s"' % tuple(missing_sets) |
2048 |
+ else: |
2049 |
+ missing_sets_str = '"%s"' % missing_sets[-1] |
2050 |
+ msg = ["emerge: incomplete set configuration, " + \ |
2051 |
+ "missing set(s): %s" % missing_sets_str] |
2052 |
+ if sets: |
2053 |
+ msg.append(" sets defined: %s" % ", ".join(sets)) |
2054 |
+ msg.append(" This usually means that '%s'" % \ |
2055 |
+ (os.path.join(portage.const.GLOBAL_CONFIG_PATH, "sets.conf"),)) |
2056 |
+ msg.append(" is missing or corrupt.") |
2057 |
+ for line in msg: |
2058 |
+ writemsg_level(line + "\n", level=logging.ERROR, noiselevel=-1) |
2059 |
+ return (None, 1) |
2060 |
+ unmerge_actions = ("unmerge", "prune", "clean", "depclean") |
2061 |
+ |
2062 |
+ for a in myfiles: |
2063 |
+ if a.startswith(SETPREFIX): |
2064 |
+ # support simple set operations (intersection, difference and union) |
2065 |
+ # on the commandline. Expressions are evaluated strictly left-to-right |
2066 |
+ if IS_OPERATOR in a or DIFF_OPERATOR in a or UNION_OPERATOR in a: |
2067 |
+ expression = a[len(SETPREFIX):] |
2068 |
+ expr_sets = [] |
2069 |
+ expr_ops = [] |
2070 |
+ while IS_OPERATOR in expression or DIFF_OPERATOR in expression or UNION_OPERATOR in expression: |
2071 |
+ is_pos = expression.rfind(IS_OPERATOR) |
2072 |
+ diff_pos = expression.rfind(DIFF_OPERATOR) |
2073 |
+ union_pos = expression.rfind(UNION_OPERATOR) |
2074 |
+ op_pos = max(is_pos, diff_pos, union_pos) |
2075 |
+ s1 = expression[:op_pos] |
2076 |
+ s2 = expression[op_pos+len(IS_OPERATOR):] |
2077 |
+ op = expression[op_pos:op_pos+len(IS_OPERATOR)] |
2078 |
+ if not s2 in sets: |
2079 |
+ display_missing_pkg_set(root_config, s2) |
2080 |
+ return (None, 1) |
2081 |
+ expr_sets.insert(0, s2) |
2082 |
+ expr_ops.insert(0, op) |
2083 |
+ expression = s1 |
2084 |
+ if not expression in sets: |
2085 |
+ display_missing_pkg_set(root_config, expression) |
2086 |
+ return (None, 1) |
2087 |
+ expr_sets.insert(0, expression) |
2088 |
+ result = set(setconfig.getSetAtoms(expression)) |
2089 |
+ for i in range(0, len(expr_ops)): |
2090 |
+ s2 = setconfig.getSetAtoms(expr_sets[i+1]) |
2091 |
+ if expr_ops[i] == IS_OPERATOR: |
2092 |
+ result.intersection_update(s2) |
2093 |
+ elif expr_ops[i] == DIFF_OPERATOR: |
2094 |
+ result.difference_update(s2) |
2095 |
+ elif expr_ops[i] == UNION_OPERATOR: |
2096 |
+ result.update(s2) |
2097 |
+ else: |
2098 |
+ raise NotImplementedError("unknown set operator %s" % expr_ops[i]) |
2099 |
+ newargs.extend(result) |
2100 |
+ else: |
2101 |
+ s = a[len(SETPREFIX):] |
2102 |
+ if s not in sets: |
2103 |
+ display_missing_pkg_set(root_config, s) |
2104 |
+ return (None, 1) |
2105 |
+ setconfig.active.append(s) |
2106 |
+ try: |
2107 |
+ set_atoms = setconfig.getSetAtoms(s) |
2108 |
+ except portage.exception.PackageSetNotFound, e: |
2109 |
+ writemsg_level(("emerge: the given set '%s' " + \ |
2110 |
+ "contains a non-existent set named '%s'.\n") % \ |
2111 |
+ (s, e), level=logging.ERROR, noiselevel=-1) |
2112 |
+ return (None, 1) |
2113 |
+ if myaction in unmerge_actions and \ |
2114 |
+ not sets[s].supportsOperation("unmerge"): |
2115 |
+ sys.stderr.write("emerge: the given set '%s' does " % s + \ |
2116 |
+ "not support unmerge operations\n") |
2117 |
+ retval = 1 |
2118 |
+ elif not set_atoms: |
2119 |
+ print "emerge: '%s' is an empty set" % s |
2120 |
+ elif myaction not in do_not_expand: |
2121 |
+ newargs.extend(set_atoms) |
2122 |
+ else: |
2123 |
+ newargs.append(SETPREFIX+s) |
2124 |
+ for e in sets[s].errors: |
2125 |
+ print e |
2126 |
+ else: |
2127 |
+ newargs.append(a) |
2128 |
+ return (newargs, retval) |
2129 |
+ |
2130 |
+def repo_name_check(trees): |
2131 |
+ missing_repo_names = set() |
2132 |
+ for root, root_trees in trees.iteritems(): |
2133 |
+ if "porttree" in root_trees: |
2134 |
+ portdb = root_trees["porttree"].dbapi |
2135 |
+ missing_repo_names.update(portdb.porttrees) |
2136 |
+ repos = portdb.getRepositories() |
2137 |
+ for r in repos: |
2138 |
+ missing_repo_names.discard(portdb.getRepositoryPath(r)) |
2139 |
+ if portdb.porttree_root in missing_repo_names and \ |
2140 |
+ not os.path.exists(os.path.join( |
2141 |
+ portdb.porttree_root, "profiles")): |
2142 |
+ # This is normal if $PORTDIR happens to be empty, |
2143 |
+ # so don't warn about it. |
2144 |
+ missing_repo_names.remove(portdb.porttree_root) |
2145 |
+ |
2146 |
+ if missing_repo_names: |
2147 |
+ msg = [] |
2148 |
+ msg.append("WARNING: One or more repositories " + \ |
2149 |
+ "have missing repo_name entries:") |
2150 |
+ msg.append("") |
2151 |
+ for p in missing_repo_names: |
2152 |
+ msg.append("\t%s/profiles/repo_name" % (p,)) |
2153 |
+ msg.append("") |
2154 |
+ msg.extend(textwrap.wrap("NOTE: Each repo_name entry " + \ |
2155 |
+ "should be a plain text file containing a unique " + \ |
2156 |
+ "name for the repository on the first line.", 70)) |
2157 |
+ writemsg_level("".join("%s\n" % l for l in msg), |
2158 |
+ level=logging.WARNING, noiselevel=-1) |
2159 |
+ |
2160 |
+ return bool(missing_repo_names) |
2161 |
+ |
2162 |
+def repo_name_duplicate_check(trees): |
2163 |
+ ignored_repos = {} |
2164 |
+ for root, root_trees in trees.iteritems(): |
2165 |
+ if 'porttree' in root_trees: |
2166 |
+ portdb = root_trees['porttree'].dbapi |
2167 |
+ if portdb.mysettings.get('PORTAGE_REPO_DUPLICATE_WARN') != '0': |
2168 |
+ for repo_name, paths in portdb._ignored_repos: |
2169 |
+ k = (root, repo_name, portdb.getRepositoryPath(repo_name)) |
2170 |
+ ignored_repos.setdefault(k, []).extend(paths) |
2171 |
+ |
2172 |
+ if ignored_repos: |
2173 |
+ msg = [] |
2174 |
+ msg.append('WARNING: One or more repositories ' + \ |
2175 |
+ 'have been ignored due to duplicate') |
2176 |
+ msg.append(' profiles/repo_name entries:') |
2177 |
+ msg.append('') |
2178 |
+ for k in sorted(ignored_repos): |
2179 |
+ msg.append(' %s overrides' % (k,)) |
2180 |
+ for path in ignored_repos[k]: |
2181 |
+ msg.append(' %s' % (path,)) |
2182 |
+ msg.append('') |
2183 |
+ msg.extend(' ' + x for x in textwrap.wrap( |
2184 |
+ "All profiles/repo_name entries must be unique in order " + \ |
2185 |
+ "to avoid having duplicates ignored. " + \ |
2186 |
+ "Set PORTAGE_REPO_DUPLICATE_WARN=\"0\" in " + \ |
2187 |
+ "/etc/make.conf if you would like to disable this warning.")) |
2188 |
+ writemsg_level(''.join('%s\n' % l for l in msg), |
2189 |
+ level=logging.WARNING, noiselevel=-1) |
2190 |
+ |
2191 |
+ return bool(ignored_repos) |
2192 |
+ |
2193 |
+def config_protect_check(trees): |
2194 |
+ for root, root_trees in trees.iteritems(): |
2195 |
+ if not root_trees["root_config"].settings.get("CONFIG_PROTECT"): |
2196 |
+ msg = "!!! CONFIG_PROTECT is empty" |
2197 |
+ if root != "/": |
2198 |
+ msg += " for '%s'" % root |
2199 |
+ writemsg_level(msg, level=logging.WARN, noiselevel=-1) |
2200 |
+ |
2201 |
+def profile_check(trees, myaction, myopts): |
2202 |
+ if myaction in ("info", "sync"): |
2203 |
+ return os.EX_OK |
2204 |
+ elif "--version" in myopts or "--help" in myopts: |
2205 |
+ return os.EX_OK |
2206 |
+ for root, root_trees in trees.iteritems(): |
2207 |
+ if root_trees["root_config"].settings.profiles: |
2208 |
+ continue |
2209 |
+ # generate some profile related warning messages |
2210 |
+ validate_ebuild_environment(trees) |
2211 |
+ msg = "If you have just changed your profile configuration, you " + \ |
2212 |
+ "should revert back to the previous configuration. Due to " + \ |
2213 |
+ "your current profile being invalid, allowed actions are " + \ |
2214 |
+ "limited to --help, --info, --sync, and --version." |
2215 |
+ writemsg_level("".join("!!! %s\n" % l for l in textwrap.wrap(msg, 70)), |
2216 |
+ level=logging.ERROR, noiselevel=-1) |
2217 |
+ return 1 |
2218 |
+ return os.EX_OK |
2219 |
+ |
2220 |
+def emerge_main(): |
2221 |
+ global portage # NFC why this is necessary now - genone |
2222 |
+ portage._disable_legacy_globals() |
2223 |
+ # Disable color until we're sure that it should be enabled (after |
2224 |
+ # EMERGE_DEFAULT_OPTS has been parsed). |
2225 |
+ portage.output.havecolor = 0 |
2226 |
+ # This first pass is just for options that need to be known as early as |
2227 |
+ # possible, such as --config-root. They will be parsed again later, |
2228 |
+ # together with EMERGE_DEFAULT_OPTS (which may vary depending on the |
2229 |
+ # the value of --config-root). |
2230 |
+ myaction, myopts, myfiles = parse_opts(sys.argv[1:], silent=True) |
2231 |
+ if "--debug" in myopts: |
2232 |
+ os.environ["PORTAGE_DEBUG"] = "1" |
2233 |
+ if "--config-root" in myopts: |
2234 |
+ os.environ["PORTAGE_CONFIGROOT"] = myopts["--config-root"] |
2235 |
+ if "--root" in myopts: |
2236 |
+ os.environ["ROOT"] = myopts["--root"] |
2237 |
+ |
2238 |
+ # Portage needs to ensure a sane umask for the files it creates. |
2239 |
+ os.umask(022) |
2240 |
+ settings, trees, mtimedb = load_emerge_config() |
2241 |
+ portdb = trees[settings["ROOT"]]["porttree"].dbapi |
2242 |
+ rval = profile_check(trees, myaction, myopts) |
2243 |
+ if rval != os.EX_OK: |
2244 |
+ return rval |
2245 |
+ |
2246 |
+ if portage._global_updates(trees, mtimedb["updates"]): |
2247 |
+ mtimedb.commit() |
2248 |
+ # Reload the whole config from scratch. |
2249 |
+ settings, trees, mtimedb = load_emerge_config(trees=trees) |
2250 |
+ portdb = trees[settings["ROOT"]]["porttree"].dbapi |
2251 |
+ |
2252 |
+ xterm_titles = "notitles" not in settings.features |
2253 |
+ |
2254 |
+ tmpcmdline = [] |
2255 |
+ if "--ignore-default-opts" not in myopts: |
2256 |
+ tmpcmdline.extend(settings["EMERGE_DEFAULT_OPTS"].split()) |
2257 |
+ tmpcmdline.extend(sys.argv[1:]) |
2258 |
+ myaction, myopts, myfiles = parse_opts(tmpcmdline) |
2259 |
+ |
2260 |
+ if "--digest" in myopts: |
2261 |
+ os.environ["FEATURES"] = os.environ.get("FEATURES","") + " digest" |
2262 |
+ # Reload the whole config from scratch so that the portdbapi internal |
2263 |
+ # config is updated with new FEATURES. |
2264 |
+ settings, trees, mtimedb = load_emerge_config(trees=trees) |
2265 |
+ portdb = trees[settings["ROOT"]]["porttree"].dbapi |
2266 |
+ |
2267 |
+ for myroot in trees: |
2268 |
+ mysettings = trees[myroot]["vartree"].settings |
2269 |
+ mysettings.unlock() |
2270 |
+ adjust_config(myopts, mysettings) |
2271 |
+ if '--pretend' not in myopts and myaction in \ |
2272 |
+ (None, 'clean', 'depclean', 'prune', 'unmerge'): |
2273 |
+ mysettings["PORTAGE_COUNTER_HASH"] = \ |
2274 |
+ trees[myroot]["vartree"].dbapi._counter_hash() |
2275 |
+ mysettings.backup_changes("PORTAGE_COUNTER_HASH") |
2276 |
+ mysettings.lock() |
2277 |
+ del myroot, mysettings |
2278 |
+ |
2279 |
+ apply_priorities(settings) |
2280 |
+ |
2281 |
+ spinner = stdout_spinner() |
2282 |
+ if "candy" in settings.features: |
2283 |
+ spinner.update = spinner.update_scroll |
2284 |
+ |
2285 |
+ if "--quiet" not in myopts: |
2286 |
+ portage.deprecated_profile_check(settings=settings) |
2287 |
+ repo_name_check(trees) |
2288 |
+ repo_name_duplicate_check(trees) |
2289 |
+ config_protect_check(trees) |
2290 |
+ |
2291 |
+ for mytrees in trees.itervalues(): |
2292 |
+ mydb = mytrees["porttree"].dbapi |
2293 |
+ # Freeze the portdbapi for performance (memoize all xmatch results). |
2294 |
+ mydb.freeze() |
2295 |
+ del mytrees, mydb |
2296 |
+ |
2297 |
+ if "moo" in myfiles: |
2298 |
+ print """ |
2299 |
+ |
2300 |
+ Larry loves Gentoo (""" + platform.system() + """) |
2301 |
+ |
2302 |
+ _______________________ |
2303 |
+< Have you mooed today? > |
2304 |
+ ----------------------- |
2305 |
+ \ ^__^ |
2306 |
+ \ (oo)\_______ |
2307 |
+ (__)\ )\/\ |
2308 |
+ ||----w | |
2309 |
+ || || |
2310 |
+ |
2311 |
+""" |
2312 |
+ |
2313 |
+ for x in myfiles: |
2314 |
+ ext = os.path.splitext(x)[1] |
2315 |
+ if (ext == ".ebuild" or ext == ".tbz2") and os.path.exists(os.path.abspath(x)): |
2316 |
+ print colorize("BAD", "\n*** emerging by path is broken and may not always work!!!\n") |
2317 |
+ break |
2318 |
+ |
2319 |
+ root_config = trees[settings["ROOT"]]["root_config"] |
2320 |
+ if myaction == "list-sets": |
2321 |
+ sys.stdout.write("".join("%s\n" % s for s in sorted(root_config.sets))) |
2322 |
+ sys.stdout.flush() |
2323 |
+ return os.EX_OK |
2324 |
+ |
2325 |
+ # only expand sets for actions taking package arguments |
2326 |
+ oldargs = myfiles[:] |
2327 |
+ if myaction in ("clean", "config", "depclean", "info", "prune", "unmerge", None): |
2328 |
+ myfiles, retval = expand_set_arguments(myfiles, myaction, root_config) |
2329 |
+ if retval != os.EX_OK: |
2330 |
+ return retval |
2331 |
+ |
2332 |
+ # Need to handle empty sets specially, otherwise emerge will react |
2333 |
+ # with the help message for empty argument lists |
2334 |
+ if oldargs and not myfiles: |
2335 |
+ print "emerge: no targets left after set expansion" |
2336 |
+ return 0 |
2337 |
+ |
2338 |
+ if ("--tree" in myopts) and ("--columns" in myopts): |
2339 |
+ print "emerge: can't specify both of \"--tree\" and \"--columns\"." |
2340 |
+ return 1 |
2341 |
+ |
2342 |
+ if ("--quiet" in myopts): |
2343 |
+ spinner.update = spinner.update_quiet |
2344 |
+ portage.util.noiselimit = -1 |
2345 |
+ |
2346 |
+ # Always create packages if FEATURES=buildpkg |
2347 |
+ # Imply --buildpkg if --buildpkgonly |
2348 |
+ if ("buildpkg" in settings.features) or ("--buildpkgonly" in myopts): |
2349 |
+ if "--buildpkg" not in myopts: |
2350 |
+ myopts["--buildpkg"] = True |
2351 |
+ |
2352 |
+ # Always try and fetch binary packages if FEATURES=getbinpkg |
2353 |
+ if ("getbinpkg" in settings.features): |
2354 |
+ myopts["--getbinpkg"] = True |
2355 |
+ |
2356 |
+ if "--buildpkgonly" in myopts: |
2357 |
+ # --buildpkgonly will not merge anything, so |
2358 |
+ # it cancels all binary package options. |
2359 |
+ for opt in ("--getbinpkg", "--getbinpkgonly", |
2360 |
+ "--usepkg", "--usepkgonly"): |
2361 |
+ myopts.pop(opt, None) |
2362 |
+ |
2363 |
+ if "--fetch-all-uri" in myopts: |
2364 |
+ myopts["--fetchonly"] = True |
2365 |
+ |
2366 |
+ if "--skipfirst" in myopts and "--resume" not in myopts: |
2367 |
+ myopts["--resume"] = True |
2368 |
+ |
2369 |
+ if ("--getbinpkgonly" in myopts) and not ("--usepkgonly" in myopts): |
2370 |
+ myopts["--usepkgonly"] = True |
2371 |
+ |
2372 |
+ if ("--getbinpkgonly" in myopts) and not ("--getbinpkg" in myopts): |
2373 |
+ myopts["--getbinpkg"] = True |
2374 |
+ |
2375 |
+ if ("--getbinpkg" in myopts) and not ("--usepkg" in myopts): |
2376 |
+ myopts["--usepkg"] = True |
2377 |
+ |
2378 |
+ # Also allow -K to apply --usepkg/-k |
2379 |
+ if ("--usepkgonly" in myopts) and not ("--usepkg" in myopts): |
2380 |
+ myopts["--usepkg"] = True |
2381 |
+ |
2382 |
+ # Allow -p to remove --ask |
2383 |
+ if "--pretend" in myopts: |
2384 |
+ myopts.pop("--ask", None) |
2385 |
+ |
2386 |
+ # forbid --ask when not in a terminal |
2387 |
+ # note: this breaks `emerge --ask | tee logfile`, but that doesn't work anyway. |
2388 |
+ if ("--ask" in myopts) and (not sys.stdin.isatty()): |
2389 |
+ portage.writemsg("!!! \"--ask\" should only be used in a terminal. Exiting.\n", |
2390 |
+ noiselevel=-1) |
2391 |
+ return 1 |
2392 |
+ |
2393 |
+ if settings.get("PORTAGE_DEBUG", "") == "1": |
2394 |
+ spinner.update = spinner.update_quiet |
2395 |
+ portage.debug=1 |
2396 |
+ if "python-trace" in settings.features: |
2397 |
+ import portage.debug |
2398 |
+ portage.debug.set_trace(True) |
2399 |
+ |
2400 |
+ if not ("--quiet" in myopts): |
2401 |
+ if not sys.stdout.isatty() or ("--nospinner" in myopts): |
2402 |
+ spinner.update = spinner.update_basic |
2403 |
+ |
2404 |
+ if myaction == 'version': |
2405 |
+ print getportageversion(settings["PORTDIR"], settings["ROOT"], |
2406 |
+ settings.profile_path, settings["CHOST"], |
2407 |
+ trees[settings["ROOT"]]["vartree"].dbapi) |
2408 |
+ return 0 |
2409 |
+ elif "--help" in myopts: |
2410 |
+ _emerge.help.help(myaction, myopts, portage.output.havecolor) |
2411 |
+ return 0 |
2412 |
+ |
2413 |
+ if "--debug" in myopts: |
2414 |
+ print "myaction", myaction |
2415 |
+ print "myopts", myopts |
2416 |
+ |
2417 |
+ if not myaction and not myfiles and "--resume" not in myopts: |
2418 |
+ _emerge.help.help(myaction, myopts, portage.output.havecolor) |
2419 |
+ return 1 |
2420 |
+ |
2421 |
+ pretend = "--pretend" in myopts |
2422 |
+ fetchonly = "--fetchonly" in myopts or "--fetch-all-uri" in myopts |
2423 |
+ buildpkgonly = "--buildpkgonly" in myopts |
2424 |
+ |
2425 |
+ # check if root user is the current user for the actions where emerge needs this |
2426 |
+ if portage.secpass < 2: |
2427 |
+ # We've already allowed "--version" and "--help" above. |
2428 |
+ if "--pretend" not in myopts and myaction not in ("search","info"): |
2429 |
+ need_superuser = myaction in ('clean', 'depclean', 'deselect', |
2430 |
+ 'prune', 'unmerge') or not \ |
2431 |
+ (fetchonly or \ |
2432 |
+ (buildpkgonly and secpass >= 1) or \ |
2433 |
+ myaction in ("metadata", "regen") or \ |
2434 |
+ (myaction == "sync" and os.access(settings["PORTDIR"], os.W_OK))) |
2435 |
+ if portage.secpass < 1 or \ |
2436 |
+ need_superuser: |
2437 |
+ if need_superuser: |
2438 |
+ access_desc = "superuser" |
2439 |
+ else: |
2440 |
+ access_desc = "portage group" |
2441 |
+ # Always show portage_group_warning() when only portage group |
2442 |
+ # access is required but the user is not in the portage group. |
2443 |
+ from portage.data import portage_group_warning |
2444 |
+ if "--ask" in myopts: |
2445 |
+ myopts["--pretend"] = True |
2446 |
+ del myopts["--ask"] |
2447 |
+ print ("%s access is required... " + \ |
2448 |
+ "adding --pretend to options\n") % access_desc |
2449 |
+ if portage.secpass < 1 and not need_superuser: |
2450 |
+ portage_group_warning() |
2451 |
+ else: |
2452 |
+ sys.stderr.write(("emerge: %s access is required\n") \ |
2453 |
+ % access_desc) |
2454 |
+ if portage.secpass < 1 and not need_superuser: |
2455 |
+ portage_group_warning() |
2456 |
+ return 1 |
2457 |
+ |
2458 |
+ disable_emergelog = False |
2459 |
+ for x in ("--pretend", "--fetchonly", "--fetch-all-uri"): |
2460 |
+ if x in myopts: |
2461 |
+ disable_emergelog = True |
2462 |
+ break |
2463 |
+ if myaction in ("search", "info"): |
2464 |
+ disable_emergelog = True |
2465 |
+ if disable_emergelog: |
2466 |
+ """ Disable emergelog for everything except build or unmerge |
2467 |
+ operations. This helps minimize parallel emerge.log entries that can |
2468 |
+ confuse log parsers. We especially want it disabled during |
2469 |
+ parallel-fetch, which uses --resume --fetchonly.""" |
2470 |
+ global emergelog |
2471 |
+ def emergelog(*pargs, **kargs): |
2472 |
+ pass |
2473 |
+ |
2474 |
+ else: |
2475 |
+ if 'EMERGE_LOG_DIR' in settings: |
2476 |
+ try: |
2477 |
+ # At least the parent needs to exist for the lock file. |
2478 |
+ portage.util.ensure_dirs(settings['EMERGE_LOG_DIR']) |
2479 |
+ except portage.exception.PortageException, e: |
2480 |
+ writemsg_level("!!! Error creating directory for " + \ |
2481 |
+ "EMERGE_LOG_DIR='%s':\n!!! %s\n" % \ |
2482 |
+ (settings['EMERGE_LOG_DIR'], e), |
2483 |
+ noiselevel=-1, level=logging.ERROR) |
2484 |
+ else: |
2485 |
+ global _emerge_log_dir |
2486 |
+ _emerge_log_dir = settings['EMERGE_LOG_DIR'] |
2487 |
+ |
2488 |
+ if not "--pretend" in myopts: |
2489 |
+ emergelog(xterm_titles, "Started emerge on: "+\ |
2490 |
+ time.strftime("%b %d, %Y %H:%M:%S", time.localtime())) |
2491 |
+ myelogstr="" |
2492 |
+ if myopts: |
2493 |
+ myelogstr=" ".join(myopts) |
2494 |
+ if myaction: |
2495 |
+ myelogstr+=" "+myaction |
2496 |
+ if myfiles: |
2497 |
+ myelogstr += " " + " ".join(oldargs) |
2498 |
+ emergelog(xterm_titles, " *** emerge " + myelogstr) |
2499 |
+ del oldargs |
2500 |
+ |
2501 |
+ def emergeexitsig(signum, frame): |
2502 |
+ signal.signal(signal.SIGINT, signal.SIG_IGN) |
2503 |
+ signal.signal(signal.SIGTERM, signal.SIG_IGN) |
2504 |
+ portage.util.writemsg("\n\nExiting on signal %(signal)s\n" % {"signal":signum}) |
2505 |
+ sys.exit(100+signum) |
2506 |
+ signal.signal(signal.SIGINT, emergeexitsig) |
2507 |
+ signal.signal(signal.SIGTERM, emergeexitsig) |
2508 |
+ |
2509 |
+ def emergeexit(): |
2510 |
+ """This gets out final log message in before we quit.""" |
2511 |
+ if "--pretend" not in myopts: |
2512 |
+ emergelog(xterm_titles, " *** terminating.") |
2513 |
+ if "notitles" not in settings.features: |
2514 |
+ xtermTitleReset() |
2515 |
+ portage.atexit_register(emergeexit) |
2516 |
+ |
2517 |
+ if myaction in ("config", "metadata", "regen", "sync"): |
2518 |
+ if "--pretend" in myopts: |
2519 |
+ sys.stderr.write(("emerge: The '%s' action does " + \ |
2520 |
+ "not support '--pretend'.\n") % myaction) |
2521 |
+ return 1 |
2522 |
+ |
2523 |
+ if "sync" == myaction: |
2524 |
+ return action_sync(settings, trees, mtimedb, myopts, myaction) |
2525 |
+ elif "metadata" == myaction: |
2526 |
+ action_metadata(settings, portdb, myopts) |
2527 |
+ elif myaction=="regen": |
2528 |
+ validate_ebuild_environment(trees) |
2529 |
+ return action_regen(settings, portdb, myopts.get("--jobs"), |
2530 |
+ myopts.get("--load-average")) |
2531 |
+ # HELP action |
2532 |
+ elif "config"==myaction: |
2533 |
+ validate_ebuild_environment(trees) |
2534 |
+ action_config(settings, trees, myopts, myfiles) |
2535 |
+ |
2536 |
+ # SEARCH action |
2537 |
+ elif "search"==myaction: |
2538 |
+ validate_ebuild_environment(trees) |
2539 |
+ action_search(trees[settings["ROOT"]]["root_config"], |
2540 |
+ myopts, myfiles, spinner) |
2541 |
+ |
2542 |
+ elif myaction in ('clean', 'depclean', 'deselect', 'prune', 'unmerge'): |
2543 |
+ validate_ebuild_environment(trees) |
2544 |
+ rval = action_uninstall(settings, trees, mtimedb["ldpath"], |
2545 |
+ myopts, myaction, myfiles, spinner) |
2546 |
+ if not (myaction == 'deselect' or buildpkgonly or fetchonly or pretend): |
2547 |
+ post_emerge(root_config, myopts, mtimedb, rval) |
2548 |
+ return rval |
2549 |
+ |
2550 |
+ elif myaction == 'info': |
2551 |
+ |
2552 |
+ # Ensure atoms are valid before calling unmerge(). |
2553 |
+ vardb = trees[settings["ROOT"]]["vartree"].dbapi |
2554 |
+ valid_atoms = [] |
2555 |
+ for x in myfiles: |
2556 |
+ if is_valid_package_atom(x): |
2557 |
+ try: |
2558 |
+ valid_atoms.append( |
2559 |
+ portage.dep_expand(x, mydb=vardb, settings=settings)) |
2560 |
+ except portage.exception.AmbiguousPackageName, e: |
2561 |
+ msg = "The short ebuild name \"" + x + \ |
2562 |
+ "\" is ambiguous. Please specify " + \ |
2563 |
+ "one of the following " + \ |
2564 |
+ "fully-qualified ebuild names instead:" |
2565 |
+ for line in textwrap.wrap(msg, 70): |
2566 |
+ writemsg_level("!!! %s\n" % (line,), |
2567 |
+ level=logging.ERROR, noiselevel=-1) |
2568 |
+ for i in e[0]: |
2569 |
+ writemsg_level(" %s\n" % colorize("INFORM", i), |
2570 |
+ level=logging.ERROR, noiselevel=-1) |
2571 |
+ writemsg_level("\n", level=logging.ERROR, noiselevel=-1) |
2572 |
+ return 1 |
2573 |
+ continue |
2574 |
+ msg = [] |
2575 |
+ msg.append("'%s' is not a valid package atom." % (x,)) |
2576 |
+ msg.append("Please check ebuild(5) for full details.") |
2577 |
+ writemsg_level("".join("!!! %s\n" % line for line in msg), |
2578 |
+ level=logging.ERROR, noiselevel=-1) |
2579 |
+ return 1 |
2580 |
+ |
2581 |
+ return action_info(settings, trees, myopts, valid_atoms) |
2582 |
+ |
2583 |
+ # "update", "system", or just process files: |
2584 |
+ else: |
2585 |
+ validate_ebuild_environment(trees) |
2586 |
+ |
2587 |
+ for x in myfiles: |
2588 |
+ if x.startswith(SETPREFIX) or \ |
2589 |
+ is_valid_package_atom(x): |
2590 |
+ continue |
2591 |
+ if x[:1] == os.sep: |
2592 |
+ continue |
2593 |
+ try: |
2594 |
+ os.lstat(x) |
2595 |
+ continue |
2596 |
+ except OSError: |
2597 |
+ pass |
2598 |
+ msg = [] |
2599 |
+ msg.append("'%s' is not a valid package atom." % (x,)) |
2600 |
+ msg.append("Please check ebuild(5) for full details.") |
2601 |
+ writemsg_level("".join("!!! %s\n" % line for line in msg), |
2602 |
+ level=logging.ERROR, noiselevel=-1) |
2603 |
+ return 1 |
2604 |
+ |
2605 |
+ if "--pretend" not in myopts: |
2606 |
+ display_news_notification(root_config, myopts) |
2607 |
+ retval = action_build(settings, trees, mtimedb, |
2608 |
+ myopts, myaction, myfiles, spinner) |
2609 |
+ root_config = trees[settings["ROOT"]]["root_config"] |
2610 |
+ post_emerge(root_config, myopts, mtimedb, retval) |
2611 |
+ |
2612 |
+ return retval |