use std::{path::PathBuf, str::FromStr};
use clap::{Parser, ValueEnum};
use log::debug;
use serde::Serialize;
use simplelog::{ColorChoice, Config, LevelFilter, TermLogger, TerminalMode};
use voa_core::{
Voa,
identifiers::{Context, CustomContext, IdentifierString, Mode, Os, Purpose, Role, Technology},
};
#[derive(Debug, Parser)]
#[command(about = "List VOA entries", version)]
struct Cli {
#[arg(long)]
pub os_id: IdentifierString,
#[arg(long)]
pub os_version_id: Option<IdentifierString>,
#[arg(long)]
pub os_variant_id: Option<IdentifierString>,
#[arg(long)]
pub os_image_id: Option<IdentifierString>,
#[arg(long)]
pub os_image_version: Option<IdentifierString>,
#[arg(long)]
pub role: String,
#[arg(long)]
#[clap(default_value = "artifact-verifier")]
pub mode: ModeArg,
#[arg(long)]
pub custom_context: Option<IdentifierString>,
}
#[derive(Clone, Debug, ValueEnum)]
enum ModeArg {
ArtifactVerifier,
TrustAnchor,
}
impl From<ModeArg> for Mode {
fn from(mode_arg: ModeArg) -> Self {
match mode_arg {
ModeArg::ArtifactVerifier => Mode::ArtifactVerifier,
ModeArg::TrustAnchor => Mode::TrustAnchor,
}
}
}
#[derive(Debug, Serialize)]
struct Verifier {
load_path: PathBuf,
verifier: PathBuf,
}
fn init_logger() {
if TermLogger::init(
LevelFilter::Debug,
Config::default(),
TerminalMode::Stderr,
ColorChoice::Auto,
)
.is_err()
{
debug!("Not initializing another logger, as one is initialized already.");
}
}
fn main() -> anyhow::Result<()> {
init_logger();
let cli = Cli::parse();
let os = Os::new(
cli.os_id,
cli.os_version_id,
cli.os_variant_id,
cli.os_image_id,
cli.os_image_version,
);
let purpose = Purpose::new(Role::from_str(&cli.role)?, cli.mode.into());
let context = if let Some(custom_context) = &cli.custom_context {
CustomContext::new(custom_context.clone()).into()
} else {
Context::Default
};
let technology = Technology::Openpgp;
let voa = Voa::new();
let verifiers = voa.lookup(os, purpose, context, technology);
let out: Vec<Verifier> = verifiers
.values()
.flat_map(|vec| vec.iter())
.map(|v| Verifier {
load_path: v.voa_location().load_path().path().into(),
verifier: v.canonicalized().into(),
})
.collect();
let json = serde_json::to_string(&out)?;
println!("{json}");
Ok(())
}