use crate::paths;
pub const USAGE: &str = "\
usage: shep-deploy <verb> [args]
deploy <sheep> [--watch auto|manual] deploy one sheep, or set how it is watched
setup <sheep> take a sheep over
survey report where every registered sheep stands
on-remove lifecycle hook; shep runs this itself
Adopted as `deploy`, the same verbs run as `shep deploy <verb> [args]`, and
`shep deploy <sheep>` deploys one sheep directly. A sheep whose name is one of
the verbs above is reached with the verb spelled out: `shep deploy deploy survey`.";
#[derive(Debug, PartialEq, Eq)]
pub enum Route<'a> {
Poll,
OnRemove,
Survey,
Deploy(&'a str),
Setup(&'a str),
Watch { sheep: &'a str, mode: &'a str },
Usage,
}
pub fn route<'a>(args: &[&'a str]) -> Route<'a> {
let route = match args {
[] => Route::Poll,
["on-remove"] => Route::OnRemove,
["survey"] => Route::Survey,
["setup" | "deploy"] => Route::Usage,
["setup", sheep] => Route::Setup(sheep),
["deploy", sheep] => Route::Deploy(sheep),
["deploy", sheep, "--watch", mode] => Route::Watch { sheep, mode },
[sheep] => Route::Deploy(sheep),
[sheep, "--watch", mode] => Route::Watch { sheep, mode },
_ => Route::Usage,
};
match route {
Route::Setup(sheep) | Route::Deploy(sheep) if !paths::is_sheep_name(sheep) => Route::Usage,
Route::Watch { sheep, .. } if !paths::is_sheep_name(sheep) => Route::Usage,
named => named,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn a_bare_name_is_a_deploy_and_a_verb_still_wins() {
assert_eq!(route(&["koji"]), Route::Deploy("koji"));
assert_eq!(route(&["deploy", "koji"]), Route::Deploy("koji"));
assert_eq!(route(&["survey"]), Route::Survey);
assert_eq!(route(&["setup", "koji"]), Route::Setup("koji"));
assert_eq!(route(&["deploy", "survey"]), Route::Deploy("survey"));
assert_eq!(route(&[]), Route::Poll);
}
#[test]
fn on_remove_routes_to_its_own_hook() {
assert_eq!(route(&["on-remove"]), Route::OnRemove);
assert_eq!(route(&["deploy", "on-remove"]), Route::Deploy("on-remove"));
}
#[test]
fn a_verb_without_its_sheep_is_a_usage_error() {
assert_eq!(route(&["setup"]), Route::Usage);
assert_eq!(route(&["deploy"]), Route::Usage);
assert_eq!(route(&["deploy", "setup"]), Route::Deploy("setup"));
assert_eq!(route(&["deploy", "deploy"]), Route::Deploy("deploy"));
}
#[test]
fn a_sheep_name_that_is_a_path_is_refused() {
for name in ["/tmp/anywhere", "../sibling", "a/b", "", ".", ".."] {
assert_eq!(route(&[name]), Route::Usage, "bare: {name}");
assert_eq!(route(&["deploy", name]), Route::Usage, "deploy: {name}");
assert_eq!(route(&["setup", name]), Route::Usage, "setup: {name}");
assert_eq!(
route(&[name, "--watch", "auto"]),
Route::Usage,
"watch: {name}"
);
}
}
}