git: Make worktrees work for bare git repositories (#21596)
Fixes #21210 by ensuring that Zed can open worktrees of bare git repositories. Co-authored-by: Peter Tripp <peter@zed.dev>
This commit is contained in:
parent
6ebd6c2893
commit
2d43ad12e6
2 changed files with 44 additions and 11 deletions
|
@ -3110,12 +3110,8 @@ impl BackgroundScannerState {
|
|||
let repository = fs.open_repo(&dot_git_abs_path)?;
|
||||
|
||||
let actual_repo_path = repository.path();
|
||||
let actual_dot_git_dir_abs_path: Arc<Path> = Arc::from(
|
||||
actual_repo_path
|
||||
.ancestors()
|
||||
.find(|ancestor| ancestor.file_name() == Some(&*DOT_GIT))?,
|
||||
);
|
||||
|
||||
let actual_dot_git_dir_abs_path = smol::block_on(find_git_dir(&actual_repo_path, fs))?;
|
||||
watcher.add(&actual_repo_path).log_err()?;
|
||||
|
||||
let dot_git_worktree_abs_path = if actual_dot_git_dir_abs_path.as_ref() == dot_git_abs_path
|
||||
|
@ -3161,6 +3157,31 @@ impl BackgroundScannerState {
|
|||
}
|
||||
}
|
||||
|
||||
async fn is_git_dir(path: &Path, fs: &dyn Fs) -> bool {
|
||||
if path.file_name() == Some(&*DOT_GIT) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If we're in a bare repository, we are not inside a `.git` folder. In a
|
||||
// bare repository, the root folder contains what would normally be in the
|
||||
// `.git` folder.
|
||||
let head_metadata = fs.metadata(&path.join("HEAD")).await;
|
||||
if !matches!(head_metadata, Ok(Some(_))) {
|
||||
return false;
|
||||
}
|
||||
let config_metadata = fs.metadata(&path.join("config")).await;
|
||||
matches!(config_metadata, Ok(Some(_)))
|
||||
}
|
||||
|
||||
async fn find_git_dir(path: &Path, fs: &dyn Fs) -> Option<Arc<Path>> {
|
||||
for ancestor in path.ancestors() {
|
||||
if is_git_dir(ancestor, fs).await {
|
||||
return Some(Arc::from(ancestor));
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
async fn build_gitignore(abs_path: &Path, fs: &dyn Fs) -> Result<Gitignore> {
|
||||
let contents = fs.load(abs_path).await?;
|
||||
let parent = abs_path.parent().unwrap_or_else(|| Path::new("/"));
|
||||
|
@ -3967,7 +3988,7 @@ impl BackgroundScanner {
|
|||
} else if fsmonitor_parse_state == Some(FsMonitorParseState::Cookies) && file_name == Some(*FSMONITOR_DAEMON) {
|
||||
fsmonitor_parse_state = Some(FsMonitorParseState::FsMonitor);
|
||||
false
|
||||
} else if fsmonitor_parse_state != Some(FsMonitorParseState::FsMonitor) && file_name == Some(*DOT_GIT) {
|
||||
} else if fsmonitor_parse_state != Some(FsMonitorParseState::FsMonitor) && smol::block_on(is_git_dir(ancestor, self.fs.as_ref())) {
|
||||
true
|
||||
} else {
|
||||
fsmonitor_parse_state.take();
|
||||
|
|
|
@ -12,7 +12,13 @@ use pretty_assertions::assert_eq;
|
|||
use rand::prelude::*;
|
||||
use serde_json::json;
|
||||
use settings::{Settings, SettingsStore};
|
||||
use std::{env, fmt::Write, mem, path::Path, sync::Arc};
|
||||
use std::{
|
||||
env,
|
||||
fmt::Write,
|
||||
mem,
|
||||
path::{Path, PathBuf},
|
||||
sync::Arc,
|
||||
};
|
||||
use util::{test::temp_tree, ResultExt};
|
||||
|
||||
#[gpui::test]
|
||||
|
@ -532,14 +538,20 @@ async fn test_open_gitignored_files(cx: &mut TestAppContext) {
|
|||
assert_eq!(fs.read_dir_call_count() - prev_read_dir_count, 1);
|
||||
});
|
||||
|
||||
let path = PathBuf::from("/root/one/node_modules/c/lib");
|
||||
|
||||
// No work happens when files and directories change within an unloaded directory.
|
||||
let prev_fs_call_count = fs.read_dir_call_count() + fs.metadata_call_count();
|
||||
fs.create_dir("/root/one/node_modules/c/lib".as_ref())
|
||||
.await
|
||||
.unwrap();
|
||||
// When we open a directory, we check each ancestor whether it's a git
|
||||
// repository. That means we have an fs.metadata call per ancestor that we
|
||||
// need to subtract here.
|
||||
let ancestors = path.ancestors().count();
|
||||
|
||||
fs.create_dir(path.as_ref()).await.unwrap();
|
||||
cx.executor().run_until_parked();
|
||||
|
||||
assert_eq!(
|
||||
fs.read_dir_call_count() + fs.metadata_call_count() - prev_fs_call_count,
|
||||
fs.read_dir_call_count() + fs.metadata_call_count() - prev_fs_call_count - ancestors,
|
||||
0
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue