##// END OF EJS Templates
rust-chg: reimplement ChgClientExt as ChgClient wrapper...
Yuya Nishihara -
r45236:d6f70692 default
parent child Browse files
Show More
@@ -1,128 +1,121
1 1 // Copyright 2018 Yuya Nishihara <yuya@tcha.org>
2 2 //
3 3 // This software may be used and distributed according to the terms of the
4 4 // GNU General Public License version 2 or any later version.
5 5
6 6 //! cHg extensions to command server client.
7 7
8 use bytes::{BufMut, Bytes, BytesMut};
8 use bytes::{BufMut, BytesMut};
9 9 use std::ffi::OsStr;
10 10 use std::io;
11 11 use std::mem;
12 12 use std::os::unix::ffi::OsStrExt;
13 13 use std::os::unix::io::AsRawFd;
14 14 use std::path::Path;
15 use tokio_hglib::protocol::{OneShotQuery, OneShotRequest};
16 use tokio_hglib::{Client, Connection};
15 use tokio_hglib::UnixClient;
17 16
18 use crate::attachio::AttachIo;
19 use crate::message::{self, Instruction};
20 use crate::runcommand::ChgRunCommand;
17 use crate::attachio;
18 use crate::message::{self, Instruction, ServerSpec};
19 use crate::runcommand;
21 20 use crate::uihandler::SystemHandler;
22 21
23 pub trait ChgClientExt<C>
24 where
25 C: Connection + AsRawFd,
26 {
22 /// Command-server client that also supports cHg extensions.
23 pub struct ChgClient {
24 client: UnixClient,
25 }
26
27 impl ChgClient {
28 /// Connects to a command server listening at the specified socket path.
29 pub async fn connect(path: impl AsRef<Path>) -> io::Result<Self> {
30 let client = UnixClient::connect(path).await?;
31 Ok(ChgClient { client })
32 }
33
34 /// Server capabilities, encoding, etc.
35 pub fn server_spec(&self) -> &ServerSpec {
36 self.client.server_spec()
37 }
38
27 39 /// Attaches the client file descriptors to the server.
28 fn attach_io<I, O, E>(self, stdin: I, stdout: O, stderr: E) -> AttachIo<C, I, O, E>
29 where
30 I: AsRawFd,
31 O: AsRawFd,
32 E: AsRawFd;
40 pub async fn attach_io(
41 &mut self,
42 stdin: &impl AsRawFd,
43 stdout: &impl AsRawFd,
44 stderr: &impl AsRawFd,
45 ) -> io::Result<()> {
46 attachio::attach_io(self.client.borrow_protocol_mut(), stdin, stdout, stderr).await
47 }
33 48
34 49 /// Changes the working directory of the server.
35 fn set_current_dir(self, dir: impl AsRef<Path>) -> OneShotRequest<C>;
50 pub async fn set_current_dir(&mut self, dir: impl AsRef<Path>) -> io::Result<()> {
51 let dir_bytes = dir.as_ref().as_os_str().as_bytes().to_owned();
52 self.client
53 .borrow_protocol_mut()
54 .send_command_with_args("chdir", dir_bytes)
55 .await
56 }
36 57
37 58 /// Updates the environment variables of the server.
38 fn set_env_vars_os(
39 self,
59 pub async fn set_env_vars_os(
60 &mut self,
40 61 vars: impl IntoIterator<Item = (impl AsRef<OsStr>, impl AsRef<OsStr>)>,
41 ) -> OneShotRequest<C>;
62 ) -> io::Result<()> {
63 self.client
64 .borrow_protocol_mut()
65 .send_command_with_args("setenv", message::pack_env_vars_os(vars))
66 .await
67 }
42 68
43 69 /// Changes the process title of the server.
44 fn set_process_name(self, name: impl AsRef<OsStr>) -> OneShotRequest<C>;
70 pub async fn set_process_name(&mut self, name: impl AsRef<OsStr>) -> io::Result<()> {
71 let name_bytes = name.as_ref().as_bytes().to_owned();
72 self.client
73 .borrow_protocol_mut()
74 .send_command_with_args("setprocname", name_bytes)
75 .await
76 }
45 77
46 78 /// Changes the umask of the server process.
47 fn set_umask(self, mask: u32) -> OneShotRequest<C>;
79 pub async fn set_umask(&mut self, mask: u32) -> io::Result<()> {
80 let mut mask_bytes = BytesMut::with_capacity(mem::size_of_val(&mask));
81 mask_bytes.put_u32(mask);
82 self.client
83 .borrow_protocol_mut()
84 .send_command_with_args("setumask2", mask_bytes)
85 .await
86 }
48 87
49 88 /// Runs the specified Mercurial command with cHg extension.
50 fn run_command_chg<H>(
51 self,
52 handler: H,
89 pub async fn run_command_chg(
90 &mut self,
91 handler: &mut impl SystemHandler,
53 92 args: impl IntoIterator<Item = impl AsRef<OsStr>>,
54 ) -> ChgRunCommand<C, H>
55 where
56 H: SystemHandler;
93 ) -> io::Result<i32> {
94 runcommand::run_command(
95 self.client.borrow_protocol_mut(),
96 handler,
97 message::pack_args_os(args),
98 )
99 .await
100 }
57 101
58 102 /// Validates if the server can run Mercurial commands with the expected
59 103 /// configuration.
60 104 ///
61 105 /// The `args` should contain early command arguments such as `--config`
62 106 /// and `-R`.
63 107 ///
64 108 /// Client-side environment must be sent prior to this request, by
65 109 /// `set_current_dir()` and `set_env_vars_os()`.
66 fn validate(
67 self,
110 pub async fn validate(
111 &mut self,
68 112 args: impl IntoIterator<Item = impl AsRef<OsStr>>,
69 ) -> OneShotQuery<C, fn(Bytes) -> io::Result<Vec<Instruction>>>;
70 }
71
72 impl<C> ChgClientExt<C> for Client<C>
73 where
74 C: Connection + AsRawFd,
75 {
76 fn attach_io<I, O, E>(self, stdin: I, stdout: O, stderr: E) -> AttachIo<C, I, O, E>
77 where
78 I: AsRawFd,
79 O: AsRawFd,
80 E: AsRawFd,
81 {
82 AttachIo::with_client(self, stdin, stdout, Some(stderr))
83 }
84
85 fn set_current_dir(self, dir: impl AsRef<Path>) -> OneShotRequest<C> {
86 OneShotRequest::start_with_args(self, b"chdir", dir.as_ref().as_os_str().as_bytes())
87 }
88
89 fn set_env_vars_os(
90 self,
91 vars: impl IntoIterator<Item = (impl AsRef<OsStr>, impl AsRef<OsStr>)>,
92 ) -> OneShotRequest<C> {
93 OneShotRequest::start_with_args(self, b"setenv", message::pack_env_vars_os(vars))
94 }
95
96 fn set_process_name(self, name: impl AsRef<OsStr>) -> OneShotRequest<C> {
97 OneShotRequest::start_with_args(self, b"setprocname", name.as_ref().as_bytes())
98 }
99
100 fn set_umask(self, mask: u32) -> OneShotRequest<C> {
101 let mut args = BytesMut::with_capacity(mem::size_of_val(&mask));
102 args.put_u32(mask);
103 OneShotRequest::start_with_args(self, b"setumask2", args)
104 }
105
106 fn run_command_chg<H>(
107 self,
108 handler: H,
109 args: impl IntoIterator<Item = impl AsRef<OsStr>>,
110 ) -> ChgRunCommand<C, H>
111 where
112 H: SystemHandler,
113 {
114 ChgRunCommand::with_client(self, handler, message::pack_args_os(args))
115 }
116
117 fn validate(
118 self,
119 args: impl IntoIterator<Item = impl AsRef<OsStr>>,
120 ) -> OneShotQuery<C, fn(Bytes) -> io::Result<Vec<Instruction>>> {
121 OneShotQuery::start_with_args(
122 self,
123 b"validate",
124 message::pack_args_os(args),
125 message::parse_instructions,
126 )
113 ) -> io::Result<Vec<Instruction>> {
114 let data = self
115 .client
116 .borrow_protocol_mut()
117 .query_with_args("validate", message::pack_args_os(args))
118 .await?;
119 message::parse_instructions(data)
127 120 }
128 121 }
@@ -1,15 +1,15
1 1 // Copyright 2018 Yuya Nishihara <yuya@tcha.org>
2 2 //
3 3 // This software may be used and distributed according to the terms of the
4 4 // GNU General Public License version 2 or any later version.
5 5
6 6 mod attachio;
7 //mod clientext;
7 mod clientext;
8 8 //pub mod locator;
9 9 pub mod message;
10 10 pub mod procutil;
11 11 mod runcommand;
12 12 mod uihandler;
13 13
14 //pub use clientext::ChgClientExt;
14 pub use clientext::ChgClient;
15 15 pub use uihandler::{ChgUiHandler, SystemHandler};
General Comments 0
You need to be logged in to leave comments. Login now