#10017·borg

split the god modules: archive.py (12 classes) and the pack machinery inside repository.py

Author: ThomasWaldmannCreated Aug 2, 2026Updated Sep 11, 2026

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