[PATCH 5 of 9 hglib] introduce a revset query builder utility

Idan Kamara idankk86 at gmail.com
Thu Jul 28 14:58:58 CDT 2011


# 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)">
+    """
+    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])


More information about the Mercurial-devel mailing list