comparison mercurial/filemerge.py @ 48586:fd9fe2658cda

filemerge: pass `simplemerge.MergeInput` to tool functions Differential Revision: https://phab.mercurial-scm.org/D12018
author Martin von Zweigbergk <martinvonz@google.com>
date Thu, 20 Jan 2022 16:16:05 -0800
parents 07069fcd9a6e
children 3c8cc987672e
comparison
equal deleted inserted replaced
48585:07069fcd9a6e 48586:fd9fe2658cda
304 if newdata != data: 304 if newdata != data:
305 util.writefile(file, newdata) 305 util.writefile(file, newdata)
306 306
307 307
308 @internaltool(b'prompt', nomerge) 308 @internaltool(b'prompt', nomerge)
309 def _iprompt(repo, mynode, fcd, fco, fca, toolconf, labels=None): 309 def _iprompt(repo, mynode, local, other, base, toolconf):
310 """Asks the user which of the local `p1()` or the other `p2()` version to 310 """Asks the user which of the local `p1()` or the other `p2()` version to
311 keep as the merged version.""" 311 keep as the merged version."""
312 ui = repo.ui 312 ui = repo.ui
313 fd = fcd.path() 313 fd = local.fctx.path()
314 uipathfn = scmutil.getuipathfn(repo) 314 uipathfn = scmutil.getuipathfn(repo)
315 315
316 # Avoid prompting during an in-memory merge since it doesn't support merge 316 # Avoid prompting during an in-memory merge since it doesn't support merge
317 # conflicts. 317 # conflicts.
318 if fcd.changectx().isinmemory(): 318 if local.fctx.changectx().isinmemory():
319 raise error.InMemoryMergeConflictsError( 319 raise error.InMemoryMergeConflictsError(
320 b'in-memory merge does not support file conflicts' 320 b'in-memory merge does not support file conflicts'
321 ) 321 )
322 322
323 prompts = partextras(labels) 323 prompts = partextras([local.label, other.label])
324 prompts[b'fd'] = uipathfn(fd) 324 prompts[b'fd'] = uipathfn(fd)
325 try: 325 try:
326 if fco.isabsent(): 326 if other.fctx.isabsent():
327 index = ui.promptchoice(_localchangedotherdeletedmsg % prompts, 2) 327 index = ui.promptchoice(_localchangedotherdeletedmsg % prompts, 2)
328 choice = [b'local', b'other', b'unresolved'][index] 328 choice = [b'local', b'other', b'unresolved'][index]
329 elif fcd.isabsent(): 329 elif local.fctx.isabsent():
330 index = ui.promptchoice(_otherchangedlocaldeletedmsg % prompts, 2) 330 index = ui.promptchoice(_otherchangedlocaldeletedmsg % prompts, 2)
331 choice = [b'other', b'local', b'unresolved'][index] 331 choice = [b'other', b'local', b'unresolved'][index]
332 else: 332 else:
333 # IMPORTANT: keep the last line of this prompt ("What do you want to 333 # IMPORTANT: keep the last line of this prompt ("What do you want to
334 # do?") very short, see comment next to _localchangedotherdeletedmsg 334 # do?") very short, see comment next to _localchangedotherdeletedmsg
345 2, 345 2,
346 ) 346 )
347 choice = [b'local', b'other', b'unresolved'][index] 347 choice = [b'local', b'other', b'unresolved'][index]
348 348
349 if choice == b'other': 349 if choice == b'other':
350 return _iother(repo, mynode, fcd, fco, fca, toolconf, labels) 350 return _iother(repo, mynode, local, other, base, toolconf)
351 elif choice == b'local': 351 elif choice == b'local':
352 return _ilocal(repo, mynode, fcd, fco, fca, toolconf, labels) 352 return _ilocal(repo, mynode, local, other, base, toolconf)
353 elif choice == b'unresolved': 353 elif choice == b'unresolved':
354 return _ifail(repo, mynode, fcd, fco, fca, toolconf, labels) 354 return _ifail(repo, mynode, local, other, base, toolconf)
355 except error.ResponseExpected: 355 except error.ResponseExpected:
356 ui.write(b"\n") 356 ui.write(b"\n")
357 return _ifail(repo, mynode, fcd, fco, fca, toolconf, labels) 357 return _ifail(repo, mynode, local, other, base, toolconf)
358 358
359 359
360 @internaltool(b'local', nomerge) 360 @internaltool(b'local', nomerge)
361 def _ilocal(repo, mynode, fcd, fco, fca, toolconf, labels=None): 361 def _ilocal(repo, mynode, local, other, base, toolconf):
362 """Uses the local `p1()` version of files as the merged version.""" 362 """Uses the local `p1()` version of files as the merged version."""
363 return 0, fcd.isabsent() 363 return 0, local.fctx.isabsent()
364 364
365 365
366 @internaltool(b'other', nomerge) 366 @internaltool(b'other', nomerge)
367 def _iother(repo, mynode, fcd, fco, fca, toolconf, labels=None): 367 def _iother(repo, mynode, local, other, base, toolconf):
368 """Uses the other `p2()` version of files as the merged version.""" 368 """Uses the other `p2()` version of files as the merged version."""
369 if fco.isabsent(): 369 if other.fctx.isabsent():
370 # local changed, remote deleted -- 'deleted' picked 370 # local changed, remote deleted -- 'deleted' picked
371 _underlyingfctxifabsent(fcd).remove() 371 _underlyingfctxifabsent(local.fctx).remove()
372 deleted = True 372 deleted = True
373 else: 373 else:
374 _underlyingfctxifabsent(fcd).write(fco.data(), fco.flags()) 374 _underlyingfctxifabsent(local.fctx).write(
375 other.fctx.data(), other.fctx.flags()
376 )
375 deleted = False 377 deleted = False
376 return 0, deleted 378 return 0, deleted
377 379
378 380
379 @internaltool(b'fail', nomerge) 381 @internaltool(b'fail', nomerge)
380 def _ifail(repo, mynode, fcd, fco, fca, toolconf, labels=None): 382 def _ifail(repo, mynode, local, other, base, toolconf):
381 """ 383 """
382 Rather than attempting to merge files that were modified on both 384 Rather than attempting to merge files that were modified on both
383 branches, it marks them as unresolved. The resolve command must be 385 branches, it marks them as unresolved. The resolve command must be
384 used to resolve these conflicts.""" 386 used to resolve these conflicts."""
385 # for change/delete conflicts write out the changed version, then fail 387 # for change/delete conflicts write out the changed version, then fail
386 if fcd.isabsent(): 388 if local.fctx.isabsent():
387 _underlyingfctxifabsent(fcd).write(fco.data(), fco.flags()) 389 _underlyingfctxifabsent(local.fctx).write(
390 other.fctx.data(), other.fctx.flags()
391 )
388 return 1, False 392 return 1, False
389 393
390 394
391 def _underlyingfctxifabsent(filectx): 395 def _underlyingfctxifabsent(filectx):
392 """Sometimes when resolving, our fcd is actually an absentfilectx, but 396 """Sometimes when resolving, our fcd is actually an absentfilectx, but
397 return filectx.changectx()[filectx.path()] 401 return filectx.changectx()[filectx.path()]
398 else: 402 else:
399 return filectx 403 return filectx
400 404
401 405
402 def _premerge(repo, fcd, fco, fca, toolconf, backup, labels): 406 def _premerge(repo, local, other, base, toolconf, backup):
403 tool, toolpath, binary, symlink, scriptfn = toolconf 407 tool, toolpath, binary, symlink, scriptfn = toolconf
404 if symlink or fcd.isabsent() or fco.isabsent(): 408 if symlink or local.fctx.isabsent() or other.fctx.isabsent():
405 return 1 409 return 1
406 410
407 ui = repo.ui 411 ui = repo.ui
408 412
409 validkeep = [b'keep', b'keep-merge3', b'keep-mergediff'] 413 validkeep = [b'keep', b'keep-merge3', b'keep-mergediff']
424 mode = b'merge' 428 mode = b'merge'
425 if premerge == b'keep-mergediff': 429 if premerge == b'keep-mergediff':
426 mode = b'mergediff' 430 mode = b'mergediff'
427 elif premerge == b'keep-merge3': 431 elif premerge == b'keep-merge3':
428 mode = b'merge3' 432 mode = b'merge3'
429 local = simplemerge.MergeInput(fcd, labels[0])
430 other = simplemerge.MergeInput(fco, labels[1])
431 base = simplemerge.MergeInput(fca, labels[2])
432 r = simplemerge.simplemerge( 433 r = simplemerge.simplemerge(
433 ui, local, base, other, quiet=True, mode=mode 434 ui, local, base, other, quiet=True, mode=mode
434 ) 435 )
435 if not r: 436 if not r:
436 ui.debug(b" premerge successful\n") 437 ui.debug(b" premerge successful\n")
437 return 0 438 return 0
438 if premerge not in validkeep: 439 if premerge not in validkeep:
439 # restore from backup and try again 440 # restore from backup and try again
440 _restorebackup(fcd, backup) 441 _restorebackup(local.fctx, backup)
441 return 1 # continue merging 442 return 1 # continue merging
442 443
443 444
444 def _mergecheck(repo, mynode, fcd, fco, fca, toolconf): 445 def _mergecheck(repo, mynode, fcd, fco, fca, toolconf):
445 tool, toolpath, binary, symlink, scriptfn = toolconf 446 tool, toolpath, binary, symlink, scriptfn = toolconf
460 ) 461 )
461 return False 462 return False
462 return True 463 return True
463 464
464 465
465 def _merge(repo, fcd, fco, fca, labels, mode): 466 def _merge(repo, local, other, base, mode):
466 """ 467 """
467 Uses the internal non-interactive simple merge algorithm for merging 468 Uses the internal non-interactive simple merge algorithm for merging
468 files. It will fail if there are any conflicts and leave markers in 469 files. It will fail if there are any conflicts and leave markers in
469 the partially merged file. Markers will have two sections, one for each side 470 the partially merged file. Markers will have two sections, one for each side
470 of merge, unless mode equals 'union' which suppresses the markers.""" 471 of merge, unless mode equals 'union' which suppresses the markers."""
471 ui = repo.ui 472 ui = repo.ui
472 473
473 local = simplemerge.MergeInput(fcd)
474 local.label = labels[0]
475 other = simplemerge.MergeInput(fco)
476 other.label = labels[1]
477 base = simplemerge.MergeInput(fca)
478 base.label = labels[2]
479 r = simplemerge.simplemerge(ui, local, base, other, mode=mode) 474 r = simplemerge.simplemerge(ui, local, base, other, mode=mode)
480 return True, r, False 475 return True, r, False
481 476
482 477
483 @internaltool( 478 @internaltool(
487 b"warning: conflicts while merging %s! " 482 b"warning: conflicts while merging %s! "
488 b"(edit, then use 'hg resolve --mark')\n" 483 b"(edit, then use 'hg resolve --mark')\n"
489 ), 484 ),
490 precheck=_mergecheck, 485 precheck=_mergecheck,
491 ) 486 )
492 def _iunion(repo, mynode, fcd, fco, fca, toolconf, backup, labels=None): 487 def _iunion(repo, mynode, local, other, base, toolconf, backup):
493 """ 488 """
494 Uses the internal non-interactive simple merge algorithm for merging 489 Uses the internal non-interactive simple merge algorithm for merging
495 files. It will use both left and right sides for conflict regions. 490 files. It will use both left and right sides for conflict regions.
496 No markers are inserted.""" 491 No markers are inserted."""
497 return _merge(repo, fcd, fco, fca, labels, b'union') 492 return _merge(repo, local, other, base, b'union')
498 493
499 494
500 @internaltool( 495 @internaltool(
501 b'merge', 496 b'merge',
502 fullmerge, 497 fullmerge,
504 b"warning: conflicts while merging %s! " 499 b"warning: conflicts while merging %s! "
505 b"(edit, then use 'hg resolve --mark')\n" 500 b"(edit, then use 'hg resolve --mark')\n"
506 ), 501 ),
507 precheck=_mergecheck, 502 precheck=_mergecheck,
508 ) 503 )
509 def _imerge(repo, mynode, fcd, fco, fca, toolconf, backup, labels=None): 504 def _imerge(repo, mynode, local, other, base, toolconf, backup):
510 """ 505 """
511 Uses the internal non-interactive simple merge algorithm for merging 506 Uses the internal non-interactive simple merge algorithm for merging
512 files. It will fail if there are any conflicts and leave markers in 507 files. It will fail if there are any conflicts and leave markers in
513 the partially merged file. Markers will have two sections, one for each side 508 the partially merged file. Markers will have two sections, one for each side
514 of merge.""" 509 of merge."""
515 return _merge(repo, fcd, fco, fca, labels, b'merge') 510 return _merge(repo, local, other, base, b'merge')
516 511
517 512
518 @internaltool( 513 @internaltool(
519 b'merge3', 514 b'merge3',
520 fullmerge, 515 fullmerge,
522 b"warning: conflicts while merging %s! " 517 b"warning: conflicts while merging %s! "
523 b"(edit, then use 'hg resolve --mark')\n" 518 b"(edit, then use 'hg resolve --mark')\n"
524 ), 519 ),
525 precheck=_mergecheck, 520 precheck=_mergecheck,
526 ) 521 )
527 def _imerge3(repo, mynode, fcd, fco, fca, toolconf, backup, labels=None): 522 def _imerge3(repo, mynode, local, other, base, toolconf, backup):
528 """ 523 """
529 Uses the internal non-interactive simple merge algorithm for merging 524 Uses the internal non-interactive simple merge algorithm for merging
530 files. It will fail if there are any conflicts and leave markers in 525 files. It will fail if there are any conflicts and leave markers in
531 the partially merged file. Marker will have three sections, one from each 526 the partially merged file. Marker will have three sections, one from each
532 side of the merge and one for the base content.""" 527 side of the merge and one for the base content."""
533 return _merge(repo, fcd, fco, fca, labels, b'merge3') 528 return _merge(repo, local, other, base, b'merge3')
534 529
535 530
536 @internaltool( 531 @internaltool(
537 b'merge3-lie-about-conflicts', 532 b'merge3-lie-about-conflicts',
538 fullmerge, 533 fullmerge,
559 b"warning: conflicts while merging %s! " 554 b"warning: conflicts while merging %s! "
560 b"(edit, then use 'hg resolve --mark')\n" 555 b"(edit, then use 'hg resolve --mark')\n"
561 ), 556 ),
562 precheck=_mergecheck, 557 precheck=_mergecheck,
563 ) 558 )
564 def _imerge_diff(repo, mynode, fcd, fco, fca, toolconf, backup, labels=None): 559 def _imerge_diff(repo, mynode, local, other, base, toolconf, backup):
565 """ 560 """
566 Uses the internal non-interactive simple merge algorithm for merging 561 Uses the internal non-interactive simple merge algorithm for merging
567 files. It will fail if there are any conflicts and leave markers in 562 files. It will fail if there are any conflicts and leave markers in
568 the partially merged file. The marker will have two sections, one with the 563 the partially merged file. The marker will have two sections, one with the
569 content from one side of the merge, and one with a diff from the base 564 content from one side of the merge, and one with a diff from the base
570 content to the content on the other side. (experimental)""" 565 content to the content on the other side. (experimental)"""
571 return _merge(repo, fcd, fco, fca, labels, b'mergediff') 566 return _merge(repo, local, other, base, b'mergediff')
572 567
573 568
574 @internaltool(b'merge-local', mergeonly, precheck=_mergecheck) 569 @internaltool(b'merge-local', mergeonly, precheck=_mergecheck)
575 def _imergelocal(repo, mynode, fcd, fco, fca, toolconf, backup, labels=None): 570 def _imergelocal(repo, mynode, local, other, base, toolconf, backup):
576 """ 571 """
577 Like :merge, but resolve all conflicts non-interactively in favor 572 Like :merge, but resolve all conflicts non-interactively in favor
578 of the local `p1()` changes.""" 573 of the local `p1()` changes."""
579 return _merge(repo, fcd, fco, fca, labels, b'local') 574 return _merge(repo, local, other, base, b'local')
580 575
581 576
582 @internaltool(b'merge-other', mergeonly, precheck=_mergecheck) 577 @internaltool(b'merge-other', mergeonly, precheck=_mergecheck)
583 def _imergeother(repo, mynode, fcd, fco, fca, toolconf, backup, labels=None): 578 def _imergeother(repo, mynode, local, other, base, toolconf, backup):
584 """ 579 """
585 Like :merge, but resolve all conflicts non-interactively in favor 580 Like :merge, but resolve all conflicts non-interactively in favor
586 of the other `p2()` changes.""" 581 of the other `p2()` changes."""
587 return _merge(repo, fcd, fco, fca, labels, b'other') 582 return _merge(repo, local, other, base, b'other')
588 583
589 584
590 @internaltool( 585 @internaltool(
591 b'tagmerge', 586 b'tagmerge',
592 mergeonly, 587 mergeonly,
594 b"automatic tag merging of %s failed! " 589 b"automatic tag merging of %s failed! "
595 b"(use 'hg resolve --tool :merge' or another merge " 590 b"(use 'hg resolve --tool :merge' or another merge "
596 b"tool of your choice)\n" 591 b"tool of your choice)\n"
597 ), 592 ),
598 ) 593 )
599 def _itagmerge(repo, mynode, fcd, fco, fca, toolconf, backup, labels=None): 594 def _itagmerge(repo, mynode, local, other, base, toolconf, backup):
600 """ 595 """
601 Uses the internal tag merge algorithm (experimental). 596 Uses the internal tag merge algorithm (experimental).
602 """ 597 """
603 success, status = tagmerge.merge(repo, fcd, fco, fca) 598 success, status = tagmerge.merge(repo, local.fctx, other.fctx, base.fctx)
604 return success, status, False 599 return success, status, False
605 600
606 601
607 @internaltool(b'dump', fullmerge, binary=True, symlink=True) 602 @internaltool(b'dump', fullmerge, binary=True, symlink=True)
608 def _idump(repo, mynode, fcd, fco, fca, toolconf, backup, labels=None): 603 def _idump(repo, mynode, local, other, base, toolconf, backup):
609 """ 604 """
610 Creates three versions of the files to merge, containing the 605 Creates three versions of the files to merge, containing the
611 contents of local, other and base. These files can then be used to 606 contents of local, other and base. These files can then be used to
612 perform a merge manually. If the file to be merged is named 607 perform a merge manually. If the file to be merged is named
613 ``a.txt``, these files will accordingly be named ``a.txt.local``, 608 ``a.txt``, these files will accordingly be named ``a.txt.local``,
615 same directory as ``a.txt``. 610 same directory as ``a.txt``.
616 611
617 This implies premerge. Therefore, files aren't dumped, if premerge 612 This implies premerge. Therefore, files aren't dumped, if premerge
618 runs successfully. Use :forcedump to forcibly write files out. 613 runs successfully. Use :forcedump to forcibly write files out.
619 """ 614 """
620 a = _workingpath(repo, fcd) 615 a = _workingpath(repo, local.fctx)
621 fd = fcd.path() 616 fd = local.fctx.path()
622 617
623 from . import context 618 from . import context
624 619
625 if isinstance(fcd, context.overlayworkingfilectx): 620 if isinstance(local.fctx, context.overlayworkingfilectx):
626 raise error.InMemoryMergeConflictsError( 621 raise error.InMemoryMergeConflictsError(
627 b'in-memory merge does not support the :dump tool.' 622 b'in-memory merge does not support the :dump tool.'
628 ) 623 )
629 624
630 util.writefile(a + b".local", fcd.decodeddata()) 625 util.writefile(a + b".local", local.fctx.decodeddata())
631 repo.wwrite(fd + b".other", fco.data(), fco.flags()) 626 repo.wwrite(fd + b".other", other.fctx.data(), other.fctx.flags())
632 repo.wwrite(fd + b".base", fca.data(), fca.flags()) 627 repo.wwrite(fd + b".base", base.fctx.data(), base.fctx.flags())
633 return False, 1, False 628 return False, 1, False
634 629
635 630
636 @internaltool(b'forcedump', mergeonly, binary=True, symlink=True) 631 @internaltool(b'forcedump', mergeonly, binary=True, symlink=True)
637 def _forcedump(repo, mynode, fcd, fco, fca, toolconf, backup, labels=None): 632 def _forcedump(repo, mynode, local, other, base, toolconf, backup):
638 """ 633 """
639 Creates three versions of the files as same as :dump, but omits premerge. 634 Creates three versions of the files as same as :dump, but omits premerge.
640 """ 635 """
641 return _idump(repo, mynode, fcd, fco, fca, toolconf, backup, labels=labels) 636 return _idump(repo, mynode, local, other, base, toolconf, backup)
642 637
643 638
644 def _xmergeimm(repo, mynode, fcd, fco, fca, toolconf, backup, labels=None): 639 def _xmergeimm(repo, mynode, local, other, base, toolconf, backup):
645 # In-memory merge simply raises an exception on all external merge tools, 640 # In-memory merge simply raises an exception on all external merge tools,
646 # for now. 641 # for now.
647 # 642 #
648 # It would be possible to run most tools with temporary files, but this 643 # It would be possible to run most tools with temporary files, but this
649 # raises the question of what to do if the user only partially resolves the 644 # raises the question of what to do if the user only partially resolves the
707 ui, tmpl, defaults=templatekw.keywords, resources=tres 702 ui, tmpl, defaults=templatekw.keywords, resources=tres
708 ) 703 )
709 ui.status(t.renderdefault(props)) 704 ui.status(t.renderdefault(props))
710 705
711 706
712 def _xmerge(repo, mynode, fcd, fco, fca, toolconf, backup, labels): 707 def _xmerge(repo, mynode, local, other, base, toolconf, backup):
708 fcd = local.fctx
709 fco = other.fctx
710 fca = base.fctx
713 tool, toolpath, binary, symlink, scriptfn = toolconf 711 tool, toolpath, binary, symlink, scriptfn = toolconf
714 uipathfn = scmutil.getuipathfn(repo) 712 uipathfn = scmutil.getuipathfn(repo)
715 if fcd.isabsent() or fco.isabsent(): 713 if fcd.isabsent() or fco.isabsent():
716 repo.ui.warn( 714 repo.ui.warn(
717 _(b'warning: %s cannot merge change/delete conflict for %s\n') 715 _(b'warning: %s cannot merge change/delete conflict for %s\n')
724 with _maketempfiles( 722 with _maketempfiles(
725 repo, fco, fca, repo.wvfs.join(backup.path()), b"$output" in args 723 repo, fco, fca, repo.wvfs.join(backup.path()), b"$output" in args
726 ) as temppaths: 724 ) as temppaths:
727 basepath, otherpath, localoutputpath = temppaths 725 basepath, otherpath, localoutputpath = temppaths
728 outpath = b"" 726 outpath = b""
729 mylabel, otherlabel = labels[:2]
730 baselabel = labels[2]
731 env = { 727 env = {
732 b'HG_FILE': fcd.path(), 728 b'HG_FILE': fcd.path(),
733 b'HG_MY_NODE': short(mynode), 729 b'HG_MY_NODE': short(mynode),
734 b'HG_OTHER_NODE': short(fco.changectx().node()), 730 b'HG_OTHER_NODE': short(fco.changectx().node()),
735 b'HG_BASE_NODE': short(fca.changectx().node()), 731 b'HG_BASE_NODE': short(fca.changectx().node()),
736 b'HG_MY_ISLINK': b'l' in fcd.flags(), 732 b'HG_MY_ISLINK': b'l' in fcd.flags(),
737 b'HG_OTHER_ISLINK': b'l' in fco.flags(), 733 b'HG_OTHER_ISLINK': b'l' in fco.flags(),
738 b'HG_BASE_ISLINK': b'l' in fca.flags(), 734 b'HG_BASE_ISLINK': b'l' in fca.flags(),
739 b'HG_MY_LABEL': mylabel, 735 b'HG_MY_LABEL': local.label,
740 b'HG_OTHER_LABEL': otherlabel, 736 b'HG_OTHER_LABEL': other.label,
741 b'HG_BASE_LABEL': baselabel, 737 b'HG_BASE_LABEL': base.label,
742 } 738 }
743 ui = repo.ui 739 ui = repo.ui
744 740
745 if b"$output" in args: 741 if b"$output" in args:
746 # read input from backup, write to original 742 # read input from backup, write to original
749 replace = { 745 replace = {
750 b'local': localpath, 746 b'local': localpath,
751 b'base': basepath, 747 b'base': basepath,
752 b'other': otherpath, 748 b'other': otherpath,
753 b'output': outpath, 749 b'output': outpath,
754 b'labellocal': mylabel, 750 b'labellocal': local.label,
755 b'labelother': otherlabel, 751 b'labelother': other.label,
756 b'labelbase': baselabel, 752 b'labelbase': base.label,
757 } 753 }
758 args = util.interpolate( 754 args = util.interpolate(
759 br'\$', 755 br'\$',
760 replace, 756 replace,
761 args, 757 args,
803 r = 1 799 r = 1
804 repo.ui.debug(b'merge tool returned: %d\n' % r) 800 repo.ui.debug(b'merge tool returned: %d\n' % r)
805 return True, r, False 801 return True, r, False
806 802
807 803
808 def _formatlabel(input, template, pad): 804 def _populate_label_detail(input, template, pad):
809 """Applies the given template to the ctx, prefixed by the label. 805 """Applies the given template to the ctx, prefixed by the label.
810 806
811 Pad is the minimum width of the label prefix, so that multiple markers 807 Pad is the minimum width of the label prefix, so that multiple markers
812 can have aligned templated parts. 808 can have aligned templated parts.
813 """ 809 """
824 820
825 # 8 for the prefix of conflict marker lines (e.g. '<<<<<<< ') 821 # 8 for the prefix of conflict marker lines (e.g. '<<<<<<< ')
826 input.label = stringutil.ellipsis(mark, 80 - 8) 822 input.label = stringutil.ellipsis(mark, 80 - 8)
827 823
828 824
829 def _formatlabels(repo, inputs, tool=None): 825 def _populate_label_details(repo, inputs, tool=None):
830 """Formats the given labels using the conflict marker template. 826 """Formats the given labels using the conflict marker template.
831 827
832 Returns a list of formatted labels. 828 Returns a list of formatted labels.
833 """ 829 """
834 ui = repo.ui 830 ui = repo.ui
841 ui, template, defaults=templatekw.keywords, resources=tres 837 ui, template, defaults=templatekw.keywords, resources=tres
842 ) 838 )
843 839
844 pad = max(len(input.label) for input in inputs) 840 pad = max(len(input.label) for input in inputs)
845 841
846 return [_formatlabel(input, tmpl, pad) for input in inputs] 842 for input in inputs:
843 _populate_label_detail(input, tmpl, pad)
847 844
848 845
849 def partextras(labels): 846 def partextras(labels):
850 """Return a dictionary of extra labels for use in prompts to the user 847 """Return a dictionary of extra labels for use in prompts to the user
851 848
1049 base = simplemerge.MergeInput(fca, labels[2]) 1046 base = simplemerge.MergeInput(fca, labels[2])
1050 if mergetype == nomerge: 1047 if mergetype == nomerge:
1051 return func( 1048 return func(
1052 repo, 1049 repo,
1053 mynode, 1050 mynode,
1054 fcd, 1051 local,
1055 fco, 1052 other,
1056 fca, 1053 base,
1057 toolconf, 1054 toolconf,
1058 [local.label, other.label, base.label],
1059 ) 1055 )
1060 1056
1061 if orig != fco.path(): 1057 if orig != fco.path():
1062 ui.status( 1058 ui.status(
1063 _(b"merging %s and %s to %s\n") 1059 _(b"merging %s and %s to %s\n")
1096 if markerstyle != b'basic': 1092 if markerstyle != b'basic':
1097 # respect 'tool's mergemarkertemplate (which defaults to 1093 # respect 'tool's mergemarkertemplate (which defaults to
1098 # command-templates.mergemarker) 1094 # command-templates.mergemarker)
1099 labeltool = tool 1095 labeltool = tool
1100 if internalmarkerstyle != b'basic' or markerstyle != b'basic': 1096 if internalmarkerstyle != b'basic' or markerstyle != b'basic':
1101 _formatlabels(repo, [local, other, base], tool=labeltool) 1097 _populate_label_details(
1098 repo, [local, other, base], tool=labeltool
1099 )
1102 1100
1103 r = _premerge( 1101 r = _premerge(
1104 repo, 1102 repo,
1105 fcd, 1103 local,
1106 fco, 1104 other,
1107 fca, 1105 base,
1108 toolconf, 1106 toolconf,
1109 backup, 1107 backup,
1110 labels=[local.label, other.label, base.label],
1111 ) 1108 )
1112 # we're done if premerge was successful (r is 0) 1109 # we're done if premerge was successful (r is 0)
1113 if not r: 1110 if not r:
1114 return r, False 1111 return r, False
1115 1112
1117 local.label = labels[0] 1114 local.label = labels[0]
1118 other.label = labels[1] 1115 other.label = labels[1]
1119 base.label = labels[2] 1116 base.label = labels[2]
1120 1117
1121 if markerstyle != b'basic': 1118 if markerstyle != b'basic':
1122 _formatlabels(repo, [local, other, base], tool=tool) 1119 _populate_label_details(repo, [local, other, base], tool=tool)
1123 1120
1124 needcheck, r, deleted = func( 1121 needcheck, r, deleted = func(
1125 repo, 1122 repo,
1126 mynode, 1123 mynode,
1127 fcd, 1124 local,
1128 fco, 1125 other,
1129 fca, 1126 base,
1130 toolconf, 1127 toolconf,
1131 backup, 1128 backup,
1132 labels=[local.label, other.label, base.label],
1133 ) 1129 )
1134 1130
1135 if needcheck: 1131 if needcheck:
1136 r = _check(repo, r, ui, tool, fcd, backup) 1132 r = _check(repo, r, ui, tool, fcd, backup)
1137 1133