feat(rust-core): add zstd chunk compression support and rewrite partially referenced packs during prune

This commit is contained in:
2026-03-22 08:47:16 +00:00
parent 0bbe462153
commit 5672ea29ff
14 changed files with 734 additions and 23 deletions

View File

@@ -6,10 +6,11 @@ import { ContainerArchive } from '../ts/index.js';
const testRepoPath = path.resolve('.nogit/test-repo');
const testRepoEncryptedPath = path.resolve('.nogit/test-repo-encrypted');
const testRepoZstdPath = path.resolve('.nogit/test-repo-zstd');
// Clean up test directories before tests
tap.preTask('cleanup test directories', async () => {
for (const p of [testRepoPath, testRepoEncryptedPath]) {
for (const p of [testRepoPath, testRepoEncryptedPath, testRepoZstdPath]) {
if (fs.existsSync(p)) {
fs.rmSync(p, { recursive: true });
}
@@ -250,4 +251,50 @@ tap.test('should open encrypted repository with correct passphrase', async () =>
await encRepo.close();
});
// ==================== Zstd Compression ====================
tap.test('should work with zstd compression', async () => {
// Init repo — the config.json will have compression: "gzip" by default.
// To test zstd, we manually update the config after init.
const zstdRepo = await ContainerArchive.init(testRepoZstdPath);
await zstdRepo.close();
// Patch config.json to use zstd
const configPath = path.join(testRepoZstdPath, 'config.json');
const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
config.compression = 'zstd';
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
// Reopen with zstd config
const repo2 = await ContainerArchive.open(testRepoZstdPath);
// Ingest
const testData = Buffer.alloc(256 * 1024, 'zstd-compressed-data');
const snapshot = await repo2.ingest(stream.Readable.from(testData), {
tags: { compression: 'zstd' },
items: [{ name: 'zstd-data.bin' }],
});
expect(snapshot.newChunks).toBeGreaterThan(0);
// Restore and verify
const restoreStream = await repo2.restore(snapshot.id);
const chunks: Buffer[] = [];
await new Promise<void>((resolve, reject) => {
restoreStream.on('data', (chunk: Buffer) => chunks.push(chunk));
restoreStream.on('end', resolve);
restoreStream.on('error', reject);
});
const restored = Buffer.concat(chunks);
expect(restored.length).toEqual(testData.length);
expect(restored.equals(testData)).toBeTrue();
// Verify
const verifyResult = await repo2.verify({ level: 'full' });
expect(verifyResult.ok).toBeTrue();
await repo2.close();
});
export default tap.start();