[Differential] [Request, 149 lines] D98: revset: support reading aliases from a .hgrevsets file
indygreg (Gregory Szorc)
phabricator at mercurial-scm.org
Sat Jul 15 23:41:58 UTC 2017
indygreg created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.
REVISION SUMMARY
It is common for projects or companies to define/recommend
common customizations for Mercurial. However, distributing these
customizations can be difficult because there's no distribution
channel built into Mercurial itself. The "configexpress"
extension is making some inroads here. But it is geared towards
hgrc files. I think there's room to make certain customizations
outside of the config system via specially named files checked
into the repository.
In this commit, we introduce a new experimental feature for
reading revset aliases from a .hgrevsets file in the working
directory. A repository can then add this file to define
custom revset aliases which will automagically be made available
to anyone who clones the repo and has a modern enough Mercurial
client [with the feature enabled].
Essentially, the .hgrevsets file is parsed as a [revsetalias]
config section but with lower priority than all config files.
This is because a user may want to overwrite an alias defined in
the repo and since not all users can commit to the repo, config
files or --config must take precedence.
One can imagine applying this pattern of "define customizations in
.hg<thing> files" to other features. For example, repositories could
also define templates - either keywords or full template maps.
Another potential area is filesets. You could create named
collections of files and do things like `hg files mycollection`
or even reference those named collections as part of building a
narrow clone or sparse checkout profile.
While I'm reasonably confident in the implementation, the feature
is marked as experimental because it is close to freeze and this
feature feels a bit dangerous to enable by default with minimal
time to bake.
REPOSITORY
rHG Mercurial
REVISION DETAIL
https://phab.mercurial-scm.org/D98
AFFECTED FILES
mercurial/configitems.py
mercurial/revset.py
tests/test-revset.t
CHANGE DETAILS
Index: tests/test-revset.t
===================================================================
--- tests/test-revset.t
+++ 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'
Index: mercurial/revset.py
===================================================================
--- mercurial/revset.py
+++ 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)
Index: mercurial/configitems.py
===================================================================
--- mercurial/configitems.py
+++ mercurial/configitems.py
@@ -199,6 +199,9 @@
coreconfigitem('experimental', 'graphshorten',
default=False,
)
+coreconfigitem('experimental', 'hgrevsetsfile',
+ default=False,
+)
coreconfigitem('experimental', 'hook-track-tags',
default=False,
)
EMAIL PREFERENCES
https://phab.mercurial-scm.org/settings/panel/emailpreferences/
To: indygreg, #hg-reviewers
Cc: mercurial-devel
More information about the Mercurial-devel
mailing list