From e7742df99fc5f5f95e1d10bc680ddfb8c515b380 Mon Sep 17 00:00:00 2001 From: Matt Torok Date: Wed, 6 Mar 2013 01:04:05 -0800 Subject: [PATCH] Updated `brew graph` Changed 'graph' command to show only installed by default. Prettified resulting graph. By default, the `brew graph` command would output a dependency graph for every formula it knew about. Now it only outputs a dependency graph the for formulas installed. If you want to see the graph for all formulas, use `brew graph --all`. Additionally, the old version of the graph command would filter out any formulas without depdency connections. The updated version now only does this if calculating dependencies for all formulas via the `--all` flag. Finally, the resulting graph has been redesigned to be simpler to read. All formulas which have no other formulas depending on them (i.e., root nodes) are aligned to the left. They are also outlined in a light grey box, which is labelled "Safe to Remove". As implied, all of the formulas in this box can be safely removed without breaking other installed formulas; all formulas outside this box have at least one installed formula depending on them. This new graph style is surpressed if the `--all` flag is used. Closes #18282. Signed-off-by: Adam Vandenberg --- Library/Contributions/cmd/brew-graph | 60 +++++++++++++++++++++------- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/Library/Contributions/cmd/brew-graph b/Library/Contributions/cmd/brew-graph index 27c80af83b11..d45c69797d21 100755 --- a/Library/Contributions/cmd/brew-graph +++ b/Library/Contributions/cmd/brew-graph @@ -1,8 +1,8 @@ #!/usr/bin/env python """ $ brew install graphviz -$ brew graph | dot -Tsvg -ohomebrew.svg -$ open homebrew.svg +$ brew graph | dot -Tsvg -ohomebrew.html +$ open homebrew.html """ from __future__ import with_statement @@ -274,13 +274,26 @@ class Graph(NodeContainer, EdgeContainer, ClusterContainer): def main(): cmd = ["brew", "deps"] - cmd.extend(sys.argv[1:] or ["--all"]) + if sys.argv[1:]: + if '--all' in sys.argv[1:]: + show = 'all' + cmd.extend(['--all']) + else: + show = 'one' + hideOrphaned = False + cmd.extend(sys.argv[1:]) + else: + show = 'installed' + cmd.extend(['--installed']) + code, output = run(cmd) output = output.strip() depgraph = list() for f in output.split("\n"): stuff = f.split(":",2) + if len(stuff) < 2: + continue name = stuff[0] deps = stuff[1].strip() if not deps: @@ -289,20 +302,39 @@ def main(): deps = deps.split(" ") depgraph.append((name, deps)) - hb = Graph("Homebrew Dependencies", attrib={'labelloc':'b', 'rankdir':'LR', 'ranksep':'5'}) - - used = set() + hb = Graph("Homebrew Dependencies", attrib={'labelloc':'t', 'rankdir':'LR', 'ranksep':'5'}) + # Independent formulas (those that are not dependended on by any other formula) get placed in + # their own subgraph so we can align them together on the left. + if show == 'installed': + sub = hb.cluster("independent", "Safe to Remove", attrib={'rank': 'min', 'style': 'filled', 'fillcolor': '#F0F0F0', 'color': 'invis'}) + else: + sub = hb + + seen = set() + def addNode(graph, name): + if name not in seen: + graph.node(name, name, attrib={'shape': 'box'}) + seen.add(name) + return True + return False + + independent = set() for f in depgraph: - for d in f[1]: - used.add(f[0]) - used.add(d) - - for f in depgraph: - if f[0] not in used: + # Filter out orphan formulas when showing all, to cut down on noise + if show == 'all' and len(f[1]) == 0: continue - n = hb.node(f[0], f[0]) + + independent.add(f[0]) for d in f[1]: - hb.link(d, f[0]) + independent.discard(d) + hb.link(f[0], d) + # Children we can add right away because we don't care where they go + addNode(hb, d) + + # For all installed formulas, place them in the 'indep' subgraph iff they + # are not depended on by other formulas, i.e. are root nodes. + for d in independent: + addNode(sub, d) hb.dot()