X-Git-Url: http://git.tremily.us/?a=blobdiff_plain;f=bin%2Femaint;h=c5415c3e3e2418533c018d70d28794f273d225d2;hb=08cd954a46def397ca7aa62e5f738cd2fa77a228;hp=0e9ba853d8f770d037935886065b84e45eda92c3;hpb=02417974e952f0c26e1a1c24ec42204be22bc1a2;p=portage.git diff --git a/bin/emaint b/bin/emaint index 0e9ba853d..c5415c3e3 100755 --- a/bin/emaint +++ b/bin/emaint @@ -1,207 +1,42 @@ -#!/usr/bin/python -O +#!/usr/bin/python -bbO +# Copyright 2005-2014 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 -import sys, os -from optparse import OptionParser, OptionValueError -if not hasattr(__builtins__, "set"): - from sets import Set as set -import re -try: - import portage -except ImportError: - from os import path as osp - sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym")) - import portage - -import portage.const, portage.exception -class WorldHandler(object): - - def name(): - return "world" - name = staticmethod(name) - - def __init__(self): - self.invalid = [] - self.not_installed = [] - self.invalid_category = [] - self.okay = [] - self.world_file = os.path.join("/", portage.const.WORLD_FILE) - self.found = os.access(self.world_file, os.R_OK) - - def _check_world(self, onProgress): - categories = set(portage.settings.categories) - myroot = portage.settings["ROOT"] - vardb = portage.db[myroot]["vartree"].dbapi - - world_atoms = open(self.world_file).read().split() - maxval = len(world_atoms) - if onProgress: - onProgress(maxval, 0) - for i, atom in enumerate(world_atoms): - if not portage.isvalidatom(atom): - self.invalid.append(atom) - if onProgress: - onProgress(maxval, i+1) - continue - okay = True - if not vardb.match(atom): - self.not_installed.append(atom) - okay = False - if portage.catsplit(atom)[0] not in categories: - self.invalid_category.append(atom) - okay = False - if okay: - self.okay.append(atom) - if onProgress: - onProgress(maxval, i+1) - - def check(self, onProgress=None): - self._check_world(onProgress) - errors = [] - if self.found: - errors += map(lambda x: "'%s' is not a valid atom" % x, self.invalid) - errors += map(lambda x: "'%s' is not installed" % x, self.not_installed) - errors += map(lambda x: "'%s' has a category that is not listed in /etc/portage/categories" % x, self.invalid_category) - else: - errors.append(self.world_file + " could not be opened for reading") - return errors - - def fix(self, onProgress=None): - self._check_world(onProgress) - errors = [] - try: - portage.write_atomic(self.world_file, "\n".join(self.okay)) - except portage.exception.PortageException: - errors.append(self.world_file + " could not be opened for writing") - return errors - -class VdbKeyHandler(object): - def name(): - return "vdbkeys" - name = staticmethod(name) - - def __init__(self): - self.list = portage.db["/"]["vartree"].dbapi.cpv_all() - self.missing = [] - self.keys = ["HOMEPAGE", "SRC_URI", "KEYWORDS", "DESCRIPTION"] - - for p in self.list: - mydir = os.path.join(os.sep, portage.settings["ROOT"], portage.const.VDB_PATH, p)+os.sep - ismissing = True - for k in self.keys: - if os.path.exists(mydir+k): - ismissing = False - break - if ismissing: - self.missing.append(p) - - def check(self): - return ["%s has missing keys" % x for x in self.missing] - - def fix(self): - - errors = [] - - for p in self.missing: - mydir = os.path.join(os.sep, portage.settings["ROOT"], portage.const.VDB_PATH, p)+os.sep - if not os.access(mydir+"environment.bz2", os.R_OK): - errors.append("Can't access %s" % (mydir+"environment.bz2")) - elif not os.access(mydir, os.W_OK): - errors.append("Can't create files in %s" % mydir) - else: - env = os.popen("bzip2 -dcq "+mydir+"environment.bz2", "r") - envlines = env.read().split("\n") - env.close() - for k in self.keys: - s = [l for l in envlines if l.startswith(k+"=")] - if len(s) > 1: - errors.append("multiple matches for %s found in %senvironment.bz2" % (k, mydir)) - elif len(s) == 0: - s = "" - else: - s = s[0].split("=",1)[1] - s = s.lstrip("$").strip("\'\"") - s = re.sub("(\\\\[nrt])+", " ", s) - s = " ".join(s.split()).strip() - if s != "": - try: - keyfile = open(mydir+os.sep+k, "w") - keyfile.write(s+"\n") - keyfile.close() - except (IOError, OSError), e: - errors.append("Could not write %s, reason was: %s" % (mydir+k, e)) - - return errors - -def emaint_main(myargv): - - # TODO: Create a system that allows external modules to be added without - # the need for hard coding. - modules = {"world" : WorldHandler} - - module_names = modules.keys() - module_names.sort() - module_names.insert(0, "all") - - def exclusive(option, *args, **kw): - var = kw.get("var", None) - if var is None: - raise ValueError("var not specified to exclusive()") - if getattr(parser, var, ""): - raise OptionValueError("%s and %s are exclusive options" % (getattr(parser, var), option)) - setattr(parser, var, str(option)) +"""System health checks and maintenance utilities. +""" +from __future__ import print_function - usage = "usage: emaint [options] " + " | ".join(module_names) - - usage+= "\n\nCurrently emaint can only check and fix problems with one's world\n" - usage+= "file. Future versions will integrate other portage check-and-fix\n" - usage+= "tools and provide a single interface to system health checks." - - - parser = OptionParser(usage=usage) - parser.add_option("-c", "--check", help="check for problems", - action="callback", callback=exclusive, callback_kwargs={"var":"action"}) - parser.add_option("-f", "--fix", help="attempt to fix problems", - action="callback", callback=exclusive, callback_kwargs={"var":"action"}) - parser.action = None - - - (options, args) = parser.parse_args(args=myargv) - if len(args) != 1: - parser.error("Incorrect number of arguments") - if args[0] not in module_names: - parser.error("%s target is not a known target" % args[0]) - - if parser.action: - action = parser.action - else: - print "Defaulting to --check" - action = "-c/--check" - - if args[0] == "all": - tasks = modules.values() - else: - tasks = [modules[args[0]]] +import sys +import errno +# This block ensures that ^C interrupts are handled quietly. +try: + import signal + def exithandler(signum, _frame): + signal.signal(signal.SIGINT, signal.SIG_IGN) + signal.signal(signal.SIGTERM, signal.SIG_IGN) + sys.exit(128 + signum) - if action == "-c/--check": - status = "Checking %s for problems" - func = "check" - else: - status = "Attempting to fix %s" - func = "fix" + signal.signal(signal.SIGINT, exithandler) + signal.signal(signal.SIGTERM, exithandler) + signal.signal(signal.SIGPIPE, signal.SIG_DFL) +except KeyboardInterrupt: + sys.exit(1) - for task in tasks: - print status % task.name() - inst = task() - result = getattr(inst, func)() - if result: - print - print "\n".join(result) - print "\n" +from os import path as osp +pym_path = osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym") +sys.path.insert(0, pym_path) +import portage +portage._internal_caller = True +from portage.emaint.main import emaint_main - print "Finished" - -if __name__ == "__main__": +try: emaint_main(sys.argv[1:]) +except IOError as e: + if e.errno == errno.EACCES: + print("\nemaint: Need superuser access") + sys.exit(1) + else: + raise