浏览代码

Enhanced parsing of partial/ambiguous refs based on https://git-scm.com/docs/gitrevisions

Chris Bunney 9 年之前
父节点
当前提交
68cd0d2615
共有 2 个文件被更改,包括 56 次插入6 次删除
  1. 9 1
      dulwich/objectspec.py
  2. 47 5
      dulwich/tests/test_objectspec.py

+ 9 - 1
dulwich/objectspec.py

@@ -46,7 +46,15 @@ def parse_ref(container, refspec):
     :raise KeyError: If the ref can not be found
     """
     refspec = to_bytes(refspec)
-    for ref in [refspec, b"refs/heads/" + refspec]:
+    possible_refs = [
+        refspec,
+        b"refs/" + refspec,
+        b"refs/tags/" + refspec,
+        b"refs/heads/" + refspec,
+        b"refs/remotes/" + refspec,
+        b"refs/remotes/"+refspec+b"/HEAD"
+    ]
+    for ref in possible_refs:
         if ref in container:
             return ref
     else:

+ 47 - 5
dulwich/tests/test_objectspec.py

@@ -71,18 +71,60 @@ class ParseCommitRangeTests(TestCase):
 
 
 class ParseRefTests(TestCase):
-
     def test_nonexistent(self):
         r = {}
         self.assertRaises(KeyError, parse_ref, r, b"thisdoesnotexist")
 
-    def test_head(self):
+    def test_ambiguous_ref(self):
+        r = {b"ambig1": 'bla',
+             b"refs/ambig1": 'bla',
+             b"refs/tags/ambig1": 'bla',
+             b"refs/heads/ambig1": 'bla',
+             b"refs/remotes/ambig1": 'bla',
+             b"refs/remotes/ambig1/HEAD": "bla"}
+        self.assertEqual(b"ambig1", parse_ref(r, b"ambig1"))
+
+    def test_ambiguous_ref2(self):
+        r = {b"refs/ambig2": 'bla',
+             b"refs/tags/ambig2": 'bla',
+             b"refs/heads/ambig2": 'bla',
+             b"refs/remotes/ambig2": 'bla',
+             b"refs/remotes/ambig2/HEAD": "bla"}
+        self.assertEqual(b"refs/ambig2", parse_ref(r, b"ambig2"))
+
+    def test_ambiguous_tag(self):
+        r = {b"refs/tags/ambig3": 'bla',
+             b"refs/heads/ambig3": 'bla',
+             b"refs/remotes/ambig3": 'bla',
+             b"refs/remotes/ambig3/HEAD": "bla"}
+        self.assertEqual(b"refs/tags/ambig3", parse_ref(r, b"ambig3"))
+
+    def test_ambiguous_head(self):
+        r = {b"refs/heads/ambig4": 'bla',
+             b"refs/remotes/ambig4": 'bla',
+             b"refs/remotes/ambig4/HEAD": "bla"}
+        self.assertEqual(b"refs/heads/ambig4", parse_ref(r, b"ambig4"))
+
+    def test_ambiguous_remote(self):
+        r = {b"refs/remotes/ambig5": 'bla',
+             b"refs/remotes/ambig5/HEAD": "bla"}
+        self.assertEqual(b"refs/remotes/ambig5", parse_ref(r, b"ambig5"))
+
+    def test_ambiguous_remote_head(self):
+        r = {b"refs/remotes/ambig6/HEAD": "bla"}
+        self.assertEqual(b"refs/remotes/ambig6/HEAD", parse_ref(r, b"ambig6"))
+
+    def test_heads_full(self):
         r = {b"refs/heads/foo": "bla"}
-        self.assertEqual(b"refs/heads/foo", parse_ref(r, b"foo"))
+        self.assertEqual(b"refs/heads/foo", parse_ref(r, b"refs/heads/foo"))
 
-    def test_full(self):
+    def test_heads_partial(self):
         r = {b"refs/heads/foo": "bla"}
-        self.assertEqual(b"refs/heads/foo", parse_ref(r, b"refs/heads/foo"))
+        self.assertEqual(b"refs/heads/foo", parse_ref(r, b"heads/foo"))
+
+    def test_tags_partial(self):
+        r = {b"refs/tags/foo": "bla"}
+        self.assertEqual(b"refs/tags/foo", parse_ref(r, b"tags/foo"))
 
 
 class ParseRefsTests(TestCase):