use thiserror::Error;
pub const MAX_REQUIRE_DEPTH: usize = 32;
#[non_exhaustive]
#[derive(Debug, Error)]
pub enum PackParseError {
#[error("unsupported pack schema_version {got:?}: this grex build only understands \"1\"")]
InvalidSchemaVersion {
got: String,
},
#[error(
"invalid pack name {got:?}: must match ^[a-z][a-z0-9-]*$ (lowercase letter first; then lowercase letters, digits, or hyphens)"
)]
InvalidName {
got: String,
},
#[error("YAML anchors/aliases are not supported (security policy)")]
YamlAliasRejected,
#[error(
"unknown top-level key {key:?}: only documented fields and `x-*` extensions are accepted"
)]
UnknownTopLevelKey {
key: String,
},
#[error(
"unknown action {key:?}: valid actions are symlink, env, mkdir, rmdir, require, when, exec"
)]
UnknownActionKey {
key: String,
},
#[error("empty action entry: each list item must have exactly one action key")]
EmptyActionEntry,
#[error(
"action entry has multiple keys {keys:?}: each list item must name exactly one action"
)]
MultipleActionKeys {
keys: Vec<String>,
},
#[error(
"require block must declare exactly one of `all_of`, `any_of`, `none_of` (got {count})"
)]
RequireCombinerArity {
count: usize,
},
#[error("invalid predicate entry: {detail}")]
InvalidPredicate {
detail: String,
},
#[error(
"exec args invariant violated (shell={shell}, cmd={cmd_present}, cmd_shell={cmd_shell_present}): \
when shell=false exactly `cmd` must be set; when shell=true exactly `cmd_shell` must be set"
)]
ExecCmdMutex {
shell: bool,
cmd_present: bool,
cmd_shell_present: bool,
},
#[error("require/when predicate nesting depth {depth} exceeds maximum {max}")]
RequireDepthExceeded {
depth: usize,
max: usize,
},
#[error("{path}: {source}")]
WithPath {
path: String,
#[source]
source: Box<PackParseError>,
},
#[error("yaml parse error: {0}")]
Inner(#[from] serde_yaml::Error),
}
impl PackParseError {
#[must_use]
pub fn with_source_path(self, path: impl Into<String>) -> Self {
match self {
Self::WithPath { source, .. } => Self::WithPath { path: path.into(), source },
other => Self::WithPath { path: path.into(), source: Box::new(other) },
}
}
}