[PATCH 5 of 9 hglib] introduce a revset query builder utility
Kevin Bullock
kbullock+mercurial at ringworld.org
Fri Jul 29 10:55:41 CDT 2011
On 28 Jul 2011, at 2:58 PM, Idan Kamara wrote:
> # HG changeset patch
> # User Idan Kamara <idankk86 at gmail.com>
> # Date 1311450939 -10800
> # Node ID 1a84d5a142ffe6e40f96cb96f4beb9a346d4fa78
> # Parent 6b7230607731fd92604e77408bd3dd08cf96c916
> introduce a revset query builder utility
>
> diff -r 6b7230607731 -r 1a84d5a142ff hglib/revset.py
> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
> +++ b/hglib/revset.py Sat Jul 23 22:55:39 2011 +0300
> @@ -0,0 +1,139 @@
> +import hglib
> +
> +def quote(x):
> + if isinstance(x, (int, revset, hglib.changeset)):
> + return str(x)
> + elif isinstance(x, str):
> + return repr(x)
> + else:
> + raise TypeError()
> +
> +def raw(s):
> + return revset(s)
> +
> +def all():
> + return revset('all()')
> +
> +def branch(x):
> + """
> + >>> branch('foo')
> + <revset "branch('foo')">
> + >>> branch('"foo"')
> + <revset 'branch(\\'"foo"\\')'>
> + >>> import hglib
> + >>> branch(hglib.changeset(0, 'abcd', 0, 0, 0, 0))
> + <revset 'branch(abcd)'>
> + """
> + return revset('branch(%s)' % quote(x))
> +
> +def revrange(x=None, y=None):
> + """
> + >>> revrange(0, raw('tip'))
> + <revset '0:tip'>
> + >>> revrange(raw('tip'), 0)
> + <revset 'tip:0'>
> + """
> + if x is None and y is None:
> + raise ValueError('must provide at least x or y')
> + if x and not isinstance(x, (int, revset, hglib.changeset)):
> + raise TypeError()
> + if y and not isinstance(y, (int, revset, hglib.changeset)):
> + raise TypeError()
> +
> + if y is None:
> + return revset('%s:' % x)
> + if x is None:
> + return revset(':%s' % y)
> + return revset('%s:%s' % (x, y))
> +
> +def last(n, x=None):
> + """
> + >>> last(1)
> + <revset 'last(all(), 1)'>
> + >>> last(1, all())
> + <revset 'last(all(), 1)'>
> + >>> last(1, branch('default'))
> + <revset "last(branch('default'), 1)">
> + """
I don't think switching the order of arguments is a good idea here. The convenience of revset.last(1) without specifying a set would be outweighed by the confusion caused by passing the arguments in the wrong place.
pacem in terris / mir / shanti / salaam / heiwa
Kevin R. Bullock
> + if x is None:
> + x = all()
> + elif not isinstance(x, (int, revset, hglib.changeset)):
> + raise TypeError()
> +
> + return revset('last(%s, %d)' % (x, n))
> +
> +def merge():
> + return revset('merge()')
> +
> +def keyword(s):
> + """
> + >>> keyword('a b')
> + <revset "keyword('a b')">
> + """
> + return revset('keyword(%r)' % s)
> +
> +def dagrange(x=None, y=None):
> + """
> + >>> dagrange(raw('a'))
> + <revset 'a::'>
> + >>> dagrange(y=raw('a'))
> + <revset '::a'>
> + >>> dagrange(raw(repr('a b')), raw('c'))
> + <revset "'a b'::c">
> + """
> + if not x and not y:
> + raise ValueError('must provide at least x or y')
> + if x and not isinstance(x, (int, revset, hglib.changeset)):
> + raise TypeError()
> + if y and not isinstance(y, (int, revset, hglib.changeset)):
> + raise TypeError()
> +
> + if not y:
> + return revset('%s::' % x)
> + if not x:
> + return revset('::%s' % y)
> + return revset('%s::%s' % (x, y))
> +
> +class revset(object):
> + def __init__(self, s):
> + self.s = s
> +
> + def __str__(self):
> + return self.s
> +
> + def __repr__(self):
> + return "<revset %r>" % str(self)
> +
> + def __xor__(self, n):
> + """
> + >>> raw('foo')^2
> + <revset 'foo^2'>
> + """
> + if not isinstance(n, int):
> + return NotImplemented
> +
> + return revset('%s^%d' % (self, n))
> +
> + def __invert__(self):
> + """
> + >>> ~branch('foo')
> + <revset "not branch('foo')">
> + >>> branch('foo') & ~branch('foo')
> + <revset "(branch('foo') and not branch('foo'))">
> + """
> + return revset('not %s' % self)
> +
> + def __and__(self, other):
> + """
> + >>> branch('foo') & (branch('bar') & branch('foobar'))
> + <revset "(branch('foo') and (branch('bar') and branch('foobar')))">
> + >>> (branch('foo') & branch('bar')) & branch('foobar')
> + <revset "((branch('foo') and branch('bar')) and branch('foobar'))">
> + """
> + return revset('(%s and %s)' % (self.s, other.s))
> +
> + def __or__(self, other):
> + return revset('(%s or %s)' % (self.s, other.s))
> +
> + def __sub__(self, other):
> + return revset('(%s - %s)' % (self.s, other.s))
> diff -r 6b7230607731 -r 1a84d5a142ff tests/test-revset.py
> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
> +++ b/tests/test-revset.py Sat Jul 23 22:55:39 2011 +0300
> @@ -0,0 +1,59 @@
> +import common
> +from hglib import hglib, error, revset as rs
> +
> +class test_revset(common.basetest):
> + def test_log(self):
> + """emulate various options to log using revsets"""
> + self.append('a', 'a')
> + rev0 = self.client.commit('first', addremove=True)
> + self.append('a', 'a')
> + rev1 = self.client.commit('second')
> + self.client.branch('foo')
> + self.append('a', 'a')
> + rev2 = self.client.commit('third')
> +
> + # -b/--branch
> + self.assertEquals(self.client.log(rs.branch('default')), [rev0, rev1])
> + self.assertEquals(self.client.log(rs.branch('foo')), [rev2])
> +
> + # log -b default -b foo
> + r = rs.branch('default') | rs.branch('foo')
> + self.assertEquals(self.client.log(r), [rev0, rev1, rev2])
> +
> + # log -b default -l 1
> + r = rs.last(1, rs.branch('default'))
> + self.assertEquals(self.client.log(r), [rev1])
> +
> + # log -b default -b foo -l 1
> + r = rs.last(1, rs.branch('default') | rs.branch('foo'))
> + self.assertEquals(self.client.log(r), [rev2])
> +
> + # -M/--no-merges
> + r = ~rs.merge()
> + self.assertEquals(self.client.log(r), [rev0, rev1, rev2])
> +
> + # -m/--only-merges
> + r = rs.merge()
> + self.assertEquals(self.client.log(r), [])
> +
> + # -k/--keyword
> + r = rs.keyword('a')
> + self.assertEquals(self.client.log(r), [rev0, rev1, rev2])
> +
> + def test_quoting(self):
> + s = "spaces and 'q'uotes"
> + self.client.branch(s)
> + self.append('a', 'a')
> + rev0 = self.client.commit('first', addremove=True)
> + self.assertEquals(rev0.branch, s)
> + self.assertEquals(self.client.log(rs.branch(s)), [rev0])
> +
> + self.client.branch('default')
> + self.append('a', 'a')
> + rev1 = self.client.commit('second')
> +
> + r = rs.revrange(0, rs.branch(s))
> + self.assertEquals(self.client.log(r), [rev0])
> +
> + r = rs.revrange(0, rs.branch(s) | rs.branch(s))
> + self.assertEquals(self.client.log(r), [rev0])
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at selenic.com
> http://selenic.com/mailman/listinfo/mercurial-devel
More information about the Mercurial-devel
mailing list