From cf2b31de33be79bb345fef2b0a4897c42578d7b4 Mon Sep 17 00:00:00 2001 From: forkless Date: Wed, 3 Jun 2026 02:03:01 +0200 Subject: [PATCH] fix: migrate old config_* ini backups to tar.gz --- _release.md | 9 ++++++++- src/ops.rs | 52 +++++++++++++++++++++++++++++++--------------------- 2 files changed, 39 insertions(+), 22 deletions(-) diff --git a/_release.md b/_release.md index 5d01e12..1bd880e 100644 --- a/_release.md +++ b/_release.md @@ -4,6 +4,13 @@ Cross-platform terminal application. No admin permissions or network access req Pre-compiled binaries — no installation, no dependencies. Just download, extract, and run. +### What's new in v0.4.1 + +• Log migration — existing `transaction.log` is moved into `logs/` on first launch +• Backup directory structure scaffolded at startup (`backups/saves/`, `backups/config/`, `logs/`) +• `ensure_dir()` helper for consistent directory creation +• All migration paths integrated into startup (config.ini, backups, log) + ### What's new in v0.4.0 • tar.gz backup format — one archive per backup event, standard `tar -xzf` recovers data without the tool @@ -15,4 +22,4 @@ extract, and run. • 6 migration tests, full round-trip tar.gz integration tests • `tar` + `flate2` dependencies added (pure Rust, ~150KB increase) -_Builds: Linux (amd64) • Windows x64_ +Builds: Linux (amd64) • Windows x64 diff --git a/src/ops.rs b/src/ops.rs index 763d7b8..63e950c 100644 --- a/src/ops.rs +++ b/src/ops.rs @@ -395,28 +395,38 @@ fn migrate_backups_from(old_root: PathBuf) -> Result { continue; } let dir_name = entry.file_name().to_string_lossy().to_string(); - if !dir_name.starts_with("notalterra_copy_") { - continue; - } - // Check if this directory contains save files - let has_saves = fs::read_dir(&path) - .map(|e| e.flatten().any(|f| { - let fname = f.file_name(); - let n = fname.to_string_lossy(); - n.starts_with("savegame_") - })) - .unwrap_or(false); - if !has_saves { - continue; - } - let backup_dir = crate::config::backups_saves_dir(); - match create_tar_gz(&path, &backup_dir, "savegame_", &format!("migrated_{dir_name}")) { - Ok((_count, _size, archive_path)) if archive_path.exists() => { - migrated += 1; + + if dir_name.starts_with("notalterra_copy_") { + // Migrate old save backups → backups/saves/ + let has_saves = fs::read_dir(&path) + .map(|e| e.flatten().any(|f| { + f.file_name().to_string_lossy().starts_with("savegame_") + })) + .unwrap_or(false); + if !has_saves { + continue; } - Ok(_) => {}, - Err(e) => { - eprintln!("migration warning: failed to archive {:?}: {}", path, e); + let backup_dir = crate::config::backups_saves_dir(); + match create_tar_gz(&path, &backup_dir, "savegame_", &format!("migrated_{dir_name}")) { + Ok((_count, _size, archive_path)) if archive_path.exists() => { + migrated += 1; + } + Ok(_) => {}, + Err(e) => { + eprintln!("migration warning: failed to archive {:?}: {}", path, e); + } + } + } else if dir_name.starts_with("config_") { + // Migrate old .ini backups → backups/config/ + let backup_dir = crate::config::backups_config_dir(); + match create_tar_gz(&path, &backup_dir, "", &format!("migrated_{dir_name}")) { + Ok((_count, _size, archive_path)) if archive_path.exists() => { + migrated += 1; + } + Ok(_) => {}, + Err(e) => { + eprintln!("migration warning: failed to archive {:?}: {}", path, e); + } } } }