mod auth;
mod cache;
mod commands;
mod render;
#[allow(dead_code)]
mod wrappers;
use std::path::PathBuf;
use clap::{Parser, Subcommand};
#[derive(Parser)]
#[command(name = "cleanlib", version, about, long_about = None, arg_required_else_help = true)]
struct Cli {
#[command(subcommand)]
command: Option<Command>,
}
#[derive(Subcommand)]
enum Command {
Status,
Config {
#[command(subcommand)]
action: ConfigAction,
},
Login {
#[arg(long)]
api_key: String,
#[arg(long)]
keyring: bool,
},
Logout {
#[arg(long)]
keyring: bool,
},
#[command(name = "risk-accept")]
RiskAccept {
#[arg(long)]
package: String,
#[arg(long)]
version: String,
#[arg(long)]
justification: String,
#[arg(long)]
proposed_by: Option<String>,
#[arg(long)]
write_to: Option<PathBuf>,
},
Verdict {
ecosystem: String,
package: String,
version: String,
#[arg(long, default_value = "text")]
output: String,
},
Scan {
#[arg(long)]
ecosystem: String,
#[arg(long)]
packages: PathBuf,
#[arg(long, default_value = "text")]
output: String,
},
Audit {
#[arg(long)]
since: Option<String>,
#[arg(long)]
decision: Option<String>,
#[arg(long)]
ecosystem: Option<String>,
#[arg(long, default_value = "text")]
output: String,
},
Policy {
#[command(subcommand)]
action: PolicyAction,
},
Fetch {
ecosystem: String,
package: String,
version: String,
#[arg(long)]
output: Option<PathBuf>,
},
Npm {
#[arg(trailing_var_arg = true, allow_hyphen_values = true)]
args: Vec<String>,
},
Pip {
#[arg(trailing_var_arg = true, allow_hyphen_values = true)]
args: Vec<String>,
},
Cargo {
#[arg(trailing_var_arg = true, allow_hyphen_values = true)]
args: Vec<String>,
},
Go {
#[arg(trailing_var_arg = true, allow_hyphen_values = true)]
args: Vec<String>,
},
}
#[derive(Subcommand)]
enum PolicyAction {
Preview {
#[arg(long)]
policy: PathBuf,
#[arg(long)]
packages: PathBuf,
#[arg(long)]
ecosystem: String,
#[arg(long, default_value = "text")]
output: String,
},
}
#[derive(Subcommand)]
enum ConfigAction {
Init {
#[arg(long, value_delimiter = ',', default_values_t = vec!["npm".to_string(), "pypi".to_string(), "go".to_string()])]
ecosystem: Vec<String>,
#[arg(long)]
scope: Option<String>,
#[arg(long)]
write: bool,
#[arg(long)]
write_to: Option<PathBuf>,
#[arg(long)]
inline_token: bool,
#[arg(long)]
force: bool,
},
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let cli = Cli::parse();
match cli.command {
Some(Command::Status) => commands::status::run(),
Some(Command::Config { action }) => match action {
ConfigAction::Init {
ecosystem,
scope,
write,
write_to,
inline_token,
force,
} => commands::config_init::run(ecosystem, scope, write, write_to, inline_token, force),
},
Some(Command::Login { api_key, keyring }) => commands::login::run(api_key, keyring),
Some(Command::Logout { keyring }) => commands::logout::run(keyring),
Some(Command::RiskAccept {
package,
version,
justification,
proposed_by,
write_to,
}) => commands::risk_accept::run(package, version, justification, proposed_by, write_to),
Some(Command::Verdict {
ecosystem,
package,
version,
output,
}) => commands::verdict::run(ecosystem, package, version, output).await,
Some(Command::Scan {
ecosystem,
packages,
output,
}) => commands::scan::run(ecosystem, packages, output).await,
Some(Command::Audit {
since,
decision,
ecosystem,
output,
}) => commands::audit::run(since, decision, ecosystem, output).await,
Some(Command::Policy { action }) => match action {
PolicyAction::Preview {
policy,
packages,
ecosystem,
output,
} => commands::policy::preview(policy, packages, ecosystem, output).await,
},
Some(Command::Fetch {
ecosystem,
package,
version,
output,
}) => commands::fetch::run(ecosystem, package, version, output).await,
Some(Command::Npm { args }) => commands::wrap::run("npm", args).await,
Some(Command::Pip { args }) => commands::wrap::run("pip", args).await,
Some(Command::Cargo { args }) => commands::wrap::run("cargo", args).await,
Some(Command::Go { args }) => commands::wrap::run("go", args).await,
None => Ok(()),
}
}