/b-gtk/fix-viz

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/b-gtk/fix-viz
256.2.26 by Gary van der Merwe
Use info from merge sort to draw lines. Needs work
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
256.2.25 by Gary van der Merwe
Use Merge sort
12
from bzrlib.tsort import merge_sort
256.2.26 by Gary van der Merwe
Use info from merge sort to draw lines. Needs work
13
14
def linegraph(branch, start, maxnum):
15
    """Produce a directed graph of a bzr branch.
16
256.2.28 by Gary van der Merwe
Better line drawing with info from merge_sort
17
    Returns a list of tuples of (revid,
256.2.27 by Gary van der Merwe
Show Revision No in tree
18
                                 node,
19
                                 lines,
20
                                 parents,
21
                                 children,
22
                                 revno_sequence).
256.2.26 by Gary van der Merwe
Use info from merge sort to draw lines. Needs work
23
24
    Node is a tuple of (column, colour) with column being a zero-indexed
25
    column number of the graph that this revision represents and colour
26
    being a zero-indexed colour (which doesn't specify any actual colour
27
    in particular) to draw the node in.
28
29
    Lines is a list of tuples which represent lines you should draw away
30
    from the revision, if you also need to draw lines into the revision
31
    you should use the lines list from the previous iteration.  Each
32
    typle in the list is in the form (start, end, colour) with start and
33
    end being zero-indexed column numbers and colour as in node.
34
35
    It's up to you how to actually draw the nodes and lines (straight,
36
    curved, kinked, etc.) and to pick the actual colours for each index.
37
    """
38
       
39
    mainline = branch.revision_history()
40
    graph_parents = branch.repository.get_revision_graph(start)
41
    graph_children = {}
256.2.42 by Gary van der Merwe
Performance improvements.
42
    for revid in graph_parents.iterkeys():
256.2.26 by Gary van der Merwe
Use info from merge sort to draw lines. Needs work
43
        graph_children[revid] = []
256.2.28 by Gary van der Merwe
Better line drawing with info from merge_sort
44
256.2.26 by Gary van der Merwe
Use info from merge sort to draw lines. Needs work
45
    merge_sorted_revisions = merge_sort(
46
        graph_parents,
47
        start,
48
        mainline,
49
        generate_revno=True)
50
    
256.2.28 by Gary van der Merwe
Better line drawing with info from merge_sort
51
    revid_index = {}
52
    branch_lines = {}
53
    linegraph = []    
256.2.26 by Gary van der Merwe
Use info from merge sort to draw lines. Needs work
54
    
256.2.40 by Gary van der Merwe
Take out a whole bunch of code for better performance.
55
    for (rev_index, (sequence_number,
56
                     revid,
57
                     merge_depth,
58
                     revno_sequence,
59
                     end_of_merge)) in enumerate(merge_sorted_revisions):
256.2.26 by Gary van der Merwe
Use info from merge sort to draw lines. Needs work
60
        
256.2.40 by Gary van der Merwe
Take out a whole bunch of code for better performance.
61
        revid_index[revid] = rev_index
256.2.28 by Gary van der Merwe
Better line drawing with info from merge_sort
62
        
63
        branch_id = revno_sequence[0:-1]
64
        
256.2.33 by Gary van der Merwe
Revert fast test
65
        branch_line = None
66
        if branch_id not in branch_lines:
256.2.42 by Gary van der Merwe
Performance improvements.
67
            branch_line = {"branch_id": branch_id,
256.2.38 by Gary van der Merwe
Add support for lines that go between branches.
68
                           "rev_indexes": [],
256.2.40 by Gary van der Merwe
Take out a whole bunch of code for better performance.
69
                           "min_index": rev_index,
256.2.38 by Gary van der Merwe
Add support for lines that go between branches.
70
                           "max_index": 0}
256.2.33 by Gary van der Merwe
Revert fast test
71
            branch_lines[branch_id] = branch_line
72
        else:
73
            branch_line = branch_lines[branch_id]
256.2.40 by Gary van der Merwe
Take out a whole bunch of code for better performance.
74
        branch_line["rev_indexes"].append(rev_index)
75
        if rev_index > branch_line["max_index"]:
76
            branch_line["max_index"] = rev_index
256.2.33 by Gary van der Merwe
Revert fast test
77
        
256.2.28 by Gary van der Merwe
Better line drawing with info from merge_sort
78
        parents = graph_parents[revid]
256.2.26 by Gary van der Merwe
Use info from merge sort to draw lines. Needs work
79
        for parent_revid in parents:
80
            graph_children[parent_revid].append(revid)
81
        
256.2.33 by Gary van der Merwe
Revert fast test
82
        linegraph.append([revid,
83
                          None,
256.2.27 by Gary van der Merwe
Show Revision No in tree
84
                          [],
85
                          parents,
256.2.33 by Gary van der Merwe
Revert fast test
86
                          None,
87
                          revno_sequence])
88
89
    branch_ids = branch_lines.keys()
256.2.39 by Gary van der Merwe
Tweek order that branch lines are processed for more understandable results.
90
    def branch_id_cmp(x, y):
91
        len_x = len(x)
92
        len_y = len(y)
93
        if len_x == len_y:
94
            return -cmp(x, y)
95
        return cmp(len_x, len_y)
96
        
97
    branch_ids.sort(branch_id_cmp)
256.2.40 by Gary van der Merwe
Take out a whole bunch of code for better performance.
98
    lines = []
256.2.42 by Gary van der Merwe
Performance improvements.
99
    empty_column = [False for i in range(len(graph_parents))]
256.2.44 by Gary van der Merwe
Chose what column to place nodes and lines in better.
100
    columns = [list(empty_column)]
256.2.42 by Gary van der Merwe
Performance improvements.
101
    
256.2.38 by Gary van der Merwe
Add support for lines that go between branches.
102
    
103
    for branch_id in branch_ids:
104
        branch_line = branch_lines[branch_id]
105
        
256.2.44 by Gary van der Merwe
Chose what column to place nodes and lines in better.
106
        parent_col_index = 0
107
        if len(branch_id) > 1:
108
            parent_branch_id = branch_id[0:-2]
109
            parent_col_index = branch_lines[parent_branch_id]["col_index"]
110
        
256.2.42 by Gary van der Merwe
Performance improvements.
111
        branch_line["col_index"] = append_line(columns,
112
                                               (branch_line["min_index"],
113
                                                branch_line["max_index"]),
256.2.44 by Gary van der Merwe
Chose what column to place nodes and lines in better.
114
                                               empty_column,
115
                                               parent_col_index)
256.2.33 by Gary van der Merwe
Revert fast test
116
        color = reduce(lambda x, y: x+y, branch_id, 0)
117
        col_index = branch_line["col_index"]
256.2.40 by Gary van der Merwe
Take out a whole bunch of code for better performance.
118
        node = (col_index, color)        
256.2.33 by Gary van der Merwe
Revert fast test
119
        
120
        for rev_index in branch_line["rev_indexes"]:
121
            (sequence_number,
122
                 revid,
123
                 merge_depth,
124
                 revno_sequence,
125
                 end_of_merge) = merge_sorted_revisions[rev_index]
126
            
127
            linegraph[rev_index][1] = node
256.2.40 by Gary van der Merwe
Take out a whole bunch of code for better performance.
128
            linegraph[rev_index][4] = graph_children[revid]
129
            
130
            for parent_revid in graph_parents[revid]:
131
                if parent_revid in revid_index:
132
                    parent_index = revid_index[parent_revid]
133
                    parent_revno = merge_sorted_revisions[parent_index][3]
134
                    parent_branch_id = parent_revno[0:-1]
256.2.42 by Gary van der Merwe
Performance improvements.
135
                    col_index = None
256.2.40 by Gary van der Merwe
Take out a whole bunch of code for better performance.
136
                    if branch_id != parent_branch_id and \
137
                                    parent_index - rev_index > 1:
256.2.42 by Gary van der Merwe
Performance improvements.
138
                        col_index = append_line(columns,
256.2.44 by Gary van der Merwe
Chose what column to place nodes and lines in better.
139
                                                (rev_index+1, parent_index-1),
140
                                                empty_column,
141
                                                branch_line["col_index"])
256.2.42 by Gary van der Merwe
Performance improvements.
142
                    lines.append((rev_index, parent_index, col_index))
256.2.40 by Gary van der Merwe
Take out a whole bunch of code for better performance.
143
    
256.2.42 by Gary van der Merwe
Performance improvements.
144
    for (child_index, parent_index, line_col_index) in lines:
145
        child_col_index = linegraph[child_index][1][0]
146
        
256.2.40 by Gary van der Merwe
Take out a whole bunch of code for better performance.
147
        parent_node = linegraph[parent_index][1]
148
        parent_col_index = parent_node[0]
149
        color = parent_node[1]
150
        
256.2.42 by Gary van der Merwe
Performance improvements.
151
        if line_col_index:
256.2.40 by Gary van der Merwe
Take out a whole bunch of code for better performance.
152
            linegraph[child_index][2].append(
153
                (child_col_index,
154
                 line_col_index,
155
                 color))
156
            for line_part_index in range(child_index+1, parent_index-1):
157
                linegraph[line_part_index][2].append(
158
                    (line_col_index,   
159
                     line_col_index,
160
                     color))
161
            linegraph[parent_index-1][2].append(
162
                (line_col_index,
163
                 parent_col_index,
164
                 color))
165
        else:
166
            linegraph[child_index][2].append(
167
                (child_col_index,
168
                 parent_col_index,
169
                 color))
170
            for line_part_index in range(child_index+1, parent_index):
171
                linegraph[line_part_index][2].append(
172
                    (parent_col_index,   
173
                     parent_col_index,
174
                     color))
175
                    
256.2.28 by Gary van der Merwe
Better line drawing with info from merge_sort
176
    
177
    return (linegraph, revid_index)
256.2.26 by Gary van der Merwe
Use info from merge sort to draw lines. Needs work
178
256.2.44 by Gary van der Merwe
Chose what column to place nodes and lines in better.
179
def append_line(columns, line, empty_column, starting_col_index):
256.2.42 by Gary van der Merwe
Performance improvements.
180
    line_range = range(line[0], line[1]+1)
256.2.44 by Gary van der Merwe
Chose what column to place nodes and lines in better.
181
    col_order = range(starting_col_index, -1, -1) + \
182
                range(starting_col_index+1, len(columns))
183
    for col_index in col_order:
184
        column = columns[col_index]
256.2.40 by Gary van der Merwe
Take out a whole bunch of code for better performance.
185
        has_overlaping_line = False
256.2.42 by Gary van der Merwe
Performance improvements.
186
        for row_index in line_range:
187
            if column[row_index]:
256.2.40 by Gary van der Merwe
Take out a whole bunch of code for better performance.
188
                has_overlaping_line = True
189
                break
190
        if not has_overlaping_line:
191
            break
192
    else:
193
        col_index = len(columns)
256.2.42 by Gary van der Merwe
Performance improvements.
194
        column = list(empty_column)
195
        columns.append(column)
256.2.40 by Gary van der Merwe
Take out a whole bunch of code for better performance.
196
    
256.2.42 by Gary van der Merwe
Performance improvements.
197
    for row_index in line_range:
198
        column[row_index] = True
199
    return col_index
256.2.26 by Gary van der Merwe
Use info from merge sort to draw lines. Needs work
200
201
def same_branch(a, b):
202
    """Return whether we think revisions a and b are on the same branch."""
203
    if len(a.parent_ids) == 1:
204
        # Defacto same branch if only parent
205
        return True
206
    elif a.committer == b.committer:
207
        # Same committer so may as well be
208
        return True
209
    else:
210
        return False