diff --git a/pisi/api.py b/pisi/api.py index 4387faef..4cc4a79b 100644 --- a/pisi/api.py +++ b/pisi/api.py @@ -228,6 +228,39 @@ def install_pkg_names(A): return True # everything went OK :) +def package_graph(A): + """Construct a package relations graph, containing + all dependencies of packages A""" + + ctx.ui.debug('A = %s' % str(A)) + + # try to construct a pisi graph of packages to + # install / reinstall + + G_f = pgraph.PGraph(packagedb) # construct G_f + + # find the "install closure" graph of G_f by package + # set A using packagedb + for x in A: + G_f.add_package(x) + B = A + #state = {} + while len(B) > 0: + Bp = set() + for x in B: + pkg = packagedb.get_package(x) + print pkg + for dep in pkg.runtimeDeps: + # we don't deal with already *satisfied* dependencies + if not dep.package in G_f.vertices(): + Bp.add(str(dep.package)) + G_f.add_dep(x, dep) +# if not dependency.installed_satisfies_dep(dep): +# if not dep.package in G_f.vertices(): +# Bp.add(str(dep.package)) +# G_f.add_dep(x, dep) + B = Bp + return G_f def upgrade(A): upgrade_pkg_names(A) diff --git a/pisi/cli/commands.py b/pisi/cli/commands.py index 86c5ad49..89f0e085 100644 --- a/pisi/cli/commands.py +++ b/pisi/cli/commands.py @@ -208,6 +208,30 @@ class Clean(Command): pisi.util.clean_locks() self.finalize() + +class Graph(Command): + """Graph package relations. +Usage: graph ... + +Write a graph of package relations, tracking dependency and +conflicts relations starting from given packages. +""" + + __metaclass__ = autocommand + + def __init__(self): + super(Graph, self).__init__() + + name = ("graph", None) + + def run(self): + self.init() + if self.args: + g = pisi.api.package_graph(self.args) + g.write_graphviz(file('pgraph.dot', 'w')) + self.finalize() + + def buildno_opts(self): self.parser.add_option("", "--ignore-build-no", action="store_true", default=False, diff --git a/pisi/graph.py b/pisi/graph.py index dfba7809..7a90ff1b 100644 --- a/pisi/graph.py +++ b/pisi/graph.py @@ -132,16 +132,20 @@ class Digraph(object): list.reverse() return list + def id_str(self, u): + s = str(u) + return s.replace('-', '_') + def write_graphviz(self, f): f.write('digraph G {\n') for u in self.vertices(): - f.write(u) + f.write(self.id_str(u)) self.write_graphviz_vlabel(f, u) f.write(';\n') f.write('\n') for u in self.vertices(): for v in self.adj(u): - f.write(u + ' -- ' + v) + f.write( self.id_str(u) + ' -> ' + self.id_str(v)) self.write_graphviz_elabel(f, u, v) f.write(';\n') f.write('\n') diff --git a/pisi/pgraph.py b/pisi/pgraph.py index efe8def2..297b3161 100644 --- a/pisi/pgraph.py +++ b/pisi/pgraph.py @@ -75,5 +75,5 @@ class PGraph(Digraph): def write_graphviz_vlabel(self, f, u): (v, r) = self.vertex_data(u) - f.write('[ ' + str(u) + '(' + str(v) + ',' + str(r) + ') ]') + f.write('[ label = \"' + str(u) + '(' + str(v) + ',' + str(r) + ')\" ]')