use std::path::PathBuf;
use clap::Parser;
use radicle::{
identity::{project::ProjectName, Visibility},
node::policy::Scope,
prelude::RepoId,
};
use radicle_term::Interactive;
const ABOUT: &str = "Initialize a Radicle repository";
#[derive(Debug, Parser)]
#[command(about = ABOUT, disable_version_flag = true)]
pub struct Args {
pub(super) path: Option<PathBuf>,
#[arg(long)]
pub(super) name: Option<ProjectName>,
#[arg(long)]
pub(super) description: Option<String>,
#[arg(long = "default-branch")]
pub(super) branch: Option<String>,
#[arg(
long,
default_value_t = Scope::All,
value_name = "SCOPE",
value_parser = ScopeParser,
)]
pub(super) scope: Scope,
#[arg(long, conflicts_with = "public")]
private: bool,
#[arg(long, conflicts_with = "private")]
public: bool,
#[arg(long, value_name = "RID")]
pub(super) existing: Option<RepoId>,
#[arg(short = 'u', long)]
pub(super) set_upstream: bool,
#[arg(long)]
pub(super) setup_signing: bool,
#[arg(long)]
no_confirm: bool,
#[arg(long)]
no_seed: bool,
#[arg(short, long)]
pub(super) verbose: bool,
}
impl Args {
pub(super) fn interactive(&self) -> Interactive {
if self.no_confirm {
Interactive::No
} else {
Interactive::Yes
}
}
pub(super) fn visibility(&self) -> Option<Visibility> {
if self.private {
debug_assert!(!self.public, "BUG: `private` and `public` should conflict");
Some(Visibility::private([]))
} else if self.public {
Some(Visibility::Public)
} else {
None
}
}
pub(super) fn seed(&self) -> bool {
!self.no_seed
}
}
#[derive(Clone, Debug)]
struct ScopeParser;
impl clap::builder::TypedValueParser for ScopeParser {
type Value = Scope;
fn parse_ref(
&self,
cmd: &clap::Command,
arg: Option<&clap::Arg>,
value: &std::ffi::OsStr,
) -> Result<Self::Value, clap::Error> {
<Scope as std::str::FromStr>::from_str.parse_ref(cmd, arg, value)
}
fn possible_values(
&self,
) -> Option<Box<dyn Iterator<Item = clap::builder::PossibleValue> + '_>> {
use clap::builder::PossibleValue;
Some(Box::new(
[PossibleValue::new("all"), PossibleValue::new("followed")].into_iter(),
))
}
}
#[cfg(test)]
mod test {
use super::Args;
use clap::error::ErrorKind;
use clap::Parser;
#[test]
fn should_parse_rid_non_urn() {
let args = Args::try_parse_from(["init", "--existing", "z3Tr6bC7ctEg2EHmLvknUr29mEDLH"]);
assert!(args.is_ok())
}
#[test]
fn should_parse_rid_urn() {
let args =
Args::try_parse_from(["init", "--existing", "rad:z3Tr6bC7ctEg2EHmLvknUr29mEDLH"]);
assert!(args.is_ok())
}
#[test]
fn should_not_parse_rid_url() {
let err =
Args::try_parse_from(["init", "--existing", "rad://z3Tr6bC7ctEg2EHmLvknUr29mEDLH"])
.unwrap_err();
assert_eq!(err.kind(), ErrorKind::ValueValidation);
}
}