test_maintenance.py 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. # test_maintenance.py -- tests for porcelain maintenance
  2. # Copyright (C) 2024 Jelmer Vernooij <jelmer@jelmer.uk>
  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 published 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 for porcelain maintenance functions."""
  22. import tempfile
  23. from dulwich import porcelain
  24. from dulwich.objects import Blob
  25. from dulwich.repo import Repo
  26. from .. import TestCase
  27. class PorcelainMaintenanceTestCase(TestCase):
  28. """Base class for porcelain maintenance tests."""
  29. def setUp(self):
  30. super().setUp()
  31. self.test_dir = tempfile.mkdtemp()
  32. self.addCleanup(self._cleanup_test_dir)
  33. self.repo = Repo.init(self.test_dir)
  34. self.addCleanup(self.repo.close)
  35. def _cleanup_test_dir(self):
  36. import shutil
  37. shutil.rmtree(self.test_dir)
  38. def _create_commit(self):
  39. """Helper to create a test commit."""
  40. blob = Blob.from_string(b"test content\n")
  41. self.repo.object_store.add_object(blob)
  42. from dulwich.objects import Commit, Tree
  43. tree = Tree()
  44. tree.add(b"testfile", 0o100644, blob.id)
  45. self.repo.object_store.add_object(tree)
  46. commit = Commit()
  47. commit.tree = tree.id
  48. commit.author = commit.committer = b"Test <test@example.com>"
  49. commit.author_time = commit.commit_time = 1000000000
  50. commit.author_timezone = commit.commit_timezone = 0
  51. commit.encoding = b"UTF-8"
  52. commit.message = b"Test commit"
  53. commit.parents = []
  54. self.repo.object_store.add_object(commit)
  55. self.repo.refs[b"refs/heads/master"] = commit.id
  56. return commit.id
  57. class PorcelainMaintenanceTest(PorcelainMaintenanceTestCase):
  58. """Tests for porcelain.maintenance_run function."""
  59. def test_maintenance_run(self):
  60. """Test porcelain maintenance_run function."""
  61. self._create_commit()
  62. result = porcelain.maintenance_run(self.test_dir)
  63. self.assertIn("gc", result.tasks_succeeded)
  64. self.assertIn("commit-graph", result.tasks_succeeded)
  65. def test_maintenance_run_with_tasks(self):
  66. """Test porcelain maintenance_run with specific tasks."""
  67. result = porcelain.maintenance_run(self.test_dir, tasks=["pack-refs"])
  68. self.assertEqual(result.tasks_run, ["pack-refs"])
  69. self.assertEqual(result.tasks_succeeded, ["pack-refs"])
  70. class MaintenanceRegisterTest(PorcelainMaintenanceTestCase):
  71. """Tests for maintenance register/unregister."""
  72. def setUp(self):
  73. super().setUp()
  74. # Set up a temporary HOME for testing global config
  75. self.temp_home = tempfile.mkdtemp()
  76. self.addCleanup(self._cleanup_temp_home)
  77. self.overrideEnv("HOME", self.temp_home)
  78. def _cleanup_temp_home(self):
  79. import shutil
  80. shutil.rmtree(self.temp_home)
  81. def test_register_repository(self):
  82. """Test registering a repository for maintenance."""
  83. porcelain.maintenance_register(self.test_dir)
  84. # Verify repository was added to global config
  85. import os
  86. from dulwich.config import ConfigFile
  87. global_config_path = os.path.expanduser("~/.gitconfig")
  88. global_config = ConfigFile.from_path(global_config_path)
  89. repos = list(global_config.get_multivar((b"maintenance",), b"repo"))
  90. self.assertIn(self.test_dir.encode(), repos)
  91. # Verify strategy was set
  92. strategy = global_config.get((b"maintenance",), b"strategy")
  93. self.assertEqual(strategy, b"incremental")
  94. # Verify auto maintenance was disabled in repo
  95. repo_config = self.repo.get_config()
  96. auto = repo_config.get_boolean((b"maintenance",), b"auto")
  97. self.assertFalse(auto)
  98. def test_register_already_registered(self):
  99. """Test registering an already registered repository."""
  100. porcelain.maintenance_register(self.test_dir)
  101. # Should not error when registering again
  102. porcelain.maintenance_register(self.test_dir)
  103. def test_unregister_repository(self):
  104. """Test unregistering a repository."""
  105. # First register
  106. porcelain.maintenance_register(self.test_dir)
  107. # Then unregister
  108. porcelain.maintenance_unregister(self.test_dir)
  109. # Verify repository was removed from global config
  110. import os
  111. from dulwich.config import ConfigFile
  112. global_config_path = os.path.expanduser("~/.gitconfig")
  113. global_config = ConfigFile.from_path(global_config_path)
  114. try:
  115. repos = list(global_config.get_multivar((b"maintenance",), b"repo"))
  116. self.assertNotIn(self.test_dir.encode(), repos)
  117. except KeyError:
  118. # No repos registered, which is fine
  119. pass
  120. def test_unregister_not_registered(self):
  121. """Test unregistering a repository that is not registered."""
  122. with self.assertRaises(ValueError):
  123. porcelain.maintenance_unregister(self.test_dir)
  124. def test_unregister_not_registered_force(self):
  125. """Test unregistering with force flag."""
  126. # Should not error with force=True
  127. porcelain.maintenance_unregister(self.test_dir, force=True)