Commit graph

3781 commits

Author SHA1 Message Date
TW
cf0968ac82
Apply suggested fix to src/borg/testsuite/archiver/extract_cmd_test.py from Copilot Autofix
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
2026-07-04 12:37:14 +02:00
TW
6529346861
Apply suggested fix to src/borg/testsuite/archiver/extract_cmd_test.py from Copilot Autofix
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
2026-07-04 12:37:13 +02:00
TW
14f96bc0b8
Apply suggested fix to src/borg/testsuite/archiver/extract_cmd_test.py from Copilot Autofix
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
2026-07-04 12:37:13 +02:00
TW
196625f7c4
Apply suggested fix to src/borg/testsuite/archiver/extract_cmd_test.py from Copilot Autofix
Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
2026-07-04 12:37:12 +02:00
Thomas Waldmann
5aaa2ddc4b
create: don't wrap repository writes in backup_io("read")
process_file() ran process_file_chunks() inside `with backup_io("read")`.

That block was meant to guard reading the *source* file, but the source
reads are already guarded individually by backup_io_iter(). The outer
wrapper additionally caught add_chunk()'s *repository* writes, so a critical
repository IO failure -- e.g. the repo running out of space during a pack
flush -- was wrapped into a per-file BackupOSError. Borg then only warned,
skipped the file, and continued, and create_inner() still committed the
archive via archive.save().

The result: `borg create` on an out-of-space repo printed a normal success
summary ("Error files: 0"), exited 0, and committed an archive that
references chunks which were never durably stored. `borg check` afterwards
reports "Missing file chunk detected" and `borg compact` reports "Repository
has N missing objects!" -- silent, unrestorable-backup data loss.

Drop the outer backup_io("read") wrapper. Source reads stay per-file
warnings (backup_io_iter is unchanged); repository OSErrors are now left
unwrapped and therefore critical, aborting create before archive.save()
runs, exactly as the BackupOSError docstring prescribes.

Reproduced on a space-limited macOS ramdisk (source > free space): before,
create exited 0 with a corrupt archive; after, create fails and commits
nothing, and the repository stays consistent across a create/delete/compact
churn matrix.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 19:48:35 +02:00
TW
98bf11363d
Merge pull request #9852 from mr-raj12/pack-defaults-compact-index-fix
size-bound 50 MB packs by default, fix stale chunk index after compact pack rewrites
2026-07-03 14:47:54 +02:00
Mrityunjay Raj
a8c2c7b1ec PackWriter: move pack size default to constants.py, keep it caller-set 2026-07-03 17:37:02 +05:30
TW
64d89c8d1b
Merge pull request #9851 from ThomasWaldmann/cache-close-resource-fixes
Release cache resources properly in Cache.close()
2026-07-03 14:04:18 +02:00
Mrityunjay Raj
1930c0cead compact: fix chunk index going stale when packs are rewritten, fixes #9850
compact_pack() updated repository.chunks, but compact computes keep/drop from
and persists its own index, which kept pointing at the deleted packs. Also:
tolerate deleting already-gone packs, start rebuilt index entries as unused.
2026-07-03 16:52:32 +05:30
Mrityunjay Raj
dd1bb247a4 PackWriter: size-bound packs of 50 MB by default, fixes #9843
max_count=3 was a testing value. The default is now max_count=None,
max_size=50_000_000; the testsuite sets BORG_PACK_MAX_COUNT=3 instead,
so small test data still produces multiple multi-object packs.
2026-07-03 16:52:07 +05:30
Mrityunjay Raj
09a1627860 repository/compact: use get_cache_dir subdirs arg, pathlib for store cache dir 2026-07-03 15:55:27 +05:30
Thomas Waldmann
a200591bb4
Release files cache dict in Cache.close()
close() persists the files cache but never drops its reference to
self._files, unlike self._chunks which is cleared right after being
saved. For a backup of many files this dict can hold hundreds of MB and
stays alive for as long as the closed cache object does.

Set self._files = None after writing it, mirroring the _chunks handling.
Accessing .files after close() was never supported anyway (close() also
tears down cache_config, which _read_files_cache needs), so this only
frees memory earlier.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 11:59:36 +02:00
Thomas Waldmann
9f5c6c5b73
Invalidate repository chunk index after clearing it in Cache.close()
AdHocWithFilesCache._chunks is the very same ChunkIndex object the
Repository holds (bound via the .chunks property). On close() we persist
it and clear the table in place (_maybe_write_chunks_cache(clear=True)),
then set self._chunks = None. But that only drops the *cache's* reference:
the Repository still points at the now-empty table and
is_chunk_index_loaded stays True.

A later access to repository.chunks in the same process (e.g.
delete_object doing self.chunks.get(id)) would then see a valid-looking
but empty index and conclude every chunk is gone, instead of rebuilding
from the repository. delete_chunkindex_from_repo() already guards its
analogous case with invalidate_chunk_index(); do the same here.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 11:59:07 +02:00
Mrityunjay Raj
db89931645 helpers/fs: let get_*_dir helpers take extra path components
get_config/cache/data/runtime_dir now accept *subdirs and ensure_dir the
full path. get_keys_dir and get_security_dir use this instead of
hand-joining "keys"/"security", and the store cache in repository.py uses
get_cache_dir("storecache") instead of its own makedirs.
2026-07-03 08:01:11 +05:30
TW
13d6d54a13
Merge pull request #9842 from wszqkzqk/allocation-granularity
testsuite: relax sparse file SEEK_DATA check
2026-07-02 21:11:23 +02:00
Zhou Qiankang
3969aeac0b
testsuite: relax sparse file SEEK_DATA check
On filesystems with large allocation units like tmpfs with hugepages,
SEEK_DATA can report an offset before the actual first non-zero byte.

The test already verifies file contents and checks st_blocks to confirm
the file is stored sparsely, so only require that the first data region
is not past the expected content.

Signed-off-by: Zhou Qiankang <wszqkzqk@qq.com>
2026-07-03 00:42:43 +08:00
TW
a14029755c
Merge pull request #9838 from mr-raj12/pack-files-pack-cache
Some checks are pending
Lint / lint (push) Waiting to run
CI / lint (push) Waiting to run
CI / security (push) Waiting to run
CI / asan_ubsan (push) Blocked by required conditions
CI / native_tests (push) Blocked by required conditions
CI / vm_tests (NetBSD, false, netbsd, 10.1) (push) Blocked by required conditions
CI / vm_tests (OmniOS, false, omnios, r151056) (push) Blocked by required conditions
CI / vm_tests (OpenBSD, false, openbsd, 7.8) (push) Blocked by required conditions
CI / vm_tests (borg-freebsd-14-x86_64-gh, FreeBSD, true, freebsd, 14.3) (push) Blocked by required conditions
CI / windows_tests (push) Blocked by required conditions
CodeQL / Analyze (push) Waiting to run
repository: env-gated writethrough cache for the packs/ namespace
2026-07-02 17:46:34 +02:00
Mrityunjay Raj
7cc2701cc0 repository: rename BORG_PACK_CACHE to BORG_STORE_CACHE and document the shared pack cache 2026-07-02 17:32:33 +05:30
Thomas Waldmann
831e47d4f1
buzhash64: update type stub for nc_level/normal_size
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-01 23:25:57 +02:00
Thomas Waldmann
0b7ec02b2f
chunkers: remove dead fill() error-return handling
fill() is declared 'except 0' and always returns 1: errors propagate as
exceptions, so the 'if not self.fill(): return None' branches were
unreachable (and process() returning None would have crashed __next__
anyway). Call fill() plainly instead.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-01 23:25:56 +02:00
Thomas Waldmann
f6b79761a2
ChunkerParams: better errors for wrong field counts, stricter compat mode
A wrong field count for a named algo (e.g. fastcdc,19,23,21 or
buzhash,19,23,21 with a forgotten field) used to fall through to the
old-style buzhash compat branch, which then crashed with a ValueError
from int('fastcdc') instead of raising a proper ArgumentTypeError.

- restrict the old-style compat branch to what it is for: four all-numeric
  fields without an algorithm name (19,23,21,4095 still works).
- for buzhash64 and fastcdc, a wrong field count now raises an
  ArgumentTypeError that spells out the expected format, which helps since
  buzhash64 recently gained nc_level and fastcdc has no window field.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-01 23:25:54 +02:00
