From 02fe09a21d1548b901fede6f90434c6455cc675b Mon Sep 17 00:00:00 2001 From: Oleksandr Usov Date: Wed, 12 Oct 2011 11:24:29 +0100 Subject: Add function to rewrite refnames & tests for it --- exporter.py | 37 ++++++++++++++++++++++++++++++++++++- tests/test_exporter.py | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 1 deletion(-) diff --git a/exporter.py b/exporter.py index 78b5dba..e67a621 100644 --- a/exporter.py +++ b/exporter.py @@ -46,7 +46,7 @@ # set new_git_branch to the previously used name) from email.Utils import parseaddr -import sys, time +import sys, time, re import bzrlib.branch import bzrlib.revision @@ -111,7 +111,42 @@ def check_ref_format(refname): return False return True +def sanitize_ref_name_for_git(name_dict, refname): + """Rewrite refname so that it will be accepted by git-fast-import. + For the detailed rules see check_ref_format. + By rewriting the refname we are breaking uniqueness guarantees provided by bzr + so we have to manually + verify that resulting ref names are unique. + + :param name_dict: additional dictionary used to enforce uniqueness of resulting refname's + :param refname: refname to rewrite + :return: new refname + """ + newRefname = re.sub( + # '/.' in refname or startswith '.' + r"/\.|^\." + # '..' in refname + r"|\.\." + # ord(c) < 040 + r"|[" + "".join([chr(x) for x in range(040)]) + r"]" + # c in '\177 ~^:?*[' + r"|[\177 ~^:?*[]" + # last char in "/." + r"|[/.]$" + # endswith '.lock' + r"|.lock$" + # "@{" in refname + r"|@{" + # "\\" in refname + r"|\\", + "_", refname) + idx = name_dict.get(newRefname, 1) + name_dict[newRefname] = idx + 1 + if idx != 1: + # append index to the resulting refname if it's not unique + newRefname += "_" + str(idx) + return newRefname class BzrFastExporter(object): diff --git a/tests/test_exporter.py b/tests/test_exporter.py index c2a8442..957945f 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, + sanitize_ref_name_for_git ) from bzrlib.plugins.fastimport.tests import ( @@ -79,11 +80,55 @@ class CheckRefFormatTests(tests.TestCase): def test_invalid(self): self.assertFalse(check_ref_format('foo')) + self.assertFalse(check_ref_format('foo/.bar')) self.assertFalse(check_ref_format('heads/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')) self.assertFalse(check_ref_format('heads/foo\bar')) + self.assertFalse(check_ref_format('heads/foo bar')) + self.assertFalse(check_ref_format('heads/foo\020bar')) + self.assertFalse(check_ref_format('heads/foo\177bar')) + +class CheckRefnameRewriting(tests.TestCase): + """Tests for sanitize_ref_name_for_git function""" + + def test_passthrough_valid(self): + self.assertEqual(sanitize_ref_name_for_git(dict(), 'heads/foo'), 'heads/foo') + self.assertEqual(sanitize_ref_name_for_git(dict(), 'foo/bar/baz'), 'foo/bar/baz') + self.assertEqual(sanitize_ref_name_for_git(dict(), 'refs///heads/foo'), 'refs///heads/foo') + self.assertEqual(sanitize_ref_name_for_git(dict(), 'foo./bar'), 'foo./bar') + self.assertEqual(sanitize_ref_name_for_git(dict(), 'heads/foo@bar'), 'heads/foo@bar') + self.assertEqual(sanitize_ref_name_for_git(dict(), 'heads/fix.lock.error'), 'heads/fix.lock.error') + + def test_rewrite_to_unique_names(self): + self.assertEqual(sanitize_ref_name_for_git(dict(), 'heads/foo/'), 'heads/foo_') + # check that with persistent dictionary we generate unique names on each invocation + q = dict() + self.assertNotEqual( + sanitize_ref_name_for_git(q, 'heads/foo/'), + sanitize_ref_name_for_git(q, 'heads/foo/')) + self.assertNotEqual( + sanitize_ref_name_for_git(q, 'heads/foo/'), + sanitize_ref_name_for_git(q, 'heads/foo/')) + + def test_rewrite_invalid(self): + self.assertTrue(check_ref_format(sanitize_ref_name_for_git(dict(), 'foo./bar'))) + self.assertTrue(check_ref_format(sanitize_ref_name_for_git(dict(), 'heads/foo/'))) + self.assertTrue(check_ref_format(sanitize_ref_name_for_git(dict(), 'heads/foo.'))) + self.assertTrue(check_ref_format(sanitize_ref_name_for_git(dict(), './foo'))) + self.assertTrue(check_ref_format(sanitize_ref_name_for_git(dict(), '.refs/foo'))) + self.assertTrue(check_ref_format(sanitize_ref_name_for_git(dict(), 'heads/foo..bar'))) + self.assertTrue(check_ref_format(sanitize_ref_name_for_git(dict(), 'heads/foo?bar'))) + self.assertTrue(check_ref_format(sanitize_ref_name_for_git(dict(), 'heads/foo.lock'))) + self.assertTrue(check_ref_format(sanitize_ref_name_for_git(dict(), 'heads/v@{ation'))) + self.assertTrue(check_ref_format(sanitize_ref_name_for_git(dict(), 'heads/foo\bar'))) + self.assertTrue(check_ref_format(sanitize_ref_name_for_git(dict(), 'heads/foo\\bar'))) + self.assertTrue(check_ref_format(sanitize_ref_name_for_git(dict(), 'heads/foo bar'))) + self.assertTrue(check_ref_format(sanitize_ref_name_for_git(dict(), 'heads/foo\020bar'))) + self.assertTrue(check_ref_format(sanitize_ref_name_for_git(dict(), 'heads/foo\177bar'))) -- cgit v1.2.1