Просмотр исходного кода

Add bitmap support to porcelain.repack() and CLI repack command

Jelmer Vernooij 2 месяцев назад
Родитель
Сommit
333f613641
4 измененных файлов с 52 добавлено и 3 удалено
  1. 7 2
      dulwich/cli.py
  2. 6 1
      dulwich/porcelain.py
  3. 16 0
      tests/test_cli.py
  4. 23 0
      tests/test_porcelain.py

+ 7 - 2
dulwich/cli.py

@@ -2834,8 +2834,13 @@ class cmd_repack(Command):
             args: Command line arguments
         """
         parser = argparse.ArgumentParser()
-        parser.parse_args(args)
-        porcelain.repack(".")
+        parser.add_argument(
+            "--write-bitmap-index",
+            action="store_true",
+            help="write a bitmap index for packs",
+        )
+        parsed_args = parser.parse_args(args)
+        porcelain.repack(".", write_bitmaps=parsed_args.write_bitmap_index)
 
 
 class cmd_reflog(Command):

+ 6 - 1
dulwich/porcelain.py

@@ -4840,16 +4840,21 @@ def ls_remote(
     )
 
 
-def repack(repo: RepoPath) -> None:
+def repack(repo: RepoPath, write_bitmaps: bool = False) -> None:
     """Repack loose files in a repository.
 
     Currently this only packs loose objects.
 
     Args:
       repo: Path to the repository
+      write_bitmaps: Whether to write bitmap indexes for packs
     """
     with open_repo_closing(repo) as r:
         r.object_store.pack_loose_objects()
+        if write_bitmaps:
+            # Update pack cache to pick up newly created packs
+            r.object_store._update_pack_cache()
+            r.object_store.generate_pack_bitmaps(r.refs.as_dict())
 
 
 def pack_objects(

+ 16 - 0
tests/test_cli.py

@@ -2550,6 +2550,22 @@ class RepackCommandTest(DulwichCliTestCase):
         pack_dir = os.path.join(self.repo_path, ".git", "objects", "pack")
         self.assertTrue(any(f.endswith(".pack") for f in os.listdir(pack_dir)))
 
+    def test_repack_write_bitmap_index(self):
+        """Test repack with --write-bitmap-index flag."""
+        # Create some objects
+        for i in range(5):
+            test_file = os.path.join(self.repo_path, f"test{i}.txt")
+            with open(test_file, "w") as f:
+                f.write(f"content {i}")
+            self._run_cli("add", f"test{i}.txt")
+            self._run_cli("commit", f"--message=Commit {i}")
+
+        _result, _stdout, _stderr = self._run_cli("repack", "--write-bitmap-index")
+        # Should create pack and bitmap files
+        pack_dir = os.path.join(self.repo_path, ".git", "objects", "pack")
+        self.assertTrue(any(f.endswith(".pack") for f in os.listdir(pack_dir)))
+        self.assertTrue(any(f.endswith(".bitmap") for f in os.listdir(pack_dir)))
+
 
 class ResetCommandTest(DulwichCliTestCase):
     """Tests for reset command."""

+ 23 - 0
tests/test_porcelain.py

@@ -7732,6 +7732,29 @@ class RepackTests(PorcelainTestCase):
         porcelain.add(repo=self.repo.path, paths=fullpath)
         porcelain.repack(self.repo)
 
+    def test_write_bitmaps(self) -> None:
+        """Test that write_bitmaps generates bitmap files."""
+        # Create some content
+        handle, fullpath = tempfile.mkstemp(dir=self.repo.path)
+        os.close(handle)
+        with open(fullpath, "w") as f:
+            f.write("test content")
+        porcelain.add(repo=self.repo.path, paths=fullpath)
+        porcelain.commit(
+            repo=self.repo.path,
+            message=b"test commit",
+            author=b"Test Author <test@example.com>",
+            committer=b"Test Committer <test@example.com>",
+        )
+
+        # Repack with bitmaps
+        porcelain.repack(self.repo, write_bitmaps=True)
+
+        # Check that bitmap files were created
+        pack_dir = os.path.join(self.repo.path, ".git", "objects", "pack")
+        bitmap_files = [f for f in os.listdir(pack_dir) if f.endswith(".bitmap")]
+        self.assertGreater(len(bitmap_files), 0)
+
 
 class LsTreeTests(PorcelainTestCase):
     def test_empty(self) -> None: