util: extract stringmatcher() from revset
authorMatt Harbison <matt_harbison@yahoo.com>
Sat, 22 Aug 2015 22:52:18 -0400
changeset 26481 7d132557e44a
parent 26480 6ae14d1ca3aa
child 26482 d2e69584e330
util: extract stringmatcher() from revset This is used to match against tags, bookmarks, etc in revsets. It will be used in a future patch to do the same tag matching in templater.
mercurial/revset.py
mercurial/util.py
--- a/mercurial/revset.py	Mon Oct 05 17:36:32 2015 -0700
+++ b/mercurial/revset.py	Sat Aug 22 22:52:18 2015 -0400
@@ -690,7 +690,7 @@
         bm = getstring(args[0],
                        # i18n: "bookmark" is a keyword
                        _('the argument to bookmark must be a string'))
-        kind, pattern, matcher = _stringmatcher(bm)
+        kind, pattern, matcher = util.stringmatcher(bm)
         bms = set()
         if kind == 'literal':
             bmrev = repo._bookmarks.get(pattern, None)
@@ -731,7 +731,7 @@
         # not a string, but another revspec, e.g. tip()
         pass
     else:
-        kind, pattern, matcher = _stringmatcher(b)
+        kind, pattern, matcher = util.stringmatcher(b)
         if kind == 'literal':
             # note: falls through to the revspec case if no branch with
             # this name exists
@@ -1019,7 +1019,7 @@
         # i18n: "extra" is a keyword
         value = getstring(args['value'], _('second argument to extra must be '
                                            'a string'))
-        kind, value, matcher = _stringmatcher(value)
+        kind, value, matcher = util.stringmatcher(value)
 
     def _matchvalue(r):
         extra = repo[r].extra()
@@ -1466,7 +1466,7 @@
     ns = getstring(args[0],
                    # i18n: "named" is a keyword
                    _('the argument to named must be a string'))
-    kind, pattern, matcher = _stringmatcher(ns)
+    kind, pattern, matcher = util.stringmatcher(ns)
     namespaces = set()
     if kind == 'literal':
         if pattern not in repo.names:
@@ -2034,7 +2034,7 @@
     m = matchmod.exact(repo.root, repo.root, ['.hgsubstate'])
 
     def submatches(names):
-        k, p, m = _stringmatcher(pat)
+        k, p, m = util.stringmatcher(pat)
         for name in names:
             if m(name):
                 yield name
@@ -2064,47 +2064,8 @@
 
     return subset.filter(matches)
 
-def _stringmatcher(pattern):
-    """
-    accepts a string, possibly starting with 're:' or 'literal:' prefix.
-    returns the matcher name, pattern, and matcher function.
-    missing or unknown prefixes are treated as literal matches.
-
-    helper for tests:
-    >>> def test(pattern, *tests):
-    ...     kind, pattern, matcher = _stringmatcher(pattern)
-    ...     return (kind, pattern, [bool(matcher(t)) for t in tests])
-
-    exact matching (no prefix):
-    >>> test('abcdefg', 'abc', 'def', 'abcdefg')
-    ('literal', 'abcdefg', [False, False, True])
-
-    regex matching ('re:' prefix)
-    >>> test('re:a.+b', 'nomatch', 'fooadef', 'fooadefbar')
-    ('re', 'a.+b', [False, False, True])
-
-    force exact matches ('literal:' prefix)
-    >>> test('literal:re:foobar', 'foobar', 're:foobar')
-    ('literal', 're:foobar', [False, True])
-
-    unknown prefixes are ignored and treated as literals
-    >>> test('foo:bar', 'foo', 'bar', 'foo:bar')
-    ('literal', 'foo:bar', [False, False, True])
-    """
-    if pattern.startswith('re:'):
-        pattern = pattern[3:]
-        try:
-            regex = re.compile(pattern)
-        except re.error as e:
-            raise error.ParseError(_('invalid regular expression: %s')
-                                   % e)
-        return 're', pattern, regex.search
-    elif pattern.startswith('literal:'):
-        pattern = pattern[8:]
-    return 'literal', pattern, pattern.__eq__
-
 def _substringmatcher(pattern):
-    kind, pattern, matcher = _stringmatcher(pattern)
+    kind, pattern, matcher = util.stringmatcher(pattern)
     if kind == 'literal':
         matcher = lambda s: pattern in s
     return kind, pattern, matcher
@@ -2124,7 +2085,7 @@
         pattern = getstring(args[0],
                             # i18n: "tag" is a keyword
                             _('the argument to tag must be a string'))
-        kind, pattern, matcher = _stringmatcher(pattern)
+        kind, pattern, matcher = util.stringmatcher(pattern)
         if kind == 'literal':
             # avoid resolving all tags
             tn = repo._tagscache.tags.get(pattern, None)
--- a/mercurial/util.py	Mon Oct 05 17:36:32 2015 -0700
+++ b/mercurial/util.py	Sat Aug 22 22:52:18 2015 -0400
@@ -1605,6 +1605,45 @@
         start, stop = lower(date), upper(date)
         return lambda x: x >= start and x <= stop
 
+def stringmatcher(pattern):
+    """
+    accepts a string, possibly starting with 're:' or 'literal:' prefix.
+    returns the matcher name, pattern, and matcher function.
+    missing or unknown prefixes are treated as literal matches.
+
+    helper for tests:
+    >>> def test(pattern, *tests):
+    ...     kind, pattern, matcher = stringmatcher(pattern)
+    ...     return (kind, pattern, [bool(matcher(t)) for t in tests])
+
+    exact matching (no prefix):
+    >>> test('abcdefg', 'abc', 'def', 'abcdefg')
+    ('literal', 'abcdefg', [False, False, True])
+
+    regex matching ('re:' prefix)
+    >>> test('re:a.+b', 'nomatch', 'fooadef', 'fooadefbar')
+    ('re', 'a.+b', [False, False, True])
+
+    force exact matches ('literal:' prefix)
+    >>> test('literal:re:foobar', 'foobar', 're:foobar')
+    ('literal', 're:foobar', [False, True])
+
+    unknown prefixes are ignored and treated as literals
+    >>> test('foo:bar', 'foo', 'bar', 'foo:bar')
+    ('literal', 'foo:bar', [False, False, True])
+    """
+    if pattern.startswith('re:'):
+        pattern = pattern[3:]
+        try:
+            regex = remod.compile(pattern)
+        except remod.error as e:
+            raise error.ParseError(_('invalid regular expression: %s')
+                                   % e)
+        return 're', pattern, regex.search
+    elif pattern.startswith('literal:'):
+        pattern = pattern[8:]
+    return 'literal', pattern, pattern.__eq__
+
 def shortuser(user):
     """Return a short representation of a user name or email address."""
     f = user.find('@')