Thomas Waldmann
3a9ffd4b9a
ChunkerParams: reject params that do not fit the chunker buffer
For buzhash64 and fastcdc, chunker params like chunk_min == chunk_max passed
CLI validation, but then failed with an AssertionError when the chunker was
constructed (buzhash64 needs window_size + 2^chunk_min + 1 <= 2^chunk_max,
fastcdc needs 2^chunk_min + 1 <= 2^chunk_max). Check this at parse time and
raise a proper ArgumentTypeError instead.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-01 23:24:27 +02:00
Thomas Waldmann
f2b96e3d15
fastcdc: add FastCDC chunker with a keyed Gear hash
Add a new "fastcdc" content-defined chunker selectable via --chunker-params.
It uses the FastCDC Gear rolling hash (fp = (fp << 1) + Gear[byte]), which is
window-less and cheaper per byte than buzhash's cyclic-polynomial update, so it
chunks noticeably faster (see "borg benchmark cpu" output), while producing
the same chunk-size distribution and deduplication.

The Gear table is keyed: it is derived from the repo id key via CSPRNG (own
"fastcdc" domain), exactly like the buzhash64 table, so chunk cut points stay
unpredictable without the key (anti-fingerprinting). It implements the same
FastCDC techniques as buzhash64 (sub-minimum skipping, normalized chunking with
a required nc_level, min/max clamping); the mask uses the high bits of the hash
(Gear accumulates entropy there).

chunker-params: "fastcdc,chunk_min,chunk_max,chunk_mask,nc_level" - there is no
window field, because Gear is window-less. e.g. fastcdc,19,23,21,2

Also: borg benchmark cpu now measures the fastcdc chunker; tests in
borg.testsuite.chunkers (golden vector, size distribution, keyed gear table,
param parsing, slow fuzz); docs and changelog.

Benchmarks (scripts/chunker_bench.py, buzhash64 vs fastcdc, both nc_level=2,
incompressible data unless noted):

  5 GiB, 2 MiB target (default params):
    buzhash64: CV 0.294, 1011 MB/s
    fastcdc:   CV 0.295, 1313 MB/s   (+30%)

  64 MiB, 64 KiB target:
    buzhash64: CV 0.374, shift-resilience 0.9928,  963 MB/s
    fastcdc:   CV 0.359, shift-resilience 0.9929, 1331 MB/s   (+38%)

  Re-backup of a 2.5 GiB file after scattered single-byte edits (dedup ratio,
  0.5 = v2 fully deduplicated, lower is better):
     64 edits:  buzhash64 0.5237, fastcdc 0.5236
    320 edits:  buzhash64 0.6133, fastcdc 0.6161

  borg benchmark cpu, 1 GB: fastcdc 3.80s, buzhash 4.36s, buzhash64 8.13s,
  fixed 0.56s.

Chunk-size distribution, deduplication and shift-resilience match buzhash64
within noise; fastcdc is consistently faster.

Also: fix bug when computing the mask, one needs to use 1ULL instead of
1, so the shifting computation is done in a uint64, not in a 32bit int.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-01 23:24:25 +02:00
Thomas Waldmann
dbadb32700
testsuite: drop remote coverage from more transport-agnostic archiver tests
lock_cmds, repo-create, repo-delete, repo-space and tar all only exercise
the generic store list/load/store/delete forwarding that every backend
implements identically:

