@@ -25,7 +25,7 @@ pub trait GitRepository: Send {
fn statuses(&self) -> Option<TreeMap<RepoPath, GitFileStatus>>;
- fn status(&self, path: &RepoPath) -> Option<GitFileStatus>;
+ fn status(&self, path: &RepoPath) -> Result<Option<GitFileStatus>>;
}
impl std::fmt::Debug for dyn GitRepository {
@@ -92,9 +92,9 @@ impl GitRepository for LibGitRepository {
Some(map)
}
- fn status(&self, path: &RepoPath) -> Option<GitFileStatus> {
- let status = self.status_file(path).log_err()?;
- read_status(status)
+ fn status(&self, path: &RepoPath) -> Result<Option<GitFileStatus>> {
+ let status = self.status_file(path)?;
+ Ok(read_status(status))
}
}
@@ -156,9 +156,9 @@ impl GitRepository for FakeGitRepository {
Some(map)
}
- fn status(&self, path: &RepoPath) -> Option<GitFileStatus> {
+ fn status(&self, path: &RepoPath) -> Result<Option<GitFileStatus>> {
let state = self.state.lock();
- state.worktree_statuses.get(path).cloned()
+ Ok(state.worktree_statuses.get(path).cloned())
}
}
@@ -1670,11 +1670,14 @@ impl Snapshot {
})
}
- pub fn statuses_for_paths(&self, paths: &[&Path]) -> Vec<Option<GitFileStatus>> {
+ pub fn statuses_for_paths<'a>(
+ &self,
+ paths: impl IntoIterator<Item = &'a Path>,
+ ) -> Vec<Option<GitFileStatus>> {
let mut cursor = self
.entries_by_path
.cursor::<(TraversalProgress, GitStatuses)>();
- let mut paths = paths.iter().peekable();
+ let mut paths = paths.into_iter().peekable();
let mut path_stack = Vec::<(&Path, usize, GitStatuses)>::new();
let mut result = Vec::new();
@@ -2040,11 +2043,15 @@ impl LocalSnapshot {
let Ok(repo_path) = entry.path.strip_prefix(&work_directory.0) else {
continue;
};
- let git_file_status = repo_ptr.status(&RepoPath(repo_path.into()));
- let status = git_file_status;
- entry.git_status = status;
- changes.push(entry.path.clone());
- edits.push(Edit::Insert(entry));
+ let git_file_status = repo_ptr
+ .status(&RepoPath(repo_path.into()))
+ .log_err()
+ .flatten();
+ if entry.git_status != git_file_status {
+ entry.git_status = git_file_status;
+ changes.push(entry.path.clone());
+ edits.push(Edit::Insert(entry));
+ }
}
self.entries_by_path.edit(edits, &());
@@ -3068,11 +3075,16 @@ impl BackgroundScanner {
}
} else {
child_entry.is_ignored = ignore_stack.is_abs_path_ignored(&child_abs_path, false);
-
- if let Some((repo_path, repo)) = &repository {
- if let Ok(path) = child_path.strip_prefix(&repo_path.0) {
- child_entry.git_status =
- repo.repo_ptr.lock().status(&RepoPath(path.into()));
+ if !child_entry.is_ignored {
+ if let Some((repo_path, repo)) = &repository {
+ if let Ok(path) = child_path.strip_prefix(&repo_path.0) {
+ child_entry.git_status = repo
+ .repo_ptr
+ .lock()
+ .status(&RepoPath(path.into()))
+ .log_err()
+ .flatten();
+ }
}
}
}
@@ -3170,11 +3182,19 @@ impl BackgroundScanner {
);
fs_entry.is_ignored = ignore_stack.is_all();
- if !fs_entry.is_dir() {
- if let Some((work_dir, repo)) = state.snapshot.local_repo_for_path(&path) {
- if let Ok(path) = path.strip_prefix(work_dir.0) {
- fs_entry.git_status =
- repo.repo_ptr.lock().status(&RepoPath(path.into()))
+ if !fs_entry.is_ignored {
+ if !fs_entry.is_dir() {
+ if let Some((work_dir, repo)) =
+ state.snapshot.local_repo_for_path(&path)
+ {
+ if let Ok(path) = path.strip_prefix(work_dir.0) {
+ fs_entry.git_status = repo
+ .repo_ptr
+ .lock()
+ .status(&RepoPath(path.into()))
+ .log_err()
+ .flatten()
+ }
}
}
}
@@ -5345,7 +5365,7 @@ mod tests {
let snapshot = tree.read_with(cx, |tree, _| tree.snapshot());
assert_eq!(
- snapshot.statuses_for_paths(&[
+ snapshot.statuses_for_paths([
Path::new(""),
Path::new("a"),
Path::new("a/b"),
@@ -1109,8 +1109,16 @@ impl ProjectPanel {
.unwrap_or(&[]);
let entry_range = range.start.saturating_sub(ix)..end_ix - ix;
- for entry in visible_worktree_entries[entry_range].iter() {
- let status = git_status_setting.then(|| entry.git_status).flatten();
+ let statuses = worktree.read(cx).statuses_for_paths(
+ visible_worktree_entries[entry_range.clone()]
+ .iter()
+ .map(|entry| entry.path.as_ref()),
+ );
+ for (entry, status) in visible_worktree_entries[entry_range]
+ .iter()
+ .zip(statuses.into_iter())
+ {
+ let status = git_status_setting.then(|| status).flatten();
let mut details = EntryDetails {
filename: entry