bzr branch
http://gegoxaren.bato24.eu/bzr/b-gtk/fix-viz
1
by Scott James Remnant
Commit the first version of bzrk. |
1 |
# -*- coding: UTF-8 -*-
|
2 |
"""Directed graph production.
|
|
3 |
||
4 |
This module contains the code to produce an ordered directed graph of a
|
|
5 |
bzr branch, such as we display in the tree view at the top of the bzrk
|
|
6 |
window.
|
|
7 |
"""
|
|
8 |
||
9 |
__copyright__ = "Copyright © 2005 Canonical Ltd." |
|
10 |
__author__ = "Scott James Remnant <scott@ubuntu.com>" |
|
11 |
||
12 |
||
256.2.21
by Gary van der Merwe
Refactor so that line graph is more contained. |
13 |
def linegraph(branch, start, maxnum): |
3
by Scott James Remnant
Split the display in two with a pane, we'll use the bottom half to show |
14 |
"""Produce a directed graph of a bzr branch. |
15 |
||
256.2.4
by Gary van der Merwe
First go at using bzrlib graph code |
16 |
Returns a list of tuples of (revision, node, lines, parents, children).
|
3
by Scott James Remnant
Split the display in two with a pane, we'll use the bottom half to show |
17 |
|
18 |
Node is a tuple of (column, colour) with column being a zero-indexed
|
|
19 |
column number of the graph that this revision represents and colour
|
|
20 |
being a zero-indexed colour (which doesn't specify any actual colour
|
|
21 |
in particular) to draw the node in.
|
|
22 |
||
23 |
Lines is a list of tuples which represent lines you should draw away
|
|
24 |
from the revision, if you also need to draw lines into the revision
|
|
25 |
you should use the lines list from the previous iteration. Each
|
|
26 |
typle in the list is in the form (start, end, colour) with start and
|
|
27 |
end being zero-indexed column numbers and colour as in node.
|
|
28 |
||
29 |
It's up to you how to actually draw the nodes and lines (straight,
|
|
30 |
curved, kinked, etc.) and to pick the actual colours for each index.
|
|
31 |
"""
|
|
256.2.4
by Gary van der Merwe
First go at using bzrlib graph code |
32 |
|
256.2.16
by Gary van der Merwe
Make sure a revision is only ever a direct parent of one child. |
33 |
def getdirectparent(childrevid, childindex, childsparents): |
256.2.6
by Gary van der Merwe
Implement color selection |
34 |
"""Return the revision id of the direct parent |
35 |
|
|
36 |
The direct parent is the first parent with the same committer"""
|
|
37 |
childrevision = revisions[childindex] |
|
38 |
directparent = directparentcache[childindex] |
|
39 |
if directparent is None: |
|
40 |
for parentrevid in childsparents: |
|
256.2.12
by Gary van der Merwe
Impove the folding of the new lines |
41 |
if parentrevid in revindex: |
256.2.16
by Gary van der Merwe
Make sure a revision is only ever a direct parent of one child. |
42 |
parentindex = revindex[parentrevid] |
43 |
parentrevision = revisions[parentindex] |
|
256.2.12
by Gary van der Merwe
Impove the folding of the new lines |
44 |
if childrevision.committer == parentrevision.committer: |
256.2.16
by Gary van der Merwe
Make sure a revision is only ever a direct parent of one child. |
45 |
# This may be a direct parent, but first check that
|
46 |
# for this parent, there are no other children, who are
|
|
47 |
# before us in the children list, for which this parent
|
|
48 |
# is also the direct parent.
|
|
49 |
# pc in all the below var name stands for parents child
|
|
50 |
first = True |
|
51 |
for pcrevid in revisionchildren[parentindex]: |
|
52 |
if pcrevid == childrevid: |
|
53 |
break
|
|
54 |
pcindex = revindex[pcrevid] |
|
55 |
pcdirectparent = getdirectparent(pcrevid, |
|
56 |
pcindex, |
|
57 |
revisionchildren[pcindex]) |
|
58 |
if pcdirectparent==parentrevid: |
|
59 |
first = False |
|
60 |
break
|
|
61 |
||
62 |
if first: |
|
63 |
directparent = parentrevid |
|
64 |
break
|
|
256.2.6
by Gary van der Merwe
Implement color selection |
65 |
#no parents have the same commiter
|
66 |
if directparent is None: |
|
67 |
directparent = "" |
|
68 |
directparentcache[childindex] = directparent |
|
69 |
return directparent |
|
256.2.11
by Gary van der Merwe
New viz lines algorithm. Not 100% yet - but close. |
70 |
|
71 |
def find_column_from_branchlineid(branchlineid): |
|
72 |
for index, column in enumerate(columns): |
|
73 |
if column is not None and column["branchlineid"] == branchlineid: |
|
74 |
return (index, column) |
|
75 |
return (None, None) |
|
76 |
||
77 |
def has_no_nodes_between (column, startindex, endindex): |
|
78 |
for nodeindex in column["nodeindexes"]: |
|
79 |
if nodeindex > startindex and nodeindex < endindex: |
|
80 |
return False |
|
81 |
return True |
|
82 |
||
83 |
def append_line (column , startindex, endindex): |
|
84 |
column["lines"].append((startindex,endindex)) |
|
85 |
if endindex > column["maxindex"] : |
|
86 |
column["maxindex"] = endindex |
|
256.2.12
by Gary van der Merwe
Impove the folding of the new lines |
87 |
|
256.2.15
by Gary van der Merwe
Make sure that we don't put lines on top of allready drawn branchlines |
88 |
def append_column (column, minindex): |
256.2.12
by Gary van der Merwe
Impove the folding of the new lines |
89 |
columnindex = None |
90 |
for (i, c) in enumerate(columns): |
|
256.2.15
by Gary van der Merwe
Make sure that we don't put lines on top of allready drawn branchlines |
91 |
if c is None or (c["branchlineid"] == "finished" \ |
92 |
and c["maxindex"] <= minindex): |
|
256.2.12
by Gary van der Merwe
Impove the folding of the new lines |
93 |
columnindex = i |
94 |
columns[columnindex] = column |
|
95 |
break
|
|
96 |
if columnindex is None: |
|
97 |
columnindex = len(columns) |
|
98 |
columns.append(column) |
|
99 |
return columnindex |
|
256.2.6
by Gary van der Merwe
Implement color selection |
100 |
|
256.2.21
by Gary van der Merwe
Refactor so that line graph is more contained. |
101 |
revids = [] |
102 |
revindex = {} |
|
103 |
for (index, revid) in enumerate(reversed( \ |
|
104 |
branch.repository.get_ancestry(start))): |
|
105 |
if revid is not None: |
|
106 |
revids.append(revid) |
|
107 |
revindex[revid] = index |
|
108 |
if maxnum is not None and index > maxnum: |
|
109 |
break
|
|
110 |
||
256.2.22
by Gary van der Merwe
Use branch.revision_history as a mainline |
111 |
mainline = branch.revision_history() |
256.2.21
by Gary van der Merwe
Refactor so that line graph is more contained. |
112 |
revisions = branch.repository.get_revisions(revids) |
113 |
revisionparents = branch.repository.get_graph().get_parents(revids) |
|
114 |
directparentcache = [None for revision in revisions] |
|
115 |
||
256.2.11
by Gary van der Merwe
New viz lines algorithm. Not 100% yet - but close. |
116 |
# This will hold what we plan to put in each column.
|
117 |
# The position of the item in this list indicates the column, and it
|
|
118 |
# it may change if we need to make space for other things.
|
|
119 |
# Each typle in the list is in the form:
|
|
120 |
# (branchlineid, nodeindexes, lines, maxindex)
|
|
121 |
# A item may be None to indicate that there is nothing in the column
|
|
122 |
columns = [] |
|
256.2.4
by Gary van der Merwe
First go at using bzrlib graph code |
123 |
|
124 |
linegraph = [] |
|
125 |
||
256.2.11
by Gary van der Merwe
New viz lines algorithm. Not 100% yet - but close. |
126 |
lastbranchlineid = 0 |
127 |
branchlineids = [] |
|
128 |
revisionchildren = [[] for revision in revisions] |
|
256.2.12
by Gary van der Merwe
Impove the folding of the new lines |
129 |
notdrawnlines = [] |
256.2.6
by Gary van der Merwe
Implement color selection |
130 |
|
256.2.4
by Gary van der Merwe
First go at using bzrlib graph code |
131 |
for (index, revision) in enumerate(revisions): |
256.2.11
by Gary van der Merwe
New viz lines algorithm. Not 100% yet - but close. |
132 |
parents = [parent for parent in revisionparents[index] \ |
256.2.4
by Gary van der Merwe
First go at using bzrlib graph code |
133 |
if parent!="null:"] |
256.2.11
by Gary van der Merwe
New viz lines algorithm. Not 100% yet - but close. |
134 |
for parentrevid in parents: |
135 |
if parentrevid in revindex: |
|
136 |
revisionchildren[revindex[parentrevid]]\ |
|
137 |
.append(revision.revision_id) |
|
138 |
||
139 |
children = revisionchildren[index] |
|
256.2.18
by Gary van der Merwe
small optimization |
140 |
|
141 |
#We use childrevid, childindex, childbranchlineid often, so cache it
|
|
142 |
children_ext = [] |
|
143 |
for childrevid in children: |
|
144 |
childindex = revindex[childrevid] |
|
145 |
children_ext.append((childrevid, |
|
146 |
childindex, |
|
147 |
branchlineids[childindex])) |
|
148 |
||
256.2.11
by Gary van der Merwe
New viz lines algorithm. Not 100% yet - but close. |
149 |
linegraph.append([revision, None, |
150 |
[], parents, children]) |
|
151 |
||
152 |
branchlineid = None |
|
256.2.22
by Gary van der Merwe
Use branch.revision_history as a mainline |
153 |
|
154 |
if revision.revision_id in mainline: |
|
155 |
branchlineid = 0 |
|
156 |
else: |
|
157 |
#Try and see if we are the same branchline as one of our children
|
|
158 |
#If we are, use the same branchlineid
|
|
159 |
for (childrevid, childindex, childbranchlineid) in children_ext: |
|
160 |
childsparents = revisionparents[childindex] |
|
161 |
||
162 |
if len(children) == 1 and len(childsparents) == 1: |
|
163 |
# one-one relationship between parent and child
|
|
164 |
branchlineid = childbranchlineid |
|
165 |
break
|
|
166 |
||
167 |
#Is the current revision the direct parent of the child?
|
|
168 |
if childbranchlineid != 0 and revision.revision_id == \ |
|
169 |
getdirectparent(childrevid, childindex, childsparents): |
|
170 |
branchlineid = childbranchlineid |
|
171 |
break
|
|
256.2.6
by Gary van der Merwe
Implement color selection |
172 |
|
256.2.11
by Gary van der Merwe
New viz lines algorithm. Not 100% yet - but close. |
173 |
if branchlineid is None: |
174 |
branchlineid = lastbranchlineid = lastbranchlineid + 1 |
|
175 |
||
176 |
branchlineids.append(branchlineid) |
|
177 |
||
178 |
(columnindex, column) = find_column_from_branchlineid(branchlineid) |
|
179 |
||
180 |
if columnindex is None: |
|
256.2.18
by Gary van der Merwe
small optimization |
181 |
for (childrevid, childindex, childbranchlineid) in children_ext: |
182 |
(i, c) = find_column_from_branchlineid(childbranchlineid) |
|
183 |
if c is not None and c["maxindex"] <= index: |
|
184 |
(columnindex, column) = (i, c) |
|
185 |
break
|
|
186 |
||
256.2.11
by Gary van der Merwe
New viz lines algorithm. Not 100% yet - but close. |
187 |
|
188 |
||
189 |
if columnindex is None: |
|
256.2.15
by Gary van der Merwe
Make sure that we don't put lines on top of allready drawn branchlines |
190 |
minindex = index |
191 |
for childrevid in children: |
|
192 |
childindex = revindex[childrevid] |
|
193 |
if childindex<minindex: |
|
194 |
minindex = childindex |
|
195 |
||
256.2.11
by Gary van der Merwe
New viz lines algorithm. Not 100% yet - but close. |
196 |
column = {"branchlineid": branchlineid, |
197 |
"nodeindexes": [index], |
|
198 |
"lines": [], |
|
199 |
"maxindex": index} |
|
256.2.15
by Gary van der Merwe
Make sure that we don't put lines on top of allready drawn branchlines |
200 |
columnindex = append_column(column, minindex) |
256.2.11
by Gary van der Merwe
New viz lines algorithm. Not 100% yet - but close. |
201 |
else: |
202 |
column["branchlineid"] = branchlineid |
|
203 |
column["nodeindexes"].append(index) |
|
204 |
||
256.2.16
by Gary van der Merwe
Make sure a revision is only ever a direct parent of one child. |
205 |
opentillparent = getdirectparent(revision.revision_id, index, parents) |
256.2.11
by Gary van der Merwe
New viz lines algorithm. Not 100% yet - but close. |
206 |
if opentillparent == "": |
207 |
if len(parents)>0: |
|
208 |
opentillparent = parents[0] |
|
256.2.10
by Gary van der Merwe
Ensure that we don't give a child a same color when we don't mean to becuase we have run through all the other colors in the wheel. |
209 |
else: |
256.2.11
by Gary van der Merwe
New viz lines algorithm. Not 100% yet - but close. |
210 |
opentillparent = None |
211 |
||
212 |
if opentillparent is not None and opentillparent in revindex: |
|
213 |
parentindex = revindex[opentillparent] |
|
214 |
if parentindex > column["maxindex"]: |
|
215 |
column["maxindex"] = parentindex |
|
216 |
||
256.2.18
by Gary van der Merwe
small optimization |
217 |
for (childrevid, childindex, childbranchlineid) in children_ext: |
256.2.11
by Gary van der Merwe
New viz lines algorithm. Not 100% yet - but close. |
218 |
(childcolumnindex, childcolumn) = \ |
219 |
find_column_from_branchlineid(childbranchlineid) |
|
256.2.10
by Gary van der Merwe
Ensure that we don't give a child a same color when we don't mean to becuase we have run through all the other colors in the wheel. |
220 |
|
256.2.11
by Gary van der Merwe
New viz lines algorithm. Not 100% yet - but close. |
221 |
if index-childindex == 1 or childcolumnindex is None: |
222 |
append_line(column,childindex,index) |
|
223 |
elif childcolumnindex >= columnindex and \ |
|
224 |
has_no_nodes_between(childcolumn, childindex, index): |
|
225 |
append_line(childcolumn,childindex,index) |
|
226 |
elif childcolumnindex > columnindex and \ |
|
227 |
has_no_nodes_between(column, childindex, index): |
|
228 |
append_line(column,childindex,index) |
|
229 |
elif childcolumnindex < columnindex and \ |
|
230 |
has_no_nodes_between(column, childindex, index): |
|
231 |
append_line(column,childindex,index) |
|
232 |
elif childcolumnindex < columnindex and \ |
|
233 |
has_no_nodes_between(childcolumn, childindex, index): |
|
234 |
append_line(childcolumn,childindex,index) |
|
256.2.4
by Gary van der Merwe
First go at using bzrlib graph code |
235 |
else: |
256.2.15
by Gary van der Merwe
Make sure that we don't put lines on top of allready drawn branchlines |
236 |
append_column({"branchlineid": "line", |
256.2.11
by Gary van der Merwe
New viz lines algorithm. Not 100% yet - but close. |
237 |
"nodeindexes": [], |
238 |
"lines": [(childindex,index)], |
|
256.2.15
by Gary van der Merwe
Make sure that we don't put lines on top of allready drawn branchlines |
239 |
"maxindex": index}, childindex) |
256.2.11
by Gary van der Merwe
New viz lines algorithm. Not 100% yet - but close. |
240 |
|
241 |
for (columnindex, column) in enumerate(columns): |
|
256.2.15
by Gary van der Merwe
Make sure that we don't put lines on top of allready drawn branchlines |
242 |
if column is not None and column["maxindex"] <= index \ |
243 |
and column["branchlineid"] != "finished": |
|
256.2.12
by Gary van der Merwe
Impove the folding of the new lines |
244 |
for nodeindex in column["nodeindexes"]: |
245 |
linegraph[nodeindex][1] = (columnindex, |
|
246 |
branchlineids[nodeindex]) |
|
247 |
||
256.2.13
by Gary van der Merwe
better lines |
248 |
for (childindex, parentindex) in column["lines"]: |
249 |
notdrawnlines.append((columnindex, childindex, parentindex)) |
|
250 |
||
256.2.15
by Gary van der Merwe
Make sure that we don't put lines on top of allready drawn branchlines |
251 |
column["branchlineid"] = "finished" |
252 |
column["nodeindexes"] = [] |
|
253 |
column["lines"] = [] |
|
256.2.12
by Gary van der Merwe
Impove the folding of the new lines |
254 |
|
255 |
for (lineindex,(columnindex, childindex, parentindex))\ |
|
256 |
in enumerate(notdrawnlines): |
|
257 |
||
258 |
childnode = linegraph[childindex][1] |
|
259 |
parentnode = linegraph[parentindex][1] |
|
260 |
if childnode is not None and parentnode is not None: |
|
261 |
notdrawnlines[lineindex] = None |
|
262 |
if parentindex>childindex+1: |
|
263 |
#out from the child to line
|
|
264 |
linegraph[childindex][2].append( |
|
265 |
(childnode[0], #the column of the child |
|
266 |
columnindex, #the column of the line |
|
267 |
parentnode[1])) |
|
268 |
||
269 |
#down the line
|
|
270 |
for linepartindex in range(childindex+1, parentindex-1): |
|
271 |
linegraph[linepartindex][2].append( |
|
272 |
(columnindex, #the column of the line |
|
273 |
columnindex, #the column of the line |
|
274 |
parentnode[1])) |
|
275 |
||
276 |
#in to the parent
|
|
277 |
linegraph[parentindex-1][2].append( |
|
278 |
(columnindex, #the column of the line |
|
279 |
parentnode[0], #the column of the parent |
|
280 |
parentnode[1])) |
|
37.1.2
by Robert Collins
Make revision sorting and linking use merge_sorted from latest bzr.dev. This |
281 |
else: |
256.2.12
by Gary van der Merwe
Impove the folding of the new lines |
282 |
#child to parent
|
283 |
linegraph[childindex][2].append( |
|
284 |
(childnode[0], #the column of the child |
|
285 |
parentnode[0], #the column of the parent |
|
286 |
parentnode[1])) |
|
287 |
||
288 |
notdrawnlines = [line for line in notdrawnlines if line is not None] |
|
289 |
||
1
by Scott James Remnant
Commit the first version of bzrk. |
290 |
|
256.2.21
by Gary van der Merwe
Refactor so that line graph is more contained. |
291 |
return (linegraph, revindex, revisions) |
2
by Scott James Remnant
Split the same branch functionality out into a separate function so |
292 |
|
27
by David Allouche
refactor distances |
293 |
|
2
by Scott James Remnant
Split the same branch functionality out into a separate function so |
294 |
def same_branch(a, b): |
295 |
"""Return whether we think revisions a and b are on the same branch.""" |
|
296 |
if len(a.parent_ids) == 1: |
|
297 |
# Defacto same branch if only parent
|
|
298 |
return True |
|
299 |
elif a.committer == b.committer: |
|
300 |
# Same committer so may as well be
|
|
301 |
return True |
|
302 |
else: |
|
303 |
return False |