Remove git repos from worktree when deleted on storage

Co-Authored-By: Mikayla Maki <mikayla@zed.dev>
This commit is contained in:
Julia 2022-09-27 14:07:53 -04:00
parent 4251e0f5f1
commit d2b18790a0
2 changed files with 50 additions and 20 deletions

View file

@ -56,7 +56,7 @@ impl GitRepository {
self.last_scan_id = scan_id;
}
pub fn with_repo(&mut self, f: Box<dyn FnOnce(&mut git2::Repository)>) {
pub fn with_repo<F: FnOnce(&mut git2::Repository)>(&mut self, f: F) {
let mut git2 = self.libgit_repository.lock();
f(&mut git2)
}

View file

@ -1311,9 +1311,7 @@ impl LocalSnapshot {
self.git_repositories
.iter()
.rev() //git_repository is ordered lexicographically
.find(|repo| {
repo.is_path_managed_by(&self.abs_path.join(path))
})
.find(|repo| repo.is_path_managed_by(&self.abs_path.join(path)))
.map(|repo| repo.clone())
}
@ -2548,13 +2546,16 @@ impl BackgroundScanner {
}
async fn update_git_repositories(&self) {
let mut snapshot = self.snapshot();
let mut git_repositories = mem::take(&mut snapshot.git_repositories);
git_repositories.retain(|git_repository| {
let dot_git_path = git_repository.content_path().join(&*DOT_GIT);
snapshot.entry_for_path(dot_git_path).is_some()
});
snapshot.git_repositories = git_repositories;
let mut snapshot = self.snapshot.lock();
let new_repos = snapshot
.git_repositories
.iter()
.cloned()
.filter(|repo| git2::Repository::open(repo.git_dir_path()).is_ok())
.collect();
snapshot.git_repositories = new_repos;
}
async fn update_ignore_status(&self, job: UpdateIgnoreStatusJob, snapshot: &LocalSnapshot) {
@ -3179,30 +3180,59 @@ mod tests {
.git_repository_for_file_path("dir1/src/b.txt".as_ref())
.unwrap();
// Need to update the file system for anything involving git
// Goal: Make this test pass
// Up Next: Invalidating git repos!
assert_eq!(repo.content_path(), root.path().join("dir1").canonicalize().unwrap());
assert_eq!(repo.git_dir_path(), root.path().join("dir1/.git").canonicalize().unwrap());
assert_eq!(
repo.content_path(),
root.path().join("dir1").canonicalize().unwrap()
);
assert_eq!(
repo.git_dir_path(),
root.path().join("dir1/.git").canonicalize().unwrap()
);
let repo = tree
.git_repository_for_file_path("dir1/deps/dep1/src/a.txt".as_ref())
.unwrap();
assert_eq!(repo.content_path(), root.path().join("dir1/deps/dep1").canonicalize().unwrap());
assert_eq!(repo.git_dir_path(), root.path().join("dir1/deps/dep1/.git").canonicalize().unwrap());
assert_eq!(
repo.content_path(),
root.path().join("dir1/deps/dep1").canonicalize().unwrap()
);
assert_eq!(
repo.git_dir_path(),
root.path()
.join("dir1/deps/dep1/.git")
.canonicalize()
.unwrap()
);
let repo = tree
.git_repository_for_git_data("dir1/.git/HEAD".as_ref())
.unwrap();
assert_eq!(repo.content_path(), root.path().join("dir1").canonicalize().unwrap());
assert_eq!(repo.git_dir_path(), root.path().join("dir1/.git").canonicalize().unwrap());
assert_eq!(
repo.content_path(),
root.path().join("dir1").canonicalize().unwrap()
);
assert_eq!(
repo.git_dir_path(),
root.path().join("dir1/.git").canonicalize().unwrap()
);
assert!(tree.does_git_repository_track_file_path(&repo, "dir1/src/b.txt".as_ref()));
assert!(!tree
.does_git_repository_track_file_path(&repo, "dir1/deps/dep1/src/a.txt".as_ref()));
});
std::fs::remove_dir_all(root.path().join("dir1/.git")).unwrap();
tree.flush_fs_events(cx).await;
tree.read_with(cx, |tree, _cx| {
let tree = tree.as_local().unwrap();
assert!(tree
.git_repository_for_file_path("dir1/src/b.txt".as_ref())
.is_none());
});
}
#[gpui::test]