##// 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 invocation.ui.write_stdout(&data)?;
60 invocation.ui.write_stdout(&data)?;
61 Ok(())
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 /// Exit with an error message and "standard" failure exit code.
15 /// Exit with an error message and "standard" failure exit code.
16 Abort { message: Vec<u8> },
16 Abort { message: Vec<u8> },
17
17
18 /// A mercurial capability as not been implemented.
18 /// Encountered something (such as a CLI argument, repository layout, …)
19 ///
19 /// not supported by this version of `rhg`. Depending on configuration
20 /// There is no error message printed in this case.
20 /// `rhg` may attempt to silently fall back to Python-based `hg`, which
21 /// Instead, we exit with a specic status code and a wrapper script may
21 /// may or may not support this feature.
22 /// fallback to Python-based Mercurial.
22 UnsupportedFeature { message: Vec<u8> },
23 Unimplemented,
24 }
23 }
25
24
26 impl CommandError {
25 impl CommandError {
@@ -32,20 +31,28 b' impl CommandError {'
32 message: utf8_to_local(message.as_ref()).into(),
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 /// For now we don’t differenciate between invalid CLI args and valid for `hg`
42 /// For now we don’t differenciate between invalid CLI args and valid for `hg`
38 /// but not supported yet by `rhg`.
43 /// but not supported yet by `rhg`.
39 impl From<clap::Error> for CommandError {
44 impl From<clap::Error> for CommandError {
40 fn from(_: clap::Error) -> Self {
45 fn from(error: clap::Error) -> Self {
41 CommandError::Unimplemented
46 CommandError::unsupported(error.to_string())
42 }
47 }
43 }
48 }
44
49
45 impl From<HgError> for CommandError {
50 impl From<HgError> for CommandError {
46 fn from(error: HgError) -> Self {
51 fn from(error: HgError) -> Self {
47 match error {
52 match error {
48 HgError::UnsupportedFeature(_) => CommandError::Unimplemented,
53 HgError::UnsupportedFeature(message) => {
54 CommandError::unsupported(message)
55 }
49 _ => CommandError::abort(error.to_string()),
56 _ => CommandError::abort(error.to_string()),
50 }
57 }
51 }
58 }
@@ -84,8 +84,15 b' fn main() {'
84 let ui = ui::Ui::new();
84 let ui = ui::Ui::new();
85
85
86 let early_args = EarlyArgs::parse(std::env::args_os());
86 let early_args = EarlyArgs::parse(std::env::args_os());
87 let non_repo_config = Config::load(early_args.config)
87 let non_repo_config =
88 .unwrap_or_else(|error| exit(&ui, Err(error.into())));
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 let repo_path = early_args.repo.as_deref().map(get_path_from_bytes);
97 let repo_path = early_args.repo.as_deref().map(get_path_from_bytes);
91 let repo_result = match Repo::find(&non_repo_config, repo_path) {
98 let repo_result = match Repo::find(&non_repo_config, repo_path) {
@@ -94,7 +101,11 b' fn main() {'
94 // Not finding a repo is not fatal yet, if `-R` was not given
101 // Not finding a repo is not fatal yet, if `-R` was not given
95 Err(NoRepoInCwdError { cwd: at })
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 let config = if let Ok(repo) = &repo_result {
111 let config = if let Ok(repo) = &repo_result {
@@ -109,7 +120,7 b' fn main() {'
109 repo_result.as_ref(),
120 repo_result.as_ref(),
110 config,
121 config,
111 );
122 );
112 exit(&ui, result)
123 exit(&ui, OnUnsupported::from_config(config), result)
113 }
124 }
114
125
115 fn exit_code(result: &Result<(), CommandError>) -> i32 {
126 fn exit_code(result: &Result<(), CommandError>) -> i32 {
@@ -119,16 +130,37 b' fn exit_code(result: &Result<(), Command'
119
130
120 // Exit with a specific code and no error message to let a potential
131 // Exit with a specific code and no error message to let a potential
121 // wrapper script fallback to Python-based Mercurial.
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>) -> ! {
139 fn exit(
127 if let Err(CommandError::Abort { message }) = &result {
140 ui: &Ui,
128 if !message.is_empty() {
141 on_unsupported: OnUnsupported,
129 // Ignore errors when writing to stderr, we’re already exiting
142 result: Result<(), CommandError>,
130 // with failure code so there’s not much more we can do.
143 ) -> ! {
131 let _ = ui.write_stderr(&format_bytes!(b"abort: {}\n", message));
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 std::process::exit(exit_code(&result))
166 std::process::exit(exit_code(&result))
@@ -226,3 +258,29 b' impl EarlyArgs {'
226 Self { config, repo }
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 Unimplemented command
13 Unimplemented command
14 $ rhg unimplemented-command
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 [252]
24 [252]
16
25
17 Finding root
26 Finding root
@@ -153,12 +162,15 b' Requirements'
153
162
154 $ echo indoor-pool >> .hg/requires
163 $ echo indoor-pool >> .hg/requires
155 $ rhg files
164 $ rhg files
165 unsupported feature: repository requires feature unknown to this Mercurial: indoor-pool
156 [252]
166 [252]
157
167
158 $ rhg cat -r 1 copy_of_original
168 $ rhg cat -r 1 copy_of_original
169 unsupported feature: repository requires feature unknown to this Mercurial: indoor-pool
159 [252]
170 [252]
160
171
161 $ rhg debugrequirements
172 $ rhg debugrequirements
173 unsupported feature: repository requires feature unknown to this Mercurial: indoor-pool
162 [252]
174 [252]
163
175
164 $ echo -e '\xFF' >> .hg/requires
176 $ echo -e '\xFF' >> .hg/requires
General Comments 0
You need to be logged in to leave comments. Login now