Track index instead of head for diffs

Julia created

Change summary

crates/git/src/repository.rs   | 32 +++++++++++++++++++++++---------
crates/project/src/fs.rs       |  7 +++++--
crates/project/src/worktree.rs |  8 +++++++-
3 files changed, 35 insertions(+), 12 deletions(-)

Detailed changes

crates/git/src/repository.rs 🔗

@@ -18,6 +18,8 @@ pub trait GitRepository: Send + Sync + std::fmt::Debug {
 
     fn set_scan_id(&mut self, scan_id: usize);
 
+    fn reopen_git_repo(&mut self) -> bool;
+
     fn git_repo(&self) -> Arc<Mutex<LibGitRepository>>;
 
     fn boxed_clone(&self) -> Box<dyn GitRepository>;
@@ -79,18 +81,15 @@ impl GitRepository for RealGitRepository {
 
     async fn load_head_text(&self, relative_file_path: &Path) -> Option<String> {
         fn logic(repo: &LibGitRepository, relative_file_path: &Path) -> Result<Option<String>> {
-            let object = repo
-                .head()?
-                .peel_to_tree()?
-                .get_path(relative_file_path)?
-                .to_object(&repo)?;
-
-            let content = match object.as_blob() {
-                Some(blob) => blob.content().to_owned(),
+            const STAGE_NORMAL: i32 = 0;
+            let index = repo.index()?;
+            let oid = match index.get_path(relative_file_path, STAGE_NORMAL) {
+                Some(entry) => entry.id,
                 None => return Ok(None),
             };
 
-            let head_text = String::from_utf8(content.to_owned())?;
+            let content = repo.find_blob(oid)?.content().to_owned();
+            let head_text = String::from_utf8(content)?;
             Ok(Some(head_text))
         }
 
@@ -101,6 +100,17 @@ impl GitRepository for RealGitRepository {
         None
     }
 
+    fn reopen_git_repo(&mut self) -> bool {
+        match LibGitRepository::open(&self.git_dir_path) {
+            Ok(repo) => {
+                self.libgit_repository = Arc::new(Mutex::new(repo));
+                true
+            }
+
+            Err(_) => false,
+        }
+    }
+
     fn git_repo(&self) -> Arc<Mutex<LibGitRepository>> {
         self.libgit_repository.clone()
     }
@@ -168,6 +178,10 @@ impl GitRepository for FakeGitRepository {
         unimplemented!()
     }
 
+    fn reopen_git_repo(&mut self) -> bool {
+        unimplemented!()
+    }
+
     fn git_repo(&self) -> Arc<Mutex<LibGitRepository>> {
         unimplemented!()
     }

crates/project/src/fs.rs 🔗

@@ -1,7 +1,7 @@
 use anyhow::{anyhow, Result};
 use fsevent::EventStream;
 use futures::{future::BoxFuture, Stream, StreamExt};
-use git::repository::{FakeGitRepository, GitRepository, RealGitRepository};
+use git::repository::{GitRepository, RealGitRepository};
 use language::LineEnding;
 use smol::io::{AsyncReadExt, AsyncWriteExt};
 use std::{
@@ -854,7 +854,10 @@ impl Fs for FakeFs {
     }
 
     fn open_repo(&self, abs_dot_git: &Path) -> Option<Box<dyn GitRepository>> {
-        Some(FakeGitRepository::open(abs_dot_git.into(), 0))
+        Some(git::repository::FakeGitRepository::open(
+            abs_dot_git.into(),
+            0,
+        ))
     }
 
     fn is_fake(&self) -> bool {

crates/project/src/worktree.rs 🔗

@@ -2603,7 +2603,13 @@ impl BackgroundScanner {
             .git_repositories
             .iter()
             .map(|repo| repo.boxed_clone())
-            .filter(|repo| git::libgit::Repository::open(repo.git_dir_path()).is_ok())
+            .filter_map(|mut repo| {
+                if repo.reopen_git_repo() {
+                    Some(repo)
+                } else {
+                    None
+                }
+            })
             .collect();
 
         snapshot.git_repositories = new_repos;