fix(update): bypass Rust arg escaping in cmd.exe handoff

Rust's std::process::Command escapes inner double quotes as \" when
wrapping the args(["/c", &cmd]) array. cmd.exe does not understand the
\" escape, so the swap-and-restart command got mangled: `start ""
"PATH"` arrived as `start \"\" \"PATH\"`, which the cmd parser
collapsed into `start \ PATH` — producing the "Windows cannot find
'\'" dialog and aborting the update.

Switching to raw_arg lets us hand cmd.exe the literal command line it
expects. The two quote characters cmd needs to keep are the outer pair
wrapping the whole /c argument; cmd's "more than two quotes, special
chars present" branch then preserves the inner path quotes intact.

Bumps version to 0.1.2 since this is the first updater fix that ships
through the updater itself for any future v0.1.2+ user.
This commit is contained in:
2026-05-16 13:04:08 +07:00
parent ca9ab4ea97
commit a132c02711
3 changed files with 9 additions and 3 deletions
Generated
+1 -1
View File
@@ -68,7 +68,7 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]]
name = "claude-code-usage-bubble"
version = "0.1.1"
version = "0.1.2"
dependencies = [
"dirs",
"embed-resource",
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "claude-code-usage-bubble"
version = "0.1.1"
version = "0.1.2"
edition = "2021"
license = "Apache-2.0"
description = "Floating bubble showing Claude Code and Codex usage on Windows"
+7 -1
View File
@@ -58,8 +58,14 @@ fn spawn_handoff(source: &std::path::Path, target: &std::path::Path) -> Result<(
let cmd = format!(
r#"timeout /t 2 /nobreak >nul & move /y "{src_str}" "{tgt_str}" & start "" "{tgt_str}""#
);
// raw_arg bypasses Rust's std auto-escaping which would turn the inner
// `"` characters into `\"`. cmd.exe does not recognise `\"`, so the
// escaped form makes `start` see the path as `\\` and emit a
// "Windows cannot find '\\'" dialog. Feeding the command line raw
// preserves the quotes cmd.exe actually expects.
Command::new("cmd.exe")
.args(["/c", &cmd])
.raw_arg("/c")
.raw_arg(format!("\"{cmd}\""))
.creation_flags(CREATE_NO_WINDOW | DETACHED_PROCESS)
.stdin(Stdio::null())
.stdout(Stdio::null())