test_patch.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. # test_patch.py -- test patch compatibility with CGit
  2. # Copyright (C) 2019 Boris Feld <boris@comet.ml>
  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. """Tests related to patch compatibility with CGit."""
  21. from io import BytesIO
  22. import os
  23. import shutil
  24. import tempfile
  25. from dulwich import porcelain
  26. from dulwich.repo import (
  27. Repo,
  28. )
  29. from dulwich.tests.compat.utils import (
  30. CompatTestCase,
  31. run_git_or_fail,
  32. )
  33. class CompatPatchTestCase(CompatTestCase):
  34. def setUp(self):
  35. super(CompatPatchTestCase, self).setUp()
  36. self.test_dir = tempfile.mkdtemp()
  37. self.addCleanup(shutil.rmtree, self.test_dir)
  38. self.repo_path = os.path.join(self.test_dir, 'repo')
  39. self.repo = Repo.init(self.repo_path, mkdir=True)
  40. self.addCleanup(self.repo.close)
  41. def test_patch_apply(self):
  42. # Prepare the repository
  43. # Create some files and commit them
  44. file_list = ["to_exists", "to_modify", "to_delete"]
  45. for file in file_list:
  46. file_path = os.path.join(self.repo_path, file)
  47. # Touch the files
  48. with open(file_path, "w"):
  49. pass
  50. self.repo.stage(file_list)
  51. first_commit = self.repo.do_commit(b"The first commit")
  52. # Make a copy of the repository so we can apply the diff later
  53. copy_path = os.path.join(self.test_dir, "copy")
  54. shutil.copytree(self.repo_path, copy_path)
  55. # Do some changes
  56. with open(os.path.join(self.repo_path, "to_modify"), "w") as f:
  57. f.write("Modified!")
  58. os.remove(os.path.join(self.repo_path, "to_delete"))
  59. with open(os.path.join(self.repo_path, "to_add"), "w"):
  60. pass
  61. self.repo.stage(["to_modify", "to_delete", "to_add"])
  62. second_commit = self.repo.do_commit(b"The second commit")
  63. # Get the patch
  64. first_tree = self.repo[first_commit].tree
  65. second_tree = self.repo[second_commit].tree
  66. outstream = BytesIO()
  67. porcelain.diff_tree(self.repo.path, first_tree, second_tree,
  68. outstream=outstream)
  69. # Save it on disk
  70. patch_path = os.path.join(self.test_dir, "patch.patch")
  71. with open(patch_path, "wb") as patch:
  72. patch.write(outstream.getvalue())
  73. # And try to apply it to the copy directory
  74. git_command = ["-C", copy_path, "apply", patch_path]
  75. run_git_or_fail(git_command)
  76. # And now check that the files contents are exactly the same between
  77. # the two repositories
  78. original_files = set(os.listdir(self.repo_path))
  79. new_files = set(os.listdir(copy_path))
  80. # Check that we have the exact same files in both repositories
  81. self.assertEqual(original_files, new_files)
  82. for file in original_files:
  83. if file == ".git":
  84. continue
  85. original_file_path = os.path.join(self.repo_path, file)
  86. copy_file_path = os.path.join(copy_path, file)
  87. self.assertTrue(os.path.isfile(copy_file_path))
  88. with open(original_file_path, "rb") as original_file:
  89. original_content = original_file.read()
  90. with open(copy_file_path, "rb") as copy_file:
  91. copy_content = copy_file.read()
  92. self.assertEqual(original_content, copy_content)