Example #1
0
 def test_tree_traversal(self):
     # low level tree tarversal
     odb = self.rorepo.odb
     H = self.rorepo.tree('29eb123beb1c55e5db4aa652d843adccbd09ae18')    # head tree
     M = self.rorepo.tree('e14e3f143e7260de9581aee27e5a9b2645db72de')    # merge tree
     B = self.rorepo.tree('f606937a7a21237c866efafcad33675e6539c103')    # base tree
     B_old = self.rorepo.tree('1f66cfbbce58b4b552b041707a12d437cc5f400a')    # old base tree
     
     # two very different trees
     entries = traverse_trees_recursive(odb, [B_old.binsha, H.binsha], '')
     self._assert_tree_entries(entries, 2)
     
     oentries = traverse_trees_recursive(odb, [H.binsha, B_old.binsha], '')
     assert len(oentries) == len(entries)
     self._assert_tree_entries(oentries, 2)
     
     # single tree
     is_no_tree = lambda i, d: i.type != 'tree'
     entries = traverse_trees_recursive(odb, [B.binsha], '')
     assert len(entries) == len(list(B.traverse(predicate=is_no_tree)))
     self._assert_tree_entries(entries, 1)
     
     # two trees
     entries = traverse_trees_recursive(odb, [B.binsha, H.binsha], '')
     self._assert_tree_entries(entries, 2)
     
     # tree trees
     entries = traverse_trees_recursive(odb, [B.binsha, H.binsha, M.binsha], '')
     self._assert_tree_entries(entries, 3)
Example #2
0
    def test_tree_traversal(self):
        # low level tree tarversal
        odb = self.rorepo.odb
        H = self.rorepo.tree(
            '29eb123beb1c55e5db4aa652d843adccbd09ae18')  # head tree
        M = self.rorepo.tree(
            'e14e3f143e7260de9581aee27e5a9b2645db72de')  # merge tree
        B = self.rorepo.tree(
            'f606937a7a21237c866efafcad33675e6539c103')  # base tree
        B_old = self.rorepo.tree(
            '1f66cfbbce58b4b552b041707a12d437cc5f400a')  # old base tree

        # two very different trees
        entries = traverse_trees_recursive(odb, [B_old.binsha, H.binsha], '')
        self._assert_tree_entries(entries, 2)

        oentries = traverse_trees_recursive(odb, [H.binsha, B_old.binsha], '')
        assert len(oentries) == len(entries)
        self._assert_tree_entries(oentries, 2)

        # single tree
        is_no_tree = lambda i, d: i.type != 'tree'
        entries = traverse_trees_recursive(odb, [B.binsha], '')
        assert len(entries) == len(list(B.traverse(predicate=is_no_tree)))
        self._assert_tree_entries(entries, 1)

        # two trees
        entries = traverse_trees_recursive(odb, [B.binsha, H.binsha], '')
        self._assert_tree_entries(entries, 2)

        # tree trees
        entries = traverse_trees_recursive(odb, [B.binsha, H.binsha, M.binsha],
                                           '')
        self._assert_tree_entries(entries, 3)
Example #3
0
def aggressive_tree_merge(odb, tree_shas):
    """
	:return: list of BaseIndexEntries representing the aggressive merge of the given
		trees. All valid entries are on stage 0, whereas the conflicting ones are left 
		on stage 1, 2 or 3, whereas stage 1 corresponds to the common ancestor tree, 
		2 to our tree and 3 to 'their' tree.
	:param tree_shas: 1, 2 or 3 trees as identified by their binary 20 byte shas
		If 1 or two, the entries will effectively correspond to the last given tree
		If 3 are given, a 3 way merge is performed"""
    out = list()
    out_append = out.append

    # one and two way is the same for us, as we don't have to handle an existing
    # index, instrea
    if len(tree_shas) in (1, 2):
        for entry in traverse_tree_recursive(odb, tree_shas[-1], ''):
            out_append(_tree_entry_to_baseindexentry(entry, 0))
        # END for each entry
        return out
    # END handle single tree

    if len(tree_shas) > 3:
        raise ValueError("Cannot handle %i trees at once" % len(tree_shas))

    # three trees
    for base, ours, theirs in traverse_trees_recursive(odb, tree_shas, ''):
        if base is not None:
            # base version exists
            if ours is not None:
                # ours exists
                if theirs is not None:
                    # it exists in all branches, if it was changed in both
                    # its a conflict, otherwise we take the changed version
                    # This should be the most common branch, so it comes first
                    if( base[0] != ours[0] and base[0] != theirs[0] and ours[0] != theirs[0] ) or \
                     ( base[1] != ours[1] and base[1] != theirs[1] and ours[1] != theirs[1] ):
                        # changed by both
                        out_append(_tree_entry_to_baseindexentry(base, 1))
                        out_append(_tree_entry_to_baseindexentry(ours, 2))
                        out_append(_tree_entry_to_baseindexentry(theirs, 3))
                    elif base[0] != ours[0] or base[1] != ours[1]:
                        # only we changed it
                        out_append(_tree_entry_to_baseindexentry(ours, 0))
                    else:
                        # either nobody changed it, or they did. In either
                        # case, use theirs
                        out_append(_tree_entry_to_baseindexentry(theirs, 0))
                    # END handle modification
                else:

                    if ours[0] != base[0] or ours[1] != base[1]:
                        # they deleted it, we changed it, conflict
                        out_append(_tree_entry_to_baseindexentry(base, 1))
                        out_append(_tree_entry_to_baseindexentry(ours, 2))
                    # else:
                    #	we didn't change it, ignore
                    #	pass
                    # END handle our change
                # END handle theirs
            else:
                if theirs is None:
                    # deleted in both, its fine - its out
                    pass
                else:
                    if theirs[0] != base[0] or theirs[1] != base[1]:
                        # deleted in ours, changed theirs, conflict
                        out_append(_tree_entry_to_baseindexentry(base, 1))
                        out_append(_tree_entry_to_baseindexentry(theirs, 3))
                    # END theirs changed
                    #else:
                    # 	theirs didnt change
                    #	pass
                # END handle theirs
            # END handle ours
        else:
            # all three can't be None
            if ours is None:
                # added in their branch
                out_append(_tree_entry_to_baseindexentry(theirs, 0))
            elif theirs is None:
                # added in our branch
                out_append(_tree_entry_to_baseindexentry(ours, 0))
            else:
                # both have it, except for the base, see whether it changed
                if ours[0] != theirs[0] or ours[1] != theirs[1]:
                    out_append(_tree_entry_to_baseindexentry(ours, 2))
                    out_append(_tree_entry_to_baseindexentry(theirs, 3))
                else:
                    # it was added the same in both
                    out_append(_tree_entry_to_baseindexentry(ours, 0))
                # END handle two items
            # END handle heads
        # END handle base exists
    # END for each entries tuple

    return out
