/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
5273.1.5 by Vincent Ladeuil
Merge bzr.dev into cleanup
1
# Copyright (C) 2006, 2009, 2010 Canonical Ltd
1551.6.7 by Aaron Bentley
Implemented two-way merge, refactored weave merge
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1551.6.7 by Aaron Bentley
Implemented two-way merge, refactored weave merge
16
#
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
17
# Author: Martin Pool <mbp@canonical.com>
1551.6.7 by Aaron Bentley
Implemented two-way merge, refactored weave merge
18
#         Aaron Bentley <aaron.bentley@utoronto.ca>
19
6624 by Jelmer Vernooij
Merge Python3 porting work ('py3 pokes')
20
from .lazy_import import lazy_import
5279.1.1 by Andrew Bennetts
lazy_import most things in merge.py; add a few representative modules to the import tariff tests; tweak a couple of other modules so that patiencediff is not necessarily imported; remove a bunch of unused imports from test_knit.py.
21
lazy_import(globals(), """
7290.14.1 by Jelmer Vernooij
Use external patiencediff.
22
import patiencediff
5279.1.1 by Andrew Bennetts
lazy_import most things in merge.py; add a few representative modules to the import tariff tests; tweak a couple of other modules so that patiencediff is not necessarily imported; remove a bunch of unused imports from test_knit.py.
23
""")
1551.6.7 by Aaron Bentley
Implemented two-way merge, refactored weave merge
24
25
26
class TextMerge(object):
1551.6.8 by Aaron Bentley
Implemented reprocess for weave
27
    """Base class for text-mergers
28
    Subclasses must implement _merge_struct.
1551.6.13 by Aaron Bentley
Cleanup
29
30
    Many methods produce or consume structured merge information.
31
    This is an iterable of tuples of lists of lines.
32
    Each tuple may have a length of 1 - 3, depending on whether the region it
33
    represents is conflicted.
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
34
1551.6.13 by Aaron Bentley
Cleanup
35
    Unconflicted region tuples have length 1.
36
    Conflicted region tuples have length 2 or 3.  Index 1 is text_a, e.g. THIS.
37
    Index 1 is text_b, e.g. OTHER.  Index 2 is optional.  If present, it
38
    represents BASE.
1551.6.8 by Aaron Bentley
Implemented reprocess for weave
39
    """
1551.6.13 by Aaron Bentley
Cleanup
40
    # TODO: Show some version information (e.g. author, date) on conflicted
41
    # regions.
6963.2.10 by Jelmer Vernooij
Fix a bunch of tests.
42
    A_MARKER = b'<<<<<<< \n'
43
    B_MARKER = b'>>>>>>> \n'
44
    SPLIT_MARKER = b'=======\n'
7143.15.2 by Jelmer Vernooij
Run autopep8.
45
1551.6.14 by Aaron Bentley
Tweaks from merge review
46
    def __init__(self, a_marker=A_MARKER, b_marker=B_MARKER,
47
                 split_marker=SPLIT_MARKER):
1551.6.7 by Aaron Bentley
Implemented two-way merge, refactored weave merge
48
        self.a_marker = a_marker
49
        self.b_marker = b_marker
50
        self.split_marker = split_marker
51
1551.6.14 by Aaron Bentley
Tweaks from merge review
52
    def _merge_struct(self):
53
        """Return structured merge info.  Must be implemented by subclasses.
54
        See TextMerge docstring for details on the format.
55
        """
56
        raise NotImplementedError('_merge_struct is abstract')
57
1551.6.7 by Aaron Bentley
Implemented two-way merge, refactored weave merge
58
    def struct_to_lines(self, struct_iter):
1551.6.8 by Aaron Bentley
Implemented reprocess for weave
59
        """Convert merge result tuples to lines"""
1551.6.7 by Aaron Bentley
Implemented two-way merge, refactored weave merge
60
        for lines in struct_iter:
61
            if len(lines) == 1:
62
                for line in lines[0]:
63
                    yield line
64
            else:
65
                yield self.a_marker
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
66
                for line in lines[0]:
1551.6.7 by Aaron Bentley
Implemented two-way merge, refactored weave merge
67
                    yield line
68
                yield self.split_marker
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
69
                for line in lines[1]:
1551.6.7 by Aaron Bentley
Implemented two-way merge, refactored weave merge
70
                    yield line
71
                yield self.b_marker
72
73
    def iter_useful(self, struct_iter):
1551.6.8 by Aaron Bentley
Implemented reprocess for weave
74
        """Iterate through input tuples, skipping empty ones."""
1551.6.7 by Aaron Bentley
Implemented two-way merge, refactored weave merge
75
        for group in struct_iter:
76
            if len(group[0]) > 0:
77
                yield group
78
            elif len(group) > 1 and len(group[1]) > 0:
79
                yield group
