Fix a bug where repositories were always being marked as changed (#22725)

Release Notes:

- N/A

Co-authored-by: cole <cole@zed.dev>
This commit is contained in:
Mikayla Maki 2025-01-06 11:03:15 -08:00 committed by GitHub
parent 3a061a91e7
commit ec2506b2e7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 41 additions and 19 deletions

View file

@ -680,7 +680,7 @@ pub fn split_worktree_update(mut message: UpdateWorktree) -> impl Iterator<Item
if !repository_map.is_empty() { if !repository_map.is_empty() {
for entry in &updated_entries { for entry in &updated_entries {
if let Some(repo) = repository_map.remove(&entry.id) { if let Some(repo) = repository_map.remove(&entry.id) {
updated_repositories.push(repo) updated_repositories.push(repo);
} }
} }
} }

View file

@ -4737,6 +4737,7 @@ impl BackgroundScanner {
Ok(()) Ok(())
} }
/// All list arguments should be sorted before calling this function
async fn reload_entries_for_paths( async fn reload_entries_for_paths(
&self, &self,
root_abs_path: Arc<Path>, root_abs_path: Arc<Path>,
@ -4793,11 +4794,16 @@ impl BackgroundScanner {
// Group all relative paths by their git repository. // Group all relative paths by their git repository.
let mut paths_by_git_repo = HashMap::default(); let mut paths_by_git_repo = HashMap::default();
for relative_path in relative_paths.iter() { for relative_path in relative_paths.iter() {
if let Some(local_repo) = state.snapshot.local_repo_for_path(relative_path) { let repository_data = state
.snapshot
.local_repo_for_path(relative_path)
.zip(state.snapshot.repository_for_path(relative_path));
if let Some((local_repo, entry)) = repository_data {
if let Ok(repo_path) = local_repo.relativize(relative_path) { if let Ok(repo_path) = local_repo.relativize(relative_path) {
paths_by_git_repo paths_by_git_repo
.entry(local_repo.work_directory.clone()) .entry(local_repo.work_directory.clone())
.or_insert_with(|| RepoPaths { .or_insert_with(|| RepoPaths {
entry: entry.clone(),
repo: local_repo.repo_ptr.clone(), repo: local_repo.repo_ptr.clone(),
repo_paths: Default::default(), repo_paths: Default::default(),
}) })
@ -4809,37 +4815,52 @@ impl BackgroundScanner {
for (work_directory, mut paths) in paths_by_git_repo { for (work_directory, mut paths) in paths_by_git_repo {
if let Ok(status) = paths.repo.status(&paths.repo_paths) { if let Ok(status) = paths.repo.status(&paths.repo_paths) {
let mut changed_path_statuses = Vec::new(); let mut changed_path_statuses = Vec::new();
let statuses = paths.entry.statuses_by_path.clone();
let mut cursor = statuses.cursor::<PathProgress>(&());
for (repo_path, status) in &*status.entries { for (repo_path, status) in &*status.entries {
paths.remove_repo_path(repo_path); paths.remove_repo_path(repo_path);
if cursor.seek_forward(&PathTarget::Path(&repo_path), Bias::Left, &()) {
if cursor.item().unwrap().status == *status {
continue;
}
}
changed_path_statuses.push(Edit::Insert(StatusEntry { changed_path_statuses.push(Edit::Insert(StatusEntry {
repo_path: repo_path.clone(), repo_path: repo_path.clone(),
status: *status, status: *status,
})); }));
} }
let mut cursor = statuses.cursor::<PathProgress>(&());
for path in paths.repo_paths { for path in paths.repo_paths {
changed_path_statuses.push(Edit::Remove(PathKey(path.0))); if cursor.seek_forward(&PathTarget::Path(&path), Bias::Left, &()) {
changed_path_statuses.push(Edit::Remove(PathKey(path.0)));
}
} }
let work_directory_id = state.snapshot.repositories.update( if !changed_path_statuses.is_empty() {
&work_directory.path_key(), let work_directory_id = state.snapshot.repositories.update(
&(), &work_directory.path_key(),
move |repository_entry| { &(),
repository_entry move |repository_entry| {
.statuses_by_path repository_entry
.edit(changed_path_statuses, &()); .statuses_by_path
repository_entry.work_directory_id .edit(changed_path_statuses, &());
},
);
if let Some(work_directory_id) = work_directory_id { repository_entry.work_directory_id
let scan_id = state.snapshot.scan_id;
state.snapshot.git_repositories.update(
&work_directory_id,
|local_repository_entry| {
local_repository_entry.status_scan_id = scan_id;
}, },
); );
if let Some(work_directory_id) = work_directory_id {
let scan_id = state.snapshot.scan_id;
state.snapshot.git_repositories.update(
&work_directory_id,
|local_repository_entry| {
local_repository_entry.status_scan_id = scan_id;
},
);
}
} }
} }
} }
@ -5435,6 +5456,7 @@ fn char_bag_for_path(root_char_bag: CharBag, path: &Path) -> CharBag {
#[derive(Debug)] #[derive(Debug)]
struct RepoPaths { struct RepoPaths {
repo: Arc<dyn GitRepository>, repo: Arc<dyn GitRepository>,
entry: RepositoryEntry,
// sorted // sorted
repo_paths: Vec<RepoPath>, repo_paths: Vec<RepoPath>,
} }