##// END OF EJS Templates
rhg: use `Command::exec` instead of `Command::status`...
rhg: use `Command::exec` instead of `Command::status` `rhg` is supposed to be a transparent executable, using a subprocess defeats that purpose. See inline comments for more details. This also introduces the `which` crate to check if the fallback executable actually exists to help debugging (plain `execve` doesn't give much information). The error code 253 is used to signify that the fallback is not found, but may mean in the future that it is otherwise invalid if we start being more specific. Differential Revision: https://phab.mercurial-scm.org/D12578

File last commit:

r46195:426294d0 default
r50041:2b1d4e0b stable
Show More
uihandler.rs
94 lines | 2.7 KiB | application/rls-services+xml | RustLexer
Yuya Nishihara
rust-chg: add callback to handle pager and shell command requests...
r40010 // 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.
Yuya Nishihara
rust-chg: reimplement uihandler by using async-trait and tokio-0.2...
r45234 use async_trait::async_trait;
Yuya Nishihara
rust-chg: add callback to handle pager and shell command requests...
r40010 use std::io;
use std::os::unix::io::AsRawFd;
use std::os::unix::process::ExitStatusExt;
Yuya Nishihara
rust-chg: upgrade to futures-0.3 based libraries...
r45231 use std::process::Stdio;
Yuya Nishihara
rust-chg: add callback to handle pager and shell command requests...
r40010 use tokio;
Yuya Nishihara
rust-chg: do not terminate tokio runtime until pager exits...
r45239 use tokio::process::{Child, ChildStdin, Command};
Yuya Nishihara
rust-chg: add callback to handle pager and shell command requests...
r40010
Yuya Nishihara
rust-chg: use "crate::" to import local modules...
r45180 use crate::message::CommandSpec;
use crate::procutil;
Yuya Nishihara
rust-chg: add callback to handle pager and shell command requests...
r40010
/// Callback to process shell command requests received from server.
Yuya Nishihara
rust-chg: reimplement uihandler by using async-trait and tokio-0.2...
r45234 #[async_trait]
pub trait SystemHandler {
Yuya Nishihara
rust-chg: add callback to handle pager and shell command requests...
r40010 type PagerStdin: AsRawFd;
/// Handles pager command request.
///
/// Returns the pipe to be attached to the server if the pager is spawned.
Martin von Zweigbergk
rust: move rustfmt.toml to repo root so it can be used by `hg fix`...
r46195 async fn spawn_pager(
&mut self,
spec: &CommandSpec,
) -> io::Result<Self::PagerStdin>;
Yuya Nishihara
rust-chg: add callback to handle pager and shell command requests...
r40010
/// Handles system command request.
///
/// Returns command exit code (positive) or signal number (negative).
Yuya Nishihara
rust-chg: reimplement uihandler by using async-trait and tokio-0.2...
r45234 async fn run_system(&mut self, spec: &CommandSpec) -> io::Result<i32>;
Yuya Nishihara
rust-chg: add callback to handle pager and shell command requests...
r40010 }
/// Default cHg implementation to process requests received from server.
Yuya Nishihara
rust-chg: do not terminate tokio runtime until pager exits...
r45239 pub struct ChgUiHandler {
pager: Option<Child>,
}
Yuya Nishihara
rust-chg: add callback to handle pager and shell command requests...
r40010
impl ChgUiHandler {
pub fn new() -> ChgUiHandler {
Yuya Nishihara
rust-chg: do not terminate tokio runtime until pager exits...
r45239 ChgUiHandler { pager: None }
}
/// Waits until the pager process exits.
pub async fn wait_pager(&mut self) -> io::Result<()> {
if let Some(p) = self.pager.take() {
p.await?;
}
Ok(())
Yuya Nishihara
rust-chg: add callback to handle pager and shell command requests...
r40010 }
}
Yuya Nishihara
rust-chg: reimplement uihandler by using async-trait and tokio-0.2...
r45234 #[async_trait]
Yuya Nishihara
rust-chg: add callback to handle pager and shell command requests...
r40010 impl SystemHandler for ChgUiHandler {
type PagerStdin = ChildStdin;
Martin von Zweigbergk
rust: move rustfmt.toml to repo root so it can be used by `hg fix`...
r46195 async fn spawn_pager(
&mut self,
spec: &CommandSpec,
) -> io::Result<Self::PagerStdin> {
let mut pager =
new_shell_command(&spec).stdin(Stdio::piped()).spawn()?;
Yuya Nishihara
rust-chg: upgrade to futures-0.3 based libraries...
r45231 let pin = pager.stdin.take().unwrap();
Yuya Nishihara
rust-chg: add callback to handle pager and shell command requests...
r40010 procutil::set_blocking_fd(pin.as_raw_fd())?;
Yuya Nishihara
rust-chg: remove SIGCHLD handler which won't work in oxidized chg...
r40155 // TODO: if pager exits, notify the server with SIGPIPE immediately.
// otherwise the server won't get SIGPIPE if it does not write
// anything. (issue5278)
// kill(peerpid, SIGPIPE);
Yuya Nishihara
rust-chg: do not terminate tokio runtime until pager exits...
r45239 self.pager = Some(pager);
Yuya Nishihara
rust-chg: reimplement uihandler by using async-trait and tokio-0.2...
r45234 Ok(pin)
Yuya Nishihara
rust-chg: add callback to handle pager and shell command requests...
r40010 }
Yuya Nishihara
rust-chg: reimplement uihandler by using async-trait and tokio-0.2...
r45234 async fn run_system(&mut self, spec: &CommandSpec) -> io::Result<i32> {
let status = new_shell_command(&spec).spawn()?.await?;
Yuya Nishihara
rust-chg: clean up excessive indents...
r45240 let code = status
.code()
.or_else(|| status.signal().map(|n| -n))
.expect("either exit code or signal should be set");
Ok(code)
Yuya Nishihara
rust-chg: add callback to handle pager and shell command requests...
r40010 }
}
fn new_shell_command(spec: &CommandSpec) -> Command {
let mut builder = Command::new("/bin/sh");
builder
.arg("-c")
.arg(&spec.command)
.current_dir(&spec.current_dir)
.env_clear()
.envs(spec.envs.iter().cloned());
builder
Gregory Szorc
rust: run rustfmt...
r44270 }