use clap::{Args, Subcommand, ValueEnum};
use objects::object::VisibilityTier;
#[derive(Clone, Debug, Subcommand)]
pub enum VisibilityCommands {
Set(VisibilitySetArgs),
Promote(VisibilityPromoteArgs),
Show(VisibilityShowArgs),
List(VisibilityListArgs),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, ValueEnum)]
#[value(rename_all = "kebab-case")]
pub enum VisibilityTierArg {
Public,
Internal,
TeamScoped,
Restricted,
Private,
}
impl VisibilityTierArg {
pub fn into_tier(self, label: Option<String>) -> Result<VisibilityTier, String> {
match self {
VisibilityTierArg::Public => Ok(VisibilityTier::Public),
VisibilityTierArg::Internal => Ok(VisibilityTier::Internal),
VisibilityTierArg::TeamScoped => match label {
Some(team_id) if !team_id.trim().is_empty() => {
Ok(VisibilityTier::TeamScoped { team_id })
}
_ => Err("the team-scoped tier requires --label <team-id>".to_string()),
},
VisibilityTierArg::Restricted => match label {
Some(scope_label) if !scope_label.trim().is_empty() => {
Ok(VisibilityTier::Restricted { scope_label })
}
_ => Err("the restricted tier requires --label <scope-label>".to_string()),
},
VisibilityTierArg::Private => match label {
Some(scope_label) if !scope_label.trim().is_empty() => {
Ok(VisibilityTier::Private { scope_label })
}
_ => Err("the private tier requires --label <scope-label>".to_string()),
},
}
}
}
#[derive(Clone, Debug, Args)]
pub struct VisibilitySetArgs {
pub state: String,
#[arg(long, value_enum)]
pub tier: VisibilityTierArg,
#[arg(long)]
pub label: Option<String>,
}
#[derive(Clone, Debug, Args)]
pub struct VisibilityPromoteArgs {
pub state: String,
#[arg(long, value_enum)]
pub tier: VisibilityTierArg,
#[arg(long)]
pub label: Option<String>,
}
#[derive(Clone, Debug, Args)]
pub struct VisibilityShowArgs {
pub state: String,
}
#[derive(Clone, Debug, Args)]
pub struct VisibilityListArgs {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn restricted_requires_non_empty_label() {
assert_eq!(
VisibilityTierArg::Restricted.into_tier(Some("legal".to_string())),
Ok(VisibilityTier::Restricted {
scope_label: "legal".to_string()
})
);
assert!(VisibilityTierArg::Restricted.into_tier(None).is_err());
assert!(
VisibilityTierArg::Restricted
.into_tier(Some(" ".to_string()))
.is_err()
);
}
#[test]
fn private_maps_to_private_tier_with_non_empty_label() {
assert_eq!(
VisibilityTierArg::Private.into_tier(Some("embargo-x".to_string())),
Ok(VisibilityTier::Private {
scope_label: "embargo-x".to_string()
})
);
}
#[test]
fn private_requires_a_label() {
assert_eq!(
VisibilityTierArg::Private.into_tier(None),
Err("the private tier requires --label <scope-label>".to_string())
);
assert_eq!(
VisibilityTierArg::Private.into_tier(Some(" ".to_string())),
Err("the private tier requires --label <scope-label>".to_string())
);
}
#[test]
fn private_flows_through_the_317_monotonicity_check_as_rank_4() {
let private = VisibilityTier::Private {
scope_label: "embargo-x".to_string(),
};
assert_eq!(private.restrictiveness_rank(), 4);
assert!(VisibilityTier::Internal.is_strictly_less_restrictive_than(&private));
assert!(VisibilityTier::Public.is_strictly_less_restrictive_than(&private));
assert!(!private.is_strictly_less_restrictive_than(&VisibilityTier::Internal));
}
}