changeset 722:aa24148a7454

uisetup: add fromsvn() and svnrev() revsets.
author Dan Villiom Podlaski Christiansen <danchr@gmail.com>
date Tue, 05 Oct 2010 16:26:19 +0200
parents af817963897e
children 4baa41e0f8ad
files hgsubversion/__init__.py hgsubversion/help/subversion.rst hgsubversion/util.py tests/test_template_keywords.py
diffstat 4 files changed, 94 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/hgsubversion/__init__.py
+++ b/hgsubversion/__init__.py
@@ -40,6 +40,13 @@ try:
 except ImportError:
    templatekw = None
 
+try:
+    from mercurial import revset
+    # force demandimport to load revset
+    revset.methods
+except ImportError:
+   revset = None
+
 import svncommands
 import util
 import svnrepo
@@ -142,6 +149,9 @@ def uisetup(ui):
     if templatekw:
         templatekw.keywords.update(util.templatekeywords)
 
+    if revset:
+        revset.symbols.update(util.revsets)
+
 def reposetup(ui, repo):
     if repo.local():
        svnrepo.generate_repo_class(ui, repo)
--- a/hgsubversion/help/subversion.rst
+++ b/hgsubversion/help/subversion.rst
@@ -57,7 +57,7 @@ only convert the latest revision; later 
 following the first. Please note that this only works for single-directory
 clones.
 
-Displaying Subversion revisions
+Finding and displaying Subversion revisions
 -------------------------------------------
 
 For revealing the relationship between Mercurial changesets and Subversion
@@ -69,6 +69,16 @@ repository. An example::
 
   $ hg log --template='{rev}:{node|short} {author|user}\nsvn: {svnrev}\n'
 
+For finding changesets from Subversion, hgsubversion extends revsets to provide
+two new selectors: ``fromsvn()`` and ``svnrev()``. (Revsets were introduced in
+Mercurial 1.6 and are accepted by several Mercurial commands for specifying
+revisions. See ``hg help revsets`` for details.) You can use ``fromsvn()`` to
+select all changesets that originate from Subversion, and ``svnrev(REV)`` to
+match changesets that originate in a specific Subversion revision. For example::
+
+  $ hg log -r 'fromsvn()'
+  $ hg log -r 'svnrev(500)'
+
 Support for externals
 ---------------------
 
--- a/hgsubversion/util.py
+++ b/hgsubversion/util.py
@@ -3,10 +3,15 @@ import os
 import urllib
 
 from mercurial import cmdutil
+from mercurial import error
 from mercurial import hg
 from mercurial import node
 from mercurial import util as hgutil
 
+try:
+    from mercurial import revset
+except ImportError:
+    pass
 
 b_re = re.compile(r'^\+\+\+ b\/([^\n]*)', re.MULTILINE)
 a_re = re.compile(r'^--- a\/([^\n]*)', re.MULTILINE)
@@ -198,3 +203,35 @@ templatekeywords = {
     'svnpath': (lambda repo, ctx, templ, **a: _templatehelper(ctx, 'svnpath')),
     'svnuuid': (lambda repo, ctx, templ, **a: _templatehelper(ctx, 'svnuuid')),
 }
+
+def revset_fromsvn(repo, subset, x):
+    args = revset.getargs(x, 0, 0, "fromsvn takes no arguments")
+
+    def matches(r):
+        convertinfo = repo[r].extra().get('convert_revision', '')
+        return convertinfo[:4] == 'svn:'
+
+    return [r for r in subset if matches(r)]
+
+def revset_svnrev(repo, subset, x):
+    args = revset.getargs(x, 1, 1, "svnrev takes one argument")
+
+    rev = revset.getstring(args[0],
+                           "the argument to svnrev() must be a number")
+    try:
+        rev = int(rev)
+    except ValueError:
+        raise error.ParseError("the argument to svnrev() must be a number")
+
+    def matches(r):
+        convertinfo = repo[r].extra().get('convert_revision', '')
+        if convertinfo[:4] != 'svn:':
+            return False
+        return int(convertinfo[40:].rsplit('@', 1)[-1]) == rev
+
+    return [r for r in subset if matches(r)]
+
+revsets = {
+    'fromsvn': revset_fromsvn,
+    'svnrev': revset_svnrev,
+}
--- a/tests/test_template_keywords.py
+++ b/tests/test_template_keywords.py
@@ -3,6 +3,7 @@ import test_util
 import unittest
 
 from mercurial import commands
+from mercurial import error
 from mercurial import ui
 try:
     from mercurial import templatekw
@@ -10,6 +11,11 @@ try:
 except ImportError:
     templatekw = None
 
+try:
+    from mercurial import revset
+    revset.methods
+except ImportError:
+   revset = None
 
 class CapturingUI(ui.ui):
 
@@ -43,6 +49,36 @@ class TestLogKeywords(test_util.TestBase
                           '1:df2126f7-00ab-4d49-b42c-7e981dde0bcf '
                           '2: '))
 
+    if templatekw and revset:
+        def test_svn_revsets(self):
+            repo = self._load_fixture_and_fetch('two_revs.svndump')
+
+            # we want one commit that isn't from Subversion
+            self.commitchanges([('foo', 'foo', 'frobnicate\n')])
+
+            defaults = {'date': None, 'rev': ['fromsvn()'], 'user': None}
+
+            ui = CapturingUI()
+            commands.log(ui, repo, template='{rev}:{svnrev} ', **defaults)
+            self.assertEqual(ui._output, '0:2 1:3 ')
+
+            defaults = {'date': None, 'rev': ['svnrev(2)'], 'user': None}
+
+            ui = CapturingUI()
+            commands.log(ui, repo, template='{rev}:{svnrev} ', **defaults)
+            self.assertEqual(ui._output, '0:2 ')
+
+            defaults = {'date': None, 'rev': ['fromsvn(1)'], 'user': None}
+
+            self.assertRaises(error.ParseError,
+                              commands.log, self.ui(), repo,
+                              template='{rev}:{svnrev} ', **defaults)
+
+            defaults = {'date': None, 'rev': ['svnrev(1, 2)'], 'user': None}
+
+            self.assertRaises(error.ParseError,
+                              commands.log, self.ui(), repo,
+                              template='{rev}:{svnrev} ', **defaults)
 
 def suite():
     all = [unittest.TestLoader().loadTestsFromTestCase(TestLogKeywords),]