test-compat: merge with stable
Nothing special to report, minor blackbox output update and color extensions was
needed for test-prune.t
--- a/.hgtags Thu May 18 23:12:52 2017 +0200
+++ b/.hgtags Mon May 22 15:28:36 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:12:52 2017 +0200
+++ b/README Mon May 22 15:28:36 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:12:52 2017 +0200
+++ b/hgext3rd/evolve/__init__.py Mon May 22 15:28:36 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:12:52 2017 +0200
+++ b/hgext3rd/evolve/exthelper.py Mon May 22 15:28:36 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:12:52 2017 +0200
+++ b/hgext3rd/evolve/hack/directaccess.py Mon May 22 15:28:36 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:12:52 2017 +0200
+++ b/hgext3rd/evolve/hack/drophack.py Mon May 22 15:28:36 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:12:52 2017 +0200
+++ b/hgext3rd/evolve/hack/inhibit.py Mon May 22 15:28:36 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:12:52 2017 +0200
+++ b/hgext3rd/evolve/legacy.py Mon May 22 15:28:36 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:12:52 2017 +0200
+++ b/hgext3rd/evolve/metadata.py Mon May 22 15:28:36 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:12:52 2017 +0200
+++ b/hgext3rd/evolve/obsdiscovery.py Mon May 22 15:28:36 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:12:52 2017 +0200
+++ b/hgext3rd/topic/__init__.py Mon May 22 15:28:36 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:12:52 2017 +0200
+++ b/tests/test-discovery-obshashrange.t Mon May 22 15:28:36 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'}
@@ -109,14 +109,12 @@
* @0000000000000000000000000000000000000000 (*)> debugobsolete cccccccccccccccccccccccccccccccccccccccc bebd167eb94d257ace0e814aeb98e6972ed2970d exited 0 after *.?? seconds (glob)
* @0000000000000000000000000000000000000000 (*)> debugobsolete dddddddddddddddddddddddddddddddddddddddd c8d03c1b5e94af74b772900c58259d2e08917735 (glob)
* @0000000000000000000000000000000000000000 (*)> alias 'debugobsolete' expands to 'debugobsolete -d '0 0'' (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 (*)> alias 'debugobsolete' expands to 'debugobsolete -d '0 0'' (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:12:52 2017 +0200
+++ b/tests/test-prev-next.t Mon May 22 15:28:36 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:12:52 2017 +0200
+++ b/tests/test-prune.t Mon May 22 15:28:36 2017 +0200
@@ -2,6 +2,7 @@
> [ui]
> logtemplate={rev}:{node|short}[{bookmarks}] ({separate('/', 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)