error.rs
115 lines
| 3.4 KiB
| application/rls-services+xml
|
RustLexer
Simon Sapin
|
r47165 | use crate::ui::utf8_to_local; | ||
Antoine Cezar
|
r45592 | use crate::ui::UiError; | ||
Simon Sapin
|
r47175 | use format_bytes::format_bytes; | ||
Simon Sapin
|
r47213 | use hg::config::{ConfigError, ConfigParseError}; | ||
Simon Sapin
|
r47175 | use hg::errors::HgError; | ||
Simon Sapin
|
r47215 | use hg::repo::RepoError; | ||
Simon Sapin
|
r47166 | use hg::revlog::revlog::RevlogError; | ||
Simon Sapin
|
r47175 | use hg::utils::files::get_bytes_from_path; | ||
Antoine Cezar
|
r45592 | use std::convert::From; | ||
/// The kind of command error | ||||
Simon Sapin
|
r47174 | #[derive(Debug)] | ||
Simon Sapin
|
r47163 | pub enum CommandError { | ||
Simon Sapin
|
r47174 | /// Exit with an error message and "standard" failure exit code. | ||
Abort { message: Vec<u8> }, | ||||
Antoine Cezar
|
r46113 | /// A mercurial capability as not been implemented. | ||
Simon Sapin
|
r47174 | /// | ||
/// There is no error message printed in this case. | ||||
/// Instead, we exit with a specic status code and a wrapper script may | ||||
/// fallback to Python-based Mercurial. | ||||
Antoine Cezar
|
r46113 | Unimplemented, | ||
Antoine Cezar
|
r45592 | } | ||
Simon Sapin
|
r47163 | impl CommandError { | ||
Simon Sapin
|
r47174 | pub fn abort(message: impl AsRef<str>) -> Self { | ||
CommandError::Abort { | ||||
// TODO: bytes-based (instead of Unicode-based) formatting | ||||
// of error messages to handle non-UTF-8 filenames etc: | ||||
// https://www.mercurial-scm.org/wiki/EncodingStrategy#Mixing_output | ||||
message: utf8_to_local(message.as_ref()).into(), | ||||
Antoine Cezar
|
r45592 | } | ||
} | ||||
Simon Sapin
|
r47174 | } | ||
Antoine Cezar
|
r45920 | |||
Simon Sapin
|
r47174 | impl From<HgError> for CommandError { | ||
fn from(error: HgError) -> Self { | ||||
match error { | ||||
HgError::UnsupportedFeature(_) => CommandError::Unimplemented, | ||||
_ => CommandError::abort(error.to_string()), | ||||
Antoine Cezar
|
r45920 | } | ||
} | ||||
Antoine Cezar
|
r45592 | } | ||
impl From<UiError> for CommandError { | ||||
Simon Sapin
|
r47174 | fn from(_error: UiError) -> Self { | ||
// If we already failed writing to stdout or stderr, | ||||
// writing an error message to stderr about it would be likely to fail | ||||
// too. | ||||
CommandError::abort("") | ||||
Antoine Cezar
|
r45592 | } | ||
} | ||||
Antoine Cezar
|
r45922 | |||
Simon Sapin
|
r47215 | impl From<RepoError> for CommandError { | ||
fn from(error: RepoError) -> Self { | ||||
Simon Sapin
|
r47175 | match error { | ||
Simon Sapin
|
r47253 | RepoError::NotFound { at } => CommandError::Abort { | ||
Simon Sapin
|
r47175 | message: format_bytes!( | ||
b"no repository found in '{}' (.hg not found)!", | ||||
Simon Sapin
|
r47253 | get_bytes_from_path(at) | ||
Simon Sapin
|
r47175 | ), | ||
}, | ||||
Simon Sapin
|
r47215 | RepoError::ConfigParseError(error) => error.into(), | ||
RepoError::Other(error) => error.into(), | ||||
Antoine Cezar
|
r45922 | } | ||
} | ||||
} | ||||
Simon Sapin
|
r47165 | |||
Simon Sapin
|
r47213 | impl From<ConfigError> for CommandError { | ||
fn from(error: ConfigError) -> Self { | ||||
match error { | ||||
Simon Sapin
|
r47215 | ConfigError::Parse(error) => error.into(), | ||
Simon Sapin
|
r47213 | ConfigError::Other(error) => error.into(), | ||
} | ||||
} | ||||
} | ||||
Simon Sapin
|
r47215 | impl From<ConfigParseError> for CommandError { | ||
fn from(error: ConfigParseError) -> Self { | ||||
let ConfigParseError { | ||||
origin, | ||||
line, | ||||
bytes, | ||||
} = error; | ||||
let line_message = if let Some(line_number) = line { | ||||
format_bytes!(b" at line {}", line_number.to_string().into_bytes()) | ||||
} else { | ||||
Vec::new() | ||||
}; | ||||
CommandError::Abort { | ||||
message: format_bytes!( | ||||
b"config parse error in {}{}: '{}'", | ||||
Simon Sapin
|
r47249 | origin, | ||
Simon Sapin
|
r47215 | line_message, | ||
bytes | ||||
), | ||||
} | ||||
} | ||||
} | ||||
Simon Sapin
|
r47166 | impl From<(RevlogError, &str)> for CommandError { | ||
fn from((err, rev): (RevlogError, &str)) -> CommandError { | ||||
Simon Sapin
|
r47165 | match err { | ||
Simon Sapin
|
r47174 | RevlogError::InvalidRevision => CommandError::abort(format!( | ||
"invalid revision identifier {}", | ||||
rev | ||||
Simon Sapin
|
r47165 | )), | ||
Simon Sapin
|
r47174 | RevlogError::AmbiguousPrefix => CommandError::abort(format!( | ||
"ambiguous revision identifier {}", | ||||
rev | ||||
Simon Sapin
|
r47165 | )), | ||
Simon Sapin
|
r47174 | RevlogError::Other(error) => error.into(), | ||
Simon Sapin
|
r47165 | } | ||
} | ||||
} | ||||