~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/merge_core.py

Merged mailine

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
from os import fdopen
1
2
import os.path
 
3
from tempfile import mkstemp
2
4
 
3
5
import changeset
4
6
from changeset import Inventory, apply_changeset, invert_dict
5
 
from bzrlib.osutils import backup_file, rename
 
7
from bzrlib.osutils import backup_file, rename, pathjoin
6
8
from bzrlib.merge3 import Merge3
7
9
import bzrlib
8
10
from bzrlib.atomicfile import AtomicFile
9
11
from changeset import get_contents
10
12
 
 
13
 
11
14
class ApplyMerge3:
 
15
    """Contents-change wrapper around merge3.Merge3"""
 
16
 
12
17
    history_based = False
13
 
    """Contents-change wrapper around merge3.Merge3"""
 
18
 
14
19
    def __init__(self, file_id, base, other, show_base=False, reprocess=False):
15
20
        self.file_id = file_id
16
21
        self.base = base
33
38
    def __ne__(self, other):
34
39
        return not (self == other)
35
40
 
36
 
    def apply(self, filename, conflict_handler, reverse=False):
37
 
        new_file = filename+".new" 
38
 
        if not reverse:
39
 
            base = self.base
40
 
            other = self.other
41
 
        else:
42
 
            base = self.other
43
 
            other = self.base
 
41
    def apply(self, filename, conflict_handler):
 
42
        output_file, new_file = mkstemp(dir=os.path.dirname(filename),
 
43
                                        prefix=os.path.basename(filename))
 
44
        output_file = fdopen(output_file, 'wb')
 
45
        base = self.base
 
46
        other = self.other
44
47
        def get_lines(tree):
45
48
            if self.file_id not in tree:
46
49
                raise Exception("%s not in tree" % self.file_id)
51
54
        m3 = Merge3(base_lines, file(filename, "rb").readlines(), other_lines)
52
55
 
53
56
        new_conflicts = False
54
 
        output_file = file(new_file, "wb")
55
57
        start_marker = "!START OF MERGE CONFLICT!" + "I HOPE THIS IS UNIQUE"
56
58
        if self.show_base is True:
57
59
            base_marker = '|' * 7
75
77
            conflict_handler.merge_conflict(new_file, filename, base_lines,
76
78
                                            other_lines)
77
79
 
 
80
 
78
81
class WeaveMerge:
79
82
    """Contents-change wrapper around weave merge"""
 
83
 
80
84
    history_based = True
 
85
 
81
86
    def __init__(self, weave, this_revision_id, other_revision_id):
82
87
        self.weave = weave
83
88
        self.this_revision_id = this_revision_id
99
104
    def __ne__(self, other):
100
105
        return not (self == other)
101
106
 
102
 
    def apply(self, filename, conflict_handler, reverse=False):
 
107
    def apply(self, filename, conflict_handler):
103
108
        this_i = self.weave.lookup(self.this_revision_id)
104
109
        other_i = self.weave.lookup(self.other_revision_id)
105
110
        plan = self.weave.plan_merge(this_i, other_i)
116
121
        else:
117
122
            out_file.commit()
118
123
 
 
124
 
119
125
class BackupBeforeChange:
120
126
    """Contents-change wrapper to back up file first"""
 
127
 
121
128
    def __init__(self, contents_change):
122
129
        self.contents_change = contents_change
123
130
 
135
142
    def __ne__(self, other):
136
143
        return not (self == other)
137
144
 
138
 
    def apply(self, filename, conflict_handler, reverse=False):
 
145
    def apply(self, filename, conflict_handler):
139
146
        backup_file(filename)
140
 
        self.contents_change.apply(filename, conflict_handler, reverse)
 
147
        self.contents_change.apply(filename, conflict_handler)
141
148
 
142
149
 
143
150
def invert_invent(inventory):
158
165
    new_cset = make_merge_changeset(cset, this, base, other, 
159
166
                                    conflict_handler, merge_factory)
160
167
    result = apply_changeset(new_cset, invert_invent(this.inventory),
161
 
                             this.basedir, conflict_handler, False)
 
168
                             this.basedir, conflict_handler)
162
169
    return result
163
170
    
164
171
 
181
188
 
182
189
    return new_cset
183
190
 
 
191
 
184
192
class ThreeWayConflict(Exception):
185
193
    def __init__(self, this, base, other):
186
194
        self.this = this
189
197
        msg = "Conflict merging %s %s and %s" % (this, base, other)
190
198
        Exception.__init__(self, msg)
191
199
 
 
200
 
192
201
def threeway_select(this, base, other):
193
202
    """Returns a value selected by the three-way algorithm.
194
203
    Raises ThreewayConflict if the algorithm yields a conflict"""
239
248
            parent_dir = {this_parent: this_dir, other_parent: other_dir, 
240
249
                          base_parent: base_dir}
241
250
            directory = parent_dir[parent]
242
 
            return os.path.join(directory, name)
 
251
            return pathjoin(directory, name)
243
252
        else:
244
253
            assert parent is None
245
254
            return None
329
338
        self.other_tree = other_tree
330
339
        self.file_id = file_id
331
340
 
332
 
    def apply(self, filename, conflict_handler, reverse=False):
333
 
        if not reverse:
334
 
            base = self.base_tree
335
 
            other = self.other_tree
336
 
        else:
337
 
            base = self.other_tree
338
 
            other = self.base_tree
 
341
    def apply(self, filename, conflict_handler):
 
342
        base = self.base_tree
 
343
        other = self.other_tree
339
344
        base_exec_flag = base.is_executable(self.file_id)
340
345
        other_exec_flag = other.is_executable(self.file_id)
341
346
        this_mode = os.stat(filename).st_mode
357
362
                to_mode = current_mode & ~0111
358
363
            os.chmod(filename, to_mode)
359
364
 
 
365