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