Example #4
0
def aggressive_tree_merge(odb, tree_shas):
    """
    :return: list of BaseIndexEntries representing the aggressive merge of the given
        trees. All valid entries are on stage 0, whereas the conflicting ones are left
        on stage 1, 2 or 3, whereas stage 1 corresponds to the common ancestor tree,
        2 to our tree and 3 to 'their' tree.
    :param tree_shas: 1, 2 or 3 trees as identified by their binary 20 byte shas
        If 1 or two, the entries will effectively correspond to the last given tree
        If 3 are given, a 3 way merge is performed"""
    out = list()
    out_append = out.append

    # one and two way is the same for us, as we don't have to handle an existing
    # index, instrea
    if len(tree_shas) in (1, 2):
        for entry in traverse_tree_recursive(odb, tree_shas[-1], ''):
            out_append(_tree_entry_to_baseindexentry(entry, 0))
        # END for each entry
        return out
    # END handle single tree

    if len(tree_shas) > 3:
        raise ValueError("Cannot handle %i trees at once" % len(tree_shas))

    # three trees
    for base, ours, theirs in traverse_trees_recursive(odb, tree_shas, ''):
        if base is not None:
            # base version exists
            if ours is not None:
                # ours exists
                if theirs is not None:
                    # it exists in all branches, if it was changed in both
                    # its a conflict, otherwise we take the changed version
                    # This should be the most common branch, so it comes first
                    if(base[0] != ours[0] and base[0] != theirs[0] and ours[0] != theirs[0]) or \
                            (base[1] != ours[1] and base[1] != theirs[1] and ours[1] != theirs[1]):
                        # changed by both
                        out_append(_tree_entry_to_baseindexentry(base, 1))
                        out_append(_tree_entry_to_baseindexentry(ours, 2))
                        out_append(_tree_entry_to_baseindexentry(theirs, 3))
                    elif base[0] != ours[0] or base[1] != ours[1]:
                        # only we changed it
                        out_append(_tree_entry_to_baseindexentry(ours, 0))
                    else:
                        # either nobody changed it, or they did. In either
                        # case, use theirs
                        out_append(_tree_entry_to_baseindexentry(theirs, 0))
                    # END handle modification
                else:

                    if ours[0] != base[0] or ours[1] != base[1]:
                        # they deleted it, we changed it, conflict
                        out_append(_tree_entry_to_baseindexentry(base, 1))
                        out_append(_tree_entry_to_baseindexentry(ours, 2))
                    # else:
                    #   we didn't change it, ignore
                    #   pass
                    # END handle our change
                # END handle theirs
            else:
                if theirs is None:
                    # deleted in both, its fine - its out
                    pass
                else:
                    if theirs[0] != base[0] or theirs[1] != base[1]:
                        # deleted in ours, changed theirs, conflict
                        out_append(_tree_entry_to_baseindexentry(base, 1))
                        out_append(_tree_entry_to_baseindexentry(theirs, 3))
                    # END theirs changed
                    # else:
                    #   theirs didnt change
                    #   pass
                # END handle theirs
            # END handle ours
        else:
            # all three can't be None
            if ours is None:
                # added in their branch
                out_append(_tree_entry_to_baseindexentry(theirs, 0))
            elif theirs is None:
                # added in our branch
                out_append(_tree_entry_to_baseindexentry(ours, 0))
            else:
                # both have it, except for the base, see whether it changed
                if ours[0] != theirs[0] or ours[1] != theirs[1]:
                    out_append(_tree_entry_to_baseindexentry(ours, 2))
                    out_append(_tree_entry_to_baseindexentry(theirs, 3))
                else:
                    # it was added the same in both
                    out_append(_tree_entry_to_baseindexentry(ours, 0))
                # END handle two items
            # END handle heads
        # END handle base exists
    # END for each entries tuple

    return out