Rename RemoteProject -> DevServerProject (#11301)

Conrad Irwin , Mikayla , and Bennet created

Co-Authored-By: Mikayla <mikayla@zed.dev>

In a fit of ill-advisedness I called these things remote projects;
forgetting that remote project is also what we call collaboratively
shared projects.

Release Notes:

- N/A

---------

Co-authored-by: Mikayla <mikayla@zed.dev>
Co-authored-by: Bennet <bennetbo@gmx.de>

Change summary

Cargo.lock                                                                |  34 
Cargo.toml                                                                |   4 
crates/call/src/room.rs                                                   |   7 
crates/client/src/user.rs                                                 |   2 
crates/collab/Cargo.toml                                                  |   2 
crates/collab/migrations.sqlite/20221109000000_test_schema.sql            |   6 
crates/collab/migrations/20240502150229_rename_to_dev_server_projects.sql |  11 
crates/collab/src/db.rs                                                   |   2 
crates/collab/src/db/ids.rs                                               |   2 
crates/collab/src/db/queries.rs                                           |   2 
crates/collab/src/db/queries/dev_server_projects.rs                       | 295 
crates/collab/src/db/queries/dev_servers.rs                               |  46 
crates/collab/src/db/queries/projects.rs                                  |  24 
crates/collab/src/db/queries/remote_projects.rs                           | 282 
crates/collab/src/db/queries/rooms.rs                                     |  22 
crates/collab/src/db/tables.rs                                            |   2 
crates/collab/src/db/tables/dev_server.rs                                 |   4 
crates/collab/src/db/tables/dev_server_project.rs                         |  10 
crates/collab/src/db/tables/project.rs                                    |  12 
crates/collab/src/rpc.rs                                                  | 104 
crates/collab/src/tests/channel_buffer_tests.rs                           |   2 
crates/collab/src/tests/dev_server_tests.rs                               |  44 
crates/collab/src/tests/editor_tests.rs                                   |  28 
crates/collab/src/tests/following_tests.rs                                |  16 
crates/collab/src/tests/integration_tests.rs                              |  72 
crates/collab/src/tests/random_project_collaboration_tests.rs             |  32 
crates/collab/src/tests/randomized_test_helpers.rs                        |   2 
crates/collab/src/tests/test_server.rs                                    |  16 
crates/collab_ui/Cargo.toml                                               |   2 
crates/collab_ui/src/collab_titlebar_item.rs                              |  16 
crates/dev_server_projects/Cargo.toml                                     |   4 
crates/dev_server_projects/src/dev_server_projects.rs                     |  56 
crates/headless/src/headless.rs                                           |  36 
crates/project/src/project.rs                                             |  22 
crates/recent_projects/Cargo.toml                                         |   2 
crates/recent_projects/src/dev_servers.rs                                 | 133 
crates/recent_projects/src/recent_projects.rs                             |  57 
crates/rpc/proto/zed.proto                                                |  42 
crates/rpc/src/proto.rs                                                   |  20 
crates/sqlez/src/connection.rs                                            |   8 
crates/workspace/Cargo.toml                                               |   2 
crates/workspace/src/persistence.rs                                       |  75 
crates/workspace/src/persistence/model.rs                                 |  22 
crates/workspace/src/workspace.rs                                         |  19 
crates/zed/Cargo.toml                                                     |   2 
crates/zed/src/main.rs                                                    |   2 
46 files changed, 834 insertions(+), 771 deletions(-)

Detailed changes

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",

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" }

crates/call/src/room.rs πŸ”—

@@ -1203,11 +1203,12 @@ impl Room {
         project: Model<Project>,
         cx: &mut ModelContext<Self>,
     ) -> Task<Result<u64>> {
-        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,
             })
         };
 

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);

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

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);

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;

crates/collab/src/db.rs πŸ”—

