91 def merge_lines( |
91 def merge_lines( |
92 self, |
92 self, |
93 name_a=None, |
93 name_a=None, |
94 name_b=None, |
94 name_b=None, |
95 name_base=None, |
95 name_base=None, |
96 start_marker='<<<<<<<', |
96 start_marker=b'<<<<<<<', |
97 mid_marker='=======', |
97 mid_marker=b'=======', |
98 end_marker='>>>>>>>', |
98 end_marker=b'>>>>>>>', |
99 base_marker=None, |
99 base_marker=None, |
100 localorother=None, |
100 localorother=None, |
101 minimize=False, |
101 minimize=False, |
102 ): |
102 ): |
103 """Return merge in cvs-like form. |
103 """Return merge in cvs-like form. |
104 """ |
104 """ |
105 self.conflicts = False |
105 self.conflicts = False |
106 newline = '\n' |
106 newline = b'\n' |
107 if len(self.a) > 0: |
107 if len(self.a) > 0: |
108 if self.a[0].endswith('\r\n'): |
108 if self.a[0].endswith(b'\r\n'): |
109 newline = '\r\n' |
109 newline = b'\r\n' |
110 elif self.a[0].endswith('\r'): |
110 elif self.a[0].endswith(b'\r'): |
111 newline = '\r' |
111 newline = b'\r' |
112 if name_a and start_marker: |
112 if name_a and start_marker: |
113 start_marker = start_marker + ' ' + name_a |
113 start_marker = start_marker + b' ' + name_a |
114 if name_b and end_marker: |
114 if name_b and end_marker: |
115 end_marker = end_marker + ' ' + name_b |
115 end_marker = end_marker + b' ' + name_b |
116 if name_base and base_marker: |
116 if name_base and base_marker: |
117 base_marker = base_marker + ' ' + name_base |
117 base_marker = base_marker + b' ' + name_base |
118 merge_regions = self.merge_regions() |
118 merge_regions = self.merge_regions() |
119 if minimize: |
119 if minimize: |
120 merge_regions = self.minimize(merge_regions) |
120 merge_regions = self.minimize(merge_regions) |
121 for t in merge_regions: |
121 for t in merge_regions: |
122 what = t[0] |
122 what = t[0] |
123 if what == 'unchanged': |
123 if what == b'unchanged': |
124 for i in range(t[1], t[2]): |
124 for i in range(t[1], t[2]): |
125 yield self.base[i] |
125 yield self.base[i] |
126 elif what == 'a' or what == 'same': |
126 elif what == b'a' or what == b'same': |
127 for i in range(t[1], t[2]): |
127 for i in range(t[1], t[2]): |
128 yield self.a[i] |
128 yield self.a[i] |
129 elif what == 'b': |
129 elif what == b'b': |
130 for i in range(t[1], t[2]): |
130 for i in range(t[1], t[2]): |
131 yield self.b[i] |
131 yield self.b[i] |
132 elif what == 'conflict': |
132 elif what == b'conflict': |
133 if localorother == 'local': |
133 if localorother == b'local': |
134 for i in range(t[3], t[4]): |
134 for i in range(t[3], t[4]): |
135 yield self.a[i] |
135 yield self.a[i] |
136 elif localorother == 'other': |
136 elif localorother == b'other': |
137 for i in range(t[5], t[6]): |
137 for i in range(t[5], t[6]): |
138 yield self.b[i] |
138 yield self.b[i] |
139 else: |
139 else: |
140 self.conflicts = True |
140 self.conflicts = True |
141 if start_marker is not None: |
141 if start_marker is not None: |
173 'conflict', base_lines, a_lines, b_lines |
173 'conflict', base_lines, a_lines, b_lines |
174 Lines from base were changed to either a or b and conflict. |
174 Lines from base were changed to either a or b and conflict. |
175 """ |
175 """ |
176 for t in self.merge_regions(): |
176 for t in self.merge_regions(): |
177 what = t[0] |
177 what = t[0] |
178 if what == 'unchanged': |
178 if what == b'unchanged': |
179 yield what, self.base[t[1] : t[2]] |
179 yield what, self.base[t[1] : t[2]] |
180 elif what == 'a' or what == 'same': |
180 elif what == b'a' or what == b'same': |
181 yield what, self.a[t[1] : t[2]] |
181 yield what, self.a[t[1] : t[2]] |
182 elif what == 'b': |
182 elif what == b'b': |
183 yield what, self.b[t[1] : t[2]] |
183 yield what, self.b[t[1] : t[2]] |
184 elif what == 'conflict': |
184 elif what == b'conflict': |
185 yield ( |
185 yield ( |
186 what, |
186 what, |
187 self.base[t[1] : t[2]], |
187 self.base[t[1] : t[2]], |
188 self.a[t[3] : t[4]], |
188 self.a[t[3] : t[4]], |
189 self.b[t[5] : t[6]], |
189 self.b[t[5] : t[6]], |
251 self.b, ib, bmatch, self.base, iz, zmatch |
251 self.b, ib, bmatch, self.base, iz, zmatch |
252 ) |
252 ) |
253 same = compare_range(self.a, ia, amatch, self.b, ib, bmatch) |
253 same = compare_range(self.a, ia, amatch, self.b, ib, bmatch) |
254 |
254 |
255 if same: |
255 if same: |
256 yield 'same', ia, amatch |
256 yield b'same', ia, amatch |
257 elif equal_a and not equal_b: |
257 elif equal_a and not equal_b: |
258 yield 'b', ib, bmatch |
258 yield b'b', ib, bmatch |
259 elif equal_b and not equal_a: |
259 elif equal_b and not equal_a: |
260 yield 'a', ia, amatch |
260 yield b'a', ia, amatch |
261 elif not equal_a and not equal_b: |
261 elif not equal_a and not equal_b: |
262 yield 'conflict', iz, zmatch, ia, amatch, ib, bmatch |
262 yield b'conflict', iz, zmatch, ia, amatch, ib, bmatch |
263 else: |
263 else: |
264 raise AssertionError("can't handle a=b=base but unmatched") |
264 raise AssertionError(b"can't handle a=b=base but unmatched") |
265 |
265 |
266 ia = amatch |
266 ia = amatch |
267 ib = bmatch |
267 ib = bmatch |
268 iz = zmatch |
268 iz = zmatch |
269 |
269 |
286 Lines where both A and B have made the same changes at the beginning |
286 Lines where both A and B have made the same changes at the beginning |
287 or the end of each merge region are eliminated from the conflict |
287 or the end of each merge region are eliminated from the conflict |
288 region and are instead considered the same. |
288 region and are instead considered the same. |
289 """ |
289 """ |
290 for region in merge_regions: |
290 for region in merge_regions: |
291 if region[0] != "conflict": |
291 if region[0] != b"conflict": |
292 yield region |
292 yield region |
293 continue |
293 continue |
294 issue, z1, z2, a1, a2, b1, b2 = region |
294 issue, z1, z2, a1, a2, b1, b2 = region |
295 alen = a2 - a1 |
295 alen = a2 - a1 |
296 blen = b2 - b1 |
296 blen = b2 - b1 |
312 ): |
312 ): |
313 ii += 1 |
313 ii += 1 |
314 endmatches = ii |
314 endmatches = ii |
315 |
315 |
316 if startmatches > 0: |
316 if startmatches > 0: |
317 yield 'same', a1, a1 + startmatches |
317 yield b'same', a1, a1 + startmatches |
318 |
318 |
319 yield ( |
319 yield ( |
320 'conflict', |
320 b'conflict', |
321 z1, |
321 z1, |
322 z2, |
322 z2, |
323 a1 + startmatches, |
323 a1 + startmatches, |
324 a2 - endmatches, |
324 a2 - endmatches, |
325 b1 + startmatches, |
325 b1 + startmatches, |
326 b2 - endmatches, |
326 b2 - endmatches, |
327 ) |
327 ) |
328 |
328 |
329 if endmatches > 0: |
329 if endmatches > 0: |
330 yield 'same', a2 - endmatches, a2 |
330 yield b'same', a2 - endmatches, a2 |
331 |
331 |
332 def find_sync_regions(self): |
332 def find_sync_regions(self): |
333 """Return a list of sync regions, where both descendants match the base. |
333 """Return a list of sync regions, where both descendants match the base. |
334 |
334 |
335 Generates a list of (base1, base2, a1, a2, b1, b2). There is |
335 Generates a list of (base1, base2, a1, a2, b1, b2). There is |
418 |
418 |
419 def _verifytext(text, path, ui, opts): |
419 def _verifytext(text, path, ui, opts): |
420 """verifies that text is non-binary (unless opts[text] is passed, |
420 """verifies that text is non-binary (unless opts[text] is passed, |
421 then we just warn)""" |
421 then we just warn)""" |
422 if stringutil.binary(text): |
422 if stringutil.binary(text): |
423 msg = _("%s looks like a binary file.") % path |
423 msg = _(b"%s looks like a binary file.") % path |
424 if not opts.get('quiet'): |
424 if not opts.get(b'quiet'): |
425 ui.warn(_('warning: %s\n') % msg) |
425 ui.warn(_(b'warning: %s\n') % msg) |
426 if not opts.get('text'): |
426 if not opts.get(b'text'): |
427 raise error.Abort(msg) |
427 raise error.Abort(msg) |
428 return text |
428 return text |
429 |
429 |
430 |
430 |
431 def _picklabels(defaults, overrides): |
431 def _picklabels(defaults, overrides): |
432 if len(overrides) > 3: |
432 if len(overrides) > 3: |
433 raise error.Abort(_("can only specify three labels.")) |
433 raise error.Abort(_(b"can only specify three labels.")) |
434 result = defaults[:] |
434 result = defaults[:] |
435 for i, override in enumerate(overrides): |
435 for i, override in enumerate(overrides): |
436 result[i] = override |
436 result[i] = override |
437 return result |
437 return result |
438 |
438 |
452 # Maintain that behavior today for BC, though perhaps in the future |
452 # Maintain that behavior today for BC, though perhaps in the future |
453 # it'd be worth considering whether merging encoded data (what the |
453 # it'd be worth considering whether merging encoded data (what the |
454 # repository usually sees) might be more useful. |
454 # repository usually sees) might be more useful. |
455 return _verifytext(ctx.decodeddata(), ctx.path(), ui, opts) |
455 return _verifytext(ctx.decodeddata(), ctx.path(), ui, opts) |
456 |
456 |
457 mode = opts.get('mode', 'merge') |
457 mode = opts.get(b'mode', b'merge') |
458 name_a, name_b, name_base = None, None, None |
458 name_a, name_b, name_base = None, None, None |
459 if mode != 'union': |
459 if mode != b'union': |
460 name_a, name_b, name_base = _picklabels( |
460 name_a, name_b, name_base = _picklabels( |
461 [localctx.path(), otherctx.path(), None], opts.get('label', []) |
461 [localctx.path(), otherctx.path(), None], opts.get(b'label', []) |
462 ) |
462 ) |
463 |
463 |
464 try: |
464 try: |
465 localtext = readctx(localctx) |
465 localtext = readctx(localctx) |
466 basetext = readctx(basectx) |
466 basetext = readctx(basectx) |
468 except error.Abort: |
468 except error.Abort: |
469 return 1 |
469 return 1 |
470 |
470 |
471 m3 = Merge3Text(basetext, localtext, othertext) |
471 m3 = Merge3Text(basetext, localtext, othertext) |
472 extrakwargs = { |
472 extrakwargs = { |
473 "localorother": opts.get("localorother", None), |
473 b"localorother": opts.get(b"localorother", None), |
474 'minimize': True, |
474 b'minimize': True, |
475 } |
475 } |
476 if mode == 'union': |
476 if mode == b'union': |
477 extrakwargs['start_marker'] = None |
477 extrakwargs[b'start_marker'] = None |
478 extrakwargs['mid_marker'] = None |
478 extrakwargs[b'mid_marker'] = None |
479 extrakwargs['end_marker'] = None |
479 extrakwargs[b'end_marker'] = None |
480 elif name_base is not None: |
480 elif name_base is not None: |
481 extrakwargs['base_marker'] = '|||||||' |
481 extrakwargs[b'base_marker'] = b'|||||||' |
482 extrakwargs['name_base'] = name_base |
482 extrakwargs[b'name_base'] = name_base |
483 extrakwargs['minimize'] = False |
483 extrakwargs[b'minimize'] = False |
484 |
484 |
485 mergedtext = "" |
485 mergedtext = b"" |
486 for line in m3.merge_lines( |
486 for line in m3.merge_lines( |
487 name_a=name_a, name_b=name_b, **pycompat.strkwargs(extrakwargs) |
487 name_a=name_a, name_b=name_b, **pycompat.strkwargs(extrakwargs) |
488 ): |
488 ): |
489 if opts.get('print'): |
489 if opts.get(b'print'): |
490 ui.fout.write(line) |
490 ui.fout.write(line) |
491 else: |
491 else: |
492 mergedtext += line |
492 mergedtext += line |
493 |
493 |
494 if not opts.get('print'): |
494 if not opts.get(b'print'): |
495 localctx.write(mergedtext, localctx.flags()) |
495 localctx.write(mergedtext, localctx.flags()) |
496 |
496 |
497 if m3.conflicts and not mode == 'union': |
497 if m3.conflicts and not mode == b'union': |
498 return 1 |
498 return 1 |