Mercurial > hg
annotate rust/chg/src/attachio.rs @ 42783:c8d3af9c7e65
perf: handle NameError for `pycompat.foo` when pycompat wasn't imported
On old Mercurial versions, we won't have a pycompat variable defined,
and then `pycompat.foo` will raise a NameError.
Differential Revision: https://phab.mercurial-scm.org/D6743
author | Martin von Zweigbergk <martinvonz@google.com> |
---|---|
date | Mon, 19 Aug 2019 10:38:38 -0700 |
parents | 7a0ffdd4af78 |
children | ce088b38f92b |
rev | line source |
---|---|
39972
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
1 // Copyright 2018 Yuya Nishihara <yuya@tcha.org> |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
2 // |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
3 // This software may be used and distributed according to the terms of the |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
4 // GNU General Public License version 2 or any later version. |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
5 |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
6 //! Functions to send client-side fds over the command server channel. |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
7 |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
8 use futures::{Async, Future, Poll}; |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
9 use std::io; |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
10 use std::os::unix::io::AsRawFd; |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
11 use tokio_hglib::{Client, Connection}; |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
12 use tokio_hglib::codec::ChannelMessage; |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
13 use tokio_hglib::protocol::MessageLoop; |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
14 |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
15 use super::message; |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
16 use super::procutil; |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
17 |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
18 /// Future to send client-side fds over the command server channel. |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
19 /// |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
20 /// This works as follows: |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
21 /// 1. Client sends "attachio" request. |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
22 /// 2. Server sends back 1-byte input request. |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
23 /// 3. Client sends fds with 1-byte dummy payload in response. |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
24 /// 4. Server returns the number of the fds received. |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
25 /// |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
26 /// If the stderr is omitted, it will be redirected to the stdout. This |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
27 /// allows us to attach the pager stdin to both stdout and stderr, and |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
28 /// dispose of the client-side handle once attached. |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
29 #[must_use = "futures do nothing unless polled"] |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
30 pub struct AttachIo<C, I, O, E> |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
31 where C: Connection, |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
32 { |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
33 msg_loop: MessageLoop<C>, |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
34 stdin: I, |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
35 stdout: O, |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
36 stderr: Option<E>, |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
37 } |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
38 |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
39 impl<C, I, O, E> AttachIo<C, I, O, E> |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
40 where C: Connection + AsRawFd, |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
41 I: AsRawFd, |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
42 O: AsRawFd, |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
43 E: AsRawFd, |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
44 { |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
45 pub fn with_client(client: Client<C>, stdin: I, stdout: O, stderr: Option<E>) |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
46 -> AttachIo<C, I, O, E> { |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
47 let msg_loop = MessageLoop::start(client, b"attachio"); |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
48 AttachIo { msg_loop, stdin, stdout, stderr } |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
49 } |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
50 } |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
51 |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
52 impl<C, I, O, E> Future for AttachIo<C, I, O, E> |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
53 where C: Connection + AsRawFd, |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
54 I: AsRawFd, |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
55 O: AsRawFd, |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
56 E: AsRawFd, |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
57 { |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
58 type Item = Client<C>; |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
59 type Error = io::Error; |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
60 |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
61 fn poll(&mut self) -> Poll<Self::Item, Self::Error> { |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
62 loop { |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
63 let (client, msg) = try_ready!(self.msg_loop.poll()); |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
64 match msg { |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
65 ChannelMessage::Data(b'r', data) => { |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
66 let fd_cnt = message::parse_result_code(data)?; |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
67 if fd_cnt == 3 { |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
68 return Ok(Async::Ready(client)); |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
69 } else { |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
70 return Err(io::Error::new(io::ErrorKind::InvalidData, |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
71 "unexpected attachio result")); |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
72 } |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
73 } |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
74 ChannelMessage::Data(..) => { |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
75 // just ignore data sent to uninteresting (optional) channel |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
76 self.msg_loop = MessageLoop::resume(client); |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
77 } |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
78 ChannelMessage::InputRequest(1) => { |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
79 // this may fail with EWOULDBLOCK in theory, but the |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
80 // payload is quite small, and the send buffer should |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
81 // be empty so the operation will complete immediately |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
82 let sock_fd = client.as_raw_fd(); |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
83 let ifd = self.stdin.as_raw_fd(); |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
84 let ofd = self.stdout.as_raw_fd(); |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
85 let efd = self.stderr.as_ref().map_or(ofd, |f| f.as_raw_fd()); |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
86 procutil::send_raw_fds(sock_fd, &[ifd, ofd, efd])?; |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
87 self.msg_loop = MessageLoop::resume(client); |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
88 } |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
89 ChannelMessage::InputRequest(..) | ChannelMessage::LineRequest(..) | |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
90 ChannelMessage::SystemRequest(..) => { |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
91 return Err(io::Error::new(io::ErrorKind::InvalidData, |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
92 "unsupported request while attaching io")); |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
93 } |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
94 } |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
95 } |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
96 } |
7a0ffdd4af78
rust-chg: add future that handles "attachio" request
Yuya Nishihara <yuya@tcha.org>
parents:
diff
changeset
|
97 } |