diff --git a/Cargo.lock b/Cargo.lock index 503a730064..e88e4f9495 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2272,6 +2272,7 @@ dependencies = [ "collections", "ctor", "dashmap", + "dev_server_projects", "editor", "env_logger", "envy", @@ -2301,7 +2302,6 @@ dependencies = [ "prost", "rand 0.8.5", "release_channel", - "remote_projects", "reqwest", "rpc", "rustc-demangle", @@ -2344,6 +2344,7 @@ dependencies = [ "clock", "collections", "db", + "dev_server_projects", "editor", "emojis", "extensions_ui", @@ -2359,7 +2360,6 @@ dependencies = [ "pretty_assertions", "project", "recent_projects", - "remote_projects", "rich_text", "rpc", "schemars", @@ -3177,6 +3177,18 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "dev_server_projects" +version = "0.1.0" +dependencies = [ + "anyhow", + "client", + "gpui", + "rpc", + "serde", + "serde_json", +] + [[package]] name = "diagnostics" version = "0.1.0" @@ -7793,6 +7805,7 @@ name = "recent_projects" version = "0.1.0" dependencies = [ "anyhow", + "dev_server_projects", "editor", "feature_flags", "fuzzy", @@ -7802,7 +7815,6 @@ dependencies = [ "ordered-float 2.10.0", "picker", "project", - "remote_projects", "rpc", "serde", "serde_json", @@ -7937,18 +7949,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "remote_projects" -version = "0.1.0" -dependencies = [ - "anyhow", - "client", - "gpui", - "rpc", - "serde", - "serde_json", -] - [[package]] name = "rend" version = "0.4.0" @@ -12407,6 +12407,7 @@ dependencies = [ "collections", "db", "derive_more", + "dev_server_projects", "env_logger", "fs", "futures 0.3.28", @@ -12419,7 +12420,6 @@ dependencies = [ "parking_lot", "postage", "project", - "remote_projects", "schemars", "serde", "serde_json", @@ -12682,6 +12682,7 @@ dependencies = [ "copilot", "copilot_ui", "db", + "dev_server_projects", "diagnostics", "editor", "env_logger", @@ -12719,7 +12720,6 @@ dependencies = [ "quick_action_bar", "recent_projects", "release_channel", - "remote_projects", "rope", "search", "serde", diff --git a/Cargo.toml b/Cargo.toml index b2ecb65f67..ca0e5f35bd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -69,7 +69,7 @@ members = [ "crates/refineable", "crates/refineable/derive_refineable", "crates/release_channel", - "crates/remote_projects", + "crates/dev_server_projects", "crates/rich_text", "crates/rope", "crates/rpc", @@ -207,7 +207,7 @@ project_symbols = { path = "crates/project_symbols" } quick_action_bar = { path = "crates/quick_action_bar" } recent_projects = { path = "crates/recent_projects" } release_channel = { path = "crates/release_channel" } -remote_projects = { path = "crates/remote_projects" } +dev_server_projects = { path = "crates/dev_server_projects" } rich_text = { path = "crates/rich_text" } rope = { path = "crates/rope" } rpc = { path = "crates/rpc" } diff --git a/crates/call/src/room.rs b/crates/call/src/room.rs index 22940537d5..61fb694024 100644 --- a/crates/call/src/room.rs +++ b/crates/call/src/room.rs @@ -1203,11 +1203,12 @@ impl Room { project: Model, cx: &mut ModelContext, ) -> Task> { - let request = if let Some(remote_project_id) = project.read(cx).remote_project_id() { + let request = if let Some(dev_server_project_id) = project.read(cx).dev_server_project_id() + { self.client.request(proto::ShareProject { room_id: self.id(), worktrees: vec![], - remote_project_id: Some(remote_project_id.0), + dev_server_project_id: Some(dev_server_project_id.0), }) } else { if let Some(project_id) = project.read(cx).remote_id() { @@ -1217,7 +1218,7 @@ impl Room { self.client.request(proto::ShareProject { room_id: self.id(), worktrees: project.read(cx).worktree_metadata_protos(cx), - remote_project_id: None, + dev_server_project_id: None, }) }; diff --git a/crates/client/src/user.rs b/crates/client/src/user.rs index 5479b73c71..aa28a1cf8e 100644 --- a/crates/client/src/user.rs +++ b/crates/client/src/user.rs @@ -33,7 +33,7 @@ pub struct DevServerId(pub u64); #[derive( Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, serde::Serialize, serde::Deserialize, )] -pub struct RemoteProjectId(pub u64); +pub struct DevServerProjectId(pub u64); #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct ParticipantIndex(pub u32); diff --git a/crates/collab/Cargo.toml b/crates/collab/Cargo.toml index 25692ca690..e8dbcf851a 100644 --- a/crates/collab/Cargo.toml +++ b/crates/collab/Cargo.toml @@ -93,7 +93,7 @@ notifications = { workspace = true, features = ["test-support"] } pretty_assertions.workspace = true project = { workspace = true, features = ["test-support"] } release_channel.workspace = true -remote_projects.workspace = true +dev_server_projects.workspace = true rpc = { workspace = true, features = ["test-support"] } sea-orm = { version = "0.12.x", features = ["sqlx-sqlite"] } serde_json.workspace = true diff --git a/crates/collab/migrations.sqlite/20221109000000_test_schema.sql b/crates/collab/migrations.sqlite/20221109000000_test_schema.sql index c9d064edec..3ce29b039c 100644 --- a/crates/collab/migrations.sqlite/20221109000000_test_schema.sql +++ b/crates/collab/migrations.sqlite/20221109000000_test_schema.sql @@ -51,7 +51,7 @@ CREATE TABLE "projects" ( "host_connection_server_id" INTEGER REFERENCES servers (id) ON DELETE CASCADE, "unregistered" BOOLEAN NOT NULL DEFAULT FALSE, "hosted_project_id" INTEGER REFERENCES hosted_projects (id), - "remote_project_id" INTEGER REFERENCES remote_projects(id) + "dev_server_project_id" INTEGER REFERENCES dev_server_projects(id) ); CREATE INDEX "index_projects_on_host_connection_server_id" ON "projects" ("host_connection_server_id"); CREATE INDEX "index_projects_on_host_connection_id_and_host_connection_server_id" ON "projects" ("host_connection_id", "host_connection_server_id"); @@ -410,10 +410,8 @@ CREATE TABLE dev_servers ( hashed_token TEXT NOT NULL ); -CREATE TABLE remote_projects ( +CREATE TABLE dev_server_projects ( id INTEGER PRIMARY KEY AUTOINCREMENT, dev_server_id INTEGER NOT NULL REFERENCES dev_servers(id), path TEXT NOT NULL ); - -ALTER TABLE hosted_projects ADD COLUMN remote_project_id INTEGER REFERENCES remote_projects(id); diff --git a/crates/collab/migrations/20240502150229_rename_to_dev_server_projects.sql b/crates/collab/migrations/20240502150229_rename_to_dev_server_projects.sql new file mode 100644 index 0000000000..0d8e9de5e6 --- /dev/null +++ b/crates/collab/migrations/20240502150229_rename_to_dev_server_projects.sql @@ -0,0 +1,11 @@ +CREATE TABLE dev_server_projects ( + id INT PRIMARY KEY GENERATED ALWAYS AS IDENTITY (START WITH 100), + dev_server_id INT NOT NULL REFERENCES dev_servers(id) ON DELETE CASCADE, + path TEXT NOT NULL +); +INSERT INTO dev_server_projects OVERRIDING SYSTEM VALUE SELECT * FROM remote_projects; + +ALTER TABLE dev_server_projects ADD CONSTRAINT uix_dev_server_projects_dev_server_id_path UNIQUE(dev_server_id, path); + +ALTER TABLE projects ADD COLUMN dev_server_project_id INTEGER REFERENCES dev_server_projects(id); +UPDATE projects SET dev_server_project_id = remote_project_id; diff --git a/crates/collab/src/db.rs b/crates/collab/src/db.rs index 4a7ae9197a..b2cb5ac90b 100644 --- a/crates/collab/src/db.rs +++ b/crates/collab/src/db.rs @@ -762,7 +762,7 @@ pub struct Project { pub collaborators: Vec, pub worktrees: BTreeMap, pub language_servers: Vec, - pub remote_project_id: Option, + pub dev_server_project_id: Option, } pub struct ProjectCollaborator { diff --git a/crates/collab/src/db/ids.rs b/crates/collab/src/db/ids.rs index 0c2ba2bc13..699189a1bd 100644 --- a/crates/collab/src/db/ids.rs +++ b/crates/collab/src/db/ids.rs @@ -84,7 +84,7 @@ id_type!(NotificationId); id_type!(NotificationKindId); id_type!(ProjectCollaboratorId); id_type!(ProjectId); -id_type!(RemoteProjectId); +id_type!(DevServerProjectId); id_type!(ReplicaId); id_type!(RoomId); id_type!(RoomParticipantId); diff --git a/crates/collab/src/db/queries.rs b/crates/collab/src/db/queries.rs index b7670aa60c..31301a0df8 100644 --- a/crates/collab/src/db/queries.rs +++ b/crates/collab/src/db/queries.rs @@ -5,6 +5,7 @@ pub mod buffers; pub mod channels; pub mod contacts; pub mod contributors; +pub mod dev_server_projects; pub mod dev_servers; pub mod embeddings; pub mod extensions; @@ -13,7 +14,6 @@ pub mod messages; pub mod notifications; pub mod projects; pub mod rate_buckets; -pub mod remote_projects; pub mod rooms; pub mod servers; pub mod users; diff --git a/crates/collab/src/db/queries/dev_server_projects.rs b/crates/collab/src/db/queries/dev_server_projects.rs new file mode 100644 index 0000000000..6a622fd14a --- /dev/null +++ b/crates/collab/src/db/queries/dev_server_projects.rs @@ -0,0 +1,295 @@ +use anyhow::anyhow; +use rpc::{proto, ConnectionId}; +use sea_orm::{ + ActiveModelTrait, ActiveValue, ColumnTrait, Condition, DatabaseTransaction, EntityTrait, + ModelTrait, QueryFilter, +}; + +use crate::db::ProjectId; + +use super::{ + dev_server, dev_server_project, project, project_collaborator, worktree, Database, DevServerId, + DevServerProjectId, RejoinedProject, ResharedProject, ServerId, UserId, +}; + +impl Database { + pub async fn get_dev_server_project( + &self, + dev_server_project_id: DevServerProjectId, + ) -> crate::Result { + self.transaction(|tx| async move { + Ok( + dev_server_project::Entity::find_by_id(dev_server_project_id) + .one(&*tx) + .await? + .ok_or_else(|| { + anyhow!("no dev server project with id {}", dev_server_project_id) + })?, + ) + }) + .await + } + + pub async fn get_projects_for_dev_server( + &self, + dev_server_id: DevServerId, + ) -> crate::Result> { + self.transaction(|tx| async move { + let servers = dev_server_project::Entity::find() + .filter(dev_server_project::Column::DevServerId.eq(dev_server_id)) + .find_also_related(project::Entity) + .all(&*tx) + .await?; + Ok(servers + .into_iter() + .map(|(dev_server_project, project)| proto::DevServerProject { + id: dev_server_project.id.to_proto(), + project_id: project.map(|p| p.id.to_proto()), + dev_server_id: dev_server_project.dev_server_id.to_proto(), + path: dev_server_project.path, + }) + .collect()) + }) + .await + } + + pub async fn dev_server_project_ids_for_user( + &self, + user_id: UserId, + tx: &DatabaseTransaction, + ) -> crate::Result> { + let dev_servers = dev_server::Entity::find() + .filter(dev_server::Column::UserId.eq(user_id)) + .find_with_related(dev_server_project::Entity) + .all(tx) + .await?; + + Ok(dev_servers + .into_iter() + .flat_map(|(_, projects)| projects.into_iter().map(|p| p.id)) + .collect()) + } + + pub async fn owner_for_dev_server_project( + &self, + dev_server_project_id: DevServerProjectId, + tx: &DatabaseTransaction, + ) -> crate::Result { + let dev_server = dev_server_project::Entity::find_by_id(dev_server_project_id) + .find_also_related(dev_server::Entity) + .one(tx) + .await? + .and_then(|(_, dev_server)| dev_server) + .ok_or_else(|| anyhow!("no dev server project"))?; + + Ok(dev_server.user_id) + } + + pub async fn get_stale_dev_server_projects( + &self, + connection: ConnectionId, + ) -> crate::Result> { + self.transaction(|tx| async move { + let projects = project::Entity::find() + .filter( + Condition::all() + .add(project::Column::HostConnectionId.eq(connection.id)) + .add(project::Column::HostConnectionServerId.eq(connection.owner_id)), + ) + .all(&*tx) + .await?; + + Ok(projects.into_iter().map(|p| p.id).collect()) + }) + .await + } + + pub async fn create_dev_server_project( + &self, + dev_server_id: DevServerId, + path: &str, + user_id: UserId, + ) -> crate::Result<(dev_server_project::Model, proto::DevServerProjectsUpdate)> { + self.transaction(|tx| async move { + let dev_server = dev_server::Entity::find_by_id(dev_server_id) + .one(&*tx) + .await? + .ok_or_else(|| anyhow!("no dev server with id {}", dev_server_id))?; + if dev_server.user_id != user_id { + return Err(anyhow!("not your dev server"))?; + } + + let project = dev_server_project::Entity::insert(dev_server_project::ActiveModel { + id: ActiveValue::NotSet, + dev_server_id: ActiveValue::Set(dev_server_id), + path: ActiveValue::Set(path.to_string()), + }) + .exec_with_returning(&*tx) + .await?; + + let status = self + .dev_server_projects_update_internal(user_id, &tx) + .await?; + + Ok((project, status)) + }) + .await + } + + pub async fn share_dev_server_project( + &self, + dev_server_project_id: DevServerProjectId, + dev_server_id: DevServerId, + connection: ConnectionId, + worktrees: &[proto::WorktreeMetadata], + ) -> crate::Result<( + proto::DevServerProject, + UserId, + proto::DevServerProjectsUpdate, + )> { + self.transaction(|tx| async move { + let dev_server = dev_server::Entity::find_by_id(dev_server_id) + .one(&*tx) + .await? + .ok_or_else(|| anyhow!("no dev server with id {}", dev_server_id))?; + + let dev_server_project = dev_server_project::Entity::find_by_id(dev_server_project_id) + .one(&*tx) + .await? + .ok_or_else(|| { + anyhow!("no dev server project with id {}", dev_server_project_id) + })?; + + if dev_server_project.dev_server_id != dev_server_id { + return Err(anyhow!("dev server project shared from wrong server"))?; + } + + let project = project::ActiveModel { + room_id: ActiveValue::Set(None), + host_user_id: ActiveValue::Set(None), + host_connection_id: ActiveValue::set(Some(connection.id as i32)), + host_connection_server_id: ActiveValue::set(Some(ServerId( + connection.owner_id as i32, + ))), + id: ActiveValue::NotSet, + hosted_project_id: ActiveValue::Set(None), + dev_server_project_id: ActiveValue::Set(Some(dev_server_project_id)), + } + .insert(&*tx) + .await?; + + if !worktrees.is_empty() { + worktree::Entity::insert_many(worktrees.iter().map(|worktree| { + worktree::ActiveModel { + id: ActiveValue::set(worktree.id as i64), + project_id: ActiveValue::set(project.id), + abs_path: ActiveValue::set(worktree.abs_path.clone()), + root_name: ActiveValue::set(worktree.root_name.clone()), + visible: ActiveValue::set(worktree.visible), + scan_id: ActiveValue::set(0), + completed_scan_id: ActiveValue::set(0), + } + })) + .exec(&*tx) + .await?; + } + + let status = self + .dev_server_projects_update_internal(dev_server.user_id, &tx) + .await?; + + Ok(( + dev_server_project.to_proto(Some(project)), + dev_server.user_id, + status, + )) + }) + .await + } + + pub async fn reshare_dev_server_projects( + &self, + reshared_projects: &Vec, + dev_server_id: DevServerId, + connection: ConnectionId, + ) -> crate::Result> { + // todo!() project_transaction? (maybe we can make the lock per-dev-server instead of per-project?) + self.transaction(|tx| async move { + let mut ret = Vec::new(); + for reshared_project in reshared_projects { + let project_id = ProjectId::from_proto(reshared_project.project_id); + let (project, dev_server_project) = project::Entity::find_by_id(project_id) + .find_also_related(dev_server_project::Entity) + .one(&*tx) + .await? + .ok_or_else(|| anyhow!("project does not exist"))?; + + if dev_server_project.map(|rp| rp.dev_server_id) != Some(dev_server_id) { + return Err(anyhow!("dev server project reshared from wrong server"))?; + } + + let Ok(old_connection_id) = project.host_connection() else { + return Err(anyhow!("dev server project was not shared"))?; + }; + + project::Entity::update(project::ActiveModel { + id: ActiveValue::set(project_id), + host_connection_id: ActiveValue::set(Some(connection.id as i32)), + host_connection_server_id: ActiveValue::set(Some(ServerId( + connection.owner_id as i32, + ))), + ..Default::default() + }) + .exec(&*tx) + .await?; + + let collaborators = project + .find_related(project_collaborator::Entity) + .all(&*tx) + .await?; + + self.update_project_worktrees(project_id, &reshared_project.worktrees, &tx) + .await?; + + ret.push(super::ResharedProject { + id: project_id, + old_connection_id, + collaborators: collaborators + .iter() + .map(|collaborator| super::ProjectCollaborator { + connection_id: collaborator.connection(), + user_id: collaborator.user_id, + replica_id: collaborator.replica_id, + is_host: collaborator.is_host, + }) + .collect(), + worktrees: reshared_project.worktrees.clone(), + }); + } + Ok(ret) + }) + .await + } + + pub async fn rejoin_dev_server_projects( + &self, + rejoined_projects: &Vec, + user_id: UserId, + connection_id: ConnectionId, + ) -> crate::Result> { + // todo!() project_transaction? (maybe we can make the lock per-dev-server instead of per-project?) + self.transaction(|tx| async move { + let mut ret = Vec::new(); + for rejoined_project in rejoined_projects { + if let Some(project) = self + .rejoin_project_internal(&tx, rejoined_project, user_id, connection_id) + .await? + { + ret.push(project); + } + } + Ok(ret) + }) + .await + } +} diff --git a/crates/collab/src/db/queries/dev_servers.rs b/crates/collab/src/db/queries/dev_servers.rs index ceb7d905da..90baaee476 100644 --- a/crates/collab/src/db/queries/dev_servers.rs +++ b/crates/collab/src/db/queries/dev_servers.rs @@ -3,7 +3,7 @@ use sea_orm::{ ActiveValue, ColumnTrait, DatabaseTransaction, EntityTrait, IntoActiveModel, QueryFilter, }; -use super::{dev_server, remote_project, Database, DevServerId, UserId}; +use super::{dev_server, dev_server_project, Database, DevServerId, UserId}; impl Database { pub async fn get_dev_server( @@ -29,43 +29,43 @@ impl Database { .await } - pub async fn remote_projects_update( + pub async fn dev_server_projects_update( &self, user_id: UserId, - ) -> crate::Result { - self.transaction( - |tx| async move { self.remote_projects_update_internal(user_id, &tx).await }, - ) + ) -> crate::Result { + self.transaction(|tx| async move { + self.dev_server_projects_update_internal(user_id, &tx).await + }) .await } - pub async fn remote_projects_update_internal( + pub async fn dev_server_projects_update_internal( &self, user_id: UserId, tx: &DatabaseTransaction, - ) -> crate::Result { + ) -> crate::Result { let dev_servers = dev_server::Entity::find() .filter(dev_server::Column::UserId.eq(user_id)) .all(tx) .await?; - let remote_projects = remote_project::Entity::find() + let dev_server_projects = dev_server_project::Entity::find() .filter( - remote_project::Column::DevServerId + dev_server_project::Column::DevServerId .is_in(dev_servers.iter().map(|d| d.id).collect::>()), ) .find_also_related(super::project::Entity) .all(tx) .await?; - Ok(proto::RemoteProjectsUpdate { + Ok(proto::DevServerProjectsUpdate { dev_servers: dev_servers .into_iter() .map(|d| d.to_proto(proto::DevServerStatus::Offline)) .collect(), - remote_projects: remote_projects + dev_server_projects: dev_server_projects .into_iter() - .map(|(remote_project, project)| remote_project.to_proto(project)) + .map(|(dev_server_project, project)| dev_server_project.to_proto(project)) .collect(), }) } @@ -75,7 +75,7 @@ impl Database { name: &str, hashed_access_token: &str, user_id: UserId, - ) -> crate::Result<(dev_server::Model, proto::RemoteProjectsUpdate)> { + ) -> crate::Result<(dev_server::Model, proto::DevServerProjectsUpdate)> { self.transaction(|tx| async move { let dev_server = dev_server::Entity::insert(dev_server::ActiveModel { id: ActiveValue::NotSet, @@ -86,9 +86,11 @@ impl Database { .exec_with_returning(&*tx) .await?; - let remote_projects = self.remote_projects_update_internal(user_id, &tx).await?; + let dev_server_projects = self + .dev_server_projects_update_internal(user_id, &tx) + .await?; - Ok((dev_server, remote_projects)) + Ok((dev_server, dev_server_projects)) }) .await } @@ -97,7 +99,7 @@ impl Database { &self, id: DevServerId, user_id: UserId, - ) -> crate::Result { + ) -> crate::Result { self.transaction(|tx| async move { let Some(dev_server) = dev_server::Entity::find_by_id(id).one(&*tx).await? else { return Err(anyhow::anyhow!("no dev server with id {}", id))?; @@ -106,8 +108,8 @@ impl Database { return Err(anyhow::anyhow!(proto::ErrorCode::Forbidden))?; } - remote_project::Entity::delete_many() - .filter(remote_project::Column::DevServerId.eq(id)) + dev_server_project::Entity::delete_many() + .filter(dev_server_project::Column::DevServerId.eq(id)) .exec(&*tx) .await?; @@ -115,9 +117,11 @@ impl Database { .exec(&*tx) .await?; - let remote_projects = self.remote_projects_update_internal(user_id, &tx).await?; + let dev_server_projects = self + .dev_server_projects_update_internal(user_id, &tx) + .await?; - Ok(remote_projects) + Ok(dev_server_projects) }) .await } diff --git a/crates/collab/src/db/queries/projects.rs b/crates/collab/src/db/queries/projects.rs index 94a083698c..5742fdd56b 100644 --- a/crates/collab/src/db/queries/projects.rs +++ b/crates/collab/src/db/queries/projects.rs @@ -30,7 +30,7 @@ impl Database { room_id: RoomId, connection: ConnectionId, worktrees: &[proto::WorktreeMetadata], - remote_project_id: Option, + dev_server_project_id: Option, ) -> Result> { self.room_transaction(room_id, |tx| async move { let participant = room_participant::Entity::find() @@ -59,9 +59,9 @@ impl Database { return Err(anyhow!("guests cannot share projects"))?; } - if let Some(remote_project_id) = remote_project_id { + if let Some(dev_server_project_id) = dev_server_project_id { let project = project::Entity::find() - .filter(project::Column::RemoteProjectId.eq(Some(remote_project_id))) + .filter(project::Column::DevServerProjectId.eq(Some(dev_server_project_id))) .one(&*tx) .await? .ok_or_else(|| anyhow!("no remote project"))?; @@ -92,7 +92,7 @@ impl Database { ))), id: ActiveValue::NotSet, hosted_project_id: ActiveValue::Set(None), - remote_project_id: ActiveValue::Set(None), + dev_server_project_id: ActiveValue::Set(None), } .insert(&*tx) .await?; @@ -155,11 +155,11 @@ impl Database { .await?; return Ok((room, guest_connection_ids)); } - if let Some(remote_project_id) = project.remote_project_id { + if let Some(dev_server_project_id) = project.dev_server_project_id { if let Some(user_id) = user_id { if user_id != self - .owner_for_remote_project(remote_project_id, &tx) + .owner_for_dev_server_project(dev_server_project_id, &tx) .await? { Err(anyhow!("cannot unshare a project hosted by another user"))? @@ -797,7 +797,7 @@ impl Database { name: language_server.name, }) .collect(), - remote_project_id: project.remote_project_id, + dev_server_project_id: project.dev_server_project_id, }; Ok((project, replica_id as ReplicaId)) } @@ -957,8 +957,8 @@ impl Database { capability: Capability, tx: &DatabaseTransaction, ) -> Result<(project::Model, ChannelRole)> { - let (mut project, remote_project) = project::Entity::find_by_id(project_id) - .find_also_related(remote_project::Entity) + let (mut project, dev_server_project) = project::Entity::find_by_id(project_id) + .find_also_related(dev_server_project::Entity) .one(tx) .await? .ok_or_else(|| anyhow!("no such project"))?; @@ -986,8 +986,8 @@ impl Database { } else { None }; - let role_from_remote_project = if let Some(remote_project) = remote_project { - let dev_server = dev_server::Entity::find_by_id(remote_project.dev_server_id) + let role_from_dev_server = if let Some(dev_server_project) = dev_server_project { + let dev_server = dev_server::Entity::find_by_id(dev_server_project.dev_server_id) .one(tx) .await? .ok_or_else(|| anyhow!("no such channel"))?; @@ -1011,7 +1011,7 @@ impl Database { None }; - let role = role_from_remote_project + let role = role_from_dev_server .or(role_from_room) .unwrap_or(ChannelRole::Banned); diff --git a/crates/collab/src/db/queries/remote_projects.rs b/crates/collab/src/db/queries/remote_projects.rs index 9baf9ad0c8..8b13789179 100644 --- a/crates/collab/src/db/queries/remote_projects.rs +++ b/crates/collab/src/db/queries/remote_projects.rs @@ -1,283 +1 @@ -use anyhow::anyhow; -use rpc::{proto, ConnectionId}; -use sea_orm::{ - ActiveModelTrait, ActiveValue, ColumnTrait, Condition, DatabaseTransaction, EntityTrait, - ModelTrait, QueryFilter, -}; -use crate::db::ProjectId; - -use super::{ - dev_server, project, project_collaborator, remote_project, worktree, Database, DevServerId, - RejoinedProject, RemoteProjectId, ResharedProject, ServerId, UserId, -}; - -impl Database { - pub async fn get_remote_project( - &self, - remote_project_id: RemoteProjectId, - ) -> crate::Result { - self.transaction(|tx| async move { - Ok(remote_project::Entity::find_by_id(remote_project_id) - .one(&*tx) - .await? - .ok_or_else(|| anyhow!("no remote project with id {}", remote_project_id))?) - }) - .await - } - - pub async fn get_remote_projects_for_dev_server( - &self, - dev_server_id: DevServerId, - ) -> crate::Result> { - self.transaction(|tx| async move { - let servers = remote_project::Entity::find() - .filter(remote_project::Column::DevServerId.eq(dev_server_id)) - .find_also_related(project::Entity) - .all(&*tx) - .await?; - Ok(servers - .into_iter() - .map(|(remote_project, project)| proto::RemoteProject { - id: remote_project.id.to_proto(), - project_id: project.map(|p| p.id.to_proto()), - dev_server_id: remote_project.dev_server_id.to_proto(), - path: remote_project.path, - }) - .collect()) - }) - .await - } - - pub async fn remote_project_ids_for_user( - &self, - user_id: UserId, - tx: &DatabaseTransaction, - ) -> crate::Result> { - let dev_servers = dev_server::Entity::find() - .filter(dev_server::Column::UserId.eq(user_id)) - .find_with_related(remote_project::Entity) - .all(tx) - .await?; - - Ok(dev_servers - .into_iter() - .flat_map(|(_, projects)| projects.into_iter().map(|p| p.id)) - .collect()) - } - - pub async fn owner_for_remote_project( - &self, - remote_project_id: RemoteProjectId, - tx: &DatabaseTransaction, - ) -> crate::Result { - let dev_server = remote_project::Entity::find_by_id(remote_project_id) - .find_also_related(dev_server::Entity) - .one(tx) - .await? - .and_then(|(_, dev_server)| dev_server) - .ok_or_else(|| anyhow!("no remote project"))?; - - Ok(dev_server.user_id) - } - - pub async fn get_stale_dev_server_projects( - &self, - connection: ConnectionId, - ) -> crate::Result> { - self.transaction(|tx| async move { - let projects = project::Entity::find() - .filter( - Condition::all() - .add(project::Column::HostConnectionId.eq(connection.id)) - .add(project::Column::HostConnectionServerId.eq(connection.owner_id)), - ) - .all(&*tx) - .await?; - - Ok(projects.into_iter().map(|p| p.id).collect()) - }) - .await - } - - pub async fn create_remote_project( - &self, - dev_server_id: DevServerId, - path: &str, - user_id: UserId, - ) -> crate::Result<(remote_project::Model, proto::RemoteProjectsUpdate)> { - self.transaction(|tx| async move { - let dev_server = dev_server::Entity::find_by_id(dev_server_id) - .one(&*tx) - .await? - .ok_or_else(|| anyhow!("no dev server with id {}", dev_server_id))?; - if dev_server.user_id != user_id { - return Err(anyhow!("not your dev server"))?; - } - - let project = remote_project::Entity::insert(remote_project::ActiveModel { - id: ActiveValue::NotSet, - dev_server_id: ActiveValue::Set(dev_server_id), - path: ActiveValue::Set(path.to_string()), - }) - .exec_with_returning(&*tx) - .await?; - - let status = self.remote_projects_update_internal(user_id, &tx).await?; - - Ok((project, status)) - }) - .await - } - - pub async fn share_remote_project( - &self, - remote_project_id: RemoteProjectId, - dev_server_id: DevServerId, - connection: ConnectionId, - worktrees: &[proto::WorktreeMetadata], - ) -> crate::Result<(proto::RemoteProject, UserId, proto::RemoteProjectsUpdate)> { - self.transaction(|tx| async move { - let dev_server = dev_server::Entity::find_by_id(dev_server_id) - .one(&*tx) - .await? - .ok_or_else(|| anyhow!("no dev server with id {}", dev_server_id))?; - - let remote_project = remote_project::Entity::find_by_id(remote_project_id) - .one(&*tx) - .await? - .ok_or_else(|| anyhow!("no remote project with id {}", remote_project_id))?; - - if remote_project.dev_server_id != dev_server_id { - return Err(anyhow!("remote project shared from wrong server"))?; - } - - let project = project::ActiveModel { - room_id: ActiveValue::Set(None), - host_user_id: ActiveValue::Set(None), - host_connection_id: ActiveValue::set(Some(connection.id as i32)), - host_connection_server_id: ActiveValue::set(Some(ServerId( - connection.owner_id as i32, - ))), - id: ActiveValue::NotSet, - hosted_project_id: ActiveValue::Set(None), - remote_project_id: ActiveValue::Set(Some(remote_project_id)), - } - .insert(&*tx) - .await?; - - if !worktrees.is_empty() { - worktree::Entity::insert_many(worktrees.iter().map(|worktree| { - worktree::ActiveModel { - id: ActiveValue::set(worktree.id as i64), - project_id: ActiveValue::set(project.id), - abs_path: ActiveValue::set(worktree.abs_path.clone()), - root_name: ActiveValue::set(worktree.root_name.clone()), - visible: ActiveValue::set(worktree.visible), - scan_id: ActiveValue::set(0), - completed_scan_id: ActiveValue::set(0), - } - })) - .exec(&*tx) - .await?; - } - - let status = self - .remote_projects_update_internal(dev_server.user_id, &tx) - .await?; - - Ok(( - remote_project.to_proto(Some(project)), - dev_server.user_id, - status, - )) - }) - .await - } - - pub async fn reshare_remote_projects( - &self, - reshared_projects: &Vec, - dev_server_id: DevServerId, - connection: ConnectionId, - ) -> crate::Result> { - // todo!() project_transaction? (maybe we can make the lock per-dev-server instead of per-project?) - self.transaction(|tx| async move { - let mut ret = Vec::new(); - for reshared_project in reshared_projects { - let project_id = ProjectId::from_proto(reshared_project.project_id); - let (project, remote_project) = project::Entity::find_by_id(project_id) - .find_also_related(remote_project::Entity) - .one(&*tx) - .await? - .ok_or_else(|| anyhow!("project does not exist"))?; - - if remote_project.map(|rp| rp.dev_server_id) != Some(dev_server_id) { - return Err(anyhow!("remote project reshared from wrong server"))?; - } - - let Ok(old_connection_id) = project.host_connection() else { - return Err(anyhow!("remote project was not shared"))?; - }; - - project::Entity::update(project::ActiveModel { - id: ActiveValue::set(project_id), - host_connection_id: ActiveValue::set(Some(connection.id as i32)), - host_connection_server_id: ActiveValue::set(Some(ServerId( - connection.owner_id as i32, - ))), - ..Default::default() - }) - .exec(&*tx) - .await?; - - let collaborators = project - .find_related(project_collaborator::Entity) - .all(&*tx) - .await?; - - self.update_project_worktrees(project_id, &reshared_project.worktrees, &tx) - .await?; - - ret.push(super::ResharedProject { - id: project_id, - old_connection_id, - collaborators: collaborators - .iter() - .map(|collaborator| super::ProjectCollaborator { - connection_id: collaborator.connection(), - user_id: collaborator.user_id, - replica_id: collaborator.replica_id, - is_host: collaborator.is_host, - }) - .collect(), - worktrees: reshared_project.worktrees.clone(), - }); - } - Ok(ret) - }) - .await - } - - pub async fn rejoin_remote_projects( - &self, - rejoined_projects: &Vec, - user_id: UserId, - connection_id: ConnectionId, - ) -> crate::Result> { - // todo!() project_transaction? (maybe we can make the lock per-dev-server instead of per-project?) - self.transaction(|tx| async move { - let mut ret = Vec::new(); - for rejoined_project in rejoined_projects { - if let Some(project) = self - .rejoin_project_internal(&tx, rejoined_project, user_id, connection_id) - .await? - { - ret.push(project); - } - } - Ok(ret) - }) - .await - } -} diff --git a/crates/collab/src/db/queries/rooms.rs b/crates/collab/src/db/queries/rooms.rs index 9cd22666eb..185bcf7b36 100644 --- a/crates/collab/src/db/queries/rooms.rs +++ b/crates/collab/src/db/queries/rooms.rs @@ -851,17 +851,17 @@ impl Database { .await?; // if any project in the room has a remote-project-id that belongs to a dev server that this user owns. - let remote_projects_for_user = self - .remote_project_ids_for_user(leaving_participant.user_id, &tx) + let dev_server_projects_for_user = self + .dev_server_project_ids_for_user(leaving_participant.user_id, &tx) .await?; - let remote_projects_to_unshare = project::Entity::find() + let dev_server_projects_to_unshare = project::Entity::find() .filter( Condition::all() .add(project::Column::RoomId.eq(room_id)) .add( - project::Column::RemoteProjectId - .is_in(remote_projects_for_user.clone()), + project::Column::DevServerProjectId + .is_in(dev_server_projects_for_user.clone()), ), ) .all(&*tx) @@ -892,7 +892,7 @@ impl Database { } if (collaborator.is_host && collaborator.connection() == connection) - || remote_projects_to_unshare.contains(&collaborator.project_id) + || dev_server_projects_to_unshare.contains(&collaborator.project_id) { left_project.should_unshare = true; } @@ -936,9 +936,9 @@ impl Database { .exec(&*tx) .await?; - if !remote_projects_to_unshare.is_empty() { + if !dev_server_projects_to_unshare.is_empty() { project::Entity::update_many() - .filter(project::Column::Id.is_in(remote_projects_to_unshare)) + .filter(project::Column::Id.is_in(dev_server_projects_to_unshare)) .set(project::ActiveModel { room_id: ActiveValue::Set(None), ..Default::default() @@ -1316,8 +1316,10 @@ impl Database { project.worktree_root_names.push(db_worktree.root_name); } } - } else if let Some(remote_project_id) = db_project.remote_project_id { - let host = self.owner_for_remote_project(remote_project_id, tx).await?; + } else if let Some(dev_server_project_id) = db_project.dev_server_project_id { + let host = self + .owner_for_dev_server_project(dev_server_project_id, tx) + .await?; if let Some((_, participant)) = participants .iter_mut() .find(|(_, v)| v.user_id == host.to_proto()) diff --git a/crates/collab/src/db/tables.rs b/crates/collab/src/db/tables.rs index 2af78f776e..b9a3c5d9d8 100644 --- a/crates/collab/src/db/tables.rs +++ b/crates/collab/src/db/tables.rs @@ -11,6 +11,7 @@ pub mod channel_message_mention; pub mod contact; pub mod contributor; pub mod dev_server; +pub mod dev_server_project; pub mod embedding; pub mod extension; pub mod extension_version; @@ -25,7 +26,6 @@ pub mod observed_channel_messages; pub mod project; pub mod project_collaborator; pub mod rate_buckets; -pub mod remote_project; pub mod room; pub mod room_participant; pub mod server; diff --git a/crates/collab/src/db/tables/dev_server.rs b/crates/collab/src/db/tables/dev_server.rs index 053db808a4..33f99631a3 100644 --- a/crates/collab/src/db/tables/dev_server.rs +++ b/crates/collab/src/db/tables/dev_server.rs @@ -16,11 +16,11 @@ impl ActiveModelBehavior for ActiveModel {} #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] pub enum Relation { - #[sea_orm(has_many = "super::remote_project::Entity")] + #[sea_orm(has_many = "super::dev_server_project::Entity")] RemoteProject, } -impl Related for Entity { +impl Related for Entity { fn to() -> RelationDef { Relation::RemoteProject.def() } diff --git a/crates/collab/src/db/tables/remote_project.rs b/crates/collab/src/db/tables/dev_server_project.rs similarity index 85% rename from crates/collab/src/db/tables/remote_project.rs rename to crates/collab/src/db/tables/dev_server_project.rs index a3c2b25725..bf90d7092d 100644 --- a/crates/collab/src/db/tables/remote_project.rs +++ b/crates/collab/src/db/tables/dev_server_project.rs @@ -1,13 +1,13 @@ use super::project; -use crate::db::{DevServerId, RemoteProjectId}; +use crate::db::{DevServerId, DevServerProjectId}; use rpc::proto; use sea_orm::entity::prelude::*; #[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)] -#[sea_orm(table_name = "remote_projects")] +#[sea_orm(table_name = "dev_server_projects")] pub struct Model { #[sea_orm(primary_key)] - pub id: RemoteProjectId, + pub id: DevServerProjectId, pub dev_server_id: DevServerId, pub path: String, } @@ -39,8 +39,8 @@ impl Related for Entity { } impl Model { - pub fn to_proto(&self, project: Option) -> proto::RemoteProject { - proto::RemoteProject { + pub fn to_proto(&self, project: Option) -> proto::DevServerProject { + proto::DevServerProject { id: self.id.to_proto(), project_id: project.map(|p| p.id.to_proto()), dev_server_id: self.dev_server_id.to_proto(), diff --git a/crates/collab/src/db/tables/project.rs b/crates/collab/src/db/tables/project.rs index bfb0b17c9a..6858af0237 100644 --- a/crates/collab/src/db/tables/project.rs +++ b/crates/collab/src/db/tables/project.rs @@ -1,4 +1,4 @@ -use crate::db::{HostedProjectId, ProjectId, RemoteProjectId, Result, RoomId, ServerId, UserId}; +use crate::db::{DevServerProjectId, HostedProjectId, ProjectId, Result, RoomId, ServerId, UserId}; use anyhow::anyhow; use rpc::ConnectionId; use sea_orm::entity::prelude::*; @@ -13,7 +13,7 @@ pub struct Model { pub host_connection_id: Option, pub host_connection_server_id: Option, pub hosted_project_id: Option, - pub remote_project_id: Option, + pub dev_server_project_id: Option, } impl Model { @@ -58,9 +58,9 @@ pub enum Relation { )] HostedProject, #[sea_orm( - belongs_to = "super::remote_project::Entity", - from = "Column::RemoteProjectId", - to = "super::remote_project::Column::Id" + belongs_to = "super::dev_server_project::Entity", + from = "Column::DevServerProjectId", + to = "super::dev_server_project::Column::Id" )] RemoteProject, } @@ -101,7 +101,7 @@ impl Related for Entity { } } -impl Related for Entity { +impl Related for Entity { fn to() -> RelationDef { Relation::RemoteProject.def() } diff --git a/crates/collab/src/rpc.rs b/crates/collab/src/rpc.rs index 0ac45051f2..9aa5d9bdbc 100644 --- a/crates/collab/src/rpc.rs +++ b/crates/collab/src/rpc.rs @@ -4,9 +4,9 @@ use crate::{ auth, db::{ self, dev_server, BufferId, Capability, Channel, ChannelId, ChannelRole, ChannelsForUser, - CreatedChannelMessage, Database, DevServerId, InviteMemberResult, MembershipUpdated, - MessageId, NotificationId, PrincipalId, Project, ProjectId, RejoinedProject, - RemoteProjectId, RemoveChannelMemberResult, ReplicaId, RespondToChannelInvite, RoomId, + CreatedChannelMessage, Database, DevServerId, DevServerProjectId, InviteMemberResult, + MembershipUpdated, MessageId, NotificationId, PrincipalId, Project, ProjectId, + RejoinedProject, RemoveChannelMemberResult, ReplicaId, RespondToChannelInvite, RoomId, ServerId, UpdatedChannelMessage, User, UserId, }, executor::Executor, @@ -411,11 +411,11 @@ impl Server { .add_message_handler(unshare_project) .add_request_handler(user_handler(join_project)) .add_request_handler(user_handler(join_hosted_project)) - .add_request_handler(user_handler(rejoin_remote_projects)) - .add_request_handler(user_handler(create_remote_project)) + .add_request_handler(user_handler(rejoin_dev_server_projects)) + .add_request_handler(user_handler(create_dev_server_project)) .add_request_handler(user_handler(create_dev_server)) .add_request_handler(user_handler(delete_dev_server)) - .add_request_handler(dev_server_handler(share_remote_project)) + .add_request_handler(dev_server_handler(share_dev_server_project)) .add_request_handler(dev_server_handler(shutdown_dev_server)) .add_request_handler(dev_server_handler(reconnect_dev_server)) .add_message_handler(user_message_handler(leave_project)) @@ -1067,12 +1067,12 @@ impl Server { .await?; } - let (contacts, channels_for_user, channel_invites, remote_projects) = + let (contacts, channels_for_user, channel_invites, dev_server_projects) = future::try_join4( self.app_state.db.get_contacts(user.id), self.app_state.db.get_channels_for_user(user.id), self.app_state.db.get_channel_invites_for_user(user.id), - self.app_state.db.remote_projects_update(user.id), + self.app_state.db.dev_server_projects_update(user.id), ) .await?; @@ -1095,7 +1095,7 @@ impl Server { build_channels_update(channels_for_user, channel_invites), )?; } - send_remote_projects_update(user.id, remote_projects, session).await; + send_dev_server_projects_update(user.id, dev_server_projects, session).await; if let Some(incoming_call) = self.app_state.db.incoming_call_for_user(user.id).await? @@ -1117,7 +1117,7 @@ impl Server { let projects = self .app_state .db - .get_remote_projects_for_dev_server(dev_server.id) + .get_projects_for_dev_server(dev_server.id) .await?; self.peer .send(connection_id, proto::DevServerInstructions { projects })?; @@ -1125,9 +1125,9 @@ impl Server { let status = self .app_state .db - .remote_projects_update(dev_server.user_id) + .dev_server_projects_update(dev_server.user_id) .await?; - send_remote_projects_update(dev_server.user_id, status, &session).await; + send_dev_server_projects_update(dev_server.user_id, status, &session).await; } } @@ -1970,8 +1970,8 @@ async fn share_project( session.connection_id, &request.worktrees, request - .remote_project_id - .map(|id| RemoteProjectId::from_proto(id)), + .dev_server_project_id + .map(|id| DevServerProjectId::from_proto(id)), ) .await?; response.send(proto::ShareProjectResponse { @@ -2023,26 +2023,26 @@ async fn unshare_project_internal( } /// DevServer makes a project available online -async fn share_remote_project( - request: proto::ShareRemoteProject, - response: Response, +async fn share_dev_server_project( + request: proto::ShareDevServerProject, + response: Response, session: DevServerSession, ) -> Result<()> { - let (remote_project, user_id, status) = session + let (dev_server_project, user_id, status) = session .db() .await - .share_remote_project( - RemoteProjectId::from_proto(request.remote_project_id), + .share_dev_server_project( + DevServerProjectId::from_proto(request.dev_server_project_id), session.dev_server_id(), session.connection_id, &request.worktrees, ) .await?; - let Some(project_id) = remote_project.project_id else { + let Some(project_id) = dev_server_project.project_id else { return Err(anyhow!("failed to share remote project"))?; }; - send_remote_projects_update(user_id, status, &session).await; + send_dev_server_projects_update(user_id, status, &session).await; response.send(proto::ShareProjectResponse { project_id })?; @@ -2135,9 +2135,9 @@ fn join_project_internal( collaborators: collaborators.clone(), language_servers: project.language_servers.clone(), role: project.role.into(), - remote_project_id: project - .remote_project_id - .map(|remote_project_id| remote_project_id.0 as u64), + dev_server_project_id: project + .dev_server_project_id + .map(|dev_server_project_id| dev_server_project_id.0 as u64), })?; for (worktree_id, worktree) in mem::take(&mut project.worktrees) { @@ -2249,9 +2249,9 @@ async fn join_hosted_project( join_project_internal(response, session, &mut project, &replica_id) } -async fn create_remote_project( - request: proto::CreateRemoteProject, - response: Response, +async fn create_dev_server_project( + request: proto::CreateDevServerProject, + response: Response, session: UserSession, ) -> Result<()> { let dev_server_id = DevServerId(request.dev_server_id as i32); @@ -2272,14 +2272,14 @@ async fn create_remote_project( .forward_request( session.connection_id, dev_server_connection_id, - proto::ValidateRemoteProjectRequest { path: path.clone() }, + proto::ValidateDevServerProjectRequest { path: path.clone() }, ) .await?; - let (remote_project, update) = session + let (dev_server_project, update) = session .db() .await - .create_remote_project( + .create_dev_server_project( DevServerId(request.dev_server_id as i32), &request.path, session.user_id(), @@ -2289,7 +2289,7 @@ async fn create_remote_project( let projects = session .db() .await - .get_remote_projects_for_dev_server(remote_project.dev_server_id) + .get_projects_for_dev_server(dev_server_project.dev_server_id) .await?; session.peer.send( @@ -2297,10 +2297,10 @@ async fn create_remote_project( proto::DevServerInstructions { projects }, )?; - send_remote_projects_update(session.user_id(), update, &session).await; + send_dev_server_projects_update(session.user_id(), update, &session).await; - response.send(proto::CreateRemoteProjectResponse { - remote_project: Some(remote_project.to_proto(None)), + response.send(proto::CreateDevServerProjectResponse { + dev_server_project: Some(dev_server_project.to_proto(None)), })?; Ok(()) } @@ -2319,7 +2319,7 @@ async fn create_dev_server( .create_dev_server(&request.name, &hashed_access_token, session.user_id()) .await?; - send_remote_projects_update(session.user_id(), status, &session).await; + send_dev_server_projects_update(session.user_id(), status, &session).await; response.send(proto::CreateDevServerResponse { dev_server_id: dev_server.id.0 as u64, @@ -2357,20 +2357,20 @@ async fn delete_dev_server( .delete_dev_server(dev_server_id, session.user_id()) .await?; - send_remote_projects_update(session.user_id(), status, &session).await; + send_dev_server_projects_update(session.user_id(), status, &session).await; response.send(proto::Ack {})?; Ok(()) } -async fn rejoin_remote_projects( +async fn rejoin_dev_server_projects( request: proto::RejoinRemoteProjects, response: Response, session: UserSession, ) -> Result<()> { let mut rejoined_projects = { let db = session.db().await; - db.rejoin_remote_projects( + db.rejoin_dev_server_projects( &request.rejoined_projects, session.user_id(), session.0.connection_id, @@ -2394,7 +2394,7 @@ async fn reconnect_dev_server( ) -> Result<()> { let reshared_projects = { let db = session.db().await; - db.reshare_remote_projects( + db.reshare_dev_server_projects( &request.reshared_projects, session.dev_server_id(), session.0.connection_id, @@ -2467,14 +2467,14 @@ async fn shutdown_dev_server_internal( connection_id: ConnectionId, session: &Session, ) -> Result<()> { - let (remote_projects, dev_server) = { + let (dev_server_projects, dev_server) = { let db = session.db().await; - let remote_projects = db.get_remote_projects_for_dev_server(dev_server_id).await?; + let dev_server_projects = db.get_projects_for_dev_server(dev_server_id).await?; let dev_server = db.get_dev_server(dev_server_id).await?; - (remote_projects, dev_server) + (dev_server_projects, dev_server) }; - for project_id in remote_projects.iter().filter_map(|p| p.project_id) { + for project_id in dev_server_projects.iter().filter_map(|p| p.project_id) { unshare_project_internal( ProjectId::from_proto(project_id), connection_id, @@ -2492,9 +2492,9 @@ async fn shutdown_dev_server_internal( let status = session .db() .await - .remote_projects_update(dev_server.user_id) + .dev_server_projects_update(dev_server.user_id) .await?; - send_remote_projects_update(dev_server.user_id, status, &session).await; + send_dev_server_projects_update(dev_server.user_id, status, &session).await; Ok(()) } @@ -4908,9 +4908,9 @@ fn channel_updated( ); } -async fn send_remote_projects_update( +async fn send_dev_server_projects_update( user_id: UserId, - mut status: proto::RemoteProjectsUpdate, + mut status: proto::DevServerProjectsUpdate, session: &Session, ) { let pool = session.connection_pool().await; @@ -4973,9 +4973,13 @@ async fn lost_dev_server_connection(session: &DevServerSession) -> Result<()> { } let user_id = session.dev_server().user_id; - let update = session.db().await.remote_projects_update(user_id).await?; + let update = session + .db() + .await + .dev_server_projects_update(user_id) + .await?; - send_remote_projects_update(user_id, update, session).await; + send_dev_server_projects_update(user_id, update, session).await; Ok(()) } diff --git a/crates/collab/src/tests/channel_buffer_tests.rs b/crates/collab/src/tests/channel_buffer_tests.rs index 5f25468530..9b006e4079 100644 --- a/crates/collab/src/tests/channel_buffer_tests.rs +++ b/crates/collab/src/tests/channel_buffer_tests.rs @@ -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_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_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. diff --git a/crates/collab/src/tests/dev_server_tests.rs b/crates/collab/src/tests/dev_server_tests.rs index e6709b6e2a..d388850d6e 100644 --- a/crates/collab/src/tests/dev_server_tests.rs +++ b/crates/collab/src/tests/dev_server_tests.rs @@ -16,7 +16,7 @@ use super::TestClient; async fn test_dev_server(cx: &mut gpui::TestAppContext, cx2: &mut gpui::TestAppContext) { let (server, client) = TestServer::start1(cx).await; - let store = cx.update(|cx| remote_projects::Store::global(cx).clone()); + let store = cx.update(|cx| dev_server_projects::Store::global(cx).clone()); let resp = store .update(cx, |store, cx| { @@ -51,7 +51,7 @@ async fn test_dev_server(cx: &mut gpui::TestAppContext, cx2: &mut gpui::TestAppC store .update(cx, |store, cx| { - store.create_remote_project( + store.create_dev_server_project( client::DevServerId(resp.dev_server_id), "/remote".to_string(), cx, @@ -64,10 +64,10 @@ async fn test_dev_server(cx: &mut gpui::TestAppContext, cx2: &mut gpui::TestAppC let remote_workspace = store .update(cx, |store, cx| { - let projects = store.remote_projects(); + let projects = store.dev_server_projects(); assert_eq!(projects.len(), 1); assert_eq!(projects[0].path, "/remote"); - workspace::join_remote_project( + workspace::join_dev_server_project( projects[0].project_id.unwrap(), client.app_state.clone(), None, @@ -110,7 +110,7 @@ async fn test_dev_server_env_files( let (server, client1, client2, channel_id) = TestServer::start2(cx1, cx2).await; let (_dev_server, remote_workspace) = - create_remote_project(&server, client1.app_state.clone(), cx1, cx3).await; + create_dev_server_project(&server, client1.app_state.clone(), cx1, cx3).await; cx1.executor().run_until_parked(); @@ -157,13 +157,13 @@ async fn test_dev_server_env_files( }); } -async fn create_remote_project( +async fn create_dev_server_project( server: &TestServer, client_app_state: Arc, cx: &mut TestAppContext, cx_devserver: &mut TestAppContext, ) -> (TestClient, WindowHandle) { - let store = cx.update(|cx| remote_projects::Store::global(cx).clone()); + let store = cx.update(|cx| dev_server_projects::Store::global(cx).clone()); let resp = store .update(cx, |store, cx| { @@ -190,7 +190,7 @@ async fn create_remote_project( store .update(cx, |store, cx| { - store.create_remote_project( + store.create_dev_server_project( client::DevServerId(resp.dev_server_id), "/remote".to_string(), cx, @@ -203,10 +203,10 @@ async fn create_remote_project( let workspace = store .update(cx, |store, cx| { - let projects = store.remote_projects(); + let projects = store.dev_server_projects(); assert_eq!(projects.len(), 1); assert_eq!(projects[0].path, "/remote"); - workspace::join_remote_project( + workspace::join_dev_server_project( projects[0].project_id.unwrap(), client_app_state, None, @@ -230,7 +230,7 @@ async fn test_dev_server_leave_room( let (server, client1, client2, channel_id) = TestServer::start2(cx1, cx2).await; let (_dev_server, remote_workspace) = - create_remote_project(&server, client1.app_state.clone(), cx1, cx3).await; + create_dev_server_project(&server, client1.app_state.clone(), cx1, cx3).await; cx1.update(|cx| { workspace::join_channel( @@ -275,7 +275,7 @@ async fn test_dev_server_reconnect( .await; let (_dev_server, remote_workspace) = - create_remote_project(&server, client1.app_state.clone(), cx1, cx3).await; + create_dev_server_project(&server, client1.app_state.clone(), cx1, cx3).await; cx1.update(|cx| { workspace::join_channel( @@ -299,12 +299,12 @@ async fn test_dev_server_reconnect( let client2 = server.create_client(cx2, "user_a").await; - let store = cx2.update(|cx| remote_projects::Store::global(cx).clone()); + let store = cx2.update(|cx| dev_server_projects::Store::global(cx).clone()); store .update(cx2, |store, cx| { - let projects = store.remote_projects(); - workspace::join_remote_project( + let projects = store.dev_server_projects(); + workspace::join_dev_server_project( projects[0].project_id.unwrap(), client2.app_state.clone(), None, @@ -316,7 +316,7 @@ async fn test_dev_server_reconnect( } #[gpui::test] -async fn test_create_remote_project_path_validation( +async fn test_create_dev_server_project_path_validation( cx1: &mut gpui::TestAppContext, cx2: &mut gpui::TestAppContext, cx3: &mut gpui::TestAppContext, @@ -328,11 +328,11 @@ async fn test_create_remote_project_path_validation( // Creating a project with a path that does exist should not fail let (_dev_server, _) = - create_remote_project(&server, client1.app_state.clone(), cx1, cx2).await; + create_dev_server_project(&server, client1.app_state.clone(), cx1, cx2).await; cx1.executor().run_until_parked(); - let store = cx1.update(|cx| remote_projects::Store::global(cx).clone()); + let store = cx1.update(|cx| dev_server_projects::Store::global(cx).clone()); let resp = store .update(cx1, |store, cx| { @@ -350,7 +350,7 @@ async fn test_create_remote_project_path_validation( // Creating a remote project with a path that does not exist should fail let result = store .update(cx1, |store, cx| { - store.create_remote_project( + store.create_dev_server_project( client::DevServerId(resp.dev_server_id), "/notfound".to_string(), cx, @@ -363,7 +363,7 @@ async fn test_create_remote_project_path_validation( let error = result.unwrap_err(); assert!(matches!( error.error_code(), - ErrorCode::RemoteProjectPathDoesNotExist + ErrorCode::DevServerProjectPathDoesNotExist )); } @@ -373,7 +373,7 @@ async fn test_save_as_remote(cx1: &mut gpui::TestAppContext, cx2: &mut gpui::Tes // Creating a project with a path that does exist should not fail let (dev_server, remote_workspace) = - create_remote_project(&server, client1.app_state.clone(), cx1, cx2).await; + create_dev_server_project(&server, client1.app_state.clone(), cx1, cx2).await; let mut cx = VisualTestContext::from_window(remote_workspace.into(), cx1); @@ -405,7 +405,7 @@ async fn test_new_file_remote(cx1: &mut gpui::TestAppContext, cx2: &mut gpui::Te // Creating a project with a path that does exist should not fail let (dev_server, remote_workspace) = - create_remote_project(&server, client1.app_state.clone(), cx1, cx2).await; + create_dev_server_project(&server, client1.app_state.clone(), cx1, cx2).await; let mut cx = VisualTestContext::from_window(remote_workspace.into(), cx1); diff --git a/crates/collab/src/tests/editor_tests.rs b/crates/collab/src/tests/editor_tests.rs index 624b633043..fd46ec68b6 100644 --- a/crates/collab/src/tests/editor_tests.rs +++ b/crates/collab/src/tests/editor_tests.rs @@ -78,7 +78,7 @@ async fn test_host_disconnect( .await .unwrap(); - let project_b = client_b.build_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_project(project_id, cx_b).await; cx_a.background_executor.run_until_parked(); assert!(worktree_a.read_with(cx_a, |tree, _| tree.as_local().unwrap().is_shared())); @@ -199,7 +199,7 @@ async fn test_newline_above_or_below_does_not_move_guest_cursor( .await .unwrap(); - let project_b = client_b.build_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_project(project_id, cx_b).await; // Open a buffer as client A let buffer_a = project_a @@ -315,7 +315,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_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_project(project_id, cx_b).await; // Open a file in an editor as the guest. let buffer_b = project_b @@ -572,7 +572,7 @@ async fn test_collaborating_with_code_actions( .unwrap(); // Join the project as client B. - let project_b = client_b.build_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_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| { @@ -787,7 +787,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_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_project(project_id, cx_b).await; let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b); let editor_b = workspace_b @@ -1036,7 +1036,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_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_project(project_id, cx_b).await; project_b.read_with(cx_b, |project, _| { let status = project.language_server_statuses().next().unwrap(); @@ -1133,7 +1133,7 @@ async fn test_share_project( .unwrap(); let client_b_peer_id = client_b.peer_id().unwrap(); let project_b = client_b - .build_remote_project(initial_project.id, cx_b) + .build_dev_server_project(initial_project.id, cx_b) .await; let replica_id_b = project_b.read_with(cx_b, |project, _| project.replica_id()); @@ -1237,7 +1237,7 @@ async fn test_share_project( .await .unwrap(); let _project_c = client_c - .build_remote_project(initial_project.id, cx_c) + .build_dev_server_project(initial_project.id, cx_c) .await; // Client B closes the editor, and client A sees client B's selections removed. @@ -1297,7 +1297,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_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_project(project_id, cx_b).await; // Open a file in an editor as the host. let buffer_a = project_a @@ -1417,7 +1417,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_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_project(project_id, cx_b).await; // Open a file in an editor as the guest. let buffer_b = project_b @@ -1578,7 +1578,7 @@ async fn test_mutual_editor_inlay_hint_cache_update( .unwrap(); // Client B joins the project - let project_b = client_b.build_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_project(project_id, cx_b).await; active_call_b .update(cx_b, |call, cx| call.set_location(Some(&project_b), cx)) .await @@ -1838,7 +1838,7 @@ async fn test_inlay_hint_refresh_is_forwarded( .await .unwrap(); - let project_b = client_b.build_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_project(project_id, cx_b).await; active_call_b .update(cx_b, |call, cx| call.set_location(Some(&project_b), cx)) .await @@ -2014,7 +2014,7 @@ struct Row10;"#}; .await .unwrap(); - let project_b = client_b.build_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_project(project_id, cx_b).await; active_call_b .update(cx_b, |call, cx| call.set_location(Some(&project_b), cx)) .await @@ -2312,7 +2312,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_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_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| { diff --git a/crates/collab/src/tests/following_tests.rs b/crates/collab/src/tests/following_tests.rs index e71fc44298..e6904edfb1 100644 --- a/crates/collab/src/tests/following_tests.rs +++ b/crates/collab/src/tests/following_tests.rs @@ -73,7 +73,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_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_project(project_id, cx_b).await; active_call_b .update(cx_b, |call, cx| call.set_location(Some(&project_b), cx)) .await @@ -161,7 +161,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_remote_project(project_id, cx_c).await; + let project_c = client_c.build_dev_server_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)) @@ -174,7 +174,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_remote_project(project_id, cx_d).await; + let project_d = client_d.build_dev_server_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)) @@ -567,7 +567,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_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_project(project_id, cx_b).await; active_call_b .update(cx_b, |call, cx| call.set_location(Some(&project_b), cx)) .await @@ -684,7 +684,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_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_project(project_id, cx_b).await; active_call_b .update(cx_b, |call, cx| call.set_location(Some(&project_b), cx)) .await @@ -1197,7 +1197,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_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_project(project_id, cx_b).await; active_call_b .update(cx_b, |call, cx| call.set_location(Some(&project_b), cx)) .await @@ -1333,7 +1333,7 @@ async fn test_peers_simultaneously_following_each_other( .await .unwrap(); - let project_b = client_b.build_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_project(project_id, cx_b).await; let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b); executor.run_until_parked(); @@ -1683,7 +1683,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_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_project(project_id, cx_b).await; active_call_b .update(cx_b, |call, cx| call.set_location(Some(&project_b), cx)) .await diff --git a/crates/collab/src/tests/integration_tests.rs b/crates/collab/src/tests/integration_tests.rs index a9a67ef2e3..682ee576ea 100644 --- a/crates/collab/src/tests/integration_tests.rs +++ b/crates/collab/src/tests/integration_tests.rs @@ -1375,7 +1375,7 @@ async fn test_unshare_project( .unwrap(); let worktree_a = project_a.read_with(cx_a, |project, _| project.worktrees().next().unwrap()); - let project_b = client_b.build_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_project(project_id, cx_b).await; executor.run_until_parked(); assert!(worktree_a.read_with(cx_a, |tree, _| tree.as_local().unwrap().is_shared())); @@ -1395,7 +1395,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_remote_project(project_id, cx_c).await; + let project_c = client_c.build_dev_server_project(project_id, cx_c).await; // When client A unshares the project, client C's project becomes read-only. project_a @@ -1412,7 +1412,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_remote_project(project_id, cx_c).await; + let project_c2 = client_c.build_dev_server_project(project_id, cx_c).await; executor.run_until_parked(); assert!(worktree_a.read_with(cx_a, |tree, _| tree.as_local().unwrap().is_shared())); @@ -1516,9 +1516,9 @@ async fn test_project_reconnect( .await .unwrap(); - let project_b1 = client_b.build_remote_project(project1_id, cx_b).await; - let project_b2 = client_b.build_remote_project(project2_id, cx_b).await; - let project_b3 = client_b.build_remote_project(project3_id, cx_b).await; + 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; executor.run_until_parked(); let worktree1_id = worktree_a1.read_with(cx_a, |worktree, _| { @@ -2314,8 +2314,8 @@ async fn test_propagate_saves_and_fs_changes( .unwrap(); // Join that worktree as clients B and C. - let project_b = client_b.build_remote_project(project_id, cx_b).await; - let project_c = client_c.build_remote_project(project_id, cx_c).await; + 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 worktree_b = project_b.read_with(cx_b, |p, _| p.worktrees().next().unwrap()); @@ -2539,7 +2539,7 @@ async fn test_git_diff_base_change( .await .unwrap(); - let project_remote = client_b.build_remote_project(project_id, cx_b).await; + let project_remote = client_b.build_dev_server_project(project_id, cx_b).await; let diff_base = " one @@ -2771,7 +2771,7 @@ async fn test_git_branch_name( .await .unwrap(); - let project_remote = client_b.build_remote_project(project_id, cx_b).await; + let project_remote = client_b.build_dev_server_project(project_id, cx_b).await; client_a .fs() .set_branch_name(Path::new("/dir/.git"), Some("branch-1")); @@ -2816,7 +2816,7 @@ async fn test_git_branch_name( assert_branch(Some("branch-2"), project, cx) }); - let project_remote_c = client_c.build_remote_project(project_id, cx_c).await; + let project_remote_c = client_c.build_dev_server_project(project_id, cx_c).await; executor.run_until_parked(); project_remote_c.read_with(cx_c, |project, cx| { @@ -2871,7 +2871,7 @@ async fn test_git_status_sync( .await .unwrap(); - let project_remote = client_b.build_remote_project(project_id, cx_b).await; + let project_remote = client_b.build_dev_server_project(project_id, cx_b).await; // Wait for it to catch up to the new status executor.run_until_parked(); @@ -2947,7 +2947,7 @@ async fn test_git_status_sync( }); // And synchronization while joining - let project_remote_c = client_c.build_remote_project(project_id, cx_c).await; + let project_remote_c = client_c.build_dev_server_project(project_id, cx_c).await; executor.run_until_parked(); project_remote_c.read_with(cx_c, |project, cx| { @@ -2995,7 +2995,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_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_project(project_id, cx_b).await; let worktree_a = project_a.read_with(cx_a, |project, _| project.worktrees().next().unwrap()); @@ -3289,7 +3289,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_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_project(project_id, cx_b).await; let worktree_b = project_b.read_with(cx_b, |project, _| project.worktrees().next().unwrap()); executor.run_until_parked(); @@ -3412,7 +3412,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_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_project(project_id, cx_b).await; // Open a buffer as client B let buffer_b = project_b @@ -3476,7 +3476,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_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_project(project_id, cx_b).await; // Open a buffer as client B let buffer_b = project_b @@ -3530,7 +3530,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_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_project(project_id, cx_b).await; // Open a buffer as client A let buffer_a = project_a @@ -3578,7 +3578,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_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_project(project_id, cx_b).await; // See that a guest has joined as client A. executor.run_until_parked(); @@ -3625,7 +3625,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_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_project(project_id, cx_b).await; let buffer_a = project_a .update(cx_a, |p, cx| p.open_buffer((worktree_id, "a.txt"), cx)) @@ -3682,8 +3682,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_remote_project(project_id, cx_b).await; - let project_c = client_c.build_remote_project(project_id, cx_c).await; + 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; // Client A sees that a guest has joined. executor.run_until_parked(); @@ -3724,7 +3724,7 @@ async fn test_leaving_project( }); // Client B re-joins the project and can open buffers as before. - let project_b2 = client_b.build_remote_project(project_id, cx_b).await; + let project_b2 = client_b.build_dev_server_project(project_id, cx_b).await; executor.run_until_parked(); project_a.read_with(cx_a, |project, _| { @@ -3900,7 +3900,7 @@ async fn test_collaborating_with_diagnostics( ); // Join the worktree as client B. - let project_b = client_b.build_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_project(project_id, cx_b).await; // Wait for server to see the diagnostics update. executor.run_until_parked(); @@ -3925,7 +3925,7 @@ async fn test_collaborating_with_diagnostics( }); // Join project as client C and observe the diagnostics. - let project_c = client_c.build_remote_project(project_id, cx_c).await; + let project_c = client_c.build_dev_server_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| { @@ -4133,7 +4133,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_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_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)) })) @@ -4239,7 +4239,7 @@ async fn test_reloading_buffer_manually( .await .unwrap(); - let project_b = client_b.build_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_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(); @@ -4337,7 +4337,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_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_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(); @@ -4457,7 +4457,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_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_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(); @@ -4560,7 +4560,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_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_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)); @@ -4705,7 +4705,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_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_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)); @@ -4862,7 +4862,7 @@ async fn test_project_search( .await .unwrap(); - let project_b = client_b.build_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_project(project_id, cx_b).await; // Perform a search as the guest. let mut results = HashMap::default(); @@ -4943,7 +4943,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_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_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)); @@ -5065,7 +5065,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_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_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)); @@ -5242,7 +5242,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_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_project(project_id, cx_b).await; // Cause the language server to start. let open_buffer_task = @@ -5337,7 +5337,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_remote_project(project_id, cx_b).await; + let project_b = client_b.build_dev_server_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(); diff --git a/crates/collab/src/tests/random_project_collaboration_tests.rs b/crates/collab/src/tests/random_project_collaboration_tests.rs index e06b79d5a8..03f3f92d51 100644 --- a/crates/collab/src/tests/random_project_collaboration_tests.rs +++ b/crates/collab/src/tests/random_project_collaboration_tests.rs @@ -217,19 +217,20 @@ impl RandomizedTest for ProjectCollaborationTest { 0..=70 => { // Open a remote project if let Some(room) = call.read_with(cx, |call, _| call.room().cloned()) { - let existing_remote_project_ids = cx.read(|cx| { + let existing_dev_server_project_ids = cx.read(|cx| { client - .remote_projects() + .dev_server_projects() .iter() .map(|p| p.read(cx).remote_id().unwrap()) .collect::>() }); - let new_remote_projects = room.read_with(cx, |room, _| { + let new_dev_server_projects = room.read_with(cx, |room, _| { room.remote_participants() .values() .flat_map(|participant| { participant.projects.iter().filter_map(|project| { - if existing_remote_project_ids.contains(&project.id) { + if existing_dev_server_project_ids.contains(&project.id) + { None } else { Some(( @@ -241,9 +242,9 @@ impl RandomizedTest for ProjectCollaborationTest { }) .collect::>() }); - if !new_remote_projects.is_empty() { + if !new_dev_server_projects.is_empty() { let (host_id, first_root_name) = - new_remote_projects.choose(rng).unwrap().clone(); + new_dev_server_projects.choose(rng).unwrap().clone(); break ClientOperation::OpenRemoteProject { host_id, first_root_name, @@ -259,8 +260,8 @@ impl RandomizedTest for ProjectCollaborationTest { // Close a remote project 71..=80 => { - if !client.remote_projects().is_empty() { - let project = client.remote_projects().choose(rng).unwrap().clone(); + if !client.dev_server_projects().is_empty() { + let project = client.dev_server_projects().choose(rng).unwrap().clone(); let first_root_name = root_name_for_project(&project, cx); break ClientOperation::CloseRemoteProject { project_root_name: first_root_name, @@ -595,12 +596,12 @@ impl RandomizedTest for ProjectCollaborationTest { ); let ix = client - .remote_projects() + .dev_server_projects() .iter() .position(|p| p == &project) .unwrap(); cx.update(|_| { - client.remote_projects_mut().remove(ix); + client.dev_server_projects_mut().remove(ix); client.buffers().retain(|p, _| *p != project); drop(project); }); @@ -642,7 +643,7 @@ impl RandomizedTest for ProjectCollaborationTest { ); let project = project.await?; - client.remote_projects_mut().push(project.clone()); + client.dev_server_projects_mut().push(project.clone()); } ClientOperation::CreateWorktreeEntry { @@ -1142,7 +1143,7 @@ impl RandomizedTest for ProjectCollaborationTest { async fn on_quiesce(_: &mut TestServer, clients: &mut [(Rc, TestAppContext)]) { for (client, client_cx) in clients.iter() { - for guest_project in client.remote_projects().iter() { + for guest_project in client.dev_server_projects().iter() { guest_project.read_with(client_cx, |guest_project, cx| { let host_project = clients.iter().find_map(|(client, cx)| { let project = client @@ -1487,8 +1488,9 @@ fn project_for_root_name( if let Some(ix) = project_ix_for_root_name(client.local_projects().deref(), root_name, cx) { return Some(client.local_projects()[ix].clone()); } - if let Some(ix) = project_ix_for_root_name(client.remote_projects().deref(), root_name, cx) { - return Some(client.remote_projects()[ix].clone()); + if let Some(ix) = project_ix_for_root_name(client.dev_server_projects().deref(), root_name, cx) + { + return Some(client.dev_server_projects()[ix].clone()); } None } @@ -1578,7 +1580,7 @@ fn choose_random_project(client: &TestClient, rng: &mut StdRng) -> Option TestPlan { deterministic.finish_waiting(); server.allow_connections(); - for project in client.remote_projects().iter() { + for project in client.dev_server_projects().iter() { project.read_with(&client_cx, |project, _| { assert!( project.is_disconnected(), diff --git a/crates/collab/src/tests/test_server.rs b/crates/collab/src/tests/test_server.rs index 6708660479..2fec21f76e 100644 --- a/crates/collab/src/tests/test_server.rs +++ b/crates/collab/src/tests/test_server.rs @@ -64,7 +64,7 @@ pub struct TestClient { #[derive(Default)] struct TestClientState { local_projects: Vec>, - remote_projects: Vec>, + dev_server_projects: Vec>, buffers: HashMap, HashSet>>, channel_buffers: HashSet>, } @@ -290,7 +290,7 @@ impl TestServer { collab_ui::init(&app_state, cx); file_finder::init(cx); menu::init(); - remote_projects::init(client.clone(), cx); + dev_server_projects::init(client.clone(), cx); settings::KeymapFile::load_asset(os_keymap, cx).unwrap(); }); @@ -735,16 +735,18 @@ impl TestClient { Ref::map(self.state.borrow(), |state| &state.local_projects) } - pub fn remote_projects(&self) -> impl Deref>> + '_ { - Ref::map(self.state.borrow(), |state| &state.remote_projects) + pub fn dev_server_projects(&self) -> impl Deref>> + '_ { + Ref::map(self.state.borrow(), |state| &state.dev_server_projects) } pub fn local_projects_mut(&self) -> impl DerefMut>> + '_ { RefMut::map(self.state.borrow_mut(), |state| &mut state.local_projects) } - pub fn remote_projects_mut(&self) -> impl DerefMut>> + '_ { - RefMut::map(self.state.borrow_mut(), |state| &mut state.remote_projects) + pub fn dev_server_projects_mut(&self) -> impl DerefMut>> + '_ { + RefMut::map(self.state.borrow_mut(), |state| { + &mut state.dev_server_projects + }) } pub fn buffers_for_project<'a>( @@ -869,7 +871,7 @@ impl TestClient { }) } - pub async fn build_remote_project( + pub async fn build_dev_server_project( &self, host_project_id: u64, guest_cx: &mut TestAppContext, diff --git a/crates/collab_ui/Cargo.toml b/crates/collab_ui/Cargo.toml index f5f25ce231..c936e12f8b 100644 --- a/crates/collab_ui/Cargo.toml +++ b/crates/collab_ui/Cargo.toml @@ -50,7 +50,7 @@ parking_lot.workspace = true picker.workspace = true project.workspace = true recent_projects.workspace = true -remote_projects.workspace = true +dev_server_projects.workspace = true rich_text.workspace = true rpc.workspace = true schemars.workspace = true diff --git a/crates/collab_ui/src/collab_titlebar_item.rs b/crates/collab_ui/src/collab_titlebar_item.rs index 23876f0ca1..acbf06d54d 100644 --- a/crates/collab_ui/src/collab_titlebar_item.rs +++ b/crates/collab_ui/src/collab_titlebar_item.rs @@ -171,8 +171,8 @@ impl Render for CollabTitlebarItem { let room = room.read(cx); let project = self.project.read(cx); let is_local = project.is_local(); - let is_remote_project = project.remote_project_id().is_some(); - let is_shared = (is_local || is_remote_project) && project.is_shared(); + let is_dev_server_project = project.dev_server_project_id().is_some(); + let is_shared = (is_local || is_dev_server_project) && project.is_shared(); let is_muted = room.is_muted(); let is_deafened = room.is_deafened().unwrap_or(false); let is_screen_sharing = room.is_screen_sharing(); @@ -180,7 +180,7 @@ impl Render for CollabTitlebarItem { let can_share_projects = room.can_share_projects(); this.when( - (is_local || is_remote_project) && can_share_projects, + (is_local || is_dev_server_project) && can_share_projects, |this| { this.child( Button::new( @@ -379,11 +379,11 @@ impl CollabTitlebarItem { if let Some(dev_server) = self.project .read(cx) - .remote_project_id() - .and_then(|remote_project_id| { - remote_projects::Store::global(cx) + .dev_server_project_id() + .and_then(|dev_server_project_id| { + dev_server_projects::Store::global(cx) .read(cx) - .dev_server_for_project(remote_project_id) + .dev_server_for_project(dev_server_project_id) }) { return Some( @@ -403,7 +403,7 @@ impl CollabTitlebarItem { .tooltip(move |cx| Tooltip::text("Project is hosted on a dev server", cx)) .on_click(cx.listener(|this, _, cx| { if let Some(workspace) = this.workspace.upgrade() { - recent_projects::RemoteProjects::open(workspace, cx) + recent_projects::DevServerProjects::open(workspace, cx) } })) .into_any_element(), diff --git a/crates/remote_projects/Cargo.toml b/crates/dev_server_projects/Cargo.toml similarity index 82% rename from crates/remote_projects/Cargo.toml rename to crates/dev_server_projects/Cargo.toml index 2e904f3326..81d50301bc 100644 --- a/crates/remote_projects/Cargo.toml +++ b/crates/dev_server_projects/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "remote_projects" +name = "dev_server_projects" version = "0.1.0" edition = "2021" publish = false @@ -9,7 +9,7 @@ license = "GPL-3.0-or-later" workspace = true [lib] -path = "src/remote_projects.rs" +path = "src/dev_server_projects.rs" doctest = false [dependencies] diff --git a/crates/remote_projects/src/remote_projects.rs b/crates/dev_server_projects/src/dev_server_projects.rs similarity index 73% rename from crates/remote_projects/src/remote_projects.rs rename to crates/dev_server_projects/src/dev_server_projects.rs index 93450ef837..499eaa479d 100644 --- a/crates/remote_projects/src/remote_projects.rs +++ b/crates/dev_server_projects/src/dev_server_projects.rs @@ -7,27 +7,27 @@ use rpc::{ use std::{collections::HashMap, sync::Arc}; use client::{Client, ProjectId}; -pub use client::{DevServerId, RemoteProjectId}; +pub use client::{DevServerId, DevServerProjectId}; pub struct Store { - remote_projects: HashMap, + dev_server_projects: HashMap, dev_servers: HashMap, _subscriptions: Vec, client: Arc, } #[derive(Debug, Clone)] -pub struct RemoteProject { - pub id: RemoteProjectId, +pub struct DevServerProject { + pub id: DevServerProjectId, pub project_id: Option, pub path: SharedString, pub dev_server_id: DevServerId, } -impl From for RemoteProject { - fn from(project: proto::RemoteProject) -> Self { +impl From for DevServerProject { + fn from(project: proto::DevServerProject) -> Self { Self { - id: RemoteProjectId(project.id), + id: DevServerProjectId(project.id), project_id: project.project_id.map(|id| ProjectId(id)), path: project.path.into(), dev_server_id: DevServerId(project.dev_server_id), @@ -68,18 +68,17 @@ impl Store { pub fn new(client: Arc, cx: &ModelContext) -> Self { Self { - remote_projects: Default::default(), + dev_server_projects: Default::default(), dev_servers: Default::default(), - _subscriptions: vec![ - client.add_message_handler(cx.weak_model(), Self::handle_remote_projects_update) - ], + _subscriptions: vec![client + .add_message_handler(cx.weak_model(), Self::handle_dev_server_projects_update)], client, } } - pub fn remote_projects_for_server(&self, id: DevServerId) -> Vec { - let mut projects: Vec = self - .remote_projects + pub fn projects_for_server(&self, id: DevServerId) -> Vec { + let mut projects: Vec = self + .dev_server_projects .values() .filter(|project| project.dev_server_id == id) .cloned() @@ -104,24 +103,25 @@ impl Store { .unwrap_or(DevServerStatus::Offline) } - pub fn remote_projects(&self) -> Vec { - let mut projects: Vec = self.remote_projects.values().cloned().collect(); + pub fn dev_server_projects(&self) -> Vec { + let mut projects: Vec = + self.dev_server_projects.values().cloned().collect(); projects.sort_by_key(|p| (p.path.clone(), p.id)); projects } - pub fn remote_project(&self, id: RemoteProjectId) -> Option<&RemoteProject> { - self.remote_projects.get(&id) + pub fn dev_server_project(&self, id: DevServerProjectId) -> Option<&DevServerProject> { + self.dev_server_projects.get(&id) } - pub fn dev_server_for_project(&self, id: RemoteProjectId) -> Option<&DevServer> { - self.remote_project(id) + pub fn dev_server_for_project(&self, id: DevServerProjectId) -> Option<&DevServer> { + self.dev_server_project(id) .and_then(|project| self.dev_server(project.dev_server_id)) } - async fn handle_remote_projects_update( + async fn handle_dev_server_projects_update( this: Model, - envelope: TypedEnvelope, + envelope: TypedEnvelope, _: Arc, mut cx: AsyncAppContext, ) -> Result<()> { @@ -132,11 +132,11 @@ impl Store { .into_iter() .map(|dev_server| (DevServerId(dev_server.dev_server_id), dev_server.into())) .collect(); - this.remote_projects = envelope + this.dev_server_projects = envelope .payload - .remote_projects + .dev_server_projects .into_iter() - .map(|project| (RemoteProjectId(project.id), project.into())) + .map(|project| (DevServerProjectId(project.id), project.into())) .collect(); cx.notify(); @@ -144,16 +144,16 @@ impl Store { Ok(()) } - pub fn create_remote_project( + pub fn create_dev_server_project( &mut self, dev_server_id: DevServerId, path: String, cx: &mut ModelContext, - ) -> Task> { + ) -> Task> { let client = self.client.clone(); cx.background_executor().spawn(async move { client - .request(proto::CreateRemoteProject { + .request(proto::CreateDevServerProject { dev_server_id: dev_server_id.0, path, }) diff --git a/crates/headless/src/headless.rs b/crates/headless/src/headless.rs index dd31360f91..aeaa042017 100644 --- a/crates/headless/src/headless.rs +++ b/crates/headless/src/headless.rs @@ -1,5 +1,5 @@ use anyhow::Result; -use client::RemoteProjectId; +use client::DevServerProjectId; use client::{user::UserStore, Client, ClientSettings}; use fs::Fs; use futures::Future; @@ -20,7 +20,7 @@ pub struct DevServer { client: Arc, app_state: AppState, remote_shutdown: bool, - projects: HashMap>, + projects: HashMap>, _subscriptions: Vec, _maintain_connection: Task>, } @@ -106,7 +106,7 @@ impl DevServer { client.add_message_handler(cx.weak_model(), Self::handle_dev_server_instructions), client.add_request_handler( cx.weak_model(), - Self::handle_validate_remote_project_request, + Self::handle_validate_dev_server_project_request, ), client.add_message_handler(cx.weak_model(), Self::handle_shutdown), ], @@ -141,12 +141,12 @@ impl DevServer { let removed_projects = this .projects .keys() - .filter(|remote_project_id| { + .filter(|dev_server_project_id| { !envelope .payload .projects .iter() - .any(|p| p.id == remote_project_id.0) + .any(|p| p.id == dev_server_project_id.0) }) .cloned() .collect::>(); @@ -155,14 +155,14 @@ impl DevServer { .payload .projects .into_iter() - .filter(|project| !this.projects.contains_key(&RemoteProjectId(project.id))) + .filter(|project| !this.projects.contains_key(&DevServerProjectId(project.id))) .collect::>(); (added_projects, removed_projects) })?; - for remote_project in added_projects { - DevServer::share_project(this.clone(), &remote_project, &mut cx).await?; + for dev_server_project in added_projects { + DevServer::share_project(this.clone(), &dev_server_project, &mut cx).await?; } this.update(&mut cx, |this, cx| { @@ -174,9 +174,9 @@ impl DevServer { Ok(()) } - async fn handle_validate_remote_project_request( + async fn handle_validate_dev_server_project_request( this: Model, - envelope: TypedEnvelope, + envelope: TypedEnvelope, _: Arc, cx: AsyncAppContext, ) -> Result { @@ -186,7 +186,7 @@ impl DevServer { let path_exists = fs.is_dir(path).await; if !path_exists { - return Err(anyhow::anyhow!(ErrorCode::RemoteProjectPathDoesNotExist))?; + return Err(anyhow::anyhow!(ErrorCode::DevServerProjectPathDoesNotExist))?; } Ok(proto::Ack {}) @@ -206,10 +206,10 @@ impl DevServer { fn unshare_project( &mut self, - remote_project_id: &RemoteProjectId, + dev_server_project_id: &DevServerProjectId, cx: &mut ModelContext, ) -> Result<()> { - if let Some(project) = self.projects.remove(remote_project_id) { + if let Some(project) = self.projects.remove(dev_server_project_id) { project.update(cx, |project, cx| project.unshare(cx))?; } Ok(()) @@ -217,7 +217,7 @@ impl DevServer { async fn share_project( this: Model, - remote_project: &proto::RemoteProject, + dev_server_project: &proto::DevServerProject, cx: &mut AsyncAppContext, ) -> Result<()> { let (client, project) = this.update(cx, |this, cx| { @@ -233,7 +233,7 @@ impl DevServer { (this.client.clone(), project) })?; - let path = shellexpand::tilde(&remote_project.path).to_string(); + let path = shellexpand::tilde(&dev_server_project.path).to_string(); project .update(cx, |project, cx| { @@ -245,8 +245,8 @@ impl DevServer { project.read_with(cx, |project, cx| project.worktree_metadata_protos(cx))?; let response = client - .request(proto::ShareRemoteProject { - remote_project_id: remote_project.id, + .request(proto::ShareDevServerProject { + dev_server_project_id: dev_server_project.id, worktrees, }) .await?; @@ -255,7 +255,7 @@ impl DevServer { project.update(cx, |project, cx| project.shared(project_id, cx))??; this.update(cx, |this, _| { this.projects - .insert(RemoteProjectId(remote_project.id), project); + .insert(DevServerProjectId(dev_server_project.id), project); })?; Ok(()) } diff --git a/crates/project/src/project.rs b/crates/project/src/project.rs index 3c72161aef..c8669bca43 100644 --- a/crates/project/src/project.rs +++ b/crates/project/src/project.rs @@ -15,7 +15,7 @@ pub mod search_history; use anyhow::{anyhow, bail, Context as _, Result}; use async_trait::async_trait; use client::{ - proto, Client, Collaborator, PendingEntitySubscription, ProjectId, RemoteProjectId, + proto, Client, Collaborator, DevServerProjectId, PendingEntitySubscription, ProjectId, TypedEnvelope, UserStore, }; use clock::ReplicaId; @@ -209,7 +209,7 @@ pub struct Project { prettier_instances: HashMap, tasks: Model, hosted_project_id: Option, - remote_project_id: Option, + dev_server_project_id: Option, search_history: SearchHistory, } @@ -744,7 +744,7 @@ impl Project { prettier_instances: HashMap::default(), tasks, hosted_project_id: None, - remote_project_id: None, + dev_server_project_id: None, search_history: Self::new_search_history(), } }) @@ -858,7 +858,7 @@ impl Project { capability: Capability::ReadWrite, remote_id, replica_id, - in_room: response.payload.remote_project_id.is_none(), + in_room: response.payload.dev_server_project_id.is_none(), }, supplementary_language_servers: HashMap::default(), language_servers: Default::default(), @@ -900,10 +900,10 @@ impl Project { prettier_instances: HashMap::default(), tasks, hosted_project_id: None, - remote_project_id: response + dev_server_project_id: response .payload - .remote_project_id - .map(|remote_project_id| RemoteProjectId(remote_project_id)), + .dev_server_project_id + .map(|dev_server_project_id| DevServerProjectId(dev_server_project_id)), search_history: Self::new_search_history(), }; this.set_role(role, cx); @@ -1262,8 +1262,8 @@ impl Project { self.hosted_project_id } - pub fn remote_project_id(&self) -> Option { - self.remote_project_id + pub fn dev_server_project_id(&self) -> Option { + self.dev_server_project_id } pub fn replica_id(&self) -> ReplicaId { @@ -1589,7 +1589,7 @@ impl Project { pub fn shared(&mut self, project_id: u64, cx: &mut ModelContext) -> Result<()> { if !matches!(self.client_state, ProjectClientState::Local) { if let ProjectClientState::Remote { in_room, .. } = &mut self.client_state { - if *in_room || self.remote_project_id.is_none() { + if *in_room || self.dev_server_project_id.is_none() { return Err(anyhow!("project was already shared")); } else { *in_room = true; @@ -1808,7 +1808,7 @@ impl Project { fn unshare_internal(&mut self, cx: &mut AppContext) -> Result<()> { if self.is_remote() { - if self.remote_project_id().is_some() { + if self.dev_server_project_id().is_some() { if let ProjectClientState::Remote { in_room, .. } = &mut self.client_state { *in_room = false } diff --git a/crates/recent_projects/Cargo.toml b/crates/recent_projects/Cargo.toml index e11ff9148e..ded5ba59fa 100644 --- a/crates/recent_projects/Cargo.toml +++ b/crates/recent_projects/Cargo.toml @@ -20,7 +20,7 @@ gpui.workspace = true menu.workspace = true ordered-float.workspace = true picker.workspace = true -remote_projects.workspace = true +dev_server_projects.workspace = true rpc.workspace = true serde.workspace = true settings.workspace = true diff --git a/crates/recent_projects/src/remote_projects.rs b/crates/recent_projects/src/dev_servers.rs similarity index 87% rename from crates/recent_projects/src/remote_projects.rs rename to crates/recent_projects/src/dev_servers.rs index 86a2495e4b..ed07480ac2 100644 --- a/crates/recent_projects/src/remote_projects.rs +++ b/crates/recent_projects/src/dev_servers.rs @@ -1,12 +1,12 @@ use std::time::Duration; +use dev_server_projects::{DevServer, DevServerId, DevServerProject, DevServerProjectId}; use feature_flags::FeatureFlagViewExt; use gpui::{ percentage, Action, Animation, AnimationExt, AppContext, ClipboardItem, DismissEvent, EventEmitter, FocusHandle, FocusableView, Model, ScrollHandle, Transformation, View, ViewContext, }; -use remote_projects::{DevServer, DevServerId, RemoteProject, RemoteProjectId}; use rpc::{ proto::{self, CreateDevServerResponse, DevServerStatus}, ErrorCode, ErrorExt, @@ -20,12 +20,12 @@ use workspace::{notifications::DetachAndPromptErr, AppState, ModalView, Workspac use crate::OpenRemote; -pub struct RemoteProjects { +pub struct DevServerProjects { mode: Mode, focus_handle: FocusHandle, scroll_handle: ScrollHandle, - remote_project_store: Model, - remote_project_path_input: View, + dev_server_store: Model, + project_path_input: View, dev_server_name_input: View, _subscription: gpui::Subscription, } @@ -36,19 +36,19 @@ struct CreateDevServer { dev_server: Option, } -struct CreateRemoteProject { +struct CreateDevServerProject { dev_server_id: DevServerId, creating: bool, - remote_project: Option, + dev_server_project: Option, } enum Mode { Default, - CreateRemoteProject(CreateRemoteProject), + CreateDevServerProject(CreateDevServerProject), CreateDevServer(CreateDevServer), } -impl RemoteProjects { +impl DevServerProjects { pub fn register(_: &mut Workspace, cx: &mut ViewContext) { cx.observe_flag::(|enabled, workspace, _| { if enabled { @@ -67,14 +67,14 @@ impl RemoteProjects { } pub fn new(cx: &mut ViewContext) -> Self { - let remote_project_path_input = cx.new_view(|cx| TextField::new(cx, "", "Project path")); + let project_path_input = cx.new_view(|cx| TextField::new(cx, "", "Project path")); let dev_server_name_input = cx.new_view(|cx| TextField::new(cx, "Name", "").with_label(FieldLabelLayout::Stacked)); let focus_handle = cx.focus_handle(); - let remote_project_store = remote_projects::Store::global(cx); + let dev_server_store = dev_server_projects::Store::global(cx); - let subscription = cx.observe(&remote_project_store, |_, _, cx| { + let subscription = cx.observe(&dev_server_store, |_, _, cx| { cx.notify(); }); @@ -82,20 +82,20 @@ impl RemoteProjects { mode: Mode::Default, focus_handle, scroll_handle: ScrollHandle::new(), - remote_project_store, - remote_project_path_input, + dev_server_store, + project_path_input, dev_server_name_input, _subscription: subscription, } } - pub fn create_remote_project( + pub fn create_dev_server_project( &mut self, dev_server_id: DevServerId, cx: &mut ViewContext, ) { let path = self - .remote_project_path_input + .project_path_input .read(cx) .editor() .read(cx) @@ -108,9 +108,9 @@ impl RemoteProjects { } if self - .remote_project_store + .dev_server_store .read(cx) - .remote_projects_for_server(dev_server_id) + .projects_for_server(dev_server_id) .iter() .any(|p| p.path == path) { @@ -132,19 +132,22 @@ impl RemoteProjects { let create = { let path = path.clone(); - self.remote_project_store.update(cx, |store, cx| { - store.create_remote_project(dev_server_id, path, cx) + self.dev_server_store.update(cx, |store, cx| { + store.create_dev_server_project(dev_server_id, path, cx) }) }; cx.spawn(|this, mut cx| async move { let result = create.await; - let remote_project = result.as_ref().ok().and_then(|r| r.remote_project.clone()); + let dev_server_project = result + .as_ref() + .ok() + .and_then(|r| r.dev_server_project.clone()); this.update(&mut cx, |this, _| { - this.mode = Mode::CreateRemoteProject(CreateRemoteProject { + this.mode = Mode::CreateDevServerProject(CreateDevServerProject { dev_server_id, creating: false, - remote_project, + dev_server_project, }); }) .log_err(); @@ -156,23 +159,23 @@ impl RemoteProjects { "The dev server is offline. Please log in and check it is connected." .to_string(), ), - ErrorCode::RemoteProjectPathDoesNotExist => { + ErrorCode::DevServerProjectPathDoesNotExist => { Some(format!("The path `{}` does not exist on the server.", path)) } _ => None, } }); - self.remote_project_path_input.update(cx, |input, cx| { + self.project_path_input.update(cx, |input, cx| { input.editor().update(cx, |editor, cx| { editor.set_text("", cx); }); }); - self.mode = Mode::CreateRemoteProject(CreateRemoteProject { + self.mode = Mode::CreateDevServerProject(CreateDevServerProject { dev_server_id, creating: true, - remote_project: None, + dev_server_project: None, }); } @@ -191,7 +194,7 @@ impl RemoteProjects { } let dev_server = self - .remote_project_store + .dev_server_store .update(cx, |store, cx| store.create_dev_server(name.clone(), cx)); cx.spawn(|this, mut cx| async move { @@ -236,7 +239,7 @@ impl RemoteProjects { } this.update(&mut cx, |this, cx| { - this.remote_project_store + this.dev_server_store .update(cx, |store, cx| store.delete_dev_server(id, cx)) })? .await @@ -247,8 +250,8 @@ impl RemoteProjects { fn confirm(&mut self, _: &menu::Confirm, cx: &mut ViewContext) { match self.mode { Mode::Default => {} - Mode::CreateRemoteProject(CreateRemoteProject { dev_server_id, .. }) => { - self.create_remote_project(dev_server_id, cx); + Mode::CreateDevServerProject(CreateDevServerProject { dev_server_id, .. }) => { + self.create_dev_server_project(dev_server_id, cx); } Mode::CreateDevServer(_) => { self.create_dev_server(cx); @@ -259,7 +262,7 @@ impl RemoteProjects { fn cancel(&mut self, _: &menu::Cancel, cx: &mut ViewContext) { match self.mode { Mode::Default => cx.emit(DismissEvent), - Mode::CreateRemoteProject(_) | Mode::CreateDevServer(_) => { + Mode::CreateDevServerProject(_) | Mode::CreateDevServer(_) => { self.mode = Mode::Default; self.focus_handle(cx).focus(cx); cx.notify(); @@ -338,15 +341,13 @@ impl RemoteProjects { .tooltip(|cx| Tooltip::text("Add a remote project", cx)) .on_click(cx.listener( move |this, _, cx| { - this.mode = Mode::CreateRemoteProject(CreateRemoteProject { - dev_server_id, - creating: false, - remote_project: None, - }); - this.remote_project_path_input - .read(cx) - .focus_handle(cx) - .focus(cx); + this.mode = + Mode::CreateDevServerProject(CreateDevServerProject { + dev_server_id, + creating: false, + dev_server_project: None, + }); + this.project_path_input.read(cx).focus_handle(cx).focus(cx); cx.notify(); }, )), @@ -365,26 +366,26 @@ impl RemoteProjects { .px_3() .child( List::new().empty_message("No projects.").children( - self.remote_project_store + self.dev_server_store .read(cx) - .remote_projects_for_server(dev_server.id) + .projects_for_server(dev_server.id) .iter() - .map(|p| self.render_remote_project(p, cx)), + .map(|p| self.render_dev_server_project(p, cx)), ), ), ) } - fn render_remote_project( + fn render_dev_server_project( &mut self, - project: &RemoteProject, + project: &DevServerProject, cx: &mut ViewContext, ) -> impl IntoElement { - let remote_project_id = project.id; + let dev_server_project_id = project.id; let project_id = project.project_id; let is_online = project_id.is_some(); - ListItem::new(("remote-project", remote_project_id.0)) + ListItem::new(("remote-project", dev_server_project_id.0)) .start_slot(Icon::new(IconName::FileTree).when(!is_online, |icon| icon.color(Color::Muted))) .child( Label::new(project.path.clone()) @@ -392,7 +393,7 @@ impl RemoteProjects { .on_click(cx.listener(move |_, _, cx| { if let Some(project_id) = project_id { if let Some(app_state) = AppState::global(cx).upgrade() { - workspace::join_remote_project(project_id, app_state, None, cx) + workspace::join_dev_server_project(project_id, app_state, None, cx) .detach_and_prompt_err("Could not join project", cx, |_, _| None) } } else { @@ -471,7 +472,7 @@ impl RemoteProjects { }) .when_some(dev_server.clone(), |div, dev_server| { let status = self - .remote_project_store + .dev_server_store .read(cx) .dev_server_status(DevServerId(dev_server.dev_server_id)); @@ -556,7 +557,7 @@ impl RemoteProjects { } fn render_default(&mut self, cx: &mut ViewContext) -> impl IntoElement { - let dev_servers = self.remote_project_store.read(cx).dev_servers(); + let dev_servers = self.dev_server_store.read(cx).dev_servers(); v_flex() .id("scroll-container") @@ -602,18 +603,18 @@ impl RemoteProjects { ) } - fn render_create_remote_project(&self, cx: &mut ViewContext) -> impl IntoElement { - let Mode::CreateRemoteProject(CreateRemoteProject { + fn render_create_dev_server_project(&self, cx: &mut ViewContext) -> impl IntoElement { + let Mode::CreateDevServerProject(CreateDevServerProject { dev_server_id, creating, - remote_project, + dev_server_project, }) = &self.mode else { unreachable!() }; let dev_server = self - .remote_project_store + .dev_server_store .read(cx) .dev_server(*dev_server_id) .cloned(); @@ -672,12 +673,12 @@ impl RemoteProjects { h_flex() .ml_5() .gap_2() - .child(self.remote_project_path_input.clone()) - .when(!*creating && remote_project.is_none(), |div| { + .child(self.project_path_input.clone()) + .when(!*creating && dev_server_project.is_none(), |div| { div.child(Button::new("create-remote-server", "Create").on_click({ let dev_server_id = *dev_server_id; cx.listener(move |this, _, cx| { - this.create_remote_project(dev_server_id, cx) + this.create_dev_server_project(dev_server_id, cx) }) })) }) @@ -685,11 +686,11 @@ impl RemoteProjects { div.child(Button::new("create-dev-server", "Creating...").disabled(true)) }), ) - .when_some(remote_project.clone(), |div, remote_project| { + .when_some(dev_server_project.clone(), |div, dev_server_project| { let status = self - .remote_project_store + .dev_server_store .read(cx) - .remote_project(RemoteProjectId(remote_project.id)) + .dev_server_project(DevServerProjectId(dev_server_project.id)) .map(|project| { if project.project_id.is_some() { DevServerStatus::Online @@ -717,17 +718,17 @@ impl RemoteProjects { }) } } -impl ModalView for RemoteProjects {} +impl ModalView for DevServerProjects {} -impl FocusableView for RemoteProjects { +impl FocusableView for DevServerProjects { fn focus_handle(&self, _cx: &AppContext) -> FocusHandle { self.focus_handle.clone() } } -impl EventEmitter for RemoteProjects {} +impl EventEmitter for DevServerProjects {} -impl Render for RemoteProjects { +impl Render for DevServerProjects { fn render(&mut self, cx: &mut ViewContext) -> impl IntoElement { div() .track_focus(&self.focus_handle) @@ -746,8 +747,8 @@ impl Render for RemoteProjects { .max_h(rems(40.)) .child(match &self.mode { Mode::Default => self.render_default(cx).into_any_element(), - Mode::CreateRemoteProject(_) => { - self.render_create_remote_project(cx).into_any_element() + Mode::CreateDevServerProject(_) => { + self.render_create_dev_server_project(cx).into_any_element() } Mode::CreateDevServer(_) => self.render_create_dev_server(cx).into_any_element(), }) diff --git a/crates/recent_projects/src/recent_projects.rs b/crates/recent_projects/src/recent_projects.rs index 8b26d71c58..7b57e72cb7 100644 --- a/crates/recent_projects/src/recent_projects.rs +++ b/crates/recent_projects/src/recent_projects.rs @@ -1,5 +1,6 @@ -mod remote_projects; +mod dev_servers; +pub use dev_servers::DevServerProjects; use feature_flags::FeatureFlagAppExt; use fuzzy::{StringMatch, StringMatchCandidate}; use gpui::{ @@ -11,7 +12,6 @@ use picker::{ highlighted_match_with_paths::{HighlightedMatchWithPaths, HighlightedText}, Picker, PickerDelegate, }; -pub use remote_projects::RemoteProjects; use rpc::proto::DevServerStatus; use serde::Deserialize; use std::{ @@ -42,8 +42,7 @@ gpui::actions!(projects, [OpenRemote]); pub fn init(cx: &mut AppContext) { cx.observe_new_views(RecentProjects::register).detach(); - cx.observe_new_views(remote_projects::RemoteProjects::register) - .detach(); + cx.observe_new_views(DevServerProjects::register).detach(); } pub struct RecentProjects { @@ -158,7 +157,7 @@ pub struct RecentProjectsDelegate { create_new_window: bool, // Flag to reset index when there is a new query vs not reset index when user delete an item reset_selected_match_index: bool, - has_any_remote_projects: bool, + has_any_dev_server_projects: bool, } impl RecentProjectsDelegate { @@ -171,16 +170,16 @@ impl RecentProjectsDelegate { create_new_window, render_paths, reset_selected_match_index: true, - has_any_remote_projects: false, + has_any_dev_server_projects: false, } } pub fn set_workspaces(&mut self, workspaces: Vec<(WorkspaceId, SerializedWorkspaceLocation)>) { self.workspaces = workspaces; - self.has_any_remote_projects = self + self.has_any_dev_server_projects = self .workspaces .iter() - .any(|(_, location)| matches!(location, SerializedWorkspaceLocation::Remote(_))); + .any(|(_, location)| matches!(location, SerializedWorkspaceLocation::DevServer(_))); } } impl EventEmitter for RecentProjectsDelegate {} @@ -235,8 +234,11 @@ impl PickerDelegate for RecentProjectsDelegate { .map(|path| path.compact().to_string_lossy().into_owned()) .collect::>() .join(""), - SerializedWorkspaceLocation::Remote(remote_project) => { - format!("{}{}", remote_project.dev_server_name, remote_project.path) + SerializedWorkspaceLocation::DevServer(dev_server_project) => { + format!( + "{}{}", + dev_server_project.dev_server_name, dev_server_project.path + ) } }; @@ -310,13 +312,13 @@ impl PickerDelegate for RecentProjectsDelegate { workspace.open_workspace_for_paths(false, paths, cx) } } - SerializedWorkspaceLocation::Remote(remote_project) => { - let store = ::remote_projects::Store::global(cx).read(cx); + SerializedWorkspaceLocation::DevServer(dev_server_project) => { + let store = dev_server_projects::Store::global(cx).read(cx); let Some(project_id) = store - .remote_project(remote_project.id) + .dev_server_project(dev_server_project.id) .and_then(|p| p.project_id) else { - let dev_server_name = remote_project.dev_server_name.clone(); + let dev_server_name = dev_server_project.dev_server_name.clone(); return cx.spawn(|workspace, mut cx| async move { let response = cx.prompt(gpui::PromptLevel::Warning, @@ -326,7 +328,7 @@ impl PickerDelegate for RecentProjectsDelegate { ).await?; if response == 1 { workspace.update(&mut cx, |workspace, cx| { - workspace.toggle_modal(cx, |cx| RemoteProjects::new(cx)) + workspace.toggle_modal(cx, |cx| DevServerProjects::new(cx)) })?; } else { workspace.update(&mut cx, |workspace, cx| { @@ -354,7 +356,7 @@ impl PickerDelegate for RecentProjectsDelegate { if continue_replacing { workspace .update(&mut cx, |_workspace, cx| { - workspace::join_remote_project(project_id, app_state, Some(handle), cx) + workspace::join_dev_server_project(project_id, app_state, Some(handle), cx) })? .await?; } @@ -363,7 +365,7 @@ impl PickerDelegate for RecentProjectsDelegate { } else { let task = - workspace::join_remote_project(project_id, app_state, None, cx); + workspace::join_dev_server_project(project_id, app_state, None, cx); cx.spawn(|_, _| async move { task.await?; Ok(()) @@ -404,13 +406,13 @@ impl PickerDelegate for RecentProjectsDelegate { let (workspace_id, location) = &self.workspaces[hit.candidate_id]; let is_current_workspace = self.is_current_workspace(*workspace_id, cx); - let is_remote = matches!(location, SerializedWorkspaceLocation::Remote(_)); + let is_remote = matches!(location, SerializedWorkspaceLocation::DevServer(_)); let dev_server_status = - if let SerializedWorkspaceLocation::Remote(remote_project) = location { - let store = ::remote_projects::Store::global(cx).read(cx); + if let SerializedWorkspaceLocation::DevServer(dev_server_project) = location { + let store = dev_server_projects::Store::global(cx).read(cx); Some( store - .remote_project(remote_project.id) + .dev_server_project(dev_server_project.id) .and_then(|p| store.dev_server(p.dev_server_id)) .map(|s| s.status) .unwrap_or_default(), @@ -422,9 +424,12 @@ impl PickerDelegate for RecentProjectsDelegate { let mut path_start_offset = 0; let paths = match location { SerializedWorkspaceLocation::Local(paths) => paths.paths(), - SerializedWorkspaceLocation::Remote(remote_project) => Arc::new(vec![PathBuf::from( - format!("{}:{}", remote_project.dev_server_name, remote_project.path), - )]), + SerializedWorkspaceLocation::DevServer(dev_server_project) => { + Arc::new(vec![PathBuf::from(format!( + "{}:{}", + dev_server_project.dev_server_name, dev_server_project.path + ))]) + } }; let (match_labels, paths): (Vec<_>, Vec<_>) = paths @@ -459,7 +464,7 @@ impl PickerDelegate for RecentProjectsDelegate { h_flex() .flex_grow() .gap_3() - .when(self.has_any_remote_projects, |this| { + .when(self.has_any_dev_server_projects, |this| { this.child(if is_remote { // if disabled, Color::Disabled let indicator_color = match dev_server_status { @@ -540,7 +545,7 @@ impl PickerDelegate for RecentProjectsDelegate { .when_some(KeyBinding::for_action(&OpenRemote, cx), |button, key| { button.child(key) }) - .child(Label::new("Connect remote…").color(Color::Muted)) + .child(Label::new("Connect…").color(Color::Muted)) .on_click(|_, cx| cx.dispatch_action(OpenRemote.boxed_clone())), ) .child( diff --git a/crates/rpc/proto/zed.proto b/crates/rpc/proto/zed.proto index 15cb0e33c1..cde0908ba0 100644 --- a/crates/rpc/proto/zed.proto +++ b/crates/rpc/proto/zed.proto @@ -220,8 +220,8 @@ message Envelope { MultiLspQuery multi_lsp_query = 175; MultiLspQueryResponse multi_lsp_query_response = 176; - CreateRemoteProject create_remote_project = 177; - CreateRemoteProjectResponse create_remote_project_response = 188; + CreateDevServerProject create_dev_server_project = 177; + CreateDevServerProjectResponse create_dev_server_project_response = 188; CreateDevServer create_dev_server = 178; CreateDevServerResponse create_dev_server_response = 179; ShutdownDevServer shutdown_dev_server = 180; @@ -229,13 +229,13 @@ message Envelope { ReconnectDevServer reconnect_dev_server = 182; ReconnectDevServerResponse reconnect_dev_server_response = 183; - ShareRemoteProject share_remote_project = 184; - JoinRemoteProject join_remote_project = 185; + ShareDevServerProject share_dev_server_project = 184; + JoinDevServerProject join_dev_server_project = 185; RejoinRemoteProjects rejoin_remote_projects = 186; RejoinRemoteProjectsResponse rejoin_remote_projects_response = 187; - RemoteProjectsUpdate remote_projects_update = 193; - ValidateRemoteProjectRequest validate_remote_project_request = 194; + DevServerProjectsUpdate dev_server_projects_update = 193; + ValidateDevServerProjectRequest validate_dev_server_project_request = 194; DeleteDevServer delete_dev_server = 195; OpenNewBuffer open_new_buffer = 196; // Current max } @@ -275,7 +275,7 @@ enum ErrorCode { NoSuchProject = 13; DevServerAlreadyOnline = 14; DevServerOffline = 15; - RemoteProjectPathDoesNotExist = 16; + DevServerProjectPathDoesNotExist = 16; RemoteUpgradeRequired = 17; reserved 6; } @@ -441,7 +441,7 @@ message LiveKitConnectionInfo { message ShareProject { uint64 room_id = 1; repeated WorktreeMetadata worktrees = 2; - optional uint64 remote_project_id = 3; + optional uint64 dev_server_project_id = 3; } message ShareProjectResponse { @@ -465,17 +465,17 @@ message JoinHostedProject { uint64 project_id = 1; } -message CreateRemoteProject { +message CreateDevServerProject { reserved 1; reserved 2; uint64 dev_server_id = 3; string path = 4; } -message CreateRemoteProjectResponse { - RemoteProject remote_project = 1; +message CreateDevServerProjectResponse { + DevServerProject dev_server_project = 1; } -message ValidateRemoteProjectRequest { +message ValidateDevServerProjectRequest { string path = 1; } @@ -507,21 +507,21 @@ message ReconnectDevServerResponse { } message DevServerInstructions { - repeated RemoteProject projects = 1; + repeated DevServerProject projects = 1; } -message RemoteProjectsUpdate { +message DevServerProjectsUpdate { repeated DevServer dev_servers = 1; - repeated RemoteProject remote_projects = 2; + repeated DevServerProject dev_server_projects = 2; } -message ShareRemoteProject { - uint64 remote_project_id = 1; +message ShareDevServerProject { + uint64 dev_server_project_id = 1; repeated WorktreeMetadata worktrees = 2; } -message JoinRemoteProject { - uint64 remote_project_id = 1; +message JoinDevServerProject { + uint64 dev_server_project_id = 1; } message JoinProjectResponse { @@ -531,7 +531,7 @@ message JoinProjectResponse { repeated Collaborator collaborators = 3; repeated LanguageServer language_servers = 4; ChannelRole role = 6; - optional uint64 remote_project_id = 7; + optional uint64 dev_server_project_id = 7; } message LeaveProject { @@ -1211,7 +1211,7 @@ message HostedProject { ChannelVisibility visibility = 4; } -message RemoteProject { +message DevServerProject { uint64 id = 1; optional uint64 project_id = 2; reserved 3; diff --git a/crates/rpc/src/proto.rs b/crates/rpc/src/proto.rs index 317941cb8c..0394ba33ba 100644 --- a/crates/rpc/src/proto.rs +++ b/crates/rpc/src/proto.rs @@ -303,22 +303,22 @@ messages!( (SetRoomParticipantRole, Foreground), (BlameBuffer, Foreground), (BlameBufferResponse, Foreground), - (CreateRemoteProject, Background), - (CreateRemoteProjectResponse, Foreground), + (CreateDevServerProject, Background), + (CreateDevServerProjectResponse, Foreground), (CreateDevServer, Foreground), (CreateDevServerResponse, Foreground), (DevServerInstructions, Foreground), (ShutdownDevServer, Foreground), (ReconnectDevServer, Foreground), (ReconnectDevServerResponse, Foreground), - (ShareRemoteProject, Foreground), - (JoinRemoteProject, Foreground), + (ShareDevServerProject, Foreground), + (JoinDevServerProject, Foreground), (RejoinRemoteProjects, Foreground), (RejoinRemoteProjectsResponse, Foreground), (MultiLspQuery, Background), (MultiLspQueryResponse, Background), - (RemoteProjectsUpdate, Foreground), - (ValidateRemoteProjectRequest, Background), + (DevServerProjectsUpdate, Foreground), + (ValidateDevServerProjectRequest, Background), (DeleteDevServer, Foreground), (OpenNewBuffer, Foreground) ); @@ -415,14 +415,14 @@ request_messages!( (LspExtExpandMacro, LspExtExpandMacroResponse), (SetRoomParticipantRole, Ack), (BlameBuffer, BlameBufferResponse), - (CreateRemoteProject, CreateRemoteProjectResponse), + (CreateDevServerProject, CreateDevServerProjectResponse), (CreateDevServer, CreateDevServerResponse), (ShutdownDevServer, Ack), - (ShareRemoteProject, ShareProjectResponse), - (JoinRemoteProject, JoinProjectResponse), + (ShareDevServerProject, ShareProjectResponse), + (JoinDevServerProject, JoinProjectResponse), (RejoinRemoteProjects, RejoinRemoteProjectsResponse), (ReconnectDevServer, ReconnectDevServerResponse), - (ValidateRemoteProjectRequest, Ack), + (ValidateDevServerProjectRequest, Ack), (MultiLspQuery, MultiLspQueryResponse), (DeleteDevServer, Ack), ); diff --git a/crates/sqlez/src/connection.rs b/crates/sqlez/src/connection.rs index f88d37c7e0..2d5d4c41f5 100644 --- a/crates/sqlez/src/connection.rs +++ b/crates/sqlez/src/connection.rs @@ -223,6 +223,14 @@ fn parse_alter_table(remaining_sql_str: &str) -> Option<(String, String)> { .skip_while(|c| c.is_whitespace()) .take_while(|c| !c.is_whitespace()) .collect::() + } else if let Some(drop_offset) = remaining_sql_str.find("drop column") { + let after_drop_offset = drop_offset + "drop column".len(); + remaining_sql_str + .chars() + .skip(after_drop_offset) + .skip_while(|c| c.is_whitespace()) + .take_while(|c| !c.is_whitespace()) + .collect::() } else { "__place_holder_column_for_syntax_checking".to_string() }; diff --git a/crates/workspace/Cargo.toml b/crates/workspace/Cargo.toml index 3b5a6be2b5..8ff08c07c8 100644 --- a/crates/workspace/Cargo.toml +++ b/crates/workspace/Cargo.toml @@ -45,7 +45,7 @@ node_runtime.workspace = true parking_lot.workspace = true postage.workspace = true project.workspace = true -remote_projects.workspace = true +dev_server_projects.workspace = true task.workspace = true schemars.workspace = true serde.workspace = true diff --git a/crates/workspace/src/persistence.rs b/crates/workspace/src/persistence.rs index 2e507dc1bb..10a5eae004 100644 --- a/crates/workspace/src/persistence.rs +++ b/crates/workspace/src/persistence.rs @@ -3,7 +3,7 @@ pub mod model; use std::path::Path; use anyhow::{anyhow, bail, Context, Result}; -use client::RemoteProjectId; +use client::DevServerProjectId; use db::{define_connection, query, sqlez::connection::Connection, sqlez_macros::sql}; use gpui::{point, size, Axis, Bounds}; @@ -22,7 +22,7 @@ use model::{ SerializedWorkspace, }; -use self::model::{DockStructure, SerializedRemoteProject, SerializedWorkspaceLocation}; +use self::model::{DockStructure, SerializedDevServerProject, SerializedWorkspaceLocation}; #[derive(Copy, Clone, Debug, PartialEq)] pub(crate) struct SerializedAxis(pub(crate) gpui::Axis); @@ -299,6 +299,16 @@ define_connection! { ALTER TABLE workspaces ADD COLUMN remote_project_id INTEGER; ALTER TABLE workspaces RENAME COLUMN workspace_location TO local_paths; ), + sql!( + DROP TABLE remote_projects; + CREATE TABLE dev_server_projects ( + id INTEGER NOT NULL UNIQUE, + path TEXT, + dev_server_name TEXT + ); + ALTER TABLE workspaces DROP COLUMN remote_project_id; + ALTER TABLE workspaces ADD COLUMN dev_server_project_id INTEGER; + ), ]; } @@ -317,7 +327,7 @@ impl WorkspaceDb { let ( workspace_id, local_paths, - remote_project_id, + dev_server_project_id, bounds, display, fullscreen, @@ -337,7 +347,7 @@ impl WorkspaceDb { SELECT workspace_id, local_paths, - remote_project_id, + dev_server_project_id, window_state, window_x, window_y, @@ -363,18 +373,18 @@ impl WorkspaceDb { .warn_on_err() .flatten()?; - let location = if let Some(remote_project_id) = remote_project_id { - let remote_project: SerializedRemoteProject = self + let location = if let Some(dev_server_project_id) = dev_server_project_id { + let dev_server_project: SerializedDevServerProject = self .select_row_bound(sql! { - SELECT remote_project_id, path, dev_server_name - FROM remote_projects - WHERE remote_project_id = ? + SELECT id, path, dev_server_name + FROM dev_server_projects + WHERE id = ? }) - .and_then(|mut prepared_statement| (prepared_statement)(remote_project_id)) + .and_then(|mut prepared_statement| (prepared_statement)(dev_server_project_id)) .context("No remote project found") .warn_on_err() .flatten()?; - SerializedWorkspaceLocation::Remote(remote_project) + SerializedWorkspaceLocation::DevServer(dev_server_project) } else if let Some(local_paths) = local_paths { SerializedWorkspaceLocation::Local(local_paths) } else { @@ -447,15 +457,15 @@ impl WorkspaceDb { ))?((workspace.id, &local_paths, workspace.docks)) .context("Updating workspace")?; } - SerializedWorkspaceLocation::Remote(remote_project) => { + SerializedWorkspaceLocation::DevServer(dev_server_project) => { conn.exec_bound(sql!( - DELETE FROM workspaces WHERE remote_project_id = ? AND workspace_id != ? - ))?((remote_project.id.0, workspace.id)) + DELETE FROM workspaces WHERE dev_server_project_id = ? AND workspace_id != ? + ))?((dev_server_project.id.0, workspace.id)) .context("clearing out old locations")?; conn.exec_bound(sql!( - INSERT INTO remote_projects( - remote_project_id, + INSERT INTO dev_server_projects( + id, path, dev_server_name ) VALUES (?1, ?2, ?3) @@ -463,13 +473,13 @@ impl WorkspaceDb { UPDATE SET path = ?2, dev_server_name = ?3 - ))?(&remote_project)?; + ))?(&dev_server_project)?; // Upsert conn.exec_bound(sql!( INSERT INTO workspaces( workspace_id, - remote_project_id, + dev_server_project_id, left_dock_visible, left_dock_active_panel, left_dock_zoom, @@ -484,7 +494,7 @@ impl WorkspaceDb { VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, CURRENT_TIMESTAMP) ON CONFLICT DO UPDATE SET - remote_project_id = ?2, + dev_server_project_id = ?2, left_dock_visible = ?3, left_dock_active_panel = ?4, left_dock_zoom = ?5, @@ -497,7 +507,7 @@ impl WorkspaceDb { timestamp = CURRENT_TIMESTAMP ))?(( workspace.id, - remote_project.id.0, + dev_server_project.id.0, workspace.docks, )) .context("Updating workspace")?; @@ -523,17 +533,17 @@ impl WorkspaceDb { query! { fn recent_workspaces() -> Result)>> { - SELECT workspace_id, local_paths, remote_project_id + SELECT workspace_id, local_paths, dev_server_project_id FROM workspaces - WHERE local_paths IS NOT NULL OR remote_project_id IS NOT NULL + WHERE local_paths IS NOT NULL OR dev_server_project_id IS NOT NULL ORDER BY timestamp DESC } } query! { - fn remote_projects() -> Result> { - SELECT remote_project_id, path, dev_server_name - FROM remote_projects + fn dev_server_projects() -> Result> { + SELECT id, path, dev_server_name + FROM dev_server_projects } } @@ -573,14 +583,15 @@ impl WorkspaceDb { ) -> Result> { let mut result = Vec::new(); let mut delete_tasks = Vec::new(); - let remote_projects = self.remote_projects()?; + let dev_server_projects = self.dev_server_projects()?; - for (id, location, remote_project_id) in self.recent_workspaces()? { - if let Some(remote_project_id) = remote_project_id.map(RemoteProjectId) { - if let Some(remote_project) = - remote_projects.iter().find(|rp| rp.id == remote_project_id) + for (id, location, dev_server_project_id) in self.recent_workspaces()? { + if let Some(dev_server_project_id) = dev_server_project_id.map(DevServerProjectId) { + if let Some(dev_server_project) = dev_server_projects + .iter() + .find(|rp| rp.id == dev_server_project_id) { - result.push((id, remote_project.clone().into())); + result.push((id, dev_server_project.clone().into())); } else { delete_tasks.push(self.delete_workspace_by_id(id)); } @@ -607,7 +618,7 @@ impl WorkspaceDb { .into_iter() .filter_map(|(_, location)| match location { SerializedWorkspaceLocation::Local(local_paths) => Some(local_paths), - SerializedWorkspaceLocation::Remote(_) => None, + SerializedWorkspaceLocation::DevServer(_) => None, }) .next()) } diff --git a/crates/workspace/src/persistence/model.rs b/crates/workspace/src/persistence/model.rs index eb64c31c1f..aef9e04e5d 100644 --- a/crates/workspace/src/persistence/model.rs +++ b/crates/workspace/src/persistence/model.rs @@ -2,7 +2,7 @@ use super::SerializedAxis; use crate::{item::ItemHandle, ItemDeserializers, Member, Pane, PaneAxis, Workspace, WorkspaceId}; use anyhow::{Context, Result}; use async_recursion::async_recursion; -use client::RemoteProjectId; +use client::DevServerProjectId; use db::sqlez::{ bindable::{Bind, Column, StaticColumnCount}, statement::Statement, @@ -18,8 +18,8 @@ use util::ResultExt; use uuid::Uuid; #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)] -pub struct SerializedRemoteProject { - pub id: RemoteProjectId, +pub struct SerializedDevServerProject { + pub id: DevServerProjectId, pub dev_server_name: String, pub path: String, } @@ -68,14 +68,14 @@ impl Column for LocalPaths { } } -impl From for SerializedWorkspaceLocation { - fn from(remote_project: SerializedRemoteProject) -> Self { - Self::Remote(remote_project) +impl From for SerializedWorkspaceLocation { + fn from(dev_server_project: SerializedDevServerProject) -> Self { + Self::DevServer(dev_server_project) } } -impl StaticColumnCount for SerializedRemoteProject {} -impl Bind for &SerializedRemoteProject { +impl StaticColumnCount for SerializedDevServerProject {} +impl Bind for &SerializedDevServerProject { fn bind(&self, statement: &Statement, start_index: i32) -> Result { let next_index = statement.bind(&self.id.0, start_index)?; let next_index = statement.bind(&self.dev_server_name, next_index)?; @@ -83,14 +83,14 @@ impl Bind for &SerializedRemoteProject { } } -impl Column for SerializedRemoteProject { +impl Column for SerializedDevServerProject { fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> { let id = statement.column_int64(start_index)?; let dev_server_name = statement.column_text(start_index + 1)?.to_string(); let path = statement.column_text(start_index + 2)?.to_string(); Ok(( Self { - id: RemoteProjectId(id as u64), + id: DevServerProjectId(id as u64), dev_server_name, path, }, @@ -102,7 +102,7 @@ impl Column for SerializedRemoteProject { #[derive(Debug, PartialEq, Clone)] pub enum SerializedWorkspaceLocation { Local(LocalPaths), - Remote(SerializedRemoteProject), + DevServer(SerializedDevServerProject), } #[derive(Debug, PartialEq, Clone)] diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 35a2a538a5..dc08370447 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -47,7 +47,7 @@ pub use pane::*; pub use pane_group::*; use persistence::{model::SerializedWorkspace, SerializedWindowsBounds, DB}; pub use persistence::{ - model::{ItemId, LocalPaths, SerializedRemoteProject, SerializedWorkspaceLocation}, + model::{ItemId, LocalPaths, SerializedDevServerProject, SerializedWorkspaceLocation}, WorkspaceDb, DB as WORKSPACE_DB, }; use postage::stream::Stream; @@ -3644,18 +3644,19 @@ impl Workspace { } else { None } - } else if let Some(remote_project_id) = self.project().read(cx).remote_project_id() { - let store = remote_projects::Store::global(cx).read(cx); + } else if let Some(dev_server_project_id) = self.project().read(cx).dev_server_project_id() + { + let store = dev_server_projects::Store::global(cx).read(cx); maybe!({ - let project = store.remote_project(remote_project_id)?; + let project = store.dev_server_project(dev_server_project_id)?; let dev_server = store.dev_server(project.dev_server_id)?; - let remote_project = SerializedRemoteProject { - id: remote_project_id, + let dev_server_project = SerializedDevServerProject { + id: dev_server_project_id, dev_server_name: dev_server.name.to_string(), path: project.path.to_string(), }; - Some(SerializedWorkspaceLocation::Remote(remote_project)) + Some(SerializedWorkspaceLocation::DevServer(dev_server_project)) }) } else { None @@ -4537,7 +4538,7 @@ async fn join_channel_internal( return None; } let project = workspace.project.read(cx); - if (project.is_local() || project.remote_project_id().is_some()) + if (project.is_local() || project.dev_server_project_id().is_some()) && project.visible_worktrees(cx).any(|tree| { tree.read(cx) .root_entry() @@ -4883,7 +4884,7 @@ pub fn join_hosted_project( }) } -pub fn join_remote_project( +pub fn join_dev_server_project( project_id: ProjectId, app_state: Arc, window_to_replace: Option>, diff --git a/crates/zed/Cargo.toml b/crates/zed/Cargo.toml index bc5df1b063..9a9f40020a 100644 --- a/crates/zed/Cargo.toml +++ b/crates/zed/Cargo.toml @@ -73,7 +73,7 @@ project_panel.workspace = true project_symbols.workspace = true quick_action_bar.workspace = true recent_projects.workspace = true -remote_projects.workspace = true +dev_server_projects.workspace = true release_channel.workspace = true rope.workspace = true search.workspace = true diff --git a/crates/zed/src/main.rs b/crates/zed/src/main.rs index df37bc15f8..9850a2f603 100644 --- a/crates/zed/src/main.rs +++ b/crates/zed/src/main.rs @@ -290,7 +290,7 @@ fn init_ui(args: Args) { ThemeRegistry::global(cx), cx, ); - remote_projects::init(client.clone(), cx); + dev_server_projects::init(client.clone(), cx); load_user_themes_in_background(fs.clone(), cx); watch_themes(fs.clone(), cx);