test-compat: merge with mercurial-3.9 mercurial-3.8
authorPierre-Yves David <pierre-yves.david@octobus.net>
Mon, 22 May 2017 15:45:42 +0200
branchmercurial-3.8
changeset 2469 bc109ed44045
parent 2468 8fadd87da07e (diff)
parent 2434 37deace44b36 (current diff)
child 2534 b3dac812fb2a
test-compat: merge with mercurial-3.9
tests/test-prune.t
--- a/.hgtags	Thu May 18 23:55:02 2017 +0200
+++ b/.hgtags	Mon May 22 15:45:42 2017 +0200
@@ -49,3 +49,4 @@
 165ad227993de4e7d819cc6c820d5b9f7b38b80d 6.0.0
 5ef112a6eb875633a7925cde61b7d2d9e65b3a56 6.0.1
 8510d3fd7c3b312dc731f4c29badc415d504558a 6.1.0
+d4ee0274a8efbaf3d73a659998248c379c61c2bf 6.2.0
--- a/README	Thu May 18 23:55:02 2017 +0200
+++ b/README	Mon May 22 15:45:42 2017 +0200
@@ -112,6 +112,16 @@
 Changelog
 =========
 
+6.2.1 - in progress
+-------------------
+
+ - prune: fix a crash related to color handling,
+ - next: fix a crash related to color handling,
+ - discovery: document the 'obshashrange' experiment,
+ - cache: reduce the warming load in case of reset,
+ - cache: add a 'experimental.obshashcache.warm-cache' option to allow
+   disabling post transaction cache warming.
+
 6.2.0 -- 2017-05-18
 -------------------
 
--- a/hgext3rd/evolve/__init__.py	Thu May 18 23:55:02 2017 +0200
+++ b/hgext3rd/evolve/__init__.py	Mon May 22 15:45:42 2017 +0200
@@ -44,9 +44,34 @@
     # * abort: abort the push
     auto-publish = ignore
 
+Obsolescence Markers Discovery Experiment
+=========================================
+
+We are experimenting with a new protocol to discover common markers during the
+local and remote repository. This experiment is still at an early stage but is
+already raising better result than the previous version when usable.
+
+Large" repositories (hundreds of thousand) are currently unsupported. Some key
+algorithm has a naive implementation with too agressive caching, creating
+memory consumption issue (this will get fixed).
+
+Medium sized repositories works fine, but be prepared for a noticable initial
+cache filling. for the Mercurial repository, this is around 20 seconds
+
+The following config control the experiment::
+
+  [experimental]
+
+  # enable new discovery protocol
+  # (needed on both client and server)
+  obshashrange = yes
+
+  # avoid cache warming after transaction
+  # (recommended 'off' for developer repositories)
+  # (recommended 'yes' for server (default))
+  obshashrange.warm-cache = no
 """
 
-
 evolutionhelptext = """
 Obsolescence markers make it possible to mark changesets that have been
 deleted or superset in a new version of the changeset.
@@ -120,6 +145,7 @@
     commands,
     context,
     copies,
+    dirstate,
     error,
     extensions,
     help,
@@ -196,6 +222,29 @@
 reposetup = eh.final_reposetup
 cmdtable = eh.cmdtable
 
+# pre hg 4.0 compat
+
+if not util.safehasattr(dirstate.dirstate, 'parentchange'):
+    import contextlib
+
+    @contextlib.contextmanager
+    def parentchange(self):
+        '''Context manager for handling dirstate parents.
+
+        If an exception occurs in the scope of the context manager,
+        the incoherent dirstate won't be written when wlock is
+        released.
+        '''
+        self._parentwriters += 1
+        yield
+        # Typically we want the "undo" step of a context manager in a
+        # finally block so it happens even when an exception
+        # occurs. In this case, however, we only want to decrement
+        # parentwriters if the code in the with statement exits
+        # normally, so we don't have a try/finally here on purpose.
+        self._parentwriters -= 1
+    dirstate.dirstate.parentchange = parentchange
+
 #####################################################################
 ### Option configuration                                          ###
 #####################################################################
@@ -841,12 +890,11 @@
                                 '(see hg help resolve)'))
         nodenew = _relocatecommit(repo, orig, commitmsg)
     except error.Abort as exc:
-        repo.dirstate.beginparentchange()
-        repo.setparents(repo['.'].node(), nullid)
-        repo.dirstate.write(tr)
-        # fix up dirstate for copies and renames
-        copies.duplicatecopies(repo, dest.rev(), orig.p1().rev())
-        repo.dirstate.endparentchange()
+        with repo.dirstate.parentchange():
+            repo.setparents(repo['.'].node(), nullid)
+            repo.dirstate.write(tr)
+            # fix up dirstate for copies and renames
+            copies.duplicatecopies(repo, dest.rev(), orig.p1().rev())
 
         class LocalMergeFailure(MergeFailure, exc.__class__):
             pass
@@ -1755,9 +1803,8 @@
     bmupdate(newid)
     repo.ui.status(_('committed as %s\n') % node.short(newid))
     # reroute the working copy parent to the new changeset
-    repo.dirstate.beginparentchange()
-    repo.dirstate.setparents(newid, node.nullid)
-    repo.dirstate.endparentchange()
+    with repo.dirstate.parentchange():
+        repo.dirstate.setparents(newid, node.nullid)
 
 def _solvedivergent(ui, repo, divergent, dryrun=False, confirm=False,
                     progresscb=None):
@@ -1857,9 +1904,8 @@
     assert tr is not None
     try:
         repo.ui.setconfig('ui', 'allowemptycommit', True, 'evolve')
-        repo.dirstate.beginparentchange()
-        repo.dirstate.setparents(divergent.node(), node.nullid)
-        repo.dirstate.endparentchange()
+        with repo.dirstate.parentchange():
+            repo.dirstate.setparents(divergent.node(), node.nullid)
         oldlen = len(repo)
         amend(ui, repo, message='', logfile='')
         if oldlen == len(repo):
@@ -2064,7 +2110,7 @@
                                    False, lambda: None, category='unstable')
                 if not result:
                     ui.status(_('working directory now at %s\n')
-                              % ui.label(repo['.'], 'evolve.node'))
+                              % ui.label(str(repo['.']), 'evolve.node'))
                 return result
             return 1
         return result
@@ -2271,7 +2317,7 @@
                     repo._bookmarks.recordchange(tr)
                 commands.update(ui, repo, newnode.rev())
                 ui.status(_('working directory now at %s\n')
-                          % ui.label(newnode, 'evolve.node'))
+                          % ui.label(str(newnode), 'evolve.node'))
                 if movebookmark:
                     bookmarksmod.activate(repo, bookactive)
 
@@ -2512,10 +2558,9 @@
         # Move local changes on filtered changeset
         obsolete.createmarkers(repo, [(old, (repo[newid],))])
         phases.retractboundary(repo, tr, oldphase, [newid])
-        repo.dirstate.beginparentchange()
-        repo.dirstate.setparents(newid, node.nullid)
-        _uncommitdirstate(repo, old, match)
-        repo.dirstate.endparentchange()
+        with repo.dirstate.parentchange():
+            repo.dirstate.setparents(newid, node.nullid)
+            _uncommitdirstate(repo, old, match)
         updatebookmarks(newid)
         if not repo[newid].files():
             ui.warn(_("new changeset is empty\n"))
@@ -2748,9 +2793,8 @@
                 obsolete.createmarkers(repo, [(ctx, (repo[new],))])
             phases.retractboundary(repo, tr, ctx.phase(), [new])
             if ctx in repo[None].parents():
-                repo.dirstate.beginparentchange()
-                repo.dirstate.setparents(new, node.nullid)
-                repo.dirstate.endparentchange()
+                with repo.dirstate.parentchange():
+                    repo.dirstate.setparents(new, node.nullid)
         tr.close()
     finally:
         lockmod.release(tr, lock, wlock)
--- a/hgext3rd/evolve/exthelper.py	Thu May 18 23:55:02 2017 +0200
+++ b/hgext3rd/evolve/exthelper.py	Mon May 22 15:45:42 2017 +0200
@@ -3,13 +3,20 @@
 #####################################################################
 
 from mercurial import (
-    cmdutil,
     commands,
     extensions,
+    registrar,
     revset,
     templatekw,
+    util,
 )
 
