test_fastexport.py 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. # test_fastexport.py -- Fast export/import functionality
  2. # Copyright (C) 2010 Jelmer Vernooij <jelmer@jelmer.uk>
  3. #
  4. # Dulwich is dual-licensed under the Apache License, Version 2.0 and the GNU
  5. # General Public License as public by the Free Software Foundation; version 2.0
  6. # or (at your option) any later version. You can redistribute it and/or
  7. # modify it under the terms of either of these two licenses.
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. #
  15. # You should have received a copy of the licenses; if not, see
  16. # <http://www.gnu.org/licenses/> for a copy of the GNU General Public License
  17. # and <http://www.apache.org/licenses/LICENSE-2.0> for a copy of the Apache
  18. # License, Version 2.0.
  19. #
  20. from io import BytesIO
  21. import stat
  22. from dulwich.object_store import (
  23. MemoryObjectStore,
  24. )
  25. from dulwich.objects import (
  26. Blob,
  27. Commit,
  28. Tree,
  29. ZERO_SHA,
  30. )
  31. from dulwich.repo import (
  32. MemoryRepo,
  33. )
  34. from dulwich.tests import (
  35. SkipTest,
  36. TestCase,
  37. )
  38. from dulwich.tests.utils import (
  39. build_commit_graph,
  40. )
  41. class GitFastExporterTests(TestCase):
  42. """Tests for the GitFastExporter tests."""
  43. def setUp(self):
  44. super(GitFastExporterTests, self).setUp()
  45. self.store = MemoryObjectStore()
  46. self.stream = BytesIO()
  47. try:
  48. from dulwich.fastexport import GitFastExporter
  49. except ImportError:
  50. raise SkipTest("python-fastimport not available")
  51. self.fastexporter = GitFastExporter(self.stream, self.store)
  52. def test_emit_blob(self):
  53. b = Blob()
  54. b.data = b"fooBAR"
  55. self.fastexporter.emit_blob(b)
  56. self.assertEqual(b'blob\nmark :1\ndata 6\nfooBAR\n',
  57. self.stream.getvalue())
  58. def test_emit_commit(self):
  59. b = Blob()
  60. b.data = b"FOO"
  61. t = Tree()
  62. t.add(b"foo", stat.S_IFREG | 0o644, b.id)
  63. c = Commit()
  64. c.committer = c.author = b"Jelmer <jelmer@host>"
  65. c.author_time = c.commit_time = 1271345553
  66. c.author_timezone = c.commit_timezone = 0
  67. c.message = b"msg"
  68. c.tree = t.id
  69. self.store.add_objects([(b, None), (t, None), (c, None)])
  70. self.fastexporter.emit_commit(c, b"refs/heads/master")
  71. self.assertEqual(b"""blob
  72. mark :1
  73. data 3
  74. FOO
  75. commit refs/heads/master
  76. mark :2
  77. author Jelmer <jelmer@host> 1271345553 +0000
  78. committer Jelmer <jelmer@host> 1271345553 +0000
  79. data 3
  80. msg
  81. M 644 :1 foo
  82. """, self.stream.getvalue())
  83. class GitImportProcessorTests(TestCase):
  84. """Tests for the GitImportProcessor tests."""
  85. def setUp(self):
  86. super(GitImportProcessorTests, self).setUp()
  87. self.repo = MemoryRepo()
  88. try:
  89. from dulwich.fastexport import GitImportProcessor
  90. except ImportError:
  91. raise SkipTest("python-fastimport not available")
  92. self.processor = GitImportProcessor(self.repo)
  93. def test_reset_handler(self):
  94. from fastimport import commands
  95. [c1] = build_commit_graph(self.repo.object_store, [[1]])
  96. cmd = commands.ResetCommand(b"refs/heads/foo", c1.id)
  97. self.processor.reset_handler(cmd)
  98. self.assertEqual(c1.id, self.repo.get_refs()[b"refs/heads/foo"])
  99. self.assertEqual(c1.id, self.processor.last_commit)
  100. def test_reset_handler_marker(self):
  101. from fastimport import commands
  102. [c1, c2] = build_commit_graph(self.repo.object_store, [[1], [2]])
  103. self.processor.markers[b'10'] = c1.id
  104. cmd = commands.ResetCommand(b"refs/heads/foo", b':10')
  105. self.processor.reset_handler(cmd)
  106. self.assertEqual(c1.id, self.repo.get_refs()[b"refs/heads/foo"])
  107. def test_reset_handler_default(self):
  108. from fastimport import commands
  109. [c1, c2] = build_commit_graph(self.repo.object_store, [[1], [2]])
  110. cmd = commands.ResetCommand(b"refs/heads/foo", None)
  111. self.processor.reset_handler(cmd)
  112. self.assertEqual(ZERO_SHA, self.repo.get_refs()[b"refs/heads/foo"])
  113. def test_commit_handler(self):
  114. from fastimport import commands
  115. cmd = commands.CommitCommand(
  116. b"refs/heads/foo", b"mrkr",
  117. (b"Jelmer", b"jelmer@samba.org", 432432432.0, 3600),
  118. (b"Jelmer", b"jelmer@samba.org", 432432432.0, 3600),
  119. b"FOO", None, [], [])
  120. self.processor.commit_handler(cmd)
  121. commit = self.repo[self.processor.last_commit]
  122. self.assertEqual(b"Jelmer <jelmer@samba.org>", commit.author)
  123. self.assertEqual(b"Jelmer <jelmer@samba.org>", commit.committer)
  124. self.assertEqual(b"FOO", commit.message)
  125. self.assertEqual([], commit.parents)
  126. self.assertEqual(432432432.0, commit.commit_time)
  127. self.assertEqual(432432432.0, commit.author_time)
  128. self.assertEqual(3600, commit.commit_timezone)
  129. self.assertEqual(3600, commit.author_timezone)
  130. self.assertEqual(commit, self.repo[b"refs/heads/foo"])
  131. def test_commit_handler_markers(self):
  132. from fastimport import commands
  133. [c1, c2, c3] = build_commit_graph(self.repo.object_store,
  134. [[1], [2], [3]])
  135. self.processor.markers[b'10'] = c1.id
  136. self.processor.markers[b'42'] = c2.id
  137. self.processor.markers[b'98'] = c3.id
  138. cmd = commands.CommitCommand(
  139. b"refs/heads/foo", b"mrkr",
  140. (b"Jelmer", b"jelmer@samba.org", 432432432.0, 3600),
  141. (b"Jelmer", b"jelmer@samba.org", 432432432.0, 3600),
  142. b"FOO", b':10', [b':42', b':98'], [])
  143. self.processor.commit_handler(cmd)
  144. commit = self.repo[self.processor.last_commit]
  145. self.assertEqual(c1.id, commit.parents[0])
  146. self.assertEqual(c2.id, commit.parents[1])
  147. self.assertEqual(c3.id, commit.parents[2])
  148. def test_import_stream(self):
  149. markers = self.processor.import_stream(BytesIO(b"""blob
  150. mark :1
  151. data 11
  152. text for a
  153. commit refs/heads/master
  154. mark :2
  155. committer Joe Foo <joe@foo.com> 1288287382 +0000
  156. data 20
  157. <The commit message>
  158. M 100644 :1 a
  159. """))
  160. self.assertEqual(2, len(markers))
  161. self.assertTrue(isinstance(self.repo[markers[b"1"]], Blob))
  162. self.assertTrue(isinstance(self.repo[markers[b"2"]], Commit))
  163. def test_file_add(self):
  164. from fastimport import commands
  165. cmd = commands.BlobCommand(b"23", b"data")
  166. self.processor.blob_handler(cmd)
  167. cmd = commands.CommitCommand(
  168. b"refs/heads/foo", b"mrkr",
  169. (b"Jelmer", b"jelmer@samba.org", 432432432.0, 3600),
  170. (b"Jelmer", b"jelmer@samba.org", 432432432.0, 3600),
  171. b"FOO", None, [],
  172. [commands.FileModifyCommand(b"path", 0o100644, b":23", None)])
  173. self.processor.commit_handler(cmd)
  174. commit = self.repo[self.processor.last_commit]
  175. self.assertEqual([
  176. (b'path', 0o100644, b'6320cd248dd8aeaab759d5871f8781b5c0505172')],
  177. self.repo[commit.tree].items())
  178. def simple_commit(self):
  179. from fastimport import commands
  180. cmd = commands.BlobCommand(b"23", b"data")
  181. self.processor.blob_handler(cmd)
  182. cmd = commands.CommitCommand(
  183. b"refs/heads/foo", b"mrkr",
  184. (b"Jelmer", b"jelmer@samba.org", 432432432.0, 3600),
  185. (b"Jelmer", b"jelmer@samba.org", 432432432.0, 3600),
  186. b"FOO", None, [],
  187. [commands.FileModifyCommand(b"path", 0o100644, b":23", None)])
  188. self.processor.commit_handler(cmd)
  189. commit = self.repo[self.processor.last_commit]
  190. return commit
  191. def make_file_commit(self, file_cmds):
  192. """Create a trivial commit with the specified file commands.
  193. :param file_cmds: File commands to run.
  194. :return: The created commit object
  195. """
  196. from fastimport import commands
  197. cmd = commands.CommitCommand(
  198. b"refs/heads/foo", b"mrkr",
  199. (b"Jelmer", b"jelmer@samba.org", 432432432.0, 3600),
  200. (b"Jelmer", b"jelmer@samba.org", 432432432.0, 3600),
  201. b"FOO", None, [], file_cmds)
  202. self.processor.commit_handler(cmd)
  203. return self.repo[self.processor.last_commit]
  204. def test_file_copy(self):
  205. from fastimport import commands
  206. self.simple_commit()
  207. commit = self.make_file_commit(
  208. [commands.FileCopyCommand(b"path", b"new_path")])
  209. self.assertEqual([
  210. (b'new_path', 0o100644,
  211. b'6320cd248dd8aeaab759d5871f8781b5c0505172'),
  212. (b'path', 0o100644,
  213. b'6320cd248dd8aeaab759d5871f8781b5c0505172'),
  214. ], self.repo[commit.tree].items())
  215. def test_file_move(self):
  216. from fastimport import commands
  217. self.simple_commit()
  218. commit = self.make_file_commit(
  219. [commands.FileRenameCommand(b"path", b"new_path")])
  220. self.assertEqual([
  221. (b'new_path', 0o100644,
  222. b'6320cd248dd8aeaab759d5871f8781b5c0505172'),
  223. ], self.repo[commit.tree].items())
  224. def test_file_delete(self):
  225. from fastimport import commands
  226. self.simple_commit()
  227. commit = self.make_file_commit([commands.FileDeleteCommand(b"path")])
  228. self.assertEqual([], self.repo[commit.tree].items())
  229. def test_file_deleteall(self):
  230. from fastimport import commands
  231. self.simple_commit()
  232. commit = self.make_file_commit([commands.FileDeleteAllCommand()])
  233. self.assertEqual([], self.repo[commit.tree].items())