示例#1
0
 def test_merge_poem(self):
     """Test case from diff3 manual"""
     m3 = Merge3(TZU, LAO, TAO)
     ml = list(m3.merge_lines('LAO', 'TAO'))
     self.log('merge result:')
     self.log(''.join(ml))
     self.assertEquals(ml, MERGED_RESULT)
示例#2
0
    def test_null_insert(self):
        m3 = Merge3([], ['aaa', 'bbb'], [])
        # todo: should use a sentinal at end as from get_matching_blocks
        # to match without zz
        self.assertEquals(list(m3.find_sync_regions()), [(0, 0, 2, 2, 0, 0)])

        self.assertEquals(list(m3.merge_regions()), [('a', 0, 2)])

        self.assertEquals(list(m3.merge_lines()), ['aaa', 'bbb'])
示例#3
0
    def test_simple_merge(self):
        base = ['a', 'b', 'c']
        # append d
        a = ['a', 'b', 'c', 'd']
        # remove b
        b = ['a', 'c']

        m3 = Merge3(base, a, b)
        self.assertEqual(['a', 'c', 'd'], list(m3.merge_lines()))
示例#4
0
    def test_conflict(self):
        base = ['a', 'b', 'c']
        # b -> b1
        a = ['a', 'b1', 'c']
        # b -> b2
        b = ['a', 'b2', 'c']

        m3 = Merge3(base, a, b)
        self.assertEqual(['a', '<<<<<<<\n', 'b1', '=======\n', 'b2', '>>>>>>>\n', 'c'], list(m3.merge_lines()))
示例#5
0
    def test_insert_agreement(self):
        m3 = Merge3(['aaa\n', 'bbb\n'], ['aaa\n', '222\n', 'bbb\n'],
                    ['aaa\n', '222\n', 'bbb\n'])

        ml = m3.merge_lines(name_a='a',
                            name_b='b',
                            start_marker='<<',
                            mid_marker='--',
                            end_marker='>>')
        self.assertEquals(''.join(ml), 'aaa\n222\nbbb\n')
示例#6
0
 def test_mac_text(self):
     base_text = 'a\r'
     this_text = 'b\r'
     other_text = 'c\r'
     m3 = Merge3(base_text.splitlines(True), other_text.splitlines(True),
                 this_text.splitlines(True))
     m_lines = m3.merge_lines('OTHER', 'THIS')
     self.assertEqual(
         '<<<<<<< OTHER\rc\r=======\rb\r'
         '>>>>>>> THIS\r'.splitlines(True), list(m_lines))
示例#7
0
def merge_entries(base_entries, this_entries, other_entries,
        guess_edits=default_guess_edits):
    """Merge changelog given base, this, and other versions."""
    m3 = Merge3(base_entries, this_entries, other_entries, allow_objects=True)
    result_entries = []
    at_top = True
    for group in m3.merge_groups():
        if 'changelog_merge' in debug.debug_flags:
            mutter('merge group:\n%r', group)
        group_kind = group[0]
        if group_kind == 'conflict':
            _, base, this, other = group
            # Find additions
            new_in_other = [
                entry for entry in other if entry not in base]
            # Find deletions
            deleted_in_other = [
                entry for entry in base if entry not in other]
            if at_top and deleted_in_other:
                # Magic!  Compare deletions and additions to try spot edits
                new_in_other, deleted_in_other, edits_in_other = guess_edits(
                    new_in_other, deleted_in_other)
            else:
                # Changes not made at the top are always preserved as is, no
                # need to try distinguish edits from adds and deletes.
                edits_in_other = []
            if 'changelog_merge' in debug.debug_flags:
                mutter('at_top: %r', at_top)
                mutter('new_in_other: %r', new_in_other)
                mutter('deleted_in_other: %r', deleted_in_other)
                mutter('edits_in_other: %r', edits_in_other)
            # Apply deletes and edits
            updated_this = [
                entry for entry in this if entry not in deleted_in_other]
            for old_entry, new_entry in edits_in_other:
                try:
                    index = updated_this.index(old_entry)
                except ValueError:
                    # edited entry no longer present in this!  Just give up and
                    # declare a conflict.
                    raise EntryConflict()
                updated_this[index] = new_entry
            if 'changelog_merge' in debug.debug_flags:
                mutter('updated_this: %r', updated_this)
            if at_top:
                # Float new entries from other to the top
                result_entries = new_in_other + result_entries
            else:
                result_entries.extend(new_in_other)
            result_entries.extend(updated_this)
        else: # unchanged, same, a, or b.
            lines = group[1]
            result_entries.extend(lines)
        at_top = False
    return result_entries
