summaryrefslogtreecommitdiffstats
path: root/pym/_emerge/__init__.py
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2009-06-26 20:06:08 +0000
committerZac Medico <zmedico@gentoo.org>2009-06-26 20:06:08 +0000
commit2801d985efc89ea124489b8b4b5d8452e40615a7 (patch)
treea0d4f13c42a5b58fc1e358b8c2a3275ff31d3b02 /pym/_emerge/__init__.py
parent6113aa2cd60a36ecd95bc379d0012bcb0c44ddfa (diff)
downloadportage-2801d985efc89ea124489b8b4b5d8452e40615a7.tar.gz
portage-2801d985efc89ea124489b8b4b5d8452e40615a7.tar.bz2
portage-2801d985efc89ea124489b8b4b5d8452e40615a7.zip
Move __init__.py to main.py.
svn path=/main/trunk/; revision=13697
Diffstat (limited to 'pym/_emerge/__init__.py')
-rw-r--r--pym/_emerge/__init__.py1282
1 files changed, 0 insertions, 1282 deletions
diff --git a/pym/_emerge/__init__.py b/pym/_emerge/__init__.py
deleted file mode 100644
index f73bc6db4..000000000
--- a/pym/_emerge/__init__.py
+++ /dev/null
@@ -1,1282 +0,0 @@
-# Copyright 1999-2009 Gentoo Foundation
-# Distributed under the terms of the GNU General Public License v2
-# $Id$
-
-import logging
-import shlex
-import signal
-import sys
-import textwrap
-import os
-import platform
-
-try:
- import portage
-except ImportError:
- from os import path as osp
- sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym"))
- import portage
-
-import _emerge.help
-import portage.xpak, commands, errno, re, time
-from portage.output import colorize, xtermTitleReset
-from portage.output import create_color_func
-good = create_color_func("GOOD")
-bad = create_color_func("BAD")
-
-import portage.elog
-import portage.dep
-portage.dep._dep_check_strict = True
-import portage.util
-import portage.locks
-import portage.exception
-from portage.data import secpass
-from portage.util import normalize_path as normpath
-from portage.util import writemsg, writemsg_level
-from portage.sets import SETPREFIX
-
-from _emerge.actions import action_config, action_sync, action_metadata, \
- action_regen, action_search, action_uninstall, action_info, action_build, \
- adjust_config, chk_updated_cfg_files, display_missing_pkg_set, \
- display_news_notification, getportageversion, load_emerge_config
-from _emerge.emergelog import emergelog
-from _emerge._flush_elog_mod_echo import _flush_elog_mod_echo
-from _emerge.is_valid_package_atom import is_valid_package_atom
-from _emerge.stdout_spinner import stdout_spinner
-
-options=[
-"--ask", "--alphabetical",
-"--buildpkg", "--buildpkgonly",
-"--changelog", "--columns",
-"--complete-graph",
-"--debug", "--deep",
-"--digest",
-"--emptytree",
-"--fetchonly", "--fetch-all-uri",
-"--getbinpkg", "--getbinpkgonly",
-"--help", "--ignore-default-opts",
-"--keep-going",
-"--noconfmem",
-"--newuse",
-"--nodeps", "--noreplace",
-"--nospinner", "--oneshot",
-"--onlydeps", "--pretend",
-"--quiet", "--resume",
-"--searchdesc", "--selective",
-"--skipfirst",
-"--tree",
-"--update",
-"--usepkg", "--usepkgonly",
-"--verbose",
-]
-
-shortmapping={
-"1":"--oneshot",
-"a":"--ask",
-"b":"--buildpkg", "B":"--buildpkgonly",
-"c":"--clean", "C":"--unmerge",
-"d":"--debug", "D":"--deep",
-"e":"--emptytree",
-"f":"--fetchonly", "F":"--fetch-all-uri",
-"g":"--getbinpkg", "G":"--getbinpkgonly",
-"h":"--help",
-"k":"--usepkg", "K":"--usepkgonly",
-"l":"--changelog",
-"n":"--noreplace", "N":"--newuse",
-"o":"--onlydeps", "O":"--nodeps",
-"p":"--pretend", "P":"--prune",
-"q":"--quiet",
-"s":"--search", "S":"--searchdesc",
-"t":"--tree",
-"u":"--update",
-"v":"--verbose", "V":"--version"
-}
-
-def chk_updated_info_files(root, infodirs, prev_mtimes, retval):
-
- if os.path.exists("/usr/bin/install-info"):
- out = portage.output.EOutput()
- regen_infodirs=[]
- for z in infodirs:
- if z=='':
- continue
- inforoot=normpath(root+z)
- if os.path.isdir(inforoot):
- infomtime = long(os.stat(inforoot).st_mtime)
- if inforoot not in prev_mtimes or \
- prev_mtimes[inforoot] != infomtime:
- regen_infodirs.append(inforoot)
-
- if not regen_infodirs:
- portage.writemsg_stdout("\n")
- out.einfo("GNU info directory index is up-to-date.")
- else:
- portage.writemsg_stdout("\n")
- out.einfo("Regenerating GNU info directory index...")
-
- dir_extensions = ("", ".gz", ".bz2")
- icount=0
- badcount=0
- errmsg = ""
- for inforoot in regen_infodirs:
- if inforoot=='':
- continue
-
- if not os.path.isdir(inforoot) or \
- not os.access(inforoot, os.W_OK):
- continue
-
- file_list = os.listdir(inforoot)
- file_list.sort()
- dir_file = os.path.join(inforoot, "dir")
- moved_old_dir = False
- processed_count = 0
- for x in file_list:
- if x.startswith(".") or \
- os.path.isdir(os.path.join(inforoot, x)):
- continue
- if x.startswith("dir"):
- skip = False
- for ext in dir_extensions:
- if x == "dir" + ext or \
- x == "dir" + ext + ".old":
- skip = True
- break
- if skip:
- continue
- if processed_count == 0:
- for ext in dir_extensions:
- try:
- os.rename(dir_file + ext, dir_file + ext + ".old")
- moved_old_dir = True
- except EnvironmentError, e:
- if e.errno != errno.ENOENT:
- raise
- del e
- processed_count += 1
- myso=commands.getstatusoutput("LANG=C LANGUAGE=C /usr/bin/install-info --dir-file="+inforoot+"/dir "+inforoot+"/"+x)[1]
- existsstr="already exists, for file `"
- if myso!="":
- if re.search(existsstr,myso):
- # Already exists... Don't increment the count for this.
- pass
- elif myso[:44]=="install-info: warning: no info dir entry in ":
- # This info file doesn't contain a DIR-header: install-info produces this
- # (harmless) warning (the --quiet switch doesn't seem to work).
- # Don't increment the count for this.
- pass
- else:
- badcount=badcount+1
- errmsg += myso + "\n"
- icount=icount+1
-
- if moved_old_dir and not os.path.exists(dir_file):
- # We didn't generate a new dir file, so put the old file
- # back where it was originally found.
- for ext in dir_extensions:
- try:
- os.rename(dir_file + ext + ".old", dir_file + ext)
- except EnvironmentError, e:
- if e.errno != errno.ENOENT:
- raise
- del e
-
- # Clean dir.old cruft so that they don't prevent
- # unmerge of otherwise empty directories.
- for ext in dir_extensions:
- try:
- os.unlink(dir_file + ext + ".old")
- except EnvironmentError, e:
- if e.errno != errno.ENOENT:
- raise
- del e
-
- #update mtime so we can potentially avoid regenerating.
- prev_mtimes[inforoot] = long(os.stat(inforoot).st_mtime)
-
- if badcount:
- out.eerror("Processed %d info files; %d errors." % \
- (icount, badcount))
- writemsg_level(errmsg, level=logging.ERROR, noiselevel=-1)
- else:
- if icount > 0:
- out.einfo("Processed %d info files." % (icount,))
-
-
-def display_preserved_libs(vardbapi):
- MAX_DISPLAY = 3
-
- # Ensure the registry is consistent with existing files.
- vardbapi.plib_registry.pruneNonExisting()
-
- if vardbapi.plib_registry.hasEntries():
- print
- print colorize("WARN", "!!!") + " existing preserved libs:"
- plibdata = vardbapi.plib_registry.getPreservedLibs()
- linkmap = vardbapi.linkmap
- consumer_map = {}
- owners = {}
- linkmap_broken = False
-
- try:
- linkmap.rebuild()
- except portage.exception.CommandNotFound, e:
- writemsg_level("!!! Command Not Found: %s\n" % (e,),
- level=logging.ERROR, noiselevel=-1)
- del e
- linkmap_broken = True
- else:
- search_for_owners = set()
- for cpv in plibdata:
- internal_plib_keys = set(linkmap._obj_key(f) \
- for f in plibdata[cpv])
- for f in plibdata[cpv]:
- if f in consumer_map:
- continue
- consumers = []
- for c in linkmap.findConsumers(f):
- # Filter out any consumers that are also preserved libs
- # belonging to the same package as the provider.
- if linkmap._obj_key(c) not in internal_plib_keys:
- consumers.append(c)
- consumers.sort()
- consumer_map[f] = consumers
- search_for_owners.update(consumers[:MAX_DISPLAY+1])
-
- owners = vardbapi._owners.getFileOwnerMap(search_for_owners)
-
- for cpv in plibdata:
- print colorize("WARN", ">>>") + " package: %s" % cpv
- samefile_map = {}
- for f in plibdata[cpv]:
- obj_key = linkmap._obj_key(f)
- alt_paths = samefile_map.get(obj_key)
- if alt_paths is None:
- alt_paths = set()
- samefile_map[obj_key] = alt_paths
- alt_paths.add(f)
-
- for alt_paths in samefile_map.itervalues():
- alt_paths = sorted(alt_paths)
- for p in alt_paths:
- print colorize("WARN", " * ") + " - %s" % (p,)
- f = alt_paths[0]
- consumers = consumer_map.get(f, [])
- for c in consumers[:MAX_DISPLAY]:
- print colorize("WARN", " * ") + " used by %s (%s)" % \
- (c, ", ".join(x.mycpv for x in owners.get(c, [])))
- if len(consumers) == MAX_DISPLAY + 1:
- print colorize("WARN", " * ") + " used by %s (%s)" % \
- (consumers[MAX_DISPLAY], ", ".join(x.mycpv \
- for x in owners.get(consumers[MAX_DISPLAY], [])))
- elif len(consumers) > MAX_DISPLAY:
- print colorize("WARN", " * ") + " used by %d other files" % (len(consumers) - MAX_DISPLAY)
- print "Use " + colorize("GOOD", "emerge @preserved-rebuild") + " to rebuild packages using these libraries"
-
-
-def post_emerge(root_config, myopts, mtimedb, retval):
- """
- Misc. things to run at the end of a merge session.
-
- Update Info Files
- Update Config Files
- Update News Items
- Commit mtimeDB
- Display preserved libs warnings
- Exit Emerge
-
- @param trees: A dictionary mapping each ROOT to it's package databases
- @type trees: dict
- @param mtimedb: The mtimeDB to store data needed across merge invocations
- @type mtimedb: MtimeDB class instance
- @param retval: Emerge's return value
- @type retval: Int
- @rype: None
- @returns:
- 1. Calls sys.exit(retval)
- """
-
- target_root = root_config.root
- trees = { target_root : root_config.trees }
- vardbapi = trees[target_root]["vartree"].dbapi
- settings = vardbapi.settings
- info_mtimes = mtimedb["info"]
-
- # Load the most current variables from ${ROOT}/etc/profile.env
- settings.unlock()
- settings.reload()
- settings.regenerate()
- settings.lock()
-
- config_protect = settings.get("CONFIG_PROTECT","").split()
- infodirs = settings.get("INFOPATH","").split(":") + \
- settings.get("INFODIR","").split(":")
-
- os.chdir("/")
-
- if retval == os.EX_OK:
- exit_msg = " *** exiting successfully."
- else:
- exit_msg = " *** exiting unsuccessfully with status '%s'." % retval
- emergelog("notitles" not in settings.features, exit_msg)
-
- _flush_elog_mod_echo()
-
- counter_hash = settings.get("PORTAGE_COUNTER_HASH")
- if "--pretend" in myopts or (counter_hash is not None and \
- counter_hash == vardbapi._counter_hash()):
- display_news_notification(root_config, myopts)
- # If vdb state has not changed then there's nothing else to do.
- sys.exit(retval)
-
- vdb_path = os.path.join(target_root, portage.VDB_PATH)
- portage.util.ensure_dirs(vdb_path)
- vdb_lock = None
- if os.access(vdb_path, os.W_OK) and not "--pretend" in myopts:
- vdb_lock = portage.locks.lockdir(vdb_path)
-
- if vdb_lock:
- try:
- if "noinfo" not in settings.features:
- chk_updated_info_files(target_root,
- infodirs, info_mtimes, retval)
- mtimedb.commit()
- finally:
- if vdb_lock:
- portage.locks.unlockdir(vdb_lock)
-
- chk_updated_cfg_files(target_root, config_protect)
-
- display_news_notification(root_config, myopts)
- if retval in (None, os.EX_OK) or (not "--pretend" in myopts):
- display_preserved_libs(vardbapi)
-
- sys.exit(retval)
-
-
-def multiple_actions(action1, action2):
- sys.stderr.write("\n!!! Multiple actions requested... Please choose one only.\n")
- sys.stderr.write("!!! '%s' or '%s'\n\n" % (action1, action2))
- sys.exit(1)
-
-def insert_optional_args(args):
- """
- Parse optional arguments and insert a value if one has
- not been provided. This is done before feeding the args
- to the optparse parser since that parser does not support
- this feature natively.
- """
-
- new_args = []
- jobs_opts = ("-j", "--jobs")
- default_arg_opts = {
- '--deselect' : ('n',),
- '--root-deps' : ('rdeps',),
- }
- arg_stack = args[:]
- arg_stack.reverse()
- while arg_stack:
- arg = arg_stack.pop()
-
- default_arg_choices = default_arg_opts.get(arg)
- if default_arg_choices is not None:
- new_args.append(arg)
- if arg_stack and arg_stack[-1] in default_arg_choices:
- new_args.append(arg_stack.pop())
- else:
- # insert default argument
- new_args.append('True')
- continue
-
- short_job_opt = bool("j" in arg and arg[:1] == "-" and arg[:2] != "--")
- if not (short_job_opt or arg in jobs_opts):
- new_args.append(arg)
- continue
-
- # Insert an empty placeholder in order to
- # satisfy the requirements of optparse.
-
- new_args.append("--jobs")
- job_count = None
- saved_opts = None
- if short_job_opt and len(arg) > 2:
- if arg[:2] == "-j":
- try:
- job_count = int(arg[2:])
- except ValueError:
- saved_opts = arg[2:]
- else:
- job_count = "True"
- saved_opts = arg[1:].replace("j", "")
-
- if job_count is None and arg_stack:
- try:
- job_count = int(arg_stack[-1])
- except ValueError:
- pass
- else:
- # Discard the job count from the stack
- # since we're consuming it here.
- arg_stack.pop()
-
- if job_count is None:
- # unlimited number of jobs
- new_args.append("True")
- else:
- new_args.append(str(job_count))
-
- if saved_opts is not None:
- new_args.append("-" + saved_opts)
-
- return new_args
-
-def parse_opts(tmpcmdline, silent=False):
- myaction=None
- myopts = {}
- myfiles=[]
-
- global options, shortmapping
-
- actions = frozenset([
- "clean", "config", "depclean",
- "info", "list-sets", "metadata",
- "prune", "regen", "search",
- "sync", "unmerge", "version",
- ])
-
- longopt_aliases = {"--cols":"--columns", "--skip-first":"--skipfirst"}
- argument_options = {
- "--config-root": {
- "help":"specify the location for portage configuration files",
- "action":"store"
- },
- "--color": {
- "help":"enable or disable color output",
- "type":"choice",
- "choices":("y", "n")
- },
-
- "--deselect": {
- "help" : "remove atoms from the world file",
- "type" : "choice",
- "choices" : ("True", "n")
- },
-
- "--jobs": {
-
- "help" : "Specifies the number of packages to build " + \
- "simultaneously.",
-
- "action" : "store"
- },
-
- "--load-average": {
-
- "help" :"Specifies that no new builds should be started " + \
- "if there are other builds running and the load average " + \
- "is at least LOAD (a floating-point number).",
-
- "action" : "store"
- },
-
- "--with-bdeps": {
- "help":"include unnecessary build time dependencies",
- "type":"choice",
- "choices":("y", "n")
- },
- "--reinstall": {
- "help":"specify conditions to trigger package reinstallation",
- "type":"choice",
- "choices":["changed-use"]
- },
- "--root": {
- "help" : "specify the target root filesystem for merging packages",
- "action" : "store"
- },
-
- "--root-deps": {
- "help" : "modify interpretation of depedencies",
- "type" : "choice",
- "choices" :("True", "rdeps")
- },
- }
-
- from optparse import OptionParser
- parser = OptionParser()
- if parser.has_option("--help"):
- parser.remove_option("--help")
-
- for action_opt in actions:
- parser.add_option("--" + action_opt, action="store_true",
- dest=action_opt.replace("-", "_"), default=False)
- for myopt in options:
- parser.add_option(myopt, action="store_true",
- dest=myopt.lstrip("--").replace("-", "_"), default=False)
- for shortopt, longopt in shortmapping.iteritems():
- parser.add_option("-" + shortopt, action="store_true",
- dest=longopt.lstrip("--").replace("-", "_"), default=False)
- for myalias, myopt in longopt_aliases.iteritems():
- parser.add_option(myalias, action="store_true",
- dest=myopt.lstrip("--").replace("-", "_"), default=False)
-
- for myopt, kwargs in argument_options.iteritems():
- parser.add_option(myopt,
- dest=myopt.lstrip("--").replace("-", "_"), **kwargs)
-
- tmpcmdline = insert_optional_args(tmpcmdline)
-
- myoptions, myargs = parser.parse_args(args=tmpcmdline)
-
- if myoptions.deselect == "True":
- myoptions.deselect = True
-
- if myoptions.root_deps == "True":
- myoptions.root_deps = True
-
- if myoptions.jobs:
- jobs = None
- if myoptions.jobs == "True":
- jobs = True
- else:
- try:
- jobs = int(myoptions.jobs)
- except ValueError:
- jobs = -1
-
- if jobs is not True and \
- jobs < 1:
- jobs = None
- if not silent:
- writemsg("!!! Invalid --jobs parameter: '%s'\n" % \
- (myoptions.jobs,), noiselevel=-1)
-
- myoptions.jobs = jobs
-
- if myoptions.load_average:
- try:
- load_average = float(myoptions.load_average)
- except ValueError:
- load_average = 0.0
-
- if load_average <= 0.0:
- load_average = None
- if not silent:
- writemsg("!!! Invalid --load-average parameter: '%s'\n" % \
- (myoptions.load_average,), noiselevel=-1)
-
- myoptions.load_average = load_average
-
- for myopt in options:
- v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"))
- if v:
- myopts[myopt] = True
-
- for myopt in argument_options:
- v = getattr(myoptions, myopt.lstrip("--").replace("-", "_"), None)
- if v is not None:
- myopts[myopt] = v
-
- if myoptions.searchdesc:
- myoptions.search = True
-
- for action_opt in actions:
- v = getattr(myoptions, action_opt.replace("-", "_"))
- if v:
- if myaction:
- multiple_actions(myaction, action_opt)
- sys.exit(1)
- myaction = action_opt
-
- if myaction is None and myoptions.deselect is True:
- myaction = 'deselect'
-
- myfiles += myargs
-
- return myaction, myopts, myfiles
-
-def validate_ebuild_environment(trees):
- for myroot in trees:
- settings = trees[myroot]["vartree"].settings
- settings.validate()
-
-def apply_priorities(settings):
- ionice(settings)
- nice(settings)
-
-def nice(settings):
- try:
- os.nice(int(settings.get("PORTAGE_NICENESS", "0")))
- except (OSError, ValueError), e:
- out = portage.output.EOutput()
- out.eerror("Failed to change nice value to '%s'" % \
- settings["PORTAGE_NICENESS"])
- out.eerror("%s\n" % str(e))
-
-def ionice(settings):
-
- ionice_cmd = settings.get("PORTAGE_IONICE_COMMAND")
- if ionice_cmd:
- ionice_cmd = shlex.split(ionice_cmd)
- if not ionice_cmd:
- return
-
- from portage.util import varexpand
- variables = {"PID" : str(os.getpid())}
- cmd = [varexpand(x, mydict=variables) for x in ionice_cmd]
-
- try:
- rval = portage.process.spawn(cmd, env=os.environ)
- except portage.exception.CommandNotFound:
- # The OS kernel probably doesn't support ionice,
- # so return silently.
- return
-
- if rval != os.EX_OK:
- out = portage.output.EOutput()
- out.eerror("PORTAGE_IONICE_COMMAND returned %d" % (rval,))
- out.eerror("See the make.conf(5) man page for PORTAGE_IONICE_COMMAND usage instructions.")
-
-def expand_set_arguments(myfiles, myaction, root_config):
- retval = os.EX_OK
- setconfig = root_config.setconfig
-
- sets = setconfig.getSets()
-
- # In order to know exactly which atoms/sets should be added to the
- # world file, the depgraph performs set expansion later. It will get
- # confused about where the atoms came from if it's not allowed to
- # expand them itself.
- do_not_expand = (None, )
- newargs = []
- for a in myfiles:
- if a in ("system", "world"):
- newargs.append(SETPREFIX+a)
- else:
- newargs.append(a)
- myfiles = newargs
- del newargs
- newargs = []
-
- # separators for set arguments
- ARG_START = "{"
- ARG_END = "}"
-
- # WARNING: all operators must be of equal length
- IS_OPERATOR = "/@"
- DIFF_OPERATOR = "-@"
- UNION_OPERATOR = "+@"
-
- for i in range(0, len(myfiles)):
- if myfiles[i].startswith(SETPREFIX):
- start = 0
- end = 0
- x = myfiles[i][len(SETPREFIX):]
- newset = ""
- while x:
- start = x.find(ARG_START)
- end = x.find(ARG_END)
- if start > 0 and start < end:
- namepart = x[:start]
- argpart = x[start+1:end]
-
- # TODO: implement proper quoting
- args = argpart.split(",")
- options = {}
- for a in args:
- if "=" in a:
- k, v = a.split("=", 1)
- options[k] = v
- else:
- options[a] = "True"
- setconfig.update(namepart, options)
- newset += (x[:start-len(namepart)]+namepart)
- x = x[end+len(ARG_END):]
- else:
- newset += x
- x = ""
- myfiles[i] = SETPREFIX+newset
-
- sets = setconfig.getSets()
-
- # display errors that occured while loading the SetConfig instance
- for e in setconfig.errors:
- print colorize("BAD", "Error during set creation: %s" % e)
-
- # emerge relies on the existance of sets with names "world" and "system"
- required_sets = ("world", "system")
- missing_sets = []
-
- for s in required_sets:
- if s not in sets:
- missing_sets.append(s)
- if missing_sets:
- if len(missing_sets) > 2:
- missing_sets_str = ", ".join('"%s"' % s for s in missing_sets[:-1])
- missing_sets_str += ', and "%s"' % missing_sets[-1]
- elif len(missing_sets) == 2:
- missing_sets_str = '"%s" and "%s"' % tuple(missing_sets)
- else:
- missing_sets_str = '"%s"' % missing_sets[-1]
- msg = ["emerge: incomplete set configuration, " + \
- "missing set(s): %s" % missing_sets_str]
- if sets:
- msg.append(" sets defined: %s" % ", ".join(sets))
- msg.append(" This usually means that '%s'" % \
- (os.path.join(portage.const.GLOBAL_CONFIG_PATH, "sets.conf"),))
- msg.append(" is missing or corrupt.")
- for line in msg:
- writemsg_level(line + "\n", level=logging.ERROR, noiselevel=-1)
- return (None, 1)
- unmerge_actions = ("unmerge", "prune", "clean", "depclean")
-
- for a in myfiles:
- if a.startswith(SETPREFIX):
- # support simple set operations (intersection, difference and union)
- # on the commandline. Expressions are evaluated strictly left-to-right
- if IS_OPERATOR in a or DIFF_OPERATOR in a or UNION_OPERATOR in a:
- expression = a[len(SETPREFIX):]
- expr_sets = []
- expr_ops = []
- while IS_OPERATOR in expression or DIFF_OPERATOR in expression or UNION_OPERATOR in expression:
- is_pos = expression.rfind(IS_OPERATOR)
- diff_pos = expression.rfind(DIFF_OPERATOR)
- union_pos = expression.rfind(UNION_OPERATOR)
- op_pos = max(is_pos, diff_pos, union_pos)
- s1 = expression[:op_pos]
- s2 = expression[op_pos+len(IS_OPERATOR):]
- op = expression[op_pos:op_pos+len(IS_OPERATOR)]
- if not s2 in sets:
- display_missing_pkg_set(root_config, s2)
- return (None, 1)
- expr_sets.insert(0, s2)
- expr_ops.insert(0, op)
- expression = s1
- if not expression in sets:
- display_missing_pkg_set(root_config, expression)
- return (None, 1)
- expr_sets.insert(0, expression)
- result = set(setconfig.getSetAtoms(expression))
- for i in range(0, len(expr_ops)):
- s2 = setconfig.getSetAtoms(expr_sets[i+1])
- if expr_ops[i] == IS_OPERATOR:
- result.intersection_update(s2)
- elif expr_ops[i] == DIFF_OPERATOR:
- result.difference_update(s2)
- elif expr_ops[i] == UNION_OPERATOR:
- result.update(s2)
- else:
- raise NotImplementedError("unknown set operator %s" % expr_ops[i])
- newargs.extend(result)
- else:
- s = a[len(SETPREFIX):]
- if s not in sets:
- display_missing_pkg_set(root_config, s)
- return (None, 1)
- setconfig.active.append(s)
- try:
- set_atoms = setconfig.getSetAtoms(s)
- except portage.exception.PackageSetNotFound, e:
- writemsg_level(("emerge: the given set '%s' " + \
- "contains a non-existent set named '%s'.\n") % \
- (s, e), level=logging.ERROR, noiselevel=-1)
- return (None, 1)
- if myaction in unmerge_actions and \
- not sets[s].supportsOperation("unmerge"):
- sys.stderr.write("emerge: the given set '%s' does " % s + \
- "not support unmerge operations\n")
- retval = 1
- elif not set_atoms:
- print "emerge: '%s' is an empty set" % s
- elif myaction not in do_not_expand:
- newargs.extend(set_atoms)
- else:
- newargs.append(SETPREFIX+s)
- for e in sets[s].errors:
- print e
- else:
- newargs.append(a)
- return (newargs, retval)
-
-def repo_name_check(trees):
- missing_repo_names = set()
- for root, root_trees in trees.iteritems():
- if "porttree" in root_trees:
- portdb = root_trees["porttree"].dbapi
- missing_repo_names.update(portdb.porttrees)
- repos = portdb.getRepositories()
- for r in repos:
- missing_repo_names.discard(portdb.getRepositoryPath(r))
- if portdb.porttree_root in missing_repo_names and \
- not os.path.exists(os.path.join(
- portdb.porttree_root, "profiles")):
- # This is normal if $PORTDIR happens to be empty,
- # so don't warn about it.
- missing_repo_names.remove(portdb.porttree_root)
-
- if missing_repo_names:
- msg = []
- msg.append("WARNING: One or more repositories " + \
- "have missing repo_name entries:")
- msg.append("")
- for p in missing_repo_names:
- msg.append("\t%s/profiles/repo_name" % (p,))
- msg.append("")
- msg.extend(textwrap.wrap("NOTE: Each repo_name entry " + \
- "should be a plain text file containing a unique " + \
- "name for the repository on the first line.", 70))
- writemsg_level("".join("%s\n" % l for l in msg),
- level=logging.WARNING, noiselevel=-1)
-
- return bool(missing_repo_names)
-
-def repo_name_duplicate_check(trees):
- ignored_repos = {}
- for root, root_trees in trees.iteritems():
- if 'porttree' in root_trees:
- portdb = root_trees['porttree'].dbapi
- if portdb.mysettings.get('PORTAGE_REPO_DUPLICATE_WARN') != '0':
- for repo_name, paths in portdb._ignored_repos:
- k = (root, repo_name, portdb.getRepositoryPath(repo_name))
- ignored_repos.setdefault(k, []).extend(paths)
-
- if ignored_repos:
- msg = []
- msg.append('WARNING: One or more repositories ' + \
- 'have been ignored due to duplicate')
- msg.append(' profiles/repo_name entries:')
- msg.append('')
- for k in sorted(ignored_repos):
- msg.append(' %s overrides' % (k,))
- for path in ignored_repos[k]:
- msg.append(' %s' % (path,))
- msg.append('')
- msg.extend(' ' + x for x in textwrap.wrap(
- "All profiles/repo_name entries must be unique in order " + \
- "to avoid having duplicates ignored. " + \
- "Set PORTAGE_REPO_DUPLICATE_WARN=\"0\" in " + \
- "/etc/make.conf if you would like to disable this warning."))
- writemsg_level(''.join('%s\n' % l for l in msg),
- level=logging.WARNING, noiselevel=-1)
-
- return bool(ignored_repos)
-
-def config_protect_check(trees):
- for root, root_trees in trees.iteritems():
- if not root_trees["root_config"].settings.get("CONFIG_PROTECT"):
- msg = "!!! CONFIG_PROTECT is empty"
- if root != "/":
- msg += " for '%s'" % root
- writemsg_level(msg, level=logging.WARN, noiselevel=-1)
-
-def profile_check(trees, myaction, myopts):
- if myaction in ("info", "sync"):
- return os.EX_OK
- elif "--version" in myopts or "--help" in myopts:
- return os.EX_OK
- for root, root_trees in trees.iteritems():
- if root_trees["root_config"].settings.profiles:
- continue
- # generate some profile related warning messages
- validate_ebuild_environment(trees)
- msg = "If you have just changed your profile configuration, you " + \
- "should revert back to the previous configuration. Due to " + \
- "your current profile being invalid, allowed actions are " + \
- "limited to --help, --info, --sync, and --version."
- writemsg_level("".join("!!! %s\n" % l for l in textwrap.wrap(msg, 70)),
- level=logging.ERROR, noiselevel=-1)
- return 1
- return os.EX_OK
-
-def emerge_main():
- global portage # NFC why this is necessary now - genone
- portage._disable_legacy_globals()
- # Disable color until we're sure that it should be enabled (after
- # EMERGE_DEFAULT_OPTS has been parsed).
- portage.output.havecolor = 0
- # This first pass is just for options that need to be known as early as
- # possible, such as --config-root. They will be parsed again later,
- # together with EMERGE_DEFAULT_OPTS (which may vary depending on the
- # the value of --config-root).
- myaction, myopts, myfiles = parse_opts(sys.argv[1:], silent=True)
- if "--debug" in myopts:
- os.environ["PORTAGE_DEBUG"] = "1"
- if "--config-root" in myopts:
- os.environ["PORTAGE_CONFIGROOT"] = myopts["--config-root"]
- if "--root" in myopts:
- os.environ["ROOT"] = myopts["--root"]
-
- # Portage needs to ensure a sane umask for the files it creates.
- os.umask(022)
- settings, trees, mtimedb = load_emerge_config()
- portdb = trees[settings["ROOT"]]["porttree"].dbapi
- rval = profile_check(trees, myaction, myopts)
- if rval != os.EX_OK:
- return rval
-
- if portage._global_updates(trees, mtimedb["updates"]):
- mtimedb.commit()
- # Reload the whole config from scratch.
- settings, trees, mtimedb = load_emerge_config(trees=trees)
- portdb = trees[settings["ROOT"]]["porttree"].dbapi
-
- xterm_titles = "notitles" not in settings.features
-
- tmpcmdline = []
- if "--ignore-default-opts" not in myopts:
- tmpcmdline.extend(settings["EMERGE_DEFAULT_OPTS"].split())
- tmpcmdline.extend(sys.argv[1:])
- myaction, myopts, myfiles = parse_opts(tmpcmdline)
-
- if "--digest" in myopts:
- os.environ["FEATURES"] = os.environ.get("FEATURES","") + " digest"
- # Reload the whole config from scratch so that the portdbapi internal
- # config is updated with new FEATURES.
- settings, trees, mtimedb = load_emerge_config(trees=trees)
- portdb = trees[settings["ROOT"]]["porttree"].dbapi
-
- for myroot in trees:
- mysettings = trees[myroot]["vartree"].settings
- mysettings.unlock()
- adjust_config(myopts, mysettings)
- if '--pretend' not in myopts and myaction in \
- (None, 'clean', 'depclean', 'prune', 'unmerge'):
- mysettings["PORTAGE_COUNTER_HASH"] = \
- trees[myroot]["vartree"].dbapi._counter_hash()
- mysettings.backup_changes("PORTAGE_COUNTER_HASH")
- mysettings.lock()
- del myroot, mysettings
-
- apply_priorities(settings)
-
- spinner = stdout_spinner()
- if "candy" in settings.features:
- spinner.update = spinner.update_scroll
-
- if "--quiet" not in myopts:
- portage.deprecated_profile_check(settings=settings)
- repo_name_check(trees)
- repo_name_duplicate_check(trees)
- config_protect_check(trees)
-
- for mytrees in trees.itervalues():
- mydb = mytrees["porttree"].dbapi
- # Freeze the portdbapi for performance (memoize all xmatch results).
- mydb.freeze()
- del mytrees, mydb
-
- if "moo" in myfiles:
- print """
-
- Larry loves Gentoo (""" + platform.system() + """)
-
- _______________________
-< Have you mooed today? >
- -----------------------
- \ ^__^
- \ (oo)\_______
- (__)\ )\/\
- ||----w |
- || ||
-
-"""
-
- for x in myfiles:
- ext = os.path.splitext(x)[1]
- if (ext == ".ebuild" or ext == ".tbz2") and os.path.exists(os.path.abspath(x)):
- print colorize("BAD", "\n*** emerging by path is broken and may not always work!!!\n")
- break
-
- root_config = trees[settings["ROOT"]]["root_config"]
- if myaction == "list-sets":
- sys.stdout.write("".join("%s\n" % s for s in sorted(root_config.sets)))
- sys.stdout.flush()
- return os.EX_OK
-
- # only expand sets for actions taking package arguments
- oldargs = myfiles[:]
- if myaction in ("clean", "config", "depclean", "info", "prune", "unmerge", None):
- myfiles, retval = expand_set_arguments(myfiles, myaction, root_config)
- if retval != os.EX_OK:
- return retval
-
- # Need to handle empty sets specially, otherwise emerge will react
- # with the help message for empty argument lists
- if oldargs and not myfiles:
- print "emerge: no targets left after set expansion"
- return 0
-
- if ("--tree" in myopts) and ("--columns" in myopts):
- print "emerge: can't specify both of \"--tree\" and \"--columns\"."
- return 1
-
- if ("--quiet" in myopts):
- spinner.update = spinner.update_quiet
- portage.util.noiselimit = -1
-
- # Always create packages if FEATURES=buildpkg
- # Imply --buildpkg if --buildpkgonly
- if ("buildpkg" in settings.features) or ("--buildpkgonly" in myopts):
- if "--buildpkg" not in myopts:
- myopts["--buildpkg"] = True
-
- # Always try and fetch binary packages if FEATURES=getbinpkg
- if ("getbinpkg" in settings.features):
- myopts["--getbinpkg"] = True
-
- if "--buildpkgonly" in myopts:
- # --buildpkgonly will not merge anything, so
- # it cancels all binary package options.
- for opt in ("--getbinpkg", "--getbinpkgonly",
- "--usepkg", "--usepkgonly"):
- myopts.pop(opt, None)
-
- if "--fetch-all-uri" in myopts:
- myopts["--fetchonly"] = True
-
- if "--skipfirst" in myopts and "--resume" not in myopts:
- myopts["--resume"] = True
-
- if ("--getbinpkgonly" in myopts) and not ("--usepkgonly" in myopts):
- myopts["--usepkgonly"] = True
-
- if ("--getbinpkgonly" in myopts) and not ("--getbinpkg" in myopts):
- myopts["--getbinpkg"] = True
-
- if ("--getbinpkg" in myopts) and not ("--usepkg" in myopts):
- myopts["--usepkg"] = True
-
- # Also allow -K to apply --usepkg/-k
- if ("--usepkgonly" in myopts) and not ("--usepkg" in myopts):
- myopts["--usepkg"] = True
-
- # Allow -p to remove --ask
- if "--pretend" in myopts:
- myopts.pop("--ask", None)
-
- # forbid --ask when not in a terminal
- # note: this breaks `emerge --ask | tee logfile`, but that doesn't work anyway.
- if ("--ask" in myopts) and (not sys.stdin.isatty()):
- portage.writemsg("!!! \"--ask\" should only be used in a terminal. Exiting.\n",
- noiselevel=-1)
- return 1
-
- if settings.get("PORTAGE_DEBUG", "") == "1":
- spinner.update = spinner.update_quiet
- portage.debug=1
- if "python-trace" in settings.features:
- import portage.debug
- portage.debug.set_trace(True)
-
- if not ("--quiet" in myopts):
- if not sys.stdout.isatty() or ("--nospinner" in myopts):
- spinner.update = spinner.update_basic
-
- if myaction == 'version':
- print getportageversion(settings["PORTDIR"], settings["ROOT"],
- settings.profile_path, settings["CHOST"],
- trees[settings["ROOT"]]["vartree"].dbapi)
- return 0
- elif "--help" in myopts:
- _emerge.help.help(myaction, myopts, portage.output.havecolor)
- return 0
-
- if "--debug" in myopts:
- print "myaction", myaction
- print "myopts", myopts
-
- if not myaction and not myfiles and "--resume" not in myopts:
- _emerge.help.help(myaction, myopts, portage.output.havecolor)
- return 1
-
- pretend = "--pretend" in myopts
- fetchonly = "--fetchonly" in myopts or "--fetch-all-uri" in myopts
- buildpkgonly = "--buildpkgonly" in myopts
-
- # check if root user is the current user for the actions where emerge needs this
- if portage.secpass < 2:
- # We've already allowed "--version" and "--help" above.
- if "--pretend" not in myopts and myaction not in ("search","info"):
- need_superuser = myaction in ('clean', 'depclean', 'deselect',
- 'prune', 'unmerge') or not \
- (fetchonly or \
- (buildpkgonly and secpass >= 1) or \
- myaction in ("metadata", "regen") or \
- (myaction == "sync" and os.access(settings["PORTDIR"], os.W_OK)))
- if portage.secpass < 1 or \
- need_superuser:
- if need_superuser:
- access_desc = "superuser"
- else:
- access_desc = "portage group"
- # Always show portage_group_warning() when only portage group
- # access is required but the user is not in the portage group.
- from portage.data import portage_group_warning
- if "--ask" in myopts:
- myopts["--pretend"] = True
- del myopts["--ask"]
- print ("%s access is required... " + \
- "adding --pretend to options\n") % access_desc
- if portage.secpass < 1 and not need_superuser:
- portage_group_warning()
- else:
- sys.stderr.write(("emerge: %s access is required\n") \
- % access_desc)
- if portage.secpass < 1 and not need_superuser:
- portage_group_warning()
- return 1
-
- disable_emergelog = False
- for x in ("--pretend", "--fetchonly", "--fetch-all-uri"):
- if x in myopts:
- disable_emergelog = True
- break
- if myaction in ("search", "info"):
- disable_emergelog = True
- if disable_emergelog:
- """ Disable emergelog for everything except build or unmerge
- operations. This helps minimize parallel emerge.log entries that can
- confuse log parsers. We especially want it disabled during
- parallel-fetch, which uses --resume --fetchonly."""
- global emergelog
- def emergelog(*pargs, **kargs):
- pass
-
- else:
- if 'EMERGE_LOG_DIR' in settings:
- try:
- # At least the parent needs to exist for the lock file.
- portage.util.ensure_dirs(settings['EMERGE_LOG_DIR'])
- except portage.exception.PortageException, e:
- writemsg_level("!!! Error creating directory for " + \
- "EMERGE_LOG_DIR='%s':\n!!! %s\n" % \
- (settings['EMERGE_LOG_DIR'], e),
- noiselevel=-1, level=logging.ERROR)
- else:
- global _emerge_log_dir
- _emerge_log_dir = settings['EMERGE_LOG_DIR']
-
- if not "--pretend" in myopts:
- emergelog(xterm_titles, "Started emerge on: "+\
- time.strftime("%b %d, %Y %H:%M:%S", time.localtime()))
- myelogstr=""
- if myopts:
- myelogstr=" ".join(myopts)
- if myaction:
- myelogstr+=" "+myaction
- if myfiles:
- myelogstr += " " + " ".join(oldargs)
- emergelog(xterm_titles, " *** emerge " + myelogstr)
- del oldargs
-
- def emergeexitsig(signum, frame):
- signal.signal(signal.SIGINT, signal.SIG_IGN)
- signal.signal(signal.SIGTERM, signal.SIG_IGN)
- portage.util.writemsg("\n\nExiting on signal %(signal)s\n" % {"signal":signum})
- sys.exit(100+signum)
- signal.signal(signal.SIGINT, emergeexitsig)
- signal.signal(signal.SIGTERM, emergeexitsig)
-
- def emergeexit():
- """This gets out final log message in before we quit."""
- if "--pretend" not in myopts:
- emergelog(xterm_titles, " *** terminating.")
- if "notitles" not in settings.features:
- xtermTitleReset()
- portage.atexit_register(emergeexit)
-
- if myaction in ("config", "metadata", "regen", "sync"):
- if "--pretend" in myopts:
- sys.stderr.write(("emerge: The '%s' action does " + \
- "not support '--pretend'.\n") % myaction)
- return 1
-
- if "sync" == myaction:
- return action_sync(settings, trees, mtimedb, myopts, myaction)
- elif "metadata" == myaction:
- action_metadata(settings, portdb, myopts)
- elif myaction=="regen":
- validate_ebuild_environment(trees)
- return action_regen(settings, portdb, myopts.get("--jobs"),
- myopts.get("--load-average"))
- # HELP action
- elif "config"==myaction:
- validate_ebuild_environment(trees)
- action_config(settings, trees, myopts, myfiles)
-
- # SEARCH action
- elif "search"==myaction:
- validate_ebuild_environment(trees)
- action_search(trees[settings["ROOT"]]["root_config"],
- myopts, myfiles, spinner)
-
- elif myaction in ('clean', 'depclean', 'deselect', 'prune', 'unmerge'):
- validate_ebuild_environment(trees)
- rval = action_uninstall(settings, trees, mtimedb["ldpath"],
- myopts, myaction, myfiles, spinner)
- if not (myaction == 'deselect' or buildpkgonly or fetchonly or pretend):
- post_emerge(root_config, myopts, mtimedb, rval)
- return rval
-
- elif myaction == 'info':
-
- # Ensure atoms are valid before calling unmerge().
- vardb = trees[settings["ROOT"]]["vartree"].dbapi
- valid_atoms = []
- for x in myfiles:
- if is_valid_package_atom(x):
- try:
- valid_atoms.append(
- portage.dep_expand(x, mydb=vardb, settings=settings))
- except portage.exception.AmbiguousPackageName, e:
- msg = "The short ebuild name \"" + x + \
- "\" is ambiguous. Please specify " + \
- "one of the following " + \
- "fully-qualified ebuild names instead:"
- for line in textwrap.wrap(msg, 70):
- writemsg_level("!!! %s\n" % (line,),
- level=logging.ERROR, noiselevel=-1)
- for i in e[0]:
- writemsg_level(" %s\n" % colorize("INFORM", i),
- level=logging.ERROR, noiselevel=-1)
- writemsg_level("\n", level=logging.ERROR, noiselevel=-1)
- return 1
- continue
- msg = []
- msg.append("'%s' is not a valid package atom." % (x,))
- msg.append("Please check ebuild(5) for full details.")
- writemsg_level("".join("!!! %s\n" % line for line in msg),
- level=logging.ERROR, noiselevel=-1)
- return 1
-
- return action_info(settings, trees, myopts, valid_atoms)
-
- # "update", "system", or just process files:
- else:
- validate_ebuild_environment(trees)
-
- for x in myfiles:
- if x.startswith(SETPREFIX) or \
- is_valid_package_atom(x):
- continue
- if x[:1] == os.sep:
- continue
- try:
- os.lstat(x)
- continue
- except OSError:
- pass
- msg = []
- msg.append("'%s' is not a valid package atom." % (x,))
- msg.append("Please check ebuild(5) for full details.")
- writemsg_level("".join("!!! %s\n" % line for line in msg),
- level=logging.ERROR, noiselevel=-1)
- return 1
-
- if "--pretend" not in myopts:
- display_news_notification(root_config, myopts)
- retval = action_build(settings, trees, mtimedb,
- myopts, myaction, myfiles, spinner)
- root_config = trees[settings["ROOT"]]["root_config"]
- post_emerge(root_config, myopts, mtimedb, retval)
-
- return retval