Initial commit

pull/218/head
Chip Senkbeil 10 months ago
parent 56b3b8f4f1
commit eeb9c955d4
No known key found for this signature in database
GPG Key ID: 35EF1F8EC72A4131

@ -7,10 +7,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Changed
- `distant_protocol::PROTOCOL_VERSION` now uses the crate's major, minor, and
patch version at compile-time (parsed via `const-str` crate) to streamline
version handling between crate and protocol
### Fixed
- CLI commands like `distant manager select` will now output errors in a JSON
format when configured to communicate using JSON
- `distant-ssh2` no longer caches the remote family globally, but instead
caches it per `Ssh` instance
### Removed
- `Cmd::program` and `Cmd::arguments` functions as they were misleading (didn't
do what `distant-local` or `distant-ssh2` do)
## [0.20.0-alpha.12]

7
Cargo.lock generated

@ -571,6 +571,12 @@ version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "520fbf3c07483f94e3e3ca9d0cfd913d7718ef2483d2cfd91c0d9e91474ab913"
[[package]]
name = "const-str"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aca749d3d3f5b87a0d6100509879f9cf486ab510803a4a4e1001da1ff61c2bd6"
[[package]]
name = "convert_case"
version = "0.4.0"
@ -952,6 +958,7 @@ name = "distant-protocol"
version = "0.20.0-alpha.12"
dependencies = [
"bitflags 2.3.1",
"const-str",
"derive_more",
"regex",
"rmp",

@ -17,6 +17,7 @@ tests = []
[dependencies]
bitflags = "2.3.1"
const-str = "0.5.6"
derive_more = { version = "0.99.17", default-features = false, features = ["deref", "deref_mut", "display", "from", "error", "into", "into_iterator", "is_variant"] }
regex = "1.8.3"
serde = { version = "1.0.163", features = ["derive"] }

@ -12,22 +12,6 @@ impl Cmd {
pub fn new(cmd: impl Into<String>) -> Self {
Self(cmd.into())
}
/// Returns reference to the program portion of the command
pub fn program(&self) -> &str {
match self.0.split_once(' ') {
Some((program, _)) => program.trim(),
None => self.0.trim(),
}
}
/// Returns reference to the arguments portion of the command
pub fn arguments(&self) -> &str {
match self.0.split_once(' ') {
Some((_, arguments)) => arguments.trim(),
None => "",
}
}
}
impl Deref for Cmd {

@ -17,7 +17,11 @@ pub use response::*;
/// Protocol version indicated by the tuple of (major, minor, patch).
///
/// This is different from the crate version, which matches that of the complete suite of distant
/// crates. Rather, this verison is used to provide stability indicators when the protocol itself
/// changes across crate versions.
pub const PROTOCOL_VERSION: SemVer = (0, 1, 0);
/// This should match the version of this crate such that any significant change to the crate
/// version will also be reflected in this constant that can be used to verify compatibility across
/// the wire.
pub const PROTOCOL_VERSION: SemVer = (
const_str::parse!(env!("CARGO_PKG_VERSION_MAJOR"), u8),
const_str::parse!(env!("CARGO_PKG_VERSION_MINOR"), u8),
const_str::parse!(env!("CARGO_PKG_VERSION_PATCH"), u8),
);

@ -16,7 +16,6 @@ use std::str::FromStr;
use std::time::Duration;
use async_compat::CompatExt;
use async_once_cell::OnceCell;
use async_trait::async_trait;
use distant_core::net::auth::{AuthHandlerMap, DummyAuthHandler, Verifier};
use distant_core::net::client::{Client, ClientConfig};
@ -25,6 +24,7 @@ use distant_core::net::server::{Server, ServerRef};
use distant_core::{DistantApiServerHandler, DistantClient, DistantSingleKeyCredentials};
use log::*;
use smol::channel::Receiver as SmolReceiver;
use tokio::sync::Mutex;
use wezterm_ssh::{
ChildKiller, Config as WezConfig, MasterPty, PtySize, Session as WezSession,
SessionEvent as WezSessionEvent,
@ -325,17 +325,20 @@ impl SshAuthHandler for LocalSshAuthHandler {
}
}
/// Represents an ssh2 client
/// Represents an ssh2 client.
pub struct Ssh {
session: WezSession,
events: SmolReceiver<WezSessionEvent>,
host: String,
port: u16,
authenticated: bool,
/// Cached copy of the family representing the remote machine.
cached_family: Mutex<Option<SshFamily>>,
}
impl Ssh {
/// Connect to a remote TCP server using SSH
/// Connect to a remote TCP server using SSH.
pub fn connect(host: impl AsRef<str>, opts: SshOpts) -> io::Result<Self> {
debug!(
"Establishing ssh connection to {} using {:?}",
@ -416,15 +419,16 @@ impl Ssh {
host: host.as_ref().to_string(),
port,
authenticated: false,
cached_family: Mutex::new(None),
})
}
/// Host this client is connected to
/// Host this client is connected to.
pub fn host(&self) -> &str {
&self.host
}
/// Port this client is connected to on remote host
/// Port this client is connected to on remote host.
pub fn port(&self) -> u16 {
self.port
}
@ -434,7 +438,7 @@ impl Ssh {
self.authenticated
}
/// Authenticates the [`Ssh`] if not already authenticated
/// Authenticates the [`Ssh`] if not already authenticated.
pub async fn authenticate(&mut self, handler: impl SshAuthHandler) -> io::Result<()> {
// If already authenticated, exit
if self.authenticated {
@ -499,10 +503,10 @@ impl Ssh {
Ok(())
}
/// Detects the family of operating system on the remote machine
/// Detects the family of operating system on the remote machine.
///
/// Caches the result such that subsequent checks will return the same family.
pub async fn detect_family(&self) -> io::Result<SshFamily> {
static INSTANCE: OnceCell<SshFamily> = OnceCell::new();
// Exit early if not authenticated as this is a requirement
if !self.authenticated {
return Err(io::Error::new(
@ -511,18 +515,23 @@ impl Ssh {
));
}
INSTANCE
.get_or_try_init(async move {
let is_windows = utils::is_windows(&self.session).await?;
let mut family = self.cached_family.lock().await;
Ok(if is_windows {
SshFamily::Windows
} else {
SshFamily::Unix
})
})
.await
.copied()
// Family value is not present, so we retrieve it now and populate our cache
if family.is_none() {
// Check if we are windows, otherwise assume unix, returning an error if encountered,
// which will also drop our lock on the cache
let is_windows = utils::is_windows(&self.session).await?;
*family = Some(if is_windows {
SshFamily::Windows
} else {
SshFamily::Unix
});
}
// Cache should always be Some(...) by this point
Ok(family.unwrap())
}
/// Consume [`Ssh`] and produce a [`DistantClient`] that is connected to a remote

Loading…
Cancel
Save