/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 = {}
42
    for revid in graph_parents.keys():
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
    revno_index = {}
53
    branch_lines = {}
54
    linegraph = []    
256.2.26 by Gary van der Merwe
Use info from merge sort to draw lines. Needs work
55
    
56
    for (index, (sequence_number,
57
                 revid,
58
                 merge_depth,
59
                 revno_sequence,
60
                 end_of_merge)) in enumerate(merge_sorted_revisions):
61
        
256.2.28 by Gary van der Merwe
Better line drawing with info from merge_sort
62
        revid_index[revid] = index
63
        revno_index[revno_sequence] = index
64
        
65
        branch_id = revno_sequence[0:-1]
66
        
67
        branch_line = None
68
        if branch_id not in branch_lines:
69
            branch_line = {}
70
            branch_lines[branch_id] = branch_line
71
            branch_line["rev_indexes"] = []
72
            branch_line["min_index"] = index - 1            
73
            branch_line["max_index"] = 0
74
        else:
75
            branch_line = branch_lines[branch_id]
76
        branch_line["rev_indexes"].append(index)
77
        
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.28 by Gary van der Merwe
Better line drawing with info from merge_sort
82
        linegraph.append([revid,
83
                          None,
256.2.27 by Gary van der Merwe
Show Revision No in tree
84
                          [],
85
                          parents,
256.2.28 by Gary van der Merwe
Better line drawing with info from merge_sort
86
                          None,
87
                          revno_sequence])
88
89
    branch_ids = branch_lines.keys()
90
    branch_ids.sort()
91
    columns = []
92
    
93
    for branch_id in branch_ids:
94
        branch_line = branch_lines[branch_id]
95
        branch_line["inward_line_ends"] = []
96
        for rev_index in branch_line["rev_indexes"]:
97
            (sequence_number,
98
                 revid,
99
                 merge_depth,
100
                 revno_sequence,
101
                 end_of_merge) = merge_sorted_revisions[rev_index]
102
            for parent_revid in graph_parents[revid]:
103
                if parent_revid in revid_index:
104
                    parent_index = revid_index[parent_revid]
105
                    parent_merge_depth = merge_sorted_revisions[parent_index][2]
106
                    if parent_merge_depth < merge_depth:
107
                        branch_line["inward_line_ends"].append(parent_index)
108
                        if branch_line["max_index"] < parent_index:
109
                            branch_line["max_index"] =parent_index
110
            
111
            for child_revid in graph_children[revid]:
112
                if child_revid in revid_index:
113
                    child_index = revid_index[child_revid]
114
                    child_merge_depth = merge_sorted_revisions[child_index][2]
115
                    if child_merge_depth < merge_depth:
116
                        branch_line["inward_line_ends"].append(child_index)
117
        
118
        col_index = None
119
        start_col_index = 0
120
        if branch_id:
121
            start_col_index = branch_lines[branch_id[0:-2]]["col_index"]+1
122
        for col_search_index in range(start_col_index,len(columns)):
123
            column = columns[col_search_index]
124
            clashing_lines = []
125
            for line in column:
126
                if (line["min_index"] <= branch_line["min_index"] and \
127
                    line["max_index"] >  branch_line["min_index"]) or \
128
                   (line["max_index"] >= branch_line["max_index"] and \
129
                    line["min_index"] <  branch_line["max_index"]):
130
                        clashing_lines.append(line)
131
            
132
            if not clashing_lines:
133
                col_index = col_search_index
134
                break
135
        
136
        if not col_index:
137
            col_index = len(columns)
138
            columns.append([])
139
        
140
        columns[col_index].append(branch_line)
141
        branch_line["col_index"] = col_index
142
143
144
    for branch_id in branch_ids:
145
        branch_line = branch_lines[branch_id]
146
        color = reduce(lambda x, y: x+y, branch_id, 0)
147
        col_index = branch_line["col_index"]
148
        node = (col_index, color)
149
        
150
        for rev_index in branch_line["rev_indexes"]:
151
            (sequence_number,
152
                 revid,
153
                 merge_depth,
154
                 revno_sequence,
155
                 end_of_merge) = merge_sorted_revisions[rev_index]
156
            children = graph_children[revid]
157
            
158
            linegraph[rev_index][1] = node
159
            linegraph[rev_index][4] = children
160
            for child_revid in children:
161
                if child_revid in revid_index:
162
                    child_index = revid_index[child_revid]
163
                    child_revno_sequence = \
164
                                        merge_sorted_revisions[child_index][3]
165
                    child_merge_depth = merge_sorted_revisions[child_index][2]
166
                    child_branch_id = child_revno_sequence[0:-1]
167
                    child_col_index = branch_lines[child_branch_id]["col_index"]
168
                    if child_merge_depth < merge_depth:
169
                        #out from the child to line
170
                        linegraph[child_index][2].append(
171
                            (child_col_index,
172
                             col_index,
173
                             color))
174
                        for line_part_index in range(child_index+1, rev_index):
175
                            linegraph[line_part_index][2].append(
176
                                (col_index,
177
                                 col_index,
178
                                 color))
179
                    else:
180
                        for line_part_index in range(child_index, rev_index-1):
181
                            linegraph[line_part_index][2].append(
182
                                (child_col_index,   
183
                                 child_col_index,
184
                                 color))
185
186
                        linegraph[rev_index-1][2].append(
187
                            (child_col_index,
188
                             col_index,
189
                             color))
190
    
191
    return (linegraph, revid_index)
256.2.26 by Gary van der Merwe
Use info from merge sort to draw lines. Needs work
192
193
194
def same_branch(a, b):
195
    """Return whether we think revisions a and b are on the same branch."""
196
    if len(a.parent_ids) == 1:
197
        # Defacto same branch if only parent
198
        return True
199
    elif a.committer == b.committer:
200
        # Same committer so may as well be
201
        return True
202
    else:
203
        return False