runcommand.rs
66 lines
| 2.4 KiB
| application/rls-services+xml
|
RustLexer
Yuya Nishihara
|
r40011 | // 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 run Mercurial command in cHg-aware command server. | ||||
use bytes::Bytes; | ||||
use std::io; | ||||
use std::os::unix::io::AsRawFd; | ||||
use tokio_hglib::codec::ChannelMessage; | ||||
Yuya Nishihara
|
r45235 | use tokio_hglib::{Connection, Protocol}; | ||
Yuya Nishihara
|
r40011 | |||
Yuya Nishihara
|
r45235 | use crate::attachio; | ||
Yuya Nishihara
|
r45180 | use crate::message::{self, CommandType}; | ||
use crate::uihandler::SystemHandler; | ||||
Yuya Nishihara
|
r40011 | |||
Yuya Nishihara
|
r45235 | /// Runs the given Mercurial command in cHg-aware command server, and | ||
/// fetches the result code. | ||||
/// | ||||
/// This is a subset of tokio-hglib's `run_command()` with the additional | ||||
/// SystemRequest support. | ||||
pub async fn run_command( | ||||
proto: &mut Protocol<impl Connection + AsRawFd>, | ||||
handler: &mut impl SystemHandler, | ||||
packed_args: impl Into<Bytes>, | ||||
) -> io::Result<i32> { | ||||
proto | ||||
.send_command_with_args("runcommand", packed_args) | ||||
.await?; | ||||
loop { | ||||
match proto.fetch_response().await? { | ||||
Yuya Nishihara
|
r45185 | ChannelMessage::Data(b'r', data) => { | ||
Yuya Nishihara
|
r45235 | return message::parse_result_code(data); | ||
Yuya Nishihara
|
r45185 | } | ||
ChannelMessage::Data(..) => { | ||||
// just ignores data sent to optional channel | ||||
} | ||||
Martin von Zweigbergk
|
r46195 | ChannelMessage::InputRequest(..) | ||
| ChannelMessage::LineRequest(..) => { | ||||
Yuya Nishihara
|
r45235 | return Err(io::Error::new( | ||
io::ErrorKind::InvalidData, | ||||
"unsupported request", | ||||
)); | ||||
} | ||||
Yuya Nishihara
|
r45185 | ChannelMessage::SystemRequest(data) => { | ||
let (cmd_type, cmd_spec) = message::parse_command_spec(data)?; | ||||
match cmd_type { | ||||
CommandType::Pager => { | ||||
Yuya Nishihara
|
r45235 | // server spins new command loop while pager request is | ||
// in progress, which can be terminated by "" command. | ||||
let pin = handler.spawn_pager(&cmd_spec).await?; | ||||
Martin von Zweigbergk
|
r46195 | attachio::attach_io(proto, &io::stdin(), &pin, &pin) | ||
.await?; | ||||
Yuya Nishihara
|
r45235 | proto.send_command("").await?; // terminator | ||
Yuya Nishihara
|
r45185 | } | ||
CommandType::System => { | ||||
Yuya Nishihara
|
r45235 | let code = handler.run_system(&cmd_spec).await?; | ||
let data = message::pack_result_code(code); | ||||
proto.send_data(data).await?; | ||||
Yuya Nishihara
|
r45185 | } | ||
Yuya Nishihara
|
r40011 | } | ||
} | ||||
} | ||||
} | ||||
} | ||||