diff --git a/crates/worktree/src/worktree.rs b/crates/worktree/src/worktree.rs index 68db7a4272..f4aef93b4d 100644 --- a/crates/worktree/src/worktree.rs +++ b/crates/worktree/src/worktree.rs @@ -2696,13 +2696,28 @@ impl BackgroundScannerState { Arc>, TreeMap, )> { - log::info!("build git repository {:?}", dot_git_path); - - let work_dir_path: Arc = dot_git_path.parent().unwrap().into(); - - // Guard against repositories inside the repository metadata - if work_dir_path.iter().any(|component| component == *DOT_GIT) { - return None; + let work_dir_path: Arc = match dot_git_path.parent() { + Some(parent_dir) => { + // Guard against repositories inside the repository metadata + if parent_dir.iter().any(|component| component == *DOT_GIT) { + log::info!( + "not building git repository for nested `.git` directory, `.git` path in the worktree: {dot_git_path:?}" + ); + return None; + }; + log::info!( + "building git repository, `.git` path in the worktree: {dot_git_path:?}" + ); + parent_dir.into() + } + None => { + // `dot_git_path.parent().is_none()` means `.git` directory is the opened worktree itself, + // no files inside that directory are tracked by git, so no need to build the repo around it + log::info!( + "not building git repository for the worktree itself, `.git` path in the worktree: {dot_git_path:?}" + ); + return None; + } }; let work_dir_id = self diff --git a/crates/worktree/src/worktree_tests.rs b/crates/worktree/src/worktree_tests.rs index 52b1d09296..1feb36fb3e 100644 --- a/crates/worktree/src/worktree_tests.rs +++ b/crates/worktree/src/worktree_tests.rs @@ -1204,6 +1204,43 @@ async fn test_fs_events_in_exclusions(cx: &mut TestAppContext) { }); } +#[gpui::test] +async fn test_fs_events_in_dot_git_worktree(cx: &mut TestAppContext) { + init_test(cx); + cx.executor().allow_parking(); + let dir = temp_tree(json!({ + ".git": { + "HEAD": "ref: refs/heads/main\n", + "foo": "foo contents", + }, + })); + let dot_git_worktree_dir = dir.path().join(".git"); + + let tree = Worktree::local( + build_client(cx), + dot_git_worktree_dir.clone(), + true, + Arc::new(RealFs), + Default::default(), + &mut cx.to_async(), + ) + .await + .unwrap(); + cx.read(|cx| tree.read(cx).as_local().unwrap().scan_complete()) + .await; + tree.flush_fs_events(cx).await; + tree.read_with(cx, |tree, _| { + check_worktree_entries(tree, &[], &["HEAD", "foo"], &[]) + }); + + std::fs::write(dot_git_worktree_dir.join("new_file"), "new file contents") + .unwrap_or_else(|e| panic!("Failed to create in {dot_git_worktree_dir:?} a new file: {e}")); + tree.flush_fs_events(cx).await; + tree.read_with(cx, |tree, _| { + check_worktree_entries(tree, &[], &["HEAD", "foo", "new_file"], &[]) + }); +} + #[gpui::test(iterations = 30)] async fn test_create_directory_during_initial_scan(cx: &mut TestAppContext) { init_test(cx);