+if util.safehasattr(registrar, 'command'):
+    command = registrar.command
+else: # compat with hg < 4.3
+    from mercurial import cmdutil
+    command = cmdutil.command
+
 class exthelper(object):
     """Helper for modular extension setup
 
@@ -30,7 +37,7 @@
         self._functionwrappers = []
         self._duckpunchers = []
         self.cmdtable = {}
-        self.command = cmdutil.command(self.cmdtable)
+        self.command = command(self.cmdtable)
 
     def merge(self, other):
         self._uicallables.extend(other._uicallables)
--- a/hgext3rd/evolve/hack/directaccess.py	Thu May 18 23:55:02 2017 +0200
+++ b/hgext3rd/evolve/hack/directaccess.py	Mon May 22 15:45:42 2017 +0200
@@ -6,9 +6,9 @@
 to xxx.
 """
 from mercurial import extensions
-from mercurial import cmdutil
 from mercurial import repoview
 from mercurial import branchmap
+from mercurial import registrar
 from mercurial import revset
 from mercurial import error
 from mercurial import commands
@@ -17,7 +17,12 @@
 from mercurial.i18n import _
 
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+
+if util.safehasattr(registrar, 'command'):
+    command = registrar.command(cmdtable)
+else: # compat with hg < 4.3
+    from mercurial import cmdutil
+    command = cmdutil.command(cmdtable)
 
 # By default, all the commands have directaccess with warnings
 # List of commands that have no directaccess and directaccess with no warning
--- a/hgext3rd/evolve/hack/drophack.py	Thu May 18 23:55:02 2017 +0200
+++ b/hgext3rd/evolve/hack/drophack.py	Mon May 22 15:45:42 2017 +0200
@@ -12,7 +12,7 @@
 import contextlib
 
 from mercurial.i18n import _
-from mercurial import cmdutil
+from mercurial import registrar
 from mercurial import repair
 from mercurial import scmutil
 from mercurial import lock as lockmod
@@ -20,7 +20,12 @@
 from mercurial import commands
 
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+
+if util.safehasattr(registrar, 'command'):
+    command = registrar.command(cmdtable)
+else: # compat with hg < 4.3
+    from mercurial import cmdutil
+    command = cmdutil.command(cmdtable)
 
 
 @contextlib.contextmanager
