コード例 #1
0
ファイル: test_tsort.py プロジェクト: c0ns0le/cygwin
 def assertSortAndIterate(self, graph, branch_tip, result_list,
         generate_revno, mainline_revisions=None):
     """Check that merge based sorting and iter_topo_order on graph works."""
     value = merge_sort(graph, branch_tip,
                        mainline_revisions=mainline_revisions,
                        generate_revno=generate_revno)
     if result_list != value:
         import pprint
         self.assertEqualDiff(pprint.pformat(result_list),
                              pprint.pformat(value))
     self.assertEquals(result_list,
         merge_sort(graph, branch_tip, mainline_revisions=mainline_revisions,
             generate_revno=generate_revno))
     self.assertEqual(result_list,
         list(MergeSorter(
             graph,
             branch_tip,
             mainline_revisions=mainline_revisions,
             generate_revno=generate_revno,
             ).iter_topo_order()))
コード例 #2
0
 def merge_sort(self, tip_key):
     """Compute the merge sorted graph output."""
     from bzrlib import tsort
     as_parent_map = dict((node.key, node.parent_keys)
                          for node in self._nodes.itervalues()
                           if node.parent_keys is not None)
     # We intentionally always generate revnos and never force the
     # mainline_revisions
     # Strip the sequence_number that merge_sort generates
     return [_MergeSortNode(key, merge_depth, revno, end_of_merge)
             for _, key, merge_depth, revno, end_of_merge
              in tsort.merge_sort(as_parent_map, tip_key,
                                  mainline_revisions=None,
                                  generate_revno=True)]
コード例 #3
0
 def assertSortAndIterate(self,
                          graph,
                          branch_tip,
                          result_list,
                          generate_revno,
                          mainline_revisions=None):
     """Check that merge based sorting and iter_topo_order on graph works."""
     value = merge_sort(graph,
                        branch_tip,
                        mainline_revisions=mainline_revisions,
                        generate_revno=generate_revno)
     if result_list != value:
         self.assertEqualDiff(pprint.pformat(result_list),
                              pprint.pformat(value))
     self.assertEqual(
         result_list,
         list(
             MergeSorter(
                 graph,
                 branch_tip,
                 mainline_revisions=mainline_revisions,
                 generate_revno=generate_revno,
             ).iter_topo_order()))
コード例 #4
0
ファイル: linegraph.py プロジェクト: jelmer/bzr-gtk
def linegraph(graph, start_revs, maxnum=None, broken_line_length=None,
              graph_data=True, mainline_only=False, root_progress=None):
    """Produce a directed graph of a bzr repository.

    Returns a tuple of (line_graph, revid_index, columns_len) where
    * line_graph is a list of tuples of (revid,
                                         node,
                                         lines,
                                         parents,
                                         children,
                                         revno_sequence),
    * revid_index is a dict of each revision with the key being the revid, and
      the value the row index, and
    * columns_len is the number of columns need to draw the line graph.


    Node is a tuple of (column, colour) with column being a zero-indexed
    column number of the graph that this revision represents and colour
    being a zero-indexed colour (which doesn't specify any actual colour
    in particular) to draw the node in.

    Lines is a list of tuples which represent lines you should draw away
    from the revision, if you also need to draw lines into the revision
    you should use the lines list from the previous iteration.  Each
    typle in the list is in the form (start, end, colour) with start and
    end being zero-indexed column numbers and colour as in node.

    It's up to you how to actually draw the nodes and lines (straight,
    curved, kinked, etc.) and to pick the actual colours for each index.
    """
    assert isinstance(start_revs, list)
    def update_root_progress(step_number):
        """IFF our container received a root progress bar, then update it."""
        if root_progress is not None:
            root_progress.update(None, step_number)

    graph_parents = {}
    ghosts = set()
    graph_children = {}
    update_root_progress(1)
    progress_bar = ui.ui_factory.nested_progress_bar()
    try:
        progress_bar.update("Arranging tree fragments")
        for i, (revid, parent_revids) in enumerate(graph.iter_ancestry(start_revs)):
            if i % 25 == 0:
                progress_bar.tick()
            if parent_revids is None:
                ghosts.add(revid)
                continue
            if parent_revids == (NULL_REVISION,):
                graph_parents[revid] = ()
            else:
                graph_parents[revid] = parent_revids
            for parent in parent_revids:
                graph_children.setdefault(parent, []).append(revid)
            graph_children.setdefault(revid, [])
    finally:
        progress_bar.finished()

    update_root_progress(2)
    progress_bar = ui.ui_factory.nested_progress_bar()
    try:
        progress_bar.update("Removing ghosts", 0, len(ghosts))
        for i, ghost in enumerate(ghosts):
            if i % 25 == 0:
                progress_bar.update(None, i)
            for ghost_child in graph_children[ghost]:
                graph_parents[ghost_child] = [p for p in graph_parents[ghost_child]
                                              if p not in ghosts]
    finally:
        progress_bar.finished()
    graph_parents["top:"] = start_revs

    if len(graph_parents)>0:
        merge_sorted_revisions = merge_sort(
            graph_parents,
            "top:",
            generate_revno=True)
    else:
        merge_sorted_revisions = ()

    if mainline_only:
        merge_sorted_revisions = [elem for elem in merge_sorted_revisions \
                                  if len(elem[3])==1 ]

    assert merge_sorted_revisions[0][1] == "top:"
    merge_sorted_revisions = merge_sorted_revisions[1:]

    revid_index = {}
    revno_index = {}

    # This will hold an item for each "branch". For a revisions, the revsion
    # number less the least significant digit is the branch_id, and used as the
    # key for the dict. Hence revision with the same revsion number less the
    # least significant digit are considered to be in the same branch line.
    # e.g.: for revisions 290.12.1 and 290.12.2, the branch_id would be 290.12,
    # and these two revisions will be in the same branch line. Each value is
    # a list of rev_indexes in the branch.
    branch_lines = {}

    linegraph = []

    update_root_progress(3)
    progress_bar = ui.ui_factory.nested_progress_bar()
    try:
        progress_bar.update("Finding nodes", 0, len(merge_sorted_revisions))
        for (rev_index, (sequence_number,
                         revid,
                         merge_depth,
                         revno_sequence,
                         end_of_merge)) in enumerate(merge_sorted_revisions):

            if rev_index % 25 == 0:
                progress_bar.update(None, rev_index)
            if maxnum and rev_index >= maxnum:
                break
            revid_index[revid] = rev_index

            parents = graph_parents[revid]
            linegraph.append([revid,
                              None,
                              [],
                              parents,
                              None,
                              revno_sequence])

            if graph_data:
                revno_index[revno_sequence] = rev_index

                branch_id = revno_sequence[0:-1]

                branch_line = None
                if branch_id not in branch_lines:
                    branch_line = []
                    branch_lines[branch_id] = branch_line
                else:
                    branch_line = branch_lines[branch_id]

                branch_line.append(rev_index)
    finally:
        progress_bar.finished()

    if graph_data:
        branch_ids = branch_lines.keys()

        def branch_id_cmp(x, y):
            """Compaire branch_id's first by the number of digits, then reversed
            by their value"""
            len_x = len(x)
            len_y = len(y)
            if len_x == len_y:
                return -cmp(x, y)
            return cmp(len_x, len_y)

        branch_ids.sort(branch_id_cmp)
        # This will hold a tuple of (child_index, parent_index, col_index) for each
        # line that needs to be drawn. If col_index is not none, then the line is
        # drawn along that column, else the the line can be drawn directly between
        # the child and parent because either the child and parent are in the same
        # branch line, or the child and parent are 1 row apart.
        lines = []
        empty_column = [False for i in range(len(graph_parents))]
        # This will hold a bit map for each cell. If the cell is true, then the
        # cell allready contains a node or line. This use when deciding what column
        # to place a branch line or line in, without it overlaping something else.
        columns = [list(empty_column)]


        update_root_progress(4)
        progress_bar = ui.ui_factory.nested_progress_bar()
        try:
            progress_bar.update("Organizing edges", 0, len(branch_ids))
            for i, branch_id in enumerate(branch_ids):
                if i % 25 == 0:
                    progress_bar.update(None, i)
                branch_line = branch_lines[branch_id]

                # Find the col_index for the direct parent branch. This will be the
                # starting point when looking for a free column.
                parent_col_index = 0
                parent_index = None
                if len(branch_id) > 1:
                    parent_revno = branch_id[0:-1]
                    if parent_revno in revno_index:
                        parent_index = revno_index[parent_revno]
                        parent_node = linegraph[parent_index][1]
                        if parent_node:
                            parent_col_index = parent_node[0]


                col_search_order = _branch_line_col_search_order(columns,
                                                                 parent_col_index)
                color = reduce(lambda x, y: x+y, branch_id, 0)
                cur_cont_line = []

                line_range = []
                last_rev_index = None
                for rev_index in branch_line:
                    if last_rev_index:
                        if broken_line_length and \
                           rev_index - last_rev_index > broken_line_length:
                            line_range.append(last_rev_index+1)
                            line_range.append(rev_index-1)
                        else:
                            line_range.extend(range(last_rev_index+1, rev_index))

                    line_range.append(rev_index)
                    last_rev_index = rev_index

                if parent_index:
                    if broken_line_length and \
                       parent_index - last_rev_index > broken_line_length:
                        line_range.append(last_rev_index+1)
                    else:
                        line_range.extend(range(last_rev_index+1, parent_index))

                col_index = _find_free_column(columns,
                                              empty_column,
                                              col_search_order,
                                              line_range)
                node = (col_index, color)
                for rev_index in branch_line:
                    linegraph[rev_index][1] = node
                    columns[col_index][rev_index] = True

                for rev_index in branch_line:
                    (sequence_number,
                         revid,
                         merge_depth,
                         revno_sequence,
                         end_of_merge) = merge_sorted_revisions[rev_index]

                    linegraph[rev_index][4] = graph_children[revid]
                    col_index = linegraph[rev_index][1][0]

                    for parent_revid in graph_parents[revid]:
                        if parent_revid in revid_index:

                            parent_index = revid_index[parent_revid]
                            parent_node = linegraph[parent_index][1]
                            if parent_node:
                                parent_col_index = parent_node[0]
                            else:
                                parent_col_index = None
                            col_search_order = \
                                    _line_col_search_order(columns,
                                                           parent_col_index,
                                                           col_index)

                            # If this line is really long, break it.
                            if len(branch_id) > 0 and \
                               broken_line_length and \
                               parent_index - rev_index > broken_line_length:
                                child_line_col_index = \
                                    _find_free_column(columns,
                                                      empty_column,
                                                      col_search_order,
                                                      (rev_index + 1,))
                                _mark_column_as_used(columns,
                                                     child_line_col_index,
                                                     (rev_index + 1,))

                                # Recall _line_col_search_order to reset it back to
                                # the beging.
                                col_search_order = \
                                        _line_col_search_order(columns,
                                                               parent_col_index,
                                                               col_index)
                                parent_col_line_index = \
                                    _find_free_column(columns,
                                                      empty_column,
                                                      col_search_order,
                                                      (parent_index - 1,))
                                _mark_column_as_used(columns,
                                                     parent_col_line_index,
                                                     (parent_index - 1,))
                                lines.append((rev_index,
                                              parent_index,
                                              (child_line_col_index,
                                               parent_col_line_index)))
                            else :
                                line_col_index = col_index
                                if parent_index - rev_index >1:
                                    line_range = range(rev_index + 1, parent_index)
                                    line_col_index = \
                                        _find_free_column(columns,
                                                          empty_column,
                                                          col_search_order,
                                                          line_range)
                                    _mark_column_as_used(columns,
                                                         line_col_index,
                                                         line_range)
                                lines.append((rev_index,
                                              parent_index,
                                              (line_col_index,)))
        finally:
            progress_bar.finished()

        update_root_progress(5)
        progress_bar = ui.ui_factory.nested_progress_bar()
        try:
            progress_bar.update("Prettifying graph", 0, len(lines))
            for i, (child_index, parent_index, line_col_indexes) in enumerate(lines):
                if i % 25 == 0:
                    progress_bar.update(None, i)
                (child_col_index, child_color) = linegraph[child_index][1]
                (parent_col_index, parent_color) = linegraph[parent_index][1]

                if len(line_col_indexes) == 1:
                    if parent_index - child_index == 1:
                        linegraph[child_index][2].append(
                            (child_col_index,
                             parent_col_index,
                             parent_color))
                    else:
                        # line from the child's column to the lines column
                        linegraph[child_index][2].append(
                            (child_col_index,
                             line_col_indexes[0],
                             parent_color))
                        # lines down the line's column
                        for line_part_index in range(child_index+1, parent_index-1):
                            linegraph[line_part_index][2].append(
                                (line_col_indexes[0], 
                                 line_col_indexes[0],
                                 parent_color))
                        # line from the line's column to the parent's column
                        linegraph[parent_index-1][2].append(
                            (line_col_indexes[0],
                             parent_col_index,
                             parent_color))
                else:
                    # Broken line
                    # line from the child's column to the lines column
                    linegraph[child_index][2].append(
                        (child_col_index,
                         line_col_indexes[0],
                         parent_color))
                    # Broken line end
                    linegraph[child_index+1][2].append(
                        (line_col_indexes[0],
                         None,
                         parent_color))

                    # Broken line end 
                    linegraph[parent_index-2][2].append(
                        (None,
                         line_col_indexes[1],
                         parent_color))
                    # line from the line's column to the parent's column
                    linegraph[parent_index-1][2].append(
                        (line_col_indexes[1],
                         parent_col_index,
                         parent_color))
        finally:
            progress_bar.finished()
        return (linegraph, revid_index, len(columns))
    else:
        return (linegraph, revid_index, 0)