2
0

test_patch.py 4.1 KB

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