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
126
127
128
129
130
|
"""
# Copyright 1999-2005 Gentoo Foundation
# This source code is distributed under the terms of version 2 of the GNU
# General Public License as published by the Free Software Foundation, a copy
# of which can be found in the main directory of this project.
Gentoo Linux Installer
$Id: runtimedeps.py,v 1.3 2005/12/26 19:26:26 agaffney Exp $
"""
import os, sys
class MissingPackagesError(Exception):
pass
class depgraph:
def __init__(self):
self.graph = {}
def add(self, node, parent=None):
if node not in self.graph:
self.graph[node] = [[], []]
if parent and parent not in self.graph[node][0]:
if parent not in self.graph:
self.graph[parent] = [[], []]
self.graph[node][0].append(parent)
self.graph[parent][1].append(node)
def remove(self, node):
for parent in self.graph[node][0]:
self.graph[parent][1].remove(node)
for child in self.graph[node][1]:
self.graph[child][0].remove(node)
return self.graph.pop(node)
def has_node(self, node):
return node in self.graph
def leaf_nodes(self):
return [node for node in self.graph if not self.graph[node][1]]
def node_count(self):
return len(self.graph)
def important_node(self):
important_node = None
importance = 0
for node in self.graph:
if len(self.graph[node][0]) > importance:
importance = len(self.graph[node][0])
important_node = node
return important_node
def resolve_deps(dep_list):
if dep_list and dep_list[0] == "||":
for dep in dep_list[1:]:
if isinstance(dep, list):
try:
atoms = resolve_deps(dep)
except MissingPackagesError:
continue
else:
atoms = [dep]
all_found = True
for atom in atoms:
if not atom.startswith("!") and not vdb.match(atom):
all_found = False
break
if all_found:
return atoms
raise MissingPackagesError(dep_list)
atoms = []
for dep in dep_list:
if isinstance(dep, list):
atoms.extend(resolve_deps(dep))
elif not dep.startswith("!"):
if not vdb.match(dep):
raise MissingPackagesError([dep])
atoms.append(dep)
return atoms
def calc_required_pkgs(atom, graph, parent=None):
pkg = portage.best(vdb.match(atom))
if not pkg:
raise MissingPackagesError([atom])
if pkg == parent:
return
already_processed = graph.has_node(pkg)
graph.add(pkg, parent)
if already_processed:
return
useflags = vdb.aux_get(pkg, ["USE"])[0].split()
rdep_raw = " ".join(vdb.aux_get(pkg, ["RDEPEND", "PDEPEND"]))
rdep_struct = portage_dep.use_reduce(portage_dep.paren_reduce(rdep_raw), uselist=useflags)
rdep_struct = portage.dep_virtual(portage_dep.dep_opconvert(rdep_struct), portage.settings)
rdep_atoms = portage.unique_array(resolve_deps(rdep_struct))
for atom in rdep_atoms:
calc_required_pkgs(atom, graph, pkg)
def prune_existing(graph):
db = portage.db[portage.root]["vartree"].dbapi
for atom in db.cp_all():
for pkg in db.match(atom):
if graph.has_node(pkg):
graph.remove(pkg)
def get_deps(pkgs):
pkglist = []
graph = depgraph()
for pkg in pkgs.split():
if not vdb.match(pkg):
continue
calc_required_pkgs(pkg, graph)
while graph.node_count():
leaf_nodes = graph.leaf_nodes()
if not leaf_nodes:
node = graph.important_node()
pkglist.append(node)
graph.remove(node)
continue
pkglist.extend(leaf_nodes)
for node in leaf_nodes:
graph.remove(node)
return pkglist
os.environ['ROOT'] = sys.argv[1]
import portage, portage_dep
vdb = portage.db["/"]["vartree"].dbapi
print "\n".join(get_deps(" ".join(sys.argv[2:])))
|