test_objectspec.py 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. # test_objectspec.py -- tests for objectspec.py
  2. # Copyright (C) 2014 Jelmer Vernooij <jelmer@jelmer.uk>
  3. #
  4. # SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  5. # Dulwich is dual-licensed under the Apache License, Version 2.0 and the GNU
  6. # General Public License as public by the Free Software Foundation; version 2.0
  7. # or (at your option) any later version. You can redistribute it and/or
  8. # modify it under the terms of either of these two licenses.
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. #
  16. # You should have received a copy of the licenses; if not, see
  17. # <http://www.gnu.org/licenses/> for a copy of the GNU General Public License
  18. # and <http://www.apache.org/licenses/LICENSE-2.0> for a copy of the Apache
  19. # License, Version 2.0.
  20. #
  21. """Tests for revision spec parsing."""
  22. # TODO: Round-trip parse-serialize-parse and serialize-parse-serialize tests.
  23. from dulwich.objects import Blob
  24. from dulwich.objectspec import (
  25. parse_commit,
  26. parse_commit_range,
  27. parse_object,
  28. parse_ref,
  29. parse_refs,
  30. parse_reftuple,
  31. parse_reftuples,
  32. parse_tree,
  33. )
  34. from dulwich.repo import MemoryRepo
  35. from dulwich.tests.utils import build_commit_graph
  36. from . import TestCase
  37. class ParseObjectTests(TestCase):
  38. """Test parse_object."""
  39. def test_nonexistent(self) -> None:
  40. r = MemoryRepo()
  41. self.assertRaises(KeyError, parse_object, r, "thisdoesnotexist")
  42. def test_blob_by_sha(self) -> None:
  43. r = MemoryRepo()
  44. b = Blob.from_string(b"Blah")
  45. r.object_store.add_object(b)
  46. self.assertEqual(b, parse_object(r, b.id))
  47. class ParseCommitRangeTests(TestCase):
  48. """Test parse_commit_range."""
  49. def test_nonexistent(self) -> None:
  50. r = MemoryRepo()
  51. self.assertRaises(KeyError, parse_commit_range, r, "thisdoesnotexist")
  52. def test_commit_by_sha(self) -> None:
  53. r = MemoryRepo()
  54. c1, c2, c3 = build_commit_graph(r.object_store, [[1], [2, 1], [3, 1, 2]])
  55. self.assertEqual([c1], list(parse_commit_range(r, c1.id)))
  56. class ParseCommitTests(TestCase):
  57. """Test parse_commit."""
  58. def test_nonexistent(self) -> None:
  59. r = MemoryRepo()
  60. self.assertRaises(KeyError, parse_commit, r, "thisdoesnotexist")
  61. def test_commit_by_sha(self) -> None:
  62. r = MemoryRepo()
  63. [c1] = build_commit_graph(r.object_store, [[1]])
  64. self.assertEqual(c1, parse_commit(r, c1.id))
  65. def test_commit_by_short_sha(self) -> None:
  66. r = MemoryRepo()
  67. [c1] = build_commit_graph(r.object_store, [[1]])
  68. self.assertEqual(c1, parse_commit(r, c1.id[:10]))
  69. class ParseRefTests(TestCase):
  70. def test_nonexistent(self) -> None:
  71. r = {}
  72. self.assertRaises(KeyError, parse_ref, r, b"thisdoesnotexist")
  73. def test_ambiguous_ref(self) -> None:
  74. r = {
  75. b"ambig1": "bla",
  76. b"refs/ambig1": "bla",
  77. b"refs/tags/ambig1": "bla",
  78. b"refs/heads/ambig1": "bla",
  79. b"refs/remotes/ambig1": "bla",
  80. b"refs/remotes/ambig1/HEAD": "bla",
  81. }
  82. self.assertEqual(b"ambig1", parse_ref(r, b"ambig1"))
  83. def test_ambiguous_ref2(self) -> None:
  84. r = {
  85. b"refs/ambig2": "bla",
  86. b"refs/tags/ambig2": "bla",
  87. b"refs/heads/ambig2": "bla",
  88. b"refs/remotes/ambig2": "bla",
  89. b"refs/remotes/ambig2/HEAD": "bla",
  90. }
  91. self.assertEqual(b"refs/ambig2", parse_ref(r, b"ambig2"))
  92. def test_ambiguous_tag(self) -> None:
  93. r = {
  94. b"refs/tags/ambig3": "bla",
  95. b"refs/heads/ambig3": "bla",
  96. b"refs/remotes/ambig3": "bla",
  97. b"refs/remotes/ambig3/HEAD": "bla",
  98. }
  99. self.assertEqual(b"refs/tags/ambig3", parse_ref(r, b"ambig3"))
  100. def test_ambiguous_head(self) -> None:
  101. r = {
  102. b"refs/heads/ambig4": "bla",
  103. b"refs/remotes/ambig4": "bla",
  104. b"refs/remotes/ambig4/HEAD": "bla",
  105. }
  106. self.assertEqual(b"refs/heads/ambig4", parse_ref(r, b"ambig4"))
  107. def test_ambiguous_remote(self) -> None:
  108. r = {b"refs/remotes/ambig5": "bla", b"refs/remotes/ambig5/HEAD": "bla"}
  109. self.assertEqual(b"refs/remotes/ambig5", parse_ref(r, b"ambig5"))
  110. def test_ambiguous_remote_head(self) -> None:
  111. r = {b"refs/remotes/ambig6/HEAD": "bla"}
  112. self.assertEqual(b"refs/remotes/ambig6/HEAD", parse_ref(r, b"ambig6"))
  113. def test_heads_full(self) -> None:
  114. r = {b"refs/heads/foo": "bla"}
  115. self.assertEqual(b"refs/heads/foo", parse_ref(r, b"refs/heads/foo"))
  116. def test_heads_partial(self) -> None:
  117. r = {b"refs/heads/foo": "bla"}
  118. self.assertEqual(b"refs/heads/foo", parse_ref(r, b"heads/foo"))
  119. def test_tags_partial(self) -> None:
  120. r = {b"refs/tags/foo": "bla"}
  121. self.assertEqual(b"refs/tags/foo", parse_ref(r, b"tags/foo"))
  122. class ParseRefsTests(TestCase):
  123. def test_nonexistent(self) -> None:
  124. r = {}
  125. self.assertRaises(KeyError, parse_refs, r, [b"thisdoesnotexist"])
  126. def test_head(self) -> None:
  127. r = {b"refs/heads/foo": "bla"}
  128. self.assertEqual([b"refs/heads/foo"], parse_refs(r, [b"foo"]))
  129. def test_full(self) -> None:
  130. r = {b"refs/heads/foo": "bla"}
  131. self.assertEqual([b"refs/heads/foo"], parse_refs(r, b"refs/heads/foo"))
  132. class ParseReftupleTests(TestCase):
  133. def test_nonexistent(self) -> None:
  134. r = {}
  135. self.assertRaises(KeyError, parse_reftuple, r, r, b"thisdoesnotexist")
  136. def test_head(self) -> None:
  137. r = {b"refs/heads/foo": "bla"}
  138. self.assertEqual(
  139. (b"refs/heads/foo", b"refs/heads/foo", False),
  140. parse_reftuple(r, r, b"foo"),
  141. )
  142. self.assertEqual(
  143. (b"refs/heads/foo", b"refs/heads/foo", True),
  144. parse_reftuple(r, r, b"+foo"),
  145. )
  146. self.assertEqual(
  147. (b"refs/heads/foo", b"refs/heads/foo", True),
  148. parse_reftuple(r, {}, b"+foo"),
  149. )
  150. self.assertEqual(
  151. (b"refs/heads/foo", b"refs/heads/foo", True),
  152. parse_reftuple(r, {}, b"foo", True),
  153. )
  154. def test_full(self) -> None:
  155. r = {b"refs/heads/foo": "bla"}
  156. self.assertEqual(
  157. (b"refs/heads/foo", b"refs/heads/foo", False),
  158. parse_reftuple(r, r, b"refs/heads/foo"),
  159. )
  160. def test_no_left_ref(self) -> None:
  161. r = {b"refs/heads/foo": "bla"}
  162. self.assertEqual(
  163. (None, b"refs/heads/foo", False),
  164. parse_reftuple(r, r, b":refs/heads/foo"),
  165. )
  166. def test_no_right_ref(self) -> None:
  167. r = {b"refs/heads/foo": "bla"}
  168. self.assertEqual(
  169. (b"refs/heads/foo", None, False),
  170. parse_reftuple(r, r, b"refs/heads/foo:"),
  171. )
  172. def test_default_with_string(self) -> None:
  173. r = {b"refs/heads/foo": "bla"}
  174. self.assertEqual(
  175. (b"refs/heads/foo", b"refs/heads/foo", False),
  176. parse_reftuple(r, r, "foo"),
  177. )
  178. class ParseReftuplesTests(TestCase):
  179. def test_nonexistent(self) -> None:
  180. r = {}
  181. self.assertRaises(KeyError, parse_reftuples, r, r, [b"thisdoesnotexist"])
  182. def test_head(self) -> None:
  183. r = {b"refs/heads/foo": "bla"}
  184. self.assertEqual(
  185. [(b"refs/heads/foo", b"refs/heads/foo", False)],
  186. parse_reftuples(r, r, [b"foo"]),
  187. )
  188. def test_full(self) -> None:
  189. r = {b"refs/heads/foo": "bla"}
  190. self.assertEqual(
  191. [(b"refs/heads/foo", b"refs/heads/foo", False)],
  192. parse_reftuples(r, r, b"refs/heads/foo"),
  193. )
  194. r = {b"refs/heads/foo": "bla"}
  195. self.assertEqual(
  196. [(b"refs/heads/foo", b"refs/heads/foo", True)],
  197. parse_reftuples(r, r, b"refs/heads/foo", True),
  198. )
  199. class ParseTreeTests(TestCase):
  200. """Test parse_tree."""
  201. def test_nonexistent(self) -> None:
  202. r = MemoryRepo()
  203. self.assertRaises(KeyError, parse_tree, r, "thisdoesnotexist")
  204. def test_from_commit(self) -> None:
  205. r = MemoryRepo()
  206. c1, c2, c3 = build_commit_graph(r.object_store, [[1], [2, 1], [3, 1, 2]])
  207. self.assertEqual(r[c1.tree], parse_tree(r, c1.id))
  208. self.assertEqual(r[c1.tree], parse_tree(r, c1.tree))
  209. def test_from_ref(self) -> None:
  210. r = MemoryRepo()
  211. c1, c2, c3 = build_commit_graph(r.object_store, [[1], [2, 1], [3, 1, 2]])
  212. r.refs[b"refs/heads/foo"] = c1.id
  213. self.assertEqual(r[c1.tree], parse_tree(r, b"foo"))