rust/chg/src/uihandler.rs
author Matt Harbison <matt_harbison@yahoo.com>
Sun, 16 Dec 2018 15:47:08 -0500
changeset 40987 e1f759f1f691
parent 40120 e70b616a077b
child 43836 ce088b38f92b
permissions -rw-r--r--
py3: conditionalize the python version in test-install.t
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
39975
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     1
// Copyright 2018 Yuya Nishihara <yuya@tcha.org>
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     2
//
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     3
// This software may be used and distributed according to the terms of the
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     4
// GNU General Public License version 2 or any later version.
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     5
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     6
use futures::Future;
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     7
use futures::future::IntoFuture;
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     8
use std::io;
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     9
use std::os::unix::io::AsRawFd;
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    10
use std::os::unix::process::ExitStatusExt;
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    11
use std::process::{Command, Stdio};
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    12
use tokio;
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    13
use tokio_process::{ChildStdin, CommandExt};
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    14
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    15
use super::message::CommandSpec;
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    16
use super::procutil;
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    17
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    18
/// Callback to process shell command requests received from server.
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    19
pub trait SystemHandler: Sized {
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    20
    type PagerStdin: AsRawFd;
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    21
    type SpawnPagerResult: IntoFuture<Item = (Self, Self::PagerStdin), Error = io::Error>;
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    22
    type RunSystemResult: IntoFuture<Item = (Self, i32), Error = io::Error>;
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    23
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    24
    /// Handles pager command request.
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    25
    ///
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    26
    /// Returns the pipe to be attached to the server if the pager is spawned.
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    27
    fn spawn_pager(self, spec: CommandSpec) -> Self::SpawnPagerResult;
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    28
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    29
    /// Handles system command request.
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    30
    ///
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    31
    /// Returns command exit code (positive) or signal number (negative).
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    32
    fn run_system(self, spec: CommandSpec) -> Self::RunSystemResult;
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    33
}
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    34
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    35
/// Default cHg implementation to process requests received from server.
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    36
pub struct ChgUiHandler {
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    37
}
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    38
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    39
impl ChgUiHandler {
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    40
    pub fn new() -> ChgUiHandler {
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    41
        ChgUiHandler {}
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    42
    }
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    43
}
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    44
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    45
impl SystemHandler for ChgUiHandler {
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    46
    type PagerStdin = ChildStdin;
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    47
    type SpawnPagerResult = io::Result<(Self, Self::PagerStdin)>;
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    48
    type RunSystemResult = Box<dyn Future<Item = (Self, i32), Error = io::Error> + Send>;
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    49
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    50
    fn spawn_pager(self, spec: CommandSpec) -> Self::SpawnPagerResult {
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    51
        let mut pager = new_shell_command(&spec)
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    52
            .stdin(Stdio::piped())
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    53
            .spawn_async()?;
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    54
        let pin = pager.stdin().take().unwrap();
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    55
        procutil::set_blocking_fd(pin.as_raw_fd())?;
40120
e70b616a077b rust-chg: remove SIGCHLD handler which won't work in oxidized chg
Yuya Nishihara <yuya@tcha.org>
parents: 39975
diff changeset
    56
        // TODO: if pager exits, notify the server with SIGPIPE immediately.
e70b616a077b rust-chg: remove SIGCHLD handler which won't work in oxidized chg
Yuya Nishihara <yuya@tcha.org>
parents: 39975
diff changeset
    57
        // otherwise the server won't get SIGPIPE if it does not write
e70b616a077b rust-chg: remove SIGCHLD handler which won't work in oxidized chg
Yuya Nishihara <yuya@tcha.org>
parents: 39975
diff changeset
    58
        // anything. (issue5278)
e70b616a077b rust-chg: remove SIGCHLD handler which won't work in oxidized chg
Yuya Nishihara <yuya@tcha.org>
parents: 39975
diff changeset
    59
        // kill(peerpid, SIGPIPE);
39975
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    60
        tokio::spawn(pager.map(|_| ()).map_err(|_| ()));  // just ignore errors
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    61
        Ok((self, pin))
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    62
    }
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    63
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    64
    fn run_system(self, spec: CommandSpec) -> Self::RunSystemResult {
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    65
        let fut = new_shell_command(&spec)
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    66
            .spawn_async()
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    67
            .into_future()
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    68
            .flatten()
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    69
            .map(|status| {
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    70
                let code = status.code().or_else(|| status.signal().map(|n| -n))
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    71
                    .expect("either exit code or signal should be set");
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    72
                (self, code)
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    73
            });
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    74
        Box::new(fut)
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    75
    }
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    76
}
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    77
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    78
fn new_shell_command(spec: &CommandSpec) -> Command {
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    79
    let mut builder = Command::new("/bin/sh");
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    80
    builder
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    81
        .arg("-c")
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    82
        .arg(&spec.command)
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    83
        .current_dir(&spec.current_dir)
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    84
        .env_clear()
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    85
        .envs(spec.envs.iter().cloned());
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    86
    builder
a9c5fc436fd5 rust-chg: add callback to handle pager and shell command requests
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    87
 }