##// END OF EJS Templates
tests: check availability of pyflakes by trying to import pyflakes module...
tests: check availability of pyflakes by trying to import pyflakes module Since e397c6d74652, we use the pyflakes module instead of the pyflakes executable. As was pointed out during the review, the hghave check can be rewritten to try to import the pyflakes module instead of spawning a new subprocess.

File last commit:

r44270:ce088b38 default
r44987:aa0e1341 default
Show More
attachio.rs
114 lines | 3.7 KiB | application/rls-services+xml | RustLexer
Yuya Nishihara
rust-chg: add future that handles "attachio" request...
r40008 // Copyright 2018 Yuya Nishihara <yuya@tcha.org>
//
// This software may be used and distributed according to the terms of the
// GNU General Public License version 2 or any later version.
//! Functions to send client-side fds over the command server channel.
use futures::{Async, Future, Poll};
use std::io;
use std::os::unix::io::AsRawFd;
use tokio_hglib::codec::ChannelMessage;
use tokio_hglib::protocol::MessageLoop;
Gregory Szorc
rust: run rustfmt...
r44270 use tokio_hglib::{Client, Connection};
Yuya Nishihara
rust-chg: add future that handles "attachio" request...
r40008
use super::message;
use super::procutil;
/// Future to send client-side fds over the command server channel.
///
/// This works as follows:
/// 1. Client sends "attachio" request.
/// 2. Server sends back 1-byte input request.
/// 3. Client sends fds with 1-byte dummy payload in response.
/// 4. Server returns the number of the fds received.
///
/// If the stderr is omitted, it will be redirected to the stdout. This
/// allows us to attach the pager stdin to both stdout and stderr, and
/// dispose of the client-side handle once attached.
#[must_use = "futures do nothing unless polled"]
pub struct AttachIo<C, I, O, E>
Gregory Szorc
rust: run rustfmt...
r44270 where
C: Connection,
Yuya Nishihara
rust-chg: add future that handles "attachio" request...
r40008 {
msg_loop: MessageLoop<C>,
stdin: I,
stdout: O,
stderr: Option<E>,
}
impl<C, I, O, E> AttachIo<C, I, O, E>
Gregory Szorc
rust: run rustfmt...
r44270 where
C: Connection + AsRawFd,
I: AsRawFd,
O: AsRawFd,
E: AsRawFd,
Yuya Nishihara
rust-chg: add future that handles "attachio" request...
r40008 {
Gregory Szorc
rust: run rustfmt...
r44270 pub fn with_client(
client: Client<C>,
stdin: I,
stdout: O,
stderr: Option<E>,
) -> AttachIo<C, I, O, E> {
Yuya Nishihara
rust-chg: add future that handles "attachio" request...
r40008 let msg_loop = MessageLoop::start(client, b"attachio");
Gregory Szorc
rust: run rustfmt...
r44270 AttachIo {
msg_loop,
stdin,
stdout,
stderr,
}
Yuya Nishihara
rust-chg: add future that handles "attachio" request...
r40008 }
}
impl<C, I, O, E> Future for AttachIo<C, I, O, E>
Gregory Szorc
rust: run rustfmt...
r44270 where
C: Connection + AsRawFd,
I: AsRawFd,
O: AsRawFd,
E: AsRawFd,
Yuya Nishihara
rust-chg: add future that handles "attachio" request...
r40008 {
type Item = Client<C>;
type Error = io::Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
loop {
let (client, msg) = try_ready!(self.msg_loop.poll());
match msg {
ChannelMessage::Data(b'r', data) => {
let fd_cnt = message::parse_result_code(data)?;
if fd_cnt == 3 {
return Ok(Async::Ready(client));
} else {
Gregory Szorc
rust: run rustfmt...
r44270 return Err(io::Error::new(
io::ErrorKind::InvalidData,
"unexpected attachio result",
));
Yuya Nishihara
rust-chg: add future that handles "attachio" request...
r40008 }
}
ChannelMessage::Data(..) => {
// just ignore data sent to uninteresting (optional) channel
self.msg_loop = MessageLoop::resume(client);
}
ChannelMessage::InputRequest(1) => {
// this may fail with EWOULDBLOCK in theory, but the
// payload is quite small, and the send buffer should
// be empty so the operation will complete immediately
let sock_fd = client.as_raw_fd();
let ifd = self.stdin.as_raw_fd();
let ofd = self.stdout.as_raw_fd();
let efd = self.stderr.as_ref().map_or(ofd, |f| f.as_raw_fd());
procutil::send_raw_fds(sock_fd, &[ifd, ofd, efd])?;
self.msg_loop = MessageLoop::resume(client);
}
Gregory Szorc
rust: run rustfmt...
r44270 ChannelMessage::InputRequest(..)
| ChannelMessage::LineRequest(..)
| ChannelMessage::SystemRequest(..) => {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"unsupported request while attaching io",
));
Yuya Nishihara
rust-chg: add future that handles "attachio" request...
r40008 }
}
}
}
}