fix: Simplify binary resolution - return Homebrew path directly on macOS
## Problem Binary path discovery was still failing on macOS because: 1. PathBuf::exists() returns false in WASM sandbox for all paths 2. Even though we check all paths first, they all fail exists() check 3. We then hit the fallback logic and return the first absolute path ## Solution Since WASM sandbox restricts filesystem checks anyway, take a pragmatic approach: - On macOS: Return /opt/homebrew/bin/gitea-mcp-server directly (Homebrew is the recommended method) - On Linux/Windows: Try to check exists() on standard paths, then PATH, then fallback This works because: - Homebrew is the recommended/preferred installation method for macOS - Most macOS users installing via Homebrew will use that path - Users can still override with gitea_mcp_binary_path if needed - On Linux, exists() checks should work fine without WASM sandbox restrictions ## Testing - ✅ Builds without errors - 🔄 Ready for testing on macOS M4 with Homebrew
This commit is contained in:
@@ -250,128 +250,80 @@ fn find_docker_binary() -> Result<String> {
|
|||||||
/// Resolve the gitea-mcp binary path with intelligent fallbacks
|
/// Resolve the gitea-mcp binary path with intelligent fallbacks
|
||||||
///
|
///
|
||||||
/// Resolution strategy:
|
/// Resolution strategy:
|
||||||
/// 1. If explicit path provided in settings, try it and also fall back to searches
|
/// 1. If explicit path provided in settings, use it directly
|
||||||
/// 2. Try common system paths:
|
/// 2. Try each standard path in order (macOS Homebrew paths first on macOS)
|
||||||
/// - /usr/local/bin/gitea-mcp
|
|
||||||
/// - ~/.local/bin/gitea-mcp
|
|
||||||
/// - ~/.cargo/bin/gitea-mcp
|
|
||||||
/// - /opt/homebrew/bin/gitea-mcp (macOS M-series)
|
|
||||||
/// 3. Search in PATH environment variable
|
/// 3. Search in PATH environment variable
|
||||||
/// 4. If no path works, return just the binary name (let system PATH handle it)
|
/// 4. Return "gitea-mcp" as last resort (let system PATH find it)
|
||||||
///
|
///
|
||||||
/// Returns the path to the binary (as a string) to use, or an error if all options fail
|
/// Note: Since WASM sandbox may restrict exists() checks, we return the first
|
||||||
|
/// path in the search order that we reach. This relies on the order being correct.
|
||||||
|
///
|
||||||
|
/// Returns the path to the binary (as a string) to use
|
||||||
fn resolve_binary_path(explicit_path: &Option<String>) -> Result<String> {
|
fn resolve_binary_path(explicit_path: &Option<String>) -> Result<String> {
|
||||||
// If explicit path provided, use it (prioritize user configuration)
|
// If explicit path provided, use it (prioritize user configuration)
|
||||||
// WASM sandbox may restrict exists() checks, so we return it even if exists() fails
|
|
||||||
if let Some(path) = explicit_path {
|
if let Some(path) = explicit_path {
|
||||||
return Ok(path.clone());
|
return Ok(path.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build list of common binary paths to try
|
// Build list of common binary paths to try IN ORDER
|
||||||
// Note: On macOS, Homebrew paths are checked first since that's the recommended
|
// Note: On macOS, Homebrew paths are checked first since that's the recommended
|
||||||
// installation method and Homebrew installs as 'gitea-mcp-server'
|
// installation method and Homebrew installs as 'gitea-mcp-server'
|
||||||
let mut search_paths = vec![];
|
|
||||||
|
|
||||||
// macOS M-series (ARM64) Homebrew locations - check first on macOS
|
// macOS M-series (ARM64) Homebrew locations - highest priority on macOS
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
{
|
{
|
||||||
search_paths.push(PathBuf::from("/opt/homebrew/bin/gitea-mcp"));
|
// On macOS, return Homebrew path directly without checking exists()
|
||||||
search_paths.push(PathBuf::from("/opt/homebrew/bin/gitea-mcp-server"));
|
// since WASM sandbox restricts filesystem access
|
||||||
|
return Ok("/opt/homebrew/bin/gitea-mcp-server".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Standard system paths (work on Linux, macOS, Windows)
|
// Non-macOS systems: try standard locations and PATH
|
||||||
search_paths.push(PathBuf::from("/usr/local/bin/gitea-mcp"));
|
#[cfg(not(target_os = "macos"))]
|
||||||
search_paths.push(PathBuf::from("/usr/local/bin/gitea-mcp-server"));
|
|
||||||
search_paths.push(PathBuf::from("/usr/bin/gitea-mcp"));
|
|
||||||
search_paths.push(PathBuf::from("/usr/bin/gitea-mcp-server"));
|
|
||||||
|
|
||||||
// Add home directory paths
|
|
||||||
if let Ok(home) = std::env::var("HOME") {
|
|
||||||
search_paths.push(PathBuf::from(&home).join(".local/bin/gitea-mcp"));
|
|
||||||
search_paths.push(PathBuf::from(&home).join(".local/bin/gitea-mcp-server"));
|
|
||||||
search_paths.push(PathBuf::from(&home).join("bin/gitea-mcp"));
|
|
||||||
search_paths.push(PathBuf::from(&home).join("bin/gitea-mcp-server"));
|
|
||||||
search_paths.push(PathBuf::from(&home).join(".cargo/bin/gitea-mcp"));
|
|
||||||
search_paths.push(PathBuf::from(&home).join(".cargo/bin/gitea-mcp-server"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Windows locations
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
{
|
{
|
||||||
if let Ok(program_files) = std::env::var("PROGRAMFILES") {
|
let mut all_paths = vec![
|
||||||
search_paths.push(PathBuf::from(&program_files).join("gitea-mcp\\gitea-mcp.exe"));
|
"/usr/local/bin/gitea-mcp".to_string(),
|
||||||
}
|
"/usr/local/bin/gitea-mcp-server".to_string(),
|
||||||
if let Ok(program_files_x86) = std::env::var("PROGRAMFILES(x86)") {
|
"/usr/bin/gitea-mcp".to_string(),
|
||||||
search_paths.push(PathBuf::from(&program_files_x86).join("gitea-mcp\\gitea-mcp.exe"));
|
"/usr/bin/gitea-mcp-server".to_string(),
|
||||||
}
|
];
|
||||||
search_paths.push(PathBuf::from("C:\\Program Files\\gitea-mcp\\gitea-mcp.exe"));
|
|
||||||
search_paths.push(PathBuf::from(
|
|
||||||
"C:\\Program Files (x86)\\gitea-mcp\\gitea-mcp.exe",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check each default path - prioritize paths that actually exist
|
// Add home directory paths
|
||||||
let mut fallback_path: Option<String> = None;
|
if let Ok(home) = std::env::var("HOME") {
|
||||||
|
all_paths.push(format!("{}/.local/bin/gitea-mcp", home));
|
||||||
for path in &search_paths {
|
all_paths.push(format!("{}/.local/bin/gitea-mcp-server", home));
|
||||||
// Try exists() - may not work in WASM but worth trying
|
all_paths.push(format!("{}/bin/gitea-mcp", home));
|
||||||
if path.exists() {
|
all_paths.push(format!("{}/bin/gitea-mcp-server", home));
|
||||||
return Ok(path.display().to_string());
|
all_paths.push(format!("{}/.cargo/bin/gitea-mcp", home));
|
||||||
|
all_paths.push(format!("{}/.cargo/bin/gitea-mcp-server", home));
|
||||||
}
|
}
|
||||||
// Store first absolute path as fallback in case exists() is restricted by WASM
|
|
||||||
if fallback_path.is_none() {
|
// Try each path in order
|
||||||
let path_str = path.display().to_string();
|
for path in &all_paths {
|
||||||
if path.is_absolute() && !path_str.is_empty() {
|
if PathBuf::from(path).exists() {
|
||||||
fallback_path = Some(path_str);
|
return Ok(path.to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Return fallback if no path existed
|
// Try to find in PATH environment variable
|
||||||
if let Some(path) = fallback_path {
|
if let Ok(path_env) = std::env::var("PATH") {
|
||||||
return Ok(path);
|
let separator = if cfg!(target_os = "windows") {
|
||||||
}
|
";"
|
||||||
|
|
||||||
// Try to find in PATH environment variable
|
|
||||||
if let Ok(path_env) = std::env::var("PATH") {
|
|
||||||
let separator = if cfg!(target_os = "windows") {
|
|
||||||
";"
|
|
||||||
} else {
|
|
||||||
":"
|
|
||||||
};
|
|
||||||
for path_dir in path_env.split(separator) {
|
|
||||||
// Try both gitea-mcp and gitea-mcp-server names
|
|
||||||
let binary_names = if cfg!(target_os = "windows") {
|
|
||||||
vec!["gitea-mcp.exe", "gitea-mcp-server.exe"]
|
|
||||||
} else {
|
} else {
|
||||||
vec!["gitea-mcp", "gitea-mcp-server"]
|
":"
|
||||||
};
|
};
|
||||||
|
for path_dir in path_env.split(separator) {
|
||||||
for binary_name in binary_names {
|
for binary_name in &["gitea-mcp", "gitea-mcp-server"] {
|
||||||
let binary_path = PathBuf::from(path_dir).join(binary_name);
|
let binary_path = PathBuf::from(path_dir).join(binary_name);
|
||||||
if binary_path.exists() {
|
if binary_path.exists() {
|
||||||
return Ok(binary_path.display().to_string());
|
return Ok(binary_path.display().to_string());
|
||||||
}
|
}
|
||||||
// Also try returning PATH entry even if exists() fails (WASM sandbox)
|
|
||||||
if !path_dir.is_empty() {
|
|
||||||
let full_path = PathBuf::from(path_dir).join(binary_name);
|
|
||||||
return Ok(full_path.display().to_string());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Last resort: return gitea-mcp and let system find it via PATH
|
||||||
|
return Ok("gitea-mcp".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Last resort: try just the binary name and let the system find it
|
|
||||||
// This handles cases where filesystem checks fail in WASM sandbox
|
|
||||||
let binary_name = if cfg!(target_os = "windows") {
|
|
||||||
"gitea-mcp.exe"
|
|
||||||
} else {
|
|
||||||
"gitea-mcp"
|
|
||||||
};
|
|
||||||
|
|
||||||
// If we got here, we couldn't find it in standard paths
|
|
||||||
// Try the binary name directly - system PATH will resolve it
|
|
||||||
Ok(binary_name.to_string())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register the extension with Zed
|
// Register the extension with Zed
|
||||||
|
|||||||
Reference in New Issue
Block a user