1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
#!/usr/bin/python -O
import sys
from copy import copy
from optparse import OptionParser, OptionValueError
import os, portage, portage_const
class WorldHandler(object):
def name():
return "world"
name = staticmethod(name)
def __init__(self):
self.invalid = []
self.not_installed = []
self.masked = []
self.unavailable = []
self.okay = []
self.found = os.access(portage_const.WORLD_FILE, os.R_OK)
for atom in open(portage_const.WORLD_FILE).read().split():
if not portage.isvalidatom(atom):
self.invalid.append(atom)
elif not portage.db["/"]["vartree"].dbapi.match(atom):
self.not_installed.append(atom)
elif not portage.db["/"]["porttree"].dbapi.xmatch("match-all", atom):
self.unavailable.append(atom)
elif not portage.db["/"]["porttree"].dbapi.match("match-visible", atom):
self.masked.append(atom)
else:
self.okay.append(atom)
def check(self):
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' is masked (manually fix by adding to package.keywords)" % x, self.masked)
errors += map(lambda x: "'%s' has no ebuilds available" % x, self.unavailable)
if self.masked:
errors += "Masked ebuilds can be manually unmasked with package.keywords or package.unmask"
else:
errors.append(portage_const.WORLD_FILE + " could not be opened for reading")
return errors
def fix(self):
errors = []
try:
open(portage_const.WORLD_FILE, "w").write("\n".join(self.okay))
except OSError:
errors.append(portage_const.WORLD_FILE + " could not be opened for writing")
return errors
modules = {"world" : WorldHandler}
module_names = modules.keys()
module_names.sort()
module_names.insert(0, "all")
def exclusive(option, unused1, unused2, unused3, var=None):
if not var:
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))
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()
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]]]
if action == "-c/--check":
status = "Checking %s for problems"
func = "check"
else:
status = "Attempting to fix %s"
func = "fix"
for task in tasks:
print status % task.name()
inst = task()
result = getattr(inst, func)()
if result:
print
print "\n".join(result)
print "\n"
print "Finished"
|