- lock_cmds: Lock only does list/store/delete on locks/*, and its one
  host-specific check (process_alive across hosts) isn't exercised
  differently by this test infra regardless of "kind" anyway.
- repo-create/repo-delete: store.create()/destroy() are trivial 1:1 RPC
  forwards in the REST backend; still exercised over the wire incidentally
  via every remaining remote test file's setup (repo-create) and via
  checks_test.py (repo-delete), which stays on remote.
- repo-space: grepped borg's own code - it never calls store.quota() at
  all, only generic store_list/store/delete on config/space-reserve.*.
- tar cmds: do_export_tar/do_import_tar route through the same
  Archive/Repository.get()/put() machinery as extract/create, so this
  is redundant with their remote coverage (same category as recreate).

create, extract, check and transfer keep "remote" because they exercise
backends that genuinely branch per transport (partial reads/content-hash
upload headers, server-side hashing, two simultaneous store connections).
Rewrote the kinds-picking policy comment in generate_archiver_tests() to
state that rule directly instead of "moves real archive data".

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-01 19:51:10 +02:00
Thomas Waldmann
9dd9ab6587
testsuite: drop check_cmd's redundant remote coverage, add targeted one
check_cmd_test.py's remaining tests only exercise the generic store
list/load/delete calls also covered by other remote-tested files
(create, extract, ...), so drop remote from its kinds like #9324 did
elsewhere.

Repository.check() does have one transport-specific path though: the
REST backend computes pack hashes server-side (nothing downloaded),
unlike other backends. No existing test actually exercised a plain
--repository-only check catching a corrupted pack via that hash
comparison (existing corruption tests all go through --verify-data,
which decrypts client-side instead). Add that as its own local+remote
test.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-01 19:38:37 +02:00
Mrityunjay Raj
260e21a3c5 repository: add env-gated writethrough cache for the packs/ namespace
BORG_PACK_CACHE enables it; BORG_PACK_MAX_COUNT/SIZE override pack sizing.
2026-07-01 13:28:16 +05:30
Thomas Waldmann
2c26091a1d testsuite: don't run transport-agnostic archiver tests over rest:// (#9324)
The remote (rest://) archiver variant spawns a borgstore-server-rest
subprocess and does synchronous HTTP-over-stdio round trips per object,
so a remote test run costs several times its local twin (e.g.
test_prune_repository_example: ~2.8s local vs ~12.2s remote). Profiling
the suite showed every one of the 40 slowest tests was a remote_archiver
variant.

Most of those tests exercise pure command logic that operates on
metadata or only formats output (prune scheduling, diff/list/info
rendering, rename, delete/undelete, recreate, key handling, debug,
return codes, fuse mount) - this behaves identically regardless of
transport, and the data path over rest is already covered by the
create/extract/check/compact/repo/lock/transfer tests.

Switch those files to kinds="local,binary" and document the policy for
picking kinds in generate_archiver_tests().

Effect (local, -n auto, no coverage): remote_archiver invocations
374 -> 178; full suite 242s -> 154s (-36%), no test failures. The win
on the overloaded macOS CI runners (cold subprocess spawns + coverage)
should be relatively larger.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 23:44:22 +02:00
TW
8addc58416
Merge pull request #9823 from ThomasWaldmann/buzhash64-normalized-chunking
Some checks are pending
Lint / lint (push) Waiting to run
CI / lint (push) Waiting to run
CI / security (push) Waiting to run
CI / asan_ubsan (push) Blocked by required conditions
CI / native_tests (push) Blocked by required conditions
CI / vm_tests (NetBSD, false, netbsd, 10.1) (push) Blocked by required conditions
CI / vm_tests (OmniOS, false, omnios, r151056) (push) Blocked by required conditions
CI / vm_tests (OpenBSD, false, openbsd, 7.8) (push) Blocked by required conditions
CI / vm_tests (borg-freebsd-14-x86_64-gh, FreeBSD, true, freebsd, 14.3) (push) Blocked by required conditions
CI / windows_tests (push) Blocked by required conditions
CodeQL / Analyze (push) Waiting to run
buzhash64: add FastCDC-style normalized chunking
2026-06-30 11:58:42 +02:00
TW
52fdfc7596
Merge pull request #9828 from mr-raj12/chunkindex-pending-flag
Some checks are pending
Lint / lint (push) Waiting to run
CI / lint (push) Waiting to run
CI / security (push) Waiting to run
CI / asan_ubsan (push) Blocked by required conditions
CI / native_tests (push) Blocked by required conditions
CI / vm_tests (NetBSD, false, netbsd, 10.1) (push) Blocked by required conditions
CI / vm_tests (OmniOS, false, omnios, r151056) (push) Blocked by required conditions
CI / vm_tests (OpenBSD, false, openbsd, 7.8) (push) Blocked by required conditions
CI / vm_tests (borg-freebsd-14-x86_64-gh, FreeBSD, true, freebsd, 14.3) (push) Blocked by required conditions
CI / windows_tests (push) Blocked by required conditions
CodeQL / Analyze (push) Waiting to run
hashindex: track unresolved pack location with F_PENDING flag
2026-06-30 10:03:52 +02:00
Mrityunjay Raj
1206808449 hashindex: make F_PENDING a user flag, drop redundant pending check
F_PENDING moves to the user flag range so it is set/cleared via normal
assignment; flush()'s store-failure path no longer re-checks is_pending.
2026-06-30 08:44:02 +05:30
Mrityunjay Raj
46642da292 legacy: use borg 1.x keys dir for v1 repos
keyfile lookup always used the borg2 keys dir; on macOS that path differs
from borg 1.x, so v1 repo keyfiles were not found.
2026-06-30 08:23:11 +05:30
TW
b08dc6334f
Merge pull request #9822 from mr-raj12/legacy-fs-extraction
Some checks are pending
Lint / lint (push) Waiting to run
CI / lint (push) Waiting to run
CI / security (push) Waiting to run
CI / asan_ubsan (push) Blocked by required conditions
CI / native_tests (push) Blocked by required conditions
CI / vm_tests (NetBSD, false, netbsd, 10.1) (push) Blocked by required conditions
CI / vm_tests (OmniOS, false, omnios, r151056) (push) Blocked by required conditions
CI / vm_tests (OpenBSD, false, openbsd, 7.8) (push) Blocked by required conditions
CI / vm_tests (borg-freebsd-14-x86_64-gh, FreeBSD, true, freebsd, 14.3) (push) Blocked by required conditions
CI / windows_tests (push) Blocked by required conditions
CodeQL / Analyze (push) Waiting to run
legacy: split borg 1.x directory resolution into borg.legacy.fs
2026-06-29 20:21:37 +02:00
Mrityunjay Raj
f50fd4fa52 hashindex: add tests for F_PENDING branches in repository list/get/flush 2026-06-29 22:45:55 +05:30
TW
467d37e856
Merge pull request #9826 from mr-raj12/check-tests-corrupt-at-store-level
tests: corrupt chunks at store level in check tests
2026-06-29 18:21:54 +02:00
Mrityunjay Raj
3b3a647b27 tests: corrupt chunks at store level in check tests
test_manifest_rebuild_corrupted_chunk now corrupts the pack at the
store level and is skipped (TODO #8572) until repair rewrites
store-corrupted packs.
2026-06-29 07:15:27 +05:30
Mrityunjay Raj
061530d199 hashindex: track unresolved pack location with F_PENDING flag
Replace the UNKNOWN_BYTES32 pack_id sentinel (in-band signalling) with a
ChunkIndex system flag, queried via is_pending(). Follow-up to #9821.
2026-06-29 06:57:56 +05:30
Mrityunjay Raj
26d3a5d441 tests: corrupt manifest off-centre to fix flaky check --repair rebuild test on Windows 2026-06-29 00:39:00 +05:30
Thomas Waldmann
0e3876d5e4
buzhash64: add FastCDC-style normalized chunking
Normalized chunking switches between a stricter and a looser cut mask
around the target chunk size. This greatly tightens the chunk-size
distribution (coefficient of variation ~0.9 -> ~0.3 in tests) and removes
the dedup-hostile max-size-clamped chunks, with unchanged deduplication.

chunker-params for buzhash64 gains a required 6th field, nc_level:

  buzhash64,chunk_min,chunk_max,chunk_mask,window_size,nc_level

Use nc_level=2 for the new default, nc_level=0 to disable (then behavior
is byte-identical to the previous single-mask chunker).

buzhash (32bit) is untouched and stays bit-compatible with borg 1.x.

The mask transition point (normal_size) defaults to a principled formula
(target minus the expected loose-phase tail) so the mean stays near the
target; it can be tuned via the normal_size constructor arg.

scripts/chunker_bench.py: evidence harness used to measure chunk-size
distribution, dedup ratio, throughput and shift-resilience.

Measurements (before = nc_level 0, after = nc_level 2; both at the default
params buzhash64,19,23,21,4095; measured with scripts/chunker_bench.py):

5 GiB of incompressible data (~2000-2700 chunks, statistically stable):

  before:  CV 0.739,  49 max-size-clamped (8 MiB) chunks,   953 MB/s
  after:   CV 0.311,   0 max-size-clamped chunks,          1024 MB/s

Re-backup of a 2.5 GiB file after a few scattered single-byte edits
(deduplication ratio; 0.5 = v2 fully deduplicated against v1, lower is
better):

   64 edits:  before 0.5424  ->  after 0.5235
  320 edits:  before 0.6791  ->  after 0.6142

Normalized chunking deduplicates better after edits: removing the
max-size-clamped chunks means a single-byte change invalidates much less
data (about 36% less dedup overhead at 320 edits). Throughput was also
consistently higher with nc_level=2 at this scale.

Also: fix bug when computing the mask, one needs to use 1ULL instead of
1, so the shifting computation is done in a uint64, not in a 32bit int.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28 12:00:09 +02:00
TW
8e6d1788da
Merge pull request #9821 from mr-raj12/pack-files-max-size
Some checks are pending
Lint / lint (push) Waiting to run
CI / lint (push) Waiting to run
CI / security (push) Waiting to run
CI / asan_ubsan (push) Blocked by required conditions
CI / native_tests (push) Blocked by required conditions
CI / vm_tests (NetBSD, false, netbsd, 10.1) (push) Blocked by required conditions
CI / vm_tests (OmniOS, false, omnios, r151056) (push) Blocked by required conditions
CI / vm_tests (OpenBSD, false, openbsd, 7.8) (push) Blocked by required conditions
CI / vm_tests (borg-freebsd-14-x86_64-gh, FreeBSD, true, freebsd, 14.3) (push) Blocked by required conditions
CI / windows_tests (push) Blocked by required conditions
CodeQL / Analyze (push) Waiting to run
repository: add max_size byte limit to PackWriter, OR-ed with max_count
2026-06-28 01:17:51 +02:00
Mrityunjay Raj
2dcb50f30e repository: assert compact_pack complete coverage reaches pack end 2026-06-28 03:46:35 +05:30
Mrityunjay Raj
0e2025885c repository: update PackWriter comments 2026-06-28 03:34:45 +05:30
Mrityunjay Raj
2a4671c1ab tests: extract corrupt_chunk_on_disk helper into repository_test.py 2026-06-28 01:43:01 +05:30
Mrityunjay Raj
e06ce2c64b repository: allow max_count=None and tighten PackWriter comments per review 2026-06-28 00:45:31 +05:30
Mrityunjay Raj
f295b3e77a repository: simplify delete/compact_pack docstrings and comments
Rename delete's persist kwarg to update_index; corrupt pack bytes on disk
in test_verify_data instead of via delete/put.
2026-06-28 00:07:38 +05:30
Mrityunjay Raj
1ebdf865fe legacy: move borg 1.x directory resolution into borg.legacy.fs
helpers.fs keeps only the borg2 layout; the v1 home/config/cache/keys/security
dir logic now lives in legacy.fs. Part of #9556.
2026-06-27 11:53:34 +05:30
Mrityunjay Raj
4fe7e0ea16 repository: fix Repository.delete edge cases (#9815)
Tolerate a stale earlier object in the pack via a compact_pack complete flag, skip the per-delete index write in check --repair via a delete persist flag, and make verify_data report the files whose chunks it removes. Add a regression test for the stale-earlier-object case.
2026-06-27 10:54:57 +05:30
Mrityunjay Raj
2206c3468f repository: add max_size byte limit to PackWriter, OR-ed with max_count
max_size=None (default) keeps count-only behaviour. Also bump default
max_count 1->3 and flush test_list's last partial pack explicitly.
2026-06-27 10:02:02 +05:30
Mrityunjay Raj
106dfbadae tests: drop the delete_chunk wrapper, call Repository.delete directly
Inline repository.delete at the check/extract/mount call sites. Drop the borgstore HEAD note from compact_pack now that it is fixed upstream.
2026-06-26 23:24:57 +05:30
Mrityunjay Raj
e74d7ef9a0 repository: make Repository.delete a real single-object delete
Rewrite the object's pack via compact_pack and persist a full chunk index. Wire debug delete-obj and the delete_chunk test helper to it, and drop the store.info HEAD coverage check from compact_pack.
2026-06-26 09:51:57 +05:30
Mrityunjay Raj
5747a19cf8 tests: delete_chunk drops a single object via compact_pack, not the whole pack
Rewrite the damage helper to rewrite the pack without the target chunk (neighbours survive) and persist the index, then revive three check tests that were skipped because the old whole-pack drop left an inconsistent index.
2026-06-26 04:05:32 +05:30