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