dispatch: only check compatibility against major and minor versions (BC)
authorGregory Szorc <gregory.szorc@gmail.com>
Thu, 15 Jan 2015 20:36:03 -0800
changeset 23871 b2d8f3685b06
parent 23870 9070e20057ae
child 23872 9f48242929a9
dispatch: only check compatibility against major and minor versions (BC) Extensions can declare compatibility with Mercurial versions. If an error occurs, Mercurial will attempt to pin blame on an extension that isn't marked as compatible. While all bets are off when it comes to the internal API, my experience has shown that a monthly/patch release of Mercurial has never broken any of the extensions I've written. I think that expecting extensions to declare compatibility with every patch release of Mercurial is asking a bit much and adds little to no value. This patch changes the blame logic from exact version matching to only match on the major and minor Mercurial versions. This means that extensions only need to mark themselves as compatible with the major, quarterly releases and not the monthly ones in order to stay current and avoid what is almost certainly unfair blame. This will mean less work for extension authors and almost certainly fewer false positives in the blame attribution.
mercurial/dispatch.py
tests/test-extension.t
--- a/mercurial/dispatch.py	Thu Jan 15 20:03:48 2015 -0800
+++ b/mercurial/dispatch.py	Thu Jan 15 20:36:03 2015 -0800
@@ -283,12 +283,19 @@
                 # We found an untested extension. It's likely the culprit.
                 worst = name, 'unknown', report
                 break
-            if compare not in testedwith.split() and testedwith != 'internal':
-                tested = [tuplever(v) for v in testedwith.split()]
-                lower = [t for t in tested if t < ct]
-                nearest = max(lower or tested)
-                if worst[0] is None or nearest < worst[1]:
-                    worst = name, nearest, report
+
+            # Never blame on extensions bundled with Mercurial.
+            if testedwith == 'internal':
+                continue
+
+            tested = [tuplever(t) for t in testedwith.split()]
+            if ct in tested:
+                continue
+
+            lower = [t for t in tested if t < ct]
+            nearest = max(lower or tested)
+            if worst[0] is None or nearest < worst[1]:
+                worst = name, nearest, report
         if worst[0] is not None:
             name, testedwith, report = worst
             if not isinstance(testedwith, str):
@@ -315,7 +322,10 @@
 
 def tuplever(v):
     try:
-        return tuple([int(i) for i in v.split('.')])
+        # Assertion: tuplever is only used for extension compatibility
+        # checking. Otherwise, the discarding of extra version fields is
+        # incorrect.
+        return tuple([int(i) for i in v.split('.')[0:2]])
     except ValueError:
         return tuple()
 
--- a/tests/test-extension.t	Thu Jan 15 20:03:48 2015 -0800
+++ b/tests/test-extension.t	Thu Jan 15 20:36:03 2015 -0800
@@ -858,7 +858,7 @@
   [255]
 
   $ cat > throw.py <<EOF
-  > from mercurial import cmdutil, commands
+  > from mercurial import cmdutil, commands, util
   > cmdtable = {}
   > command = cmdutil.command(cmdtable)
   > class Bogon(Exception): pass
@@ -910,7 +910,7 @@
   $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
   >   throw 2>&1 | egrep '^\*\*'
   ** Unknown exception encountered with possibly-broken third-party extension older
-  ** which supports versions 1.9.3 of Mercurial.
+  ** which supports versions 1.9 of Mercurial.
   ** Please disable older and try your action again.
   ** If that fixes the bug please report it to the extension author.
   ** Python * (glob)
@@ -923,7 +923,7 @@
   $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
   >   throw 2>&1 | egrep '^\*\*'
   ** Unknown exception encountered with possibly-broken third-party extension older
-  ** which supports versions 1.9.3 of Mercurial.
+  ** which supports versions 1.9 of Mercurial.
   ** Please disable older and try your action again.
   ** If that fixes the bug please report it to the extension author.
   ** Python * (glob)
@@ -936,7 +936,7 @@
   $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
   >   throw 2>&1 | egrep '^\*\*'
   ** Unknown exception encountered with possibly-broken third-party extension throw
-  ** which supports versions 2.1.1 of Mercurial.
+  ** which supports versions 2.1 of Mercurial.
   ** Please disable throw and try your action again.
   ** If that fixes the bug please report it to http://example.com/bts
   ** Python * (glob)
@@ -954,6 +954,17 @@
   ** Mercurial Distributed SCM (*) (glob)
   ** Extensions loaded: throw
 
+Patch version is ignored during compatibility check
+  $ echo "testedwith = '3.2'" >> throw.py
+  $ echo "util.version = lambda:'3.2.2'" >> throw.py
+  $ rm -f throw.pyc throw.pyo
+  $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
+  ** unknown exception encountered, please report by visiting
+  ** http://mercurial.selenic.com/wiki/BugTracker
+  ** Python * (glob)
+  ** Mercurial Distributed SCM (*) (glob)
+  ** Extensions loaded: throw
+
 Test version number support in 'hg version':
   $ echo '__version__ = (1, 2, 3)' >> throw.py
   $ rm -f throw.pyc throw.pyo