Rip out project registration and use sharing/unsharing instead
This commit is contained in:
parent
be8990ea78
commit
074b8f18d1
7 changed files with 333 additions and 525 deletions
|
@ -314,11 +314,14 @@ async fn test_share_project(
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
|
let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
|
||||||
let project_id = project_a.read_with(cx_a, |project, _| project.remote_id().unwrap());
|
let project_id = project_a
|
||||||
|
.update(cx_a, |project, cx| project.share(cx))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// Join that project as client B
|
// Join that project as client B
|
||||||
let client_b_peer_id = client_b.peer_id;
|
let client_b_peer_id = client_b.peer_id;
|
||||||
let project_b = client_b.build_remote_project(&project_a, cx_a, cx_b).await;
|
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||||
let replica_id_b = project_b.read_with(cx_b, |project, _| {
|
let replica_id_b = project_b.read_with(cx_b, |project, _| {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
project
|
project
|
||||||
|
@ -390,17 +393,7 @@ async fn test_share_project(
|
||||||
|
|
||||||
// Client B can join again on a different window because they are already a participant.
|
// Client B can join again on a different window because they are already a participant.
|
||||||
let client_b2 = server.create_client(cx_b2, "user_b").await;
|
let client_b2 = server.create_client(cx_b2, "user_b").await;
|
||||||
let project_b2 = Project::remote(
|
let project_b2 = client_b2.build_remote_project(project_id, cx_b2).await;
|
||||||
project_id,
|
|
||||||
client_b2.client.clone(),
|
|
||||||
client_b2.user_store.clone(),
|
|
||||||
client_b2.project_store.clone(),
|
|
||||||
client_b2.language_registry.clone(),
|
|
||||||
FakeFs::new(cx_b2.background()),
|
|
||||||
cx_b2.to_async(),
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
deterministic.run_until_parked();
|
deterministic.run_until_parked();
|
||||||
project_a.read_with(cx_a, |project, _| {
|
project_a.read_with(cx_a, |project, _| {
|
||||||
assert_eq!(project.collaborators().len(), 2);
|
assert_eq!(project.collaborators().len(), 2);
|
||||||
|
@ -449,8 +442,12 @@ async fn test_unshare_project(
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
|
let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
|
||||||
|
let project_id = project_a
|
||||||
|
.update(cx_a, |project, cx| project.share(cx))
|
||||||
|
.await
|
||||||
|
.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_remote_project(&project_a, cx_a, cx_b).await;
|
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||||
assert!(worktree_a.read_with(cx_a, |tree, _| tree.as_local().unwrap().is_shared()));
|
assert!(worktree_a.read_with(cx_a, |tree, _| tree.as_local().unwrap().is_shared()));
|
||||||
|
|
||||||
project_b
|
project_b
|
||||||
|
@ -467,7 +464,11 @@ async fn test_unshare_project(
|
||||||
assert!(project_b.read_with(cx_b, |project, _| project.is_read_only()));
|
assert!(project_b.read_with(cx_b, |project, _| project.is_read_only()));
|
||||||
|
|
||||||
// Client B can join again after client A re-shares.
|
// Client B can join again after client A re-shares.
|
||||||
let project_b2 = client_b.build_remote_project(&project_a, cx_a, cx_b).await;
|
let project_id = project_a
|
||||||
|
.update(cx_a, |project, cx| project.share(cx))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let project_b2 = client_b.build_remote_project(project_id, cx_b).await;
|
||||||
assert!(worktree_a.read_with(cx_a, |tree, _| tree.as_local().unwrap().is_shared()));
|
assert!(worktree_a.read_with(cx_a, |tree, _| tree.as_local().unwrap().is_shared()));
|
||||||
project_b2
|
project_b2
|
||||||
.update(cx_b, |p, cx| p.open_buffer((worktree_id, "a.txt"), cx))
|
.update(cx_b, |p, cx| p.open_buffer((worktree_id, "a.txt"), cx))
|
||||||
|
@ -517,9 +518,12 @@ async fn test_host_disconnect(
|
||||||
|
|
||||||
let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
|
let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).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());
|
||||||
project_a.read_with(cx_a, |project, _| project.remote_id().unwrap());
|
let project_id = project_a
|
||||||
|
.update(cx_a, |project, cx| project.share(cx))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let project_b = client_b.build_remote_project(&project_a, cx_a, cx_b).await;
|
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||||
assert!(worktree_a.read_with(cx_a, |tree, _| tree.as_local().unwrap().is_shared()));
|
assert!(worktree_a.read_with(cx_a, |tree, _| tree.as_local().unwrap().is_shared()));
|
||||||
|
|
||||||
let (_, workspace_b) =
|
let (_, workspace_b) =
|
||||||
|
@ -574,7 +578,11 @@ async fn test_host_disconnect(
|
||||||
});
|
});
|
||||||
|
|
||||||
// Ensure guests can still join.
|
// Ensure guests can still join.
|
||||||
let project_b2 = client_b.build_remote_project(&project_a, cx_a, cx_b).await;
|
let project_id = project_a
|
||||||
|
.update(cx_a, |project, cx| project.share(cx))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let project_b2 = client_b.build_remote_project(project_id, cx_b).await;
|
||||||
assert!(worktree_a.read_with(cx_a, |tree, _| tree.as_local().unwrap().is_shared()));
|
assert!(worktree_a.read_with(cx_a, |tree, _| tree.as_local().unwrap().is_shared()));
|
||||||
project_b2
|
project_b2
|
||||||
.update(cx_b, |p, cx| p.open_buffer((worktree_id, "a.txt"), cx))
|
.update(cx_b, |p, cx| p.open_buffer((worktree_id, "a.txt"), cx))
|
||||||
|
@ -613,10 +621,14 @@ async fn test_propagate_saves_and_fs_changes(
|
||||||
.await;
|
.await;
|
||||||
let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
|
let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
|
||||||
let worktree_a = project_a.read_with(cx_a, |p, cx| p.worktrees(cx).next().unwrap());
|
let worktree_a = project_a.read_with(cx_a, |p, cx| p.worktrees(cx).next().unwrap());
|
||||||
|
let project_id = project_a
|
||||||
|
.update(cx_a, |project, cx| project.share(cx))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// Join that worktree as clients B and C.
|
// Join that worktree as clients B and C.
|
||||||
let project_b = client_b.build_remote_project(&project_a, cx_a, cx_b).await;
|
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||||
let project_c = client_c.build_remote_project(&project_a, cx_a, cx_c).await;
|
let project_c = client_c.build_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());
|
||||||
let worktree_c = project_c.read_with(cx_c, |p, cx| p.worktrees(cx).next().unwrap());
|
let worktree_c = project_c.read_with(cx_c, |p, cx| p.worktrees(cx).next().unwrap());
|
||||||
|
|
||||||
|
@ -756,7 +768,11 @@ async fn test_fs_operations(
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
let (project_a, worktree_id) = client_a.build_local_project("/dir", cx_a).await;
|
let (project_a, worktree_id) = client_a.build_local_project("/dir", cx_a).await;
|
||||||
let project_b = client_b.build_remote_project(&project_a, cx_a, cx_b).await;
|
let project_id = project_a
|
||||||
|
.update(cx_a, |project, cx| project.share(cx))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let project_b = client_b.build_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());
|
||||||
|
@ -1016,7 +1032,11 @@ async fn test_buffer_conflict_after_save(cx_a: &mut TestAppContext, cx_b: &mut T
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
let (project_a, worktree_id) = client_a.build_local_project("/dir", cx_a).await;
|
let (project_a, worktree_id) = client_a.build_local_project("/dir", cx_a).await;
|
||||||
let project_b = client_b.build_remote_project(&project_a, cx_a, cx_b).await;
|
let project_id = project_a
|
||||||
|
.update(cx_a, |project, cx| project.share(cx))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let project_b = client_b.build_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
|
||||||
|
@ -1065,7 +1085,11 @@ async fn test_buffer_reloading(cx_a: &mut TestAppContext, cx_b: &mut TestAppCont
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
let (project_a, worktree_id) = client_a.build_local_project("/dir", cx_a).await;
|
let (project_a, worktree_id) = client_a.build_local_project("/dir", cx_a).await;
|
||||||
let project_b = client_b.build_remote_project(&project_a, cx_a, cx_b).await;
|
let project_id = project_a
|
||||||
|
.update(cx_a, |project, cx| project.share(cx))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let project_b = client_b.build_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
|
||||||
|
@ -1114,7 +1138,11 @@ async fn test_editing_while_guest_opens_buffer(
|
||||||
.insert_tree("/dir", json!({ "a.txt": "a-contents" }))
|
.insert_tree("/dir", json!({ "a.txt": "a-contents" }))
|
||||||
.await;
|
.await;
|
||||||
let (project_a, worktree_id) = client_a.build_local_project("/dir", cx_a).await;
|
let (project_a, worktree_id) = client_a.build_local_project("/dir", cx_a).await;
|
||||||
let project_b = client_b.build_remote_project(&project_a, cx_a, cx_b).await;
|
let project_id = project_a
|
||||||
|
.update(cx_a, |project, cx| project.share(cx))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let project_b = client_b.build_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
|
||||||
|
@ -1156,7 +1184,11 @@ async fn test_leaving_worktree_while_opening_buffer(
|
||||||
.insert_tree("/dir", json!({ "a.txt": "a-contents" }))
|
.insert_tree("/dir", json!({ "a.txt": "a-contents" }))
|
||||||
.await;
|
.await;
|
||||||
let (project_a, worktree_id) = client_a.build_local_project("/dir", cx_a).await;
|
let (project_a, worktree_id) = client_a.build_local_project("/dir", cx_a).await;
|
||||||
let project_b = client_b.build_remote_project(&project_a, cx_a, cx_b).await;
|
let project_id = project_a
|
||||||
|
.update(cx_a, |project, cx| project.share(cx))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let project_b = client_b.build_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.
|
||||||
project_a
|
project_a
|
||||||
|
@ -1201,7 +1233,11 @@ async fn test_canceling_buffer_opening(
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
let (project_a, worktree_id) = client_a.build_local_project("/dir", cx_a).await;
|
let (project_a, worktree_id) = client_a.build_local_project("/dir", cx_a).await;
|
||||||
let project_b = client_b.build_remote_project(&project_a, cx_a, cx_b).await;
|
let project_id = project_a
|
||||||
|
.update(cx_a, |project, cx| project.share(cx))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let project_b = client_b.build_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))
|
||||||
|
@ -1243,7 +1279,11 @@ async fn test_leaving_project(cx_a: &mut TestAppContext, cx_b: &mut TestAppConte
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
let (project_a, _) = client_a.build_local_project("/a", cx_a).await;
|
let (project_a, _) = client_a.build_local_project("/a", cx_a).await;
|
||||||
let _project_b = client_b.build_remote_project(&project_a, cx_a, cx_b).await;
|
let project_id = project_a
|
||||||
|
.update(cx_a, |project, cx| project.share(cx))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let _project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
// Client A sees that a guest has joined.
|
// Client A sees that a guest has joined.
|
||||||
project_a
|
project_a
|
||||||
|
@ -1257,7 +1297,7 @@ async fn test_leaving_project(cx_a: &mut TestAppContext, cx_b: &mut TestAppConte
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
// Rejoin the project as client B
|
// Rejoin the project as client B
|
||||||
let _project_b = client_b.build_remote_project(&project_a, cx_a, cx_b).await;
|
let _project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
// Client A sees that a guest has re-joined.
|
// Client A sees that a guest has re-joined.
|
||||||
project_a
|
project_a
|
||||||
|
@ -1317,7 +1357,10 @@ async fn test_collaborating_with_diagnostics(
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
|
let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
|
||||||
let project_id = project_a.update(cx_a, |p, _| p.next_remote_id()).await;
|
let project_id = project_a
|
||||||
|
.update(cx_a, |project, cx| project.share(cx))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// Cause the language server to start.
|
// Cause the language server to start.
|
||||||
let _buffer = cx_a
|
let _buffer = cx_a
|
||||||
|
@ -1335,7 +1378,7 @@ async fn test_collaborating_with_diagnostics(
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Join the worktree as client B.
|
// Join the worktree as client B.
|
||||||
let project_b = client_b.build_remote_project(&project_a, cx_a, cx_b).await;
|
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
// Simulate a language server reporting errors for a file.
|
// Simulate a language server reporting errors for a file.
|
||||||
let mut fake_language_server = fake_language_servers.next().await.unwrap();
|
let mut fake_language_server = fake_language_servers.next().await.unwrap();
|
||||||
|
@ -1383,7 +1426,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_remote_project(&project_a, cx_a, cx_c).await;
|
let project_c = client_c.build_remote_project(project_id, cx_c).await;
|
||||||
deterministic.run_until_parked();
|
deterministic.run_until_parked();
|
||||||
project_c.read_with(cx_c, |project, cx| {
|
project_c.read_with(cx_c, |project, cx| {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -1561,7 +1604,11 @@ async fn test_collaborating_with_completion(cx_a: &mut TestAppContext, cx_b: &mu
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
|
let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
|
||||||
let project_b = client_b.build_remote_project(&project_a, cx_a, cx_b).await;
|
let project_id = project_a
|
||||||
|
.update(cx_a, |project, cx| project.share(cx))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let project_b = client_b.build_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
|
||||||
|
@ -1705,8 +1752,12 @@ async fn test_reloading_buffer_manually(cx_a: &mut TestAppContext, cx_b: &mut Te
|
||||||
.update(cx_a, |p, cx| p.open_buffer((worktree_id, "a.rs"), cx))
|
.update(cx_a, |p, cx| p.open_buffer((worktree_id, "a.rs"), cx))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
let project_id = project_a
|
||||||
|
.update(cx_a, |project, cx| project.share(cx))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let project_b = client_b.build_remote_project(&project_a, cx_a, cx_b).await;
|
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
let buffer_b = cx_b
|
let buffer_b = cx_b
|
||||||
.background()
|
.background()
|
||||||
|
@ -1805,7 +1856,11 @@ async fn test_formatting_buffer(cx_a: &mut TestAppContext, cx_b: &mut TestAppCon
|
||||||
.insert_tree(&directory, json!({ "a.rs": "let one = \"two\"" }))
|
.insert_tree(&directory, json!({ "a.rs": "let one = \"two\"" }))
|
||||||
.await;
|
.await;
|
||||||
let (project_a, worktree_id) = client_a.build_local_project(&directory, cx_a).await;
|
let (project_a, worktree_id) = client_a.build_local_project(&directory, cx_a).await;
|
||||||
let project_b = client_b.build_remote_project(&project_a, cx_a, cx_b).await;
|
let project_id = project_a
|
||||||
|
.update(cx_a, |project, cx| project.share(cx))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
let buffer_b = cx_b
|
let buffer_b = cx_b
|
||||||
.background()
|
.background()
|
||||||
|
@ -1908,7 +1963,11 @@ async fn test_definition(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) {
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
let (project_a, worktree_id) = client_a.build_local_project("/root/dir-1", cx_a).await;
|
let (project_a, worktree_id) = client_a.build_local_project("/root/dir-1", cx_a).await;
|
||||||
let project_b = client_b.build_remote_project(&project_a, cx_a, cx_b).await;
|
let project_id = project_a
|
||||||
|
.update(cx_a, |project, cx| project.share(cx))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
// Open the file on client B.
|
// Open the file on client B.
|
||||||
let buffer_b = cx_b
|
let buffer_b = cx_b
|
||||||
|
@ -2047,7 +2106,11 @@ async fn test_references(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) {
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
let (project_a, worktree_id) = client_a.build_local_project("/root/dir-1", cx_a).await;
|
let (project_a, worktree_id) = client_a.build_local_project("/root/dir-1", cx_a).await;
|
||||||
let project_b = client_b.build_remote_project(&project_a, cx_a, cx_b).await;
|
let project_id = project_a
|
||||||
|
.update(cx_a, |project, cx| project.share(cx))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
// Open the file on client B.
|
// Open the file on client B.
|
||||||
let buffer_b = cx_b
|
let buffer_b = cx_b
|
||||||
|
@ -2142,8 +2205,12 @@ async fn test_project_search(cx_a: &mut TestAppContext, cx_b: &mut TestAppContex
|
||||||
worktree_2
|
worktree_2
|
||||||
.read_with(cx_a, |tree, _| tree.as_local().unwrap().scan_complete())
|
.read_with(cx_a, |tree, _| tree.as_local().unwrap().scan_complete())
|
||||||
.await;
|
.await;
|
||||||
|
let project_id = project_a
|
||||||
|
.update(cx_a, |project, cx| project.share(cx))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let project_b = client_b.build_remote_project(&project_a, cx_a, cx_b).await;
|
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
// Perform a search as the guest.
|
// Perform a search as the guest.
|
||||||
let results = project_b
|
let results = project_b
|
||||||
|
@ -2212,7 +2279,11 @@ async fn test_document_highlights(cx_a: &mut TestAppContext, cx_b: &mut TestAppC
|
||||||
client_a.language_registry.add(Arc::new(language));
|
client_a.language_registry.add(Arc::new(language));
|
||||||
|
|
||||||
let (project_a, worktree_id) = client_a.build_local_project("/root-1", cx_a).await;
|
let (project_a, worktree_id) = client_a.build_local_project("/root-1", cx_a).await;
|
||||||
let project_b = client_b.build_remote_project(&project_a, cx_a, cx_b).await;
|
let project_id = project_a
|
||||||
|
.update(cx_a, |project, cx| project.share(cx))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
// Open the file on client B.
|
// Open the file on client B.
|
||||||
let buffer_b = cx_b
|
let buffer_b = cx_b
|
||||||
|
@ -2309,7 +2380,11 @@ async fn test_lsp_hover(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) {
|
||||||
client_a.language_registry.add(Arc::new(language));
|
client_a.language_registry.add(Arc::new(language));
|
||||||
|
|
||||||
let (project_a, worktree_id) = client_a.build_local_project("/root-1", cx_a).await;
|
let (project_a, worktree_id) = client_a.build_local_project("/root-1", cx_a).await;
|
||||||
let project_b = client_b.build_remote_project(&project_a, cx_a, cx_b).await;
|
let project_id = project_a
|
||||||
|
.update(cx_a, |project, cx| project.share(cx))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
// Open the file as the guest
|
// Open the file as the guest
|
||||||
let buffer_b = cx_b
|
let buffer_b = cx_b
|
||||||
|
@ -2414,7 +2489,11 @@ async fn test_project_symbols(cx_a: &mut TestAppContext, cx_b: &mut TestAppConte
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
let (project_a, worktree_id) = client_a.build_local_project("/code/crate-1", cx_a).await;
|
let (project_a, worktree_id) = client_a.build_local_project("/code/crate-1", cx_a).await;
|
||||||
let project_b = client_b.build_remote_project(&project_a, cx_a, cx_b).await;
|
let project_id = project_a
|
||||||
|
.update(cx_a, |project, cx| project.share(cx))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
// Cause the language server to start.
|
// Cause the language server to start.
|
||||||
let _buffer = cx_b
|
let _buffer = cx_b
|
||||||
|
@ -2510,7 +2589,11 @@ async fn test_open_buffer_while_getting_definition_pointing_to_it(
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
let (project_a, worktree_id) = client_a.build_local_project("/root", cx_a).await;
|
let (project_a, worktree_id) = client_a.build_local_project("/root", cx_a).await;
|
||||||
let project_b = client_b.build_remote_project(&project_a, cx_a, cx_b).await;
|
let project_id = project_a
|
||||||
|
.update(cx_a, |project, cx| project.share(cx))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
let buffer_b1 = cx_b
|
let buffer_b1 = cx_b
|
||||||
.background()
|
.background()
|
||||||
|
@ -2581,9 +2664,13 @@ async fn test_collaborating_with_code_actions(
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
|
let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
|
||||||
|
let project_id = project_a
|
||||||
|
.update(cx_a, |project, cx| project.share(cx))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// Join the project as client B.
|
// Join the project as client B.
|
||||||
let project_b = client_b.build_remote_project(&project_a, cx_a, cx_b).await;
|
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||||
let (_window_b, workspace_b) =
|
let (_window_b, workspace_b) =
|
||||||
cx_b.add_window(|cx| Workspace::new(project_b.clone(), |_, _| unimplemented!(), cx));
|
cx_b.add_window(|cx| Workspace::new(project_b.clone(), |_, _| unimplemented!(), cx));
|
||||||
let editor_b = workspace_b
|
let editor_b = workspace_b
|
||||||
|
@ -2798,7 +2885,11 @@ async fn test_collaborating_with_renames(cx_a: &mut TestAppContext, cx_b: &mut T
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
let (project_a, worktree_id) = client_a.build_local_project("/dir", cx_a).await;
|
let (project_a, worktree_id) = client_a.build_local_project("/dir", cx_a).await;
|
||||||
let project_b = client_b.build_remote_project(&project_a, cx_a, cx_b).await;
|
let project_id = project_a
|
||||||
|
.update(cx_a, |project, cx| project.share(cx))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
let (_window_b, workspace_b) =
|
let (_window_b, workspace_b) =
|
||||||
cx_b.add_window(|cx| Workspace::new(project_b.clone(), |_, _| unimplemented!(), cx));
|
cx_b.add_window(|cx| Workspace::new(project_b.clone(), |_, _| unimplemented!(), cx));
|
||||||
|
@ -3006,7 +3097,11 @@ async fn test_language_server_statuses(
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
let project_b = client_b.build_remote_project(&project_a, cx_a, cx_b).await;
|
let project_id = project_a
|
||||||
|
.update(cx_a, |project, cx| project.share(cx))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||||
project_b.read_with(cx_b, |project, _| {
|
project_b.read_with(cx_b, |project, _| {
|
||||||
let status = project.language_server_statuses().next().unwrap();
|
let status = project.language_server_statuses().next().unwrap();
|
||||||
assert_eq!(status.name, "the-language-server");
|
assert_eq!(status.name, "the-language-server");
|
||||||
|
@ -3485,79 +3580,6 @@ async fn test_contacts(
|
||||||
[("user_a".to_string(), true), ("user_b".to_string(), true)]
|
[("user_a".to_string(), true), ("user_b".to_string(), true)]
|
||||||
);
|
);
|
||||||
|
|
||||||
// Share a project as client A.
|
|
||||||
client_a.fs.create_dir(Path::new("/a")).await.unwrap();
|
|
||||||
let (project_a, _) = client_a.build_local_project("/a", cx_a).await;
|
|
||||||
|
|
||||||
deterministic.run_until_parked();
|
|
||||||
assert_eq!(
|
|
||||||
contacts(&client_a, cx_a),
|
|
||||||
[("user_b".to_string(), true), ("user_c".to_string(), true)]
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
contacts(&client_b, cx_b),
|
|
||||||
[("user_a".to_string(), true), ("user_c".to_string(), true)]
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
contacts(&client_c, cx_c),
|
|
||||||
[("user_a".to_string(), true), ("user_b".to_string(), true)]
|
|
||||||
);
|
|
||||||
|
|
||||||
let _project_b = client_b.build_remote_project(&project_a, cx_a, cx_b).await;
|
|
||||||
|
|
||||||
deterministic.run_until_parked();
|
|
||||||
assert_eq!(
|
|
||||||
contacts(&client_a, cx_a),
|
|
||||||
[("user_b".to_string(), true), ("user_c".to_string(), true)]
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
contacts(&client_b, cx_b),
|
|
||||||
[("user_a".to_string(), true,), ("user_c".to_string(), true)]
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
contacts(&client_c, cx_c),
|
|
||||||
[("user_a".to_string(), true,), ("user_b".to_string(), true)]
|
|
||||||
);
|
|
||||||
|
|
||||||
// Add a local project as client B
|
|
||||||
client_a.fs.create_dir("/b".as_ref()).await.unwrap();
|
|
||||||
let (_project_b, _) = client_b.build_local_project("/b", cx_b).await;
|
|
||||||
|
|
||||||
deterministic.run_until_parked();
|
|
||||||
assert_eq!(
|
|
||||||
contacts(&client_a, cx_a),
|
|
||||||
[("user_b".to_string(), true), ("user_c".to_string(), true)]
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
contacts(&client_b, cx_b),
|
|
||||||
[("user_a".to_string(), true), ("user_c".to_string(), true)]
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
contacts(&client_c, cx_c),
|
|
||||||
[("user_a".to_string(), true,), ("user_b".to_string(), true)]
|
|
||||||
);
|
|
||||||
|
|
||||||
project_a
|
|
||||||
.condition(cx_a, |project, _| {
|
|
||||||
project.collaborators().contains_key(&client_b.peer_id)
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
|
|
||||||
cx_a.update(move |_| drop(project_a));
|
|
||||||
deterministic.run_until_parked();
|
|
||||||
assert_eq!(
|
|
||||||
contacts(&client_a, cx_a),
|
|
||||||
[("user_b".to_string(), true), ("user_c".to_string(), true)]
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
contacts(&client_b, cx_b),
|
|
||||||
[("user_a".to_string(), true), ("user_c".to_string(), true)]
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
contacts(&client_c, cx_c),
|
|
||||||
[("user_a".to_string(), true), ("user_b".to_string(), true)]
|
|
||||||
);
|
|
||||||
|
|
||||||
server.disconnect_client(client_c.current_user_id(cx_c));
|
server.disconnect_client(client_c.current_user_id(cx_c));
|
||||||
server.forbid_connections();
|
server.forbid_connections();
|
||||||
deterministic.advance_clock(rpc::RECEIVE_TIMEOUT);
|
deterministic.advance_clock(rpc::RECEIVE_TIMEOUT);
|
||||||
|
@ -3811,8 +3833,11 @@ async fn test_following(cx_a: &mut TestAppContext, cx_b: &mut TestAppContext) {
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
|
let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
|
||||||
|
let project_id = project_a
|
||||||
let project_b = client_b.build_remote_project(&project_a, cx_a, cx_b).await;
|
.update(cx_a, |project, cx| project.share(cx))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
// Client A opens some editors.
|
// Client A opens some editors.
|
||||||
let workspace_a = client_a.build_workspace(&project_a, cx_a);
|
let workspace_a = client_a.build_workspace(&project_a, cx_a);
|
||||||
|
@ -4019,9 +4044,13 @@ async fn test_peers_following_each_other(cx_a: &mut TestAppContext, cx_b: &mut T
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
|
let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
|
||||||
|
let project_id = project_a
|
||||||
|
.update(cx_a, |project, cx| project.share(cx))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// Client B joins the project.
|
// Client B joins the project.
|
||||||
let project_b = client_b.build_remote_project(&project_a, cx_a, cx_b).await;
|
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
// Client A opens some editors.
|
// Client A opens some editors.
|
||||||
let workspace_a = client_a.build_workspace(&project_a, cx_a);
|
let workspace_a = client_a.build_workspace(&project_a, cx_a);
|
||||||
|
@ -4182,7 +4211,11 @@ async fn test_auto_unfollowing(cx_a: &mut TestAppContext, cx_b: &mut TestAppCont
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
|
let (project_a, worktree_id) = client_a.build_local_project("/a", cx_a).await;
|
||||||
let project_b = client_b.build_remote_project(&project_a, cx_a, cx_b).await;
|
let project_id = project_a
|
||||||
|
.update(cx_a, |project, cx| project.share(cx))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||||
|
|
||||||
// Client A opens some editors.
|
// Client A opens some editors.
|
||||||
let workspace_a = client_a.build_workspace(&project_a, cx_a);
|
let workspace_a = client_a.build_workspace(&project_a, cx_a);
|
||||||
|
@ -4331,8 +4364,12 @@ async fn test_peers_simultaneously_following_each_other(
|
||||||
client_a.fs.insert_tree("/a", json!({})).await;
|
client_a.fs.insert_tree("/a", json!({})).await;
|
||||||
let (project_a, _) = client_a.build_local_project("/a", cx_a).await;
|
let (project_a, _) = client_a.build_local_project("/a", cx_a).await;
|
||||||
let workspace_a = client_a.build_workspace(&project_a, cx_a);
|
let workspace_a = client_a.build_workspace(&project_a, cx_a);
|
||||||
|
let project_id = project_a
|
||||||
|
.update(cx_a, |project, cx| project.share(cx))
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let project_b = client_b.build_remote_project(&project_a, cx_a, cx_b).await;
|
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||||
let workspace_b = client_b.build_workspace(&project_b, cx_b);
|
let workspace_b = client_b.build_workspace(&project_b, cx_b);
|
||||||
|
|
||||||
deterministic.run_until_parked();
|
deterministic.run_until_parked();
|
||||||
|
@ -4445,9 +4482,6 @@ async fn test_random_collaboration(
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
let host_project_id = host_project
|
|
||||||
.update(&mut host_cx, |p, _| p.next_remote_id())
|
|
||||||
.await;
|
|
||||||
|
|
||||||
let (collab_worktree, _) = host_project
|
let (collab_worktree, _) = host_project
|
||||||
.update(&mut host_cx, |project, cx| {
|
.update(&mut host_cx, |project, cx| {
|
||||||
|
@ -4588,7 +4622,7 @@ async fn test_random_collaboration(
|
||||||
.await;
|
.await;
|
||||||
host_language_registry.add(Arc::new(language));
|
host_language_registry.add(Arc::new(language));
|
||||||
|
|
||||||
host_project
|
let host_project_id = host_project
|
||||||
.update(&mut host_cx, |project, cx| project.share(cx))
|
.update(&mut host_cx, |project, cx| project.share(cx))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -5155,40 +5189,26 @@ impl TestClient {
|
||||||
worktree
|
worktree
|
||||||
.read_with(cx, |tree, _| tree.as_local().unwrap().scan_complete())
|
.read_with(cx, |tree, _| tree.as_local().unwrap().scan_complete())
|
||||||
.await;
|
.await;
|
||||||
project
|
|
||||||
.update(cx, |project, _| project.next_remote_id())
|
|
||||||
.await;
|
|
||||||
(project, worktree.read_with(cx, |tree, _| tree.id()))
|
(project, worktree.read_with(cx, |tree, _| tree.id()))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn build_remote_project(
|
async fn build_remote_project(
|
||||||
&self,
|
&self,
|
||||||
host_project: &ModelHandle<Project>,
|
host_project_id: u64,
|
||||||
host_cx: &mut TestAppContext,
|
|
||||||
guest_cx: &mut TestAppContext,
|
guest_cx: &mut TestAppContext,
|
||||||
) -> ModelHandle<Project> {
|
) -> ModelHandle<Project> {
|
||||||
let host_project_id = host_project
|
|
||||||
.read_with(host_cx, |project, _| project.next_remote_id())
|
|
||||||
.await;
|
|
||||||
host_project
|
|
||||||
.update(host_cx, |project, cx| project.share(cx))
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
let languages = host_project.read_with(host_cx, |project, _| project.languages().clone());
|
|
||||||
let project_b = guest_cx.spawn(|cx| {
|
let project_b = guest_cx.spawn(|cx| {
|
||||||
Project::remote(
|
Project::remote(
|
||||||
host_project_id,
|
host_project_id,
|
||||||
self.client.clone(),
|
self.client.clone(),
|
||||||
self.user_store.clone(),
|
self.user_store.clone(),
|
||||||
self.project_store.clone(),
|
self.project_store.clone(),
|
||||||
languages,
|
self.language_registry.clone(),
|
||||||
FakeFs::new(cx.background()),
|
FakeFs::new(cx.background()),
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
project_b.await.unwrap()
|
||||||
let project = project_b.await.unwrap();
|
|
||||||
project
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_workspace(
|
fn build_workspace(
|
||||||
|
|
|
@ -151,11 +151,10 @@ impl Server {
|
||||||
.add_message_handler(Server::leave_room)
|
.add_message_handler(Server::leave_room)
|
||||||
.add_request_handler(Server::call)
|
.add_request_handler(Server::call)
|
||||||
.add_message_handler(Server::decline_call)
|
.add_message_handler(Server::decline_call)
|
||||||
.add_request_handler(Server::register_project)
|
.add_request_handler(Server::share_project)
|
||||||
.add_request_handler(Server::unregister_project)
|
.add_message_handler(Server::unshare_project)
|
||||||
.add_request_handler(Server::join_project)
|
.add_request_handler(Server::join_project)
|
||||||
.add_message_handler(Server::leave_project)
|
.add_message_handler(Server::leave_project)
|
||||||
.add_message_handler(Server::unshare_project)
|
|
||||||
.add_message_handler(Server::update_project)
|
.add_message_handler(Server::update_project)
|
||||||
.add_message_handler(Server::register_project_activity)
|
.add_message_handler(Server::register_project_activity)
|
||||||
.add_request_handler(Server::update_worktree)
|
.add_request_handler(Server::update_worktree)
|
||||||
|
@ -470,18 +469,18 @@ impl Server {
|
||||||
async fn sign_out(self: &mut Arc<Self>, connection_id: ConnectionId) -> Result<()> {
|
async fn sign_out(self: &mut Arc<Self>, connection_id: ConnectionId) -> Result<()> {
|
||||||
self.peer.disconnect(connection_id);
|
self.peer.disconnect(connection_id);
|
||||||
|
|
||||||
let mut projects_to_unregister = Vec::new();
|
let mut projects_to_unshare = Vec::new();
|
||||||
let removed_user_id;
|
let removed_user_id;
|
||||||
{
|
{
|
||||||
let mut store = self.store().await;
|
let mut store = self.store().await;
|
||||||
let removed_connection = store.remove_connection(connection_id)?;
|
let removed_connection = store.remove_connection(connection_id)?;
|
||||||
|
|
||||||
for (project_id, project) in removed_connection.hosted_projects {
|
for (project_id, project) in removed_connection.hosted_projects {
|
||||||
projects_to_unregister.push(project_id);
|
projects_to_unshare.push(project_id);
|
||||||
broadcast(connection_id, project.guests.keys().copied(), |conn_id| {
|
broadcast(connection_id, project.guests.keys().copied(), |conn_id| {
|
||||||
self.peer.send(
|
self.peer.send(
|
||||||
conn_id,
|
conn_id,
|
||||||
proto::UnregisterProject {
|
proto::UnshareProject {
|
||||||
project_id: project_id.to_proto(),
|
project_id: project_id.to_proto(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -514,7 +513,7 @@ impl Server {
|
||||||
|
|
||||||
self.update_user_contacts(removed_user_id).await.trace_err();
|
self.update_user_contacts(removed_user_id).await.trace_err();
|
||||||
|
|
||||||
for project_id in projects_to_unregister {
|
for project_id in projects_to_unshare {
|
||||||
self.app_state
|
self.app_state
|
||||||
.db
|
.db
|
||||||
.unregister_project(project_id)
|
.unregister_project(project_id)
|
||||||
|
@ -687,10 +686,10 @@ impl Server {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn register_project(
|
async fn share_project(
|
||||||
self: Arc<Server>,
|
self: Arc<Server>,
|
||||||
request: TypedEnvelope<proto::RegisterProject>,
|
request: TypedEnvelope<proto::ShareProject>,
|
||||||
response: Response<proto::RegisterProject>,
|
response: Response<proto::ShareProject>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let user_id = self
|
let user_id = self
|
||||||
.store()
|
.store()
|
||||||
|
@ -699,44 +698,15 @@ impl Server {
|
||||||
let project_id = self.app_state.db.register_project(user_id).await?;
|
let project_id = self.app_state.db.register_project(user_id).await?;
|
||||||
self.store()
|
self.store()
|
||||||
.await
|
.await
|
||||||
.register_project(request.sender_id, project_id)?;
|
.share_project(request.sender_id, project_id)?;
|
||||||
|
|
||||||
response.send(proto::RegisterProjectResponse {
|
response.send(proto::ShareProjectResponse {
|
||||||
project_id: project_id.to_proto(),
|
project_id: project_id.to_proto(),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn unregister_project(
|
|
||||||
self: Arc<Server>,
|
|
||||||
request: TypedEnvelope<proto::UnregisterProject>,
|
|
||||||
response: Response<proto::UnregisterProject>,
|
|
||||||
) -> Result<()> {
|
|
||||||
let project_id = ProjectId::from_proto(request.payload.project_id);
|
|
||||||
let project = self
|
|
||||||
.store()
|
|
||||||
.await
|
|
||||||
.unregister_project(project_id, request.sender_id)?;
|
|
||||||
self.app_state.db.unregister_project(project_id).await?;
|
|
||||||
|
|
||||||
broadcast(
|
|
||||||
request.sender_id,
|
|
||||||
project.guests.keys().copied(),
|
|
||||||
|conn_id| {
|
|
||||||
self.peer.send(
|
|
||||||
conn_id,
|
|
||||||
proto::UnregisterProject {
|
|
||||||
project_id: project_id.to_proto(),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
},
|
|
||||||
);
|
|
||||||
response.send(proto::Ack {})?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn unshare_project(
|
async fn unshare_project(
|
||||||
self: Arc<Server>,
|
self: Arc<Server>,
|
||||||
message: TypedEnvelope<proto::UnshareProject>,
|
message: TypedEnvelope<proto::UnshareProject>,
|
||||||
|
@ -746,9 +716,11 @@ impl Server {
|
||||||
.store()
|
.store()
|
||||||
.await
|
.await
|
||||||
.unshare_project(project_id, message.sender_id)?;
|
.unshare_project(project_id, message.sender_id)?;
|
||||||
broadcast(message.sender_id, project.guest_connection_ids, |conn_id| {
|
broadcast(
|
||||||
self.peer.send(conn_id, message.payload.clone())
|
message.sender_id,
|
||||||
});
|
project.guest_connection_ids(),
|
||||||
|
|conn_id| self.peer.send(conn_id, message.payload.clone()),
|
||||||
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,10 +96,6 @@ pub struct LeftProject {
|
||||||
pub remove_collaborator: bool,
|
pub remove_collaborator: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct UnsharedProject {
|
|
||||||
pub guest_connection_ids: Vec<ConnectionId>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub struct Metrics {
|
pub struct Metrics {
|
||||||
pub connections: usize,
|
pub connections: usize,
|
||||||
|
@ -201,9 +197,9 @@ impl Store {
|
||||||
self.leave_channel(connection_id, channel_id);
|
self.leave_channel(connection_id, channel_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unregister and leave all projects.
|
// Unshare and leave all projects.
|
||||||
for project_id in connection_projects {
|
for project_id in connection_projects {
|
||||||
if let Ok(project) = self.unregister_project(project_id, connection_id) {
|
if let Ok(project) = self.unshare_project(project_id, connection_id) {
|
||||||
result.hosted_projects.insert(project_id, project);
|
result.hosted_projects.insert(project_id, project);
|
||||||
} else if self.leave_project(connection_id, project_id).is_ok() {
|
} else if self.leave_project(connection_id, project_id).is_ok() {
|
||||||
result.guest_project_ids.insert(project_id);
|
result.guest_project_ids.insert(project_id);
|
||||||
|
@ -566,7 +562,7 @@ impl Store {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register_project(
|
pub fn share_project(
|
||||||
&mut self,
|
&mut self,
|
||||||
host_connection_id: ConnectionId,
|
host_connection_id: ConnectionId,
|
||||||
project_id: ProjectId,
|
project_id: ProjectId,
|
||||||
|
@ -595,6 +591,35 @@ impl Store {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn unshare_project(
|
||||||
|
&mut self,
|
||||||
|
project_id: ProjectId,
|
||||||
|
connection_id: ConnectionId,
|
||||||
|
) -> Result<Project> {
|
||||||
|
match self.projects.entry(project_id) {
|
||||||
|
btree_map::Entry::Occupied(e) => {
|
||||||
|
if e.get().host_connection_id == connection_id {
|
||||||
|
let project = e.remove();
|
||||||
|
|
||||||
|
if let Some(host_connection) = self.connections.get_mut(&connection_id) {
|
||||||
|
host_connection.projects.remove(&project_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
for guest_connection in project.guests.keys() {
|
||||||
|
if let Some(connection) = self.connections.get_mut(guest_connection) {
|
||||||
|
connection.projects.remove(&project_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(project)
|
||||||
|
} else {
|
||||||
|
Err(anyhow!("no such project"))?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
btree_map::Entry::Vacant(_) => Err(anyhow!("no such project"))?,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn update_project(
|
pub fn update_project(
|
||||||
&mut self,
|
&mut self,
|
||||||
project_id: ProjectId,
|
project_id: ProjectId,
|
||||||
|
@ -628,66 +653,6 @@ impl Store {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unregister_project(
|
|
||||||
&mut self,
|
|
||||||
project_id: ProjectId,
|
|
||||||
connection_id: ConnectionId,
|
|
||||||
) -> Result<Project> {
|
|
||||||
match self.projects.entry(project_id) {
|
|
||||||
btree_map::Entry::Occupied(e) => {
|
|
||||||
if e.get().host_connection_id == connection_id {
|
|
||||||
let project = e.remove();
|
|
||||||
|
|
||||||
if let Some(host_connection) = self.connections.get_mut(&connection_id) {
|
|
||||||
host_connection.projects.remove(&project_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
for guest_connection in project.guests.keys() {
|
|
||||||
if let Some(connection) = self.connections.get_mut(guest_connection) {
|
|
||||||
connection.projects.remove(&project_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(project)
|
|
||||||
} else {
|
|
||||||
Err(anyhow!("no such project"))?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
btree_map::Entry::Vacant(_) => Err(anyhow!("no such project"))?,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn unshare_project(
|
|
||||||
&mut self,
|
|
||||||
project_id: ProjectId,
|
|
||||||
connection_id: ConnectionId,
|
|
||||||
) -> Result<UnsharedProject> {
|
|
||||||
let project = self
|
|
||||||
.projects
|
|
||||||
.get_mut(&project_id)
|
|
||||||
.ok_or_else(|| anyhow!("no such project"))?;
|
|
||||||
anyhow::ensure!(
|
|
||||||
project.host_connection_id == connection_id,
|
|
||||||
"no such project"
|
|
||||||
);
|
|
||||||
|
|
||||||
let guest_connection_ids = project.guest_connection_ids();
|
|
||||||
project.active_replica_ids.clear();
|
|
||||||
project.guests.clear();
|
|
||||||
project.language_servers.clear();
|
|
||||||
project.worktrees.clear();
|
|
||||||
|
|
||||||
for connection_id in &guest_connection_ids {
|
|
||||||
if let Some(connection) = self.connections.get_mut(connection_id) {
|
|
||||||
connection.projects.remove(&project_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(UnsharedProject {
|
|
||||||
guest_connection_ids,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn update_diagnostic_summary(
|
pub fn update_diagnostic_summary(
|
||||||
&mut self,
|
&mut self,
|
||||||
project_id: ProjectId,
|
project_id: ProjectId,
|
||||||
|
|
|
@ -845,14 +845,6 @@ mod tests {
|
||||||
.detach();
|
.detach();
|
||||||
});
|
});
|
||||||
|
|
||||||
let request = server.receive::<proto::RegisterProject>().await.unwrap();
|
|
||||||
server
|
|
||||||
.respond(
|
|
||||||
request.receipt(),
|
|
||||||
proto::RegisterProjectResponse { project_id: 200 },
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
let get_users_request = server.receive::<proto::GetUsers>().await.unwrap();
|
let get_users_request = server.receive::<proto::GetUsers>().await.unwrap();
|
||||||
server
|
server
|
||||||
.respond(
|
.respond(
|
||||||
|
|
|
@ -35,7 +35,6 @@ use lsp::{
|
||||||
};
|
};
|
||||||
use lsp_command::*;
|
use lsp_command::*;
|
||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use postage::stream::Stream;
|
|
||||||
use postage::watch;
|
use postage::watch;
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
use search::SearchQuery;
|
use search::SearchQuery;
|
||||||
|
@ -153,10 +152,8 @@ enum WorktreeHandle {
|
||||||
|
|
||||||
enum ProjectClientState {
|
enum ProjectClientState {
|
||||||
Local {
|
Local {
|
||||||
is_shared: bool,
|
remote_id: Option<u64>,
|
||||||
remote_id_tx: watch::Sender<Option<u64>>,
|
_detect_unshare: Task<Option<()>>,
|
||||||
remote_id_rx: watch::Receiver<Option<u64>>,
|
|
||||||
_maintain_remote_id: Task<Option<()>>,
|
|
||||||
},
|
},
|
||||||
Remote {
|
Remote {
|
||||||
sharing_has_stopped: bool,
|
sharing_has_stopped: bool,
|
||||||
|
@ -382,7 +379,6 @@ impl Project {
|
||||||
client.add_model_message_handler(Self::handle_update_language_server);
|
client.add_model_message_handler(Self::handle_update_language_server);
|
||||||
client.add_model_message_handler(Self::handle_remove_collaborator);
|
client.add_model_message_handler(Self::handle_remove_collaborator);
|
||||||
client.add_model_message_handler(Self::handle_update_project);
|
client.add_model_message_handler(Self::handle_update_project);
|
||||||
client.add_model_message_handler(Self::handle_unregister_project);
|
|
||||||
client.add_model_message_handler(Self::handle_unshare_project);
|
client.add_model_message_handler(Self::handle_unshare_project);
|
||||||
client.add_model_message_handler(Self::handle_create_buffer_for_peer);
|
client.add_model_message_handler(Self::handle_create_buffer_for_peer);
|
||||||
client.add_model_message_handler(Self::handle_update_buffer_file);
|
client.add_model_message_handler(Self::handle_update_buffer_file);
|
||||||
|
@ -423,24 +419,19 @@ impl Project {
|
||||||
cx: &mut MutableAppContext,
|
cx: &mut MutableAppContext,
|
||||||
) -> ModelHandle<Self> {
|
) -> ModelHandle<Self> {
|
||||||
cx.add_model(|cx: &mut ModelContext<Self>| {
|
cx.add_model(|cx: &mut ModelContext<Self>| {
|
||||||
let (remote_id_tx, remote_id_rx) = watch::channel();
|
let mut status = client.status();
|
||||||
let _maintain_remote_id = cx.spawn_weak({
|
let _detect_unshare = cx.spawn_weak(move |this, mut cx| {
|
||||||
let mut status_rx = client.clone().status();
|
async move {
|
||||||
move |this, mut cx| async move {
|
let is_connected = status.next().await.map_or(false, |s| s.is_connected());
|
||||||
while let Some(status) = status_rx.recv().await {
|
// Even if we're initially connected, any future change of the status means we momentarily disconnected.
|
||||||
let this = this.upgrade(&cx)?;
|
if !is_connected || status.next().await.is_some() {
|
||||||
if status.is_connected() {
|
if let Some(this) = this.upgrade(&cx) {
|
||||||
this.update(&mut cx, |this, cx| this.register(cx))
|
let _ = this.update(&mut cx, |this, cx| this.unshare(cx));
|
||||||
.await
|
|
||||||
.log_err()?;
|
|
||||||
} else {
|
|
||||||
this.update(&mut cx, |this, cx| this.unregister(cx))
|
|
||||||
.await
|
|
||||||
.log_err();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
Ok(())
|
||||||
}
|
}
|
||||||
|
.log_err()
|
||||||
});
|
});
|
||||||
|
|
||||||
let handle = cx.weak_handle();
|
let handle = cx.weak_handle();
|
||||||
|
@ -456,10 +447,8 @@ impl Project {
|
||||||
loading_local_worktrees: Default::default(),
|
loading_local_worktrees: Default::default(),
|
||||||
buffer_snapshots: Default::default(),
|
buffer_snapshots: Default::default(),
|
||||||
client_state: ProjectClientState::Local {
|
client_state: ProjectClientState::Local {
|
||||||
is_shared: false,
|
remote_id: None,
|
||||||
remote_id_tx,
|
_detect_unshare,
|
||||||
remote_id_rx,
|
|
||||||
_maintain_remote_id,
|
|
||||||
},
|
},
|
||||||
opened_buffer: watch::channel(),
|
opened_buffer: watch::channel(),
|
||||||
client_subscriptions: Vec::new(),
|
client_subscriptions: Vec::new(),
|
||||||
|
@ -762,113 +751,9 @@ impl Project {
|
||||||
&self.fs
|
&self.fs
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unregister(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
|
|
||||||
self.unshare(cx).log_err();
|
|
||||||
if let ProjectClientState::Local { remote_id_rx, .. } = &mut self.client_state {
|
|
||||||
if let Some(remote_id) = *remote_id_rx.borrow() {
|
|
||||||
let request = self.client.request(proto::UnregisterProject {
|
|
||||||
project_id: remote_id,
|
|
||||||
});
|
|
||||||
return cx.spawn(|this, mut cx| async move {
|
|
||||||
let response = request.await;
|
|
||||||
|
|
||||||
// Unregistering the project causes the server to send out a
|
|
||||||
// contact update removing this project from the host's list
|
|
||||||
// of online projects. Wait until this contact update has been
|
|
||||||
// processed before clearing out this project's remote id, so
|
|
||||||
// that there is no moment where this project appears in the
|
|
||||||
// contact metadata and *also* has no remote id.
|
|
||||||
this.update(&mut cx, |this, cx| {
|
|
||||||
this.user_store()
|
|
||||||
.update(cx, |store, _| store.contact_updates_done())
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
|
|
||||||
this.update(&mut cx, |this, cx| {
|
|
||||||
if let ProjectClientState::Local { remote_id_tx, .. } =
|
|
||||||
&mut this.client_state
|
|
||||||
{
|
|
||||||
*remote_id_tx.borrow_mut() = None;
|
|
||||||
}
|
|
||||||
this.client_subscriptions.clear();
|
|
||||||
this.metadata_changed(cx);
|
|
||||||
});
|
|
||||||
response.map(drop)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Task::ready(Ok(()))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn register(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
|
|
||||||
if let ProjectClientState::Local { remote_id_rx, .. } = &self.client_state {
|
|
||||||
if remote_id_rx.borrow().is_some() {
|
|
||||||
return Task::ready(Ok(()));
|
|
||||||
}
|
|
||||||
|
|
||||||
let response = self.client.request(proto::RegisterProject {});
|
|
||||||
cx.spawn(|this, mut cx| async move {
|
|
||||||
let remote_id = response.await?.project_id;
|
|
||||||
this.update(&mut cx, |this, cx| {
|
|
||||||
if let ProjectClientState::Local { remote_id_tx, .. } = &mut this.client_state {
|
|
||||||
*remote_id_tx.borrow_mut() = Some(remote_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.metadata_changed(cx);
|
|
||||||
cx.emit(Event::RemoteIdChanged(Some(remote_id)));
|
|
||||||
this.client_subscriptions
|
|
||||||
.push(this.client.add_model_for_remote_entity(remote_id, cx));
|
|
||||||
Ok(())
|
|
||||||
})
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
Task::ready(Err(anyhow!("can't register a remote project")))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn remote_id(&self) -> Option<u64> {
|
pub fn remote_id(&self) -> Option<u64> {
|
||||||
match &self.client_state {
|
match &self.client_state {
|
||||||
ProjectClientState::Local { remote_id_rx, .. } => *remote_id_rx.borrow(),
|
ProjectClientState::Local { remote_id, .. } => *remote_id,
|
||||||
ProjectClientState::Remote { remote_id, .. } => Some(*remote_id),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn next_remote_id(&self) -> impl Future<Output = u64> {
|
|
||||||
let mut id = None;
|
|
||||||
let mut watch = None;
|
|
||||||
match &self.client_state {
|
|
||||||
ProjectClientState::Local { remote_id_rx, .. } => watch = Some(remote_id_rx.clone()),
|
|
||||||
ProjectClientState::Remote { remote_id, .. } => id = Some(*remote_id),
|
|
||||||
}
|
|
||||||
|
|
||||||
async move {
|
|
||||||
if let Some(id) = id {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
let mut watch = watch.unwrap();
|
|
||||||
loop {
|
|
||||||
let id = *watch.borrow();
|
|
||||||
if let Some(id) = id {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
watch.next().await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn shared_remote_id(&self) -> Option<u64> {
|
|
||||||
match &self.client_state {
|
|
||||||
ProjectClientState::Local {
|
|
||||||
remote_id_rx,
|
|
||||||
is_shared,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
if *is_shared {
|
|
||||||
*remote_id_rx.borrow()
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ProjectClientState::Remote { remote_id, .. } => Some(*remote_id),
|
ProjectClientState::Remote { remote_id, .. } => Some(*remote_id),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -881,7 +766,7 @@ impl Project {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn metadata_changed(&mut self, cx: &mut ModelContext<Self>) {
|
fn metadata_changed(&mut self, cx: &mut ModelContext<Self>) {
|
||||||
if let ProjectClientState::Local { remote_id_rx, .. } = &self.client_state {
|
if let ProjectClientState::Local { remote_id, .. } = &self.client_state {
|
||||||
// Broadcast worktrees only if the project is online.
|
// Broadcast worktrees only if the project is online.
|
||||||
let worktrees = self
|
let worktrees = self
|
||||||
.worktrees
|
.worktrees
|
||||||
|
@ -892,7 +777,7 @@ impl Project {
|
||||||
.map(|worktree| worktree.read(cx).as_local().unwrap().metadata_proto())
|
.map(|worktree| worktree.read(cx).as_local().unwrap().metadata_proto())
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
if let Some(project_id) = *remote_id_rx.borrow() {
|
if let Some(project_id) = *remote_id {
|
||||||
self.client
|
self.client
|
||||||
.send(proto::UpdateProject {
|
.send(proto::UpdateProject {
|
||||||
project_id,
|
project_id,
|
||||||
|
@ -1164,28 +1049,22 @@ impl Project {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn share(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
|
pub fn share(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<u64>> {
|
||||||
let project_id;
|
if let ProjectClientState::Local { remote_id, .. } = &mut self.client_state {
|
||||||
if let ProjectClientState::Local {
|
if let Some(remote_id) = remote_id {
|
||||||
remote_id_rx,
|
return Task::ready(Ok(*remote_id));
|
||||||
is_shared,
|
|
||||||
..
|
|
||||||
} = &mut self.client_state
|
|
||||||
{
|
|
||||||
if *is_shared {
|
|
||||||
return Task::ready(Ok(()));
|
|
||||||
}
|
}
|
||||||
*is_shared = true;
|
|
||||||
if let Some(id) = *remote_id_rx.borrow() {
|
|
||||||
project_id = id;
|
|
||||||
} else {
|
|
||||||
return Task::ready(Err(anyhow!("project hasn't been registered")));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return Task::ready(Err(anyhow!("can't share a remote project")));
|
|
||||||
};
|
|
||||||
|
|
||||||
for open_buffer in self.opened_buffers.values_mut() {
|
let response = self.client.request(proto::ShareProject {});
|
||||||
|
cx.spawn(|this, mut cx| async move {
|
||||||
|
let project_id = response.await?.project_id;
|
||||||
|
let mut worktree_share_tasks = Vec::new();
|
||||||
|
this.update(&mut cx, |this, cx| {
|
||||||
|
if let ProjectClientState::Local { remote_id, .. } = &mut this.client_state {
|
||||||
|
*remote_id = Some(project_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
for open_buffer in this.opened_buffers.values_mut() {
|
||||||
match open_buffer {
|
match open_buffer {
|
||||||
OpenBuffer::Strong(_) => {}
|
OpenBuffer::Strong(_) => {}
|
||||||
OpenBuffer::Weak(buffer) => {
|
OpenBuffer::Weak(buffer) => {
|
||||||
|
@ -1197,7 +1076,7 @@ impl Project {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for worktree_handle in self.worktrees.iter_mut() {
|
for worktree_handle in this.worktrees.iter_mut() {
|
||||||
match worktree_handle {
|
match worktree_handle {
|
||||||
WorktreeHandle::Strong(_) => {}
|
WorktreeHandle::Strong(_) => {}
|
||||||
WorktreeHandle::Weak(worktree) => {
|
WorktreeHandle::Weak(worktree) => {
|
||||||
|
@ -1208,16 +1087,15 @@ impl Project {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut tasks = Vec::new();
|
for worktree in this.worktrees(cx).collect::<Vec<_>>() {
|
||||||
for worktree in self.worktrees(cx).collect::<Vec<_>>() {
|
|
||||||
worktree.update(cx, |worktree, cx| {
|
worktree.update(cx, |worktree, cx| {
|
||||||
let worktree = worktree.as_local_mut().unwrap();
|
let worktree = worktree.as_local_mut().unwrap();
|
||||||
tasks.push(worktree.share(project_id, cx));
|
worktree_share_tasks.push(worktree.share(project_id, cx));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
for (server_id, status) in &self.language_server_statuses {
|
for (server_id, status) in &this.language_server_statuses {
|
||||||
self.client
|
this.client
|
||||||
.send(proto::StartLanguageServer {
|
.send(proto::StartLanguageServer {
|
||||||
project_id,
|
project_id,
|
||||||
server: Some(proto::LanguageServer {
|
server: Some(proto::LanguageServer {
|
||||||
|
@ -1228,29 +1106,28 @@ impl Project {
|
||||||
.log_err();
|
.log_err();
|
||||||
}
|
}
|
||||||
|
|
||||||
cx.spawn(|this, mut cx| async move {
|
this.client_subscriptions
|
||||||
for task in tasks {
|
.push(this.client.add_model_for_remote_entity(project_id, cx));
|
||||||
task.await?;
|
this.metadata_changed(cx);
|
||||||
}
|
cx.emit(Event::RemoteIdChanged(Some(project_id)));
|
||||||
this.update(&mut cx, |_, cx| cx.notify());
|
cx.notify();
|
||||||
Ok(())
|
});
|
||||||
|
|
||||||
|
futures::future::try_join_all(worktree_share_tasks).await?;
|
||||||
|
Ok(project_id)
|
||||||
})
|
})
|
||||||
|
} else {
|
||||||
|
Task::ready(Err(anyhow!("can't share a remote project")))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unshare(&mut self, cx: &mut ModelContext<Self>) -> Result<()> {
|
pub fn unshare(&mut self, cx: &mut ModelContext<Self>) -> Result<()> {
|
||||||
if let ProjectClientState::Local {
|
if let ProjectClientState::Local { remote_id, .. } = &mut self.client_state {
|
||||||
is_shared,
|
if let Some(project_id) = remote_id.take() {
|
||||||
remote_id_rx,
|
|
||||||
..
|
|
||||||
} = &mut self.client_state
|
|
||||||
{
|
|
||||||
if !*is_shared {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
*is_shared = false;
|
|
||||||
self.collaborators.clear();
|
self.collaborators.clear();
|
||||||
self.shared_buffers.clear();
|
self.shared_buffers.clear();
|
||||||
|
self.client_subscriptions.clear();
|
||||||
|
|
||||||
for worktree_handle in self.worktrees.iter_mut() {
|
for worktree_handle in self.worktrees.iter_mut() {
|
||||||
if let WorktreeHandle::Strong(worktree) = worktree_handle {
|
if let WorktreeHandle::Strong(worktree) = worktree_handle {
|
||||||
let is_visible = worktree.update(cx, |worktree, _| {
|
let is_visible = worktree.update(cx, |worktree, _| {
|
||||||
|
@ -1269,8 +1146,8 @@ impl Project {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.metadata_changed(cx);
|
||||||
cx.notify();
|
cx.notify();
|
||||||
if let Some(project_id) = *remote_id_rx.borrow() {
|
|
||||||
self.client.send(proto::UnshareProject { project_id })?;
|
self.client.send(proto::UnshareProject { project_id })?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1750,7 +1627,7 @@ impl Project {
|
||||||
) -> Option<()> {
|
) -> Option<()> {
|
||||||
match event {
|
match event {
|
||||||
BufferEvent::Operation(operation) => {
|
BufferEvent::Operation(operation) => {
|
||||||
if let Some(project_id) = self.shared_remote_id() {
|
if let Some(project_id) = self.remote_id() {
|
||||||
let request = self.client.request(proto::UpdateBuffer {
|
let request = self.client.request(proto::UpdateBuffer {
|
||||||
project_id,
|
project_id,
|
||||||
buffer_id: buffer.read(cx).remote_id(),
|
buffer_id: buffer.read(cx).remote_id(),
|
||||||
|
@ -2155,7 +2032,7 @@ impl Project {
|
||||||
)
|
)
|
||||||
.ok();
|
.ok();
|
||||||
|
|
||||||
if let Some(project_id) = this.shared_remote_id() {
|
if let Some(project_id) = this.remote_id() {
|
||||||
this.client
|
this.client
|
||||||
.send(proto::StartLanguageServer {
|
.send(proto::StartLanguageServer {
|
||||||
project_id,
|
project_id,
|
||||||
|
@ -2562,7 +2439,7 @@ impl Project {
|
||||||
language_server_id: usize,
|
language_server_id: usize,
|
||||||
event: proto::update_language_server::Variant,
|
event: proto::update_language_server::Variant,
|
||||||
) {
|
) {
|
||||||
if let Some(project_id) = self.shared_remote_id() {
|
if let Some(project_id) = self.remote_id() {
|
||||||
self.client
|
self.client
|
||||||
.send(proto::UpdateLanguageServer {
|
.send(proto::UpdateLanguageServer {
|
||||||
project_id,
|
project_id,
|
||||||
|
@ -4273,7 +4150,7 @@ impl Project {
|
||||||
|
|
||||||
pub fn is_shared(&self) -> bool {
|
pub fn is_shared(&self) -> bool {
|
||||||
match &self.client_state {
|
match &self.client_state {
|
||||||
ProjectClientState::Local { is_shared, .. } => *is_shared,
|
ProjectClientState::Local { remote_id, .. } => remote_id.is_some(),
|
||||||
ProjectClientState::Remote { .. } => false,
|
ProjectClientState::Remote { .. } => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4310,7 +4187,7 @@ impl Project {
|
||||||
|
|
||||||
let project_id = project.update(&mut cx, |project, cx| {
|
let project_id = project.update(&mut cx, |project, cx| {
|
||||||
project.add_worktree(&worktree, cx);
|
project.add_worktree(&worktree, cx);
|
||||||
project.shared_remote_id()
|
project.remote_id()
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Some(project_id) = project_id {
|
if let Some(project_id) = project_id {
|
||||||
|
@ -4439,7 +4316,7 @@ impl Project {
|
||||||
renamed_buffers.push((cx.handle(), old_path));
|
renamed_buffers.push((cx.handle(), old_path));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(project_id) = self.shared_remote_id() {
|
if let Some(project_id) = self.remote_id() {
|
||||||
self.client
|
self.client
|
||||||
.send(proto::UpdateBufferFile {
|
.send(proto::UpdateBufferFile {
|
||||||
project_id,
|
project_id,
|
||||||
|
@ -4552,16 +4429,6 @@ impl Project {
|
||||||
|
|
||||||
// RPC message handlers
|
// RPC message handlers
|
||||||
|
|
||||||
async fn handle_unregister_project(
|
|
||||||
this: ModelHandle<Self>,
|
|
||||||
_: TypedEnvelope<proto::UnregisterProject>,
|
|
||||||
_: Arc<Client>,
|
|
||||||
mut cx: AsyncAppContext,
|
|
||||||
) -> Result<()> {
|
|
||||||
this.update(&mut cx, |this, cx| this.disconnected_from_host(cx));
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn handle_unshare_project(
|
async fn handle_unshare_project(
|
||||||
this: ModelHandle<Self>,
|
this: ModelHandle<Self>,
|
||||||
_: TypedEnvelope<proto::UnshareProject>,
|
_: TypedEnvelope<proto::UnshareProject>,
|
||||||
|
@ -5987,10 +5854,10 @@ impl Entity for Project {
|
||||||
self.project_store.update(cx, ProjectStore::prune_projects);
|
self.project_store.update(cx, ProjectStore::prune_projects);
|
||||||
|
|
||||||
match &self.client_state {
|
match &self.client_state {
|
||||||
ProjectClientState::Local { remote_id_rx, .. } => {
|
ProjectClientState::Local { remote_id, .. } => {
|
||||||
if let Some(project_id) = *remote_id_rx.borrow() {
|
if let Some(project_id) = *remote_id {
|
||||||
self.client
|
self.client
|
||||||
.send(proto::UnregisterProject { project_id })
|
.send(proto::UnshareProject { project_id })
|
||||||
.log_err();
|
.log_err();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,15 +22,14 @@ message Envelope {
|
||||||
DeclineCall decline_call = 13;
|
DeclineCall decline_call = 13;
|
||||||
RoomUpdated room_updated = 14;
|
RoomUpdated room_updated = 14;
|
||||||
|
|
||||||
RegisterProject register_project = 15;
|
ShareProject share_project = 15;
|
||||||
RegisterProjectResponse register_project_response = 16;
|
ShareProjectResponse share_project_response = 16;
|
||||||
UnregisterProject unregister_project = 17;
|
UnshareProject unshare_project = 17;
|
||||||
JoinProject join_project = 21;
|
JoinProject join_project = 21;
|
||||||
JoinProjectResponse join_project_response = 22;
|
JoinProjectResponse join_project_response = 22;
|
||||||
LeaveProject leave_project = 23;
|
LeaveProject leave_project = 23;
|
||||||
AddProjectCollaborator add_project_collaborator = 24;
|
AddProjectCollaborator add_project_collaborator = 24;
|
||||||
RemoveProjectCollaborator remove_project_collaborator = 25;
|
RemoveProjectCollaborator remove_project_collaborator = 25;
|
||||||
UnshareProject unshare_project = 26;
|
|
||||||
|
|
||||||
GetDefinition get_definition = 27;
|
GetDefinition get_definition = 27;
|
||||||
GetDefinitionResponse get_definition_response = 28;
|
GetDefinitionResponse get_definition_response = 28;
|
||||||
|
@ -195,13 +194,13 @@ message RoomUpdated {
|
||||||
Room room = 1;
|
Room room = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message RegisterProject {}
|
message ShareProject {}
|
||||||
|
|
||||||
message RegisterProjectResponse {
|
message ShareProjectResponse {
|
||||||
uint64 project_id = 1;
|
uint64 project_id = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
message UnregisterProject {
|
message UnshareProject {
|
||||||
uint64 project_id = 1;
|
uint64 project_id = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,10 +284,6 @@ message RemoveProjectCollaborator {
|
||||||
uint32 peer_id = 2;
|
uint32 peer_id = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
message UnshareProject {
|
|
||||||
uint64 project_id = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message GetDefinition {
|
message GetDefinition {
|
||||||
uint64 project_id = 1;
|
uint64 project_id = 1;
|
||||||
uint64 buffer_id = 2;
|
uint64 buffer_id = 2;
|
||||||
|
|
|
@ -141,10 +141,8 @@ messages!(
|
||||||
(PrepareRename, Background),
|
(PrepareRename, Background),
|
||||||
(PrepareRenameResponse, Background),
|
(PrepareRenameResponse, Background),
|
||||||
(ProjectEntryResponse, Foreground),
|
(ProjectEntryResponse, Foreground),
|
||||||
(RegisterProjectResponse, Foreground),
|
|
||||||
(RemoveContact, Foreground),
|
(RemoveContact, Foreground),
|
||||||
(Ping, Foreground),
|
(Ping, Foreground),
|
||||||
(RegisterProject, Foreground),
|
|
||||||
(RegisterProjectActivity, Foreground),
|
(RegisterProjectActivity, Foreground),
|
||||||
(ReloadBuffers, Foreground),
|
(ReloadBuffers, Foreground),
|
||||||
(ReloadBuffersResponse, Foreground),
|
(ReloadBuffersResponse, Foreground),
|
||||||
|
@ -158,11 +156,12 @@ messages!(
|
||||||
(SearchProjectResponse, Background),
|
(SearchProjectResponse, Background),
|
||||||
(SendChannelMessage, Foreground),
|
(SendChannelMessage, Foreground),
|
||||||
(SendChannelMessageResponse, Foreground),
|
(SendChannelMessageResponse, Foreground),
|
||||||
|
(ShareProject, Foreground),
|
||||||
|
(ShareProjectResponse, Foreground),
|
||||||
(ShowContacts, Foreground),
|
(ShowContacts, Foreground),
|
||||||
(StartLanguageServer, Foreground),
|
(StartLanguageServer, Foreground),
|
||||||
(Test, Foreground),
|
(Test, Foreground),
|
||||||
(Unfollow, Foreground),
|
(Unfollow, Foreground),
|
||||||
(UnregisterProject, Foreground),
|
|
||||||
(UnshareProject, Foreground),
|
(UnshareProject, Foreground),
|
||||||
(UpdateBuffer, Foreground),
|
(UpdateBuffer, Foreground),
|
||||||
(UpdateBufferFile, Foreground),
|
(UpdateBufferFile, Foreground),
|
||||||
|
@ -212,7 +211,6 @@ request_messages!(
|
||||||
(Ping, Ack),
|
(Ping, Ack),
|
||||||
(PerformRename, PerformRenameResponse),
|
(PerformRename, PerformRenameResponse),
|
||||||
(PrepareRename, PrepareRenameResponse),
|
(PrepareRename, PrepareRenameResponse),
|
||||||
(RegisterProject, RegisterProjectResponse),
|
|
||||||
(ReloadBuffers, ReloadBuffersResponse),
|
(ReloadBuffers, ReloadBuffersResponse),
|
||||||
(RequestContact, Ack),
|
(RequestContact, Ack),
|
||||||
(RemoveContact, Ack),
|
(RemoveContact, Ack),
|
||||||
|
@ -221,8 +219,8 @@ request_messages!(
|
||||||
(SaveBuffer, BufferSaved),
|
(SaveBuffer, BufferSaved),
|
||||||
(SearchProject, SearchProjectResponse),
|
(SearchProject, SearchProjectResponse),
|
||||||
(SendChannelMessage, SendChannelMessageResponse),
|
(SendChannelMessage, SendChannelMessageResponse),
|
||||||
|
(ShareProject, ShareProjectResponse),
|
||||||
(Test, Test),
|
(Test, Test),
|
||||||
(UnregisterProject, Ack),
|
|
||||||
(UpdateBuffer, Ack),
|
(UpdateBuffer, Ack),
|
||||||
(UpdateWorktree, Ack),
|
(UpdateWorktree, Ack),
|
||||||
);
|
);
|
||||||
|
@ -263,7 +261,6 @@ entity_messages!(
|
||||||
SearchProject,
|
SearchProject,
|
||||||
StartLanguageServer,
|
StartLanguageServer,
|
||||||
Unfollow,
|
Unfollow,
|
||||||
UnregisterProject,
|
|
||||||
UnshareProject,
|
UnshareProject,
|
||||||
UpdateBuffer,
|
UpdateBuffer,
|
||||||
UpdateBufferFile,
|
UpdateBufferFile,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue