git: Improve perf of syncing changes
This commit is contained in:
parent
52f2b32557
commit
31a4f6d411
1 changed files with 40 additions and 19 deletions
|
@ -48,13 +48,13 @@ use rpc::{
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::{
|
use std::{
|
||||||
cmp::Ordering,
|
cmp::Ordering,
|
||||||
collections::{BTreeSet, VecDeque},
|
collections::{BTreeMap, BTreeSet, VecDeque},
|
||||||
future::Future,
|
future::Future,
|
||||||
mem,
|
mem,
|
||||||
ops::Range,
|
ops::Range,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
sync::{
|
sync::{
|
||||||
Arc,
|
Arc, OnceLock,
|
||||||
atomic::{self, AtomicU64},
|
atomic::{self, AtomicU64},
|
||||||
},
|
},
|
||||||
time::Instant,
|
time::Instant,
|
||||||
|
@ -72,6 +72,7 @@ pub struct GitStore {
|
||||||
buffer_store: Entity<BufferStore>,
|
buffer_store: Entity<BufferStore>,
|
||||||
worktree_store: Entity<WorktreeStore>,
|
worktree_store: Entity<WorktreeStore>,
|
||||||
repositories: HashMap<RepositoryId, Entity<Repository>>,
|
repositories: HashMap<RepositoryId, Entity<Repository>>,
|
||||||
|
repositories_by_abs_root_path: BTreeMap<Arc<Path>, Entity<Repository>>,
|
||||||
active_repo_id: Option<RepositoryId>,
|
active_repo_id: Option<RepositoryId>,
|
||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
loading_diffs:
|
loading_diffs:
|
||||||
|
@ -400,6 +401,7 @@ impl GitStore {
|
||||||
buffer_store,
|
buffer_store,
|
||||||
worktree_store,
|
worktree_store,
|
||||||
repositories: HashMap::default(),
|
repositories: HashMap::default(),
|
||||||
|
repositories_by_abs_root_path: BTreeMap::default(),
|
||||||
active_repo_id: None,
|
active_repo_id: None,
|
||||||
_subscriptions,
|
_subscriptions,
|
||||||
loading_diffs: HashMap::default(),
|
loading_diffs: HashMap::default(),
|
||||||
|
@ -1193,23 +1195,35 @@ impl GitStore {
|
||||||
) {
|
) {
|
||||||
let mut removed_ids = Vec::new();
|
let mut removed_ids = Vec::new();
|
||||||
for update in updated_git_repositories.iter() {
|
for update in updated_git_repositories.iter() {
|
||||||
if let Some((id, existing)) = self.repositories.iter().find(|(_, repo)| {
|
let existing_repo = update
|
||||||
let existing_work_directory_abs_path =
|
.old_work_directory_abs_path
|
||||||
repo.read(cx).work_directory_abs_path.clone();
|
.as_ref()
|
||||||
Some(&existing_work_directory_abs_path)
|
.and_then(|k| self.repositories_by_abs_root_path.get(k))
|
||||||
== update.old_work_directory_abs_path.as_ref()
|
.or_else(|| {
|
||||||
|| Some(&existing_work_directory_abs_path)
|
update
|
||||||
== update.new_work_directory_abs_path.as_ref()
|
.new_work_directory_abs_path
|
||||||
}) {
|
.as_ref()
|
||||||
|
.and_then(|k| self.repositories_by_abs_root_path.get(k))
|
||||||
|
});
|
||||||
|
if let Some(existing) = existing_repo {
|
||||||
if let Some(new_work_directory_abs_path) =
|
if let Some(new_work_directory_abs_path) =
|
||||||
update.new_work_directory_abs_path.clone()
|
update.new_work_directory_abs_path.clone()
|
||||||
{
|
{
|
||||||
existing.update(cx, |existing, cx| {
|
let old_path = existing.update(cx, |existing, cx| {
|
||||||
existing.snapshot.work_directory_abs_path = new_work_directory_abs_path;
|
let old_path = std::mem::replace(
|
||||||
|
&mut existing.snapshot.work_directory_abs_path,
|
||||||
|
new_work_directory_abs_path.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
existing.schedule_scan(updates_tx.clone(), cx);
|
existing.schedule_scan(updates_tx.clone(), cx);
|
||||||
|
old_path
|
||||||
});
|
});
|
||||||
|
let existing = existing.clone();
|
||||||
|
self.repositories_by_abs_root_path.remove(&old_path);
|
||||||
|
self.repositories_by_abs_root_path
|
||||||
|
.insert(new_work_directory_abs_path, existing);
|
||||||
} else {
|
} else {
|
||||||
removed_ids.push(*id);
|
removed_ids.push(existing.read(cx).id);
|
||||||
}
|
}
|
||||||
} else if let UpdatedGitRepository {
|
} else if let UpdatedGitRepository {
|
||||||
new_work_directory_abs_path: Some(work_directory_abs_path),
|
new_work_directory_abs_path: Some(work_directory_abs_path),
|
||||||
|
@ -1240,7 +1254,9 @@ impl GitStore {
|
||||||
.push(cx.subscribe(&repo, Self::on_repository_event));
|
.push(cx.subscribe(&repo, Self::on_repository_event));
|
||||||
self._subscriptions
|
self._subscriptions
|
||||||
.push(cx.subscribe(&repo, Self::on_jobs_updated));
|
.push(cx.subscribe(&repo, Self::on_jobs_updated));
|
||||||
self.repositories.insert(id, repo);
|
self.repositories.insert(id, repo.clone());
|
||||||
|
self.repositories_by_abs_root_path
|
||||||
|
.insert(work_directory_abs_path.clone(), repo);
|
||||||
cx.emit(GitStoreEvent::RepositoryAdded(id));
|
cx.emit(GitStoreEvent::RepositoryAdded(id));
|
||||||
self.active_repo_id.get_or_insert_with(|| {
|
self.active_repo_id.get_or_insert_with(|| {
|
||||||
cx.emit(GitStoreEvent::ActiveRepositoryChanged(Some(id)));
|
cx.emit(GitStoreEvent::ActiveRepositoryChanged(Some(id)));
|
||||||
|
@ -1254,7 +1270,11 @@ impl GitStore {
|
||||||
self.active_repo_id = None;
|
self.active_repo_id = None;
|
||||||
cx.emit(GitStoreEvent::ActiveRepositoryChanged(None));
|
cx.emit(GitStoreEvent::ActiveRepositoryChanged(None));
|
||||||
}
|
}
|
||||||
self.repositories.remove(&id);
|
let repo = self.repositories.remove(&id);
|
||||||
|
if let Some(repo) = repo {
|
||||||
|
self.repositories_by_abs_root_path
|
||||||
|
.remove(&repo.read(cx).work_directory_abs_path);
|
||||||
|
}
|
||||||
if let Some(updates_tx) = updates_tx.as_ref() {
|
if let Some(updates_tx) = updates_tx.as_ref() {
|
||||||
updates_tx
|
updates_tx
|
||||||
.unbounded_send(DownstreamUpdate::RemoveRepository(id))
|
.unbounded_send(DownstreamUpdate::RemoveRepository(id))
|
||||||
|
@ -1413,13 +1433,14 @@ impl GitStore {
|
||||||
cx: &App,
|
cx: &App,
|
||||||
) -> Option<(Entity<Repository>, RepoPath)> {
|
) -> Option<(Entity<Repository>, RepoPath)> {
|
||||||
let abs_path = self.worktree_store.read(cx).absolutize(path, cx)?;
|
let abs_path = self.worktree_store.read(cx).absolutize(path, cx)?;
|
||||||
self.repositories
|
let range: Range<Arc<Path>> = Arc::from("".as_ref())..Arc::from(abs_path.as_ref());
|
||||||
.values()
|
self.repositories_by_abs_root_path
|
||||||
.filter_map(|repo| {
|
.range(range)
|
||||||
|
.last()
|
||||||
|
.and_then(|(_, repo)| {
|
||||||
let repo_path = repo.read(cx).abs_path_to_repo_path(&abs_path)?;
|
let repo_path = repo.read(cx).abs_path_to_repo_path(&abs_path)?;
|
||||||
Some((repo.clone(), repo_path))
|
Some((repo.clone(), repo_path))
|
||||||
})
|
})
|
||||||
.max_by_key(|(repo, _)| repo.read(cx).work_directory_abs_path.clone())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn git_init(
|
pub fn git_init(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue