#![allow(clippy::default_trait_access)]
use crate::schema::RoleType;
use chrono::{DateTime, Utc};
use snafu::{Backtrace, Snafu};
use std::io;
use std::path::PathBuf;
use url::Url;
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, Snafu)]
#[snafu(visibility = "pub(crate)")]
#[non_exhaustive]
pub enum Error {
#[snafu(display("Unable to canonicalize path '{}': {}", path.display(), source))]
AbsolutePath {
path: PathBuf,
source: std::io::Error,
backtrace: Backtrace,
},
#[snafu(display("Failed to create file at datastore path {}: {}", path.display(), source))]
DatastoreCreate {
path: PathBuf,
source: std::io::Error,
backtrace: Backtrace,
},
#[snafu(display("Failed to open file from datastore path {}: {}", path.display(), source))]
DatastoreOpen {
path: PathBuf,
source: std::io::Error,
backtrace: Backtrace,
},
#[snafu(display("Failed to remove file at datastore path {}: {}", path.display(), source))]
DatastoreRemove {
path: PathBuf,
source: std::io::Error,
backtrace: Backtrace,
},
#[snafu(display("Failed to serialize {} to JSON at datastore path {}: {}", what, path.display(), source))]
DatastoreSerialize {
what: String,
path: PathBuf,
source: serde_json::Error,
backtrace: Backtrace,
},
#[snafu(display("Failed to create directory '{}': {}", path.display(), source))]
DirCreate {
path: PathBuf,
source: std::io::Error,
backtrace: Backtrace,
},
#[snafu(display("{} metadata is expired", role))]
ExpiredMetadata {
role: RoleType,
backtrace: Backtrace,
},
#[snafu(display("Failed to read {}: {}", path.display(), source))]
FileRead {
path: PathBuf,
source: std::io::Error,
backtrace: Backtrace,
},
#[snafu(display("Failed to parse {}: {}", path.display(), source))]
FileParseJson {
path: PathBuf,
source: serde_json::Error,
backtrace: Backtrace,
},
#[snafu(display("Failed to write to {}: {}", path.display(), source))]
FileWrite {
path: PathBuf,
source: std::io::Error,
backtrace: Backtrace,
},
#[snafu(display(
"Hash mismatch for {}: calculated {}, expected {}",
context,
calculated,
expected,
))]
HashMismatch {
context: String,
calculated: String,
expected: String,
backtrace: Backtrace,
},
#[snafu(display("Failed to join \"{}\" to URL \"{}\": {}", path, url, source))]
JoinUrl {
path: String,
url: url::Url,
source: url::ParseError,
backtrace: Backtrace,
},
#[snafu(display("Unable to parse keypair: {}", source))]
KeyPairFromKeySource {
source: Box<dyn std::error::Error + Send + Sync + 'static>,
backtrace: Backtrace,
},
#[snafu(display("Private key rejected: {}", source))]
KeyRejected {
source: ring::error::KeyRejected,
backtrace: Backtrace,
},
#[snafu(display("Unable to match any of the provided keys with root.json"))]
KeysNotFoundInRoot { backtrace: Backtrace },
#[snafu(display("Unrecognized private key format"))]
KeyUnrecognized { backtrace: Backtrace },
#[snafu(display("Failed to create symlink at '{}': {}", path.display(), source))]
LinkCreate {
path: PathBuf,
source: io::Error,
backtrace: Backtrace,
},
#[snafu(display("Maximum size {} (specified by {}) exceeded", max_size, specifier))]
MaxSizeExceeded {
max_size: u64,
specifier: &'static str,
backtrace: Backtrace,
},
#[snafu(display("Maximum root updates {} exceeded", max_root_updates))]
MaxUpdatesExceeded {
max_root_updates: u64,
backtrace: Backtrace,
},
#[snafu(display("Meta for {:?} missing from {} metadata", file, role))]
MetaMissing {
file: &'static str,
role: RoleType,
backtrace: Backtrace,
},
#[snafu(display("Missing '{}' when building repo from RepositoryEditor", field))]
Missing { field: String, backtrace: Backtrace },
#[snafu(display("Unable to determine file name from path: '{}'", path.display()))]
NoFileName { path: PathBuf, backtrace: Backtrace },
#[snafu(display("Key for role '{}' doesn't exist in root.json", role))]
NoRoleKeysinRoot { role: String },
#[snafu(display(
"Found version {} of {} metadata when we had previously fetched version {}",
new_version,
role,
current_version
))]
OlderMetadata {
role: RoleType,
current_version: u64,
new_version: u64,
backtrace: Backtrace,
},
#[snafu(display("Failed to parse {} metadata: {}", role, source))]
ParseMetadata {
role: RoleType,
source: serde_json::Error,
backtrace: Backtrace,
},
#[snafu(display("Failed to parse trusted root metadata: {}", source))]
ParseTrustedMetadata {
source: serde_json::Error,
backtrace: Backtrace,
},
#[snafu(display("Failed to parse URL {:?}: {}", url, source))]
ParseUrl {
url: String,
source: url::ParseError,
backtrace: Backtrace,
},
#[snafu(display("Requested copy/link of '{}' which is not a file", path.display()))]
PathIsNotFile { path: PathBuf, backtrace: Backtrace },
#[snafu(display("Requested copy/link of '{}' which is not a repo target", path.display()))]
PathIsNotTarget { path: PathBuf, backtrace: Backtrace },
#[snafu(display("Path {} is not valid UTF-8", path.display()))]
PathUtf8 { path: PathBuf, backtrace: Backtrace },
#[snafu(display("Failed to serialize role '{}' for signing: {}", role, source))]
SerializeRole {
role: String,
source: serde_json::Error,
backtrace: Backtrace,
},
#[snafu(display("Failed to serialize signed role '{}': {}", role, source))]
SerializeSignedRole {
role: String,
source: serde_json::Error,
backtrace: Backtrace,
},
#[snafu(display("Failed to sign message"))]
Sign {
source: ring::error::Unspecified,
backtrace: Backtrace,
},
#[snafu(display("Unable to find signing keys for role '{}'", role))]
SigningKeysNotFound { role: String },
#[snafu(display(
"Tried to use role metadata with spec version '{}', version '{}' is supported",
given,
supported
))]
SpecVersion {
given: String,
supported: String,
backtrace: Backtrace,
},
#[snafu(display(
"System time stepped backward: system time '{}', last known time '{}'",
sys_time,
latest_known_time,
))]
SystemTimeSteppedBackward {
sys_time: DateTime<Utc>,
latest_known_time: DateTime<Utc>,
},
#[snafu(display("Unable to create Target from path '{}': {}", path.display(), source))]
TargetFromPath {
path: PathBuf,
source: crate::schema::Error,
backtrace: Backtrace,
},
#[snafu(display("Failed to fetch {}: {}", url, source))]
Transport {
url: url::Url,
source: Box<dyn std::error::Error + Send + Sync>,
backtrace: Backtrace,
},
#[snafu(display("Failed to verify {} metadata: {}", role, source))]
VerifyMetadata {
role: RoleType,
source: crate::schema::Error,
backtrace: Backtrace,
},
#[snafu(display("Failed to verify trusted root metadata: {}", source))]
VerifyTrustedMetadata {
source: crate::schema::Error,
backtrace: Backtrace,
},
#[snafu(display(
"{} metadata version mismatch: fetched {}, expected {}",
role,
fetched,
expected
))]
VersionMismatch {
role: RoleType,
fetched: u64,
expected: u64,
backtrace: Backtrace,
},
#[snafu(display("Error reading data from '{}': {}", url, source))]
CacheFileRead {
url: Url,
source: std::io::Error,
backtrace: Backtrace,
},
#[snafu(display("Error writing data to '{}': {}", path.display(), source))]
CacheFileWrite {
path: PathBuf,
source: std::io::Error,
backtrace: Backtrace,
},
#[snafu(display("Error creating the directory '{}': {}", path.display(), source))]
CacheDirectoryCreate {
path: PathBuf,
source: std::io::Error,
backtrace: Backtrace,
},
#[snafu(display("Error writing target file to '{}': {}", path.display(), source))]
CacheTargetWrite {
path: PathBuf,
source: std::io::Error,
backtrace: Backtrace,
},
#[snafu(display("The target '{}' was not found", target_name))]
CacheTargetMissing {
target_name: String,
backtrace: Backtrace,
},
#[snafu(display("Failed to walk directory tree '{}': {}", directory.display(), source))]
WalkDir {
directory: PathBuf,
source: walkdir::Error,
backtrace: Backtrace,
},
}
impl From<Error> for std::io::Error {
fn from(err: Error) -> Self {
Self::new(std::io::ErrorKind::Other, err)
}
}