2 # Copyright 1999-2006 Gentoo Foundation
3 # Distributed under the terms of the GNU General Public License v2
18 from os import path as osp
19 sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym"))
22 from portage import digraph
23 from portage.const import NEWS_LIB_PATH
26 import portage.xpak, commands, errno, re, socket, time
27 from portage.output import blue, bold, colorize, darkgreen, \
28 red, xtermTitleReset, yellow
29 from portage.output import create_color_func
30 good = create_color_func("GOOD")
31 bad = create_color_func("BAD")
35 portage.dep._dep_check_strict = True
38 import portage.exception
39 from portage.cache.cache_errors import CacheError
40 from portage.data import secpass
41 from portage.util import normalize_path as normpath
42 from portage.util import cmp_sort_key, writemsg, writemsg_level
43 from portage.sets import load_default_config, SETPREFIX
44 from portage.sets.base import InternalPackageSet
46 from itertools import chain, izip
48 from _emerge.clear_caches import clear_caches
49 from _emerge.countdown import countdown
50 from _emerge.create_depgraph_params import create_depgraph_params
51 from _emerge.Dependency import Dependency
52 from _emerge.depgraph import depgraph, resume_depgraph
53 from _emerge.DepPrioritySatisfiedRange import DepPrioritySatisfiedRange
54 from _emerge.emergelog import emergelog
55 from _emerge._flush_elog_mod_echo import _flush_elog_mod_echo
56 from _emerge.is_valid_package_atom import is_valid_package_atom
57 from _emerge.MetadataRegen import MetadataRegen
58 from _emerge.Package import Package
59 from _emerge.ProgressHandler import ProgressHandler
60 from _emerge.RootConfig import RootConfig
61 from _emerge.Scheduler import Scheduler
62 from _emerge.search import search
63 from _emerge.SetArg import SetArg
64 from _emerge.show_invalid_depstring_notice import show_invalid_depstring_notice
65 from _emerge.stdout_spinner import stdout_spinner
66 from _emerge.unmerge import unmerge
67 from _emerge.UnmergeDepPriority import UnmergeDepPriority
68 from _emerge.UseFlagDisplay import UseFlagDisplay
69 from _emerge.userquery import userquery
73 "clean", "config", "depclean",
74 "info", "list-sets", "metadata",
75 "prune", "regen", "search",
76 "sync", "unmerge", "version",
79 "--ask", "--alphabetical",
80 "--buildpkg", "--buildpkgonly",
81 "--changelog", "--columns",
86 "--fetchonly", "--fetch-all-uri",
87 "--getbinpkg", "--getbinpkgonly",
88 "--help", "--ignore-default-opts",
92 "--nodeps", "--noreplace",
93 "--nospinner", "--oneshot",
94 "--onlydeps", "--pretend",
95 "--quiet", "--resume",
96 "--searchdesc", "--selective",
100 "--usepkg", "--usepkgonly",
107 "b":"--buildpkg", "B":"--buildpkgonly",
108 "c":"--clean", "C":"--unmerge",
109 "d":"--debug", "D":"--deep",
111 "f":"--fetchonly", "F":"--fetch-all-uri",
112 "g":"--getbinpkg", "G":"--getbinpkgonly",
114 "k":"--usepkg", "K":"--usepkgonly",
116 "n":"--noreplace", "N":"--newuse",
117 "o":"--onlydeps", "O":"--nodeps",
118 "p":"--pretend", "P":"--prune",
120 "s":"--search", "S":"--searchdesc",
123 "v":"--verbose", "V":"--version"
126 def getgccversion(chost):
129 return: the current in-use gcc version
132 gcc_ver_command = 'gcc -dumpversion'
133 gcc_ver_prefix = 'gcc-'
135 gcc_not_found_error = red(
136 "!!! No gcc found. You probably need to 'source /etc/profile'\n" +
137 "!!! to update the environment of this terminal and possibly\n" +
138 "!!! other terminals also.\n"
141 mystatus, myoutput = commands.getstatusoutput("gcc-config -c")
142 if mystatus == os.EX_OK and myoutput.startswith(chost + "-"):
143 return myoutput.replace(chost + "-", gcc_ver_prefix, 1)
145 mystatus, myoutput = commands.getstatusoutput(
146 chost + "-" + gcc_ver_command)
147 if mystatus == os.EX_OK:
148 return gcc_ver_prefix + myoutput
150 mystatus, myoutput = commands.getstatusoutput(gcc_ver_command)
151 if mystatus == os.EX_OK:
152 return gcc_ver_prefix + myoutput
154 portage.writemsg(gcc_not_found_error, noiselevel=-1)
155 return "[unavailable]"
157 def getportageversion(portdir, target_root, profile, chost, vardb):
158 profilever = "unavailable"
160 realpath = os.path.realpath(profile)
161 basepath = os.path.realpath(os.path.join(portdir, "profiles"))
162 if realpath.startswith(basepath):
163 profilever = realpath[1 + len(basepath):]
166 profilever = "!" + os.readlink(profile)
169 del realpath, basepath
172 libclist = vardb.match("virtual/libc")
173 libclist += vardb.match("virtual/glibc")
174 libclist = portage.util.unique_array(libclist)
176 xs=portage.catpkgsplit(x)
178 libcver+=","+"-".join(xs[1:])
180 libcver="-".join(xs[1:])
182 libcver="unavailable"
184 gccver = getgccversion(chost)
185 unameout=platform.release()+" "+platform.machine()
187 return "Portage " + portage.VERSION +" ("+profilever+", "+gccver+", "+libcver+", "+unameout+")"
189 def chk_updated_info_files(root, infodirs, prev_mtimes, retval):
191 if os.path.exists("/usr/bin/install-info"):
192 out = portage.output.EOutput()
197 inforoot=normpath(root+z)
198 if os.path.isdir(inforoot):
199 infomtime = long(os.stat(inforoot).st_mtime)
200 if inforoot not in prev_mtimes or \
201 prev_mtimes[inforoot] != infomtime:
202 regen_infodirs.append(inforoot)
204 if not regen_infodirs:
205 portage.writemsg_stdout("\n")
206 out.einfo("GNU info directory index is up-to-date.")
208 portage.writemsg_stdout("\n")
209 out.einfo("Regenerating GNU info directory index...")
211 dir_extensions = ("", ".gz", ".bz2")
215 for inforoot in regen_infodirs:
219 if not os.path.isdir(inforoot) or \
220 not os.access(inforoot, os.W_OK):
223 file_list = os.listdir(inforoot)
225 dir_file = os.path.join(inforoot, "dir")
226 moved_old_dir = False
229 if x.startswith(".") or \
230 os.path.isdir(os.path.join(inforoot, x)):
232 if x.startswith("dir"):
234 for ext in dir_extensions:
235 if x == "dir" + ext or \
236 x == "dir" + ext + ".old":
241 if processed_count == 0:
242 for ext in dir_extensions:
244 os.rename(dir_file + ext, dir_file + ext + ".old")
246 except EnvironmentError, e:
247 if e.errno != errno.ENOENT:
251 myso=commands.getstatusoutput("LANG=C LANGUAGE=C /usr/bin/install-info --dir-file="+inforoot+"/dir "+inforoot+"/"+x)[1]
252 existsstr="already exists, for file `"
254 if re.search(existsstr,myso):
255 # Already exists... Don't increment the count for this.
257 elif myso[:44]=="install-info: warning: no info dir entry in ":
258 # This info file doesn't contain a DIR-header: install-info produces this
259 # (harmless) warning (the --quiet switch doesn't seem to work).
260 # Don't increment the count for this.
264 errmsg += myso + "\n"
267 if moved_old_dir and not os.path.exists(dir_file):
268 # We didn't generate a new dir file, so put the old file
269 # back where it was originally found.
270 for ext in dir_extensions:
272 os.rename(dir_file + ext + ".old", dir_file + ext)
273 except EnvironmentError, e:
274 if e.errno != errno.ENOENT:
278 # Clean dir.old cruft so that they don't prevent
279 # unmerge of otherwise empty directories.
280 for ext in dir_extensions:
282 os.unlink(dir_file + ext + ".old")
283 except EnvironmentError, e:
284 if e.errno != errno.ENOENT:
288 #update mtime so we can potentially avoid regenerating.
289 prev_mtimes[inforoot] = long(os.stat(inforoot).st_mtime)
292 out.eerror("Processed %d info files; %d errors." % \
294 writemsg_level(errmsg, level=logging.ERROR, noiselevel=-1)
297 out.einfo("Processed %d info files." % (icount,))
300 def display_news_notification(root_config, myopts):
301 target_root = root_config.root
302 trees = root_config.trees
303 settings = trees["vartree"].settings
304 portdb = trees["porttree"].dbapi
305 vardb = trees["vartree"].dbapi
306 NEWS_PATH = os.path.join("metadata", "news")
307 UNREAD_PATH = os.path.join(target_root, NEWS_LIB_PATH, "news")
308 newsReaderDisplay = False
309 update = "--pretend" not in myopts
311 for repo in portdb.getRepositories():
312 unreadItems = checkUpdatedNewsItems(
313 portdb, vardb, NEWS_PATH, UNREAD_PATH, repo, update=update)
315 if not newsReaderDisplay:
316 newsReaderDisplay = True
318 print colorize("WARN", " * IMPORTANT:"),
319 print "%s news items need reading for repository '%s'." % (unreadItems, repo)
322 if newsReaderDisplay:
323 print colorize("WARN", " *"),
324 print "Use " + colorize("GOOD", "eselect news") + " to read news items."
327 def display_preserved_libs(vardbapi):
330 # Ensure the registry is consistent with existing files.
331 vardbapi.plib_registry.pruneNonExisting()
333 if vardbapi.plib_registry.hasEntries():
335 print colorize("WARN", "!!!") + " existing preserved libs:"
336 plibdata = vardbapi.plib_registry.getPreservedLibs()
337 linkmap = vardbapi.linkmap
340 linkmap_broken = False
344 except portage.exception.CommandNotFound, e:
345 writemsg_level("!!! Command Not Found: %s\n" % (e,),
346 level=logging.ERROR, noiselevel=-1)
348 linkmap_broken = True
350 search_for_owners = set()
352 internal_plib_keys = set(linkmap._obj_key(f) \
353 for f in plibdata[cpv])
354 for f in plibdata[cpv]:
355 if f in consumer_map:
358 for c in linkmap.findConsumers(f):
359 # Filter out any consumers that are also preserved libs
360 # belonging to the same package as the provider.
361 if linkmap._obj_key(c) not in internal_plib_keys:
364 consumer_map[f] = consumers
365 search_for_owners.update(consumers[:MAX_DISPLAY+1])
367 owners = vardbapi._owners.getFileOwnerMap(search_for_owners)
370 print colorize("WARN", ">>>") + " package: %s" % cpv
372 for f in plibdata[cpv]:
373 obj_key = linkmap._obj_key(f)
374 alt_paths = samefile_map.get(obj_key)
375 if alt_paths is None:
377 samefile_map[obj_key] = alt_paths
380 for alt_paths in samefile_map.itervalues():
381 alt_paths = sorted(alt_paths)
383 print colorize("WARN", " * ") + " - %s" % (p,)
385 consumers = consumer_map.get(f, [])
386 for c in consumers[:MAX_DISPLAY]:
387 print colorize("WARN", " * ") + " used by %s (%s)" % \
388 (c, ", ".join(x.mycpv for x in owners.get(c, [])))
389 if len(consumers) == MAX_DISPLAY + 1:
390 print colorize("WARN", " * ") + " used by %s (%s)" % \
391 (consumers[MAX_DISPLAY], ", ".join(x.mycpv \
392 for x in owners.get(consumers[MAX_DISPLAY], [])))
393 elif len(consumers) > MAX_DISPLAY:
394 print colorize("WARN", " * ") + " used by %d other files" % (len(consumers) - MAX_DISPLAY)
395 print "Use " + colorize("GOOD", "emerge @preserved-rebuild") + " to rebuild packages using these libraries"
398 def post_emerge(root_config, myopts, mtimedb, retval):
400 Misc. things to run at the end of a merge session.
406 Display preserved libs warnings
409 @param trees: A dictionary mapping each ROOT to it's package databases
411 @param mtimedb: The mtimeDB to store data needed across merge invocations
412 @type mtimedb: MtimeDB class instance
413 @param retval: Emerge's return value
417 1. Calls sys.exit(retval)
420 target_root = root_config.root
421 trees = { target_root : root_config.trees }
422 vardbapi = trees[target_root]["vartree"].dbapi
423 settings = vardbapi.settings
424 info_mtimes = mtimedb["info"]
426 # Load the most current variables from ${ROOT}/etc/profile.env
429 settings.regenerate()
432 config_protect = settings.get("CONFIG_PROTECT","").split()
433 infodirs = settings.get("INFOPATH","").split(":") + \
434 settings.get("INFODIR","").split(":")
438 if retval == os.EX_OK:
439 exit_msg = " *** exiting successfully."
441 exit_msg = " *** exiting unsuccessfully with status '%s'." % retval
442 emergelog("notitles" not in settings.features, exit_msg)
444 _flush_elog_mod_echo()
446 counter_hash = settings.get("PORTAGE_COUNTER_HASH")
447 if "--pretend" in myopts or (counter_hash is not None and \
448 counter_hash == vardbapi._counter_hash()):
449 display_news_notification(root_config, myopts)
450 # If vdb state has not changed then there's nothing else to do.
453 vdb_path = os.path.join(target_root, portage.VDB_PATH)
454 portage.util.ensure_dirs(vdb_path)
456 if os.access(vdb_path, os.W_OK) and not "--pretend" in myopts:
457 vdb_lock = portage.locks.lockdir(vdb_path)
461 if "noinfo" not in settings.features:
462 chk_updated_info_files(target_root,
463 infodirs, info_mtimes, retval)
467 portage.locks.unlockdir(vdb_lock)
469 chk_updated_cfg_files(target_root, config_protect)
471 display_news_notification(root_config, myopts)
472 if retval in (None, os.EX_OK) or (not "--pretend" in myopts):
473 display_preserved_libs(vardbapi)
478 def chk_updated_cfg_files(target_root, config_protect):
480 #number of directories with some protect files in them
482 for x in config_protect:
483 x = os.path.join(target_root, x.lstrip(os.path.sep))
484 if not os.access(x, os.W_OK):
485 # Avoid Permission denied errors generated
489 mymode = os.lstat(x).st_mode
492 if stat.S_ISLNK(mymode):
493 # We want to treat it like a directory if it
494 # is a symlink to an existing directory.
496 real_mode = os.stat(x).st_mode
497 if stat.S_ISDIR(real_mode):
501 if stat.S_ISDIR(mymode):
502 mycommand = "find '%s' -name '.*' -type d -prune -o -name '._cfg????_*'" % x
504 mycommand = "find '%s' -maxdepth 1 -name '._cfg????_%s'" % \
505 os.path.split(x.rstrip(os.path.sep))
506 mycommand += " ! -name '.*~' ! -iname '.*.bak' -print0"
507 a = commands.getstatusoutput(mycommand)
509 sys.stderr.write(" %s error scanning '%s': " % (bad("*"), x))
511 # Show the error message alone, sending stdout to /dev/null.
512 os.system(mycommand + " 1>/dev/null")
514 files = a[1].split('\0')
515 # split always produces an empty string as the last element
516 if files and not files[-1]:
520 print "\n"+colorize("WARN", " * IMPORTANT:"),
521 if stat.S_ISDIR(mymode):
522 print "%d config files in '%s' need updating." % \
525 print "config file '%s' needs updating." % x
528 print " "+yellow("*")+" See the "+colorize("INFORM","CONFIGURATION FILES")+ \
529 " section of the " + bold("emerge")
530 print " "+yellow("*")+" man page to learn how to update config files."
532 def checkUpdatedNewsItems(portdb, vardb, NEWS_PATH, UNREAD_PATH, repo_id,
535 Examines news items in repodir + '/' + NEWS_PATH and attempts to find unread items
536 Returns the number of unread (yet relevent) items.
538 @param portdb: a portage tree database
539 @type portdb: pordbapi
540 @param vardb: an installed package database
541 @type vardb: vardbapi
550 1. The number of unread but relevant news items.
553 from portage.news import NewsManager
554 manager = NewsManager(portdb, vardb, NEWS_PATH, UNREAD_PATH)
555 return manager.getUnreadItems( repo_id, update=update )
557 def action_sync(settings, trees, mtimedb, myopts, myaction):
558 xterm_titles = "notitles" not in settings.features
559 emergelog(xterm_titles, " === sync")
560 portdb = trees[settings["ROOT"]]["porttree"].dbapi
561 myportdir = portdb.porttree_root
562 out = portage.output.EOutput()
564 sys.stderr.write("!!! PORTDIR is undefined. Is /etc/make.globals missing?\n")
566 if myportdir[-1]=="/":
567 myportdir=myportdir[:-1]
569 st = os.stat(myportdir)
573 print ">>>",myportdir,"not found, creating it."
574 os.makedirs(myportdir,0755)
575 st = os.stat(myportdir)
578 spawn_kwargs["env"] = settings.environ()
579 if 'usersync' in settings.features and \
580 portage.data.secpass >= 2 and \
581 (st.st_uid != os.getuid() and st.st_mode & 0700 or \
582 st.st_gid != os.getgid() and st.st_mode & 0070):
584 homedir = pwd.getpwuid(st.st_uid).pw_dir
588 # Drop privileges when syncing, in order to match
589 # existing uid/gid settings.
590 spawn_kwargs["uid"] = st.st_uid
591 spawn_kwargs["gid"] = st.st_gid
592 spawn_kwargs["groups"] = [st.st_gid]
593 spawn_kwargs["env"]["HOME"] = homedir
595 if not st.st_mode & 0020:
597 spawn_kwargs["umask"] = umask
599 syncuri = settings.get("SYNC", "").strip()
601 writemsg_level("!!! SYNC is undefined. Is /etc/make.globals missing?\n",
602 noiselevel=-1, level=logging.ERROR)
605 vcs_dirs = frozenset([".git", ".svn", "CVS", ".hg"])
606 vcs_dirs = vcs_dirs.intersection(os.listdir(myportdir))
610 updatecache_flg = False
611 if myaction == "metadata":
612 print "skipping sync"
613 updatecache_flg = True
614 elif ".git" in vcs_dirs:
615 # Update existing git repository, and ignore the syncuri. We are
616 # going to trust the user and assume that the user is in the branch
617 # that he/she wants updated. We'll let the user manage branches with
619 if portage.process.find_binary("git") is None:
620 msg = ["Command not found: git",
621 "Type \"emerge dev-util/git\" to enable git support."]
623 writemsg_level("!!! %s\n" % l,
624 level=logging.ERROR, noiselevel=-1)
626 msg = ">>> Starting git pull in %s..." % myportdir
627 emergelog(xterm_titles, msg )
628 writemsg_level(msg + "\n")
629 exitcode = portage.process.spawn_bash("cd %s ; git pull" % \
630 (portage._shell_quote(myportdir),), **spawn_kwargs)
631 if exitcode != os.EX_OK:
632 msg = "!!! git pull error in %s." % myportdir
633 emergelog(xterm_titles, msg)
634 writemsg_level(msg + "\n", level=logging.ERROR, noiselevel=-1)
636 msg = ">>> Git pull in %s successful" % myportdir
637 emergelog(xterm_titles, msg)
638 writemsg_level(msg + "\n")
639 exitcode = git_sync_timestamps(settings, myportdir)
640 if exitcode == os.EX_OK:
641 updatecache_flg = True
642 elif syncuri[:8]=="rsync://":
643 for vcs_dir in vcs_dirs:
644 writemsg_level(("!!! %s appears to be under revision " + \
645 "control (contains %s).\n!!! Aborting rsync sync.\n") % \
646 (myportdir, vcs_dir), level=logging.ERROR, noiselevel=-1)
648 if not os.path.exists("/usr/bin/rsync"):
649 print "!!! /usr/bin/rsync does not exist, so rsync support is disabled."
650 print "!!! Type \"emerge net-misc/rsync\" to enable rsync support."
655 if settings["PORTAGE_RSYNC_OPTS"] == "":
656 portage.writemsg("PORTAGE_RSYNC_OPTS empty or unset, using hardcoded defaults\n")
658 "--recursive", # Recurse directories
659 "--links", # Consider symlinks
660 "--safe-links", # Ignore links outside of tree
661 "--perms", # Preserve permissions
662 "--times", # Preserive mod times
663 "--compress", # Compress the data transmitted
664 "--force", # Force deletion on non-empty dirs
665 "--whole-file", # Don't do block transfers, only entire files
666 "--delete", # Delete files that aren't in the master tree
667 "--stats", # Show final statistics about what was transfered
668 "--timeout="+str(mytimeout), # IO timeout if not done in X seconds
669 "--exclude=/distfiles", # Exclude distfiles from consideration
670 "--exclude=/local", # Exclude local from consideration
671 "--exclude=/packages", # Exclude packages from consideration
675 # The below validation is not needed when using the above hardcoded
678 portage.writemsg("Using PORTAGE_RSYNC_OPTS instead of hardcoded defaults\n", 1)
680 shlex.split(settings.get("PORTAGE_RSYNC_OPTS","")))
681 for opt in ("--recursive", "--times"):
682 if opt not in rsync_opts:
683 portage.writemsg(yellow("WARNING:") + " adding required option " + \
684 "%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
685 rsync_opts.append(opt)
687 for exclude in ("distfiles", "local", "packages"):
688 opt = "--exclude=/%s" % exclude
689 if opt not in rsync_opts:
690 portage.writemsg(yellow("WARNING:") + \
691 " adding required option %s not included in " % opt + \
692 "PORTAGE_RSYNC_OPTS (can be overridden with --exclude='!')\n")
693 rsync_opts.append(opt)
695 if syncuri.rstrip("/").endswith(".gentoo.org/gentoo-portage"):
696 def rsync_opt_startswith(opt_prefix):
698 if x.startswith(opt_prefix):
702 if not rsync_opt_startswith("--timeout="):
703 rsync_opts.append("--timeout=%d" % mytimeout)
705 for opt in ("--compress", "--whole-file"):
706 if opt not in rsync_opts:
707 portage.writemsg(yellow("WARNING:") + " adding required option " + \
708 "%s not included in PORTAGE_RSYNC_OPTS\n" % opt)
709 rsync_opts.append(opt)
711 if "--quiet" in myopts:
712 rsync_opts.append("--quiet") # Shut up a lot
714 rsync_opts.append("--verbose") # Print filelist
716 if "--verbose" in myopts:
717 rsync_opts.append("--progress") # Progress meter for each file
719 if "--debug" in myopts:
720 rsync_opts.append("--checksum") # Force checksum on all files
722 # Real local timestamp file.
723 servertimestampfile = os.path.join(
724 myportdir, "metadata", "timestamp.chk")
726 content = portage.util.grabfile(servertimestampfile)
730 mytimestamp = time.mktime(time.strptime(content[0],
731 "%a, %d %b %Y %H:%M:%S +0000"))
732 except (OverflowError, ValueError):
737 rsync_initial_timeout = \
738 int(settings.get("PORTAGE_RSYNC_INITIAL_TIMEOUT", "15"))
740 rsync_initial_timeout = 15
743 maxretries=int(settings["PORTAGE_RSYNC_RETRIES"])
744 except SystemExit, e:
745 raise # Needed else can't exit
747 maxretries=3 #default number of retries
750 user_name, hostname, port = re.split(
751 "rsync://([^:/]+@)?([^:/]*)(:[0-9]+)?", syncuri, maxsplit=3)[1:4]
754 if user_name is None:
757 all_rsync_opts = set(rsync_opts)
758 extra_rsync_opts = shlex.split(
759 settings.get("PORTAGE_RSYNC_EXTRA_OPTS",""))
760 all_rsync_opts.update(extra_rsync_opts)
761 family = socket.AF_INET
762 if "-4" in all_rsync_opts or "--ipv4" in all_rsync_opts:
763 family = socket.AF_INET
764 elif socket.has_ipv6 and \
765 ("-6" in all_rsync_opts or "--ipv6" in all_rsync_opts):
766 family = socket.AF_INET6
768 SERVER_OUT_OF_DATE = -1
769 EXCEEDED_MAX_RETRIES = -2
775 for addrinfo in socket.getaddrinfo(
776 hostname, None, family, socket.SOCK_STREAM):
777 if socket.has_ipv6 and addrinfo[0] == socket.AF_INET6:
778 # IPv6 addresses need to be enclosed in square brackets
779 ips.append("[%s]" % addrinfo[4][0])
781 ips.append(addrinfo[4][0])
782 from random import shuffle
784 except SystemExit, e:
785 raise # Needed else can't exit
787 print "Notice:",str(e)
792 dosyncuri = syncuri.replace(
793 "//" + user_name + hostname + port + "/",
794 "//" + user_name + ips[0] + port + "/", 1)
795 except SystemExit, e:
796 raise # Needed else can't exit
798 print "Notice:",str(e)
802 if "--ask" in myopts:
803 if userquery("Do you want to sync your Portage tree with the mirror at\n" + blue(dosyncuri) + bold("?"))=="No":
808 emergelog(xterm_titles, ">>> Starting rsync with " + dosyncuri)
809 if "--quiet" not in myopts:
810 print ">>> Starting rsync with "+dosyncuri+"..."
812 emergelog(xterm_titles,
813 ">>> Starting retry %d of %d with %s" % \
814 (retries,maxretries,dosyncuri))
815 print "\n\n>>> Starting retry %d of %d with %s" % (retries,maxretries,dosyncuri)
817 if mytimestamp != 0 and "--quiet" not in myopts:
818 print ">>> Checking server timestamp ..."
820 rsynccommand = ["/usr/bin/rsync"] + rsync_opts + extra_rsync_opts
822 if "--debug" in myopts:
827 # Even if there's no timestamp available locally, fetch the
828 # timestamp anyway as an initial probe to verify that the server is
829 # responsive. This protects us from hanging indefinitely on a
830 # connection attempt to an unresponsive server which rsync's
831 # --timeout option does not prevent.
833 # Temporary file for remote server timestamp comparison.
834 from tempfile import mkstemp
835 fd, tmpservertimestampfile = mkstemp()
837 mycommand = rsynccommand[:]
838 mycommand.append(dosyncuri.rstrip("/") + \
839 "/metadata/timestamp.chk")
840 mycommand.append(tmpservertimestampfile)
844 def timeout_handler(signum, frame):
845 raise portage.exception.PortageException("timed out")
846 signal.signal(signal.SIGALRM, timeout_handler)
847 # Timeout here in case the server is unresponsive. The
848 # --timeout rsync option doesn't apply to the initial
849 # connection attempt.
850 if rsync_initial_timeout:
851 signal.alarm(rsync_initial_timeout)
853 mypids.extend(portage.process.spawn(
854 mycommand, env=settings.environ(), returnpid=True))
855 exitcode = os.waitpid(mypids[0], 0)[1]
856 content = portage.grabfile(tmpservertimestampfile)
858 if rsync_initial_timeout:
861 os.unlink(tmpservertimestampfile)
864 except portage.exception.PortageException, e:
868 if mypids and os.waitpid(mypids[0], os.WNOHANG) == (0,0):
869 os.kill(mypids[0], signal.SIGTERM)
870 os.waitpid(mypids[0], 0)
871 # This is the same code rsync uses for timeout.
874 if exitcode != os.EX_OK:
876 exitcode = (exitcode & 0xff) << 8
878 exitcode = exitcode >> 8
880 portage.process.spawned_pids.remove(mypids[0])
883 servertimestamp = time.mktime(time.strptime(
884 content[0], "%a, %d %b %Y %H:%M:%S +0000"))
885 except (OverflowError, ValueError):
887 del mycommand, mypids, content
888 if exitcode == os.EX_OK:
889 if (servertimestamp != 0) and (servertimestamp == mytimestamp):
890 emergelog(xterm_titles,
891 ">>> Cancelling sync -- Already current.")
894 print ">>> Timestamps on the server and in the local repository are the same."
895 print ">>> Cancelling all further sync action. You are already up to date."
897 print ">>> In order to force sync, remove '%s'." % servertimestampfile
901 elif (servertimestamp != 0) and (servertimestamp < mytimestamp):
902 emergelog(xterm_titles,
903 ">>> Server out of date: %s" % dosyncuri)
906 print ">>> SERVER OUT OF DATE: %s" % dosyncuri
908 print ">>> In order to force sync, remove '%s'." % servertimestampfile
911 exitcode = SERVER_OUT_OF_DATE
912 elif (servertimestamp == 0) or (servertimestamp > mytimestamp):
914 mycommand = rsynccommand + [dosyncuri+"/", myportdir]
915 exitcode = portage.process.spawn(mycommand, **spawn_kwargs)
916 if exitcode in [0,1,3,4,11,14,20,21]:
918 elif exitcode in [1,3,4,11,14,20,21]:
921 # Code 2 indicates protocol incompatibility, which is expected
922 # for servers with protocol < 29 that don't support
923 # --prune-empty-directories. Retry for a server that supports
924 # at least rsync protocol version 29 (>=rsync-2.6.4).
929 if retries<=maxretries:
930 print ">>> Retrying..."
935 updatecache_flg=False
936 exitcode = EXCEEDED_MAX_RETRIES
940 emergelog(xterm_titles, "=== Sync completed with %s" % dosyncuri)
941 elif exitcode == SERVER_OUT_OF_DATE:
943 elif exitcode == EXCEEDED_MAX_RETRIES:
945 ">>> Exceeded PORTAGE_RSYNC_RETRIES: %s\n" % maxretries)
950 msg.append("Rsync has reported that there is a syntax error. Please ensure")
951 msg.append("that your SYNC statement is proper.")
952 msg.append("SYNC=" + settings["SYNC"])
954 msg.append("Rsync has reported that there is a File IO error. Normally")
955 msg.append("this means your disk is full, but can be caused by corruption")
956 msg.append("on the filesystem that contains PORTDIR. Please investigate")
957 msg.append("and try again after the problem has been fixed.")
958 msg.append("PORTDIR=" + settings["PORTDIR"])
960 msg.append("Rsync was killed before it finished.")
962 msg.append("Rsync has not successfully finished. It is recommended that you keep")
963 msg.append("trying or that you use the 'emerge-webrsync' option if you are unable")
964 msg.append("to use rsync due to firewall or other restrictions. This should be a")
965 msg.append("temporary problem unless complications exist with your network")
966 msg.append("(and possibly your system's filesystem) configuration.")
970 elif syncuri[:6]=="cvs://":
971 if not os.path.exists("/usr/bin/cvs"):
972 print "!!! /usr/bin/cvs does not exist, so CVS support is disabled."
973 print "!!! Type \"emerge dev-util/cvs\" to enable CVS support."
976 cvsdir=os.path.dirname(myportdir)
977 if not os.path.exists(myportdir+"/CVS"):
979 print ">>> Starting initial cvs checkout with "+syncuri+"..."
980 if os.path.exists(cvsdir+"/gentoo-x86"):
981 print "!!! existing",cvsdir+"/gentoo-x86 directory; exiting."
986 if e.errno != errno.ENOENT:
988 "!!! existing '%s' directory; exiting.\n" % myportdir)
991 if portage.spawn("cd "+cvsdir+"; cvs -z0 -d "+cvsroot+" co -P gentoo-x86",settings,free=1):
992 print "!!! cvs checkout error; exiting."
994 os.rename(os.path.join(cvsdir, "gentoo-x86"), myportdir)
997 print ">>> Starting cvs update with "+syncuri+"..."
998 retval = portage.process.spawn_bash(
999 "cd %s; cvs -z0 -q update -dP" % \
1000 (portage._shell_quote(myportdir),), **spawn_kwargs)
1001 if retval != os.EX_OK:
1005 writemsg_level("!!! Unrecognized protocol: SYNC='%s'\n" % (syncuri,),
1006 noiselevel=-1, level=logging.ERROR)
1009 if updatecache_flg and \
1010 myaction != "metadata" and \
1011 "metadata-transfer" not in settings.features:
1012 updatecache_flg = False
1014 # Reload the whole config from scratch.
1015 settings, trees, mtimedb = load_emerge_config(trees=trees)
1016 root_config = trees[settings["ROOT"]]["root_config"]
1017 portdb = trees[settings["ROOT"]]["porttree"].dbapi
1019 if updatecache_flg and \
1020 os.path.exists(os.path.join(myportdir, 'metadata', 'cache')):
1022 # Only update cache for myportdir since that's
1023 # the only one that's been synced here.
1024 action_metadata(settings, portdb, myopts, porttrees=[myportdir])
1026 if portage._global_updates(trees, mtimedb["updates"]):
1028 # Reload the whole config from scratch.
1029 settings, trees, mtimedb = load_emerge_config(trees=trees)
1030 portdb = trees[settings["ROOT"]]["porttree"].dbapi
1031 root_config = trees[settings["ROOT"]]["root_config"]
1033 mybestpv = portdb.xmatch("bestmatch-visible",
1034 portage.const.PORTAGE_PACKAGE_ATOM)
1035 mypvs = portage.best(
1036 trees[settings["ROOT"]]["vartree"].dbapi.match(
1037 portage.const.PORTAGE_PACKAGE_ATOM))
1039 chk_updated_cfg_files("/", settings.get("CONFIG_PROTECT","").split())
1041 if myaction != "metadata":
1042 if os.access(portage.USER_CONFIG_PATH + "/bin/post_sync", os.X_OK):
1043 retval = portage.process.spawn(
1044 [os.path.join(portage.USER_CONFIG_PATH, "bin", "post_sync"),
1045 dosyncuri], env=settings.environ())
1046 if retval != os.EX_OK:
1047 print red(" * ")+bold("spawn failed of "+ portage.USER_CONFIG_PATH + "/bin/post_sync")
1049 if(mybestpv != mypvs) and not "--quiet" in myopts:
1051 print red(" * ")+bold("An update to portage is available.")+" It is _highly_ recommended"
1052 print red(" * ")+"that you update portage now, before any other packages are updated."
1054 print red(" * ")+"To update portage, run 'emerge portage' now."
1057 display_news_notification(root_config, myopts)
1060 def git_sync_timestamps(settings, portdir):
1062 Since git doesn't preserve timestamps, synchronize timestamps between
1063 entries and ebuilds/eclasses. Assume the cache has the correct timestamp
1064 for a given file as long as the file in the working tree is not modified
1067 cache_dir = os.path.join(portdir, "metadata", "cache")
1068 if not os.path.isdir(cache_dir):
1070 writemsg_level(">>> Synchronizing timestamps...\n")
1072 from portage.cache.cache_errors import CacheError
1074 cache_db = settings.load_best_module("portdbapi.metadbmodule")(
1075 portdir, "metadata/cache", portage.auxdbkeys[:], readonly=True)
1076 except CacheError, e:
1077 writemsg_level("!!! Unable to instantiate cache: %s\n" % (e,),
1078 level=logging.ERROR, noiselevel=-1)
1081 ec_dir = os.path.join(portdir, "eclass")
1083 ec_names = set(f[:-7] for f in os.listdir(ec_dir) \
1084 if f.endswith(".eclass"))
1086 writemsg_level("!!! Unable to list eclasses: %s\n" % (e,),
1087 level=logging.ERROR, noiselevel=-1)
1090 args = [portage.const.BASH_BINARY, "-c",
1091 "cd %s && git diff-index --name-only --diff-filter=M HEAD" % \
1092 portage._shell_quote(portdir)]
1094 proc = subprocess.Popen(args, stdout=subprocess.PIPE)
1095 modified_files = set(l.rstrip("\n") for l in proc.stdout)
1097 if rval != os.EX_OK:
1100 modified_eclasses = set(ec for ec in ec_names \
1101 if os.path.join("eclass", ec + ".eclass") in modified_files)
1103 updated_ec_mtimes = {}
1105 for cpv in cache_db:
1106 cpv_split = portage.catpkgsplit(cpv)
1107 if cpv_split is None:
1108 writemsg_level("!!! Invalid cache entry: %s\n" % (cpv,),
1109 level=logging.ERROR, noiselevel=-1)
1112 cat, pn, ver, rev = cpv_split
1113 cat, pf = portage.catsplit(cpv)
1114 relative_eb_path = os.path.join(cat, pn, pf + ".ebuild")
1115 if relative_eb_path in modified_files:
1119 cache_entry = cache_db[cpv]
1120 eb_mtime = cache_entry.get("_mtime_")
1121 ec_mtimes = cache_entry.get("_eclasses_")
1123 writemsg_level("!!! Missing cache entry: %s\n" % (cpv,),
1124 level=logging.ERROR, noiselevel=-1)
1126 except CacheError, e:
1127 writemsg_level("!!! Unable to access cache entry: %s %s\n" % \
1128 (cpv, e), level=logging.ERROR, noiselevel=-1)
1131 if eb_mtime is None:
1132 writemsg_level("!!! Missing ebuild mtime: %s\n" % (cpv,),
1133 level=logging.ERROR, noiselevel=-1)
1137 eb_mtime = long(eb_mtime)
1139 writemsg_level("!!! Invalid ebuild mtime: %s %s\n" % \
1140 (cpv, eb_mtime), level=logging.ERROR, noiselevel=-1)
1143 if ec_mtimes is None:
1144 writemsg_level("!!! Missing eclass mtimes: %s\n" % (cpv,),
1145 level=logging.ERROR, noiselevel=-1)
1148 if modified_eclasses.intersection(ec_mtimes):
1151 missing_eclasses = set(ec_mtimes).difference(ec_names)
1152 if missing_eclasses:
1153 writemsg_level("!!! Non-existent eclass(es): %s %s\n" % \
1154 (cpv, sorted(missing_eclasses)), level=logging.ERROR,
1158 eb_path = os.path.join(portdir, relative_eb_path)
1160 current_eb_mtime = os.stat(eb_path)
1162 writemsg_level("!!! Missing ebuild: %s\n" % \
1163 (cpv,), level=logging.ERROR, noiselevel=-1)
1166 inconsistent = False
1167 for ec, (ec_path, ec_mtime) in ec_mtimes.iteritems():
1168 updated_mtime = updated_ec_mtimes.get(ec)
1169 if updated_mtime is not None and updated_mtime != ec_mtime:
1170 writemsg_level("!!! Inconsistent eclass mtime: %s %s\n" % \
1171 (cpv, ec), level=logging.ERROR, noiselevel=-1)
1178 if current_eb_mtime != eb_mtime:
1179 os.utime(eb_path, (eb_mtime, eb_mtime))
1181 for ec, (ec_path, ec_mtime) in ec_mtimes.iteritems():
1182 if ec in updated_ec_mtimes:
1184 ec_path = os.path.join(ec_dir, ec + ".eclass")
1185 current_mtime = long(os.stat(ec_path).st_mtime)
1186 if current_mtime != ec_mtime:
1187 os.utime(ec_path, (ec_mtime, ec_mtime))
1188 updated_ec_mtimes[ec] = ec_mtime
1192 def action_metadata(settings, portdb, myopts, porttrees=None):
1193 if porttrees is None:
1194 porttrees = portdb.porttrees
1195 portage.writemsg_stdout("\n>>> Updating Portage cache\n")
1196 old_umask = os.umask(0002)
1197 cachedir = os.path.normpath(settings.depcachedir)
1198 if cachedir in ["/", "/bin", "/dev", "/etc", "/home",
1199 "/lib", "/opt", "/proc", "/root", "/sbin",
1200 "/sys", "/tmp", "/usr", "/var"]:
1201 print >> sys.stderr, "!!! PORTAGE_DEPCACHEDIR IS SET TO A PRIMARY " + \
1202 "ROOT DIRECTORY ON YOUR SYSTEM."
1203 print >> sys.stderr, \
1204 "!!! This is ALMOST CERTAINLY NOT what you want: '%s'" % cachedir
1206 if not os.path.exists(cachedir):
1207 os.makedirs(cachedir)
1209 auxdbkeys = [x for x in portage.auxdbkeys if not x.startswith("UNUSED_0")]
1210 auxdbkeys = tuple(auxdbkeys)
1212 class TreeData(object):
1213 __slots__ = ('dest_db', 'eclass_db', 'path', 'src_db', 'valid_nodes')
1214 def __init__(self, dest_db, eclass_db, path, src_db):
1215 self.dest_db = dest_db
1216 self.eclass_db = eclass_db
1218 self.src_db = src_db
1219 self.valid_nodes = set()
1222 for path in porttrees:
1223 src_db = portdb._pregen_auxdb.get(path)
1224 if src_db is None and \
1225 os.path.isdir(os.path.join(path, 'metadata', 'cache')):
1226 src_db = portdb.metadbmodule(
1227 path, 'metadata/cache', auxdbkeys, readonly=True)
1229 src_db.ec = portdb._repo_info[path].eclass_db
1230 except AttributeError:
1233 if src_db is not None:
1234 porttrees_data.append(TreeData(portdb.auxdb[path],
1235 portdb._repo_info[path].eclass_db, path, src_db))
1237 porttrees = [tree_data.path for tree_data in porttrees_data]
1239 isatty = sys.stdout.isatty()
1240 quiet = not isatty or '--quiet' in myopts
1243 progressBar = portage.output.TermProgressBar()
1244 progressHandler = ProgressHandler()
1245 onProgress = progressHandler.onProgress
1247 progressBar.set(progressHandler.curval, progressHandler.maxval)
1248 progressHandler.display = display
1249 def sigwinch_handler(signum, frame):
1250 lines, progressBar.term_columns = \
1251 portage.output.get_term_size()
1252 signal.signal(signal.SIGWINCH, sigwinch_handler)
1254 # Temporarily override portdb.porttrees so portdb.cp_all()
1255 # will only return the relevant subset.
1256 portdb_porttrees = portdb.porttrees
1257 portdb.porttrees = porttrees
1259 cp_all = portdb.cp_all()
1261 portdb.porttrees = portdb_porttrees
1264 maxval = len(cp_all)
1265 if onProgress is not None:
1266 onProgress(maxval, curval)
1268 from portage.cache.util import quiet_mirroring
1269 from portage import eapi_is_supported, \
1270 _validate_cache_for_unsupported_eapis
1272 # TODO: Display error messages, but do not interfere with the progress bar.
1274 # 1) erase the progress bar
1275 # 2) show the error message
1276 # 3) redraw the progress bar on a new line
1277 noise = quiet_mirroring()
1280 for tree_data in porttrees_data:
1281 for cpv in portdb.cp_list(cp, mytree=tree_data.path):
1282 tree_data.valid_nodes.add(cpv)
1284 src = tree_data.src_db[cpv]
1286 noise.missing_entry(cpv)
1289 except CacheError, ce:
1290 noise.exception(cpv, ce)
1294 eapi = src.get('EAPI')
1297 eapi = eapi.lstrip('-')
1298 eapi_supported = eapi_is_supported(eapi)
1299 if not eapi_supported:
1300 if not _validate_cache_for_unsupported_eapis:
1301 noise.misc(cpv, "unable to validate " + \
1302 "cache for EAPI='%s'" % eapi)
1307 dest = tree_data.dest_db[cpv]
1308 except (KeyError, CacheError):
1311 for d in (src, dest):
1312 if d is not None and d.get('EAPI') in ('', '0'):
1315 if dest is not None:
1316 if not (dest['_mtime_'] == src['_mtime_'] and \
1317 tree_data.eclass_db.is_eclass_data_valid(
1318 dest['_eclasses_']) and \
1319 set(dest['_eclasses_']) == set(src['_eclasses_'])):
1322 # We don't want to skip the write unless we're really
1323 # sure that the existing cache is identical, so don't
1324 # trust _mtime_ and _eclasses_ alone.
1325 for k in set(chain(src, dest)).difference(
1326 ('_mtime_', '_eclasses_')):
1327 if dest.get(k, '') != src.get(k, ''):
1331 if dest is not None:
1332 # The existing data is valid and identical,
1333 # so there's no need to overwrite it.
1337 inherited = src.get('INHERITED', '')
1338 eclasses = src.get('_eclasses_')
1339 except CacheError, ce:
1340 noise.exception(cpv, ce)
1344 if eclasses is not None:
1345 if not tree_data.eclass_db.is_eclass_data_valid(
1347 noise.eclass_stale(cpv)
1349 inherited = eclasses
1351 inherited = inherited.split()
1353 if tree_data.src_db.complete_eclass_entries and \
1355 noise.corruption(cpv, "missing _eclasses_ field")
1359 # Even if _eclasses_ already exists, replace it with data from
1360 # eclass_cache, in order to insert local eclass paths.
1362 eclasses = tree_data.eclass_db.get_eclass_data(inherited)
1364 # INHERITED contains a non-existent eclass.
1365 noise.eclass_stale(cpv)
1368 if eclasses is None:
1369 noise.eclass_stale(cpv)
1371 src['_eclasses_'] = eclasses
1373 src['_eclasses_'] = {}
1375 if not eapi_supported:
1377 'EAPI' : '-' + eapi,
1378 '_mtime_' : src['_mtime_'],
1379 '_eclasses_' : src['_eclasses_'],
1383 tree_data.dest_db[cpv] = src
1384 except CacheError, ce:
1385 noise.exception(cpv, ce)
1389 if onProgress is not None:
1390 onProgress(maxval, curval)
1392 if onProgress is not None:
1393 onProgress(maxval, curval)
1395 for tree_data in porttrees_data:
1397 dead_nodes = set(tree_data.dest_db.iterkeys())
1398 except CacheError, e:
1399 writemsg_level("Error listing cache entries for " + \
1400 "'%s': %s, continuing...\n" % (tree_data.path, e),
1401 level=logging.ERROR, noiselevel=-1)
1404 dead_nodes.difference_update(tree_data.valid_nodes)
1405 for cpv in dead_nodes:
1407 del tree_data.dest_db[cpv]
1408 except (KeyError, CacheError):
1412 # make sure the final progress is displayed
1413 progressHandler.display()
1415 signal.signal(signal.SIGWINCH, signal.SIG_DFL)
1420 def action_regen(settings, portdb, max_jobs, max_load):
1421 xterm_titles = "notitles" not in settings.features
1422 emergelog(xterm_titles, " === regen")
1423 #regenerate cache entries
1424 portage.writemsg_stdout("Regenerating cache entries...\n")
1426 os.close(sys.stdin.fileno())
1427 except SystemExit, e:
1428 raise # Needed else can't exit
1433 regen = MetadataRegen(portdb, max_jobs=max_jobs, max_load=max_load)
1436 portage.writemsg_stdout("done!\n")
1437 return regen.returncode
1439 def action_config(settings, trees, myopts, myfiles):
1440 if len(myfiles) != 1:
1441 print red("!!! config can only take a single package atom at this time\n")
1443 if not is_valid_package_atom(myfiles[0]):
1444 portage.writemsg("!!! '%s' is not a valid package atom.\n" % myfiles[0],
1446 portage.writemsg("!!! Please check ebuild(5) for full details.\n")
1447 portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n")
1451 pkgs = trees[settings["ROOT"]]["vartree"].dbapi.match(myfiles[0])
1452 except portage.exception.AmbiguousPackageName, e:
1453 # Multiple matches thrown from cpv_expand
1456 print "No packages found.\n"
1459 if "--ask" in myopts:
1461 print "Please select a package to configure:"
1465 options.append(str(idx))
1466 print options[-1]+") "+pkg
1469 idx = userquery("Selection?", options)
1472 pkg = pkgs[int(idx)-1]
1474 print "The following packages available:"
1477 print "\nPlease use a specific atom or the --ask option."
1483 if "--ask" in myopts:
1484 if userquery("Ready to configure "+pkg+"?") == "No":
1487 print "Configuring pkg..."
1489 ebuildpath = trees[settings["ROOT"]]["vartree"].dbapi.findname(pkg)
1490 mysettings = portage.config(clone=settings)
1491 vardb = trees[mysettings["ROOT"]]["vartree"].dbapi
1492 debug = mysettings.get("PORTAGE_DEBUG") == "1"
1493 retval = portage.doebuild(ebuildpath, "config", mysettings["ROOT"],
1495 debug=(settings.get("PORTAGE_DEBUG", "") == 1), cleanup=True,
1496 mydbapi=trees[settings["ROOT"]]["vartree"].dbapi, tree="vartree")
1497 if retval == os.EX_OK:
1498 portage.doebuild(ebuildpath, "clean", mysettings["ROOT"],
1499 mysettings, debug=debug, mydbapi=vardb, tree="vartree")
1502 def action_info(settings, trees, myopts, myfiles):
1503 print getportageversion(settings["PORTDIR"], settings["ROOT"],
1504 settings.profile_path, settings["CHOST"],
1505 trees[settings["ROOT"]]["vartree"].dbapi)
1507 header_title = "System Settings"
1509 print header_width * "="
1510 print header_title.rjust(int(header_width/2 + len(header_title)/2))
1511 print header_width * "="
1512 print "System uname: "+platform.platform(aliased=1)
1514 lastSync = portage.grabfile(os.path.join(
1515 settings["PORTDIR"], "metadata", "timestamp.chk"))
1516 print "Timestamp of tree:",
1522 output=commands.getstatusoutput("distcc --version")
1524 print str(output[1].split("\n",1)[0]),
1525 if "distcc" in settings.features:
1530 output=commands.getstatusoutput("ccache -V")
1532 print str(output[1].split("\n",1)[0]),
1533 if "ccache" in settings.features:
1538 myvars = ["sys-devel/autoconf", "sys-devel/automake", "virtual/os-headers",
1539 "sys-devel/binutils", "sys-devel/libtool", "dev-lang/python"]
1540 myvars += portage.util.grabfile(settings["PORTDIR"]+"/profiles/info_pkgs")
1541 myvars = portage.util.unique_array(myvars)
1545 if portage.isvalidatom(x):
1546 pkg_matches = trees["/"]["vartree"].dbapi.match(x)
1547 pkg_matches = [portage.catpkgsplit(cpv)[1:] for cpv in pkg_matches]
1548 pkg_matches.sort(key=cmp_sort_key(portage.pkgcmp))
1550 for pn, ver, rev in pkg_matches:
1552 pkgs.append(ver + "-" + rev)
1556 pkgs = ", ".join(pkgs)
1557 print "%-20s %s" % (x+":", pkgs)
1559 print "%-20s %s" % (x+":", "[NOT VALID]")
1561 libtool_vers = ",".join(trees["/"]["vartree"].dbapi.match("sys-devel/libtool"))
1563 if "--verbose" in myopts:
1564 myvars=settings.keys()
1566 myvars = ['GENTOO_MIRRORS', 'CONFIG_PROTECT', 'CONFIG_PROTECT_MASK',
1567 'PORTDIR', 'DISTDIR', 'PKGDIR', 'PORTAGE_TMPDIR',
1568 'PORTDIR_OVERLAY', 'USE', 'CHOST', 'CFLAGS', 'CXXFLAGS',
1569 'ACCEPT_KEYWORDS', 'SYNC', 'FEATURES', 'EMERGE_DEFAULT_OPTS']
1571 myvars.extend(portage.util.grabfile(settings["PORTDIR"]+"/profiles/info_vars"))
1573 myvars = portage.util.unique_array(myvars)
1574 use_expand = settings.get('USE_EXPAND', '').split()
1576 use_expand_hidden = set(
1577 settings.get('USE_EXPAND_HIDDEN', '').upper().split())
1578 alphabetical_use = '--alphabetical' in myopts
1579 root_config = trees[settings["ROOT"]]['root_config']
1585 print '%s="%s"' % (x, settings[x])
1587 use = set(settings["USE"].split())
1588 for varname in use_expand:
1589 flag_prefix = varname.lower() + "_"
1591 if f.startswith(flag_prefix):
1595 print 'USE="%s"' % " ".join(use),
1596 for varname in use_expand:
1597 myval = settings.get(varname)
1599 print '%s="%s"' % (varname, myval),
1602 unset_vars.append(x)
1604 print "Unset: "+", ".join(unset_vars)
1607 if "--debug" in myopts:
1608 for x in dir(portage):
1609 module = getattr(portage, x)
1610 if "cvs_id_string" in dir(module):
1611 print "%s: %s" % (str(x), str(module.cvs_id_string))
1613 # See if we can find any packages installed matching the strings
1614 # passed on the command line
1616 vardb = trees[settings["ROOT"]]["vartree"].dbapi
1617 portdb = trees[settings["ROOT"]]["porttree"].dbapi
1619 mypkgs.extend(vardb.match(x))
1621 # If some packages were found...
1623 # Get our global settings (we only print stuff if it varies from
1624 # the current config)
1625 mydesiredvars = [ 'CHOST', 'CFLAGS', 'CXXFLAGS', 'LDFLAGS' ]
1626 auxkeys = mydesiredvars + list(vardb._aux_cache_keys)
1627 auxkeys.append('DEFINED_PHASES')
1629 pkgsettings = portage.config(clone=settings)
1631 # Loop through each package
1632 # Only print settings if they differ from global settings
1633 header_title = "Package Settings"
1634 print header_width * "="
1635 print header_title.rjust(int(header_width/2 + len(header_title)/2))
1636 print header_width * "="
1637 from portage.output import EOutput
1640 # Get all package specific variables
1641 metadata = dict(izip(auxkeys, vardb.aux_get(cpv, auxkeys)))
1642 pkg = Package(built=True, cpv=cpv,
1643 installed=True, metadata=izip(Package.metadata_keys,
1644 (metadata.get(x, '') for x in Package.metadata_keys)),
1645 root_config=root_config, type_name='installed')
1647 print "\n%s was built with the following:" % \
1648 colorize("INFORM", str(pkg.cpv))
1650 pkgsettings.setcpv(pkg)
1651 forced_flags = set(chain(pkgsettings.useforce,
1652 pkgsettings.usemask))
1653 use = set(pkg.use.enabled)
1654 use.discard(pkgsettings.get('ARCH'))
1655 use_expand_flags = set()
1658 for varname in use_expand:
1659 flag_prefix = varname.lower() + "_"
1661 if f.startswith(flag_prefix):
1662 use_expand_flags.add(f)
1663 use_enabled.setdefault(
1664 varname.upper(), []).append(f[len(flag_prefix):])
1666 for f in pkg.iuse.all:
1667 if f.startswith(flag_prefix):
1668 use_expand_flags.add(f)
1670 use_disabled.setdefault(
1671 varname.upper(), []).append(f[len(flag_prefix):])
1673 var_order = set(use_enabled)
1674 var_order.update(use_disabled)
1675 var_order = sorted(var_order)
1676 var_order.insert(0, 'USE')
1677 use.difference_update(use_expand_flags)
1678 use_enabled['USE'] = list(use)
1679 use_disabled['USE'] = []
1681 for f in pkg.iuse.all:
1682 if f not in use and \
1683 f not in use_expand_flags:
1684 use_disabled['USE'].append(f)
1686 for varname in var_order:
1687 if varname in use_expand_hidden:
1690 for f in use_enabled.get(varname, []):
1691 flags.append(UseFlagDisplay(f, True, f in forced_flags))
1692 for f in use_disabled.get(varname, []):
1693 flags.append(UseFlagDisplay(f, False, f in forced_flags))
1694 if alphabetical_use:
1695 flags.sort(key=UseFlagDisplay.sort_combined)
1697 flags.sort(key=UseFlagDisplay.sort_separated)
1698 print '%s="%s"' % (varname, ' '.join(str(f) for f in flags)),
1701 for myvar in mydesiredvars:
1702 if metadata[myvar].split() != settings.get(myvar, '').split():
1703 print "%s=\"%s\"" % (myvar, metadata[myvar])
1706 if metadata['DEFINED_PHASES']:
1707 if 'info' not in metadata['DEFINED_PHASES'].split():
1710 print ">>> Attempting to run pkg_info() for '%s'" % pkg.cpv
1711 ebuildpath = vardb.findname(pkg.cpv)
1712 if not ebuildpath or not os.path.exists(ebuildpath):
1713 out.ewarn("No ebuild found for '%s'" % pkg.cpv)
1715 portage.doebuild(ebuildpath, "info", pkgsettings["ROOT"],
1716 pkgsettings, debug=(settings.get("PORTAGE_DEBUG", "") == 1),
1717 mydbapi=trees[settings["ROOT"]]["vartree"].dbapi,
1720 def action_search(root_config, myopts, myfiles, spinner):
1722 print "emerge: no search terms provided."
1724 searchinstance = search(root_config,
1725 spinner, "--searchdesc" in myopts,
1726 "--quiet" not in myopts, "--usepkg" in myopts,
1727 "--usepkgonly" in myopts)
1728 for mysearch in myfiles:
1730 searchinstance.execute(mysearch)
1731 except re.error, comment:
1732 print "\n!!! Regular expression error in \"%s\": %s" % ( mysearch, comment )
1734 searchinstance.output()
1736 def action_uninstall(settings, trees, ldpath_mtimes,
1737 opts, action, files, spinner):
1739 # For backward compat, some actions do not require leading '='.
1740 ignore_missing_eq = action in ('clean', 'unmerge')
1741 root = settings['ROOT']
1742 vardb = trees[root]['vartree'].dbapi
1746 # Ensure atoms are valid before calling unmerge().
1747 # For backward compat, leading '=' is not required.
1749 if is_valid_package_atom(x) or \
1750 (ignore_missing_eq and is_valid_package_atom('=' + x)):
1754 portage.dep_expand(x, mydb=vardb, settings=settings))
1755 except portage.exception.AmbiguousPackageName, e:
1756 msg = "The short ebuild name \"" + x + \
1757 "\" is ambiguous. Please specify " + \
1758 "one of the following " + \
1759 "fully-qualified ebuild names instead:"
1760 for line in textwrap.wrap(msg, 70):
1761 writemsg_level("!!! %s\n" % (line,),
1762 level=logging.ERROR, noiselevel=-1)
1764 writemsg_level(" %s\n" % colorize("INFORM", i),
1765 level=logging.ERROR, noiselevel=-1)
1766 writemsg_level("\n", level=logging.ERROR, noiselevel=-1)
1769 elif x.startswith(os.sep):
1770 if not x.startswith(root):
1771 writemsg_level(("!!! '%s' does not start with" + \
1772 " $ROOT.\n") % x, level=logging.ERROR, noiselevel=-1)
1774 # Queue these up since it's most efficient to handle
1775 # multiple files in a single iter_owners() call.
1776 lookup_owners.append(x)
1780 msg.append("'%s' is not a valid package atom." % (x,))
1781 msg.append("Please check ebuild(5) for full details.")
1782 writemsg_level("".join("!!! %s\n" % line for line in msg),
1783 level=logging.ERROR, noiselevel=-1)
1788 search_for_multiple = False
1789 if len(lookup_owners) > 1:
1790 search_for_multiple = True
1792 for x in lookup_owners:
1793 if not search_for_multiple and os.path.isdir(x):
1794 search_for_multiple = True
1795 relative_paths.append(x[len(root):])
1798 for pkg, relative_path in \
1799 vardb._owners.iter_owners(relative_paths):
1800 owners.add(pkg.mycpv)
1801 if not search_for_multiple:
1806 slot = vardb.aux_get(cpv, ['SLOT'])[0]
1808 # portage now masks packages with missing slot, but it's
1809 # possible that one was installed by an older version
1810 atom = portage.cpv_getkey(cpv)
1812 atom = '%s:%s' % (portage.cpv_getkey(cpv), slot)
1813 valid_atoms.append(portage.dep.Atom(atom))
1815 writemsg_level(("!!! '%s' is not claimed " + \
1816 "by any package.\n") % lookup_owners[0],
1817 level=logging.WARNING, noiselevel=-1)
1819 if files and not valid_atoms:
1822 if action in ('clean', 'unmerge') or \
1823 (action == 'prune' and "--nodeps" in opts):
1824 # When given a list of atoms, unmerge them in the order given.
1825 ordered = action == 'unmerge'
1826 unmerge(trees[settings["ROOT"]]['root_config'], opts, action,
1827 valid_atoms, ldpath_mtimes, ordered=ordered)
1829 elif action == 'deselect':
1830 rval = action_deselect(settings, trees, opts, valid_atoms)
1832 rval = action_depclean(settings, trees, ldpath_mtimes,
1833 opts, action, valid_atoms, spinner)
1837 def action_deselect(settings, trees, opts, atoms):
1838 root_config = trees[settings['ROOT']]['root_config']
1839 world_set = root_config.sets['world']
1840 if not hasattr(world_set, 'update'):
1841 writemsg_level("World set does not appear to be mutable.\n",
1842 level=logging.ERROR, noiselevel=-1)
1845 vardb = root_config.trees['vartree'].dbapi
1846 expanded_atoms = set(atoms)
1847 from portage.dep import Atom
1849 for cpv in vardb.match(atom):
1850 slot, = vardb.aux_get(cpv, ['SLOT'])
1853 expanded_atoms.add(Atom('%s:%s' % (portage.cpv_getkey(cpv), slot)))
1855 pretend = '--pretend' in opts
1857 if not pretend and hasattr(world_set, 'lock'):
1861 discard_atoms = set()
1863 for atom in world_set:
1864 if not isinstance(atom, Atom):
1867 for arg_atom in expanded_atoms:
1868 if arg_atom.intersects(atom) and \
1869 not (arg_atom.slot and not atom.slot):
1870 discard_atoms.add(atom)
1873 for atom in sorted(discard_atoms):
1874 print ">>> Removing %s from \"world\" favorites file..." % \
1875 colorize("INFORM", str(atom))
1878 prompt = "Would you like to remove these " + \
1879 "packages from your world favorites?"
1880 if userquery(prompt) == 'No':
1883 remaining = set(world_set)
1884 remaining.difference_update(discard_atoms)
1886 world_set.replace(remaining)
1888 print ">>> No matching atoms found in \"world\" favorites file..."
1894 def action_depclean(settings, trees, ldpath_mtimes,
1895 myopts, action, myfiles, spinner):
1896 # Kill packages that aren't explicitly merged or are required as a
1897 # dependency of another package. World file is explicit.
1899 # Global depclean or prune operations are not very safe when there are
1900 # missing dependencies since it's unknown how badly incomplete
1901 # the dependency graph is, and we might accidentally remove packages
1902 # that should have been pulled into the graph. On the other hand, it's
1903 # relatively safe to ignore missing deps when only asked to remove
1904 # specific packages.
1905 allow_missing_deps = len(myfiles) > 0
1908 msg.append("Always study the list of packages to be cleaned for any obvious\n")
1909 msg.append("mistakes. Packages that are part of the world set will always\n")
1910 msg.append("be kept. They can be manually added to this set with\n")
1911 msg.append(good("`emerge --noreplace <atom>`") + ". Packages that are listed in\n")
1912 msg.append("package.provided (see portage(5)) will be removed by\n")
1913 msg.append("depclean, even if they are part of the world set.\n")
1915 msg.append("As a safety measure, depclean will not remove any packages\n")
1916 msg.append("unless *all* required dependencies have been resolved. As a\n")
1917 msg.append("consequence, it is often necessary to run %s\n" % \
1918 good("`emerge --update"))
1919 msg.append(good("--newuse --deep @system @world`") + \
1920 " prior to depclean.\n")
1922 if action == "depclean" and "--quiet" not in myopts and not myfiles:
1923 portage.writemsg_stdout("\n")
1925 portage.writemsg_stdout(colorize("WARN", " * ") + x)
1927 xterm_titles = "notitles" not in settings.features
1928 myroot = settings["ROOT"]
1929 root_config = trees[myroot]["root_config"]
1930 getSetAtoms = root_config.setconfig.getSetAtoms
1931 vardb = trees[myroot]["vartree"].dbapi
1932 deselect = myopts.get('--deselect') != 'n'
1934 required_set_names = ("system", "world")
1938 for s in required_set_names:
1939 required_sets[s] = InternalPackageSet(
1940 initial_atoms=getSetAtoms(s))
1943 # When removing packages, use a temporary version of world
1944 # which excludes packages that are intended to be eligible for
1946 world_temp_set = required_sets["world"]
1947 system_set = required_sets["system"]
1949 if not system_set or not world_temp_set:
1952 writemsg_level("!!! You have no system list.\n",
1953 level=logging.ERROR, noiselevel=-1)
1955 if not world_temp_set:
1956 writemsg_level("!!! You have no world file.\n",
1957 level=logging.WARNING, noiselevel=-1)
1959 writemsg_level("!!! Proceeding is likely to " + \
1960 "break your installation.\n",
1961 level=logging.WARNING, noiselevel=-1)
1962 if "--pretend" not in myopts:
1963 countdown(int(settings["EMERGE_WARNING_DELAY"]), ">>> Depclean")
1965 if action == "depclean":
1966 emergelog(xterm_titles, " >>> depclean")
1969 args_set = InternalPackageSet()
1971 args_set.update(myfiles)
1972 matched_packages = False
1975 matched_packages = True
1977 if not matched_packages:
1978 writemsg_level(">>> No packages selected for removal by %s\n" % \
1982 writemsg_level("\nCalculating dependencies ")
1983 resolver_params = create_depgraph_params(myopts, "remove")
1984 resolver = depgraph(settings, trees, myopts, resolver_params, spinner)
1985 vardb = resolver.trees[myroot]["vartree"].dbapi
1987 if action == "depclean":
1992 world_temp_set.clear()
1994 # Pull in everything that's installed but not matched
1995 # by an argument atom since we don't want to clean any
1996 # package if something depends on it.
2001 if args_set.findAtomForPackage(pkg) is None:
2002 world_temp_set.add("=" + pkg.cpv)
2004 except portage.exception.InvalidDependString, e:
2005 show_invalid_depstring_notice(pkg,
2006 pkg.metadata["PROVIDE"], str(e))
2008 world_temp_set.add("=" + pkg.cpv)
2011 elif action == "prune":
2014 world_temp_set.clear()
2016 # Pull in everything that's installed since we don't
2017 # to prune a package if something depends on it.
2018 world_temp_set.update(vardb.cp_all())
2022 # Try to prune everything that's slotted.
2023 for cp in vardb.cp_all():
2024 if len(vardb.cp_list(cp)) > 1:
2027 # Remove atoms from world that match installed packages
2028 # that are also matched by argument atoms, but do not remove
2029 # them if they match the highest installed version.
2032 pkgs_for_cp = vardb.match_pkgs(pkg.cp)
2033 if not pkgs_for_cp or pkg not in pkgs_for_cp:
2034 raise AssertionError("package expected in matches: " + \
2035 "cp = %s, cpv = %s matches = %s" % \
2036 (pkg.cp, pkg.cpv, [str(x) for x in pkgs_for_cp]))
2038 highest_version = pkgs_for_cp[-1]
2039 if pkg == highest_version:
2040 # pkg is the highest version
2041 world_temp_set.add("=" + pkg.cpv)
2044 if len(pkgs_for_cp) <= 1:
2045 raise AssertionError("more packages expected: " + \
2046 "cp = %s, cpv = %s matches = %s" % \
2047 (pkg.cp, pkg.cpv, [str(x) for x in pkgs_for_cp]))
2050 if args_set.findAtomForPackage(pkg) is None:
2051 world_temp_set.add("=" + pkg.cpv)
2053 except portage.exception.InvalidDependString, e:
2054 show_invalid_depstring_notice(pkg,
2055 pkg.metadata["PROVIDE"], str(e))
2057 world_temp_set.add("=" + pkg.cpv)
2061 for s, package_set in required_sets.iteritems():
2062 set_atom = SETPREFIX + s
2063 set_arg = SetArg(arg=set_atom, set=package_set,
2064 root_config=resolver.roots[myroot])
2065 set_args[s] = set_arg
2066 for atom in set_arg.set:
2067 resolver._dep_stack.append(
2068 Dependency(atom=atom, root=myroot, parent=set_arg))
2069 resolver.digraph.add(set_arg, None)
2071 success = resolver._complete_graph()
2072 writemsg_level("\b\b... done!\n")
2074 resolver.display_problems()
2079 def unresolved_deps():
2081 unresolvable = set()
2082 for dep in resolver._initially_unsatisfied_deps:
2083 if isinstance(dep.parent, Package) and \
2084 (dep.priority > UnmergeDepPriority.SOFT):
2085 unresolvable.add((dep.atom, dep.parent.cpv))
2087 if not unresolvable:
2090 if unresolvable and not allow_missing_deps:
2093 msg.append("Dependencies could not be completely resolved due to")
2094 msg.append("the following required packages not being installed:")
2096 for atom, parent in unresolvable:
2097 msg.append(" %s pulled in by:" % (atom,))
2098 msg.append(" %s" % (parent,))
2100 msg.append("Have you forgotten to run " + \
2101 good("`emerge --update --newuse --deep @system @world`") + " prior")
2102 msg.append(("to %s? It may be necessary to manually " + \
2103 "uninstall packages that no longer") % action)
2104 msg.append("exist in the portage tree since " + \
2105 "it may not be possible to satisfy their")
2106 msg.append("dependencies. Also, be aware of " + \
2107 "the --with-bdeps option that is documented")
2108 msg.append("in " + good("`man emerge`") + ".")
2109 if action == "prune":
2111 msg.append("If you would like to ignore " + \
2112 "dependencies then use %s." % good("--nodeps"))
2113 writemsg_level("".join("%s%s\n" % (prefix, line) for line in msg),
2114 level=logging.ERROR, noiselevel=-1)
2118 if unresolved_deps():
2121 graph = resolver.digraph.copy()
2122 required_pkgs_total = 0
2124 if isinstance(node, Package):
2125 required_pkgs_total += 1
2127 def show_parents(child_node):
2128 parent_nodes = graph.parent_nodes(child_node)
2129 if not parent_nodes:
2130 # With --prune, the highest version can be pulled in without any
2131 # real parent since all installed packages are pulled in. In that
2132 # case there's nothing to show here.
2135 for node in parent_nodes:
2136 parent_strs.append(str(getattr(node, "cpv", node)))
2139 msg.append(" %s pulled in by:\n" % (child_node.cpv,))
2140 for parent_str in parent_strs:
2141 msg.append(" %s\n" % (parent_str,))
2143 portage.writemsg_stdout("".join(msg), noiselevel=-1)
2145 def cmp_pkg_cpv(pkg1, pkg2):
2146 """Sort Package instances by cpv."""
2147 if pkg1.cpv > pkg2.cpv:
2149 elif pkg1.cpv == pkg2.cpv:
2154 def create_cleanlist():
2157 if action == "depclean":
2160 for pkg in sorted(vardb, key=cmp_sort_key(cmp_pkg_cpv)):
2163 arg_atom = args_set.findAtomForPackage(pkg)
2164 except portage.exception.InvalidDependString:
2165 # this error has already been displayed by now
2169 if pkg not in graph:
2170 pkgs_to_remove.append(pkg)
2171 elif "--verbose" in myopts:
2175 for pkg in sorted(vardb, key=cmp_sort_key(cmp_pkg_cpv)):
2176 if pkg not in graph:
2177 pkgs_to_remove.append(pkg)
2178 elif "--verbose" in myopts:
2181 elif action == "prune":
2182 # Prune really uses all installed instead of world. It's not
2183 # a real reverse dependency so don't display it as such.
2184 graph.remove(set_args["world"])
2186 for atom in args_set:
2187 for pkg in vardb.match_pkgs(atom):
2188 if pkg not in graph:
2189 pkgs_to_remove.append(pkg)
2190 elif "--verbose" in myopts:
2193 if not pkgs_to_remove:
2195 ">>> No packages selected for removal by %s\n" % action)
2196 if "--verbose" not in myopts:
2198 ">>> To see reverse dependencies, use %s\n" % \
2200 if action == "prune":
2202 ">>> To ignore dependencies, use %s\n" % \
2205 return pkgs_to_remove
2207 cleanlist = create_cleanlist()
2210 clean_set = set(cleanlist)
2212 # Check if any of these package are the sole providers of libraries
2213 # with consumers that have not been selected for removal. If so, these
2214 # packages and any dependencies need to be added to the graph.
2215 real_vardb = trees[myroot]["vartree"].dbapi
2216 linkmap = real_vardb.linkmap
2217 liblist = linkmap.listLibraryObjects()
2223 writemsg_level(">>> Checking for lib consumers...\n")
2225 for pkg in cleanlist:
2226 pkg_dblink = real_vardb._dblink(pkg.cpv)
2227 provided_libs = set()
2230 if pkg_dblink.isowner(lib, myroot):
2231 provided_libs.add(lib)
2233 if not provided_libs:
2237 for lib in provided_libs:
2238 lib_consumers = consumer_cache.get(lib)
2239 if lib_consumers is None:
2240 lib_consumers = linkmap.findConsumers(lib)
2241 consumer_cache[lib] = lib_consumers
2243 consumers[lib] = lib_consumers
2248 for lib, lib_consumers in consumers.items():
2249 for consumer_file in list(lib_consumers):
2250 if pkg_dblink.isowner(consumer_file, myroot):
2251 lib_consumers.remove(consumer_file)
2252 if not lib_consumers:
2258 for lib, lib_consumers in consumers.iteritems():
2260 soname = soname_cache.get(lib)
2262 soname = linkmap.getSoname(lib)
2263 soname_cache[lib] = soname
2265 consumer_providers = []
2266 for lib_consumer in lib_consumers:
2267 providers = provider_cache.get(lib)
2268 if providers is None:
2269 providers = linkmap.findProviders(lib_consumer)
2270 provider_cache[lib_consumer] = providers
2271 if soname not in providers:
2272 # Why does this happen?
2274 consumer_providers.append(
2275 (lib_consumer, providers[soname]))
2277 consumers[lib] = consumer_providers
2279 consumer_map[pkg] = consumers
2283 search_files = set()
2284 for consumers in consumer_map.itervalues():
2285 for lib, consumer_providers in consumers.iteritems():
2286 for lib_consumer, providers in consumer_providers:
2287 search_files.add(lib_consumer)
2288 search_files.update(providers)
2290 writemsg_level(">>> Assigning files to packages...\n")
2291 file_owners = real_vardb._owners.getFileOwnerMap(search_files)
2293 for pkg, consumers in consumer_map.items():
2294 for lib, consumer_providers in consumers.items():
2295 lib_consumers = set()
2297 for lib_consumer, providers in consumer_providers:
2298 owner_set = file_owners.get(lib_consumer)
2299 provider_dblinks = set()
2300 provider_pkgs = set()
2302 if len(providers) > 1:
2303 for provider in providers:
2304 provider_set = file_owners.get(provider)
2305 if provider_set is not None:
2306 provider_dblinks.update(provider_set)
2308 if len(provider_dblinks) > 1:
2309 for provider_dblink in provider_dblinks:
2310 pkg_key = ("installed", myroot,
2311 provider_dblink.mycpv, "nomerge")
2312 if pkg_key not in clean_set:
2313 provider_pkgs.add(vardb.get(pkg_key))
2318 if owner_set is not None:
2319 lib_consumers.update(owner_set)
2321 for consumer_dblink in list(lib_consumers):
2322 if ("installed", myroot, consumer_dblink.mycpv,
2323 "nomerge") in clean_set:
2324 lib_consumers.remove(consumer_dblink)
2328 consumers[lib] = lib_consumers
2332 del consumer_map[pkg]
2335 # TODO: Implement a package set for rebuilding consumer packages.
2337 msg = "In order to avoid breakage of link level " + \
2338 "dependencies, one or more packages will not be removed. " + \
2339 "This can be solved by rebuilding " + \
2340 "the packages that pulled them in."
2343 from textwrap import wrap
2344 writemsg_level("".join(prefix + "%s\n" % line for \
2345 line in wrap(msg, 70)), level=logging.WARNING, noiselevel=-1)
2348 for pkg, consumers in consumer_map.iteritems():
2349 unique_consumers = set(chain(*consumers.values()))
2350 unique_consumers = sorted(consumer.mycpv \
2351 for consumer in unique_consumers)
2353 msg.append(" %s pulled in by:" % (pkg.cpv,))
2354 for consumer in unique_consumers:
2355 msg.append(" %s" % (consumer,))
2357 writemsg_level("".join(prefix + "%s\n" % line for line in msg),
2358 level=logging.WARNING, noiselevel=-1)
2360 # Add lib providers to the graph as children of lib consumers,
2361 # and also add any dependencies pulled in by the provider.
2362 writemsg_level(">>> Adding lib providers to graph...\n")
2364 for pkg, consumers in consumer_map.iteritems():
2365 for consumer_dblink in set(chain(*consumers.values())):
2366 consumer_pkg = vardb.get(("installed", myroot,
2367 consumer_dblink.mycpv, "nomerge"))
2368 if not resolver._add_pkg(pkg,
2369 Dependency(parent=consumer_pkg,
2370 priority=UnmergeDepPriority(runtime=True),
2372 resolver.display_problems()
2375 writemsg_level("\nCalculating dependencies ")
2376 success = resolver._complete_graph()
2377 writemsg_level("\b\b... done!\n")
2378 resolver.display_problems()
2381 if unresolved_deps():
2384 graph = resolver.digraph.copy()
2385 required_pkgs_total = 0
2387 if isinstance(node, Package):
2388 required_pkgs_total += 1
2389 cleanlist = create_cleanlist()
2392 clean_set = set(cleanlist)
2394 # Use a topological sort to create an unmerge order such that
2395 # each package is unmerged before it's dependencies. This is
2396 # necessary to avoid breaking things that may need to run
2397 # during pkg_prerm or pkg_postrm phases.
2399 # Create a new graph to account for dependencies between the
2400 # packages being unmerged.
2404 dep_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
2405 runtime = UnmergeDepPriority(runtime=True)
2406 runtime_post = UnmergeDepPriority(runtime_post=True)
2407 buildtime = UnmergeDepPriority(buildtime=True)
2410 "PDEPEND": runtime_post,
2411 "DEPEND": buildtime,
2414 for node in clean_set:
2415 graph.add(node, None)
2417 node_use = node.metadata["USE"].split()
2418 for dep_type in dep_keys:
2419 depstr = node.metadata[dep_type]
2423 portage.dep._dep_check_strict = False
2424 success, atoms = portage.dep_check(depstr, None, settings,
2425 myuse=node_use, trees=resolver._graph_trees,
2428 portage.dep._dep_check_strict = True
2430 # Ignore invalid deps of packages that will
2431 # be uninstalled anyway.
2434 priority = priority_map[dep_type]
2436 if not isinstance(atom, portage.dep.Atom):
2437 # Ignore invalid atoms returned from dep_check().
2441 matches = vardb.match_pkgs(atom)
2444 for child_node in matches:
2445 if child_node in clean_set:
2446 graph.add(child_node, node, priority=priority)
2449 if len(graph.order) == len(graph.root_nodes()):
2450 # If there are no dependencies between packages
2451 # let unmerge() group them by cat/pn.
2453 cleanlist = [pkg.cpv for pkg in graph.order]
2455 # Order nodes from lowest to highest overall reference count for
2456 # optimal root node selection.
2458 for node in graph.order:
2459 node_refcounts[node] = len(graph.parent_nodes(node))
2460 def cmp_reference_count(node1, node2):
2461 return node_refcounts[node1] - node_refcounts[node2]
2462 graph.order.sort(key=cmp_sort_key(cmp_reference_count))
2464 ignore_priority_range = [None]
2465 ignore_priority_range.extend(
2466 xrange(UnmergeDepPriority.MIN, UnmergeDepPriority.MAX + 1))
2467 while not graph.empty():
2468 for ignore_priority in ignore_priority_range:
2469 nodes = graph.root_nodes(ignore_priority=ignore_priority)
2473 raise AssertionError("no root nodes")
2474 if ignore_priority is not None:
2475 # Some deps have been dropped due to circular dependencies,
2476 # so only pop one node in order do minimize the number that
2481 cleanlist.append(node.cpv)
2483 unmerge(root_config, myopts, "unmerge", cleanlist,
2484 ldpath_mtimes, ordered=ordered)
2486 if action == "prune":
2489 if not cleanlist and "--quiet" in myopts:
2492 print "Packages installed: "+str(len(vardb.cpv_all()))
2493 print "Packages in world: " + \
2494 str(len(root_config.sets["world"].getAtoms()))
2495 print "Packages in system: " + \
2496 str(len(root_config.sets["system"].getAtoms()))
2497 print "Required packages: "+str(required_pkgs_total)
2498 if "--pretend" in myopts:
2499 print "Number to remove: "+str(len(cleanlist))
2501 print "Number removed: "+str(len(cleanlist))
2503 def action_build(settings, trees, mtimedb,
2504 myopts, myaction, myfiles, spinner):
2506 # validate the state of the resume data
2507 # so that we can make assumptions later.
2508 for k in ("resume", "resume_backup"):
2509 if k not in mtimedb:
2511 resume_data = mtimedb[k]
2512 if not isinstance(resume_data, dict):
2515 mergelist = resume_data.get("mergelist")
2516 if not isinstance(mergelist, list):
2520 if not (isinstance(x, list) and len(x) == 4):
2522 pkg_type, pkg_root, pkg_key, pkg_action = x
2523 if pkg_root not in trees:
2524 # Current $ROOT setting differs,
2525 # so the list must be stale.
2531 resume_opts = resume_data.get("myopts")
2532 if not isinstance(resume_opts, (dict, list)):
2535 favorites = resume_data.get("favorites")
2536 if not isinstance(favorites, list):
2541 if "--resume" in myopts and \
2542 ("resume" in mtimedb or
2543 "resume_backup" in mtimedb):
2545 if "resume" not in mtimedb:
2546 mtimedb["resume"] = mtimedb["resume_backup"]
2547 del mtimedb["resume_backup"]
2549 # "myopts" is a list for backward compatibility.
2550 resume_opts = mtimedb["resume"].get("myopts", [])
2551 if isinstance(resume_opts, list):
2552 resume_opts = dict((k,True) for k in resume_opts)
2553 for opt in ("--ask", "--color", "--skipfirst", "--tree"):
2554 resume_opts.pop(opt, None)
2556 # Current options always override resume_opts.
2557 resume_opts.update(myopts)
2559 myopts.update(resume_opts)
2561 if "--debug" in myopts:
2562 writemsg_level("myopts %s\n" % (myopts,))
2564 # Adjust config according to options of the command being resumed.
2565 for myroot in trees:
2566 mysettings = trees[myroot]["vartree"].settings
2568 adjust_config(myopts, mysettings)
2570 del myroot, mysettings
2572 ldpath_mtimes = mtimedb["ldpath"]
2575 buildpkgonly = "--buildpkgonly" in myopts
2576 pretend = "--pretend" in myopts
2577 fetchonly = "--fetchonly" in myopts or "--fetch-all-uri" in myopts
2578 ask = "--ask" in myopts
2579 nodeps = "--nodeps" in myopts
2580 oneshot = "--oneshot" in myopts or "--onlydeps" in myopts
2581 tree = "--tree" in myopts
2584 del myopts["--tree"]
2585 portage.writemsg(colorize("WARN", " * ") + \
2586 "--tree is broken with --nodeps. Disabling...\n")
2587 debug = "--debug" in myopts
2588 verbose = "--verbose" in myopts
2589 quiet = "--quiet" in myopts
2590 if pretend or fetchonly:
2591 # make the mtimedb readonly
2592 mtimedb.filename = None
2593 if '--digest' in myopts or 'digest' in settings.features:
2594 if '--digest' in myopts:
2595 msg = "The --digest option"
2597 msg = "The FEATURES=digest setting"
2599 msg += " can prevent corruption from being" + \
2600 " noticed. The `repoman manifest` command is the preferred" + \
2601 " way to generate manifests and it is capable of doing an" + \
2602 " entire repository or category at once."
2604 writemsg(prefix + "\n")
2605 from textwrap import wrap
2606 for line in wrap(msg, 72):
2607 writemsg("%s%s\n" % (prefix, line))
2608 writemsg(prefix + "\n")
2610 if "--quiet" not in myopts and \
2611 ("--pretend" in myopts or "--ask" in myopts or \
2612 "--tree" in myopts or "--verbose" in myopts):
2614 if "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
2616 elif "--buildpkgonly" in myopts:
2620 if "--tree" in myopts and action != "fetched": # Tree doesn't work with fetching
2622 print darkgreen("These are the packages that would be %s, in reverse order:") % action
2626 print darkgreen("These are the packages that would be %s, in order:") % action
2629 show_spinner = "--quiet" not in myopts and "--nodeps" not in myopts
2630 if not show_spinner:
2631 spinner.update = spinner.update_quiet
2634 favorites = mtimedb["resume"].get("favorites")
2635 if not isinstance(favorites, list):
2639 print "Calculating dependencies ",
2640 myparams = create_depgraph_params(myopts, myaction)
2642 resume_data = mtimedb["resume"]
2643 mergelist = resume_data["mergelist"]
2644 if mergelist and "--skipfirst" in myopts:
2645 for i, task in enumerate(mergelist):
2646 if isinstance(task, list) and \
2647 task and task[-1] == "merge":
2654 success, mydepgraph, dropped_tasks = resume_depgraph(
2655 settings, trees, mtimedb, myopts, myparams, spinner)
2656 except (portage.exception.PackageNotFound,
2657 depgraph.UnsatisfiedResumeDep), e:
2658 if isinstance(e, depgraph.UnsatisfiedResumeDep):
2659 mydepgraph = e.depgraph
2662 from textwrap import wrap
2663 from portage.output import EOutput
2666 resume_data = mtimedb["resume"]
2667 mergelist = resume_data.get("mergelist")
2668 if not isinstance(mergelist, list):
2670 if mergelist and debug or (verbose and not quiet):
2671 out.eerror("Invalid resume list:")
2674 for task in mergelist:
2675 if isinstance(task, list):
2676 out.eerror(indent + str(tuple(task)))
2679 if isinstance(e, depgraph.UnsatisfiedResumeDep):
2680 out.eerror("One or more packages are either masked or " + \
2681 "have missing dependencies:")
2685 if dep.atom is None:
2686 out.eerror(indent + "Masked package:")
2687 out.eerror(2 * indent + str(dep.parent))
2690 out.eerror(indent + str(dep.atom) + " pulled in by:")
2691 out.eerror(2 * indent + str(dep.parent))
2693 msg = "The resume list contains packages " + \
2694 "that are either masked or have " + \
2695 "unsatisfied dependencies. " + \
2696 "Please restart/continue " + \
2697 "the operation manually, or use --skipfirst " + \
2698 "to skip the first package in the list and " + \
2699 "any other packages that may be " + \
2700 "masked or have missing dependencies."
2701 for line in wrap(msg, 72):
2703 elif isinstance(e, portage.exception.PackageNotFound):
2704 out.eerror("An expected package is " + \
2705 "not available: %s" % str(e))
2707 msg = "The resume list contains one or more " + \
2708 "packages that are no longer " + \
2709 "available. Please restart/continue " + \
2710 "the operation manually."
2711 for line in wrap(msg, 72):
2715 print "\b\b... done!"
2719 portage.writemsg("!!! One or more packages have been " + \
2720 "dropped due to\n" + \
2721 "!!! masking or unsatisfied dependencies:\n\n",
2723 for task in dropped_tasks:
2724 portage.writemsg(" " + str(task) + "\n", noiselevel=-1)
2725 portage.writemsg("\n", noiselevel=-1)
2728 if mydepgraph is not None:
2729 mydepgraph.display_problems()
2730 if not (ask or pretend):
2731 # delete the current list and also the backup
2732 # since it's probably stale too.
2733 for k in ("resume", "resume_backup"):
2734 mtimedb.pop(k, None)
2739 if ("--resume" in myopts):
2740 print darkgreen("emerge: It seems we have nothing to resume...")
2743 myparams = create_depgraph_params(myopts, myaction)
2744 if "--quiet" not in myopts and "--nodeps" not in myopts:
2745 print "Calculating dependencies ",
2747 mydepgraph = depgraph(settings, trees, myopts, myparams, spinner)
2749 retval, favorites = mydepgraph.select_files(myfiles)
2750 except portage.exception.PackageNotFound, e:
2751 portage.writemsg("\n!!! %s\n" % str(e), noiselevel=-1)
2753 except portage.exception.PackageSetNotFound, e:
2754 root_config = trees[settings["ROOT"]]["root_config"]
2755 display_missing_pkg_set(root_config, e.value)
2758 print "\b\b... done!"
2760 mydepgraph.display_problems()
2763 if "--pretend" not in myopts and \
2764 ("--ask" in myopts or "--tree" in myopts or \
2765 "--verbose" in myopts) and \
2766 not ("--quiet" in myopts and "--ask" not in myopts):
2767 if "--resume" in myopts:
2768 mymergelist = mydepgraph.altlist()
2769 if len(mymergelist) == 0:
2770 print colorize("INFORM", "emerge: It seems we have nothing to resume...")
2772 favorites = mtimedb["resume"]["favorites"]
2773 retval = mydepgraph.display(
2774 mydepgraph.altlist(reversed=tree),
2775 favorites=favorites)
2776 mydepgraph.display_problems()
2777 if retval != os.EX_OK:
2779 prompt="Would you like to resume merging these packages?"
2781 retval = mydepgraph.display(
2782 mydepgraph.altlist(reversed=("--tree" in myopts)),
2783 favorites=favorites)
2784 mydepgraph.display_problems()
2785 if retval != os.EX_OK:
2788 for x in mydepgraph.altlist():
2789 if isinstance(x, Package) and x.operation == "merge":
2793 sets = trees[settings["ROOT"]]["root_config"].sets
2794 world_candidates = None
2795 if "--noreplace" in myopts and \
2796 not oneshot and favorites:
2797 # Sets that are not world candidates are filtered
2798 # out here since the favorites list needs to be
2799 # complete for depgraph.loadResumeCommand() to
2800 # operate correctly.
2801 world_candidates = [x for x in favorites \
2802 if not (x.startswith(SETPREFIX) and \
2803 not sets[x[1:]].world_candidate)]
2804 if "--noreplace" in myopts and \
2805 not oneshot and world_candidates:
2807 for x in world_candidates:
2808 print " %s %s" % (good("*"), x)
2809 prompt="Would you like to add these packages to your world favorites?"
2810 elif settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]:
2811 prompt="Nothing to merge; would you like to auto-clean packages?"
2814 print "Nothing to merge; quitting."
2817 elif "--fetchonly" in myopts or "--fetch-all-uri" in myopts:
2818 prompt="Would you like to fetch the source files for these packages?"
2820 prompt="Would you like to merge these packages?"
2822 if "--ask" in myopts and userquery(prompt) == "No":
2827 # Don't ask again (e.g. when auto-cleaning packages after merge)
2828 myopts.pop("--ask", None)
2830 if ("--pretend" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts):
2831 if ("--resume" in myopts):
2832 mymergelist = mydepgraph.altlist()
2833 if len(mymergelist) == 0:
2834 print colorize("INFORM", "emerge: It seems we have nothing to resume...")
2836 favorites = mtimedb["resume"]["favorites"]
2837 retval = mydepgraph.display(
2838 mydepgraph.altlist(reversed=tree),
2839 favorites=favorites)
2840 mydepgraph.display_problems()
2841 if retval != os.EX_OK:
2844 retval = mydepgraph.display(
2845 mydepgraph.altlist(reversed=("--tree" in myopts)),
2846 favorites=favorites)
2847 mydepgraph.display_problems()
2848 if retval != os.EX_OK:
2850 if "--buildpkgonly" in myopts:
2851 graph_copy = mydepgraph.digraph.clone()
2852 removed_nodes = set()
2853 for node in graph_copy:
2854 if not isinstance(node, Package) or \
2855 node.operation == "nomerge":
2856 removed_nodes.add(node)
2857 graph_copy.difference_update(removed_nodes)
2858 if not graph_copy.hasallzeros(ignore_priority = \
2859 DepPrioritySatisfiedRange.ignore_medium):
2860 print "\n!!! --buildpkgonly requires all dependencies to be merged."
2861 print "!!! You have to merge the dependencies before you can build this package.\n"
2864 if "--buildpkgonly" in myopts:
2865 graph_copy = mydepgraph.digraph.clone()
2866 removed_nodes = set()
2867 for node in graph_copy:
2868 if not isinstance(node, Package) or \
2869 node.operation == "nomerge":
2870 removed_nodes.add(node)
2871 graph_copy.difference_update(removed_nodes)
2872 if not graph_copy.hasallzeros(ignore_priority = \
2873 DepPrioritySatisfiedRange.ignore_medium):
2874 print "\n!!! --buildpkgonly requires all dependencies to be merged."
2875 print "!!! Cannot merge requested packages. Merge deps and try again.\n"
2878 if ("--resume" in myopts):
2879 favorites=mtimedb["resume"]["favorites"]
2880 mymergelist = mydepgraph.altlist()
2881 mydepgraph.break_refs(mymergelist)
2882 mergetask = Scheduler(settings, trees, mtimedb, myopts,
2883 spinner, mymergelist, favorites, mydepgraph.schedulerGraph())
2884 del mydepgraph, mymergelist
2887 retval = mergetask.merge()
2888 merge_count = mergetask.curval
2890 if "resume" in mtimedb and \
2891 "mergelist" in mtimedb["resume"] and \
2892 len(mtimedb["resume"]["mergelist"]) > 1:
2893 mtimedb["resume_backup"] = mtimedb["resume"]
2894 del mtimedb["resume"]
2896 mtimedb["resume"]={}
2897 # Stored as a dict starting with portage-2.1.6_rc1, and supported
2898 # by >=portage-2.1.3_rc8. Versions <portage-2.1.3_rc8 only support
2899 # a list type for options.
2900 mtimedb["resume"]["myopts"] = myopts.copy()
2902 # Convert Atom instances to plain str.
2903 mtimedb["resume"]["favorites"] = [str(x) for x in favorites]
2905 pkglist = mydepgraph.altlist()
2906 mydepgraph.saveNomergeFavorites()
2907 mydepgraph.break_refs(pkglist)
2908 mergetask = Scheduler(settings, trees, mtimedb, myopts,
2909 spinner, pkglist, favorites, mydepgraph.schedulerGraph())
2910 del mydepgraph, pkglist
2913 retval = mergetask.merge()
2914 merge_count = mergetask.curval
2916 if retval == os.EX_OK and not (buildpkgonly or fetchonly or pretend):
2917 if "yes" == settings.get("AUTOCLEAN"):
2918 portage.writemsg_stdout(">>> Auto-cleaning packages...\n")
2919 unmerge(trees[settings["ROOT"]]["root_config"],
2920 myopts, "clean", [],
2921 ldpath_mtimes, autoclean=1)
2923 portage.writemsg_stdout(colorize("WARN", "WARNING:")
2924 + " AUTOCLEAN is disabled. This can cause serious"
2925 + " problems due to overlapping packages.\n")
2926 trees[settings["ROOT"]]["vartree"].dbapi.plib_registry.pruneNonExisting()
2930 def multiple_actions(action1, action2):
2931 sys.stderr.write("\n!!! Multiple actions requested... Please choose one only.\n")
2932 sys.stderr.write("!!! '%s' or '%s'\n\n" % (action1, action2))
2935 def insert_optional_args(args):
2937 Parse optional arguments and insert a value if one has
2938 not been provided. This is done before feeding the args
2939 to the optparse parser since that parser does not support
2940 this feature natively.
2944 jobs_opts = ("-j", "--jobs")
2945 default_arg_opts = {
2946 '--deselect' : ('n',),
2947 '--root-deps' : ('rdeps',),
2952 arg = arg_stack.pop()
2954 default_arg_choices = default_arg_opts.get(arg)
2955 if default_arg_choices is not None:
2956 new_args.append(arg)
2957 if arg_stack and arg_stack[-1] in default_arg_choices:
2958 new_args.append(arg_stack.pop())
2960 # insert default argument
2961 new_args.append('True')
2964 short_job_opt = bool("j" in arg and arg[:1] == "-" and arg[:2] != "--")
2965 if not (short_job_opt or arg in jobs_opts):
2966 new_args.append(arg)
2969 # Insert an empty placeholder in order to
2970 # satisfy the requirements of optparse.
2972 new_args.append("--jobs")
2975 if short_job_opt and len(arg) > 2:
2978 job_count = int(arg[2:])
2980 saved_opts = arg[2:]
2983 saved_opts = arg[1:].replace("j", "")
2985 if job_count is None and arg_stack:
2987 job_count = int(arg_stack[-1])
2991 # Discard the job count from the stack
2992 # since we're consuming it here.
2995 if job_count is None:
2996 # unlimited number of jobs
2997 new_args.append("True")
2999 new_args.append(str(job_count))
3001 if saved_opts is not None:
3002 new_args.append("-" + saved_opts)
3006 def parse_opts(tmpcmdline, silent=False):
3011 global actions, options, shortmapping
3013 longopt_aliases = {"--cols":"--columns", "--skip-first":"--skipfirst"}
3014 argument_options = {
3016 "help":"specify the location for portage configuration files",
3020 "help":"enable or disable color output",
3022 "choices":("y", "n")
3026 "help" : "remove atoms from the world file",
3028 "choices" : ("True", "n")
3033 "help" : "Specifies the number of packages to build " + \
3041 "help" :"Specifies that no new builds should be started " + \
3042 "if there are other builds running and the load average " + \
3043 "is at least LOAD (a floating-point number).",
3049 "help":"include unnecessary build time dependencies",
3051 "choices":("y", "n")
3054 "help":"specify conditions to trigger package reinstallation",
3056 "choices":["changed-use"]
3059 "help" : "specify the target root filesystem for merging packages",
3064 "help" : "modify interpretation of depedencies",
3066 "choices" :("True", "rdeps")
3070 from optparse import OptionParser
3071 parser = OptionParser()
3072 if parser.has_option("--help"):
3073 parser.remove_option("--help")
3075 for action_opt in actions:
3076 parser.add_option("--" + action_opt, action="store_true",
3077 dest=action_opt.replace("-", "_"), default=False)
3078 for myopt in options:
3079 parser.add_option(myopt, action="store_true",
3080 dest=myopt.lstrip("--").replace("-", "_"), default=False)
3081 for shortopt, longopt in shortmapping.iteritems():
3082 parser.add_option("-" + shortopt, action="store_true",
3083 dest=longopt.lstrip("--").replace("-", "_"), default=False)
3084 for myalias, myopt in longopt_aliases.iteritems():
3085 parser.add_option(myalias, action="store_true",
3086 dest=myopt.lstrip("--").replace("-", "_"), default=False)
3088 for myopt, kwargs in argument_options.iteritems():
3089 parser.add_option(myopt,
3090 dest=myopt.lstrip("--").replace("-", "_"), **kwargs)
3092 tmpcmdline = insert_optional_args(tmpcmdline)
3094 myoptions, myargs = parser.parse_args(args=tmpcmdline)
3096 if myoptions.deselect == "True":
3097 myoptions.deselect = True
3099 if myoptions.root_deps == "True":
3100 myoptions.root_deps = True
3104 if myoptions.jobs == "True":
3108 jobs = int(myoptions.jobs)
3112 if jobs is not True and \
3116 writemsg("!!! Invalid --jobs parameter: '%s'\n" % \
3117 (myoptions.jobs,), noiselevel=-1)
3119 myoptions.jobs = jobs
3121 if myoptions.load_average:
3123 load_average = float(myoptions.load_average)
3127 if load_average <= 0.0:
3130 writemsg("!!! Invalid --load-average parameter: '%s'\n" % \
3131 (myoptions.load_average,), noiselevel=-1)
3133 myoptions.load_average = load_average
3135 for myopt in options:
3136 v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"))
3138 myopts[myopt] = True
3140 for myopt in argument_options:
3141 v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"), None)
3145 if myoptions.searchdesc:
3146 myoptions.search = True
3148 for action_opt in actions:
3149 v = getattr(myoptions, action_opt.replace("-", "_"))
3152 multiple_actions(myaction, action_opt)
3154 myaction = action_opt
3156 if myaction is None and myoptions.deselect is True:
3157 myaction = 'deselect'
3161 return myaction, myopts, myfiles
3163 def validate_ebuild_environment(trees):
3164 for myroot in trees:
3165 settings = trees[myroot]["vartree"].settings
3168 def load_emerge_config(trees=None):
3170 for k, envvar in (("config_root", "PORTAGE_CONFIGROOT"), ("target_root", "ROOT")):
3171 v = os.environ.get(envvar, None)
3174 trees = portage.create_trees(trees=trees, **kwargs)
3176 for root, root_trees in trees.iteritems():
3177 settings = root_trees["vartree"].settings
3178 setconfig = load_default_config(settings, root_trees)
3179 root_trees["root_config"] = RootConfig(settings, root_trees, setconfig)
3181 settings = trees["/"]["vartree"].settings
3183 for myroot in trees:
3185 settings = trees[myroot]["vartree"].settings
3188 mtimedbfile = os.path.join("/", portage.CACHE_PATH.lstrip(os.path.sep), "mtimedb")
3189 mtimedb = portage.MtimeDB(mtimedbfile)
3191 return settings, trees, mtimedb
3193 def adjust_config(myopts, settings):
3194 """Make emerge specific adjustments to the config."""
3196 # To enhance usability, make some vars case insensitive by forcing them to
3198 for myvar in ("AUTOCLEAN", "NOCOLOR"):
3199 if myvar in settings:
3200 settings[myvar] = settings[myvar].lower()
3201 settings.backup_changes(myvar)
3204 # Kill noauto as it will break merges otherwise.
3205 if "noauto" in settings.features:
3206 settings.features.remove('noauto')
3207 settings['FEATURES'] = ' '.join(sorted(settings.features))
3208 settings.backup_changes("FEATURES")
3212 CLEAN_DELAY = int(settings.get("CLEAN_DELAY", str(CLEAN_DELAY)))
3213 except ValueError, e:
3214 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
3215 portage.writemsg("!!! Unable to parse integer: CLEAN_DELAY='%s'\n" % \
3216 settings["CLEAN_DELAY"], noiselevel=-1)
3217 settings["CLEAN_DELAY"] = str(CLEAN_DELAY)
3218 settings.backup_changes("CLEAN_DELAY")
3220 EMERGE_WARNING_DELAY = 10
3222 EMERGE_WARNING_DELAY = int(settings.get(
3223 "EMERGE_WARNING_DELAY", str(EMERGE_WARNING_DELAY)))
3224 except ValueError, e:
3225 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
3226 portage.writemsg("!!! Unable to parse integer: EMERGE_WARNING_DELAY='%s'\n" % \
3227 settings["EMERGE_WARNING_DELAY"], noiselevel=-1)
3228 settings["EMERGE_WARNING_DELAY"] = str(EMERGE_WARNING_DELAY)
3229 settings.backup_changes("EMERGE_WARNING_DELAY")
3231 if "--quiet" in myopts:
3232 settings["PORTAGE_QUIET"]="1"
3233 settings.backup_changes("PORTAGE_QUIET")
3235 if "--verbose" in myopts:
3236 settings["PORTAGE_VERBOSE"] = "1"
3237 settings.backup_changes("PORTAGE_VERBOSE")
3239 # Set so that configs will be merged regardless of remembered status
3240 if ("--noconfmem" in myopts):
3241 settings["NOCONFMEM"]="1"
3242 settings.backup_changes("NOCONFMEM")
3244 # Set various debug markers... They should be merged somehow.
3247 PORTAGE_DEBUG = int(settings.get("PORTAGE_DEBUG", str(PORTAGE_DEBUG)))
3248 if PORTAGE_DEBUG not in (0, 1):
3249 portage.writemsg("!!! Invalid value: PORTAGE_DEBUG='%i'\n" % \
3250 PORTAGE_DEBUG, noiselevel=-1)
3251 portage.writemsg("!!! PORTAGE_DEBUG must be either 0 or 1\n",
3254 except ValueError, e:
3255 portage.writemsg("!!! %s\n" % str(e), noiselevel=-1)
3256 portage.writemsg("!!! Unable to parse integer: PORTAGE_DEBUG='%s'\n" %\
3257 settings["PORTAGE_DEBUG"], noiselevel=-1)
3259 if "--debug" in myopts:
3261 settings["PORTAGE_DEBUG"] = str(PORTAGE_DEBUG)
3262 settings.backup_changes("PORTAGE_DEBUG")
3264 if settings.get("NOCOLOR") not in ("yes","true"):
3265 portage.output.havecolor = 1
3267 """The explicit --color < y | n > option overrides the NOCOLOR environment
3268 variable and stdout auto-detection."""
3269 if "--color" in myopts:
3270 if "y" == myopts["--color"]:
3271 portage.output.havecolor = 1
3272 settings["NOCOLOR"] = "false"
3274 portage.output.havecolor = 0
3275 settings["NOCOLOR"] = "true"
3276 settings.backup_changes("NOCOLOR")
3277 elif not sys.stdout.isatty() and settings.get("NOCOLOR") != "no":
3278 portage.output.havecolor = 0
3279 settings["NOCOLOR"] = "true"
3280 settings.backup_changes("NOCOLOR")
3282 def apply_priorities(settings):
3288 os.nice(int(settings.get("PORTAGE_NICENESS", "0")))
3289 except (OSError, ValueError), e:
3290 out = portage.output.EOutput()
3291 out.eerror("Failed to change nice value to '%s'" % \
3292 settings["PORTAGE_NICENESS"])
3293 out.eerror("%s\n" % str(e))
3295 def ionice(settings):
3297 ionice_cmd = settings.get("PORTAGE_IONICE_COMMAND")
3299 ionice_cmd = shlex.split(ionice_cmd)
3303 from portage.util import varexpand
3304 variables = {"PID" : str(os.getpid())}
3305 cmd = [varexpand(x, mydict=variables) for x in ionice_cmd]
3308 rval = portage.process.spawn(cmd, env=os.environ)
3309 except portage.exception.CommandNotFound:
3310 # The OS kernel probably doesn't support ionice,
3311 # so return silently.
3314 if rval != os.EX_OK:
3315 out = portage.output.EOutput()
3316 out.eerror("PORTAGE_IONICE_COMMAND returned %d" % (rval,))
3317 out.eerror("See the make.conf(5) man page for PORTAGE_IONICE_COMMAND usage instructions.")
3319 def display_missing_pkg_set(root_config, set_name):
3322 msg.append(("emerge: There are no sets to satisfy '%s'. " + \
3323 "The following sets exist:") % \
3324 colorize("INFORM", set_name))
3327 for s in sorted(root_config.sets):
3328 msg.append(" %s" % s)
3331 writemsg_level("".join("%s\n" % l for l in msg),
3332 level=logging.ERROR, noiselevel=-1)
3334 def expand_set_arguments(myfiles, myaction, root_config):
3336 setconfig = root_config.setconfig
3338 sets = setconfig.getSets()
3340 # In order to know exactly which atoms/sets should be added to the
3341 # world file, the depgraph performs set expansion later. It will get
3342 # confused about where the atoms came from if it's not allowed to
3343 # expand them itself.
3344 do_not_expand = (None, )
3347 if a in ("system", "world"):
3348 newargs.append(SETPREFIX+a)
3355 # separators for set arguments
3359 # WARNING: all operators must be of equal length
3361 DIFF_OPERATOR = "-@"
3362 UNION_OPERATOR = "+@"
3364 for i in range(0, len(myfiles)):
3365 if myfiles[i].startswith(SETPREFIX):
3368 x = myfiles[i][len(SETPREFIX):]
3371 start = x.find(ARG_START)
3372 end = x.find(ARG_END)
3373 if start > 0 and start < end:
3374 namepart = x[:start]
3375 argpart = x[start+1:end]
3377 # TODO: implement proper quoting
3378 args = argpart.split(",")
3382 k, v = a.split("=", 1)
3386 setconfig.update(namepart, options)
3387 newset += (x[:start-len(namepart)]+namepart)
3388 x = x[end+len(ARG_END):]
3392 myfiles[i] = SETPREFIX+newset
3394 sets = setconfig.getSets()
3396 # display errors that occured while loading the SetConfig instance
3397 for e in setconfig.errors:
3398 print colorize("BAD", "Error during set creation: %s" % e)
3400 # emerge relies on the existance of sets with names "world" and "system"
3401 required_sets = ("world", "system")
3404 for s in required_sets:
3406 missing_sets.append(s)
3408 if len(missing_sets) > 2:
3409 missing_sets_str = ", ".join('"%s"' % s for s in missing_sets[:-1])
3410 missing_sets_str += ', and "%s"' % missing_sets[-1]
3411 elif len(missing_sets) == 2:
3412 missing_sets_str = '"%s" and "%s"' % tuple(missing_sets)
3414 missing_sets_str = '"%s"' % missing_sets[-1]
3415 msg = ["emerge: incomplete set configuration, " + \
3416 "missing set(s): %s" % missing_sets_str]
3418 msg.append(" sets defined: %s" % ", ".join(sets))
3419 msg.append(" This usually means that '%s'" % \
3420 (os.path.join(portage.const.GLOBAL_CONFIG_PATH, "sets.conf"),))
3421 msg.append(" is missing or corrupt.")
3423 writemsg_level(line + "\n", level=logging.ERROR, noiselevel=-1)
3425 unmerge_actions = ("unmerge", "prune", "clean", "depclean")
3428 if a.startswith(SETPREFIX):
3429 # support simple set operations (intersection, difference and union)
3430 # on the commandline. Expressions are evaluated strictly left-to-right
3431 if IS_OPERATOR in a or DIFF_OPERATOR in a or UNION_OPERATOR in a:
3432 expression = a[len(SETPREFIX):]
3435 while IS_OPERATOR in expression or DIFF_OPERATOR in expression or UNION_OPERATOR in expression:
3436 is_pos = expression.rfind(IS_OPERATOR)
3437 diff_pos = expression.rfind(DIFF_OPERATOR)
3438 union_pos = expression.rfind(UNION_OPERATOR)
3439 op_pos = max(is_pos, diff_pos, union_pos)
3440 s1 = expression[:op_pos]
3441 s2 = expression[op_pos+len(IS_OPERATOR):]
3442 op = expression[op_pos:op_pos+len(IS_OPERATOR)]
3444 display_missing_pkg_set(root_config, s2)
3446 expr_sets.insert(0, s2)
3447 expr_ops.insert(0, op)
3449 if not expression in sets:
3450 display_missing_pkg_set(root_config, expression)
3452 expr_sets.insert(0, expression)
3453 result = set(setconfig.getSetAtoms(expression))
3454 for i in range(0, len(expr_ops)):
3455 s2 = setconfig.getSetAtoms(expr_sets[i+1])
3456 if expr_ops[i] == IS_OPERATOR:
3457 result.intersection_update(s2)
3458 elif expr_ops[i] == DIFF_OPERATOR:
3459 result.difference_update(s2)
3460 elif expr_ops[i] == UNION_OPERATOR:
3463 raise NotImplementedError("unknown set operator %s" % expr_ops[i])
3464 newargs.extend(result)
3466 s = a[len(SETPREFIX):]
3468 display_missing_pkg_set(root_config, s)
3470 setconfig.active.append(s)
3472 set_atoms = setconfig.getSetAtoms(s)
3473 except portage.exception.PackageSetNotFound, e:
3474 writemsg_level(("emerge: the given set '%s' " + \
3475 "contains a non-existent set named '%s'.\n") % \
3476 (s, e), level=logging.ERROR, noiselevel=-1)
3478 if myaction in unmerge_actions and \
3479 not sets[s].supportsOperation("unmerge"):
3480 sys.stderr.write("emerge: the given set '%s' does " % s + \
3481 "not support unmerge operations\n")
3484 print "emerge: '%s' is an empty set" % s
3485 elif myaction not in do_not_expand:
3486 newargs.extend(set_atoms)
3488 newargs.append(SETPREFIX+s)
3489 for e in sets[s].errors:
3493 return (newargs, retval)
3495 def repo_name_check(trees):
3496 missing_repo_names = set()
3497 for root, root_trees in trees.iteritems():
3498 if "porttree" in root_trees:
3499 portdb = root_trees["porttree"].dbapi
3500 missing_repo_names.update(portdb.porttrees)
3501 repos = portdb.getRepositories()
3503 missing_repo_names.discard(portdb.getRepositoryPath(r))
3504 if portdb.porttree_root in missing_repo_names and \
3505 not os.path.exists(os.path.join(
3506 portdb.porttree_root, "profiles")):
3507 # This is normal if $PORTDIR happens to be empty,
3508 # so don't warn about it.
3509 missing_repo_names.remove(portdb.porttree_root)
3511 if missing_repo_names:
3513 msg.append("WARNING: One or more repositories " + \
3514 "have missing repo_name entries:")
3516 for p in missing_repo_names:
3517 msg.append("\t%s/profiles/repo_name" % (p,))
3519 msg.extend(textwrap.wrap("NOTE: Each repo_name entry " + \
3520 "should be a plain text file containing a unique " + \
3521 "name for the repository on the first line.", 70))
3522 writemsg_level("".join("%s\n" % l for l in msg),
3523 level=logging.WARNING, noiselevel=-1)
3525 return bool(missing_repo_names)
3527 def repo_name_duplicate_check(trees):
3529 for root, root_trees in trees.iteritems():
3530 if 'porttree' in root_trees:
3531 portdb = root_trees['porttree'].dbapi
3532 if portdb.mysettings.get('PORTAGE_REPO_DUPLICATE_WARN') != '0':
3533 for repo_name, paths in portdb._ignored_repos:
3534 k = (root, repo_name, portdb.getRepositoryPath(repo_name))
3535 ignored_repos.setdefault(k, []).extend(paths)
3539 msg.append('WARNING: One or more repositories ' + \
3540 'have been ignored due to duplicate')
3541 msg.append(' profiles/repo_name entries:')
3543 for k in sorted(ignored_repos):
3544 msg.append(' %s overrides' % (k,))
3545 for path in ignored_repos[k]:
3546 msg.append(' %s' % (path,))
3548 msg.extend(' ' + x for x in textwrap.wrap(
3549 "All profiles/repo_name entries must be unique in order " + \
3550 "to avoid having duplicates ignored. " + \
3551 "Set PORTAGE_REPO_DUPLICATE_WARN=\"0\" in " + \
3552 "/etc/make.conf if you would like to disable this warning."))
3553 writemsg_level(''.join('%s\n' % l for l in msg),
3554 level=logging.WARNING, noiselevel=-1)
3556 return bool(ignored_repos)
3558 def config_protect_check(trees):
3559 for root, root_trees in trees.iteritems():
3560 if not root_trees["root_config"].settings.get("CONFIG_PROTECT"):
3561 msg = "!!! CONFIG_PROTECT is empty"
3563 msg += " for '%s'" % root
3564 writemsg_level(msg, level=logging.WARN, noiselevel=-1)
3566 def profile_check(trees, myaction, myopts):
3567 if myaction in ("info", "sync"):
3569 elif "--version" in myopts or "--help" in myopts:
3571 for root, root_trees in trees.iteritems():
3572 if root_trees["root_config"].settings.profiles:
3574 # generate some profile related warning messages
3575 validate_ebuild_environment(trees)
3576 msg = "If you have just changed your profile configuration, you " + \
3577 "should revert back to the previous configuration. Due to " + \
3578 "your current profile being invalid, allowed actions are " + \
3579 "limited to --help, --info, --sync, and --version."
3580 writemsg_level("".join("!!! %s\n" % l for l in textwrap.wrap(msg, 70)),
3581 level=logging.ERROR, noiselevel=-1)
3586 global portage # NFC why this is necessary now - genone
3587 portage._disable_legacy_globals()
3588 # Disable color until we're sure that it should be enabled (after
3589 # EMERGE_DEFAULT_OPTS has been parsed).
3590 portage.output.havecolor = 0
3591 # This first pass is just for options that need to be known as early as
3592 # possible, such as --config-root. They will be parsed again later,
3593 # together with EMERGE_DEFAULT_OPTS (which may vary depending on the
3594 # the value of --config-root).
3595 myaction, myopts, myfiles = parse_opts(sys.argv[1:], silent=True)
3596 if "--debug" in myopts:
3597 os.environ["PORTAGE_DEBUG"] = "1"
3598 if "--config-root" in myopts:
3599 os.environ["PORTAGE_CONFIGROOT"] = myopts["--config-root"]
3600 if "--root" in myopts:
3601 os.environ["ROOT"] = myopts["--root"]
3603 # Portage needs to ensure a sane umask for the files it creates.
3605 settings, trees, mtimedb = load_emerge_config()
3606 portdb = trees[settings["ROOT"]]["porttree"].dbapi
3607 rval = profile_check(trees, myaction, myopts)
3608 if rval != os.EX_OK:
3611 if portage._global_updates(trees, mtimedb["updates"]):
3613 # Reload the whole config from scratch.
3614 settings, trees, mtimedb = load_emerge_config(trees=trees)
3615 portdb = trees[settings["ROOT"]]["porttree"].dbapi
3617 xterm_titles = "notitles" not in settings.features
3620 if "--ignore-default-opts" not in myopts:
3621 tmpcmdline.extend(settings["EMERGE_DEFAULT_OPTS"].split())
3622 tmpcmdline.extend(sys.argv[1:])
3623 myaction, myopts, myfiles = parse_opts(tmpcmdline)
3625 if "--digest" in myopts:
3626 os.environ["FEATURES"] = os.environ.get("FEATURES","") + " digest"
3627 # Reload the whole config from scratch so that the portdbapi internal
3628 # config is updated with new FEATURES.
3629 settings, trees, mtimedb = load_emerge_config(trees=trees)
3630 portdb = trees[settings["ROOT"]]["porttree"].dbapi
3632 for myroot in trees:
3633 mysettings = trees[myroot]["vartree"].settings
3635 adjust_config(myopts, mysettings)
3636 if '--pretend' not in myopts and myaction in \
3637 (None, 'clean', 'depclean', 'prune', 'unmerge'):
3638 mysettings["PORTAGE_COUNTER_HASH"] = \
3639 trees[myroot]["vartree"].dbapi._counter_hash()
3640 mysettings.backup_changes("PORTAGE_COUNTER_HASH")
3642 del myroot, mysettings
3644 apply_priorities(settings)
3646 spinner = stdout_spinner()
3647 if "candy" in settings.features:
3648 spinner.update = spinner.update_scroll
3650 if "--quiet" not in myopts:
3651 portage.deprecated_profile_check(settings=settings)
3652 repo_name_check(trees)
3653 repo_name_duplicate_check(trees)
3654 config_protect_check(trees)
3656 for mytrees in trees.itervalues():
3657 mydb = mytrees["porttree"].dbapi
3658 # Freeze the portdbapi for performance (memoize all xmatch results).
3662 if "moo" in myfiles:
3665 Larry loves Gentoo (""" + platform.system() + """)
3667 _______________________
3668 < Have you mooed today? >
3669 -----------------------
3679 ext = os.path.splitext(x)[1]
3680 if (ext == ".ebuild" or ext == ".tbz2") and os.path.exists(os.path.abspath(x)):
3681 print colorize("BAD", "\n*** emerging by path is broken and may not always work!!!\n")
3684 root_config = trees[settings["ROOT"]]["root_config"]
3685 if myaction == "list-sets":
3686 sys.stdout.write("".join("%s\n" % s for s in sorted(root_config.sets)))
3690 # only expand sets for actions taking package arguments
3691 oldargs = myfiles[:]
3692 if myaction in ("clean", "config", "depclean", "info", "prune", "unmerge", None):
3693 myfiles, retval = expand_set_arguments(myfiles, myaction, root_config)
3694 if retval != os.EX_OK:
3697 # Need to handle empty sets specially, otherwise emerge will react
3698 # with the help message for empty argument lists
3699 if oldargs and not myfiles:
3700 print "emerge: no targets left after set expansion"
3703 if ("--tree" in myopts) and ("--columns" in myopts):
3704 print "emerge: can't specify both of \"--tree\" and \"--columns\"."
3707 if ("--quiet" in myopts):
3708 spinner.update = spinner.update_quiet
3709 portage.util.noiselimit = -1
3711 # Always create packages if FEATURES=buildpkg
3712 # Imply --buildpkg if --buildpkgonly
3713 if ("buildpkg" in settings.features) or ("--buildpkgonly" in myopts):
3714 if "--buildpkg" not in myopts:
3715 myopts["--buildpkg"] = True
3717 # Always try and fetch binary packages if FEATURES=getbinpkg
3718 if ("getbinpkg" in settings.features):
3719 myopts["--getbinpkg"] = True
3721 if "--buildpkgonly" in myopts:
3722 # --buildpkgonly will not merge anything, so
3723 # it cancels all binary package options.
3724 for opt in ("--getbinpkg", "--getbinpkgonly",
3725 "--usepkg", "--usepkgonly"):
3726 myopts.pop(opt, None)
3728 if "--fetch-all-uri" in myopts:
3729 myopts["--fetchonly"] = True
3731 if "--skipfirst" in myopts and "--resume" not in myopts:
3732 myopts["--resume"] = True
3734 if ("--getbinpkgonly" in myopts) and not ("--usepkgonly" in myopts):
3735 myopts["--usepkgonly"] = True
3737 if ("--getbinpkgonly" in myopts) and not ("--getbinpkg" in myopts):
3738 myopts["--getbinpkg"] = True
3740 if ("--getbinpkg" in myopts) and not ("--usepkg" in myopts):
3741 myopts["--usepkg"] = True
3743 # Also allow -K to apply --usepkg/-k
3744 if ("--usepkgonly" in myopts) and not ("--usepkg" in myopts):
3745 myopts["--usepkg"] = True
3747 # Allow -p to remove --ask
3748 if "--pretend" in myopts:
3749 myopts.pop("--ask", None)
3751 # forbid --ask when not in a terminal
3752 # note: this breaks `emerge --ask | tee logfile`, but that doesn't work anyway.
3753 if ("--ask" in myopts) and (not sys.stdin.isatty()):
3754 portage.writemsg("!!! \"--ask\" should only be used in a terminal. Exiting.\n",
3758 if settings.get("PORTAGE_DEBUG", "") == "1":
3759 spinner.update = spinner.update_quiet
3761 if "python-trace" in settings.features:
3762 import portage.debug
3763 portage.debug.set_trace(True)
3765 if not ("--quiet" in myopts):
3766 if not sys.stdout.isatty() or ("--nospinner" in myopts):
3767 spinner.update = spinner.update_basic
3769 if myaction == 'version':
3770 print getportageversion(settings["PORTDIR"], settings["ROOT"],
3771 settings.profile_path, settings["CHOST"],
3772 trees[settings["ROOT"]]["vartree"].dbapi)
3774 elif "--help" in myopts:
3775 _emerge.help.help(myaction, myopts, portage.output.havecolor)
3778 if "--debug" in myopts:
3779 print "myaction", myaction
3780 print "myopts", myopts
3782 if not myaction and not myfiles and "--resume" not in myopts:
3783 _emerge.help.help(myaction, myopts, portage.output.havecolor)
3786 pretend = "--pretend" in myopts
3787 fetchonly = "--fetchonly" in myopts or "--fetch-all-uri" in myopts
3788 buildpkgonly = "--buildpkgonly" in myopts
3790 # check if root user is the current user for the actions where emerge needs this
3791 if portage.secpass < 2:
3792 # We've already allowed "--version" and "--help" above.
3793 if "--pretend" not in myopts and myaction not in ("search","info"):
3794 need_superuser = myaction in ('clean', 'depclean', 'deselect',
3795 'prune', 'unmerge') or not \
3797 (buildpkgonly and secpass >= 1) or \
3798 myaction in ("metadata", "regen") or \
3799 (myaction == "sync" and os.access(settings["PORTDIR"], os.W_OK)))
3800 if portage.secpass < 1 or \
3803 access_desc = "superuser"
3805 access_desc = "portage group"
3806 # Always show portage_group_warning() when only portage group
3807 # access is required but the user is not in the portage group.
3808 from portage.data import portage_group_warning
3809 if "--ask" in myopts:
3810 myopts["--pretend"] = True
3812 print ("%s access is required... " + \
3813 "adding --pretend to options\n") % access_desc
3814 if portage.secpass < 1 and not need_superuser:
3815 portage_group_warning()
3817 sys.stderr.write(("emerge: %s access is required\n") \
3819 if portage.secpass < 1 and not need_superuser:
3820 portage_group_warning()
3823 disable_emergelog = False
3824 for x in ("--pretend", "--fetchonly", "--fetch-all-uri"):
3826 disable_emergelog = True
3828 if myaction in ("search", "info"):
3829 disable_emergelog = True
3830 if disable_emergelog:
3831 """ Disable emergelog for everything except build or unmerge
3832 operations. This helps minimize parallel emerge.log entries that can
3833 confuse log parsers. We especially want it disabled during
3834 parallel-fetch, which uses --resume --fetchonly."""
3836 def emergelog(*pargs, **kargs):
3840 if 'EMERGE_LOG_DIR' in settings:
3842 # At least the parent needs to exist for the lock file.
3843 portage.util.ensure_dirs(settings['EMERGE_LOG_DIR'])
3844 except portage.exception.PortageException, e:
3845 writemsg_level("!!! Error creating directory for " + \
3846 "EMERGE_LOG_DIR='%s':\n!!! %s\n" % \
3847 (settings['EMERGE_LOG_DIR'], e),
3848 noiselevel=-1, level=logging.ERROR)
3850 global _emerge_log_dir
3851 _emerge_log_dir = settings['EMERGE_LOG_DIR']
3853 if not "--pretend" in myopts:
3854 emergelog(xterm_titles, "Started emerge on: "+\
3855 time.strftime("%b %d, %Y %H:%M:%S", time.localtime()))
3858 myelogstr=" ".join(myopts)
3860 myelogstr+=" "+myaction
3862 myelogstr += " " + " ".join(oldargs)
3863 emergelog(xterm_titles, " *** emerge " + myelogstr)
3866 def emergeexitsig(signum, frame):
3867 signal.signal(signal.SIGINT, signal.SIG_IGN)
3868 signal.signal(signal.SIGTERM, signal.SIG_IGN)
3869 portage.util.writemsg("\n\nExiting on signal %(signal)s\n" % {"signal":signum})
3870 sys.exit(100+signum)
3871 signal.signal(signal.SIGINT, emergeexitsig)
3872 signal.signal(signal.SIGTERM, emergeexitsig)
3875 """This gets out final log message in before we quit."""
3876 if "--pretend" not in myopts:
3877 emergelog(xterm_titles, " *** terminating.")
3878 if "notitles" not in settings.features:
3880 portage.atexit_register(emergeexit)
3882 if myaction in ("config", "metadata", "regen", "sync"):
3883 if "--pretend" in myopts:
3884 sys.stderr.write(("emerge: The '%s' action does " + \
3885 "not support '--pretend'.\n") % myaction)
3888 if "sync" == myaction:
3889 return action_sync(settings, trees, mtimedb, myopts, myaction)
3890 elif "metadata" == myaction:
3891 action_metadata(settings, portdb, myopts)
3892 elif myaction=="regen":
3893 validate_ebuild_environment(trees)
3894 return action_regen(settings, portdb, myopts.get("--jobs"),
3895 myopts.get("--load-average"))
3897 elif "config"==myaction:
3898 validate_ebuild_environment(trees)
3899 action_config(settings, trees, myopts, myfiles)
3902 elif "search"==myaction:
3903 validate_ebuild_environment(trees)
3904 action_search(trees[settings["ROOT"]]["root_config"],
3905 myopts, myfiles, spinner)
3907 elif myaction in ('clean', 'depclean', 'deselect', 'prune', 'unmerge'):
3908 validate_ebuild_environment(trees)
3909 rval = action_uninstall(settings, trees, mtimedb["ldpath"],
3910 myopts, myaction, myfiles, spinner)
3911 if not (myaction == 'deselect' or buildpkgonly or fetchonly or pretend):
3912 post_emerge(root_config, myopts, mtimedb, rval)
3915 elif myaction == 'info':
3917 # Ensure atoms are valid before calling unmerge().
3918 vardb = trees[settings["ROOT"]]["vartree"].dbapi
3921 if is_valid_package_atom(x):
3924 portage.dep_expand(x, mydb=vardb, settings=settings))
3925 except portage.exception.AmbiguousPackageName, e:
3926 msg = "The short ebuild name \"" + x + \
3927 "\" is ambiguous. Please specify " + \
3928 "one of the following " + \
3929 "fully-qualified ebuild names instead:"
3930 for line in textwrap.wrap(msg, 70):
3931 writemsg_level("!!! %s\n" % (line,),
3932 level=logging.ERROR, noiselevel=-1)
3934 writemsg_level(" %s\n" % colorize("INFORM", i),
3935 level=logging.ERROR, noiselevel=-1)
3936 writemsg_level("\n", level=logging.ERROR, noiselevel=-1)
3940 msg.append("'%s' is not a valid package atom." % (x,))
3941 msg.append("Please check ebuild(5) for full details.")
3942 writemsg_level("".join("!!! %s\n" % line for line in msg),
3943 level=logging.ERROR, noiselevel=-1)
3946 return action_info(settings, trees, myopts, valid_atoms)
3948 # "update", "system", or just process files:
3950 validate_ebuild_environment(trees)
3953 if x.startswith(SETPREFIX) or \
3954 is_valid_package_atom(x):
3964 msg.append("'%s' is not a valid package atom." % (x,))
3965 msg.append("Please check ebuild(5) for full details.")
3966 writemsg_level("".join("!!! %s\n" % line for line in msg),
3967 level=logging.ERROR, noiselevel=-1)
3970 if "--pretend" not in myopts:
3971 display_news_notification(root_config, myopts)
3972 retval = action_build(settings, trees, mtimedb,
3973 myopts, myaction, myfiles, spinner)
3974 root_config = trees[settings["ROOT"]]["root_config"]
3975 post_emerge(root_config, myopts, mtimedb, retval)