43
42
    It's up to you how to actually draw the nodes and lines (straight,
 
44
43
    curved, kinked, etc.) and to pick the actual colours for each index.
 
46
 
    assert isinstance(start_revs, list)
 
47
 
    def update_root_progress(step_number):
 
48
 
        """IFF our container received a root progress bar, then update it."""
 
49
 
        if root_progress is not None:
 
50
 
            root_progress.update(None, step_number)
 
 
46
    graph = repository.get_graph()
 
54
49
    graph_children = {}
 
55
 
    update_root_progress(1)
 
56
 
    progress_bar = ui.ui_factory.nested_progress_bar()
 
58
 
        progress_bar.update("Arranging tree fragments")
 
59
 
        for i, (revid, parent_revids) in enumerate(graph.iter_ancestry(start_revs)):
 
62
 
            if parent_revids is None:
 
65
 
            if parent_revids == (NULL_REVISION,):
 
66
 
                graph_parents[revid] = ()
 
68
 
                graph_parents[revid] = parent_revids
 
69
 
            for parent in parent_revids:
 
70
 
                graph_children.setdefault(parent, []).append(revid)
 
71
 
            graph_children.setdefault(revid, [])
 
73
 
        progress_bar.finished()
 
75
 
    update_root_progress(2)
 
76
 
    progress_bar = ui.ui_factory.nested_progress_bar()
 
78
 
        progress_bar.update("Removing ghosts", 0, len(ghosts))
 
79
 
        for i, ghost in enumerate(ghosts):
 
81
 
                progress_bar.update(None, i)
 
82
 
            for ghost_child in graph_children[ghost]:
 
