Gentoo Archives: gentoo-commits

From: "Fabian Groffen (grobian)" <grobian@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] portage r13719 - main/branches/prefix/pym/_emerge
Date: Sun, 28 Jun 2009 13:36:43
Message-Id: E1MKuYe-0005YW-DT@stork.gentoo.org
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