feat(peer): journal download file ownership
Track the exact regular files owned by each completed and in-flight peer download instead of sweeping every non-reserved path after cancellation. Bind the record to the canonical games directory, publish pending ownership before payload mutation, and use the final version.ini rename as the recovery commit point. Make replacement, cancellation, and startup recovery preserve unknown files and install state while removing stale or partial downloader-owned bytes. Add a new-format baseline so legacy discarded sentinels cannot make partially modified payloads ready, sync payload and journal state in transaction order, and serialize startup recovery against operation admission. Document ambiguous legacy target adoption, portable alias transitions, and the other ownership tradeoffs in the refactor decision log. Test Plan: - `just clippy` -- passed - `just test` -- passed (182 peer-core tests plus the full workspace) - `just fmt` -- Rust, TOML, and Prettier formatting completed; the command then stopped on 40 pre-existing rumdl findings in unrelated Markdown content - `git diff --cached --check` -- passed
This commit is contained in:
14 files changed
+1478
-265
No files matched your search
@@ -55,29 +55,6 @@ pub(crate) fn is_download_protected_root_name(name: &str) -> bool {
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns whether cancellation cleanup must preserve an application-owned entry.
|
||||
///
|
||||
/// Version transaction scratch files are intentionally excluded: they belong to
|
||||
/// the cancelled download and are safe to sweep. Install and migration state is
|
||||
/// independent of that download and must survive it.
|
||||
pub(crate) fn is_preserved_on_download_discard(name: &str) -> bool {
|
||||
let key = portable_name_key(name);
|
||||
key == "LOCAL"
|
||||
|| key.starts_with(".LOCAL.")
|
||||
|| matches!(
|
||||
key.as_str(),
|
||||
".SYNC"
|
||||
| ".LANSPREAD"
|
||||
| ".LANSPREAD.JSON"
|
||||
| ".LANSPREAD.JSON.TMP"
|
||||
| ".LANSPREAD_OWNED"
|
||||
| ".SOFTLAN_FIRST_START_DONE"
|
||||
| ".SOFTLAN_GAME_INSTALLED"
|
||||
| "INSTALL_INTENT.JSON"
|
||||
| "INSTALL_INTENT.JSON.TMP"
|
||||
)
|
||||
}
|
||||
|
||||
/// Returns whether an entry in the configured games directory is application state.
|
||||
pub(crate) fn is_ignored_games_root_name(name: &str) -> bool {
|
||||
portable_name_key(name) == ".LANSPREAD"
|
||||
@@ -112,14 +89,4 @@ mod tests {
|
||||
assert!(!is_download_protected_root_name(VERSION_INI));
|
||||
assert!(!is_download_protected_root_name("archive.eti"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cancellation_policy_sweeps_only_download_transaction_state() {
|
||||
assert!(is_preserved_on_download_discard(LOCAL_DIR));
|
||||
assert!(is_preserved_on_download_discard(BACKUP_DIR));
|
||||
assert!(is_preserved_on_download_discard(LEGACY_INTENT_FILE));
|
||||
assert!(!is_preserved_on_download_discard(VERSION_INI));
|
||||
assert!(!is_preserved_on_download_discard(VERSION_TMP_FILE));
|
||||
assert!(!is_preserved_on_download_discard("archive.eti"));
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user