--- a/hgext3rd/evolve/hack/inhibit.py	Thu May 18 23:55:02 2017 +0200
+++ b/hgext3rd/evolve/hack/inhibit.py	Mon May 22 15:45:42 2017 +0200
@@ -14,20 +14,25 @@
 However as the inhibitor are not fitting in an append only model, this is
 incompatible with sharing mutable history.
 """
-from mercurial import localrepo
-from mercurial import obsolete
-from mercurial import extensions
-from mercurial import cmdutil
+from mercurial import bookmarks
+from mercurial import commands
 from mercurial import error
+from mercurial import extensions
+from mercurial import localrepo
+from mercurial import lock as lockmod
+from mercurial import obsolete
+from mercurial import registrar
 from mercurial import scmutil
-from mercurial import commands
-from mercurial import lock as lockmod
-from mercurial import bookmarks
 from mercurial import util
 from mercurial.i18n import _
 
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+
+if util.safehasattr(registrar, 'command'):
+    command = registrar.command(cmdtable)
+else: # compat with hg < 4.3
+    from mercurial import cmdutil
+    command = cmdutil.command(cmdtable)
 
 def _inhibitenabled(repo):
     return util.safehasattr(repo, '_obsinhibit')
@@ -176,14 +181,14 @@
         finally:
             tr.release()
 
-def _createmarkers(orig, repo, relations, flag=0, date=None, metadata=None):
+def _createmarkers(orig, repo, relations, *args, **kwargs):
     """wrap markers create to make sure we de-inhibit target nodes"""
     # wrapping transactio to unify the one in each function
     lock = tr = None
     try:
         lock = repo.lock()
         tr = repo.transaction('add-obsolescence-marker')
-        orig(repo, relations, flag, date, metadata)
+        orig(repo, relations, *args, **kwargs)
         precs = (r[0].node() for r in relations)
         _deinhibitmarkers(repo, precs)
         tr.close()
--- a/hgext3rd/evolve/legacy.py	Thu May 18 23:55:02 2017 +0200
+++ b/hgext3rd/evolve/legacy.py	Mon May 22 15:45:42 2017 +0200
@@ -24,12 +24,17 @@
 import sys
 import json
 
-from mercurial import cmdutil
 from mercurial.i18n import _
 from mercurial import lock as lockmod
 from mercurial.node import bin, nullid
+from mercurial import registrar
 from mercurial import util
 
+if util.safehasattr(registrar, 'command'):
+    commandfunc = registrar.command
+else: # compat with hg < 4.3
+    from mercurial import cmdutil
+    commandfunc = cmdutil.command
 
 #####################################################################
 ### Older format management                                       ###
@@ -75,7 +80,7 @@
     return rels
 
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+command = commandfunc(cmdtable)
 @command('debugconvertobsolete', [], '')
 def cmddebugconvertobsolete(ui, repo):
     """import markers from an .hg/obsolete-relations file"""
--- a/hgext3rd/evolve/metadata.py	Thu May 18 23:55:02 2017 +0200
+++ b/hgext3rd/evolve/metadata.py	Mon May 22 15:45:42 2017 +0200
@@ -5,7 +5,7 @@
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2 or any later version.
 
-__version__ = '6.2.0'
+__version__ = '6.2.1.dev'
 testedwith = '3.8.4 3.9.2 4.0.2 4.1.2 4.2'
 minimumhgversion = '3.8'
 buglink = 'https://bz.mercurial-scm.org/'
--- a/hgext3rd/evolve/obsdiscovery.py	Thu May 18 23:55:02 2017 +0200
+++ b/hgext3rd/evolve/obsdiscovery.py	Mon May 22 15:45:42 2017 +0200
@@ -523,12 +523,17 @@
             con = self._con
             if con is not None:
                 con.execute(_reset)
-            # rewarm the whole cache
+            # rewarm key revisions
+            #
+            # (The current invalidation is too wide, but rewarming every single
+            # revision is quite costly)
+            newrevs = []
             stop = self._cachekey[0] # tiprev
-            if revs:
-                stop = max(revs)
-            if 0 <= stop:
-                revs = repo.changelog.revs(stop=stop)
+            for h in repo.filtered('immutable').changelog.headrevs():
+                if h <= stop:
+                    newrevs.append(h)
+            newrevs.extend(revs)
+            revs = newrevs
 
         # warm the cache for the new revs
         for r in revs:
@@ -672,7 +677,12 @@
                 repo = reporef()
                 if repo is None:
                     return
-                if not repo.ui.configbool('experimental', 'obshashrange', False):
+                hasobshashrange = repo.ui.configbool('experimental',
+                                                     'obshashrange', False)
+                hascachewarm = repo.ui.configbool('experimental',
+                                                  'obshashrange.warm-cache',
+                                                  True)
+                if not (hasobshashrange and hascachewarm):
                     return
                 repo = repo.unfiltered()
                 # As pointed in 'obscache.update', we could have the changelog
--- a/hgext3rd/topic/__init__.py	Thu May 18 23:55:02 2017 +0200
+++ b/hgext3rd/topic/__init__.py	Mon May 22 15:45:42 2017 +0200
@@ -69,6 +69,7 @@
     obsolete,
     patch,
     phases,
+    registrar,
     util,
 )
 
@@ -81,8 +82,13 @@
     discovery,
 )
 
+if util.safehasattr(registrar, 'command'):
+    commandfunc = registrar.command
+else: # compat with hg < 4.3
+    commandfunc = cmdutil.command
+
 cmdtable = {}
-command = cmdutil.command(cmdtable)
+command = commandfunc(cmdtable)
 colortable = {'topic.active': 'green',
               'topic.list.troubledcount': 'red',
               'topic.list.headcount.multiple': 'yellow',
--- a/tests/test-discovery-obshashrange.t	Thu May 18 23:55:02 2017 +0200
+++ b/tests/test-discovery-obshashrange.t	Mon May 22 15:45:42 2017 +0200
@@ -76,7 +76,7 @@
   $ hg debugobsolete aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa `getid 'desc(r1)'`
   $ hg debugobsolete bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb `getid 'desc(r2)'`
   $ hg debugobsolete cccccccccccccccccccccccccccccccccccccccc `getid 'desc(r4)'`
-  $ hg debugobsolete dddddddddddddddddddddddddddddddddddddddd `getid 'desc(r5)'`
+  $ hg debugobsolete dddddddddddddddddddddddddddddddddddddddd `getid 'desc(r5)'` --config experimental.obshashrange.warm-cache=0
   $ hg debugobsolete eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee `getid 'desc(r7)'`
   $ hg debugobsolete
   aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 66f7d451a68b85ed82ff5fcc254daf50c74144bd 0 (Thu Jan 01 00:00:00 1970 +0000) {'user': 'test'}
@@ -105,13 +105,11 @@
   * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obscache in *.???? seconds (0r, 1o) (glob)
   * @0000000000000000000000000000000000000000 (*)> debugobsolete cccccccccccccccccccccccccccccccccccccccc bebd167eb94d257ace0e814aeb98e6972ed2970d exited 0 after *.?? seconds (glob)
   * @0000000000000000000000000000000000000000 (*)> debugobsolete dddddddddddddddddddddddddddddddddddddddd c8d03c1b5e94af74b772900c58259d2e08917735 (glob)
-  * @0000000000000000000000000000000000000000 (*)> obshashcache reset - new markers affect cached ranges (glob)
-  * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obshashrange in *.???? seconds (0r, 1o) (glob)
   * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obscache in *.???? seconds (0r, 1o) (glob)
-  * @0000000000000000000000000000000000000000 (*)> debugobsolete dddddddddddddddddddddddddddddddddddddddd c8d03c1b5e94af74b772900c58259d2e08917735 exited 0 after *.?? seconds (glob)
+  * @0000000000000000000000000000000000000000 (*)> debugobsolete dddddddddddddddddddddddddddddddddddddddd c8d03c1b5e94af74b772900c58259d2e08917735 --config experimental.obshashrange.warm-cache=0 exited 0 after *.?? seconds (glob)
   * @0000000000000000000000000000000000000000 (*)> debugobsolete eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee 4de32a90b66cd083ebf3c00b41277aa7abca51dd (glob)
   * @0000000000000000000000000000000000000000 (*)> obshashcache reset - new markers affect cached ranges (glob)
-  * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obshashrange in *.???? seconds (0r, 1o) (glob)
+  * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obshashrange in *.???? seconds (0r, 2o) (glob)
   * @0000000000000000000000000000000000000000 (*)> updated evo-ext-obscache in *.???? seconds (0r, 1o) (glob)
   * @0000000000000000000000000000000000000000 (*)> debugobsolete eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee 4de32a90b66cd083ebf3c00b41277aa7abca51dd exited 0 after *.?? seconds (glob)
   * @0000000000000000000000000000000000000000 (*)> debugobsolete (glob)
--- a/tests/test-prev-next.t	Thu May 18 23:55:02 2017 +0200
+++ b/tests/test-prev-next.t	Mon May 22 15:45:42 2017 +0200
@@ -171,10 +171,13 @@
   atop:[3] added b (2)
   hg rebase -r 4e26ef31f919 -d 9ad178109a19
   working directory now at 9ad178109a19
-  $ hg next --evolve
-  move:[2] added c
-  atop:[3] added b (2)
-  working directory now at e3b6d5df389b
+
+(add color output for smoke testing)
+
+  $ hg next --evolve --color debug
+  move:[[evolve.rev|2]] added c
+  atop:[[evolve.rev|3]] added b (2)
+  [ ui.status|working directory now at [evolve.node|e3b6d5df389b]]
 
 next with ambiguity
 
--- a/tests/test-prune.t	Thu May 18 23:55:02 2017 +0200
+++ b/tests/test-prune.t	Mon May 22 15:45:42 2017 +0200
@@ -2,6 +2,7 @@
   > [ui]
   > logtemplate={rev}:{node|short}[{bookmarks}] ({obsolete}/{phase}) {desc|firstline}\n
   > [extensions]
+  > color =
   > EOF
   $ echo "evolve=$(echo $(dirname $TESTDIR))/hgext3rd/evolve/" >> $HGRCPATH
 
@@ -71,10 +72,12 @@
 
 pruning multiple changeset at once
 
-  $ hg prune 2:
-  0 files updated, 0 files merged, 3 files removed, 0 files unresolved
-  working directory now at 1f0dee641bb7
-  2 changesets pruned
+(add color output to test it does not crash)
+
+  $ hg prune 2: --color debug
+  [ ui.status|0 files updated, 0 files merged, 3 files removed, 0 files unresolved]
+  [ ui.status|working directory now at [evolve.node|1f0dee641bb7]]
+  [ ui.status|2 changesets pruned]
   $ hg debugobsolete
   9d206ffc875e1bc304590549be293be36821e66c 0 {47d2a3944de8b013de3be9578e8e344ea2e6c097} (Sat Dec 15 00:00:00 1979 +0000) {'user': 'blah'}
   7c3bad9141dcb46ff89abf5f61856facd56e476c 0 {1f0dee641bb7258c56bd60e93edfa2405381c41e} (*) {'user': 'test'} (glob)