Detailed changes
@@ -13222,6 +13222,7 @@ dependencies = [
"dap",
"dap_adapters",
"debug_adapter_extension",
+ "editor",
"env_logger 0.11.8",
"extension",
"extension_host",
@@ -13260,6 +13261,7 @@ dependencies = [
"unindent",
"util",
"watch",
+ "workspace",
"worktree",
"zlog",
]
@@ -134,6 +134,7 @@ use project::{
},
session::{Session, SessionEvent},
},
+ git_store::{GitStoreEvent, RepositoryEvent},
project_settings::DiagnosticSeverity,
};
@@ -1866,6 +1867,31 @@ 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| {
+ match event {
+ GitStoreEvent::RepositoryUpdated(
+ _,
+ RepositoryEvent::Updated {
+ new_instance: true, ..
+ },
+ _,
+ ) => {
+ this.load_diff_task = Some(
+ update_uncommitted_diff_for_buffer(
+ cx.entity(),
+ &project,
+ this.buffer.read(cx).all_buffers(),
+ this.buffer.clone(),
+ cx,
+ )
+ .shared(),
+ );
+ }
+ _ => {}
+ }
+ }));
}
}
@@ -475,7 +475,7 @@ impl GitPanel {
}
GitStoreEvent::RepositoryUpdated(
_,
- RepositoryEvent::Updated { full_scan },
+ RepositoryEvent::Updated { full_scan, .. },
true,
) => {
this.schedule_update(*full_scan, window, cx);
@@ -292,7 +292,7 @@ pub enum RepositoryState {
#[derive(Clone, Debug)]
pub enum RepositoryEvent {
- Updated { full_scan: bool },
+ Updated { full_scan: bool, new_instance: bool },
MergeHeadsChanged,
}
@@ -1496,7 +1496,7 @@ impl GitStore {
repo.update(cx, {
let update = update.clone();
- |repo, cx| repo.apply_remote_update(update, cx)
+ |repo, cx| repo.apply_remote_update(update, is_new, cx)
})?;
this.active_repo_id.get_or_insert_with(|| {
@@ -3597,7 +3597,10 @@ impl Repository {
let snapshot = this.update(&mut cx, |this, cx| {
this.snapshot.branch = branch;
let snapshot = this.snapshot.clone();
- cx.emit(RepositoryEvent::Updated { full_scan: false });
+ cx.emit(RepositoryEvent::Updated {
+ full_scan: false,
+ new_instance: false,
+ });
snapshot
})?;
if let Some(updates_tx) = updates_tx {
@@ -3942,6 +3945,7 @@ 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(
@@ -3975,7 +3979,10 @@ impl Repository {
if update.is_last_update {
self.snapshot.scan_id = update.scan_id;
}
- cx.emit(RepositoryEvent::Updated { full_scan: true });
+ cx.emit(RepositoryEvent::Updated {
+ full_scan: true,
+ new_instance: is_new,
+ });
Ok(())
}
@@ -4305,7 +4312,10 @@ impl Repository {
.ok();
}
}
- cx.emit(RepositoryEvent::Updated { full_scan: false });
+ cx.emit(RepositoryEvent::Updated {
+ full_scan: false,
+ new_instance: false,
+ });
})
},
);
@@ -4565,7 +4575,10 @@ async fn compute_snapshot(
|| branch != prev_snapshot.branch
|| statuses_by_path != prev_snapshot.statuses_by_path
{
- events.push(RepositoryEvent::Updated { full_scan: true });
+ events.push(RepositoryEvent::Updated {
+ full_scan: true,
+ new_instance: false,
+ });
}
// Cache merge conflict paths so they don't change from staging/unstaging,
@@ -75,6 +75,8 @@ assistant_tools.workspace = true
client = { workspace = true, features = ["test-support"] }
clock = { workspace = true, features = ["test-support"] }
dap = { workspace = true, features = ["test-support"] }
+editor = { workspace = true, features = ["test-support"] }
+workspace = { workspace = true, features = ["test-support"] }
fs = { workspace = true, features = ["test-support"] }
gpui = { workspace = true, features = ["test-support"] }
http_client = { workspace = true, features = ["test-support"] }
@@ -1434,6 +1434,148 @@ async fn test_remote_git_diffs(cx: &mut TestAppContext, server_cx: &mut TestAppC
});
}
+// TODO: this test fails on Windows.
+#[cfg(not(windows))]
+#[gpui::test]
+async fn test_remote_git_diffs_when_recv_update_repository_delay(
+ cx: &mut TestAppContext,
+ server_cx: &mut TestAppContext,
+) {
+ use editor::Editor;
+ use gpui::VisualContext;
+ let text_2 = "
+ fn one() -> usize {
+ 1
+ }
+ "
+ .unindent();
+ let text_1 = "
+ fn one() -> usize {
+ 0
+ }
+ "
+ .unindent();
+
+ let fs = FakeFs::new(server_cx.executor());
+ fs.insert_tree(
+ "/code",
+ json!({
+ "project1": {
+ "src": {
+ "lib.rs": text_2
+ },
+ "README.md": "# project 1",
+ },
+ }),
+ )
+ .await;
+
+ let (project, _headless) = init_test(&fs, cx, server_cx).await;
+ let (worktree, _) = project
+ .update(cx, |project, cx| {
+ project.find_or_create_worktree("/code/project1", true, cx)
+ })
+ .await
+ .unwrap();
+ let worktree_id = cx.update(|cx| worktree.read(cx).id());
+ let buffer = project
+ .update(cx, |project, cx| {
+ project.open_buffer((worktree_id, Path::new("src/lib.rs")), cx)
+ })
+ .await
+ .unwrap();
+ let buffer_id = cx.update(|cx| buffer.read(cx).remote_id());
+ cx.update(|cx| {
+ workspace::init_settings(cx);
+ editor::init_settings(cx);
+ });
+ let cx = cx.add_empty_window();
+ let editor = cx.new_window_entity(|window, cx| {
+ Editor::for_buffer(buffer, Some(project.clone()), window, cx)
+ });
+
+ // Remote server will send proto::UpdateRepository after the instance of Editor create.
+ fs.insert_tree(
+ "/code",
+ json!({
+ "project1": {
+ ".git": {},
+ },
+ }),
+ )
+ .await;
+
+ fs.set_index_for_repo(
+ Path::new("/code/project1/.git"),
+ &[("src/lib.rs".into(), text_1.clone())],
+ );
+ fs.set_head_for_repo(
+ Path::new("/code/project1/.git"),
+ &[("src/lib.rs".into(), text_1.clone())],
+ "sha",
+ );
+
+ cx.executor().run_until_parked();
+ let diff = editor
+ .read_with(cx, |editor, cx| {
+ editor
+ .buffer()
+ .read_with(cx, |buffer, _| buffer.diff_for(buffer_id))
+ })
+ .unwrap();
+
+ diff.read_with(cx, |diff, cx| {
+ assert_eq!(diff.base_text_string().unwrap(), text_1);
+ assert_eq!(
+ diff.secondary_diff()
+ .unwrap()
+ .read(cx)
+ .base_text_string()
+ .unwrap(),
+ text_1
+ );
+ });
+
+ // stage the current buffer's contents
+ fs.set_index_for_repo(
+ Path::new("/code/project1/.git"),
+ &[("src/lib.rs".into(), text_2.clone())],
+ );
+
+ cx.executor().run_until_parked();
+ diff.read_with(cx, |diff, cx| {
+ assert_eq!(diff.base_text_string().unwrap(), text_1);
+ assert_eq!(
+ diff.secondary_diff()
+ .unwrap()
+ .read(cx)
+ .base_text_string()
+ .unwrap(),
+ text_2
+ );
+ });
+
+ // commit the current buffer's contents
+ fs.set_head_for_repo(
+ Path::new("/code/project1/.git"),
+ &[("src/lib.rs".into(), text_2.clone())],
+ "sha",
+ );
+
+ cx.executor().run_until_parked();
+ diff.read_with(cx, |diff, cx| {
+ assert_eq!(diff.base_text_string().unwrap(), text_2);
+ assert_eq!(
+ diff.secondary_diff()
+ .unwrap()
+ .read(cx)
+ .base_text_string()
+ .unwrap(),
+ text_2
+ );
+ });
+}
+
#[gpui::test]
async fn test_remote_git_branches(cx: &mut TestAppContext, server_cx: &mut TestAppContext) {
let fs = FakeFs::new(server_cx.executor());