4
4
from bzrlib.errors import BzrCommandError, NoCommonRoot, NoSuchRevision
5
5
from bzrlib.fetch import greedy_fetch
6
6
from bzrlib.graph import node_distances, select_farthest
7
from bzrlib.revision import combined_graph, MultipleRevisionSources
7
from bzrlib.revision import combined_graph, revision_graph
8
from bzrlib.revision import MultipleRevisionSources
20
21
committer_alias = {'abentley': 'Aaron Bentley'}
21
def add_relations(rev_id):
22
if rev_id in ancestors:
25
if rev_id not in nodes:
26
nodes[rev_id] = Node("n%d" % counter, label = rev_id)
28
revision = branch.get_revision(rev_id)
29
ancestors [rev_id] = []
30
for p in (p.revision_id for p in revision.parents):
32
if p not in descendants:
34
descendants[p].append(rev_id)
35
ancestors [rev_id].append(rev_id)
37
22
def short_committer(committer):
38
23
new_committer = re.sub('<.*>', '', committer).strip(' ')
39
24
if len(new_committer) < 2:
75
60
new_ancestors[me][new_parent] = distance
76
61
return new_ancestors
78
def compact_descendants(descendants, ancestors):
81
for me, my_descendants in descendants.iteritems():
84
new_descendants[me] = []
85
for descendant in my_descendants:
86
new_descendant = descendant
87
while can_skip(new_descendant, descendants, ancestors):
88
skip.add(new_descendant)
89
if new_descendant in new_descendants:
90
del new_descendants[new_descendant]
91
new_descendant = descendants[new_descendant][0]
92
new_descendants[me].append(new_descendant)
93
return new_descendants
96
def graph_ancestry(branch, collapse=True):
98
q = ((i+1, n) for (i, n) in enumerate(branch.revision_history()))
101
branch_name = os.path.basename(branch.base)
102
except AttributeError:
104
for (revno, rev_id) in q:
105
nodes[rev_id] = Node("R%d" % revno, color="#ffff00", rev_id=rev_id,
111
lines = [branch.last_patch()]
112
while len(lines) > 0:
115
if rev_id not in nodes:
116
nodes[rev_id] = Node("n%d" % counter, label=rev_id,
121
revision = branch.get_revision(rev_id)
122
except bzrlib.errors.NoSuchRevision:
123
nodes[rev_id].node_style.append('dotted')
125
if nodes[rev_id].committer is None:
126
nodes[rev_id].committer = short_committer(revision.committer)
127
parent_ids = [r.revision_id for r in revision.parents]
128
ancestors [rev_id] = parent_ids
129
for parent in parent_ids:
130
if parent not in ancestors:
131
new_lines.add(parent)
132
descendants[parent] = []
133
descendants[parent].append(rev_id)
137
for node in nodes.itervalues():
138
node.label = node.get_label()
140
visible_descendants = compact_descendants(descendants, ancestors)
142
visible_descendants = descendants
144
for key, values in visible_descendants.iteritems():
146
node_relations.append((nodes[key], nodes[value]))
147
return node_relations
149
63
def get_committer(rev_id, source):
151
65
committer = short_committer(source.get_revision(rev_id).committer)
170
84
class Grapher(object):
171
def __init__(self, branch, other_branch):
85
def __init__(self, branch, other_branch=None):
172
86
object.__init__(self)
173
87
self.branch = branch
174
88
self.other_branch = other_branch
175
greedy_fetch(branch, other_branch)
176
89
revision_a = self.branch.last_patch()
177
revision_b = self.other_branch.last_patch()
179
self.root, self.ancestors, self.descendants, self.common = \
180
combined_graph(revision_a, revision_b, self.branch)
181
except bzrlib.errors.NoCommonRoot:
182
raise bzrlib.errors.NoCommonAncestor(revision_a, revision_b)
90
if other_branch is not None:
91
greedy_fetch(branch, other_branch)
92
revision_b = self.other_branch.last_patch()
94
self.root, self.ancestors, self.descendants, self.common = \
95
combined_graph(revision_a, revision_b, self.branch)
96
except bzrlib.errors.NoCommonRoot:
97
raise bzrlib.errors.NoCommonAncestor(revision_a, revision_b)
99
self.root, self.ancestors, self.descendants = \
100
revision_graph(revision_a, branch)
103
self.n_history = branch.revision_history()
183
104
self.distances = node_distances(self.descendants, self.ancestors,
185
self.base = select_farthest(self.distances, self.common)
186
self.n_history = branch.revision_history()
187
self.m_history = other_branch.revision_history()
106
if other_branch is not None:
107
self.base = select_farthest(self.distances, self.common)
108
self.m_history = other_branch.revision_history()
189
113
def dot_node(self, node, num):
276
200
def write_ancestry_file(branch, filename, collapse=True, antialias=True,
277
201
merge_branch=None, ranking="forced"):
278
202
b = Branch.open_containing(branch)
279
if merge_branch is None:
280
relations = graph_ancestry(b, collapse)
203
if merge_branch is not None:
282
204
m = Branch.open_containing(merge_branch)
283
grapher = Grapher(b, m)
284
relations = grapher.get_relations(collapse)
207
grapher = Grapher(b, m)
208
relations = grapher.get_relations(collapse)
286
210
ext = filename.split('.')[-1]
287
211
output = dot_output(relations, ranking)