Skip to content

feat(history): add per-file backup history - #80

Merged
olxgdm merged 5 commits into
mainfrom
79-add-per-file-snapshot-history-for-cfgsync-backups
Jul 10, 2026
Merged

feat(history): add per-file backup history#80
olxgdm merged 5 commits into
mainfrom
79-add-per-file-snapshot-history-for-cfgsync-backups

Conversation

@olxgdm

@olxgdm olxgdm commented Jul 8, 2026

Copy link
Copy Markdown
Owner

Summary

Implements per-file snapshot history for tracked cfgsync files while preserving the existing latest-copy workflow.

This adds a versioned <storage>/history.json manifest plus human-readable historical content under <storage>/history/, without changing registry.json version 1, TrackedEntry, or the latest backup layout under <storage>/files/.

What Changed

  • Added cfgsync history <file> to list per-file versions newest-first as:
    version-id created-at-utc size-bytes sha256.
  • Added cfgsync diff <file> --version <id> to compare a historical version against the current original file.
  • Added cfgsync restore <file> --version <id> for single-file historical restore.
  • Preserved dry-run restore preview and prefix remapping for historical restore.
  • Rejected restore --all --version <id> because history versions are per-file, not global snapshots.
  • Added HistoryManifest, HistoryError, and storage helpers for history manifest/content resolution.
  • Added a shared VersionedBackupService used by backup and watch.
  • Moved SHA-256/content comparison helpers into reusable utilities.
  • Updated init to create history/ and an empty history.json, while preserving existing valid history on rerun.
  • Kept use compatible with storage roots that do not yet have a history manifest.
  • Updated README examples and behavior notes for history, historical diff, historical restore, dry-run, and prefix remapping.

Behavior Details

  • First backup creates both the latest copy and an initial history version.
  • Changed content creates a new history version and refreshes the latest copy.
  • Unchanged content does not create duplicate history.
  • Existing latest backups without history are adopted before recording future changed versions.
  • --missing-only records history only when it creates a missing latest copy.
  • --force keeps the existing overwrite behavior while still avoiding duplicate history content.
  • Missing history.json loads as empty history for history-aware commands.
  • Malformed, unsupported, duplicate, or unsafe-path history manifests fail with clear HistoryError messages.
  • history <file> lists manifest entries without requiring historical content files to still exist.
  • diff --version and restore --version validate that the selected historical content exists.

Tests

  • Added manifest load/save and validation coverage.
  • Added history command and CLI coverage.
  • Updated backup/watch tests for initial history, changed content, unchanged content, adoption, --missing-only, --force, and watch-created versions.
  • Updated diff/restore CLI tests for historical versions, dry-run, prefix remapping, unknown versions, missing historical content, malformed history, and restore --all --version rejection.

Verification

cmake --build build
ctest --test-dir build --output-on-failure

All tests passed locally: 306/306.

Closes #79

Add a versioned history manifest and readable history storage under each cfgsync storage root while preserving the latest-copy workflow.

Implement cfgsync history <file>, historical diff, and single-file historical restore with dry-run and prefix remapping support. Reject restore --all --version because history versions are per-file rather than global restore points.

Refactor backup and watch through a shared versioned backup service so changed content records history, first backups create initial versions, existing latest copies can be adopted, and duplicate content versions are avoided.

Update README and add focused manifest, command, CLI, backup, watch, diff, and restore coverage.

Verification:

- cmake --build build

- ctest --test-dir build --output-on-failure
@olxgdm olxgdm linked an issue Jul 8, 2026 that may be closed by this pull request
olxgdm added 4 commits July 8, 2026 21:00
Add focused unit coverage for history manifest initialization and validation, storage history path helpers, reusable file content helpers, and deterministic version id suffixing in the versioned backup service.

Verification:

- cmake --build build

- ctest --test-dir build --output-on-failure
Replace Sonar-flagged patterns with clearer C++20 equivalents in the history backup path without changing behavior.

Use if init-statements, unqualified enum cases, transparent string sets, std::to_address, and a helper for latest history SHA selection.

Verification:

- cmake --build build

- ctest --test-dir build --output-on-failure
Make history CLI tests derive expected size and historical content paths from manifest and storage resolution instead of Unix-specific byte and separator assumptions.

Verification:

- ctest --test-dir build -R 'HistoryCommandCliTest.ListsHistoryVersionsNewestFirst|RestoreCommandCliTest.SingleRestoreWithMissingHistoricalContentReturnsNonZero' --output-on-failure

- cmake --build build

- ctest --test-dir build --output-on-failure
@sonarqubecloud

Copy link
Copy Markdown

@olxgdm
olxgdm marked this pull request as ready for review July 10, 2026 13:43
@olxgdm
olxgdm merged commit a9bcbca into main Jul 10, 2026
6 checks passed
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.

Add per-file snapshot history for cfgsync backups

1 participant