Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/filemerge.py @ 35947:9037c29e9f53
filemerge: support passing labels to external merge tools
This adds $labellocal, $labelother, and $labelbase to the replacement set for
merge-tools.<tool>.args config variables, and to the environment as HG_MY_LABEL,
HG_OTHER_LABEL, and HG_BASE_LABEL, respectively.
We also add merge-tools.<tool>.mergemarkers and
merge-tools.<tool>.mergemarkertemplate config variables as counterparts of
the variables available in [ui]. We are intentionally *not* respecting
ui.mergemarkers when calling out to external merge programs; too often the
default template will be too wide to display comfortably in most GUIs.
Differential Revision: https://phab.mercurial-scm.org/D2011
author | Kyle Lippincott <spectral@google.com> |
---|---|
date | Wed, 17 Jan 2018 17:35:05 -0800 |
parents | c87926ebe096 |
children | 3ab9d74dd1c5 |
comparison
equal
deleted
inserted
replaced
35946:cd2342302928 | 35947:9037c29e9f53 |
---|---|
511 unused, unused, unused, back = files | 511 unused, unused, unused, back = files |
512 a = _workingpath(repo, fcd) | 512 a = _workingpath(repo, fcd) |
513 b, c = _maketempfiles(repo, fco, fca) | 513 b, c = _maketempfiles(repo, fco, fca) |
514 try: | 514 try: |
515 out = "" | 515 out = "" |
516 mylabel, otherlabel = labels[:2] | |
517 if len(labels) >= 3: | |
518 baselabel = labels[2] | |
519 else: | |
520 baselabel = 'base' | |
516 env = {'HG_FILE': fcd.path(), | 521 env = {'HG_FILE': fcd.path(), |
517 'HG_MY_NODE': short(mynode), | 522 'HG_MY_NODE': short(mynode), |
518 'HG_OTHER_NODE': str(fco.changectx()), | 523 'HG_OTHER_NODE': str(fco.changectx()), |
519 'HG_BASE_NODE': str(fca.changectx()), | 524 'HG_BASE_NODE': str(fca.changectx()), |
520 'HG_MY_ISLINK': 'l' in fcd.flags(), | 525 'HG_MY_ISLINK': 'l' in fcd.flags(), |
521 'HG_OTHER_ISLINK': 'l' in fco.flags(), | 526 'HG_OTHER_ISLINK': 'l' in fco.flags(), |
522 'HG_BASE_ISLINK': 'l' in fca.flags(), | 527 'HG_BASE_ISLINK': 'l' in fca.flags(), |
528 'HG_MY_LABEL': mylabel, | |
529 'HG_OTHER_LABEL': otherlabel, | |
530 'HG_BASE_LABEL': baselabel, | |
523 } | 531 } |
524 ui = repo.ui | 532 ui = repo.ui |
525 | 533 |
526 args = _toolstr(ui, tool, "args") | 534 args = _toolstr(ui, tool, "args") |
527 if "$output" in args: | 535 if "$output" in args: |
528 # read input from backup, write to original | 536 # read input from backup, write to original |
529 out = a | 537 out = a |
530 a = repo.wvfs.join(back.path()) | 538 a = repo.wvfs.join(back.path()) |
531 replace = {'local': a, 'base': b, 'other': c, 'output': out} | 539 replace = {'local': a, 'base': b, 'other': c, 'output': out, |
540 'labellocal': mylabel, 'labelother': otherlabel, | |
541 'labelbase': baselabel} | |
532 args = util.interpolate(br'\$', replace, args, | 542 args = util.interpolate(br'\$', replace, args, |
533 lambda s: util.shellquote(util.localpath(s))) | 543 lambda s: util.shellquote(util.localpath(s))) |
534 cmd = toolpath + ' ' + args | 544 cmd = toolpath + ' ' + args |
535 if _toolbool(ui, tool, "gui"): | 545 if _toolbool(ui, tool, "gui"): |
536 repo.ui.status(_('running merge tool %s for file %s\n') % | 546 repo.ui.status(_('running merge tool %s for file %s\n') % |
564 # 8 for the prefix of conflict marker lines (e.g. '<<<<<<< ') | 574 # 8 for the prefix of conflict marker lines (e.g. '<<<<<<< ') |
565 return util.ellipsis(mark, 80 - 8) | 575 return util.ellipsis(mark, 80 - 8) |
566 | 576 |
567 _defaultconflictlabels = ['local', 'other'] | 577 _defaultconflictlabels = ['local', 'other'] |
568 | 578 |
569 def _formatlabels(repo, fcd, fco, fca, labels): | 579 def _formatlabels(repo, fcd, fco, fca, labels, tool=None): |
570 """Formats the given labels using the conflict marker template. | 580 """Formats the given labels using the conflict marker template. |
571 | 581 |
572 Returns a list of formatted labels. | 582 Returns a list of formatted labels. |
573 """ | 583 """ |
574 cd = fcd.changectx() | 584 cd = fcd.changectx() |
575 co = fco.changectx() | 585 co = fco.changectx() |
576 ca = fca.changectx() | 586 ca = fca.changectx() |
577 | 587 |
578 ui = repo.ui | 588 ui = repo.ui |
579 template = ui.config('ui', 'mergemarkertemplate') | 589 template = ui.config('ui', 'mergemarkertemplate') |
590 if tool is not None: | |
591 template = _toolstr(ui, tool, 'mergemarkertemplate', template) | |
580 template = templater.unquotestring(template) | 592 template = templater.unquotestring(template) |
581 tres = formatter.templateresources(ui, repo) | 593 tres = formatter.templateresources(ui, repo) |
582 tmpl = formatter.maketemplater(ui, template, defaults=templatekw.keywords, | 594 tmpl = formatter.maketemplater(ui, template, defaults=templatekw.keywords, |
583 resources=tres) | 595 resources=tres) |
584 | 596 |
704 if tool in internals: | 716 if tool in internals: |
705 func = internals[tool] | 717 func = internals[tool] |
706 mergetype = func.mergetype | 718 mergetype = func.mergetype |
707 onfailure = func.onfailure | 719 onfailure = func.onfailure |
708 precheck = func.precheck | 720 precheck = func.precheck |
721 isexternal = False | |
709 else: | 722 else: |
710 if wctx.isinmemory(): | 723 if wctx.isinmemory(): |
711 func = _xmergeimm | 724 func = _xmergeimm |
712 else: | 725 else: |
713 func = _xmerge | 726 func = _xmerge |
714 mergetype = fullmerge | 727 mergetype = fullmerge |
715 onfailure = _("merging %s failed!\n") | 728 onfailure = _("merging %s failed!\n") |
716 precheck = None | 729 precheck = None |
730 isexternal = True | |
717 | 731 |
718 toolconf = tool, toolpath, binary, symlink | 732 toolconf = tool, toolpath, binary, symlink |
719 | 733 |
720 if mergetype == nomerge: | 734 if mergetype == nomerge: |
721 r, deleted = func(repo, mynode, orig, fcd, fco, fca, toolconf, labels) | 735 r, deleted = func(repo, mynode, orig, fcd, fco, fca, toolconf, labels) |
741 | 755 |
742 back = _makebackup(repo, ui, wctx, fcd, premerge) | 756 back = _makebackup(repo, ui, wctx, fcd, premerge) |
743 files = (None, None, None, back) | 757 files = (None, None, None, back) |
744 r = 1 | 758 r = 1 |
745 try: | 759 try: |
746 markerstyle = ui.config('ui', 'mergemarkers') | 760 internalmarkerstyle = ui.config('ui', 'mergemarkers') |
761 if isexternal: | |
762 markerstyle = _toolstr(ui, tool, 'mergemarkers') | |
763 else: | |
764 markerstyle = internalmarkerstyle | |
765 | |
747 if not labels: | 766 if not labels: |
748 labels = _defaultconflictlabels | 767 labels = _defaultconflictlabels |
768 formattedlabels = labels | |
749 if markerstyle != 'basic': | 769 if markerstyle != 'basic': |
750 labels = _formatlabels(repo, fcd, fco, fca, labels) | 770 formattedlabels = _formatlabels(repo, fcd, fco, fca, labels, |
771 tool=tool) | |
751 | 772 |
752 if premerge and mergetype == fullmerge: | 773 if premerge and mergetype == fullmerge: |
753 r = _premerge(repo, fcd, fco, fca, toolconf, files, labels=labels) | 774 # conflict markers generated by premerge will use 'detailed' |
775 # settings if either ui.mergemarkers or the tool's mergemarkers | |
776 # setting is 'detailed'. This way tools can have basic labels in | |
777 # space-constrained areas of the UI, but still get full information | |
778 # in conflict markers if premerge is 'keep' or 'keep-merge3'. | |
779 premergelabels = labels | |
780 labeltool = None | |
781 if markerstyle != 'basic': | |
782 # respect 'tool's mergemarkertemplate (which defaults to | |
783 # ui.mergemarkertemplate) | |
784 labeltool = tool | |
785 if internalmarkerstyle != 'basic' or markerstyle != 'basic': | |
786 premergelabels = _formatlabels(repo, fcd, fco, fca, | |
787 premergelabels, tool=labeltool) | |
788 | |
789 r = _premerge(repo, fcd, fco, fca, toolconf, files, | |
790 labels=premergelabels) | |
754 # complete if premerge successful (r is 0) | 791 # complete if premerge successful (r is 0) |
755 return not r, r, False | 792 return not r, r, False |
756 | 793 |
757 needcheck, r, deleted = func(repo, mynode, orig, fcd, fco, fca, | 794 needcheck, r, deleted = func(repo, mynode, orig, fcd, fco, fca, |
758 toolconf, files, labels=labels) | 795 toolconf, files, labels=formattedlabels) |
759 | 796 |
760 if needcheck: | 797 if needcheck: |
761 r = _check(repo, r, ui, tool, fcd, files) | 798 r = _check(repo, r, ui, tool, fcd, files) |
762 | 799 |
763 if r: | 800 if r: |