##// END OF EJS Templates
debian: support a "chg-first" installation mechanism (hg is actually chg)...
debian: support a "chg-first" installation mechanism (hg is actually chg) This mechanism builds chg such that it looks for `hg` to be available at /usr/lib/mercurial/hg instead of in the $PATH as `hg`, and makes the `hg` in /usr/bin be a symlink to `chg`. It's important to note that the hg binary must continue to be named `hg`. If we wanted to instead place it at /usr/bin/pyhg or something similar, we would need to modify Mercurial to allow that basename. Failure to do so would break Mercurial's shell aliases that use `hg`, `chg`, or `$HG`. I don't know if we should ever have a setup like this be the default setup, but I'm willing to get more information on our experience with it for making such a determination. Actually making it the default might be rather involved, as we don't maintain the official debian packaging rules. Differential Revision: https://phab.mercurial-scm.org/D10020

File last commit:

r47335:5ce2aa7c default
r47374:90481550 default
Show More
error.rs
136 lines | 4.0 KiB | application/rls-services+xml | RustLexer
use crate::ui::utf8_to_local;
use crate::ui::UiError;
use crate::NoRepoInCwdError;
use format_bytes::format_bytes;
use hg::config::{ConfigError, ConfigParseError};
use hg::errors::HgError;
use hg::repo::RepoError;
use hg::revlog::revlog::RevlogError;
use hg::utils::files::get_bytes_from_path;
use std::convert::From;
/// The kind of command error
#[derive(Debug)]
pub enum CommandError {
/// Exit with an error message and "standard" failure exit code.
Abort { message: Vec<u8> },
/// A mercurial capability as not been implemented.
///
/// 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.
Unimplemented,
}
impl CommandError {
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(),
}
}
}
/// For now we don’t differenciate between invalid CLI args and valid for `hg`
/// but not supported yet by `rhg`.
impl From<clap::Error> for CommandError {
fn from(_: clap::Error) -> Self {
CommandError::Unimplemented
}
}
impl From<HgError> for CommandError {
fn from(error: HgError) -> Self {
match error {
HgError::UnsupportedFeature(_) => CommandError::Unimplemented,
_ => CommandError::abort(error.to_string()),
}
}
}
impl From<UiError> for CommandError {
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("")
}
}
impl From<RepoError> for CommandError {
fn from(error: RepoError) -> Self {
match error {
RepoError::NotFound { at } => CommandError::Abort {
message: format_bytes!(
b"repository {} not found",
get_bytes_from_path(at)
),
},
RepoError::ConfigParseError(error) => error.into(),
RepoError::Other(error) => error.into(),
}
}
}
impl<'a> From<&'a NoRepoInCwdError> for CommandError {
fn from(error: &'a NoRepoInCwdError) -> Self {
let NoRepoInCwdError { cwd } = error;
CommandError::Abort {
message: format_bytes!(
b"no repository found in '{}' (.hg not found)!",
get_bytes_from_path(cwd)
),
}
}
}
impl From<ConfigError> for CommandError {
fn from(error: ConfigError) -> Self {
match error {
ConfigError::Parse(error) => error.into(),
ConfigError::Other(error) => error.into(),
}
}
}
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 {}{}: '{}'",
origin,
line_message,
bytes
),
}
}
}
impl From<(RevlogError, &str)> for CommandError {
fn from((err, rev): (RevlogError, &str)) -> CommandError {
match err {
RevlogError::InvalidRevision => CommandError::abort(format!(
"invalid revision identifier {}",
rev
)),
RevlogError::AmbiguousPrefix => CommandError::abort(format!(
"ambiguous revision identifier {}",
rev
)),
RevlogError::Other(error) => error.into(),
}
}
}