@@ -762,7 +762,7 @@ pub struct Project {
     pub collaborators: Vec<ProjectCollaborator>,
     pub worktrees: BTreeMap<u64, Worktree>,
     pub language_servers: Vec<proto::LanguageServer>,
-    pub remote_project_id: Option<RemoteProjectId>,
+    pub dev_server_project_id: Option<DevServerProjectId>,
 }
 
 pub struct ProjectCollaborator {

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);

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;

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<dev_server_project::Model> {
+        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<Vec<proto::DevServerProject>> {
+        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<Vec<DevServerProjectId>> {
+        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<UserId> {
+        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<Vec<ProjectId>> {
+        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<proto::UpdateProject>,
+        dev_server_id: DevServerId,
+        connection: ConnectionId,
+    ) -> crate::Result<Vec<ResharedProject>> {
+        // 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<proto::RejoinProject>,
+        user_id: UserId,
+        connection_id: ConnectionId,
+    ) -> crate::Result<Vec<RejoinedProject>> {
+        // 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
+    }
+}

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<proto::RemoteProjectsUpdate> {
-        self.transaction(
-            |tx| async move { self.remote_projects_update_internal(user_id, &tx).await },
-        )
+    ) -> crate::Result<proto::DevServerProjectsUpdate> {
+        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<proto::RemoteProjectsUpdate> {
+    ) -> crate::Result<proto::DevServerProjectsUpdate> {
         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::<Vec<_>>()),
             )
             .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<proto::RemoteProjectsUpdate> {
+    ) -> crate::Result<proto::DevServerProjectsUpdate> {
         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
     }

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<RemoteProjectId>,
+        dev_server_project_id: Option<DevServerProjectId>,
     ) -> Result<TransactionGuard<(ProjectId, proto::Room)>> {
         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);
 

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<remote_project::Model> {
-        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<Vec<proto::RemoteProject>> {
-        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<Vec<RemoteProjectId>> {
-        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<UserId> {
-        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<Vec<ProjectId>> {
-        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<proto::UpdateProject>,
-        dev_server_id: DevServerId,
-        connection: ConnectionId,
-    ) -> crate::Result<Vec<ResharedProject>> {
-        // 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<proto::RejoinProject>,
-        user_id: UserId,
-        connection_id: ConnectionId,
-    ) -> crate::Result<Vec<RejoinedProject>> {
-        // 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
-    }
-}

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())

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;

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<super::remote_project::Entity> for Entity {
+impl Related<super::dev_server_project::Entity> for Entity {
     fn to() -> RelationDef {
         Relation::RemoteProject.def()
     }

crates/collab/src/db/tables/remote_project.rs β†’ 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<super::dev_server::Entity> for Entity {
 }
 
 impl Model {
-    pub fn to_proto(&self, project: Option<project::Model>) -> proto::RemoteProject {
-        proto::RemoteProject {
+    pub fn to_proto(&self, project: Option<project::Model>) -> 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(),

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<i32>,
     pub host_connection_server_id: Option<ServerId>,
     pub hosted_project_id: Option<HostedProjectId>,
-    pub remote_project_id: Option<RemoteProjectId>,
+    pub dev_server_project_id: Option<DevServerProjectId>,
 }
 
 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<super::hosted_project::Entity> for Entity {
     }
 }
 
-impl Related<super::remote_project::Entity> for Entity {
+impl Related<super::dev_server_project::Entity> for Entity {
     fn to() -> RelationDef {
         Relation::RemoteProject.def()
     }

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<proto::ShareRemoteProject>,
+async fn share_dev_server_project(
+    request: proto::ShareDevServerProject,
+    response: Response<proto::ShareDevServerProject>,
     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<proto::CreateRemoteProject>,
+async fn create_dev_server_project(
+    request: proto::CreateDevServerProject,
+    response: Response<proto::CreateDevServerProject>,
     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<proto::RejoinRemoteProjects>,
     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(())
 }

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.

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<AppState>,
     cx: &mut TestAppContext,
     cx_devserver: &mut TestAppContext,
 ) -> (TestClient, WindowHandle<Workspace>) {
-    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);
 

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| {

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

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();

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::<Vec<_>>()
                             });
-                            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::<Vec<_>>()
                             });
-                            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<TestClient>, 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<Model<
         .local_projects()
         .deref()
         .iter()
-        .chain(client.remote_projects().iter())
+        .chain(client.dev_server_projects().iter())
         .choose(rng)
         .cloned()
 }

crates/collab/src/tests/randomized_test_helpers.rs πŸ”—

@@ -533,7 +533,7 @@ impl<T: RandomizedTest> TestPlan<T> {
                 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(),

crates/collab/src/tests/test_server.rs πŸ”—

@@ -64,7 +64,7 @@ pub struct TestClient {
 #[derive(Default)]
 struct TestClientState {
     local_projects: Vec<Model<Project>>,
-    remote_projects: Vec<Model<Project>>,
+    dev_server_projects: Vec<Model<Project>>,
     buffers: HashMap<Model<Project>, HashSet<Model<language::Buffer>>>,
     channel_buffers: HashSet<Model<ChannelBuffer>>,
 }
@@ -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<Target = Vec<Model<Project>>> + '_ {
-        Ref::map(self.state.borrow(), |state| &state.remote_projects)
+    pub fn dev_server_projects(&self) -> impl Deref<Target = Vec<Model<Project>>> + '_ {
+        Ref::map(self.state.borrow(), |state| &state.dev_server_projects)
     }
 
     pub fn local_projects_mut(&self) -> impl DerefMut<Target = Vec<Model<Project>>> + '_ {
         RefMut::map(self.state.borrow_mut(), |state| &mut state.local_projects)
     }
 
-    pub fn remote_projects_mut(&self) -> impl DerefMut<Target = Vec<Model<Project>>> + '_ {
-        RefMut::map(self.state.borrow_mut(), |state| &mut state.remote_projects)
+    pub fn dev_server_projects_mut(&self) -> impl DerefMut<Target = Vec<Model<Project>>> + '_ {
+        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,

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

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(),

crates/remote_projects/Cargo.toml β†’ 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]

crates/remote_projects/src/remote_projects.rs β†’ 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<RemoteProjectId, RemoteProject>,
+    dev_server_projects: HashMap<DevServerProjectId, DevServerProject>,
     dev_servers: HashMap<DevServerId, DevServer>,
     _subscriptions: Vec<client::Subscription>,
     client: Arc<Client>,
 }
 
 #[derive(Debug, Clone)]
-pub struct RemoteProject {
-    pub id: RemoteProjectId,
+pub struct DevServerProject {
+    pub id: DevServerProjectId,
     pub project_id: Option<ProjectId>,
     pub path: SharedString,
     pub dev_server_id: DevServerId,
 }
 
-impl From<proto::RemoteProject> for RemoteProject {
-    fn from(project: proto::RemoteProject) -> Self {
+impl From<proto::DevServerProject> 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<Client>, cx: &ModelContext<Self>) -> 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<RemoteProject> {
-        let mut projects: Vec<RemoteProject> = self
-            .remote_projects
+    pub fn projects_for_server(&self, id: DevServerId) -> Vec<DevServerProject> {
+        let mut projects: Vec<DevServerProject> = 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<RemoteProject> {
-        let mut projects: Vec<RemoteProject> = self.remote_projects.values().cloned().collect();
+    pub fn dev_server_projects(&self) -> Vec<DevServerProject> {
+        let mut projects: Vec<DevServerProject> =
+            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<Self>,
-        envelope: TypedEnvelope<proto::RemoteProjectsUpdate>,
+        envelope: TypedEnvelope<proto::DevServerProjectsUpdate>,
         _: Arc<Client>,
         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<Self>,
-    ) -> Task<Result<proto::CreateRemoteProjectResponse>> {
+    ) -> Task<Result<proto::CreateDevServerProjectResponse>> {
         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,
                 })

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<Client>,
     app_state: AppState,
     remote_shutdown: bool,
-    projects: HashMap<RemoteProjectId, Model<Project>>,
+    projects: HashMap<DevServerProjectId, Model<Project>>,
     _subscriptions: Vec<client::Subscription>,
     _maintain_connection: Task<Option<()>>,
 }
@@ -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::<Vec<_>>();
@@ -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::<Vec<_>>();
 
             (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<Self>,
-        envelope: TypedEnvelope<proto::ValidateRemoteProjectRequest>,
+        envelope: TypedEnvelope<proto::ValidateDevServerProjectRequest>,
         _: Arc<Client>,
         cx: AsyncAppContext,
     ) -> Result<proto::Ack> {
@@ -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<Self>,
     ) -> 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<Self>,
-        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(())
     }

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<PathBuf, PrettierInstance>,
     tasks: Model<Inventory>,
     hosted_project_id: Option<ProjectId>,
-    remote_project_id: Option<client::RemoteProjectId>,
+    dev_server_project_id: Option<client::DevServerProjectId>,
     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<RemoteProjectId> {
-        self.remote_project_id
+    pub fn dev_server_project_id(&self) -> Option<DevServerProjectId> {
+        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<Self>) -> 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
                 }

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

crates/recent_projects/src/remote_projects.rs β†’ 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_projects::Store>,
-    remote_project_path_input: View<TextField>,
+    dev_server_store: Model<dev_server_projects::Store>,
+    project_path_input: View<TextField>,
     dev_server_name_input: View<TextField>,
     _subscription: gpui::Subscription,
 }
@@ -36,19 +36,19 @@ struct CreateDevServer {
     dev_server: Option<CreateDevServerResponse>,
 }
 
-struct CreateRemoteProject {
+struct CreateDevServerProject {
     dev_server_id: DevServerId,
     creating: bool,
-    remote_project: Option<proto::RemoteProject>,
+    dev_server_project: Option<proto::DevServerProject>,
 }
 
 enum Mode {
     Default,
-    CreateRemoteProject(CreateRemoteProject),
+    CreateDevServerProject(CreateDevServerProject),
     CreateDevServer(CreateDevServer),
 }
 
-impl RemoteProjects {
+impl DevServerProjects {
     pub fn register(_: &mut Workspace, cx: &mut ViewContext<Workspace>) {
         cx.observe_flag::<feature_flags::Remoting, _>(|enabled, workspace, _| {
             if enabled {
@@ -67,14 +67,14 @@ impl RemoteProjects {
     }
 
     pub fn new(cx: &mut ViewContext<Self>) -> 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<Self>,
     ) {
         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<Self>) {
         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<Self>) {
         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<Self>,
     ) -> 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<Self>) -> 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<Self>) -> impl IntoElement {
-        let Mode::CreateRemoteProject(CreateRemoteProject {
+    fn render_create_dev_server_project(&self, cx: &mut ViewContext<Self>) -> 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<DismissEvent> for RemoteProjects {}
+impl EventEmitter<DismissEvent> for DevServerProjects {}
 
-impl Render for RemoteProjects {
+impl Render for DevServerProjects {
     fn render(&mut self, cx: &mut ViewContext<Self>) -> 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(),
             })

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<DismissEvent> for RecentProjectsDelegate {}
@@ -235,8 +234,11 @@ impl PickerDelegate for RecentProjectsDelegate {
                         .map(|path| path.compact().to_string_lossy().into_owned())
                         .collect::<Vec<_>>()
                         .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(

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;

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),
 );

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::<String>()
+                    } 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::<String>()
                     } else {
                         "__place_holder_column_for_syntax_checking".to_string()
                     };

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

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<Vec<(WorkspaceId, LocalPaths, Option<u64>)>> {
-            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<Vec<SerializedRemoteProject>> {
-            SELECT remote_project_id, path, dev_server_name
-            FROM remote_projects
+        fn dev_server_projects() -> Result<Vec<SerializedDevServerProject>> {
+            SELECT id, path, dev_server_name
+            FROM dev_server_projects
         }
     }
 
@@ -573,14 +583,15 @@ impl WorkspaceDb {
     ) -> Result<Vec<(WorkspaceId, SerializedWorkspaceLocation)>> {
         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())
     }

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<SerializedRemoteProject> for SerializedWorkspaceLocation {
-    fn from(remote_project: SerializedRemoteProject) -> Self {
-        Self::Remote(remote_project)
+impl From<SerializedDevServerProject> 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<i32> {
         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)]

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<AppState>,
     window_to_replace: Option<WindowHandle<Workspace>>,

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

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);