From 136d5a75dcb5c1b3e057e069efeae5ef14f31dba Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 17 Aug 2011 14:27:47 +0200 Subject: In "plain" mode, skip tags that contain characters not valid in Git. --- NEWS | 3 +++ exporter.py | 37 +++++++++++++++++++++++++++++++++++++ tests/test_exporter.py | 28 ++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+) diff --git a/NEWS b/NEWS index 45c601a..f1f6ca5 100644 --- a/NEWS +++ b/NEWS @@ -23,6 +23,9 @@ Bug fixes These options are not supported by the underlying svn-fast-export.py yet. (Jelmer Vernooij, #513747) +* In "plain" mode, skip tags that contain characters not valid in Git. + (Jelmer Vernooij, #386986) + 0.10 08-Mar-2011 Changes diff --git a/exporter.py b/exporter.py index 6d1a9c0..cc9452b 100644 --- a/exporter.py +++ b/exporter.py @@ -61,6 +61,39 @@ def _get_output_stream(destination): else: return open(destination, 'wb') +# from dulwich.repo: +def check_ref_format(refname): + """Check if a refname is correctly formatted. + + Implements all the same rules as git-check-ref-format[1]. + + [1] http://www.kernel.org/pub/software/scm/git/docs/git-check-ref-format.html + + :param refname: The refname to check + :return: True if refname is valid, False otherwise + """ + # These could be combined into one big expression, but are listed separately + # to parallel [1]. + if '/.' in refname or refname.startswith('.'): + return False + if '/' not in refname: + return False + if '..' in refname: + return False + for c in refname: + if ord(c) < 040 or c in '\177 ~^:?*[': + return False + if refname[-1] in '/.': + return False + if refname.endswith('.lock'): + return False + if '@{' in refname: + return False + if '\\' in refname: + return False + return True + + class BzrFastExporter(object): @@ -507,6 +540,10 @@ class BzrFastExporter(object): 'revision %s' % (tag, revid)) else: git_ref = 'refs/tags/%s' % tag.encode("utf-8") + if self.plain_format and not check_ref_format(git_ref): + self.warning('not creating tag %r as its name would not be ' + 'valid in git.', git_ref) + continue self.print_cmd(commands.ResetCommand(git_ref, ":" + str(mark))) def _next_tmp_branch_name(self): diff --git a/tests/test_exporter.py b/tests/test_exporter.py index fe50e3b..24fedb1 100644 --- a/tests/test_exporter.py +++ b/tests/test_exporter.py @@ -24,6 +24,7 @@ from bzrlib import tests from bzrlib.plugins.fastimport.exporter import ( _get_output_stream, + check_ref_format, ) from bzrlib.plugins.fastimport.tests import ( @@ -60,3 +61,30 @@ class TestOutputStream(tests.TestCase): f = open(filename, 'r') self.assertEquals("foo", f.read()) f.close() + + +# from dulwich.tests.test_repository: +class CheckRefFormatTests(tests.TestCase): + """Tests for the check_ref_format function. + + These are the same tests as in the git test suite. + """ + + def test_valid(self): + self.assertTrue(check_ref_format('heads/foo')) + self.assertTrue(check_ref_format('foo/bar/baz')) + self.assertTrue(check_ref_format('refs///heads/foo')) + self.assertTrue(check_ref_format('foo./bar')) + self.assertTrue(check_ref_format('heads/foo@bar')) + self.assertTrue(check_ref_format('heads/fix.lock.error')) + + def test_invalid(self): + self.assertFalse(check_ref_format('foo')) + self.assertFalse(check_ref_format('heads/foo/')) + self.assertFalse(check_ref_format('./foo')) + self.assertFalse(check_ref_format('.refs/foo')) + self.assertFalse(check_ref_format('heads/foo..bar')) + self.assertFalse(check_ref_format('heads/foo?bar')) + self.assertFalse(check_ref_format('heads/foo.lock')) + self.assertFalse(check_ref_format('heads/v@{ation')) + self.assertFalse(check_ref_format('heads/foo\bar')) -- cgit v1.2.1