Move repository state RPC handlers to the GitStore (#27391)
This is another in the series of PRs to make the GitStore own all repository state and enable better concurrency control for git repository scans. After this PR, the `RepositoryEntry`s stored in worktree snapshots are used only as a staging ground for local GitStores to pull from after git-related events; non-local worktrees don't store them at all, although this is not reflected in the types. GitTraversal and other places that need information about repositories get it from the GitStore. The GitStore also takes over handling of the new UpdateRepository and RemoveRepository messages. However, repositories are still discovered and scanned on a per-worktree basis, and we're still identifying them by the (worktree-specific) project entry ID of their working directory. - [x] Remove WorkDirectory from RepositoryEntry - [x] Remove worktree IDs from repository-related RPC messages - [x] Handle UpdateRepository and RemoveRepository RPCs from the GitStore Release Notes: - N/A --------- Co-authored-by: Max <max@zed.dev> Co-authored-by: Max Brunsfeld <maxbrunsfeld@gmail.com>
This commit is contained in:
parent
1e8b50f471
commit
6924720b35
22 changed files with 1387 additions and 1399 deletions
|
@ -334,7 +334,8 @@ impl ProjectPanel {
|
|||
this.update_visible_entries(None, cx);
|
||||
cx.notify();
|
||||
}
|
||||
project::Event::WorktreeUpdatedGitRepositories(_)
|
||||
project::Event::GitStateUpdated
|
||||
| project::Event::ActiveRepositoryChanged
|
||||
| project::Event::WorktreeUpdatedEntries(_, _)
|
||||
| project::Event::WorktreeAdded(_)
|
||||
| project::Event::WorktreeOrderChanged => {
|
||||
|
@ -1553,6 +1554,7 @@ impl ProjectPanel {
|
|||
.map(|entry| entry.worktree_id)
|
||||
.filter_map(|id| project.worktree_for_id(id, cx).map(|w| (id, w.read(cx))))
|
||||
.max_by(|(_, a), (_, b)| a.root_name().cmp(b.root_name()))?;
|
||||
let git_store = project.git_store().read(cx);
|
||||
|
||||
let marked_entries_in_worktree = sanitized_entries
|
||||
.iter()
|
||||
|
@ -1577,18 +1579,20 @@ impl ProjectPanel {
|
|||
let parent_entry = worktree.entry_for_path(parent_path)?;
|
||||
|
||||
// Remove all siblings that are being deleted except the last marked entry
|
||||
let snapshot = worktree.snapshot();
|
||||
let repo_snapshots = git_store.repo_snapshots(cx);
|
||||
let worktree_snapshot = worktree.snapshot();
|
||||
let hide_gitignore = ProjectPanelSettings::get_global(cx).hide_gitignore;
|
||||
let mut siblings: Vec<_> = ChildEntriesGitIter::new(&snapshot, parent_path)
|
||||
.filter(|sibling| {
|
||||
(sibling.id == latest_entry.id)
|
||||
|| (!marked_entries_in_worktree.contains(&&SelectedEntry {
|
||||
worktree_id,
|
||||
entry_id: sibling.id,
|
||||
}) && (!hide_gitignore || !sibling.is_ignored))
|
||||
})
|
||||
.map(|entry| entry.to_owned())
|
||||
.collect();
|
||||
let mut siblings: Vec<_> =
|
||||
ChildEntriesGitIter::new(&repo_snapshots, &worktree_snapshot, parent_path)
|
||||
.filter(|sibling| {
|
||||
(sibling.id == latest_entry.id)
|
||||
|| (!marked_entries_in_worktree.contains(&&SelectedEntry {
|
||||
worktree_id,
|
||||
entry_id: sibling.id,
|
||||
}) && (!hide_gitignore || !sibling.is_ignored))
|
||||
})
|
||||
.map(|entry| entry.to_owned())
|
||||
.collect();
|
||||
|
||||
project::sort_worktree_entries(&mut siblings);
|
||||
let sibling_entry_index = siblings
|
||||
|
@ -2605,6 +2609,7 @@ impl ProjectPanel {
|
|||
let auto_collapse_dirs = settings.auto_fold_dirs;
|
||||
let hide_gitignore = settings.hide_gitignore;
|
||||
let project = self.project.read(cx);
|
||||
let repo_snapshots = project.git_store().read(cx).repo_snapshots(cx);
|
||||
self.last_worktree_root_id = project
|
||||
.visible_worktrees(cx)
|
||||
.next_back()
|
||||
|
@ -2615,15 +2620,15 @@ impl ProjectPanel {
|
|||
self.visible_entries.clear();
|
||||
let mut max_width_item = None;
|
||||
for worktree in project.visible_worktrees(cx) {
|
||||
let snapshot = worktree.read(cx).snapshot();
|
||||
let worktree_id = snapshot.id();
|
||||
let worktree_snapshot = worktree.read(cx).snapshot();
|
||||
let worktree_id = worktree_snapshot.id();
|
||||
|
||||
let expanded_dir_ids = match self.expanded_dir_ids.entry(worktree_id) {
|
||||
hash_map::Entry::Occupied(e) => e.into_mut(),
|
||||
hash_map::Entry::Vacant(e) => {
|
||||
// The first time a worktree's root entry becomes available,
|
||||
// mark that root entry as expanded.
|
||||
if let Some(entry) = snapshot.root_entry() {
|
||||
if let Some(entry) = worktree_snapshot.root_entry() {
|
||||
e.insert(vec![entry.id]).as_slice()
|
||||
} else {
|
||||
&[]
|
||||
|
@ -2645,14 +2650,15 @@ impl ProjectPanel {
|
|||
}
|
||||
|
||||
let mut visible_worktree_entries = Vec::new();
|
||||
let mut entry_iter = GitTraversal::new(snapshot.entries(true, 0));
|
||||
let mut entry_iter =
|
||||
GitTraversal::new(&repo_snapshots, worktree_snapshot.entries(true, 0));
|
||||
let mut auto_folded_ancestors = vec![];
|
||||
while let Some(entry) = entry_iter.entry() {
|
||||
if auto_collapse_dirs && entry.kind.is_dir() {
|
||||
auto_folded_ancestors.push(entry.id);
|
||||
if !self.unfolded_dir_ids.contains(&entry.id) {
|
||||
if let Some(root_path) = snapshot.root_entry() {
|
||||
let mut child_entries = snapshot.child_entries(&entry.path);
|
||||
if let Some(root_path) = worktree_snapshot.root_entry() {
|
||||
let mut child_entries = worktree_snapshot.child_entries(&entry.path);
|
||||
if let Some(child) = child_entries.next() {
|
||||
if entry.path != root_path.path
|
||||
&& child_entries.next().is_none()
|
||||
|
@ -3297,10 +3303,16 @@ impl ProjectPanel {
|
|||
.cloned();
|
||||
}
|
||||
|
||||
let repo_snapshots = self
|
||||
.project
|
||||
.read(cx)
|
||||
.git_store()
|
||||
.read(cx)
|
||||
.repo_snapshots(cx);
|
||||
let worktree = self.project.read(cx).worktree_for_id(worktree_id, cx)?;
|
||||
worktree.update(cx, |tree, _| {
|
||||
utils::ReversibleIterable::new(
|
||||
GitTraversal::new(tree.entries(true, 0usize)),
|
||||
GitTraversal::new(&repo_snapshots, tree.entries(true, 0usize)),
|
||||
reverse_search,
|
||||
)
|
||||
.find_single_ended(|ele| predicate(*ele, worktree_id))
|
||||
|
@ -3320,6 +3332,12 @@ impl ProjectPanel {
|
|||
.iter()
|
||||
.map(|(worktree_id, _, _)| *worktree_id)
|
||||
.collect();
|
||||
let repo_snapshots = self
|
||||
.project
|
||||
.read(cx)
|
||||
.git_store()
|
||||
.read(cx)
|
||||
.repo_snapshots(cx);
|
||||
|
||||
let mut last_found: Option<SelectedEntry> = None;
|
||||
|
||||
|
@ -3334,12 +3352,10 @@ impl ProjectPanel {
|
|||
let root_entry = tree.root_entry()?;
|
||||
let tree_id = tree.id();
|
||||
|
||||
let mut first_iter = GitTraversal::new(tree.traverse_from_path(
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
entry.path.as_ref(),
|
||||
));
|
||||
let mut first_iter = GitTraversal::new(
|
||||
&repo_snapshots,
|
||||
tree.traverse_from_path(true, true, true, entry.path.as_ref()),
|
||||
);
|
||||
|
||||
if reverse_search {
|
||||
first_iter.next();
|
||||
|
@ -3352,7 +3368,7 @@ impl ProjectPanel {
|
|||
.find(|ele| predicate(*ele, tree_id))
|
||||
.map(|ele| ele.to_owned());
|
||||
|
||||
let second_iter = GitTraversal::new(tree.entries(true, 0usize));
|
||||
let second_iter = GitTraversal::new(&repo_snapshots, tree.entries(true, 0usize));
|
||||
|
||||
let second = if reverse_search {
|
||||
second_iter
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue