diff --git a/Cargo.lock b/Cargo.lock index 8a50b6b..9fe1889 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -429,7 +429,7 @@ dependencies = [ [[package]] name = "distant" -version = "0.15.0-alpha.1" +version = "0.15.0-alpha.2" dependencies = [ "assert_cmd", "assert_fs", @@ -453,7 +453,7 @@ dependencies = [ [[package]] name = "distant-core" -version = "0.15.0-alpha.1" +version = "0.15.0-alpha.2" dependencies = [ "assert_fs", "bytes", @@ -480,7 +480,7 @@ dependencies = [ [[package]] name = "distant-ssh2" -version = "0.15.0-alpha.1" +version = "0.15.0-alpha.2" dependencies = [ "assert_cmd", "assert_fs", diff --git a/Cargo.toml b/Cargo.toml index 2df5aa5..74e0858 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ name = "distant" description = "Operate on a remote computer through file and process manipulation" categories = ["command-line-utilities"] keywords = ["cli"] -version = "0.15.0-alpha.1" +version = "0.15.0-alpha.2" authors = ["Chip Senkbeil "] edition = "2018" homepage = "https://github.com/chipsenkbeil/distant" @@ -28,7 +28,7 @@ ssh2 = ["distant-ssh2"] [dependencies] derive_more = { version = "0.99.16", default-features = false, features = ["display", "from", "error", "is_variant"] } -distant-core = { version = "=0.15.0-alpha.1", path = "distant-core", features = ["structopt"] } +distant-core = { version = "=0.15.0-alpha.2", path = "distant-core", features = ["structopt"] } flexi_logger = "0.18.0" fork = "0.1.18" log = "0.4.14" @@ -41,7 +41,7 @@ strum = { version = "0.21.0", features = ["derive"] } whoami = "1.1.2" # Optional native SSH functionality -distant-ssh2 = { version = "=0.15.0-alpha.1", path = "distant-ssh2", optional = true } +distant-ssh2 = { version = "=0.15.0-alpha.2", path = "distant-ssh2", optional = true } [dev-dependencies] assert_cmd = "2.0.0" diff --git a/distant-core/Cargo.toml b/distant-core/Cargo.toml index 2ce47a9..a37bbdf 100644 --- a/distant-core/Cargo.toml +++ b/distant-core/Cargo.toml @@ -2,7 +2,7 @@ name = "distant-core" description = "Core library for distant, enabling operation on a remote computer through file and process manipulation" categories = ["network-programming"] -version = "0.15.0-alpha.1" +version = "0.15.0-alpha.2" authors = ["Chip Senkbeil "] edition = "2018" homepage = "https://github.com/chipsenkbeil/distant" diff --git a/distant-core/src/client/lsp/mod.rs b/distant-core/src/client/lsp/mod.rs index 62bbb89..d8e2467 100644 --- a/distant-core/src/client/lsp/mod.rs +++ b/distant-core/src/client/lsp/mod.rs @@ -1,5 +1,5 @@ use super::{RemoteProcess, RemoteProcessError, RemoteStderr, RemoteStdin, RemoteStdout}; -use crate::client::Session; +use crate::client::SessionChannel; use futures::stream::{Stream, StreamExt}; use std::{ fmt::Write, @@ -25,11 +25,11 @@ impl RemoteLspProcess { /// the process like an LSP server pub async fn spawn( tenant: impl Into, - session: &mut Session, + channel: SessionChannel, cmd: impl Into, args: Vec, ) -> Result { - let mut inner = RemoteProcess::spawn(tenant, session, cmd, args).await?; + let mut inner = RemoteProcess::spawn(tenant, channel, cmd, args).await?; let stdin = inner.stdin.take().map(RemoteLspStdin::new); let stdout = inner.stdout.take().map(RemoteLspStdout::new); let stderr = inner.stderr.take().map(RemoteLspStderr::new); @@ -248,6 +248,7 @@ fn read_lsp_messages(input: String) -> io::Result<(Option, Vec) mod tests { use super::*; use crate::{ + client::Session, data::{Request, RequestData, Response, ResponseData}, net::{InmemoryStream, PlainCodec, Transport}, }; @@ -259,11 +260,11 @@ mod tests { // Configures an lsp process with a means to send & receive data from outside async fn spawn_lsp_process() -> (Transport, RemoteLspProcess) { let (mut t1, t2) = Transport::make_pair(); - let mut session = Session::initialize(t2).unwrap(); + let session = Session::initialize(t2).unwrap(); let spawn_task = tokio::spawn(async move { RemoteLspProcess::spawn( String::from("test-tenant"), - &mut session, + session.clone_channel(), String::from("cmd"), vec![String::from("arg")], ) diff --git a/distant-core/src/client/process.rs b/distant-core/src/client/process.rs index 35405b1..38ef355 100644 --- a/distant-core/src/client/process.rs +++ b/distant-core/src/client/process.rs @@ -1,5 +1,5 @@ use crate::{ - client::{Mailbox, Session, SessionChannel}, + client::{Mailbox, SessionChannel}, constants::CLIENT_MAILBOX_CAPACITY, data::{Request, RequestData, ResponseData}, net::TransportError, @@ -61,7 +61,7 @@ impl RemoteProcess { /// Spawns the specified process on the remote machine using the given session pub async fn spawn( tenant: impl Into, - session: &mut Session, + mut channel: SessionChannel, cmd: impl Into, args: Vec, ) -> Result { @@ -69,7 +69,7 @@ impl RemoteProcess { let cmd = cmd.into(); // Submit our run request and get back a mailbox for responses - let mut mailbox = session + let mut mailbox = channel .mail(Request::new( tenant.as_str(), vec![RequestData::ProcRun { cmd, args }], @@ -121,7 +121,6 @@ impl RemoteProcess { }); // Spawn a task that takes stdin from our channel and forwards it to the remote process - let channel = session.clone_channel(); let req_task = tokio::spawn(async move { process_outgoing_requests(tenant, id, channel, stdin_rx, kill_rx).await }); @@ -302,6 +301,7 @@ async fn process_incoming_responses( mod tests { use super::*; use crate::{ + client::Session, data::{Error, ErrorKind, Response}, net::{InmemoryStream, PlainCodec, Transport}, }; @@ -313,14 +313,14 @@ mod tests { #[tokio::test] async fn spawn_should_return_invalid_data_if_payload_size_unexpected() { - let (mut transport, mut session) = make_session(); + let (mut transport, session) = make_session(); // Create a task for process spawning as we need to handle the request and a response // in a separate async block let spawn_task = tokio::spawn(async move { RemoteProcess::spawn( String::from("test-tenant"), - &mut session, + session.clone_channel(), String::from("cmd"), vec![String::from("arg")], ) @@ -351,14 +351,14 @@ mod tests { #[tokio::test] async fn spawn_should_return_invalid_data_if_did_not_get_a_indicator_that_process_started() { - let (mut transport, mut session) = make_session(); + let (mut transport, session) = make_session(); // Create a task for process spawning as we need to handle the request and a response // in a separate async block let spawn_task = tokio::spawn(async move { RemoteProcess::spawn( String::from("test-tenant"), - &mut session, + session.clone_channel(), String::from("cmd"), vec![String::from("arg")], ) @@ -396,14 +396,14 @@ mod tests { #[tokio::test] async fn kill_should_return_error_if_internal_tasks_already_completed() { - let (mut transport, mut session) = make_session(); + let (mut transport, session) = make_session(); // Create a task for process spawning as we need to handle the request and a response // in a separate async block let spawn_task = tokio::spawn(async move { RemoteProcess::spawn( String::from("test-tenant"), - &mut session, + session.clone_channel(), String::from("cmd"), vec![String::from("arg")], ) @@ -441,14 +441,14 @@ mod tests { #[tokio::test] async fn kill_should_send_proc_kill_request_and_then_cause_stdin_forwarding_to_close() { - let (mut transport, mut session) = make_session(); + let (mut transport, session) = make_session(); // Create a task for process spawning as we need to handle the request and a response // in a separate async block let spawn_task = tokio::spawn(async move { RemoteProcess::spawn( String::from("test-tenant"), - &mut session, + session.clone_channel(), String::from("cmd"), vec![String::from("arg")], ) @@ -497,14 +497,14 @@ mod tests { #[tokio::test] async fn stdin_should_be_forwarded_from_receiver_field() { - let (mut transport, mut session) = make_session(); + let (mut transport, session) = make_session(); // Create a task for process spawning as we need to handle the request and a response // in a separate async block let spawn_task = tokio::spawn(async move { RemoteProcess::spawn( String::from("test-tenant"), - &mut session, + session.clone_channel(), String::from("cmd"), vec![String::from("arg")], ) @@ -552,14 +552,14 @@ mod tests { #[tokio::test] async fn stdout_should_be_forwarded_to_receiver_field() { - let (mut transport, mut session) = make_session(); + let (mut transport, session) = make_session(); // Create a task for process spawning as we need to handle the request and a response // in a separate async block let spawn_task = tokio::spawn(async move { RemoteProcess::spawn( String::from("test-tenant"), - &mut session, + session.clone_channel(), String::from("cmd"), vec![String::from("arg")], ) @@ -601,14 +601,14 @@ mod tests { #[tokio::test] async fn stderr_should_be_forwarded_to_receiver_field() { - let (mut transport, mut session) = make_session(); + let (mut transport, session) = make_session(); // Create a task for process spawning as we need to handle the request and a response // in a separate async block let spawn_task = tokio::spawn(async move { RemoteProcess::spawn( String::from("test-tenant"), - &mut session, + session.clone_channel(), String::from("cmd"), vec![String::from("arg")], ) @@ -650,14 +650,14 @@ mod tests { #[tokio::test] async fn wait_should_return_error_if_internal_tasks_fail() { - let (mut transport, mut session) = make_session(); + let (mut transport, session) = make_session(); // Create a task for process spawning as we need to handle the request and a response // in a separate async block let spawn_task = tokio::spawn(async move { RemoteProcess::spawn( String::from("test-tenant"), - &mut session, + session.clone_channel(), String::from("cmd"), vec![String::from("arg")], ) @@ -692,14 +692,14 @@ mod tests { #[tokio::test] async fn wait_should_return_error_if_connection_terminates_before_receiving_done_response() { - let (mut transport, mut session) = make_session(); + let (mut transport, session) = make_session(); // Create a task for process spawning as we need to handle the request and a response // in a separate async block let spawn_task = tokio::spawn(async move { RemoteProcess::spawn( String::from("test-tenant"), - &mut session, + session.clone_channel(), String::from("cmd"), vec![String::from("arg")], ) @@ -741,14 +741,14 @@ mod tests { #[tokio::test] async fn receiving_done_response_should_result_in_wait_returning_exit_information() { - let (mut transport, mut session) = make_session(); + let (mut transport, session) = make_session(); // Create a task for process spawning as we need to handle the request and a response // in a separate async block let spawn_task = tokio::spawn(async move { RemoteProcess::spawn( String::from("test-tenant"), - &mut session, + session.clone_channel(), String::from("cmd"), vec![String::from("arg")], ) diff --git a/distant-core/src/client/session/ext.rs b/distant-core/src/client/session/ext.rs index 7e89381..191cbc2 100644 --- a/distant-core/src/client/session/ext.rs +++ b/distant-core/src/client/session/ext.rs @@ -1,14 +1,15 @@ use crate::{ - client::{RemoteLspProcess, RemoteProcess, RemoteProcessError, Session}, + client::{RemoteLspProcess, RemoteProcess, RemoteProcessError, SessionChannel}, data::{DirEntry, Error as Failure, FileType, Request, RequestData, ResponseData}, net::TransportError, }; use derive_more::{Display, Error, From}; use std::{future::Future, path::PathBuf, pin::Pin}; -/// Represents an error that can occur related to convenience functions tied to a [`Session`] +/// Represents an error that can occur related to convenience functions tied to a +/// [`SessionChannel`] through [`SessionChannelExt`] #[derive(Debug, Display, Error, From)] -pub enum SessionExtError { +pub enum SessionChannelExtError { /// Occurs when the remote action fails Failure(#[error(not(source))] Failure), @@ -19,7 +20,7 @@ pub enum SessionExtError { MismatchedResponse, } -pub type AsyncReturn<'a, T, E = SessionExtError> = +pub type AsyncReturn<'a, T, E = SessionChannelExtError> = Pin> + Send + 'a>>; /// Represents metadata about some path on a remote machine @@ -35,8 +36,8 @@ pub struct Metadata { pub modified: Option, } -/// Provides convenience functions on top of a [`Session`] -pub trait SessionExt { +/// Provides convenience functions on top of a [`SessionChannel`] +pub trait SessionChannelExt { /// Appends to a remote file using the data from a collection of bytes fn append_file( &mut self, @@ -166,7 +167,7 @@ macro_rules! make_body { if data.is_ok() { Ok(()) } else { - Err(SessionExtError::MismatchedResponse) + Err(SessionChannelExtError::MismatchedResponse) } }) }; @@ -177,12 +178,12 @@ macro_rules! make_body { $self .send(req) .await - .map_err(SessionExtError::from) + .map_err(SessionChannelExtError::from) .and_then(|res| { if res.payload.len() == 1 { Ok(res.payload.into_iter().next().unwrap()) } else { - Err(SessionExtError::MismatchedResponse) + Err(SessionChannelExtError::MismatchedResponse) } }) .and_then($and_then) @@ -190,7 +191,7 @@ macro_rules! make_body { }}; } -impl SessionExt for Session { +impl SessionChannelExt for SessionChannel { fn append_file( &mut self, tenant: impl Into, @@ -258,7 +259,7 @@ impl SessionExt for Session { RequestData::Exists { path: path.into() }, |data| match data { ResponseData::Exists(x) => Ok(x), - _ => Err(SessionExtError::MismatchedResponse), + _ => Err(SessionChannelExtError::MismatchedResponse), } ) } @@ -296,7 +297,7 @@ impl SessionExt for Session { created, modified, }), - _ => Err(SessionExtError::MismatchedResponse), + _ => Err(SessionChannelExtError::MismatchedResponse), } ) } @@ -322,7 +323,7 @@ impl SessionExt for Session { }, |data| match data { ResponseData::DirEntries { entries, errors } => Ok((entries, errors)), - _ => Err(SessionExtError::MismatchedResponse), + _ => Err(SessionChannelExtError::MismatchedResponse), } ) } @@ -338,7 +339,7 @@ impl SessionExt for Session { RequestData::FileRead { path: path.into() }, |data| match data { ResponseData::Blob { data } => Ok(data), - _ => Err(SessionExtError::MismatchedResponse), + _ => Err(SessionChannelExtError::MismatchedResponse), } ) } @@ -354,7 +355,7 @@ impl SessionExt for Session { RequestData::FileReadText { path: path.into() }, |data| match data { ResponseData::Text { data } => Ok(data), - _ => Err(SessionExtError::MismatchedResponse), + _ => Err(SessionChannelExtError::MismatchedResponse), } ) } @@ -395,7 +396,7 @@ impl SessionExt for Session { ) -> AsyncReturn<'_, RemoteProcess, RemoteProcessError> { let tenant = tenant.into(); let cmd = cmd.into(); - Box::pin(async move { RemoteProcess::spawn(tenant, self, cmd, args).await }) + Box::pin(async move { RemoteProcess::spawn(tenant, self.clone(), cmd, args).await }) } fn spawn_lsp( @@ -406,7 +407,7 @@ impl SessionExt for Session { ) -> AsyncReturn<'_, RemoteLspProcess, RemoteProcessError> { let tenant = tenant.into(); let cmd = cmd.into(); - Box::pin(async move { RemoteLspProcess::spawn(tenant, self, cmd, args).await }) + Box::pin(async move { RemoteLspProcess::spawn(tenant, self.clone(), cmd, args).await }) } fn write_file( diff --git a/distant-core/src/client/session/mod.rs b/distant-core/src/client/session/mod.rs index cdc27b4..d332c78 100644 --- a/distant-core/src/client/session/mod.rs +++ b/distant-core/src/client/session/mod.rs @@ -20,7 +20,7 @@ use tokio::{ }; mod ext; -pub use ext::{Metadata, SessionExt, SessionExtError}; +pub use ext::{Metadata, SessionChannelExt, SessionChannelExtError}; mod info; pub use info::{SessionInfo, SessionInfoFile, SessionInfoParseError}; diff --git a/distant-ssh2/Cargo.toml b/distant-ssh2/Cargo.toml index b2ce429..b28d22d 100644 --- a/distant-ssh2/Cargo.toml +++ b/distant-ssh2/Cargo.toml @@ -2,7 +2,7 @@ name = "distant-ssh2" description = "Library to enable native ssh-2 protocol for use with distant sessions" categories = ["network-programming"] -version = "0.15.0-alpha.1" +version = "0.15.0-alpha.2" authors = ["Chip Senkbeil "] edition = "2018" homepage = "https://github.com/chipsenkbeil/distant" @@ -12,7 +12,7 @@ license = "MIT OR Apache-2.0" [dependencies] async-compat = "0.2.1" -distant-core = { version = "=0.15.0-alpha.1", path = "../distant-core" } +distant-core = { version = "=0.15.0-alpha.2", path = "../distant-core" } futures = "0.3.16" log = "0.4.14" rand = { version = "0.8.4", features = ["getrandom"] } diff --git a/src/subcommand/action.rs b/src/subcommand/action.rs index 31207bf..a22d9c9 100644 --- a/src/subcommand/action.rs +++ b/src/subcommand/action.rs @@ -88,7 +88,8 @@ async fn start( // the stdin will be used for sending ProcStdin to remote process (_, Some(RequestData::ProcRun { cmd, args })) if is_shell_format => { let mut proc = - RemoteProcess::spawn(utils::new_tenant(), &mut session, cmd, args).await?; + RemoteProcess::spawn(utils::new_tenant(), session.clone_channel(), cmd, args) + .await?; // If we also parsed an LSP's initialize request for its session, we want to forward // it along in the case of a process call diff --git a/src/subcommand/lsp.rs b/src/subcommand/lsp.rs index f33b371..37a46d9 100644 --- a/src/subcommand/lsp.rs +++ b/src/subcommand/lsp.rs @@ -65,11 +65,16 @@ async fn run_async(cmd: LspSubcommand, opt: CommonOpt) -> Result<(), Error> { async fn start( cmd: LspSubcommand, - mut session: Session, + session: Session, lsp_data: Option, ) -> Result<(), Error> { - let mut proc = - RemoteLspProcess::spawn(utils::new_tenant(), &mut session, cmd.cmd, cmd.args).await?; + let mut proc = RemoteLspProcess::spawn( + utils::new_tenant(), + session.clone_channel(), + cmd.cmd, + cmd.args, + ) + .await?; // If we also parsed an LSP's initialize request for its session, we want to forward // it along in the case of a process call