示例#8
0
 def test_minimal_conflicts_common(self):
     """Reprocessing"""
     base_text = ("a\n" * 20).splitlines(True)
     this_text = ("a\n" * 10 + "b\n" * 10).splitlines(True)
     other_text = ("a\n" * 10 + "c\n" + "b\n" * 8 + "c\n").splitlines(True)
     m3 = Merge3(base_text, other_text, this_text)
     m_lines = m3.merge_lines('OTHER', 'THIS', reprocess=True)
     merged_text = "".join(list(m_lines))
     optimal_text = ("a\n" * 10 + "<<<<<<< OTHER\nc\n" + 8 * "b\n" +
                     "c\n=======\n" + 10 * "b\n" + ">>>>>>> THIS\n")
     self.assertEqualDiff(optimal_text, merged_text)
示例#9
0
 def test_reprocess_and_base(self):
     """Reprocessing and showing base breaks correctly"""
     base_text = ("a\n" * 20).splitlines(True)
     this_text = ("a\n" * 10 + "b\n" * 10).splitlines(True)
     other_text = ("a\n" * 10 + "c\n" + "b\n" * 8 + "c\n").splitlines(True)
     m3 = Merge3(base_text, other_text, this_text)
     m_lines = m3.merge_lines('OTHER',
                              'THIS',
                              reprocess=True,
                              base_marker='|||||||')
     self.assertRaises(CantReprocessAndShowBase, list, m_lines)
示例#10
0
    def test_replace_clash(self):
        """Both try to insert lines in the same place."""
        m3 = Merge3(['aaa', '000', 'bbb'], ['aaa', '111', 'bbb'],
                    ['aaa', '222', 'bbb'])

        self.assertEquals(m3.find_unconflicted(), [(0, 1), (2, 3)])

        self.assertEquals(list(m3.find_sync_regions()), [
            (0, 1, 0, 1, 0, 1),
            (2, 3, 2, 3, 2, 3),
            (3, 3, 3, 3, 3, 3),
        ])
示例#11
0
    def test_merge3_cherrypick(self):
        base_text = "a\nb\n"
        this_text = "a\n"
        other_text = "a\nb\nc\n"
        # When cherrypicking, lines in base are not part of the conflict
        m3 = Merge3(base_text.splitlines(True),
                    this_text.splitlines(True),
                    other_text.splitlines(True),
                    is_cherrypick=True)
        m_lines = m3.merge_lines()
        self.assertEqualDiff('a\n<<<<<<<\n=======\nc\n>>>>>>>\n',
                             ''.join(m_lines))

        # This is not symmetric
        m3 = Merge3(base_text.splitlines(True),
                    other_text.splitlines(True),
                    this_text.splitlines(True),
                    is_cherrypick=True)
        m_lines = m3.merge_lines()
        self.assertEqualDiff('a\n<<<<<<<\nb\nc\n=======\n>>>>>>>\n',
                             ''.join(m_lines))
