Skip to content

Commit 153724a

Browse files
authored
Clean up handling of serialized ssh connection ids (#36781)
Small follow-up to #36714 Release Notes: - N/A
1 parent bc566fe commit 153724a

File tree

4 files changed

+93
-97
lines changed

4 files changed

+93
-97
lines changed

crates/remote/src/ssh_session.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,6 @@ use util::{
5252
paths::{PathStyle, RemotePathBuf},
5353
};
5454

55-
#[derive(
56-
Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, serde::Serialize, serde::Deserialize,
57-
)]
58-
pub struct SshProjectId(pub u64);
59-
6055
#[derive(Clone)]
6156
pub struct SshSocket {
6257
connection_options: SshConnectionOptions,

crates/workspace/src/persistence.rs

Lines changed: 85 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ use std::{
99
};
1010

1111
use anyhow::{Context as _, Result, bail};
12+
use collections::HashMap;
1213
use db::{define_connection, query, sqlez::connection::Connection, sqlez_macros::sql};
1314
use gpui::{Axis, Bounds, Task, WindowBounds, WindowId, point, size};
1415
use project::debugger::breakpoint_store::{BreakpointState, SourceBreakpoint};
1516

1617
use language::{LanguageName, Toolchain};
1718
use project::WorktreeId;
18-
use remote::ssh_session::SshProjectId;
1919
use sqlez::{
2020
bindable::{Bind, Column, StaticColumnCount},
2121
statement::{SqlType, Statement},
@@ -33,7 +33,7 @@ use crate::{
3333

3434
use model::{
3535
GroupId, ItemId, PaneId, SerializedItem, SerializedPane, SerializedPaneGroup,
36-
SerializedSshConnection, SerializedWorkspace,
36+
SerializedSshConnection, SerializedWorkspace, SshConnectionId,
3737
};
3838

3939
use self::model::{DockStructure, SerializedWorkspaceLocation};
@@ -615,15 +615,15 @@ impl WorkspaceDb {
615615
pub(crate) fn ssh_workspace_for_roots<P: AsRef<Path>>(
616616
&self,
617617
worktree_roots: &[P],
618-
ssh_project_id: SshProjectId,
618+
ssh_project_id: SshConnectionId,
619619
) -> Option<SerializedWorkspace> {
620620
self.workspace_for_roots_internal(worktree_roots, Some(ssh_project_id))
621621
}
622622

623623
pub(crate) fn workspace_for_roots_internal<P: AsRef<Path>>(
624624
&self,
625625
worktree_roots: &[P],
626-
ssh_connection_id: Option<SshProjectId>,
626+
ssh_connection_id: Option<SshConnectionId>,
627627
) -> Option<SerializedWorkspace> {
628628
// paths are sorted before db interactions to ensure that the order of the paths
629629
// doesn't affect the workspace selection for existing workspaces
@@ -762,15 +762,21 @@ impl WorkspaceDb {
762762
/// that used this workspace previously
763763
pub(crate) async fn save_workspace(&self, workspace: SerializedWorkspace) {
764764
let paths = workspace.paths.serialize();
765-
let ssh_connection_id = match &workspace.location {
766-
SerializedWorkspaceLocation::Local => None,
767-
SerializedWorkspaceLocation::Ssh(serialized_ssh_connection) => {
768-
Some(serialized_ssh_connection.id.0)
769-
}
770-
};
771765
log::debug!("Saving workspace at location: {:?}", workspace.location);
772766
self.write(move |conn| {
773767
conn.with_savepoint("update_worktrees", || {
768+
let ssh_connection_id = match &workspace.location {
769+
SerializedWorkspaceLocation::Local => None,
770+
SerializedWorkspaceLocation::Ssh(connection) => {
771+
Some(Self::get_or_create_ssh_connection_query(
772+
conn,
773+
connection.host.clone(),
774+
connection.port,
775+
connection.user.clone(),
776+
)?.0)
777+
}
778+
};
779+
774780
// Clear out panes and pane_groups
775781
conn.exec_bound(sql!(
776782
DELETE FROM pane_groups WHERE workspace_id = ?1;
@@ -893,39 +899,34 @@ impl WorkspaceDb {
893899
host: String,
894900
port: Option<u16>,
895901
user: Option<String>,
896-
) -> Result<SshProjectId> {
897-
if let Some(id) = self
898-
.get_ssh_connection(host.clone(), port, user.clone())
899-
.await?
902+
) -> Result<SshConnectionId> {
903+
self.write(move |conn| Self::get_or_create_ssh_connection_query(conn, host, port, user))
904+
.await
905+
}
906+
907+
fn get_or_create_ssh_connection_query(
908+
this: &Connection,
909+
host: String,
910+
port: Option<u16>,
911+
user: Option<String>,
912+
) -> Result<SshConnectionId> {
913+
if let Some(id) = this.select_row_bound(sql!(
914+
SELECT id FROM ssh_connections WHERE host IS ? AND port IS ? AND user IS ? LIMIT 1
915+
))?((host.clone(), port, user.clone()))?
900916
{
901-
Ok(SshProjectId(id))
917+
Ok(SshConnectionId(id))
902918
} else {
903919
log::debug!("Inserting SSH project at host {host}");
904-
let id = self
905-
.insert_ssh_connection(host, port, user)
906-
.await?
907-
.context("failed to insert ssh project")?;
908-
Ok(SshProjectId(id))
909-
}
910-
}
911-
912-
query! {
913-
async fn get_ssh_connection(host: String, port: Option<u16>, user: Option<String>) -> Result<Option<u64>> {
914-
SELECT id
915-
FROM ssh_connections
916-
WHERE host IS ? AND port IS ? AND user IS ?
917-
LIMIT 1
918-
}
919-
}
920-
921-
query! {
922-
async fn insert_ssh_connection(host: String, port: Option<u16>, user: Option<String>) -> Result<Option<u64>> {
923-
INSERT INTO ssh_connections (
924-
host,
925-
port,
926-
user
927-
) VALUES (?1, ?2, ?3)
928-
RETURNING id
920+
let id = this.select_row_bound(sql!(
921+
INSERT INTO ssh_connections (
922+
host,
923+
port,
924+
user
925+
) VALUES (?1, ?2, ?3)
926+
RETURNING id
927+
))?((host, port, user))?
928+
.context("failed to insert ssh project")?;
929+
Ok(SshConnectionId(id))
929930
}
930931
}
931932

@@ -963,15 +964,15 @@ impl WorkspaceDb {
963964
fn session_workspaces(
964965
&self,
965966
session_id: String,
966-
) -> Result<Vec<(PathList, Option<u64>, Option<SshProjectId>)>> {
967+
) -> Result<Vec<(PathList, Option<u64>, Option<SshConnectionId>)>> {
967968
Ok(self
968969
.session_workspaces_query(session_id)?
969970
.into_iter()
970971
.map(|(paths, order, window_id, ssh_connection_id)| {
971972
(
972973
PathList::deserialize(&SerializedPathList { paths, order }),
973974
window_id,
974-
ssh_connection_id.map(SshProjectId),
975+
ssh_connection_id.map(SshConnectionId),
975976
)
976977
})
977978
.collect())
@@ -1001,15 +1002,15 @@ impl WorkspaceDb {
10011002
}
10021003
}
10031004

1004-
fn ssh_connections(&self) -> Result<Vec<SerializedSshConnection>> {
1005+
fn ssh_connections(&self) -> Result<HashMap<SshConnectionId, SerializedSshConnection>> {
10051006
Ok(self
10061007
.ssh_connections_query()?
10071008
.into_iter()
1008-
.map(|(id, host, port, user)| SerializedSshConnection {
1009-
id: SshProjectId(id),
1010-
host,
1011-
port,
1012-
user,
1009+
.map(|(id, host, port, user)| {
1010+
(
1011+
SshConnectionId(id),
1012+
SerializedSshConnection { host, port, user },
1013+
)
10131014
})
10141015
.collect())
10151016
}
@@ -1021,19 +1022,18 @@ impl WorkspaceDb {
10211022
}
10221023
}
10231024

1024-
pub fn ssh_connection(&self, id: SshProjectId) -> Result<SerializedSshConnection> {
1025+
pub(crate) fn ssh_connection(&self, id: SshConnectionId) -> Result<SerializedSshConnection> {
10251026
let row = self.ssh_connection_query(id.0)?;
10261027
Ok(SerializedSshConnection {
1027-
id: SshProjectId(row.0),
1028-
host: row.1,
1029-
port: row.2,
1030-
user: row.3,
1028+
host: row.0,
1029+
port: row.1,
1030+
user: row.2,
10311031
})
10321032
}
10331033

10341034
query! {
1035-
fn ssh_connection_query(id: u64) -> Result<(u64, String, Option<u16>, Option<String>)> {
1036-
SELECT id, host, port, user
1035+
fn ssh_connection_query(id: u64) -> Result<(String, Option<u16>, Option<String>)> {
1036+
SELECT host, port, user
10371037
FROM ssh_connections
10381038
WHERE id = ?
10391039
}
@@ -1075,10 +1075,8 @@ impl WorkspaceDb {
10751075
let ssh_connections = self.ssh_connections()?;
10761076

10771077
for (id, paths, ssh_connection_id) in self.recent_workspaces()? {
1078-
if let Some(ssh_connection_id) = ssh_connection_id.map(SshProjectId) {
1079-
if let Some(ssh_connection) =
1080-
ssh_connections.iter().find(|rp| rp.id == ssh_connection_id)
1081-
{
1078+
if let Some(ssh_connection_id) = ssh_connection_id.map(SshConnectionId) {
1079+
if let Some(ssh_connection) = ssh_connections.get(&ssh_connection_id) {
10821080
result.push((
10831081
id,
10841082
SerializedWorkspaceLocation::Ssh(ssh_connection.clone()),
@@ -2340,12 +2338,10 @@ mod tests {
23402338
]
23412339
.into_iter()
23422340
.map(|(host, user)| async {
2343-
let id = db
2344-
.get_or_create_ssh_connection(host.to_string(), None, Some(user.to_string()))
2341+
db.get_or_create_ssh_connection(host.to_string(), None, Some(user.to_string()))
23452342
.await
23462343
.unwrap();
23472344
SerializedSshConnection {
2348-
id,
23492345
host: host.into(),
23502346
port: None,
23512347
user: Some(user.into()),
@@ -2501,26 +2497,34 @@ mod tests {
25012497
let stored_projects = db.ssh_connections().unwrap();
25022498
assert_eq!(
25032499
stored_projects,
2504-
&[
2505-
SerializedSshConnection {
2506-
id: ids[0],
2507-
host: "example.com".into(),
2508-
port: None,
2509-
user: None,
2510-
},
2511-
SerializedSshConnection {
2512-
id: ids[1],
2513-
host: "anotherexample.com".into(),
2514-
port: Some(123),
2515-
user: Some("user2".into()),
2516-
},
2517-
SerializedSshConnection {
2518-
id: ids[2],
2519-
host: "yetanother.com".into(),
2520-
port: Some(345),
2521-
user: None,
2522-
},
2500+
[
2501+
(
2502+
ids[0],
2503+
SerializedSshConnection {
2504+
host: "example.com".into(),
2505+
port: None,
2506+
user: None,
2507+
}
2508+
),
2509+
(
2510+
ids[1],
2511+
SerializedSshConnection {
2512+
host: "anotherexample.com".into(),
2513+
port: Some(123),
2514+
user: Some("user2".into()),
2515+
}
2516+
),
2517+
(
2518+
ids[2],
2519+
SerializedSshConnection {
2520+
host: "yetanother.com".into(),
2521+
port: Some(345),
2522+
user: None,
2523+
}
2524+
),
25232525
]
2526+
.into_iter()
2527+
.collect::<HashMap<_, _>>(),
25242528
);
25252529
}
25262530

crates/workspace/src/persistence/model.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ use db::sqlez::{
1212
use gpui::{AsyncWindowContext, Entity, WeakEntity};
1313

1414
use project::{Project, debugger::breakpoint_store::SourceBreakpoint};
15-
use remote::ssh_session::SshProjectId;
1615
use serde::{Deserialize, Serialize};
1716
use std::{
1817
collections::BTreeMap,
@@ -22,9 +21,13 @@ use std::{
2221
use util::ResultExt;
2322
use uuid::Uuid;
2423

24+
#[derive(
25+
Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, serde::Serialize, serde::Deserialize,
26+
)]
27+
pub(crate) struct SshConnectionId(pub u64);
28+
2529
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
2630
pub struct SerializedSshConnection {
27-
pub id: SshProjectId,
2831
pub host: String,
2932
pub port: Option<u16>,
3033
pub user: Option<String>,

crates/workspace/src/workspace.rs

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,7 @@ use project::{
7474
DirectoryLister, Project, ProjectEntryId, ProjectPath, ResolvedPath, Worktree, WorktreeId,
7575
debugger::{breakpoint_store::BreakpointStoreEvent, session::ThreadStatus},
7676
};
77-
use remote::{
78-
SshClientDelegate, SshConnectionOptions,
79-
ssh_session::{ConnectionIdentifier, SshProjectId},
80-
};
77+
use remote::{SshClientDelegate, SshConnectionOptions, ssh_session::ConnectionIdentifier};
8178
use schemars::JsonSchema;
8279
use serde::Deserialize;
8380
use session::AppSession;
@@ -1128,7 +1125,6 @@ pub struct Workspace {
11281125
terminal_provider: Option<Box<dyn TerminalProvider>>,
11291126
debugger_provider: Option<Arc<dyn DebuggerProvider>>,
11301127
serializable_items_tx: UnboundedSender<Box<dyn SerializableItemHandle>>,
1131-
serialized_ssh_connection_id: Option<SshProjectId>,
11321128
_items_serializer: Task<Result<()>>,
11331129
session_id: Option<String>,
11341130
scheduled_tasks: Vec<Task<()>>,
@@ -1461,7 +1457,7 @@ impl Workspace {
14611457
serializable_items_tx,
14621458
_items_serializer,
14631459
session_id: Some(session_id),
1464-
serialized_ssh_connection_id: None,
1460+
14651461
scheduled_tasks: Vec::new(),
14661462
}
14671463
}
@@ -5288,11 +5284,9 @@ impl Workspace {
52885284

52895285
fn serialize_workspace_location(&self, cx: &App) -> WorkspaceLocation {
52905286
let paths = PathList::new(&self.root_paths(cx));
5291-
let connection = self.project.read(cx).ssh_connection_options(cx);
5292-
if let Some((id, connection)) = self.serialized_ssh_connection_id.zip(connection) {
5287+
if let Some(connection) = self.project.read(cx).ssh_connection_options(cx) {
52935288
WorkspaceLocation::Location(
52945289
SerializedWorkspaceLocation::Ssh(SerializedSshConnection {
5295-
id,
52965290
host: connection.host,
52975291
port: connection.port,
52985292
user: connection.username,

0 commit comments

Comments
 (0)