From bb8798a8444eb96af94236ba41ea0652b91baf59 Mon Sep 17 00:00:00 2001 From: Julia Date: Tue, 20 Sep 2022 17:50:29 -0400 Subject: [PATCH] WIP pls amend me Co-Authored-By: Max Brunsfeld Co-Authored-By: Mikayla Maki --- Cargo.lock | 1 + crates/project/Cargo.toml | 1 + crates/project/src/project.rs | 2 +- crates/project/src/worktree.rs | 76 +++++++++++++++++++++++++++++++++- 4 files changed, 78 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1f60f1d36c..040db0fd41 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3996,6 +3996,7 @@ dependencies = [ "fsevent", "futures", "fuzzy", + "git2", "gpui", "ignore", "language", diff --git a/crates/project/Cargo.toml b/crates/project/Cargo.toml index a4ea6f2286..76eef0efa7 100644 --- a/crates/project/Cargo.toml +++ b/crates/project/Cargo.toml @@ -52,6 +52,7 @@ smol = "1.2.5" thiserror = "1.0.29" toml = "0.5" rocksdb = "0.18" +git2 = { version = "0.15", default-features = false } [dev-dependencies] client = { path = "../client", features = ["test-support"] } diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 8fa1fe9622..4d16c6ad1f 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -4538,7 +4538,7 @@ impl Project { }) .detach(); } - + let push_strong_handle = { let worktree = worktree.read(cx); self.is_shared() || worktree.is_visible() || worktree.is_remote() diff --git a/crates/project/src/worktree.rs b/crates/project/src/worktree.rs index 4d2b509738..b054f93328 100644 --- a/crates/project/src/worktree.rs +++ b/crates/project/src/worktree.rs @@ -27,7 +27,7 @@ use language::{ Buffer, DiagnosticEntry, LineEnding, PointUtf16, Rope, }; use lazy_static::lazy_static; -use parking_lot::Mutex; +use parking_lot::{Mutex, RwLock}; use postage::{ prelude::{Sink as _, Stream as _}, watch, @@ -105,12 +105,20 @@ pub struct Snapshot { pub struct LocalSnapshot { abs_path: Arc, ignores_by_parent_abs_path: HashMap, (Arc, usize)>, + git_repositories: Vec, removed_entry_ids: HashMap, next_entry_id: Arc, snapshot: Snapshot, extension_counts: HashMap, } +#[derive(Clone)] +pub(crate) struct GitRepositoryState { + content_path: Arc, + git_dir_path: Arc, + repository: Arc>, +} + impl Deref for LocalSnapshot { type Target = Snapshot; @@ -143,6 +151,7 @@ struct ShareState { pub enum Event { UpdatedEntries, + UpdatedGitRepositories(Vec), } impl Entity for Worktree { @@ -373,6 +382,7 @@ impl LocalWorktree { let mut snapshot = LocalSnapshot { abs_path, ignores_by_parent_abs_path: Default::default(), + git_repositories: Default::default(), removed_entry_ids: Default::default(), next_entry_id, snapshot: Snapshot { @@ -504,6 +514,7 @@ impl LocalWorktree { fn poll_snapshot(&mut self, force: bool, cx: &mut ModelContext) { self.poll_task.take(); + match self.scan_state() { ScanState::Idle => { self.snapshot = self.background_snapshot.lock().clone(); @@ -512,6 +523,7 @@ impl LocalWorktree { } cx.emit(Event::UpdatedEntries); } + ScanState::Initializing => { let is_fake_fs = self.fs.is_fake(); self.snapshot = self.background_snapshot.lock().clone(); @@ -528,12 +540,14 @@ impl LocalWorktree { })); cx.emit(Event::UpdatedEntries); } + _ => { if force { self.snapshot = self.background_snapshot.lock().clone(); } } } + cx.notify(); } @@ -1285,6 +1299,10 @@ impl LocalSnapshot { pub fn extension_counts(&self) -> &HashMap { &self.extension_counts } + + pub(crate) fn git_repository_for_file_path(&self, path: &Path) -> Option { + None + } #[cfg(test)] pub(crate) fn build_initial_update(&self, project_id: u64) -> proto::UpdateWorktree { @@ -3042,6 +3060,61 @@ mod tests { assert!(tree.entry_for_path(".git").unwrap().is_ignored); }); } + + #[gpui::test] + async fn test_git_repository_for_path(cx: &mut TestAppContext) { + let fs = FakeFs::new(cx.background()); + fs.insert_tree( + "/root", + json!({ + "dir1": { + ".git": {}, + "deps": { + "dep1": { + ".git": {}, + "src": { + "a.txt": "" + } + } + }, + "src": { + "b.txt": "" + } + }, + "c.txt": "" + }), + ) + .await; + + let http_client = FakeHttpClient::with_404_response(); + let client = Client::new(http_client); + let tree = Worktree::local( + client, + Arc::from(Path::new("/root")), + true, + fs.clone(), + Default::default(), + &mut cx.to_async(), + ) + .await + .unwrap(); + + cx.foreground().run_until_parked(); + + tree.read_with(cx, |tree, cx| { + let tree = tree.as_local().unwrap(); + + assert!(tree.git_repository_for_file_path("c.txt".as_ref()).is_none()); + + let repo1 = tree.git_repository_for_file_path("dir1/src/b.txt".as_ref()).unwrap().lock(); + assert_eq!(repo1.content_path.as_ref(), Path::new("dir1")); + assert_eq!(repo1.git_dir_path.as_ref(), Path::new("dir1/.git")); + + let repo2 = tree.git_repository_for_file_path("dir1/deps/dep1/src/a.txt".as_ref()).unwrap().lock(); + assert_eq!(repo2.content_path.as_ref(), Path::new("dir1/deps/dep1")); + assert_eq!(repo2.git_dir_path.as_ref(), Path::new("dir1/deps/dep1/.git")); + }); + } #[gpui::test] async fn test_write_file(cx: &mut TestAppContext) { @@ -3161,6 +3234,7 @@ mod tests { abs_path: root_dir.path().into(), removed_entry_ids: Default::default(), ignores_by_parent_abs_path: Default::default(), + git_repositories: Default::default(), next_entry_id: next_entry_id.clone(), snapshot: Snapshot { id: WorktreeId::from_usize(0),