Fix double-prefix sidecar dir and stale PID lock on startup
All checks were successful
Release / Run Tests (push) Successful in 29s
Tests / Python Backend Tests (push) Successful in 8s
Tests / Frontend Tests (push) Successful in 10s
Tests / Rust Sidecar Tests (push) Successful in 4m7s
Release / Bump version and tag (push) Successful in 4s

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) <noreply@anthropic.com>
This commit is contained in:
Developer
2026-04-07 08:46:20 -07:00
parent 5139936e18
commit 924cae6c75

View File

@@ -54,7 +54,8 @@ fn read_installed_version() -> Option<String> {
} }
fn sidecar_dir_for_version(version: &str) -> PathBuf { 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 { 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) { fn cleanup_old_versions(current_version: &str) {
let data = data_dir(); 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) { if let Ok(entries) = std::fs::read_dir(data) {
for entry in entries.flatten() { for entry in entries.flatten() {
let name = entry.file_name().to_string_lossy().to_string(); let name = entry.file_name().to_string_lossy().to_string();
if name.starts_with("sidecar-v") // e.g. sidecar-v1.0.1 if name.starts_with("sidecar-")
&& name != current_dir_name && name != current_version
&& entry.path().is_dir() && entry.path().is_dir()
{ {
let _ = std::fs::remove_dir_all(entry.path()); let _ = std::fs::remove_dir_all(entry.path());
@@ -433,6 +434,20 @@ impl SidecarManager {
.ok_or_else(|| "Sidecar running but port unknown".into()); .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) let is_dev = cfg!(debug_assertions)
|| std::env::var("LOCAL_TRANSCRIPTION_DEV") || std::env::var("LOCAL_TRANSCRIPTION_DEV")
.map(|v| v == "1") .map(|v| v == "1")
@@ -791,7 +806,7 @@ mod tests {
fn sidecar_dir_for_version_contains_version() { fn sidecar_dir_for_version_contains_version() {
let data = ensure_dirs_initialised(); let data = ensure_dirs_initialised();
let dir = sidecar_dir_for_version("sidecar-v1.2.3"); 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] #[test]
@@ -836,9 +851,8 @@ mod tests {
std::fs::create_dir_all(data.join(d)).unwrap(); std::fs::create_dir_all(data.join(d)).unwrap();
} }
// cleanup_old_versions builds `current_dir_name = "sidecar-{version}"`. // current_version is the full tag, e.g. "sidecar-v1.0.2"
// Passing "v1.0.2" produces "sidecar-v1.0.2" which matches our dir name. cleanup_old_versions("sidecar-v1.0.2");
cleanup_old_versions("v1.0.2");
assert!( assert!(
!data.join("sidecar-v1.0.0").exists(), !data.join("sidecar-v1.0.0").exists(),