Fix diff indicators not restored when reopening remote project (#31384)
Closes #30917 Release Notes: - Fix diff indicators not restored when reopening remote project --------- Co-authored-by: Cole Miller <cole@zed.dev>
This commit is contained in:
parent
b686fb2917
commit
c766f52f88
6 changed files with 192 additions and 7 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -13222,6 +13222,7 @@ dependencies = [
|
||||||
"dap",
|
"dap",
|
||||||
"dap_adapters",
|
"dap_adapters",
|
||||||
"debug_adapter_extension",
|
"debug_adapter_extension",
|
||||||
|
"editor",
|
||||||
"env_logger 0.11.8",
|
"env_logger 0.11.8",
|
||||||
"extension",
|
"extension",
|
||||||
"extension_host",
|
"extension_host",
|
||||||
|
@ -13260,6 +13261,7 @@ dependencies = [
|
||||||
"unindent",
|
"unindent",
|
||||||
"util",
|
"util",
|
||||||
"watch",
|
"watch",
|
||||||
|
"workspace",
|
||||||
"worktree",
|
"worktree",
|
||||||
"zlog",
|
"zlog",
|
||||||
]
|
]
|
||||||
|
|
|
@ -134,6 +134,7 @@ use project::{
|
||||||
},
|
},
|
||||||
session::{Session, SessionEvent},
|
session::{Session, SessionEvent},
|
||||||
},
|
},
|
||||||
|
git_store::{GitStoreEvent, RepositoryEvent},
|
||||||
project_settings::DiagnosticSeverity,
|
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(
|
GitStoreEvent::RepositoryUpdated(
|
||||||
_,
|
_,
|
||||||
RepositoryEvent::Updated { full_scan },
|
RepositoryEvent::Updated { full_scan, .. },
|
||||||
true,
|
true,
|
||||||
) => {
|
) => {
|
||||||
this.schedule_update(*full_scan, window, cx);
|
this.schedule_update(*full_scan, window, cx);
|
||||||
|
|
|
@ -292,7 +292,7 @@ pub enum RepositoryState {
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum RepositoryEvent {
|
pub enum RepositoryEvent {
|
||||||
Updated { full_scan: bool },
|
Updated { full_scan: bool, new_instance: bool },
|
||||||
MergeHeadsChanged,
|
MergeHeadsChanged,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1496,7 +1496,7 @@ impl GitStore {
|
||||||
|
|
||||||
repo.update(cx, {
|
repo.update(cx, {
|
||||||
let update = update.clone();
|
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(|| {
|
this.active_repo_id.get_or_insert_with(|| {
|
||||||
|
@ -3597,7 +3597,10 @@ impl Repository {
|
||||||
let snapshot = this.update(&mut cx, |this, cx| {
|
let snapshot = this.update(&mut cx, |this, cx| {
|
||||||
this.snapshot.branch = branch;
|
this.snapshot.branch = branch;
|
||||||
let snapshot = this.snapshot.clone();
|
let snapshot = this.snapshot.clone();
|
||||||
cx.emit(RepositoryEvent::Updated { full_scan: false });
|
cx.emit(RepositoryEvent::Updated {
|
||||||
|
full_scan: false,
|
||||||
|
new_instance: false,
|
||||||
|
});
|
||||||
snapshot
|
snapshot
|
||||||
})?;
|
})?;
|
||||||
if let Some(updates_tx) = updates_tx {
|
if let Some(updates_tx) = updates_tx {
|
||||||
|
@ -3942,6 +3945,7 @@ impl Repository {
|
||||||
pub(crate) fn apply_remote_update(
|
pub(crate) fn apply_remote_update(
|
||||||
&mut self,
|
&mut self,
|
||||||
update: proto::UpdateRepository,
|
update: proto::UpdateRepository,
|
||||||
|
is_new: bool,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let conflicted_paths = TreeSet::from_ordered_entries(
|
let conflicted_paths = TreeSet::from_ordered_entries(
|
||||||
|
@ -3975,7 +3979,10 @@ impl Repository {
|
||||||
if update.is_last_update {
|
if update.is_last_update {
|
||||||
self.snapshot.scan_id = update.scan_id;
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4305,7 +4312,10 @@ impl Repository {
|
||||||
.ok();
|
.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
|
|| branch != prev_snapshot.branch
|
||||||
|| statuses_by_path != prev_snapshot.statuses_by_path
|
|| 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,
|
// 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"] }
|
client = { workspace = true, features = ["test-support"] }
|
||||||
clock = { workspace = true, features = ["test-support"] }
|
clock = { workspace = true, features = ["test-support"] }
|
||||||
dap = { 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"] }
|
fs = { workspace = true, features = ["test-support"] }
|
||||||
gpui = { workspace = true, features = ["test-support"] }
|
gpui = { workspace = true, features = ["test-support"] }
|
||||||
http_client = { 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]
|
#[gpui::test]
|
||||||
async fn test_remote_git_branches(cx: &mut TestAppContext, server_cx: &mut TestAppContext) {
|
async fn test_remote_git_branches(cx: &mut TestAppContext, server_cx: &mut TestAppContext) {
|
||||||
let fs = FakeFs::new(server_cx.executor());
|
let fs = FakeFs::new(server_cx.executor());
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue