error.rs
83 lines
| 2.6 KiB
| application/rls-services+xml
|
RustLexer
|
r47165 | use crate::ui::utf8_to_local; | ||
|
r45592 | use crate::ui::UiError; | ||
|
r47175 | use format_bytes::format_bytes; | ||
use hg::errors::HgError; | ||||
use hg::repo::RepoFindError; | ||||
|
r47166 | use hg::revlog::revlog::RevlogError; | ||
|
r47175 | use hg::utils::files::get_bytes_from_path; | ||
|
r45592 | use std::convert::From; | ||
/// The kind of command error | ||||
|
r47174 | #[derive(Debug)] | ||
|
r47163 | pub enum CommandError { | ||
|
r47174 | /// Exit with an error message and "standard" failure exit code. | ||
Abort { message: Vec<u8> }, | ||||
|
r46113 | /// A mercurial capability as not been implemented. | ||
|
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. | ||||
|
r46113 | Unimplemented, | ||
|
r45592 | } | ||
|
r47163 | impl CommandError { | ||
|
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(), | ||||
|
r45592 | } | ||
} | ||||
|
r47174 | } | ||
|
r45920 | |||
|
r47174 | impl From<HgError> for CommandError { | ||
fn from(error: HgError) -> Self { | ||||
match error { | ||||
HgError::UnsupportedFeature(_) => CommandError::Unimplemented, | ||||
_ => CommandError::abort(error.to_string()), | ||||
|
r45920 | } | ||
} | ||||
|
r45592 | } | ||
impl From<UiError> for CommandError { | ||||
|
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("") | ||||
|
r45592 | } | ||
} | ||||
|
r45922 | |||
|
r47175 | impl From<RepoFindError> for CommandError { | ||
fn from(error: RepoFindError) -> Self { | ||||
match error { | ||||
RepoFindError::NotFoundInCurrentDirectoryOrAncestors { | ||||
current_directory, | ||||
} => CommandError::Abort { | ||||
message: format_bytes!( | ||||
b"no repository found in '{}' (.hg not found)!", | ||||
get_bytes_from_path(current_directory) | ||||
), | ||||
}, | ||||
RepoFindError::Other(error) => error.into(), | ||||
|
r45922 | } | ||
} | ||||
} | ||||
|
r47165 | |||
|
r47166 | impl From<(RevlogError, &str)> for CommandError { | ||
fn from((err, rev): (RevlogError, &str)) -> CommandError { | ||||
|
r47165 | match err { | ||
|
r47174 | RevlogError::InvalidRevision => CommandError::abort(format!( | ||
"invalid revision identifier {}", | ||||
rev | ||||
|
r47165 | )), | ||
|
r47174 | RevlogError::AmbiguousPrefix => CommandError::abort(format!( | ||
"ambiguous revision identifier {}", | ||||
rev | ||||
|
r47165 | )), | ||
|
r47174 | RevlogError::Other(error) => error.into(), | ||
|
r47165 | } | ||
} | ||||
} | ||||