# HG changeset patch # User Dan Villiom Podlaski Christiansen # Date 1286288779 -7200 # Node ID aa24148a74549270d02a16b5fa3e8cf2dbc99f61 # Parent af817963897e358234fc61534ba1e9fa6ae2228d uisetup: add fromsvn() and svnrev() revsets. diff --git a/hgsubversion/__init__.py b/hgsubversion/__init__.py --- 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) diff --git a/hgsubversion/help/subversion.rst b/hgsubversion/help/subversion.rst --- 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 --------------------- diff --git a/hgsubversion/util.py b/hgsubversion/util.py --- 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, +} diff --git a/tests/test_template_keywords.py b/tests/test_template_keywords.py --- 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),]