Skip to content

Phase 1: journaled rollback with staged trash - #15

Open
zackkitzmiller wants to merge 2 commits into
fix/phase0-remove-hardcoded-keyfrom
feat/phase1-journaled-rollback
Open

Phase 1: journaled rollback with staged trash#15
zackkitzmiller wants to merge 2 commits into
fix/phase0-remove-hardcoded-keyfrom
feat/phase1-journaled-rollback

Conversation

@zackkitzmiller

Copy link
Copy Markdown
Member

Why

Rollback was not trustworthy: duplicate deletions were permanent (remove_file) and never recorded in the undo log, the undo log was overwritten every run (only the last operation was reversible), fs::rename silently overwrote existing destination files, cross-filesystem moves failed outright, and 'reclaimed bytes' was computed by stat-ing files after deleting them (always 0).

Stacked on #14.

Changes

  • Staged trash: deletions move to <data_dir>/spindle/trash/<run-id>/ (mirroring original paths). spindle --purge [--older-than DAYS] permanently reclaims space and reports real bytes freed.
  • Run journal: every execute writes <data_dir>/spindle/journal/<run-id>.json with all moves + staged deletions. --undo reverses the latest run, --undo-run <id> targets a specific one, --list-undo lists history with move/deletion counts and trash sizes. Undone journals are kept, renamed .undone.json.
  • Safe moves: destination collisions auto-rename (name (1).ext) — the journal and organized ledger record the actual destination; EXDEV falls back to copy + blake3 verification + source removal.
  • Graceful partial undo: individual restore failures (e.g. purged trash) are collected and reported instead of aborting; the journal is kept for retry.
  • Legacy compat: --undo-log <path> still restores old-format .spindle_undo.json logs.

Test plan

  • cargo test — 349 passed (new: collision auto-rename, journal roundtrip incl. actual destinations, staged-deletion undo, purge byte accounting, purge age cutoff, undo-after-purge tolerance, legacy log restore)
  • cargo clippy --all-targets — clean

- deletions now move to <data_dir>/spindle/trash/<run-id>/ instead of
  being permanently removed; 'spindle --purge [--older-than N]'
  reclaims the space for real
- every run writes an append-only journal (<data_dir>/spindle/journal/)
  recording moves and staged deletions; --undo reverses the latest run,
  --undo-run <id> targets one, --list-undo shows history
- moves never overwrite: destination collisions auto-rename to
  'name (1).ext' and the journal/ledger record the actual destination
- cross-device moves fall back to copy + blake3 verify + remove
- legacy .spindle_undo.json logs still restorable via --undo-log
- reclaimable bytes now measured before staging (was always 0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant