Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 195538 Details for
Bug 275047
[PATCH] Split pym/_emerge/__init__.py into several small files
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
actions.py
actions.py (text/plain), 85.31 KB, created by
Sebastian Luther (few)
on 2009-06-23 07:38:51 UTC
(
hide
)
Description:
actions.py
Filename:
MIME Type:
Creator:
Sebastian Luther (few)
Created:
2009-06-23 07:38:51 UTC
Size:
85.31 KB
patch
obsolete
>import commands >import errno >import logging >import os >import platform >import pwd >import re >import shlex >import signal >import socket >import stat >import sys >import textwrap >import time >from itertools import chain, izip > >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 > >from portage import digraph >from portage.cache.cache_errors import CacheError >from portage.const import NEWS_LIB_PATH >from portage.output import blue, bold, colorize, create_color_func, darkgreen, \ > red, yellow >good = create_color_func("GOOD") >bad = create_color_func("BAD") >from portage.sets import load_default_config, SETPREFIX >from portage.sets.base import InternalPackageSet >from portage.util import cmp_sort_key, writemsg, writemsg_level > >from _emerge.clear_caches import clear_caches >from _emerge.countdown import countdown >from _emerge.create_depgraph_params import create_depgraph_params >from _emerge.Dependency import Dependency >from _emerge.depgraph import depgraph, resume_depgraph >from _emerge.DepPrioritySatisfiedRange import DepPrioritySatisfiedRange >from _emerge.emergelog import emergelog >from _emerge.is_valid_package_atom import is_valid_package_atom >from _emerge.MetadataRegen import MetadataRegen >from _emerge.Package import Package >from _emerge.ProgressHandler import ProgressHandler >from _emerge.RootConfig import RootConfig >from _emerge.Scheduler import Scheduler >from _emerge.search import search >from _emerge.SetArg import SetArg >from _emerge.show_invalid_depstring_notice import show_invalid_depstring_notice >from _emerge.unmerge import unmerge >from _emerge.UnmergeDepPriority import UnmergeDepPriority >from _emerge.UseFlagDisplay import UseFlagDisplay >from _emerge.userquery import userquery > >def action_build(settings, trees, mtimedb, > myopts, myaction, myfiles, spinner): > > # validate the state of the resume data > # so that we can make assumptions later. > for k in ("resume", "resume_backup"): > if k not in mtimedb: > continue > resume_data = mtimedb[k] > if not isinstance(resume_data, dict): > del mtimedb[k] > continue > mergelist = resume_data.get("mergelist") > if not isinstance(mergelist, list): > del mtimedb[k] > continue > for x in mergelist: > if not (isinstance(x, list) and len(x) == 4): > continue > pkg_type, pkg_root, pkg_key, pkg_action = x > if pkg_root not in trees: > # Current $ROOT setting differs, > # so the list must be stale. > mergelist = None > break > if not mergelist: > del mtimedb[k] > continue > resume_opts = resume_data.get("myopts") > if not isinstance(resume_opts, (dict, list)): > del mtimedb[k] > continue > favorites = resume_data.get("favorites") > if not isinstance(favorites, list): > del mtimedb[k] > continue > > resume = False > if "--resume" in myopts and \ > ("resume" in mtimedb or > "resume_backup" in mtimedb): > resume = True > if "resume" not in mtimedb: > mtimedb["resume"] = mtimedb["resume_backup"] > del mtimedb["resume_backup"] > mtimedb.commit() > # "myopts" is a list for backward compatibility. > resume_opts = mtimedb["resume"].get("myopts", []) > if isinstance(resume_opts, list): > resume_opts = dict((k,True) for k in resume_opts) > for opt in ("--ask", "--color", "--skipfirst", "--tree"): > resume_opts.pop(opt, None) > > # Current options always override resume_opts. > resume_opts.update(myopts) > myopts.clear() > myopts.update(resume_opts) > > if "--debug" in myopts: > writemsg_level("myopts %s\n" % (myopts,)) > > # Adjust config according to options of the command being resumed. > for myroot in trees: > mysettings = trees[myroot]["vartree"].settings > mysettings.unlock() > adjust_config(myopts, mysettings) > mysettings.lock() > del myroot, mysettings > > ldpath_mtimes = mtimedb["ldpath"] > favorites=[] > merge_count = 0 > buildpkgonly = "--buildpkgonly" in myopts > pretend = "--pretend" in myopts > fetchonly = "--fetchonly" in myopts or "--fetch-all-uri" in myopts > ask = "--ask" in myopts > nodeps = "--nodeps" in myopts > oneshot = "--oneshot" in myopts or "--onlydeps" in myopts > tree = "--tree" in myopts > if nodeps and tree: > tree = False > del myopts["--tree"] > portage.writemsg(colorize("WARN", " * ") + \ > "--tree is broken with --nodeps. Disabling...\n") > debug = "--debug" in myopts > verbose = "--verbose" in myopts > quiet = "--quiet" in myopts > if pretend or fetchonly: > # make the mtimedb readonly > mtimedb.filename = None > if '--digest' in myopts or 'digest' in settings.features: > if '--digest' in myopts: > msg = "The --digest option" > else: > msg = "The FEATURES=digest setting" > > msg += " can prevent corruption from being" + \ > " noticed. The `repoman manifest` command is the preferred" + \ > " way to generate manifests and it is capable of doing an" + \ > " entire repository or category at once." > prefix = bad(" * ") > writemsg(prefix + "\n") > from textwrap import wrap > for line in wrap(msg, 72): > writemsg("%s%s\n" % (prefix, line)) > writemsg(prefix + "\n") > > if "--quiet" not in myopts and \ > ("--pretend" in myopts or "--ask" in myopts or \ > "--tree" in myopts or "--verbose" in myopts): > action = "" > if "--fetchonly" in myopts or "--fetch-all-uri" in myopts: > action = "fetched" > elif "--buildpkgonly" in myopts: > action = "built" > else: > action = "merged" > if "--tree" in myopts and action != "fetched": # Tree doesn't work with fetching > print > print darkgreen("These are the packages that would be %s, in reverse order:") % action > print > else: > print > print darkgreen("These are the packages that would be %s, in order:") % action > print > > show_spinner = "--quiet" not in myopts and "--nodeps" not in myopts > if not show_spinner: > spinner.update = spinner.update_quiet > > if resume: > favorites = mtimedb["resume"].get("favorites") > if not isinstance(favorites, list): > favorites = [] > > if show_spinner: > print "Calculating dependencies ", > myparams = create_depgraph_params(myopts, myaction) > > resume_data = mtimedb["resume"] > mergelist = resume_data["mergelist"] > if mergelist and "--skipfirst" in myopts: > for i, task in enumerate(mergelist): > if isinstance(task, list) and \ > task and task[-1] == "merge": > del mergelist[i] > break > > success = False > mydepgraph = None > try: > success, mydepgraph, dropped_tasks = resume_depgraph( > settings, trees, mtimedb, myopts, myparams, spinner) > except (portage.exception.PackageNotFound, > depgraph.UnsatisfiedResumeDep), e: > if isinstance(e, depgraph.UnsatisfiedResumeDep): > mydepgraph = e.depgraph > if show_spinner: > print > from textwrap import wrap > from portage.output import EOutput > out = EOutput() > > resume_data = mtimedb["resume"] > mergelist = resume_data.get("mergelist") > if not isinstance(mergelist, list): > mergelist = [] > if mergelist and debug or (verbose and not quiet): > out.eerror("Invalid resume list:") > out.eerror("") > indent = " " > for task in mergelist: > if isinstance(task, list): > out.eerror(indent + str(tuple(task))) > out.eerror("") > > if isinstance(e, depgraph.UnsatisfiedResumeDep): > out.eerror("One or more packages are either masked or " + \ > "have missing dependencies:") > out.eerror("") > indent = " " > for dep in e.value: > if dep.atom is None: > out.eerror(indent + "Masked package:") > out.eerror(2 * indent + str(dep.parent)) > out.eerror("") > else: > out.eerror(indent + str(dep.atom) + " pulled in by:") > out.eerror(2 * indent + str(dep.parent)) > out.eerror("") > msg = "The resume list contains packages " + \ > "that are either masked or have " + \ > "unsatisfied dependencies. " + \ > "Please restart/continue " + \ > "the operation manually, or use --skipfirst " + \ > "to skip the first package in the list and " + \ > "any other packages that may be " + \ > "masked or have missing dependencies." > for line in wrap(msg, 72): > out.eerror(line) > elif isinstance(e, portage.exception.PackageNotFound): > out.eerror("An expected package is " + \ > "not available: %s" % str(e)) > out.eerror("") > msg = "The resume list contains one or more " + \ > "packages that are no longer " + \ > "available. Please restart/continue " + \ > "the operation manually." > for line in wrap(msg, 72): > out.eerror(line) > else: > if show_spinner: > print "\b\b... done!" > > if success: > if dropped_tasks: > portage.writemsg("!!! One or more packages have been " + \ > "dropped due to\n" + \ > "!!! masking or unsatisfied dependencies:\n\n", > noiselevel=-1) > for task in dropped_tasks: > portage.writemsg(" " + str(task) + "\n", noiselevel=-1) > portage.writemsg("\n", noiselevel=-1) > del dropped_tasks > else: > if mydepgraph is not None: > mydepgraph.display_problems() > if not (ask or pretend): > # delete the current list and also the backup > # since it's probably stale too. > for k in ("resume", "resume_backup"): > mtimedb.pop(k, None) > mtimedb.commit() > > return 1 > else: > if ("--resume" in myopts): > print darkgreen("emerge: It seems we have nothing to resume...") > return os.EX_OK > > myparams = create_depgraph_params(myopts, myaction) > if "--quiet" not in myopts and "--nodeps" not in myopts: > print "Calculating dependencies ", > sys.stdout.flush() > mydepgraph = depgraph(settings, trees, myopts, myparams, spinner) > try: > retval, favorites = mydepgraph.select_files(myfiles) > except portage.exception.PackageNotFound, e: > portage.writemsg("\n!!! %s\n" % str(e), noiselevel=-1) > return 1 > except portage.exception.PackageSetNotFound, e: > root_config = trees[settings["ROOT"]]["root_config"] > display_missing_pkg_set(root_config, e.value) > return 1 > if show_spinner: > print "\b\b... done!" > if not retval: > mydepgraph.display_problems() > return 1 > > if "--pretend" not in myopts and \ > ("--ask" in myopts or "--tree" in myopts or \ > "--verbose" in myopts) and \ > not ("--quiet" in myopts and "--ask" not in myopts): > if "--resume" in myopts: > mymergelist = mydepgraph.altlist() > if len(mymergelist) == 0: > print colorize("INFORM", "emerge: It seems we have nothing to resume...") > return os.EX_OK > favorites = mtimedb["resume"]["favorites"] > retval = mydepgraph.display( > mydepgraph.altlist(reversed=tree), > favorites=favorites) > mydepgraph.display_problems() > if retval != os.EX_OK: > return retval > prompt="Would you like to resume merging these packages?" > else: > retval = mydepgraph.display( > mydepgraph.altlist(reversed=("--tree" in myopts)), > favorites=favorites) > mydepgraph.display_problems() > if retval != os.EX_OK: > return retval > mergecount=0 > for x in mydepgraph.altlist(): > if isinstance(x, Package) and x.operation == "merge": > mergecount += 1 > > if mergecount==0: > sets = trees[settings["ROOT"]]["root_config"].sets > world_candidates = None > if "--noreplace" in myopts and \ > not oneshot and favorites: > # Sets that are not world candidates are filtered > # out here since the favorites list needs to be > # complete for depgraph.loadResumeCommand() to > # operate correctly. > world_candidates = [x for x in favorites \ > if not (x.startswith(SETPREFIX) and \ > not sets[x[1:]].world_candidate)] > if "--noreplace" in myopts and \ > not oneshot and world_candidates: > print > for x in world_candidates: > print " %s %s" % (good("*"), x) > prompt="Would you like to add these packages to your world favorites?" > elif settings["AUTOCLEAN"] and "yes"==settings["AUTOCLEAN"]: > prompt="Nothing to merge; would you like to auto-clean packages?" > else: > print > print "Nothing to merge; quitting." > print > return os.EX_OK > elif "--fetchonly" in myopts or "--fetch-all-uri" in myopts: > prompt="Would you like to fetch the source files for these packages?" > else: > prompt="Would you like to merge these packages?" > print > if "--ask" in myopts and userquery(prompt) == "No": > print > print "Quitting." > print > return os.EX_OK > # Don't ask again (e.g. when auto-cleaning packages after merge) > myopts.pop("--ask", None) > > if ("--pretend" in myopts) and not ("--fetchonly" in myopts or "--fetch-all-uri" in myopts): > if ("--resume" in myopts): > mymergelist = mydepgraph.altlist() > if len(mymergelist) == 0: > print colorize("INFORM", "emerge: It seems we have nothing to resume...") > return os.EX_OK > favorites = mtimedb["resume"]["favorites"] > retval = mydepgraph.display( > mydepgraph.altlist(reversed=tree), > favorites=favorites) > mydepgraph.display_problems() > if retval != os.EX_OK: > return retval > else: > retval = mydepgraph.display( > mydepgraph.altlist(reversed=("--tree" in myopts)), > favorites=favorites) > mydepgraph.display_problems() > if retval != os.EX_OK: > return retval > if "--buildpkgonly" in myopts: > graph_copy = mydepgraph.digraph.clone() > removed_nodes = set() > for node in graph_copy: > if not isinstance(node, Package) or \ > node.operation == "nomerge": > removed_nodes.add(node) > graph_copy.difference_update(removed_nodes) > if not graph_copy.hasallzeros(ignore_priority = \ > DepPrioritySatisfiedRange.ignore_medium): > print "\n!!! --buildpkgonly requires all dependencies to be merged." > print "!!! You have to merge the dependencies before you can build this package.\n" > return 1 > else: > if "--buildpkgonly" in myopts: > graph_copy = mydepgraph.digraph.clone() > removed_nodes = set() > for node in graph_copy: > if not isinstance(node, Package) or \ > node.operation == "nomerge": > removed_nodes.add(node) > graph_copy.difference_update(removed_nodes) > if not graph_copy.hasallzeros(ignore_priority = \ > DepPrioritySatisfiedRange.ignore_medium): > print "\n!!! --buildpkgonly requires all dependencies to be merged." > print "!!! Cannot merge requested packages. Merge deps and try again.\n" > return 1 > > if ("--resume" in myopts): > favorites=mtimedb["resume"]["favorites"] > mymergelist = mydepgraph.altlist() > mydepgraph.break_refs(mymergelist) > mergetask = Scheduler(settings, trees, mtimedb, myopts, > spinner, mymergelist, favorites, mydepgraph.schedulerGraph()) > del mydepgraph, mymergelist > clear_caches(trees) > > retval = mergetask.merge() > merge_count = mergetask.curval > else: > if "resume" in mtimedb and \ > "mergelist" in mtimedb["resume"] and \ > len(mtimedb["resume"]["mergelist"]) > 1: > mtimedb["resume_backup"] = mtimedb["resume"] > del mtimedb["resume"] > mtimedb.commit() > mtimedb["resume"]={} > # Stored as a dict starting with portage-2.1.6_rc1, and supported > # by >=portage-2.1.3_rc8. Versions <portage-2.1.3_rc8 only support > # a list type for options. > mtimedb["resume"]["myopts"] = myopts.copy() > > # Convert Atom instances to plain str. > mtimedb["resume"]["favorites"] = [str(x) for x in favorites] > > pkglist = mydepgraph.altlist() > mydepgraph.saveNomergeFavorites() > mydepgraph.break_refs(pkglist) > mergetask = Scheduler(settings, trees, mtimedb, myopts, > spinner, pkglist, favorites, mydepgraph.schedulerGraph()) > del mydepgraph, pkglist > clear_caches(trees) > > retval = mergetask.merge() > merge_count = mergetask.curval > > if retval == os.EX_OK and not (buildpkgonly or fetchonly or pretend): > if "yes" == settings.get("AUTOCLEAN"): > portage.writemsg_stdout(">>> Auto-cleaning packages...\n") > unmerge(trees[settings["ROOT"]]["root_config"], > myopts, "clean", [], > ldpath_mtimes, autoclean=1) > else: > portage.writemsg_stdout(colorize("WARN", "WARNING:") > + " AUTOCLEAN is disabled. This can cause serious" > + " problems due to overlapping packages.\n") > trees[settings["ROOT"]]["vartree"].dbapi.plib_registry.pruneNonExisting() > > return retval > >def action_config(settings, trees, myopts, myfiles): > if len(myfiles) != 1: > print red("!!! config can only take a single package atom at this time\n") > sys.exit(1) > if not is_valid_package_atom(myfiles[0]): > portage.writemsg("!!! '%s' is not a valid package atom.\n" % myfiles[0], > noiselevel=-1) > portage.writemsg("!!! Please check ebuild(5) for full details.\n") > portage.writemsg("!!! (Did you specify a version but forget to prefix with '='?)\n") > sys.exit(1) > print > try: > pkgs = trees[settings["ROOT"]]["vartree"].dbapi.match(myfiles[0]) > except portage.exception.AmbiguousPackageName, e: > # Multiple matches thrown from cpv_expand > pkgs = e.args[0] > if len(pkgs) == 0: > print "No packages found.\n" > sys.exit(0) > elif len(pkgs) > 1: > if "--ask" in myopts: > options = [] > print "Please select a package to configure:" > idx = 0 > for pkg in pkgs: > idx += 1 > options.append(str(idx)) > print options[-1]+") "+pkg > print "X) Cancel" > options.append("X") > idx = userquery("Selection?", options) > if idx == "X": > sys.exit(0) > pkg = pkgs[int(idx)-1] > else: > print "The following packages available:" > for pkg in pkgs: > print "* "+pkg > print "\nPlease use a specific atom or the --ask option." > sys.exit(1) > else: > pkg = pkgs[0] > > print > if "--ask" in myopts: > if userquery("Ready to configure "+pkg+"?") == "No": > sys.exit(0) > else: > print "Configuring pkg..." > print > ebuildpath = trees[settings["ROOT"]]["vartree"].dbapi.findname(pkg) > mysettings = portage.config(clone=settings) > vardb = trees[mysettings["ROOT"]]["vartree"].dbapi > debug = mysettings.get("PORTAGE_DEBUG") == "1" > retval = portage.doebuild(ebuildpath, "config", mysettings["ROOT"], > mysettings, > debug=(settings.get("PORTAGE_DEBUG", "") == 1), cleanup=True, > mydbapi=trees[settings["ROOT"]]["vartree"].dbapi, tree="vartree") > if retval == os.EX_OK: > portage.doebuild(ebuildpath, "clean", mysettings["ROOT"], > mysettings, debug=debug, mydbapi=vardb, tree="vartree") > print > >def action_depclean(settings, trees, ldpath_mtimes, > myopts, action, myfiles, spinner): > # Kill packages that aren't explicitly merged or are required as a > # dependency of another package. World file is explicit. > > # Global depclean or prune operations are not very safe when there are > # missing dependencies since it's unknown how badly incomplete > # the dependency graph is, and we might accidentally remove packages > # that should have been pulled into the graph. On the other hand, it's > # relatively safe to ignore missing deps when only asked to remove > # specific packages. > allow_missing_deps = len(myfiles) > 0 > > msg = [] > msg.append("Always study the list of packages to be cleaned for any obvious\n") > msg.append("mistakes. Packages that are part of the world set will always\n") > msg.append("be kept. They can be manually added to this set with\n") > msg.append(good("`emerge --noreplace <atom>`") + ". Packages that are listed in\n") > msg.append("package.provided (see portage(5)) will be removed by\n") > msg.append("depclean, even if they are part of the world set.\n") > msg.append("\n") > msg.append("As a safety measure, depclean will not remove any packages\n") > msg.append("unless *all* required dependencies have been resolved. As a\n") > msg.append("consequence, it is often necessary to run %s\n" % \ > good("`emerge --update")) > msg.append(good("--newuse --deep @system @world`") + \ > " prior to depclean.\n") > > if action == "depclean" and "--quiet" not in myopts and not myfiles: > portage.writemsg_stdout("\n") > for x in msg: > portage.writemsg_stdout(colorize("WARN", " * ") + x) > > xterm_titles = "notitles" not in settings.features > myroot = settings["ROOT"] > root_config = trees[myroot]["root_config"] > getSetAtoms = root_config.setconfig.getSetAtoms > vardb = trees[myroot]["vartree"].dbapi > deselect = myopts.get('--deselect') != 'n' > > required_set_names = ("system", "world") > required_sets = {} > set_args = [] > > for s in required_set_names: > required_sets[s] = InternalPackageSet( > initial_atoms=getSetAtoms(s)) > > > # When removing packages, use a temporary version of world > # which excludes packages that are intended to be eligible for > # removal. > world_temp_set = required_sets["world"] > system_set = required_sets["system"] > > if not system_set or not world_temp_set: > > if not system_set: > writemsg_level("!!! You have no system list.\n", > level=logging.ERROR, noiselevel=-1) > > if not world_temp_set: > writemsg_level("!!! You have no world file.\n", > level=logging.WARNING, noiselevel=-1) > > writemsg_level("!!! Proceeding is likely to " + \ > "break your installation.\n", > level=logging.WARNING, noiselevel=-1) > if "--pretend" not in myopts: > countdown(int(settings["EMERGE_WARNING_DELAY"]), ">>> Depclean") > > if action == "depclean": > emergelog(xterm_titles, " >>> depclean") > > args_set = InternalPackageSet() > if myfiles: > args_set.update(myfiles) > matched_packages = False > for x in args_set: > if vardb.match(x): > matched_packages = True > break > if not matched_packages: > writemsg_level(">>> No packages selected for removal by %s\n" % \ > action) > return > > writemsg_level("\nCalculating dependencies ") > resolver_params = create_depgraph_params(myopts, "remove") > resolver = depgraph(settings, trees, myopts, resolver_params, spinner) > vardb = resolver.trees[myroot]["vartree"].dbapi > > if action == "depclean": > > if args_set: > > if deselect: > world_temp_set.clear() > > # Pull in everything that's installed but not matched > # by an argument atom since we don't want to clean any > # package if something depends on it. > for pkg in vardb: > spinner.update() > > try: > if args_set.findAtomForPackage(pkg) is None: > world_temp_set.add("=" + pkg.cpv) > continue > except portage.exception.InvalidDependString, e: > show_invalid_depstring_notice(pkg, > pkg.metadata["PROVIDE"], str(e)) > del e > world_temp_set.add("=" + pkg.cpv) > continue > > elif action == "prune": > > if deselect: > world_temp_set.clear() > > # Pull in everything that's installed since we don't > # to prune a package if something depends on it. > world_temp_set.update(vardb.cp_all()) > > if not args_set: > > # Try to prune everything that's slotted. > for cp in vardb.cp_all(): > if len(vardb.cp_list(cp)) > 1: > args_set.add(cp) > > # Remove atoms from world that match installed packages > # that are also matched by argument atoms, but do not remove > # them if they match the highest installed version. > for pkg in vardb: > spinner.update() > pkgs_for_cp = vardb.match_pkgs(pkg.cp) > if not pkgs_for_cp or pkg not in pkgs_for_cp: > raise AssertionError("package expected in matches: " + \ > "cp = %s, cpv = %s matches = %s" % \ > (pkg.cp, pkg.cpv, [str(x) for x in pkgs_for_cp])) > > highest_version = pkgs_for_cp[-1] > if pkg == highest_version: > # pkg is the highest version > world_temp_set.add("=" + pkg.cpv) > continue > > if len(pkgs_for_cp) <= 1: > raise AssertionError("more packages expected: " + \ > "cp = %s, cpv = %s matches = %s" % \ > (pkg.cp, pkg.cpv, [str(x) for x in pkgs_for_cp])) > > try: > if args_set.findAtomForPackage(pkg) is None: > world_temp_set.add("=" + pkg.cpv) > continue > except portage.exception.InvalidDependString, e: > show_invalid_depstring_notice(pkg, > pkg.metadata["PROVIDE"], str(e)) > del e > world_temp_set.add("=" + pkg.cpv) > continue > > set_args = {} > for s, package_set in required_sets.iteritems(): > set_atom = SETPREFIX + s > set_arg = SetArg(arg=set_atom, set=package_set, > root_config=resolver.roots[myroot]) > set_args[s] = set_arg > for atom in set_arg.set: > resolver._dep_stack.append( > Dependency(atom=atom, root=myroot, parent=set_arg)) > resolver.digraph.add(set_arg, None) > > success = resolver._complete_graph() > writemsg_level("\b\b... done!\n") > > resolver.display_problems() > > if not success: > return 1 > > def unresolved_deps(): > > unresolvable = set() > for dep in resolver._initially_unsatisfied_deps: > if isinstance(dep.parent, Package) and \ > (dep.priority > UnmergeDepPriority.SOFT): > unresolvable.add((dep.atom, dep.parent.cpv)) > > if not unresolvable: > return False > > if unresolvable and not allow_missing_deps: > prefix = bad(" * ") > msg = [] > msg.append("Dependencies could not be completely resolved due to") > msg.append("the following required packages not being installed:") > msg.append("") > for atom, parent in unresolvable: > msg.append(" %s pulled in by:" % (atom,)) > msg.append(" %s" % (parent,)) > msg.append("") > msg.append("Have you forgotten to run " + \ > good("`emerge --update --newuse --deep @system @world`") + " prior") > msg.append(("to %s? It may be necessary to manually " + \ > "uninstall packages that no longer") % action) > msg.append("exist in the portage tree since " + \ > "it may not be possible to satisfy their") > msg.append("dependencies. Also, be aware of " + \ > "the --with-bdeps option that is documented") > msg.append("in " + good("`man emerge`") + ".") > if action == "prune": > msg.append("") > msg.append("If you would like to ignore " + \ > "dependencies then use %s." % good("--nodeps")) > writemsg_level("".join("%s%s\n" % (prefix, line) for line in msg), > level=logging.ERROR, noiselevel=-1) > return True > return False > > if unresolved_deps(): > return 1 > > graph = resolver.digraph.copy() > required_pkgs_total = 0 > for node in graph: > if isinstance(node, Package): > required_pkgs_total += 1 > > def show_parents(child_node): > parent_nodes = graph.parent_nodes(child_node) > if not parent_nodes: > # With --prune, the highest version can be pulled in without any > # real parent since all installed packages are pulled in. In that > # case there's nothing to show here. > return > parent_strs = [] > for node in parent_nodes: > parent_strs.append(str(getattr(node, "cpv", node))) > parent_strs.sort() > msg = [] > msg.append(" %s pulled in by:\n" % (child_node.cpv,)) > for parent_str in parent_strs: > msg.append(" %s\n" % (parent_str,)) > msg.append("\n") > portage.writemsg_stdout("".join(msg), noiselevel=-1) > > def cmp_pkg_cpv(pkg1, pkg2): > """Sort Package instances by cpv.""" > if pkg1.cpv > pkg2.cpv: > return 1 > elif pkg1.cpv == pkg2.cpv: > return 0 > else: > return -1 > > def create_cleanlist(): > pkgs_to_remove = [] > > if action == "depclean": > if args_set: > > for pkg in sorted(vardb, key=cmp_sort_key(cmp_pkg_cpv)): > arg_atom = None > try: > arg_atom = args_set.findAtomForPackage(pkg) > except portage.exception.InvalidDependString: > # this error has already been displayed by now > continue > > if arg_atom: > if pkg not in graph: > pkgs_to_remove.append(pkg) > elif "--verbose" in myopts: > show_parents(pkg) > > else: > for pkg in sorted(vardb, key=cmp_sort_key(cmp_pkg_cpv)): > if pkg not in graph: > pkgs_to_remove.append(pkg) > elif "--verbose" in myopts: > show_parents(pkg) > > elif action == "prune": > # Prune really uses all installed instead of world. It's not > # a real reverse dependency so don't display it as such. > graph.remove(set_args["world"]) > > for atom in args_set: > for pkg in vardb.match_pkgs(atom): > if pkg not in graph: > pkgs_to_remove.append(pkg) > elif "--verbose" in myopts: > show_parents(pkg) > > if not pkgs_to_remove: > writemsg_level( > ">>> No packages selected for removal by %s\n" % action) > if "--verbose" not in myopts: > writemsg_level( > ">>> To see reverse dependencies, use %s\n" % \ > good("--verbose")) > if action == "prune": > writemsg_level( > ">>> To ignore dependencies, use %s\n" % \ > good("--nodeps")) > > return pkgs_to_remove > > cleanlist = create_cleanlist() > > if len(cleanlist): > clean_set = set(cleanlist) > > # Check if any of these package are the sole providers of libraries > # with consumers that have not been selected for removal. If so, these > # packages and any dependencies need to be added to the graph. > real_vardb = trees[myroot]["vartree"].dbapi > linkmap = real_vardb.linkmap > liblist = linkmap.listLibraryObjects() > consumer_cache = {} > provider_cache = {} > soname_cache = {} > consumer_map = {} > > writemsg_level(">>> Checking for lib consumers...\n") > > for pkg in cleanlist: > pkg_dblink = real_vardb._dblink(pkg.cpv) > provided_libs = set() > > for lib in liblist: > if pkg_dblink.isowner(lib, myroot): > provided_libs.add(lib) > > if not provided_libs: > continue > > consumers = {} > for lib in provided_libs: > lib_consumers = consumer_cache.get(lib) > if lib_consumers is None: > lib_consumers = linkmap.findConsumers(lib) > consumer_cache[lib] = lib_consumers > if lib_consumers: > consumers[lib] = lib_consumers > > if not consumers: > continue > > for lib, lib_consumers in consumers.items(): > for consumer_file in list(lib_consumers): > if pkg_dblink.isowner(consumer_file, myroot): > lib_consumers.remove(consumer_file) > if not lib_consumers: > del consumers[lib] > > if not consumers: > continue > > for lib, lib_consumers in consumers.iteritems(): > > soname = soname_cache.get(lib) > if soname is None: > soname = linkmap.getSoname(lib) > soname_cache[lib] = soname > > consumer_providers = [] > for lib_consumer in lib_consumers: > providers = provider_cache.get(lib) > if providers is None: > providers = linkmap.findProviders(lib_consumer) > provider_cache[lib_consumer] = providers > if soname not in providers: > # Why does this happen? > continue > consumer_providers.append( > (lib_consumer, providers[soname])) > > consumers[lib] = consumer_providers > > consumer_map[pkg] = consumers > > if consumer_map: > > search_files = set() > for consumers in consumer_map.itervalues(): > for lib, consumer_providers in consumers.iteritems(): > for lib_consumer, providers in consumer_providers: > search_files.add(lib_consumer) > search_files.update(providers) > > writemsg_level(">>> Assigning files to packages...\n") > file_owners = real_vardb._owners.getFileOwnerMap(search_files) > > for pkg, consumers in consumer_map.items(): > for lib, consumer_providers in consumers.items(): > lib_consumers = set() > > for lib_consumer, providers in consumer_providers: > owner_set = file_owners.get(lib_consumer) > provider_dblinks = set() > provider_pkgs = set() > > if len(providers) > 1: > for provider in providers: > provider_set = file_owners.get(provider) > if provider_set is not None: > provider_dblinks.update(provider_set) > > if len(provider_dblinks) > 1: > for provider_dblink in provider_dblinks: > pkg_key = ("installed", myroot, > provider_dblink.mycpv, "nomerge") > if pkg_key not in clean_set: > provider_pkgs.add(vardb.get(pkg_key)) > > if provider_pkgs: > continue > > if owner_set is not None: > lib_consumers.update(owner_set) > > for consumer_dblink in list(lib_consumers): > if ("installed", myroot, consumer_dblink.mycpv, > "nomerge") in clean_set: > lib_consumers.remove(consumer_dblink) > continue > > if lib_consumers: > consumers[lib] = lib_consumers > else: > del consumers[lib] > if not consumers: > del consumer_map[pkg] > > if consumer_map: > # TODO: Implement a package set for rebuilding consumer packages. > > msg = "In order to avoid breakage of link level " + \ > "dependencies, one or more packages will not be removed. " + \ > "This can be solved by rebuilding " + \ > "the packages that pulled them in." > > prefix = bad(" * ") > from textwrap import wrap > writemsg_level("".join(prefix + "%s\n" % line for \ > line in wrap(msg, 70)), level=logging.WARNING, noiselevel=-1) > > msg = [] > for pkg, consumers in consumer_map.iteritems(): > unique_consumers = set(chain(*consumers.values())) > unique_consumers = sorted(consumer.mycpv \ > for consumer in unique_consumers) > msg.append("") > msg.append(" %s pulled in by:" % (pkg.cpv,)) > for consumer in unique_consumers: > msg.append(" %s" % (consumer,)) > msg.append("") > writemsg_level("".join(prefix + "%s\n" % line for line in msg), > level=logging.WARNING, noiselevel=-1) > > # Add lib providers to the graph as children of lib consumers, > # and also add any dependencies pulled in by the provider. > writemsg_level(">>> Adding lib providers to graph...\n") > > for pkg, consumers in consumer_map.iteritems(): > for consumer_dblink in set(chain(*consumers.values())): > consumer_pkg = vardb.get(("installed", myroot, > consumer_dblink.mycpv, "nomerge")) > if not resolver._add_pkg(pkg, > Dependency(parent=consumer_pkg, > priority=UnmergeDepPriority(runtime=True), > root=pkg.root)): > resolver.display_problems() > return 1 > > writemsg_level("\nCalculating dependencies ") > success = resolver._complete_graph() > writemsg_level("\b\b... done!\n") > resolver.display_problems() > if not success: > return 1 > if unresolved_deps(): > return 1 > > graph = resolver.digraph.copy() > required_pkgs_total = 0 > for node in graph: > if isinstance(node, Package): > required_pkgs_total += 1 > cleanlist = create_cleanlist() > if not cleanlist: > return 0 > clean_set = set(cleanlist) > > # Use a topological sort to create an unmerge order such that > # each package is unmerged before it's dependencies. This is > # necessary to avoid breaking things that may need to run > # during pkg_prerm or pkg_postrm phases. > > # Create a new graph to account for dependencies between the > # packages being unmerged. > graph = digraph() > del cleanlist[:] > > dep_keys = ["DEPEND", "RDEPEND", "PDEPEND"] > runtime = UnmergeDepPriority(runtime=True) > runtime_post = UnmergeDepPriority(runtime_post=True) > buildtime = UnmergeDepPriority(buildtime=True) > priority_map = { > "RDEPEND": runtime, > "PDEPEND": runtime_post, > "DEPEND": buildtime, > } > > for node in clean_set: > graph.add(node, None) > mydeps = [] > node_use = node.metadata["USE"].split() > for dep_type in dep_keys: > depstr = node.metadata[dep_type] > if not depstr: > continue > try: > portage.dep._dep_check_strict = False > success, atoms = portage.dep_check(depstr, None, settings, > myuse=node_use, trees=resolver._graph_trees, > myroot=myroot) > finally: > portage.dep._dep_check_strict = True > if not success: > # Ignore invalid deps of packages that will > # be uninstalled anyway. > continue > > priority = priority_map[dep_type] > for atom in atoms: > if not isinstance(atom, portage.dep.Atom): > # Ignore invalid atoms returned from dep_check(). > continue > if atom.blocker: > continue > matches = vardb.match_pkgs(atom) > if not matches: > continue > for child_node in matches: > if child_node in clean_set: > graph.add(child_node, node, priority=priority) > > ordered = True > if len(graph.order) == len(graph.root_nodes()): > # If there are no dependencies between packages > # let unmerge() group them by cat/pn. > ordered = False > cleanlist = [pkg.cpv for pkg in graph.order] > else: > # Order nodes from lowest to highest overall reference count for > # optimal root node selection. > node_refcounts = {} > for node in graph.order: > node_refcounts[node] = len(graph.parent_nodes(node)) > def cmp_reference_count(node1, node2): > return node_refcounts[node1] - node_refcounts[node2] > graph.order.sort(key=cmp_sort_key(cmp_reference_count)) > > ignore_priority_range = [None] > ignore_priority_range.extend( > xrange(UnmergeDepPriority.MIN, UnmergeDepPriority.MAX + 1)) > while not graph.empty(): > for ignore_priority in ignore_priority_range: > nodes = graph.root_nodes(ignore_priority=ignore_priority) > if nodes: > break > if not nodes: > raise AssertionError("no root nodes") > if ignore_priority is not None: > # Some deps have been dropped due to circular dependencies, > # so only pop one node in order do minimize the number that > # are dropped. > del nodes[1:] > for node in nodes: > graph.remove(node) > cleanlist.append(node.cpv) > > unmerge(root_config, myopts, "unmerge", cleanlist, > ldpath_mtimes, ordered=ordered) > > if action == "prune": > return > > if not cleanlist and "--quiet" in myopts: > return > > print "Packages installed: "+str(len(vardb.cpv_all())) > print "Packages in world: " + \ > str(len(root_config.sets["world"].getAtoms())) > print "Packages in system: " + \ > str(len(root_config.sets["system"].getAtoms())) > print "Required packages: "+str(required_pkgs_total) > if "--pretend" in myopts: > print "Number to remove: "+str(len(cleanlist)) > else: > print "Number removed: "+str(len(cleanlist)) > >def action_deselect(settings, trees, opts, atoms): > root_config = trees[settings['ROOT']]['root_config'] > world_set = root_config.sets['world'] > if not hasattr(world_set, 'update'): > writemsg_level("World set does not appear to be mutable.\n", > level=logging.ERROR, noiselevel=-1) > return 1 > > vardb = root_config.trees['vartree'].dbapi > expanded_atoms = set(atoms) > from portage.dep import Atom > for atom in atoms: > for cpv in vardb.match(atom): > slot, = vardb.aux_get(cpv, ['SLOT']) > if not slot: > slot = '0' > expanded_atoms.add(Atom('%s:%s' % (portage.cpv_getkey(cpv), slot))) > > pretend = '--pretend' in opts > locked = False > if not pretend and hasattr(world_set, 'lock'): > world_set.lock() > locked = True > try: > discard_atoms = set() > world_set.load() > for atom in world_set: > if not isinstance(atom, Atom): > # nested set > continue > for arg_atom in expanded_atoms: > if arg_atom.intersects(atom) and \ > not (arg_atom.slot and not atom.slot): > discard_atoms.add(atom) > break > if discard_atoms: > for atom in sorted(discard_atoms): > print ">>> Removing %s from \"world\" favorites file..." % \ > colorize("INFORM", str(atom)) > > if '--ask' in opts: > prompt = "Would you like to remove these " + \ > "packages from your world favorites?" > if userquery(prompt) == 'No': > return os.EX_OK > > remaining = set(world_set) > remaining.difference_update(discard_atoms) > if not pretend: > world_set.replace(remaining) > else: > print ">>> No matching atoms found in \"world\" favorites file..." > finally: > if locked: > world_set.unlock() > return os.EX_OK > >def action_info(settings, trees, myopts, myfiles): > print getportageversion(settings["PORTDIR"], settings["ROOT"], > settings.profile_path, settings["CHOST"], > trees[settings["ROOT"]]["vartree"].dbapi) > header_width = 65 > header_title = "System Settings" > if myfiles: > print header_width * "=" > print header_title.rjust(int(header_width/2 + len(header_title)/2)) > print header_width * "=" > print "System uname: "+platform.platform(aliased=1) > > lastSync = portage.grabfile(os.path.join( > settings["PORTDIR"], "metadata", "timestamp.chk")) > print "Timestamp of tree:", > if lastSync: > print lastSync[0] > else: > print "Unknown" > > output=commands.getstatusoutput("distcc --version") > if not output[0]: > print str(output[1].split("\n",1)[0]), > if "distcc" in settings.features: > print "[enabled]" > else: > print "[disabled]" > > output=commands.getstatusoutput("ccache -V") > if not output[0]: > print str(output[1].split("\n",1)[0]), > if "ccache" in settings.features: > print "[enabled]" > else: > print "[disabled]" > > myvars = ["sys-devel/autoconf", "sys-devel/automake", "virtual/os-headers", > "sys-devel/binutils", "sys-devel/libtool", "dev-lang/python"] > myvars += portage.util.grabfile(settings["PORTDIR"]+"/profiles/info_pkgs") > myvars = portage.util.unique_array(myvars) > myvars.sort() > > for x in myvars: > if portage.isvalidatom(x): > pkg_matches = trees["/"]["vartree"].dbapi.match(x) > pkg_matches = [portage.catpkgsplit(cpv)[1:] for cpv in pkg_matches] > pkg_matches.sort(key=cmp_sort_key(portage.pkgcmp)) > pkgs = [] > for pn, ver, rev in pkg_matches: > if rev != "r0": > pkgs.append(ver + "-" + rev) > else: > pkgs.append(ver) > if pkgs: > pkgs = ", ".join(pkgs) > print "%-20s %s" % (x+":", pkgs) > else: > print "%-20s %s" % (x+":", "[NOT VALID]") > > libtool_vers = ",".join(trees["/"]["vartree"].dbapi.match("sys-devel/libtool")) > > if "--verbose" in myopts: > myvars=settings.keys() > else: > myvars = ['GENTOO_MIRRORS', 'CONFIG_PROTECT', 'CONFIG_PROTECT_MASK', > 'PORTDIR', 'DISTDIR', 'PKGDIR', 'PORTAGE_TMPDIR', > 'PORTDIR_OVERLAY', 'USE', 'CHOST', 'CFLAGS', 'CXXFLAGS', > 'ACCEPT_KEYWORDS', 'SYNC', 'FEATURES', 'EMERGE_DEFAULT_OPTS'] > > myvars.extend(portage.util.grabfile(settings["PORTDIR"]+"/profiles/info_vars")) > > myvars = portage.util.unique_array(myvars) > use_expand = settings.get('USE_EXPAND', '').split() > use_expand.sort() > use_expand_hidden = set( > settings.get('USE_EXPAND_HIDDEN', '').upper().split()) > alphabetical_use = '--alphabetical' in myopts > root_config = trees[settings["ROOT"]]['root_config'] > unset_vars = [] > myvars.sort() > for x in myvars: > if x in settings: > if x != "USE": > print '%s="%s"' % (x, settings[x]) > else: > use = set(settings["USE"].split()) > for varname in use_expand: > flag_prefix = varname.lower() + "_" > for f in list(use): > if f.startswith(flag_prefix): > use.remove(f) > use = list(use) > use.sort() > print 'USE="%s"' % " ".join(use), > for varname in use_expand: > myval = settings.get(varname) > if myval: > print '%s="%s"' % (varname, myval), > print > else: > unset_vars.append(x) > if unset_vars: > print "Unset: "+", ".join(unset_vars) > print > > if "--debug" in myopts: > for x in dir(portage): > module = getattr(portage, x) > if "cvs_id_string" in dir(module): > print "%s: %s" % (str(x), str(module.cvs_id_string)) > > # See if we can find any packages installed matching the strings > # passed on the command line > mypkgs = [] > vardb = trees[settings["ROOT"]]["vartree"].dbapi > portdb = trees[settings["ROOT"]]["porttree"].dbapi > for x in myfiles: > mypkgs.extend(vardb.match(x)) > > # If some packages were found... > if mypkgs: > # Get our global settings (we only print stuff if it varies from > # the current config) > mydesiredvars = [ 'CHOST', 'CFLAGS', 'CXXFLAGS', 'LDFLAGS' ] > auxkeys = mydesiredvars + list(vardb._aux_cache_keys) > auxkeys.append('DEFINED_PHASES') > global_vals = {} > pkgsettings = portage.config(clone=settings) > > # Loop through each package > # Only print settings if they differ from global settings > header_title = "Package Settings" > print header_width * "=" > print header_title.rjust(int(header_width/2 + len(header_title)/2)) > print header_width * "=" > from portage.output import EOutput > out = EOutput() > for cpv in mypkgs: > # Get all package specific variables > metadata = dict(izip(auxkeys, vardb.aux_get(cpv, auxkeys))) > pkg = Package(built=True, cpv=cpv, > installed=True, metadata=izip(Package.metadata_keys, > (metadata.get(x, '') for x in Package.metadata_keys)), > root_config=root_config, type_name='installed') > > print "\n%s was built with the following:" % \ > colorize("INFORM", str(pkg.cpv)) > > pkgsettings.setcpv(pkg) > forced_flags = set(chain(pkgsettings.useforce, > pkgsettings.usemask)) > use = set(pkg.use.enabled) > use.discard(pkgsettings.get('ARCH')) > use_expand_flags = set() > use_enabled = {} > use_disabled = {} > for varname in use_expand: > flag_prefix = varname.lower() + "_" > for f in use: > if f.startswith(flag_prefix): > use_expand_flags.add(f) > use_enabled.setdefault( > varname.upper(), []).append(f[len(flag_prefix):]) > > for f in pkg.iuse.all: > if f.startswith(flag_prefix): > use_expand_flags.add(f) > if f not in use: > use_disabled.setdefault( > varname.upper(), []).append(f[len(flag_prefix):]) > > var_order = set(use_enabled) > var_order.update(use_disabled) > var_order = sorted(var_order) > var_order.insert(0, 'USE') > use.difference_update(use_expand_flags) > use_enabled['USE'] = list(use) > use_disabled['USE'] = [] > > for f in pkg.iuse.all: > if f not in use and \ > f not in use_expand_flags: > use_disabled['USE'].append(f) > > for varname in var_order: > if varname in use_expand_hidden: > continue > flags = [] > for f in use_enabled.get(varname, []): > flags.append(UseFlagDisplay(f, True, f in forced_flags)) > for f in use_disabled.get(varname, []): > flags.append(UseFlagDisplay(f, False, f in forced_flags)) > if alphabetical_use: > flags.sort(key=UseFlagDisplay.sort_combined) > else: > flags.sort(key=UseFlagDisplay.sort_separated) > print '%s="%s"' % (varname, ' '.join(str(f) for f in flags)), > print > > for myvar in mydesiredvars: > if metadata[myvar].split() != settings.get(myvar, '').split(): > print "%s=\"%s\"" % (myvar, metadata[myvar]) > print > > if metadata['DEFINED_PHASES']: > if 'info' not in metadata['DEFINED_PHASES'].split(): > continue > > print ">>> Attempting to run pkg_info() for '%s'" % pkg.cpv > ebuildpath = vardb.findname(pkg.cpv) > if not ebuildpath or not os.path.exists(ebuildpath): > out.ewarn("No ebuild found for '%s'" % pkg.cpv) > continue > portage.doebuild(ebuildpath, "info", pkgsettings["ROOT"], > pkgsettings, debug=(settings.get("PORTAGE_DEBUG", "") == 1), > mydbapi=trees[settings["ROOT"]]["vartree"].dbapi, > tree="vartree") > >def action_metadata(settings, portdb, myopts, porttrees=None): > if porttrees is None: > porttrees = portdb.porttrees > portage.writemsg_stdout("\n>>> Updating Portage cache\n") > old_umask = os.umask(0002) > cachedir = os.path.normpath(settings.depcachedir) > if cachedir in ["/", "/bin", "/dev", "/etc", "/home", > "/lib", "/opt", "/proc", "/root", "/sbin", > "/sys", "/tmp", "/usr", "/var"]: > print >> sys.stderr, "!!! PORTAGE_DEPCACHEDIR IS SET TO A PRIMARY " + \ > "ROOT DIRECTORY ON YOUR SYSTEM." > print >> sys.stderr, \ > "!!! This is ALMOST CERTAINLY NOT what you want: '%s'" % cachedir > sys.exit(73) > if not os.path.exists(cachedir): > os.makedirs(cachedir) > > auxdbkeys = [x for x in portage.auxdbkeys if not x.startswith("UNUSED_0")] > auxdbkeys = tuple(auxdbkeys) > > class TreeData(object): > __slots__ = ('dest_db', 'eclass_db', 'path', 'src_db', 'valid_nodes') > def __init__(self, dest_db, eclass_db, path, src_db): > self.dest_db = dest_db > self.eclass_db = eclass_db > self.path = path > self.src_db = src_db > self.valid_nodes = set() > > porttrees_data = [] > for path in porttrees: > src_db = portdb._pregen_auxdb.get(path) > if src_db is None and \ > os.path.isdir(os.path.join(path, 'metadata', 'cache')): > src_db = portdb.metadbmodule( > path, 'metadata/cache', auxdbkeys, readonly=True) > try: > src_db.ec = portdb._repo_info[path].eclass_db > except AttributeError: > pass > > if src_db is not None: > porttrees_data.append(TreeData(portdb.auxdb[path], > portdb._repo_info[path].eclass_db, path, src_db)) > > porttrees = [tree_data.path for tree_data in porttrees_data] > > isatty = sys.stdout.isatty() > quiet = not isatty or '--quiet' in myopts > onProgress = None > if not quiet: > progressBar = portage.output.TermProgressBar() > progressHandler = ProgressHandler() > onProgress = progressHandler.onProgress > def display(): > progressBar.set(progressHandler.curval, progressHandler.maxval) > progressHandler.display = display > def sigwinch_handler(signum, frame): > lines, progressBar.term_columns = \ > portage.output.get_term_size() > signal.signal(signal.SIGWINCH, sigwinch_handler) > > # Temporarily override portdb.porttrees so portdb.cp_all() > # will only return the relevant subset. > portdb_porttrees = portdb.porttrees > portdb.porttrees = porttrees > try: > cp_all = portdb.cp_all() > finally: > portdb.porttrees = portdb_porttrees > > curval = 0 > maxval = len(cp_all) > if onProgress is not None: > onProgress(maxval, curval) > > from portage.cache.util import quiet_mirroring > from portage import eapi_is_supported, \ > _validate_cache_for_unsupported_eapis > > # TODO: Display error messages, but do not interfere with the progress bar. > # Here's how: > # 1) erase the progress bar > # 2) show the error message > # 3) redraw the progress bar on a new line > noise = quiet_mirroring() > > for cp in cp_all: > for tree_data in porttrees_data: > for cpv in portdb.cp_list(cp, mytree=tree_data.path): > tree_data.valid_nodes.add(cpv) > try: > src = tree_data.src_db[cpv] > except KeyError, e: > noise.missing_entry(cpv) > del e > continue > except CacheError, ce: > noise.exception(cpv, ce) > del ce > continue > > eapi = src.get('EAPI') > if not eapi: > eapi = '0' > eapi = eapi.lstrip('-') > eapi_supported = eapi_is_supported(eapi) > if not eapi_supported: > if not _validate_cache_for_unsupported_eapis: > noise.misc(cpv, "unable to validate " + \ > "cache for EAPI='%s'" % eapi) > continue > > dest = None > try: > dest = tree_data.dest_db[cpv] > except (KeyError, CacheError): > pass > > for d in (src, dest): > if d is not None and d.get('EAPI') in ('', '0'): > del d['EAPI'] > > if dest is not None: > if not (dest['_mtime_'] == src['_mtime_'] and \ > tree_data.eclass_db.is_eclass_data_valid( > dest['_eclasses_']) and \ > set(dest['_eclasses_']) == set(src['_eclasses_'])): > dest = None > else: > # We don't want to skip the write unless we're really > # sure that the existing cache is identical, so don't > # trust _mtime_ and _eclasses_ alone. > for k in set(chain(src, dest)).difference( > ('_mtime_', '_eclasses_')): > if dest.get(k, '') != src.get(k, ''): > dest = None > break > > if dest is not None: > # The existing data is valid and identical, > # so there's no need to overwrite it. > continue > > try: > inherited = src.get('INHERITED', '') > eclasses = src.get('_eclasses_') > except CacheError, ce: > noise.exception(cpv, ce) > del ce > continue > > if eclasses is not None: > if not tree_data.eclass_db.is_eclass_data_valid( > src['_eclasses_']): > noise.eclass_stale(cpv) > continue > inherited = eclasses > else: > inherited = inherited.split() > > if tree_data.src_db.complete_eclass_entries and \ > eclasses is None: > noise.corruption(cpv, "missing _eclasses_ field") > continue > > if inherited: > # Even if _eclasses_ already exists, replace it with data from > # eclass_cache, in order to insert local eclass paths. > try: > eclasses = tree_data.eclass_db.get_eclass_data(inherited) > except KeyError: > # INHERITED contains a non-existent eclass. > noise.eclass_stale(cpv) > continue > > if eclasses is None: > noise.eclass_stale(cpv) > continue > src['_eclasses_'] = eclasses > else: > src['_eclasses_'] = {} > > if not eapi_supported: > src = { > 'EAPI' : '-' + eapi, > '_mtime_' : src['_mtime_'], > '_eclasses_' : src['_eclasses_'], > } > > try: > tree_data.dest_db[cpv] = src > except CacheError, ce: > noise.exception(cpv, ce) > del ce > > curval += 1 > if onProgress is not None: > onProgress(maxval, curval) > > if onProgress is not None: > onProgress(maxval, curval) > > for tree_data in porttrees_data: > try: > dead_nodes = set(tree_data.dest_db.iterkeys()) > except CacheError, e: > writemsg_level("Error listing cache entries for " + \ > "'%s': %s, continuing...\n" % (tree_data.path, e), > level=logging.ERROR, noiselevel=-1) > del e > else: > dead_nodes.difference_update(tree_data.valid_nodes) > for cpv in dead_nodes: > try: > del tree_data.dest_db[cpv] > except (KeyError, CacheError): > pass > > if not quiet: > # make sure the final progress is displayed > progressHandler.display() > print > signal.signal(signal.SIGWINCH, signal.SIG_DFL) > > sys.stdout.flush() > os.umask(old_umask) > >def action_regen(settings, portdb, max_jobs, max_load): > xterm_titles = "notitles" not in settings.features > emergelog(xterm_titles, " === regen") > #regenerate cache entries > portage.writemsg_stdout("Regenerating cache entries...\n") > try: > os.close(sys.stdin.fileno()) > except SystemExit, e: > raise # Needed else can't exit > except: > pass > sys.stdout.flush() > > regen = MetadataRegen(portdb, max_jobs=max_jobs, max_load=max_load) > regen.run() > > portage.writemsg_stdout("done!\n") > return regen.returncode > >def action_search(root_config, myopts, myfiles, spinner): > if not myfiles: > print "emerge: no search terms provided." > else: > searchinstance = search(root_config, > spinner, "--searchdesc" in myopts, > "--quiet" not in myopts, "--usepkg" in myopts, > "--usepkgonly" in myopts) > for mysearch in myfiles: > try: > searchinstance.execute(mysearch) > except re.error, comment: > print "\n!!! Regular expression error in \"%s\": %s" % ( mysearch, comment ) > sys.exit(1) > searchinstance.output() > >def action_sync(settings, trees, mtimedb, myopts, myaction): > xterm_titles = "notitles" not in settings.features > emergelog(xterm_titles, " === sync") > portdb = trees[settings["ROOT"]]["porttree"].dbapi > myportdir = portdb.porttree_root > out = portage.output.EOutput() > if not myportdir: > sys.stderr.write("!!! PORTDIR is undefined. Is /etc/make.globals missing?\n") > sys.exit(1) > if myportdir[-1]=="/": > myportdir=myportdir[:-1] > try: > st = os.stat(myportdir) > except OSError: > st = None > if st is None: > print ">>>",myportdir,"not found, creating it." > os.makedirs(myportdir,0755) > st = os.stat(myportdir) > > spawn_kwargs = {} > spawn_kwargs["env"] = settings.environ() > if 'usersync' in settings.features and \ > portage.data.secpass >= 2 and \ > (st.st_uid != os.getuid() and st.st_mode & 0700 or \ > st.st_gid != os.getgid() and st.st_mode & 0070): > try: > homedir = pwd.getpwuid(st.st_uid).pw_dir > except KeyError: > pass > else: > # Drop privileges when syncing, in order to match > # existing uid/gid settings. > spawn_kwargs["uid"] = st.st_uid > spawn_kwargs["gid"] = st.st_gid > spawn_kwargs["groups"] = [st.st_gid] > spawn_kwargs["env"]["HOME"] = homedir > umask = 0002 > if not st.st_mode & 0020: > umask = umask | 0020 > spawn_kwargs["umask"] = umask > > syncuri = settings.get("SYNC", "").strip() > if not syncuri: > writemsg_level("!!! SYNC is undefined. Is /etc/make.globals missing?\n", > noiselevel=-1, level=logging.ERROR) > return 1 > > vcs_dirs = frozenset([".git", ".svn", "CVS", ".hg"]) > vcs_dirs = vcs_dirs.intersection(os.listdir(myportdir)) > > os.umask(0022) > dosyncuri = syncuri > updatecache_flg = False > if myaction == "metadata": > print "skipping sync" > updatecache_flg = True > elif ".git" in vcs_dirs: > # Update existing git repository, and ignore the syncuri. We are > # going to trust the user and assume that the user is in the branch > # that he/she wants updated. We'll let the user manage branches with > # git directly. > if portage.process.find_binary("git") is None: > msg = ["Command not found: git", > "Type \"emerge dev-util/git\" to enable git support."] > for l in msg: > writemsg_level("!!! %s\n" % l, > level=logging.ERROR, noiselevel=-1) > return 1 > msg = ">>> Starting git pull in %s..." % myportdir > emergelog(xterm_titles, msg ) > writemsg_level(msg + "\n") > exitcode = portage.process.spawn_bash("cd %s ; git pull" % \ > (portage._shell_quote(myportdir),), **spawn_kwargs) > if exitcode != os.EX_OK: > msg = "!!! git pull error in %s." % myportdir > emergelog(xterm_titles, msg) > writemsg_level(msg + "\n", level=logging.ERROR, noiselevel=-1) > return exitcode > msg = ">>> Git pull in %s successful" % myportdir > emergelog(xterm_titles, msg) > writemsg_level(msg + "\n") > exitcode = git_sync_timestamps(settings, myportdir) > if exitcode == os.EX_OK: > updatecache_flg = True > elif syncuri[:8]=="rsync://": > for vcs_dir in vcs_dirs: > writemsg_level(("!!! %s appears to be under revision " + \ > "control (contains %s).\n!!! Aborting rsync sync.\n") % \ > (myportdir, vcs_dir), level=logging.ERROR, noiselevel=-1) > return 1 > if not os.path.exists("/usr/bin/rsync"): > print "!!! /usr/bin/rsync does not exist, so rsync support is disabled." > print "!!! Type \"emerge net-misc/rsync\" to enable rsync support." > sys.exit(1) > mytimeout=180 > > rsync_opts = [] > if settings["PORTAGE_RSYNC_OPTS"] == "": > portage.writemsg("PORTAGE_RSYNC_OPTS empty or unset, using hardcoded defaults\n") > rsync_opts.extend([ > "--recursive", # Recurse directories > "--links", # Consider symlinks > "--safe-links", # Ignore links outside of tree > "--perms", # Preserve permissions > "--times", # Preserive mod times > "--compress", # Compress the data transmitted > "--force", # Force deletion on non-empty dirs > "--whole-file", # Don't do block transfers, only entire files > "--delete", # Delete files that aren't in the master tree > "--stats", # Show final statistics about what was transfered > "--timeout="+str(mytimeout), # IO timeout if not done in X seconds > "--exclude=/distfiles", # Exclude distfiles from consideration > "--exclude=/local", # Exclude local from consideration > "--exclude=/packages", # Exclude packages from consideration > ]) > > else: > # The below validation is not needed when using the above hardcoded > # defaults. > > portage.writemsg("Using PORTAGE_RSYNC_OPTS instead of hardcoded defaults\n", 1) > rsync_opts.extend( > shlex.split(settings.get("PORTAGE_RSYNC_OPTS",""))) > for opt in ("--recursive", "--times"): > if opt not in rsync_opts: > portage.writemsg(yellow("WARNING:") + " adding required option " + \ > "%s not included in PORTAGE_RSYNC_OPTS\n" % opt) > rsync_opts.append(opt) > > for exclude in ("distfiles", "local", "packages"): > opt = "--exclude=/%s" % exclude > if opt not in rsync_opts: > portage.writemsg(yellow("WARNING:") + \ > " adding required option %s not included in " % opt + \ > "PORTAGE_RSYNC_OPTS (can be overridden with --exclude='!')\n") > rsync_opts.append(opt) > > if syncuri.rstrip("/").endswith(".gentoo.org/gentoo-portage"): > def rsync_opt_startswith(opt_prefix): > for x in rsync_opts: > if x.startswith(opt_prefix): > return True > return False > > if not rsync_opt_startswith("--timeout="): > rsync_opts.append("--timeout=%d" % mytimeout) > > for opt in ("--compress", "--whole-file"): > if opt not in rsync_opts: > portage.writemsg(yellow("WARNING:") + " adding required option " + \ > "%s not included in PORTAGE_RSYNC_OPTS\n" % opt) > rsync_opts.append(opt) > > if "--quiet" in myopts: > rsync_opts.append("--quiet") # Shut up a lot > else: > rsync_opts.append("--verbose") # Print filelist > > if "--verbose" in myopts: > rsync_opts.append("--progress") # Progress meter for each file > > if "--debug" in myopts: > rsync_opts.append("--checksum") # Force checksum on all files > > # Real local timestamp file. > servertimestampfile = os.path.join( > myportdir, "metadata", "timestamp.chk") > > content = portage.util.grabfile(servertimestampfile) > mytimestamp = 0 > if content: > try: > mytimestamp = time.mktime(time.strptime(content[0], > "%a, %d %b %Y %H:%M:%S +0000")) > except (OverflowError, ValueError): > pass > del content > > try: > rsync_initial_timeout = \ > int(settings.get("PORTAGE_RSYNC_INITIAL_TIMEOUT", "15")) > except ValueError: > rsync_initial_timeout = 15 > > try: > maxretries=int(settings["PORTAGE_RSYNC_RETRIES"]) > except SystemExit, e: > raise # Needed else can't exit > except: > maxretries=3 #default number of retries > > retries=0 > user_name, hostname, port = re.split( > "rsync://([^:/]+@)?([^:/]*)(:[0-9]+)?", syncuri, maxsplit=3)[1:4] > if port is None: > port="" > if user_name is None: > user_name="" > updatecache_flg=True > all_rsync_opts = set(rsync_opts) > extra_rsync_opts = shlex.split( > settings.get("PORTAGE_RSYNC_EXTRA_OPTS","")) > all_rsync_opts.update(extra_rsync_opts) > family = socket.AF_INET > if "-4" in all_rsync_opts or "--ipv4" in all_rsync_opts: > family = socket.AF_INET > elif socket.has_ipv6 and \ > ("-6" in all_rsync_opts or "--ipv6" in all_rsync_opts): > family = socket.AF_INET6 > ips=[] > SERVER_OUT_OF_DATE = -1 > EXCEEDED_MAX_RETRIES = -2 > while (1): > if ips: > del ips[0] > if ips==[]: > try: > for addrinfo in socket.getaddrinfo( > hostname, None, family, socket.SOCK_STREAM): > if socket.has_ipv6 and addrinfo[0] == socket.AF_INET6: > # IPv6 addresses need to be enclosed in square brackets > ips.append("[%s]" % addrinfo[4][0]) > else: > ips.append(addrinfo[4][0]) > from random import shuffle > shuffle(ips) > except SystemExit, e: > raise # Needed else can't exit > except Exception, e: > print "Notice:",str(e) > dosyncuri=syncuri > > if ips: > try: > dosyncuri = syncuri.replace( > "//" + user_name + hostname + port + "/", > "//" + user_name + ips[0] + port + "/", 1) > except SystemExit, e: > raise # Needed else can't exit > except Exception, e: > print "Notice:",str(e) > dosyncuri=syncuri > > if (retries==0): > if "--ask" in myopts: > if userquery("Do you want to sync your Portage tree with the mirror at\n" + blue(dosyncuri) + bold("?"))=="No": > print > print "Quitting." > print > sys.exit(0) > emergelog(xterm_titles, ">>> Starting rsync with " + dosyncuri) > if "--quiet" not in myopts: > print ">>> Starting rsync with "+dosyncuri+"..." > else: > emergelog(xterm_titles, > ">>> Starting retry %d of %d with %s" % \ > (retries,maxretries,dosyncuri)) > print "\n\n>>> Starting retry %d of %d with %s" % (retries,maxretries,dosyncuri) > > if mytimestamp != 0 and "--quiet" not in myopts: > print ">>> Checking server timestamp ..." > > rsynccommand = ["/usr/bin/rsync"] + rsync_opts + extra_rsync_opts > > if "--debug" in myopts: > print rsynccommand > > exitcode = os.EX_OK > servertimestamp = 0 > # Even if there's no timestamp available locally, fetch the > # timestamp anyway as an initial probe to verify that the server is > # responsive. This protects us from hanging indefinitely on a > # connection attempt to an unresponsive server which rsync's > # --timeout option does not prevent. > if True: > # Temporary file for remote server timestamp comparison. > from tempfile import mkstemp > fd, tmpservertimestampfile = mkstemp() > os.close(fd) > mycommand = rsynccommand[:] > mycommand.append(dosyncuri.rstrip("/") + \ > "/metadata/timestamp.chk") > mycommand.append(tmpservertimestampfile) > content = None > mypids = [] > try: > def timeout_handler(signum, frame): > raise portage.exception.PortageException("timed out") > signal.signal(signal.SIGALRM, timeout_handler) > # Timeout here in case the server is unresponsive. The > # --timeout rsync option doesn't apply to the initial > # connection attempt. > if rsync_initial_timeout: > signal.alarm(rsync_initial_timeout) > try: > mypids.extend(portage.process.spawn( > mycommand, env=settings.environ(), returnpid=True)) > exitcode = os.waitpid(mypids[0], 0)[1] > content = portage.grabfile(tmpservertimestampfile) > finally: > if rsync_initial_timeout: > signal.alarm(0) > try: > os.unlink(tmpservertimestampfile) > except OSError: > pass > except portage.exception.PortageException, e: > # timed out > print e > del e > if mypids and os.waitpid(mypids[0], os.WNOHANG) == (0,0): > os.kill(mypids[0], signal.SIGTERM) > os.waitpid(mypids[0], 0) > # This is the same code rsync uses for timeout. > exitcode = 30 > else: > if exitcode != os.EX_OK: > if exitcode & 0xff: > exitcode = (exitcode & 0xff) << 8 > else: > exitcode = exitcode >> 8 > if mypids: > portage.process.spawned_pids.remove(mypids[0]) > if content: > try: > servertimestamp = time.mktime(time.strptime( > content[0], "%a, %d %b %Y %H:%M:%S +0000")) > except (OverflowError, ValueError): > pass > del mycommand, mypids, content > if exitcode == os.EX_OK: > if (servertimestamp != 0) and (servertimestamp == mytimestamp): > emergelog(xterm_titles, > ">>> Cancelling sync -- Already current.") > print > print ">>>" > print ">>> Timestamps on the server and in the local repository are the same." > print ">>> Cancelling all further sync action. You are already up to date." > print ">>>" > print ">>> In order to force sync, remove '%s'." % servertimestampfile > print ">>>" > print > sys.exit(0) > elif (servertimestamp != 0) and (servertimestamp < mytimestamp): > emergelog(xterm_titles, > ">>> Server out of date: %s" % dosyncuri) > print > print ">>>" > print ">>> SERVER OUT OF DATE: %s" % dosyncuri > print ">>>" > print ">>> In order to force sync, remove '%s'." % servertimestampfile > print ">>>" > print > exitcode = SERVER_OUT_OF_DATE > elif (servertimestamp == 0) or (servertimestamp > mytimestamp): > # actual sync > mycommand = rsynccommand + [dosyncuri+"/", myportdir] > exitcode = portage.process.spawn(mycommand, **spawn_kwargs) > if exitcode in [0,1,3,4,11,14,20,21]: > break > elif exitcode in [1,3,4,11,14,20,21]: > break > else: > # Code 2 indicates protocol incompatibility, which is expected > # for servers with protocol < 29 that don't support > # --prune-empty-directories. Retry for a server that supports > # at least rsync protocol version 29 (>=rsync-2.6.4). > pass > > retries=retries+1 > > if retries<=maxretries: > print ">>> Retrying..." > time.sleep(11) > else: > # over retries > # exit loop > updatecache_flg=False > exitcode = EXCEEDED_MAX_RETRIES > break > > if (exitcode==0): > emergelog(xterm_titles, "=== Sync completed with %s" % dosyncuri) > elif exitcode == SERVER_OUT_OF_DATE: > sys.exit(1) > elif exitcode == EXCEEDED_MAX_RETRIES: > sys.stderr.write( > ">>> Exceeded PORTAGE_RSYNC_RETRIES: %s\n" % maxretries) > sys.exit(1) > elif (exitcode>0): > msg = [] > if exitcode==1: > msg.append("Rsync has reported that there is a syntax error. Please ensure") > msg.append("that your SYNC statement is proper.") > msg.append("SYNC=" + settings["SYNC"]) > elif exitcode==11: > msg.append("Rsync has reported that there is a File IO error. Normally") > msg.append("this means your disk is full, but can be caused by corruption") > msg.append("on the filesystem that contains PORTDIR. Please investigate") > msg.append("and try again after the problem has been fixed.") > msg.append("PORTDIR=" + settings["PORTDIR"]) > elif exitcode==20: > msg.append("Rsync was killed before it finished.") > else: > msg.append("Rsync has not successfully finished. It is recommended that you keep") > msg.append("trying or that you use the 'emerge-webrsync' option if you are unable") > msg.append("to use rsync due to firewall or other restrictions. This should be a") > msg.append("temporary problem unless complications exist with your network") > msg.append("(and possibly your system's filesystem) configuration.") > for line in msg: > out.eerror(line) > sys.exit(exitcode) > elif syncuri[:6]=="cvs://": > if not os.path.exists("/usr/bin/cvs"): > print "!!! /usr/bin/cvs does not exist, so CVS support is disabled." > print "!!! Type \"emerge dev-util/cvs\" to enable CVS support." > sys.exit(1) > cvsroot=syncuri[6:] > cvsdir=os.path.dirname(myportdir) > if not os.path.exists(myportdir+"/CVS"): > #initial checkout > print ">>> Starting initial cvs checkout with "+syncuri+"..." > if os.path.exists(cvsdir+"/gentoo-x86"): > print "!!! existing",cvsdir+"/gentoo-x86 directory; exiting." > sys.exit(1) > try: > os.rmdir(myportdir) > except OSError, e: > if e.errno != errno.ENOENT: > sys.stderr.write( > "!!! existing '%s' directory; exiting.\n" % myportdir) > sys.exit(1) > del e > if portage.spawn("cd "+cvsdir+"; cvs -z0 -d "+cvsroot+" co -P gentoo-x86",settings,free=1): > print "!!! cvs checkout error; exiting." > sys.exit(1) > os.rename(os.path.join(cvsdir, "gentoo-x86"), myportdir) > else: > #cvs update > print ">>> Starting cvs update with "+syncuri+"..." > retval = portage.process.spawn_bash( > "cd %s; cvs -z0 -q update -dP" % \ > (portage._shell_quote(myportdir),), **spawn_kwargs) > if retval != os.EX_OK: > sys.exit(retval) > dosyncuri = syncuri > else: > writemsg_level("!!! Unrecognized protocol: SYNC='%s'\n" % (syncuri,), > noiselevel=-1, level=logging.ERROR) > return 1 > > if updatecache_flg and \ > myaction != "metadata" and \ > "metadata-transfer" not in settings.features: > updatecache_flg = False > > # Reload the whole config from scratch. > settings, trees, mtimedb = load_emerge_config(trees=trees) > root_config = trees[settings["ROOT"]]["root_config"] > portdb = trees[settings["ROOT"]]["porttree"].dbapi > > if updatecache_flg and \ > os.path.exists(os.path.join(myportdir, 'metadata', 'cache')): > > # Only update cache for myportdir since that's > # the only one that's been synced here. > action_metadata(settings, portdb, myopts, porttrees=[myportdir]) > > 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 > root_config = trees[settings["ROOT"]]["root_config"] > > mybestpv = portdb.xmatch("bestmatch-visible", > portage.const.PORTAGE_PACKAGE_ATOM) > mypvs = portage.best( > trees[settings["ROOT"]]["vartree"].dbapi.match( > portage.const.PORTAGE_PACKAGE_ATOM)) > > chk_updated_cfg_files("/", settings.get("CONFIG_PROTECT","").split()) > > if myaction != "metadata": > if os.access(portage.USER_CONFIG_PATH + "/bin/post_sync", os.X_OK): > retval = portage.process.spawn( > [os.path.join(portage.USER_CONFIG_PATH, "bin", "post_sync"), > dosyncuri], env=settings.environ()) > if retval != os.EX_OK: > print red(" * ")+bold("spawn failed of "+ portage.USER_CONFIG_PATH + "/bin/post_sync") > > if(mybestpv != mypvs) and not "--quiet" in myopts: > print > print red(" * ")+bold("An update to portage is available.")+" It is _highly_ recommended" > print red(" * ")+"that you update portage now, before any other packages are updated." > print > print red(" * ")+"To update portage, run 'emerge portage' now." > print > > display_news_notification(root_config, myopts) > return os.EX_OK > >def action_uninstall(settings, trees, ldpath_mtimes, > opts, action, files, spinner): > > # For backward compat, some actions do not require leading '='. > ignore_missing_eq = action in ('clean', 'unmerge') > root = settings['ROOT'] > vardb = trees[root]['vartree'].dbapi > valid_atoms = [] > lookup_owners = [] > > # Ensure atoms are valid before calling unmerge(). > # For backward compat, leading '=' is not required. > for x in files: > if is_valid_package_atom(x) or \ > (ignore_missing_eq and 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 > > elif x.startswith(os.sep): > if not x.startswith(root): > writemsg_level(("!!! '%s' does not start with" + \ > " $ROOT.\n") % x, level=logging.ERROR, noiselevel=-1) > return 1 > # Queue these up since it's most efficient to handle > # multiple files in a single iter_owners() call. > lookup_owners.append(x) > > else: > 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 lookup_owners: > relative_paths = [] > search_for_multiple = False > if len(lookup_owners) > 1: > search_for_multiple = True > > for x in lookup_owners: > if not search_for_multiple and os.path.isdir(x): > search_for_multiple = True > relative_paths.append(x[len(root):]) > > owners = set() > for pkg, relative_path in \ > vardb._owners.iter_owners(relative_paths): > owners.add(pkg.mycpv) > if not search_for_multiple: > break > > if owners: > for cpv in owners: > slot = vardb.aux_get(cpv, ['SLOT'])[0] > if not slot: > # portage now masks packages with missing slot, but it's > # possible that one was installed by an older version > atom = portage.cpv_getkey(cpv) > else: > atom = '%s:%s' % (portage.cpv_getkey(cpv), slot) > valid_atoms.append(portage.dep.Atom(atom)) > else: > writemsg_level(("!!! '%s' is not claimed " + \ > "by any package.\n") % lookup_owners[0], > level=logging.WARNING, noiselevel=-1) > > if files and not valid_atoms: > return 1 > > if action in ('clean', 'unmerge') or \ > (action == 'prune' and "--nodeps" in opts): > # When given a list of atoms, unmerge them in the order given. > ordered = action == 'unmerge' > unmerge(trees[settings["ROOT"]]['root_config'], opts, action, > valid_atoms, ldpath_mtimes, ordered=ordered) > rval = os.EX_OK > elif action == 'deselect': > rval = action_deselect(settings, trees, opts, valid_atoms) > else: > rval = action_depclean(settings, trees, ldpath_mtimes, > opts, action, valid_atoms, spinner) > > return rval > >def adjust_config(myopts, settings): > """Make emerge specific adjustments to the config.""" > > # To enhance usability, make some vars case insensitive by forcing them to > # lower case. > for myvar in ("AUTOCLEAN", "NOCOLOR"): > if myvar in settings: > settings[myvar] = settings[myvar].lower() > settings.backup_changes(myvar) > del myvar > > # Kill noauto as it will break merges otherwise. > if "noauto" in settings.features: > settings.features.remove('noauto') > settings['FEATURES'] = ' '.join(sorted(settings.features)) > settings.backup_changes("FEATURES") > > CLEAN_DELAY = 5 > try: > CLEAN_DELAY = int(settings.get("CLEAN_DELAY", str(CLEAN_DELAY))) > except ValueError, e: > portage.writemsg("!!! %s\n" % str(e), noiselevel=-1) > portage.writemsg("!!! Unable to parse integer: CLEAN_DELAY='%s'\n" % \ > settings["CLEAN_DELAY"], noiselevel=-1) > settings["CLEAN_DELAY"] = str(CLEAN_DELAY) > settings.backup_changes("CLEAN_DELAY") > > EMERGE_WARNING_DELAY = 10 > try: > EMERGE_WARNING_DELAY = int(settings.get( > "EMERGE_WARNING_DELAY", str(EMERGE_WARNING_DELAY))) > except ValueError, e: > portage.writemsg("!!! %s\n" % str(e), noiselevel=-1) > portage.writemsg("!!! Unable to parse integer: EMERGE_WARNING_DELAY='%s'\n" % \ > settings["EMERGE_WARNING_DELAY"], noiselevel=-1) > settings["EMERGE_WARNING_DELAY"] = str(EMERGE_WARNING_DELAY) > settings.backup_changes("EMERGE_WARNING_DELAY") > > if "--quiet" in myopts: > settings["PORTAGE_QUIET"]="1" > settings.backup_changes("PORTAGE_QUIET") > > if "--verbose" in myopts: > settings["PORTAGE_VERBOSE"] = "1" > settings.backup_changes("PORTAGE_VERBOSE") > > # Set so that configs will be merged regardless of remembered status > if ("--noconfmem" in myopts): > settings["NOCONFMEM"]="1" > settings.backup_changes("NOCONFMEM") > > # Set various debug markers... They should be merged somehow. > PORTAGE_DEBUG = 0 > try: > PORTAGE_DEBUG = int(settings.get("PORTAGE_DEBUG", str(PORTAGE_DEBUG))) > if PORTAGE_DEBUG not in (0, 1): > portage.writemsg("!!! Invalid value: PORTAGE_DEBUG='%i'\n" % \ > PORTAGE_DEBUG, noiselevel=-1) > portage.writemsg("!!! PORTAGE_DEBUG must be either 0 or 1\n", > noiselevel=-1) > PORTAGE_DEBUG = 0 > except ValueError, e: > portage.writemsg("!!! %s\n" % str(e), noiselevel=-1) > portage.writemsg("!!! Unable to parse integer: PORTAGE_DEBUG='%s'\n" %\ > settings["PORTAGE_DEBUG"], noiselevel=-1) > del e > if "--debug" in myopts: > PORTAGE_DEBUG = 1 > settings["PORTAGE_DEBUG"] = str(PORTAGE_DEBUG) > settings.backup_changes("PORTAGE_DEBUG") > > if settings.get("NOCOLOR") not in ("yes","true"): > portage.output.havecolor = 1 > > """The explicit --color < y | n > option overrides the NOCOLOR environment > variable and stdout auto-detection.""" > if "--color" in myopts: > if "y" == myopts["--color"]: > portage.output.havecolor = 1 > settings["NOCOLOR"] = "false" > else: > portage.output.havecolor = 0 > settings["NOCOLOR"] = "true" > settings.backup_changes("NOCOLOR") > elif not sys.stdout.isatty() and settings.get("NOCOLOR") != "no": > portage.output.havecolor = 0 > settings["NOCOLOR"] = "true" > settings.backup_changes("NOCOLOR") > >def display_missing_pkg_set(root_config, set_name): > > msg = [] > msg.append(("emerge: There are no sets to satisfy '%s'. " + \ > "The following sets exist:") % \ > colorize("INFORM", set_name)) > msg.append("") > > for s in sorted(root_config.sets): > msg.append(" %s" % s) > msg.append("") > > writemsg_level("".join("%s\n" % l for l in msg), > level=logging.ERROR, noiselevel=-1) > >def getportageversion(portdir, target_root, profile, chost, vardb): > profilever = "unavailable" > if profile: > realpath = os.path.realpath(profile) > basepath = os.path.realpath(os.path.join(portdir, "profiles")) > if realpath.startswith(basepath): > profilever = realpath[1 + len(basepath):] > else: > try: > profilever = "!" + os.readlink(profile) > except (OSError): > pass > del realpath, basepath > > libcver=[] > libclist = vardb.match("virtual/libc") > libclist += vardb.match("virtual/glibc") > libclist = portage.util.unique_array(libclist) > for x in libclist: > xs=portage.catpkgsplit(x) > if libcver: > libcver+=","+"-".join(xs[1:]) > else: > libcver="-".join(xs[1:]) > if libcver==[]: > libcver="unavailable" > > gccver = getgccversion(chost) > unameout=platform.release()+" "+platform.machine() > > return "Portage " + portage.VERSION +" ("+profilever+", "+gccver+", "+libcver+", "+unameout+")" > >def git_sync_timestamps(settings, portdir): > """ > Since git doesn't preserve timestamps, synchronize timestamps between > entries and ebuilds/eclasses. Assume the cache has the correct timestamp > for a given file as long as the file in the working tree is not modified > (relative to HEAD). > """ > cache_dir = os.path.join(portdir, "metadata", "cache") > if not os.path.isdir(cache_dir): > return os.EX_OK > writemsg_level(">>> Synchronizing timestamps...\n") > > from portage.cache.cache_errors import CacheError > try: > cache_db = settings.load_best_module("portdbapi.metadbmodule")( > portdir, "metadata/cache", portage.auxdbkeys[:], readonly=True) > except CacheError, e: > writemsg_level("!!! Unable to instantiate cache: %s\n" % (e,), > level=logging.ERROR, noiselevel=-1) > return 1 > > ec_dir = os.path.join(portdir, "eclass") > try: > ec_names = set(f[:-7] for f in os.listdir(ec_dir) \ > if f.endswith(".eclass")) > except OSError, e: > writemsg_level("!!! Unable to list eclasses: %s\n" % (e,), > level=logging.ERROR, noiselevel=-1) > return 1 > > args = [portage.const.BASH_BINARY, "-c", > "cd %s && git diff-index --name-only --diff-filter=M HEAD" % \ > portage._shell_quote(portdir)] > import subprocess > proc = subprocess.Popen(args, stdout=subprocess.PIPE) > modified_files = set(l.rstrip("\n") for l in proc.stdout) > rval = proc.wait() > if rval != os.EX_OK: > return rval > > modified_eclasses = set(ec for ec in ec_names \ > if os.path.join("eclass", ec + ".eclass") in modified_files) > > updated_ec_mtimes = {} > > for cpv in cache_db: > cpv_split = portage.catpkgsplit(cpv) > if cpv_split is None: > writemsg_level("!!! Invalid cache entry: %s\n" % (cpv,), > level=logging.ERROR, noiselevel=-1) > continue > > cat, pn, ver, rev = cpv_split > cat, pf = portage.catsplit(cpv) > relative_eb_path = os.path.join(cat, pn, pf + ".ebuild") > if relative_eb_path in modified_files: > continue > > try: > cache_entry = cache_db[cpv] > eb_mtime = cache_entry.get("_mtime_") > ec_mtimes = cache_entry.get("_eclasses_") > except KeyError: > writemsg_level("!!! Missing cache entry: %s\n" % (cpv,), > level=logging.ERROR, noiselevel=-1) > continue > except CacheError, e: > writemsg_level("!!! Unable to access cache entry: %s %s\n" % \ > (cpv, e), level=logging.ERROR, noiselevel=-1) > continue > > if eb_mtime is None: > writemsg_level("!!! Missing ebuild mtime: %s\n" % (cpv,), > level=logging.ERROR, noiselevel=-1) > continue > > try: > eb_mtime = long(eb_mtime) > except ValueError: > writemsg_level("!!! Invalid ebuild mtime: %s %s\n" % \ > (cpv, eb_mtime), level=logging.ERROR, noiselevel=-1) > continue > > if ec_mtimes is None: > writemsg_level("!!! Missing eclass mtimes: %s\n" % (cpv,), > level=logging.ERROR, noiselevel=-1) > continue > > if modified_eclasses.intersection(ec_mtimes): > continue > > missing_eclasses = set(ec_mtimes).difference(ec_names) > if missing_eclasses: > writemsg_level("!!! Non-existent eclass(es): %s %s\n" % \ > (cpv, sorted(missing_eclasses)), level=logging.ERROR, > noiselevel=-1) > continue > > eb_path = os.path.join(portdir, relative_eb_path) > try: > current_eb_mtime = os.stat(eb_path) > except OSError: > writemsg_level("!!! Missing ebuild: %s\n" % \ > (cpv,), level=logging.ERROR, noiselevel=-1) > continue > > inconsistent = False > for ec, (ec_path, ec_mtime) in ec_mtimes.iteritems(): > updated_mtime = updated_ec_mtimes.get(ec) > if updated_mtime is not None and updated_mtime != ec_mtime: > writemsg_level("!!! Inconsistent eclass mtime: %s %s\n" % \ > (cpv, ec), level=logging.ERROR, noiselevel=-1) > inconsistent = True > break > > if inconsistent: > continue > > if current_eb_mtime != eb_mtime: > os.utime(eb_path, (eb_mtime, eb_mtime)) > > for ec, (ec_path, ec_mtime) in ec_mtimes.iteritems(): > if ec in updated_ec_mtimes: > continue > ec_path = os.path.join(ec_dir, ec + ".eclass") > current_mtime = long(os.stat(ec_path).st_mtime) > if current_mtime != ec_mtime: > os.utime(ec_path, (ec_mtime, ec_mtime)) > updated_ec_mtimes[ec] = ec_mtime > > return os.EX_OK > >def load_emerge_config(trees=None): > kwargs = {} > for k, envvar in (("config_root", "PORTAGE_CONFIGROOT"), ("target_root", "ROOT")): > v = os.environ.get(envvar, None) > if v and v.strip(): > kwargs[k] = v > trees = portage.create_trees(trees=trees, **kwargs) > > for root, root_trees in trees.iteritems(): > settings = root_trees["vartree"].settings > setconfig = load_default_config(settings, root_trees) > root_trees["root_config"] = RootConfig(settings, root_trees, setconfig) > > settings = trees["/"]["vartree"].settings > > for myroot in trees: > if myroot != "/": > settings = trees[myroot]["vartree"].settings > break > > mtimedbfile = os.path.join("/", portage.CACHE_PATH.lstrip(os.path.sep), "mtimedb") > mtimedb = portage.MtimeDB(mtimedbfile) > > return settings, trees, mtimedb > >def chk_updated_cfg_files(target_root, config_protect): > if config_protect: > #number of directories with some protect files in them > procount=0 > for x in config_protect: > x = os.path.join(target_root, x.lstrip(os.path.sep)) > if not os.access(x, os.W_OK): > # Avoid Permission denied errors generated > # later by `find`. > continue > try: > mymode = os.lstat(x).st_mode > except OSError: > continue > if stat.S_ISLNK(mymode): > # We want to treat it like a directory if it > # is a symlink to an existing directory. > try: > real_mode = os.stat(x).st_mode > if stat.S_ISDIR(real_mode): > mymode = real_mode > except OSError: > pass > if stat.S_ISDIR(mymode): > mycommand = "find '%s' -name '.*' -type d -prune -o -name '._cfg????_*'" % x > else: > mycommand = "find '%s' -maxdepth 1 -name '._cfg????_%s'" % \ > os.path.split(x.rstrip(os.path.sep)) > mycommand += " ! -name '.*~' ! -iname '.*.bak' -print0" > a = commands.getstatusoutput(mycommand) > if a[0] != 0: > sys.stderr.write(" %s error scanning '%s': " % (bad("*"), x)) > sys.stderr.flush() > # Show the error message alone, sending stdout to /dev/null. > os.system(mycommand + " 1>/dev/null") > else: > files = a[1].split('\0') > # split always produces an empty string as the last element > if files and not files[-1]: > del files[-1] > if files: > procount += 1 > print "\n"+colorize("WARN", " * IMPORTANT:"), > if stat.S_ISDIR(mymode): > print "%d config files in '%s' need updating." % \ > (len(files), x) > else: > print "config file '%s' needs updating." % x > > if procount: > print " "+yellow("*")+" See the "+colorize("INFORM","CONFIGURATION FILES")+ \ > " section of the " + bold("emerge") > print " "+yellow("*")+" man page to learn how to update config files." > >def display_news_notification(root_config, myopts): > target_root = root_config.root > trees = root_config.trees > settings = trees["vartree"].settings > portdb = trees["porttree"].dbapi > vardb = trees["vartree"].dbapi > NEWS_PATH = os.path.join("metadata", "news") > UNREAD_PATH = os.path.join(target_root, NEWS_LIB_PATH, "news") > newsReaderDisplay = False > update = "--pretend" not in myopts > > for repo in portdb.getRepositories(): > unreadItems = checkUpdatedNewsItems( > portdb, vardb, NEWS_PATH, UNREAD_PATH, repo, update=update) > if unreadItems: > if not newsReaderDisplay: > newsReaderDisplay = True > print > print colorize("WARN", " * IMPORTANT:"), > print "%s news items need reading for repository '%s'." % (unreadItems, repo) > > > if newsReaderDisplay: > print colorize("WARN", " *"), > print "Use " + colorize("GOOD", "eselect news") + " to read news items." > print > >def getgccversion(chost): > """ > rtype: C{str} > return: the current in-use gcc version > """ > > gcc_ver_command = 'gcc -dumpversion' > gcc_ver_prefix = 'gcc-' > > gcc_not_found_error = red( > "!!! No gcc found. You probably need to 'source /etc/profile'\n" + > "!!! to update the environment of this terminal and possibly\n" + > "!!! other terminals also.\n" > ) > > mystatus, myoutput = commands.getstatusoutput("gcc-config -c") > if mystatus == os.EX_OK and myoutput.startswith(chost + "-"): > return myoutput.replace(chost + "-", gcc_ver_prefix, 1) > > mystatus, myoutput = commands.getstatusoutput( > chost + "-" + gcc_ver_command) > if mystatus == os.EX_OK: > return gcc_ver_prefix + myoutput > > mystatus, myoutput = commands.getstatusoutput(gcc_ver_command) > if mystatus == os.EX_OK: > return gcc_ver_prefix + myoutput > > portage.writemsg(gcc_not_found_error, noiselevel=-1) > return "[unavailable]" > >def checkUpdatedNewsItems(portdb, vardb, NEWS_PATH, UNREAD_PATH, repo_id, > update=False): > """ > Examines news items in repodir + '/' + NEWS_PATH and attempts to find unread items > Returns the number of unread (yet relevent) items. > > @param portdb: a portage tree database > @type portdb: pordbapi > @param vardb: an installed package database > @type vardb: vardbapi > @param NEWS_PATH: > @type NEWS_PATH: > @param UNREAD_PATH: > @type UNREAD_PATH: > @param repo_id: > @type repo_id: > @rtype: Integer > @returns: > 1. The number of unread but relevant news items. > > """ > from portage.news import NewsManager > manager = NewsManager(portdb, vardb, NEWS_PATH, UNREAD_PATH) > return manager.getUnreadItems( repo_id, update=update ) >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 275047
:
195438
|
195483
|
195492
|
195498
|
195530
|
195537
| 195538