[PATCH 1 of 2] filemerge: add support for multiple merge tool versions (RFC)

Mathias De Maré mathias.demare at gmail.com
Wed Dec 16 07:07:03 UTC 2015


# HG changeset patch
# User Mathias De Maré <mathias.demare at gmail.com>
# Date 1450249051 -3600
#      Wed Dec 16 07:57:31 2015 +0100
# Node ID 958659a81ec2cea8037e4e8ba1bf9841c0272f88
# Parent  7e8a883da1711008262150bb6f64131812de3e0b
filemerge: add support for multiple merge tool versions (RFC)

Previously, it was only possible to specify a single set of
mergetool arguments.
In case of new mergetool features, it was not possible to enable
these due to compatibility concerns.

This patch allows specifying a different 'minimum version'
for a specific set of arguments.

diff --git a/mercurial/filemerge.py b/mercurial/filemerge.py
--- a/mercurial/filemerge.py
+++ b/mercurial/filemerge.py
@@ -12,6 +12,8 @@
 import re
 import tempfile
 
+from StringIO import StringIO
+
 from .i18n import _
 from .node import nullid, short
 
@@ -452,6 +454,49 @@
     repo.wwrite(fd + ".base", fca.data(), fca.flags())
     return False, 1, False
 
+def _findversionedargs(repo, ui, tool, toolpath, env):
+    args = _toolstr(ui, tool, "args", '$local $base $other')
+
+    versionlist = _toollist(ui, tool, "versions")
+    if not versionlist:
+        return args
+
+    check = _toolstr(ui, tool, "versioncheckargs", "--version")
+
+    output = StringIO()
+    r = util.system(toolpath + ' ' + check, environ=env, out=output)
+    repo.ui.debug('merge tool version returned: %d\n' % r)
+    output.seek(0)
+    versionoutput = output.read()
+    repo.ui.debug('merge tool version: %s\n' % versionoutput)
+
+    regex = _toolstr(ui, tool, "versionregex")
+    if not regex:
+        repo.ui.debug('merge tool did not specify version regex, ' \
+                      'falling back to default args\n')
+        return args
+
+    repo.ui.debug('detecting merge tool version with regex %s\n' % regex)
+
+    versionmatch = re.search(regex, versionoutput)
+    if not versionmatch:
+        repo.ui.debug('failed to find merge tool version, ' \
+                      'falling back to default args\n')
+        return args
+
+    localversion = versionmatch.group(1)
+    selectedversion = None
+    for version in versionlist: #assume ascending
+        if util.versiontuple(localversion) < version:
+            continue
+        selectedversion = version
+
+    if selectedversion:
+        repo.ui.debug('selected merge tool base version: %s\n'
+                       % selectedversion)
+        args = _toolstr(ui, tool, "args." + selectedversion)
+    return args
+
 def _xmerge(repo, mynode, orig, fcd, fco, fca, toolconf, files, labels=None):
     tool, toolpath, binary, symlink = toolconf
     if fcd.isabsent() or fco.isabsent():
@@ -471,7 +516,8 @@
 
     ui = repo.ui
 
-    args = _toolstr(ui, tool, "args", '$local $base $other')
+    args = _findversionedargs(repo, ui, tool, toolpath, env)
+
     if "$output" in args:
         out, a = a, back # read input from backup, write to original
     replace = {'local': a, 'base': b, 'other': c, 'output': out}
diff --git a/tests/test-merge-tools.t b/tests/test-merge-tools.t
--- a/tests/test-merge-tools.t
+++ b/tests/test-merge-tools.t
@@ -1130,6 +1130,51 @@
   # hg resolve --list
   R f
 
+Handling a merge tool with different version
+
+  $ cat << EOF > versionedtool
+  > if [ "\$1" = "--version" ]; then
+  >     echo "\$MERGETOOLVERSION";
+  > else
+  >     echo "Running with args \$@";
+  > fi
+  > EOF
+  $ beforemerge
+  [merge-tools]
+  false.whatever=
+  true.priority=1
+  true.executable=cat
+  # hg update -C 1
+
+  $ export MERGETOOLVERSION=1.2
+  $ hg merge -r 2 \
+  >    --config merge-tools.true.executable='sh' \
+  >    --config merge-tools.true.args='./versionedtool older-than-1.3' \
+  >    --config merge-tools.true.versions='1.3' \
+  >    --config merge-tools.true.args.1.3='./versionedtool 1.3-or-newer' \
+  >    --config merge-tools.true.versionregex='(\d\.\d\.\d)' \
+  >    --config merge-tools.true.versioncheckargs='./versionedtool --version'
+  merging f
+  Running with args older-than-1.3
+  0 files updated, 1 files merged, 0 files removed, 0 files unresolved
+  (branch merge, don't forget to commit)
+  $ hg up -C 1
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+
+  $ export MERGETOOLVERSION=1.3.1
+  $ hg merge -r 2 \
+  >    --config merge-tools.true.executable='sh' \
+  >    --config merge-tools.true.args='./versionedtool older-than-1.3' \
+  >    --config merge-tools.true.versions='1.3' \
+  >    --config merge-tools.true.args.1.3='./versionedtool 1.3-or-newer' \
+  >    --config merge-tools.true.versionregex='(\d\.\d\.\d)' \
+  >    --config merge-tools.true.versioncheckargs='./versionedtool --version'
+  merging f
+  Running with args 1.3-or-newer
+  0 files updated, 1 files merged, 0 files removed, 0 files unresolved
+  (branch merge, don't forget to commit)
+  $ rm versionedtool
+
 Issue3581: Merging a filename that needs to be quoted
 (This test doesn't work on Windows filesystems even on Linux, so check
 for Unix-like permission)


More information about the Mercurial-devel mailing list