##// END OF EJS Templates
rhg: Add a `rhg.on-unsupported` configuration key...
Simon Sapin -
r47424:33f2d56a default
parent child Browse files
Show More
@@ -60,6 +60,8 b' pub fn run(invocation: &crate::CliInvoca'
60 60 invocation.ui.write_stdout(&data)?;
61 61 Ok(())
62 62 }
63 None => Err(CommandError::Unimplemented.into()),
63 None => Err(CommandError::unsupported(
64 "`rhg cat` without `--rev` / `-r`",
65 )),
64 66 }
65 67 }
@@ -15,12 +15,11 b' pub enum CommandError {'
15 15 /// Exit with an error message and "standard" failure exit code.
16 16 Abort { message: Vec<u8> },
17 17
18 /// A mercurial capability as not been implemented.
19 ///
20 /// There is no error message printed in this case.
21 /// Instead, we exit with a specic status code and a wrapper script may
22 /// fallback to Python-based Mercurial.
23 Unimplemented,
18 /// Encountered something (such as a CLI argument, repository layout, …)
19 /// not supported by this version of `rhg`. Depending on configuration
20 /// `rhg` may attempt to silently fall back to Python-based `hg`, which
21 /// may or may not support this feature.
22 UnsupportedFeature { message: Vec<u8> },
24 23 }
25 24
26 25 impl CommandError {
@@ -32,20 +31,28 b' impl CommandError {'
32 31 message: utf8_to_local(message.as_ref()).into(),
33 32 }
34 33 }
34
35 pub fn unsupported(message: impl AsRef<str>) -> Self {
36 CommandError::UnsupportedFeature {
37 message: utf8_to_local(message.as_ref()).into(),
38 }
39 }
35 40 }
36 41
37 42 /// For now we don’t differenciate between invalid CLI args and valid for `hg`
38 43 /// but not supported yet by `rhg`.
39 44 impl From<clap::Error> for CommandError {
40 fn from(_: clap::Error) -> Self {
41 CommandError::Unimplemented
45 fn from(error: clap::Error) -> Self {
46 CommandError::unsupported(error.to_string())
42 47 }
43 48 }
44 49
45 50 impl From<HgError> for CommandError {
46 51 fn from(error: HgError) -> Self {
47 52 match error {
48 HgError::UnsupportedFeature(_) => CommandError::Unimplemented,
53 HgError::UnsupportedFeature(message) => {
54 CommandError::unsupported(message)
55 }
49 56 _ => CommandError::abort(error.to_string()),
50 57 }
51 58 }
@@ -84,8 +84,15 b' fn main() {'
84 84 let ui = ui::Ui::new();
85 85
86 86 let early_args = EarlyArgs::parse(std::env::args_os());
87 let non_repo_config = Config::load(early_args.config)
88 .unwrap_or_else(|error| exit(&ui, Err(error.into())));
87 let non_repo_config =
88 Config::load(early_args.config).unwrap_or_else(|error| {
89 // Normally this is decided based on config, but we don’t have that
90 // available. As of this writing config loading never returns an
91 // "unsupported" error but that is not enforced by the type system.
92 let on_unsupported = OnUnsupported::Abort;
93
94 exit(&ui, on_unsupported, Err(error.into()))
95 });
89 96
90 97 let repo_path = early_args.repo.as_deref().map(get_path_from_bytes);
91 98 let repo_result = match Repo::find(&non_repo_config, repo_path) {
@@ -94,7 +101,11 b' fn main() {'
94 101 // Not finding a repo is not fatal yet, if `-R` was not given
95 102 Err(NoRepoInCwdError { cwd: at })
96 103 }
97 Err(error) => exit(&ui, Err(error.into())),
104 Err(error) => exit(
105 &ui,
106 OnUnsupported::from_config(&non_repo_config),
107 Err(error.into()),
108 ),
98 109 };
99 110
100 111 let config = if let Ok(repo) = &repo_result {
@@ -109,7 +120,7 b' fn main() {'
109 120 repo_result.as_ref(),
110 121 config,
111 122 );
112 exit(&ui, result)
123 exit(&ui, OnUnsupported::from_config(config), result)
113 124 }
114 125
115 126 fn exit_code(result: &Result<(), CommandError>) -> i32 {
@@ -119,16 +130,37 b' fn exit_code(result: &Result<(), Command'
119 130
120 131 // Exit with a specific code and no error message to let a potential
121 132 // wrapper script fallback to Python-based Mercurial.
122 Err(CommandError::Unimplemented) => exitcode::UNIMPLEMENTED,
133 Err(CommandError::UnsupportedFeature { .. }) => {
134 exitcode::UNIMPLEMENTED
135 }
123 136 }
124 137 }
125 138
126 fn exit(ui: &Ui, result: Result<(), CommandError>) -> ! {
127 if let Err(CommandError::Abort { message }) = &result {
128 if !message.is_empty() {
129 // Ignore errors when writing to stderr, we’re already exiting
130 // with failure code so there’s not much more we can do.
131 let _ = ui.write_stderr(&format_bytes!(b"abort: {}\n", message));
139 fn exit(
140 ui: &Ui,
141 on_unsupported: OnUnsupported,
142 result: Result<(), CommandError>,
143 ) -> ! {
144 match &result {
145 Ok(_) => {}
146 Err(CommandError::Abort { message }) => {
147 if !message.is_empty() {
148 // Ignore errors when writing to stderr, we’re already exiting
149 // with failure code so there’s not much more we can do.
150 let _ =
151 ui.write_stderr(&format_bytes!(b"abort: {}\n", message));
152 }
153 }
154 Err(CommandError::UnsupportedFeature { message }) => {
155 match on_unsupported {
156 OnUnsupported::Abort => {
157 let _ = ui.write_stderr(&format_bytes!(
158 b"unsupported feature: {}\n",
159 message
160 ));
161 }
162 OnUnsupported::AbortSilent => {}
163 }
132 164 }
133 165 }
134 166 std::process::exit(exit_code(&result))
@@ -226,3 +258,29 b' impl EarlyArgs {'
226 258 Self { config, repo }
227 259 }
228 260 }
261
262 /// What to do when encountering some unsupported feature.
263 ///
264 /// See `HgError::UnsupportedFeature` and `CommandError::UnsupportedFeature`.
265 enum OnUnsupported {
266 /// Print an error message describing what feature is not supported,
267 /// and exit with code 252.
268 Abort,
269 /// Silently exit with code 252.
270 AbortSilent,
271 }
272
273 impl OnUnsupported {
274 fn from_config(config: &Config) -> Self {
275 let default = OnUnsupported::Abort;
276 match config.get(b"rhg", b"on-unsupported") {
277 Some(b"abort") => OnUnsupported::Abort,
278 Some(b"abort-silent") => OnUnsupported::AbortSilent,
279 None => default,
280 Some(_) => {
281 // TODO: warn about unknown config value
282 default
283 }
284 }
285 }
286 }
@@ -12,6 +12,15 b' Define an rhg function that will only ru'
12 12
13 13 Unimplemented command
14 14 $ rhg unimplemented-command
15 unsupported feature: error: Found argument 'unimplemented-command' which wasn't expected, or isn't valid in this context
16
17 USAGE:
18 rhg [OPTIONS] <SUBCOMMAND>
19
20 For more information try --help
21
22 [252]
23 $ rhg unimplemented-command --config rhg.on-unsupported=abort-silent
15 24 [252]
16 25
17 26 Finding root
@@ -153,12 +162,15 b' Requirements'
153 162
154 163 $ echo indoor-pool >> .hg/requires
155 164 $ rhg files
165 unsupported feature: repository requires feature unknown to this Mercurial: indoor-pool
156 166 [252]
157 167
158 168 $ rhg cat -r 1 copy_of_original
169 unsupported feature: repository requires feature unknown to this Mercurial: indoor-pool
159 170 [252]
160 171
161 172 $ rhg debugrequirements
173 unsupported feature: repository requires feature unknown to this Mercurial: indoor-pool
162 174 [252]
163 175
164 176 $ echo -e '\xFF' >> .hg/requires
General Comments 0
You need to be logged in to leave comments. Login now