Gentoo Archives: gentoo-commits

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