test_fastexport.py 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. # test_fastexport.py -- Fast export/import functionality
  2. # Copyright (C) 2010 Jelmer Vernooij <jelmer@samba.org>
  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_import_stream(self):
  132. markers = self.processor.import_stream(BytesIO(b"""blob
  133. mark :1
  134. data 11
  135. text for a
  136. commit refs/heads/master
  137. mark :2
  138. committer Joe Foo <joe@foo.com> 1288287382 +0000
  139. data 20
  140. <The commit message>
  141. M 100644 :1 a
  142. """))
  143. self.assertEqual(2, len(markers))
  144. self.assertTrue(isinstance(self.repo[markers[b"1"]], Blob))
  145. self.assertTrue(isinstance(self.repo[markers[b"2"]], Commit))
  146. def test_file_add(self):
  147. from fastimport import commands
  148. cmd = commands.BlobCommand(b"23", b"data")
  149. self.processor.blob_handler(cmd)
  150. cmd = commands.CommitCommand(
  151. b"refs/heads/foo", b"mrkr",
  152. (b"Jelmer", b"jelmer@samba.org", 432432432.0, 3600),
  153. (b"Jelmer", b"jelmer@samba.org", 432432432.0, 3600),
  154. b"FOO", None, [],
  155. [commands.FileModifyCommand(b"path", 0o100644, b":23", None)])
  156. self.processor.commit_handler(cmd)
  157. commit = self.repo[self.processor.last_commit]
  158. self.assertEqual([
  159. (b'path', 0o100644, b'6320cd248dd8aeaab759d5871f8781b5c0505172')],
  160. self.repo[commit.tree].items())
  161. def simple_commit(self):
  162. from fastimport import commands
  163. cmd = commands.BlobCommand(b"23", b"data")
  164. self.processor.blob_handler(cmd)
  165. cmd = commands.CommitCommand(
  166. b"refs/heads/foo", b"mrkr",
  167. (b"Jelmer", b"jelmer@samba.org", 432432432.0, 3600),
  168. (b"Jelmer", b"jelmer@samba.org", 432432432.0, 3600),
  169. b"FOO", None, [],
  170. [commands.FileModifyCommand(b"path", 0o100644, b":23", None)])
  171. self.processor.commit_handler(cmd)
  172. commit = self.repo[self.processor.last_commit]
  173. return commit
  174. def make_file_commit(self, file_cmds):
  175. """Create a trivial commit with the specified file commands.
  176. :param file_cmds: File commands to run.
  177. :return: The created commit object
  178. """
  179. from fastimport import commands
  180. cmd = commands.CommitCommand(
  181. b"refs/heads/foo", b"mrkr",
  182. (b"Jelmer", b"jelmer@samba.org", 432432432.0, 3600),
  183. (b"Jelmer", b"jelmer@samba.org", 432432432.0, 3600),
  184. b"FOO", None, [], file_cmds)
  185. self.processor.commit_handler(cmd)
  186. return self.repo[self.processor.last_commit]
  187. def test_file_copy(self):
  188. from fastimport import commands
  189. self.simple_commit()
  190. commit = self.make_file_commit(
  191. [commands.FileCopyCommand(b"path", b"new_path")])
  192. self.assertEqual([
  193. (b'new_path', 0o100644,
  194. b'6320cd248dd8aeaab759d5871f8781b5c0505172'),
  195. (b'path', 0o100644,
  196. b'6320cd248dd8aeaab759d5871f8781b5c0505172'),
  197. ], self.repo[commit.tree].items())
  198. def test_file_move(self):
  199. from fastimport import commands
  200. self.simple_commit()
  201. commit = self.make_file_commit(
  202. [commands.FileRenameCommand(b"path", b"new_path")])
  203. self.assertEqual([
  204. (b'new_path', 0o100644,
  205. b'6320cd248dd8aeaab759d5871f8781b5c0505172'),
  206. ], self.repo[commit.tree].items())
  207. def test_file_delete(self):
  208. from fastimport import commands
  209. self.simple_commit()
  210. commit = self.make_file_commit([commands.FileDeleteCommand(b"path")])
  211. self.assertEqual([], self.repo[commit.tree].items())
  212. def test_file_deleteall(self):
  213. from fastimport import commands
  214. self.simple_commit()
  215. commit = self.make_file_commit([commands.FileDeleteAllCommand()])
  216. self.assertEqual([], self.repo[commit.tree].items())