blob: e8b2c2e13ebd9776e1cb98996ffd1f1477cfc3c6 [file] [log] [blame]
# Copyright 1999-2018 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
from __future__ import print_function
import argparse
import locale
import platform
import sys
import portage
portage.proxy.lazyimport.lazyimport(globals(),
'logging',
'portage.dep:Atom',
'portage.util:writemsg_level',
'textwrap',
'_emerge.actions:load_emerge_config,run_action,' + \
'validate_ebuild_environment',
'_emerge.help:help@emerge_help',
'_emerge.is_valid_package_atom:insert_category_into_atom'
)
from portage import os
from portage.sync import _SUBMODULE_PATH_MAP
if sys.hexversion >= 0x3000000:
long = int
options=[
"--alphabetical",
"--ask-enter-invalid",
"--buildpkgonly",
"--changed-use",
"--changelog", "--columns",
"--debug",
"--digest",
"--emptytree",
"--verbose-conflicts",
"--fetchonly", "--fetch-all-uri",
"--ignore-default-opts",
"--noconfmem",
"--newrepo",
"--newuse",
"--nodeps", "--noreplace",
"--nospinner", "--oneshot",
"--onlydeps", "--pretend",
"--quiet-repo-display",
"--quiet-unmerge-warn",
"--resume",
"--searchdesc",
"--skipfirst",
"--tree",
"--unordered-display",
"--update",
]
shortmapping={
"1":"--oneshot",
"B":"--buildpkgonly",
"c":"--depclean",
"C":"--unmerge",
"d":"--debug",
"e":"--emptytree",
"f":"--fetchonly", "F":"--fetch-all-uri",
"h":"--help",
"l":"--changelog",
"n":"--noreplace", "N":"--newuse",
"o":"--onlydeps", "O":"--nodeps",
"p":"--pretend", "P":"--prune",
"r":"--resume",
"s":"--search", "S":"--searchdesc",
"t":"--tree",
"u":"--update", "U":"--changed-use",
"V":"--version"
}
COWSAY_MOO = r"""
Larry loves Gentoo (%s)
_______________________
< Have you mooed today? >
-----------------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
"""
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.
"""
class valid_integers(object):
def __contains__(self, s):
try:
return int(s) >= 0
except (ValueError, OverflowError):
return False
valid_integers = valid_integers()
class valid_floats(object):
def __contains__(self, s):
try:
return float(s) >= 0
except (ValueError, OverflowError):
return False
valid_floats = valid_floats()
y_or_n = ('y', 'n',)
new_args = []
default_arg_opts = {
'--alert' : y_or_n,
'--ask' : y_or_n,
'--autounmask' : y_or_n,
'--autounmask-continue' : y_or_n,
'--autounmask-only' : y_or_n,
'--autounmask-keep-keywords' : y_or_n,
'--autounmask-keep-masks': y_or_n,
'--autounmask-unrestricted-atoms' : y_or_n,
'--autounmask-write' : y_or_n,
'--binpkg-changed-deps' : y_or_n,
'--buildpkg' : y_or_n,
'--changed-deps' : y_or_n,
'--changed-slot' : y_or_n,
'--changed-deps-report' : y_or_n,
'--complete-graph' : y_or_n,
'--deep' : valid_integers,
'--depclean-lib-check' : y_or_n,
'--deselect' : y_or_n,
'--binpkg-respect-use' : y_or_n,
'--fail-clean' : y_or_n,
'--fuzzy-search' : y_or_n,
'--getbinpkg' : y_or_n,
'--getbinpkgonly' : y_or_n,
'--ignore-world' : y_or_n,
'--jobs' : valid_integers,
'--keep-going' : y_or_n,
'--load-average' : valid_floats,
'--onlydeps-with-rdeps' : y_or_n,
'--package-moves' : y_or_n,
'--quiet' : y_or_n,
'--quiet-build' : y_or_n,
'--quiet-fail' : y_or_n,
'--read-news' : y_or_n,
'--rebuild-if-new-slot': y_or_n,
'--rebuild-if-new-rev' : y_or_n,
'--rebuild-if-new-ver' : y_or_n,
'--rebuild-if-unbuilt' : y_or_n,
'--rebuilt-binaries' : y_or_n,
'--root-deps' : ('rdeps',),
'--select' : y_or_n,
'--selective' : y_or_n,
"--use-ebuild-visibility": y_or_n,
'--usepkg' : y_or_n,
'--usepkgonly' : y_or_n,
'--verbose' : y_or_n,
'--verbose-slot-rebuilds': y_or_n,
'--with-test-deps' : y_or_n,
}
short_arg_opts = {
'D' : valid_integers,
'j' : valid_integers,
}
# Don't make things like "-kn" expand to "-k n"
# since existence of -n makes it too ambiguous.
short_arg_opts_n = {
'a' : y_or_n,
'A' : y_or_n,
'b' : y_or_n,
'g' : y_or_n,
'G' : y_or_n,
'k' : y_or_n,
'K' : y_or_n,
'q' : y_or_n,
'v' : y_or_n,
'w' : y_or_n,
}
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
if arg[:1] != "-" or arg[:2] == "--":
new_args.append(arg)
continue
match = None
for k, arg_choices in short_arg_opts.items():
if k in arg:
match = k
break
if match is None:
for k, arg_choices in short_arg_opts_n.items():
if k in arg:
match = k
break
if match is None:
new_args.append(arg)
continue
if len(arg) == 2:
new_args.append(arg)
if arg_stack and arg_stack[-1] in arg_choices:
new_args.append(arg_stack.pop())
else:
# insert default argument
new_args.append('True')
continue
# Insert an empty placeholder in order to
# satisfy the requirements of optparse.
new_args.append("-" + match)
opt_arg = None
saved_opts = None
if arg[1:2] == match:
if match not in short_arg_opts_n and arg[2:] in arg_choices:
opt_arg = arg[2:]
else:
saved_opts = arg[2:]
opt_arg = "True"
else:
saved_opts = arg[1:].replace(match, "")
opt_arg = "True"
if opt_arg is None and arg_stack and \
arg_stack[-1] in arg_choices:
opt_arg = arg_stack.pop()
if opt_arg is None:
new_args.append("True")
else:
new_args.append(opt_arg)
if saved_opts is not None:
# Recycle these on arg_stack since they
# might contain another match.
arg_stack.append("-" + saved_opts)
return new_args
def _find_bad_atoms(atoms, less_strict=False):
"""
Declares all atoms as invalid that have an operator,
a use dependency, a blocker or a repo spec.
It accepts atoms with wildcards.
In less_strict mode it accepts operators and repo specs.
"""
bad_atoms = []
for x in ' '.join(atoms).split():
atom = x
if "/" not in x.split(":")[0]:
x_cat = insert_category_into_atom(x, 'dummy-category')
if x_cat is not None:
atom = x_cat
bad_atom = False
try:
atom = Atom(atom, allow_wildcard=True, allow_repo=less_strict)
except portage.exception.InvalidAtom:
bad_atom = True
if bad_atom or (atom.operator and not less_strict) or atom.blocker or atom.use:
bad_atoms.append(x)
return bad_atoms
def parse_opts(tmpcmdline, silent=False):
myaction=None
myopts = {}
myfiles=[]
actions = frozenset([
"clean", "check-news", "config", "depclean", "help",
"info", "list-sets", "metadata", "moo",
"prune", "rage-clean", "regen", "search",
"sync", "unmerge", "version",
])
longopt_aliases = {"--cols":"--columns", "--skip-first":"--skipfirst"}
y_or_n = ("y", "n")
true_y_or_n = ("True", "y", "n")
true_y = ("True", "y")
argument_options = {
"--alert": {
"shortopt" : "-A",
"help" : "alert (terminal bell) on prompts",
"choices" : true_y_or_n
},
"--ask": {
"shortopt" : "-a",
"help" : "prompt before performing any actions",
"choices" : true_y_or_n
},
"--autounmask": {
"help" : "automatically unmask packages",
"choices" : true_y_or_n
},
"--autounmask-backtrack": {
"help": ("continue backtracking when there are autounmask "
"configuration changes"),
"choices":("y", "n")
},
"--autounmask-continue": {
"help" : "write autounmask changes and continue",
"choices" : true_y_or_n
},
"--autounmask-only": {
"help" : "only perform --autounmask",
"choices" : true_y_or_n
},
"--autounmask-unrestricted-atoms": {
"help" : "write autounmask changes with >= atoms if possible",
"choices" : true_y_or_n
},
"--autounmask-keep-keywords": {
"help" : "don't add package.accept_keywords entries",
"choices" : true_y_or_n
},
"--autounmask-keep-masks": {
"help" : "don't add package.unmask entries",
"choices" : true_y_or_n
},
"--autounmask-write": {
"help" : "write changes made by --autounmask to disk",
"choices" : true_y_or_n
},
"--accept-properties": {
"help":"temporarily override ACCEPT_PROPERTIES",
"action":"store"
},
"--accept-restrict": {
"help":"temporarily override ACCEPT_RESTRICT",
"action":"store"
},
"--backtrack": {
"help" : "Specifies how many times to backtrack if dependency " + \
"calculation fails ",
"action" : "store"
},
"--binpkg-changed-deps": {
"help" : ("reject binary packages with outdated "
"dependencies"),
"choices" : true_y_or_n
},
"--buildpkg": {
"shortopt" : "-b",
"help" : "build binary packages",
"choices" : true_y_or_n
},
"--buildpkg-exclude": {
"help" :"A space separated list of package atoms for which " + \
"no binary packages should be built. This option overrides all " + \
"possible ways to enable building of binary packages.",
"action" : "append"
},
"--changed-deps": {
"help" : ("replace installed packages with "
"outdated dependencies"),
"choices" : true_y_or_n
},
"--changed-deps-report": {
"help" : ("report installed packages with "
"outdated dependencies"),
"choices" : true_y_or_n
},
"--changed-slot": {
"help" : ("replace installed packages with "
"outdated SLOT metadata"),
"choices" : true_y_or_n
},
"--config-root": {
"help":"specify the location for portage configuration files",
"action":"store"
},
"--color": {
"help":"enable or disable color output",
"choices":("y", "n")
},
"--complete-graph": {
"help" : "completely account for all known dependencies",
"choices" : true_y_or_n
},
"--complete-graph-if-new-use": {
"help" : "trigger --complete-graph behavior if USE or IUSE will change for an installed package",
"choices" : y_or_n
},
"--complete-graph-if-new-ver": {
"help" : "trigger --complete-graph behavior if an installed package version will change (upgrade or downgrade)",
"choices" : y_or_n
},
"--deep": {
"shortopt" : "-D",
"help" : "Specifies how deep to recurse into dependencies " + \
"of packages given as arguments. If no argument is given, " + \
"depth is unlimited. Default behavior is to skip " + \
"dependencies of installed packages.",
"action" : "store"
},
"--depclean-lib-check": {
"help" : "check for consumers of libraries before removing them",
"choices" : true_y_or_n
},
"--deselect": {
"help" : "remove atoms/sets from the world file",
"choices" : true_y_or_n
},
"--dynamic-deps": {
"help": "substitute the dependencies of installed packages with the dependencies of unbuilt ebuilds",
"choices": y_or_n
},
"--exclude": {
"help" :"A space separated list of package names or slot atoms. " + \
"Emerge won't install any ebuild or binary package that " + \
"matches any of the given package atoms.",
"action" : "append"
},
"--fail-clean": {
"help" : "clean temp files after build failure",
"choices" : true_y_or_n
},
"--fuzzy-search": {
"help": "Enable or disable fuzzy search",
"choices": true_y_or_n
},
"--ignore-built-slot-operator-deps": {
"help": "Ignore the slot/sub-slot := operator parts of dependencies that have "
"been recorded when packages where built. This option is intended "
"only for debugging purposes, and it only affects built packages "
"that specify slot/sub-slot := operator dependencies using the "
"experimental \"4-slot-abi\" EAPI.",
"choices": y_or_n
},
"--ignore-soname-deps": {
"help": "Ignore the soname dependencies of binary and "
"installed packages. This option is enabled by "
"default, since soname dependencies are relatively "
"new, and the required metadata is not guaranteed to "
"exist for binary and installed packages built with "
"older versions of portage.",
"choices": y_or_n
},
"--ignore-world": {
"help" : "ignore the @world package set and its dependencies",
"choices" : true_y_or_n
},
"--jobs": {
"shortopt" : "-j",
"help" : "Specifies the number of packages to build " + \
"simultaneously.",
"action" : "store"
},
"--keep-going": {
"help" : "continue as much as possible after an error",
"choices" : true_y_or_n
},
"--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"
},
"--misspell-suggestions": {
"help" : "enable package name misspell suggestions",
"choices" : ("y", "n")
},
"--with-bdeps": {
"help":"include unnecessary build time dependencies",
"choices":("y", "n")
},
"--with-bdeps-auto": {
"help":("automatically enable --with-bdeps for installation"
" actions, unless --usepkg is enabled"),
"choices":("y", "n")
},
"--reinstall": {
"help":"specify conditions to trigger package reinstallation",
"choices":["changed-use"]
},
"--reinstall-atoms": {
"help" :"A space separated list of package names or slot atoms. " + \
"Emerge will treat matching packages as if they are not " + \
"installed, and reinstall them if necessary. Implies --deep.",
"action" : "append",
},
"--binpkg-respect-use": {
"help" : "discard binary packages if their use flags \
don't match the current configuration",
"choices" : true_y_or_n
},
"--getbinpkg": {
"shortopt" : "-g",
"help" : "fetch binary packages",
"choices" : true_y_or_n
},
"--getbinpkgonly": {
"shortopt" : "-G",
"help" : "fetch binary packages only",
"choices" : true_y_or_n
},
"--usepkg-exclude": {
"help" :"A space separated list of package names or slot atoms. " + \
"Emerge will ignore matching binary packages. ",
"action" : "append",
},
"--onlydeps-with-rdeps": {
"help" : "modify interpretation of depedencies",
"choices" : true_y_or_n
},
"--rebuild-exclude": {
"help" :"A space separated list of package names or slot atoms. " + \
"Emerge will not rebuild these packages due to the " + \
"--rebuild flag. ",
"action" : "append",
},
"--rebuild-ignore": {
"help" :"A space separated list of package names or slot atoms. " + \
"Emerge will not rebuild packages that depend on matching " + \
"packages due to the --rebuild flag. ",
"action" : "append",
},
"--package-moves": {
"help" : "perform package moves when necessary",
"choices" : true_y_or_n
},
"--prefix": {
"help" : "specify the installation prefix",
"action" : "store"
},
"--pkg-format": {
"help" : "format of result binary package",
"action" : "store",
},
"--quiet": {
"shortopt" : "-q",
"help" : "reduced or condensed output",
"choices" : true_y_or_n
},
"--quiet-build": {
"help" : "redirect build output to logs",
"choices" : true_y_or_n,
},
"--quiet-fail": {
"help" : "suppresses display of the build log on stdout",
"choices" : true_y_or_n,
},
"--read-news": {
"help" : "offer to read unread news via eselect",
"choices" : true_y_or_n
},
"--rebuild-if-new-slot": {
"help" : ("Automatically rebuild or reinstall packages when slot/sub-slot := "
"operator dependencies can be satisfied by a newer slot, so that "
"older packages slots will become eligible for removal by the "
"--depclean action as soon as possible."),
"choices" : true_y_or_n
},
"--rebuild-if-new-rev": {
"help" : "Rebuild packages when dependencies that are " + \
"used at both build-time and run-time are built, " + \
"if the dependency is not already installed with the " + \
"same version and revision.",
"choices" : true_y_or_n
},
"--rebuild-if-new-ver": {
"help" : "Rebuild packages when dependencies that are " + \
"used at both build-time and run-time are built, " + \
"if the dependency is not already installed with the " + \
"same version. Revision numbers are ignored.",
"choices" : true_y_or_n
},
"--rebuild-if-unbuilt": {
"help" : "Rebuild packages when dependencies that are " + \
"used at both build-time and run-time are built.",
"choices" : true_y_or_n
},
"--rebuilt-binaries": {
"help" : "replace installed packages with binary " + \
"packages that have been rebuilt",
"choices" : true_y_or_n
},
"--rebuilt-binaries-timestamp": {
"help" : "use only binaries that are newer than this " + \
"timestamp for --rebuilt-binaries",
"action" : "store"
},
"--root": {
"help" : "specify the target root filesystem for merging packages",
"action" : "store"
},
"--root-deps": {
"help" : "modify interpretation of depedencies",
"choices" :("True", "rdeps")
},
"--search-index": {
"help": "Enable or disable indexed search (enabled by default)",
"choices": y_or_n
},
"--search-similarity": {
"help": ("Set minimum similarity percentage for fuzzy seach "
"(a floating-point number between 0 and 100)"),
"action": "store"
},
"--select": {
"shortopt" : "-w",
"help" : "add specified packages to the world set " + \
"(inverse of --oneshot)",
"choices" : true_y_or_n
},
"--selective": {
"help" : "identical to --noreplace",
"choices" : true_y_or_n
},
"--sync-submodule": {
"help" : ("Restrict sync to the specified submodule(s)."
" (--sync action only)"),
"choices" : tuple(_SUBMODULE_PATH_MAP),
"action" : "append",
},
"--sysroot": {
"help":"specify the location for build dependencies specified in DEPEND",
"action":"store"
},
"--use-ebuild-visibility": {
"help" : "use unbuilt ebuild metadata for visibility checks on built packages",
"choices" : true_y_or_n
},
"--useoldpkg-atoms": {
"help" :"A space separated list of package names or slot atoms. " + \
"Emerge will prefer matching binary packages over newer unbuilt packages. ",
"action" : "append",
},
"--usepkg": {
"shortopt" : "-k",
"help" : "use binary packages",
"choices" : true_y_or_n
},
"--usepkgonly": {
"shortopt" : "-K",
"help" : "use only binary packages",
"choices" : true_y_or_n
},
"--verbose": {
"shortopt" : "-v",
"help" : "verbose output",
"choices" : true_y_or_n
},
"--verbose-slot-rebuilds": {
"help" : "verbose slot rebuild output",
"choices" : true_y_or_n
},
"--with-test-deps": {
"help" : "pull in test deps for packages " + \
"matched by arguments",
"choices" : true_y_or_n
},
}
parser = argparse.ArgumentParser(add_help=False)
for action_opt in actions:
parser.add_argument("--" + action_opt, action="store_true",
dest=action_opt.replace("-", "_"), default=False)
for myopt in options:
parser.add_argument(myopt, action="store_true",
dest=myopt.lstrip("--").replace("-", "_"), default=False)
for shortopt, longopt in shortmapping.items():
parser.add_argument("-" + shortopt, action="store_true",
dest=longopt.lstrip("--").replace("-", "_"), default=False)
for myalias, myopt in longopt_aliases.items():
parser.add_argument(myalias, action="store_true",
dest=myopt.lstrip("--").replace("-", "_"), default=False)
for myopt, kwargs in argument_options.items():
shortopt = kwargs.pop("shortopt", None)
args = [myopt]
if shortopt is not None:
args.append(shortopt)
parser.add_argument(dest=myopt.lstrip("--").replace("-", "_"),
*args, **kwargs)
tmpcmdline = insert_optional_args(tmpcmdline)
myoptions, myargs = parser.parse_known_args(args=tmpcmdline)
if myoptions.alert in true_y:
myoptions.alert = True
else:
myoptions.alert = None
if myoptions.ask in true_y:
myoptions.ask = True
else:
myoptions.ask = None
if myoptions.autounmask in true_y:
myoptions.autounmask = True
if myoptions.autounmask_continue in true_y:
myoptions.autounmask_continue = True
if myoptions.autounmask_only in true_y:
myoptions.autounmask_only = True
else:
myoptions.autounmask_only = None
if myoptions.autounmask_unrestricted_atoms in true_y:
myoptions.autounmask_unrestricted_atoms = True
if myoptions.autounmask_keep_keywords in true_y:
myoptions.autounmask_keep_keywords = True
if myoptions.autounmask_keep_masks in true_y:
myoptions.autounmask_keep_masks = True
if myoptions.autounmask_write in true_y:
myoptions.autounmask_write = True
if myoptions.binpkg_changed_deps is not None:
if myoptions.binpkg_changed_deps in true_y:
myoptions.binpkg_changed_deps = 'y'
else:
myoptions.binpkg_changed_deps = 'n'
if myoptions.buildpkg in true_y:
myoptions.buildpkg = True
if myoptions.buildpkg_exclude:
bad_atoms = _find_bad_atoms(myoptions.buildpkg_exclude, less_strict=True)
if bad_atoms and not silent:
parser.error("Invalid Atom(s) in --buildpkg-exclude parameter: '%s'\n" % \
(",".join(bad_atoms),))
if myoptions.changed_deps is not None:
if myoptions.changed_deps in true_y:
myoptions.changed_deps = 'y'
else:
myoptions.changed_deps = 'n'
if myoptions.changed_deps_report is not None:
if myoptions.changed_deps_report in true_y:
myoptions.changed_deps_report = 'y'
else:
myoptions.changed_deps_report = 'n'
if myoptions.changed_slot is not None:
if myoptions.changed_slot in true_y:
myoptions.changed_slot = True
else:
myoptions.changed_slot = None
if myoptions.changed_use is not False:
myoptions.reinstall = "changed-use"
myoptions.changed_use = False
if myoptions.deselect in true_y:
myoptions.deselect = True
if myoptions.binpkg_respect_use is not None:
if myoptions.binpkg_respect_use in true_y:
myoptions.binpkg_respect_use = 'y'
else:
myoptions.binpkg_respect_use = 'n'
if myoptions.complete_graph in true_y:
myoptions.complete_graph = True
else:
myoptions.complete_graph = None
if myoptions.depclean_lib_check in true_y:
myoptions.depclean_lib_check = True
if myoptions.exclude:
bad_atoms = _find_bad_atoms(myoptions.exclude)
if bad_atoms and not silent:
parser.error("Invalid Atom(s) in --exclude parameter: '%s' (only package names and slot atoms (with wildcards) allowed)\n" % \
(",".join(bad_atoms),))
if myoptions.reinstall_atoms:
bad_atoms = _find_bad_atoms(myoptions.reinstall_atoms)
if bad_atoms and not silent:
parser.error("Invalid Atom(s) in --reinstall-atoms parameter: '%s' (only package names and slot atoms (with wildcards) allowed)\n" % \
(",".join(bad_atoms),))
if myoptions.rebuild_exclude:
bad_atoms = _find_bad_atoms(myoptions.rebuild_exclude)
if bad_atoms and not silent:
parser.error("Invalid Atom(s) in --rebuild-exclude parameter: '%s' (only package names and slot atoms (with wildcards) allowed)\n" % \
(",".join(bad_atoms),))
if myoptions.rebuild_ignore:
bad_atoms = _find_bad_atoms(myoptions.rebuild_ignore)
if bad_atoms and not silent:
parser.error("Invalid Atom(s) in --rebuild-ignore parameter: '%s' (only package names and slot atoms (with wildcards) allowed)\n" % \
(",".join(bad_atoms),))
if myoptions.usepkg_exclude:
bad_atoms = _find_bad_atoms(myoptions.usepkg_exclude)
if bad_atoms and not silent:
parser.error("Invalid Atom(s) in --usepkg-exclude parameter: '%s' (only package names and slot atoms (with wildcards) allowed)\n" % \
(",".join(bad_atoms),))
if myoptions.useoldpkg_atoms:
bad_atoms = _find_bad_atoms(myoptions.useoldpkg_atoms)
if bad_atoms and not silent:
parser.error("Invalid Atom(s) in --useoldpkg-atoms parameter: '%s' (only package names and slot atoms (with wildcards) allowed)\n" % \
(",".join(bad_atoms),))
if myoptions.fail_clean in true_y:
myoptions.fail_clean = True
if myoptions.fuzzy_search in true_y:
myoptions.fuzzy_search = True
if myoptions.getbinpkg in true_y:
myoptions.getbinpkg = True
else:
myoptions.getbinpkg = None
if myoptions.getbinpkgonly in true_y:
myoptions.getbinpkgonly = True
else:
myoptions.getbinpkgonly = None
if myoptions.ignore_world in true_y:
myoptions.ignore_world = True
if myoptions.keep_going in true_y:
myoptions.keep_going = True
else:
myoptions.keep_going = None
if myoptions.package_moves in true_y:
myoptions.package_moves = True
if myoptions.quiet in true_y:
myoptions.quiet = True
else:
myoptions.quiet = None
if myoptions.quiet_build in true_y:
myoptions.quiet_build = 'y'
if myoptions.quiet_fail in true_y:
myoptions.quiet_fail = 'y'
if myoptions.read_news in true_y:
myoptions.read_news = True
else:
myoptions.read_news = None
if myoptions.rebuild_if_new_slot in true_y:
myoptions.rebuild_if_new_slot = 'y'
if myoptions.rebuild_if_new_ver in true_y:
myoptions.rebuild_if_new_ver = True
else:
myoptions.rebuild_if_new_ver = None
if myoptions.rebuild_if_new_rev in true_y:
myoptions.rebuild_if_new_rev = True
myoptions.rebuild_if_new_ver = None
else:
myoptions.rebuild_if_new_rev = None
if myoptions.rebuild_if_unbuilt in true_y:
myoptions.rebuild_if_unbuilt = True
myoptions.rebuild_if_new_rev = None
myoptions.rebuild_if_new_ver = None
else:
myoptions.rebuild_if_unbuilt = None
if myoptions.rebuilt_binaries in true_y:
myoptions.rebuilt_binaries = True
if myoptions.root_deps in true_y:
myoptions.root_deps = True
if myoptions.select in true_y:
myoptions.select = True
myoptions.oneshot = False
elif myoptions.select == "n":
myoptions.oneshot = True
if myoptions.selective in true_y:
myoptions.selective = True
if myoptions.backtrack is not None:
try:
backtrack = int(myoptions.backtrack)
except (OverflowError, ValueError):
backtrack = -1
if backtrack < 0:
backtrack = None
if not silent:
parser.error("Invalid --backtrack parameter: '%s'\n" % \
(myoptions.backtrack,))
myoptions.backtrack = backtrack
if myoptions.deep is not None:
deep = None
if myoptions.deep == "True":
deep = True
else:
try:
deep = int(myoptions.deep)
except (OverflowError, ValueError):
deep = -1
if deep is not True and deep < 0:
deep = None
if not silent:
parser.error("Invalid --deep parameter: '%s'\n" % \
(myoptions.deep,))
myoptions.deep = deep
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:
parser.error("Invalid --jobs parameter: '%s'\n" % \
(myoptions.jobs,))
myoptions.jobs = jobs
if myoptions.load_average == "True":
myoptions.load_average = None
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:
parser.error("Invalid --load-average parameter: '%s'\n" % \
(myoptions.load_average,))
myoptions.load_average = load_average
if myoptions.rebuilt_binaries_timestamp:
try:
rebuilt_binaries_timestamp = int(myoptions.rebuilt_binaries_timestamp)
except ValueError:
rebuilt_binaries_timestamp = -1
if rebuilt_binaries_timestamp < 0:
rebuilt_binaries_timestamp = 0
if not silent:
parser.error("Invalid --rebuilt-binaries-timestamp parameter: '%s'\n" % \
(myoptions.rebuilt_binaries_timestamp,))
myoptions.rebuilt_binaries_timestamp = rebuilt_binaries_timestamp
if myoptions.search_similarity:
try:
search_similarity = float(myoptions.search_similarity)
except ValueError:
parser.error("Invalid --search-similarity parameter "
"(not a number): '{}'\n".format(
myoptions.search_similarity))
if search_similarity < 0 or search_similarity > 100:
parser.error("Invalid --search-similarity parameter "
"(not between 0 and 100): '{}'\n".format(
myoptions.search_similarity))
myoptions.search_similarity = search_similarity
if myoptions.use_ebuild_visibility in true_y:
myoptions.use_ebuild_visibility = True
else:
# None or "n"
pass
if myoptions.usepkg in true_y:
myoptions.usepkg = True
else:
myoptions.usepkg = None
if myoptions.usepkgonly in true_y:
myoptions.usepkgonly = True
else:
myoptions.usepkgonly = None
if myoptions.verbose in true_y:
myoptions.verbose = True
else:
myoptions.verbose = None
if myoptions.with_test_deps in true_y:
myoptions.with_test_deps = True
else:
myoptions.with_test_deps = None
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 profile_check(trees, myaction):
if myaction in ("help", "info", "search", "sync", "version"):
return os.EX_OK
for root_trees in trees.values():
if (root_trees["root_config"].settings.profiles and
'ARCH' in root_trees["root_config"].settings):
continue
# generate some profile related warning messages
validate_ebuild_environment(trees)
msg = ("Your current profile is invalid. If you have just changed "
"your profile configuration, you should revert back to the "
"previous configuration. Allowed actions are limited to "
"--help, --info, --search, --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(args=None):
"""
@param args: command arguments (default: sys.argv[1:])
@type args: list
"""
if args is None:
args = sys.argv[1:]
args = portage._decode_argv(args)
# Use system locale.
try:
locale.setlocale(locale.LC_ALL, "")
except locale.Error as e:
writemsg_level("setlocale: %s\n" % e, level=logging.WARN)
# 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(args, silent=True)
if "--debug" in myopts:
os.environ["PORTAGE_DEBUG"] = "1"
if "--config-root" in myopts:
os.environ["PORTAGE_CONFIGROOT"] = myopts["--config-root"]
if "--sysroot" in myopts:
os.environ["SYSROOT"] = myopts["--sysroot"]
if "--root" in myopts:
os.environ["ROOT"] = myopts["--root"]
if "--prefix" in myopts:
os.environ["EPREFIX"] = myopts["--prefix"]
if "--accept-properties" in myopts:
os.environ["ACCEPT_PROPERTIES"] = myopts["--accept-properties"]
if "--accept-restrict" in myopts:
os.environ["ACCEPT_RESTRICT"] = myopts["--accept-restrict"]
# optimize --help (no need to load config / EMERGE_DEFAULT_OPTS)
if myaction == "help":
emerge_help()
return os.EX_OK
elif myaction == "moo":
print(COWSAY_MOO % platform.system())
return os.EX_OK
elif myaction == "sync":
# need to set this to True now in order for the repository config
# loading to allow new repos with non-existent directories
portage._sync_mode = True
# Verify that /dev/null exists and is a device file as a cheap early
# filter for obviously broken /dev/s.
try:
if os.stat(os.devnull).st_rdev == 0:
writemsg_level("Failed to validate a sane '/dev'.\n"
"'/dev/null' is not a device file.\n",
level=logging.ERROR, noiselevel=-1)
return 1
except OSError:
writemsg_level("Failed to validate a sane '/dev'.\n"
"'/dev/null' does not exist.\n",
level=logging.ERROR, noiselevel=-1)
return 1
# Verify that BASH process substitution works as another cheap early
# filter. Process substitution uses '/dev/fd'.
with open(os.devnull, 'r+b') as dev_null:
fd_pipes = {
0: dev_null.fileno(),
1: dev_null.fileno(),
2: dev_null.fileno(),
}
if portage.process.spawn_bash("[[ $(< <(echo foo) ) == foo ]]",
fd_pipes=fd_pipes) != 0:
writemsg_level("Failed to validate a sane '/dev'.\n"
"bash process substitution doesn't work; this may be an "
"indication of a broken '/dev/fd'.\n",
level=logging.ERROR, noiselevel=-1)
return 1
# Portage needs to ensure a sane umask for the files it creates.
os.umask(0o22)
emerge_config = load_emerge_config(
action=myaction, args=myfiles, opts=myopts)
# Make locale variables from configuration files (make.defaults, make.conf) affect locale of emerge process.
for locale_var_name in ("LANGUAGE", "LC_ALL", "LC_ADDRESS", "LC_COLLATE", "LC_CTYPE",
"LC_IDENTIFICATION", "LC_MEASUREMENT", "LC_MESSAGES", "LC_MONETARY",
"LC_NAME", "LC_NUMERIC", "LC_PAPER", "LC_TELEPHONE", "LC_TIME", "LANG"):
locale_var_value = emerge_config.running_config.settings.get(locale_var_name)
if locale_var_value is not None:
os.environ.setdefault(locale_var_name, locale_var_value)
try:
locale.setlocale(locale.LC_ALL, "")
except locale.Error as e:
writemsg_level("setlocale: %s\n" % e, level=logging.WARN)
tmpcmdline = []
if "--ignore-default-opts" not in myopts:
tmpcmdline.extend(portage.util.shlex_split(
emerge_config.target_config.settings.get(
"EMERGE_DEFAULT_OPTS", "")))
tmpcmdline.extend(args)
emerge_config.action, emerge_config.opts, emerge_config.args = \
parse_opts(tmpcmdline)
try:
return run_action(emerge_config)
finally:
# Call destructors for our portdbapi instances.
for x in emerge_config.trees.values():
if "porttree" in x.lazy_items:
continue
x["porttree"].dbapi.close_caches()