Fix bug where git statuses would not be initialized on startup
move git status queries to be on entry creation co-authored-by: max <max@zed.dev>
This commit is contained in:
parent
2f97c7a4f1
commit
ca077408d7
1 changed files with 50 additions and 42 deletions
|
@ -1822,6 +1822,14 @@ impl LocalSnapshot {
|
||||||
self.git_repositories.get(&repo.work_directory.0)
|
self.git_repositories.get(&repo.work_directory.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn local_repo_for_path(
|
||||||
|
&self,
|
||||||
|
path: &Path,
|
||||||
|
) -> Option<(RepositoryWorkDirectory, &LocalRepositoryEntry)> {
|
||||||
|
let (path, repo) = self.repository_and_work_directory_for_path(path)?;
|
||||||
|
Some((path, self.git_repositories.get(&repo.work_directory_id())?))
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn repo_for_metadata(
|
pub(crate) fn repo_for_metadata(
|
||||||
&self,
|
&self,
|
||||||
path: &Path,
|
path: &Path,
|
||||||
|
@ -1997,6 +2005,8 @@ impl LocalSnapshot {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
self.scan_statuses(repo_lock.deref(), &work_directory);
|
||||||
|
|
||||||
drop(repo_lock);
|
drop(repo_lock);
|
||||||
|
|
||||||
self.git_repositories.insert(
|
self.git_repositories.insert(
|
||||||
|
@ -2016,10 +2026,12 @@ impl LocalSnapshot {
|
||||||
&mut self,
|
&mut self,
|
||||||
repo_ptr: &dyn GitRepository,
|
repo_ptr: &dyn GitRepository,
|
||||||
work_directory: &RepositoryWorkDirectory,
|
work_directory: &RepositoryWorkDirectory,
|
||||||
path: &Path,
|
|
||||||
) {
|
) {
|
||||||
let mut edits = vec![];
|
let mut edits = vec![];
|
||||||
for mut entry in self.descendent_entries(false, false, path).cloned() {
|
for mut entry in self
|
||||||
|
.descendent_entries(false, false, &work_directory.0)
|
||||||
|
.cloned()
|
||||||
|
{
|
||||||
let Ok(repo_path) = entry.path.strip_prefix(&work_directory.0) else {
|
let Ok(repo_path) = entry.path.strip_prefix(&work_directory.0) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
@ -2754,6 +2766,7 @@ impl BackgroundScanner {
|
||||||
let mut state = self.state.lock();
|
let mut state = self.state.lock();
|
||||||
state.snapshot.completed_scan_id = state.snapshot.scan_id;
|
state.snapshot.completed_scan_id = state.snapshot.scan_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.send_status_update(false, None);
|
self.send_status_update(false, None);
|
||||||
|
|
||||||
// Process any any FS events that occurred while performing the initial scan.
|
// Process any any FS events that occurred while performing the initial scan.
|
||||||
|
@ -2813,7 +2826,7 @@ impl BackgroundScanner {
|
||||||
|
|
||||||
if let Some(paths) = paths {
|
if let Some(paths) = paths {
|
||||||
for path in paths {
|
for path in paths {
|
||||||
self.reload_git_status(&path, &mut *snapshot, self.fs.as_ref());
|
self.reload_git_repo(&path, &mut *snapshot, self.fs.as_ref());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2940,14 +2953,18 @@ impl BackgroundScanner {
|
||||||
let mut new_jobs: Vec<Option<ScanJob>> = Vec::new();
|
let mut new_jobs: Vec<Option<ScanJob>> = Vec::new();
|
||||||
let mut ignore_stack = job.ignore_stack.clone();
|
let mut ignore_stack = job.ignore_stack.clone();
|
||||||
let mut new_ignore = None;
|
let mut new_ignore = None;
|
||||||
let (root_abs_path, root_char_bag, next_entry_id) = {
|
let (root_abs_path, root_char_bag, next_entry_id, repository) = {
|
||||||
let snapshot = &self.state.lock().snapshot;
|
let snapshot = &self.state.lock().snapshot;
|
||||||
(
|
(
|
||||||
snapshot.abs_path().clone(),
|
snapshot.abs_path().clone(),
|
||||||
snapshot.root_char_bag,
|
snapshot.root_char_bag,
|
||||||
self.next_entry_id.clone(),
|
self.next_entry_id.clone(),
|
||||||
|
snapshot
|
||||||
|
.local_repo_for_path(&job.path)
|
||||||
|
.map(|(work_dir, repo)| (work_dir, repo.clone())),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut child_paths = self.fs.read_dir(&job.abs_path).await?;
|
let mut child_paths = self.fs.read_dir(&job.abs_path).await?;
|
||||||
while let Some(child_abs_path) = child_paths.next().await {
|
while let Some(child_abs_path) = child_paths.next().await {
|
||||||
let child_abs_path: Arc<Path> = match child_abs_path {
|
let child_abs_path: Arc<Path> = match child_abs_path {
|
||||||
|
@ -3040,6 +3057,13 @@ impl BackgroundScanner {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
child_entry.is_ignored = ignore_stack.is_abs_path_ignored(&child_abs_path, false);
|
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()));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
new_entries.push(child_entry);
|
new_entries.push(child_entry);
|
||||||
|
@ -3117,6 +3141,7 @@ impl BackgroundScanner {
|
||||||
let ignore_stack = state
|
let ignore_stack = state
|
||||||
.snapshot
|
.snapshot
|
||||||
.ignore_stack_for_abs_path(&abs_path, metadata.is_dir);
|
.ignore_stack_for_abs_path(&abs_path, metadata.is_dir);
|
||||||
|
|
||||||
let mut fs_entry = Entry::new(
|
let mut fs_entry = Entry::new(
|
||||||
path.clone(),
|
path.clone(),
|
||||||
&metadata,
|
&metadata,
|
||||||
|
@ -3124,6 +3149,16 @@ impl BackgroundScanner {
|
||||||
state.snapshot.root_char_bag,
|
state.snapshot.root_char_bag,
|
||||||
);
|
);
|
||||||
fs_entry.is_ignored = ignore_stack.is_all();
|
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()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
state.insert_entry(fs_entry, self.fs.as_ref());
|
state.insert_entry(fs_entry, self.fs.as_ref());
|
||||||
|
|
||||||
if let Some(scan_queue_tx) = &scan_queue_tx {
|
if let Some(scan_queue_tx) = &scan_queue_tx {
|
||||||
|
@ -3183,7 +3218,7 @@ impl BackgroundScanner {
|
||||||
Some(())
|
Some(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reload_git_status(
|
fn reload_git_repo(
|
||||||
&self,
|
&self,
|
||||||
path: &Path,
|
path: &Path,
|
||||||
snapshot: &mut LocalSnapshot,
|
snapshot: &mut LocalSnapshot,
|
||||||
|
@ -3230,32 +3265,7 @@ impl BackgroundScanner {
|
||||||
entry.branch = branch.map(Into::into);
|
entry.branch = branch.map(Into::into);
|
||||||
});
|
});
|
||||||
|
|
||||||
snapshot.scan_statuses(repo.deref(), &work_dir, &work_dir.0);
|
snapshot.scan_statuses(repo.deref(), &work_dir);
|
||||||
} else {
|
|
||||||
if snapshot
|
|
||||||
.entry_for_path(&path)
|
|
||||||
.map(|entry| entry.is_ignored)
|
|
||||||
.unwrap_or(false)
|
|
||||||
{
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let repo = snapshot.repository_for_path(&path)?;
|
|
||||||
let work_directory = &repo.work_directory(snapshot)?;
|
|
||||||
let work_dir_id = repo.work_directory.clone();
|
|
||||||
let (local_repo, git_dir_scan_id) =
|
|
||||||
snapshot.git_repositories.update(&work_dir_id, |entry| {
|
|
||||||
(entry.repo_ptr.clone(), entry.git_dir_scan_id)
|
|
||||||
})?;
|
|
||||||
|
|
||||||
// Short circuit if we've already scanned everything
|
|
||||||
if git_dir_scan_id == scan_id {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
let repo_ptr = local_repo.lock();
|
|
||||||
|
|
||||||
snapshot.scan_statuses(repo_ptr.deref(), &work_directory, path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(())
|
Some(())
|
||||||
|
@ -5270,6 +5280,15 @@ mod tests {
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
fs.set_status_for_repo(
|
||||||
|
&Path::new("/root/.git"),
|
||||||
|
&[
|
||||||
|
(Path::new("a/b/c1.txt"), GitFileStatus::Added),
|
||||||
|
(Path::new("a/d/e2.txt"), GitFileStatus::Modified),
|
||||||
|
(Path::new("g/h2.txt"), GitFileStatus::Conflict),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
let http_client = FakeHttpClient::with_404_response();
|
let http_client = FakeHttpClient::with_404_response();
|
||||||
let client = cx.read(|cx| Client::new(http_client, cx));
|
let client = cx.read(|cx| Client::new(http_client, cx));
|
||||||
let tree = Worktree::local(
|
let tree = Worktree::local(
|
||||||
|
@ -5285,17 +5304,6 @@ mod tests {
|
||||||
|
|
||||||
cx.foreground().run_until_parked();
|
cx.foreground().run_until_parked();
|
||||||
|
|
||||||
fs.set_status_for_repo(
|
|
||||||
&Path::new("/root/.git"),
|
|
||||||
&[
|
|
||||||
(Path::new("a/b/c1.txt"), GitFileStatus::Added),
|
|
||||||
(Path::new("a/d/e2.txt"), GitFileStatus::Modified),
|
|
||||||
(Path::new("g/h2.txt"), GitFileStatus::Conflict),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
|
|
||||||
cx.foreground().run_until_parked();
|
|
||||||
|
|
||||||
let snapshot = tree.read_with(cx, |tree, _| tree.snapshot());
|
let snapshot = tree.read_with(cx, |tree, _| tree.snapshot());
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue