pub fn split_selector(selector: &str) -> Option<(&str, &str)> {
selector
.split_once('/')
.filter(|(p, s)| !p.is_empty() && !s.is_empty())
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ProjectMismatch {
pub flag: String,
pub selector: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Target {
Everything,
Project {
project: String,
},
Service {
service: String,
project: Option<String>,
},
}
pub fn resolve_target(
service: Option<&str>,
project: Option<&str>,
) -> Result<Target, ProjectMismatch> {
if let Some(selector) = service {
let (selector_project, service_name) = match split_selector(selector) {
Some((p, s)) => (Some(p), s),
None => (None, selector),
};
if let (Some(flag), Some(sel)) = (project, selector_project)
&& flag != sel
{
return Err(ProjectMismatch {
flag: flag.to_string(),
selector: sel.to_string(),
});
}
return Ok(Target::Service {
service: service_name.to_string(),
project: project.or(selector_project).map(str::to_string),
});
}
match project {
Some(project) => Ok(Target::Project {
project: project.to_string(),
}),
None => Ok(Target::Everything),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn none_resolves_to_everything() {
assert_eq!(resolve_target(None, None).unwrap(), Target::Everything);
}
#[test]
fn project_flag_resolves_to_project() {
assert_eq!(
resolve_target(None, Some("alpha")).unwrap(),
Target::Project {
project: "alpha".into()
}
);
}
#[test]
fn bare_service_leaves_project_unresolved() {
assert_eq!(
resolve_target(Some("worker"), None).unwrap(),
Target::Service {
service: "worker".into(),
project: None
}
);
}
#[test]
fn qualified_selector_splits() {
assert_eq!(
resolve_target(Some("alpha/worker"), None).unwrap(),
Target::Service {
service: "worker".into(),
project: Some("alpha".into())
}
);
}
#[test]
fn flag_and_matching_selector_agree() {
assert_eq!(
resolve_target(Some("alpha/worker"), Some("alpha")).unwrap(),
Target::Service {
service: "worker".into(),
project: Some("alpha".into())
}
);
}
#[test]
fn flag_conflicting_with_selector_is_a_mismatch() {
let err = resolve_target(Some("beta/worker"), Some("alpha")).unwrap_err();
assert_eq!(err.flag, "alpha");
assert_eq!(err.selector, "beta");
}
}