199 lines · 6.7 KB · Rust
RawDownload
use crate::RemoteConnectionOptions; /// A normalized remote identity for matching live remote hosts against/// persisted remote metadata.////// This mirrors workspace persistence identity semantics rather than full/// `RemoteConnectionOptions` equality, so runtime-only fields like SSH/// nicknames or Docker environment overrides do not affect matching.#[derive(Debug, Clone, PartialEq, Eq, Hash)]pub enum RemoteConnectionIdentity {    Ssh {        host: String,        username: Option<String>,        port: Option<u16>,    },    Wsl {        distro_name: String,        user: Option<String>,    },    Docker {        container_id: String,        name: String,        remote_user: String,    },    #[cfg(any(test, feature = "test-support"))]    Mock { id: u64 },} impl RemoteConnectionIdentity {    /// A stable string form of this identity, suitable for use in    /// persistence keys (e.g. database keys scoped to a remote host).    pub fn persistence_key(&self) -> String {        match self {            Self::Ssh {                host,                username,                port,            } => format!(                "ssh:{}@{}:{}",                username.as_deref().unwrap_or_default(),                host,                port.map(|port| port.to_string()).unwrap_or_default()            ),            Self::Wsl { distro_name, user } => format!(                "wsl:{}@{}",                user.as_deref().unwrap_or_default(),                distro_name            ),            Self::Docker {                container_id,                name,                remote_user,            } => format!("docker:{remote_user}@{name}:{container_id}"),            #[cfg(any(test, feature = "test-support"))]            Self::Mock { id } => format!("mock:{id}"),        }    }} impl From<&RemoteConnectionOptions> for RemoteConnectionIdentity {    fn from(options: &RemoteConnectionOptions) -> Self {        match options {            RemoteConnectionOptions::Ssh(options) => Self::Ssh {                host: options.host.to_string(),                username: options.username.clone(),                port: options.port,            },            RemoteConnectionOptions::Wsl(options) => Self::Wsl {                distro_name: options.distro_name.clone(),                user: options.user.clone(),            },            RemoteConnectionOptions::Docker(options) => Self::Docker {                container_id: options.container_id.clone(),                name: options.name.clone(),                remote_user: options.remote_user.clone(),            },            #[cfg(any(test, feature = "test-support"))]            RemoteConnectionOptions::Mock(options) => Self::Mock { id: options.id },        }    }} pub fn remote_connection_identity(options: &RemoteConnectionOptions) -> RemoteConnectionIdentity {    options.into()} pub fn same_remote_connection_identity(    left: Option<&RemoteConnectionOptions>,    right: Option<&RemoteConnectionOptions>,) -> bool {    match (left, right) {        (Some(left), Some(right)) => {            remote_connection_identity(left) == remote_connection_identity(right)        }        (None, None) => true,        _ => false,    }} #[cfg(test)]mod tests {    use std::collections::BTreeMap;     use super::*;    use crate::{DockerConnectionOptions, SshConnectionOptions, WslConnectionOptions};     #[test]    fn ssh_identity_ignores_non_persisted_runtime_fields() {        let left = RemoteConnectionOptions::Ssh(SshConnectionOptions {            host: "example.com".into(),            username: Some("anth".to_string()),            port: Some(2222),            password: Some("secret".to_string()),            args: Some(vec!["-v".to_string()]),            connection_timeout: Some(30),            nickname: Some("work".to_string()),            upload_binary_over_ssh: true,            ..Default::default()        });        let right = RemoteConnectionOptions::Ssh(SshConnectionOptions {            host: "example.com".into(),            username: Some("anth".to_string()),            port: Some(2222),            password: None,            args: None,            connection_timeout: None,            nickname: None,            upload_binary_over_ssh: false,            ..Default::default()        });         assert!(same_remote_connection_identity(Some(&left), Some(&right),));    }     #[test]    fn ssh_identity_distinguishes_persistence_key_fields() {        let left = RemoteConnectionOptions::Ssh(SshConnectionOptions {            host: "example.com".into(),            username: Some("anth".to_string()),            port: Some(2222),            ..Default::default()        });        let right = RemoteConnectionOptions::Ssh(SshConnectionOptions {            host: "example.com".into(),            username: Some("anth".to_string()),            port: Some(2223),            ..Default::default()        });         assert!(!same_remote_connection_identity(Some(&left), Some(&right),));    }     #[test]    fn wsl_identity_includes_user() {        let left = RemoteConnectionOptions::Wsl(WslConnectionOptions {            distro_name: "Ubuntu".to_string(),            user: Some("anth".to_string()),        });        let right = RemoteConnectionOptions::Wsl(WslConnectionOptions {            distro_name: "Ubuntu".to_string(),            user: Some("root".to_string()),        });         assert!(!same_remote_connection_identity(Some(&left), Some(&right),));    }     #[test]    fn docker_identity_ignores_non_persisted_runtime_fields() {        let left = RemoteConnectionOptions::Docker(DockerConnectionOptions {            name: "zed-dev".to_string(),            container_id: "container-123".to_string(),            remote_user: "anth".to_string(),            upload_binary_over_docker_exec: true,            use_podman: true,            remote_env: BTreeMap::from([("FOO".to_string(), "BAR".to_string())]),        });        let right = RemoteConnectionOptions::Docker(DockerConnectionOptions {            name: "zed-dev".to_string(),            container_id: "container-123".to_string(),            remote_user: "anth".to_string(),            upload_binary_over_docker_exec: false,            use_podman: false,            remote_env: BTreeMap::new(),        });         assert!(same_remote_connection_identity(Some(&left), Some(&right),));    }     #[test]    fn local_identity_matches_only_local_identity() {        let remote = RemoteConnectionOptions::Wsl(WslConnectionOptions {            distro_name: "Ubuntu".to_string(),            user: Some("anth".to_string()),        });         assert!(same_remote_connection_identity(None, None));        assert!(!same_remote_connection_identity(None, Some(&remote)));    }}