diff --git a/crates/git/src/repository.rs b/crates/git/src/repository.rs index 32904aa9a9001187193c91a055a5e0393221514d..728d84e34d59626585fcec72d023bcef4dc79249 100644 --- a/crates/git/src/repository.rs +++ b/crates/git/src/repository.rs @@ -1046,7 +1046,6 @@ impl GitRepository for RealGitRepository { let git = git_binary?; let output = git .build_command(&[ - "--no-optional-locks", "show", "--no-patch", "--format=%H%x00%B%x00%at%x00%ae%x00%an%x00", @@ -1084,7 +1083,6 @@ impl GitRepository for RealGitRepository { let git = git_binary?; let show_output = git .build_command(&[ - "--no-optional-locks", "show", "--format=", "-z", @@ -1105,7 +1103,7 @@ impl GitRepository for RealGitRepository { let parent_sha = format!("{}^", commit); let mut cat_file_process = git - .build_command(&["--no-optional-locks", "cat-file", "--batch=%(objectsize)"]) + .build_command(&["cat-file", "--batch=%(objectsize)"]) .stdin(Stdio::piped()) .stdout(Stdio::piped()) .stderr(Stdio::piped()) @@ -1417,11 +1415,7 @@ impl GitRepository for RealGitRepository { .spawn(async move { let git = git_binary?; let mut process = git - .build_command(&[ - "--no-optional-locks", - "cat-file", - "--batch-check=%(objectname)", - ]) + .build_command(&["cat-file", "--batch-check=%(objectname)"]) .stdin(Stdio::piped()) .stdout(Stdio::piped()) .stderr(Stdio::piped()) @@ -1495,7 +1489,6 @@ impl GitRepository for RealGitRepository { }; let mut args = vec![ - OsString::from("--no-optional-locks"), OsString::from("diff-tree"), OsString::from("-r"), OsString::from("-z"), @@ -1612,7 +1605,7 @@ impl GitRepository for RealGitRepository { .spawn(async move { let git = git_binary?; let output = git - .build_command(&["--no-optional-locks", "worktree", "list", "--porcelain"]) + .build_command(&["worktree", "list", "--porcelain"]) .output() .await?; if output.status.success() { @@ -1634,7 +1627,6 @@ impl GitRepository for RealGitRepository { ) -> BoxFuture<'_, Result<()>> { let git_binary = self.git_binary(); let mut args = vec![ - OsString::from("--no-optional-locks"), OsString::from("worktree"), OsString::from("add"), OsString::from("-b"), @@ -1668,11 +1660,7 @@ impl GitRepository for RealGitRepository { self.executor .spawn(async move { - let mut args: Vec = vec![ - "--no-optional-locks".into(), - "worktree".into(), - "remove".into(), - ]; + let mut args: Vec = vec!["worktree".into(), "remove".into()]; if force { args.push("--force".into()); } @@ -1690,7 +1678,6 @@ impl GitRepository for RealGitRepository { self.executor .spawn(async move { let args: Vec = vec![ - "--no-optional-locks".into(), "worktree".into(), "move".into(), "--".into(), @@ -1833,7 +1820,7 @@ impl GitRepository for RealGitRepository { commit_delimiter ); - let mut args = vec!["--no-optional-locks", "log", "--follow", &format_string]; + let mut args = vec!["log", "--follow", &format_string]; let skip_str; let limit_str; @@ -2741,7 +2728,7 @@ async fn run_commit_data_reader( request_rx: smol::channel::Receiver, ) -> Result<()> { let mut process = git - .build_command(&["--no-optional-locks", "cat-file", "--batch"]) + .build_command(&["cat-file", "--batch"]) .stdin(Stdio::piped()) .stdout(Stdio::piped()) .stderr(Stdio::piped()) @@ -2855,7 +2842,6 @@ fn parse_initial_graph_output<'a>( fn git_status_args(path_prefixes: &[RepoPath]) -> Vec { let mut args = vec![ - OsString::from("--no-optional-locks"), OsString::from("status"), OsString::from("--porcelain=v1"), OsString::from("--untracked-files=all"), @@ -3039,6 +3025,7 @@ impl GitBinary { let mut command = new_command(&self.git_binary_path); command.current_dir(&self.working_directory); command.args(["-c", "core.fsmonitor=false"]); + command.arg("--no-optional-locks"); command.arg("--no-pager"); if !self.is_trusted { diff --git a/crates/worktree/src/worktree.rs b/crates/worktree/src/worktree.rs index 6bd78f55ad709212002d3cf6ffcd3d41da5d5f8b..07f01e21758aa79509e7d6466e2f3b798eb7b8d3 100644 --- a/crates/worktree/src/worktree.rs +++ b/crates/worktree/src/worktree.rs @@ -7,7 +7,9 @@ use chardetng::EncodingDetector; use clock::ReplicaId; use collections::{HashMap, HashSet, VecDeque}; use encoding_rs::Encoding; -use fs::{Fs, MTime, PathEvent, RemoveOptions, Watcher, copy_recursive, read_dir_items}; +use fs::{ + Fs, MTime, PathEvent, PathEventKind, RemoveOptions, Watcher, copy_recursive, read_dir_items, +}; use futures::{ FutureExt as _, Stream, StreamExt, channel::{ @@ -4137,7 +4139,7 @@ impl BackgroundScanner { } for (ix, event) in events.iter().enumerate() { - let abs_path = &SanitizedPath::new(&event.path); + let abs_path = SanitizedPath::new(&event.path); let mut is_git_related = false; let mut dot_git_paths = None; @@ -4154,13 +4156,33 @@ impl BackgroundScanner { } if let Some((dot_git_abs_path, path_in_git_dir)) = dot_git_paths { - if skipped_files_in_dot_git + // We ignore `""` as well, as that is going to be the + // `.git` folder itself. WE do not care about it, if + // there are changes within we will see them, we need + // this ignore to prevent us from accidentally observing + // the ignored created file due to the events not being + // empty after filtering. + + let is_dot_git_changed = { + path_in_git_dir == Path::new("") + && event.kind == Some(PathEventKind::Changed) + && abs_path + .strip_prefix(root_canonical_path) + .ok() + .and_then(|it| RelPath::new(it, PathStyle::local()).ok()) + .is_some_and(|it| { + snapshot + .entry_for_path(&it) + .is_some_and(|entry| entry.kind == EntryKind::Dir) + }) + }; + let condition = skipped_files_in_dot_git.iter().any(|skipped| { + OsStr::new(skipped) == path_in_git_dir.as_path().as_os_str() + }) || skipped_dirs_in_dot_git .iter() - .any(|skipped| OsStr::new(skipped) == path_in_git_dir.as_path().as_os_str()) - || skipped_dirs_in_dot_git.iter().any(|skipped_git_subdir| { - path_in_git_dir.starts_with(skipped_git_subdir) - }) - { + .any(|skipped_git_subdir| path_in_git_dir.starts_with(skipped_git_subdir)) + || is_dot_git_changed; + if condition { log::debug!( "ignoring event {abs_path:?} as it's in the .git directory among skipped files or directories" );