comparison rust/rhg/src/main.rs @ 46601:755c31a1caf9

rhg: Add support for the blackbox extension Only `command` and `commandfinish` events are logged. The `dirty`, `logsource`, `track` and `ignore` configuration items are not supported yet. To indicate commands executed without Python, a `(rust) ` prefix is added in corresponding log messages. Differential Revision: https://phab.mercurial-scm.org/D10012
author Simon Sapin <simon.sapin@octobus.net>
date Tue, 16 Feb 2021 13:08:37 +0100
parents d2e61f00ee9d
children 4e4c70401028
comparison
equal deleted inserted replaced
46600:36f3a64846c8 46601:755c31a1caf9
7 use format_bytes::format_bytes; 7 use format_bytes::format_bytes;
8 use hg::config::Config; 8 use hg::config::Config;
9 use hg::repo::{Repo, RepoError}; 9 use hg::repo::{Repo, RepoError};
10 use std::path::{Path, PathBuf}; 10 use std::path::{Path, PathBuf};
11 11
12 mod blackbox;
12 mod error; 13 mod error;
13 mod exitcode; 14 mod exitcode;
14 mod ui; 15 mod ui;
15 use error::CommandError; 16 use error::CommandError;
16 17
34 // Not ok: `--config section.key1=val section.key2=val2` 35 // Not ok: `--config section.key1=val section.key2=val2`
35 .number_of_values(1), 36 .number_of_values(1),
36 ) 37 )
37 } 38 }
38 39
39 fn main_with_result(ui: &ui::Ui) -> Result<(), CommandError> { 40 fn main_with_result(
41 ui: &ui::Ui,
42 process_start_time: &blackbox::ProcessStartTime,
43 ) -> Result<(), CommandError> {
40 env_logger::init(); 44 env_logger::init();
41 let app = App::new("rhg") 45 let app = App::new("rhg")
42 .setting(AppSettings::AllowInvalidUtf8) 46 .setting(AppSettings::AllowInvalidUtf8)
43 .setting(AppSettings::SubcommandRequired) 47 .setting(AppSettings::SubcommandRequired)
44 .setting(AppSettings::VersionlessSubcommands) 48 .setting(AppSettings::VersionlessSubcommands)
81 Err(NoRepoInCwdError { cwd: at }) 85 Err(NoRepoInCwdError { cwd: at })
82 } 86 }
83 Err(error) => return Err(error.into()), 87 Err(error) => return Err(error.into()),
84 }; 88 };
85 89
86 run(&CliInvocation { 90 let invocation = CliInvocation {
87 ui, 91 ui,
88 subcommand_args, 92 subcommand_args,
89 non_repo_config, 93 non_repo_config,
90 repo: repo.as_ref(), 94 repo: repo.as_ref(),
91 }) 95 };
96 let blackbox = blackbox::Blackbox::new(&invocation, process_start_time)?;
97 blackbox.log_command_start();
98 let result = run(&invocation);
99 blackbox.log_command_end(exit_code(&result));
100 result
92 } 101 }
93 102
94 fn main() { 103 fn main() {
104 // Run this first, before we find out if the blackbox extension is even
105 // enabled, in order to include everything in-between in the duration
106 // measurements. Reading config files can be slow if they’re on NFS.
107 let process_start_time = blackbox::ProcessStartTime::now();
108
95 let ui = ui::Ui::new(); 109 let ui = ui::Ui::new();
96 110
97 let exit_code = match main_with_result(&ui) { 111 let result = main_with_result(&ui, &process_start_time);
112 if let Err(CommandError::Abort { message }) = &result {
113 if !message.is_empty() {
114 // Ignore errors when writing to stderr, we’re already exiting
115 // with failure code so there’s not much more we can do.
116 let _ = ui.write_stderr(&format_bytes!(b"abort: {}\n", message));
117 }
118 }
119 std::process::exit(exit_code(&result))
120 }
121
122 fn exit_code(result: &Result<(), CommandError>) -> i32 {
123 match result {
98 Ok(()) => exitcode::OK, 124 Ok(()) => exitcode::OK,
125 Err(CommandError::Abort { .. }) => exitcode::ABORT,
99 126
100 // Exit with a specific code and no error message to let a potential 127 // Exit with a specific code and no error message to let a potential
101 // wrapper script fallback to Python-based Mercurial. 128 // wrapper script fallback to Python-based Mercurial.
102 Err(CommandError::Unimplemented) => exitcode::UNIMPLEMENTED, 129 Err(CommandError::Unimplemented) => exitcode::UNIMPLEMENTED,
103 130 }
104 Err(CommandError::Abort { message }) => {
105 if !message.is_empty() {
106 // Ignore errors when writing to stderr, we’re already exiting
107 // with failure code so there’s not much more we can do.
108 let _ =
109 ui.write_stderr(&format_bytes!(b"abort: {}\n", message));
110 }
111 exitcode::ABORT
112 }
113 };
114 std::process::exit(exit_code)
115 } 131 }
116 132
117 macro_rules! subcommands { 133 macro_rules! subcommands {
118 ($( $command: ident )+) => { 134 ($( $command: ident )+) => {
119 mod commands { 135 mod commands {