comparison rust/rhg/src/blackbox.rs @ 49070:137a93125902

rhg: refactor to pass argv down, instead of caling args_os() This refactoring makes it easy to patch some command-line preprocessing into rhg. We use this to support using rhg as a shebang interpreter, for example. Differential Revision: https://phab.mercurial-scm.org/D12543
author Arseniy Alekseyev <aalekseyev@janestreet.com>
date Tue, 12 Apr 2022 20:01:49 +0100
parents abbecb5cd6f3
children d39ac3468ad4
comparison
equal deleted inserted replaced
49069:a31e9840178e 49070:137a93125902
3 use crate::CliInvocation; 3 use crate::CliInvocation;
4 use format_bytes::format_bytes; 4 use format_bytes::format_bytes;
5 use hg::errors::HgError; 5 use hg::errors::HgError;
6 use hg::repo::Repo; 6 use hg::repo::Repo;
7 use hg::utils::{files::get_bytes_from_os_str, shell_quote}; 7 use hg::utils::{files::get_bytes_from_os_str, shell_quote};
8 use std::ffi::OsString;
8 9
9 const ONE_MEBIBYTE: u64 = 1 << 20; 10 const ONE_MEBIBYTE: u64 = 1 << 20;
10 11
11 // TODO: somehow keep defaults in sync with `configitem` in `hgext/blackbox.py` 12 // TODO: somehow keep defaults in sync with `configitem` in `hgext/blackbox.py`
12 const DEFAULT_MAX_SIZE: u64 = ONE_MEBIBYTE; 13 const DEFAULT_MAX_SIZE: u64 = ONE_MEBIBYTE;
81 process_start_time, 82 process_start_time,
82 configured, 83 configured,
83 }) 84 })
84 } 85 }
85 86
86 pub fn log_command_start(&self) { 87 pub fn log_command_start<'arg>(
88 &self,
89 argv: impl Iterator<Item = &'arg OsString>,
90 ) {
87 if let Some(configured) = &self.configured { 91 if let Some(configured) = &self.configured {
88 let message = format_bytes!(b"(rust) {}", format_cli_args()); 92 let message = format_bytes!(b"(rust) {}", format_cli_args(argv));
89 configured.log(&self.process_start_time.calendar_based, &message); 93 configured.log(&self.process_start_time.calendar_based, &message);
90 } 94 }
91 } 95 }
92 96
93 pub fn log_command_end(&self, exit_code: i32) { 97 pub fn log_command_end<'arg>(
98 &self,
99 argv: impl Iterator<Item = &'arg OsString>,
100 exit_code: i32,
101 ) {
94 if let Some(configured) = &self.configured { 102 if let Some(configured) = &self.configured {
95 let now = chrono::Local::now(); 103 let now = chrono::Local::now();
96 let duration = self 104 let duration = self
97 .process_start_time 105 .process_start_time
98 .monotonic_clock 106 .monotonic_clock
99 .elapsed() 107 .elapsed()
100 .as_secs_f64(); 108 .as_secs_f64();
101 let message = format_bytes!( 109 let message = format_bytes!(
102 b"(rust) {} exited {} after {} seconds", 110 b"(rust) {} exited {} after {} seconds",
103 format_cli_args(), 111 format_cli_args(argv),
104 exit_code, 112 exit_code,
105 format_bytes::Utf8(format_args!("{:.03}", duration)) 113 format_bytes::Utf8(format_args!("{:.03}", duration))
106 ); 114 );
107 configured.log(&now, &message); 115 configured.log(&now, &message);
108 } 116 }
145 } 153 }
146 } 154 }
147 } 155 }
148 } 156 }
149 157
150 fn format_cli_args() -> Vec<u8> { 158 fn format_cli_args<'a>(
151 let mut args = std::env::args_os(); 159 mut args: impl Iterator<Item = &'a OsString>,
160 ) -> Vec<u8> {
152 let _ = args.next(); // Skip the first (or zeroth) arg, the name of the `rhg` executable 161 let _ = args.next(); // Skip the first (or zeroth) arg, the name of the `rhg` executable
153 let mut args = args.map(|arg| shell_quote(&get_bytes_from_os_str(arg))); 162 let mut args = args.map(|arg| shell_quote(&get_bytes_from_os_str(arg)));
154 let mut formatted = Vec::new(); 163 let mut formatted = Vec::new();
155 if let Some(arg) = args.next() { 164 if let Some(arg) = args.next() {
156 formatted.extend(arg) 165 formatted.extend(arg)