##// END OF EJS Templates
simplemerge: enable option to resolve conflicts one way...
Jordi Gutiérrez Hermoso -
r26223:ed12abab default
parent child Browse files
Show More
@@ -1,410 +1,418
1 # Copyright (C) 2004, 2005 Canonical Ltd
1 # Copyright (C) 2004, 2005 Canonical Ltd
2 #
2 #
3 # This program is free software; you can redistribute it and/or modify
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
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
5 # the Free Software Foundation; either version 2 of the License, or
6 # (at your option) any later version.
6 # (at your option) any later version.
7 #
7 #
8 # This program is distributed in the hope that it will be useful,
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
11 # GNU General Public License for more details.
12 #
12 #
13 # You should have received a copy of the GNU General Public License
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, see <http://www.gnu.org/licenses/>.
14 # along with this program; if not, see <http://www.gnu.org/licenses/>.
15
15
16 # mbp: "you know that thing where cvs gives you conflict markers?"
16 # mbp: "you know that thing where cvs gives you conflict markers?"
17 # s: "i hate that."
17 # s: "i hate that."
18
18
19 from __future__ import absolute_import
19 from __future__ import absolute_import
20
20
21 import os
21 import os
22 import sys
22 import sys
23
23
24 from .i18n import _
24 from .i18n import _
25 from . import (
25 from . import (
26 mdiff,
26 mdiff,
27 scmutil,
27 scmutil,
28 util,
28 util,
29 )
29 )
30
30
31 class CantReprocessAndShowBase(Exception):
31 class CantReprocessAndShowBase(Exception):
32 pass
32 pass
33
33
34 def intersect(ra, rb):
34 def intersect(ra, rb):
35 """Given two ranges return the range where they intersect or None.
35 """Given two ranges return the range where they intersect or None.
36
36
37 >>> intersect((0, 10), (0, 6))
37 >>> intersect((0, 10), (0, 6))
38 (0, 6)
38 (0, 6)
39 >>> intersect((0, 10), (5, 15))
39 >>> intersect((0, 10), (5, 15))
40 (5, 10)
40 (5, 10)
41 >>> intersect((0, 10), (10, 15))
41 >>> intersect((0, 10), (10, 15))
42 >>> intersect((0, 9), (10, 15))
42 >>> intersect((0, 9), (10, 15))
43 >>> intersect((0, 9), (7, 15))
43 >>> intersect((0, 9), (7, 15))
44 (7, 9)
44 (7, 9)
45 """
45 """
46 assert ra[0] <= ra[1]
46 assert ra[0] <= ra[1]
47 assert rb[0] <= rb[1]
47 assert rb[0] <= rb[1]
48
48
49 sa = max(ra[0], rb[0])
49 sa = max(ra[0], rb[0])
50 sb = min(ra[1], rb[1])
50 sb = min(ra[1], rb[1])
51 if sa < sb:
51 if sa < sb:
52 return sa, sb
52 return sa, sb
53 else:
53 else:
54 return None
54 return None
55
55
56 def compare_range(a, astart, aend, b, bstart, bend):
56 def compare_range(a, astart, aend, b, bstart, bend):
57 """Compare a[astart:aend] == b[bstart:bend], without slicing.
57 """Compare a[astart:aend] == b[bstart:bend], without slicing.
58 """
58 """
59 if (aend - astart) != (bend - bstart):
59 if (aend - astart) != (bend - bstart):
60 return False
60 return False
61 for ia, ib in zip(xrange(astart, aend), xrange(bstart, bend)):
61 for ia, ib in zip(xrange(astart, aend), xrange(bstart, bend)):
62 if a[ia] != b[ib]:
62 if a[ia] != b[ib]:
63 return False
63 return False
64 else:
64 else:
65 return True
65 return True
66
66
67 class Merge3Text(object):
67 class Merge3Text(object):
68 """3-way merge of texts.
68 """3-way merge of texts.
69
69
70 Given strings BASE, OTHER, THIS, tries to produce a combined text
70 Given strings BASE, OTHER, THIS, tries to produce a combined text
71 incorporating the changes from both BASE->OTHER and BASE->THIS."""
71 incorporating the changes from both BASE->OTHER and BASE->THIS."""
72 def __init__(self, basetext, atext, btext, base=None, a=None, b=None):
72 def __init__(self, basetext, atext, btext, base=None, a=None, b=None):
73 self.basetext = basetext
73 self.basetext = basetext
74 self.atext = atext
74 self.atext = atext
75 self.btext = btext
75 self.btext = btext
76 if base is None:
76 if base is None:
77 base = mdiff.splitnewlines(basetext)
77 base = mdiff.splitnewlines(basetext)
78 if a is None:
78 if a is None:
79 a = mdiff.splitnewlines(atext)
79 a = mdiff.splitnewlines(atext)
80 if b is None:
80 if b is None:
81 b = mdiff.splitnewlines(btext)
81 b = mdiff.splitnewlines(btext)
82 self.base = base
82 self.base = base
83 self.a = a
83 self.a = a
84 self.b = b
84 self.b = b
85
85
86 def merge_lines(self,
86 def merge_lines(self,
87 name_a=None,
87 name_a=None,
88 name_b=None,
88 name_b=None,
89 name_base=None,
89 name_base=None,
90 start_marker='<<<<<<<',
90 start_marker='<<<<<<<',
91 mid_marker='=======',
91 mid_marker='=======',
92 end_marker='>>>>>>>',
92 end_marker='>>>>>>>',
93 base_marker=None):
93 base_marker=None,
94 localorother=None):
94 """Return merge in cvs-like form.
95 """Return merge in cvs-like form.
95 """
96 """
96 self.conflicts = False
97 self.conflicts = False
97 newline = '\n'
98 newline = '\n'
98 if len(self.a) > 0:
99 if len(self.a) > 0:
99 if self.a[0].endswith('\r\n'):
100 if self.a[0].endswith('\r\n'):
100 newline = '\r\n'
101 newline = '\r\n'
101 elif self.a[0].endswith('\r'):
102 elif self.a[0].endswith('\r'):
102 newline = '\r'
103 newline = '\r'
103 if name_a and start_marker:
104 if name_a and start_marker:
104 start_marker = start_marker + ' ' + name_a
105 start_marker = start_marker + ' ' + name_a
105 if name_b and end_marker:
106 if name_b and end_marker:
106 end_marker = end_marker + ' ' + name_b
107 end_marker = end_marker + ' ' + name_b
107 if name_base and base_marker:
108 if name_base and base_marker:
108 base_marker = base_marker + ' ' + name_base
109 base_marker = base_marker + ' ' + name_base
109 merge_regions = self.merge_regions()
110 merge_regions = self.merge_regions()
110 for t in merge_regions:
111 for t in merge_regions:
111 what = t[0]
112 what = t[0]
112 if what == 'unchanged':
113 if what == 'unchanged':
113 for i in range(t[1], t[2]):
114 for i in range(t[1], t[2]):
114 yield self.base[i]
115 yield self.base[i]
115 elif what == 'a' or what == 'same':
116 elif what == 'a' or what == 'same':
116 for i in range(t[1], t[2]):
117 for i in range(t[1], t[2]):
117 yield self.a[i]
118 yield self.a[i]
118 elif what == 'b':
119 elif what == 'b':
119 for i in range(t[1], t[2]):
120 for i in range(t[1], t[2]):
120 yield self.b[i]
121 yield self.b[i]
121 elif what == 'conflict':
122 elif what == 'conflict':
123 if localorother == 'local':
124 for i in range(t[3], t[4]):
125 yield self.a[i]
126 elif localorother == 'other':
127 for i in range(t[5], t[6]):
128 yield self.b[i]
129 else:
122 self.conflicts = True
130 self.conflicts = True
123 if start_marker is not None:
131 if start_marker is not None:
124 yield start_marker + newline
132 yield start_marker + newline
125 for i in range(t[3], t[4]):
133 for i in range(t[3], t[4]):
126 yield self.a[i]
134 yield self.a[i]
127 if base_marker is not None:
135 if base_marker is not None:
128 yield base_marker + newline
136 yield base_marker + newline
129 for i in range(t[1], t[2]):
137 for i in range(t[1], t[2]):
130 yield self.base[i]
138 yield self.base[i]
131 if mid_marker is not None:
139 if mid_marker is not None:
132 yield mid_marker + newline
140 yield mid_marker + newline
133 for i in range(t[5], t[6]):
141 for i in range(t[5], t[6]):
134 yield self.b[i]
142 yield self.b[i]
135 if end_marker is not None:
143 if end_marker is not None:
136 yield end_marker + newline
144 yield end_marker + newline
137 else:
145 else:
138 raise ValueError(what)
146 raise ValueError(what)
139
147
140 def merge_groups(self):
148 def merge_groups(self):
141 """Yield sequence of line groups. Each one is a tuple:
149 """Yield sequence of line groups. Each one is a tuple:
142
150
143 'unchanged', lines
151 'unchanged', lines
144 Lines unchanged from base
152 Lines unchanged from base
145
153
146 'a', lines
154 'a', lines
147 Lines taken from a
155 Lines taken from a
148
156
149 'same', lines
157 'same', lines
150 Lines taken from a (and equal to b)
158 Lines taken from a (and equal to b)
151
159
152 'b', lines
160 'b', lines
153 Lines taken from b
161 Lines taken from b
154
162
155 'conflict', base_lines, a_lines, b_lines
163 'conflict', base_lines, a_lines, b_lines
156 Lines from base were changed to either a or b and conflict.
164 Lines from base were changed to either a or b and conflict.
157 """
165 """
158 for t in self.merge_regions():
166 for t in self.merge_regions():
159 what = t[0]
167 what = t[0]
160 if what == 'unchanged':
168 if what == 'unchanged':
161 yield what, self.base[t[1]:t[2]]
169 yield what, self.base[t[1]:t[2]]
162 elif what == 'a' or what == 'same':
170 elif what == 'a' or what == 'same':
163 yield what, self.a[t[1]:t[2]]
171 yield what, self.a[t[1]:t[2]]
164 elif what == 'b':
172 elif what == 'b':
165 yield what, self.b[t[1]:t[2]]
173 yield what, self.b[t[1]:t[2]]
166 elif what == 'conflict':
174 elif what == 'conflict':
167 yield (what,
175 yield (what,
168 self.base[t[1]:t[2]],
176 self.base[t[1]:t[2]],
169 self.a[t[3]:t[4]],
177 self.a[t[3]:t[4]],
170 self.b[t[5]:t[6]])
178 self.b[t[5]:t[6]])
171 else:
179 else:
172 raise ValueError(what)
180 raise ValueError(what)
173
181
174 def merge_regions(self):
182 def merge_regions(self):
175 """Return sequences of matching and conflicting regions.
183 """Return sequences of matching and conflicting regions.
176
184
177 This returns tuples, where the first value says what kind we
185 This returns tuples, where the first value says what kind we
178 have:
186 have:
179
187
180 'unchanged', start, end
188 'unchanged', start, end
181 Take a region of base[start:end]
189 Take a region of base[start:end]
182
190
183 'same', astart, aend
191 'same', astart, aend
184 b and a are different from base but give the same result
192 b and a are different from base but give the same result
185
193
186 'a', start, end
194 'a', start, end
187 Non-clashing insertion from a[start:end]
195 Non-clashing insertion from a[start:end]
188
196
189 Method is as follows:
197 Method is as follows:
190
198
191 The two sequences align only on regions which match the base
199 The two sequences align only on regions which match the base
192 and both descendants. These are found by doing a two-way diff
200 and both descendants. These are found by doing a two-way diff
193 of each one against the base, and then finding the
201 of each one against the base, and then finding the
194 intersections between those regions. These "sync regions"
202 intersections between those regions. These "sync regions"
195 are by definition unchanged in both and easily dealt with.
203 are by definition unchanged in both and easily dealt with.
196
204
197 The regions in between can be in any of three cases:
205 The regions in between can be in any of three cases:
198 conflicted, or changed on only one side.
206 conflicted, or changed on only one side.
199 """
207 """
200
208
201 # section a[0:ia] has been disposed of, etc
209 # section a[0:ia] has been disposed of, etc
202 iz = ia = ib = 0
210 iz = ia = ib = 0
203
211
204 for region in self.find_sync_regions():
212 for region in self.find_sync_regions():
205 zmatch, zend, amatch, aend, bmatch, bend = region
213 zmatch, zend, amatch, aend, bmatch, bend = region
206 #print 'match base [%d:%d]' % (zmatch, zend)
214 #print 'match base [%d:%d]' % (zmatch, zend)
207
215
208 matchlen = zend - zmatch
216 matchlen = zend - zmatch
209 assert matchlen >= 0
217 assert matchlen >= 0
210 assert matchlen == (aend - amatch)
218 assert matchlen == (aend - amatch)
211 assert matchlen == (bend - bmatch)
219 assert matchlen == (bend - bmatch)
212
220
213 len_a = amatch - ia
221 len_a = amatch - ia
214 len_b = bmatch - ib
222 len_b = bmatch - ib
215 len_base = zmatch - iz
223 len_base = zmatch - iz
216 assert len_a >= 0
224 assert len_a >= 0
217 assert len_b >= 0
225 assert len_b >= 0
218 assert len_base >= 0
226 assert len_base >= 0
219
227
220 #print 'unmatched a=%d, b=%d' % (len_a, len_b)
228 #print 'unmatched a=%d, b=%d' % (len_a, len_b)
221
229
222 if len_a or len_b:
230 if len_a or len_b:
223 # try to avoid actually slicing the lists
231 # try to avoid actually slicing the lists
224 equal_a = compare_range(self.a, ia, amatch,
232 equal_a = compare_range(self.a, ia, amatch,
225 self.base, iz, zmatch)
233 self.base, iz, zmatch)
226 equal_b = compare_range(self.b, ib, bmatch,
234 equal_b = compare_range(self.b, ib, bmatch,
227 self.base, iz, zmatch)
235 self.base, iz, zmatch)
228 same = compare_range(self.a, ia, amatch,
236 same = compare_range(self.a, ia, amatch,
229 self.b, ib, bmatch)
237 self.b, ib, bmatch)
230
238
231 if same:
239 if same:
232 yield 'same', ia, amatch
240 yield 'same', ia, amatch
233 elif equal_a and not equal_b:
241 elif equal_a and not equal_b:
234 yield 'b', ib, bmatch
242 yield 'b', ib, bmatch
235 elif equal_b and not equal_a:
243 elif equal_b and not equal_a:
236 yield 'a', ia, amatch
244 yield 'a', ia, amatch
237 elif not equal_a and not equal_b:
245 elif not equal_a and not equal_b:
238 yield 'conflict', iz, zmatch, ia, amatch, ib, bmatch
246 yield 'conflict', iz, zmatch, ia, amatch, ib, bmatch
239 else:
247 else:
240 raise AssertionError("can't handle a=b=base but unmatched")
248 raise AssertionError("can't handle a=b=base but unmatched")
241
249
242 ia = amatch
250 ia = amatch
243 ib = bmatch
251 ib = bmatch
244 iz = zmatch
252 iz = zmatch
245
253
246 # if the same part of the base was deleted on both sides
254 # if the same part of the base was deleted on both sides
247 # that's OK, we can just skip it.
255 # that's OK, we can just skip it.
248
256
249
257
250 if matchlen > 0:
258 if matchlen > 0:
251 assert ia == amatch
259 assert ia == amatch
252 assert ib == bmatch
260 assert ib == bmatch
253 assert iz == zmatch
261 assert iz == zmatch
254
262
255 yield 'unchanged', zmatch, zend
263 yield 'unchanged', zmatch, zend
256 iz = zend
264 iz = zend
257 ia = aend
265 ia = aend
258 ib = bend
266 ib = bend
259
267
260 def find_sync_regions(self):
268 def find_sync_regions(self):
261 """Return a list of sync regions, where both descendants match the base.
269 """Return a list of sync regions, where both descendants match the base.
262
270
263 Generates a list of (base1, base2, a1, a2, b1, b2). There is
271 Generates a list of (base1, base2, a1, a2, b1, b2). There is
264 always a zero-length sync region at the end of all the files.
272 always a zero-length sync region at the end of all the files.
265 """
273 """
266
274
267 ia = ib = 0
275 ia = ib = 0
268 amatches = mdiff.get_matching_blocks(self.basetext, self.atext)
276 amatches = mdiff.get_matching_blocks(self.basetext, self.atext)
269 bmatches = mdiff.get_matching_blocks(self.basetext, self.btext)
277 bmatches = mdiff.get_matching_blocks(self.basetext, self.btext)
270 len_a = len(amatches)
278 len_a = len(amatches)
271 len_b = len(bmatches)
279 len_b = len(bmatches)
272
280
273 sl = []
281 sl = []
274
282
275 while ia < len_a and ib < len_b:
283 while ia < len_a and ib < len_b:
276 abase, amatch, alen = amatches[ia]
284 abase, amatch, alen = amatches[ia]
277 bbase, bmatch, blen = bmatches[ib]
285 bbase, bmatch, blen = bmatches[ib]
278
286
279 # there is an unconflicted block at i; how long does it
287 # there is an unconflicted block at i; how long does it
280 # extend? until whichever one ends earlier.
288 # extend? until whichever one ends earlier.
281 i = intersect((abase, abase + alen), (bbase, bbase + blen))
289 i = intersect((abase, abase + alen), (bbase, bbase + blen))
282 if i:
290 if i:
283 intbase = i[0]
291 intbase = i[0]
284 intend = i[1]
292 intend = i[1]
285 intlen = intend - intbase
293 intlen = intend - intbase
286
294
287 # found a match of base[i[0], i[1]]; this may be less than
295 # found a match of base[i[0], i[1]]; this may be less than
288 # the region that matches in either one
296 # the region that matches in either one
289 assert intlen <= alen
297 assert intlen <= alen
290 assert intlen <= blen
298 assert intlen <= blen
291 assert abase <= intbase
299 assert abase <= intbase
292 assert bbase <= intbase
300 assert bbase <= intbase
293
301
294 asub = amatch + (intbase - abase)
302 asub = amatch + (intbase - abase)
295 bsub = bmatch + (intbase - bbase)
303 bsub = bmatch + (intbase - bbase)
296 aend = asub + intlen
304 aend = asub + intlen
297 bend = bsub + intlen
305 bend = bsub + intlen
298
306
299 assert self.base[intbase:intend] == self.a[asub:aend], \
307 assert self.base[intbase:intend] == self.a[asub:aend], \
300 (self.base[intbase:intend], self.a[asub:aend])
308 (self.base[intbase:intend], self.a[asub:aend])
301
309
302 assert self.base[intbase:intend] == self.b[bsub:bend]
310 assert self.base[intbase:intend] == self.b[bsub:bend]
303
311
304 sl.append((intbase, intend,
312 sl.append((intbase, intend,
305 asub, aend,
313 asub, aend,
306 bsub, bend))
314 bsub, bend))
307
315
308 # advance whichever one ends first in the base text
316 # advance whichever one ends first in the base text
309 if (abase + alen) < (bbase + blen):
317 if (abase + alen) < (bbase + blen):
310 ia += 1
318 ia += 1
311 else:
319 else:
312 ib += 1
320 ib += 1
313
321
314 intbase = len(self.base)
322 intbase = len(self.base)
315 abase = len(self.a)
323 abase = len(self.a)
316 bbase = len(self.b)
324 bbase = len(self.b)
317 sl.append((intbase, intbase, abase, abase, bbase, bbase))
325 sl.append((intbase, intbase, abase, abase, bbase, bbase))
318
326
319 return sl
327 return sl
320
328
321 def find_unconflicted(self):
329 def find_unconflicted(self):
322 """Return a list of ranges in base that are not conflicted."""
330 """Return a list of ranges in base that are not conflicted."""
323 am = mdiff.get_matching_blocks(self.basetext, self.atext)
331 am = mdiff.get_matching_blocks(self.basetext, self.atext)
324 bm = mdiff.get_matching_blocks(self.basetext, self.btext)
332 bm = mdiff.get_matching_blocks(self.basetext, self.btext)
325
333
326 unc = []
334 unc = []
327
335
328 while am and bm:
336 while am and bm:
329 # there is an unconflicted block at i; how long does it
337 # there is an unconflicted block at i; how long does it
330 # extend? until whichever one ends earlier.
338 # extend? until whichever one ends earlier.
331 a1 = am[0][0]
339 a1 = am[0][0]
332 a2 = a1 + am[0][2]
340 a2 = a1 + am[0][2]
333 b1 = bm[0][0]
341 b1 = bm[0][0]
334 b2 = b1 + bm[0][2]
342 b2 = b1 + bm[0][2]
335 i = intersect((a1, a2), (b1, b2))
343 i = intersect((a1, a2), (b1, b2))
336 if i:
344 if i:
337 unc.append(i)
345 unc.append(i)
338
346
339 if a2 < b2:
347 if a2 < b2:
340 del am[0]
348 del am[0]
341 else:
349 else:
342 del bm[0]
350 del bm[0]
343
351
344 return unc
352 return unc
345
353
346 def simplemerge(ui, local, base, other, **opts):
354 def simplemerge(ui, local, base, other, **opts):
347 def readfile(filename):
355 def readfile(filename):
348 f = open(filename, "rb")
356 f = open(filename, "rb")
349 text = f.read()
357 text = f.read()
350 f.close()
358 f.close()
351 if util.binary(text):
359 if util.binary(text):
352 msg = _("%s looks like a binary file.") % filename
360 msg = _("%s looks like a binary file.") % filename
353 if not opts.get('quiet'):
361 if not opts.get('quiet'):
354 ui.warn(_('warning: %s\n') % msg)
362 ui.warn(_('warning: %s\n') % msg)
355 if not opts.get('text'):
363 if not opts.get('text'):
356 raise util.Abort(msg)
364 raise util.Abort(msg)
357 return text
365 return text
358
366
359 mode = opts.get('mode','merge')
367 mode = opts.get('mode','merge')
360 if mode == 'union':
368 if mode == 'union':
361 name_a = None
369 name_a = None
362 name_b = None
370 name_b = None
363 name_base = None
371 name_base = None
364 else:
372 else:
365 name_a = local
373 name_a = local
366 name_b = other
374 name_b = other
367 name_base = None
375 name_base = None
368 labels = opts.get('label', [])
376 labels = opts.get('label', [])
369 if len(labels) > 0:
377 if len(labels) > 0:
370 name_a = labels[0]
378 name_a = labels[0]
371 if len(labels) > 1:
379 if len(labels) > 1:
372 name_b = labels[1]
380 name_b = labels[1]
373 if len(labels) > 2:
381 if len(labels) > 2:
374 name_base = labels[2]
382 name_base = labels[2]
375 if len(labels) > 3:
383 if len(labels) > 3:
376 raise util.Abort(_("can only specify three labels."))
384 raise util.Abort(_("can only specify three labels."))
377
385
378 try:
386 try:
379 localtext = readfile(local)
387 localtext = readfile(local)
380 basetext = readfile(base)
388 basetext = readfile(base)
381 othertext = readfile(other)
389 othertext = readfile(other)
382 except util.Abort:
390 except util.Abort:
383 return 1
391 return 1
384
392
385 local = os.path.realpath(local)
393 local = os.path.realpath(local)
386 if not opts.get('print'):
394 if not opts.get('print'):
387 opener = scmutil.opener(os.path.dirname(local))
395 opener = scmutil.opener(os.path.dirname(local))
388 out = opener(os.path.basename(local), "w", atomictemp=True)
396 out = opener(os.path.basename(local), "w", atomictemp=True)
389 else:
397 else:
390 out = sys.stdout
398 out = sys.stdout
391
399
392 m3 = Merge3Text(basetext, localtext, othertext)
400 m3 = Merge3Text(basetext, localtext, othertext)
393 extrakwargs = {}
401 extrakwargs = {"localorother": opts.get("localorother", None)}
394 if mode == 'union':
402 if mode == 'union':
395 extrakwargs['start_marker'] = None
403 extrakwargs['start_marker'] = None
396 extrakwargs['mid_marker'] = None
404 extrakwargs['mid_marker'] = None
397 extrakwargs['end_marker'] = None
405 extrakwargs['end_marker'] = None
398 elif name_base is not None:
406 elif name_base is not None:
399 extrakwargs['base_marker'] = '|||||||'
407 extrakwargs['base_marker'] = '|||||||'
400 extrakwargs['name_base'] = name_base
408 extrakwargs['name_base'] = name_base
401 for line in m3.merge_lines(name_a=name_a, name_b=name_b, **extrakwargs):
409 for line in m3.merge_lines(name_a=name_a, name_b=name_b, **extrakwargs):
402 out.write(line)
410 out.write(line)
403
411
404 if not opts.get('print'):
412 if not opts.get('print'):
405 out.close()
413 out.close()
406
414
407 if m3.conflicts and not mode == 'union':
415 if m3.conflicts and not mode == 'union':
408 if not opts.get('quiet'):
416 if not opts.get('quiet'):
409 ui.warn(_("warning: conflicts during merge.\n"))
417 ui.warn(_("warning: conflicts during merge.\n"))
410 return 1
418 return 1
General Comments 0
You need to be logged in to leave comments. Login now