From 924cae6c75a20ea5dcdd4251e34077b9053a1bbb Mon Sep 17 00:00:00 2001 From: Developer Date: Tue, 7 Apr 2026 08:46:20 -0700 Subject: [PATCH] Fix double-prefix sidecar dir and stale PID lock on startup Two bugs preventing sidecar from starting: 1. Directory was "sidecar-sidecar-v1.0.3" (double prefix) because sidecar_dir_for_version() prepended "sidecar-" to a version that already contained it. Now uses the tag directly as the dir name. 2. After a crash, the Python InstanceLock PID file at ~/.local-transcription/app.lock remained, blocking the next launch with "Another instance is already running". Now clears the stale lock file before spawning the sidecar. Also fixed cleanup_old_versions() and tests to match the corrected directory naming. Co-Authored-By: Claude Opus 4.6 (1M context) --- src-tauri/src/sidecar/mod.rs | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src-tauri/src/sidecar/mod.rs b/src-tauri/src/sidecar/mod.rs index 9d97ab5..9ffb970 100644 --- a/src-tauri/src/sidecar/mod.rs +++ b/src-tauri/src/sidecar/mod.rs @@ -54,7 +54,8 @@ fn read_installed_version() -> Option { } fn sidecar_dir_for_version(version: &str) -> PathBuf { - data_dir().join(format!("sidecar-{version}")) + // version is the full tag name, e.g. "sidecar-v1.0.3" -- use it directly + data_dir().join(version) } fn binary_path_for_version(version: &str) -> PathBuf { @@ -371,12 +372,12 @@ fn extract_zip(zip_path: &std::path::Path, dest: &std::path::Path) -> Result<(), fn cleanup_old_versions(current_version: &str) { let data = data_dir(); - let current_dir_name = format!("sidecar-{current_version}"); + // current_version is already the full tag, e.g. "sidecar-v1.0.3" if let Ok(entries) = std::fs::read_dir(data) { for entry in entries.flatten() { let name = entry.file_name().to_string_lossy().to_string(); - if name.starts_with("sidecar-v") // e.g. sidecar-v1.0.1 - && name != current_dir_name + if name.starts_with("sidecar-") + && name != current_version && entry.path().is_dir() { let _ = std::fs::remove_dir_all(entry.path()); @@ -433,6 +434,20 @@ impl SidecarManager { .ok_or_else(|| "Sidecar running but port unknown".into()); } + // Clear stale PID lock from a previous crash so the sidecar can start. + // The Python InstanceLock writes to ~/.local-transcription/app.lock + if let Ok(home) = std::env::var("USERPROFILE") + .or_else(|_| std::env::var("HOME")) + { + let lock_file = PathBuf::from(home) + .join(".local-transcription") + .join("app.lock"); + if lock_file.exists() { + eprintln!("[sidecar] Removing stale lock file: {}", lock_file.display()); + let _ = std::fs::remove_file(&lock_file); + } + } + let is_dev = cfg!(debug_assertions) || std::env::var("LOCAL_TRANSCRIPTION_DEV") .map(|v| v == "1") @@ -791,7 +806,7 @@ mod tests { fn sidecar_dir_for_version_contains_version() { let data = ensure_dirs_initialised(); let dir = sidecar_dir_for_version("sidecar-v1.2.3"); - assert_eq!(dir, data.join("sidecar-sidecar-v1.2.3")); + assert_eq!(dir, data.join("sidecar-v1.2.3")); } #[test] @@ -836,9 +851,8 @@ mod tests { std::fs::create_dir_all(data.join(d)).unwrap(); } - // cleanup_old_versions builds `current_dir_name = "sidecar-{version}"`. - // Passing "v1.0.2" produces "sidecar-v1.0.2" which matches our dir name. - cleanup_old_versions("v1.0.2"); + // current_version is the full tag, e.g. "sidecar-v1.0.2" + cleanup_old_versions("sidecar-v1.0.2"); assert!( !data.join("sidecar-v1.0.0").exists(),