comparison mercurial/simplemerge.py @ 48603:77e24ee8994b

simplemerge: take arguments as annotated context objects The labels we put in conflict markers are formatted so the part before the ':' (typically says things like "local") is padded so the ':' is aligned among the labels. That means that if you specify a long label for "base" but the conflict marker style is "merge" (i.e. 2-way), the other two will have unwanted padding. We often don't specify a label for the base, so we don't notice the problem (and it may very well be that it didn't exist before my D11972). I think the best fix is to pass the labels along with the context objects, so the low-level code that switches on the marker style to use (i.e. `simplemerge`) can do the formatting. This patch starts doing that by passing a fully-formatted label to `simplemerge`. A coming patch will move the formatting to `simplemerge`. Differential Revision: https://phab.mercurial-scm.org/D12013
author Martin von Zweigbergk <martinvonz@google.com>
date Thu, 20 Jan 2022 11:00:30 -0800
parents 50de08904c63
children 3c8cc987672e
comparison
equal deleted inserted replaced
48602:62682662346c 48603:77e24ee8994b
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 from .i18n import _ 21 from .i18n import _
22 from .thirdparty import attr
22 from . import ( 23 from . import (
23 error, 24 error,
24 mdiff, 25 mdiff,
25 pycompat, 26 pycompat,
26 ) 27 )
282 if not opts.get('text'): 283 if not opts.get('text'):
283 raise error.Abort(msg) 284 raise error.Abort(msg)
284 return text 285 return text
285 286
286 287
287 def _picklabels(overrides): 288 def _format_labels(*inputs):
288 if len(overrides) > 3: 289 labels = []
289 raise error.Abort(_(b"can only specify three labels.")) 290 for input in inputs:
290 result = [None, None, None] 291 if input.label:
291 for i, override in enumerate(overrides): 292 labels.append(input.label)
292 result[i] = override 293 else:
293 return result 294 labels.append(None)
295 return labels
294 296
295 297
296 def _detect_newline(m3): 298 def _detect_newline(m3):
297 if len(m3.a) > 0: 299 if len(m3.a) > 0:
298 if m3.a[0].endswith(b'\r\n'): 300 if m3.a[0].endswith(b'\r\n'):
460 else: 462 else:
461 lines.extend(group_lines) 463 lines.extend(group_lines)
462 return lines 464 return lines
463 465
464 466
465 def simplemerge(ui, localctx, basectx, otherctx, **opts): 467 @attr.s
468 class MergeInput(object):
469 fctx = attr.ib()
470 label = attr.ib(default=None)
471
472
473 def simplemerge(ui, local, base, other, **opts):
466 """Performs the simplemerge algorithm. 474 """Performs the simplemerge algorithm.
467 475
468 The merged result is written into `localctx`. 476 The merged result is written into `localctx`.
469 """ 477 """
470 478
477 # it'd be worth considering whether merging encoded data (what the 485 # it'd be worth considering whether merging encoded data (what the
478 # repository usually sees) might be more useful. 486 # repository usually sees) might be more useful.
479 return _verifytext(ctx.decodeddata(), ctx.path(), ui, opts) 487 return _verifytext(ctx.decodeddata(), ctx.path(), ui, opts)
480 488
481 try: 489 try:
482 localtext = readctx(localctx) 490 localtext = readctx(local.fctx)
483 basetext = readctx(basectx) 491 basetext = readctx(base.fctx)
484 othertext = readctx(otherctx) 492 othertext = readctx(other.fctx)
485 except error.Abort: 493 except error.Abort:
486 return True 494 return True
487 495
488 m3 = Merge3Text(basetext, localtext, othertext) 496 m3 = Merge3Text(basetext, localtext, othertext)
489 conflicts = False 497 conflicts = False
493 elif mode == b'local': 501 elif mode == b'local':
494 lines = _resolve(m3, (1,)) 502 lines = _resolve(m3, (1,))
495 elif mode == b'other': 503 elif mode == b'other':
496 lines = _resolve(m3, (2,)) 504 lines = _resolve(m3, (2,))
497 else: 505 else:
498 name_a, name_b, name_base = _picklabels(opts.get('label', []))
499 if mode == b'mergediff': 506 if mode == b'mergediff':
500 lines, conflicts = render_mergediff(m3, name_a, name_b, name_base) 507 labels = _format_labels(local, other, base)
508 lines, conflicts = render_mergediff(m3, *labels)
501 elif mode == b'merge3': 509 elif mode == b'merge3':
502 lines, conflicts = render_merge3(m3, name_a, name_b, name_base) 510 labels = _format_labels(local, other, base)
511 lines, conflicts = render_merge3(m3, *labels)
503 else: 512 else:
504 lines, conflicts = render_minimized(m3, name_a, name_b) 513 labels = _format_labels(local, other)
514 lines, conflicts = render_minimized(m3, *labels)
505 515
506 mergedtext = b''.join(lines) 516 mergedtext = b''.join(lines)
507 if opts.get('print'): 517 if opts.get('print'):
508 ui.fout.write(mergedtext) 518 ui.fout.write(mergedtext)
509 else: 519 else:
510 # localctx.flags() already has the merged flags (done in 520 # local.fctx.flags() already has the merged flags (done in
511 # mergestate.resolve()) 521 # mergestate.resolve())
512 localctx.write(mergedtext, localctx.flags()) 522 local.fctx.write(mergedtext, local.fctx.flags())
513 523
514 return conflicts 524 return conflicts