83
 
                graph_parents[ghost_child] = [p for p in graph_parents[ghost_child]
 
86
 
        progress_bar.finished()
 
 
50
    for (revid, parent_revids) in graph.iter_ancestry(start_revs):
 
 
51
        if parent_revids is None:
 
 
54
        if parent_revids == (NULL_REVISION,):
 
 
55
            graph_parents[revid] = ()
 
 
57
            graph_parents[revid] = parent_revids
 
 
58
        for parent in parent_revids:
 
 
59
            graph_children.setdefault(parent, []).append(revid)
 
 
60
        graph_children.setdefault(revid, [])
 
 
62
        for ghost_child in graph_children[ghost]:
 
 
63
            graph_parents[ghost_child] = [p for p in graph_parents[ghost_child]
 
87
65
    graph_parents["top:"] = start_revs
 
89
67
    if len(graph_parents)>0:
 
 
112
90
    # and these two revisions will be in the same branch line. Each value is
 
113
91
    # a list of rev_indexes in the branch.
 
118
 
    update_root_progress(3)
 
119
 
    progress_bar = ui.ui_factory.nested_progress_bar()
 
121
 
        progress_bar.update("Finding nodes", 0, len(merge_sorted_revisions))
 
122
 
        for (rev_index, (sequence_number,
 
126
 
                         end_of_merge)) in enumerate(merge_sorted_revisions):
 
128
 
            if rev_index % 25 == 0:
 
129
 
                progress_bar.update(None, rev_index)
 
130
 
            if maxnum and rev_index >= maxnum:
 
132
 
            revid_index[revid] = rev_index
 
134
 
            parents = graph_parents[revid]
 
135
 
            linegraph.append([revid,
 
143
 
                revno_index[revno_sequence] = rev_index
 
145
 
                branch_id = revno_sequence[0:-1]
 
148
 
                if branch_id not in branch_lines:
 
150
 
                    branch_lines[branch_id] = branch_line
 
152
 
                    branch_line = branch_lines[branch_id]
 
154
 
                branch_line.append(rev_index)
 
156
 
        progress_bar.finished()
 
 
96
    for (rev_index, (sequence_number,
 
 
100
                     end_of_merge)) in enumerate(merge_sorted_revisions):
 
 
101
        if maxnum and rev_index >= maxnum:
 
 
103
        revid_index[revid] = rev_index
 
 
105
        parents = graph_parents[revid]
 
 
106
        linegraph.append([revid,
 
 
114
            revno_index[revno_sequence] = rev_index
 
 
116
            branch_id = revno_sequence[0:-1]
 
 
119
            if branch_id not in branch_lines:
 
 
121
                branch_lines[branch_id] = branch_line
 
 
123
                branch_line = branch_lines[branch_id]
 
 
125
            branch_line.append(rev_index)        
 
159
128
        branch_ids = branch_lines.keys()
 
161
130
        def branch_id_cmp(x, y):
 
162
131
            """Compaire branch_id's first by the number of digits, then reversed
 
163
132
            by their value"""
 
 
179
148
        # cell allready contains a node or line. This use when deciding what column
 
180
149
        # to place a branch line or line in, without it overlaping something else.
 
181
150
        columns = [list(empty_column)]
 
184
 
        update_root_progress(4)
 
185
 
        progress_bar = ui.ui_factory.nested_progress_bar()
 
187
 
            progress_bar.update("Organizing edges", 0, len(branch_ids))
 
188
 
            for i, branch_id in enumerate(branch_ids):
 
190
 
                    progress_bar.update(None, i)
 
191
 
                branch_line = branch_lines[branch_id]
 
193
 
                # Find the col_index for the direct parent branch. This will be the
 
194
 
                # starting point when looking for a free column.
 
197
 
                if len(branch_id) > 1:
 
198
 
                    parent_revno = branch_id[0:-1]
 
199
 
                    if parent_revno in revno_index:
 
200
 
                        parent_index = revno_index[parent_revno]
 
 
153
        for branch_id in branch_ids:
 
 
154
            branch_line = branch_lines[branch_id]
 
 
156
            # Find the col_index for the direct parent branch. This will be the
 
 
157
            # starting point when looking for a free column.
 
 
160
            if len(branch_id) > 1:
 
 
161
                parent_revno = branch_id[0:-1]
 
 
162
                if parent_revno in revno_index:
 
 
163
                    parent_index = revno_index[parent_revno]
 
 
164
                    parent_node = linegraph[parent_index][1]
 
 
166
                        parent_col_index = parent_node[0]
 
 
169
            col_search_order = _branch_line_col_search_order(columns,
 
 
171
            color = reduce(lambda x, y: x+y, branch_id, 0)
 
 
175
            last_rev_index = None
 
 
176
            for rev_index in branch_line:
 
 
178
                    if broken_line_length and \
 
 
179
                       rev_index - last_rev_index > broken_line_length:
 
 
180
                        line_range.append(last_rev_index+1)
 
 
181
                        line_range.append(rev_index-1)
 
 
183
                        line_range.extend(range(last_rev_index+1, rev_index))
 
 
185
                line_range.append(rev_index)
 
 
186
                last_rev_index = rev_index
 
 
189
                if broken_line_length and \
 
 
190
                   parent_index - last_rev_index > broken_line_length:
 
 
191
                    line_range.append(last_rev_index+1)
 
 
193
                    line_range.extend(range(last_rev_index+1, parent_index))
 
 
195
            col_index = _find_free_column(columns,
 
 
199
            node = (col_index, color)
 
 
200
            for rev_index in branch_line:
 
 
201
                linegraph[rev_index][1] = node
 
 
202
                columns[col_index][rev_index] = True
 
 
204
            for rev_index in branch_line:
 
 
209
                     end_of_merge) = merge_sorted_revisions[rev_index]
 
 
211
                linegraph[rev_index][4] = graph_children[revid]
 
 
212
                col_index = linegraph[rev_index][1][0]
 
 
214
                for parent_revid in graph_parents[revid]:
 
 
215
                    if parent_revid in revid_index:
 
 
217
                        parent_index = revid_index[parent_revid]                            
 
201
218
                        parent_node = linegraph[parent_index][1]
 
203
220
                            parent_col_index = parent_node[0]
 
206
 
                col_search_order = _branch_line_col_search_order(columns,
 
208
 
                color = reduce(lambda x, y: x+y, branch_id, 0)
 
212
 
                last_rev_index = None
 
213
 
                for rev_index in branch_line:
 
215
 
                        if broken_line_length and \
 
216
 
                           rev_index - last_rev_index > broken_line_length:
 
217
 
                            line_range.append(last_rev_index+1)
 
218
 
                            line_range.append(rev_index-1)
 
220
 
                            line_range.extend(range(last_rev_index+1, rev_index))
 
222
 
                    line_range.append(rev_index)
 
223
 
                    last_rev_index = rev_index
 
226
 
                    if broken_line_length and \
 
227
 
                       parent_index - last_rev_index > broken_line_length:
 
228
 
                        line_range.append(last_rev_index+1)
 
230
 
                        line_range.extend(range(last_rev_index+1, parent_index))
 
232
 
                col_index = _find_free_column(columns,
 
236
 
                node = (col_index, color)
 
237
 
                for rev_index in branch_line:
 
238
 
                    linegraph[rev_index][1] = node
 
239
 
                    columns[col_index][rev_index] = True
 
241
 
                for rev_index in branch_line:
 
246
 
                         end_of_merge) = merge_sorted_revisions[rev_index]
 
248
 
                    linegraph[rev_index][4] = graph_children[revid]
 
249
 
                    col_index = linegraph[rev_index][1][0]
 
251
 
                    for parent_revid in graph_parents[revid]:
 
252
 
                        if parent_revid in revid_index:
 
254
 
                            parent_index = revid_index[parent_revid]
 
255
 
                            parent_node = linegraph[parent_index][1]
 
257
 
                                parent_col_index = parent_node[0]
 
259
 
                                parent_col_index = None
 
 
222
                            parent_col_index = None
 
 
224
                                _line_col_search_order(columns,
 
 
228
                        # If this line is really long, break it.
 
 
229
                        if len(branch_id) > 0 and \
 
 
230
                           broken_line_length and \
 
 
231
                           parent_index - rev_index > broken_line_length:
 
 
232
                            child_line_col_index = \
 
 
233
                                _find_free_column(columns,
 
 
237
                            _mark_column_as_used(columns,
 
 
238
                                                 child_line_col_index,
 
 
241
                            # Recall _line_col_search_order to reset it back to
 
260
243
                            col_search_order = \
 
261
244
                                    _line_col_search_order(columns,
 
262
245
                                                           parent_col_index,
 
265
 
                            # If this line is really long, break it.
 
266
 
                            if len(branch_id) > 0 and \
 
267
 
                               broken_line_length and \
 
268
 
                               parent_index - rev_index > broken_line_length:
 
269
 
                                child_line_col_index = \
 
270
 
                                    _find_free_column(columns,
 
274
 
                                _mark_column_as_used(columns,
 
275
 
                                                     child_line_col_index,
 
278
 
                                # Recall _line_col_search_order to reset it back to
 
281
 
                                        _line_col_search_order(columns,
 
284
 
                                parent_col_line_index = \
 
285
 
                                    _find_free_column(columns,
 
289
 
                                _mark_column_as_used(columns,
 
290
 
                                                     parent_col_line_index,
 
292
 
                                lines.append((rev_index,
 
294
 
                                              (child_line_col_index,
 
295
 
                                               parent_col_line_index)))
 
297
 
                                line_col_index = col_index
 
298
 
                                if parent_index - rev_index >1:
 
299
 
                                    line_range = range(rev_index + 1, parent_index)
 
301
 
                                        _find_free_column(columns,
 
305
 
                                    _mark_column_as_used(columns,
 
308
 
                                lines.append((rev_index,
 
312
 
            progress_bar.finished()
 
314
 
        update_root_progress(5)
 
315
 
        progress_bar = ui.ui_factory.nested_progress_bar()
 
317
 
            progress_bar.update("Prettifying graph", 0, len(lines))
 
318
 
            for i, (child_index, parent_index, line_col_indexes) in enumerate(lines):
 
320
 
                    progress_bar.update(None, i)
 
321
 
                (child_col_index, child_color) = linegraph[child_index][1]
 
322
 
                (parent_col_index, parent_color) = linegraph[parent_index][1]
 
324
 
                if len(line_col_indexes) == 1:
 
325
 
                    if parent_index - child_index == 1:
 
326
 
                        linegraph[child_index][2].append(
 
331
 
                        # line from the child's column to the lines column
 
332
 
                        linegraph[child_index][2].append(
 
336
 
                        # lines down the line's column
 
337
 
                        for line_part_index in range(child_index+1, parent_index-1):
 
338
 
                            linegraph[line_part_index][2].append(
 
339
 
                                (line_col_indexes[0], 
 
342
 
                        # line from the line's column to the parent's column
 
343
 
                        linegraph[parent_index-1][2].append(
 
344
 
                            (line_col_indexes[0],
 
 
247
                            parent_col_line_index = \
 
 
248
                                _find_free_column(columns,
 
 
252
                            _mark_column_as_used(columns,
 
 
253
                                                 parent_col_line_index,
 
 
255
                            lines.append((rev_index,
 
 
257
                                          (child_line_col_index,
 
 
258
                                           parent_col_line_index)))
 
 
260
                            line_col_index = col_index
 
 
261
                            if parent_index - rev_index >1:
 
 
262
                                line_range = range(rev_index + 1, parent_index)
 
 
264
                                    _find_free_column(columns,
 
 
268
                                _mark_column_as_used(columns,
 
 
271
                            lines.append((rev_index,
 
 
275
        for (child_index, parent_index, line_col_indexes) in lines:
 
 
276
            (child_col_index, child_color) = linegraph[child_index][1]
 
 
277
            (parent_col_index, parent_color) = linegraph[parent_index][1]
 
 
279
            if len(line_col_indexes) == 1:
 
 
280
                if parent_index - child_index == 1:
 
 
281
                    linegraph[child_index][2].append(
 
349
286
                    # line from the child's column to the lines column
 
350
287
                    linegraph[child_index][2].append(
 
351
288
                        (child_col_index,
 
352
289
                         line_col_indexes[0],
 
355
 
                    linegraph[child_index+1][2].append(
 
356
 
                        (line_col_indexes[0],
 
361
 
                    linegraph[parent_index-2][2].append(
 
 
291
                    # lines down the line's column
 
 
292
                    for line_part_index in range(child_index+1, parent_index-1):
 
 
293
                        linegraph[line_part_index][2].append(
 
 
294
                            (line_col_indexes[0],   
 
365
297
                    # line from the line's column to the parent's column
 
366
298
                    linegraph[parent_index-1][2].append(
 
367
 
                        (line_col_indexes[1],
 
 
299
                        (line_col_indexes[0],
 
368
300
                         parent_col_index,
 
371
 
            progress_bar.finished()
 
 
304
                # line from the child's column to the lines column
 
 
305
                linegraph[child_index][2].append(
 
 
310
                linegraph[child_index+1][2].append(
 
 
311
                    (line_col_indexes[0],
 
 
316
                linegraph[parent_index-2][2].append(
 
 
320
                # line from the line's column to the parent's column
 
 
321
                linegraph[parent_index-1][2].append(
 
 
322
                    (line_col_indexes[1],
 
372
325
        return (linegraph, revid_index, len(columns))
 
374
327
        return (linegraph, revid_index, 0)
 
377
330
def _branch_line_col_search_order(columns, parent_col_index):
 
378
331
    for col_index in range(parent_col_index, len(columns)):