test_patch.py 4.0 KB

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