Show More
@@ -5,55 +5,99 b'' | |||
|
5 | 5 | |
|
6 | 6 | //! cHg extensions to command server client. |
|
7 | 7 | |
|
8 |
use bytes::{BufMut, |
|
|
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 |
|
|
19 | use crate::message::{self, Instruction}; | |
|
20 |
use crate::runcommand |
|
|
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 |
|
|
|
31 |
|
|
|
32 |
|
|
|
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>) -> |
|
|
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 |
) -> |
|
|
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>) -> |
|
|
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) -> |
|
|
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 |
|
|
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. |
@@ -63,66 +107,15 b' where' | |||
|
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 |
|
|
|
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 | } |
@@ -4,12 +4,12 b'' | |||
|
4 | 4 | // GNU General Public License version 2 or any later version. |
|
5 | 5 | |
|
6 | 6 | mod attachio; |
|
7 |
|
|
|
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 |
|
|
|
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