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
46 changed files with 834 additions and 771 deletions
|
@ -93,7 +93,7 @@ notifications = { workspace = true, features = ["test-support"] }
|
|||
pretty_assertions.workspace = true
|
||||
project = { workspace = true, features = ["test-support"] }
|
||||
release_channel.workspace = true
|
||||
remote_projects.workspace = true
|
||||
dev_server_projects.workspace = true
|
||||
rpc = { workspace = true, features = ["test-support"] }
|
||||
sea-orm = { version = "0.12.x", features = ["sqlx-sqlite"] }
|
||||
serde_json.workspace = true
|
||||
|
|
|
@ -51,7 +51,7 @@ CREATE TABLE "projects" (
|
|||
"host_connection_server_id" INTEGER REFERENCES servers (id) ON DELETE CASCADE,
|
||||
"unregistered" BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
"hosted_project_id" INTEGER REFERENCES hosted_projects (id),
|
||||
"remote_project_id" INTEGER REFERENCES remote_projects(id)
|
||||
"dev_server_project_id" INTEGER REFERENCES dev_server_projects(id)
|
||||
);
|
||||
CREATE INDEX "index_projects_on_host_connection_server_id" ON "projects" ("host_connection_server_id");
|
||||
CREATE INDEX "index_projects_on_host_connection_id_and_host_connection_server_id" ON "projects" ("host_connection_id", "host_connection_server_id");
|
||||
|
@ -410,10 +410,8 @@ CREATE TABLE dev_servers (
|
|||
hashed_token TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE remote_projects (
|
||||
CREATE TABLE dev_server_projects (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
dev_server_id INTEGER NOT NULL REFERENCES dev_servers(id),
|
||||
path TEXT NOT NULL
|
||||
);
|
||||
|
||||
ALTER TABLE hosted_projects ADD COLUMN remote_project_id INTEGER REFERENCES remote_projects(id);
|
||||
|
|
|
@ -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 worktrees: BTreeMap<u64, Worktree>,
|
||||
pub language_servers: Vec<proto::LanguageServer>,
|
||||
pub remote_project_id: Option<RemoteProjectId>,
|
||||
pub dev_server_project_id: Option<DevServerProjectId>,
|
||||
}
|
||||
|
||||
pub struct ProjectCollaborator {
|
||||
|
|
|
@ -84,7 +84,7 @@ id_type!(NotificationId);
|
|||
id_type!(NotificationKindId);
|
||||
id_type!(ProjectCollaboratorId);
|
||||
id_type!(ProjectId);
|
||||
id_type!(RemoteProjectId);
|
||||
id_type!(DevServerProjectId);
|
||||
id_type!(ReplicaId);
|
||||
id_type!(RoomId);
|
||||
id_type!(RoomParticipantId);
|
||||
|
|
|
@ -5,6 +5,7 @@ pub mod buffers;
|
|||
pub mod channels;
|
||||
pub mod contacts;
|
||||
pub mod contributors;
|
||||
pub mod dev_server_projects;
|
||||
pub mod dev_servers;
|
||||
pub mod embeddings;
|
||||
pub mod extensions;
|
||||
|
@ -13,7 +14,6 @@ pub mod messages;
|
|||
pub mod notifications;
|
||||
pub mod projects;
|
||||
pub mod rate_buckets;
|
||||
pub mod remote_projects;
|
||||
pub mod rooms;
|
||||
pub mod servers;
|
||||
pub mod users;
|
||||
|
|
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,
|
||||
};
|
||||
|
||||
use super::{dev_server, remote_project, Database, DevServerId, UserId};
|
||||
use super::{dev_server, dev_server_project, Database, DevServerId, UserId};
|
||||
|
||||
impl Database {
|
||||
pub async fn get_dev_server(
|
||||
|
@ -29,43 +29,43 @@ impl Database {
|
|||
.await
|
||||
}
|
||||
|
||||
pub async fn remote_projects_update(
|
||||
pub async fn dev_server_projects_update(
|
||||
&self,
|
||||
user_id: UserId,
|
||||
) -> crate::Result<proto::RemoteProjectsUpdate> {
|
||||
self.transaction(
|
||||
|tx| async move { self.remote_projects_update_internal(user_id, &tx).await },
|
||||
)
|
||||
) -> crate::Result<proto::DevServerProjectsUpdate> {
|
||||
self.transaction(|tx| async move {
|
||||
self.dev_server_projects_update_internal(user_id, &tx).await
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn remote_projects_update_internal(
|
||||
pub async fn dev_server_projects_update_internal(
|
||||
&self,
|
||||
user_id: UserId,
|
||||
tx: &DatabaseTransaction,
|
||||
) -> crate::Result<proto::RemoteProjectsUpdate> {
|
||||
) -> crate::Result<proto::DevServerProjectsUpdate> {
|
||||
let dev_servers = dev_server::Entity::find()
|
||||
.filter(dev_server::Column::UserId.eq(user_id))
|
||||
.all(tx)
|
||||
.await?;
|
||||
|
||||
let remote_projects = remote_project::Entity::find()
|
||||
let dev_server_projects = dev_server_project::Entity::find()
|
||||
.filter(
|
||||
remote_project::Column::DevServerId
|
||||
dev_server_project::Column::DevServerId
|
||||
.is_in(dev_servers.iter().map(|d| d.id).collect::<Vec<_>>()),
|
||||
)
|
||||
.find_also_related(super::project::Entity)
|
||||
.all(tx)
|
||||
.await?;
|
||||
|
||||
Ok(proto::RemoteProjectsUpdate {
|
||||
Ok(proto::DevServerProjectsUpdate {
|
||||
dev_servers: dev_servers
|
||||
.into_iter()
|
||||
.map(|d| d.to_proto(proto::DevServerStatus::Offline))
|
||||
.collect(),
|
||||
remote_projects: remote_projects
|
||||
dev_server_projects: dev_server_projects
|
||||
.into_iter()
|
||||
.map(|(remote_project, project)| remote_project.to_proto(project))
|
||||
.map(|(dev_server_project, project)| dev_server_project.to_proto(project))
|
||||
.collect(),
|
||||
})
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ impl Database {
|
|||
name: &str,
|
||||
hashed_access_token: &str,
|
||||
user_id: UserId,
|
||||
) -> crate::Result<(dev_server::Model, proto::RemoteProjectsUpdate)> {
|
||||
) -> crate::Result<(dev_server::Model, proto::DevServerProjectsUpdate)> {
|
||||
self.transaction(|tx| async move {
|
||||
let dev_server = dev_server::Entity::insert(dev_server::ActiveModel {
|
||||
id: ActiveValue::NotSet,
|
||||
|
@ -86,9 +86,11 @@ impl Database {
|
|||
.exec_with_returning(&*tx)
|
||||
.await?;
|
||||
|
||||
let remote_projects = self.remote_projects_update_internal(user_id, &tx).await?;
|
||||
let dev_server_projects = self
|
||||
.dev_server_projects_update_internal(user_id, &tx)
|
||||
.await?;
|
||||
|
||||
Ok((dev_server, remote_projects))
|
||||
Ok((dev_server, dev_server_projects))
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
@ -97,7 +99,7 @@ impl Database {
|
|||
&self,
|
||||
id: DevServerId,
|
||||
user_id: UserId,
|
||||
) -> crate::Result<proto::RemoteProjectsUpdate> {
|
||||
) -> crate::Result<proto::DevServerProjectsUpdate> {
|
||||
self.transaction(|tx| async move {
|
||||
let Some(dev_server) = dev_server::Entity::find_by_id(id).one(&*tx).await? else {
|
||||
return Err(anyhow::anyhow!("no dev server with id {}", id))?;
|
||||
|
@ -106,8 +108,8 @@ impl Database {
|
|||
return Err(anyhow::anyhow!(proto::ErrorCode::Forbidden))?;
|
||||
}
|
||||
|
||||
remote_project::Entity::delete_many()
|
||||
.filter(remote_project::Column::DevServerId.eq(id))
|
||||
dev_server_project::Entity::delete_many()
|
||||
.filter(dev_server_project::Column::DevServerId.eq(id))
|
||||
.exec(&*tx)
|
||||
.await?;
|
||||
|
||||
|
@ -115,9 +117,11 @@ impl Database {
|
|||
.exec(&*tx)
|
||||
.await?;
|
||||
|
||||
let remote_projects = self.remote_projects_update_internal(user_id, &tx).await?;
|
||||
let dev_server_projects = self
|
||||
.dev_server_projects_update_internal(user_id, &tx)
|
||||
.await?;
|
||||
|
||||
Ok(remote_projects)
|
||||
Ok(dev_server_projects)
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ impl Database {
|
|||
room_id: RoomId,
|
||||
connection: ConnectionId,
|
||||
worktrees: &[proto::WorktreeMetadata],
|
||||
remote_project_id: Option<RemoteProjectId>,
|
||||
dev_server_project_id: Option<DevServerProjectId>,
|
||||
) -> Result<TransactionGuard<(ProjectId, proto::Room)>> {
|
||||
self.room_transaction(room_id, |tx| async move {
|
||||
let participant = room_participant::Entity::find()
|
||||
|
@ -59,9 +59,9 @@ impl Database {
|
|||
return Err(anyhow!("guests cannot share projects"))?;
|
||||
}
|
||||
|
||||
if let Some(remote_project_id) = remote_project_id {
|
||||
if let Some(dev_server_project_id) = dev_server_project_id {
|
||||
let project = project::Entity::find()
|
||||
.filter(project::Column::RemoteProjectId.eq(Some(remote_project_id)))
|
||||
.filter(project::Column::DevServerProjectId.eq(Some(dev_server_project_id)))
|
||||
.one(&*tx)
|
||||
.await?
|
||||
.ok_or_else(|| anyhow!("no remote project"))?;
|
||||
|
@ -92,7 +92,7 @@ impl Database {
|
|||
))),
|
||||
id: ActiveValue::NotSet,
|
||||
hosted_project_id: ActiveValue::Set(None),
|
||||
remote_project_id: ActiveValue::Set(None),
|
||||
dev_server_project_id: ActiveValue::Set(None),
|
||||
}
|
||||
.insert(&*tx)
|
||||
.await?;
|
||||
|
@ -155,11 +155,11 @@ impl Database {
|
|||
.await?;
|
||||
return Ok((room, guest_connection_ids));
|
||||
}
|
||||
if let Some(remote_project_id) = project.remote_project_id {
|
||||
if let Some(dev_server_project_id) = project.dev_server_project_id {
|
||||
if let Some(user_id) = user_id {
|
||||
if user_id
|
||||
!= self
|
||||
.owner_for_remote_project(remote_project_id, &tx)
|
||||
.owner_for_dev_server_project(dev_server_project_id, &tx)
|
||||
.await?
|
||||
{
|
||||
Err(anyhow!("cannot unshare a project hosted by another user"))?
|
||||
|
@ -797,7 +797,7 @@ impl Database {
|
|||
name: language_server.name,
|
||||
})
|
||||
.collect(),
|
||||
remote_project_id: project.remote_project_id,
|
||||
dev_server_project_id: project.dev_server_project_id,
|
||||
};
|
||||
Ok((project, replica_id as ReplicaId))
|
||||
}
|
||||
|
@ -957,8 +957,8 @@ impl Database {
|
|||
capability: Capability,
|
||||
tx: &DatabaseTransaction,
|
||||
) -> Result<(project::Model, ChannelRole)> {
|
||||
let (mut project, remote_project) = project::Entity::find_by_id(project_id)
|
||||
.find_also_related(remote_project::Entity)
|
||||
let (mut project, dev_server_project) = project::Entity::find_by_id(project_id)
|
||||
.find_also_related(dev_server_project::Entity)
|
||||
.one(tx)
|
||||
.await?
|
||||
.ok_or_else(|| anyhow!("no such project"))?;
|
||||
|
@ -986,8 +986,8 @@ impl Database {
|
|||
} else {
|
||||
None
|
||||
};
|
||||
let role_from_remote_project = if let Some(remote_project) = remote_project {
|
||||
let dev_server = dev_server::Entity::find_by_id(remote_project.dev_server_id)
|
||||
let role_from_dev_server = if let Some(dev_server_project) = dev_server_project {
|
||||
let dev_server = dev_server::Entity::find_by_id(dev_server_project.dev_server_id)
|
||||
.one(tx)
|
||||
.await?
|
||||
.ok_or_else(|| anyhow!("no such channel"))?;
|
||||
|
@ -1011,7 +1011,7 @@ impl Database {
|
|||
None
|
||||
};
|
||||
|
||||
let role = role_from_remote_project
|
||||
let role = role_from_dev_server
|
||||
.or(role_from_room)
|
||||
.unwrap_or(ChannelRole::Banned);
|
||||
|
||||
|
|
|
@ -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?;
|
||||
|
||||
// if any project in the room has a remote-project-id that belongs to a dev server that this user owns.
|
||||
let remote_projects_for_user = self
|
||||
.remote_project_ids_for_user(leaving_participant.user_id, &tx)
|
||||
let dev_server_projects_for_user = self
|
||||
.dev_server_project_ids_for_user(leaving_participant.user_id, &tx)
|
||||
.await?;
|
||||
|
||||
let remote_projects_to_unshare = project::Entity::find()
|
||||
let dev_server_projects_to_unshare = project::Entity::find()
|
||||
.filter(
|
||||
Condition::all()
|
||||
.add(project::Column::RoomId.eq(room_id))
|
||||
.add(
|
||||
project::Column::RemoteProjectId
|
||||
.is_in(remote_projects_for_user.clone()),
|
||||
project::Column::DevServerProjectId
|
||||
.is_in(dev_server_projects_for_user.clone()),
|
||||
),
|
||||
)
|
||||
.all(&*tx)
|
||||
|
@ -892,7 +892,7 @@ impl Database {
|
|||
}
|
||||
|
||||
if (collaborator.is_host && collaborator.connection() == connection)
|
||||
|| remote_projects_to_unshare.contains(&collaborator.project_id)
|
||||
|| dev_server_projects_to_unshare.contains(&collaborator.project_id)
|
||||
{
|
||||
left_project.should_unshare = true;
|
||||
}
|
||||
|
@ -936,9 +936,9 @@ impl Database {
|
|||
.exec(&*tx)
|
||||
.await?;
|
||||
|
||||
if !remote_projects_to_unshare.is_empty() {
|
||||
if !dev_server_projects_to_unshare.is_empty() {
|
||||
project::Entity::update_many()
|
||||
.filter(project::Column::Id.is_in(remote_projects_to_unshare))
|
||||
.filter(project::Column::Id.is_in(dev_server_projects_to_unshare))
|
||||
.set(project::ActiveModel {
|
||||
room_id: ActiveValue::Set(None),
|
||||
..Default::default()
|
||||
|
@ -1316,8 +1316,10 @@ impl Database {
|
|||
project.worktree_root_names.push(db_worktree.root_name);
|
||||
}
|
||||
}
|
||||
} else if let Some(remote_project_id) = db_project.remote_project_id {
|
||||
let host = self.owner_for_remote_project(remote_project_id, tx).await?;
|
||||
} else if let Some(dev_server_project_id) = db_project.dev_server_project_id {
|
||||
let host = self
|
||||
.owner_for_dev_server_project(dev_server_project_id, tx)
|
||||
.await?;
|
||||
if let Some((_, participant)) = participants
|
||||
.iter_mut()
|
||||
.find(|(_, v)| v.user_id == host.to_proto())
|
||||
|
|
|
@ -11,6 +11,7 @@ pub mod channel_message_mention;
|
|||
pub mod contact;
|
||||
pub mod contributor;
|
||||
pub mod dev_server;
|
||||
pub mod dev_server_project;
|
||||
pub mod embedding;
|
||||
pub mod extension;
|
||||
pub mod extension_version;
|
||||
|
@ -25,7 +26,6 @@ pub mod observed_channel_messages;
|
|||
pub mod project;
|
||||
pub mod project_collaborator;
|
||||
pub mod rate_buckets;
|
||||
pub mod remote_project;
|
||||
pub mod room;
|
||||
pub mod room_participant;
|
||||
pub mod server;
|
||||
|
|
|
@ -16,11 +16,11 @@ impl ActiveModelBehavior for ActiveModel {}
|
|||
|
||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||
pub enum Relation {
|
||||
#[sea_orm(has_many = "super::remote_project::Entity")]
|
||||
#[sea_orm(has_many = "super::dev_server_project::Entity")]
|
||||
RemoteProject,
|
||||
}
|
||||
|
||||
impl Related<super::remote_project::Entity> for Entity {
|
||||
impl Related<super::dev_server_project::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::RemoteProject.def()
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
use super::project;
|
||||
use crate::db::{DevServerId, RemoteProjectId};
|
||||
use crate::db::{DevServerId, DevServerProjectId};
|
||||
use rpc::proto;
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
|
||||
#[sea_orm(table_name = "remote_projects")]
|
||||
#[sea_orm(table_name = "dev_server_projects")]
|
||||
pub struct Model {
|
||||
#[sea_orm(primary_key)]
|
||||
pub id: RemoteProjectId,
|
||||
pub id: DevServerProjectId,
|
||||
pub dev_server_id: DevServerId,
|
||||
pub path: String,
|
||||
}
|
||||
|
@ -39,8 +39,8 @@ impl Related<super::dev_server::Entity> for Entity {
|
|||
}
|
||||
|
||||
impl Model {
|
||||
pub fn to_proto(&self, project: Option<project::Model>) -> proto::RemoteProject {
|
||||
proto::RemoteProject {
|
||||
pub fn to_proto(&self, project: Option<project::Model>) -> proto::DevServerProject {
|
||||
proto::DevServerProject {
|
||||
id: self.id.to_proto(),
|
||||
project_id: project.map(|p| p.id.to_proto()),
|
||||
dev_server_id: self.dev_server_id.to_proto(),
|
|
@ -1,4 +1,4 @@
|
|||
use crate::db::{HostedProjectId, ProjectId, RemoteProjectId, Result, RoomId, ServerId, UserId};
|
||||
use crate::db::{DevServerProjectId, HostedProjectId, ProjectId, Result, RoomId, ServerId, UserId};
|
||||
use anyhow::anyhow;
|
||||
use rpc::ConnectionId;
|
||||
use sea_orm::entity::prelude::*;
|
||||
|
@ -13,7 +13,7 @@ pub struct Model {
|
|||
pub host_connection_id: Option<i32>,
|
||||
pub host_connection_server_id: Option<ServerId>,
|
||||
pub hosted_project_id: Option<HostedProjectId>,
|
||||
pub remote_project_id: Option<RemoteProjectId>,
|
||||
pub dev_server_project_id: Option<DevServerProjectId>,
|
||||
}
|
||||
|
||||
impl Model {
|
||||
|
@ -58,9 +58,9 @@ pub enum Relation {
|
|||
)]
|
||||
HostedProject,
|
||||
#[sea_orm(
|
||||
belongs_to = "super::remote_project::Entity",
|
||||
from = "Column::RemoteProjectId",
|
||||
to = "super::remote_project::Column::Id"
|
||||
belongs_to = "super::dev_server_project::Entity",
|
||||
from = "Column::DevServerProjectId",
|
||||
to = "super::dev_server_project::Column::Id"
|
||||
)]
|
||||
RemoteProject,
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ impl Related<super::hosted_project::Entity> for Entity {
|
|||
}
|
||||
}
|
||||
|
||||
impl Related<super::remote_project::Entity> for Entity {
|
||||
impl Related<super::dev_server_project::Entity> for Entity {
|
||||
fn to() -> RelationDef {
|
||||
Relation::RemoteProject.def()
|
||||
}
|
||||
|
|
|
@ -4,9 +4,9 @@ use crate::{
|
|||
auth,
|
||||
db::{
|
||||
self, dev_server, BufferId, Capability, Channel, ChannelId, ChannelRole, ChannelsForUser,
|
||||
CreatedChannelMessage, Database, DevServerId, InviteMemberResult, MembershipUpdated,
|
||||
MessageId, NotificationId, PrincipalId, Project, ProjectId, RejoinedProject,
|
||||
RemoteProjectId, RemoveChannelMemberResult, ReplicaId, RespondToChannelInvite, RoomId,
|
||||
CreatedChannelMessage, Database, DevServerId, DevServerProjectId, InviteMemberResult,
|
||||
MembershipUpdated, MessageId, NotificationId, PrincipalId, Project, ProjectId,
|
||||
RejoinedProject, RemoveChannelMemberResult, ReplicaId, RespondToChannelInvite, RoomId,
|
||||
ServerId, UpdatedChannelMessage, User, UserId,
|
||||
},
|
||||
executor::Executor,
|
||||
|
@ -411,11 +411,11 @@ impl Server {
|
|||
.add_message_handler(unshare_project)
|
||||
.add_request_handler(user_handler(join_project))
|
||||
.add_request_handler(user_handler(join_hosted_project))
|
||||
.add_request_handler(user_handler(rejoin_remote_projects))
|
||||
.add_request_handler(user_handler(create_remote_project))
|
||||
.add_request_handler(user_handler(rejoin_dev_server_projects))
|
||||
.add_request_handler(user_handler(create_dev_server_project))
|
||||
.add_request_handler(user_handler(create_dev_server))
|
||||
.add_request_handler(user_handler(delete_dev_server))
|
||||
.add_request_handler(dev_server_handler(share_remote_project))
|
||||
.add_request_handler(dev_server_handler(share_dev_server_project))
|
||||
.add_request_handler(dev_server_handler(shutdown_dev_server))
|
||||
.add_request_handler(dev_server_handler(reconnect_dev_server))
|
||||
.add_message_handler(user_message_handler(leave_project))
|
||||
|
@ -1067,12 +1067,12 @@ impl Server {
|
|||
.await?;
|
||||
}
|
||||
|
||||
let (contacts, channels_for_user, channel_invites, remote_projects) =
|
||||
let (contacts, channels_for_user, channel_invites, dev_server_projects) =
|
||||
future::try_join4(
|
||||
self.app_state.db.get_contacts(user.id),
|
||||
self.app_state.db.get_channels_for_user(user.id),
|
||||
self.app_state.db.get_channel_invites_for_user(user.id),
|
||||
self.app_state.db.remote_projects_update(user.id),
|
||||
self.app_state.db.dev_server_projects_update(user.id),
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
@ -1095,7 +1095,7 @@ impl Server {
|
|||
build_channels_update(channels_for_user, channel_invites),
|
||||
)?;
|
||||
}
|
||||
send_remote_projects_update(user.id, remote_projects, session).await;
|
||||
send_dev_server_projects_update(user.id, dev_server_projects, session).await;
|
||||
|
||||
if let Some(incoming_call) =
|
||||
self.app_state.db.incoming_call_for_user(user.id).await?
|
||||
|
@ -1117,7 +1117,7 @@ impl Server {
|
|||
let projects = self
|
||||
.app_state
|
||||
.db
|
||||
.get_remote_projects_for_dev_server(dev_server.id)
|
||||
.get_projects_for_dev_server(dev_server.id)
|
||||
.await?;
|
||||
self.peer
|
||||
.send(connection_id, proto::DevServerInstructions { projects })?;
|
||||
|
@ -1125,9 +1125,9 @@ impl Server {
|
|||
let status = self
|
||||
.app_state
|
||||
.db
|
||||
.remote_projects_update(dev_server.user_id)
|
||||
.dev_server_projects_update(dev_server.user_id)
|
||||
.await?;
|
||||
send_remote_projects_update(dev_server.user_id, status, &session).await;
|
||||
send_dev_server_projects_update(dev_server.user_id, status, &session).await;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1970,8 +1970,8 @@ async fn share_project(
|
|||
session.connection_id,
|
||||
&request.worktrees,
|
||||
request
|
||||
.remote_project_id
|
||||
.map(|id| RemoteProjectId::from_proto(id)),
|
||||
.dev_server_project_id
|
||||
.map(|id| DevServerProjectId::from_proto(id)),
|
||||
)
|
||||
.await?;
|
||||
response.send(proto::ShareProjectResponse {
|
||||
|
@ -2023,26 +2023,26 @@ async fn unshare_project_internal(
|
|||
}
|
||||
|
||||
/// DevServer makes a project available online
|
||||
async fn share_remote_project(
|
||||
request: proto::ShareRemoteProject,
|
||||
response: Response<proto::ShareRemoteProject>,
|
||||
async fn share_dev_server_project(
|
||||
request: proto::ShareDevServerProject,
|
||||
response: Response<proto::ShareDevServerProject>,
|
||||
session: DevServerSession,
|
||||
) -> Result<()> {
|
||||
let (remote_project, user_id, status) = session
|
||||
let (dev_server_project, user_id, status) = session
|
||||
.db()
|
||||
.await
|
||||
.share_remote_project(
|
||||
RemoteProjectId::from_proto(request.remote_project_id),
|
||||
.share_dev_server_project(
|
||||
DevServerProjectId::from_proto(request.dev_server_project_id),
|
||||
session.dev_server_id(),
|
||||
session.connection_id,
|
||||
&request.worktrees,
|
||||
)
|
||||
.await?;
|
||||
let Some(project_id) = remote_project.project_id else {
|
||||
let Some(project_id) = dev_server_project.project_id else {
|
||||
return Err(anyhow!("failed to share remote project"))?;
|
||||
};
|
||||
|
||||
send_remote_projects_update(user_id, status, &session).await;
|
||||
send_dev_server_projects_update(user_id, status, &session).await;
|
||||
|
||||
response.send(proto::ShareProjectResponse { project_id })?;
|
||||
|
||||
|
@ -2135,9 +2135,9 @@ fn join_project_internal(
|
|||
collaborators: collaborators.clone(),
|
||||
language_servers: project.language_servers.clone(),
|
||||
role: project.role.into(),
|
||||
remote_project_id: project
|
||||
.remote_project_id
|
||||
.map(|remote_project_id| remote_project_id.0 as u64),
|
||||
dev_server_project_id: project
|
||||
.dev_server_project_id
|
||||
.map(|dev_server_project_id| dev_server_project_id.0 as u64),
|
||||
})?;
|
||||
|
||||
for (worktree_id, worktree) in mem::take(&mut project.worktrees) {
|
||||
|
@ -2249,9 +2249,9 @@ async fn join_hosted_project(
|
|||
join_project_internal(response, session, &mut project, &replica_id)
|
||||
}
|
||||
|
||||
async fn create_remote_project(
|
||||
request: proto::CreateRemoteProject,
|
||||
response: Response<proto::CreateRemoteProject>,
|
||||
async fn create_dev_server_project(
|
||||
request: proto::CreateDevServerProject,
|
||||
response: Response<proto::CreateDevServerProject>,
|
||||
session: UserSession,
|
||||
) -> Result<()> {
|
||||
let dev_server_id = DevServerId(request.dev_server_id as i32);
|
||||
|
@ -2272,14 +2272,14 @@ async fn create_remote_project(
|
|||
.forward_request(
|
||||
session.connection_id,
|
||||
dev_server_connection_id,
|
||||
proto::ValidateRemoteProjectRequest { path: path.clone() },
|
||||
proto::ValidateDevServerProjectRequest { path: path.clone() },
|
||||
)
|
||||
.await?;
|
||||
|
||||
let (remote_project, update) = session
|
||||
let (dev_server_project, update) = session
|
||||
.db()
|
||||
.await
|
||||
.create_remote_project(
|
||||
.create_dev_server_project(
|
||||
DevServerId(request.dev_server_id as i32),
|
||||
&request.path,
|
||||
session.user_id(),
|
||||
|
@ -2289,7 +2289,7 @@ async fn create_remote_project(
|
|||
let projects = session
|
||||
.db()
|
||||
.await
|
||||
.get_remote_projects_for_dev_server(remote_project.dev_server_id)
|
||||
.get_projects_for_dev_server(dev_server_project.dev_server_id)
|
||||
.await?;
|
||||
|
||||
session.peer.send(
|
||||
|
@ -2297,10 +2297,10 @@ async fn create_remote_project(
|
|||
proto::DevServerInstructions { projects },
|
||||
)?;
|
||||
|
||||
send_remote_projects_update(session.user_id(), update, &session).await;
|
||||
send_dev_server_projects_update(session.user_id(), update, &session).await;
|
||||
|
||||
response.send(proto::CreateRemoteProjectResponse {
|
||||
remote_project: Some(remote_project.to_proto(None)),
|
||||
response.send(proto::CreateDevServerProjectResponse {
|
||||
dev_server_project: Some(dev_server_project.to_proto(None)),
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -2319,7 +2319,7 @@ async fn create_dev_server(
|
|||
.create_dev_server(&request.name, &hashed_access_token, session.user_id())
|
||||
.await?;
|
||||
|
||||
send_remote_projects_update(session.user_id(), status, &session).await;
|
||||
send_dev_server_projects_update(session.user_id(), status, &session).await;
|
||||
|
||||
response.send(proto::CreateDevServerResponse {
|
||||
dev_server_id: dev_server.id.0 as u64,
|
||||
|
@ -2357,20 +2357,20 @@ async fn delete_dev_server(
|
|||
.delete_dev_server(dev_server_id, session.user_id())
|
||||
.await?;
|
||||
|
||||
send_remote_projects_update(session.user_id(), status, &session).await;
|
||||
send_dev_server_projects_update(session.user_id(), status, &session).await;
|
||||
|
||||
response.send(proto::Ack {})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn rejoin_remote_projects(
|
||||
async fn rejoin_dev_server_projects(
|
||||
request: proto::RejoinRemoteProjects,
|
||||
response: Response<proto::RejoinRemoteProjects>,
|
||||
session: UserSession,
|
||||
) -> Result<()> {
|
||||
let mut rejoined_projects = {
|
||||
let db = session.db().await;
|
||||
db.rejoin_remote_projects(
|
||||
db.rejoin_dev_server_projects(
|
||||
&request.rejoined_projects,
|
||||
session.user_id(),
|
||||
session.0.connection_id,
|
||||
|
@ -2394,7 +2394,7 @@ async fn reconnect_dev_server(
|
|||
) -> Result<()> {
|
||||
let reshared_projects = {
|
||||
let db = session.db().await;
|
||||
db.reshare_remote_projects(
|
||||
db.reshare_dev_server_projects(
|
||||
&request.reshared_projects,
|
||||
session.dev_server_id(),
|
||||
session.0.connection_id,
|
||||
|
@ -2467,14 +2467,14 @@ async fn shutdown_dev_server_internal(
|
|||
connection_id: ConnectionId,
|
||||
session: &Session,
|
||||
) -> Result<()> {
|
||||
let (remote_projects, dev_server) = {
|
||||
let (dev_server_projects, dev_server) = {
|
||||
let db = session.db().await;
|
||||
let remote_projects = db.get_remote_projects_for_dev_server(dev_server_id).await?;
|
||||
let dev_server_projects = db.get_projects_for_dev_server(dev_server_id).await?;
|
||||
let dev_server = db.get_dev_server(dev_server_id).await?;
|
||||
(remote_projects, dev_server)
|
||||
(dev_server_projects, dev_server)
|
||||
};
|
||||
|
||||
for project_id in remote_projects.iter().filter_map(|p| p.project_id) {
|
||||
for project_id in dev_server_projects.iter().filter_map(|p| p.project_id) {
|
||||
unshare_project_internal(
|
||||
ProjectId::from_proto(project_id),
|
||||
connection_id,
|
||||
|
@ -2492,9 +2492,9 @@ async fn shutdown_dev_server_internal(
|
|||
let status = session
|
||||
.db()
|
||||
.await
|
||||
.remote_projects_update(dev_server.user_id)
|
||||
.dev_server_projects_update(dev_server.user_id)
|
||||
.await?;
|
||||
send_remote_projects_update(dev_server.user_id, status, &session).await;
|
||||
send_dev_server_projects_update(dev_server.user_id, status, &session).await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -4908,9 +4908,9 @@ fn channel_updated(
|
|||
);
|
||||
}
|
||||
|
||||
async fn send_remote_projects_update(
|
||||
async fn send_dev_server_projects_update(
|
||||
user_id: UserId,
|
||||
mut status: proto::RemoteProjectsUpdate,
|
||||
mut status: proto::DevServerProjectsUpdate,
|
||||
session: &Session,
|
||||
) {
|
||||
let pool = session.connection_pool().await;
|
||||
|
@ -4973,9 +4973,13 @@ async fn lost_dev_server_connection(session: &DevServerSession) -> Result<()> {
|
|||
}
|
||||
|
||||
let user_id = session.dev_server().user_id;
|
||||
let update = session.db().await.remote_projects_update(user_id).await?;
|
||||
let update = session
|
||||
.db()
|
||||
.await
|
||||
.dev_server_projects_update(user_id)
|
||||
.await?;
|
||||
|
||||
send_remote_projects_update(user_id, update, session).await;
|
||||
send_dev_server_projects_update(user_id, update, session).await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -246,7 +246,7 @@ async fn test_channel_notes_participant_indices(
|
|||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||
.await
|
||||
.unwrap();
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b);
|
||||
|
||||
// Clients A and B open the same file.
|
||||
|
|
|
@ -16,7 +16,7 @@ use super::TestClient;
|
|||
async fn test_dev_server(cx: &mut gpui::TestAppContext, cx2: &mut gpui::TestAppContext) {
|
||||
let (server, client) = TestServer::start1(cx).await;
|
||||
|
||||
let store = cx.update(|cx| remote_projects::Store::global(cx).clone());
|
||||
let store = cx.update(|cx| dev_server_projects::Store::global(cx).clone());
|
||||
|
||||
let resp = store
|
||||
.update(cx, |store, cx| {
|
||||
|
@ -51,7 +51,7 @@ async fn test_dev_server(cx: &mut gpui::TestAppContext, cx2: &mut gpui::TestAppC
|
|||
|
||||
store
|
||||
.update(cx, |store, cx| {
|
||||
store.create_remote_project(
|
||||
store.create_dev_server_project(
|
||||
client::DevServerId(resp.dev_server_id),
|
||||
"/remote".to_string(),
|
||||
cx,
|
||||
|
@ -64,10 +64,10 @@ async fn test_dev_server(cx: &mut gpui::TestAppContext, cx2: &mut gpui::TestAppC
|
|||
|
||||
let remote_workspace = store
|
||||
.update(cx, |store, cx| {
|
||||
let projects = store.remote_projects();
|
||||
let projects = store.dev_server_projects();
|
||||
assert_eq!(projects.len(), 1);
|
||||
assert_eq!(projects[0].path, "/remote");
|
||||
workspace::join_remote_project(
|
||||
workspace::join_dev_server_project(
|
||||
projects[0].project_id.unwrap(),
|
||||
client.app_state.clone(),
|
||||
None,
|
||||
|
@ -110,7 +110,7 @@ async fn test_dev_server_env_files(
|
|||
let (server, client1, client2, channel_id) = TestServer::start2(cx1, cx2).await;
|
||||
|
||||
let (_dev_server, remote_workspace) =
|
||||
create_remote_project(&server, client1.app_state.clone(), cx1, cx3).await;
|
||||
create_dev_server_project(&server, client1.app_state.clone(), cx1, cx3).await;
|
||||
|
||||
cx1.executor().run_until_parked();
|
||||
|
||||
|
@ -157,13 +157,13 @@ async fn test_dev_server_env_files(
|
|||
});
|
||||
}
|
||||
|
||||
async fn create_remote_project(
|
||||
async fn create_dev_server_project(
|
||||
server: &TestServer,
|
||||
client_app_state: Arc<AppState>,
|
||||
cx: &mut TestAppContext,
|
||||
cx_devserver: &mut TestAppContext,
|
||||
) -> (TestClient, WindowHandle<Workspace>) {
|
||||
let store = cx.update(|cx| remote_projects::Store::global(cx).clone());
|
||||
let store = cx.update(|cx| dev_server_projects::Store::global(cx).clone());
|
||||
|
||||
let resp = store
|
||||
.update(cx, |store, cx| {
|
||||
|
@ -190,7 +190,7 @@ async fn create_remote_project(
|
|||
|
||||
store
|
||||
.update(cx, |store, cx| {
|
||||
store.create_remote_project(
|
||||
store.create_dev_server_project(
|
||||
client::DevServerId(resp.dev_server_id),
|
||||
"/remote".to_string(),
|
||||
cx,
|
||||
|
@ -203,10 +203,10 @@ async fn create_remote_project(
|
|||
|
||||
let workspace = store
|
||||
.update(cx, |store, cx| {
|
||||
let projects = store.remote_projects();
|
||||
let projects = store.dev_server_projects();
|
||||
assert_eq!(projects.len(), 1);
|
||||
assert_eq!(projects[0].path, "/remote");
|
||||
workspace::join_remote_project(
|
||||
workspace::join_dev_server_project(
|
||||
projects[0].project_id.unwrap(),
|
||||
client_app_state,
|
||||
None,
|
||||
|
@ -230,7 +230,7 @@ async fn test_dev_server_leave_room(
|
|||
let (server, client1, client2, channel_id) = TestServer::start2(cx1, cx2).await;
|
||||
|
||||
let (_dev_server, remote_workspace) =
|
||||
create_remote_project(&server, client1.app_state.clone(), cx1, cx3).await;
|
||||
create_dev_server_project(&server, client1.app_state.clone(), cx1, cx3).await;
|
||||
|
||||
cx1.update(|cx| {
|
||||
workspace::join_channel(
|
||||
|
@ -275,7 +275,7 @@ async fn test_dev_server_reconnect(
|
|||
.await;
|
||||
|
||||
let (_dev_server, remote_workspace) =
|
||||
create_remote_project(&server, client1.app_state.clone(), cx1, cx3).await;
|
||||
create_dev_server_project(&server, client1.app_state.clone(), cx1, cx3).await;
|
||||
|
||||
cx1.update(|cx| {
|
||||
workspace::join_channel(
|
||||
|
@ -299,12 +299,12 @@ async fn test_dev_server_reconnect(
|
|||
|
||||
let client2 = server.create_client(cx2, "user_a").await;
|
||||
|
||||
let store = cx2.update(|cx| remote_projects::Store::global(cx).clone());
|
||||
let store = cx2.update(|cx| dev_server_projects::Store::global(cx).clone());
|
||||
|
||||
store
|
||||
.update(cx2, |store, cx| {
|
||||
let projects = store.remote_projects();
|
||||
workspace::join_remote_project(
|
||||
let projects = store.dev_server_projects();
|
||||
workspace::join_dev_server_project(
|
||||
projects[0].project_id.unwrap(),
|
||||
client2.app_state.clone(),
|
||||
None,
|
||||
|
@ -316,7 +316,7 @@ async fn test_dev_server_reconnect(
|
|||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_create_remote_project_path_validation(
|
||||
async fn test_create_dev_server_project_path_validation(
|
||||
cx1: &mut gpui::TestAppContext,
|
||||
cx2: &mut gpui::TestAppContext,
|
||||
cx3: &mut gpui::TestAppContext,
|
||||
|
@ -328,11 +328,11 @@ async fn test_create_remote_project_path_validation(
|
|||
|
||||
// Creating a project with a path that does exist should not fail
|
||||
let (_dev_server, _) =
|
||||
create_remote_project(&server, client1.app_state.clone(), cx1, cx2).await;
|
||||
create_dev_server_project(&server, client1.app_state.clone(), cx1, cx2).await;
|
||||
|
||||
cx1.executor().run_until_parked();
|
||||
|
||||
let store = cx1.update(|cx| remote_projects::Store::global(cx).clone());
|
||||
let store = cx1.update(|cx| dev_server_projects::Store::global(cx).clone());
|
||||
|
||||
let resp = store
|
||||
.update(cx1, |store, cx| {
|
||||
|
@ -350,7 +350,7 @@ async fn test_create_remote_project_path_validation(
|
|||
// Creating a remote project with a path that does not exist should fail
|
||||
let result = store
|
||||
.update(cx1, |store, cx| {
|
||||
store.create_remote_project(
|
||||
store.create_dev_server_project(
|
||||
client::DevServerId(resp.dev_server_id),
|
||||
"/notfound".to_string(),
|
||||
cx,
|
||||
|
@ -363,7 +363,7 @@ async fn test_create_remote_project_path_validation(
|
|||
let error = result.unwrap_err();
|
||||
assert!(matches!(
|
||||
error.error_code(),
|
||||
ErrorCode::RemoteProjectPathDoesNotExist
|
||||
ErrorCode::DevServerProjectPathDoesNotExist
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -373,7 +373,7 @@ async fn test_save_as_remote(cx1: &mut gpui::TestAppContext, cx2: &mut gpui::Tes
|
|||
|
||||
// Creating a project with a path that does exist should not fail
|
||||
let (dev_server, remote_workspace) =
|
||||
create_remote_project(&server, client1.app_state.clone(), cx1, cx2).await;
|
||||
create_dev_server_project(&server, client1.app_state.clone(), cx1, cx2).await;
|
||||
|
||||
let mut cx = VisualTestContext::from_window(remote_workspace.into(), cx1);
|
||||
|
||||
|
@ -405,7 +405,7 @@ async fn test_new_file_remote(cx1: &mut gpui::TestAppContext, cx2: &mut gpui::Te
|
|||
|
||||
// Creating a project with a path that does exist should not fail
|
||||
let (dev_server, remote_workspace) =
|
||||
create_remote_project(&server, client1.app_state.clone(), cx1, cx2).await;
|
||||
create_dev_server_project(&server, client1.app_state.clone(), cx1, cx2).await;
|
||||
|
||||
let mut cx = VisualTestContext::from_window(remote_workspace.into(), cx1);
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ async fn test_host_disconnect(
|
|||
.await
|
||||
.unwrap();
|
||||
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
cx_a.background_executor.run_until_parked();
|
||||
|
||||
assert!(worktree_a.read_with(cx_a, |tree, _| tree.as_local().unwrap().is_shared()));
|
||||
|
@ -199,7 +199,7 @@ async fn test_newline_above_or_below_does_not_move_guest_cursor(
|
|||
.await
|
||||
.unwrap();
|
||||
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
|
||||
// Open a buffer as client A
|
||||
let buffer_a = project_a
|
||||
|
@ -315,7 +315,7 @@ async fn test_collaborating_with_completion(cx_a: &mut TestAppContext, cx_b: &mu
|
|||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||
.await
|
||||
.unwrap();
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
|
||||
// Open a file in an editor as the guest.
|
||||
let buffer_b = project_b
|
||||
|
@ -572,7 +572,7 @@ async fn test_collaborating_with_code_actions(
|
|||
.unwrap();
|
||||
|
||||
// Join the project as client B.
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b);
|
||||
let editor_b = workspace_b
|
||||
.update(cx_b, |workspace, cx| {
|
||||
|
@ -787,7 +787,7 @@ async fn test_collaborating_with_renames(cx_a: &mut TestAppContext, cx_b: &mut T
|
|||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||
.await
|
||||
.unwrap();
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
|
||||
let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b);
|
||||
let editor_b = workspace_b
|
||||
|
@ -1036,7 +1036,7 @@ async fn test_language_server_statuses(cx_a: &mut TestAppContext, cx_b: &mut Tes
|
|||
.await
|
||||
.unwrap();
|
||||
executor.run_until_parked();
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
|
||||
project_b.read_with(cx_b, |project, _| {
|
||||
let status = project.language_server_statuses().next().unwrap();
|
||||
|
@ -1133,7 +1133,7 @@ async fn test_share_project(
|
|||
.unwrap();
|
||||
let client_b_peer_id = client_b.peer_id().unwrap();
|
||||
let project_b = client_b
|
||||
.build_remote_project(initial_project.id, cx_b)
|
||||
.build_dev_server_project(initial_project.id, cx_b)
|
||||
.await;
|
||||
|
||||
let replica_id_b = project_b.read_with(cx_b, |project, _| project.replica_id());
|
||||
|
@ -1237,7 +1237,7 @@ async fn test_share_project(
|
|||
.await
|
||||
.unwrap();
|
||||
let _project_c = client_c
|
||||
.build_remote_project(initial_project.id, cx_c)
|
||||
.build_dev_server_project(initial_project.id, cx_c)
|
||||
.await;
|
||||
|
||||
// Client B closes the editor, and client A sees client B's selections removed.
|
||||
|
@ -1297,7 +1297,7 @@ async fn test_on_input_format_from_host_to_guest(
|
|||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||
.await
|
||||
.unwrap();
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
|
||||
// Open a file in an editor as the host.
|
||||
let buffer_a = project_a
|
||||
|
@ -1417,7 +1417,7 @@ async fn test_on_input_format_from_guest_to_host(
|
|||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||
.await
|
||||
.unwrap();
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
|
||||
// Open a file in an editor as the guest.
|
||||
let buffer_b = project_b
|
||||
|
@ -1578,7 +1578,7 @@ async fn test_mutual_editor_inlay_hint_cache_update(
|
|||
.unwrap();
|
||||
|
||||
// Client B joins the project
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
active_call_b
|
||||
.update(cx_b, |call, cx| call.set_location(Some(&project_b), cx))
|
||||
.await
|
||||
|
@ -1838,7 +1838,7 @@ async fn test_inlay_hint_refresh_is_forwarded(
|
|||
.await
|
||||
.unwrap();
|
||||
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
active_call_b
|
||||
.update(cx_b, |call, cx| call.set_location(Some(&project_b), cx))
|
||||
.await
|
||||
|
@ -2014,7 +2014,7 @@ struct Row10;"#};
|
|||
.await
|
||||
.unwrap();
|
||||
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
active_call_b
|
||||
.update(cx_b, |call, cx| call.set_location(Some(&project_b), cx))
|
||||
.await
|
||||
|
@ -2312,7 +2312,7 @@ async fn test_git_blame_is_forwarded(cx_a: &mut TestAppContext, cx_b: &mut TestA
|
|||
.unwrap();
|
||||
|
||||
// Join the project as client B.
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b);
|
||||
let editor_b = workspace_b
|
||||
.update(cx_b, |workspace, cx| {
|
||||
|
|
|
@ -73,7 +73,7 @@ async fn test_basic_following(
|
|||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||
.await
|
||||
.unwrap();
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
active_call_b
|
||||
.update(cx_b, |call, cx| call.set_location(Some(&project_b), cx))
|
||||
.await
|
||||
|
@ -161,7 +161,7 @@ async fn test_basic_following(
|
|||
|
||||
executor.run_until_parked();
|
||||
let active_call_c = cx_c.read(ActiveCall::global);
|
||||
let project_c = client_c.build_remote_project(project_id, cx_c).await;
|
||||
let project_c = client_c.build_dev_server_project(project_id, cx_c).await;
|
||||
let (workspace_c, cx_c) = client_c.build_workspace(&project_c, cx_c);
|
||||
active_call_c
|
||||
.update(cx_c, |call, cx| call.set_location(Some(&project_c), cx))
|
||||
|
@ -174,7 +174,7 @@ async fn test_basic_following(
|
|||
|
||||
cx_d.executor().run_until_parked();
|
||||
let active_call_d = cx_d.read(ActiveCall::global);
|
||||
let project_d = client_d.build_remote_project(project_id, cx_d).await;
|
||||
let project_d = client_d.build_dev_server_project(project_id, cx_d).await;
|
||||
let (workspace_d, cx_d) = client_d.build_workspace(&project_d, cx_d);
|
||||
active_call_d
|
||||
.update(cx_d, |call, cx| call.set_location(Some(&project_d), cx))
|
||||
|
@ -567,7 +567,7 @@ async fn test_following_tab_order(
|
|||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||
.await
|
||||
.unwrap();
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
active_call_b
|
||||
.update(cx_b, |call, cx| call.set_location(Some(&project_b), cx))
|
||||
.await
|
||||
|
@ -684,7 +684,7 @@ async fn test_peers_following_each_other(cx_a: &mut TestAppContext, cx_b: &mut T
|
|||
.unwrap();
|
||||
|
||||
// Client B joins the project.
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
active_call_b
|
||||
.update(cx_b, |call, cx| call.set_location(Some(&project_b), cx))
|
||||
.await
|
||||
|
@ -1197,7 +1197,7 @@ async fn test_auto_unfollowing(cx_a: &mut TestAppContext, cx_b: &mut TestAppCont
|
|||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||
.await
|
||||
.unwrap();
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
active_call_b
|
||||
.update(cx_b, |call, cx| call.set_location(Some(&project_b), cx))
|
||||
.await
|
||||
|
@ -1333,7 +1333,7 @@ async fn test_peers_simultaneously_following_each_other(
|
|||
.await
|
||||
.unwrap();
|
||||
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
let (workspace_b, cx_b) = client_b.build_workspace(&project_b, cx_b);
|
||||
|
||||
executor.run_until_parked();
|
||||
|
@ -1683,7 +1683,7 @@ async fn test_following_into_excluded_file(
|
|||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||
.await
|
||||
.unwrap();
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
active_call_b
|
||||
.update(cx_b, |call, cx| call.set_location(Some(&project_b), cx))
|
||||
.await
|
||||
|
|
|
@ -1375,7 +1375,7 @@ async fn test_unshare_project(
|
|||
.unwrap();
|
||||
|
||||
let worktree_a = project_a.read_with(cx_a, |project, _| project.worktrees().next().unwrap());
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
executor.run_until_parked();
|
||||
|
||||
assert!(worktree_a.read_with(cx_a, |tree, _| tree.as_local().unwrap().is_shared()));
|
||||
|
@ -1395,7 +1395,7 @@ async fn test_unshare_project(
|
|||
assert!(project_b.read_with(cx_b, |project, _| project.is_disconnected()));
|
||||
|
||||
// Client C opens the project.
|
||||
let project_c = client_c.build_remote_project(project_id, cx_c).await;
|
||||
let project_c = client_c.build_dev_server_project(project_id, cx_c).await;
|
||||
|
||||
// When client A unshares the project, client C's project becomes read-only.
|
||||
project_a
|
||||
|
@ -1412,7 +1412,7 @@ async fn test_unshare_project(
|
|||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||
.await
|
||||
.unwrap();
|
||||
let project_c2 = client_c.build_remote_project(project_id, cx_c).await;
|
||||
let project_c2 = client_c.build_dev_server_project(project_id, cx_c).await;
|
||||
executor.run_until_parked();
|
||||
|
||||
assert!(worktree_a.read_with(cx_a, |tree, _| tree.as_local().unwrap().is_shared()));
|
||||
|
@ -1516,9 +1516,9 @@ async fn test_project_reconnect(
|
|||
.await
|
||||
.unwrap();
|
||||
|
||||
let project_b1 = client_b.build_remote_project(project1_id, cx_b).await;
|
||||
let project_b2 = client_b.build_remote_project(project2_id, cx_b).await;
|
||||
let project_b3 = client_b.build_remote_project(project3_id, cx_b).await;
|
||||
let project_b1 = client_b.build_dev_server_project(project1_id, cx_b).await;
|
||||
let project_b2 = client_b.build_dev_server_project(project2_id, cx_b).await;
|
||||
let project_b3 = client_b.build_dev_server_project(project3_id, cx_b).await;
|
||||
executor.run_until_parked();
|
||||
|
||||
let worktree1_id = worktree_a1.read_with(cx_a, |worktree, _| {
|
||||
|
@ -2314,8 +2314,8 @@ async fn test_propagate_saves_and_fs_changes(
|
|||
.unwrap();
|
||||
|
||||
// Join that worktree as clients B and C.
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_c = client_c.build_remote_project(project_id, cx_c).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
let project_c = client_c.build_dev_server_project(project_id, cx_c).await;
|
||||
|
||||
let worktree_b = project_b.read_with(cx_b, |p, _| p.worktrees().next().unwrap());
|
||||
|
||||
|
@ -2539,7 +2539,7 @@ async fn test_git_diff_base_change(
|
|||
.await
|
||||
.unwrap();
|
||||
|
||||
let project_remote = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_remote = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
|
||||
let diff_base = "
|
||||
one
|
||||
|
@ -2771,7 +2771,7 @@ async fn test_git_branch_name(
|
|||
.await
|
||||
.unwrap();
|
||||
|
||||
let project_remote = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_remote = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
client_a
|
||||
.fs()
|
||||
.set_branch_name(Path::new("/dir/.git"), Some("branch-1"));
|
||||
|
@ -2816,7 +2816,7 @@ async fn test_git_branch_name(
|
|||
assert_branch(Some("branch-2"), project, cx)
|
||||
});
|
||||
|
||||
let project_remote_c = client_c.build_remote_project(project_id, cx_c).await;
|
||||
let project_remote_c = client_c.build_dev_server_project(project_id, cx_c).await;
|
||||
executor.run_until_parked();
|
||||
|
||||
project_remote_c.read_with(cx_c, |project, cx| {
|
||||
|
@ -2871,7 +2871,7 @@ async fn test_git_status_sync(
|
|||
.await
|
||||
.unwrap();
|
||||
|
||||
let project_remote = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_remote = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
|
||||
// Wait for it to catch up to the new status
|
||||
executor.run_until_parked();
|
||||
|
@ -2947,7 +2947,7 @@ async fn test_git_status_sync(
|
|||
});
|
||||
|
||||
// And synchronization while joining
|
||||
let project_remote_c = client_c.build_remote_project(project_id, cx_c).await;
|
||||
let project_remote_c = client_c.build_dev_server_project(project_id, cx_c).await;
|
||||
executor.run_until_parked();
|
||||
|
||||
project_remote_c.read_with(cx_c, |project, cx| {
|
||||
|
@ -2995,7 +2995,7 @@ async fn test_fs_operations(
|
|||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||
.await
|
||||
.unwrap();
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
|
||||
let worktree_a = project_a.read_with(cx_a, |project, _| project.worktrees().next().unwrap());
|
||||
|
||||
|
@ -3289,7 +3289,7 @@ async fn test_local_settings(
|
|||
executor.run_until_parked();
|
||||
|
||||
// As client B, join that project and observe the local settings.
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
|
||||
let worktree_b = project_b.read_with(cx_b, |project, _| project.worktrees().next().unwrap());
|
||||
executor.run_until_parked();
|
||||
|
@ -3412,7 +3412,7 @@ async fn test_buffer_conflict_after_save(
|
|||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||
.await
|
||||
.unwrap();
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
|
||||
// Open a buffer as client B
|
||||
let buffer_b = project_b
|
||||
|
@ -3476,7 +3476,7 @@ async fn test_buffer_reloading(
|
|||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||
.await
|
||||
.unwrap();
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
|
||||
// Open a buffer as client B
|
||||
let buffer_b = project_b
|
||||
|
@ -3530,7 +3530,7 @@ async fn test_editing_while_guest_opens_buffer(
|
|||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||
.await
|
||||
.unwrap();
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
|
||||
// Open a buffer as client A
|
||||
let buffer_a = project_a
|
||||
|
@ -3578,7 +3578,7 @@ async fn test_leaving_worktree_while_opening_buffer(
|
|||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||
.await
|
||||
.unwrap();
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
|
||||
// See that a guest has joined as client A.
|
||||
executor.run_until_parked();
|
||||
|
@ -3625,7 +3625,7 @@ async fn test_canceling_buffer_opening(
|
|||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||
.await
|
||||
.unwrap();
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
|
||||
let buffer_a = project_a
|
||||
.update(cx_a, |p, cx| p.open_buffer((worktree_id, "a.txt"), cx))
|
||||
|
@ -3682,8 +3682,8 @@ async fn test_leaving_project(
|
|||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||
.await
|
||||
.unwrap();
|
||||
let project_b1 = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_c = client_c.build_remote_project(project_id, cx_c).await;
|
||||
let project_b1 = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
let project_c = client_c.build_dev_server_project(project_id, cx_c).await;
|
||||
|
||||
// Client A sees that a guest has joined.
|
||||
executor.run_until_parked();
|
||||
|
@ -3724,7 +3724,7 @@ async fn test_leaving_project(
|
|||
});
|
||||
|
||||
// Client B re-joins the project and can open buffers as before.
|
||||
let project_b2 = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b2 = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
executor.run_until_parked();
|
||||
|
||||
project_a.read_with(cx_a, |project, _| {
|
||||
|
@ -3900,7 +3900,7 @@ async fn test_collaborating_with_diagnostics(
|
|||
);
|
||||
|
||||
// Join the worktree as client B.
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
|
||||
// Wait for server to see the diagnostics update.
|
||||
executor.run_until_parked();
|
||||
|
@ -3925,7 +3925,7 @@ async fn test_collaborating_with_diagnostics(
|
|||
});
|
||||
|
||||
// Join project as client C and observe the diagnostics.
|
||||
let project_c = client_c.build_remote_project(project_id, cx_c).await;
|
||||
let project_c = client_c.build_dev_server_project(project_id, cx_c).await;
|
||||
executor.run_until_parked();
|
||||
let project_c_diagnostic_summaries =
|
||||
Rc::new(RefCell::new(project_c.read_with(cx_c, |project, cx| {
|
||||
|
@ -4133,7 +4133,7 @@ async fn test_collaborating_with_lsp_progress_updates_and_diagnostics_ordering(
|
|||
.unwrap();
|
||||
|
||||
// Join the project as client B and open all three files.
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
let guest_buffers = futures::future::try_join_all(file_names.iter().map(|file_name| {
|
||||
project_b.update(cx_b, |p, cx| p.open_buffer((worktree_id, file_name), cx))
|
||||
}))
|
||||
|
@ -4239,7 +4239,7 @@ async fn test_reloading_buffer_manually(
|
|||
.await
|
||||
.unwrap();
|
||||
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
|
||||
let open_buffer = project_b.update(cx_b, |p, cx| p.open_buffer((worktree_id, "a.rs"), cx));
|
||||
let buffer_b = cx_b.executor().spawn(open_buffer).await.unwrap();
|
||||
|
@ -4337,7 +4337,7 @@ async fn test_formatting_buffer(
|
|||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||
.await
|
||||
.unwrap();
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
|
||||
let open_buffer = project_b.update(cx_b, |p, cx| p.open_buffer((worktree_id, "a.rs"), cx));
|
||||
let buffer_b = cx_b.executor().spawn(open_buffer).await.unwrap();
|
||||
|
@ -4457,7 +4457,7 @@ async fn test_prettier_formatting_buffer(
|
|||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||
.await
|
||||
.unwrap();
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
let open_buffer = project_b.update(cx_b, |p, cx| p.open_buffer((worktree_id, "a.rs"), cx));
|
||||
let buffer_b = cx_b.executor().spawn(open_buffer).await.unwrap();
|
||||
|
||||
|
@ -4560,7 +4560,7 @@ async fn test_definition(
|
|||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||
.await
|
||||
.unwrap();
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
|
||||
// Open the file on client B.
|
||||
let open_buffer = project_b.update(cx_b, |p, cx| p.open_buffer((worktree_id, "a.rs"), cx));
|
||||
|
@ -4705,7 +4705,7 @@ async fn test_references(
|
|||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||
.await
|
||||
.unwrap();
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
|
||||
// Open the file on client B.
|
||||
let open_buffer = project_b.update(cx_b, |p, cx| p.open_buffer((worktree_id, "one.rs"), cx));
|
||||
|
@ -4862,7 +4862,7 @@ async fn test_project_search(
|
|||
.await
|
||||
.unwrap();
|
||||
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
|
||||
// Perform a search as the guest.
|
||||
let mut results = HashMap::default();
|
||||
|
@ -4943,7 +4943,7 @@ async fn test_document_highlights(
|
|||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||
.await
|
||||
.unwrap();
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
|
||||
// Open the file on client B.
|
||||
let open_b = project_b.update(cx_b, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx));
|
||||
|
@ -5065,7 +5065,7 @@ async fn test_lsp_hover(
|
|||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||
.await
|
||||
.unwrap();
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
|
||||
// Open the file as the guest
|
||||
let open_buffer = project_b.update(cx_b, |p, cx| p.open_buffer((worktree_id, "main.rs"), cx));
|
||||
|
@ -5242,7 +5242,7 @@ async fn test_project_symbols(
|
|||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||
.await
|
||||
.unwrap();
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
|
||||
// Cause the language server to start.
|
||||
let open_buffer_task =
|
||||
|
@ -5337,7 +5337,7 @@ async fn test_open_buffer_while_getting_definition_pointing_to_it(
|
|||
.update(cx_a, |call, cx| call.share_project(project_a.clone(), cx))
|
||||
.await
|
||||
.unwrap();
|
||||
let project_b = client_b.build_remote_project(project_id, cx_b).await;
|
||||
let project_b = client_b.build_dev_server_project(project_id, cx_b).await;
|
||||
|
||||
let open_buffer_task = project_b.update(cx_b, |p, cx| p.open_buffer((worktree_id, "a.rs"), cx));
|
||||
let buffer_b1 = cx_b.executor().spawn(open_buffer_task).await.unwrap();
|
||||
|
|
|
@ -217,19 +217,20 @@ impl RandomizedTest for ProjectCollaborationTest {
|
|||
0..=70 => {
|
||||
// Open a remote project
|
||||
if let Some(room) = call.read_with(cx, |call, _| call.room().cloned()) {
|
||||
let existing_remote_project_ids = cx.read(|cx| {
|
||||
let existing_dev_server_project_ids = cx.read(|cx| {
|
||||
client
|
||||
.remote_projects()
|
||||
.dev_server_projects()
|
||||
.iter()
|
||||
.map(|p| p.read(cx).remote_id().unwrap())
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
let new_remote_projects = room.read_with(cx, |room, _| {
|
||||
let new_dev_server_projects = room.read_with(cx, |room, _| {
|
||||
room.remote_participants()
|
||||
.values()
|
||||
.flat_map(|participant| {
|
||||
participant.projects.iter().filter_map(|project| {
|
||||
if existing_remote_project_ids.contains(&project.id) {
|
||||
if existing_dev_server_project_ids.contains(&project.id)
|
||||
{
|
||||
None
|
||||
} else {
|
||||
Some((
|
||||
|
@ -241,9 +242,9 @@ impl RandomizedTest for ProjectCollaborationTest {
|
|||
})
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
if !new_remote_projects.is_empty() {
|
||||
if !new_dev_server_projects.is_empty() {
|
||||
let (host_id, first_root_name) =
|
||||
new_remote_projects.choose(rng).unwrap().clone();
|
||||
new_dev_server_projects.choose(rng).unwrap().clone();
|
||||
break ClientOperation::OpenRemoteProject {
|
||||
host_id,
|
||||
first_root_name,
|
||||
|
@ -259,8 +260,8 @@ impl RandomizedTest for ProjectCollaborationTest {
|
|||
|
||||
// Close a remote project
|
||||
71..=80 => {
|
||||
if !client.remote_projects().is_empty() {
|
||||
let project = client.remote_projects().choose(rng).unwrap().clone();
|
||||
if !client.dev_server_projects().is_empty() {
|
||||
let project = client.dev_server_projects().choose(rng).unwrap().clone();
|
||||
let first_root_name = root_name_for_project(&project, cx);
|
||||
break ClientOperation::CloseRemoteProject {
|
||||
project_root_name: first_root_name,
|
||||
|
@ -595,12 +596,12 @@ impl RandomizedTest for ProjectCollaborationTest {
|
|||
);
|
||||
|
||||
let ix = client
|
||||
.remote_projects()
|
||||
.dev_server_projects()
|
||||
.iter()
|
||||
.position(|p| p == &project)
|
||||
.unwrap();
|
||||
cx.update(|_| {
|
||||
client.remote_projects_mut().remove(ix);
|
||||
client.dev_server_projects_mut().remove(ix);
|
||||
client.buffers().retain(|p, _| *p != project);
|
||||
drop(project);
|
||||
});
|
||||
|
@ -642,7 +643,7 @@ impl RandomizedTest for ProjectCollaborationTest {
|
|||
);
|
||||
|
||||
let project = project.await?;
|
||||
client.remote_projects_mut().push(project.clone());
|
||||
client.dev_server_projects_mut().push(project.clone());
|
||||
}
|
||||
|
||||
ClientOperation::CreateWorktreeEntry {
|
||||
|
@ -1142,7 +1143,7 @@ impl RandomizedTest for ProjectCollaborationTest {
|
|||
|
||||
async fn on_quiesce(_: &mut TestServer, clients: &mut [(Rc<TestClient>, TestAppContext)]) {
|
||||
for (client, client_cx) in clients.iter() {
|
||||
for guest_project in client.remote_projects().iter() {
|
||||
for guest_project in client.dev_server_projects().iter() {
|
||||
guest_project.read_with(client_cx, |guest_project, cx| {
|
||||
let host_project = clients.iter().find_map(|(client, cx)| {
|
||||
let project = client
|
||||
|
@ -1487,8 +1488,9 @@ fn project_for_root_name(
|
|||
if let Some(ix) = project_ix_for_root_name(client.local_projects().deref(), root_name, cx) {
|
||||
return Some(client.local_projects()[ix].clone());
|
||||
}
|
||||
if let Some(ix) = project_ix_for_root_name(client.remote_projects().deref(), root_name, cx) {
|
||||
return Some(client.remote_projects()[ix].clone());
|
||||
if let Some(ix) = project_ix_for_root_name(client.dev_server_projects().deref(), root_name, cx)
|
||||
{
|
||||
return Some(client.dev_server_projects()[ix].clone());
|
||||
}
|
||||
None
|
||||
}
|
||||
|
@ -1578,7 +1580,7 @@ fn choose_random_project(client: &TestClient, rng: &mut StdRng) -> Option<Model<
|
|||
.local_projects()
|
||||
.deref()
|
||||
.iter()
|
||||
.chain(client.remote_projects().iter())
|
||||
.chain(client.dev_server_projects().iter())
|
||||
.choose(rng)
|
||||
.cloned()
|
||||
}
|
||||
|
|
|
@ -533,7 +533,7 @@ impl<T: RandomizedTest> TestPlan<T> {
|
|||
deterministic.finish_waiting();
|
||||
server.allow_connections();
|
||||
|
||||
for project in client.remote_projects().iter() {
|
||||
for project in client.dev_server_projects().iter() {
|
||||
project.read_with(&client_cx, |project, _| {
|
||||
assert!(
|
||||
project.is_disconnected(),
|
||||
|
|
|
@ -64,7 +64,7 @@ pub struct TestClient {
|
|||
#[derive(Default)]
|
||||
struct TestClientState {
|
||||
local_projects: Vec<Model<Project>>,
|
||||
remote_projects: Vec<Model<Project>>,
|
||||
dev_server_projects: Vec<Model<Project>>,
|
||||
buffers: HashMap<Model<Project>, HashSet<Model<language::Buffer>>>,
|
||||
channel_buffers: HashSet<Model<ChannelBuffer>>,
|
||||
}
|
||||
|
@ -290,7 +290,7 @@ impl TestServer {
|
|||
collab_ui::init(&app_state, cx);
|
||||
file_finder::init(cx);
|
||||
menu::init();
|
||||
remote_projects::init(client.clone(), cx);
|
||||
dev_server_projects::init(client.clone(), cx);
|
||||
settings::KeymapFile::load_asset(os_keymap, cx).unwrap();
|
||||
});
|
||||
|
||||
|
@ -735,16 +735,18 @@ impl TestClient {
|
|||
Ref::map(self.state.borrow(), |state| &state.local_projects)
|
||||
}
|
||||
|
||||
pub fn remote_projects(&self) -> impl Deref<Target = Vec<Model<Project>>> + '_ {
|
||||
Ref::map(self.state.borrow(), |state| &state.remote_projects)
|
||||
pub fn dev_server_projects(&self) -> impl Deref<Target = Vec<Model<Project>>> + '_ {
|
||||
Ref::map(self.state.borrow(), |state| &state.dev_server_projects)
|
||||
}
|
||||
|
||||
pub fn local_projects_mut(&self) -> impl DerefMut<Target = Vec<Model<Project>>> + '_ {
|
||||
RefMut::map(self.state.borrow_mut(), |state| &mut state.local_projects)
|
||||
}
|
||||
|
||||
pub fn remote_projects_mut(&self) -> impl DerefMut<Target = Vec<Model<Project>>> + '_ {
|
||||
RefMut::map(self.state.borrow_mut(), |state| &mut state.remote_projects)
|
||||
pub fn dev_server_projects_mut(&self) -> impl DerefMut<Target = Vec<Model<Project>>> + '_ {
|
||||
RefMut::map(self.state.borrow_mut(), |state| {
|
||||
&mut state.dev_server_projects
|
||||
})
|
||||
}
|
||||
|
||||
pub fn buffers_for_project<'a>(
|
||||
|
@ -869,7 +871,7 @@ impl TestClient {
|
|||
})
|
||||
}
|
||||
|
||||
pub async fn build_remote_project(
|
||||
pub async fn build_dev_server_project(
|
||||
&self,
|
||||
host_project_id: u64,
|
||||
guest_cx: &mut TestAppContext,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue