summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOleksandr Usov <oleksandr.usov@tibra.com>2011-10-12 11:24:29 +0100
committerOleksandr Usov <oleksandr.usov@tibra.com>2011-10-12 11:24:29 +0100
commit02fe09a21d1548b901fede6f90434c6455cc675b (patch)
treed3d9e6da6f9d7ab2364ada863a93f1301e35fc68
parent254ac63f937e378d5e516cfc1b9f82b35cc277c8 (diff)
downloadbzr-fastimport-02fe09a21d1548b901fede6f90434c6455cc675b.tar.gz
Add function to rewrite refnames & tests for it
-rw-r--r--exporter.py37
-rw-r--r--tests/test_exporter.py45
2 files changed, 81 insertions, 1 deletions
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')))