示例#12
0
    def _merge_if_needed(self, base_revision, new_body):
        if self.revision == base_revision:
            return new_body

        base = WikiPageRevision.query(
            WikiPageRevision.title == self.title,
            WikiPageRevision.revision == base_revision).get().body
        merged = ''.join(Merge3(base, self.body, new_body).merge_lines())
        conflicted = len(re.findall(PageOperationMixin.re_conflicted,
                                    merged)) > 0
        if conflicted:
            raise ConflictError('Conflicted', base, new_body, merged)
        return merged
示例#13
0
    def test_replace_multi(self):
        """Replacement with regions of different size."""
        m3 = Merge3(['aaa', '000', '000', 'bbb'],
                    ['aaa', '111', '111', '111', 'bbb'],
                    ['aaa', '222', '222', '222', '222', 'bbb'])

        self.assertEquals(m3.find_unconflicted(), [(0, 1), (3, 4)])

        self.assertEquals(list(m3.find_sync_regions()), [
            (0, 1, 0, 1, 0, 1),
            (3, 4, 4, 5, 5, 6),
            (4, 4, 5, 5, 6, 6),
        ])
示例#14
0
    def test_no_changes(self):
        """No conflicts because nothing changed"""
        m3 = Merge3(['aaa', 'bbb'], ['aaa', 'bbb'], ['aaa', 'bbb'])

        self.assertEquals(m3.find_unconflicted(), [(0, 2)])

        self.assertEquals(list(m3.find_sync_regions()), [(0, 2, 0, 2, 0, 2),
                                                         (2, 2, 2, 2, 2, 2)])

        self.assertEquals(list(m3.merge_regions()), [('unchanged', 0, 2)])

        self.assertEquals(list(m3.merge_groups()),
                          [('unchanged', ['aaa', 'bbb'])])
示例#15
0
    def test_front_insert(self):
        m3 = Merge3(['zz'], ['aaa', 'bbb', 'zz'], ['zz'])

        # todo: should use a sentinal at end as from get_matching_blocks
        # to match without zz
        self.assertEquals(list(m3.find_sync_regions()), [
            (0, 1, 2, 3, 0, 1),
            (1, 1, 3, 3, 1, 1),
        ])

        self.assertEquals(list(m3.merge_regions()), [('a', 0, 2),
                                                     ('unchanged', 0, 1)])

        self.assertEquals(list(m3.merge_groups()), [('a', ['aaa', 'bbb']),
                                                    ('unchanged', ['zz'])])
示例#16
0
    def test_no_conflicts(self):
        """No conflicts because only one side changed"""
        m3 = Merge3(['aaa', 'bbb'], ['aaa', '111', 'bbb'], ['aaa', 'bbb'])

        self.assertEquals(m3.find_unconflicted(), [(0, 1), (1, 2)])

        self.assertEquals(list(m3.find_sync_regions()), [
            (0, 1, 0, 1, 0, 1),
            (1, 2, 2, 3, 1, 2),
            (2, 2, 3, 3, 2, 2),
        ])

        self.assertEquals(list(m3.merge_regions()), [
            ('unchanged', 0, 1),
            ('a', 1, 2),
            ('unchanged', 1, 2),
        ])
示例#17
0
    def test_minimal_conflicts_nonunique(self):
        def add_newline(s):
            """Add a newline to each entry in the string"""
            return [(x + '\n') for x in s]

        base_text = add_newline("abacddefgghij")
        this_text = add_newline("abacddefgghijkalmontfprz")
        other_text = add_newline("abacddefgghijknlmontfprd")
        m3 = Merge3(base_text, other_text, this_text)
        m_lines = m3.merge_lines('OTHER', 'THIS', reprocess=True)
        merged_text = "".join(list(m_lines))
        optimal_text = ''.join(
            add_newline("abacddefgghijk") +
            ["<<<<<<< OTHER\nn\n=======\na\n>>>>>>> THIS\n"] +
            add_newline('lmontfpr') +
            ["<<<<<<< OTHER\nd\n=======\nz\n>>>>>>> THIS\n"])
        self.assertEqualDiff(optimal_text, merged_text)
