~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/merge_core.py

[merge] robert's integration branch

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
from bzrlib.osutils import backup_file, rename
6
6
from bzrlib.merge3 import Merge3
7
7
import bzrlib
 
8
from bzrlib.atomicfile import AtomicFile
8
9
from changeset import get_contents
9
10
 
10
11
class ApplyMerge3:
 
12
    history_based = False
11
13
    """Contents-change wrapper around merge3.Merge3"""
12
 
    def __init__(self, file_id, base, other):
 
14
    def __init__(self, file_id, base, other, show_base=False, reprocess=False):
13
15
        self.file_id = file_id
14
16
        self.base = base
15
17
        self.other = other
 
18
        self.show_base = show_base
 
19
        self.reprocess = reprocess
16
20
 
17
21
    def is_creation(self):
18
22
        return False
49
53
        new_conflicts = False
50
54
        output_file = file(new_file, "wb")
51
55
        start_marker = "!START OF MERGE CONFLICT!" + "I HOPE THIS IS UNIQUE"
 
56
        if self.show_base is True:
 
57
            base_marker = '|' * 7
 
58
        else:
 
59
            base_marker = None
52
60
        for line in m3.merge_lines(name_a = "TREE", name_b = "MERGE-SOURCE", 
53
 
                       start_marker=start_marker):
 
61
                       name_base = "BASE-REVISION",
 
62
                       start_marker=start_marker, base_marker=base_marker,
 
63
                       reprocess = self.reprocess):
54
64
            if line.startswith(start_marker):
55
65
                new_conflicts = True
56
66
                output_file.write(line.replace(start_marker, '<' * 7))
65
75
            conflict_handler.merge_conflict(new_file, filename, base_lines,
66
76
                                            other_lines)
67
77
 
 
78
class WeaveMerge:
 
79
    """Contents-change wrapper around weave merge"""
 
80
    history_based = True
 
81
    def __init__(self, weave, this_revision_id, other_revision_id):
 
82
        self.weave = weave
 
83
        self.this_revision_id = this_revision_id
 
84
        self.other_revision_id = other_revision_id
 
85
 
 
86
    def is_creation(self):
 
87
        return False
 
88
 
 
89
    def is_deletion(self):
 
90
        return False
 
91
 
 
92
    def __eq__(self, other):
 
93
        if not isinstance(other, WeaveMerge):
 
94
            return False
 
95
        return self.weave == other.weave and\
 
96
            self.this_revision_id == other.this_revision_id and\
 
97
            self.other_revision_id == other.other_revision_id
 
98
 
 
99
    def __ne__(self, other):
 
100
        return not (self == other)
 
101
 
 
102
    def apply(self, filename, conflict_handler, reverse=False):
 
103
        this_i = self.weave.lookup(self.this_revision_id)
 
104
        other_i = self.weave.lookup(self.other_revision_id)
 
105
        plan = self.weave.plan_merge(this_i, other_i)
 
106
        lines = self.weave.weave_merge(plan)
 
107
        conflicts = False
 
108
        out_file = AtomicFile(filename, mode='wb')
 
109
        for line in lines:
 
110
            if line == '<<<<<<<\n':
 
111
                conflicts = True
 
112
            out_file.write(line)
 
113
        if conflicts:
 
114
            conflict_handler.weave_merge_conflict(filename, self.weave,
 
115
                                                  other_i, out_file)
 
116
        else:
 
117
            out_file.commit()
68
118
 
69
119
class BackupBeforeChange:
70
120
    """Contents-change wrapper to back up file first"""
109
159
                                    conflict_handler, merge_factory)
110
160
    result = apply_changeset(new_cset, invert_invent(this.inventory),
111
161
                             this.basedir, conflict_handler, False)
112
 
    conflict_handler.finalize()
113
162
    return result
114
 
 
115
163
    
116
164
 
117
165
def make_merge_changeset(cset, this, base, other, 
221
269
        return merge_factory(entry.id, base, other)
222
270
 
223
271
    if isinstance(contents, changeset.ReplaceContents):
224
 
        if contents.old_contents is None and contents.new_contents is None:
 
272
        base_contents = contents.old_contents
 
273
        other_contents = contents.new_contents
 
274
        if base_contents is None and other_contents is None:
225
275
            return None
226
 
        if contents.new_contents is None:
 
276
        if other_contents is None:
227
277
            this_contents = get_contents(this, entry.id)
228
278
            if this_path is not None and bzrlib.osutils.lexists(this_path):
229
 
                if this_contents != contents.old_contents:
 
279
                if this_contents != base_contents:
230
280
                    return conflict_handler.rem_contents_conflict(this_path, 
231
 
                        this_contents, contents.old_contents)
 
281
                        this_contents, base_contents)
232
282
                return contents
233
283
            else:
234
284
                return None
235
 
        elif contents.old_contents is None:
 
285
        elif base_contents is None:
236
286
            if this_path is None or not bzrlib.osutils.lexists(this_path):
237
287
                return contents
238
288
            else:
239
289
                this_contents = get_contents(this, entry.id)
240
 
                if this_contents == contents.new_contents:
 
290
                if this_contents == other_contents:
241
291
                    return None
242
292
                else:
243
293
                    conflict_handler.new_contents_conflict(this_path, 
244
 
                                                           other_contents)
245
 
        elif isinstance(contents.old_contents, changeset.TreeFileCreate) and \
246
 
            isinstance(contents.new_contents, changeset.TreeFileCreate):
 
294
                        other_contents)
 
295
        elif isinstance(base_contents, changeset.TreeFileCreate) and \
 
296
            isinstance(other_contents, changeset.TreeFileCreate):
247
297
            return make_merge()
248
298
        else:
249
299
            this_contents = get_contents(this, entry.id)
250
 
            if this_contents == contents.old_contents:
 
300
            if this_contents == base_contents:
251
301
                return contents
252
 
            elif this_contents == contents.new_contents:
 
302
            elif this_contents == other_contents:
253
303
                return None
254
 
            elif contents.old_contents == contents.new_contents:
 
304
            elif base_contents == other_contents:
255
305
                return None
256
306
            else:
257
 
                conflict_handler.threeway_contents_conflict(this_path, 
258
 
                    this_contents, contents.old_contents,
259
 
                    contents.new_contents)
 
307
                conflict_handler.threeway_contents_conflict(this_path,
 
308
                                                            this_contents,
 
309
                                                            base_contents,
 
310
                                                            other_contents)
260
311
                
261
312
 
262
313
def make_merged_metadata(entry, base, other):