#![allow(clippy::large_enum_variant)]
#![allow(clippy::default_trait_access)]
use snafu::{Backtrace, Snafu};
use std::path::PathBuf;
pub(crate) type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, Snafu)]
#[snafu(visibility(pub(crate)))]
pub(crate) enum Error {
#[snafu(display("Failed to clone repository: {}", source))]
CloneRepository {
source: tough::error::Error,
backtrace: Backtrace,
},
#[snafu(display("Failed to run {}: {}", command_str, source))]
CommandExec {
command_str: String,
source: std::io::Error,
backtrace: Backtrace,
},
#[snafu(display("Command {} failed with {}", command_str, status))]
CommandStatus {
command_str: String,
status: std::process::ExitStatus,
backtrace: Backtrace,
},
#[snafu(display("Command {} output is not valid UTF-8: {}", command_str, source))]
CommandUtf8 {
command_str: String,
source: std::string::FromUtf8Error,
backtrace: Backtrace,
},
#[snafu(display("Cannot determine current directory: {}", source))]
CurrentDir {
source: std::io::Error,
backtrace: Backtrace,
},
#[snafu(display("Date argument '{}' is invalid: {}", input, msg))]
DateArgInvalid { input: String, msg: &'static str },
#[snafu(display(
"Date argument had count '{}' that failed to parse as integer: {}",
input,
source
))]
DateArgCount {
input: String,
source: std::num::ParseIntError,
},
#[snafu(display("Failed to create directory '{}': {}", path.display(), source))]
DirCreate {
path: PathBuf,
source: std::io::Error,
backtrace: Backtrace,
},
#[snafu(display("Invalid delegation structure: {}", source))]
DelegationStructure {
source: tough::error::Error,
backtrace: Backtrace,
},
#[snafu(display("Couldn't find role '{}': {}", role, source))]
DelegateeNotFound {
role: String,
source: tough::error::Error,
backtrace: Backtrace,
},
#[snafu(display("The a file or directory already exists at '{}'", path.display()))]
DownloadOutdirExists { path: PathBuf, backtrace: Backtrace },
#[snafu(display(
"Failed to create a Repository Editor with root.json '{}': {}",
path.display(),
source
))]
EditorCreate {
path: PathBuf,
source: tough::error::Error,
},
#[snafu(display("Failed to create a RepositoryEditor from an existing repo with root.json '{}': {}", path.display(), source))]
EditorFromRepo {
path: PathBuf,
source: tough::error::Error,
backtrace: Backtrace,
},
#[snafu(display("Failed to open {}: {}", path.display(), source))]
FileOpen {
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 copy {} to {}: {}", source.file.path().display(), path.display(), source.error))]
FilePersist {
path: PathBuf,
source: tempfile::PersistError,
backtrace: Backtrace,
},
#[snafu(display("Failed to create temporary file in {}: {}", path.display(), source))]
FileTempCreate {
path: PathBuf,
source: std::io::Error,
backtrace: Backtrace,
},
#[snafu(display("Failed to write to {}: {}", path.display(), source))]
FileWrite {
path: PathBuf,
source: std::io::Error,
backtrace: Backtrace,
},
#[snafu(display("Failed to write to {}: {}", path.display(), source))]
FileWriteJson {
path: PathBuf,
source: serde_json::Error,
backtrace: Backtrace,
},
#[snafu(display("Failed to initialize global thread pool: {}", source))]
InitializeThreadPool {
source: rayon::ThreadPoolBuildError,
backtrace: Backtrace,
},
#[snafu(display("Invalid target name: {}", source))]
InvalidTargetName { source: tough::error::Error },
#[snafu(display("Failed to serialize to JSON: {}", source))]
JsonSerialization {
source: tough::schema::Error,
backtrace: Backtrace,
},
#[snafu(display("Duplicate key ID: {}", key_id))]
KeyDuplicate {
key_id: String,
backtrace: Backtrace,
},
#[snafu(display("Failed to calculate key ID: {}", source))]
KeyId {
#[snafu(backtrace)]
source: tough::schema::Error,
},
#[snafu(display("Unable to parse keypair: {}", source))]
KeyPairParse {
source: tough::error::Error,
backtrace: Backtrace,
},
#[snafu(display("Unable to parse keypair: {}", source))]
KeyPairFromKeySource {
source: Box<dyn std::error::Error + Send + Sync + 'static>,
backtrace: Backtrace,
},
#[snafu(display(
"Failed to symlink target data from '{}' to '{}': {}",
indir.display(),
outdir.display(),
source
))]
LinkTargets {
indir: PathBuf,
outdir: PathBuf,
source: tough::error::Error,
backtrace: Backtrace,
},
#[snafu(display("Unable to initialize logger: {}", source))]
Logger {
source: log::SetLoggerError,
backtrace: Backtrace,
},
#[snafu(display("Unable to load incoming metadata: {}", source))]
LoadMetadata {
source: tough::error::Error,
backtrace: Backtrace,
},
#[snafu(display("Metadata error: {}", source))]
Metadata {
source: tough::error::Error,
backtrace: Backtrace,
},
#[snafu(display("Missing: {}", what))]
Missing { what: String, backtrace: Backtrace },
#[snafu(display("Unable to determine file name from path: '{}'", path.display()))]
NoFileName { path: PathBuf, backtrace: Backtrace },
#[snafu(display("Failed to open file {}: {}", path.display(), source))]
OpenFile {
path: PathBuf,
source: std::io::Error,
backtrace: Backtrace,
},
#[snafu(display("Failed to open trusted root metadata file {}: {}", path.display(), source))]
OpenRoot {
path: PathBuf,
source: std::io::Error,
backtrace: Backtrace,
},
#[snafu(display("Path {} does not have a parent", path.display()))]
PathParent { path: PathBuf, backtrace: Backtrace },
#[snafu(display("Path {} is not valid UTF-8", path.display()))]
PathUtf8 { path: PathBuf, backtrace: Backtrace },
#[snafu(display("Failed to load repository: {}", source))]
RepoLoad {
source: tough::error::Error,
backtrace: Backtrace,
},
#[snafu(display("Failed to copy from response: {}", source))]
ReqwestCopy {
source: reqwest::Error,
backtrace: Backtrace,
},
#[snafu(display("Error making request: {}", source))]
ReqwestGet {
source: reqwest::Error,
backtrace: Backtrace,
},
#[snafu(display("Response '{}' from '{}': {}", get_status_code(source), url, source))]
BadResponse {
url: String,
source: reqwest::Error,
backtrace: Backtrace,
},
#[snafu(display("Failed to sign repository: {}", source))]
SignRepo {
source: tough::error::Error,
backtrace: Backtrace,
},
#[snafu(display(
"Root was signed with {} signatures; it must be signed with at least {}",
signature_count,
threshold,
))]
SignatureRoot {
threshold: u64,
signature_count: usize,
},
#[snafu(display("Failed to sign '{}': {}", path.display(), source))]
SignRoot {
path: PathBuf,
source: tough::error::Error,
backtrace: Backtrace,
},
#[snafu(display("Unable to create Target from path '{}': {}", path.display(), source))]
TargetFromPath {
path: PathBuf,
source: tough::schema::Error,
backtrace: Backtrace,
},
#[snafu(display("Failed to add targets from directory '{}': {}", dir.display(), source))]
TargetsFromDir {
dir: PathBuf,
source: tough::error::Error,
backtrace: Backtrace,
},
#[snafu(display("Target not found: {}", target))]
TargetNotFound {
target: String,
backtrace: Backtrace,
},
#[snafu(display("Failed to create temporary directory: {}", source))]
TempDir {
source: std::io::Error,
backtrace: Backtrace,
},
#[snafu(display("Unrecognized URL scheme \"{}\"", scheme))]
UnrecognizedScheme {
scheme: String,
backtrace: Backtrace,
},
#[snafu(display(
"Unstable root: '{}' role contains {} keys, threshold is {}",
role,
actual,
threshold
))]
UnstableRoot {
role: tough::schema::RoleType,
threshold: u64,
actual: usize,
},
#[snafu(display("Failed to parse URL \"{}\": {}", url, source))]
UrlParse {
url: String,
source: url::ParseError,
backtrace: Backtrace,
},
#[snafu(display("Version number overflow"))]
VersionOverflow { backtrace: Backtrace },
#[snafu(display("Version number is zero"))]
VersionZero { backtrace: Backtrace },
#[snafu(display("Failed to walk directory tree '{}': {}", directory.display(), source))]
WalkDir {
directory: PathBuf,
source: walkdir::Error,
backtrace: Backtrace,
},
#[snafu(display("Failed write: {}", source))]
WriteKeySource {
source: Box<dyn std::error::Error + Send + Sync + 'static>,
backtrace: Backtrace,
},
#[snafu(display("Failed writing repo data to disk at '{}': {}", directory.display(), source))]
WriteRepo {
directory: PathBuf,
source: tough::error::Error,
backtrace: Backtrace,
},
#[snafu(display("Unable to write roles: {:?}", roles))]
WriteRoles {
roles: Vec<String>,
source: tough::error::Error,
backtrace: Backtrace,
},
#[snafu(display("Failed writing target data to disk: {}", source))]
WriteTarget {
source: std::io::Error,
backtrace: Backtrace,
},
}
fn get_status_code(source: &reqwest::Error) -> String {
source
.status()
.as_ref()
.map_or("Unknown", reqwest::StatusCode::as_str)
.to_string()
}