Mercurial > hg-stable
changeset 44852:d6f706929120
rust-chg: reimplement ChgClientExt as ChgClient wrapper
ChgClient is no longer an extension trait because:
a. Client object is not consumed and recreated in future-0.3 world, which
unblocks writing a simple wrapper struct.
b. async fn isn't allowed in trait.
Overall, the API should become simpler.
Differential Revision: https://phab.mercurial-scm.org/D8446
author | Yuya Nishihara <yuya@tcha.org> |
---|---|
date | Fri, 10 Apr 2020 23:26:36 +0900 |
parents | 94cace4b80ea |
children | a347a329e48d |
files | rust/chg/src/clientext.rs rust/chg/src/lib.rs |
diffstat | 2 files changed, 82 insertions(+), 89 deletions(-) [+] |
line wrap: on
line diff
--- a/rust/chg/src/clientext.rs Fri Apr 10 22:44:51 2020 +0900 +++ b/rust/chg/src/clientext.rs Fri Apr 10 23:26:36 2020 +0900 @@ -5,55 +5,99 @@ //! cHg extensions to command server client. -use bytes::{BufMut, Bytes, BytesMut}; +use bytes::{BufMut, BytesMut}; use std::ffi::OsStr; use std::io; use std::mem; use std::os::unix::ffi::OsStrExt; use std::os::unix::io::AsRawFd; use std::path::Path; -use tokio_hglib::protocol::{OneShotQuery, OneShotRequest}; -use tokio_hglib::{Client, Connection}; +use tokio_hglib::UnixClient; -use crate::attachio::AttachIo; -use crate::message::{self, Instruction}; -use crate::runcommand::ChgRunCommand; +use crate::attachio; +use crate::message::{self, Instruction, ServerSpec}; +use crate::runcommand; use crate::uihandler::SystemHandler; -pub trait ChgClientExt<C> -where - C: Connection + AsRawFd, -{ +/// Command-server client that also supports cHg extensions. +pub struct ChgClient { + client: UnixClient, +} + +impl ChgClient { + /// Connects to a command server listening at the specified socket path. + pub async fn connect(path: impl AsRef<Path>) -> io::Result<Self> { + let client = UnixClient::connect(path).await?; + Ok(ChgClient { client }) + } + + /// Server capabilities, encoding, etc. + pub fn server_spec(&self) -> &ServerSpec { + self.client.server_spec() + } + /// Attaches the client file descriptors to the server. - fn attach_io<I, O, E>(self, stdin: I, stdout: O, stderr: E) -> AttachIo<C, I, O, E> - where - I: AsRawFd, - O: AsRawFd, - E: AsRawFd; + pub async fn attach_io( + &mut self, + stdin: &impl AsRawFd, + stdout: &impl AsRawFd, + stderr: &impl AsRawFd, + ) -> io::Result<()> { + attachio::attach_io(self.client.borrow_protocol_mut(), stdin, stdout, stderr).await + } /// Changes the working directory of the server. - fn set_current_dir(self, dir: impl AsRef<Path>) -> OneShotRequest<C>; + pub async fn set_current_dir(&mut self, dir: impl AsRef<Path>) -> io::Result<()> { + let dir_bytes = dir.as_ref().as_os_str().as_bytes().to_owned(); + self.client + .borrow_protocol_mut() + .send_command_with_args("chdir", dir_bytes) + .await + } /// Updates the environment variables of the server. - fn set_env_vars_os( - self, + pub async fn set_env_vars_os( + &mut self, vars: impl IntoIterator<Item = (impl AsRef<OsStr>, impl AsRef<OsStr>)>, - ) -> OneShotRequest<C>; + ) -> io::Result<()> { + self.client + .borrow_protocol_mut() + .send_command_with_args("setenv", message::pack_env_vars_os(vars)) + .await + } /// Changes the process title of the server. - fn set_process_name(self, name: impl AsRef<OsStr>) -> OneShotRequest<C>; + pub async fn set_process_name(&mut self, name: impl AsRef<OsStr>) -> io::Result<()> { + let name_bytes = name.as_ref().as_bytes().to_owned(); + self.client + .borrow_protocol_mut() + .send_command_with_args("setprocname", name_bytes) + .await + } /// Changes the umask of the server process. - fn set_umask(self, mask: u32) -> OneShotRequest<C>; + pub async fn set_umask(&mut self, mask: u32) -> io::Result<()> { + let mut mask_bytes = BytesMut::with_capacity(mem::size_of_val(&mask)); + mask_bytes.put_u32(mask); + self.client + .borrow_protocol_mut() + .send_command_with_args("setumask2", mask_bytes) + .await + } /// Runs the specified Mercurial command with cHg extension. - fn run_command_chg<H>( - self, - handler: H, + pub async fn run_command_chg( + &mut self, + handler: &mut impl SystemHandler, args: impl IntoIterator<Item = impl AsRef<OsStr>>, - ) -> ChgRunCommand<C, H> - where - H: SystemHandler; + ) -> io::Result<i32> { + runcommand::run_command( + self.client.borrow_protocol_mut(), + handler, + message::pack_args_os(args), + ) + .await + } /// Validates if the server can run Mercurial commands with the expected /// configuration. @@ -63,66 +107,15 @@ /// /// Client-side environment must be sent prior to this request, by /// `set_current_dir()` and `set_env_vars_os()`. - fn validate( - self, + pub async fn validate( + &mut self, args: impl IntoIterator<Item = impl AsRef<OsStr>>, - ) -> OneShotQuery<C, fn(Bytes) -> io::Result<Vec<Instruction>>>; -} - -impl<C> ChgClientExt<C> for Client<C> -where - C: Connection + AsRawFd, -{ - fn attach_io<I, O, E>(self, stdin: I, stdout: O, stderr: E) -> AttachIo<C, I, O, E> - where - I: AsRawFd, - O: AsRawFd, - E: AsRawFd, - { - AttachIo::with_client(self, stdin, stdout, Some(stderr)) - } - - fn set_current_dir(self, dir: impl AsRef<Path>) -> OneShotRequest<C> { - OneShotRequest::start_with_args(self, b"chdir", dir.as_ref().as_os_str().as_bytes()) - } - - fn set_env_vars_os( - self, - vars: impl IntoIterator<Item = (impl AsRef<OsStr>, impl AsRef<OsStr>)>, - ) -> OneShotRequest<C> { - OneShotRequest::start_with_args(self, b"setenv", message::pack_env_vars_os(vars)) - } - - fn set_process_name(self, name: impl AsRef<OsStr>) -> OneShotRequest<C> { - OneShotRequest::start_with_args(self, b"setprocname", name.as_ref().as_bytes()) - } - - fn set_umask(self, mask: u32) -> OneShotRequest<C> { - let mut args = BytesMut::with_capacity(mem::size_of_val(&mask)); - args.put_u32(mask); - OneShotRequest::start_with_args(self, b"setumask2", args) - } - - fn run_command_chg<H>( - self, - handler: H, - args: impl IntoIterator<Item = impl AsRef<OsStr>>, - ) -> ChgRunCommand<C, H> - where - H: SystemHandler, - { - ChgRunCommand::with_client(self, handler, message::pack_args_os(args)) - } - - fn validate( - self, - args: impl IntoIterator<Item = impl AsRef<OsStr>>, - ) -> OneShotQuery<C, fn(Bytes) -> io::Result<Vec<Instruction>>> { - OneShotQuery::start_with_args( - self, - b"validate", - message::pack_args_os(args), - message::parse_instructions, - ) + ) -> io::Result<Vec<Instruction>> { + let data = self + .client + .borrow_protocol_mut() + .query_with_args("validate", message::pack_args_os(args)) + .await?; + message::parse_instructions(data) } }
--- a/rust/chg/src/lib.rs Fri Apr 10 22:44:51 2020 +0900 +++ b/rust/chg/src/lib.rs Fri Apr 10 23:26:36 2020 +0900 @@ -4,12 +4,12 @@ // GNU General Public License version 2 or any later version. mod attachio; -//mod clientext; +mod clientext; //pub mod locator; pub mod message; pub mod procutil; mod runcommand; mod uihandler; -//pub use clientext::ChgClientExt; +pub use clientext::ChgClient; pub use uihandler::{ChgUiHandler, SystemHandler};