use std::io;
use std::error;
use std::fmt;
use std::string;
use std::path;
use base64::URL_SAFE_NO_PAD;
use {thrussh, thrussh_keys, libpijul, hyper, rustyline, term, toml, hex, base64, ring};
#[derive(Debug)]
pub enum Error {
ArgumentError(String, String),
NotInARepository,
InARepository(path::PathBuf),
IO(io::Error),
Rustyline(rustyline::error::ReadlineError),
Term(term::Error),
Repository(libpijul::error::Error),
UTF8(string::FromUtf8Error),
Hex(hex::FromHexError),
SSH(thrussh::Error),
SSHKeys(thrussh_keys::Error),
Hyper(hyper::error::Error),
TomlDe(toml::de::Error),
TomlSer(toml::ser::Error),
MetaDecoding,
MissingRemoteRepository,
PatchNotFound(String, libpijul::Hash),
InvalidPath(String),
WrongHash,
BranchAlreadyExists,
CannotDeleteCurrentBranch,
NoSuchBranch,
IsDirectory,
Base64(base64::DecodeError),
Ring(ring::error::Unspecified),
WillNotOverwriteKeyFile(path::PathBuf),
BranchDoesNotHavePatch { branch_name: String, patch: libpijul::Hash }
}
impl Error {
pub fn lacks_space(&self) -> bool {
match *self {
Error::Repository(ref r) => r.lacks_space(),
_ => false
}
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::ArgumentError(ref cmd, ref msg) =>
write!(f, "{}: an invalid argument have been provided\n\t{}", cmd, msg),
Error::NotInARepository => write!(f, "Not in a repository"),
Error::InARepository(ref p) => write!(f, "Error: inside repository {}", p.display()),
Error::IO(ref err) => write!(f, "IO error: {}", err),
Error::Rustyline(ref err) => write!(f, "Rustyline error: {}", err),
Error::Term(ref err) => write!(f, "Term error: {}", err),
Error::Repository(ref err) => write!(f, "Repository error: {}", err),
Error::SSH(ref err) => write!(f, "SSH: {}", err),
Error::SSHKeys(ref err) => write!(f, "SSH keys: {}", err),
Error::Hex(ref err) => write!(f, "Hex: {}", err),
Error::Hyper(ref err) => write!(f, "Hyper: {}", err),
Error::UTF8(ref err) => write!(f, "UTF8Error: {}", err),
Error::MetaDecoding => write!(f, "MetaDecoding"),
Error::MissingRemoteRepository => write!(f, "Missing remote repository"),
Error::PatchNotFound(ref path, ref hash) => {
write!(f, "Patch {:?} not found in {}", hash, path)
}
Error::InvalidPath(ref p) => write!(f, "Invalid path {}", p),
Error::WrongHash => write!(f, "Wrong hash"),
Error::BranchAlreadyExists => write!(f, "Branch already exists"),
Error::CannotDeleteCurrentBranch => write!(f, "Cannot delete current branch"),
Error::NoSuchBranch => write!(f, "No such branch"),
Error::IsDirectory => write!(f, "Is a directory"),
Error::TomlDe(ref e) => write!(f, "Toml de err: {}", e),
Error::TomlSer(ref e) => write!(f, "Toml ser err: {}", e),
Error::Base64(ref e) => write!(f, "Base64 err: {}", e),
Error::Ring(ref e) => write!(f, "*ring* err: {}", e),
Error::WillNotOverwriteKeyFile(ref e) => write!(f, "Will not overwrite key file: {:?}", e),
Error::BranchDoesNotHavePatch { ref branch_name, ref patch } => write!(f, "Branch {:?} doesn't have patch {:?}", branch_name, patch.to_base64(URL_SAFE_NO_PAD)),
}
}
}
impl error::Error for Error {
fn description(&self) -> &str {
match *self {
Error::ArgumentError(_, _) => "Invalid CLI argument",
Error::NotInARepository => "Not in a repository",
Error::InARepository(_) => "In a repository",
Error::IO(ref err) => err.description(),
Error::Rustyline(ref err) => err.description(),
Error::Term(ref err) => err.description(),
Error::Repository(ref err) => err.description(),
Error::SSH(ref err) => err.description(),
Error::SSHKeys(ref err) => err.description(),
Error::Hex(ref err) => err.description(),
Error::Hyper(ref err) => err.description(),
Error::UTF8(ref err) => err.description(),
Error::MetaDecoding => "Error in the decoding of metadata",
Error::MissingRemoteRepository => "Missing remote repository",
Error::PatchNotFound(_, _) => "Patch not found",
Error::InvalidPath(_) => "Invalid path",
Error::WrongHash => "Wrong hash",
Error::BranchAlreadyExists => "Branch already exists",
Error::CannotDeleteCurrentBranch => "Cannot delete current branch",
Error::NoSuchBranch => "No such branch",
Error::IsDirectory => "Is a directory",
Error::TomlDe(ref e) => e.description(),
Error::TomlSer(ref e) => e.description(),
Error::Base64(ref e) => e.description(),
Error::Ring(ref e) => e.description(),
Error::WillNotOverwriteKeyFile(_) => "Will not overwrite key file",
Error::BranchDoesNotHavePatch { .. } => "The branch doesn't the requested patch",
}
}
fn cause(&self) -> Option<&error::Error> {
match *self {
Error::ArgumentError(_, _) => None,
Error::IO(ref err) => Some(err),
Error::Rustyline(ref err) => Some(err),
Error::Term(ref err) => Some(err),
Error::Repository(ref err) => Some(err),
Error::NotInARepository => None,
Error::InARepository(_) => None,
Error::SSH(ref err) => Some(err),
Error::SSHKeys(ref err) => Some(err),
Error::Hex(ref err) => Some(err),
Error::Hyper(ref err) => Some(err),
Error::UTF8(ref err) => Some(err),
Error::MetaDecoding => None,
Error::MissingRemoteRepository => None,
Error::PatchNotFound(_, _) => None,
Error::InvalidPath(_) => None,
Error::WrongHash => None,
Error::BranchAlreadyExists => None,
Error::CannotDeleteCurrentBranch => None,
Error::NoSuchBranch => None,
Error::IsDirectory => None,
Error::TomlDe(ref err) => Some(err),
Error::TomlSer(ref err) => Some(err),
Error::Base64(ref err) => Some(err),
Error::Ring(ref err) => Some(err),
Error::WillNotOverwriteKeyFile(_) => None,
Error::BranchDoesNotHavePatch { .. } => None,
}
}
}
impl From<io::Error> for Error {
fn from(err: io::Error) -> Error {
Error::IO(err)
}
}
impl From<thrussh::Error> for Error {
fn from(err: thrussh::Error) -> Error {
Error::SSH(err)
}
}
impl From<thrussh_keys::Error> for Error {
fn from(err: thrussh_keys::Error) -> Error {
Error::SSHKeys(err)
}
}
impl From<thrussh::HandlerError<Error>> for Error {
fn from(err: thrussh::HandlerError<Error>) -> Error {
match err {
thrussh::HandlerError::Handler(e) => e,
thrussh::HandlerError::Error(e) => Error::SSH(e)
}
}
}
impl From<libpijul::error::Error> for Error {
fn from(err: libpijul::error::Error) -> Error {
Error::Repository(err)
}
}
impl From<string::FromUtf8Error> for Error {
fn from(err: string::FromUtf8Error) -> Error {
Error::UTF8(err)
}
}
impl From<hex::FromHexError> for Error {
fn from(err: hex::FromHexError) -> Error {
Error::Hex(err)
}
}
impl From<hyper::error::Error> for Error {
fn from(err: hyper::error::Error) -> Error {
Error::Hyper(err)
}
}
impl From<Error> for thrussh::HandlerError<Error> {
fn from(e: Error) -> thrussh::HandlerError<Error> {
thrussh::HandlerError::Handler(e)
}
}
impl From<rustyline::error::ReadlineError> for Error {
fn from(e: rustyline::error::ReadlineError) -> Error {
Error::Rustyline(e)
}
}
impl From<term::Error> for Error {
fn from(e: term::Error) -> Error {
Error::Term(e)
}
}
impl From<toml::de::Error> for Error {
fn from(e: toml::de::Error) -> Error {
Error::TomlDe(e)
}
}
impl From<toml::ser::Error> for Error {
fn from(e: toml::ser::Error) -> Error {
Error::TomlSer(e)
}
}
impl From<base64::DecodeError> for Error {
fn from(e: base64::DecodeError) -> Error {
Error::Base64(e)
}
}
impl From<ring::error::Unspecified> for Error {
fn from(e: ring::error::Unspecified) -> Error {
Error::Ring(e)
}
}