From a global code review of the borg2 codebase (2026-08). Companion to #10016.
Problem
Two modules have accreted far too many responsibilities:
src/borg/archive.py (~2500 lines) contains: Statistics, BackupIO/backup_io_iter, DownloadPipeline, ChunkBuffer/CacheChunkBuffer, Archive, MetadataCollector, ChunksProcessor, FilesystemObjectProcessors, TarfileObjectProcessors, RobustUnpacker, ArchiveChecker, and ArchiveRecreater. That is the read pipeline, the write pipeline, the archive entity, the checker, and the recreater in one file — nearly every change to any of them touches this module, and it is a magnet for circular imports (see #10016).
src/borg/repository.py (~1450 lines) contains both the Repository API and the entire pack subsystem: PackWriter, PackReader, PackTracker, check_pack_objects, superseded_gap_ranges, plus compact_pack/merge_packs/transform_pack. The pack format is a self-contained concern with its own invariants and tests.
Proposed direction
Mirror the successful borg.archiver split (one command per module):
borg/archive/ package: statistics.py, pipeline.py (DownloadPipeline/ChunkBuffer), archive.py (the entity), create.py (the processors + MetadataCollector), check.py, recreate.py.
borg/packs/ package for PackWriter/PackReader/PackTracker and the pack-level compact/merge/transform operations; repository.py keeps the Repository API and delegates.
Mechanical moves, no behavior change intended; 2.0 breaking internal API makes this cheap now and much more expensive later.
🤖 Generated with Claude Code
From a global code review of the borg2 codebase (2026-08). Companion to #10016.
Problem
Two modules have accreted far too many responsibilities:
src/borg/archive.py(~2500 lines) contains:Statistics,BackupIO/backup_io_iter,DownloadPipeline,ChunkBuffer/CacheChunkBuffer,Archive,MetadataCollector,ChunksProcessor,FilesystemObjectProcessors,TarfileObjectProcessors,RobustUnpacker,ArchiveChecker, andArchiveRecreater. That is the read pipeline, the write pipeline, the archive entity, the checker, and the recreater in one file — nearly every change to any of them touches this module, and it is a magnet for circular imports (see #10016).src/borg/repository.py(~1450 lines) contains both theRepositoryAPI and the entire pack subsystem:PackWriter,PackReader,PackTracker,check_pack_objects,superseded_gap_ranges, pluscompact_pack/merge_packs/transform_pack. The pack format is a self-contained concern with its own invariants and tests.Proposed direction
Mirror the successful
borg.archiversplit (one command per module):borg/archive/package:statistics.py,pipeline.py(DownloadPipeline/ChunkBuffer),archive.py(the entity),create.py(the processors + MetadataCollector),check.py,recreate.py.borg/packs/package for PackWriter/PackReader/PackTracker and the pack-level compact/merge/transform operations;repository.pykeeps the Repository API and delegates.Mechanical moves, no behavior change intended; 2.0 breaking internal API makes this cheap now and much more expensive later.
🤖 Generated with Claude Code