cargo-fetcher 0.6.1

🎁 Experimental alternative to cargo fetch
Documentation
use anyhow::Error;
use cf::{mirror, Ctx};
use log::{error, info};
use std::time::Duration;

#[derive(structopt::StructOpt)]
pub struct Args {
    #[structopt(
        short,
        long = "max-stale",
        default_value = "1d",
        parse(try_from_str = parse_duration),
        long_help = "The duration for which the index will not be replaced after its most recent update.

Times may be specified with no suffix (default days), or one of:
* (s)econds
* (m)inutes
* (h)ours
* (d)ays

"
    )]
    max_stale: Duration,
}

pub fn cmd(ctx: Ctx, include_index: bool, args: Args) -> Result<(), Error> {
    rayon::join(
        || {
            if !include_index {
                return;
            }

            info!("mirroring crates.io index");
            match mirror::registry_index(&ctx, args.max_stale) {
                Ok(_) => info!("successfully mirrored crates.io index"),
                Err(e) => error!("failed to mirror crates.io index: {}", e),
            }
        },
        || match mirror::locked_crates(&ctx) {
            Ok(_) => {
                info!("finished uploading crates");
            }
            Err(e) => error!("failed to mirror crates: {}", e),
        },
    );

    Ok(())
}

fn parse_duration(src: &str) -> Result<Duration, Error> {
    let suffix_pos = src.find(char::is_alphabetic).unwrap_or_else(|| src.len());

    let num: u64 = src[..suffix_pos].parse()?;
    let suffix = if suffix_pos == src.len() {
        "d"
    } else {
        &src[suffix_pos..]
    };

    let duration = match suffix {
        "s" | "S" => Duration::from_secs(num),
        "m" | "M" => Duration::from_secs(num * 60),
        "h" | "H" => Duration::from_secs(num * 60 * 60),
        "d" | "D" => Duration::from_secs(num * 60 * 60 * 24),
        s => return Err(anyhow::anyhow!("unknown duration suffix '{}'", s)),
    };

    Ok(duration)
}