125
by Aaron Bentley
Added pastegraph |
1 |
#!/usr/bin/env python2.4
|
2 |
from subprocess import Popen, PIPE |
|
3 |
from urllib import urlencode |
|
4 |
from xml.sax.saxutils import escape |
|
5 |
import os.path |
|
6 |
||
7 |
class Node(object): |
|
135
by Aaron Bentley
Enhanced revision-crediting |
8 |
def __init__(self, name, color=None, label=None, rev_id=None): |
125
by Aaron Bentley
Added pastegraph |
9 |
self.name = name |
10 |
self.color = color |
|
128
by Aaron Bentley
Got initial graphing functionality working |
11 |
self.label = label |
130
by Aaron Bentley
Added committer to revisions |
12 |
self.committer = None |
137
by Aaron Bentley
Put dotted outlines on missing revisions |
13 |
self.rev_id = rev_id |
14 |
self.node_style = [] |
|
135
by Aaron Bentley
Enhanced revision-crediting |
15 |
|
16 |
def get_label(self): |
|
17 |
label = None |
|
18 |
if self.committer is not None: |
|
19 |
label="%s\\n%s" % (self.name, self.committer) |
|
20 |
elif self.rev_id is not None: |
|
21 |
try: |
|
22 |
first_segment = '-'.join(self.rev_id.split('-')[:-2]) |
|
23 |
except ValueError: |
|
24 |
first_segment = [] |
|
25 |
if '@' in first_segment: |
|
26 |
label="%s\\n%s" % (self.name, first_segment) |
|
27 |
return label |
|
125
by Aaron Bentley
Added pastegraph |
28 |
|
29 |
def define(self): |
|
137
by Aaron Bentley
Put dotted outlines on missing revisions |
30 |
attributes = [] |
130
by Aaron Bentley
Added committer to revisions |
31 |
style = [] |
125
by Aaron Bentley
Added pastegraph |
32 |
if self.color is not None: |
137
by Aaron Bentley
Put dotted outlines on missing revisions |
33 |
attributes.append('fillcolor="%s"' % self.color) |
34 |
style.append('filled') |
|
35 |
style.extend(self.node_style) |
|
36 |
if len(style) > 0: |
|
37 |
attributes.append('style="%s"' % ",".join(style)) |
|
135
by Aaron Bentley
Enhanced revision-crediting |
38 |
label = self.get_label() |
39 |
if label is not None: |
|
137
by Aaron Bentley
Put dotted outlines on missing revisions |
40 |
attributes.append('label="%s"' % label) |
41 |
if len(attributes) > 0: |
|
42 |
return '%s[%s]' % (self.name, " ".join(attributes)) |
|
125
by Aaron Bentley
Added pastegraph |
43 |
|
44 |
def __str__(self): |
|
45 |
return self.name |
|
46 |
||
128
by Aaron Bentley
Got initial graphing functionality working |
47 |
def dot_output(relations): |
125
by Aaron Bentley
Added pastegraph |
48 |
defined = set() |
49 |
yield "digraph G\n" |
|
50 |
yield "{\n" |
|
51 |
for (start, end) in relations: |
|
52 |
if start.name not in defined: |
|
53 |
defined.add(start.name) |
|
54 |
my_def = start.define() |
|
55 |
if my_def is not None: |
|
56 |
yield " %s;\n" % my_def |
|
57 |
if end.name not in defined: |
|
58 |
defined.add(end.name) |
|
59 |
my_def = end.define() |
|
60 |
if my_def is not None: |
|
61 |
yield " %s;\n" % my_def |
|
62 |
||
63 |
yield " %s->%s;\n" % (start.name, end.name) |
|
64 |
yield "}\n" |
|
65 |
||
134
by Aaron Bentley
support multiple image formats for graph-ancestry |
66 |
def invoke_dot(input, out_file=None, file_type='svg'): |
67 |
cmdline = ['dot', '-T%s' % file_type] |
|
125
by Aaron Bentley
Added pastegraph |
68 |
if out_file is not None: |
69 |
cmdline.extend(('-o', out_file)) |
|
138
by Aaron Bentley
Handle systems without dot (the horror!). From Magnus Therning. |
70 |
try: |
71 |
dot_proc = Popen(cmdline, stdin=PIPE) |
|
72 |
except OSError, e: |
|
73 |
if e.errno == 2: |
|
74 |
print "You need 'dot' to create ancestry graphs" |
|
75 |
return
|
|
125
by Aaron Bentley
Added pastegraph |
76 |
for line in input: |
77 |
dot_proc.stdin.write(line) |
|
78 |
dot_proc.stdin.close() |
|
79 |
return dot_proc.wait() |