Detailed changes
@@ -156,7 +156,7 @@ use project::{
},
session::{Session, SessionEvent},
},
- git_store::{GitStoreEvent, RepositoryEvent},
+ git_store::GitStoreEvent,
lsp_store::{
CacheInlayHints, CompletionDocumentation, FormatTrigger, LspFormatTarget,
OpenLspBufferHandle,
@@ -1978,14 +1978,7 @@ impl Editor {
let git_store = project.read(cx).git_store().clone();
let project = project.clone();
project_subscriptions.push(cx.subscribe(&git_store, move |this, _, event, cx| {
- if let GitStoreEvent::RepositoryUpdated(
- _,
- RepositoryEvent::Updated {
- new_instance: true, ..
- },
- _,
- ) = event
- {
+ if let GitStoreEvent::RepositoryAdded = event {
this.load_diff_task = Some(
update_uncommitted_diff_for_buffer(
cx.entity(),
@@ -12615,18 +12615,6 @@ async fn test_strip_whitespace_and_format_via_lsp(cx: &mut TestAppContext) {
)
.await;
- cx.run_until_parked();
- // Set up a buffer white some trailing whitespace and no trailing newline.
- cx.set_state(
- &[
- "one ", //
- "twoΛ", //
- "three ", //
- "four", //
- ]
- .join("\n"),
- );
-
// Record which buffer changes have been sent to the language server
let buffer_changes = Arc::new(Mutex::new(Vec::new()));
cx.lsp
@@ -12641,8 +12629,6 @@ async fn test_strip_whitespace_and_format_via_lsp(cx: &mut TestAppContext) {
);
}
});
- cx.run_until_parked();
-
// Handle formatting requests to the language server.
cx.lsp
.set_request_handler::<lsp::request::Formatting, _, _>({
@@ -12691,6 +12677,18 @@ async fn test_strip_whitespace_and_format_via_lsp(cx: &mut TestAppContext) {
}
});
+ // Set up a buffer white some trailing whitespace and no trailing newline.
+ cx.set_state(
+ &[
+ "one ", //
+ "twoΛ", //
+ "three ", //
+ "four", //
+ ]
+ .join("\n"),
+ );
+ cx.run_until_parked();
+
// Submit a format request.
let format = cx
.update_editor(|editor, window, cx| editor.format(&Format, window, cx))
@@ -16,7 +16,7 @@ use markdown::Markdown;
use multi_buffer::{MultiBuffer, RowInfo};
use project::{
Project, ProjectItem as _,
- git_store::{GitStoreEvent, Repository, RepositoryEvent},
+ git_store::{GitStoreEvent, Repository},
};
use smallvec::SmallVec;
use std::{sync::Arc, time::Duration};
@@ -235,8 +235,8 @@ impl GitBlame {
let git_store = project.read(cx).git_store().clone();
let git_store_subscription =
cx.subscribe(&git_store, move |this, _, event, cx| match event {
- GitStoreEvent::RepositoryUpdated(_, RepositoryEvent::Updated { .. }, _)
- | GitStoreEvent::RepositoryAdded(_)
+ GitStoreEvent::RepositoryUpdated(_, _, _)
+ | GitStoreEvent::RepositoryAdded
| GitStoreEvent::RepositoryRemoved(_) => {
log::debug!("Status of git repositories updated. Regenerating blame data...",);
this.generate(cx);
@@ -11,14 +11,20 @@ use git::{
},
status::{FileStatus, GitStatus, StatusCode, TrackedStatus, UnmergedStatus},
};
-use gpui::{AsyncApp, BackgroundExecutor, SharedString, Task};
+use gpui::{AsyncApp, BackgroundExecutor, SharedString, Task, TaskLabel};
use ignore::gitignore::GitignoreBuilder;
use parking_lot::Mutex;
use rope::Rope;
use smol::future::FutureExt as _;
-use std::{path::PathBuf, sync::Arc};
+use std::{
+ path::PathBuf,
+ sync::{Arc, LazyLock},
+};
use util::{paths::PathStyle, rel_path::RelPath};
+pub static LOAD_INDEX_TEXT_TASK: LazyLock<TaskLabel> = LazyLock::new(TaskLabel::new);
+pub static LOAD_HEAD_TEXT_TASK: LazyLock<TaskLabel> = LazyLock::new(TaskLabel::new);
+
#[derive(Clone)]
pub struct FakeGitRepository {
pub(crate) fs: Arc<FakeFs>,
@@ -79,33 +85,29 @@ impl GitRepository for FakeGitRepository {
fn reload_index(&self) {}
fn load_index_text(&self, path: RepoPath) -> BoxFuture<'_, Option<String>> {
- async {
- self.with_state_async(false, move |state| {
- state
- .index_contents
- .get(&path)
- .context("not present in index")
- .cloned()
- })
- .await
- .ok()
- }
- .boxed()
+ let fut = self.with_state_async(false, move |state| {
+ state
+ .index_contents
+ .get(&path)
+ .context("not present in index")
+ .cloned()
+ });
+ self.executor
+ .spawn_labeled(*LOAD_INDEX_TEXT_TASK, async move { fut.await.ok() })
+ .boxed()
}
fn load_committed_text(&self, path: RepoPath) -> BoxFuture<'_, Option<String>> {
- async {
- self.with_state_async(false, move |state| {
- state
- .head_contents
- .get(&path)
- .context("not present in HEAD")
- .cloned()
- })
- .await
- .ok()
- }
- .boxed()
+ let fut = self.with_state_async(false, move |state| {
+ state
+ .head_contents
+ .get(&path)
+ .context("not present in HEAD")
+ .cloned()
+ });
+ self.executor
+ .spawn_labeled(*LOAD_HEAD_TEXT_TASK, async move { fut.await.ok() })
+ .boxed()
}
fn load_commit(
@@ -58,6 +58,9 @@ use smol::io::AsyncReadExt;
#[cfg(any(test, feature = "test-support"))]
use std::ffi::OsStr;
+#[cfg(any(test, feature = "test-support"))]
+pub use fake_git_repo::{LOAD_HEAD_TEXT_TASK, LOAD_INDEX_TEXT_TASK};
+
pub trait Watcher: Send + Sync {
fn add(&self, path: &Path) -> Result<()>;
fn remove(&self, path: &Path) -> Result<()>;
@@ -425,13 +425,20 @@ impl GitPanel {
}
GitStoreEvent::RepositoryUpdated(
_,
- RepositoryEvent::Updated { full_scan, .. },
+ RepositoryEvent::StatusesChanged { full_scan: true }
+ | RepositoryEvent::BranchChanged
+ | RepositoryEvent::MergeHeadsChanged,
true,
) => {
- this.schedule_update(*full_scan, window, cx);
+ this.schedule_update(true, window, cx);
}
-
- GitStoreEvent::RepositoryAdded(_) | GitStoreEvent::RepositoryRemoved(_) => {
+ GitStoreEvent::RepositoryUpdated(
+ _,
+ RepositoryEvent::StatusesChanged { full_scan: false },
+ true,
+ )
+ | GitStoreEvent::RepositoryAdded
+ | GitStoreEvent::RepositoryRemoved(_) => {
this.schedule_update(false, window, cx);
}
GitStoreEvent::IndexWriteError(error) => {
@@ -6,7 +6,7 @@ use crate::{
};
use anyhow::Result;
use buffer_diff::{BufferDiff, DiffHunkSecondaryStatus};
-use collections::HashSet;
+use collections::{HashMap, HashSet};
use editor::{
Editor, EditorEvent, SelectionEffects,
actions::{GoToHunk, GoToPreviousHunk},
@@ -27,7 +27,7 @@ use language::{Anchor, Buffer, Capability, OffsetRangeExt};
use multi_buffer::{MultiBuffer, PathKey};
use project::{
Project, ProjectPath,
- git_store::{GitStore, GitStoreEvent, Repository},
+ git_store::{GitStore, GitStoreEvent, Repository, RepositoryEvent},
};
use settings::{Settings, SettingsStore};
use std::any::{Any, TypeId};
@@ -57,12 +57,13 @@ pub struct ProjectDiff {
multibuffer: Entity<MultiBuffer>,
editor: Entity<Editor>,
git_store: Entity<GitStore>,
+ buffer_diff_subscriptions: HashMap<RepoPath, (Entity<BufferDiff>, Subscription)>,
workspace: WeakEntity<Workspace>,
focus_handle: FocusHandle,
update_needed: postage::watch::Sender<()>,
pending_scroll: Option<PathKey>,
_task: Task<Result<()>>,
- _subscription: Subscription,
+ _git_store_subscription: Subscription,
}
#[derive(Debug)]
@@ -177,7 +178,11 @@ impl ProjectDiff {
window,
move |this, _git_store, event, _window, _cx| match event {
GitStoreEvent::ActiveRepositoryChanged(_)
- | GitStoreEvent::RepositoryUpdated(_, _, true)
+ | GitStoreEvent::RepositoryUpdated(
+ _,
+ RepositoryEvent::StatusesChanged { full_scan: _ },
+ true,
+ )
| GitStoreEvent::ConflictsUpdated => {
*this.update_needed.borrow_mut() = ();
}
@@ -217,10 +222,11 @@ impl ProjectDiff {
focus_handle,
editor,
multibuffer,
+ buffer_diff_subscriptions: Default::default(),
pending_scroll: None,
update_needed: send,
_task: worker,
- _subscription: git_store_subscription,
+ _git_store_subscription: git_store_subscription,
}
}
@@ -365,6 +371,7 @@ impl ProjectDiff {
self.multibuffer.update(cx, |multibuffer, cx| {
multibuffer.clear(cx);
});
+ self.buffer_diff_subscriptions.clear();
return vec![];
};
@@ -407,6 +414,8 @@ impl ProjectDiff {
});
self.multibuffer.update(cx, |multibuffer, cx| {
for path in previous_paths {
+ self.buffer_diff_subscriptions
+ .remove(&path.path.clone().into());
multibuffer.remove_excerpts_for_path(path, cx);
}
});
@@ -419,9 +428,15 @@ impl ProjectDiff {
window: &mut Window,
cx: &mut Context<Self>,
) {
- let path_key = diff_buffer.path_key;
- let buffer = diff_buffer.buffer;
- let diff = diff_buffer.diff;
+ let path_key = diff_buffer.path_key.clone();
+ let buffer = diff_buffer.buffer.clone();
+ let diff = diff_buffer.diff.clone();
+
+ let subscription = cx.subscribe(&diff, move |this, _, _, _| {
+ *this.update_needed.borrow_mut() = ();
+ });
+ self.buffer_diff_subscriptions
+ .insert(path_key.path.clone().into(), (diff.clone(), subscription));
let conflict_addon = self
.editor
@@ -440,9 +455,10 @@ impl ProjectDiff {
.unwrap_or_default();
let conflicts = conflicts.iter().map(|conflict| conflict.range.clone());
- let excerpt_ranges = merge_anchor_ranges(diff_hunk_ranges, conflicts, &snapshot)
- .map(|range| range.to_point(&snapshot))
- .collect::<Vec<_>>();
+ let excerpt_ranges =
+ merge_anchor_ranges(diff_hunk_ranges.into_iter(), conflicts, &snapshot)
+ .map(|range| range.to_point(&snapshot))
+ .collect::<Vec<_>>();
let (was_empty, is_excerpt_newly_added) = self.multibuffer.update(cx, |multibuffer, cx| {
let was_empty = multibuffer.is_empty();
@@ -519,8 +535,7 @@ impl ProjectDiff {
self.multibuffer
.read(cx)
.excerpt_paths()
- .map(|key| key.path())
- .cloned()
+ .map(|key| key.path.clone())
.collect()
}
}
@@ -1621,8 +1636,8 @@ mod tests {
cx,
&"
- original
- + different
- Λ"
+ + Λdifferent
+ "
.unindent(),
);
}
@@ -1950,6 +1965,7 @@ mod tests {
.unindent(),
);
+ // The project diff updates its excerpts when a new hunk appears in a buffer that already has a diff.
let buffer = project
.update(cx, |project, cx| {
project.open_local_buffer(path!("/project/foo.txt"), cx)
@@ -2002,4 +2018,63 @@ mod tests {
.unindent(),
);
}
+
+ #[gpui::test]
+ async fn test_update_on_uncommit(cx: &mut TestAppContext) {
+ init_test(cx);
+
+ let fs = FakeFs::new(cx.executor());
+ fs.insert_tree(
+ path!("/project"),
+ json!({
+ ".git": {},
+ "README.md": "# My cool project\n".to_owned()
+ }),
+ )
+ .await;
+ fs.set_head_and_index_for_repo(
+ Path::new(path!("/project/.git")),
+ &[("README.md", "# My cool project\n".to_owned())],
+ );
+ let project = Project::test(fs.clone(), [Path::new(path!("/project"))], cx).await;
+ let worktree_id = project.read_with(cx, |project, cx| {
+ project.worktrees(cx).next().unwrap().read(cx).id()
+ });
+ let (workspace, cx) =
+ cx.add_window_view(|window, cx| Workspace::test_new(project.clone(), window, cx));
+ cx.run_until_parked();
+
+ let _editor = workspace
+ .update_in(cx, |workspace, window, cx| {
+ workspace.open_path((worktree_id, rel_path("README.md")), None, true, window, cx)
+ })
+ .await
+ .unwrap()
+ .downcast::<Editor>()
+ .unwrap();
+
+ cx.focus(&workspace);
+ cx.update(|window, cx| {
+ window.dispatch_action(project_diff::Diff.boxed_clone(), cx);
+ });
+ cx.run_until_parked();
+ let item = workspace.update(cx, |workspace, cx| {
+ workspace.active_item_as::<ProjectDiff>(cx).unwrap()
+ });
+ cx.focus(&item);
+ let editor = item.read_with(cx, |item, _| item.editor.clone());
+
+ fs.set_head_and_index_for_repo(
+ Path::new(path!("/project/.git")),
+ &[(
+ "README.md",
+ "# My cool project\nDetails to come.\n".to_owned(),
+ )],
+ );
+ cx.run_until_parked();
+
+ let mut cx = EditorTestContext::for_editor_in(editor, cx).await;
+
+ cx.assert_excerpts_with_selections("[EXCERPT]\nΛ# My cool project\nDetails to come.\n");
+ }
}
@@ -72,7 +72,7 @@ impl StashList {
if let Some(repo) = repository.clone() {
_subscriptions.push(
cx.subscribe_in(&repo, window, |this, _, event, window, cx| {
- if matches!(event, RepositoryEvent::Updated { .. }) {
+ if matches!(event, RepositoryEvent::StashEntriesChanged) {
let stash_entries = this.picker.read_with(cx, |picker, cx| {
picker
.delegate
@@ -166,8 +166,8 @@ impl MultiBufferDiffHunk {
#[derive(PartialEq, Eq, Ord, PartialOrd, Clone, Hash, Debug)]
pub struct PathKey {
// Used by the derived PartialOrd & Ord
- sort_prefix: Option<u64>,
- path: Arc<RelPath>,
+ pub sort_prefix: Option<u64>,
+ pub path: Arc<RelPath>,
}
impl PathKey {
@@ -190,11 +190,6 @@ impl PathKey {
}
}
}
-
- #[cfg(any(test, feature = "test-support"))]
- pub fn path(&self) -> &Arc<RelPath> {
- &self.path
- }
}
pub type MultiBufferPoint = Point;
@@ -301,9 +301,13 @@ pub enum RepositoryState {
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum RepositoryEvent {
- Updated { full_scan: bool, new_instance: bool },
+ StatusesChanged {
+ // TODO could report which statuses changed here
+ full_scan: bool,
+ },
MergeHeadsChanged,
- PathsChanged,
+ BranchChanged,
+ StashEntriesChanged,
}
#[derive(Clone, Debug)]
@@ -313,7 +317,7 @@ pub struct JobsUpdated;
pub enum GitStoreEvent {
ActiveRepositoryChanged(Option<RepositoryId>),
RepositoryUpdated(RepositoryId, RepositoryEvent, bool),
- RepositoryAdded(RepositoryId),
+ RepositoryAdded,
RepositoryRemoved(RepositoryId),
IndexWriteError(anyhow::Error),
JobsUpdated,
@@ -1218,7 +1222,7 @@ impl GitStore {
self._subscriptions
.push(cx.subscribe(&repo, Self::on_jobs_updated));
self.repositories.insert(id, repo);
- cx.emit(GitStoreEvent::RepositoryAdded(id));
+ cx.emit(GitStoreEvent::RepositoryAdded);
self.active_repo_id.get_or_insert_with(|| {
cx.emit(GitStoreEvent::ActiveRepositoryChanged(Some(id)));
id
@@ -1485,11 +1489,10 @@ impl GitStore {
let id = RepositoryId::from_proto(update.id);
let client = this.upstream_client().context("no upstream client")?;
- let mut is_new = false;
+ let mut repo_subscription = None;
let repo = this.repositories.entry(id).or_insert_with(|| {
- is_new = true;
let git_store = cx.weak_entity();
- cx.new(|cx| {
+ let repo = cx.new(|cx| {
Repository::remote(
id,
Path::new(&update.abs_path).into(),
@@ -1499,16 +1502,16 @@ impl GitStore {
git_store,
cx,
)
- })
+ });
+ repo_subscription = Some(cx.subscribe(&repo, Self::on_repository_event));
+ cx.emit(GitStoreEvent::RepositoryAdded);
+ repo
});
- if is_new {
- this._subscriptions
- .push(cx.subscribe(repo, Self::on_repository_event))
- }
+ this._subscriptions.extend(repo_subscription);
repo.update(cx, {
let update = update.clone();
- |repo, cx| repo.apply_remote_update(update, is_new, cx)
+ |repo, cx| repo.apply_remote_update(update, cx)
})?;
this.active_repo_id.get_or_insert_with(|| {
@@ -3877,18 +3880,15 @@ impl Repository {
environment,
..
} => {
+ // TODO would be nice to not have to do this manually
let result = backend.stash_drop(index, environment).await;
if result.is_ok()
&& let Ok(stash_entries) = backend.stash_entries().await
{
let snapshot = this.update(&mut cx, |this, cx| {
this.snapshot.stash_entries = stash_entries;
- let snapshot = this.snapshot.clone();
- cx.emit(RepositoryEvent::Updated {
- full_scan: false,
- new_instance: false,
- });
- snapshot
+ cx.emit(RepositoryEvent::StashEntriesChanged);
+ this.snapshot.clone()
})?;
if let Some(updates_tx) = updates_tx {
updates_tx
@@ -4048,18 +4048,15 @@ impl Repository {
cx.clone(),
)
.await;
+ // TODO would be nice to not have to do this manually
if result.is_ok() {
let branches = backend.branches().await?;
let branch = branches.into_iter().find(|branch| branch.is_head);
log::info!("head branch after scan is {branch:?}");
let snapshot = this.update(&mut cx, |this, cx| {
this.snapshot.branch = branch;
- let snapshot = this.snapshot.clone();
- cx.emit(RepositoryEvent::Updated {
- full_scan: false,
- new_instance: false,
- });
- snapshot
+ cx.emit(RepositoryEvent::BranchChanged);
+ this.snapshot.clone()
})?;
if let Some(updates_tx) = updates_tx {
updates_tx
@@ -4458,7 +4455,6 @@ impl Repository {
pub(crate) fn apply_remote_update(
&mut self,
update: proto::UpdateRepository,
- is_new: bool,
cx: &mut Context<Self>,
) -> Result<()> {
let conflicted_paths = TreeSet::from_ordered_entries(
@@ -4467,21 +4463,30 @@ impl Repository {
.into_iter()
.filter_map(|path| RepoPath::from_proto(&path).log_err()),
);
- self.snapshot.branch = update.branch_summary.as_ref().map(proto_to_branch);
- self.snapshot.head_commit = update
+ let new_branch = update.branch_summary.as_ref().map(proto_to_branch);
+ let new_head_commit = update
.head_commit_details
.as_ref()
.map(proto_to_commit_details);
+ if self.snapshot.branch != new_branch || self.snapshot.head_commit != new_head_commit {
+ cx.emit(RepositoryEvent::BranchChanged)
+ }
+ self.snapshot.branch = new_branch;
+ self.snapshot.head_commit = new_head_commit;
self.snapshot.merge.conflicted_paths = conflicted_paths;
self.snapshot.merge.message = update.merge_message.map(SharedString::from);
- self.snapshot.stash_entries = GitStash {
+ let new_stash_entries = GitStash {
entries: update
.stash_entries
.iter()
.filter_map(|entry| proto_to_stash(entry).ok())
.collect(),
};
+ if self.snapshot.stash_entries != new_stash_entries {
+ cx.emit(RepositoryEvent::StashEntriesChanged)
+ }
+ self.snapshot.stash_entries = new_stash_entries;
let edits = update
.removed_statuses
@@ -4500,14 +4505,13 @@ impl Repository {
}),
)
.collect::<Vec<_>>();
+ if !edits.is_empty() {
+ cx.emit(RepositoryEvent::StatusesChanged { full_scan: true });
+ }
self.snapshot.statuses_by_path.edit(edits, ());
if update.is_last_update {
self.snapshot.scan_id = update.scan_id;
}
- cx.emit(RepositoryEvent::Updated {
- full_scan: true,
- new_instance: is_new,
- });
Ok(())
}
@@ -4830,23 +4834,19 @@ impl Repository {
.await;
this.update(&mut cx, |this, cx| {
- let needs_update = !changed_path_statuses.is_empty()
- || this.snapshot.stash_entries != stash_entries;
- this.snapshot.stash_entries = stash_entries;
+ if this.snapshot.stash_entries != stash_entries {
+ cx.emit(RepositoryEvent::StashEntriesChanged);
+ this.snapshot.stash_entries = stash_entries;
+ }
+
if !changed_path_statuses.is_empty() {
+ cx.emit(RepositoryEvent::StatusesChanged { full_scan: false });
this.snapshot
.statuses_by_path
.edit(changed_path_statuses, ());
this.snapshot.scan_id += 1;
}
- if needs_update {
- cx.emit(RepositoryEvent::Updated {
- full_scan: false,
- new_instance: false,
- });
- }
-
if let Some(updates_tx) = updates_tx {
updates_tx
.unbounded_send(DownstreamUpdate::UpdateRepository(
@@ -4854,7 +4854,6 @@ impl Repository {
))
.ok();
}
- cx.emit(RepositoryEvent::PathsChanged);
})
},
);
@@ -5117,28 +5116,24 @@ async fn compute_snapshot(
MergeDetails::load(&backend, &statuses_by_path, &prev_snapshot).await?;
log::debug!("new merge details (changed={merge_heads_changed:?}): {merge_details:?}");
- if merge_heads_changed
- || branch != prev_snapshot.branch
- || statuses_by_path != prev_snapshot.statuses_by_path
- {
- events.push(RepositoryEvent::Updated {
- full_scan: true,
- new_instance: false,
- });
- }
-
- // Cache merge conflict paths so they don't change from staging/unstaging,
- // until the merge heads change (at commit time, etc.).
if merge_heads_changed {
events.push(RepositoryEvent::MergeHeadsChanged);
}
+ if statuses_by_path != prev_snapshot.statuses_by_path {
+ events.push(RepositoryEvent::StatusesChanged { full_scan: true })
+ }
+
// Useful when branch is None in detached head state
let head_commit = match backend.head_sha().await {
Some(head_sha) => backend.show(head_sha).await.log_err(),
None => None,
};
+ if branch != prev_snapshot.branch || head_commit != prev_snapshot.head_commit {
+ events.push(RepositoryEvent::BranchChanged);
+ }
+
// Used by edit prediction data collection
let remote_origin_url = backend.remote_url("origin");
let remote_upstream_url = backend.remote_url("upstream");
@@ -8936,10 +8936,7 @@ async fn test_ignored_dirs_events(cx: &mut gpui::TestAppContext) {
assert_eq!(
repository_updates.lock().drain(..).collect::<Vec<_>>(),
vec![
- RepositoryEvent::Updated {
- full_scan: true,
- new_instance: false,
- },
+ RepositoryEvent::StatusesChanged { full_scan: true },
RepositoryEvent::MergeHeadsChanged,
],
"Initial worktree scan should produce a repo update event"
@@ -9000,7 +8997,6 @@ async fn test_ignored_dirs_events(cx: &mut gpui::TestAppContext) {
repository_updates
.lock()
.iter()
- .filter(|update| !matches!(update, RepositoryEvent::PathsChanged))
.cloned()
.collect::<Vec<_>>(),
Vec::new(),
@@ -9104,17 +9100,10 @@ async fn test_odd_events_for_ignored_dirs(
});
assert_eq!(
- repository_updates
- .lock()
- .drain(..)
- .filter(|update| !matches!(update, RepositoryEvent::PathsChanged))
- .collect::<Vec<_>>(),
+ repository_updates.lock().drain(..).collect::<Vec<_>>(),
vec![
- RepositoryEvent::Updated {
- full_scan: true,
- new_instance: false,
- },
RepositoryEvent::MergeHeadsChanged,
+ RepositoryEvent::BranchChanged
],
"Initial worktree scan should produce a repo update event"
);
@@ -9142,7 +9131,6 @@ async fn test_odd_events_for_ignored_dirs(
repository_updates
.lock()
.iter()
- .filter(|update| !matches!(update, RepositoryEvent::PathsChanged))
.cloned()
.collect::<Vec<_>>(),
Vec::new(),
@@ -496,8 +496,12 @@ impl ProjectPanel {
&git_store,
window,
|this, _, event, window, cx| match event {
- GitStoreEvent::RepositoryUpdated(_, RepositoryEvent::Updated { .. }, _)
- | GitStoreEvent::RepositoryAdded(_)
+ GitStoreEvent::RepositoryUpdated(
+ _,
+ RepositoryEvent::StatusesChanged { full_scan: _ },
+ _,
+ )
+ | GitStoreEvent::RepositoryAdded
| GitStoreEvent::RepositoryRemoved(_) => {
this.update_visible_entries(None, false, false, window, cx);
cx.notify();
@@ -30,10 +30,7 @@ use gpui::{
Subscription, WeakEntity, Window, actions, div,
};
use onboarding_banner::OnboardingBanner;
-use project::{
- Project, WorktreeSettings,
- git_store::{GitStoreEvent, RepositoryEvent},
-};
+use project::{Project, WorktreeSettings, git_store::GitStoreEvent};
use remote::RemoteConnectionOptions;
use settings::{Settings, SettingsLocation};
use std::sync::Arc;
@@ -287,9 +284,7 @@ impl TitleBar {
subscriptions.push(
cx.subscribe(&git_store, move |_, _, event, cx| match event {
GitStoreEvent::ActiveRepositoryChanged(_)
- | GitStoreEvent::RepositoryUpdated(_, RepositoryEvent::Updated { .. }, _)
- | GitStoreEvent::RepositoryAdded(_)
- | GitStoreEvent::RepositoryRemoved(_) => {
+ | GitStoreEvent::RepositoryUpdated(_, _, true) => {
cx.notify();
}
_ => {}