From d592894f280e0d12a50b7342890375dbbb3c98e4 Mon Sep 17 00:00:00 2001 From: Christoph Brandau Date: Mon, 6 Jul 2026 08:22:41 +0200 Subject: [PATCH] fix(git): split long path args to avoid Windows CreateProcess limit Git operations that stage or restore many files could exceed the Windows command line length limit, causing os error 206 failures. This change splits file paths into size-bounded chunks and concatenates the output from multiple git invocations to keep commands within safe limits. - Chunk file path arguments for Windows compatibility - Add a local dev command to list pkg-config packages --- .claude/settings.local.json | 3 ++- package-lock.json | 4 ++-- src-tauri/src/git.rs | 41 ++++++++++++++++++++++++++++++++----- 3 files changed, 40 insertions(+), 8 deletions(-) diff --git a/.claude/settings.local.json b/.claude/settings.local.json index f7ccea6..7d9e6ce 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -78,7 +78,8 @@ "Bash(rustfmt --edition 2024 --check src/badge.rs src/main.rs)", "Bash(rustfmt --edition 2024 --check src/git.rs)", "Bash(rustfmt --edition 2024 --check src/badge.rs)", - "Bash(rustfmt --edition 2024 --check src/git.rs src/main.rs)" + "Bash(rustfmt --edition 2024 --check src/git.rs src/main.rs)", + "Bash(pkg-config --list-all)" ] } } diff --git a/package-lock.json b/package-lock.json index 589dd3e..a7855eb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "git-lite", - "version": "2026.7.12", + "version": "2026.7.11", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "git-lite", - "version": "2026.7.12", + "version": "2026.7.11", "dependencies": { "@lucide/svelte": "^1.21.0", "@tailwindcss/vite": "^4.3.1", diff --git a/src-tauri/src/git.rs b/src-tauri/src/git.rs index 7d25b81..a3a67c8 100644 --- a/src-tauri/src/git.rs +++ b/src-tauri/src/git.rs @@ -3415,16 +3415,47 @@ fn is_auth_error(details: &str) -> bool { || d.contains("authentication required") } +// Windows' CreateProcess rejects command lines longer than ~32K chars with +// "os error 206" (filename or extension too long). Staging/restoring a large +// number of files can easily exceed that, so split the paths across multiple +// invocations and concatenate their output. +const MAX_PATH_ARGS_CHARS: usize = 8_000; + fn run_git_with_paths( repo: &Path, base_args: &[&str], files: &[String], ) -> Result, String> { - let mut args = Vec::with_capacity(base_args.len() + files.len() + 1); - args.extend(base_args.iter().map(OsString::from)); - args.push(OsString::from("--")); - args.extend(files.iter().map(OsString::from)); - run_git(repo, args) + if files.is_empty() { + let args: Vec = base_args.iter().map(OsString::from).collect(); + return run_git(repo, args); + } + + let mut combined = Vec::new(); + let mut start = 0; + while start < files.len() { + let mut end = start; + let mut chunk_chars = 0usize; + while end < files.len() { + let len = files[end].len() + 1; + if end > start && chunk_chars + len > MAX_PATH_ARGS_CHARS { + break; + } + chunk_chars += len; + end += 1; + } + let chunk = &files[start..end]; + + let mut args = Vec::with_capacity(base_args.len() + chunk.len() + 1); + args.extend(base_args.iter().map(OsString::from)); + args.push(OsString::from("--")); + args.extend(chunk.iter().map(OsString::from)); + combined.extend(run_git(repo, args)?); + + start = end; + } + + Ok(combined) } fn run_git_with_paths_cancellable(