use std::path::Path;
use anyhow::Context as _;
use decdn_client::uri::{DecdnUri, UriTarget};
use decdn_common::cli::GetArgs;
pub async fn get(args: &GetArgs, config_path: Option<&Path>) -> anyhow::Result<()> {
let uri = parse_and_check(args)?;
match uri.target {
UriTarget::Blob => super::fetch::fetch(args, &uri, config_path).await,
_ => super::bundle_pull::bundle_pull(args, &uri, config_path).await,
}
}
fn parse_and_check(args: &GetArgs) -> anyhow::Result<DecdnUri> {
let uri: DecdnUri = args
.uri
.parse()
.with_context(|| format!("parse URI {:?}", args.uri))?;
match &uri.target {
UriTarget::Blob => {
let given = bundle_flags_given(args);
anyhow::ensure!(
given.is_empty(),
"{} only apply to a bundle URI (`decdn:<hash>/`), not a blob URI",
given.join(", ")
);
return Ok(uri);
}
UriTarget::BundleEntry(_) => {
let given = entry_filters_given(args);
anyhow::ensure!(
given.is_empty(),
"{} do not apply to an entry URI: the URI already names one entry",
given.join(", ")
);
}
_ => {}
}
anyhow::ensure!(
args.output != Path::new("-"),
"`-o -` (stdout) takes a blob URI (`decdn:<hash>`); a bundle needs an output directory"
);
Ok(uri)
}
fn bundle_flags_given(args: &GetArgs) -> Vec<&'static str> {
let mut given = entry_filters_given(args);
for (set, name) in [
(args.jobs.is_some(), "--jobs"),
(args.max_lane_streams.is_some(), "--max-lane-streams"),
(args.overwrite, "--overwrite"),
(args.dry_run, "--dry-run"),
(args.json, "--json"),
] {
if set {
given.push(name);
}
}
given
}
fn entry_filters_given(args: &GetArgs) -> Vec<&'static str> {
[
(!args.include.is_empty(), "--include"),
(!args.exclude.is_empty(), "--exclude"),
(args.select, "--select"),
]
.into_iter()
.filter_map(|(set, name)| set.then_some(name))
.collect()
}
#[cfg(test)]
#[allow(
clippy::unwrap_used,
clippy::expect_used,
clippy::indexing_slicing,
clippy::panic
)]
mod tests;