use exitfailure::ExitFailure;
use log::debug;
use std::collections::HashMap;
use std::path::PathBuf;
use std::time::Duration;
use structopt::StructOpt;
use tokio::sync::mpsc::channel;
use cached_path::{Cache, Error};
#[derive(Debug, StructOpt)]
#[structopt(
name = "cached-path",
about = "Get the cached path to a resource.",
setting = structopt::clap::AppSettings::ColoredHelp,
)]
struct Opt {
#[structopt()]
resource: Vec<String>,
#[structopt(long = "root", env = "RUST_CACHED_PATH_ROOT")]
root: Option<PathBuf>,
#[structopt(long = "timeout")]
timeout: Option<u64>,
#[structopt(long = "connect-timeout")]
connect_timeout: Option<u64>,
#[structopt(long = "max-retries", default_value = "3")]
max_retries: u32,
#[structopt(long = "max-backoff", default_value = "5000")]
max_backoff: u32,
#[structopt(long = "freshness-lifetime")]
freshness_lifetime: Option<u64>,
}
#[tokio::main]
async fn main() -> Result<(), ExitFailure> {
env_logger::init();
let opt = Opt::from_args();
debug!("{:?}", opt);
let cache = build_cache_from_opt(&opt).await?;
let (tx, mut rx) = channel(100);
for resource in &opt.resource {
let mut tx = tx.clone();
let resource = resource.clone();
let cache = cache.clone();
tokio::spawn(async move {
let result = cache.cached_path(&resource[..]).await;
if tx.send((resource, result)).await.is_err() {
std::process::exit(1);
};
});
}
drop(tx);
let mut cached_paths: HashMap<String, PathBuf> = HashMap::new();
while let Some((resource, result)) = rx.recv().await {
let path = result?;
cached_paths.insert(resource, path);
}
for resource in &opt.resource {
let path = cached_paths.get(&resource[..]).unwrap();
println!("{}", path.to_string_lossy());
}
Ok(())
}
async fn build_cache_from_opt(opt: &Opt) -> Result<Cache, Error> {
let mut cache_builder = Cache::builder();
if let Some(root) = &opt.root {
cache_builder = cache_builder.root(root.clone());
}
if let Some(timeout) = opt.timeout {
cache_builder = cache_builder.timeout(Duration::from_secs(timeout));
}
if let Some(connect_timeout) = opt.connect_timeout {
cache_builder = cache_builder.connect_timeout(Duration::from_secs(connect_timeout));
}
if let Some(freshness_lifetime) = opt.freshness_lifetime {
cache_builder = cache_builder.freshness_lifetime(freshness_lifetime);
}
cache_builder = cache_builder.max_retries(opt.max_retries);
cache_builder = cache_builder.max_backoff(opt.max_backoff);
cache_builder.build().await
}