Since ec7b9bec19c9, stripping large amount of changesets causes RuntimeError at revset. -- script to reproduce -- #!/bin/sh -e hg init repo cd repo touch foo hg add foo for i in `seq 0 399`; do echo $i >> foo hg ci -m $i done hg --config extensions.mq= strip 0 ---- -- traceback -- ** unknown exception encountered, please report by visiting ** http://mercurial.selenic.com/wiki/BugTracker ** Python 2.7.3 (default, Aug 26 2012, 11:57:48) [GCC 4.7.1] ** Mercurial Distributed SCM (version 2.3+44-fc14953e8e34) ** Extensions loaded: mq Traceback (most recent call last): File "/home/yuya/work/hghacks/mercurial/hg", line 38, in <module> mercurial.dispatch.run() File "/home/yuya/work/hghacks/mercurial/mercurial/dispatch.py", line 28, in run sys.exit((dispatch(request(sys.argv[1:])) or 0) & 255) File "/home/yuya/work/hghacks/mercurial/mercurial/dispatch.py", line 65, in dispatch return _runcatch(req) File "/home/yuya/work/hghacks/mercurial/mercurial/dispatch.py", line 88, in _runcatch return _dispatch(req) File "/home/yuya/work/hghacks/mercurial/mercurial/dispatch.py", line 740, in _dispatch cmdpats, cmdoptions) File "/home/yuya/work/hghacks/mercurial/mercurial/dispatch.py", line 514, in runcommand ret = _runcommand(ui, options, cmd, d) File "/home/yuya/work/hghacks/mercurial/mercurial/dispatch.py", line 830, in _runcommand return checkargs() File "/home/yuya/work/hghacks/mercurial/mercurial/dispatch.py", line 801, in checkargs return cmdfunc() File "/home/yuya/work/hghacks/mercurial/mercurial/dispatch.py", line 737, in <lambda> d = lambda: util.checksignature(func)(ui, *args, **cmdoptions) File "/home/yuya/work/hghacks/mercurial/mercurial/util.py", line 471, in check return func(*args, **kwargs) File "/home/yuya/work/hghacks/mercurial/hgext/mq.py", line 3039, in strip force=opts.get('force')) File "/home/yuya/work/hghacks/mercurial/hgext/mq.py", line 1118, in strip repair.strip(self.ui, repo, revs, backup) File "/home/yuya/work/hghacks/mercurial/mercurial/repair.py", line 116, in strip rset, rset) File "/home/yuya/work/hghacks/mercurial/mercurial/localrepo.py", line 371, in revs return [r for r in m(self, range(len(self)))] File "/home/yuya/work/hghacks/mercurial/mercurial/revset.py", line 1752, in mfunc return getset(repo, subset, tree) File "/home/yuya/work/hghacks/mercurial/mercurial/revset.py", line 187, in getset return methods[x[0]](repo, subset, *x[1:]) File "/home/yuya/work/hghacks/mercurial/mercurial/revset.py", line 260, in func return symbols[a[1]](repo, subset, b) File "/home/yuya/work/hghacks/mercurial/mercurial/revset.py", line 1329, in sort for r in getset(repo, subset, s): File "/home/yuya/work/hghacks/mercurial/mercurial/revset.py", line 187, in getset return methods[x[0]](repo, subset, *x[1:]) File "/home/yuya/work/hghacks/mercurial/mercurial/revset.py", line 260, in func return symbols[a[1]](repo, subset, b) File "/home/yuya/work/hghacks/mercurial/mercurial/revset.py", line 837, in heads s = getset(repo, subset, x) File "/home/yuya/work/hghacks/mercurial/mercurial/revset.py", line 187, in getset return methods[x[0]](repo, subset, *x[1:]) File "/home/yuya/work/hghacks/mercurial/mercurial/revset.py", line 243, in andset return getset(repo, getset(repo, subset, x), y) File "/home/yuya/work/hghacks/mercurial/mercurial/revset.py", line 187, in getset return methods[x[0]](repo, subset, *x[1:]) File "/home/yuya/work/hghacks/mercurial/mercurial/revset.py", line 252, in notset s = set(getset(repo, subset, x)) File "/home/yuya/work/hghacks/mercurial/mercurial/revset.py", line 187, in getset return methods[x[0]](repo, subset, *x[1:]) File "/home/yuya/work/hghacks/mercurial/mercurial/revset.py", line 246, in orset xl = getset(repo, subset, x) ... File "/home/yuya/work/hghacks/mercurial/mercurial/revset.py", line 246, in orset xl = getset(repo, subset, x) RuntimeError: maximum recursion depth exceeded ----
I've seen this one too.
Adding guilty party fingered by bisect. This first line here is the culprit: rset = ' or '.join([str(r) for r in tostrip]) newbmtarget = repo.revs('sort(heads(ancestors(%r) - (%r)), -rev)', rset, rset) The large 'or' join creates a depth-N unbalanced tree structure that revset eventually recurses too deeply on. Instead, this should use the 'l' modifier: repo.revs('ancestors(%ld)', listofrevnums) which builds a structure that we handle efficiently (search for _list in revset.py).
(In reply to comment #2) You wouldn't happen to have the guilty changeset id handy, would you?
Confirmed the fix by http://hg.intevation.org/mercurial/crew/rev/63e9b0732518 Thanks!
Fixed by http://selenic.com/repo/hg/rev/7c865f30e2b8 Pierre-Yves David <pierre-yves.david@ens-lyon.org> strip: fix revset usage (issue3604) The `repair` code builds a giant revset query instead of using the "%lr" idiom. It is inefficient and crash when the number of stripped changeset is too big. This changeset replaces the bad code by a better revset usage. (please test the fix)
Also confirmed the fix at release 2.3.1, thanks.