SSH Remoting: Fix bugs in worktree syncing (#18406)
Release Notes: - N/A --------- Co-authored-by: conrad <conrad@zed.dev>
This commit is contained in:
parent
11058765be
commit
71da81c743
12 changed files with 157 additions and 92 deletions
|
@ -32,6 +32,7 @@ macro_rules! id_type {
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
pub fn from_proto(value: u64) -> Self {
|
pub fn from_proto(value: u64) -> Self {
|
||||||
|
debug_assert!(value != 0);
|
||||||
Self(value as i32)
|
Self(value as i32)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -285,7 +285,7 @@ impl Database {
|
||||||
)
|
)
|
||||||
.one(&*tx)
|
.one(&*tx)
|
||||||
.await?
|
.await?
|
||||||
.ok_or_else(|| anyhow!("no such project"))?;
|
.ok_or_else(|| anyhow!("no such project: {project_id}"))?;
|
||||||
|
|
||||||
// Update metadata.
|
// Update metadata.
|
||||||
worktree::Entity::update(worktree::ActiveModel {
|
worktree::Entity::update(worktree::ActiveModel {
|
||||||
|
|
|
@ -246,7 +246,7 @@ async fn test_channel_notes_participant_indices(
|
||||||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b);
|
let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b);
|
||||||
|
|
||||||
// Clients A and B open the same file.
|
// Clients A and B open the same file.
|
||||||
|
|
|
@ -76,7 +76,7 @@ async fn test_host_disconnect(
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
cx_a.background_executor.run_until_parked();
|
cx_a.background_executor.run_until_parked();
|
||||||
|
|
||||||
assert!(worktree_a.read_with(cx_a, |tree, _| tree.has_update_observer()));
|
assert!(worktree_a.read_with(cx_a, |tree, _| tree.has_update_observer()));
|
||||||
|
@ -192,7 +192,7 @@ async fn test_newline_above_or_below_does_not_move_guest_cursor(
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
// Open a buffer as client A
|
// Open a buffer as client A
|
||||||
let buffer_a = project_a
|
let buffer_a = project_a
|
||||||
|
@ -308,7 +308,7 @@ async fn test_collaborating_with_completion(cx_a: &mut TestAppContext, cx_b: &mu
|
||||||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
// Open a file in an editor as the guest.
|
// Open a file in an editor as the guest.
|
||||||
let buffer_b = project_b
|
let buffer_b = project_b
|
||||||
|
@ -565,7 +565,7 @@ async fn test_collaborating_with_code_actions(
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Join the project as client B.
|
// Join the project as client B.
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b);
|
let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b);
|
||||||
let editor_b = workspace_b
|
let editor_b = workspace_b
|
||||||
.update(cx_b, |workspace, cx| {
|
.update(cx_b, |workspace, cx| {
|
||||||
|
@ -780,7 +780,7 @@ async fn test_collaborating_with_renames(cx_a: &mut TestAppContext, cx_b: &mut T
|
||||||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b);
|
let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b);
|
||||||
let editor_b = workspace_b
|
let editor_b = workspace_b
|
||||||
|
@ -1030,7 +1030,7 @@ async fn test_language_server_statuses(cx_a: &mut TestAppContext, cx_b: &mut Tes
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
executor.run_until_parked();
|
executor.run_until_parked();
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
project_b.read_with(cx_b, |project, cx| {
|
project_b.read_with(cx_b, |project, cx| {
|
||||||
let status = project.language_server_statuses(cx).next().unwrap().1;
|
let status = project.language_server_statuses(cx).next().unwrap().1;
|
||||||
|
@ -1126,9 +1126,7 @@ async fn test_share_project(
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let client_b_peer_id = client_b.peer_id().unwrap();
|
let client_b_peer_id = client_b.peer_id().unwrap();
|
||||||
let project_b = client_b
|
let project_b = client_b.join_remote_project(initial_project.id, cx_b).await;
|
||||||
.build_dev_server_project(initial_project.id, cx_b)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
let replica_id_b = project_b.read_with(cx_b, |project, _| project.replica_id());
|
let replica_id_b = project_b.read_with(cx_b, |project, _| project.replica_id());
|
||||||
|
|
||||||
|
@ -1230,9 +1228,7 @@ async fn test_share_project(
|
||||||
.update(cx_c, |call, cx| call.accept_incoming(cx))
|
.update(cx_c, |call, cx| call.accept_incoming(cx))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let _project_c = client_c
|
let _project_c = client_c.join_remote_project(initial_project.id, cx_c).await;
|
||||||
.build_dev_server_project(initial_project.id, cx_c)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
// Client B closes the editor, and client A sees client B's selections removed.
|
// Client B closes the editor, and client A sees client B's selections removed.
|
||||||
cx_b.update(move |_| drop(editor_b));
|
cx_b.update(move |_| drop(editor_b));
|
||||||
|
@ -1291,7 +1287,7 @@ async fn test_on_input_format_from_host_to_guest(
|
||||||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
// Open a file in an editor as the host.
|
// Open a file in an editor as the host.
|
||||||
let buffer_a = project_a
|
let buffer_a = project_a
|
||||||
|
@ -1411,7 +1407,7 @@ async fn test_on_input_format_from_guest_to_host(
|
||||||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
// Open a file in an editor as the guest.
|
// Open a file in an editor as the guest.
|
||||||
let buffer_b = project_b
|
let buffer_b = project_b
|
||||||
|
@ -1574,7 +1570,7 @@ async fn test_mutual_editor_inlay_hint_cache_update(
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Client B joins the project
|
// Client B joins the project
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
active_call_b
|
active_call_b
|
||||||
.update(cx_b, |call, cx| call.set_location(Some(&project_b), cx))
|
.update(cx_b, |call, cx| call.set_location(Some(&project_b), cx))
|
||||||
.await
|
.await
|
||||||
|
@ -1836,7 +1832,7 @@ async fn test_inlay_hint_refresh_is_forwarded(
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
active_call_b
|
active_call_b
|
||||||
.update(cx_b, |call, cx| call.set_location(Some(&project_b), cx))
|
.update(cx_b, |call, cx| call.set_location(Some(&project_b), cx))
|
||||||
.await
|
.await
|
||||||
|
@ -2050,7 +2046,7 @@ async fn test_git_blame_is_forwarded(cx_a: &mut TestAppContext, cx_b: &mut TestA
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Join the project as client B.
|
// Join the project as client B.
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b);
|
let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b);
|
||||||
let editor_b = workspace_b
|
let editor_b = workspace_b
|
||||||
.update(cx_b, |workspace, cx| {
|
.update(cx_b, |workspace, cx| {
|
||||||
|
|
|
@ -74,7 +74,7 @@ async fn test_basic_following(
|
||||||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
active_call_b
|
active_call_b
|
||||||
.update(cx_b, |call, cx| call.set_location(Some(&project_b), cx))
|
.update(cx_b, |call, cx| call.set_location(Some(&project_b), cx))
|
||||||
.await
|
.await
|
||||||
|
@ -162,7 +162,7 @@ async fn test_basic_following(
|
||||||
|
|
||||||
executor.run_until_parked();
|
executor.run_until_parked();
|
||||||
let active_call_c = cx_c.read(ActiveCall::global);
|
let active_call_c = cx_c.read(ActiveCall::global);
|
||||||
let project_c = client_c.build_dev_server_project(project_id, cx_c).await;
|
let project_c = client_c.join_remote_project(project_id, cx_c).await;
|
||||||
let (workspace_c, cx_c) = client_c.build_workspace(&project_c, cx_c);
|
let (workspace_c, cx_c) = client_c.build_workspace(&project_c, cx_c);
|
||||||
active_call_c
|
active_call_c
|
||||||
.update(cx_c, |call, cx| call.set_location(Some(&project_c), cx))
|
.update(cx_c, |call, cx| call.set_location(Some(&project_c), cx))
|
||||||
|
@ -175,7 +175,7 @@ async fn test_basic_following(
|
||||||
|
|
||||||
cx_d.executor().run_until_parked();
|
cx_d.executor().run_until_parked();
|
||||||
let active_call_d = cx_d.read(ActiveCall::global);
|
let active_call_d = cx_d.read(ActiveCall::global);
|
||||||
let project_d = client_d.build_dev_server_project(project_id, cx_d).await;
|
let project_d = client_d.join_remote_project(project_id, cx_d).await;
|
||||||
let (workspace_d, cx_d) = client_d.build_workspace(&project_d, cx_d);
|
let (workspace_d, cx_d) = client_d.build_workspace(&project_d, cx_d);
|
||||||
active_call_d
|
active_call_d
|
||||||
.update(cx_d, |call, cx| call.set_location(Some(&project_d), cx))
|
.update(cx_d, |call, cx| call.set_location(Some(&project_d), cx))
|
||||||
|
@ -569,7 +569,7 @@ async fn test_following_tab_order(
|
||||||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
active_call_b
|
active_call_b
|
||||||
.update(cx_b, |call, cx| call.set_location(Some(&project_b), cx))
|
.update(cx_b, |call, cx| call.set_location(Some(&project_b), cx))
|
||||||
.await
|
.await
|
||||||
|
@ -686,7 +686,7 @@ async fn test_peers_following_each_other(cx_a: &mut TestAppContext, cx_b: &mut T
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Client B joins the project.
|
// Client B joins the project.
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
active_call_b
|
active_call_b
|
||||||
.update(cx_b, |call, cx| call.set_location(Some(&project_b), cx))
|
.update(cx_b, |call, cx| call.set_location(Some(&project_b), cx))
|
||||||
.await
|
.await
|
||||||
|
@ -1199,7 +1199,7 @@ async fn test_auto_unfollowing(cx_a: &mut TestAppContext, cx_b: &mut TestAppCont
|
||||||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
active_call_b
|
active_call_b
|
||||||
.update(cx_b, |call, cx| call.set_location(Some(&project_b), cx))
|
.update(cx_b, |call, cx| call.set_location(Some(&project_b), cx))
|
||||||
.await
|
.await
|
||||||
|
@ -1335,7 +1335,7 @@ async fn test_peers_simultaneously_following_each_other(
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b);
|
let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b);
|
||||||
|
|
||||||
executor.run_until_parked();
|
executor.run_until_parked();
|
||||||
|
@ -1685,7 +1685,7 @@ async fn test_following_into_excluded_file(
|
||||||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
active_call_b
|
active_call_b
|
||||||
.update(cx_b, |call, cx| call.set_location(Some(&project_b), cx))
|
.update(cx_b, |call, cx| call.set_location(Some(&project_b), cx))
|
||||||
.await
|
.await
|
||||||
|
|
|
@ -1372,7 +1372,7 @@ async fn test_unshare_project(
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let worktree_a = project_a.read_with(cx_a, |project, cx| project.worktrees(cx).next().unwrap());
|
let worktree_a = project_a.read_with(cx_a, |project, cx| project.worktrees(cx).next().unwrap());
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
executor.run_until_parked();
|
executor.run_until_parked();
|
||||||
|
|
||||||
assert!(worktree_a.read_with(cx_a, |tree, _| tree.has_update_observer()));
|
assert!(worktree_a.read_with(cx_a, |tree, _| tree.has_update_observer()));
|
||||||
|
@ -1392,7 +1392,7 @@ async fn test_unshare_project(
|
||||||
assert!(project_b.read_with(cx_b, |project, _| project.is_disconnected()));
|
assert!(project_b.read_with(cx_b, |project, _| project.is_disconnected()));
|
||||||
|
|
||||||
// Client C opens the project.
|
// Client C opens the project.
|
||||||
let project_c = client_c.build_dev_server_project(project_id, cx_c).await;
|
let project_c = client_c.join_remote_project(project_id, cx_c).await;
|
||||||
|
|
||||||
// When client A unshares the project, client C's project becomes read-only.
|
// When client A unshares the project, client C's project becomes read-only.
|
||||||
project_a
|
project_a
|
||||||
|
@ -1409,7 +1409,7 @@ async fn test_unshare_project(
|
||||||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let project_c2 = client_c.build_dev_server_project(project_id, cx_c).await;
|
let project_c2 = client_c.join_remote_project(project_id, cx_c).await;
|
||||||
executor.run_until_parked();
|
executor.run_until_parked();
|
||||||
|
|
||||||
assert!(worktree_a.read_with(cx_a, |tree, _| tree.has_update_observer()));
|
assert!(worktree_a.read_with(cx_a, |tree, _| tree.has_update_observer()));
|
||||||
|
@ -1514,9 +1514,9 @@ async fn test_project_reconnect(
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let project_b1 = client_b.build_dev_server_project(project1_id, cx_b).await;
|
let project_b1 = client_b.join_remote_project(project1_id, cx_b).await;
|
||||||
let project_b2 = client_b.build_dev_server_project(project2_id, cx_b).await;
|
let project_b2 = client_b.join_remote_project(project2_id, cx_b).await;
|
||||||
let project_b3 = client_b.build_dev_server_project(project3_id, cx_b).await;
|
let project_b3 = client_b.join_remote_project(project3_id, cx_b).await;
|
||||||
executor.run_until_parked();
|
executor.run_until_parked();
|
||||||
|
|
||||||
let worktree1_id = worktree_a1.read_with(cx_a, |worktree, _| {
|
let worktree1_id = worktree_a1.read_with(cx_a, |worktree, _| {
|
||||||
|
@ -2310,8 +2310,8 @@ async fn test_propagate_saves_and_fs_changes(
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Join that worktree as clients B and C.
|
// Join that worktree as clients B and C.
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
let project_c = client_c.build_dev_server_project(project_id, cx_c).await;
|
let project_c = client_c.join_remote_project(project_id, cx_c).await;
|
||||||
|
|
||||||
let worktree_b = project_b.read_with(cx_b, |p, cx| p.worktrees(cx).next().unwrap());
|
let worktree_b = project_b.read_with(cx_b, |p, cx| p.worktrees(cx).next().unwrap());
|
||||||
|
|
||||||
|
@ -2535,7 +2535,7 @@ async fn test_git_diff_base_change(
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let project_remote = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_remote = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
let diff_base = "
|
let diff_base = "
|
||||||
one
|
one
|
||||||
|
@ -2791,7 +2791,7 @@ async fn test_git_branch_name(
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let project_remote = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_remote = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
client_a
|
client_a
|
||||||
.fs()
|
.fs()
|
||||||
.set_branch_name(Path::new("/dir/.git"), Some("branch-1"));
|
.set_branch_name(Path::new("/dir/.git"), Some("branch-1"));
|
||||||
|
@ -2836,7 +2836,7 @@ async fn test_git_branch_name(
|
||||||
assert_branch(Some("branch-2"), project, cx)
|
assert_branch(Some("branch-2"), project, cx)
|
||||||
});
|
});
|
||||||
|
|
||||||
let project_remote_c = client_c.build_dev_server_project(project_id, cx_c).await;
|
let project_remote_c = client_c.join_remote_project(project_id, cx_c).await;
|
||||||
executor.run_until_parked();
|
executor.run_until_parked();
|
||||||
|
|
||||||
project_remote_c.read_with(cx_c, |project, cx| {
|
project_remote_c.read_with(cx_c, |project, cx| {
|
||||||
|
@ -2891,7 +2891,7 @@ async fn test_git_status_sync(
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let project_remote = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_remote = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
// Wait for it to catch up to the new status
|
// Wait for it to catch up to the new status
|
||||||
executor.run_until_parked();
|
executor.run_until_parked();
|
||||||
|
@ -2967,7 +2967,7 @@ async fn test_git_status_sync(
|
||||||
});
|
});
|
||||||
|
|
||||||
// And synchronization while joining
|
// And synchronization while joining
|
||||||
let project_remote_c = client_c.build_dev_server_project(project_id, cx_c).await;
|
let project_remote_c = client_c.join_remote_project(project_id, cx_c).await;
|
||||||
executor.run_until_parked();
|
executor.run_until_parked();
|
||||||
|
|
||||||
project_remote_c.read_with(cx_c, |project, cx| {
|
project_remote_c.read_with(cx_c, |project, cx| {
|
||||||
|
@ -3015,7 +3015,7 @@ async fn test_fs_operations(
|
||||||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
let worktree_a = project_a.read_with(cx_a, |project, cx| project.worktrees(cx).next().unwrap());
|
let worktree_a = project_a.read_with(cx_a, |project, cx| project.worktrees(cx).next().unwrap());
|
||||||
let worktree_b = project_b.read_with(cx_b, |project, cx| project.worktrees(cx).next().unwrap());
|
let worktree_b = project_b.read_with(cx_b, |project, cx| project.worktrees(cx).next().unwrap());
|
||||||
|
@ -3316,7 +3316,7 @@ async fn test_local_settings(
|
||||||
executor.run_until_parked();
|
executor.run_until_parked();
|
||||||
|
|
||||||
// As client B, join that project and observe the local settings.
|
// As client B, join that project and observe the local settings.
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
let worktree_b = project_b.read_with(cx_b, |project, cx| project.worktrees(cx).next().unwrap());
|
let worktree_b = project_b.read_with(cx_b, |project, cx| project.worktrees(cx).next().unwrap());
|
||||||
executor.run_until_parked();
|
executor.run_until_parked();
|
||||||
|
@ -3439,7 +3439,7 @@ async fn test_buffer_conflict_after_save(
|
||||||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
// Open a buffer as client B
|
// Open a buffer as client B
|
||||||
let buffer_b = project_b
|
let buffer_b = project_b
|
||||||
|
@ -3503,7 +3503,7 @@ async fn test_buffer_reloading(
|
||||||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
// Open a buffer as client B
|
// Open a buffer as client B
|
||||||
let buffer_b = project_b
|
let buffer_b = project_b
|
||||||
|
@ -3557,7 +3557,7 @@ async fn test_editing_while_guest_opens_buffer(
|
||||||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
// Open a buffer as client A
|
// Open a buffer as client A
|
||||||
let buffer_a = project_a
|
let buffer_a = project_a
|
||||||
|
@ -3605,7 +3605,7 @@ async fn test_leaving_worktree_while_opening_buffer(
|
||||||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
// See that a guest has joined as client A.
|
// See that a guest has joined as client A.
|
||||||
executor.run_until_parked();
|
executor.run_until_parked();
|
||||||
|
@ -3652,7 +3652,7 @@ async fn test_canceling_buffer_opening(
|
||||||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
let buffer_a = project_a
|
let buffer_a = project_a
|
||||||
.update(cx_a, |p, cx| p.open_buffer((worktree_id, "a.txt"), cx))
|
.update(cx_a, |p, cx| p.open_buffer((worktree_id, "a.txt"), cx))
|
||||||
|
@ -3709,8 +3709,8 @@ async fn test_leaving_project(
|
||||||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let project_b1 = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b1 = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
let project_c = client_c.build_dev_server_project(project_id, cx_c).await;
|
let project_c = client_c.join_remote_project(project_id, cx_c).await;
|
||||||
|
|
||||||
// Client A sees that a guest has joined.
|
// Client A sees that a guest has joined.
|
||||||
executor.run_until_parked();
|
executor.run_until_parked();
|
||||||
|
@ -3751,7 +3751,7 @@ async fn test_leaving_project(
|
||||||
});
|
});
|
||||||
|
|
||||||
// Client B re-joins the project and can open buffers as before.
|
// Client B re-joins the project and can open buffers as before.
|
||||||
let project_b2 = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b2 = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
executor.run_until_parked();
|
executor.run_until_parked();
|
||||||
|
|
||||||
project_a.read_with(cx_a, |project, _| {
|
project_a.read_with(cx_a, |project, _| {
|
||||||
|
@ -3927,7 +3927,7 @@ async fn test_collaborating_with_diagnostics(
|
||||||
);
|
);
|
||||||
|
|
||||||
// Join the worktree as client B.
|
// Join the worktree as client B.
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
// Wait for server to see the diagnostics update.
|
// Wait for server to see the diagnostics update.
|
||||||
executor.run_until_parked();
|
executor.run_until_parked();
|
||||||
|
@ -3952,7 +3952,7 @@ async fn test_collaborating_with_diagnostics(
|
||||||
});
|
});
|
||||||
|
|
||||||
// Join project as client C and observe the diagnostics.
|
// Join project as client C and observe the diagnostics.
|
||||||
let project_c = client_c.build_dev_server_project(project_id, cx_c).await;
|
let project_c = client_c.join_remote_project(project_id, cx_c).await;
|
||||||
executor.run_until_parked();
|
executor.run_until_parked();
|
||||||
let project_c_diagnostic_summaries =
|
let project_c_diagnostic_summaries =
|
||||||
Rc::new(RefCell::new(project_c.read_with(cx_c, |project, cx| {
|
Rc::new(RefCell::new(project_c.read_with(cx_c, |project, cx| {
|
||||||
|
@ -4160,7 +4160,7 @@ async fn test_collaborating_with_lsp_progress_updates_and_diagnostics_ordering(
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Join the project as client B and open all three files.
|
// Join the project as client B and open all three files.
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
let guest_buffers = futures::future::try_join_all(file_names.iter().map(|file_name| {
|
let guest_buffers = futures::future::try_join_all(file_names.iter().map(|file_name| {
|
||||||
project_b.update(cx_b, |p, cx| p.open_buffer((worktree_id, file_name), cx))
|
project_b.update(cx_b, |p, cx| p.open_buffer((worktree_id, file_name), cx))
|
||||||
}))
|
}))
|
||||||
|
@ -4266,7 +4266,7 @@ async fn test_reloading_buffer_manually(
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
let open_buffer = project_b.update(cx_b, |p, cx| p.open_buffer((worktree_id, "a.rs"), cx));
|
let open_buffer = project_b.update(cx_b, |p, cx| p.open_buffer((worktree_id, "a.rs"), cx));
|
||||||
let buffer_b = cx_b.executor().spawn(open_buffer).await.unwrap();
|
let buffer_b = cx_b.executor().spawn(open_buffer).await.unwrap();
|
||||||
|
@ -4364,7 +4364,7 @@ async fn test_formatting_buffer(
|
||||||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
let open_buffer = project_b.update(cx_b, |p, cx| p.open_buffer((worktree_id, "a.rs"), cx));
|
let open_buffer = project_b.update(cx_b, |p, cx| p.open_buffer((worktree_id, "a.rs"), cx));
|
||||||
let buffer_b = cx_b.executor().spawn(open_buffer).await.unwrap();
|
let buffer_b = cx_b.executor().spawn(open_buffer).await.unwrap();
|
||||||
|
@ -4486,7 +4486,7 @@ async fn test_prettier_formatting_buffer(
|
||||||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
let open_buffer = project_b.update(cx_b, |p, cx| p.open_buffer((worktree_id, "a.ts"), cx));
|
let open_buffer = project_b.update(cx_b, |p, cx| p.open_buffer((worktree_id, "a.ts"), cx));
|
||||||
let buffer_b = cx_b.executor().spawn(open_buffer).await.unwrap();
|
let buffer_b = cx_b.executor().spawn(open_buffer).await.unwrap();
|
||||||
|
|
||||||
|
@ -4599,7 +4599,7 @@ async fn test_definition(
|
||||||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
// Open the file on client B.
|
// Open the file on client B.
|
||||||
let open_buffer = project_b.update(cx_b, |p, cx| p.open_buffer((worktree_id, "a.rs"), cx));
|
let open_buffer = project_b.update(cx_b, |p, cx| p.open_buffer((worktree_id, "a.rs"), cx));
|
||||||
|
@ -4744,7 +4744,7 @@ async fn test_references(
|
||||||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
// Open the file on client B.
|
// Open the file on client B.
|
||||||
let open_buffer = project_b.update(cx_b, |p, cx| p.open_buffer((worktree_id, "one.rs"), cx));
|
let open_buffer = project_b.update(cx_b, |p, cx| p.open_buffer((worktree_id, "one.rs"), cx));
|
||||||
|
@ -4901,7 +4901,7 @@ async fn test_project_search(
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
// Perform a search as the guest.
|
// Perform a search as the guest.
|
||||||
let mut results = HashMap::default();
|
let mut results = HashMap::default();
|
||||||
|
@ -4991,7 +4991,7 @@ async fn test_document_highlights(
|
||||||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
// Open the file on client B.
|
// Open the file on client B.
|
||||||
let open_b = project_b.update(cx_b, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx));
|
let open_b = project_b.update(cx_b, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx));
|
||||||
|
@ -5109,7 +5109,7 @@ async fn test_lsp_hover(
|
||||||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
// Open the file as the guest
|
// Open the file as the guest
|
||||||
let open_buffer = project_b.update(cx_b, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx));
|
let open_buffer = project_b.update(cx_b, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx));
|
||||||
|
@ -5286,7 +5286,7 @@ async fn test_project_symbols(
|
||||||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
// Cause the language server to start.
|
// Cause the language server to start.
|
||||||
let open_buffer_task =
|
let open_buffer_task =
|
||||||
|
@ -5381,7 +5381,7 @@ async fn test_open_buffer_while_getting_definition_pointing_to_it(
|
||||||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
let open_buffer_task = project_b.update(cx_b, |p, cx| p.open_buffer((worktree_id, "a.rs"), cx));
|
let open_buffer_task = project_b.update(cx_b, |p, cx| p.open_buffer((worktree_id, "a.rs"), cx));
|
||||||
let buffer_b1 = cx_b.executor().spawn(open_buffer_task).await.unwrap();
|
let buffer_b1 = cx_b.executor().spawn(open_buffer_task).await.unwrap();
|
||||||
|
@ -6470,7 +6470,7 @@ async fn test_context_collaboration_with_reconnect(
|
||||||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
// Client A sees that a guest has joined.
|
// Client A sees that a guest has joined.
|
||||||
executor.run_until_parked();
|
executor.run_until_parked();
|
||||||
|
|
|
@ -9,7 +9,7 @@ use remote_server::HeadlessProject;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use std::{path::Path, sync::Arc};
|
use std::{path::Path, sync::Arc};
|
||||||
|
|
||||||
#[gpui::test]
|
#[gpui::test(iterations = 10)]
|
||||||
async fn test_sharing_an_ssh_remote_project(
|
async fn test_sharing_an_ssh_remote_project(
|
||||||
cx_a: &mut TestAppContext,
|
cx_a: &mut TestAppContext,
|
||||||
cx_b: &mut TestAppContext,
|
cx_b: &mut TestAppContext,
|
||||||
|
@ -54,9 +54,8 @@ async fn test_sharing_an_ssh_remote_project(
|
||||||
let (project_a, worktree_id) = client_a
|
let (project_a, worktree_id) = client_a
|
||||||
.build_ssh_project("/code/project1", client_ssh, cx_a)
|
.build_ssh_project("/code/project1", client_ssh, cx_a)
|
||||||
.await;
|
.await;
|
||||||
executor.run_until_parked();
|
|
||||||
|
|
||||||
// User A shares the remote project.
|
// While the SSH worktree is being scanned, user A shares the remote project.
|
||||||
let active_call_a = cx_a.read(ActiveCall::global);
|
let active_call_a = cx_a.read(ActiveCall::global);
|
||||||
let project_id = active_call_a
|
let project_id = active_call_a
|
||||||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||||
|
@ -64,12 +63,30 @@ async fn test_sharing_an_ssh_remote_project(
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// User B joins the project.
|
// User B joins the project.
|
||||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
let project_b = client_b.join_remote_project(project_id, cx_b).await;
|
||||||
let worktree_b = project_b
|
let worktree_b = project_b
|
||||||
.update(cx_b, |project, cx| project.worktree_for_id(worktree_id, cx))
|
.update(cx_b, |project, cx| project.worktree_for_id(worktree_id, cx))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
let worktree_a = project_a
|
||||||
|
.update(cx_a, |project, cx| project.worktree_for_id(worktree_id, cx))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
executor.run_until_parked();
|
executor.run_until_parked();
|
||||||
|
|
||||||
|
worktree_a.update(cx_a, |worktree, _cx| {
|
||||||
|
assert_eq!(
|
||||||
|
worktree.paths().map(Arc::as_ref).collect::<Vec<_>>(),
|
||||||
|
vec![
|
||||||
|
Path::new(".zed"),
|
||||||
|
Path::new(".zed/settings.json"),
|
||||||
|
Path::new("README.md"),
|
||||||
|
Path::new("src"),
|
||||||
|
Path::new("src/lib.rs"),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
worktree_b.update(cx_b, |worktree, _cx| {
|
worktree_b.update(cx_b, |worktree, _cx| {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
worktree.paths().map(Arc::as_ref).collect::<Vec<_>>(),
|
worktree.paths().map(Arc::as_ref).collect::<Vec<_>>(),
|
||||||
|
|
|
@ -921,7 +921,7 @@ impl TestClient {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn build_dev_server_project(
|
pub async fn join_remote_project(
|
||||||
&self,
|
&self,
|
||||||
host_project_id: u64,
|
host_project_id: u64,
|
||||||
guest_cx: &mut TestAppContext,
|
guest_cx: &mut TestAppContext,
|
||||||
|
|
|
@ -204,8 +204,11 @@ impl WorktreeStore {
|
||||||
self.loading_worktrees.insert(path.clone(), task.shared());
|
self.loading_worktrees.insert(path.clone(), task.shared());
|
||||||
}
|
}
|
||||||
let task = self.loading_worktrees.get(&path).unwrap().clone();
|
let task = self.loading_worktrees.get(&path).unwrap().clone();
|
||||||
cx.background_executor().spawn(async move {
|
cx.spawn(|this, mut cx| async move {
|
||||||
match task.await {
|
let result = task.await;
|
||||||
|
this.update(&mut cx, |this, _| this.loading_worktrees.remove(&path))
|
||||||
|
.ok();
|
||||||
|
match result {
|
||||||
Ok(worktree) => Ok(worktree),
|
Ok(worktree) => Ok(worktree),
|
||||||
Err(err) => Err((*err).cloned()),
|
Err(err) => Err((*err).cloned()),
|
||||||
}
|
}
|
||||||
|
@ -219,7 +222,8 @@ impl WorktreeStore {
|
||||||
visible: bool,
|
visible: bool,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) -> Task<Result<Model<Worktree>, Arc<anyhow::Error>>> {
|
) -> Task<Result<Model<Worktree>, Arc<anyhow::Error>>> {
|
||||||
let mut abs_path = abs_path.as_ref().to_string_lossy().to_string();
|
let path_key: Arc<Path> = abs_path.as_ref().into();
|
||||||
|
let mut abs_path = path_key.clone().to_string_lossy().to_string();
|
||||||
// If we start with `/~` that means the ssh path was something like `ssh://user@host/~/home-dir-folder/`
|
// If we start with `/~` that means the ssh path was something like `ssh://user@host/~/home-dir-folder/`
|
||||||
// in which case want to strip the leading the `/`.
|
// in which case want to strip the leading the `/`.
|
||||||
// On the host-side, the `~` will get expanded.
|
// On the host-side, the `~` will get expanded.
|
||||||
|
@ -261,8 +265,9 @@ impl WorktreeStore {
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
this.update(&mut cx, |this, cx| this.add(&worktree, cx))?;
|
this.update(&mut cx, |this, cx| {
|
||||||
|
this.add(&worktree, cx);
|
||||||
|
})?;
|
||||||
Ok(worktree)
|
Ok(worktree)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -280,10 +285,6 @@ impl WorktreeStore {
|
||||||
cx.spawn(move |this, mut cx| async move {
|
cx.spawn(move |this, mut cx| async move {
|
||||||
let worktree = Worktree::local(path.clone(), visible, fs, next_entry_id, &mut cx).await;
|
let worktree = Worktree::local(path.clone(), visible, fs, next_entry_id, &mut cx).await;
|
||||||
|
|
||||||
this.update(&mut cx, |project, _| {
|
|
||||||
project.loading_worktrees.remove(&path);
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let worktree = worktree?;
|
let worktree = worktree?;
|
||||||
this.update(&mut cx, |this, cx| this.add(&worktree, cx))?;
|
this.update(&mut cx, |this, cx| this.add(&worktree, cx))?;
|
||||||
|
|
||||||
|
@ -317,7 +318,7 @@ impl WorktreeStore {
|
||||||
});
|
});
|
||||||
|
|
||||||
let abs_path = abs_path.as_ref().to_path_buf();
|
let abs_path = abs_path.as_ref().to_path_buf();
|
||||||
cx.spawn(move |project, mut cx| async move {
|
cx.spawn(move |project, cx| async move {
|
||||||
let (tx, rx) = futures::channel::oneshot::channel();
|
let (tx, rx) = futures::channel::oneshot::channel();
|
||||||
let tx = RefCell::new(Some(tx));
|
let tx = RefCell::new(Some(tx));
|
||||||
let Some(project) = project.upgrade() else {
|
let Some(project) = project.upgrade() else {
|
||||||
|
@ -339,14 +340,10 @@ impl WorktreeStore {
|
||||||
request.await?;
|
request.await?;
|
||||||
let worktree = rx.await.map_err(|e| anyhow!(e))?;
|
let worktree = rx.await.map_err(|e| anyhow!(e))?;
|
||||||
drop(observer);
|
drop(observer);
|
||||||
project.update(&mut cx, |project, _| {
|
|
||||||
project.loading_worktrees.remove(&path);
|
|
||||||
})?;
|
|
||||||
Ok(worktree)
|
Ok(worktree)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[track_caller]
|
|
||||||
pub fn add(&mut self, worktree: &Model<Worktree>, cx: &mut ModelContext<Self>) {
|
pub fn add(&mut self, worktree: &Model<Worktree>, cx: &mut ModelContext<Self>) {
|
||||||
let worktree_id = worktree.read(cx).id();
|
let worktree_id = worktree.read(cx).id();
|
||||||
debug_assert!(self.worktrees().all(|w| w.read(cx).id() != worktree_id));
|
debug_assert!(self.worktrees().all(|w| w.read(cx).id() != worktree_id));
|
||||||
|
@ -553,9 +550,12 @@ impl WorktreeStore {
|
||||||
let client = client.clone();
|
let client = client.clone();
|
||||||
async move {
|
async move {
|
||||||
if client.is_via_collab() {
|
if client.is_via_collab() {
|
||||||
client.request(update).map(|result| result.is_ok()).await
|
client
|
||||||
|
.request(update)
|
||||||
|
.map(|result| result.log_err().is_some())
|
||||||
|
.await
|
||||||
} else {
|
} else {
|
||||||
client.send(update).is_ok()
|
client.send(update).log_err().is_some()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -564,6 +564,48 @@ async fn test_canceling_buffer_opening(cx: &mut TestAppContext, server_cx: &mut
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[gpui::test]
|
||||||
|
async fn test_adding_then_removing_then_adding_worktrees(
|
||||||
|
cx: &mut TestAppContext,
|
||||||
|
server_cx: &mut TestAppContext,
|
||||||
|
) {
|
||||||
|
let (project, _headless, _fs) = init_test(cx, server_cx).await;
|
||||||
|
let (_worktree, _) = project
|
||||||
|
.update(cx, |project, cx| {
|
||||||
|
project.find_or_create_worktree("/code/project1", true, cx)
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let (worktree_2, _) = project
|
||||||
|
.update(cx, |project, cx| {
|
||||||
|
project.find_or_create_worktree("/code/project2", true, cx)
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let worktree_id_2 = worktree_2.read_with(cx, |tree, _| tree.id());
|
||||||
|
|
||||||
|
project.update(cx, |project, cx| project.remove_worktree(worktree_id_2, cx));
|
||||||
|
|
||||||
|
let (worktree_2, _) = project
|
||||||
|
.update(cx, |project, cx| {
|
||||||
|
project.find_or_create_worktree("/code/project2", true, cx)
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
cx.run_until_parked();
|
||||||
|
worktree_2.update(cx, |worktree, _cx| {
|
||||||
|
assert!(worktree.is_visible());
|
||||||
|
let entries = worktree.entries(true, 0).collect::<Vec<_>>();
|
||||||
|
assert_eq!(entries.len(), 2);
|
||||||
|
assert_eq!(
|
||||||
|
entries[1].path.to_string_lossy().to_string(),
|
||||||
|
"README.md".to_string()
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn init_logger() {
|
fn init_logger() {
|
||||||
if std::env::var("RUST_LOG").is_ok() {
|
if std::env::var("RUST_LOG").is_ok() {
|
||||||
env_logger::try_init().ok();
|
env_logger::try_init().ok();
|
||||||
|
|
|
@ -1826,10 +1826,13 @@ impl RemoteWorktree {
|
||||||
let initial_update = self
|
let initial_update = self
|
||||||
.snapshot
|
.snapshot
|
||||||
.build_initial_update(project_id, self.id().to_proto());
|
.build_initial_update(project_id, self.id().to_proto());
|
||||||
self.updates_tx = Some(tx);
|
self.update_observer = Some(tx);
|
||||||
cx.spawn(|this, mut cx| async move {
|
cx.spawn(|this, mut cx| async move {
|
||||||
let mut update = initial_update;
|
let mut update = initial_update;
|
||||||
loop {
|
loop {
|
||||||
|
// SSH projects use a special project ID of 0, and we need to
|
||||||
|
// remap it to the correct one here.
|
||||||
|
update.project_id = project_id;
|
||||||
if !callback(update).await {
|
if !callback(update).await {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1841,7 +1844,7 @@ impl RemoteWorktree {
|
||||||
}
|
}
|
||||||
this.update(&mut cx, |this, _| {
|
this.update(&mut cx, |this, _| {
|
||||||
let this = this.as_remote_mut().unwrap();
|
let this = this.as_remote_mut().unwrap();
|
||||||
this.updates_tx.take();
|
this.update_observer.take();
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
|
|
|
@ -9,12 +9,18 @@ SUMMARY
|
||||||
Each instance of Zed will be signed in as a different user specified in
|
Each instance of Zed will be signed in as a different user specified in
|
||||||
either \`.admins.json\` or \`.admins.default.json\`.
|
either \`.admins.json\` or \`.admins.default.json\`.
|
||||||
|
|
||||||
|
All arguments after the initial options will be passed through to the first
|
||||||
|
instance of Zed. This can be used to test SSH remoting along with collab, like
|
||||||
|
so:
|
||||||
|
|
||||||
|
$ script/zed-local -2 ssh://your-ssh-uri-here
|
||||||
|
|
||||||
OPTIONS
|
OPTIONS
|
||||||
--help Print this help message
|
--help Print this help message
|
||||||
--release Build Zed in release mode
|
--release Build Zed in release mode
|
||||||
-2, -3, -4, ... Spawn multiple Zed instances, with their windows tiled.
|
-2, -3, -4, ... Spawn multiple Zed instances, with their windows tiled.
|
||||||
--top Arrange the Zed windows so they take up the top half of the screen.
|
--top Arrange the Zed windows so they take up the top half of the screen.
|
||||||
--stable Use stable Zed release installed on local machine for all instances (except for the first one).
|
--stable Use stable Zed release installed on local machine for all instances (except for the first one).
|
||||||
`.trim();
|
`.trim();
|
||||||
|
|
||||||
const { spawn, execSync, execFileSync } = require("child_process");
|
const { spawn, execSync, execFileSync } = require("child_process");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue