1 # Copyright 1999-2012 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
4 from __future__ import print_function
14 portage.proxy.lazyimport.lazyimport(globals(),
15 'portage.news:count_unread_news,display_news_notifications',
17 from portage import os
18 from portage import _encodings
19 from portage import _unicode_decode
21 import portage.xpak, errno, re, time
22 from portage.output import colorize, xtermTitle, xtermTitleReset
23 from portage.output import create_color_func
24 good = create_color_func("GOOD")
25 bad = create_color_func("BAD")
27 from portage.const import _ENABLE_DYN_LINK_MAP
31 import portage.exception
32 from portage.data import secpass
33 from portage.dbapi.dep_expand import dep_expand
34 from portage.util import normalize_path as normpath
35 from portage.util import (shlex_split, varexpand,
36 writemsg_level, writemsg_stdout)
37 from portage._sets import SETPREFIX
38 from portage._global_updates import _global_updates
40 from _emerge.actions import action_config, action_sync, action_metadata, \
41 action_regen, action_search, action_uninstall, action_info, action_build, \
42 adjust_configs, chk_updated_cfg_files, display_missing_pkg_set, \
43 display_news_notification, getportageversion, load_emerge_config
45 from _emerge.emergelog import emergelog
46 from _emerge._flush_elog_mod_echo import _flush_elog_mod_echo
47 from _emerge.is_valid_package_atom import is_valid_package_atom
48 from _emerge.stdout_spinner import stdout_spinner
49 from _emerge.userquery import userquery
51 if sys.hexversion >= 0x3000000:
56 "--ask-enter-invalid",
59 "--changelog", "--columns",
63 "--fetchonly", "--fetch-all-uri",
64 "--ignore-default-opts",
67 "--nodeps", "--noreplace",
68 "--nospinner", "--oneshot",
69 "--onlydeps", "--pretend",
70 "--quiet-repo-display",
71 "--quiet-unmerge-warn",
76 "--unordered-display",
79 "--verbose-main-repo-display",
89 "f":"--fetchonly", "F":"--fetch-all-uri",
92 "n":"--noreplace", "N":"--newuse",
93 "o":"--onlydeps", "O":"--nodeps",
94 "p":"--pretend", "P":"--prune",
96 "s":"--search", "S":"--searchdesc",
99 "v":"--verbose", "V":"--version"
104 Larry loves Gentoo (%s)
106 _______________________
107 < Have you mooed today? >
108 -----------------------
117 def chk_updated_info_files(root, infodirs, prev_mtimes, retval):
119 if os.path.exists("/usr/bin/install-info"):
120 out = portage.output.EOutput()
125 inforoot=normpath(root+z)
126 if os.path.isdir(inforoot) and \
127 not [x for x in os.listdir(inforoot) \
128 if x.startswith('.keepinfodir')]:
129 infomtime = os.stat(inforoot)[stat.ST_MTIME]
130 if inforoot not in prev_mtimes or \
131 prev_mtimes[inforoot] != infomtime:
132 regen_infodirs.append(inforoot)
134 if not regen_infodirs:
135 portage.writemsg_stdout("\n")
136 if portage.util.noiselimit >= 0:
137 out.einfo("GNU info directory index is up-to-date.")
139 portage.writemsg_stdout("\n")
140 if portage.util.noiselimit >= 0:
141 out.einfo("Regenerating GNU info directory index...")
143 dir_extensions = ("", ".gz", ".bz2")
147 for inforoot in regen_infodirs:
151 if not os.path.isdir(inforoot) or \
152 not os.access(inforoot, os.W_OK):
155 file_list = os.listdir(inforoot)
157 dir_file = os.path.join(inforoot, "dir")
158 moved_old_dir = False
161 if x.startswith(".") or \
162 os.path.isdir(os.path.join(inforoot, x)):
164 if x.startswith("dir"):
166 for ext in dir_extensions:
167 if x == "dir" + ext or \
168 x == "dir" + ext + ".old":
173 if processed_count == 0:
174 for ext in dir_extensions:
176 os.rename(dir_file + ext, dir_file + ext + ".old")
178 except EnvironmentError as e:
179 if e.errno != errno.ENOENT:
184 proc = subprocess.Popen(
185 ['/usr/bin/install-info',
186 '--dir-file=%s' % os.path.join(inforoot, "dir"),
187 os.path.join(inforoot, x)],
188 env=dict(os.environ, LANG="C", LANGUAGE="C"),
189 stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
193 myso = _unicode_decode(
194 proc.communicate()[0]).rstrip("\n")
196 existsstr="already exists, for file `"
198 if re.search(existsstr,myso):
199 # Already exists... Don't increment the count for this.
201 elif myso[:44]=="install-info: warning: no info dir entry in ":
202 # This info file doesn't contain a DIR-header: install-info produces this
203 # (harmless) warning (the --quiet switch doesn't seem to work).
204 # Don't increment the count for this.
208 errmsg += myso + "\n"
211 if moved_old_dir and not os.path.exists(dir_file):
212 # We didn't generate a new dir file, so put the old file
213 # back where it was originally found.
214 for ext in dir_extensions:
216 os.rename(dir_file + ext + ".old", dir_file + ext)
217 except EnvironmentError as e:
218 if e.errno != errno.ENOENT:
222 # Clean dir.old cruft so that they don't prevent
223 # unmerge of otherwise empty directories.
224 for ext in dir_extensions:
226 os.unlink(dir_file + ext + ".old")
227 except EnvironmentError as e:
228 if e.errno != errno.ENOENT:
232 #update mtime so we can potentially avoid regenerating.
233 prev_mtimes[inforoot] = os.stat(inforoot)[stat.ST_MTIME]
236 out.eerror("Processed %d info files; %d errors." % \
238 writemsg_level(errmsg, level=logging.ERROR, noiselevel=-1)
240 if icount > 0 and portage.util.noiselimit >= 0:
241 out.einfo("Processed %d info files." % (icount,))
243 def display_preserved_libs(vardbapi, myopts):
246 if vardbapi._linkmap is None or \
247 vardbapi._plib_registry is None:
248 # preserve-libs is entirely disabled
251 # Explicitly load and prune the PreservedLibsRegistry in order
252 # to ensure that we do not display stale data.
253 vardbapi._plib_registry.load()
255 if vardbapi._plib_registry.hasEntries():
256 if "--quiet" in myopts:
258 print(colorize("WARN", "!!!") + " existing preserved libs found")
262 print(colorize("WARN", "!!!") + " existing preserved libs:")
264 plibdata = vardbapi._plib_registry.getPreservedLibs()
265 linkmap = vardbapi._linkmap
271 except portage.exception.CommandNotFound as e:
272 writemsg_level("!!! Command Not Found: %s\n" % (e,),
273 level=logging.ERROR, noiselevel=-1)
276 search_for_owners = set()
278 internal_plib_keys = set(linkmap._obj_key(f) \
279 for f in plibdata[cpv])
280 for f in plibdata[cpv]:
281 if f in consumer_map:
284 for c in linkmap.findConsumers(f):
285 # Filter out any consumers that are also preserved libs
286 # belonging to the same package as the provider.
287 if linkmap._obj_key(c) not in internal_plib_keys:
290 consumer_map[f] = consumers
291 search_for_owners.update(consumers[:MAX_DISPLAY+1])
294 for f in search_for_owners:
296 for owner in linkmap.getOwners(f):
297 owner_dblink = vardbapi._dblink(owner)
298 if owner_dblink.exists():
299 owner_set.add(owner_dblink)
301 owners[f] = owner_set
304 print(colorize("WARN", ">>>") + " package: %s" % cpv)
306 for f in plibdata[cpv]:
307 obj_key = linkmap._obj_key(f)
308 alt_paths = samefile_map.get(obj_key)
309 if alt_paths is None:
311 samefile_map[obj_key] = alt_paths
314 for alt_paths in samefile_map.values():
315 alt_paths = sorted(alt_paths)
317 print(colorize("WARN", " * ") + " - %s" % (p,))
319 consumers = consumer_map.get(f, [])
320 for c in consumers[:MAX_DISPLAY]:
321 print(colorize("WARN", " * ") + " used by %s (%s)" % \
322 (c, ", ".join(x.mycpv for x in owners.get(c, []))))
323 if len(consumers) == MAX_DISPLAY + 1:
324 print(colorize("WARN", " * ") + " used by %s (%s)" % \
325 (consumers[MAX_DISPLAY], ", ".join(x.mycpv \
326 for x in owners.get(consumers[MAX_DISPLAY], []))))
327 elif len(consumers) > MAX_DISPLAY:
328 print(colorize("WARN", " * ") + " used by %d other files" % (len(consumers) - MAX_DISPLAY))
329 print("Use " + colorize("GOOD", "emerge @preserved-rebuild") + " to rebuild packages using these libraries")
331 def post_emerge(myaction, myopts, myfiles,
332 target_root, trees, mtimedb, retval):
334 Misc. things to run at the end of a merge session.
340 Display preserved libs warnings
342 @param myaction: The action returned from parse_opts()
343 @type myaction: String
344 @param myopts: emerge options
346 @param myfiles: emerge arguments
348 @param target_root: The target EROOT for myaction
349 @type target_root: String
350 @param trees: A dictionary mapping each ROOT to it's package databases
352 @param mtimedb: The mtimeDB to store data needed across merge invocations
353 @type mtimedb: MtimeDB class instance
354 @param retval: Emerge's return value
358 root_config = trees[target_root]["root_config"]
359 vardbapi = trees[target_root]['vartree'].dbapi
360 settings = vardbapi.settings
361 info_mtimes = mtimedb["info"]
363 # Load the most current variables from ${ROOT}/etc/profile.env
366 settings.regenerate()
369 config_protect = shlex_split(settings.get("CONFIG_PROTECT", ""))
370 infodirs = settings.get("INFOPATH","").split(":") + \
371 settings.get("INFODIR","").split(":")
375 if retval == os.EX_OK:
376 exit_msg = " *** exiting successfully."
378 exit_msg = " *** exiting unsuccessfully with status '%s'." % retval
379 emergelog("notitles" not in settings.features, exit_msg)
381 _flush_elog_mod_echo()
383 if not vardbapi._pkgs_changed:
384 # GLEP 42 says to display news *after* an emerge --pretend
385 if "--pretend" in myopts:
386 display_news_notification(root_config, myopts)
387 # If vdb state has not changed then there's nothing else to do.
390 vdb_path = os.path.join(root_config.settings['EROOT'], portage.VDB_PATH)
391 portage.util.ensure_dirs(vdb_path)
393 if os.access(vdb_path, os.W_OK) and not "--pretend" in myopts:
399 if "noinfo" not in settings.features:
400 chk_updated_info_files(target_root,
401 infodirs, info_mtimes, retval)
407 display_preserved_libs(vardbapi, myopts)
408 chk_updated_cfg_files(settings['EROOT'], config_protect)
410 display_news_notification(root_config, myopts)
412 postemerge = os.path.join(settings["PORTAGE_CONFIGROOT"],
413 portage.USER_CONFIG_PATH, "bin", "post_emerge")
414 if os.access(postemerge, os.X_OK):
415 hook_retval = portage.process.spawn(
416 [postemerge], env=settings.environ())
417 if hook_retval != os.EX_OK:
419 " %s spawn failed of %s\n" % (bad("*"), postemerge,),
420 level=logging.ERROR, noiselevel=-1)
424 if "--quiet" not in myopts and \
425 myaction is None and "@world" in myfiles:
426 show_depclean_suggestion()
428 def show_depclean_suggestion():
429 out = portage.output.EOutput()
430 msg = "After world updates, it is important to remove " + \
431 "obsolete packages with emerge --depclean. Refer " + \
432 "to `man emerge` for more information."
433 for line in textwrap.wrap(msg, 72):
436 def multiple_actions(action1, action2):
437 sys.stderr.write("\n!!! Multiple actions requested... Please choose one only.\n")
438 sys.stderr.write("!!! '%s' or '%s'\n\n" % (action1, action2))
441 def insert_optional_args(args):
443 Parse optional arguments and insert a value if one has
444 not been provided. This is done before feeding the args
445 to the optparse parser since that parser does not support
446 this feature natively.
449 class valid_integers(object):
450 def __contains__(self, s):
453 except (ValueError, OverflowError):
456 valid_integers = valid_integers()
463 '--autounmask' : y_or_n,
464 '--autounmask-keep-masks': y_or_n,
465 '--autounmask-unrestricted-atoms' : y_or_n,
466 '--autounmask-write' : y_or_n,
467 '--buildpkg' : y_or_n,
468 '--complete-graph' : y_or_n,
469 '--deep' : valid_integers,
470 '--deselect' : y_or_n,
471 '--binpkg-respect-use' : y_or_n,
472 '--fail-clean' : y_or_n,
473 '--getbinpkg' : y_or_n,
474 '--getbinpkgonly' : y_or_n,
475 '--jobs' : valid_integers,
476 '--keep-going' : y_or_n,
477 '--package-moves' : y_or_n,
479 '--quiet-build' : y_or_n,
480 '--rebuild-if-new-slot-abi': y_or_n,
481 '--rebuild-if-new-rev' : y_or_n,
482 '--rebuild-if-new-ver' : y_or_n,
483 '--rebuild-if-unbuilt' : y_or_n,
484 '--rebuilt-binaries' : y_or_n,
485 '--root-deps' : ('rdeps',),
487 '--selective' : y_or_n,
488 "--use-ebuild-visibility": y_or_n,
490 '--usepkgonly' : y_or_n,
493 if _ENABLE_DYN_LINK_MAP:
494 default_arg_opts['--depclean-lib-check'] = y_or_n
497 'D' : valid_integers,
498 'j' : valid_integers,
501 # Don't make things like "-kn" expand to "-k n"
502 # since existence of -n makes it too ambiguous.
516 arg = arg_stack.pop()
518 default_arg_choices = default_arg_opts.get(arg)
519 if default_arg_choices is not None:
521 if arg_stack and arg_stack[-1] in default_arg_choices:
522 new_args.append(arg_stack.pop())
524 # insert default argument
525 new_args.append('True')
528 if arg[:1] != "-" or arg[:2] == "--":
533 for k, arg_choices in short_arg_opts.items():
539 for k, arg_choices in short_arg_opts_n.items():
550 if arg_stack and arg_stack[-1] in arg_choices:
551 new_args.append(arg_stack.pop())
553 # insert default argument
554 new_args.append('True')
557 # Insert an empty placeholder in order to
558 # satisfy the requirements of optparse.
560 new_args.append("-" + match)
564 if arg[1:2] == match:
565 if match not in short_arg_opts_n and arg[2:] in arg_choices:
571 saved_opts = arg[1:].replace(match, "")
574 if opt_arg is None and arg_stack and \
575 arg_stack[-1] in arg_choices:
576 opt_arg = arg_stack.pop()
579 new_args.append("True")
581 new_args.append(opt_arg)
583 if saved_opts is not None:
584 # Recycle these on arg_stack since they
585 # might contain another match.
586 arg_stack.append("-" + saved_opts)
590 def _find_bad_atoms(atoms, less_strict=False):
592 Declares all atoms as invalid that have an operator,
593 a use dependency, a blocker or a repo spec.
594 It accepts atoms with wildcards.
595 In less_strict mode it accepts operators and repo specs.
598 for x in ' '.join(atoms).split():
601 atom = portage.dep.Atom(x, allow_wildcard=True, allow_repo=less_strict)
602 except portage.exception.InvalidAtom:
604 atom = portage.dep.Atom("*/"+x, allow_wildcard=True, allow_repo=less_strict)
605 except portage.exception.InvalidAtom:
608 if bad_atom or (atom.operator and not less_strict) or atom.blocker or atom.use:
613 def parse_opts(tmpcmdline, silent=False):
618 actions = frozenset([
619 "clean", "check-news", "config", "depclean", "help",
620 "info", "list-sets", "metadata", "moo",
621 "prune", "regen", "search",
622 "sync", "unmerge", "version",
625 longopt_aliases = {"--cols":"--columns", "--skip-first":"--skipfirst"}
627 true_y_or_n = ("True", "y", "n")
628 true_y = ("True", "y")
633 "help" : "prompt before performing any actions",
635 "choices" : true_y_or_n
639 "help" : "automatically unmask packages",
641 "choices" : true_y_or_n
644 "--autounmask-unrestricted-atoms": {
645 "help" : "write autounmask changes with >= atoms if possible",
647 "choices" : true_y_or_n
650 "--autounmask-keep-masks": {
651 "help" : "don't add package.unmask entries",
653 "choices" : true_y_or_n
656 "--autounmask-write": {
657 "help" : "write changes made by --autounmask to disk",
659 "choices" : true_y_or_n
662 "--accept-properties": {
663 "help":"temporarily override ACCEPT_PROPERTIES",
669 "help" : "Specifies how many times to backtrack if dependency " + \
670 "calculation fails ",
677 "help" : "build binary packages",
679 "choices" : true_y_or_n
682 "--buildpkg-exclude": {
683 "help" :"A space separated list of package atoms for which " + \
684 "no binary packages should be built. This option overrides all " + \
685 "possible ways to enable building of binary packages.",
691 "help":"specify the location for portage configuration files",
695 "help":"enable or disable color output",
700 "--complete-graph": {
701 "help" : "completely account for all known dependencies",
703 "choices" : true_y_or_n
706 "--complete-graph-if-new-ver": {
707 "help" : "trigger --complete-graph behavior if an installed package version will change (upgrade or downgrade)",
716 "help" : "Specifies how deep to recurse into dependencies " + \
717 "of packages given as arguments. If no argument is given, " + \
718 "depth is unlimited. Default behavior is to skip " + \
719 "dependencies of installed packages.",
725 "help" : "remove atoms/sets from the world file",
727 "choices" : true_y_or_n
731 "help": "substitute the dependencies of installed packages with the dependencies of unbuilt ebuilds",
737 "help" :"A space separated list of package names or slot atoms. " + \
738 "Emerge won't install any ebuild or binary package that " + \
739 "matches any of the given package atoms.",
745 "help" : "clean temp files after build failure",
747 "choices" : true_y_or_n
750 "--ignore-built-slot-abi-deps": {
751 "help": "Ignore the SLOT/ABI := operator parts of dependencies that have "
752 "been recorded when packages where built. This option is intended "
753 "only for debugging purposes, and it only affects built packages "
754 "that specify SLOT/ABI := operator dependencies using the "
755 "experimental \"4-slot-abi\" EAPI.",
764 "help" : "Specifies the number of packages to build " + \
771 "help" : "continue as much as possible after an error",
773 "choices" : true_y_or_n
778 "help" :"Specifies that no new builds should be started " + \
779 "if there are other builds running and the load average " + \
780 "is at least LOAD (a floating-point number).",
785 "--misspell-suggestions": {
786 "help" : "enable package name misspell suggestions",
788 "choices" : ("y", "n")
792 "help":"include unnecessary build time dependencies",
797 "help":"specify conditions to trigger package reinstallation",
799 "choices":["changed-use"]
802 "--reinstall-atoms": {
803 "help" :"A space separated list of package names or slot atoms. " + \
804 "Emerge will treat matching packages as if they are not " + \
805 "installed, and reinstall them if necessary. Implies --deep.",
810 "--binpkg-respect-use": {
811 "help" : "discard binary packages if their use flags \
812 don't match the current configuration",
814 "choices" : true_y_or_n
819 "help" : "fetch binary packages",
821 "choices" : true_y_or_n
826 "help" : "fetch binary packages only",
828 "choices" : true_y_or_n
831 "--usepkg-exclude": {
832 "help" :"A space separated list of package names or slot atoms. " + \
833 "Emerge will ignore matching binary packages. ",
838 "--rebuild-exclude": {
839 "help" :"A space separated list of package names or slot atoms. " + \
840 "Emerge will not rebuild these packages due to the " + \
846 "--rebuild-ignore": {
847 "help" :"A space separated list of package names or slot atoms. " + \
848 "Emerge will not rebuild packages that depend on matching " + \
849 "packages due to the --rebuild flag. ",
855 "help" : "perform package moves when necessary",
857 "choices" : true_y_or_n
862 "help" : "reduced or condensed output",
864 "choices" : true_y_or_n
868 "help" : "redirect build output to logs",
870 "choices" : true_y_or_n,
873 "--rebuild-if-new-slot-abi": {
874 "help" : ("Automatically rebuild or reinstall packages when SLOT/ABI := "
875 "operator dependencies can be satisfied by a newer slot, so that "
876 "older packages slots will become eligible for removal by the "
877 "--depclean action as soon as possible."),
879 "choices" : true_y_or_n
882 "--rebuild-if-new-rev": {
883 "help" : "Rebuild packages when dependencies that are " + \
884 "used at both build-time and run-time are built, " + \
885 "if the dependency is not already installed with the " + \
886 "same version and revision.",
888 "choices" : true_y_or_n
891 "--rebuild-if-new-ver": {
892 "help" : "Rebuild packages when dependencies that are " + \
893 "used at both build-time and run-time are built, " + \
894 "if the dependency is not already installed with the " + \
895 "same version. Revision numbers are ignored.",
897 "choices" : true_y_or_n
900 "--rebuild-if-unbuilt": {
901 "help" : "Rebuild packages when dependencies that are " + \
902 "used at both build-time and run-time are built.",
904 "choices" : true_y_or_n
907 "--rebuilt-binaries": {
908 "help" : "replace installed packages with binary " + \
909 "packages that have been rebuilt",
911 "choices" : true_y_or_n
914 "--rebuilt-binaries-timestamp": {
915 "help" : "use only binaries that are newer than this " + \
916 "timestamp for --rebuilt-binaries",
921 "help" : "specify the target root filesystem for merging packages",
926 "help" : "modify interpretation of depedencies",
928 "choices" :("True", "rdeps")
932 "help" : "add specified packages to the world set " + \
933 "(inverse of --oneshot)",
935 "choices" : true_y_or_n
939 "help" : "identical to --noreplace",
941 "choices" : true_y_or_n
944 "--use-ebuild-visibility": {
945 "help" : "use unbuilt ebuild metadata for visibility checks on built packages",
947 "choices" : true_y_or_n
950 "--useoldpkg-atoms": {
951 "help" :"A space separated list of package names or slot atoms. " + \
952 "Emerge will prefer matching binary packages over newer unbuilt packages. ",
959 "help" : "use binary packages",
961 "choices" : true_y_or_n
966 "help" : "use only binary packages",
968 "choices" : true_y_or_n
973 if _ENABLE_DYN_LINK_MAP:
974 argument_options["--depclean-lib-check"] = {
975 "help" : "check for consumers of libraries before removing them",
977 "choices" : true_y_or_n
980 from optparse import OptionParser
981 parser = OptionParser()
982 if parser.has_option("--help"):
983 parser.remove_option("--help")
985 for action_opt in actions:
986 parser.add_option("--" + action_opt, action="store_true",
987 dest=action_opt.replace("-", "_"), default=False)
988 for myopt in options:
989 parser.add_option(myopt, action="store_true",
990 dest=myopt.lstrip("--").replace("-", "_"), default=False)
991 for shortopt, longopt in shortmapping.items():
992 parser.add_option("-" + shortopt, action="store_true",
993 dest=longopt.lstrip("--").replace("-", "_"), default=False)
994 for myalias, myopt in longopt_aliases.items():
995 parser.add_option(myalias, action="store_true",
996 dest=myopt.lstrip("--").replace("-", "_"), default=False)
998 for myopt, kwargs in argument_options.items():
999 shortopt = kwargs.pop("shortopt", None)
1001 if shortopt is not None:
1002 args.append(shortopt)
1003 parser.add_option(dest=myopt.lstrip("--").replace("-", "_"),
1006 tmpcmdline = insert_optional_args(tmpcmdline)
1008 myoptions, myargs = parser.parse_args(args=tmpcmdline)
1010 if myoptions.ask in true_y:
1011 myoptions.ask = True
1013 myoptions.ask = None
1015 if myoptions.autounmask in true_y:
1016 myoptions.autounmask = True
1018 if myoptions.autounmask_unrestricted_atoms in true_y:
1019 myoptions.autounmask_unrestricted_atoms = True
1021 if myoptions.autounmask_keep_masks in true_y:
1022 myoptions.autounmask_keep_masks = True
1024 if myoptions.autounmask_write in true_y:
1025 myoptions.autounmask_write = True
1027 if myoptions.buildpkg in true_y:
1028 myoptions.buildpkg = True
1030 if myoptions.buildpkg_exclude:
1031 bad_atoms = _find_bad_atoms(myoptions.buildpkg_exclude, less_strict=True)
1032 if bad_atoms and not silent:
1033 parser.error("Invalid Atom(s) in --buildpkg-exclude parameter: '%s'\n" % \
1034 (",".join(bad_atoms),))
1036 if myoptions.changed_use is not False:
1037 myoptions.reinstall = "changed-use"
1038 myoptions.changed_use = False
1040 if myoptions.deselect in true_y:
1041 myoptions.deselect = True
1043 if myoptions.binpkg_respect_use is not None:
1044 if myoptions.binpkg_respect_use in true_y:
1045 myoptions.binpkg_respect_use = 'y'
1047 myoptions.binpkg_respect_use = 'n'
1049 if myoptions.complete_graph in true_y:
1050 myoptions.complete_graph = True
1052 myoptions.complete_graph = None
1054 if _ENABLE_DYN_LINK_MAP:
1055 if myoptions.depclean_lib_check in true_y:
1056 myoptions.depclean_lib_check = True
1058 if myoptions.exclude:
1059 bad_atoms = _find_bad_atoms(myoptions.exclude)
1060 if bad_atoms and not silent:
1061 parser.error("Invalid Atom(s) in --exclude parameter: '%s' (only package names and slot atoms (with wildcards) allowed)\n" % \
1062 (",".join(bad_atoms),))
1064 if myoptions.reinstall_atoms:
1065 bad_atoms = _find_bad_atoms(myoptions.reinstall_atoms)
1066 if bad_atoms and not silent:
1067 parser.error("Invalid Atom(s) in --reinstall-atoms parameter: '%s' (only package names and slot atoms (with wildcards) allowed)\n" % \
1068 (",".join(bad_atoms),))
1070 if myoptions.rebuild_exclude:
1071 bad_atoms = _find_bad_atoms(myoptions.rebuild_exclude)
1072 if bad_atoms and not silent:
1073 parser.error("Invalid Atom(s) in --rebuild-exclude parameter: '%s' (only package names and slot atoms (with wildcards) allowed)\n" % \
1074 (",".join(bad_atoms),))
1076 if myoptions.rebuild_ignore:
1077 bad_atoms = _find_bad_atoms(myoptions.rebuild_ignore)
1078 if bad_atoms and not silent:
1079 parser.error("Invalid Atom(s) in --rebuild-ignore parameter: '%s' (only package names and slot atoms (with wildcards) allowed)\n" % \
1080 (",".join(bad_atoms),))
1082 if myoptions.usepkg_exclude:
1083 bad_atoms = _find_bad_atoms(myoptions.usepkg_exclude)
1084 if bad_atoms and not silent:
1085 parser.error("Invalid Atom(s) in --usepkg-exclude parameter: '%s' (only package names and slot atoms (with wildcards) allowed)\n" % \
1086 (",".join(bad_atoms),))
1088 if myoptions.useoldpkg_atoms:
1089 bad_atoms = _find_bad_atoms(myoptions.useoldpkg_atoms)
1090 if bad_atoms and not silent:
1091 parser.error("Invalid Atom(s) in --useoldpkg-atoms parameter: '%s' (only package names and slot atoms (with wildcards) allowed)\n" % \
1092 (",".join(bad_atoms),))
1094 if myoptions.fail_clean in true_y:
1095 myoptions.fail_clean = True
1097 if myoptions.getbinpkg in true_y:
1098 myoptions.getbinpkg = True
1100 myoptions.getbinpkg = None
1102 if myoptions.getbinpkgonly in true_y:
1103 myoptions.getbinpkgonly = True
1105 myoptions.getbinpkgonly = None
1107 if myoptions.keep_going in true_y:
1108 myoptions.keep_going = True
1110 myoptions.keep_going = None
1112 if myoptions.package_moves in true_y:
1113 myoptions.package_moves = True
1115 if myoptions.quiet in true_y:
1116 myoptions.quiet = True
1118 myoptions.quiet = None
1120 if myoptions.quiet_build in true_y:
1121 myoptions.quiet_build = 'y'
1123 if myoptions.rebuild_if_new_slot_abi in true_y:
1124 myoptions.rebuild_if_new_slot_abi = 'y'
1126 if myoptions.rebuild_if_new_ver in true_y:
1127 myoptions.rebuild_if_new_ver = True
1129 myoptions.rebuild_if_new_ver = None
1131 if myoptions.rebuild_if_new_rev in true_y:
1132 myoptions.rebuild_if_new_rev = True
1133 myoptions.rebuild_if_new_ver = None
1135 myoptions.rebuild_if_new_rev = None
1137 if myoptions.rebuild_if_unbuilt in true_y:
1138 myoptions.rebuild_if_unbuilt = True
1139 myoptions.rebuild_if_new_rev = None
1140 myoptions.rebuild_if_new_ver = None
1142 myoptions.rebuild_if_unbuilt = None
1144 if myoptions.rebuilt_binaries in true_y:
1145 myoptions.rebuilt_binaries = True
1147 if myoptions.root_deps in true_y:
1148 myoptions.root_deps = True
1150 if myoptions.select in true_y:
1151 myoptions.select = True
1152 myoptions.oneshot = False
1153 elif myoptions.select == "n":
1154 myoptions.oneshot = True
1156 if myoptions.selective in true_y:
1157 myoptions.selective = True
1159 if myoptions.backtrack is not None:
1162 backtrack = int(myoptions.backtrack)
1163 except (OverflowError, ValueError):
1169 parser.error("Invalid --backtrack parameter: '%s'\n" % \
1170 (myoptions.backtrack,))
1172 myoptions.backtrack = backtrack
1174 if myoptions.deep is not None:
1176 if myoptions.deep == "True":
1180 deep = int(myoptions.deep)
1181 except (OverflowError, ValueError):
1184 if deep is not True and deep < 0:
1187 parser.error("Invalid --deep parameter: '%s'\n" % \
1190 myoptions.deep = deep
1194 if myoptions.jobs == "True":
1198 jobs = int(myoptions.jobs)
1202 if jobs is not True and \
1206 parser.error("Invalid --jobs parameter: '%s'\n" % \
1209 myoptions.jobs = jobs
1211 if myoptions.load_average:
1213 load_average = float(myoptions.load_average)
1217 if load_average <= 0.0:
1220 parser.error("Invalid --load-average parameter: '%s'\n" % \
1221 (myoptions.load_average,))
1223 myoptions.load_average = load_average
1225 if myoptions.rebuilt_binaries_timestamp:
1227 rebuilt_binaries_timestamp = int(myoptions.rebuilt_binaries_timestamp)
1229 rebuilt_binaries_timestamp = -1
1231 if rebuilt_binaries_timestamp < 0:
1232 rebuilt_binaries_timestamp = 0
1234 parser.error("Invalid --rebuilt-binaries-timestamp parameter: '%s'\n" % \
1235 (myoptions.rebuilt_binaries_timestamp,))
1237 myoptions.rebuilt_binaries_timestamp = rebuilt_binaries_timestamp
1239 if myoptions.use_ebuild_visibility in true_y:
1240 myoptions.use_ebuild_visibility = True
1245 if myoptions.usepkg in true_y:
1246 myoptions.usepkg = True
1248 myoptions.usepkg = None
1250 if myoptions.usepkgonly in true_y:
1251 myoptions.usepkgonly = True
1253 myoptions.usepkgonly = None
1255 for myopt in options:
1256 v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"))
1258 myopts[myopt] = True
1260 for myopt in argument_options:
1261 v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"), None)
1265 if myoptions.searchdesc:
1266 myoptions.search = True
1268 for action_opt in actions:
1269 v = getattr(myoptions, action_opt.replace("-", "_"))
1272 multiple_actions(myaction, action_opt)
1274 myaction = action_opt
1276 if myaction is None and myoptions.deselect is True:
1277 myaction = 'deselect'
1279 if myargs and isinstance(myargs[0], bytes):
1280 for i in range(len(myargs)):
1281 myargs[i] = portage._unicode_decode(myargs[i])
1285 return myaction, myopts, myfiles
1287 # Warn about features that may confuse users and
1288 # lead them to report invalid bugs.
1289 _emerge_features_warn = frozenset(['keeptemp', 'keepwork'])
1291 def validate_ebuild_environment(trees):
1292 features_warn = set()
1293 for myroot in trees:
1294 settings = trees[myroot]["vartree"].settings
1296 features_warn.update(
1297 _emerge_features_warn.intersection(settings.features))
1300 msg = "WARNING: The FEATURES variable contains one " + \
1301 "or more values that should be disabled under " + \
1302 "normal circumstances: %s" % " ".join(features_warn)
1303 out = portage.output.EOutput()
1304 for line in textwrap.wrap(msg, 65):
1307 def apply_priorities(settings):
1313 os.nice(int(settings.get("PORTAGE_NICENESS", "0")))
1314 except (OSError, ValueError) as e:
1315 out = portage.output.EOutput()
1316 out.eerror("Failed to change nice value to '%s'" % \
1317 settings["PORTAGE_NICENESS"])
1318 out.eerror("%s\n" % str(e))
1320 def ionice(settings):
1322 ionice_cmd = settings.get("PORTAGE_IONICE_COMMAND")
1324 ionice_cmd = portage.util.shlex_split(ionice_cmd)
1328 variables = {"PID" : str(os.getpid())}
1329 cmd = [varexpand(x, mydict=variables) for x in ionice_cmd]
1332 rval = portage.process.spawn(cmd, env=os.environ)
1333 except portage.exception.CommandNotFound:
1334 # The OS kernel probably doesn't support ionice,
1335 # so return silently.
1338 if rval != os.EX_OK:
1339 out = portage.output.EOutput()
1340 out.eerror("PORTAGE_IONICE_COMMAND returned %d" % (rval,))
1341 out.eerror("See the make.conf(5) man page for PORTAGE_IONICE_COMMAND usage instructions.")
1343 def clean_logs(settings):
1345 if "clean-logs" not in settings.features:
1348 clean_cmd = settings.get("PORT_LOGDIR_CLEAN")
1350 clean_cmd = shlex_split(clean_cmd)
1354 logdir = settings.get("PORT_LOGDIR")
1355 if logdir is None or not os.path.isdir(logdir):
1358 variables = {"PORT_LOGDIR" : logdir}
1359 cmd = [varexpand(x, mydict=variables) for x in clean_cmd]
1362 rval = portage.process.spawn(cmd, env=os.environ)
1363 except portage.exception.CommandNotFound:
1366 if rval != os.EX_OK:
1367 out = portage.output.EOutput()
1368 out.eerror("PORT_LOGDIR_CLEAN returned %d" % (rval,))
1369 out.eerror("See the make.conf(5) man page for "
1370 "PORT_LOGDIR_CLEAN usage instructions.")
1372 def setconfig_fallback(root_config):
1373 from portage._sets.base import DummyPackageSet
1374 from portage._sets.files import WorldSelectedSet
1375 from portage._sets.profiles import PackagesSystemSet
1376 setconfig = root_config.setconfig
1377 setconfig.psets['world'] = DummyPackageSet(atoms=['@selected', '@system'])
1378 setconfig.psets['selected'] = WorldSelectedSet(root_config.settings['EROOT'])
1379 setconfig.psets['system'] = \
1380 PackagesSystemSet(root_config.settings.profiles)
1381 root_config.sets = setconfig.getSets()
1383 def get_missing_sets(root_config):
1384 # emerge requires existence of "world", "selected", and "system"
1387 for s in ("selected", "system", "world",):
1388 if s not in root_config.sets:
1389 missing_sets.append(s)
1393 def missing_sets_warning(root_config, missing_sets):
1394 if len(missing_sets) > 2:
1395 missing_sets_str = ", ".join('"%s"' % s for s in missing_sets[:-1])
1396 missing_sets_str += ', and "%s"' % missing_sets[-1]
1397 elif len(missing_sets) == 2:
1398 missing_sets_str = '"%s" and "%s"' % tuple(missing_sets)
1400 missing_sets_str = '"%s"' % missing_sets[-1]
1401 msg = ["emerge: incomplete set configuration, " + \
1402 "missing set(s): %s" % missing_sets_str]
1403 if root_config.sets:
1404 msg.append(" sets defined: %s" % ", ".join(root_config.sets))
1405 global_config_path = portage.const.GLOBAL_CONFIG_PATH
1406 if root_config.settings['EPREFIX']:
1407 global_config_path = os.path.join(root_config.settings['EPREFIX'],
1408 portage.const.GLOBAL_CONFIG_PATH.lstrip(os.sep))
1409 msg.append(" This usually means that '%s'" % \
1410 (os.path.join(global_config_path, "sets/portage.conf"),))
1411 msg.append(" is missing or corrupt.")
1412 msg.append(" Falling back to default world and system set configuration!!!")
1414 writemsg_level(line + "\n", level=logging.ERROR, noiselevel=-1)
1416 def ensure_required_sets(trees):
1417 warning_shown = False
1418 for root_trees in trees.values():
1419 missing_sets = get_missing_sets(root_trees["root_config"])
1420 if missing_sets and not warning_shown:
1421 warning_shown = True
1422 missing_sets_warning(root_trees["root_config"], missing_sets)
1424 setconfig_fallback(root_trees["root_config"])
1426 def expand_set_arguments(myfiles, myaction, root_config):
1428 setconfig = root_config.setconfig
1430 sets = setconfig.getSets()
1432 # In order to know exactly which atoms/sets should be added to the
1433 # world file, the depgraph performs set expansion later. It will get
1434 # confused about where the atoms came from if it's not allowed to
1435 # expand them itself.
1436 do_not_expand = (None, )
1439 if a in ("system", "world"):
1440 newargs.append(SETPREFIX+a)
1447 # separators for set arguments
1451 for i in range(0, len(myfiles)):
1452 if myfiles[i].startswith(SETPREFIX):
1455 x = myfiles[i][len(SETPREFIX):]
1458 start = x.find(ARG_START)
1459 end = x.find(ARG_END)
1460 if start > 0 and start < end:
1461 namepart = x[:start]
1462 argpart = x[start+1:end]
1464 # TODO: implement proper quoting
1465 args = argpart.split(",")
1469 k, v = a.split("=", 1)
1473 setconfig.update(namepart, options)
1474 newset += (x[:start-len(namepart)]+namepart)
1475 x = x[end+len(ARG_END):]
1479 myfiles[i] = SETPREFIX+newset
1481 sets = setconfig.getSets()
1483 # display errors that occurred while loading the SetConfig instance
1484 for e in setconfig.errors:
1485 print(colorize("BAD", "Error during set creation: %s" % e))
1487 unmerge_actions = ("unmerge", "prune", "clean", "depclean")
1490 if a.startswith(SETPREFIX):
1491 s = a[len(SETPREFIX):]
1493 display_missing_pkg_set(root_config, s)
1495 setconfig.active.append(s)
1497 set_atoms = setconfig.getSetAtoms(s)
1498 except portage.exception.PackageSetNotFound as e:
1499 writemsg_level(("emerge: the given set '%s' " + \
1500 "contains a non-existent set named '%s'.\n") % \
1501 (s, e), level=logging.ERROR, noiselevel=-1)
1503 if myaction in unmerge_actions and \
1504 not sets[s].supportsOperation("unmerge"):
1505 sys.stderr.write("emerge: the given set '%s' does " % s + \
1506 "not support unmerge operations\n")
1509 print("emerge: '%s' is an empty set" % s)
1510 elif myaction not in do_not_expand:
1511 newargs.extend(set_atoms)
1513 newargs.append(SETPREFIX+s)
1514 for e in sets[s].errors:
1518 return (newargs, retval)
1520 def repo_name_check(trees):
1521 missing_repo_names = set()
1522 for root_trees in trees.values():
1523 porttree = root_trees.get("porttree")
1525 portdb = porttree.dbapi
1526 missing_repo_names.update(portdb.getMissingRepoNames())
1527 if portdb.porttree_root in missing_repo_names and \
1528 not os.path.exists(os.path.join(
1529 portdb.porttree_root, "profiles")):
1530 # This is normal if $PORTDIR happens to be empty,
1531 # so don't warn about it.
1532 missing_repo_names.remove(portdb.porttree_root)
1534 if missing_repo_names:
1536 msg.append("WARNING: One or more repositories " + \
1537 "have missing repo_name entries:")
1539 for p in missing_repo_names:
1540 msg.append("\t%s/profiles/repo_name" % (p,))
1542 msg.extend(textwrap.wrap("NOTE: Each repo_name entry " + \
1543 "should be a plain text file containing a unique " + \
1544 "name for the repository on the first line.", 70))
1546 writemsg_level("".join("%s\n" % l for l in msg),
1547 level=logging.WARNING, noiselevel=-1)
1549 return bool(missing_repo_names)
1551 def repo_name_duplicate_check(trees):
1553 for root, root_trees in trees.items():
1554 if 'porttree' in root_trees:
1555 portdb = root_trees['porttree'].dbapi
1556 if portdb.settings.get('PORTAGE_REPO_DUPLICATE_WARN') != '0':
1557 for repo_name, paths in portdb.getIgnoredRepos():
1558 k = (root, repo_name, portdb.getRepositoryPath(repo_name))
1559 ignored_repos.setdefault(k, []).extend(paths)
1563 msg.append('WARNING: One or more repositories ' + \
1564 'have been ignored due to duplicate')
1565 msg.append(' profiles/repo_name entries:')
1567 for k in sorted(ignored_repos):
1568 msg.append(' %s overrides' % ", ".join(k))
1569 for path in ignored_repos[k]:
1570 msg.append(' %s' % (path,))
1572 msg.extend(' ' + x for x in textwrap.wrap(
1573 "All profiles/repo_name entries must be unique in order " + \
1574 "to avoid having duplicates ignored. " + \
1575 "Set PORTAGE_REPO_DUPLICATE_WARN=\"0\" in " + \
1576 "/etc/make.conf if you would like to disable this warning."))
1578 writemsg_level(''.join('%s\n' % l for l in msg),
1579 level=logging.WARNING, noiselevel=-1)
1581 return bool(ignored_repos)
1583 def config_protect_check(trees):
1584 for root, root_trees in trees.items():
1585 settings = root_trees["root_config"].settings
1586 if not settings.get("CONFIG_PROTECT"):
1587 msg = "!!! CONFIG_PROTECT is empty"
1588 if settings["ROOT"] != "/":
1589 msg += " for '%s'" % root
1591 writemsg_level(msg, level=logging.WARN, noiselevel=-1)
1593 def profile_check(trees, myaction):
1594 if myaction in ("help", "info", "search", "sync", "version"):
1596 for root_trees in trees.values():
1597 if root_trees["root_config"].settings.profiles:
1599 # generate some profile related warning messages
1600 validate_ebuild_environment(trees)
1601 msg = ("Your current profile is invalid. If you have just changed "
1602 "your profile configuration, you should revert back to the "
1603 "previous configuration. Allowed actions are limited to "
1604 "--help, --info, --search, --sync, and --version.")
1605 writemsg_level("".join("!!! %s\n" % l for l in textwrap.wrap(msg, 70)),
1606 level=logging.ERROR, noiselevel=-1)
1611 procfs_path = '/proc'
1612 if platform.system() not in ("Linux",) or \
1613 os.path.ismount(procfs_path):
1615 msg = "It seems that %s is not mounted. You have been warned." % procfs_path
1616 writemsg_level("".join("!!! %s\n" % l for l in textwrap.wrap(msg, 70)),
1617 level=logging.ERROR, noiselevel=-1)
1620 def emerge_main(args=None):
1622 @param args: command arguments (default: sys.argv[1:])
1628 portage._disable_legacy_globals()
1629 portage.dep._internal_warnings = True
1630 # Disable color until we're sure that it should be enabled (after
1631 # EMERGE_DEFAULT_OPTS has been parsed).
1632 portage.output.havecolor = 0
1633 # This first pass is just for options that need to be known as early as
1634 # possible, such as --config-root. They will be parsed again later,
1635 # together with EMERGE_DEFAULT_OPTS (which may vary depending on the
1636 # the value of --config-root).
1637 myaction, myopts, myfiles = parse_opts(args, silent=True)
1638 if "--debug" in myopts:
1639 os.environ["PORTAGE_DEBUG"] = "1"
1640 if "--config-root" in myopts:
1641 os.environ["PORTAGE_CONFIGROOT"] = myopts["--config-root"]
1642 if "--root" in myopts:
1643 os.environ["ROOT"] = myopts["--root"]
1644 if "--accept-properties" in myopts:
1645 os.environ["ACCEPT_PROPERTIES"] = myopts["--accept-properties"]
1647 # Portage needs to ensure a sane umask for the files it creates.
1649 settings, trees, mtimedb = load_emerge_config()
1650 portdb = trees[settings['EROOT']]['porttree'].dbapi
1651 rval = profile_check(trees, myaction)
1652 if rval != os.EX_OK:
1656 if "--ignore-default-opts" not in myopts:
1657 tmpcmdline.extend(settings["EMERGE_DEFAULT_OPTS"].split())
1658 tmpcmdline.extend(args)
1659 myaction, myopts, myfiles = parse_opts(tmpcmdline)
1661 # skip global updates prior to sync, since it's called after sync
1662 if myaction not in ('help', 'info', 'sync', 'version') and \
1663 myopts.get('--package-moves') != 'n' and \
1664 _global_updates(trees, mtimedb["updates"], quiet=("--quiet" in myopts)):
1666 # Reload the whole config from scratch.
1667 settings, trees, mtimedb = load_emerge_config(trees=trees)
1668 portdb = trees[settings['EROOT']]['porttree'].dbapi
1670 xterm_titles = "notitles" not in settings.features
1672 xtermTitle("emerge")
1674 if "--digest" in myopts:
1675 os.environ["FEATURES"] = os.environ.get("FEATURES","") + " digest"
1676 # Reload the whole config from scratch so that the portdbapi internal
1677 # config is updated with new FEATURES.
1678 settings, trees, mtimedb = load_emerge_config(trees=trees)
1679 portdb = trees[settings['EROOT']]['porttree'].dbapi
1681 # NOTE: adjust_configs() can map options to FEATURES, so any relevant
1682 # options adjustments should be made prior to calling adjust_configs().
1683 if "--buildpkgonly" in myopts:
1684 myopts["--buildpkg"] = True
1686 adjust_configs(myopts, trees)
1687 apply_priorities(settings)
1689 if myaction == 'version':
1690 writemsg_stdout(getportageversion(
1691 settings["PORTDIR"], None,
1692 settings.profile_path, settings["CHOST"],
1693 trees[settings['EROOT']]['vartree'].dbapi) + '\n', noiselevel=-1)
1695 elif myaction == 'help':
1699 spinner = stdout_spinner()
1700 if "candy" in settings.features:
1701 spinner.update = spinner.update_scroll
1703 if "--quiet" not in myopts:
1704 portage.deprecated_profile_check(settings=settings)
1705 if portage.const._ENABLE_REPO_NAME_WARN:
1706 # Bug #248603 - Disable warnings about missing
1707 # repo_name entries for stable branch.
1708 repo_name_check(trees)
1709 repo_name_duplicate_check(trees)
1710 config_protect_check(trees)
1713 if "getbinpkg" in settings.features:
1714 myopts["--getbinpkg"] = True
1716 if "--getbinpkgonly" in myopts:
1717 myopts["--getbinpkg"] = True
1719 if "--getbinpkgonly" in myopts:
1720 myopts["--usepkgonly"] = True
1722 if "--getbinpkg" in myopts:
1723 myopts["--usepkg"] = True
1725 if "--usepkgonly" in myopts:
1726 myopts["--usepkg"] = True
1728 if "--buildpkgonly" in myopts:
1729 # --buildpkgonly will not merge anything, so
1730 # it cancels all binary package options.
1731 for opt in ("--getbinpkg", "--getbinpkgonly",
1732 "--usepkg", "--usepkgonly"):
1733 myopts.pop(opt, None)
1735 for mytrees in trees.values():
1736 mydb = mytrees["porttree"].dbapi
1737 # Freeze the portdbapi for performance (memoize all xmatch results).
1740 if myaction in ('search', None) and \
1741 "--usepkg" in myopts:
1742 # Populate the bintree with current --getbinpkg setting.
1743 # This needs to happen before expand_set_arguments(), in case
1744 # any sets use the bintree.
1745 mytrees["bintree"].populate(
1746 getbinpkgs="--getbinpkg" in myopts)
1750 if "moo" in myfiles:
1751 print(COWSAY_MOO % platform.system())
1752 msg = ("The above `emerge moo` display is deprecated. "
1753 "Please use `emerge --moo` instead.")
1754 for line in textwrap.wrap(msg, 50):
1755 print(" %s %s" % (colorize("WARN", "*"), line))
1758 ext = os.path.splitext(x)[1]
1759 if (ext == ".ebuild" or ext == ".tbz2") and os.path.exists(os.path.abspath(x)):
1760 print(colorize("BAD", "\n*** emerging by path is broken and may not always work!!!\n"))
1763 root_config = trees[settings['EROOT']]['root_config']
1764 if myaction == "moo":
1765 print(COWSAY_MOO % platform.system())
1767 elif myaction == "list-sets":
1768 writemsg_stdout("".join("%s\n" % s for s in sorted(root_config.sets)))
1770 elif myaction == "check-news":
1771 news_counts = count_unread_news(
1772 root_config.trees["porttree"].dbapi,
1773 root_config.trees["vartree"].dbapi)
1774 if any(news_counts.values()):
1775 display_news_notifications(news_counts)
1776 elif "--quiet" not in myopts:
1777 print("", colorize("GOOD", "*"), "No news items were found.")
1780 ensure_required_sets(trees)
1782 # only expand sets for actions taking package arguments
1783 oldargs = myfiles[:]
1784 if myaction in ("clean", "config", "depclean", "info", "prune", "unmerge", None):
1785 myfiles, retval = expand_set_arguments(myfiles, myaction, root_config)
1786 if retval != os.EX_OK:
1789 # Need to handle empty sets specially, otherwise emerge will react
1790 # with the help message for empty argument lists
1791 if oldargs and not myfiles:
1792 print("emerge: no targets left after set expansion")
1795 if ("--tree" in myopts) and ("--columns" in myopts):
1796 print("emerge: can't specify both of \"--tree\" and \"--columns\".")
1799 if '--emptytree' in myopts and '--noreplace' in myopts:
1800 writemsg_level("emerge: can't specify both of " + \
1801 "\"--emptytree\" and \"--noreplace\".\n",
1802 level=logging.ERROR, noiselevel=-1)
1805 if ("--quiet" in myopts):
1806 spinner.update = spinner.update_quiet
1807 portage.util.noiselimit = -1
1809 if "--fetch-all-uri" in myopts:
1810 myopts["--fetchonly"] = True
1812 if "--skipfirst" in myopts and "--resume" not in myopts:
1813 myopts["--resume"] = True
1815 # Allow -p to remove --ask
1816 if "--pretend" in myopts:
1817 myopts.pop("--ask", None)
1819 # forbid --ask when not in a terminal
1820 # note: this breaks `emerge --ask | tee logfile`, but that doesn't work anyway.
1821 if ("--ask" in myopts) and (not sys.stdin.isatty()):
1822 portage.writemsg("!!! \"--ask\" should only be used in a terminal. Exiting.\n",
1826 if settings.get("PORTAGE_DEBUG", "") == "1":
1827 spinner.update = spinner.update_quiet
1828 portage.util.noiselimit = 0
1829 if "python-trace" in settings.features:
1830 import portage.debug as portage_debug
1831 portage_debug.set_trace(True)
1833 if not ("--quiet" in myopts):
1834 if '--nospinner' in myopts or \
1835 settings.get('TERM') == 'dumb' or \
1836 not sys.stdout.isatty():
1837 spinner.update = spinner.update_basic
1839 if "--debug" in myopts:
1840 print("myaction", myaction)
1841 print("myopts", myopts)
1843 if not myaction and not myfiles and "--resume" not in myopts:
1847 pretend = "--pretend" in myopts
1848 fetchonly = "--fetchonly" in myopts or "--fetch-all-uri" in myopts
1849 buildpkgonly = "--buildpkgonly" in myopts
1851 # check if root user is the current user for the actions where emerge needs this
1852 if portage.secpass < 2:
1853 # We've already allowed "--version" and "--help" above.
1854 if "--pretend" not in myopts and myaction not in ("search","info"):
1855 need_superuser = myaction in ('clean', 'depclean', 'deselect',
1856 'prune', 'unmerge') or not \
1858 (buildpkgonly and secpass >= 1) or \
1859 myaction in ("metadata", "regen", "sync"))
1860 if portage.secpass < 1 or \
1863 access_desc = "superuser"
1865 access_desc = "portage group"
1866 # Always show portage_group_warning() when only portage group
1867 # access is required but the user is not in the portage group.
1868 from portage.data import portage_group_warning
1869 if "--ask" in myopts:
1870 writemsg_stdout("This action requires %s access...\n" % \
1871 (access_desc,), noiselevel=-1)
1872 if portage.secpass < 1 and not need_superuser:
1873 portage_group_warning()
1874 if userquery("Would you like to add --pretend to options?",
1875 "--ask-enter-invalid" in myopts) == "No":
1876 return 128 + signal.SIGINT
1877 myopts["--pretend"] = True
1880 sys.stderr.write(("emerge: %s access is required\n") \
1882 if portage.secpass < 1 and not need_superuser:
1883 portage_group_warning()
1886 # Disable emergelog for everything except build or unmerge operations.
1887 # This helps minimize parallel emerge.log entries that can confuse log
1888 # parsers like genlop.
1889 disable_emergelog = False
1890 for x in ("--pretend", "--fetchonly", "--fetch-all-uri"):
1892 disable_emergelog = True
1894 if disable_emergelog:
1896 elif myaction in ("search", "info"):
1897 disable_emergelog = True
1898 elif portage.data.secpass < 1:
1899 disable_emergelog = True
1901 _emerge.emergelog._disable = disable_emergelog
1903 if not disable_emergelog:
1904 if 'EMERGE_LOG_DIR' in settings:
1906 # At least the parent needs to exist for the lock file.
1907 portage.util.ensure_dirs(settings['EMERGE_LOG_DIR'])
1908 except portage.exception.PortageException as e:
1909 writemsg_level("!!! Error creating directory for " + \
1910 "EMERGE_LOG_DIR='%s':\n!!! %s\n" % \
1911 (settings['EMERGE_LOG_DIR'], e),
1912 noiselevel=-1, level=logging.ERROR)
1913 portage.util.ensure_dirs(_emerge.emergelog._emerge_log_dir)
1915 _emerge.emergelog._emerge_log_dir = settings["EMERGE_LOG_DIR"]
1917 _emerge.emergelog._emerge_log_dir = os.path.join(os.sep,
1918 settings["EPREFIX"].lstrip(os.sep), "var", "log")
1919 portage.util.ensure_dirs(_emerge.emergelog._emerge_log_dir)
1921 if not "--pretend" in myopts:
1922 emergelog(xterm_titles, "Started emerge on: "+\
1924 time.strftime("%b %d, %Y %H:%M:%S", time.localtime()),
1925 encoding=_encodings['content'], errors='replace'))
1929 for opt, arg in myopts.items():
1931 opt_list.append(opt)
1932 elif isinstance(arg, list):
1933 # arguments like --exclude that use 'append' action
1935 opt_list.append("%s=%s" % (opt, x))
1937 opt_list.append("%s=%s" % (opt, arg))
1938 myelogstr=" ".join(opt_list)
1940 myelogstr += " --" + myaction
1942 myelogstr += " " + " ".join(oldargs)
1943 emergelog(xterm_titles, " *** emerge " + myelogstr)
1946 def emergeexitsig(signum, frame):
1947 signal.signal(signal.SIGINT, signal.SIG_IGN)
1948 signal.signal(signal.SIGTERM, signal.SIG_IGN)
1949 portage.util.writemsg("\n\nExiting on signal %(signal)s\n" % {"signal":signum})
1950 sys.exit(128 + signum)
1951 signal.signal(signal.SIGINT, emergeexitsig)
1952 signal.signal(signal.SIGTERM, emergeexitsig)
1955 """This gets out final log message in before we quit."""
1956 if "--pretend" not in myopts:
1957 emergelog(xterm_titles, " *** terminating.")
1960 portage.atexit_register(emergeexit)
1962 if myaction in ("config", "metadata", "regen", "sync"):
1963 if "--pretend" in myopts:
1964 sys.stderr.write(("emerge: The '%s' action does " + \
1965 "not support '--pretend'.\n") % myaction)
1968 if "sync" == myaction:
1969 return action_sync(settings, trees, mtimedb, myopts, myaction)
1970 elif "metadata" == myaction:
1971 action_metadata(settings, portdb, myopts)
1972 elif myaction=="regen":
1973 validate_ebuild_environment(trees)
1974 return action_regen(settings, portdb, myopts.get("--jobs"),
1975 myopts.get("--load-average"))
1977 elif "config"==myaction:
1978 validate_ebuild_environment(trees)
1979 action_config(settings, trees, myopts, myfiles)
1982 elif "search"==myaction:
1983 validate_ebuild_environment(trees)
1984 action_search(trees[settings['EROOT']]['root_config'],
1985 myopts, myfiles, spinner)
1987 elif myaction in ('clean', 'depclean', 'deselect', 'prune', 'unmerge'):
1988 validate_ebuild_environment(trees)
1989 rval = action_uninstall(settings, trees, mtimedb["ldpath"],
1990 myopts, myaction, myfiles, spinner)
1991 if not (myaction == 'deselect' or buildpkgonly or fetchonly or pretend):
1992 post_emerge(myaction, myopts, myfiles, settings['EROOT'],
1993 trees, mtimedb, rval)
1996 elif myaction == 'info':
1998 # Ensure atoms are valid before calling unmerge().
1999 vardb = trees[settings['EROOT']]['vartree'].dbapi
2000 portdb = trees[settings['EROOT']]['porttree'].dbapi
2001 bindb = trees[settings['EROOT']]["bintree"].dbapi
2004 if is_valid_package_atom(x, allow_repo=True):
2006 #look at the installed files first, if there is no match
2007 #look at the ebuilds, since EAPI 4 allows running pkg_info
2008 #on non-installed packages
2009 valid_atom = dep_expand(x, mydb=vardb, settings=settings)
2010 if valid_atom.cp.split("/")[0] == "null":
2011 valid_atom = dep_expand(x, mydb=portdb, settings=settings)
2012 if valid_atom.cp.split("/")[0] == "null" and "--usepkg" in myopts:
2013 valid_atom = dep_expand(x, mydb=bindb, settings=settings)
2014 valid_atoms.append(valid_atom)
2015 except portage.exception.AmbiguousPackageName as e:
2016 msg = "The short ebuild name \"" + x + \
2017 "\" is ambiguous. Please specify " + \
2018 "one of the following " + \
2019 "fully-qualified ebuild names instead:"
2020 for line in textwrap.wrap(msg, 70):
2021 writemsg_level("!!! %s\n" % (line,),
2022 level=logging.ERROR, noiselevel=-1)
2024 writemsg_level(" %s\n" % colorize("INFORM", i),
2025 level=logging.ERROR, noiselevel=-1)
2026 writemsg_level("\n", level=logging.ERROR, noiselevel=-1)
2030 msg.append("'%s' is not a valid package atom." % (x,))
2031 msg.append("Please check ebuild(5) for full details.")
2032 writemsg_level("".join("!!! %s\n" % line for line in msg),
2033 level=logging.ERROR, noiselevel=-1)
2036 return action_info(settings, trees, myopts, valid_atoms)
2038 # "update", "system", or just process files:
2040 validate_ebuild_environment(trees)
2043 if x.startswith(SETPREFIX) or \
2044 is_valid_package_atom(x, allow_repo=True):
2054 msg.append("'%s' is not a valid package atom." % (x,))
2055 msg.append("Please check ebuild(5) for full details.")
2056 writemsg_level("".join("!!! %s\n" % line for line in msg),
2057 level=logging.ERROR, noiselevel=-1)
2060 # GLEP 42 says to display news *after* an emerge --pretend
2061 if "--pretend" not in myopts:
2062 display_news_notification(root_config, myopts)
2063 retval = action_build(settings, trees, mtimedb,
2064 myopts, myaction, myfiles, spinner)
2065 post_emerge(myaction, myopts, myfiles, settings['EROOT'],
2066 trees, mtimedb, retval)