use std::path::PathBuf;
use binstalk_downloader::download::{Download, PkgFmt};
use clap::Parser;
use detect_targets::get_desired_targets;
use miette::{IntoDiagnostic, Result, bail};
use tracing::{debug, info};
use crate::{
actions::Context,
download::{DownloadSource, client},
};
use super::CaddyArgs;
#[derive(Debug, Clone, Parser)]
pub struct DownloadArgs {
#[arg(value_name = "VERSION", default_value = "latest")]
pub version: String,
#[arg(long)]
pub path: PathBuf,
#[arg(long)]
pub url_only: bool,
#[arg(long)]
pub target: Option<String>,
}
pub async fn run(ctx: Context<CaddyArgs, DownloadArgs>) -> Result<()> {
let DownloadArgs {
version,
path,
url_only,
target,
} = ctx.args_sub;
let detected_targets = get_desired_targets(target.map(|t| vec![t]));
let detected_targets = detected_targets.get().await;
let client = client().await?;
let host = DownloadSource::Tools.host();
let mut url = None;
for target in detected_targets {
let try_url = host
.join(&format!(
"/caddy/{version}/caddy-{target}{ext}?bust={date}",
ext = if target.contains("windows") {
".exe"
} else {
""
},
date = chrono::Utc::now(),
))
.into_diagnostic()?;
debug!(url=%try_url, "trying URL");
if client
.remote_gettable(try_url.clone())
.await
.into_diagnostic()?
{
url.replace((target, try_url));
break;
}
}
let Some((target, url)) = url else {
bail!(
"no valid URL found for caddy {} on {}",
version,
detected_targets.join(", ")
);
};
if url_only {
println!("{}", url);
return Ok(());
}
if !path.exists() {
debug!(?path, "creating directory");
std::fs::create_dir_all(&path).into_diagnostic()?;
}
let fullpath = path.join(format!(
"caddy{}",
if target.contains("windows") {
".exe"
} else {
""
}
));
info!(%url, path=?fullpath, "downloading");
Download::new(client, url.clone())
.and_extract(PkgFmt::Bin, &fullpath)
.await
.into_diagnostic()?;
#[cfg(unix)]
if !target.contains("windows") {
use std::{
fs::{Permissions, set_permissions},
os::unix::fs::PermissionsExt,
};
info!(path=?fullpath, "marking as executable");
set_permissions(&fullpath, Permissions::from_mode(0o755)).into_diagnostic()?;
}
Ok(())
}