comparison rust/rhg/src/main.rs @ 46631:80840b651721

rhg: Group values passed to every sub-command into a struct The set of which values this is is evidently not stable yet, so this will make changes easier. Also it is growing, and the function signatures are getting out hand. Differential Revision: https://phab.mercurial-scm.org/D10003
author Simon Sapin <simon.sapin@octobus.net>
date Mon, 15 Feb 2021 20:05:32 +0100
parents 21d3b40b4c0e
children 5ce2aa7c2ad5
comparison
equal deleted inserted replaced
46630:21d3b40b4c0e 46631:80840b651721
1 extern crate log; 1 extern crate log;
2 use crate::ui::Ui;
2 use clap::App; 3 use clap::App;
3 use clap::AppSettings; 4 use clap::AppSettings;
4 use clap::Arg; 5 use clap::Arg;
5 use clap::ArgMatches; 6 use clap::ArgMatches;
6 use format_bytes::format_bytes; 7 use format_bytes::format_bytes;
8 use hg::config::Config;
7 use std::path::Path; 9 use std::path::Path;
8 10
9 mod error; 11 mod error;
10 mod exitcode; 12 mod exitcode;
11 mod ui; 13 mod ui;
46 let matches = app.clone().get_matches_safe()?; 48 let matches = app.clone().get_matches_safe()?;
47 49
48 let (subcommand_name, subcommand_matches) = matches.subcommand(); 50 let (subcommand_name, subcommand_matches) = matches.subcommand();
49 let run = subcommand_run_fn(subcommand_name) 51 let run = subcommand_run_fn(subcommand_name)
50 .expect("unknown subcommand name from clap despite AppSettings::SubcommandRequired"); 52 .expect("unknown subcommand name from clap despite AppSettings::SubcommandRequired");
51 let args = subcommand_matches 53 let subcommand_args = subcommand_matches
52 .expect("no subcommand arguments from clap despite AppSettings::SubcommandRequired"); 54 .expect("no subcommand arguments from clap despite AppSettings::SubcommandRequired");
53 55
54 // Global arguments can be in either based on e.g. `hg -R ./foo log` v.s. 56 // Global arguments can be in either based on e.g. `hg -R ./foo log` v.s.
55 // `hg log -R ./foo` 57 // `hg log -R ./foo`
56 let value_of_global_arg = 58 let value_of_global_arg = |name| {
57 |name| args.value_of_os(name).or_else(|| matches.value_of_os(name)); 59 subcommand_args
60 .value_of_os(name)
61 .or_else(|| matches.value_of_os(name))
62 };
58 // For arguments where multiple occurences are allowed, return a 63 // For arguments where multiple occurences are allowed, return a
59 // possibly-iterator of all values. 64 // possibly-iterator of all values.
60 let values_of_global_arg = |name: &str| { 65 let values_of_global_arg = |name: &str| {
61 let a = matches.values_of_os(name).into_iter().flatten(); 66 let a = matches.values_of_os(name).into_iter().flatten();
62 let b = args.values_of_os(name).into_iter().flatten(); 67 let b = subcommand_args.values_of_os(name).into_iter().flatten();
63 a.chain(b) 68 a.chain(b)
64 }; 69 };
65 70
66 let repo_path = value_of_global_arg("repository").map(Path::new);
67 let config_args = values_of_global_arg("config") 71 let config_args = values_of_global_arg("config")
68 // `get_bytes_from_path` works for OsStr the same as for Path 72 // `get_bytes_from_path` works for OsStr the same as for Path
69 .map(hg::utils::files::get_bytes_from_path); 73 .map(hg::utils::files::get_bytes_from_path);
70 let config = hg::config::Config::load(config_args)?; 74 let non_repo_config = &hg::config::Config::load(config_args)?;
71 run(&ui, &config, repo_path, args) 75
76 let repo_path = value_of_global_arg("repository").map(Path::new);
77
78 run(&CliInvocation {
79 ui,
80 subcommand_args,
81 non_repo_config,
82 repo_path,
83 })
72 } 84 }
73 85
74 fn main() { 86 fn main() {
75 let ui = ui::Ui::new(); 87 let ui = Ui::new();
76 88
77 let exit_code = match main_with_result(&ui) { 89 let exit_code = match main_with_result(&ui) {
78 Ok(()) => exitcode::OK, 90 Ok(()) => exitcode::OK,
79 91
80 // Exit with a specific code and no error message to let a potential 92 // Exit with a specific code and no error message to let a potential
107 $( 119 $(
108 .subcommand(add_global_args(commands::$command::args())) 120 .subcommand(add_global_args(commands::$command::args()))
109 )+ 121 )+
110 } 122 }
111 123
112 fn subcommand_run_fn(name: &str) -> Option<fn( 124 pub type RunFn = fn(&CliInvocation) -> Result<(), CommandError>;
113 &ui::Ui, 125
114 &hg::config::Config, 126 fn subcommand_run_fn(name: &str) -> Option<RunFn> {
115 Option<&Path>,
116 &ArgMatches,
117 ) -> Result<(), CommandError>> {
118 match name { 127 match name {
119 $( 128 $(
120 stringify!($command) => Some(commands::$command::run), 129 stringify!($command) => Some(commands::$command::run),
121 )+ 130 )+
122 _ => None, 131 _ => None,
131 debugrequirements 140 debugrequirements
132 files 141 files
133 root 142 root
134 config 143 config
135 } 144 }
145 pub struct CliInvocation<'a> {
146 ui: &'a Ui,
147 subcommand_args: &'a ArgMatches<'a>,
148 non_repo_config: &'a Config,
149 repo_path: Option<&'a Path>,
150 }