##// END OF EJS Templates
rust: run rustfmt...
Gregory Szorc -
r44270:ce088b38 default
parent child Browse files
Show More
@@ -8,9 +8,9 b''
8 use futures::{Async, Future, Poll};
8 use futures::{Async, Future, Poll};
9 use std::io;
9 use std::io;
10 use std::os::unix::io::AsRawFd;
10 use std::os::unix::io::AsRawFd;
11 use tokio_hglib::{Client, Connection};
12 use tokio_hglib::codec::ChannelMessage;
11 use tokio_hglib::codec::ChannelMessage;
13 use tokio_hglib::protocol::MessageLoop;
12 use tokio_hglib::protocol::MessageLoop;
13 use tokio_hglib::{Client, Connection};
14
14
15 use super::message;
15 use super::message;
16 use super::procutil;
16 use super::procutil;
@@ -28,7 +28,8 b' use super::procutil;'
28 /// dispose of the client-side handle once attached.
28 /// dispose of the client-side handle once attached.
29 #[must_use = "futures do nothing unless polled"]
29 #[must_use = "futures do nothing unless polled"]
30 pub struct AttachIo<C, I, O, E>
30 pub struct AttachIo<C, I, O, E>
31 where C: Connection,
31 where
32 C: Connection,
32 {
33 {
33 msg_loop: MessageLoop<C>,
34 msg_loop: MessageLoop<C>,
34 stdin: I,
35 stdin: I,
@@ -37,23 +38,34 b' pub struct AttachIo<C, I, O, E>'
37 }
38 }
38
39
39 impl<C, I, O, E> AttachIo<C, I, O, E>
40 impl<C, I, O, E> AttachIo<C, I, O, E>
40 where C: Connection + AsRawFd,
41 where
41 I: AsRawFd,
42 C: Connection + AsRawFd,
42 O: AsRawFd,
43 I: AsRawFd,
43 E: AsRawFd,
44 O: AsRawFd,
45 E: AsRawFd,
44 {
46 {
45 pub fn with_client(client: Client<C>, stdin: I, stdout: O, stderr: Option<E>)
47 pub fn with_client(
46 -> AttachIo<C, I, O, E> {
48 client: Client<C>,
49 stdin: I,
50 stdout: O,
51 stderr: Option<E>,
52 ) -> AttachIo<C, I, O, E> {
47 let msg_loop = MessageLoop::start(client, b"attachio");
53 let msg_loop = MessageLoop::start(client, b"attachio");
48 AttachIo { msg_loop, stdin, stdout, stderr }
54 AttachIo {
55 msg_loop,
56 stdin,
57 stdout,
58 stderr,
59 }
49 }
60 }
50 }
61 }
51
62
52 impl<C, I, O, E> Future for AttachIo<C, I, O, E>
63 impl<C, I, O, E> Future for AttachIo<C, I, O, E>
53 where C: Connection + AsRawFd,
64 where
54 I: AsRawFd,
65 C: Connection + AsRawFd,
55 O: AsRawFd,
66 I: AsRawFd,
56 E: AsRawFd,
67 O: AsRawFd,
68 E: AsRawFd,
57 {
69 {
58 type Item = Client<C>;
70 type Item = Client<C>;
59 type Error = io::Error;
71 type Error = io::Error;
@@ -67,8 +79,10 b' impl<C, I, O, E> Future for AttachIo<C, '
67 if fd_cnt == 3 {
79 if fd_cnt == 3 {
68 return Ok(Async::Ready(client));
80 return Ok(Async::Ready(client));
69 } else {
81 } else {
70 return Err(io::Error::new(io::ErrorKind::InvalidData,
82 return Err(io::Error::new(
71 "unexpected attachio result"));
83 io::ErrorKind::InvalidData,
84 "unexpected attachio result",
85 ));
72 }
86 }
73 }
87 }
74 ChannelMessage::Data(..) => {
88 ChannelMessage::Data(..) => {
@@ -86,10 +100,13 b' impl<C, I, O, E> Future for AttachIo<C, '
86 procutil::send_raw_fds(sock_fd, &[ifd, ofd, efd])?;
100 procutil::send_raw_fds(sock_fd, &[ifd, ofd, efd])?;
87 self.msg_loop = MessageLoop::resume(client);
101 self.msg_loop = MessageLoop::resume(client);
88 }
102 }
89 ChannelMessage::InputRequest(..) | ChannelMessage::LineRequest(..) |
103 ChannelMessage::InputRequest(..)
90 ChannelMessage::SystemRequest(..) => {
104 | ChannelMessage::LineRequest(..)
91 return Err(io::Error::new(io::ErrorKind::InvalidData,
105 | ChannelMessage::SystemRequest(..) => {
92 "unsupported request while attaching io"));
106 return Err(io::Error::new(
107 io::ErrorKind::InvalidData,
108 "unsupported request while attaching io",
109 ));
93 }
110 }
94 }
111 }
95 }
112 }
@@ -9,8 +9,8 b' use std::ffi::OsStr;'
9 use std::os::unix::ffi::OsStrExt;
9 use std::os::unix::ffi::OsStrExt;
10 use std::os::unix::io::AsRawFd;
10 use std::os::unix::io::AsRawFd;
11 use std::path::Path;
11 use std::path::Path;
12 use tokio_hglib::protocol::OneShotRequest;
12 use tokio_hglib::{Client, Connection};
13 use tokio_hglib::{Client, Connection};
13 use tokio_hglib::protocol::OneShotRequest;
14
14
15 use super::attachio::AttachIo;
15 use super::attachio::AttachIo;
16 use super::message;
16 use super::message;
@@ -18,46 +18,54 b' use super::runcommand::ChgRunCommand;'
18 use super::uihandler::SystemHandler;
18 use super::uihandler::SystemHandler;
19
19
20 pub trait ChgClientExt<C>
20 pub trait ChgClientExt<C>
21 where C: Connection + AsRawFd,
21 where
22 C: Connection + AsRawFd,
22 {
23 {
23 /// Attaches the client file descriptors to the server.
24 /// Attaches the client file descriptors to the server.
24 fn attach_io<I, O, E>(self, stdin: I, stdout: O, stderr: E) -> AttachIo<C, I, O, E>
25 fn attach_io<I, O, E>(self, stdin: I, stdout: O, stderr: E) -> AttachIo<C, I, O, E>
25 where I: AsRawFd,
26 where
26 O: AsRawFd,
27 I: AsRawFd,
27 E: AsRawFd;
28 O: AsRawFd,
29 E: AsRawFd;
28
30
29 /// Changes the working directory of the server.
31 /// Changes the working directory of the server.
30 fn set_current_dir<P>(self, dir: P) -> OneShotRequest<C>
32 fn set_current_dir<P>(self, dir: P) -> OneShotRequest<C>
31 where P: AsRef<Path>;
33 where
34 P: AsRef<Path>;
32
35
33 /// Runs the specified Mercurial command with cHg extension.
36 /// Runs the specified Mercurial command with cHg extension.
34 fn run_command_chg<I, P, H>(self, handler: H, args: I) -> ChgRunCommand<C, H>
37 fn run_command_chg<I, P, H>(self, handler: H, args: I) -> ChgRunCommand<C, H>
35 where I: IntoIterator<Item = P>,
38 where
36 P: AsRef<OsStr>,
39 I: IntoIterator<Item = P>,
37 H: SystemHandler;
40 P: AsRef<OsStr>,
41 H: SystemHandler;
38 }
42 }
39
43
40 impl<C> ChgClientExt<C> for Client<C>
44 impl<C> ChgClientExt<C> for Client<C>
41 where C: Connection + AsRawFd,
45 where
46 C: Connection + AsRawFd,
42 {
47 {
43 fn attach_io<I, O, E>(self, stdin: I, stdout: O, stderr: E) -> AttachIo<C, I, O, E>
48 fn attach_io<I, O, E>(self, stdin: I, stdout: O, stderr: E) -> AttachIo<C, I, O, E>
44 where I: AsRawFd,
49 where
45 O: AsRawFd,
50 I: AsRawFd,
46 E: AsRawFd,
51 O: AsRawFd,
52 E: AsRawFd,
47 {
53 {
48 AttachIo::with_client(self, stdin, stdout, Some(stderr))
54 AttachIo::with_client(self, stdin, stdout, Some(stderr))
49 }
55 }
50
56
51 fn set_current_dir<P>(self, dir: P) -> OneShotRequest<C>
57 fn set_current_dir<P>(self, dir: P) -> OneShotRequest<C>
52 where P: AsRef<Path>,
58 where
59 P: AsRef<Path>,
53 {
60 {
54 OneShotRequest::start_with_args(self, b"chdir", dir.as_ref().as_os_str().as_bytes())
61 OneShotRequest::start_with_args(self, b"chdir", dir.as_ref().as_os_str().as_bytes())
55 }
62 }
56
63
57 fn run_command_chg<I, P, H>(self, handler: H, args: I) -> ChgRunCommand<C, H>
64 fn run_command_chg<I, P, H>(self, handler: H, args: I) -> ChgRunCommand<C, H>
58 where I: IntoIterator<Item = P>,
65 where
59 P: AsRef<OsStr>,
66 I: IntoIterator<Item = P>,
60 H: SystemHandler,
67 P: AsRef<OsStr>,
68 H: SystemHandler,
61 {
69 {
62 ChgRunCommand::with_client(self, handler, message::pack_args_os(args))
70 ChgRunCommand::with_client(self, handler, message::pack_args_os(args))
63 }
71 }
@@ -91,11 +91,16 b' pub fn default_server_socket_dir() -> Pa'
91 /// Determines the default hg command.
91 /// Determines the default hg command.
92 pub fn default_hg_command() -> OsString {
92 pub fn default_hg_command() -> OsString {
93 // TODO: maybe allow embedding the path at compile time (or load from hgrc)
93 // TODO: maybe allow embedding the path at compile time (or load from hgrc)
94 env::var_os("CHGHG").or(env::var_os("HG")).unwrap_or(OsStr::new("hg").to_owned())
94 env::var_os("CHGHG")
95 .or(env::var_os("HG"))
96 .unwrap_or(OsStr::new("hg").to_owned())
95 }
97 }
96
98
97 fn default_timeout() -> Duration {
99 fn default_timeout() -> Duration {
98 let secs = env::var("CHGTIMEOUT").ok().and_then(|s| s.parse().ok()).unwrap_or(60);
100 let secs = env::var("CHGTIMEOUT")
101 .ok()
102 .and_then(|s| s.parse().ok())
103 .unwrap_or(60);
99 Duration::from_secs(secs)
104 Duration::from_secs(secs)
100 }
105 }
101
106
@@ -103,19 +108,24 b' fn default_timeout() -> Duration {'
103 ///
108 ///
104 /// If the directory already exists, tests its permission.
109 /// If the directory already exists, tests its permission.
105 fn create_secure_dir<P>(path: P) -> io::Result<()>
110 fn create_secure_dir<P>(path: P) -> io::Result<()>
106 where P: AsRef<Path>,
111 where
112 P: AsRef<Path>,
107 {
113 {
108 DirBuilder::new().mode(0o700).create(path.as_ref()).or_else(|err| {
114 DirBuilder::new()
109 if err.kind() == io::ErrorKind::AlreadyExists {
115 .mode(0o700)
110 check_secure_dir(path).map(|_| ())
116 .create(path.as_ref())
111 } else {
117 .or_else(|err| {
112 Err(err)
118 if err.kind() == io::ErrorKind::AlreadyExists {
113 }
119 check_secure_dir(path).map(|_| ())
114 })
120 } else {
121 Err(err)
122 }
123 })
115 }
124 }
116
125
117 fn check_secure_dir<P>(path: P) -> io::Result<P>
126 fn check_secure_dir<P>(path: P) -> io::Result<P>
118 where P: AsRef<Path>,
127 where
128 P: AsRef<Path>,
119 {
129 {
120 let a = fs::symlink_metadata(path.as_ref())?;
130 let a = fs::symlink_metadata(path.as_ref())?;
121 if a.is_dir() && a.uid() == procutil::get_effective_uid() && (a.mode() & 0o777) == 0o700 {
131 if a.is_dir() && a.uid() == procutil::get_effective_uid() && (a.mode() & 0o777) == 0o700 {
@@ -9,9 +9,9 b' extern crate log;'
9 extern crate tokio;
9 extern crate tokio;
10 extern crate tokio_hglib;
10 extern crate tokio_hglib;
11
11
12 use chg::{ChgClientExt, ChgUiHandler};
13 use chg::locator;
12 use chg::locator;
14 use chg::procutil;
13 use chg::procutil;
14 use chg::{ChgClientExt, ChgUiHandler};
15 use futures::sync::oneshot;
15 use futures::sync::oneshot;
16 use std::env;
16 use std::env;
17 use std::io;
17 use std::io;
@@ -42,13 +42,19 b' impl log::Log for DebugLogger {'
42 // just make the output looks similar to chg of C
42 // just make the output looks similar to chg of C
43 let l = format!("{}", record.level()).to_lowercase();
43 let l = format!("{}", record.level()).to_lowercase();
44 let t = self.start.elapsed();
44 let t = self.start.elapsed();
45 writeln!(io::stderr(), "chg: {}: {}.{:06} {}",
45 writeln!(
46 l, t.as_secs(), t.subsec_micros(), record.args()).unwrap_or(());
46 io::stderr(),
47 "chg: {}: {}.{:06} {}",
48 l,
49 t.as_secs(),
50 t.subsec_micros(),
51 record.args()
52 )
53 .unwrap_or(());
47 }
54 }
48 }
55 }
49
56
50 fn flush(&self) {
57 fn flush(&self) {}
51 }
52 }
58 }
53
59
54 fn main() {
60 fn main() {
@@ -71,28 +77,24 b' fn run() -> io::Result<i32> {'
71 let handler = ChgUiHandler::new();
77 let handler = ChgUiHandler::new();
72 let (result_tx, result_rx) = oneshot::channel();
78 let (result_tx, result_rx) = oneshot::channel();
73 let fut = UnixClient::connect(sock_path)
79 let fut = UnixClient::connect(sock_path)
74 .and_then(|client| {
80 .and_then(|client| client.set_current_dir(current_dir))
75 client.set_current_dir(current_dir)
81 .and_then(|client| client.attach_io(io::stdin(), io::stdout(), io::stderr()))
76 })
77 .and_then(|client| {
78 client.attach_io(io::stdin(), io::stdout(), io::stderr())
79 })
80 .and_then(|client| {
82 .and_then(|client| {
81 let pid = client.server_spec().process_id.unwrap();
83 let pid = client.server_spec().process_id.unwrap();
82 let pgid = client.server_spec().process_group_id;
84 let pgid = client.server_spec().process_group_id;
83 procutil::setup_signal_handler_once(pid, pgid)?;
85 procutil::setup_signal_handler_once(pid, pgid)?;
84 Ok(client)
86 Ok(client)
85 })
87 })
86 .and_then(|client| {
88 .and_then(|client| client.run_command_chg(handler, env::args_os().skip(1)))
87 client.run_command_chg(handler, env::args_os().skip(1))
88 })
89 .map(|(_client, _handler, code)| {
89 .map(|(_client, _handler, code)| {
90 procutil::restore_signal_handler_once()?;
90 procutil::restore_signal_handler_once()?;
91 Ok(code)
91 Ok(code)
92 })
92 })
93 .or_else(|err| Ok(Err(err))) // pass back error to caller
93 .or_else(|err| Ok(Err(err))) // pass back error to caller
94 .map(|res| result_tx.send(res).unwrap());
94 .map(|res| result_tx.send(res).unwrap());
95 tokio::run(fut);
95 tokio::run(fut);
96 result_rx.wait().unwrap_or(Err(io::Error::new(io::ErrorKind::Other,
96 result_rx.wait().unwrap_or(Err(io::Error::new(
97 "no exit code set")))
97 io::ErrorKind::Other,
98 "no exit code set",
99 )))
98 }
100 }
@@ -11,7 +11,7 b' use std::ffi::{OsStr, OsString};'
11 use std::io;
11 use std::io;
12 use std::os::unix::ffi::OsStrExt;
12 use std::os::unix::ffi::OsStrExt;
13
13
14 pub use tokio_hglib::message::*; // re-exports
14 pub use tokio_hglib::message::*; // re-exports
15
15
16 /// Shell command type requested by the server.
16 /// Shell command type requested by the server.
17 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
17 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
@@ -42,7 +42,10 b' pub fn parse_command_spec(data: Bytes) -'
42 let mut s = l.splitn(2, |&c| c == b'=');
42 let mut s = l.splitn(2, |&c| c == b'=');
43 let k = s.next().unwrap();
43 let k = s.next().unwrap();
44 let v = s.next().ok_or(new_parse_error("malformed env"))?;
44 let v = s.next().ok_or(new_parse_error("malformed env"))?;
45 envs.push((OsStr::from_bytes(k).to_owned(), OsStr::from_bytes(v).to_owned()));
45 envs.push((
46 OsStr::from_bytes(k).to_owned(),
47 OsStr::from_bytes(v).to_owned(),
48 ));
46 }
49 }
47
50
48 let spec = CommandSpec {
51 let spec = CommandSpec {
@@ -57,41 +60,54 b' fn parse_command_type(value: &[u8]) -> i'
57 match value {
60 match value {
58 b"pager" => Ok(CommandType::Pager),
61 b"pager" => Ok(CommandType::Pager),
59 b"system" => Ok(CommandType::System),
62 b"system" => Ok(CommandType::System),
60 _ => Err(new_parse_error(format!("unknown command type: {}", decode_latin1(value)))),
63 _ => Err(new_parse_error(format!(
64 "unknown command type: {}",
65 decode_latin1(value)
66 ))),
61 }
67 }
62 }
68 }
63
69
64 fn decode_latin1<S>(s: S) -> String
70 fn decode_latin1<S>(s: S) -> String
65 where S: AsRef<[u8]>,
71 where
72 S: AsRef<[u8]>,
66 {
73 {
67 s.as_ref().iter().map(|&c| c as char).collect()
74 s.as_ref().iter().map(|&c| c as char).collect()
68 }
75 }
69
76
70 fn new_parse_error<E>(error: E) -> io::Error
77 fn new_parse_error<E>(error: E) -> io::Error
71 where E: Into<Box<error::Error + Send + Sync>>,
78 where
79 E: Into<Box<error::Error + Send + Sync>>,
72 {
80 {
73 io::Error::new(io::ErrorKind::InvalidData, error)
81 io::Error::new(io::ErrorKind::InvalidData, error)
74 }
82 }
75
83
76 #[cfg(test)]
84 #[cfg(test)]
77 mod tests {
85 mod tests {
86 use super::*;
78 use std::os::unix::ffi::OsStringExt;
87 use std::os::unix::ffi::OsStringExt;
79 use super::*;
80
88
81 #[test]
89 #[test]
82 fn parse_command_spec_good() {
90 fn parse_command_spec_good() {
83 let src = [b"pager".as_ref(),
91 let src = [
84 b"less -FRX".as_ref(),
92 b"pager".as_ref(),
85 b"/tmp".as_ref(),
93 b"less -FRX".as_ref(),
86 b"LANG=C".as_ref(),
94 b"/tmp".as_ref(),
87 b"HGPLAIN=".as_ref()].join(&0);
95 b"LANG=C".as_ref(),
96 b"HGPLAIN=".as_ref(),
97 ]
98 .join(&0);
88 let spec = CommandSpec {
99 let spec = CommandSpec {
89 command: os_string_from(b"less -FRX"),
100 command: os_string_from(b"less -FRX"),
90 current_dir: os_string_from(b"/tmp"),
101 current_dir: os_string_from(b"/tmp"),
91 envs: vec![(os_string_from(b"LANG"), os_string_from(b"C")),
102 envs: vec![
92 (os_string_from(b"HGPLAIN"), os_string_from(b""))],
103 (os_string_from(b"LANG"), os_string_from(b"C")),
104 (os_string_from(b"HGPLAIN"), os_string_from(b"")),
105 ],
93 };
106 };
94 assert_eq!(parse_command_spec(Bytes::from(src)).unwrap(), (CommandType::Pager, spec));
107 assert_eq!(
108 parse_command_spec(Bytes::from(src)).unwrap(),
109 (CommandType::Pager, spec)
110 );
95 }
111 }
96
112
97 #[test]
113 #[test]
@@ -33,7 +33,7 b' pub fn set_blocking_fd(fd: RawFd) -> io:'
33 }
33 }
34 let r = unsafe { libc::fcntl(fd, libc::F_SETFL, flags & !libc::O_NONBLOCK) };
34 let r = unsafe { libc::fcntl(fd, libc::F_SETFL, flags & !libc::O_NONBLOCK) };
35 if r < 0 {
35 if r < 0 {
36 return Err(io::Error::last_os_error())
36 return Err(io::Error::last_os_error());
37 }
37 }
38 Ok(())
38 Ok(())
39 }
39 }
@@ -11,9 +11,9 b' use futures::{Async, Future, Poll};'
11 use std::io;
11 use std::io;
12 use std::mem;
12 use std::mem;
13 use std::os::unix::io::AsRawFd;
13 use std::os::unix::io::AsRawFd;
14 use tokio_hglib::{Client, Connection};
15 use tokio_hglib::codec::ChannelMessage;
14 use tokio_hglib::codec::ChannelMessage;
16 use tokio_hglib::protocol::MessageLoop;
15 use tokio_hglib::protocol::MessageLoop;
16 use tokio_hglib::{Client, Connection};
17
17
18 use super::attachio::AttachIo;
18 use super::attachio::AttachIo;
19 use super::message::{self, CommandType};
19 use super::message::{self, CommandType};
@@ -26,8 +26,9 b' enum AsyncS<R, S> {'
26 }
26 }
27
27
28 enum CommandState<C, H>
28 enum CommandState<C, H>
29 where C: Connection,
29 where
30 H: SystemHandler,
30 C: Connection,
31 H: SystemHandler,
31 {
32 {
32 Running(MessageLoop<C>, H),
33 Running(MessageLoop<C>, H),
33 SpawningPager(Client<C>, <H::SpawnPagerResult as IntoFuture>::Future),
34 SpawningPager(Client<C>, <H::SpawnPagerResult as IntoFuture>::Future),
@@ -41,18 +42,19 b' type CommandPoll<C, H> = io::Result<(Asy'
41 /// Future resolves to `(exit_code, client)`.
42 /// Future resolves to `(exit_code, client)`.
42 #[must_use = "futures do nothing unless polled"]
43 #[must_use = "futures do nothing unless polled"]
43 pub struct ChgRunCommand<C, H>
44 pub struct ChgRunCommand<C, H>
44 where C: Connection,
45 where
45 H: SystemHandler,
46 C: Connection,
47 H: SystemHandler,
46 {
48 {
47 state: CommandState<C, H>,
49 state: CommandState<C, H>,
48 }
50 }
49
51
50 impl<C, H> ChgRunCommand<C, H>
52 impl<C, H> ChgRunCommand<C, H>
51 where C: Connection + AsRawFd,
53 where
52 H: SystemHandler,
54 C: Connection + AsRawFd,
55 H: SystemHandler,
53 {
56 {
54 pub fn with_client(client: Client<C>, handler: H, packed_args: Bytes)
57 pub fn with_client(client: Client<C>, handler: H, packed_args: Bytes) -> ChgRunCommand<C, H> {
55 -> ChgRunCommand<C, H> {
56 let msg_loop = MessageLoop::start_with_args(client, b"runcommand", packed_args);
58 let msg_loop = MessageLoop::start_with_args(client, b"runcommand", packed_args);
57 ChgRunCommand {
59 ChgRunCommand {
58 state: CommandState::Running(msg_loop, handler),
60 state: CommandState::Running(msg_loop, handler),
@@ -61,8 +63,9 b' impl<C, H> ChgRunCommand<C, H>'
61 }
63 }
62
64
63 impl<C, H> Future for ChgRunCommand<C, H>
65 impl<C, H> Future for ChgRunCommand<C, H>
64 where C: Connection + AsRawFd,
66 where
65 H: SystemHandler,
67 C: Connection + AsRawFd,
68 H: SystemHandler,
66 {
69 {
67 type Item = (Client<C>, H, i32);
70 type Item = (Client<C>, H, i32);
68 type Error = io::Error;
71 type Error = io::Error;
@@ -87,8 +90,9 b' impl<C, H> Future for ChgRunCommand<C, H'
87 }
90 }
88
91
89 impl<C, H> CommandState<C, H>
92 impl<C, H> CommandState<C, H>
90 where C: Connection + AsRawFd,
93 where
91 H: SystemHandler,
94 C: Connection + AsRawFd,
95 H: SystemHandler,
92 {
96 {
93 fn poll(self) -> CommandPoll<C, H> {
97 fn poll(self) -> CommandPoll<C, H> {
94 match self {
98 match self {
@@ -102,14 +106,16 b' impl<C, H> CommandState<C, H>'
102 CommandState::SpawningPager(client, mut fut) => {
106 CommandState::SpawningPager(client, mut fut) => {
103 if let Async::Ready((handler, pin)) = fut.poll()? {
107 if let Async::Ready((handler, pin)) = fut.poll()? {
104 let fut = AttachIo::with_client(client, io::stdin(), pin, None);
108 let fut = AttachIo::with_client(client, io::stdin(), pin, None);
105 Ok(AsyncS::PollAgain(CommandState::AttachingPager(fut, handler)))
109 Ok(AsyncS::PollAgain(CommandState::AttachingPager(
110 fut, handler,
111 )))
106 } else {
112 } else {
107 Ok(AsyncS::NotReady(CommandState::SpawningPager(client, fut)))
113 Ok(AsyncS::NotReady(CommandState::SpawningPager(client, fut)))
108 }
114 }
109 }
115 }
110 CommandState::AttachingPager(mut fut, handler) => {
116 CommandState::AttachingPager(mut fut, handler) => {
111 if let Async::Ready(client) = fut.poll()? {
117 if let Async::Ready(client) = fut.poll()? {
112 let msg_loop = MessageLoop::start(client, b""); // terminator
118 let msg_loop = MessageLoop::start(client, b""); // terminator
113 Ok(AsyncS::PollAgain(CommandState::Running(msg_loop, handler)))
119 Ok(AsyncS::PollAgain(CommandState::Running(msg_loop, handler)))
114 } else {
120 } else {
115 Ok(AsyncS::NotReady(CommandState::AttachingPager(fut, handler)))
121 Ok(AsyncS::NotReady(CommandState::AttachingPager(fut, handler)))
@@ -124,14 +130,15 b' impl<C, H> CommandState<C, H>'
124 Ok(AsyncS::NotReady(CommandState::WaitingSystem(client, fut)))
130 Ok(AsyncS::NotReady(CommandState::WaitingSystem(client, fut)))
125 }
131 }
126 }
132 }
127 CommandState::Finished => panic!("poll ChgRunCommand after it's done")
133 CommandState::Finished => panic!("poll ChgRunCommand after it's done"),
128 }
134 }
129 }
135 }
130 }
136 }
131
137
132 fn process_message<C, H>(client: Client<C>, handler: H, msg: ChannelMessage) -> CommandPoll<C, H>
138 fn process_message<C, H>(client: Client<C>, handler: H, msg: ChannelMessage) -> CommandPoll<C, H>
133 where C: Connection,
139 where
134 H: SystemHandler,
140 C: Connection,
141 H: SystemHandler,
135 {
142 {
136 match msg {
143 match msg {
137 ChannelMessage::Data(b'r', data) => {
144 ChannelMessage::Data(b'r', data) => {
@@ -143,9 +150,10 b' fn process_message<C, H>(client: Client<'
143 let msg_loop = MessageLoop::resume(client);
150 let msg_loop = MessageLoop::resume(client);
144 Ok(AsyncS::PollAgain(CommandState::Running(msg_loop, handler)))
151 Ok(AsyncS::PollAgain(CommandState::Running(msg_loop, handler)))
145 }
152 }
146 ChannelMessage::InputRequest(..) | ChannelMessage::LineRequest(..) => {
153 ChannelMessage::InputRequest(..) | ChannelMessage::LineRequest(..) => Err(io::Error::new(
147 Err(io::Error::new(io::ErrorKind::InvalidData, "unsupported request"))
154 io::ErrorKind::InvalidData,
148 }
155 "unsupported request",
156 )),
149 ChannelMessage::SystemRequest(data) => {
157 ChannelMessage::SystemRequest(data) => {
150 let (cmd_type, cmd_spec) = message::parse_command_spec(data)?;
158 let (cmd_type, cmd_spec) = message::parse_command_spec(data)?;
151 match cmd_type {
159 match cmd_type {
@@ -3,8 +3,8 b''
3 // This software may be used and distributed according to the terms of the
3 // This software may be used and distributed according to the terms of the
4 // GNU General Public License version 2 or any later version.
4 // GNU General Public License version 2 or any later version.
5
5
6 use futures::future::IntoFuture;
6 use futures::Future;
7 use futures::Future;
7 use futures::future::IntoFuture;
8 use std::io;
8 use std::io;
9 use std::os::unix::io::AsRawFd;
9 use std::os::unix::io::AsRawFd;
10 use std::os::unix::process::ExitStatusExt;
10 use std::os::unix::process::ExitStatusExt;
@@ -33,8 +33,7 b' pub trait SystemHandler: Sized {'
33 }
33 }
34
34
35 /// Default cHg implementation to process requests received from server.
35 /// Default cHg implementation to process requests received from server.
36 pub struct ChgUiHandler {
36 pub struct ChgUiHandler {}
37 }
38
37
39 impl ChgUiHandler {
38 impl ChgUiHandler {
40 pub fn new() -> ChgUiHandler {
39 pub fn new() -> ChgUiHandler {
@@ -57,7 +56,7 b' impl SystemHandler for ChgUiHandler {'
57 // otherwise the server won't get SIGPIPE if it does not write
56 // otherwise the server won't get SIGPIPE if it does not write
58 // anything. (issue5278)
57 // anything. (issue5278)
59 // kill(peerpid, SIGPIPE);
58 // kill(peerpid, SIGPIPE);
60 tokio::spawn(pager.map(|_| ()).map_err(|_| ())); // just ignore errors
59 tokio::spawn(pager.map(|_| ()).map_err(|_| ())); // just ignore errors
61 Ok((self, pin))
60 Ok((self, pin))
62 }
61 }
63
62
@@ -67,7 +66,9 b' impl SystemHandler for ChgUiHandler {'
67 .into_future()
66 .into_future()
68 .flatten()
67 .flatten()
69 .map(|status| {
68 .map(|status| {
70 let code = status.code().or_else(|| status.signal().map(|n| -n))
69 let code = status
70 .code()
71 .or_else(|| status.signal().map(|n| -n))
71 .expect("either exit code or signal should be set");
72 .expect("either exit code or signal should be set");
72 (self, code)
73 (self, code)
73 });
74 });
@@ -84,4 +85,4 b' fn new_shell_command(spec: &CommandSpec)'
84 .env_clear()
85 .env_clear()
85 .envs(spec.envs.iter().cloned());
86 .envs(spec.envs.iter().cloned());
86 builder
87 builder
87 }
88 }
@@ -170,8 +170,8 b" pub struct StatusResult<'a> {"
170 pub removed: Vec<&'a HgPath>,
170 pub removed: Vec<&'a HgPath>,
171 pub deleted: Vec<&'a HgPath>,
171 pub deleted: Vec<&'a HgPath>,
172 pub clean: Vec<&'a HgPath>,
172 pub clean: Vec<&'a HgPath>,
173 // TODO ignored
173 /* TODO ignored
174 // TODO unknown
174 * TODO unknown */
175 }
175 }
176
176
177 fn build_response(
177 fn build_response(
@@ -8,7 +8,6 b''
8 //! Bindings for the `hg::status` module provided by the
8 //! Bindings for the `hg::status` module provided by the
9 //! `hg-core` crate. From Python, this will be seen as
9 //! `hg-core` crate. From Python, this will be seen as
10 //! `rustext.dirstate.status`.
10 //! `rustext.dirstate.status`.
11 //!
12
11
13 use crate::dirstate::DirstateMap;
12 use crate::dirstate::DirstateMap;
14 use cpython::exc::ValueError;
13 use cpython::exc::ValueError;
@@ -10,7 +10,6 b''
10 //! `hg-core` crate. From Python, this will be seen as `rustext.filepatterns`
10 //! `hg-core` crate. From Python, this will be seen as `rustext.filepatterns`
11 //! and can be used as replacement for the the pure `filepatterns` Python
11 //! and can be used as replacement for the the pure `filepatterns` Python
12 //! module.
12 //! module.
13 //!
14 use crate::exceptions::{PatternError, PatternFileError};
13 use crate::exceptions::{PatternError, PatternFileError};
15 use cpython::{
14 use cpython::{
16 PyBytes, PyDict, PyModule, PyObject, PyResult, PyTuple, Python, ToPyObject,
15 PyBytes, PyDict, PyModule, PyObject, PyResult, PyTuple, Python, ToPyObject,
@@ -9,7 +9,6 b''
9 //! `hg-core` package.
9 //! `hg-core` package.
10 //!
10 //!
11 //! From Python, this will be seen as `mercurial.rustext.parsers`
11 //! From Python, this will be seen as `mercurial.rustext.parsers`
12 //!
13 use cpython::{
12 use cpython::{
14 exc, PyBytes, PyDict, PyErr, PyInt, PyModule, PyResult, PyTuple, Python,
13 exc, PyBytes, PyDict, PyErr, PyInt, PyModule, PyResult, PyTuple, Python,
15 PythonObject, ToPyObject,
14 PythonObject, ToPyObject,
@@ -18,9 +18,8 b' struct PythonConfig {'
18 fn get_python_config() -> PythonConfig {
18 fn get_python_config() -> PythonConfig {
19 // The python27-sys crate exports a Cargo variable defining the full
19 // The python27-sys crate exports a Cargo variable defining the full
20 // path to the interpreter being used.
20 // path to the interpreter being used.
21 let python = env::var("DEP_PYTHON27_PYTHON_INTERPRETER").expect(
21 let python = env::var("DEP_PYTHON27_PYTHON_INTERPRETER")
22 "Missing DEP_PYTHON27_PYTHON_INTERPRETER; bad python27-sys crate?",
22 .expect("Missing DEP_PYTHON27_PYTHON_INTERPRETER; bad python27-sys crate?");
23 );
24
23
25 if !Path::new(&python).exists() {
24 if !Path::new(&python).exists() {
26 panic!(
25 panic!(
@@ -33,8 +32,8 b' fn get_python_config() -> PythonConfig {'
33 let separator = "SEPARATOR STRING";
32 let separator = "SEPARATOR STRING";
34
33
35 let script = "import sysconfig; \
34 let script = "import sysconfig; \
36 c = sysconfig.get_config_vars(); \
35 c = sysconfig.get_config_vars(); \
37 print('SEPARATOR STRING'.join('%s=%s' % i for i in c.items()))";
36 print('SEPARATOR STRING'.join('%s=%s' % i for i in c.items()))";
38
37
39 let mut command = Command::new(&python);
38 let mut command = Command::new(&python);
40 command.arg("-c").arg(script);
39 command.arg("-c").arg(script);
@@ -5,18 +5,18 b''
5 // This software may be used and distributed according to the terms of the
5 // This software may be used and distributed according to the terms of the
6 // GNU General Public License version 2 or any later version.
6 // GNU General Public License version 2 or any later version.
7
7
8 extern crate cpython;
8 extern crate libc;
9 extern crate libc;
9 extern crate cpython;
10 extern crate python27_sys;
10 extern crate python27_sys;
11
11
12 use cpython::{NoArgs, ObjectProtocol, PyModule, PyResult, Python};
12 use cpython::{NoArgs, ObjectProtocol, PyModule, PyResult, Python};
13 use libc::{c_char, c_int};
13 use libc::{c_char, c_int};
14
14
15 use std::env;
15 use std::env;
16 use std::path::PathBuf;
17 use std::ffi::{CString, OsStr};
16 use std::ffi::{CString, OsStr};
18 #[cfg(target_family = "unix")]
17 #[cfg(target_family = "unix")]
19 use std::os::unix::ffi::{OsStrExt, OsStringExt};
18 use std::os::unix::ffi::{OsStrExt, OsStringExt};
19 use std::path::PathBuf;
20
20
21 #[derive(Debug)]
21 #[derive(Debug)]
22 struct Environment {
22 struct Environment {
General Comments 0
You need to be logged in to leave comments. Login now