diff --git a/mercurial/configitems.py b/mercurial/configitems.py --- a/mercurial/configitems.py +++ b/mercurial/configitems.py @@ -199,6 +199,9 @@ coreconfigitem('experimental', 'graphshorten', default=False, ) +coreconfigitem('experimental', 'hgrevsetsfile', + default=False, +) coreconfigitem('experimental', 'hook-track-tags', default=False, ) diff --git a/mercurial/revset.py b/mercurial/revset.py --- a/mercurial/revset.py +++ b/mercurial/revset.py @@ -2061,6 +2061,9 @@ If localalias is not None, it is a dict {name: definitionstring}. It takes precedence over [revsetalias] config section. + + Aliases from the config file and a ``.hgrevsets`` file in the working + directory are only expanded if ``ui`` is defined. """ if not specs: def mfunc(repo, subset=None): @@ -2079,6 +2082,12 @@ aliases = [] warn = None + + # Aliases from the .hgrevsets file in the repo have the lowest priority + # because the user is in the least control of them. An hgrc or config + # option can be set easily. A file in the repo cannot be changed as easily. + if ui and repo and repo.ui.configbool('experimental', 'hgrevsetsfile'): + aliases.extend(_parsehgrevsetsfile(repo)) if ui: aliases.extend(ui.configitems('revsetalias')) warn = ui.warn @@ -2108,6 +2117,47 @@ if func._safe: safesymbols.add(name) +def _parsehgrevsetsfile(repo): + options = {} + + data = repo.wvfs.tryread('.hgrevsets') + for line in data.splitlines(): + line = line.strip() + if not line or line.startswith('#'): + continue + + if '=' not in line: + repo.ui.warn(_('invalid syntax in .hgrevsets: %s\n') % line) + continue + + name, value = line.split('=', 1) + options[name.strip()] = value.strip() + + aliases = [] + ourversion = util.versiontuple(n=2) + + for key, value in options.iteritems(): + if ':' in key: + continue + + # Revsets in repo may require features not available to old clients. + # Allow revsets to self-advertise minimum version requirements. + minversion = options.get('%s:minversion' % key) + if minversion: + try: + wantversion = util.versiontuple(minversion, n=2) + except IndexError: + repo.ui.warn(_('illegal value for %s in .hgrevsetsfile: %s\n') % + ('%s:minversion' % key, minversion)) + continue + + if wantversion > ourversion: + continue + + aliases.append((key, value)) + + return aliases + # load built-in predicates explicitly to setup safesymbols loadpredicate(None, None, predicate) diff --git a/tests/test-revset.t b/tests/test-revset.t --- a/tests/test-revset.t +++ b/tests/test-revset.t @@ -4114,6 +4114,102 @@ 5:904fa392b941 6:e0cc66ef77e8 +.hgrevsets file from working directory can define aliases + + $ cat > .hgrevsets << EOF + > filealiasall = all() + > filealiasthroughfour = 0:4 + > EOF + + $ hg log -q -r 'filealiasall' + abort: unknown revision 'filealiasall'! + [255] + + $ hg log -q -r 'filealiasall' --config experimental.hgrevsetsfile=true + 0:2785f51eece5 + 1:d75937da8da0 + 2:5ed5505e9f1c + 3:8528aa5637f2 + 4:2326846efdab + 5:904fa392b941 + 6:e0cc66ef77e8 + 7:013af1973af4 + 8:d5d0dcbdc4d9 + 9:24286f4ae135 + +.hgrevsets is combined with revsetalias + + $ hg log -q -r 'filealiasall & m' --config experimental.hgrevsetsfile=true + 6:e0cc66ef77e8 + +Value from config overwrites .hgrevsets + + $ cat > .hgrevsets << EOF + > m = all() + > EOF + + $ hg log -q -r m --config experimental.hgrevsetsfile=true + 6:e0cc66ef77e8 + +Minimum version filtering in .hgrevset entries works + + $ cat > fakeversion.py << EOF + > from mercurial import util + > util.version = lambda: '4.1' + > EOF + + $ cat > .hgrevsets << EOF + > requiresnew = 0:1 + > requiresnew:minversion = 4.2 + > requiresold = 2:3 + > requiresold:minversion = 4.1 + > EOF + + $ hg log -q -r requiresnew --config experimental.hgrevsetsfile=true --config extensions.fakeversion=`pwd`/fakeversion.py + abort: unknown revision 'requiresnew'! + [255] + + $ hg log -q -r requiresold --config experimental.hgrevsetsfile=true --config extensions.fakeversion=`pwd`/fakeversion.py + 2:5ed5505e9f1c + 3:8528aa5637f2 + +Missing .hgrevsetsfile is OK + + $ rm .hgrevsets + $ hg log -q -r 1 --config experimental.hgrevsetsfile=true + 1:d75937da8da0 + +Invalid syntax in .hgrevsets file + + $ cat > .hgrevsets << EOF + > fileall = all() + > bar + > EOF + + $ hg log -q -r fileall --config experimental.hgrevsetsfile=true + invalid syntax in .hgrevsets: bar + 0:2785f51eece5 + 1:d75937da8da0 + 2:5ed5505e9f1c + 3:8528aa5637f2 + 4:2326846efdab + 5:904fa392b941 + 6:e0cc66ef77e8 + 7:013af1973af4 + 8:d5d0dcbdc4d9 + 9:24286f4ae135 + +Unable to parse :minversion in .hgrevsets file + + $ cat > .hgrevsets << EOF + > fileall = all() + > fileall:minversion = invalid + > EOF + + $ hg log -q -r foo --config experimental.hgrevsetsfile=true + abort: unknown revision 'foo'! + [255] + issue2549 - correct optimizations $ try 'limit(1 or 2 or 3, 2) and not 2'