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