Detailed changes
@@ -32,6 +32,7 @@ macro_rules! id_type {
#[allow(unused)]
#[allow(missing_docs)]
pub fn from_proto(value: u64) -> Self {
+ debug_assert!(value != 0);
Self(value as i32)
}
@@ -285,7 +285,7 @@ impl Database {
)
.one(&*tx)
.await?
- .ok_or_else(|| anyhow!("no such project"))?;
+ .ok_or_else(|| anyhow!("no such project: {project_id}"))?;
// Update metadata.
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))
.await
.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);
// Clients A and B open the same file.
@@ -76,7 +76,7 @@ async fn test_host_disconnect(
.await
.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();
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
.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
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))
.await
.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.
let buffer_b = project_b
@@ -565,7 +565,7 @@ async fn test_collaborating_with_code_actions(
.unwrap();
// 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 editor_b = workspace_b
.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))
.await
.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 editor_b = workspace_b
@@ -1030,7 +1030,7 @@ async fn test_language_server_statuses(cx_a: &mut TestAppContext, cx_b: &mut Tes
.await
.unwrap();
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| {
let status = project.language_server_statuses(cx).next().unwrap().1;
@@ -1126,9 +1126,7 @@ async fn test_share_project(
.await
.unwrap();
let client_b_peer_id = client_b.peer_id().unwrap();
- let project_b = client_b
- .build_dev_server_project(initial_project.id, cx_b)
- .await;
+ let project_b = client_b.join_remote_project(initial_project.id, cx_b).await;
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))
.await
.unwrap();
- let _project_c = client_c
- .build_dev_server_project(initial_project.id, cx_c)
- .await;
+ let _project_c = client_c.join_remote_project(initial_project.id, cx_c).await;
// Client B closes the editor, and client A sees client B's selections removed.
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))
.await
.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.
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))
.await
.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.
let buffer_b = project_b
@@ -1574,7 +1570,7 @@ async fn test_mutual_editor_inlay_hint_cache_update(
.unwrap();
// 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
.update(cx_b, |call, cx| call.set_location(Some(&project_b), cx))
.await
@@ -1836,7 +1832,7 @@ async fn test_inlay_hint_refresh_is_forwarded(
.await
.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
.update(cx_b, |call, cx| call.set_location(Some(&project_b), cx))
.await
@@ -2050,7 +2046,7 @@ async fn test_git_blame_is_forwarded(cx_a: &mut TestAppContext, cx_b: &mut TestA
.unwrap();
// 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 editor_b = workspace_b
.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))
.await
.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
.update(cx_b, |call, cx| call.set_location(Some(&project_b), cx))
.await
@@ -162,7 +162,7 @@ async fn test_basic_following(
executor.run_until_parked();
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);
active_call_c
.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();
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);
active_call_d
.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))
.await
.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
.update(cx_b, |call, cx| call.set_location(Some(&project_b), cx))
.await
@@ -686,7 +686,7 @@ async fn test_peers_following_each_other(cx_a: &mut TestAppContext, cx_b: &mut T
.unwrap();
// 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
.update(cx_b, |call, cx| call.set_location(Some(&project_b), cx))
.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))
.await
.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
.update(cx_b, |call, cx| call.set_location(Some(&project_b), cx))
.await
@@ -1335,7 +1335,7 @@ async fn test_peers_simultaneously_following_each_other(
.await
.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);
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))
.await
.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
.update(cx_b, |call, cx| call.set_location(Some(&project_b), cx))
.await
@@ -1372,7 +1372,7 @@ async fn test_unshare_project(
.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();
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()));
// 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.
project_a
@@ -1409,7 +1409,7 @@ async fn test_unshare_project(
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
.await
.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();
assert!(worktree_a.read_with(cx_a, |tree, _| tree.has_update_observer()));
@@ -1514,9 +1514,9 @@ async fn test_project_reconnect(
.await
.unwrap();
- let project_b1 = client_b.build_dev_server_project(project1_id, cx_b).await;
- let project_b2 = client_b.build_dev_server_project(project2_id, cx_b).await;
- let project_b3 = client_b.build_dev_server_project(project3_id, cx_b).await;
+ let project_b1 = client_b.join_remote_project(project1_id, cx_b).await;
+ let project_b2 = client_b.join_remote_project(project2_id, cx_b).await;
+ let project_b3 = client_b.join_remote_project(project3_id, cx_b).await;
executor.run_until_parked();
let worktree1_id = worktree_a1.read_with(cx_a, |worktree, _| {
@@ -2310,8 +2310,8 @@ async fn test_propagate_saves_and_fs_changes(
.unwrap();
// Join that worktree as clients B and C.
- let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
- let project_c = client_c.build_dev_server_project(project_id, cx_c).await;
+ let project_b = client_b.join_remote_project(project_id, cx_b).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());
@@ -2535,7 +2535,7 @@ async fn test_git_diff_base_change(
.await
.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 = "
one
@@ -2791,7 +2791,7 @@ async fn test_git_branch_name(
.await
.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
.fs()
.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)
});
- 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();
project_remote_c.read_with(cx_c, |project, cx| {
@@ -2891,7 +2891,7 @@ async fn test_git_status_sync(
.await
.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
executor.run_until_parked();
@@ -2967,7 +2967,7 @@ async fn test_git_status_sync(
});
// 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();
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))
.await
.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_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();
// 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());
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))
.await
.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
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))
.await
.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
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))
.await
.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
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))
.await
.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.
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))
.await
.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
.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))
.await
.unwrap();
- let project_b1 = client_b.build_dev_server_project(project_id, cx_b).await;
- let project_c = client_c.build_dev_server_project(project_id, cx_c).await;
+ let project_b1 = client_b.join_remote_project(project_id, cx_b).await;
+ let project_c = client_c.join_remote_project(project_id, cx_c).await;
// Client A sees that a guest has joined.
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.
- 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();
project_a.read_with(cx_a, |project, _| {
@@ -3927,7 +3927,7 @@ async fn test_collaborating_with_diagnostics(
);
// 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.
executor.run_until_parked();
@@ -3952,7 +3952,7 @@ async fn test_collaborating_with_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();
let project_c_diagnostic_summaries =
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();
// 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| {
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
.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 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))
.await
.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 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))
.await
.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 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))
.await
.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.
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))
.await
.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.
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
.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.
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))
.await
.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.
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))
.await
.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
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))
.await
.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.
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))
.await
.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 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))
.await
.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.
executor.run_until_parked();
@@ -9,7 +9,7 @@ use remote_server::HeadlessProject;
use serde_json::json;
use std::{path::Path, sync::Arc};
-#[gpui::test]
+#[gpui::test(iterations = 10)]
async fn test_sharing_an_ssh_remote_project(
cx_a: &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
.build_ssh_project("/code/project1", client_ssh, cx_a)
.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 project_id = active_call_a
.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();
// 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
.update(cx_b, |project, cx| project.worktree_for_id(worktree_id, cx))
.unwrap();
+ let worktree_a = project_a
+ .update(cx_a, |project, cx| project.worktree_for_id(worktree_id, cx))
+ .unwrap();
+
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| {
assert_eq!(
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,
host_project_id: u64,
guest_cx: &mut TestAppContext,
@@ -204,8 +204,11 @@ impl WorktreeStore {
self.loading_worktrees.insert(path.clone(), task.shared());
}
let task = self.loading_worktrees.get(&path).unwrap().clone();
- cx.background_executor().spawn(async move {
- match task.await {
+ cx.spawn(|this, mut cx| async move {
+ let result = task.await;
+ this.update(&mut cx, |this, _| this.loading_worktrees.remove(&path))
+ .ok();
+ match result {
Ok(worktree) => Ok(worktree),
Err(err) => Err((*err).cloned()),
}
@@ -219,7 +222,8 @@ impl WorktreeStore {
visible: bool,
cx: &mut ModelContext<Self>,
) -> 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/`
// in which case want to strip the leading the `/`.
// 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)
})
}
@@ -280,10 +285,6 @@ impl WorktreeStore {
cx.spawn(move |this, mut cx| async move {
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?;
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();
- cx.spawn(move |project, mut cx| async move {
+ cx.spawn(move |project, cx| async move {
let (tx, rx) = futures::channel::oneshot::channel();
let tx = RefCell::new(Some(tx));
let Some(project) = project.upgrade() else {
@@ -339,14 +340,10 @@ impl WorktreeStore {
request.await?;
let worktree = rx.await.map_err(|e| anyhow!(e))?;
drop(observer);
- project.update(&mut cx, |project, _| {
- project.loading_worktrees.remove(&path);
- })?;
Ok(worktree)
})
}
- #[track_caller]
pub fn add(&mut self, worktree: &Model<Worktree>, cx: &mut ModelContext<Self>) {
let worktree_id = worktree.read(cx).id();
debug_assert!(self.worktrees().all(|w| w.read(cx).id() != worktree_id));
@@ -553,9 +550,12 @@ impl WorktreeStore {
let client = client.clone();
async move {
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 {
- 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() {
if std::env::var("RUST_LOG").is_ok() {
env_logger::try_init().ok();
@@ -1826,10 +1826,13 @@ impl RemoteWorktree {
let initial_update = self
.snapshot
.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 {
let mut update = initial_update;
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 {
break;
}
@@ -1841,7 +1844,7 @@ impl RemoteWorktree {
}
this.update(&mut cx, |this, _| {
let this = this.as_remote_mut().unwrap();
- this.updates_tx.take();
+ this.update_observer.take();
})
})
.detach();
@@ -9,12 +9,18 @@ SUMMARY
Each instance of Zed will be signed in as a different user specified in
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
- --help Print this help message
- --release Build Zed in release mode
- -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.
- --stable Use stable Zed release installed on local machine for all instances (except for the first one).
+ --help Print this help message
+ --release Build Zed in release mode
+ -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.
+ --stable Use stable Zed release installed on local machine for all instances (except for the first one).
`.trim();
const { spawn, execSync, execFileSync } = require("child_process");