Rename config_path→ini_path

This commit is contained in:
2026-06-01 10:35:52 +02:00
parent c0ae977159
commit 761112d1ce
4 changed files with 40 additions and 40 deletions
+1 -1
View File
@@ -129,7 +129,7 @@ Created automatically next to the binary:
save_path = C:\Users\...\Subnautica2\Saved\SaveGames
save_scan = 2026-05-31 18:00:00
disclaimer_accepted = true
config_path = C:\Users\...\Subnautica2\Saved\Config\Windows
ini_path = C:\Users\...\Subnautica2\Saved\Config\Windows
```
Delete `config.ini` to force a fresh scan on next launch.
+8 -8
View File
@@ -8,7 +8,7 @@
//! save_path = C:\Users\...\Subnautica2\Saved\SaveGames
//! save_scan = 2026-05-26 19:45:22
//! disclaimer_accepted = true
//! config_path = C:\Users\...\Subnautica2\Saved\Config\Windows
//! ini_path = C:\Users\...\Subnautica2\Saved\Config\Windows
//! ```
use anyhow::{Context, Result};
@@ -22,7 +22,7 @@ pub struct AppConfig {
/// Last-known save folder (SaveGames)
pub save_path: Option<String>,
/// Last-known Config\Windows folder
pub config_path: Option<String>,
pub ini_path: Option<String>,
/// Timestamp of last successful scan
pub save_scan: Option<String>,
/// Whether disclaimer was accepted
@@ -30,7 +30,7 @@ pub struct AppConfig {
}
/// Path to config.ini alongside the binary.
pub fn config_path() -> PathBuf {
pub fn ini_path() -> PathBuf {
let exe_dir = std::env::current_exe()
.ok()
.and_then(|p| p.parent().map(Path::to_path_buf))
@@ -60,8 +60,8 @@ pub fn load_config(path: &Path) -> Result<AppConfig> {
if let Some(val) = trimmed.strip_prefix("save_path").and_then(strip_eq) {
cfg.save_path = Some(val.to_string());
} else if let Some(val) = trimmed.strip_prefix("config_path").and_then(strip_eq) {
cfg.config_path = Some(val.to_string());
} else if let Some(val) = trimmed.strip_prefix("ini_path").and_then(strip_eq) {
cfg.ini_path = Some(val.to_string());
} else if let Some(val) = trimmed.strip_prefix("save_scan").and_then(strip_eq) {
cfg.save_scan = Some(val.to_string());
} else if let Some(val) = trimmed.strip_prefix("disclaimer_accepted").and_then(strip_eq) {
@@ -94,8 +94,8 @@ pub fn save_config(path: &Path, cfg: &AppConfig) -> Result<()> {
if let Some(ref lp) = cfg.save_path {
writeln!(f, "save_path = {lp}")?;
}
if let Some(ref cp) = cfg.config_path {
writeln!(f, "config_path = {cp}")?;
if let Some(ref cp) = cfg.ini_path {
writeln!(f, "ini_path = {cp}")?;
}
if let Some(ref ls) = cfg.save_scan {
writeln!(f, "save_scan = {ls}")?;
@@ -116,7 +116,7 @@ pub fn save_config(path: &Path, cfg: &AppConfig) -> Result<()> {
/// Collect key/value pairs from the old config that this tool doesn't own.
fn preserved_keys(path: &Path) -> Result<Vec<(String, String)>> {
let known = &["save_path", "config_path", "save_scan", "disclaimer_accepted"];
let known = &["save_path", "ini_path", "save_scan", "disclaimer_accepted"];
let mut out = Vec::new();
let f = fs::File::open(path)?;
+3 -3
View File
@@ -355,7 +355,7 @@ pub fn validate_custom_path(input: &str) -> Option<PathBuf> {
/// Derive the Config\Windows path from a SaveGames path.
///
/// Walks up to the `Saved` ancestor, then down to `Config/Windows`.
pub fn derive_config_path(save_path: &Path) -> Option<PathBuf> {
pub fn derive_ini_path(save_path: &Path) -> Option<PathBuf> {
let mut current = save_path.to_path_buf();
// Walk up looking for "Saved" component
@@ -376,11 +376,11 @@ mod tests {
use super::*;
#[test]
fn test_derive_config_path_sample() {
fn test_derive_ini_path_sample() {
// Should resolve from a save path even if dirs don't exist locally
let save = Path::new("C:/Users/test/AppData/Local/Subnautica2/Saved/SaveGames");
// Since we can't test existence, at least verify the walk logic compiles
let result = derive_config_path(save);
let result = derive_ini_path(save);
// On a test machine without the game, this returns None — which is fine
let _ = result;
}
+28 -28
View File
@@ -69,7 +69,7 @@ fn main() -> Result<()> {
struct App {
config: AppConfig,
config_path: PathBuf,
ini_path: PathBuf,
log_path: PathBuf,
save_folder: Option<PathBuf>,
tui_state: tui::AppState,
@@ -77,8 +77,8 @@ struct App {
impl App {
fn new() -> Result<Self> {
let config_path = crate::config::config_path();
let config = crate::config::load_config(&config_path)?;
let ini_path = crate::config::ini_path();
let config = crate::config::load_config(&ini_path)?;
let log_path = guard::log_path();
let save_folder = config.save_path.as_deref().map(PathBuf::from);
@@ -92,7 +92,7 @@ impl App {
Ok(Self {
config,
config_path,
ini_path,
log_path,
save_folder,
tui_state,
@@ -175,7 +175,7 @@ fn run_app<B: Backend>(terminal: &mut Terminal<B>) -> Result<()> {
app.save_folder = Some(first.path.clone());
app.config.save_path = Some(first.path.display().to_string());
app.config.save_scan = Some(chrono::Local::now().format("%Y-%m-%d %H:%M:%S").to_string());
crate::config::save_config(&app.config_path, &app.config)?;
crate::config::save_config(&app.ini_path, &app.config)?;
refresh_stats(&mut app.tui_state, app.save_folder.as_deref());
true
} else {
@@ -260,13 +260,13 @@ fn run_disclaimer<B: Backend>(terminal: &mut Terminal<B>, app: &mut App) -> Resu
KeyCode::Char('y') | KeyCode::Char('Y') => {
guard::log_action("LICENSE", "accepted", "OK", &app.log_path)?;
app.config.disclaimer_accepted = true;
crate::config::save_config(&app.config_path, &app.config)?;
crate::config::save_config(&app.ini_path, &app.config)?;
return Ok(Some(true));
}
KeyCode::Char('n') | KeyCode::Char('N') => {
guard::log_action("LICENSE", "declined", "OK", &app.log_path)?;
app.config.disclaimer_accepted = false;
crate::config::save_config(&app.config_path, &app.config)?;
crate::config::save_config(&app.ini_path, &app.config)?;
return Ok(Some(false));
}
KeyCode::Esc => {
@@ -277,7 +277,7 @@ fn run_disclaimer<B: Backend>(terminal: &mut Terminal<B>, app: &mut App) -> Resu
let detail = if accepted { "accepted" } else { "declined" };
guard::log_action("LICENSE", detail, "OK", &app.log_path)?;
app.config.disclaimer_accepted = accepted;
crate::config::save_config(&app.config_path, &app.config)?;
crate::config::save_config(&app.ini_path, &app.config)?;
return Ok(Some(accepted));
}
_ => {}
@@ -355,7 +355,7 @@ fn action_locate_saves<B: Backend>(terminal: &mut Terminal<B>, app: &mut App) ->
app.save_folder = Some(first.path.clone());
app.config.save_path = Some(first.path.display().to_string());
app.config.save_scan = Some(chrono::Local::now().format("%Y-%m-%d %H:%M:%S").to_string());
crate::config::save_config(&app.config_path, &app.config)?;
crate::config::save_config(&app.ini_path, &app.config)?;
}
refresh_stats(&mut app.tui_state, app.save_folder.as_deref());
@@ -703,7 +703,7 @@ fn action_restore_backup<B: Backend>(terminal: &mut Terminal<B>, app: &mut App)
// ── .ini submenu ───────────────────────────────────────────────────────────
fn run_ini_submenu<B: Backend>(terminal: &mut Terminal<B>, app: &mut App) -> Result<()> {
let config_path = get_config_path(terminal, app)?;
let ini_path = get_ini_path(terminal, app)?;
let backup_root = app.backup_root();
let items: Vec<&str> = vec![
@@ -737,9 +737,9 @@ fn run_ini_submenu<B: Backend>(terminal: &mut Terminal<B>, app: &mut App) -> Res
KeyCode::Enter => {
let idx = state.selected().unwrap_or(0);
match idx {
0 => ini_backup_action(terminal, app, &config_path, &backup_root)?,
1 => ini_restore_action(terminal, app, &config_path, &backup_root)?,
2 => ini_delete_action(terminal, app, &config_path, &backup_root)?,
0 => ini_backup_action(terminal, app, &ini_path, &backup_root)?,
1 => ini_restore_action(terminal, app, &ini_path, &backup_root)?,
2 => ini_delete_action(terminal, app, &ini_path, &backup_root)?,
3 => break,
_ => {}
}
@@ -757,10 +757,10 @@ fn run_ini_submenu<B: Backend>(terminal: &mut Terminal<B>, app: &mut App) -> Res
fn ini_backup_action<B: Backend>(
terminal: &mut Terminal<B>,
app: &mut App,
config_path: &Path,
ini_path: &Path,
backup_root: &Path,
) -> Result<()> {
match ops::backup_ini_files(config_path, backup_root) {
match ops::backup_ini_files(ini_path, backup_root) {
Ok(result) => {
let verified = if result.verified { "verified" } else { "unverified" };
app.set_status(
@@ -784,7 +784,7 @@ fn ini_backup_action<B: Backend>(
fn ini_restore_action<B: Backend>(
terminal: &mut Terminal<B>,
app: &mut App,
config_path: &Path,
ini_path: &Path,
backup_root: &Path,
) -> Result<()> {
let backups = ops::list_ini_backups(backup_root);
@@ -822,8 +822,8 @@ fn ini_restore_action<B: Backend>(
let idx = state.selected().unwrap_or(0);
let chosen = &backups[idx];
guard::log_action("AUTO_BAK", &format!("ini pre-restore → {}", config_path.display()), "OK", &app.log_path)?;
match ops::restore_ini_files(chosen, config_path, backup_root) {
guard::log_action("AUTO_BAK", &format!("ini pre-restore → {}", ini_path.display()), "OK", &app.log_path)?;
match ops::restore_ini_files(chosen, ini_path, backup_root) {
Ok(n) => {
guard::log_action("CONFIG_RESTORE", &chosen.display().to_string(), "OK", &app.log_path)?;
let msg = format!("{n} .ini file(s) restored.");
@@ -847,7 +847,7 @@ fn ini_restore_action<B: Backend>(
fn ini_delete_action<B: Backend>(
terminal: &mut Terminal<B>,
app: &mut App,
config_path: &Path,
ini_path: &Path,
backup_root: &Path,
) -> Result<()> {
let has_backup = backup_root.exists()
@@ -875,10 +875,10 @@ fn ini_delete_action<B: Backend>(
return Ok(());
}
match ops::delete_ini_files(config_path, backup_root) {
match ops::delete_ini_files(ini_path, backup_root) {
Ok(n) => {
let msg = format!("Deleted {n} .ini file(s).\nThe game will regenerate defaults on next launch.");
guard::log_action("CONFIG_DEL", &config_path.display().to_string(), "OK", &app.log_path)?;
guard::log_action("CONFIG_DEL", &ini_path.display().to_string(), "OK", &app.log_path)?;
ok_dialog(terminal, app, ".ini Delete Complete", &msg)?;
}
Err(e) => {
@@ -1012,7 +1012,7 @@ fn ensure_save_folder<B: Backend>(_terminal: &mut Terminal<B>, app: &mut App) ->
if let Some(first) = folders.first() {
app.save_folder = Some(first.path.clone());
app.config.save_path = Some(first.path.display().to_string());
crate::config::save_config(&app.config_path, &app.config)?;
crate::config::save_config(&app.ini_path, &app.config)?;
refresh_stats(&mut app.tui_state, app.save_folder.as_deref());
return Ok(first.path.clone());
}
@@ -1021,9 +1021,9 @@ fn ensure_save_folder<B: Backend>(_terminal: &mut Terminal<B>, app: &mut App) ->
}
/// Get or discover the Config\Windows path.
fn get_config_path<B: Backend>(_terminal: &mut Terminal<B>, app: &mut App) -> Result<PathBuf> {
fn get_ini_path<B: Backend>(_terminal: &mut Terminal<B>, app: &mut App) -> Result<PathBuf> {
// Try cached config path
if let Some(ref cp) = app.config.config_path {
if let Some(ref cp) = app.config.ini_path {
let p = PathBuf::from(cp);
if p.exists() {
return Ok(p);
@@ -1032,7 +1032,7 @@ fn get_config_path<B: Backend>(_terminal: &mut Terminal<B>, app: &mut App) -> Re
// Derive from save folder
if let Some(ref sf) = app.save_folder {
if let Some(cp) = discovery::derive_config_path(sf) {
if let Some(cp) = discovery::derive_ini_path(sf) {
return Ok(cp);
}
}
@@ -1040,9 +1040,9 @@ fn get_config_path<B: Backend>(_terminal: &mut Terminal<B>, app: &mut App) -> Re
// Fall back to discovery
let folders = discovery::discover_save_folders();
for f in &folders {
if let Some(cp) = discovery::derive_config_path(&f.path) {
app.config.config_path = Some(cp.display().to_string());
crate::config::save_config(&app.config_path, &app.config)?;
if let Some(cp) = discovery::derive_ini_path(&f.path) {
app.config.ini_path = Some(cp.display().to_string());
crate::config::save_config(&app.ini_path, &app.config)?;
return Ok(cp);
}
}