mirror of
https://github.com/delibae/claude-prism.git
synced 2026-08-28 05:14:59 +00:00
fix: address Copilot review — refactor git-bash detection and improve error handling
- Refactor: extract shared find_git_bash() function used by both create_command and check_claude_status (eliminates code duplication) - Validate user-specified CLAUDE_CODE_GIT_BASH_PATH exists before using it, falling back to auto-detection if the path is invalid - Check existing error state before setting stderr errors to avoid masking more specific earlier errors - Make zero-output error message platform-aware (git-bash hint only on Windows) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
ef5cd94f4d
commit
6434f176e1
2 changed files with 32 additions and 46 deletions
|
|
@ -571,39 +571,13 @@ fn create_command(
|
|||
// Set effort level (default: low for fast responses)
|
||||
cmd.env("CLAUDE_CODE_EFFORT_LEVEL", effort_level.unwrap_or("low"));
|
||||
|
||||
// On Windows, auto-detect git-bash if CLAUDE_CODE_GIT_BASH_PATH is not set.
|
||||
// On Windows, ensure CLAUDE_CODE_GIT_BASH_PATH is set.
|
||||
// Claude Code requires git-bash to run on Windows.
|
||||
// Uses find_git_bash() which also validates user-specified paths.
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
if std::env::var("CLAUDE_CODE_GIT_BASH_PATH").is_err() {
|
||||
// Reuse the same detection logic as is_git_bash_available()
|
||||
let mut found: Option<String> = None;
|
||||
let candidates = [
|
||||
r"C:\Program Files\Git\bin\bash.exe",
|
||||
r"C:\Program Files (x86)\Git\bin\bash.exe",
|
||||
];
|
||||
for candidate in &candidates {
|
||||
if std::path::Path::new(candidate).is_file() {
|
||||
found = Some(candidate.to_string());
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Also try deriving from git.exe on PATH
|
||||
if found.is_none() {
|
||||
if let Ok(git_path) = which::which("git") {
|
||||
if let Some(cmd_dir) = git_path.parent() {
|
||||
if let Some(git_root) = cmd_dir.parent() {
|
||||
let bash = git_root.join("bin").join("bash.exe");
|
||||
if bash.is_file() {
|
||||
found = Some(bash.to_string_lossy().to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(bash_path) = found {
|
||||
cmd.env("CLAUDE_CODE_GIT_BASH_PATH", bash_path);
|
||||
}
|
||||
if let Some(bash_path) = find_git_bash() {
|
||||
cmd.env("CLAUDE_CODE_GIT_BASH_PATH", bash_path);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -904,13 +878,15 @@ pub struct ClaudeStatus {
|
|||
pub missing_git: bool,
|
||||
}
|
||||
|
||||
/// Check whether Git for Windows (git-bash) is available on Windows.
|
||||
/// Find the path to git-bash on Windows.
|
||||
/// Returns `Some(path)` if found, `None` otherwise.
|
||||
/// Used by both `create_command` (to set the env var) and `check_claude_status` (to report status).
|
||||
#[cfg(target_os = "windows")]
|
||||
fn is_git_bash_available() -> bool {
|
||||
// 1. User-specified override
|
||||
fn find_git_bash() -> Option<String> {
|
||||
// 1. User-specified override (only if the path actually exists)
|
||||
if let Ok(p) = std::env::var("CLAUDE_CODE_GIT_BASH_PATH") {
|
||||
if PathBuf::from(&p).exists() {
|
||||
return true;
|
||||
if PathBuf::from(&p).is_file() {
|
||||
return Some(p);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -920,8 +896,8 @@ fn is_git_bash_available() -> bool {
|
|||
r"C:\Program Files (x86)\Git\bin\bash.exe",
|
||||
];
|
||||
for path in &candidates {
|
||||
if PathBuf::from(path).exists() {
|
||||
return true;
|
||||
if PathBuf::from(path).is_file() {
|
||||
return Some(path.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -930,22 +906,27 @@ fn is_git_bash_available() -> bool {
|
|||
// git.exe is typically at Git/cmd/git.exe → bash.exe at Git/bin/bash.exe
|
||||
if let Some(cmd_dir) = git_path.parent() {
|
||||
if let Some(git_root) = cmd_dir.parent() {
|
||||
if git_root.join("bin").join("bash.exe").exists() {
|
||||
return true;
|
||||
let bash = git_root.join("bin").join("bash.exe");
|
||||
if bash.is_file() {
|
||||
return Some(bash.to_string_lossy().to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4. bash directly on PATH
|
||||
which::which("bash").is_ok()
|
||||
if let Ok(bash_path) = which::which("bash") {
|
||||
return Some(bash_path.to_string_lossy().to_string());
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn check_claude_status() -> Result<ClaudeStatus, String> {
|
||||
// On Windows, check for Git for Windows first — Claude Code requires it.
|
||||
#[cfg(target_os = "windows")]
|
||||
let missing_git = !is_git_bash_available();
|
||||
let missing_git = find_git_bash().is_none();
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
let missing_git = false;
|
||||
|
||||
|
|
|
|||
|
|
@ -308,9 +308,12 @@ export function useClaudeEvents() {
|
|||
!chatStore._cancelledByUser
|
||||
) {
|
||||
if (count === 0) {
|
||||
const isWindows = navigator.userAgent.includes("Windows");
|
||||
chatStore._setError(
|
||||
tabId,
|
||||
"Claude process failed to start. Check that Claude Code CLI is installed and git-bash is available on Windows.",
|
||||
isWindows
|
||||
? "Claude process failed to start. Check that Claude Code CLI is installed and git-bash is available."
|
||||
: "Claude process failed to start. Check that Claude Code CLI is installed.",
|
||||
);
|
||||
} else {
|
||||
chatStore._setError(
|
||||
|
|
@ -423,11 +426,13 @@ export function useClaudeEvents() {
|
|||
) {
|
||||
log.error(`[${tabId}] CRITICAL: ${payload}`);
|
||||
}
|
||||
// Surface critical stderr messages to the user UI
|
||||
// Surface critical stderr messages to the user UI (only if no error is already set)
|
||||
if (
|
||||
payload.includes("git-bash") ||
|
||||
payload.includes("git bash") ||
|
||||
payload.includes("bash.exe")
|
||||
(payload.includes("git-bash") ||
|
||||
payload.includes("git bash") ||
|
||||
payload.includes("bash.exe")) &&
|
||||
!useClaudeChatStore.getState().tabs.find((t) => t.id === tabId)
|
||||
?.error
|
||||
) {
|
||||
useClaudeChatStore
|
||||
.getState()
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue