Mercurial > hg
comparison rust/rhg/src/error.rs @ 49488:9f14126cfc4c
rust: add support for hints in error messages
This will be used by the narrow support code in the next commit.
author | Raphaël Gomès <rgomes@octobus.net> |
---|---|
date | Tue, 19 Jul 2022 17:07:09 +0200 |
parents | ffd4b1f1c9cb |
children | 7c93e38a0bbd |
comparison
equal
deleted
inserted
replaced
49487:e8481625c582 | 49488:9f14126cfc4c |
---|---|
18 pub enum CommandError { | 18 pub enum CommandError { |
19 /// Exit with an error message and "standard" failure exit code. | 19 /// Exit with an error message and "standard" failure exit code. |
20 Abort { | 20 Abort { |
21 message: Vec<u8>, | 21 message: Vec<u8>, |
22 detailed_exit_code: exit_codes::ExitCode, | 22 detailed_exit_code: exit_codes::ExitCode, |
23 hint: Option<Vec<u8>>, | |
23 }, | 24 }, |
24 | 25 |
25 /// Exit with a failure exit code but no message. | 26 /// Exit with a failure exit code but no message. |
26 Unsuccessful, | 27 Unsuccessful, |
27 | 28 |
48 // TODO: bytes-based (instead of Unicode-based) formatting | 49 // TODO: bytes-based (instead of Unicode-based) formatting |
49 // of error messages to handle non-UTF-8 filenames etc: | 50 // of error messages to handle non-UTF-8 filenames etc: |
50 // https://www.mercurial-scm.org/wiki/EncodingStrategy#Mixing_output | 51 // https://www.mercurial-scm.org/wiki/EncodingStrategy#Mixing_output |
51 message: utf8_to_local(message.as_ref()).into(), | 52 message: utf8_to_local(message.as_ref()).into(), |
52 detailed_exit_code: detailed_exit_code, | 53 detailed_exit_code: detailed_exit_code, |
54 hint: None, | |
55 } | |
56 } | |
57 | |
58 pub fn abort_with_exit_code_and_hint( | |
59 message: impl AsRef<str>, | |
60 detailed_exit_code: exit_codes::ExitCode, | |
61 hint: Option<impl AsRef<str>>, | |
62 ) -> Self { | |
63 CommandError::Abort { | |
64 message: utf8_to_local(message.as_ref()).into(), | |
65 detailed_exit_code, | |
66 hint: hint.map(|h| utf8_to_local(h.as_ref()).into()), | |
53 } | 67 } |
54 } | 68 } |
55 | 69 |
56 pub fn abort_with_exit_code_bytes( | 70 pub fn abort_with_exit_code_bytes( |
57 message: impl AsRef<[u8]>, | 71 message: impl AsRef<[u8]>, |
60 // TODO: use this everywhere it makes sense instead of the string | 74 // TODO: use this everywhere it makes sense instead of the string |
61 // version. | 75 // version. |
62 CommandError::Abort { | 76 CommandError::Abort { |
63 message: message.as_ref().into(), | 77 message: message.as_ref().into(), |
64 detailed_exit_code, | 78 detailed_exit_code, |
79 hint: None, | |
65 } | 80 } |
66 } | 81 } |
67 | 82 |
68 pub fn unsupported(message: impl AsRef<str>) -> Self { | 83 pub fn unsupported(message: impl AsRef<str>) -> Self { |
69 CommandError::UnsupportedFeature { | 84 CommandError::UnsupportedFeature { |
90 CommandError::unsupported("Encountered a censored node") | 105 CommandError::unsupported("Encountered a censored node") |
91 } | 106 } |
92 HgError::Abort { | 107 HgError::Abort { |
93 message, | 108 message, |
94 detailed_exit_code, | 109 detailed_exit_code, |
95 } => { | 110 hint, |
96 CommandError::abort_with_exit_code(message, detailed_exit_code) | 111 } => CommandError::abort_with_exit_code_and_hint( |
97 } | 112 message, |
113 detailed_exit_code, | |
114 hint, | |
115 ), | |
98 _ => CommandError::abort(error.to_string()), | 116 _ => CommandError::abort(error.to_string()), |
99 } | 117 } |
100 } | 118 } |
101 } | 119 } |
102 | 120 |
119 } | 137 } |
120 | 138 |
121 impl From<RepoError> for CommandError { | 139 impl From<RepoError> for CommandError { |
122 fn from(error: RepoError) -> Self { | 140 fn from(error: RepoError) -> Self { |
123 match error { | 141 match error { |
124 RepoError::NotFound { at } => CommandError::Abort { | 142 RepoError::NotFound { at } => { |
125 message: format_bytes!( | 143 CommandError::abort_with_exit_code_bytes( |
126 b"abort: repository {} not found", | 144 format_bytes!( |
127 get_bytes_from_path(at) | 145 b"abort: repository {} not found", |
128 ), | 146 get_bytes_from_path(at) |
129 detailed_exit_code: exit_codes::ABORT, | 147 ), |
130 }, | 148 exit_codes::ABORT, |
149 ) | |
150 } | |
131 RepoError::ConfigParseError(error) => error.into(), | 151 RepoError::ConfigParseError(error) => error.into(), |
132 RepoError::Other(error) => error.into(), | 152 RepoError::Other(error) => error.into(), |
133 } | 153 } |
134 } | 154 } |
135 } | 155 } |
136 | 156 |
137 impl<'a> From<&'a NoRepoInCwdError> for CommandError { | 157 impl<'a> From<&'a NoRepoInCwdError> for CommandError { |
138 fn from(error: &'a NoRepoInCwdError) -> Self { | 158 fn from(error: &'a NoRepoInCwdError) -> Self { |
139 let NoRepoInCwdError { cwd } = error; | 159 let NoRepoInCwdError { cwd } = error; |
140 CommandError::Abort { | 160 CommandError::abort_with_exit_code_bytes( |
141 message: format_bytes!( | 161 format_bytes!( |
142 b"abort: no repository found in '{}' (.hg not found)!", | 162 b"abort: no repository found in '{}' (.hg not found)!", |
143 get_bytes_from_path(cwd) | 163 get_bytes_from_path(cwd) |
144 ), | 164 ), |
145 detailed_exit_code: exit_codes::ABORT, | 165 exit_codes::ABORT, |
146 } | 166 ) |
147 } | 167 } |
148 } | 168 } |
149 | 169 |
150 impl From<ConfigError> for CommandError { | 170 impl From<ConfigError> for CommandError { |
151 fn from(error: ConfigError) -> Self { | 171 fn from(error: ConfigError) -> Self { |
166 let line_message = if let Some(line_number) = line { | 186 let line_message = if let Some(line_number) = line { |
167 format_bytes!(b":{}", line_number.to_string().into_bytes()) | 187 format_bytes!(b":{}", line_number.to_string().into_bytes()) |
168 } else { | 188 } else { |
169 Vec::new() | 189 Vec::new() |
170 }; | 190 }; |
171 CommandError::Abort { | 191 CommandError::abort_with_exit_code_bytes( |
172 message: format_bytes!( | 192 format_bytes!( |
173 b"config error at {}{}: {}", | 193 b"config error at {}{}: {}", |
174 origin, | 194 origin, |
175 line_message, | 195 line_message, |
176 message | 196 message |
177 ), | 197 ), |
178 detailed_exit_code: exit_codes::CONFIG_ERROR_ABORT, | 198 exit_codes::CONFIG_ERROR_ABORT, |
179 } | 199 ) |
180 } | 200 } |
181 } | 201 } |
182 | 202 |
183 impl From<(RevlogError, &str)> for CommandError { | 203 impl From<(RevlogError, &str)> for CommandError { |
184 fn from((err, rev): (RevlogError, &str)) -> CommandError { | 204 fn from((err, rev): (RevlogError, &str)) -> CommandError { |