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