#![allow(missing_docs)]
#![cfg_attr(feature = "clippy", allow(redundant_closure))]
use std::{
error::Error as StdError,
io::{self, Write},
path::PathBuf,
};
use thiserror::Error;
use valico::json_schema::ValidationState;
pub type Result<T, E = Error> = std::result::Result<T, E>;
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum Error {
#[error("could not convert {0:?} to the equivalent Windows path")]
ConvertMountedPathToWindows(String),
#[error("data did not confirm to schema: {0}")]
DoesNotConformToSchema(String),
#[error("invalid interpolation syntax {0:?}")]
InterpolateInvalidSyntax(String),
#[error("undefined environment variable in interpolation {0:?}")]
InterpolateUndefinedVariable(String),
#[error("cannot parse without interpolating environment variables {0:?}")]
InterpolationDisabled(String),
#[error("invalid {wanted} {input:?}")]
InvalidValue { wanted: String, input: String },
#[error("I/O error")]
IoError(#[source] io::Error),
#[error("cannot parse env variable declaration {line:?}")]
ParseEnv { line: String },
#[error("not a Docker-compatible git URL {url:?}")]
ParseGitUrl {
url: String,
source: Option<Box<dyn StdError + Send + Sync + 'static>>,
},
#[error("error reading file {:?}", .path.display())]
ReadFile {
path: PathBuf,
source: Box<dyn StdError + Send + Sync + 'static>,
},
#[error("unsupported docker-compose.yml version {0:?}")]
UnsupportedVersion(String),
#[error("could not validate `docker-compose.yml` file")]
ValidationFailed {
source: Box<dyn StdError + Send + Sync + 'static>,
},
#[error("error writing to file {:?}", .path.display())]
WriteFile {
path: PathBuf,
source: Box<dyn StdError + Send + Sync + 'static>,
},
#[error(transparent)]
Yaml(#[from] serde_yaml::Error),
}
impl Error {
pub(crate) fn does_not_conform_to_schema(state: ValidationState) -> Error {
assert!(!state.is_strictly_valid());
let mut out: Vec<u8> = vec![];
for err in &state.errors {
write!(&mut out, "\n- validation error: {:?}", err)
.expect("cannot format validation error");
}
for url in &state.missing {
write!(&mut out, "\n- missing {}", url).expect("cannot format URL");
}
Error::DoesNotConformToSchema(String::from_utf8_lossy(&out).into_owned())
}
pub(crate) fn invalid_value<S1, S2>(wanted: S1, input: S2) -> Error
where
S1: Into<String>,
S2: Into<String>,
{
Error::InvalidValue {
wanted: wanted.into(),
input: input.into(),
}
}
pub(crate) fn parse_git_url<E>(url: String, source: E) -> Error
where
E: StdError + Send + Sync + 'static,
{
Error::ParseGitUrl {
url,
source: Some(Box::new(source)),
}
}
pub(crate) fn read_file<P, E>(path: P, source: E) -> Error
where
P: Into<PathBuf>,
E: StdError + Send + Sync + 'static,
{
Error::ReadFile {
path: path.into(),
source: Box::new(source),
}
}
pub(crate) fn validation_failed<E>(source: E) -> Error
where
E: StdError + Send + Sync + 'static,
{
Error::ValidationFailed {
source: Box::new(source),
}
}
pub(crate) fn write_file<P, E>(path: P, source: E) -> Error
where
P: Into<PathBuf>,
E: StdError + Send + Sync + 'static,
{
Error::WriteFile {
path: path.into(),
source: Box::new(source),
}
}
}