diff --git a/CHANGELOG.md b/CHANGELOG.md index 2db309d..a176506 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,14 @@ All notable changes to NotAlterra are documented in this file. --- +## [v0.4.3] — 2026-06-09 + +### Fixed +- **Dashboard counts** — "Saves" now shows `.bak` recovery file count, "Backups" shows `.tar.gz` archive count +- **Backup mtime preservation** — tar archives now store source file modification times, preventing epoch dates on restored files +- **Navigation bound** — restore backup picker no longer stops before migrated entries +- **Save folder dialog** — pre-fills with the current path if one is already set + ## [v0.4.2] — 2026-06-09 ### Added diff --git a/Cargo.lock b/Cargo.lock index 67a3726..4688985 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -540,7 +540,7 @@ dependencies = [ [[package]] name = "notalterra" -version = "0.4.2" +version = "0.4.3" dependencies = [ "anyhow", "chrono", diff --git a/Cargo.toml b/Cargo.toml index 1da46c8..bed726f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "notalterra" -version = "0.4.2" +version = "0.4.3" edition = "2021" authors = ["NotAlterra"] license = "MIT" diff --git a/_release.md b/_release.md index 708f51c..bd84e34 100644 --- a/_release.md +++ b/_release.md @@ -6,23 +6,14 @@ extract, and run. --- -### v0.4.2 — Pinned headers & layout polish +### v0.4.3 — Dashboard & backup integrity fixes -**UI** -• Restore backup picker: pinned column headers, wider Backup column, right-aligned Size -• INI restore picker: matching pinned header with "INI Backup" / "Size" columns -• All picker highlight colour changed to yellow for better visibility -• Main menu entries shifted 1 left; INI submenu entries aligned with main menu -• Spacer row between list content and status bar on all screens -• Non-blocking info dialog for backup-in-progress (no button, auto-replaced) - -**Layout** -• Backup column widened from 30→38 chars; header/data total widths matched -• Size header right-aligned above file-size values in both restore pickers -• INI submenu header changed to cyan, shifted 3 right - -**Backup flow** -• No intermediate spinner page — info popup followed by summary dialog +**Fixed** +• Dashboard counts now correct: "Saves" shows `.bak` recovery file count, "Backups" shows `.tar.gz` archive count +• Backup archives now preserve source file modification times — restored files keep their original dates instead of showing 1970-01-01 on Windows +• Restore backup picker navigation no longer stops before migrated entries +• Save folder input dialog pre-fills with the currently set path +• SLSA provenance attestation re-enabled (`upload-assets: true`) --- diff --git a/docs/BUG_REPORT_TEMPLATE.md b/docs/BUG_REPORT_TEMPLATE.md index d96ef17..44fe9d8 100644 --- a/docs/BUG_REPORT_TEMPLATE.md +++ b/docs/BUG_REPORT_TEMPLATE.md @@ -24,7 +24,7 @@ What happened? What did you expect to happen instead? ### Environment - **OS**: (e.g. Windows 11, Ubuntu 24.04, Steam Deck) -- **NotAlterra version**: (shown in the title bar, e.g. v0.4.2) +- **NotAlterra version**: (shown in the title bar, e.g. v0.4.3) - **Subnautica 2 install**: (Steam, Xbox, Epic, custom) ### Logs diff --git a/docs/CVE_TEMPLATE.md b/docs/CVE_TEMPLATE.md index 5f0c618..1f85d55 100644 --- a/docs/CVE_TEMPLATE.md +++ b/docs/CVE_TEMPLATE.md @@ -55,7 +55,7 @@ triggers the issue. ### Affected versions -- NotAlterra version(s): (e.g. v0.4.2) +- NotAlterra version(s): (e.g. v0.4.3) - Platform: (Windows / Linux / both) ### Impact assessment diff --git a/src/main.rs b/src/main.rs index c65219c..9286e3b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -139,9 +139,10 @@ fn exe_dir() -> PathBuf { /// any backup/restore operation. fn refresh_stats(tui_state: &mut tui::AppState, save_folder: Option<&Path>) { tui_state.save_path = save_folder.map(|p| p.display().to_string()); - let (live, bak, ini) = ops::folder_stats(save_folder); - tui_state.live_save_count = live; - tui_state.backup_count = bak; + let (_live, _bak, ini) = ops::folder_stats(save_folder); + // "Saves" = .bak recovery files (the restore points in the save folder) + tui_state.live_save_count = _bak; + tui_state.backup_count = ops::list_full_backups().len(); tui_state.has_ini_backup = ini; tui_state.context_path = Some(crate::config::get_backup_root().display().to_string()); } diff --git a/src/ops.rs b/src/ops.rs index 49b1605..8a1a575 100644 --- a/src/ops.rs +++ b/src/ops.rs @@ -138,6 +138,15 @@ fn create_tar_gz( .with_context(|| format!("failed to set path '{name}' in tar header"))?; header.set_size(data.len() as u64); header.set_mode(0o644); // owner read/write, group/other read + // Preserve the source file's mtime so the extracted file keeps its + // original date. Without this, the mtime defaults to epoch (1970). + if let Ok(src_meta) = fs::metadata(&src_path) { + if let Ok(mtime) = src_meta.modified() { + if let Ok(dur) = mtime.duration_since(std::time::UNIX_EPOCH) { + header.set_mtime(dur.as_secs()); + } + } + } header.set_cksum(); tar_builder .append(&header, &data[..]) @@ -358,8 +367,12 @@ pub fn list_bak_files_with_meta(save_folder: &Path) -> Vec { let filename = entry.file_name().to_string_lossy().to_string(); let meta = fs::metadata(&path).ok(); let size = meta.as_ref().map(|m| m.len()).unwrap_or(0); - let mtime = meta.as_ref().and_then(|m| m.modified().ok()).and_then(|t| { + let mtime = meta.as_ref().and_then(|m| { + // Try modified time first; fall back to creation time (Windows) + let t = m.modified().or_else(|_| m.created()).ok()?; let secs = t.duration_since(std::time::UNIX_EPOCH).ok()?.as_secs(); + // Reject epoch (Jan 1 1970) — indicates filesystem couldn't provide a real time + if secs == 0 { return None; } Local .timestamp_opt(secs as i64, 0) .single()