summaryrefslogtreecommitdiffstats
path: root/bin/emaint
blob: a3868772fcd97fca3f11a46f3a7a4e7b903c0a6b (plain)
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
#!/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.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)
			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)
		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


# this sucks, should track this in a different manner.
modules = {"world" : WorldHandler}

module_names = modules.keys()
module_names.sort()
module_names.insert(0, "all")

if __name__ == "__main__":
	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))


	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"