Fixed opening workspace with wrong command

This commit is contained in:
Andrew Zambazos
2026-05-13 20:32:27 +12:00
parent f69841ada9
commit 397714f34e
+61 -5
View File
@@ -6,10 +6,15 @@ use std::collections::HashSet;
use std::env; use std::env;
use std::fs; use std::fs;
use std::io::Cursor; use std::io::Cursor;
#[cfg(target_os = "windows")]
use std::os::windows::process::CommandExt;
use std::path::Path; use std::path::Path;
use std::path::PathBuf; use std::path::PathBuf;
use std::process::Command; use std::process::Command;
#[cfg(target_os = "windows")]
const CREATE_NO_WINDOW: u32 = 0x08000000;
#[derive(Serialize)] #[derive(Serialize)]
struct GitCommandResult { struct GitCommandResult {
command: String, command: String,
@@ -163,6 +168,13 @@ fn resolve_git_binary(git_path: Option<String>) -> String {
.to_string() .to_string()
} }
fn new_background_command(program: &str) -> Command {
let mut command = Command::new(program);
#[cfg(target_os = "windows")]
command.creation_flags(CREATE_NO_WINDOW);
command
}
fn run_git_command( fn run_git_command(
repo_path: Option<&str>, repo_path: Option<&str>,
git_path: Option<String>, git_path: Option<String>,
@@ -170,7 +182,7 @@ fn run_git_command(
) -> Result<GitCommandResult, String> { ) -> Result<GitCommandResult, String> {
// Central command executor keeps Git command behavior consistent. // Central command executor keeps Git command behavior consistent.
let git_binary = resolve_git_binary(git_path); let git_binary = resolve_git_binary(git_path);
let mut command = Command::new(&git_binary); let mut command = new_background_command(&git_binary);
if let Some(path) = repo_path { if let Some(path) = repo_path {
if !Path::new(path).exists() { if !Path::new(path).exists() {
@@ -203,7 +215,8 @@ fn run_git_output(
return Err(format!("Repository path does not exist: {path}")); return Err(format!("Repository path does not exist: {path}"));
} }
let output = Command::new(&git_binary) let mut command = new_background_command(&git_binary);
let output = command
.current_dir(path) .current_dir(path)
.args(&args) .args(&args)
.output() .output()
@@ -246,6 +259,48 @@ fn validate_repo_dir(repo_path: &str) -> Result<String, String> {
Ok(path.to_string()) Ok(path.to_string())
} }
#[cfg(target_os = "windows")]
fn normalize_windows_verbatim_path(path: &str) -> String {
if let Some(stripped) = path.strip_prefix(r"\\?\UNC\") {
format!(r"\\{stripped}")
} else if let Some(stripped) = path.strip_prefix(r"\\?\") {
stripped.to_string()
} else {
path.to_string()
}
}
fn user_facing_path(path: &Path) -> String {
let path = path.to_string_lossy().to_string();
#[cfg(target_os = "windows")]
{
normalize_windows_verbatim_path(&path)
}
#[cfg(not(target_os = "windows"))]
{
path
}
}
fn repo_display_path(path: &Path) -> String {
let display_path = path.canonicalize().unwrap_or_else(|_| path.to_path_buf());
user_facing_path(&display_path)
}
fn normalize_external_repo_path(path: &str) -> String {
#[cfg(target_os = "windows")]
{
normalize_windows_verbatim_path(path)
}
#[cfg(not(target_os = "windows"))]
{
path.to_string()
}
}
fn validate_git_path(path: &str) -> Result<String, String> { fn validate_git_path(path: &str) -> Result<String, String> {
let normalized = normalize_repo_path(path)?; let normalized = normalize_repo_path(path)?;
if normalized.is_empty() { if normalized.is_empty() {
@@ -870,7 +925,7 @@ fn normalize_git_remote_url(value: &str) -> String {
fn local_remote_urls(repo_path: &Path, git_path: Option<String>) -> Vec<String> { fn local_remote_urls(repo_path: &Path, git_path: Option<String>) -> Vec<String> {
let git_binary = resolve_git_binary(git_path); let git_binary = resolve_git_binary(git_path);
let Ok(output) = Command::new(&git_binary) let Ok(output) = new_background_command(&git_binary)
.current_dir(repo_path) .current_dir(repo_path)
.args(["config", "--get-regexp", r"^remote\..*\.url$"]) .args(["config", "--get-regexp", r"^remote\..*\.url$"])
.output() .output()
@@ -915,8 +970,7 @@ fn collect_repo_candidates(
if is_git_repo(root) { if is_git_repo(root) {
if seen.insert(dedupe_key(root)) { if seen.insert(dedupe_key(root)) {
let display_path = root.canonicalize().unwrap_or_else(|_| root.to_path_buf()); let path = repo_display_path(root);
let path = display_path.to_string_lossy().to_string();
let Some(matched_remote_url) = let Some(matched_remote_url) =
matched_server_remote(root, git_path.clone(), allowed_remote_urls) matched_server_remote(root, git_path.clone(), allowed_remote_urls)
else { else {
@@ -1534,6 +1588,7 @@ fn commit_detail(
#[tauri::command] #[tauri::command]
fn open_in_file_explorer(repo_path: String) -> Result<(), String> { fn open_in_file_explorer(repo_path: String) -> Result<(), String> {
let repo_path = validate_repo_dir(&repo_path)?; let repo_path = validate_repo_dir(&repo_path)?;
let repo_path = normalize_external_repo_path(&repo_path);
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
let mut command = { let mut command = {
let mut cmd = Command::new("explorer"); let mut cmd = Command::new("explorer");
@@ -1562,6 +1617,7 @@ fn open_in_file_explorer(repo_path: String) -> Result<(), String> {
#[tauri::command] #[tauri::command]
fn open_in_external_editor(repo_path: String, editor_path: String) -> Result<(), String> { fn open_in_external_editor(repo_path: String, editor_path: String) -> Result<(), String> {
let repo_path = validate_repo_dir(&repo_path)?; let repo_path = validate_repo_dir(&repo_path)?;
let repo_path = normalize_external_repo_path(&repo_path);
let editor_path = editor_path.trim(); let editor_path = editor_path.trim();
if editor_path.is_empty() { if editor_path.is_empty() {
return Err("Configure an external editor command in Settings first.".to_string()); return Err("Configure an external editor command in Settings first.".to_string());