##// END OF EJS Templates
filemerge: support passing labels to external merge tools...
Kyle Lippincott -
r35981:9037c29e default
parent child Browse files
Show More
@@ -743,6 +743,16 b" coreconfigitem('merge-tools', br'.*\\.gui"
743 generic=True,
743 generic=True,
744 priority=-1,
744 priority=-1,
745 )
745 )
746 coreconfigitem('merge-tools', br'.*\.mergemarkers$',
747 default='basic',
748 generic=True,
749 priority=-1,
750 )
751 coreconfigitem('merge-tools', br'.*\.mergemarkertemplate$',
752 default=dynamicdefault, # take from ui.mergemarkertemplate
753 generic=True,
754 priority=-1,
755 )
746 coreconfigitem('merge-tools', br'.*\.priority$',
756 coreconfigitem('merge-tools', br'.*\.priority$',
747 default=0,
757 default=0,
748 generic=True,
758 generic=True,
@@ -513,6 +513,11 b' def _xmerge(repo, mynode, orig, fcd, fco'
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()),
@@ -520,6 +525,9 b' def _xmerge(repo, mynode, orig, fcd, fco'
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
@@ -528,7 +536,9 b' def _xmerge(repo, mynode, orig, fcd, fco'
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
@@ -566,7 +576,7 b' def _formatconflictmarker(ctx, template,'
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.
@@ -577,6 +587,8 b' def _formatlabels(repo, fcd, fco, fca, l'
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,
@@ -706,6 +718,7 b' def _filemerge(premerge, repo, wctx, myn'
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
@@ -714,6 +727,7 b' def _filemerge(premerge, repo, wctx, myn'
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
@@ -743,19 +757,42 b' def _filemerge(premerge, repo, wctx, myn'
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)
@@ -1363,13 +1363,18 b' Supported arguments:'
1363 ``args``
1363 ``args``
1364 The arguments to pass to the tool executable. You can refer to the
1364 The arguments to pass to the tool executable. You can refer to the
1365 files being merged as well as the output file through these
1365 files being merged as well as the output file through these
1366 variables: ``$base``, ``$local``, ``$other``, ``$output``. The meaning
1366 variables: ``$base``, ``$local``, ``$other``, ``$output``.
1367 of ``$local`` and ``$other`` can vary depending on which action is being
1367
1368 performed. During and update or merge, ``$local`` represents the original
1368 The meaning of ``$local`` and ``$other`` can vary depending on which action is
1369 state of the file, while ``$other`` represents the commit you are updating
1369 being performed. During an update or merge, ``$local`` represents the original
1370 to or the commit you are merging with. During a rebase ``$local``
1370 state of the file, while ``$other`` represents the commit you are updating to or
1371 represents the destination of the rebase, and ``$other`` represents the
1371 the commit you are merging with. During a rebase, ``$local`` represents the
1372 commit being rebased.
1372 destination of the rebase, and ``$other`` represents the commit being rebased.
1373
1374 Some operations define custom labels to assist with identifying the revisions,
1375 accessible via ``$labellocal``, ``$labelother``, and ``$labelbase``. If custom
1376 labels are not available, these will be ``local``, ``other``, and ``base``,
1377 respectively.
1373 (default: ``$local $base $other``)
1378 (default: ``$local $base $other``)
1374
1379
1375 ``premerge``
1380 ``premerge``
@@ -1405,6 +1410,21 b' Supported arguments:'
1405 ``gui``
1410 ``gui``
1406 This tool requires a graphical interface to run. (default: False)
1411 This tool requires a graphical interface to run. (default: False)
1407
1412
1413 ``mergemarkers``
1414 Controls whether the labels passed via ``$labellocal``, ``$labelother``, and
1415 ``$labelbase`` are ``detailed`` (respecting ``mergemarkertemplate``) or
1416 ``basic``. If ``premerge`` is ``keep`` or ``keep-merge3``, the conflict
1417 markers generated during premerge will be ``detailed`` if either this option or
1418 the corresponding option in the ``[ui]`` section is ``detailed``.
1419 (default: ``basic``)
1420
1421 ``mergemarkertemplate``
1422 This setting can be used to override ``mergemarkertemplate`` from the ``[ui]``
1423 section on a per-tool basis; this applies to the ``$label``-prefixed variables
1424 and to the conflict markers that are generated if ``premerge`` is ``keep` or
1425 ``keep-merge3``. See the corresponding variable in ``[ui]`` for more
1426 information.
1427
1408 .. container:: windows
1428 .. container:: windows
1409
1429
1410 ``regkey``
1430 ``regkey``
@@ -2120,6 +2140,8 b' User interface controls.'
2120 markers is different from the encoding of the merged files,
2140 markers is different from the encoding of the merged files,
2121 serious problems may occur.
2141 serious problems may occur.
2122
2142
2143 Can be overridden per-merge-tool, see the ``[merge-tools]`` section.
2144
2123 ``origbackuppath``
2145 ``origbackuppath``
2124 The path to a directory used to store generated .orig files. If the path is
2146 The path to a directory used to store generated .orig files. If the path is
2125 not a directory, one will be created. If set, files stored in this
2147 not a directory, one will be created. If set, files stored in this
@@ -1059,6 +1059,150 b' premerge=keep-merge3 keeps conflict mark'
1059 # hg resolve --list
1059 # hg resolve --list
1060 R f
1060 R f
1061
1061
1062 premerge=keep respects ui.mergemarkers=basic:
1063
1064 $ beforemerge
1065 [merge-tools]
1066 false.whatever=
1067 true.priority=1
1068 true.executable=cat
1069 # hg update -C 1
1070 $ hg merge -r 4 --config merge-tools.true.premerge=keep --config ui.mergemarkers=basic
1071 merging f
1072 <<<<<<< working copy
1073 revision 1
1074 space
1075 =======
1076 revision 4
1077 >>>>>>> merge rev
1078 revision 0
1079 space
1080 revision 4
1081 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1082 (branch merge, don't forget to commit)
1083 $ aftermerge
1084 # cat f
1085 <<<<<<< working copy
1086 revision 1
1087 space
1088 =======
1089 revision 4
1090 >>>>>>> merge rev
1091 # hg stat
1092 M f
1093 # hg resolve --list
1094 R f
1095
1096 premerge=keep ignores ui.mergemarkers=basic if true.mergemarkers=detailed:
1097
1098 $ beforemerge
1099 [merge-tools]
1100 false.whatever=
1101 true.priority=1
1102 true.executable=cat
1103 # hg update -C 1
1104 $ hg merge -r 4 --config merge-tools.true.premerge=keep \
1105 > --config ui.mergemarkers=basic \
1106 > --config merge-tools.true.mergemarkers=detailed
1107 merging f
1108 <<<<<<< working copy: ef83787e2614 - test: revision 1
1109 revision 1
1110 space
1111 =======
1112 revision 4
1113 >>>>>>> merge rev: 81448d39c9a0 - test: revision 4
1114 revision 0
1115 space
1116 revision 4
1117 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1118 (branch merge, don't forget to commit)
1119 $ aftermerge
1120 # cat f
1121 <<<<<<< working copy: ef83787e2614 - test: revision 1
1122 revision 1
1123 space
1124 =======
1125 revision 4
1126 >>>>>>> merge rev: 81448d39c9a0 - test: revision 4
1127 # hg stat
1128 M f
1129 # hg resolve --list
1130 R f
1131
1132 premerge=keep respects ui.mergemarkertemplate instead of
1133 true.mergemarkertemplate if true.mergemarkers=basic:
1134
1135 $ beforemerge
1136 [merge-tools]
1137 false.whatever=
1138 true.priority=1
1139 true.executable=cat
1140 # hg update -C 1
1141 $ hg merge -r 4 --config merge-tools.true.premerge=keep \
1142 > --config ui.mergemarkertemplate='uitmpl {rev}' \
1143 > --config merge-tools.true.mergemarkertemplate='tooltmpl {short(node)}'
1144 merging f
1145 <<<<<<< working copy: uitmpl 1
1146 revision 1
1147 space
1148 =======
1149 revision 4
1150 >>>>>>> merge rev: uitmpl 4
1151 revision 0
1152 space
1153 revision 4
1154 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1155 (branch merge, don't forget to commit)
1156 $ aftermerge
1157 # cat f
1158 <<<<<<< working copy: uitmpl 1
1159 revision 1
1160 space
1161 =======
1162 revision 4
1163 >>>>>>> merge rev: uitmpl 4
1164 # hg stat
1165 M f
1166 # hg resolve --list
1167 R f
1168
1169 premerge=keep respects true.mergemarkertemplate instead of
1170 true.mergemarkertemplate if true.mergemarkers=detailed:
1171
1172 $ beforemerge
1173 [merge-tools]
1174 false.whatever=
1175 true.priority=1
1176 true.executable=cat
1177 # hg update -C 1
1178 $ hg merge -r 4 --config merge-tools.true.premerge=keep \
1179 > --config ui.mergemarkertemplate='uitmpl {rev}' \
1180 > --config merge-tools.true.mergemarkertemplate='tooltmpl {short(node)}' \
1181 > --config merge-tools.true.mergemarkers=detailed
1182 merging f
1183 <<<<<<< working copy: tooltmpl ef83787e2614
1184 revision 1
1185 space
1186 =======
1187 revision 4
1188 >>>>>>> merge rev: tooltmpl 81448d39c9a0
1189 revision 0
1190 space
1191 revision 4
1192 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1193 (branch merge, don't forget to commit)
1194 $ aftermerge
1195 # cat f
1196 <<<<<<< working copy: tooltmpl ef83787e2614
1197 revision 1
1198 space
1199 =======
1200 revision 4
1201 >>>>>>> merge rev: tooltmpl 81448d39c9a0
1202 # hg stat
1203 M f
1204 # hg resolve --list
1205 R f
1062
1206
1063 Tool execution
1207 Tool execution
1064
1208
@@ -1190,6 +1334,142 b' Merge using tool with a path that must b'
1190 # hg resolve --list
1334 # hg resolve --list
1191 R f
1335 R f
1192
1336
1337 Merge using a tool that supports labellocal, labelother, and labelbase, checking
1338 that they're quoted properly as well. This is using the default 'basic'
1339 mergemarkers even though ui.mergemarkers is 'detailed', so it's ignoring both
1340 mergemarkertemplate settings:
1341
1342 $ beforemerge
1343 [merge-tools]
1344 false.whatever=
1345 true.priority=1
1346 true.executable=cat
1347 # hg update -C 1
1348 $ cat <<EOF > printargs_merge_tool
1349 > while test \$# -gt 0; do echo arg: \"\$1\"; shift; done
1350 > EOF
1351 $ hg --config merge-tools.true.executable='sh' \
1352 > --config merge-tools.true.args='./printargs_merge_tool ll:$labellocal lo: $labelother lb:$labelbase": "$base' \
1353 > --config merge-tools.true.mergemarkertemplate='tooltmpl {short(node)}' \
1354 > --config ui.mergemarkertemplate='uitmpl {rev}' \
1355 > --config ui.mergemarkers=detailed \
1356 > merge -r 2
1357 merging f
1358 arg: "ll:working copy"
1359 arg: "lo:"
1360 arg: "merge rev"
1361 arg: "lb:base: /tmp/f~base.*" (glob)
1362 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1363 (branch merge, don't forget to commit)
1364 $ rm -f 'printargs_merge_tool'
1365
1366 Merge using a tool that supports labellocal, labelother, and labelbase, checking
1367 that they're quoted properly as well. This is using 'detailed' mergemarkers,
1368 even though ui.mergemarkers is 'basic', and using the tool's
1369 mergemarkertemplate:
1370
1371 $ beforemerge
1372 [merge-tools]
1373 false.whatever=
1374 true.priority=1
1375 true.executable=cat
1376 # hg update -C 1
1377 $ cat <<EOF > printargs_merge_tool
1378 > while test \$# -gt 0; do echo arg: \"\$1\"; shift; done
1379 > EOF
1380 $ hg --config merge-tools.true.executable='sh' \
1381 > --config merge-tools.true.args='./printargs_merge_tool ll:$labellocal lo: $labelother lb:$labelbase": "$base' \
1382 > --config merge-tools.true.mergemarkers=detailed \
1383 > --config merge-tools.true.mergemarkertemplate='tooltmpl {short(node)}' \
1384 > --config ui.mergemarkertemplate='uitmpl {rev}' \
1385 > --config ui.mergemarkers=basic \
1386 > merge -r 2
1387 merging f
1388 arg: "ll:working copy: tooltmpl ef83787e2614"
1389 arg: "lo:"
1390 arg: "merge rev: tooltmpl 0185f4e0cf02"
1391 arg: "lb:base: /tmp/f~base.*" (glob)
1392 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1393 (branch merge, don't forget to commit)
1394 $ rm -f 'printargs_merge_tool'
1395
1396 The merge tool still gets labellocal and labelother as 'basic' even when
1397 premerge=keep is used and has 'detailed' markers:
1398
1399 $ beforemerge
1400 [merge-tools]
1401 false.whatever=
1402 true.priority=1
1403 true.executable=cat
1404 # hg update -C 1
1405 $ cat <<EOF > mytool
1406 > echo labellocal: \"\$1\"
1407 > echo labelother: \"\$2\"
1408 > echo "output (arg)": \"\$3\"
1409 > echo "output (contents)":
1410 > cat "\$3"
1411 > EOF
1412 $ hg --config merge-tools.true.executable='sh' \
1413 > --config merge-tools.true.args='mytool $labellocal $labelother $output' \
1414 > --config merge-tools.true.premerge=keep \
1415 > --config merge-tools.true.mergemarkertemplate='tooltmpl {short(node)}' \
1416 > --config ui.mergemarkertemplate='uitmpl {rev}' \
1417 > --config ui.mergemarkers=detailed \
1418 > merge -r 2
1419 merging f
1420 labellocal: "working copy"
1421 labelother: "merge rev"
1422 output (arg): "$TESTTMP/f"
1423 output (contents):
1424 <<<<<<< working copy: uitmpl 1
1425 revision 1
1426 =======
1427 revision 2
1428 >>>>>>> merge rev: uitmpl 2
1429 space
1430 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1431 (branch merge, don't forget to commit)
1432 $ rm -f 'mytool'
1433
1434 premerge=keep uses the *tool's* mergemarkertemplate if tool's
1435 mergemarkers=detailed; labellocal and labelother also use the tool's template
1436
1437 $ beforemerge
1438 [merge-tools]
1439 false.whatever=
1440 true.priority=1
1441 true.executable=cat
1442 # hg update -C 1
1443 $ cat <<EOF > mytool
1444 > echo labellocal: \"\$1\"
1445 > echo labelother: \"\$2\"
1446 > echo "output (arg)": \"\$3\"
1447 > echo "output (contents)":
1448 > cat "\$3"
1449 > EOF
1450 $ hg --config merge-tools.true.executable='sh' \
1451 > --config merge-tools.true.args='mytool $labellocal $labelother $output' \
1452 > --config merge-tools.true.premerge=keep \
1453 > --config merge-tools.true.mergemarkers=detailed \
1454 > --config merge-tools.true.mergemarkertemplate='tooltmpl {short(node)}' \
1455 > --config ui.mergemarkertemplate='uitmpl {rev}' \
1456 > --config ui.mergemarkers=detailed \
1457 > merge -r 2
1458 merging f
1459 labellocal: "working copy: tooltmpl ef83787e2614"
1460 labelother: "merge rev: tooltmpl 0185f4e0cf02"
1461 output (arg): "$TESTTMP/f"
1462 output (contents):
1463 <<<<<<< working copy: tooltmpl ef83787e2614
1464 revision 1
1465 =======
1466 revision 2
1467 >>>>>>> merge rev: tooltmpl 0185f4e0cf02
1468 space
1469 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
1470 (branch merge, don't forget to commit)
1471 $ rm -f 'mytool'
1472
1193 Issue3581: Merging a filename that needs to be quoted
1473 Issue3581: Merging a filename that needs to be quoted
1194 (This test doesn't work on Windows filesystems even on Linux, so check
1474 (This test doesn't work on Windows filesystems even on Linux, so check
1195 for Unix-like permission)
1475 for Unix-like permission)
General Comments 0
You need to be logged in to leave comments. Login now