summaryrefslogtreecommitdiff
blob: b35bc98f5f2c157b343a6921bb2e08f73042d681 (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
116
117
118
119
120
121
122
123
124
125
#!/usr/bin/env python

seconds_per_week = 7 * 24 * 60 * 60
# reinstall_period = None
reinstall_period = 10 * seconds_per_week

import os
import sys
import time

import portage

current_time = time.time()

portdb = portage.portdb
portdb.porttrees = [portdb.porttree_root] # exclude overlays
portdb.freeze()
settings = portage.config(clone=portage.settings)
vardb = portage.db[settings["ROOT"]]["vartree"].dbapi
fakedb = portage.fakedbapi(settings=portage.settings)
deps = {}

metadata_keys = [k for k in portage.auxdbkeys if not k.startswith("UNUSED_")]
dep_keys = ["DEPEND", "RDEPEND", "PDEPEND"]
good_pkgs = set()
bad_pkgs = set()

for cp in portdb.cp_all():
	best_visible = portdb.xmatch("bestmatch-visible", cp)
	if best_visible:
		best_installed = portage.best(vardb.match(cp))
		reinstall = False
		if best_installed and reinstall_period is not None:
			try:
				mtime = os.stat(os.path.join(
					vardb.getpath(best_installed), 'COUNTER')).st_mtime
			except OSError:
				reinstall = True
			else:
				if current_time - mtime > reinstall_period:
					reinstall = True
					#sys.stderr.write("%s is %.1f weeks old\n" % \
					#	(best_installed,
					#	(current_time - mtime) / seconds_per_week))

		if reinstall or best_visible != best_installed:

			traversed = set()
			dep_stack = []
			dep_stack.append(("=" + best_visible, best_visible))
			unsatisfied_dep = False

			while dep_stack:
				dep_atom, parent = dep_stack.pop()
				dep_pkg = portdb.xmatch("bestmatch-visible", dep_atom)
				if not dep_pkg:
					unsatisfied_dep = True
					bad_pkgs.add(parent)
					break

				if dep_pkg in bad_pkgs:
					unsatisfied_dep = True
					bad_pkgs.add(parent)
					break

				if dep_pkg in good_pkgs or dep_pkg in traversed:
					continue

				metadata = dict(zip(metadata_keys,
					portdb.aux_get(dep_pkg, metadata_keys)))

				# If this package isn't the highest visible version
				# in the slot then drop it in order to avoid a slot
				# conflict.
				slot_atom = "%s:%s" % (portage.cpv_getkey(dep_pkg),
					metadata["SLOT"])
				best_visible_slot = portdb.xmatch("bestmatch-visible",
					slot_atom)
				if dep_pkg != best_visible_slot:
					unsatisfied_dep = True
					bad_pkgs.add(dep_pkg)
					bad_pkgs.add(parent)
					break

				dep_str = " ".join(metadata[k] for k in dep_keys)
				settings.setcpv(dep_pkg, mydb=metadata)
				metadata["USE"] = settings["PORTAGE_USE"]
				success, atoms = portage.dep_check(dep_str,
					None, settings, myuse=metadata["USE"].split(),
					trees=portage.db, myroot=settings["ROOT"])

				if not success:
					sys.stderr.write(atoms + "\n")
					unsatisfied_dep = True
					bad_pkgs.add(dep_pkg)
					bad_pkgs.add(parent)
					break

				traversed.add(dep_pkg)
				fakedb.cpv_inject(dep_pkg, metadata=metadata)

				deps[dep_pkg] = atoms
				for atom in atoms:
					if atom.blocker:
						continue
					dep_stack.append((atom, dep_pkg))

			if unsatisfied_dep:
				bad_pkgs.add(best_visible)
			else:
				good_pkgs.update(traversed)
				print cp

for cpv in good_pkgs:
	for atom in deps[cpv]:
		if atom.blocker:
			continue
		if not atom.use:
			continue
		if not fakedb.match(atom):
			sys.stderr.write("%s has unsatisfied USE dep: %s\n" % (cpv, atom))
			#for cpv2 in fakedb.match(atom.cp):
			#	sys.stderr.write("   %s IUSE: %s USE: %s\n" % (cpv2,
			#		fakedb.aux_get(cpv2, ["IUSE"])[0],
			#		fakedb.aux_get(cpv2, ["USE"])[0]))