annotate rust/rhg/src/main.rs @ 46704:7284b524b441

rhg: Make configuration available as early as possible in main() Differential Revision: https://phab.mercurial-scm.org/D10090
author Simon Sapin <simon.sapin@octobus.net>
date Mon, 01 Mar 2021 13:51:35 +0100
parents 4e4c70401028
children 33f2d56acc73
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
45536
b1cea0dc9db0 rhg: Add debug timing
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45535
diff changeset
1 extern crate log;
46631
80840b651721 rhg: Group values passed to every sub-command into a struct
Simon Sapin <simon.sapin@octobus.net>
parents: 46630
diff changeset
2 use crate::ui::Ui;
45051
18f8d3b31baa rhg: add a limited `rhg root` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45050
diff changeset
3 use clap::App;
18f8d3b31baa rhg: add a limited `rhg root` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45050
diff changeset
4 use clap::AppSettings;
46555
d8730ff51d5a rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46554
diff changeset
5 use clap::Arg;
45535
f17caf8f3fef rhg: add a limited `rhg debugdata` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45451
diff changeset
6 use clap::ArgMatches;
46513
ca3f73cc3cf4 rhg: Simplify CommandError based on its use
Simon Sapin <simon.sapin@octobus.net>
parents: 45938
diff changeset
7 use format_bytes::format_bytes;
46631
80840b651721 rhg: Group values passed to every sub-command into a struct
Simon Sapin <simon.sapin@octobus.net>
parents: 46630
diff changeset
8 use hg::config::Config;
46632
5ce2aa7c2ad5 rhg: Move `Repo` object creation into `main()`
Simon Sapin <simon.sapin@octobus.net>
parents: 46631
diff changeset
9 use hg::repo::{Repo, RepoError};
46704
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
10 use hg::utils::files::{get_bytes_from_os_str, get_path_from_bytes};
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
11 use hg::utils::SliceExt;
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
12 use std::ffi::OsString;
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
13 use std::path::PathBuf;
45051
18f8d3b31baa rhg: add a limited `rhg root` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45050
diff changeset
14
46640
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46635
diff changeset
15 mod blackbox;
45002
bacf6c7ef01b rhg: add Command trait for subcommands implemented by rhg
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45001
diff changeset
16 mod error;
45001
cf04f62d1579 rhg: add rhg crate
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
17 mod exitcode;
45050
513b3ef277a3 rhg: add RootCommand using hg-core FindRoot operation to prepare `hg root`
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45002
diff changeset
18 mod ui;
45535
f17caf8f3fef rhg: add a limited `rhg debugdata` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45451
diff changeset
19 use error::CommandError;
45001
cf04f62d1579 rhg: add rhg crate
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
20
46640
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46635
diff changeset
21 fn main_with_result(
46704
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
22 process_start_time: &blackbox::ProcessStartTime,
46640
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46635
diff changeset
23 ui: &ui::Ui,
46704
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
24 repo: Result<&Repo, &NoRepoInCwdError>,
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
25 config: &Config,
46640
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46635
diff changeset
26 ) -> Result<(), CommandError> {
45535
f17caf8f3fef rhg: add a limited `rhg debugdata` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45451
diff changeset
27 let app = App::new("rhg")
46647
4e4c70401028 rhg: Use clap’s support for global CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
28 .global_setting(AppSettings::AllowInvalidUtf8)
45051
18f8d3b31baa rhg: add a limited `rhg root` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45050
diff changeset
29 .setting(AppSettings::SubcommandRequired)
18f8d3b31baa rhg: add a limited `rhg root` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45050
diff changeset
30 .setting(AppSettings::VersionlessSubcommands)
46647
4e4c70401028 rhg: Use clap’s support for global CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
31 .arg(
4e4c70401028 rhg: Use clap’s support for global CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
32 Arg::with_name("repository")
4e4c70401028 rhg: Use clap’s support for global CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
33 .help("repository root directory")
4e4c70401028 rhg: Use clap’s support for global CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
34 .short("-R")
4e4c70401028 rhg: Use clap’s support for global CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
35 .long("--repository")
4e4c70401028 rhg: Use clap’s support for global CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
36 .value_name("REPO")
4e4c70401028 rhg: Use clap’s support for global CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
37 .takes_value(true)
4e4c70401028 rhg: Use clap’s support for global CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
38 // Both ok: `hg -R ./foo log` or `hg log -R ./foo`
4e4c70401028 rhg: Use clap’s support for global CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
39 .global(true),
4e4c70401028 rhg: Use clap’s support for global CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
40 )
4e4c70401028 rhg: Use clap’s support for global CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
41 .arg(
4e4c70401028 rhg: Use clap’s support for global CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
42 Arg::with_name("config")
4e4c70401028 rhg: Use clap’s support for global CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
43 .help("set/override config option (use 'section.name=value')")
4e4c70401028 rhg: Use clap’s support for global CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
44 .long("--config")
4e4c70401028 rhg: Use clap’s support for global CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
45 .value_name("CONFIG")
4e4c70401028 rhg: Use clap’s support for global CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
46 .takes_value(true)
4e4c70401028 rhg: Use clap’s support for global CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
47 .global(true)
4e4c70401028 rhg: Use clap’s support for global CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
48 // Ok: `--config section.key1=val --config section.key2=val2`
4e4c70401028 rhg: Use clap’s support for global CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
49 .multiple(true)
4e4c70401028 rhg: Use clap’s support for global CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
50 // Not ok: `--config section.key1=val section.key2=val2`
4e4c70401028 rhg: Use clap’s support for global CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
51 .number_of_values(1),
4e4c70401028 rhg: Use clap’s support for global CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
52 )
46554
95d37db31479 rhg: Replace subcommand boilerplate with a macro
Simon Sapin <simon.sapin@octobus.net>
parents: 46553
diff changeset
53 .version("0.0.1");
95d37db31479 rhg: Replace subcommand boilerplate with a macro
Simon Sapin <simon.sapin@octobus.net>
parents: 46553
diff changeset
54 let app = add_subcommand_args(app);
45051
18f8d3b31baa rhg: add a limited `rhg root` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45050
diff changeset
55
46630
21d3b40b4c0e rhg: Remove error message on unsupported CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
56 let matches = app.clone().get_matches_safe()?;
46555
d8730ff51d5a rhg: Add support for -R and --repository command-line arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46554
diff changeset
57
46554
95d37db31479 rhg: Replace subcommand boilerplate with a macro
Simon Sapin <simon.sapin@octobus.net>
parents: 46553
diff changeset
58 let (subcommand_name, subcommand_matches) = matches.subcommand();
95d37db31479 rhg: Replace subcommand boilerplate with a macro
Simon Sapin <simon.sapin@octobus.net>
parents: 46553
diff changeset
59 let run = subcommand_run_fn(subcommand_name)
95d37db31479 rhg: Replace subcommand boilerplate with a macro
Simon Sapin <simon.sapin@octobus.net>
parents: 46553
diff changeset
60 .expect("unknown subcommand name from clap despite AppSettings::SubcommandRequired");
46631
80840b651721 rhg: Group values passed to every sub-command into a struct
Simon Sapin <simon.sapin@octobus.net>
parents: 46630
diff changeset
61 let subcommand_args = subcommand_matches
46554
95d37db31479 rhg: Replace subcommand boilerplate with a macro
Simon Sapin <simon.sapin@octobus.net>
parents: 46553
diff changeset
62 .expect("no subcommand arguments from clap despite AppSettings::SubcommandRequired");
45051
18f8d3b31baa rhg: add a limited `rhg root` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45050
diff changeset
63
46640
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46635
diff changeset
64 let invocation = CliInvocation {
46631
80840b651721 rhg: Group values passed to every sub-command into a struct
Simon Sapin <simon.sapin@octobus.net>
parents: 46630
diff changeset
65 ui,
80840b651721 rhg: Group values passed to every sub-command into a struct
Simon Sapin <simon.sapin@octobus.net>
parents: 46630
diff changeset
66 subcommand_args,
46704
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
67 config,
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
68 repo,
46640
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46635
diff changeset
69 };
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46635
diff changeset
70 let blackbox = blackbox::Blackbox::new(&invocation, process_start_time)?;
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46635
diff changeset
71 blackbox.log_command_start();
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46635
diff changeset
72 let result = run(&invocation);
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46635
diff changeset
73 blackbox.log_command_end(exit_code(&result));
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46635
diff changeset
74 result
46630
21d3b40b4c0e rhg: Remove error message on unsupported CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
75 }
46554
95d37db31479 rhg: Replace subcommand boilerplate with a macro
Simon Sapin <simon.sapin@octobus.net>
parents: 46553
diff changeset
76
46630
21d3b40b4c0e rhg: Remove error message on unsupported CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
77 fn main() {
46640
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46635
diff changeset
78 // Run this first, before we find out if the blackbox extension is even
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46635
diff changeset
79 // enabled, in order to include everything in-between in the duration
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46635
diff changeset
80 // measurements. Reading config files can be slow if they’re on NFS.
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46635
diff changeset
81 let process_start_time = blackbox::ProcessStartTime::now();
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46635
diff changeset
82
46704
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
83 env_logger::init();
46632
5ce2aa7c2ad5 rhg: Move `Repo` object creation into `main()`
Simon Sapin <simon.sapin@octobus.net>
parents: 46631
diff changeset
84 let ui = ui::Ui::new();
46630
21d3b40b4c0e rhg: Remove error message on unsupported CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
85
46704
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
86 let early_args = EarlyArgs::parse(std::env::args_os());
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
87 let non_repo_config = Config::load(early_args.config)
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
88 .unwrap_or_else(|error| exit(&ui, Err(error.into())));
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
89
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
90 let repo_path = early_args.repo.as_deref().map(get_path_from_bytes);
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
91 let repo_result = match Repo::find(&non_repo_config, repo_path) {
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
92 Ok(repo) => Ok(repo),
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
93 Err(RepoError::NotFound { at }) if repo_path.is_none() => {
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
94 // Not finding a repo is not fatal yet, if `-R` was not given
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
95 Err(NoRepoInCwdError { cwd: at })
46640
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46635
diff changeset
96 }
46704
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
97 Err(error) => exit(&ui, Err(error.into())),
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
98 };
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
99
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
100 let config = if let Ok(repo) = &repo_result {
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
101 repo.config()
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
102 } else {
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
103 &non_repo_config
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
104 };
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
105
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
106 let result = main_with_result(
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
107 &process_start_time,
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
108 &ui,
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
109 repo_result.as_ref(),
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
110 config,
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
111 );
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
112 exit(&ui, result)
46640
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46635
diff changeset
113 }
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46635
diff changeset
114
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46635
diff changeset
115 fn exit_code(result: &Result<(), CommandError>) -> i32 {
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46635
diff changeset
116 match result {
46630
21d3b40b4c0e rhg: Remove error message on unsupported CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46557
diff changeset
117 Ok(()) => exitcode::OK,
46640
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46635
diff changeset
118 Err(CommandError::Abort { .. }) => exitcode::ABORT,
46513
ca3f73cc3cf4 rhg: Simplify CommandError based on its use
Simon Sapin <simon.sapin@octobus.net>
parents: 45938
diff changeset
119
ca3f73cc3cf4 rhg: Simplify CommandError based on its use
Simon Sapin <simon.sapin@octobus.net>
parents: 45938
diff changeset
120 // Exit with a specific code and no error message to let a potential
ca3f73cc3cf4 rhg: Simplify CommandError based on its use
Simon Sapin <simon.sapin@octobus.net>
parents: 45938
diff changeset
121 // wrapper script fallback to Python-based Mercurial.
ca3f73cc3cf4 rhg: Simplify CommandError based on its use
Simon Sapin <simon.sapin@octobus.net>
parents: 45938
diff changeset
122 Err(CommandError::Unimplemented) => exitcode::UNIMPLEMENTED,
46640
755c31a1caf9 rhg: Add support for the blackbox extension
Simon Sapin <simon.sapin@octobus.net>
parents: 46635
diff changeset
123 }
45001
cf04f62d1579 rhg: add rhg crate
Antoine Cezar <antoine.cezar@octobus.net>
parents:
diff changeset
124 }
45535
f17caf8f3fef rhg: add a limited `rhg debugdata` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45451
diff changeset
125
46704
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
126 fn exit(ui: &Ui, result: Result<(), CommandError>) -> ! {
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
127 if let Err(CommandError::Abort { message }) = &result {
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
128 if !message.is_empty() {
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
129 // Ignore errors when writing to stderr, we’re already exiting
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
130 // with failure code so there’s not much more we can do.
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
131 let _ = ui.write_stderr(&format_bytes!(b"abort: {}\n", message));
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
132 }
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
133 }
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
134 std::process::exit(exit_code(&result))
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
135 }
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
136
46554
95d37db31479 rhg: Replace subcommand boilerplate with a macro
Simon Sapin <simon.sapin@octobus.net>
parents: 46553
diff changeset
137 macro_rules! subcommands {
95d37db31479 rhg: Replace subcommand boilerplate with a macro
Simon Sapin <simon.sapin@octobus.net>
parents: 46553
diff changeset
138 ($( $command: ident )+) => {
95d37db31479 rhg: Replace subcommand boilerplate with a macro
Simon Sapin <simon.sapin@octobus.net>
parents: 46553
diff changeset
139 mod commands {
95d37db31479 rhg: Replace subcommand boilerplate with a macro
Simon Sapin <simon.sapin@octobus.net>
parents: 46553
diff changeset
140 $(
95d37db31479 rhg: Replace subcommand boilerplate with a macro
Simon Sapin <simon.sapin@octobus.net>
parents: 46553
diff changeset
141 pub mod $command;
95d37db31479 rhg: Replace subcommand boilerplate with a macro
Simon Sapin <simon.sapin@octobus.net>
parents: 46553
diff changeset
142 )+
95d37db31479 rhg: Replace subcommand boilerplate with a macro
Simon Sapin <simon.sapin@octobus.net>
parents: 46553
diff changeset
143 }
95d37db31479 rhg: Replace subcommand boilerplate with a macro
Simon Sapin <simon.sapin@octobus.net>
parents: 46553
diff changeset
144
95d37db31479 rhg: Replace subcommand boilerplate with a macro
Simon Sapin <simon.sapin@octobus.net>
parents: 46553
diff changeset
145 fn add_subcommand_args<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> {
95d37db31479 rhg: Replace subcommand boilerplate with a macro
Simon Sapin <simon.sapin@octobus.net>
parents: 46553
diff changeset
146 app
95d37db31479 rhg: Replace subcommand boilerplate with a macro
Simon Sapin <simon.sapin@octobus.net>
parents: 46553
diff changeset
147 $(
46647
4e4c70401028 rhg: Use clap’s support for global CLI arguments
Simon Sapin <simon.sapin@octobus.net>
parents: 46640
diff changeset
148 .subcommand(commands::$command::args())
46554
95d37db31479 rhg: Replace subcommand boilerplate with a macro
Simon Sapin <simon.sapin@octobus.net>
parents: 46553
diff changeset
149 )+
95d37db31479 rhg: Replace subcommand boilerplate with a macro
Simon Sapin <simon.sapin@octobus.net>
parents: 46553
diff changeset
150 }
46543
a6e4e4650bac rhg: Parse system and user configuration at program start
Simon Sapin <simon.sapin@octobus.net>
parents: 46513
diff changeset
151
46631
80840b651721 rhg: Group values passed to every sub-command into a struct
Simon Sapin <simon.sapin@octobus.net>
parents: 46630
diff changeset
152 pub type RunFn = fn(&CliInvocation) -> Result<(), CommandError>;
80840b651721 rhg: Group values passed to every sub-command into a struct
Simon Sapin <simon.sapin@octobus.net>
parents: 46630
diff changeset
153
80840b651721 rhg: Group values passed to every sub-command into a struct
Simon Sapin <simon.sapin@octobus.net>
parents: 46630
diff changeset
154 fn subcommand_run_fn(name: &str) -> Option<RunFn> {
46554
95d37db31479 rhg: Replace subcommand boilerplate with a macro
Simon Sapin <simon.sapin@octobus.net>
parents: 46553
diff changeset
155 match name {
95d37db31479 rhg: Replace subcommand boilerplate with a macro
Simon Sapin <simon.sapin@octobus.net>
parents: 46553
diff changeset
156 $(
95d37db31479 rhg: Replace subcommand boilerplate with a macro
Simon Sapin <simon.sapin@octobus.net>
parents: 46553
diff changeset
157 stringify!($command) => Some(commands::$command::run),
95d37db31479 rhg: Replace subcommand boilerplate with a macro
Simon Sapin <simon.sapin@octobus.net>
parents: 46553
diff changeset
158 )+
95d37db31479 rhg: Replace subcommand boilerplate with a macro
Simon Sapin <simon.sapin@octobus.net>
parents: 46553
diff changeset
159 _ => None,
95d37db31479 rhg: Replace subcommand boilerplate with a macro
Simon Sapin <simon.sapin@octobus.net>
parents: 46553
diff changeset
160 }
45548
33ded2d3f4fc rhg: add a limited `rhg cat -r` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45543
diff changeset
161 }
46554
95d37db31479 rhg: Replace subcommand boilerplate with a macro
Simon Sapin <simon.sapin@octobus.net>
parents: 46553
diff changeset
162 };
45535
f17caf8f3fef rhg: add a limited `rhg debugdata` subcommand
Antoine Cezar <antoine.cezar@octobus.net>
parents: 45451
diff changeset
163 }
46554
95d37db31479 rhg: Replace subcommand boilerplate with a macro
Simon Sapin <simon.sapin@octobus.net>
parents: 46553
diff changeset
164
95d37db31479 rhg: Replace subcommand boilerplate with a macro
Simon Sapin <simon.sapin@octobus.net>
parents: 46553
diff changeset
165 subcommands! {
95d37db31479 rhg: Replace subcommand boilerplate with a macro
Simon Sapin <simon.sapin@octobus.net>
parents: 46553
diff changeset
166 cat
95d37db31479 rhg: Replace subcommand boilerplate with a macro
Simon Sapin <simon.sapin@octobus.net>
parents: 46553
diff changeset
167 debugdata
95d37db31479 rhg: Replace subcommand boilerplate with a macro
Simon Sapin <simon.sapin@octobus.net>
parents: 46553
diff changeset
168 debugrequirements
95d37db31479 rhg: Replace subcommand boilerplate with a macro
Simon Sapin <simon.sapin@octobus.net>
parents: 46553
diff changeset
169 files
95d37db31479 rhg: Replace subcommand boilerplate with a macro
Simon Sapin <simon.sapin@octobus.net>
parents: 46553
diff changeset
170 root
46557
a25033eb43b5 rhg: add limited support for the `config` sub-command
Simon Sapin <simon.sapin@octobus.net>
parents: 46556
diff changeset
171 config
46554
95d37db31479 rhg: Replace subcommand boilerplate with a macro
Simon Sapin <simon.sapin@octobus.net>
parents: 46553
diff changeset
172 }
46631
80840b651721 rhg: Group values passed to every sub-command into a struct
Simon Sapin <simon.sapin@octobus.net>
parents: 46630
diff changeset
173 pub struct CliInvocation<'a> {
80840b651721 rhg: Group values passed to every sub-command into a struct
Simon Sapin <simon.sapin@octobus.net>
parents: 46630
diff changeset
174 ui: &'a Ui,
80840b651721 rhg: Group values passed to every sub-command into a struct
Simon Sapin <simon.sapin@octobus.net>
parents: 46630
diff changeset
175 subcommand_args: &'a ArgMatches<'a>,
46704
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
176 config: &'a Config,
46632
5ce2aa7c2ad5 rhg: Move `Repo` object creation into `main()`
Simon Sapin <simon.sapin@octobus.net>
parents: 46631
diff changeset
177 /// References inside `Result` is a bit peculiar but allow
5ce2aa7c2ad5 rhg: Move `Repo` object creation into `main()`
Simon Sapin <simon.sapin@octobus.net>
parents: 46631
diff changeset
178 /// `invocation.repo?` to work out with `&CliInvocation` since this
5ce2aa7c2ad5 rhg: Move `Repo` object creation into `main()`
Simon Sapin <simon.sapin@octobus.net>
parents: 46631
diff changeset
179 /// `Result` type is `Copy`.
5ce2aa7c2ad5 rhg: Move `Repo` object creation into `main()`
Simon Sapin <simon.sapin@octobus.net>
parents: 46631
diff changeset
180 repo: Result<&'a Repo, &'a NoRepoInCwdError>,
5ce2aa7c2ad5 rhg: Move `Repo` object creation into `main()`
Simon Sapin <simon.sapin@octobus.net>
parents: 46631
diff changeset
181 }
5ce2aa7c2ad5 rhg: Move `Repo` object creation into `main()`
Simon Sapin <simon.sapin@octobus.net>
parents: 46631
diff changeset
182
5ce2aa7c2ad5 rhg: Move `Repo` object creation into `main()`
Simon Sapin <simon.sapin@octobus.net>
parents: 46631
diff changeset
183 struct NoRepoInCwdError {
5ce2aa7c2ad5 rhg: Move `Repo` object creation into `main()`
Simon Sapin <simon.sapin@octobus.net>
parents: 46631
diff changeset
184 cwd: PathBuf,
46631
80840b651721 rhg: Group values passed to every sub-command into a struct
Simon Sapin <simon.sapin@octobus.net>
parents: 46630
diff changeset
185 }
46632
5ce2aa7c2ad5 rhg: Move `Repo` object creation into `main()`
Simon Sapin <simon.sapin@octobus.net>
parents: 46631
diff changeset
186
46704
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
187 /// CLI arguments to be parsed "early" in order to be able to read
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
188 /// configuration before using Clap. Ideally we would also use Clap for this,
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
189 /// see <https://github.com/clap-rs/clap/discussions/2366>.
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
190 ///
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
191 /// These arguments are still declared when we do use Clap later, so that Clap
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
192 /// does not return an error for their presence.
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
193 struct EarlyArgs {
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
194 /// Values of all `--config` arguments. (Possibly none)
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
195 config: Vec<Vec<u8>>,
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
196 /// Value of the `-R` or `--repository` argument, if any.
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
197 repo: Option<Vec<u8>>,
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
198 }
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
199
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
200 impl EarlyArgs {
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
201 fn parse(args: impl IntoIterator<Item = OsString>) -> Self {
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
202 let mut args = args.into_iter().map(get_bytes_from_os_str);
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
203 let mut config = Vec::new();
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
204 let mut repo = None;
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
205 // Use `while let` instead of `for` so that we can also call
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
206 // `args.next()` inside the loop.
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
207 while let Some(arg) = args.next() {
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
208 if arg == b"--config" {
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
209 if let Some(value) = args.next() {
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
210 config.push(value)
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
211 }
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
212 } else if let Some(value) = arg.drop_prefix(b"--config=") {
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
213 config.push(value.to_owned())
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
214 }
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
215
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
216 if arg == b"--repository" || arg == b"-R" {
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
217 if let Some(value) = args.next() {
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
218 repo = Some(value)
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
219 }
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
220 } else if let Some(value) = arg.drop_prefix(b"--repository=") {
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
221 repo = Some(value.to_owned())
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
222 } else if let Some(value) = arg.drop_prefix(b"-R") {
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
223 repo = Some(value.to_owned())
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
224 }
46632
5ce2aa7c2ad5 rhg: Move `Repo` object creation into `main()`
Simon Sapin <simon.sapin@octobus.net>
parents: 46631
diff changeset
225 }
46704
7284b524b441 rhg: Make configuration available as early as possible in main()
Simon Sapin <simon.sapin@octobus.net>
parents: 46647
diff changeset
226 Self { config, repo }
46632
5ce2aa7c2ad5 rhg: Move `Repo` object creation into `main()`
Simon Sapin <simon.sapin@octobus.net>
parents: 46631
diff changeset
227 }
5ce2aa7c2ad5 rhg: Move `Repo` object creation into `main()`
Simon Sapin <simon.sapin@octobus.net>
parents: 46631
diff changeset
228 }