Include repositories with workdir changes in worktree UpdatedGitRepsositories event

This commit is contained in:
Max Brunsfeld 2023-05-26 15:21:51 -07:00
parent 2db57b5139
commit 1f42bfc1bd
2 changed files with 72 additions and 35 deletions

View file

@ -5071,9 +5071,9 @@ impl Project {
return None; return None;
} }
let path = &project_path.path; let path = &project_path.path;
changed_repos changed_repos.iter().find(|(work_dir, change)| {
.iter() path.starts_with(work_dir) && change.git_dir_changed
.find(|(work_dir, _)| path.starts_with(work_dir))?; })?;
let receiver = receiver.clone(); let receiver = receiver.clone();
let path = path.clone(); let path = path.clone();
Some(async move { Some(async move {
@ -5096,9 +5096,9 @@ impl Project {
return None; return None;
} }
let path = file.path(); let path = file.path();
changed_repos changed_repos.iter().find(|(work_dir, change)| {
.iter() path.starts_with(work_dir) && change.git_dir_changed
.find(|(work_dir, _)| path.starts_with(work_dir))?; })?;
Some((buffer, path.clone())) Some((buffer, path.clone()))
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();

View file

@ -330,7 +330,7 @@ pub struct BackgroundScannerState {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct LocalRepositoryEntry { pub struct LocalRepositoryEntry {
pub(crate) scan_id: usize, pub(crate) work_dir_scan_id: usize,
pub(crate) git_dir_scan_id: usize, pub(crate) git_dir_scan_id: usize,
pub(crate) repo_ptr: Arc<Mutex<dyn GitRepository>>, pub(crate) repo_ptr: Arc<Mutex<dyn GitRepository>>,
/// Path to the actual .git folder. /// Path to the actual .git folder.
@ -863,19 +863,33 @@ impl LocalWorktree {
match Ord::cmp(&new_entry_id, &old_entry_id) { match Ord::cmp(&new_entry_id, &old_entry_id) {
Ordering::Less => { Ordering::Less => {
if let Some(entry) = new_snapshot.entry_for_id(new_entry_id) { if let Some(entry) = new_snapshot.entry_for_id(new_entry_id) {
changes.push((entry.path.clone(), None)); changes.push((
entry.path.clone(),
GitRepositoryChange {
old_repository: None,
git_dir_changed: true,
},
));
} }
new_repos.next(); new_repos.next();
} }
Ordering::Equal => { Ordering::Equal => {
if new_repo.git_dir_scan_id != old_repo.git_dir_scan_id { let git_dir_changed =
new_repo.git_dir_scan_id != old_repo.git_dir_scan_id;
let work_dir_changed =
new_repo.work_dir_scan_id != old_repo.work_dir_scan_id;
if git_dir_changed || work_dir_changed {
if let Some(entry) = new_snapshot.entry_for_id(new_entry_id) { if let Some(entry) = new_snapshot.entry_for_id(new_entry_id) {
let old_repo = old_snapshot
.repository_entries
.get(&RepositoryWorkDirectory(entry.path.clone()))
.cloned();
changes.push(( changes.push((
entry.path.clone(), entry.path.clone(),
old_snapshot GitRepositoryChange {
.repository_entries old_repository: old_repo,
.get(&RepositoryWorkDirectory(entry.path.clone())) git_dir_changed,
.cloned(), },
)); ));
} }
} }
@ -884,12 +898,16 @@ impl LocalWorktree {
} }
Ordering::Greater => { Ordering::Greater => {
if let Some(entry) = old_snapshot.entry_for_id(old_entry_id) { if let Some(entry) = old_snapshot.entry_for_id(old_entry_id) {
let old_repo = old_snapshot
.repository_entries
.get(&RepositoryWorkDirectory(entry.path.clone()))
.cloned();
changes.push(( changes.push((
entry.path.clone(), entry.path.clone(),
old_snapshot GitRepositoryChange {
.repository_entries old_repository: old_repo,
.get(&RepositoryWorkDirectory(entry.path.clone())) git_dir_changed: true,
.cloned(), },
)); ));
} }
old_repos.next(); old_repos.next();
@ -898,18 +916,28 @@ impl LocalWorktree {
} }
(Some((entry_id, _)), None) => { (Some((entry_id, _)), None) => {
if let Some(entry) = new_snapshot.entry_for_id(entry_id) { if let Some(entry) = new_snapshot.entry_for_id(entry_id) {
changes.push((entry.path.clone(), None)); changes.push((
entry.path.clone(),
GitRepositoryChange {
old_repository: None,
git_dir_changed: true,
},
));
} }
new_repos.next(); new_repos.next();
} }
(None, Some((entry_id, _))) => { (None, Some((entry_id, _))) => {
if let Some(entry) = old_snapshot.entry_for_id(entry_id) { if let Some(entry) = old_snapshot.entry_for_id(entry_id) {
let old_repo = old_snapshot
.repository_entries
.get(&RepositoryWorkDirectory(entry.path.clone()))
.cloned();
changes.push(( changes.push((
entry.path.clone(), entry.path.clone(),
old_snapshot GitRepositoryChange {
.repository_entries old_repository: old_repo,
.get(&RepositoryWorkDirectory(entry.path.clone())) git_dir_changed: true,
.cloned(), },
)); ));
} }
old_repos.next(); old_repos.next();
@ -1890,11 +1918,12 @@ impl LocalSnapshot {
updated_entries.push(proto::Entry::from(entry)); updated_entries.push(proto::Entry::from(entry));
} }
} }
for (work_dir_path, old_repo) in repo_changes.iter() {
for (work_dir_path, change) in repo_changes.iter() {
let new_repo = self let new_repo = self
.repository_entries .repository_entries
.get(&RepositoryWorkDirectory(work_dir_path.clone())); .get(&RepositoryWorkDirectory(work_dir_path.clone()));
match (old_repo, new_repo) { match (&change.old_repository, new_repo) {
(Some(old_repo), Some(new_repo)) => { (Some(old_repo), Some(new_repo)) => {
updated_repositories.push(new_repo.build_update(old_repo)); updated_repositories.push(new_repo.build_update(old_repo));
} }
@ -2042,7 +2071,7 @@ impl LocalSnapshot {
self.git_repositories.insert( self.git_repositories.insert(
work_dir_id, work_dir_id,
LocalRepositoryEntry { LocalRepositoryEntry {
scan_id, work_dir_scan_id: scan_id,
git_dir_scan_id: scan_id, git_dir_scan_id: scan_id,
repo_ptr: repo, repo_ptr: repo,
git_dir_path: parent_path.clone(), git_dir_path: parent_path.clone(),
@ -2494,8 +2523,16 @@ pub enum PathChange {
Loaded, Loaded,
} }
pub struct GitRepositoryChange {
/// The previous state of the repository, if it already existed.
pub old_repository: Option<RepositoryEntry>,
/// Whether the content of the .git directory changed. This will be false
/// if only the repository's work directory changed.
pub git_dir_changed: bool,
}
pub type UpdatedEntriesSet = Arc<[(Arc<Path>, ProjectEntryId, PathChange)]>; pub type UpdatedEntriesSet = Arc<[(Arc<Path>, ProjectEntryId, PathChange)]>;
pub type UpdatedGitRepositoriesSet = Arc<[(Arc<Path>, Option<RepositoryEntry>)]>; pub type UpdatedGitRepositoriesSet = Arc<[(Arc<Path>, GitRepositoryChange)]>;
impl Entry { impl Entry {
fn new( fn new(
@ -3181,7 +3218,7 @@ impl BackgroundScanner {
snapshot snapshot
.git_repositories .git_repositories
.update(&work_dir_id, |entry| entry.scan_id = scan_id); .update(&work_dir_id, |entry| entry.work_dir_scan_id = scan_id);
snapshot.repository_entries.update(&work_dir, |entry| { snapshot.repository_entries.update(&work_dir, |entry| {
entry entry
@ -3230,7 +3267,7 @@ impl BackgroundScanner {
let statuses = repo.statuses().unwrap_or_default(); let statuses = repo.statuses().unwrap_or_default();
snapshot.git_repositories.update(&entry_id, |entry| { snapshot.git_repositories.update(&entry_id, |entry| {
entry.scan_id = scan_id; entry.work_dir_scan_id = scan_id;
entry.git_dir_scan_id = scan_id; entry.git_dir_scan_id = scan_id;
}); });
@ -3253,14 +3290,14 @@ impl BackgroundScanner {
let work_dir = repo.work_directory(snapshot)?; let work_dir = repo.work_directory(snapshot)?;
let work_dir_id = repo.work_directory.clone(); let work_dir_id = repo.work_directory.clone();
snapshot let (local_repo, git_dir_scan_id) =
.git_repositories snapshot.git_repositories.update(&work_dir_id, |entry| {
.update(&work_dir_id, |entry| entry.scan_id = scan_id); entry.work_dir_scan_id = scan_id;
(entry.repo_ptr.clone(), entry.git_dir_scan_id)
let local_repo = snapshot.get_local_repo(&repo)?.to_owned(); })?;
// Short circuit if we've already scanned everything // Short circuit if we've already scanned everything
if local_repo.git_dir_scan_id == scan_id { if git_dir_scan_id == scan_id {
return None; return None;
} }
@ -3271,7 +3308,7 @@ impl BackgroundScanner {
continue; continue;
}; };
let status = local_repo.repo_ptr.lock().status(&repo_path); let status = local_repo.lock().status(&repo_path);
if let Some(status) = status { if let Some(status) = status {
repository.statuses.insert(repo_path.clone(), status); repository.statuses.insert(repo_path.clone(), status);
} else { } else {