feat(history): add per-file backup history - #80
Merged
olxgdm merged 5 commits intoJul 10, 2026
Conversation
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
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
|
olxgdm
marked this pull request as ready for review
July 10, 2026 13:43
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Summary
Implements per-file snapshot history for tracked cfgsync files while preserving the existing latest-copy workflow.
This adds a versioned
<storage>/history.jsonmanifest plus human-readable historical content under<storage>/history/, without changingregistry.jsonversion1,TrackedEntry, or the latest backup layout under<storage>/files/.What Changed
cfgsync history <file>to list per-file versions newest-first as:version-id created-at-utc size-bytes sha256.cfgsync diff <file> --version <id>to compare a historical version against the current original file.cfgsync restore <file> --version <id>for single-file historical restore.restore --all --version <id>because history versions are per-file, not global snapshots.HistoryManifest,HistoryError, and storage helpers for history manifest/content resolution.VersionedBackupServiceused by backup and watch.initto createhistory/and an emptyhistory.json, while preserving existing valid history on rerun.usecompatible with storage roots that do not yet have a history manifest.Behavior Details
--missing-onlyrecords history only when it creates a missing latest copy.--forcekeeps the existing overwrite behavior while still avoiding duplicate history content.history.jsonloads as empty history for history-aware commands.HistoryErrormessages.history <file>lists manifest entries without requiring historical content files to still exist.diff --versionandrestore --versionvalidate that the selected historical content exists.Tests
--missing-only,--force, and watch-created versions.restore --all --versionrejection.Verification
All tests passed locally: 306/306.
Closes #79