diff --git a/AGENTS.md b/AGENTS.md index b0c0ce2..baa784e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -19,7 +19,7 @@ PYTHONPATH=src python3 -m bd_archive ... ``` ```bash -bd-archive create -s -n -o [-w ] [-D /dev/srN] [-b BYTES] [-r %] [-c zstd|lzma|...] [-l ] [--ratio | --sample ] [-y] +bd-archive create -s -n -o [-w ] [-D /dev/srN] [-b BYTES] [-r %] [-c zstd|lzma|...] [-l ] [--ratio | --sample ] [--base ] [--min-last-disc-fill PERCENT] [-y] bd-archive burn -i [-D /dev/srN] [--start N] [--no-verify] [--skip-fit-check] [-S ] bd-archive verify [] bd-archive extract -o [-D /dev/srN] [-w ] @@ -47,11 +47,11 @@ src/bd_archive/ ├── __main__.py # entry point for `python -m bd_archive` ├── _par2_helper.py # dar -E hook: invoked as `python -m bd_archive._par2_helper ...` ├── cli.py # argparse + dispatch + top-level exception handling (uniform cancel/error output) -├── constants.py # MiB, DISC_OVERSIZE_TOLERANCE, PAR2_AND_MISC_OVERHEAD, DISC_END_MARGIN, POST_BURN_MOUNT_TIMEOUT, ISO9660_VOLUME_LABEL_MAX, PAR2_RECOVERY_RE +├── constants.py # MiB, DISC_OVERSIZE_TOLERANCE, PAR2_AND_MISC_OVERHEAD, DISC_END_MARGIN, POST_BURN_MOUNT_TIMEOUT, ISO9660_VOLUME_LABEL_MAX, ISO9660_LABEL_NAME_MAX, ISO9660_LABEL_SUFFIX_LEN, PAR2_RECOVERY_RE ├── ui/ # logger, prompts (interactive), progress (byte-counted, TTY-aware) ├── shell/ # runner.py: run() (+ SIGINT handling); deps.py: check_deps(); format.py: human_bytes() ├── tools/ # one thin wrapper per external CLI -│ ├── dar.py # dar create_sliced/isolate_catalog/compress/extract_sequential (Bad-CRC parser) +│ ├── dar.py # dar create_sliced (incl. -A ref, -P excludes, -E hook) / isolate_catalog / compress / extract_sequential (-wa overwrite for chain restore, Bad-CRC parser) / list_catalog_paths (`dar -l` parse) │ ├── par2.py # par2 create/verify/repair (+ VerifyResult, is_par2_index) │ ├── mkisofs.py # ISO9660+UDF image build (`-iso-level 3 -udf -V -publisher -input-charset utf-8 -graft-points`) │ ├── growisofs.py # burn (+ DeviceBusyError on sg lock, SIGINT double-press abort with BURN_ABORT_GRACE_S=5s) @@ -63,11 +63,11 @@ src/bd_archive/ │ └── lsof.py # find_device_holders (optional — no-op if lsof absent) ├── archive/ # domain logic over tools/ │ ├── checksums.py # sha512 verify (verify_slice per-file, used by extract on staging) -│ ├── config.py # ArchiveConfig, write_readme -│ ├── dar_archive.py # DarArchive (slices, catalog, work-dir layout) +│ ├── config.py # ArchiveConfig (incl. generation, dar_name), write_readme +│ ├── dar_archive.py # DarArchive (slices, catalog, work-dir layout) + parse_dar_filename (chain/gen detection from filename) │ ├── disc.py # DiscIO (mount/mount_with_retry/umount/eject/close_tray_if_open/burn) + find_sg_device │ ├── sizing.py # compute_slice_bytes, measure_compression_ratio -│ ├── source_scan.py # SourceScan + scan_source +│ ├── source_scan.py # SourceScan + scan_source; SourceFile + list_source_files (auto-defer pool); scan_delta_bytes (incremental preview) │ └── verify.py # verify_disc() └── commands/ # one file per subcommand ├── create.py @@ -82,10 +82,12 @@ Layering: `commands/` → `archive/` → `tools/` → `shell/`. Lower layers nev Four subcommands form a pipeline. `create` previews disc count + last-disc fill before prompting for confirmation, so users can dry-run sizing without committing. -1. **`create`** (`commands/create.py`) reads disc capacity via `tools.mediainfo.detect_disc_capacity` (or `args.bytes`), scans the source, and computes slice sizing plus a disc-count estimate (optionally measuring the compression ratio via `--sample`). The user confirms via `prompt_yn` before any heavy work begins (skip with `-y`). Then runs `tools.dar.create_sliced` with `--hash sha512 --min-digits 4 -Q` (plus `-z[:level] -am` when compression is enabled) to slice the source into per-disc-sized `.dar` files in `/tmp/`. par2 is generated **inline** via dar's `-E` hook (`bd_archive._par2_helper`) — the hook fires after each slice is fully written, so par2 reads the slice while it is still hot in the OS page cache, eliminating most SSD read traffic of the create phase. After dar completes, the catalog is isolated. For each slice in order: regenerate `README.txt` with the right disc number and call `tools.mkisofs.build` (mkisofs `-iso-level 3 -udf -V