Phase 0: repository format with packs, dedup and incremental runs (spike B)

Content-addressed repository on an IBackend (local implementation):
4 MiB blobs, deflate when it helps, each blob encrypted with its id as
associated data, ~32 MiB packs with an encrypted header, one index file
per pack, snapshots as encrypted JSON lines written last.

Spike B: 390 MiB tree, peak 54 MiB; unchanged run reads nothing; a 1 MiB
change in a 300 MiB file uploads one blob; full and partial restore are
bit-identical; tampering is detected.
This commit is contained in:
2026-10-01 18:18:38 +02:00
parent fee189aec3
commit 4fce893389
8 changed files with 690 additions and 0 deletions
+30
View File
@@ -0,0 +1,30 @@
<?php
declare(strict_types=1);
// SPDX-FileCopyrightText: 2026 Dillard Blom
// SPDX-License-Identifier: AGPL-3.0-or-later
namespace OCA\NgBackup\Backend;
/**
* Minimal object store used by the repository. Paths are relative, '/'-separated.
* Implementations: a local directory (spike, tests), and adapters over files_external storages.
*/
interface IBackend {
/** Store an object; the stream is read to EOF. Must not leave a partial object behind on failure. */
public function put(string $path, $stream): void;
/** @return resource readable stream of the whole object */
public function get(string $path);
/** @return string bytes [$offset, $offset + $length) of the object (used to fetch single blobs from a pack) */
public function getRange(string $path, int $offset, int $length): string;
public function exists(string $path): bool;
/** @return list<string> object paths below $prefix (recursive) */
public function list(string $prefix): array;
public function delete(string $path): void;
}