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() {
for entry in &updated_entries {
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(())
}
/// All list arguments should be sorted before calling this function
async fn reload_entries_for_paths(
&self,
root_abs_path: Arc<Path>,
@ -4793,11 +4794,16 @@ impl BackgroundScanner {
// Group all relative paths by their git repository.
let mut paths_by_git_repo = HashMap::default();
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) {
paths_by_git_repo
.entry(local_repo.work_directory.clone())
.or_insert_with(|| RepoPaths {
entry: entry.clone(),
repo: local_repo.repo_ptr.clone(),
repo_paths: Default::default(),
})
@ -4809,18 +4815,31 @@ impl BackgroundScanner {
for (work_directory, mut paths) in paths_by_git_repo {
if let Ok(status) = paths.repo.status(&paths.repo_paths) {
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 {
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 {
repo_path: repo_path.clone(),
status: *status,
}));
}
let mut cursor = statuses.cursor::<PathProgress>(&());
for path in paths.repo_paths {
if cursor.seek_forward(&PathTarget::Path(&path), Bias::Left, &()) {
changed_path_statuses.push(Edit::Remove(PathKey(path.0)));
}
}
if !changed_path_statuses.is_empty() {
let work_directory_id = state.snapshot.repositories.update(
&work_directory.path_key(),
&(),
@ -4828,6 +4847,7 @@ impl BackgroundScanner {
repository_entry
.statuses_by_path
.edit(changed_path_statuses, &());
repository_entry.work_directory_id
},
);
@ -4843,6 +4863,7 @@ impl BackgroundScanner {
}
}
}
}
for (path, metadata) in relative_paths.iter().zip(metadata.into_iter()) {
let abs_path: Arc<Path> = root_abs_path.join(path).into();
@ -5435,6 +5456,7 @@ fn char_bag_for_path(root_char_bag: CharBag, path: &Path) -> CharBag {
#[derive(Debug)]
struct RepoPaths {
repo: Arc<dyn GitRepository>,
entry: RepositoryEntry,
// sorted
repo_paths: Vec<RepoPath>,
}