use std::path::PathBuf;
use clap::{Parser, Subcommand};
use gird::{github, Error};
use ureq::Response;
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
struct Config {
artifact: String,
#[arg(short, long)]
exclude: Vec<String>,
#[arg(short, long)]
output: Option<PathBuf>,
#[command(subcommand)]
source: Source,
}
#[derive(Subcommand, Debug)]
enum Source {
Github {
user: String,
repository: String,
},
}
fn default_filename(response: &Response, artifact: &str) -> String {
if let Some(dispostition) = response.header("Content-Disposition") {
if let Some((_, fname)) = dispostition.split_once("filename=") {
return String::from(fname);
}
}
let url = response.get_url().to_string();
let path = if let Some((before, _)) = response.get_url().split_once("?") {
before
} else {
url.as_str()
};
match path.rsplit_once('/') {
Some((_, after)) if !after.is_empty() => after.to_string(),
_ => match response.header("Content-Type") {
Some(ct) if ct == "application/gzip" => format!("{}.tar.gz", artifact),
Some(ct) if ct == "application/x-bzip" => format!("{}.tar.bz", artifact),
Some(ct) if ct == "application/x-bzip2" => format!("{}.tar.bz2", artifact),
Some(ct) if ct == "application/zip" => format!("{}.zip", artifact),
Some(ct) if ct == "application/vnd.rar" => format!("{}.rar", artifact),
Some(ct) if ct == "application/x-7z-compressed" => format!("{}.7z", artifact),
Some(ct) if ct == "application/java-archive" => format!("{}.jar", artifact),
_ => format!("{}.bin", artifact),
},
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = Config::parse();
let response = match config.source {
Source::Github { user, repository } => github::download_release(
config.artifact.as_str(),
config.exclude.iter(),
user.as_str(),
repository.as_str(),
)?,
};
let mut output = config.output.unwrap_or_else(|| {
std::env::current_dir().expect("Cannot determine current working directory")
});
if output.is_dir() {
output.push(default_filename(&response, &config.artifact));
}
std::fs::create_dir_all(
output
.parent()
.ok_or_else(|| Error::Misc("Unable to determine the output directory".into()))?,
)?;
let mut outfile = std::fs::File::create(&output)?;
std::io::copy(&mut response.into_reader(), &mut outfile)?;
println!("Saved {}", output.to_string_lossy());
Ok(())
}