use std::{fs, path::PathBuf};
use clap::{Args, Parser, Subcommand};
use datahugger::{resolve, DownloadExt};
use indicatif::MultiProgress;
use reqwest::{
header::{HeaderMap, HeaderValue, AUTHORIZATION, USER_AGENT},
ClientBuilder,
};
use tracing_subscriber::{EnvFilter, FmtSubscriber};
#[derive(Parser)]
#[command(version, about, long_about = None)]
#[command(propagate_version = true)]
struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
enum Commands {
Download(DownloadArgs),
Inspect(InspectArgs),
}
#[derive(Args)]
struct InspectArgs {
url: String,
#[arg(short, long, default_value_t = 0)]
limit: usize,
}
#[derive(Args)]
struct DownloadArgs {
url: String,
#[arg(short, long, default_value_t = 0)]
limit: usize,
#[arg(short, long, value_name = "DIR")]
to: Option<PathBuf>,
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let subscriber = FmtSubscriber::builder()
.with_thread_ids(true)
.with_target(false)
.with_env_filter(EnvFilter::from_default_env())
.finish();
tracing::subscriber::set_global_default(subscriber)?;
let cli = Cli::parse();
match cli.command {
Commands::Download(args) => {
let url = &args.url;
let user_agent = format!("datahugger-cli/{}", env!("CARGO_PKG_VERSION"));
let mut headers = HeaderMap::new();
if let Ok(token) = std::env::var("GITHUB_TOKEN") {
headers.insert(
AUTHORIZATION,
HeaderValue::from_str(&format!("token {token}"))?,
);
}
if let Ok(token) = std::env::var("DRYAD_API_TOKEN") {
headers.insert(
AUTHORIZATION,
HeaderValue::from_str(&format!("Bearer {token}"))?,
);
}
headers.insert(USER_AGENT, HeaderValue::from_str(&user_agent)?);
let client = ClientBuilder::new()
.user_agent(user_agent)
.default_headers(headers)
.use_native_tls()
.build()?;
let repo = match resolve(url).await {
Ok(repo) => repo,
Err(err) => {
eprintln!("failed to resolve '{url}': {err:?}");
std::process::exit(1);
}
};
let mp = MultiProgress::new();
let dst = args.to.unwrap_or_else(|| PathBuf::from("."));
fs::create_dir_all(&dst)?;
let _ = repo
.download_with_validation(&client, dst, mp, args.limit)
.await
.map_err(|err| {
eprintln!("download failed: {err:?}");
std::process::exit(1);
});
}
Commands::Inspect(args) => {
let url = &args.url;
let user_agent = format!("datahugger-cli/{}", env!("CARGO_PKG_VERSION"));
let mut headers = HeaderMap::new();
if let Ok(token) = std::env::var("GITHUB_TOKEN") {
headers.insert(
AUTHORIZATION,
HeaderValue::from_str(&format!("token {token}"))?,
);
}
if let Ok(token) = std::env::var("DRYAD_API_TOKEN") {
headers.insert(
AUTHORIZATION,
HeaderValue::from_str(&format!("Bearer {token}"))?,
);
}
headers.insert(USER_AGENT, HeaderValue::from_str(&user_agent)?);
let client = ClientBuilder::new()
.user_agent(user_agent)
.default_headers(headers)
.use_native_tls()
.build()?;
let repo = match resolve(url).await {
Ok(repo) => repo,
Err(err) => {
eprintln!("failed to resolve '{url}': {err:?}");
std::process::exit(1);
}
};
let mp = MultiProgress::new();
let _ = repo
.print_meta(&client, mp, args.limit)
.await
.map_err(|err| {
eprintln!("inspect failed: {err:?}");
std::process::exit(1);
});
}
}
Ok(())
}