[Bug 4624] New: Moderately complex (x or y or ... or z) revsets with about 350 items fail to parse after exceeding maximum recursion depth

mercurial-bugs at selenic.com mercurial-bugs at selenic.com
Sat Apr 25 16:39:53 UTC 2015


http://bz.selenic.com/show_bug.cgi?id=4624

          Priority: normal
            Bug ID: 4624
                CC: mercurial-devel at selenic.com
          Assignee: bugzilla at selenic.com
           Summary: Moderately complex (x or y or ... or z) revsets with
                    about 350 items fail to parse after exceeding maximum
                    recursion depth
          Severity: bug
    Classification: Unclassified
                OS: Mac OS
          Reporter: selenic at yghe.net
          Hardware: Macintosh
            Status: UNCONFIRMED
           Version: 3.4-rc
         Component: Mercurial
           Product: Mercurial

A moderately complex revset like this (with about 350 named revisions):

```
hg log --rev 'tip - (1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1
or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1
or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1
or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1
or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1
or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1
or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1
or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1
or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1
or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1
or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1
or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1
or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1
or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1
or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1
or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1
or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1
or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1
or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1
or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1
or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1
or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1 or 1
or 1 or 1)'
```

..fails to parse:

```
** unknown exception encountered, please report by visiting
** http://mercurial.selenic.com/wiki/BugTracker
** Python 2.7.6 (default, Sep  9 2014, 15:04:36) [GCC 4.2.1 Compatible Apple
LLVM 6.0 (clang-600.0.39)]
** Mercurial Distributed SCM (version 3.1.1+20140916)
** Extensions loaded: 
Traceback (most recent call last):
  File "/usr/local/bin/hg", line 43, in <module>
    mercurial.dispatch.run()
  File "/Library/Python/2.7/site-packages/mercurial/dispatch.py", line 28, in
run
    sys.exit((dispatch(request(sys.argv[1:])) or 0) & 255)
  File "/Library/Python/2.7/site-packages/mercurial/dispatch.py", line 69, in
dispatch
    ret = _runcatch(req)
  File "/Library/Python/2.7/site-packages/mercurial/dispatch.py", line 138, in
_runcatch
    return _dispatch(req)
  File "/Library/Python/2.7/site-packages/mercurial/dispatch.py", line 820, in
_dispatch
    cmdpats, cmdoptions)
  File "/Library/Python/2.7/site-packages/mercurial/dispatch.py", line 600, in
runcommand
    ret = _runcommand(ui, options, cmd, d)
  File "/Library/Python/2.7/site-packages/mercurial/dispatch.py", line 911, in
_runcommand
    return checkargs()
  File "/Library/Python/2.7/site-packages/mercurial/dispatch.py", line 882, in
checkargs
    return cmdfunc()
  File "/Library/Python/2.7/site-packages/mercurial/dispatch.py", line 817, in
<lambda>
    d = lambda: util.checksignature(func)(ui, *args, **cmdoptions)
  File "/Library/Python/2.7/site-packages/mercurial/util.py", line 550, in
check
    return func(*args, **kwargs)
  File "/Library/Python/2.7/site-packages/mercurial/commands.py", line 4182, in
log
    revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
  File "/Library/Python/2.7/site-packages/mercurial/cmdutil.py", line 1736, in
getlogrevs
    revs = scmutil.revrange(repo, opts['rev'])
  File "/Library/Python/2.7/site-packages/mercurial/scmutil.py", line 565, in
revrange
    m = revset.match(repo.ui, spec, repo)
  File "/Library/Python/2.7/site-packages/mercurial/revset.py", line 2058, in
match
    tree = findaliases(ui, tree)
  File "/Library/Python/2.7/site-packages/mercurial/revset.py", line 2042, in
findaliases
    return _expandaliases(aliases, tree, [], {})
  File "/Library/Python/2.7/site-packages/mercurial/revset.py", line 2033, in
_expandaliases
    for t in tree)
  File "/Library/Python/2.7/site-packages/mercurial/revset.py", line 2033, in
<genexpr>
    for t in tree)
  File "/Library/Python/2.7/site-packages/mercurial/revset.py", line 2033, in
_expandaliases
    for t in tree)
  File "/Library/Python/2.7/site-packages/mercurial/revset.py", line 2033, in
<genexpr>
    for t in tree)

... <snip 1300 lines> ...

  File "/Library/Python/2.7/site-packages/mercurial/revset.py", line 2033, in
<genexpr>
    for t in tree)
  File "/Library/Python/2.7/site-packages/mercurial/revset.py", line 2010, in
_expandaliases
    if not isinstance(tree, tuple):
RuntimeError: maximum recursion depth exceeded while calling a Python object
```

This is similar to #3604, although that avoided the issue by using a different
construct internally. In the general case, this can be worked around by
rewriting the revset like this:

```
((1 or 2 or ... or 256) or (257 or 258 or ... or 512))
```

...which is fine, but a little silly.

It is possible that no real human users ever run into this and that "about 350"
is, practically, good enough, and the parser isn't worth fixing, even given
internal cases like #3604.

For context, my use case is that I want to identify new commits on some
configurable subset of branches after pulling a repository. Some users have
configured this set of branches to include thousands of branches, because they
use Mercurial in interesting and creative ways. I can likely use the
`ancestors(...)` construct from #3604, but before finding that it wasn't
obvious to me that `ancestors(x, y, ...)` would have performance similar to `x
or y or ...`, as it "feels" like a more complex construction. Without special
knowledge of the internals, `x or y or ...` seemed like the simplest way to
express the query.

-- 
You are receiving this mail because:
You are on the CC list for the bug.


More information about the Mercurial-devel mailing list