From 89fe3af99a57e6b0c44a6c2d95fcebd8b1cb1821 Mon Sep 17 00:00:00 2001 From: wuyangfan <1102042793@qq.com> Date: Sun, 17 May 2026 17:19:20 +0800 Subject: [PATCH] fix: AltGr text input in commit field and clearer repo open errors Treat Ctrl+Alt character input as text on Windows so AltGr layouts (e.g. German braces) work in the commit message field (#2848). Improve repository open error messages for discovery/not-found failures instead of misleading bare-repo wording (#2866). Co-authored-by: Cursor --- asyncgit/src/sync/utils.rs | 54 ++++++++++++++++++++++++++++++++----- src/components/textinput.rs | 34 ++++++++++++++++++++--- 2 files changed, 79 insertions(+), 9 deletions(-) diff --git a/asyncgit/src/sync/utils.rs b/asyncgit/src/sync/utils.rs index 148e29baa9..8386cb5940 100644 --- a/asyncgit/src/sync/utils.rs +++ b/asyncgit/src/sync/utils.rs @@ -24,20 +24,51 @@ pub struct Head { pub id: CommitId, } +fn format_repo_open_error(err: &str, path: &Path) -> String { + let err_lower = err.to_ascii_lowercase(); + + if err_lower.contains("bare") { + return format!( + "repository at '{}' appears to be bare; pass an explicit worktree with -w", + path.display() + ); + } + + if err_lower.contains("not found") + || err_lower.contains("could not find") + || err_lower.contains("no such file") + || err_lower.contains("failed to discover") + { + return format!( + "could not open git repository at '{}' ({err})\n\ + hint: verify the path exists and is readable (sandboxing may block access)", + path.display() + ); + } + + format!( + "could not open git repository at '{}': {err}", + path.display() + ) +} + /// pub fn repo_open_error(repo_path: &RepoPath) -> Option { + let path = repo_path.gitpath(); + if let Err(e) = Repository::open_ext( - repo_path.gitpath(), + path, RepositoryOpenFlags::FROM_ENV, Vec::<&Path>::new(), ) { - return Some(e.to_string()); + return Some(format_repo_open_error(&e.to_string(), path)); } - gix::ThreadSafeRepository::discover_with_environment_overrides( - repo_path.gitpath(), - ) - .map_or_else(|e| Some(e.to_string()), |_| None) + gix::ThreadSafeRepository::discover_with_environment_overrides(path) + .map_or_else( + |e| Some(format_repo_open_error(&e.to_string(), path)), + |_| None, + ) } /// @@ -482,6 +513,17 @@ mod tests { Ok(()) } + #[test] + fn format_repo_open_error_not_found() { + let msg = format_repo_open_error( + "repository not found", + Path::new("/i4/repo"), + ); + assert!(msg.contains("could not open git repository")); + assert!(msg.contains("sandboxing")); + assert!(!msg.to_ascii_lowercase().contains("non-bare")); + } + #[test] fn test_head_empty() -> Result<()> { let (_td, repo) = repo_init_empty()?; diff --git a/src/components/textinput.rs b/src/components/textinput.rs index 357fef1df1..5784804a74 100644 --- a/src/components/textinput.rs +++ b/src/components/textinput.rs @@ -259,15 +259,31 @@ impl TextInputComponent { } } + fn is_text_char_input(ctrl: bool, alt: bool) -> bool { + if !ctrl && !alt { + return true; + } + + #[cfg(windows)] + { + // AltGr is commonly reported as Ctrl+Alt on Windows (e.g. German `{` `}`) + if ctrl && alt { + return true; + } + } + + false + } + #[allow(clippy::too_many_lines, clippy::unnested_or_patterns)] fn process_inputs(ta: &mut TextArea<'_>, input: &Input) -> bool { match input { Input { key: Key::Char(c), - ctrl: false, - alt: false, + ctrl, + alt, .. - } => { + } if Self::is_text_char_input(*ctrl, *alt) => { ta.insert_char(*c); true } @@ -887,4 +903,16 @@ mod tests { assert_eq!(ta.cursor(), save_cursor); } } + + #[test] + fn test_is_text_char_input_without_modifiers() { + assert!(TextInputComponent::is_text_char_input(false, false)); + assert!(!TextInputComponent::is_text_char_input(true, false)); + } + + #[test] + #[cfg(windows)] + fn test_is_text_char_input_altgr() { + assert!(TextInputComponent::is_text_char_input(true, true)); + } }