Skip to content

Conversation

@Rettend
Copy link

@Rettend Rettend commented Dec 23, 2025

fix #10665

Cursor sends paths in this format: /c:/Users, I'm not sure why, but to my knowledge this prevents GitButler from working with Cursor Hooks on Windows.

The fix just removes the slash.

I verified that after the fix but cursor after-edit and but cursor stop are triggered and finish.

Copilot AI review requested due to automatic review settings December 23, 2025 22:35
@vercel
Copy link

vercel bot commented Dec 23, 2025

@Rettend is attempting to deploy a commit to the GitButler Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions github-actions bot added the rust Pull requests that update Rust code label Dec 23, 2025
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a Windows-specific issue where Cursor hooks fail because Cursor sends workspace paths in the format /c:/Users/... instead of the standard C:/Users/.... The leading slash causes GitButler CLI commands to fail with "Failed to access a directory" errors.

Key Changes:

  • Added cursor_path_to_pathbuf() function that detects and strips the leading slash from Windows drive paths in the /c:/ format
  • Updated handle_after_edit() and handle_stop() to use the new path conversion function
  • Added basic unit tests to verify the path transformation behavior

Comment on lines +326 to +337
fn test_cursor_path_to_pathbuf_windows_drive_paths() {
#[cfg(target_os = "windows")]
{
assert_eq!(
cursor_path_to_pathbuf("/C:/repo").to_string_lossy(),
"C:/repo"
);
assert_eq!(
cursor_path_to_pathbuf("/M:/work/repo").to_string_lossy(),
"M:/work/repo"
);
}
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function should also handle edge cases where paths are malformed or have lowercase drive letters. Consider adding test cases for:

  • Lowercase drive letters (e.g., /c:/repo instead of /C:/repo)
  • Edge case where the path is exactly /C: (length < 3 after stripping prefix)
  • Paths with backslashes (e.g., /C:\repo)

The current byte checking at position 1 would be correct for lowercase drive letters since ASCII 'c' and 'C' both have ':' at position 1 when checking without_leading_slash.as_bytes()[1], but the tests should verify this behavior explicitly.

Copilot uses AI. Check for mistakes.
Comment on lines +326 to +337
fn test_cursor_path_to_pathbuf_windows_drive_paths() {
#[cfg(target_os = "windows")]
{
assert_eq!(
cursor_path_to_pathbuf("/C:/repo").to_string_lossy(),
"C:/repo"
);
assert_eq!(
cursor_path_to_pathbuf("/M:/work/repo").to_string_lossy(),
"M:/work/repo"
);
}
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test should also verify that paths without the problematic format are left unchanged on Windows. For example, regular Windows paths like C:/repo (without the leading slash) should remain as C:/repo, and Unix-style paths like /home/user should remain unchanged. This ensures the function doesn't modify paths unnecessarily.

Copilot uses AI. Check for mistakes.
{
if let Some(without_leading_slash) = input.strip_prefix('/') {
let b = without_leading_slash.as_bytes();
if b.len() >= 3 && b[1] == b':' && (b[2] == b'/' || b[2] == b'\\') {
Copy link

Copilot AI Dec 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The byte index check uses hardcoded positions (b[1] and b[2]) but doesn't explicitly validate that b[0] is an ASCII alphabetic character representing a drive letter. While the current logic may work in practice since Cursor sends valid drive letters, it would be more robust to check that b[0] is in the range A-Z or a-z. This would prevent false positives for paths like /1:/foo being treated as Windows drive paths.

Suggested change
if b.len() >= 3 && b[1] == b':' && (b[2] == b'/' || b[2] == b'\\') {
if b.len() >= 3
&& ((b[0] >= b'a' && b[0] <= b'z') || (b[0] >= b'A' && b[0] <= b'Z'))
&& b[1] == b':'
&& (b[2] == b'/' || b[2] == b'\\')
{

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

rust Pull requests that update Rust code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cursor hooks: but cursor after-edit/stop fails when workspace_roots is /m:/... on Windows

1 participant