# test_sha256_pack.py -- Tests for SHA256 pack support # Copyright (C) 2024 The Dulwich contributors # # SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later # Dulwich is dual-licensed under the Apache License, Version 2.0 and the GNU # General Public License as public by the Free Software Foundation; version 2.0 # or (at your option) any later version. You can redistribute it and/or # modify it under the terms of either of these two licenses. # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # You should have received a copy of the licenses; if not, see # for a copy of the GNU General Public License # and for a copy of the Apache # License, Version 2.0. # """Tests for SHA256 pack support in Dulwich.""" import shutil import tempfile import unittest from io import BytesIO from dulwich.object_format import SHA256 from dulwich.pack import ( load_pack_index_file, write_pack_index_v2, ) class SHA256PackTests(unittest.TestCase): """Tests for SHA256 pack support.""" def setUp(self): """Set up test repository directory.""" self.test_dir = tempfile.mkdtemp() def tearDown(self): """Clean up test repository.""" shutil.rmtree(self.test_dir) def test_pack_index_v2_with_sha256(self): """Test that pack index v2 correctly handles SHA256 hashes.""" # Create SHA256 entries manually (simulating what would happen in a SHA256 repo) entries = [] for i in range(5): # Create a fake SHA256 hash sha256_hash = SHA256.hash_func(f"test object {i}".encode()).digest() offset = i * 1000 # Fake offsets crc32 = i # Fake CRC32 entries.append((sha256_hash, offset, crc32)) # Sort entries by SHA (required for pack index) entries.sort(key=lambda e: e[0]) # Write SHA256 pack index with SHA1 pack checksum (Git always uses SHA1 for pack checksums) index_buf = BytesIO() from hashlib import sha1 pack_checksum = sha1(b"fake pack data").digest() write_pack_index_v2(index_buf, entries, pack_checksum) # Load and verify the index index_buf.seek(0) pack_idx = load_pack_index_file("", index_buf, SHA256) # Check that the index loaded correctly self.assertEqual(len(pack_idx), 5) self.assertEqual(pack_idx.version, 2) # Verify hash_size detection self.assertEqual(pack_idx.hash_size, 32) # Verify we can look up objects by SHA256 for sha256_hash, offset, _ in entries: # This should not raise KeyError found_offset = pack_idx.object_offset(sha256_hash) self.assertEqual(found_offset, offset) def test_pack_index_v1_with_sha256(self): """Test that pack index v1 correctly rejects SHA256 hashes.""" # Create SHA256 entries manually entries = [] for i in range(5): # Create a fake SHA256 hash sha256_hash = SHA256.hash_func(f"test v1 object {i}".encode()).digest() offset = i * 1000 # Fake offsets crc32 = None # v1 doesn't store CRC32 entries.append((sha256_hash, offset, crc32)) # Sort entries by SHA (required for pack index) entries.sort(key=lambda e: e[0]) # Import write_pack_index_v1 from dulwich.pack import write_pack_index_v1 # Write SHA256 pack index v1 with SHA1 pack checksum index_buf = BytesIO() from hashlib import sha1 pack_checksum = sha1(b"fake v1 pack data").digest() # Pack index v1 only supports SHA-1, so this should raise TypeError with self.assertRaises(TypeError) as cm: write_pack_index_v1(index_buf, entries, pack_checksum) self.assertIn("pack index v1 only supports SHA-1", str(cm.exception)) if __name__ == "__main__": unittest.main()