1 : #include "dotgraph.hh"
2 : #include "normalise.hh"
3 :
4 :
5 : static string dotQuote(const string & s)
6 0 : {
7 0 : return "\"" + s + "\"";
8 : }
9 :
10 :
11 : static string nextColour()
12 0 : {
13 0 : static int n = 0;
14 : static string colours[] =
15 : { "black", "red", "green", "blue"
16 0 : , "magenta", "burlywood" };
17 0 : return colours[n++ % (sizeof(colours) / sizeof(string))];
18 : }
19 :
20 :
21 : static string makeEdge(const string & src, const string & dst)
22 0 : {
23 0 : format f = format("%1% -> %2% [color = %3%];\n")
24 0 : % dotQuote(src) % dotQuote(dst) % dotQuote(nextColour());
25 0 : return f.str();
26 : }
27 :
28 :
29 : static string makeNode(const string & id, const string & label,
30 : const string & colour)
31 0 : {
32 : format f = format("%1% [label = %2%, shape = box, "
33 : "style = filled, fillcolor = %3%];\n")
34 0 : % dotQuote(id) % dotQuote(label) % dotQuote(colour);
35 0 : return f.str();
36 : }
37 :
38 :
39 : static string symbolicName(const string & path)
40 0 : {
41 0 : string p = baseNameOf(path);
42 0 : if (isHash(string(p, 0, Hash::hashSize * 2)) &&
43 : p[Hash::hashSize * 2] == '-')
44 0 : p = string(p, Hash::hashSize * 2 + 1);
45 0 : return p;
46 : }
47 :
48 :
49 : string pathLabel(const Path & nePath, const string & elemPath)
50 0 : {
51 0 : return (string) nePath + "-" + elemPath;
52 : }
53 :
54 :
55 : void printClosure(const Path & nePath, const StoreExpr & fs)
56 0 : {
57 0 : PathSet workList(fs.closure.roots);
58 0 : PathSet doneSet;
59 :
60 0 : for (PathSet::iterator i = workList.begin(); i != workList.end(); i++) {
61 0 : cout << makeEdge(pathLabel(nePath, *i), nePath);
62 : }
63 :
64 0 : while (!workList.empty()) {
65 0 : Path path = *(workList.begin());
66 0 : workList.erase(path);
67 :
68 0 : if (doneSet.find(path) == doneSet.end()) {
69 0 : doneSet.insert(path);
70 :
71 0 : ClosureElems::const_iterator elem = fs.closure.elems.find(path);
72 0 : if (elem == fs.closure.elems.end())
73 0 : throw Error(format("bad closure, missing path `%1%'") % path);
74 :
75 0 : for (StringSet::const_iterator i = elem->second.refs.begin();
76 : i != elem->second.refs.end(); i++)
77 : {
78 0 : workList.insert(*i);
79 0 : cout << makeEdge(pathLabel(nePath, *i), pathLabel(nePath, path));
80 : }
81 :
82 0 : cout << makeNode(pathLabel(nePath, path),
83 : symbolicName(path), "#ff0000");
84 : }
85 : }
86 : }
87 :
88 :
89 : void printDotGraph(const PathSet & roots)
90 0 : {
91 0 : PathSet workList(roots);
92 0 : PathSet doneSet;
93 :
94 0 : cout << "digraph G {\n";
95 :
96 0 : while (!workList.empty()) {
97 0 : Path nePath = *(workList.begin());
98 0 : workList.erase(nePath);
99 :
100 0 : if (doneSet.find(nePath) == doneSet.end()) {
101 0 : doneSet.insert(nePath);
102 :
103 4018 : StoreExpr ne = storeExprFromPath(nePath);
104 56 :
105 0 : string label, colour;
106 :
107 0 : if (ne.type == StoreExpr::neDerivation) {
108 0 : for (PathSet::iterator i = ne.derivation.inputs.begin();
109 : i != ne.derivation.inputs.end(); i++)
110 : {
111 0 : workList.insert(*i);
112 0 : cout << makeEdge(*i, nePath);
113 : }
114 :
115 0 : label = "derivation";
116 0 : colour = "#00ff00";
117 0 : for (StringPairs::iterator i = ne.derivation.env.begin();
118 : i != ne.derivation.env.end(); i++)
119 0 : if (i->first == "name") label = i->second;
120 : }
121 :
122 0 : else if (ne.type == StoreExpr::neClosure) {
123 0 : label = "<closure>";
124 0 : colour = "#00ffff";
125 0 : printClosure(nePath, ne);
126 : }
127 :
128 0 : else abort();
129 :
130 0 : cout << makeNode(nePath, label, colour);
131 : }
132 : }
133 :
134 0 : cout << "}\n";
135 : }
|