示例#18
0
    def test_minimal_conflicts_unique(self):
        def add_newline(s):
            """Add a newline to each entry in the string"""
            return [(x + '\n') for x in s]

        base_text = add_newline("abcdefghijklm")
        this_text = add_newline("abcdefghijklmNOPQRSTUVWXYZ")
        other_text = add_newline("abcdefghijklm1OPQRSTUVWXY2")
        m3 = Merge3(base_text, other_text, this_text)
        m_lines = m3.merge_lines('OTHER', 'THIS', reprocess=True)
        merged_text = "".join(list(m_lines))
        optimal_text = ''.join(
            add_newline("abcdefghijklm") +
            ["<<<<<<< OTHER\n1\n=======\nN\n>>>>>>> THIS\n"] +
            add_newline('OPQRSTUVWXY') +
            ["<<<<<<< OTHER\n2\n=======\nZ\n>>>>>>> THIS\n"])
        self.assertEqualDiff(optimal_text, merged_text)
示例#19
0
    def test_append_clash(self):
        m3 = Merge3(['aaa\n', 'bbb\n'], ['aaa\n', 'bbb\n', '222\n'],
                    ['aaa\n', 'bbb\n', '333\n'])

        ml = m3.merge_lines(name_a='a',
                            name_b='b',
                            start_marker='<<',
                            mid_marker='--',
                            end_marker='>>')
        self.assertEquals(''.join(ml), '''\
aaa
bbb
<< a
222
--
333
>> b
''')
示例#20
0
 def test_merge3_cherrypick_w_mixed(self):
     base_text = 'a\nb\nc\nd\ne\n'
     this_text = 'a\nb\nq\n'
     other_text = 'a\nb\nc\nd\nf\ne\ng\n'
     # When cherrypicking, lines in base are not part of the conflict
     m3 = Merge3(base_text.splitlines(True),
                 this_text.splitlines(True),
                 other_text.splitlines(True),
                 is_cherrypick=True)
     m_lines = m3.merge_lines()
     self.assertEqualDiff(
         'a\n'
         'b\n'
         '<<<<<<<\n'
         'q\n'
         '=======\n'
         'f\n'
         '>>>>>>>\n'
         '<<<<<<<\n'
         '=======\n'
         'g\n'
         '>>>>>>>\n', ''.join(m_lines))
示例#21
0
    def test_insert_clash(self):
        """Both try to insert lines in the same place."""
        m3 = Merge3(['aaa\n', 'bbb\n'], ['aaa\n', '111\n', 'bbb\n'],
                    ['aaa\n', '222\n', 'bbb\n'])

        self.assertEquals(m3.find_unconflicted(), [(0, 1), (1, 2)])

        self.assertEquals(list(m3.find_sync_regions()), [
            (0, 1, 0, 1, 0, 1),
            (1, 2, 2, 3, 2, 3),
            (2, 2, 3, 3, 3, 3),
        ])

        self.assertEquals(list(m3.merge_regions()),
                          [('unchanged', 0, 1), ('conflict', 1, 1, 1, 2, 1, 2),
                           ('unchanged', 1, 2)])

        self.assertEquals(list(m3.merge_groups()), [
            ('unchanged', ['aaa\n']),
            ('conflict', [], ['111\n'], ['222\n']),
            ('unchanged', ['bbb\n']),
        ])

        ml = m3.merge_lines(name_a='a',
                            name_b='b',
                            start_marker='<<',
                            mid_marker='--',
                            end_marker='>>')
        self.assertEquals(''.join(ml), '''aaa
<< a
111
--
222
>> b
bbb
''')
示例#22
0
    def test_append_agreement(self):
        m3 = Merge3(['aaa\n', 'bbb\n'], ['aaa\n', 'bbb\n', '222\n'],
                    ['aaa\n', 'bbb\n', '222\n'])

        self.assertEquals(''.join(m3.merge_lines()), 'aaa\nbbb\n222\n')