libojo/
error.rs

1// Copyright 2018-2019 Joe Neeman.
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8//
9// See the LICENSE-APACHE or LICENSE-MIT files at the top-level directory
10// of this distribution.
11
12// Allow missing docs in this module, for now, because we need to think more about the types of
13// errors we're exposing.
14#![allow(missing_docs)]
15
16use serde_yaml;
17use std::ffi::OsString;
18use std::path::PathBuf;
19use std::{self, fmt, io};
20
21use crate::{NodeId, PatchId};
22
23#[derive(Debug)]
24pub enum PatchIdError {
25    Base64Decode(base64::DecodeError),
26    InvalidLength(usize),
27    Collision(crate::PatchId),
28}
29
30impl From<base64::DecodeError> for PatchIdError {
31    fn from(e: base64::DecodeError) -> PatchIdError {
32        PatchIdError::Base64Decode(e)
33    }
34}
35
36impl fmt::Display for PatchIdError {
37    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38        use self::PatchIdError::*;
39
40        match self {
41            Base64Decode(e) => e.fmt(f),
42            InvalidLength(n) => write!(f, "Found the wrong number of bytes: {}", n),
43            Collision(p) => write!(
44                f,
45                "Encountered a collision between patch hashes: {}",
46                p.to_base64()
47            ),
48        }
49    }
50}
51
52impl std::error::Error for PatchIdError {
53    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
54        use self::PatchIdError::*;
55
56        match self {
57            Base64Decode(e) => Some(e),
58            _ => None,
59        }
60    }
61}
62
63#[derive(Debug)]
64pub enum Error {
65    BranchExists(String),
66    CurrentBranch(String),
67    DbCorruption,
68    Encoding(std::string::FromUtf8Error),
69    IdMismatch(PatchId, PatchId),
70    Io(io::Error, String),
71    MissingDep(PatchId),
72    NoFilename(PathBuf),
73    NoParent(PathBuf),
74    NonUtfFilename(OsString),
75    NotOrdered,
76    PatchId(PatchIdError),
77    RepoExists(PathBuf),
78    RepoNotFound(PathBuf),
79    Serde(serde_yaml::Error),
80    UnknownBranch(String),
81    UnknownNode(NodeId),
82    UnknownPatch(PatchId),
83}
84
85impl fmt::Display for Error {
86    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87        match self {
88            Error::BranchExists(b) => write!(f, "The branch \"{}\" already exists", b),
89            Error::CurrentBranch(b) => write!(f, "\"{}\" is the current branch", b),
90            Error::DbCorruption => write!(f, "Found corruption in the database"),
91            Error::Encoding(e) => e.fmt(f),
92            Error::IdMismatch(actual, expected) => write!(
93                f,
94                "Expected {}, found {}",
95                expected.to_base64(),
96                actual.to_base64()
97            ),
98            Error::Io(e, msg) => write!(f, "I/O error: {}. Details: {}", msg, e),
99            Error::MissingDep(id) => write!(f, "Missing a dependency: {}", id.to_base64()),
100            Error::NoFilename(p) => write!(f, "This path didn't end in a filename: {:?}", p),
101            Error::NoParent(p) => write!(f, "I could not find the parent directory of: {:?}", p),
102            Error::NonUtfFilename(p) => {
103                write!(f, "This filename couldn't be converted to UTF-8: {:?}", p)
104            }
105            Error::NotOrdered => write!(f, "The data does not represent a totally ordered file"),
106            Error::PatchId(e) => write!(f, "Found a broken PatchId\n\tcaused by: {}", e),
107            Error::RepoExists(p) => write!(f, "There is already a repository in {:?}", p),
108            Error::RepoNotFound(p) => write!(
109                f,
110                "I could not find a repository tracking this path: {:?}",
111                p
112            ),
113            Error::Serde(e) => e.fmt(f),
114            Error::UnknownBranch(b) => write!(f, "There is no branch named {:?}", b),
115            Error::UnknownNode(n) => write!(f, "There is no node with id {:?}", n),
116            Error::UnknownPatch(p) => write!(f, "There is no patch with hash {:?}", p.to_base64()),
117        }
118    }
119}
120
121impl std::error::Error for Error {
122    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
123        match self {
124            Error::Encoding(e) => Some(e),
125            Error::Io(e, _) => Some(e),
126            Error::PatchId(e) => Some(e),
127            Error::Serde(e) => Some(e),
128            _ => None,
129        }
130    }
131}
132
133impl From<PatchIdError> for Error {
134    fn from(e: PatchIdError) -> Error {
135        Error::PatchId(e)
136    }
137}
138
139impl From<io::Error> for Error {
140    fn from(e: io::Error) -> Error {
141        Error::Io(e, "".to_owned())
142    }
143}
144
145impl From<(io::Error, &'static str)> for Error {
146    fn from((e, msg): (io::Error, &'static str)) -> Error {
147        Error::Io(e, msg.to_owned())
148    }
149}
150
151impl From<serde_yaml::Error> for Error {
152    fn from(e: serde_yaml::Error) -> Error {
153        Error::Serde(e)
154    }
155}
156
157impl From<std::string::FromUtf8Error> for Error {
158    fn from(e: std::string::FromUtf8Error) -> Error {
159        Error::Encoding(e)
160    }
161}