use basis::Approver;
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Approve {
Always,
#[default]
Prompt,
Never,
}
pub trait PromptHost: Send + Sync {
fn can_ask(&self) -> bool;
fn approver(&self) -> Box<dyn Approver>;
}
pub fn validate_approval(approve: Approve, interactive: bool) -> Result<(), crate::Error> {
match approve {
Approve::Always | Approve::Never => Ok(()),
Approve::Prompt if interactive => Ok(()),
Approve::Prompt => Err(crate::Error::new(
"`Approve::Prompt` needs a process driving the task with a prompt host that can \
currently ask; use `Always` or `Never` for work nobody is attached to",
)),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn prompt_approval_needs_a_driver_that_can_ask() {
for approve in [Approve::Always, Approve::Never] {
assert!(
validate_approval(approve, false).is_ok(),
"{approve:?} asks nobody"
);
assert!(
validate_approval(approve, true).is_ok(),
"{approve:?} asks nobody"
);
}
assert!(
validate_approval(Approve::Prompt, true).is_ok(),
"a host that can ask is exactly what `Prompt` needs"
);
let refused = validate_approval(Approve::Prompt, false)
.expect_err("nobody able to ask means nobody to ask")
.to_string();
assert!(refused.contains("ask"), "{refused}");
}
}