Load git repositories when inserting the entry for the .git

Don't wait until populating that directory entry, for two reasons:
* In the case of submodules, .git is not a directory
* We don't eagerly populate .git directories, since their contents
  are automatically ignored.
This commit is contained in:
Max Brunsfeld 2023-06-16 10:46:14 -07:00
parent 6fe74602ac
commit 3c06bd056a

View file

@ -2218,17 +2218,23 @@ impl BackgroundScannerState {
fn insert_entry(&mut self, mut entry: Entry, fs: &dyn Fs) -> Entry { fn insert_entry(&mut self, mut entry: Entry, fs: &dyn Fs) -> Entry {
self.reuse_entry_id(&mut entry); self.reuse_entry_id(&mut entry);
self.snapshot.insert_entry(entry, fs) let entry = self.snapshot.insert_entry(entry, fs);
if entry.path.file_name() == Some(&DOT_GIT) {
let changed_paths = self.snapshot.build_repo(entry.path.clone(), fs);
if let Some(changed_paths) = changed_paths {
util::extend_sorted(&mut self.changed_paths, changed_paths, usize::MAX, Ord::cmp)
}
}
entry
} }
#[must_use = "Changed paths must be used for diffing later"]
fn populate_dir( fn populate_dir(
&mut self, &mut self,
parent_path: Arc<Path>, parent_path: &Arc<Path>,
entries: impl IntoIterator<Item = Entry>, entries: impl IntoIterator<Item = Entry>,
ignore: Option<Arc<Gitignore>>, ignore: Option<Arc<Gitignore>>,
fs: &dyn Fs, fs: &dyn Fs,
) -> Option<Vec<Arc<Path>>> { ) {
let mut parent_entry = if let Some(parent_entry) = self let mut parent_entry = if let Some(parent_entry) = self
.snapshot .snapshot
.entries_by_path .entries_by_path
@ -2240,15 +2246,13 @@ impl BackgroundScannerState {
"populating a directory {:?} that has been removed", "populating a directory {:?} that has been removed",
parent_path parent_path
); );
return None; return;
}; };
match parent_entry.kind { match parent_entry.kind {
EntryKind::PendingDir => { EntryKind::PendingDir => parent_entry.kind = EntryKind::Dir,
parent_entry.kind = EntryKind::Dir;
}
EntryKind::Dir => {} EntryKind::Dir => {}
_ => return None, _ => return,
} }
if let Some(ignore) = ignore { if let Some(ignore) = ignore {
@ -2260,8 +2264,13 @@ impl BackgroundScannerState {
let mut entries_by_path_edits = vec![Edit::Insert(parent_entry)]; let mut entries_by_path_edits = vec![Edit::Insert(parent_entry)];
let mut entries_by_id_edits = Vec::new(); let mut entries_by_id_edits = Vec::new();
let mut dotgit_path = None;
for mut entry in entries { for mut entry in entries {
if entry.path.file_name() == Some(&DOT_GIT) {
dotgit_path = Some(entry.path.clone());
}
self.reuse_entry_id(&mut entry); self.reuse_entry_id(&mut entry);
entries_by_id_edits.push(Edit::Insert(PathEntry { entries_by_id_edits.push(Edit::Insert(PathEntry {
id: entry.id, id: entry.id,
@ -2277,10 +2286,15 @@ impl BackgroundScannerState {
.edit(entries_by_path_edits, &()); .edit(entries_by_path_edits, &());
self.snapshot.entries_by_id.edit(entries_by_id_edits, &()); self.snapshot.entries_by_id.edit(entries_by_id_edits, &());
if parent_path.file_name() == Some(&DOT_GIT) { if let Some(dotgit_path) = dotgit_path {
return self.snapshot.build_repo(parent_path, fs); let changed_paths = self.snapshot.build_repo(dotgit_path, fs);
if let Some(changed_paths) = changed_paths {
util::extend_sorted(&mut self.changed_paths, changed_paths, usize::MAX, Ord::cmp)
}
}
if let Err(ix) = self.changed_paths.binary_search(parent_path) {
self.changed_paths.insert(ix, parent_path.clone());
} }
None
} }
fn remove_path(&mut self, path: &Path) { fn remove_path(&mut self, path: &Path) {
@ -3297,22 +3311,9 @@ impl BackgroundScanner {
new_entries.push(child_entry); new_entries.push(child_entry);
} }
{ self.state
let mut state = self.state.lock(); .lock()
let changed_paths = .populate_dir(&job.path, new_entries, new_ignore, self.fs.as_ref());
state.populate_dir(job.path.clone(), new_entries, new_ignore, self.fs.as_ref());
if let Err(ix) = state.changed_paths.binary_search(&job.path) {
state.changed_paths.insert(ix, job.path.clone());
}
if let Some(changed_paths) = changed_paths {
util::extend_sorted(
&mut state.changed_paths,
changed_paths,
usize::MAX,
Ord::cmp,
)
}
}
for new_job in new_jobs { for new_job in new_jobs {
if let Some(new_job) = new_job { if let Some(new_job) = new_job {