##// END OF EJS Templates
rust-chg: modernize entry function...
Yuya Nishihara -
r45238:9fc9526e default
parent child Browse files
Show More
@@ -1,25 +1,22 b''
1 1 [package]
2 2 name = "chg"
3 3 version = "0.1.0"
4 4 authors = ["Yuya Nishihara <yuya@tcha.org>"]
5 5 description = "Client for Mercurial command server with cHg extension"
6 6 license = "GPL-2.0+"
7 7 edition = "2018"
8 8
9 # TODO: enable auto discovery
10 autobins = false
11
12 9 [dependencies]
13 10 async-trait = "0.1"
14 11 bytes = "0.5"
15 12 futures = "0.3"
16 13 libc = "0.2"
17 14 log = { version = "0.4", features = ["std"] }
18 15 tokio-hglib = "0.3"
19 16
20 17 [dependencies.tokio]
21 18 version = "0.2"
22 19 features = ["rt-core", "io-util", "time", "process", "macros"]
23 20
24 21 [build-dependencies]
25 22 cc = "1.0"
@@ -1,97 +1,87 b''
1 1 // Copyright 2018 Yuya Nishihara <yuya@tcha.org>
2 2 //
3 3 // This software may be used and distributed according to the terms of the
4 4 // GNU General Public License version 2 or any later version.
5 5
6 6 use chg::locator::{self, Locator};
7 7 use chg::procutil;
8 use chg::{ChgClientExt, ChgUiHandler};
9 use futures::sync::oneshot;
8 use chg::ChgUiHandler;
10 9 use std::env;
11 10 use std::io;
11 use std::io::Write;
12 12 use std::process;
13 13 use std::time::Instant;
14 use tokio::prelude::*;
15 14
16 15 struct DebugLogger {
17 16 start: Instant,
18 17 }
19 18
20 19 impl DebugLogger {
21 20 pub fn new() -> DebugLogger {
22 21 DebugLogger {
23 22 start: Instant::now(),
24 23 }
25 24 }
26 25 }
27 26
28 27 impl log::Log for DebugLogger {
29 28 fn enabled(&self, metadata: &log::Metadata) -> bool {
30 29 metadata.target().starts_with("chg::")
31 30 }
32 31
33 32 fn log(&self, record: &log::Record) {
34 33 if self.enabled(record.metadata()) {
35 34 // just make the output looks similar to chg of C
36 35 let l = format!("{}", record.level()).to_lowercase();
37 36 let t = self.start.elapsed();
38 37 writeln!(
39 38 io::stderr(),
40 39 "chg: {}: {}.{:06} {}",
41 40 l,
42 41 t.as_secs(),
43 42 t.subsec_micros(),
44 43 record.args()
45 44 )
46 45 .unwrap_or(());
47 46 }
48 47 }
49 48
50 49 fn flush(&self) {}
51 50 }
52 51
53 52 fn main() {
54 53 if env::var_os("CHGDEBUG").is_some() {
55 54 log::set_boxed_logger(Box::new(DebugLogger::new()))
56 55 .expect("any logger should not be installed yet");
57 56 log::set_max_level(log::LevelFilter::Debug);
58 57 }
59 58
60 59 // TODO: add loop detection by $CHGINTERNALMARK
61 60
62 61 let umask = unsafe { procutil::get_umask() }; // not thread safe
63 62 let code = run(umask).unwrap_or_else(|err| {
64 63 writeln!(io::stderr(), "chg: abort: {}", err).unwrap_or(());
65 64 255
66 65 });
67 66 process::exit(code);
68 67 }
69 68
70 fn run(umask: u32) -> io::Result<i32> {
69 #[tokio::main]
70 async fn run(umask: u32) -> io::Result<i32> {
71 71 let mut loc = Locator::prepare_from_env()?;
72 72 loc.set_early_args(locator::collect_early_args(env::args_os().skip(1)));
73 let handler = ChgUiHandler::new();
74 let (result_tx, result_rx) = oneshot::channel();
75 let fut = loc
76 .connect()
77 .and_then(|(_, client)| client.attach_io(io::stdin(), io::stdout(), io::stderr()))
78 .and_then(move |client| client.set_umask(umask))
79 .and_then(|client| {
80 let pid = client.server_spec().process_id.unwrap();
81 let pgid = client.server_spec().process_group_id;
82 procutil::setup_signal_handler_once(pid, pgid)?;
83 Ok(client)
84 })
85 .and_then(|client| client.run_command_chg(handler, env::args_os().skip(1)))
86 .map(|(_client, _handler, code)| {
87 procutil::restore_signal_handler_once()?;
88 Ok(code)
89 })
90 .or_else(|err| Ok(Err(err))) // pass back error to caller
91 .map(|res| result_tx.send(res).unwrap());
92 tokio::run(fut);
93 result_rx.wait().unwrap_or(Err(io::Error::new(
94 io::ErrorKind::Other,
95 "no exit code set",
96 )))
73 let mut handler = ChgUiHandler::new();
74 let mut client = loc.connect().await?;
75 client
76 .attach_io(&io::stdin(), &io::stdout(), &io::stderr())
77 .await?;
78 client.set_umask(umask).await?;
79 let pid = client.server_spec().process_id.unwrap();
80 let pgid = client.server_spec().process_group_id;
81 procutil::setup_signal_handler_once(pid, pgid)?;
82 let code = client
83 .run_command_chg(&mut handler, env::args_os().skip(1))
84 .await?;
85 procutil::restore_signal_handler_once()?;
86 Ok(code)
97 87 }
General Comments 0
You need to be logged in to leave comments. Login now