80
1551.6.8 by Aaron Bentley
Implemented reprocess for weave
81
    def merge_lines(self, reprocess=False):
1551.6.14 by Aaron Bentley
Tweaks from merge review
82
        """Produce an iterable of lines, suitable for writing to a file
1551.6.13 by Aaron Bentley
Cleanup
83
        Returns a tuple of (line iterable, conflict indicator)
84
        If reprocess is True, a two-way merge will be performed on the
85
        intermediate structure, to reduce conflict regions.
86
        """
1551.6.11 by Aaron Bentley
Switched TextMerge_lines to work on a list
87
        struct = []
1551.6.12 by Aaron Bentley
Indicate conflicts from merge_lines, insead of guessing
88
        conflicts = False
1551.6.11 by Aaron Bentley
Switched TextMerge_lines to work on a list
89
        for group in self.merge_struct(reprocess):
90
            struct.append(group)
1551.6.12 by Aaron Bentley
Indicate conflicts from merge_lines, insead of guessing
91
            if len(group) > 1:
92
                conflicts = True
93
        return self.struct_to_lines(struct), conflicts
1551.6.8 by Aaron Bentley
Implemented reprocess for weave
94
95
    def merge_struct(self, reprocess=False):
1551.6.13 by Aaron Bentley
Cleanup
96
        """Produce structured merge info"""
1551.6.8 by Aaron Bentley
Implemented reprocess for weave
97
        struct_iter = self.iter_useful(self._merge_struct())
98
        if reprocess is True:
99
            return self.reprocess_struct(struct_iter)
100
        else:
101
            return struct_iter
102
103
    @staticmethod
104
    def reprocess_struct(struct_iter):
1551.6.14 by Aaron Bentley
Tweaks from merge review
105
        """ Perform a two-way merge on structural merge info.
1551.6.13 by Aaron Bentley
Cleanup
106
        This reduces the size of conflict regions, but breaks the connection
1551.6.14 by Aaron Bentley
Tweaks from merge review
107
        between the BASE text and the conflict region.
1551.6.13 by Aaron Bentley
Cleanup
108
109
        This process may split a single conflict region into several smaller
110
        ones, but will not introduce new conflicts.
111
        """
1551.6.8 by Aaron Bentley
Implemented reprocess for weave
112
        for group in struct_iter:
113
            if len(group) == 1:
114
                yield group
115
            else:
116
                for newgroup in Merge2(group[0], group[1]).merge_struct():
117
                    yield newgroup
1551.6.7 by Aaron Bentley
Implemented two-way merge, refactored weave merge
118
119
120
class Merge2(TextMerge):
1551.6.14 by Aaron Bentley
Tweaks from merge review
121
    """ Two-way merge.
1551.6.7 by Aaron Bentley
Implemented two-way merge, refactored weave merge
122
    In a two way merge, common regions are shown as unconflicting, and uncommon
123
    regions produce conflicts.
124
    """
1551.6.13 by Aaron Bentley
Cleanup
125
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
126
    def __init__(self, lines_a, lines_b, a_marker=TextMerge.A_MARKER,
127
                 b_marker=TextMerge.B_MARKER,
1551.6.14 by Aaron Bentley
Tweaks from merge review
128
                 split_marker=TextMerge.SPLIT_MARKER):
1551.6.7 by Aaron Bentley
Implemented two-way merge, refactored weave merge
129
        TextMerge.__init__(self, a_marker, b_marker, split_marker)
130
        self.lines_a = lines_a
131
        self.lines_b = lines_b
132
133
    def _merge_struct(self):
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
134
        """Return structured merge info.
1551.6.13 by Aaron Bentley
Cleanup
135
        See TextMerge docstring.
136
        """
5279.1.1 by Andrew Bennetts
lazy_import most things in merge.py; add a few representative modules to the import tariff tests; tweak a couple of other modules so that patiencediff is not necessarily imported; remove a bunch of unused imports from test_knit.py.
137
        sm = patiencediff.PatienceSequenceMatcher(
138
            None, self.lines_a, self.lines_b)
1551.6.7 by Aaron Bentley
Implemented two-way merge, refactored weave merge
139
        pos_a = 0
140
        pos_b = 0
141
        for ai, bi, l in sm.get_matching_blocks():
142
            # non-matching lines
143
            yield(self.lines_a[pos_a:ai], self.lines_b[pos_b:bi])
144
            # matching lines
7143.15.2 by Jelmer Vernooij
Run autopep8.
145
            yield(self.lines_a[ai:ai + l],)
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
146
            pos_a = ai + l
1551.6.7 by Aaron Bentley
Implemented two-way merge, refactored weave merge
147
            pos_b = bi + l
148
        # final non-matching lines
149
        yield(self.lines_a[pos_a:-1], self.lines_b[pos_b:-1])