use std::collections::HashMap;
use std::io::{BufRead, BufReader};
use std::ops::Deref;
use std::panic::panic_any;
use std::process::Stdio;
use std::sync::{Arc, Mutex};
use std::time::{Duration, SystemTime};
use std::{fs::File, io, panic, path::PathBuf};

use cargo_metadata::{Metadata, Package};
use clap::{CommandFactory, Parser};
use console::Term;
use errors::{
    AggregateCriteriaDescription, AggregateCriteriaDescriptionMismatchError,
    AggregateCriteriaImplies, AggregateError, AggregateErrors, AggregateImpliesMismatchError,
    AuditAsError, AuditAsErrors, CacheAcquireError, CertifyError, CratePolicyError,
    CratePolicyErrors, FetchAuditError, LoadTomlError, NeedsAuditAsErrors,
    NeedsPolicyVersionErrors, PackageError, ShouldntBeAuditAsErrors, TomlParseError,
    UnusedAuditAsErrors, UnusedPolicyVersionErrors, UserInfoError,
};
use format::{CriteriaName, CriteriaStr, PackageName, Policy, PolicyEntry, SortedSet, VetVersion};
use futures_util::future::{join_all, try_join_all};
use indicatif::ProgressDrawTarget;
use lazy_static::lazy_static;
use miette::{miette, Context, Diagnostic, IntoDiagnostic, SourceOffset};
use network::Network;
use out::{progress_bar, IncProgressOnDrop};
use reqwest::Url;
use serde::de::Deserialize;
use serialization::spanned::Spanned;
use storage::fetch_registry;
use thiserror::Error;
use tracing::{error, info, trace, warn};

use crate::cli::*;
use crate::criteria::CriteriaMapper;
use crate::errors::{
    CommandError, DownloadError, FetchAndDiffError, FetchError, MetadataAcquireError, SourceFile,
};
use crate::format::{
    AuditEntry, AuditKind, AuditsFile, ConfigFile, CratesUserId, CriteriaEntry, ExemptedDependency,
    FetchCommand, MetaConfig, MetaConfigInstance, PackageStr, SortedMap, StoreInfo, TrustEntry,
    WildcardEntry,
};
use crate::git_tool::Pager;
use crate::out::{indeterminate_spinner, Out, StderrLogWriter, MULTIPROGRESS};
use crate::storage::{Cache, Store};

mod cli;
mod criteria;
pub mod errors;
mod flock;
pub mod format;
mod git_tool;
pub mod network;
mod out;
pub mod resolver;
mod serialization;
pub mod storage;
mod string_format;
#[cfg(test)]
mod tests;

/// Absolutely All The Global Configurations
pub struct Config {
    /// Cargo.toml `metadata.vet`
    pub metacfg: MetaConfig,
    /// `cargo metadata`
    pub metadata: Metadata,
    /// Freestanding configuration values
    _rest: PartialConfig,
}

/// Configuration vars that are available in a free-standing situation
/// (no actual cargo-vet instance to load/query).
pub struct PartialConfig {
    /// Details of the CLI invocation (args)
    pub cli: Cli,
    /// The date and time to use as the current time.
    pub now: chrono::DateTime<chrono::Utc>,
    /// Path to the cache directory we're using
    pub cache_dir: PathBuf,
    /// Whether we should mock the global cache (for unit testing)
    pub mock_cache: bool,
}

impl PartialConfig {
    pub fn today(&self) -> chrono::NaiveDate {
        self.now.date_naive()
    }
}

// Makes it a bit easier to have both a "partial" and "full" config
impl Deref for Config {
    type Target = PartialConfig;
    fn deref(&self) -> &Self::Target {
        &self._rest
    }
}

pub trait PackageExt {
    fn is_third_party(&self, policy: &Policy) -> bool;
    fn is_crates_io(&self) -> bool;
    fn policy_entry<'a>(&self, policy: &'a Policy) -> Option<&'a PolicyEntry>;
    fn git_rev(&self) -> Option<String>;
    fn vet_version(&self) -> VetVersion;
}

impl PackageExt for Package {
    fn is_third_party(&self, policy: &Policy) -> bool {
        let forced_third_party = self
            .policy_entry(policy)
            .and_then(|policy| policy.audit_as_crates_io)
            .unwrap_or(false);

        forced_third_party || self.is_crates_io()
    }

    fn is_crates_io(&self) -> bool {
        self.source
            .as_ref()
            .map(|s| s.is_crates_io())
            .unwrap_or(false)
    }

    fn policy_entry<'a>(&self, policy: &'a Policy) -> Option<&'a PolicyEntry> {
        policy.get(&self.name, &self.vet_version())
    }

    fn git_rev(&self) -> Option<String> {
        self.source.as_ref().and_then(|s| {
            let git_source = s.repr.strip_prefix("git+")?;
            let source_url = Url::parse(git_source).ok()?;
            Some(source_url.fragment()?.to_owned())
        })
    }

    fn vet_version(&self) -> VetVersion {
        VetVersion {
            semver: self.version.clone(),
            git_rev: self.git_rev(),
        }
    }
}

const CACHE_DIR_SUFFIX: &str = "cargo-vet";
const CARGO_ENV: &str = "CARGO";
// package.metadata.vet
const PACKAGE_VET_CONFIG: &str = "vet";
// workspace.metadata.vet
const WORKSPACE_VET_CONFIG: &str = "vet";

const DURATION_DAY: Duration = Duration::from_secs(60 * 60 * 24);

lazy_static! {
    static ref WILDCARD_AUDIT_EXPIRATION_DURATION: chrono::Duration = chrono::Duration::weeks(6);
}
/// This string is always used in a context such as "in the next {STR}".
const WILDCARD_AUDIT_EXPIRATION_STRING: &str = "six weeks";

/// Trick to let us std::process::exit while still cleaning up
/// by panicking with this type instead of a string.
struct ExitPanic(i32);

type ReportErrorFunc = dyn Fn(&miette::Report) + Send + Sync + 'static;

// XXX: We might be able to get rid of this `lazy_static` after 1.63 due to
// `const Mutex::new` being stabilized.
lazy_static! {
    static ref REPORT_ERROR: Mutex<Option<Box<ReportErrorFunc>>> = Mutex::new(None);
}

fn set_report_errors_as_json(out: Arc<dyn Out>) {
    *REPORT_ERROR.lock().unwrap() = Some(Box::new(move |error| {
        // Manually invoke JSONReportHandler to format the error as a report
        // to out_.
        let mut report = String::new();
        miette::JSONReportHandler::new()
            .render_report(&mut report, error.as_ref())
            .unwrap();
        writeln!(out, r#"{{"error": {report}}}"#);
    }));
}

fn report_error(error: &miette::Report) {
    {
        let guard = REPORT_ERROR.lock().unwrap();
        if let Some(do_report) = &*guard {
            do_report(error);
            return;
        }
    }
    error!("{:?}", error);
}

fn main() -> Result<(), ()> {
    // NOTE: Limit the maximum number of blocking threads to 128, rather than
    // the default of 512.
    // This may limit concurrency in some cases, but cargo-vet isn't running a
    // server, and should avoid consuming all available resources.
    let runtime = tokio::runtime::Builder::new_multi_thread()
        .worker_threads(1)
        .max_blocking_threads(128)
        .enable_all()
        .build()
        .unwrap();
    let _guard = runtime.enter();

    // Wrap main up in a catch_panic so that we can use it to implement std::process::exit with
    // unwinding, allowing us to silently exit the program while still cleaning up.
    let panic_result = std::panic::catch_unwind(real_main);
    let main_result = match panic_result {
        Ok(main_result) => main_result,
        Err(e) => {
            if let Some(ExitPanic(code)) = e.downcast_ref::<ExitPanic>() {
                // Exit panic, just silently exit with this status
                std::process::exit(*code);
            } else {
                // Normal panic, let it ride
                std::panic::resume_unwind(e);
            }
        }
    };
    main_result.map_err(|e| {
        report_error(&e);
        std::process::exit(-1);
    })
}

fn real_main() -> Result<(), miette::Report> {
    use cli::Commands::*;

    let fake_cli = cli::FakeCli::parse();
    let cli::FakeCli::Vet(cli) = fake_cli;

    //////////////////////////////////////////////////////
    // Setup logging / output
    //////////////////////////////////////////////////////

    // Init the logger (and make trace logging less noisy)
    if let Some(log_path) = &cli.log_file {
        let log_file = File::create(log_path).unwrap();
        tracing_subscriber::fmt::fmt()
            .with_max_level(cli.verbose)
            .with_target(false)
            .without_time()
            .with_ansi(false)
            .with_writer(log_file)
            .init();
    } else {
        tracing_subscriber::fmt::fmt()
            .with_max_level(cli.verbose)
            .with_target(false)
            .without_time()
            .with_ansi(console::colors_enabled_stderr())
            .with_writer(StderrLogWriter::new)
            .init();
    }

    // Control how errors are formatted by setting the miette hook. This will
    // only be used for errors presented to humans, when formatting an error as
    // JSON, it will be handled by a custom `report_error` override, bypassing
    // the hook.
    let using_log_file = cli.log_file.is_some();
    miette::set_hook(Box::new(move |_| {
        let graphical_theme = if console::colors_enabled_stderr() && !using_log_file {
            miette::GraphicalTheme::unicode()
        } else {
            miette::GraphicalTheme::unicode_nocolor()
        };
        Box::new(
            miette::MietteHandlerOpts::new()
                .graphical_theme(graphical_theme)
                .build(),
        )
    }))
    .expect("failed to initialize error handler");

    // Now that miette is set up, use it to format panics.
    panic::set_hook(Box::new(move |panic_info| {
        if panic_info.payload().is::<ExitPanic>() {
            return;
        }

        let payload = panic_info.payload();
        let message = if let Some(msg) = payload.downcast_ref::<&str>() {
            msg
        } else if let Some(msg) = payload.downcast_ref::<String>() {
            &msg[..]
        } else {
            "something went wrong"
        };

        #[derive(Debug, Error, Diagnostic)]
        #[error("{message}")]
        pub struct PanicError {
            pub message: String,
            #[help]
            pub help: Option<String>,
        }

        report_error(
            &miette::Report::from(PanicError {
                message: message.to_owned(),
                help: panic_info
                    .location()
                    .map(|loc| format!("at {}:{}:{}", loc.file(), loc.line(), loc.column())),
            })
            .wrap_err("cargo vet panicked"),
        );
    }));

    // Initialize the MULTIPROGRESS's draw target, so that future progress
    // events are rendered to stderr.
    MULTIPROGRESS.set_draw_target(ProgressDrawTarget::stderr());

    // Setup our output stream
    let out: Arc<dyn Out> = if let Some(output_path) = &cli.output_file {
        Arc::new(File::create(output_path).unwrap())
    } else {
        Arc::new(Term::stdout())
    };

    // If we're outputting JSON, replace the error report method such that it
    // writes errors out to the normal output stream as JSON.
    if cli.output_format == OutputFormat::Json {
        set_report_errors_as_json(out.clone());
    }

    ////////////////////////////////////////////////////
    // Potentially handle freestanding commands
    ////////////////////////////////////////////////////

    let cache_dir = cli.cache_dir.clone().unwrap_or_else(|| {
        dirs::cache_dir()
            .unwrap_or_else(std::env::temp_dir)
            .join(CACHE_DIR_SUFFIX)
    });
    let now = cli
        .current_time
        .unwrap_or_else(|| chrono::DateTime::from(SystemTime::now()));
    let partial_cfg = PartialConfig {
        cli,
        now,
        cache_dir,
        mock_cache: false,
    };

    match &partial_cfg.cli.command {
        Some(Aggregate(sub_args)) => return cmd_aggregate(&out, &partial_cfg, sub_args),
        Some(HelpMarkdown(sub_args)) => return cmd_help_md(&out, &partial_cfg, sub_args),
        Some(Gc(sub_args)) => return cmd_gc(&out, &partial_cfg, sub_args),
        _ => {
            // Not a freestanding command, time to do full parsing and setup
        }
    }

    ///////////////////////////////////////////////////
    // Fetch cargo metadata
    ///////////////////////////////////////////////////

    let cli = &partial_cfg.cli;
    let cargo_path = std::env::var_os(CARGO_ENV).expect("Cargo failed to set $CARGO, how?");

    let mut cmd = cargo_metadata::MetadataCommand::new();
    cmd.cargo_path(cargo_path);
    if let Some(manifest_path) = &cli.manifest_path {
        cmd.manifest_path(manifest_path);
    }
    if !cli.no_all_features {
        cmd.features(cargo_metadata::CargoOpt::AllFeatures);
    }
    if cli.no_default_features {
        cmd.features(cargo_metadata::CargoOpt::NoDefaultFeatures);
    }
    if !cli.features.is_empty() {
        cmd.features(cargo_metadata::CargoOpt::SomeFeatures(cli.features.clone()));
    }
    // We never want cargo-vet to update the Cargo.lock.
    // For frozen runs we also don't want to touch the network.
    let mut other_options = Vec::new();
    if cli.frozen {
        other_options.push("--frozen".to_string());
    } else {
        other_options.push("--locked".to_string());
    }
    if !using_log_file
        && cli.output_format == OutputFormat::Human
        && console::colors_enabled_stderr()
    {
        other_options.push("--color=always".to_string());
    }
    cmd.other_options(other_options);

    info!("Running: {:#?}", cmd.cargo_command());

    // ERRORS: immediate fatal diagnostic
    let metadata = {
        let _spinner = indeterminate_spinner("Running", "`cargo metadata`");
        cmd.exec().map_err(MetadataAcquireError::from)?
    };

    // trace!("Got Metadata! {:#?}", metadata);
    trace!("Got Metadata!");

    //////////////////////////////////////////////////////
    // Parse out our own configuration
    //////////////////////////////////////////////////////

    let default_config = MetaConfigInstance {
        version: Some(1),
        store: Some(StoreInfo {
            path: Some(
                metadata
                    .workspace_root
                    .join(storage::DEFAULT_STORE)
                    .into_std_path_buf(),
            ),
        }),
    };

    // FIXME: what is `store.path` relative to here?
    let workspace_metacfg = metadata
        .workspace_metadata
        .get(WORKSPACE_VET_CONFIG)
        .map(|cfg| {
            // ERRORS: immediate fatal diagnostic
            MetaConfigInstance::deserialize(cfg)
                .into_diagnostic()
                .wrap_err("Workspace had [{WORKSPACE_VET_CONFIG}] but it was malformed")
        })
        .transpose()?;

    // FIXME: what is `store.path` relative to here?
    let package_metacfg = metadata
        .root_package()
        .and_then(|r| r.metadata.get(PACKAGE_VET_CONFIG))
        .map(|cfg| {
            // ERRORS: immediate fatal diagnostic
            MetaConfigInstance::deserialize(cfg)
                .into_diagnostic()
                .wrap_err("Root package had [{PACKAGE_VET_CONFIG}] but it was malformed")
        })
        .transpose()?;

    let cli_metacfg = cli.store_path.as_ref().map(|path| MetaConfigInstance {
        version: Some(1),
        store: Some(StoreInfo {
            path: Some(path.clone()),
        }),
    });

    if workspace_metacfg.is_some() && package_metacfg.is_some() {
        // ERRORS: immediate fatal diagnostic
        return Err(miette!("Both a workspace and a package defined [metadata.vet]! We don't know what that means, if you do, let us know!"));
    }

    let mut metacfgs = vec![default_config];
    if let Some(metacfg) = workspace_metacfg {
        metacfgs.push(metacfg);
    }
    if let Some(metacfg) = package_metacfg {
        metacfgs.push(metacfg);
    }
    if let Some(metacfg) = cli_metacfg {
        metacfgs.push(metacfg);
    }
    let metacfg = MetaConfig(metacfgs);

    info!("Final Metadata Config: ");
    info!("  - version: {}", metacfg.version());
    info!("  - store.path: {:#?}", metacfg.store_path());

    //////////////////////////////////////////////////////
    // Run the actual command
    //////////////////////////////////////////////////////

    let init = Store::is_init(&metacfg);
    if matches!(cli.command, Some(Commands::Init { .. })) {
        if init {
            // ERRORS: immediate fatal diagnostic
            return Err(miette!(
                "'cargo vet' already initialized (store found at {})",
                metacfg.store_path().display()
            ));
        }
    } else if !init {
        // ERRORS: immediate fatal diagnostic
        return Err(miette!(
            "You must run 'cargo vet init' (store not found at {})",
            metacfg.store_path().display()
        ));
    }

    let cfg = Config {
        metacfg,
        metadata,
        _rest: partial_cfg,
    };

    use RegenerateSubcommands::*;
    match &cfg.cli.command {
        None => cmd_check(&out, &cfg, &cfg.cli.check_args),
        Some(Check(sub_args)) => cmd_check(&out, &cfg, sub_args),
        Some(Init(sub_args)) => cmd_init(&out, &cfg, sub_args),
        Some(Certify(sub_args)) => cmd_certify(&out, &cfg, sub_args),
        Some(Import(sub_args)) => cmd_import(&out, &cfg, sub_args),
        Some(Trust(sub_args)) => cmd_trust(&out, &cfg, sub_args),
        Some(AddExemption(sub_args)) => cmd_add_exemption(&out, &cfg, sub_args),
        Some(RecordViolation(sub_args)) => cmd_record_violation(&out, &cfg, sub_args),
        Some(Suggest(sub_args)) => cmd_suggest(&out, &cfg, sub_args),
        Some(Fmt(sub_args)) => cmd_fmt(&out, &cfg, sub_args),
        Some(Prune(sub_args)) => cmd_prune(&out, &cfg, sub_args),
        Some(DumpGraph(sub_args)) => cmd_dump_graph(&out, &cfg, sub_args),
        Some(Inspect(sub_args)) => cmd_inspect(&out, &cfg, sub_args),
        Some(Diff(sub_args)) => cmd_diff(&out, &cfg, sub_args),
        Some(Regenerate(Imports(sub_args))) => cmd_regenerate_imports(&out, &cfg, sub_args),
        Some(Regenerate(Exemptions(sub_args))) => cmd_regenerate_exemptions(&out, &cfg, sub_args),
        Some(Regenerate(AuditAsCratesIo(sub_args))) => {
            cmd_regenerate_audit_as(&out, &cfg, sub_args)
        }
        Some(Regenerate(Unpublished(sub_args))) => cmd_regenerate_unpublished(&out, &cfg, sub_args),
        Some(Renew(sub_args)) => cmd_renew(&out, &cfg, sub_args),
        Some(Aggregate(_)) | Some(HelpMarkdown(_)) | Some(Gc(_)) => unreachable!("handled earlier"),
    }
}

fn cmd_init(_out: &Arc<dyn Out>, cfg: &Config, _sub_args: &InitArgs) -> Result<(), miette::Report> {
    // Initialize vet
    trace!("initializing...");

    let network = Network::acquire(cfg);
    let mut store = Store::create(cfg)?;

    check_crate_policies(cfg, &store)?;
    tokio::runtime::Handle::current().block_on(fix_audit_as(cfg, network.as_ref(), &mut store))?;

    // Run the resolver to regenerate exemptions, this will fill in exemptions
    // such that the vet now passes.
    resolver::update_store(cfg, &mut store, |_| resolver::UpdateMode {
        search_mode: resolver::SearchMode::RegenerateExemptions,
        prune_exemptions: true,
        prune_imports: true,
    });

    store.commit()?;

    Ok(())
}

fn cmd_inspect(
    out: &Arc<dyn Out>,
    cfg: &Config,
    sub_args: &InspectArgs,
) -> Result<(), miette::Report> {
    let version = &sub_args.version;
    let package = &*sub_args.package;

    let fetched = {
        let network = Network::acquire(cfg);
        let store = Store::acquire(cfg, network.as_ref(), false)?;
        let cache = Cache::acquire(cfg)?;

        // Record this command for magic in `vet certify`
        cache.set_last_fetch(FetchCommand::Inspect {
            package: package.to_owned(),
            version: version.clone(),
        });

        if sub_args.mode == FetchMode::Sourcegraph && version.git_rev.is_none() {
            let url = format!("https://sourcegraph.com/crates/{package}@v{version}");
            tokio::runtime::Handle::current()
                .block_on(prompt_criteria_eulas(
                    out,
                    cfg,
                    network.as_ref(),
                    &store,
                    package,
                    None,
                    version,
                    Some(&url),
                ))
                .into_diagnostic()?;

            open::that(&url).into_diagnostic().wrap_err_with(|| {
                format!("Couldn't open {url} in your browser, try --mode=local?")
            })?;

            writeln!(out, "\nUse |cargo vet certify| to record your audit.");
            return Ok(());
        }

        tokio::runtime::Handle::current().block_on(async {
            let (pkg, eulas) = tokio::join!(
                async {
                    // If we're fetching a git revision for inspection, don't
                    // use fetch_package, as we want to point the user at the
                    // actual cargo checkout, rather than our repack, which may
                    // be incomplete, and will be clobbered by GC.
                    if let Some(git_rev) = &version.git_rev {
                        storage::locate_local_checkout(&cfg.metadata, package, version).ok_or_else(
                            || FetchError::UnknownGitRevision {
                                package: package.to_owned(),
                                git_rev: git_rev.to_owned(),
                            },
                        )
                    } else {
                        cache
                            .fetch_package(&cfg.metadata, network.as_ref(), package, version)
                            .await
                    }
                },
                prompt_criteria_eulas(
                    out,
                    cfg,
                    network.as_ref(),
                    &store,
                    package,
                    None,
                    version,
                    None,
                ),
            );
            eulas.into_diagnostic()?;
            pkg.into_diagnostic()
        })?
    };

    #[cfg(target_family = "unix")]
    if let Some(shell) = std::env::var_os("SHELL") {
        // Loosely borrowed from cargo crev.
        writeln!(out, "Opening nested shell in: {fetched:#?}");
        writeln!(out, "Use `exit` or Ctrl-D to finish.",);
        let status = std::process::Command::new(shell)
            .current_dir(fetched.clone())
            .env("PWD", fetched)
            .status()
            .map_err(CommandError::CommandFailed)
            .into_diagnostic()?;

        writeln!(out, "\nUse |cargo vet certify| to record your audit.");

        if let Some(code) = status.code() {
            panic_any(ExitPanic(code));
        }
        return Ok(());
    }

    writeln!(out, "  fetched to {fetched:#?}");
    writeln!(out, "\nUse |cargo vet certify| to record your audit.");
    Ok(())
}

fn cmd_certify(
    out: &Arc<dyn Out>,
    cfg: &Config,
    sub_args: &CertifyArgs,
) -> Result<(), miette::Report> {
    // Certify that you have reviewed a crate's source for some version / delta
    let network = Network::acquire(cfg);
    let mut store = Store::acquire(cfg, network.as_ref(), false)?;

    // Grab the last fetch and immediately drop the cache
    let last_fetch = Cache::acquire(cfg)?.get_last_fetch();

    do_cmd_certify(out, cfg, sub_args, &mut store, network.as_ref(), last_fetch)?;

    store.commit()?;
    Ok(())
}

fn do_cmd_certify(
    out: &Arc<dyn Out>,
    cfg: &Config,
    sub_args: &CertifyArgs,
    store: &mut Store,
    network: Option<&Network>,
    last_fetch: Option<FetchCommand>,
) -> Result<(), CertifyError> {
    // Before setting up magic, we need to agree on a package
    let package = if let Some(package) = &sub_args.package {
        package.clone()
    } else if let Some(last_fetch) = &last_fetch {
        // If we just fetched a package, assume we want to certify it
        last_fetch.package().to_owned()
    } else {
        return Err(CertifyError::CouldntGuessPackage);
    };

    // FIXME: can/should we check if the version makes sense..?
    if !sub_args.force
        && !foreign_packages(&cfg.metadata, &store.config).any(|pkg| pkg.name == *package)
    {
        return Err(CertifyError::NotAPackage(package));
    }

    #[derive(Debug)]
    enum CertifyKind {
        Delta {
            from: VetVersion,
            to: VetVersion,
        },
        Full {
            version: VetVersion,
        },
        Wildcard {
            user_login: String,
            user_id: CratesUserId,
            start: chrono::NaiveDate,
            end: chrono::NaiveDate,
            set_renew_false: bool,
        },
    }

    let kind = if let Some(login) = &sub_args.wildcard {
        // Fetch publisher information for relevant versions of `package`.
        let publishers = store.ensure_publisher_versions(cfg, network, &package)?;
        let published_versions = publishers
            .iter()
            .filter(|publisher| &publisher.user_login == login);

        let earliest = published_versions
            .min_by_key(|p| p.when)
            .ok_or_else(|| CertifyError::NotAPublisher(login.to_owned(), package.to_owned()))?;

        // Get the from and to dates, defaulting to a from date of the earliest
        // published package by the user, and a to date of 12 months from today.
        let start = sub_args.start_date.unwrap_or(earliest.when);

        let max_end = cfg.today() + chrono::Months::new(12);
        let end = sub_args.end_date.unwrap_or(max_end);
        let set_renew_false = sub_args.end_date.is_some();
        if end > max_end {
            return Err(CertifyError::BadWildcardEndDate(end));
        }

        CertifyKind::Wildcard {
            user_login: earliest.user_login.to_owned(),
            user_id: earliest.user_id,
            start,
            end,
            set_renew_false,
        }
    } else if let Some(v1) = &sub_args.version1 {
        // If explicit versions were provided, use those
        if let Some(v2) = &sub_args.version2 {
            // This is a delta audit
            CertifyKind::Delta {
                from: v1.clone(),
                to: v2.clone(),
            }
        } else {
            // This is a full audit
            CertifyKind::Full {
                version: v1.clone(),
            }
        }
    } else if let Some(fetch) = last_fetch.filter(|f| f.package() == package) {
        // Otherwise, is we just fetched this package, use the version(s) we fetched
        match fetch {
            FetchCommand::Inspect { version, .. } => CertifyKind::Full { version },
            FetchCommand::Diff {
                version1, version2, ..
            } => CertifyKind::Delta {
                from: version1,
                to: version2,
            },
        }
    } else {
        return Err(CertifyError::CouldntGuessVersion(package));
    };

    let (username, who) = if sub_args.who.is_empty() {
        let user_info = get_user_info()?;
        let who = format!("{} <{}>", user_info.username, user_info.email);
        (user_info.username, vec![Spanned::from(who)])
    } else {
        (
            sub_args.who.join(", "),
            sub_args
                .who
                .iter()
                .map(|w| Spanned::from(w.clone()))
                .collect(),
        )
    };

    let (criteria_guess, prompt) = if sub_args.criteria.is_empty() {
        // If we don't have explicit cli criteria, guess the criteria
        //
        // * Check what would cause `cargo vet` to encounter fewer errors
        // * Otherwise check what would cause `cargo vet suggest` to suggest fewer audits
        // * Otherwise guess nothing
        //
        // Regardless of the guess, prompt the user to confirm (just needs to mash enter)
        match &kind {
            CertifyKind::Full { version } => (
                guess_audit_criteria(cfg, store, &package, None, version),
                Some(format!(
                    "choose criteria to certify for {package}:{version}"
                )),
            ),
            CertifyKind::Delta { from, to } => (
                guess_audit_criteria(cfg, store, &package, Some(from), to),
                Some(format!(
                    "choose criteria to certify for {package}:{from} -> {to}"
                )),
            ),
            CertifyKind::Wildcard { .. } => {
                // FIXME: Consider predicting the criteria better for wildcard
                // audits in the future.
                (
                    vec![format::SAFE_TO_DEPLOY.to_owned()],
                    Some(format!("choose criteria to certify for {package}:*")),
                )
            }
        }
    } else {
        // If we do have explcit criteria, don't prompt, but still pass through
        // prompt_pick_criteria to simplify and validate.
        (sub_args.criteria.clone(), None)
    };
    let criteria_names =
        criteria_picker(out, &store.audits.criteria, criteria_guess, prompt.as_ref())?;

    let statement = match &kind {
        CertifyKind::Full { version } => {
            format!(
                    "I, {username}, certify that I have audited version {version} of {package} in accordance with the above criteria.",
                )
        }
        CertifyKind::Delta { from, to } => {
            format!(
                    "I, {username}, certify that I have audited the changes from version {from} to {to} of {package} in accordance with the above criteria.",
                )
        }
        CertifyKind::Wildcard {
            user_login,
            start,
            end,
            ..
        } => {
            format!(
                    "I, {username}, certify that any version of {package} published by '{user_login}' between {start} and {end} will satisfy the above criteria.",
                )
        }
    };

    let mut notes = sub_args.notes.clone();
    if !sub_args.accept_all {
        // Get all the EULAs at once
        let eulas = tokio::runtime::Handle::current().block_on(join_all(
            criteria_names.iter().map(|criteria| async {
                (
                    &criteria[..],
                    eula_for_criteria(network, &store.audits.criteria, criteria).await,
                )
            }),
        ));

        let mut editor = out.editor("VET_CERTIFY")?;
        if let Some(notes) = &notes {
            editor.select_comment_char(notes);
        }

        editor.add_comments(
            "Please read the following criteria and then follow the instructions below:",
        )?;
        editor.add_text("")?;

        for (criteria, eula) in &eulas {
            editor.add_comments(&format!("=== BEGIN CRITERIA {criteria:?} ==="))?;
            editor.add_comments("")?;
            editor.add_comments(eula)?;
            editor.add_comments("")?;
            editor.add_comments("=== END CRITERIA ===")?;
            editor.add_comments("")?;
        }
        editor.add_comments("Uncomment the following statement:")?;
        editor.add_text("")?;
        editor.add_comments(&statement)?;
        editor.add_text("")?;
        editor.add_comments("Add any notes about your audit below this line:")?;
        editor.add_text("")?;
        if let Some(notes) = &notes {
            editor.add_text(notes)?;
        }

        let editor_result = editor.edit()?;

        // Check to make sure that the statement was uncommented as the first
        // line in the parsed file, and remove blank lines between the statement
        // and notes.
        let new_notes = match editor_result.trim_start().strip_prefix(&statement) {
            Some(notes) => notes.trim_start_matches('\n'),
            None => {
                // FIXME: Might be nice to try to save any notes the user typed
                // in and re-try the prompt if the user asks for it, in case
                // they wrote some nice notes, but forgot to uncomment the
                // statement.
                return Err(CertifyError::CouldntFindCertifyStatement);
            }
        };

        // Strip trailing newline if notes would otherwise contain no newlines.
        let new_notes = new_notes
            .strip_suffix('\n')
            .filter(|s| !s.contains('\n'))
            .unwrap_or(new_notes);

        notes = if new_notes.is_empty() {
            None
        } else {
            Some(new_notes.to_owned())
        };
    }

    let criteria = criteria_names.into_iter().map(|s| s.into()).collect();
    match kind {
        CertifyKind::Full { version } => {
            store
                .audits
                .audits
                .entry(package.clone())
                .or_default()
                .push(AuditEntry {
                    kind: AuditKind::Full { version },
                    criteria,
                    who,
                    notes,
                    aggregated_from: vec![],
                    is_fresh_import: false,
                });
        }
        CertifyKind::Delta { from, to } => {
            store
                .audits
                .audits
                .entry(package.clone())
                .or_default()
                .push(AuditEntry {
                    kind: AuditKind::Delta { from, to },
                    criteria,
                    who,
                    notes,
                    aggregated_from: vec![],
                    is_fresh_import: false,
                });
        }
        CertifyKind::Wildcard {
            user_id,
            start,
            end,
            set_renew_false,
            ..
        } => {
            store
                .audits
                .wildcard_audits
                .entry(package.clone())
                .or_default()
                .push(WildcardEntry {
                    who,
                    criteria,
                    user_id,
                    start: start.into(),
                    end: end.into(),
                    renew: set_renew_false.then_some(false),
                    notes,
                    aggregated_from: vec![],
                    is_fresh_import: false,
                });
        }
    };

    store
        .validate(cfg.today(), false)
        .expect("the new audit entry made the store invalid?");

    // Minimize exemptions after adding the new audit. This will be used to
    // potentially update imports, and remove now-unnecessary exemptions for the
    // target package. We only prefer fresh imports and prune exemptions for the
    // package we certified, to avoid unrelated changes.
    resolver::update_store(cfg, store, |name| resolver::UpdateMode {
        search_mode: if name == &package[..] {
            resolver::SearchMode::PreferFreshImports
        } else {
            resolver::SearchMode::PreferExemptions
        },
        prune_exemptions: name == &package[..],
        prune_imports: false,
    });

    Ok(())
}

fn criteria_picker(
    out: &Arc<dyn Out>,
    store_criteria: &SortedMap<CriteriaName, CriteriaEntry>,
    criteria_guess: Vec<CriteriaName>,
    prompt: Option<&impl AsRef<str>>,
) -> Result<Vec<CriteriaName>, CertifyError> {
    let criteria_mapper = CriteriaMapper::new(store_criteria);

    let mut chosen_criteria = criteria_guess;
    if let Some(prompt) = prompt {
        // Prompt for criteria
        loop {
            out.clear_screen()?;
            writeln!(out, "{}", prompt.as_ref());
            for (criteria_idx, criteria_name) in criteria_mapper.all_criteria_names().enumerate() {
                if chosen_criteria.iter().any(|s| s == criteria_name) {
                    writeln!(
                        out,
                        "  {}. {}",
                        criteria_idx + 1,
                        out.style().green().bold().apply_to(criteria_name)
                    );
                } else {
                    writeln!(
                        out,
                        "  {}. {}",
                        criteria_idx + 1,
                        out.style().bold().dim().apply_to(criteria_name)
                    );
                }
            }

            writeln!(out);
            writeln!(out, "current selection: {:?}", chosen_criteria);
            writeln!(out, "(press ENTER to accept the current criteria)");
            let input = out.read_line_with_prompt("> ")?;
            let input = input.trim();
            if input.is_empty() {
                if chosen_criteria.is_empty() {
                    return Err(CertifyError::NoCriteriaChosen);
                }
                // User done selecting criteria
                break;
            }

            // FIXME: these errors get cleared away right away
            let answer = if let Ok(val) = input.parse::<usize>() {
                val
            } else {
                // ERRORS: immediate error print to output for feedback, non-fatal
                writeln!(out, "error: not a valid integer");
                continue;
            };
            if answer == 0 || answer > criteria_mapper.len() {
                // ERRORS: immediate error print to output for feedback, non-fatal
                writeln!(out, "error: not a valid criteria");
                continue;
            }

            let selection = criteria_mapper.criteria_name(answer - 1).to_owned();
            if chosen_criteria.contains(&selection) {
                chosen_criteria.retain(|x| x != &selection);
            } else {
                chosen_criteria.push(selection);
            }
        }
    }

    // Round-trip this through the criteria_mapper to clean up `implies` relationships
    let criteria_set = criteria_mapper.criteria_from_list(&chosen_criteria);
    Ok(criteria_mapper
        .criteria_names(&criteria_set)
        .map(|s| s.to_owned())
        .collect::<Vec<_>>())
}

/// Attempt to guess which criteria are being certified for a given package and
/// audit kind.
///
/// The logic which this method uses to guess the criteria to use is as follows:
///
/// * Check what would cause `cargo vet` to encounter fewer errors
/// * Otherwise check what would cause `cargo vet suggest` to suggest fewer audits
/// * Otherwise guess nothing
fn guess_audit_criteria(
    cfg: &Config,
    store: &Store,
    package: PackageStr<'_>,
    from: Option<&VetVersion>,
    to: &VetVersion,
) -> Vec<String> {
    // Attempt to resolve a normal `cargo vet`, and try to find criteria which
    // would heal some errors in that result if it fails.
    let criteria = resolver::resolve(&cfg.metadata, cfg.cli.filter_graph.as_ref(), store)
        .compute_suggested_criteria(package, from, to);
    if !criteria.is_empty() {
        return criteria;
    }

    // If a normal `cargo vet` failed to turn up any criteria, try a more
    // aggressive `cargo vet suggest`.
    //
    // This is as much as we can do, so just return the result whether or not we
    // find anything.
    resolver::resolve(
        &cfg.metadata,
        cfg.cli.filter_graph.as_ref(),
        &store.clone_for_suggest(true),
    )
    .compute_suggested_criteria(package, from, to)
}

/// Prompt the user to read the EULAs for the expected criteria which they will
/// be certifying for with this diff or inspect command.
///
/// This method is async so it can be performed concurrently with waiting for
/// the downloads to complete.
#[allow(clippy::too_many_arguments)]
async fn prompt_criteria_eulas(
    out: &Arc<dyn Out>,
    cfg: &Config,
    network: Option<&Network>,
    store: &Store,
    package: PackageStr<'_>,
    from: Option<&VetVersion>,
    to: &VetVersion,
    url: Option<&str>,
) -> Result<(), io::Error> {
    let description = if let Some(from) = from {
        format!("You are about to diff versions {from} and {to} of '{package}'")
    } else {
        format!("You are about to inspect version {to} of '{package}'")
    };

    // Guess which criteria the user is going to be auditing the package for.
    let criteria_names = guess_audit_criteria(cfg, store, package, from, to);

    // FIXME: These `writeln` calls can do blocking I/O, but they hopefully
    // shouldn't block long enough for it interfere with downloading packages in
    // the background. We do the `read_line_with_prompt` call async.
    if criteria_names.is_empty() {
        writeln!(out, "{}", out.style().bold().apply_to(description));
        warn!("unable to determine likely criteria, this may not be a relevant audit for this project.");
    } else {
        let eulas = join_all(criteria_names.iter().map(|criteria| async {
            (
                &criteria[..],
                eula_for_criteria(network, &store.audits.criteria, criteria).await,
            )
        }))
        .await;

        for (idx, (criteria, eula)) in eulas.into_iter().enumerate() {
            let prompt = if idx == 0 {
                format!("{description}, likely to certify it for {criteria:?}, which means:")
            } else {
                format!("... and for {criteria:?}, which means:")
            };
            writeln!(
                out,
                "{}\n\n  {}",
                out.style().bold().apply_to(prompt),
                eula.replace('\n', "\n  "),
            );
        }

        writeln!(
            out,
            "{}",
            out.style().bold().apply_to(
                "Please read the above criteria and consider them when performing the audit."
            )
        );
    }

    writeln!(
        out,
        "{}",
        out.style().bold().apply_to(
            "Other software projects may rely on this audit. Ask for help if you're not sure.\n"
        )
    );

    let final_prompt = if let Some(url) = url {
        writeln!(
            out,
            "You can inspect the {} here: {}\n",
            if from.is_some() { "diff" } else { "crate" },
            url,
        );
        "(press ENTER to open in your browser, or re-run with --mode=local)"
    } else {
        "(press ENTER to inspect locally)"
    };

    let out_ = out.clone();
    tokio::task::spawn_blocking(move || out_.read_line_with_prompt(final_prompt)).await??;
    Ok(())
}

fn cmd_import(
    _out: &Arc<dyn Out>,
    cfg: &Config,
    sub_args: &ImportArgs,
) -> Result<(), miette::Report> {
    let Some(network) = Network::acquire(cfg) else {
        return Err(miette!("`cargo vet import` cannot be run while frozen"));
    };

    // Determine the URL for the import, potentially fetching the registry to
    // find it.
    let registry_file;
    let import_urls = if sub_args.url.is_empty() {
        registry_file = tokio::runtime::Handle::current().block_on(fetch_registry(&network))?;
        registry_file
            .registry
            .get(&sub_args.name)
            .ok_or_else(|| miette!("no peer named {} found in the registry", &sub_args.name))
            .map(|entry| entry.url.clone())?
    } else {
        sub_args.url.clone()
    };

    let mut store = Store::acquire_offline(cfg)?;

    // Insert a new entry for the new import, or update an existing entry to use
    // the newly specified URLs.
    store
        .config
        .imports
        .entry(sub_args.name.clone())
        .or_default()
        .url = import_urls;

    // After adding the new entry, go online, this will fetch the new import.
    let cache = Cache::acquire(cfg)?;
    tokio::runtime::Handle::current().block_on(store.go_online(cfg, &network, &cache, false))?;

    // Update the store state, pruning unnecessary exemptions, and cleaning out
    // unnecessary old imports.
    resolver::update_store(cfg, &mut store, |_| resolver::UpdateMode {
        search_mode: resolver::SearchMode::PreferFreshImports,
        prune_exemptions: true,
        prune_imports: true,
    });

    store.commit()?;

    Ok(())
}

fn cmd_trust(out: &Arc<dyn Out>, cfg: &Config, sub_args: &TrustArgs) -> Result<(), miette::Report> {
    // Certify that you have reviewed a crate's source for some version / delta
    let network = Network::acquire(cfg);
    let mut store = Store::acquire(cfg, network.as_ref(), false)?;

    do_cmd_trust(out, cfg, sub_args, &mut store, network.as_ref())?;

    store.commit()?;

    Ok(())
}

fn do_cmd_trust(
    out: &Arc<dyn Out>,
    cfg: &Config,
    sub_args: &TrustArgs,
    store: &mut Store,
    network: Option<&Network>,
) -> Result<(), miette::Report> {
    if let Some(package) = &sub_args.package {
        // Fetch publisher information for relevant versions of `package`.
        let publishers = store.ensure_publisher_versions(cfg, network, package)?;

        let publisher_login = if let Some(login) = &sub_args.publisher_login {
            login.clone()
        } else if let Some(first) = publishers.first() {
            if publishers
                .iter()
                .all(|publisher| publisher.user_id == first.user_id)
            {
                first.user_login.clone()
            } else {
                return Err(miette!(
                    "The package '{}' has multiple known publishers, \
                    please explicitly specify which publisher to trust",
                    package
                ));
            }
        } else {
            return Err(miette!(
                "The package '{}' has no known publishers, so cannot be trusted",
                package
            ));
        };

        apply_cmd_trust(
            out,
            cfg,
            store,
            network,
            package,
            &publisher_login,
            sub_args.start_date,
            sub_args.end_date,
            &sub_args.criteria,
            sub_args.notes.as_ref(),
        )
    } else if let Some(publisher_login) = &sub_args.all {
        // Run the resolver against the store in "suggest" mode to discover the
        // set of packages which either fail to audit or need exemptions.
        let suggest_store = store.clone_for_suggest(true);
        let report =
            resolver::resolve(&cfg.metadata, cfg.cli.filter_graph.as_ref(), &suggest_store);
        let resolver::Conclusion::FailForVet(fail) = &report.conclusion else {
            return Err(miette!("No failing or exempted crates, trust --all will do nothing"));
        };

        // Enumerate the failed packages to collect the set of packages which
        // will be trusted.
        let mut failed_criteria = report.criteria_mapper.no_criteria();
        let mut trust = Vec::new();
        let mut skipped = Vec::new();
        for (failure_idx, audit_failure) in &fail.failures {
            let package = &report.graph.nodes[*failure_idx];

            // Ensure the store has publisher information for this package. This
            // is a no-op if called multiple times for the same package.
            let publishers = store.ensure_publisher_versions(cfg, network, package.name)?;
            let by_user = publishers
                .iter()
                .filter(|p| &p.user_login == publisher_login)
                .count();
            if by_user == 0 {
                continue; // never published by this user
            }

            // Record if we're skipping this package due to multiple publishers.
            if by_user != publishers.len() && !sub_args.allow_multiple_publishers {
                skipped.push(package.name);
            } else {
                trust.push(package.name);
                failed_criteria.unioned_with(&audit_failure.criteria_failures);
            }
        }
        trust.sort();
        trust.dedup();

        // Delay warning about skipped entries until after `criteria_picker`, as
        // that may clear the terminal.
        let maybe_warn_skipped = || {
            if !skipped.is_empty() {
                skipped.sort();
                skipped.dedup();
                warn!(
                    "Skipped {} due to multiple publishers",
                    string_format::FormatShortList::new(skipped)
                );
                warn!("  Run with --allow-multiple-publishers to also trust these packages");
            }
        };

        if trust.is_empty() {
            maybe_warn_skipped();
            return Err(miette!(
                "No failing or exempted packages published by {publisher_login}"
            ));
        }

        let criteria_names = criteria_picker(
            out,
            &store.audits.criteria,
            if sub_args.criteria.is_empty() {
                report
                    .criteria_mapper
                    .criteria_names(&failed_criteria)
                    .map(|s| s.to_owned())
                    .collect()
            } else {
                sub_args.criteria.clone()
            },
            if sub_args.criteria.is_empty() {
                Some(format!(
                    "choose trusted criteria for packages published by {publisher_login} ({})",
                    string_format::FormatShortList::new(trust.clone())
                ))
            } else {
                None
            }
            .as_ref(),
        )?;

        maybe_warn_skipped();

        for package in &trust {
            apply_cmd_trust(
                out,
                cfg,
                store,
                network,
                package,
                publisher_login,
                sub_args.start_date,
                sub_args.end_date,
                &criteria_names,
                sub_args.notes.as_ref(),
            )?;
        }

        Ok(())
    } else {
        Err(miette!("Please specify either a package to trust or --all"))
    }
}

#[allow(clippy::too_many_arguments)]
fn apply_cmd_trust(
    out: &Arc<dyn Out>,
    cfg: &Config,
    store: &mut Store,
    network: Option<&Network>,
    package: &str,
    publisher_login: &str,
    start_date: Option<chrono::NaiveDate>,
    end_date: Option<chrono::NaiveDate>,
    criteria: &[CriteriaName],
    notes: Option<&String>,
) -> Result<(), miette::Report> {
    // Fetch publisher information for relevant versions of `package`.
    let publishers = store.ensure_publisher_versions(cfg, network, package)?;

    let published_versions = publishers
        .iter()
        .filter(|publisher| publisher.user_login == publisher_login);

    let earliest = published_versions.min_by_key(|p| p.when).ok_or_else(|| {
        CertifyError::NotAPublisher(publisher_login.to_owned(), package.to_owned())
    })?;
    let user_id = earliest.user_id;

    // Get the from and to dates, defaulting to a from date of the earliest
    // published package by the user, and a to date of 12 months from today.
    let start = start_date.unwrap_or(earliest.when);

    let end = end_date.unwrap_or(cfg.today() + chrono::Months::new(12));

    let criteria_names = criteria_picker(
        out,
        &store.audits.criteria,
        if criteria.is_empty() {
            vec![format::SAFE_TO_DEPLOY.to_owned()]
        } else {
            criteria.to_owned()
        },
        if criteria.is_empty() {
            Some(format!(
                "choose trusted criteria for {package}:* published by {publisher_login}"
            ))
        } else {
            None
        }
        .as_ref(),
    )?;
    let criteria = criteria_names.into_iter().map(Spanned::from).collect();

    // Check if we have an existing trust entry which could be extended to
    // handle a wider date range, and update that instead if possible.
    let trust_entries = store.audits.trusted.entry(package.to_owned()).or_default();
    if let Some(trust_entry) = trust_entries.iter_mut().find(|trust_entry| {
        trust_entry.criteria == criteria
            && trust_entry.user_id == user_id
            && start <= *trust_entry.start
            && *trust_entry.end <= end
            && notes.is_none()
    }) {
        trust_entry.start = start.into();
        trust_entry.end = end.into();
    } else {
        trust_entries.push(TrustEntry {
            criteria,
            user_id,
            start: start.into(),
            end: end.into(),
            notes: notes.cloned(),
            aggregated_from: vec![],
        });
    }

    store
        .validate(cfg.today(), false)
        .expect("the new trusted entry made the store invalid?");

    // Minimize exemptions after adding the new trust entry. This will be used
    // to potentially update imports, and remove now-unnecessary exemptions for
    // the target package. We only prefer fresh imports and prune exemptions for
    // the package we trusted, to avoid unrelated changes.
    resolver::update_store(cfg, store, |name| resolver::UpdateMode {
        search_mode: if name == package {
            resolver::SearchMode::PreferFreshImports
        } else {
            resolver::SearchMode::PreferExemptions
        },
        prune_exemptions: name == package,
        prune_imports: false,
    });
    Ok(())
}

fn cmd_record_violation(
    out: &Arc<dyn Out>,
    cfg: &Config,
    sub_args: &RecordViolationArgs,
) -> Result<(), miette::Report> {
    // Mark a package as a violation
    let mut store = Store::acquire_offline(cfg)?;

    let kind = AuditKind::Violation {
        violation: sub_args.versions.clone(),
    };

    let (_username, who) = if sub_args.who.is_empty() {
        let user_info = get_user_info()?;
        let who = format!("{} <{}>", user_info.username, user_info.email);
        (user_info.username, vec![Spanned::from(who)])
    } else {
        (
            sub_args.who.join(", "),
            sub_args
                .who
                .iter()
                .map(|w| Spanned::from(w.clone()))
                .collect(),
        )
    };

    let notes = sub_args.notes.clone();

    let criteria = if sub_args.criteria.is_empty() {
        // TODO: provide an interactive prompt for this
        vec![store.config.default_criteria.clone().into()]
    } else {
        sub_args
            .criteria
            .iter()
            .map(|s| s.to_owned().into())
            .collect()
    };

    // FIXME: can/should we check if the version makes sense..?
    if !sub_args.force
        && !foreign_packages(&cfg.metadata, &store.config).any(|pkg| pkg.name == sub_args.package)
    {
        // ERRORS: immediate fatal diagnostic? should we allow you to forbid random packages?
        // You're definitely *allowed* to have unused audits, otherwise you'd be constantly deleting
        // useful audits whenever you update your dependencies! But this might be a useful guard
        // against typosquatting or other weird issues?
        return Err(miette!(
            "'{}' isn't one of your foreign packages",
            sub_args.package
        ));
    }

    // Ok! Ready to commit the audit!
    let new_entry = AuditEntry {
        kind,
        criteria,
        who,
        notes,
        aggregated_from: vec![],
        is_fresh_import: false,
    };

    store
        .audits
        .audits
        .entry(sub_args.package.clone())
        .or_default()
        .push(new_entry);

    store.commit()?;

    writeln!(out, "If you've identified a security vulnerability in {} please report it at https://github.com/rustsec/advisory-db#reporting-vulnerabilities", sub_args.package);

    Ok(())
}

fn cmd_add_exemption(
    _out: &Arc<dyn Out>,
    cfg: &Config,
    sub_args: &AddExemptionArgs,
) -> Result<(), miette::Report> {
    // Add an exemption entry
    let mut store = Store::acquire_offline(cfg)?;

    let notes = sub_args.notes.clone();

    let criteria = if sub_args.criteria.is_empty() {
        // TODO: provide an interactive prompt for this
        vec![store.config.default_criteria.clone().into()]
    } else {
        sub_args
            .criteria
            .iter()
            .map(|s| s.to_owned().into())
            .collect()
    };

    let suggest = !sub_args.no_suggest;

    // FIXME: can/should we check if the version makes sense..?
    if !sub_args.force
        && !foreign_packages(&cfg.metadata, &store.config).any(|pkg| pkg.name == sub_args.package)
    {
        // ERRORS: immediate fatal diagnostic? should we allow you to certify random packages?
        // You're definitely *allowed* to have unused audits, otherwise you'd be constantly deleting
        // useful audits whenever you update your dependencies! But this might be a useful guard
        // against typosquatting or other weird issues?
        return Err(miette!(
            "'{}' isn't one of your foreign packages",
            sub_args.package
        ));
    }

    // Ok! Ready to commit the audit!
    let new_entry = ExemptedDependency {
        criteria,
        notes,
        version: sub_args.version.clone(),
        suggest,
    };

    store
        .config
        .exemptions
        .entry(sub_args.package.clone())
        .or_default()
        .push(new_entry);

    store.commit()?;

    Ok(())
}

fn cmd_suggest(
    out: &Arc<dyn Out>,
    cfg: &Config,
    _sub_args: &SuggestArgs,
) -> Result<(), miette::Report> {
    // Run the checker to validate that the current set of deps is covered by the current cargo vet store
    trace!("suggesting...");
    let network = Network::acquire(cfg);
    let suggest_store = Store::acquire(cfg, network.as_ref(), false)?.clone_for_suggest(true);

    // DO THE THING!!!!
    let report = resolver::resolve(&cfg.metadata, cfg.cli.filter_graph.as_ref(), &suggest_store);
    let suggest = report.compute_suggest(cfg, &suggest_store, network.as_ref())?;
    match cfg.cli.output_format {
        OutputFormat::Human => report
            .print_suggest_human(out, cfg, suggest.as_ref())
            .into_diagnostic()?,
        OutputFormat::Json => report.print_json(out, suggest.as_ref())?,
    }

    Ok(())
}

fn cmd_regenerate_imports(
    out: &Arc<dyn Out>,
    cfg: &Config,
    _sub_args: &RegenerateImportsArgs,
) -> Result<(), miette::Report> {
    trace!("regenerating imports...");

    if cfg.cli.locked {
        // ERRORS: just a warning that you're holding it wrong, unclear if immediate or buffered,
        // or if this should be a hard error, or if we should ignore the --locked flag and
        // just do it anyway
        writeln!(
            out,
            "warning: ran `regenerate imports` with --locked, this won't do anything!"
        );
        return Ok(());
    }

    let network = Network::acquire(cfg);
    let mut store = Store::acquire(cfg, network.as_ref(), true)?;

    // Update the store state, pruning unnecessary exemptions, and cleaning out
    // unnecessary old imports.
    resolver::update_store(cfg, &mut store, |_| resolver::UpdateMode {
        search_mode: resolver::SearchMode::PreferFreshImports,
        prune_exemptions: true,
        prune_imports: true,
    });

    store.commit()?;
    Ok(())
}

fn cmd_regenerate_audit_as(
    _out: &Arc<dyn Out>,
    cfg: &Config,
    _sub_args: &RegenerateAuditAsCratesIoArgs,
) -> Result<(), miette::Report> {
    trace!("regenerating audit-as-crates-io...");
    let network = Network::acquire(cfg);
    let mut store = Store::acquire_offline(cfg)?;

    tokio::runtime::Handle::current().block_on(fix_audit_as(cfg, network.as_ref(), &mut store))?;

    // We were successful, commit the store
    store.commit()?;

    Ok(())
}

fn cmd_regenerate_unpublished(
    out: &Arc<dyn Out>,
    cfg: &Config,
    _sub_args: &RegenerateUnpublishedArgs,
) -> Result<(), miette::Report> {
    trace!("regenerating unpublished entries...");

    if cfg.cli.locked {
        // ERRORS: just a warning that you're holding it wrong, unclear if immediate or buffered,
        // or if this should be a hard error, or if we should ignore the --locked flag and
        // just do it anyway
        writeln!(
            out,
            "warning: ran `regenerate unpublished` with --locked, this won't do anything!"
        );
        return Ok(());
    }

    let network = Network::acquire(cfg);
    let mut store = Store::acquire(cfg, network.as_ref(), false)?;

    // Strip all non-fresh entries from the unpublished table, marking the
    // previously fresh entries as non-fresh.
    if let Some(live_imports) = &mut store.live_imports {
        for unpublished in live_imports.unpublished.values_mut() {
            unpublished.retain_mut(|u| std::mem::replace(&mut u.is_fresh_import, false));
        }
    }

    // Run a minimal store update to import new entries which would now be
    // required for `check` to pass. Note that this won't ensure `check`
    // actually passes after the change.
    resolver::update_store(cfg, &mut store, |_| resolver::UpdateMode {
        search_mode: resolver::SearchMode::PreferExemptions,
        prune_exemptions: false,
        prune_imports: false,
    });

    store.commit()?;
    Ok(())
}

fn cmd_renew(out: &Arc<dyn Out>, cfg: &Config, sub_args: &RenewArgs) -> Result<(), miette::Report> {
    trace!("renewing wildcard audits");
    let mut store = Store::acquire_offline(cfg)?;
    do_cmd_renew(out, cfg, &mut store, sub_args);
    store.commit()?;
    Ok(())
}

fn do_cmd_renew(out: &Arc<dyn Out>, cfg: &Config, store: &mut Store, sub_args: &RenewArgs) {
    assert!(sub_args.expiring ^ sub_args.crate_name.is_some());

    // We need the cache to map user ids to user names, though we can work around it if there is an
    // error.
    let cache = Cache::acquire(cfg).ok();

    let new_end_date = cfg.today() + chrono::Months::new(12);

    let mut renewing: WildcardAuditRenewal;

    if let Some(name) = &sub_args.crate_name {
        match WildcardAuditRenewal::single_crate(name, store) {
            Some(renewal) => {
                renewing = renewal;
                if renewing.is_empty() {
                    info!("no wildcard audits for {name} are eligible for renewal (all have `renew = false`)");
                    return;
                }
            }
            None => {
                warn!("ran `renew {name}`, but there are no wildcard audits for the crate");
                return;
            }
        }
    } else {
        // Find and update all expiring crates.
        assert!(sub_args.expiring);
        renewing = WildcardAuditRenewal::expiring(cfg, store);

        if renewing.is_empty() {
            info!("no wildcard audits that are eligible for renewal have expired or are expiring in the next {WILDCARD_AUDIT_EXPIRATION_STRING}");
            return;
        }
    }

    renewing.renew(new_end_date);

    writeln!(
        out,
        "Updated wildcard audits for the following crates and publishers to expire on {new_end_date}:"
    );

    let user_string = |user_id: u64| -> String {
        cache
            .as_ref()
            .and_then(|c| c.get_crates_user_info(user_id))
            .map(|n| n.to_string())
            .unwrap_or_else(|| format!("id={}", user_id))
    };
    for (name, entries) in renewing.crates {
        writeln!(
            out,
            "  {}: {:80}",
            name,
            string_format::FormatShortList::new(
                entries
                    .iter()
                    .map(|(entry, _)| user_string(entry.user_id))
                    .collect()
            )
        );
    }
}

/// Adjust the store to satisfy audit-as-crates-io issues
///
/// Every reported issue will be resolved by just setting `audit-as-crates-io = Some(false)`,
/// because that always works, no matter what the problem is.
async fn fix_audit_as(
    cfg: &Config,
    network: Option<&Network>,
    store: &mut Store,
) -> Result<(), CacheAcquireError> {
    let _spinner = indeterminate_spinner("Fetching", "crate metadata");

    let mut cache = Cache::acquire(cfg)?;

    let third_party_packages = foreign_packages_strict(&cfg.metadata, &store.config)
        .map(|p| &p.name)
        .collect::<SortedSet<_>>();

    let issues = check_audit_as_crates_io(cfg, store, network, &mut cache).await;
    if let Err(AuditAsErrors { errors }) = issues {
        fn get_policy_entry<'a>(
            store: &'a mut Store,
            cfg: &Config,
            third_party_packages: &SortedSet<&String>,
            error: &PackageError,
        ) -> &'a mut PolicyEntry {
            let is_third_party = third_party_packages.contains(&error.package);
            let all_versions = || {
                cfg.metadata
                    .packages
                    .iter()
                    .filter_map(|p| (p.name == error.package).then(|| p.vet_version()))
                    .collect()
            };
            // This can only fail if there's a logical error in `check_audit_as_crates_io`.
            store
                .config
                .policy
                .get_mut_or_default(
                    error.package.clone(),
                    is_third_party.then_some(error.version.as_ref()).flatten(),
                    all_versions,
                )
                .expect("unexpected crate policy state")
        }

        for error in errors {
            match error {
                AuditAsError::NeedsAuditAs(NeedsAuditAsErrors { errors }) => {
                    for err in errors {
                        // We'll default audit-as-crates-io to true if the
                        // crate's description or repository matches an existing
                        // package on crates.io.
                        //
                        // XXX: This is just indended to reduce the chance of
                        // false positives, but is certainly a bit of a loose
                        // comparison. If it turns out to be an issue we can
                        // improve it in the future.
                        let default_audit_as = if network.is_some() {
                            // NOTE: Handle all errors silently here, as we can always recover by
                            // setting `audit-as-crates-io = false`. The error cases below are very
                            // unlikely to occur since information will be cached from the initial
                            // checks which generated the NeedsAuditAsErrors.
                            let crates_api_metadata =
                                match cache.get_crate_metadata(network, &err.package).await {
                                    Ok(v) => v,
                                    Err(e) => {
                                        warn!("crate metadata error for {}: {e}", &err.package);
                                        Default::default()
                                    }
                                };

                            cfg.metadata.packages.iter().any(|p| {
                                p.name == err.package && crates_api_metadata.consider_as_same(p)
                            })
                        } else {
                            false
                        };

                        get_policy_entry(store, cfg, &third_party_packages, &err)
                            .audit_as_crates_io = Some(default_audit_as);
                    }
                }
                AuditAsError::ShouldntBeAuditAs(ShouldntBeAuditAsErrors { errors }) => {
                    for err in errors {
                        get_policy_entry(store, cfg, &third_party_packages, &err)
                            .audit_as_crates_io = Some(false);
                    }
                }
                AuditAsError::UnusedAuditAs(unuseds) => {
                    for err in unuseds.errors {
                        // XXX: consider removing the policy completely if
                        // there's nothing left in it anymore?
                        if let Some(policy) = store
                            .config
                            .policy
                            .get_mut(&err.package, err.version.as_ref())
                        {
                            policy.audit_as_crates_io = None;
                        }
                    }
                }
            }
        }
    }
    Ok(())
}

fn cmd_regenerate_exemptions(
    _out: &Arc<dyn Out>,
    cfg: &Config,
    _sub_args: &RegenerateExemptionsArgs,
) -> Result<(), miette::Report> {
    trace!("regenerating exemptions...");
    let network = Network::acquire(cfg);
    let mut store = Store::acquire(cfg, network.as_ref(), false)?;

    // Update the store using a full RegenerateExemptions search.
    resolver::update_store(cfg, &mut store, |_| resolver::UpdateMode {
        search_mode: resolver::SearchMode::RegenerateExemptions,
        prune_exemptions: true,
        prune_imports: true,
    });

    // We were successful, commit the store
    store.commit()?;

    Ok(())
}

fn cmd_diff(out: &Arc<dyn Out>, cfg: &Config, sub_args: &DiffArgs) -> Result<(), miette::Report> {
    let version1 = &sub_args.version1;
    let version2 = &sub_args.version2;
    let package = &*sub_args.package;

    let to_compare = {
        let network = Network::acquire(cfg);
        let store = Store::acquire(cfg, network.as_ref(), false)?;
        let cache = Cache::acquire(cfg)?;

        // Record this command for magic in `vet certify`
        cache.set_last_fetch(FetchCommand::Diff {
            package: package.to_owned(),
            version1: version1.clone(),
            version2: version2.clone(),
        });

        if sub_args.mode == FetchMode::Sourcegraph
            && version1.git_rev.is_none()
            && version2.git_rev.is_none()
        {
            let url = format!(
                "https://sourcegraph.com/crates/{package}/-/compare/v{version1}...v{version2}?visible=1000000"
            );
            tokio::runtime::Handle::current()
                .block_on(prompt_criteria_eulas(
                    out,
                    cfg,
                    network.as_ref(),
                    &store,
                    package,
                    Some(version1),
                    version2,
                    Some(&url),
                ))
                .into_diagnostic()?;

            open::that(&url).into_diagnostic().wrap_err_with(|| {
                format!("Couldn't open {url} in your browser, try --mode=local?")
            })?;

            writeln!(out, "\nUse |cargo vet certify| to record your audit.");

            return Ok(());
        }

        tokio::runtime::Handle::current().block_on(async {
            // NOTE: don't `try_join` everything as we don't want to abort the
            // prompt to the user if the download fails while it is being shown, as
            // that could be disorienting.
            let (to_compare, eulas) = tokio::join!(
                async {
                    let (pkg1, pkg2) = tokio::try_join!(
                        cache.fetch_package(&cfg.metadata, network.as_ref(), package, version1),
                        cache.fetch_package(&cfg.metadata, network.as_ref(), package, version2)
                    )?;
                    let (_, to_compare) = cache
                        .diffstat_package(
                            &pkg1,
                            &pkg2,
                            version1.git_rev.is_some() || version2.git_rev.is_some(),
                        )
                        .await?;
                    Ok::<_, FetchAndDiffError>(to_compare)
                },
                prompt_criteria_eulas(
                    out,
                    cfg,
                    network.as_ref(),
                    &store,
                    package,
                    Some(version1),
                    version2,
                    None,
                )
            );
            eulas.into_diagnostic()?;
            to_compare.into_diagnostic()
        })?
    };

    writeln!(out);

    // Start a pager to show the output from our diff invocations. This will
    // fall back to just printing to `stdout` if no pager is available or we're
    // not piped to a terminal.
    let mut pager = Pager::new(&**out).into_diagnostic()?;

    for (from, to) in to_compare {
        let output = std::process::Command::new("git")
            .arg("-c")
            .arg("core.safecrlf=false")
            .arg("diff")
            .arg(if pager.use_color() {
                "--color=always"
            } else {
                "--color=never"
            })
            .arg("--no-index")
            .arg("--ignore-cr-at-eol")
            .arg(&from)
            .arg(&to)
            .stdout(Stdio::piped())
            .output()
            .map_err(CommandError::CommandFailed)
            .into_diagnostic()?;
        io::Write::write_all(&mut pager, &output.stdout).into_diagnostic()?;
    }

    pager.wait().into_diagnostic()?;

    writeln!(out, "\nUse |cargo vet certify| to record your audit.");

    Ok(())
}

fn cmd_check(
    out: &Arc<dyn Out>,
    cfg: &Config,
    _sub_args: &CheckArgs,
) -> Result<(), miette::Report> {
    // Run the checker to validate that the current set of deps is covered by the current cargo vet store
    trace!("vetting...");

    let network = Network::acquire(cfg);
    let mut store = Store::acquire(cfg, network.as_ref(), false)?;

    if !cfg.cli.locked {
        // Check if any of our first-parties are in the crates.io registry
        let mut cache = Cache::acquire(cfg).into_diagnostic()?;
        // Check crate policies prior to audit_as_crates_io because the suggestions of
        // check_audit_as_crates_io will rely on the correct structure of crate policies.
        check_crate_policies(cfg, &store)?;
        tokio::runtime::Handle::current().block_on(check_audit_as_crates_io(
            cfg,
            &store,
            network.as_ref(),
            &mut cache,
        ))?;
    }

    // DO THE THING!!!!
    let report = resolver::resolve(&cfg.metadata, cfg.cli.filter_graph.as_ref(), &store);

    // Bare `cargo vet` shouldn't suggest in CI
    let suggest = if !cfg.cli.locked {
        report.compute_suggest(cfg, &store, network.as_ref())?
    } else {
        None
    };

    match cfg.cli.output_format {
        OutputFormat::Human => report
            .print_human(out, cfg, suggest.as_ref())
            .into_diagnostic()?,
        OutputFormat::Json => report.print_json(out, suggest.as_ref())?,
    }

    // Only save imports if we succeeded, to avoid any modifications on error.
    if report.has_errors() {
        // ERRORS: immediate fatal diagnostic? Arguably should be silent.
        // Err(eyre!("report contains errors"))?;
        panic_any(ExitPanic(-1));
    } else {
        if !cfg.cli.locked {
            // Simulate a full `fetch-imports` run, and record the potential
            // pruned imports and exemptions.
            let (pruned_imports, pruned_exemptions) =
                resolver::get_store_updates(cfg, &store, |_| resolver::UpdateMode {
                    search_mode: resolver::SearchMode::PreferFreshImports,
                    prune_exemptions: true,
                    prune_imports: true,
                });

            // Perform a minimal store update to pull in necessary imports,
            // while avoiding any other changes to exemptions or imports.
            resolver::update_store(cfg, &mut store, |_| resolver::UpdateMode {
                search_mode: resolver::SearchMode::PreferExemptions,
                prune_exemptions: false,
                prune_imports: false,
            });

            // XXX: Consider trying to be more precise here? Would require some
            // more clever comparisons.
            if store.config.exemptions != pruned_exemptions {
                warn!("Your supply-chain has unnecessary exemptions which could be relaxed or pruned.");
                warn!("  Consider running `cargo vet prune` to prune unnecessary exemptions and imports.");
            } else if store.imports != pruned_imports {
                warn!("Your supply-chain has unnecessary imports which could be pruned.");
                warn!("  Consider running `cargo vet prune` to prune unnecessary imports.");
            }

            // Check if we have `unpublished` entries for crates which have since been published.
            let since_published: Vec<_> = pruned_imports
                .unpublished
                .iter()
                .filter(|(_, unpublished)| unpublished.iter().any(|u| !u.still_unpublished))
                .map(|(package, _)| package)
                .collect();
            if !since_published.is_empty() {
                let published = string_format::FormatShortList::new(since_published);
                warn!("Your supply-chain depends on previously unpublished versions of {published} which have since been published.");
                warn!("  Consider running `cargo vet regenerate unpublished` to remove these entries.");
            }

            // Warn about wildcard audits which will be expiring soon or have expired.
            let expiry = WildcardAuditRenewal::expiring(cfg, &mut store);

            if !expiry.is_empty() {
                let expired = expiry.expired_crates();
                let expiring_soon = expiry.expiring_crates();
                if !expired.is_empty() {
                    let expired = string_format::FormatShortList::new(expired);
                    warn!(
                        "Your audit set contains wildcard audits for {expired} which have expired."
                    );
                }
                if !expiring_soon.is_empty() {
                    let expiring = string_format::FormatShortList::new(expiring_soon);
                    warn!("Your audit set contains wildcard audits for {expiring} which expire within the next {WILDCARD_AUDIT_EXPIRATION_STRING}.");
                }
                warn!("  Consider running `cargo vet renew --expiring` or adding `renew = false` to the wildcard entries in audits.toml.");
            }
        }

        store.commit()?;
    }

    Ok(())
}

#[derive(Default)]
struct WildcardAuditRenewal<'a> {
    // the bool indicates whether the entry for that user id is already expired (true) or will
    // expire soon (false)
    pub crates: SortedMap<PackageStr<'a>, Vec<(&'a mut WildcardEntry, bool)>>,
}

impl<'a> WildcardAuditRenewal<'a> {
    /// Get all wildcard audit entries which have expired or will expire soon.
    ///
    /// This function _does not_ modify the store, but since the mutable references to the entries
    /// are stored (for potential use by `renew`), it must take a mutable Store.
    pub fn expiring(cfg: &Config, store: &'a mut Store) -> Self {
        let expire_date = cfg.today() + *WILDCARD_AUDIT_EXPIRATION_DURATION;

        let mut crates: SortedMap<PackageStr<'a>, Vec<(&'a mut WildcardEntry, bool)>> =
            Default::default();
        for (name, audits) in store.audits.wildcard_audits.iter_mut() {
            // Check whether there are any audits expiring by the expiration date. Of those
            // audits, check whether all of them are already expired (to change the warning
            // message to be more informative).
            for entry in audits.iter_mut().filter(|e| e.should_renew(expire_date)) {
                let expired = entry.should_renew(cfg.today());
                crates.entry(name).or_default().push((entry, expired));
            }
        }

        WildcardAuditRenewal { crates }
    }

    /// Create a renewal with a single crate explicitly provided.
    ///
    /// This will renew all eligible audits, regardless of expiration. Thus `expired_crates` and
    /// `expiring_crates` should not be used.
    pub fn single_crate(name: PackageStr<'a>, store: &'a mut Store) -> Option<Self> {
        let mut crates: SortedMap<PackageStr<'a>, Vec<(&'a mut WildcardEntry, bool)>> =
            Default::default();
        let audits = store.audits.wildcard_audits.get_mut(name)?;
        for entry in audits {
            if entry.renew.unwrap_or(true) {
                // We don't care about the expiring/expired, so insert with false.
                crates.entry(name).or_default().push((entry, false));
            }
        }
        Some(WildcardAuditRenewal { crates })
    }

    /// Whether there are no wildcard audits expiring or expired.
    pub fn is_empty(&self) -> bool {
        self.crates.is_empty()
    }

    /// Get the crate names for which wildcard audits have expired.
    pub fn expired_crates(&'a self) -> Vec<PackageStr<'a>> {
        self.crates
            .iter()
            .filter_map(|(name, ids)| ids.iter().any(|(_, expired)| *expired).then_some(*name))
            .collect()
    }

    /// Get the crate names for which wildcard audits will expire soon.
    pub fn expiring_crates(&'a self) -> Vec<PackageStr<'a>> {
        self.crates
            .iter()
            .filter_map(|(name, ids)| ids.iter().any(|(_, expired)| !*expired).then_some(*name))
            .collect()
    }

    /// Renew all stored entries.
    pub fn renew(&mut self, new_end_date: chrono::NaiveDate) {
        for entry in self
            .crates
            .values_mut()
            .flat_map(|v| v.iter_mut().map(|t| &mut t.0))
        {
            entry.end = new_end_date.into();
        }
    }
}

fn cmd_prune(
    _out: &Arc<dyn Out>,
    cfg: &Config,
    sub_args: &PruneArgs,
) -> Result<(), miette::Report> {
    let network = Network::acquire(cfg);
    let mut store = Store::acquire(cfg, network.as_ref(), false)?;

    let _spinner = indeterminate_spinner("Pruning", "unnecessary imports and exemptions");

    // Update the store with the live state, pruning unnecessary exemptions and
    // imports.
    resolver::update_store(cfg, &mut store, |_| resolver::UpdateMode {
        search_mode: if sub_args.no_exemptions {
            resolver::SearchMode::PreferExemptions
        } else {
            resolver::SearchMode::PreferFreshImports
        },
        prune_exemptions: !sub_args.no_exemptions,
        prune_imports: !sub_args.no_imports,
    });

    store.commit()?;

    Ok(())
}

fn cmd_aggregate(
    out: &Arc<dyn Out>,
    cfg: &PartialConfig,
    sub_args: &AggregateArgs,
) -> Result<(), miette::Report> {
    let network =
        Network::acquire(cfg).ok_or_else(|| miette!("cannot aggregate imports when --frozen"))?;

    let mut urls = Vec::new();
    {
        let sources_file = BufReader::new(
            File::open(&sub_args.sources)
                .into_diagnostic()
                .wrap_err("failed to open sources file")?,
        );
        for line_result in sources_file.lines() {
            let line = line_result
                .into_diagnostic()
                .wrap_err("failed to read sources file")?;
            let trimmed = line.trim();
            if trimmed.is_empty() || trimmed.starts_with('#') {
                // Ignore comment and empty lines.
                continue;
            }
            urls.push(
                Url::parse(trimmed)
                    .into_diagnostic()
                    .wrap_err_with(|| format!("failed to parse url: {trimmed:?}"))?,
            );
        }
    }

    let progress_bar = progress_bar("Fetching", "source audits", urls.len() as u64);
    let sources = tokio::runtime::Handle::current()
        .block_on(try_join_all(urls.into_iter().map(|url| async {
            let _guard = IncProgressOnDrop(&progress_bar, 1);
            let url_string = url.to_string();
            let audit_bytes = network.download(url).await?;
            let audit_string = String::from_utf8(audit_bytes).map_err(LoadTomlError::from)?;
            let audit_source = SourceFile::new(&url_string, audit_string.clone());
            let audit_file: AuditsFile = toml::de::from_str(&audit_string)
                .map_err(|error| {
                    let (line, col) = error.line_col().unwrap_or((0, 0));
                    TomlParseError {
                        source_code: audit_source,
                        span: SourceOffset::from_location(&audit_string, line + 1, col + 1),
                        error,
                    }
                })
                .map_err(LoadTomlError::from)?;
            Ok::<_, FetchAuditError>((url_string, audit_file))
        })))
        .into_diagnostic()?;

    let merged_audits = do_aggregate_audits(sources).into_diagnostic()?;
    let document = serialization::to_formatted_toml(merged_audits, None).into_diagnostic()?;
    write!(out, "{document}");
    Ok(())
}

fn do_aggregate_audits(sources: Vec<(String, AuditsFile)>) -> Result<AuditsFile, AggregateErrors> {
    let mut errors = Vec::new();
    let mut aggregate = AuditsFile {
        criteria: SortedMap::new(),
        wildcard_audits: SortedMap::new(),
        audits: SortedMap::new(),
        // FIXME: How should we handle aggregating trusted entries? Should we do
        // any form of de-duplication?
        trusted: SortedMap::new(),
    };

    for (source, audit_file) in sources {
        // Add each criteria from the original source, managing duplicates by
        // ensuring that their descriptions map 1:1.
        for (criteria_name, mut criteria_entry) in audit_file.criteria {
            match aggregate.criteria.entry(criteria_name) {
                std::collections::btree_map::Entry::Vacant(vacant) => {
                    criteria_entry.aggregated_from.push(source.clone().into());
                    vacant.insert(criteria_entry);
                }
                std::collections::btree_map::Entry::Occupied(occupied) => {
                    let prev_source = occupied
                        .get()
                        .aggregated_from
                        .last()
                        .map(|s| s.to_string())
                        .unwrap_or_default();
                    // NOTE: We don't record the new `aggregated_from` chain in
                    // this case, as we already have a chain for the existing
                    // entry which we don't want to clobber. This means that
                    // source order in the `sources.list` file can impact where
                    // your criteria are credited to originate from.
                    if occupied.get().description != criteria_entry.description
                        || occupied.get().description_url != criteria_entry.description_url
                    {
                        errors.push(AggregateError::CriteriaDescriptionMismatch(
                            AggregateCriteriaDescriptionMismatchError {
                                criteria_name: occupied.key().to_owned(),
                                first: AggregateCriteriaDescription {
                                    source: prev_source.clone(),
                                    description: occupied.get().description.clone(),
                                    description_url: occupied.get().description_url.clone(),
                                },
                                second: AggregateCriteriaDescription {
                                    source: source.clone(),
                                    description: criteria_entry.description.clone(),
                                    description_url: criteria_entry.description_url.clone(),
                                },
                            },
                        ))
                    }
                    if occupied.get().implies != criteria_entry.implies {
                        errors.push(AggregateError::ImpliesMismatch(
                            AggregateImpliesMismatchError {
                                criteria_name: occupied.key().to_owned(),
                                first: AggregateCriteriaImplies {
                                    source: prev_source.clone(),
                                    implies: occupied
                                        .get()
                                        .implies
                                        .iter()
                                        .map(|c| c.to_string())
                                        .collect(),
                                },
                                second: AggregateCriteriaImplies {
                                    source: source.clone(),
                                    implies: criteria_entry
                                        .implies
                                        .iter()
                                        .map(|c| c.to_string())
                                        .collect(),
                                },
                            },
                        ));
                    }
                }
            }
        }
        for (package_name, entries) in audit_file.audits {
            aggregate
                .audits
                .entry(package_name)
                .or_default()
                .extend(entries.into_iter().map(|mut audit_entry| {
                    audit_entry.aggregated_from.push(source.clone().into());
                    audit_entry
                }));
        }
        for (package_name, entries) in audit_file.wildcard_audits {
            aggregate
                .wildcard_audits
                .entry(package_name)
                .or_default()
                .extend(entries.into_iter().map(|mut wildcard_entry| {
                    wildcard_entry.aggregated_from.push(source.clone().into());
                    wildcard_entry
                }));
        }
        for (package_name, entries) in audit_file.trusted {
            aggregate
                .trusted
                .entry(package_name)
                .or_default()
                .extend(entries.into_iter().map(|mut trusted_entry| {
                    trusted_entry.aggregated_from.push(source.clone().into());
                    trusted_entry
                }));
        }
    }
    if errors.is_empty() {
        Ok(aggregate)
    } else {
        Err(AggregateErrors { errors })
    }
}

fn cmd_dump_graph(
    out: &Arc<dyn Out>,
    cfg: &Config,
    sub_args: &DumpGraphArgs,
) -> Result<(), miette::Report> {
    // Dump a mermaid-js graph
    trace!("dumping...");

    let graph = resolver::DepGraph::new(&cfg.metadata, cfg.cli.filter_graph.as_ref(), None);
    match cfg.cli.output_format {
        OutputFormat::Human => graph.print_mermaid(out, sub_args).into_diagnostic()?,
        OutputFormat::Json => {
            serde_json::to_writer_pretty(&**out, &graph.nodes).into_diagnostic()?
        }
    }

    Ok(())
}

fn cmd_fmt(_out: &Arc<dyn Out>, cfg: &Config, _sub_args: &FmtArgs) -> Result<(), miette::Report> {
    // Reformat all the files (just load and store them, formatting is implicit).
    trace!("formatting...");
    // We don't need to fetch foreign audits to format files
    let store = Store::acquire_offline(cfg)?;
    store.commit()?;
    Ok(())
}

/// Perform crimes on clap long_help to generate markdown docs
fn cmd_help_md(
    out: &Arc<dyn Out>,
    _cfg: &PartialConfig,
    _sub_args: &HelpMarkdownArgs,
) -> Result<(), miette::Report> {
    let app_name = "cargo-vet";
    let pretty_app_name = "cargo vet";
    // Make a new App to get the help message this time.

    writeln!(out, "# {pretty_app_name} CLI manual");
    writeln!(out);
    writeln!(
        out,
        "> This manual can be regenerated with `{pretty_app_name} help-markdown`"
    );
    writeln!(out);

    let mut fake_cli = FakeCli::command().term_width(0);
    let full_command = fake_cli.get_subcommands_mut().next().unwrap();
    full_command.build();
    let mut todo = vec![full_command];
    let mut is_full_command = true;

    while let Some(command) = todo.pop() {
        let mut help_buf = Vec::new();
        command.write_long_help(&mut help_buf).unwrap();
        let help = String::from_utf8(help_buf).unwrap();

        // First line is --version
        let mut lines = help.lines();
        let version_line = lines.next().unwrap();
        let subcommand_name = command.get_name();

        if is_full_command {
            writeln!(out, "Version: `{version_line}`");
            writeln!(out);
        } else {
            // Give subcommands some breathing room
            writeln!(out, "<br><br><br>");
            writeln!(out, "## {pretty_app_name} {subcommand_name}");
        }

        let mut in_subcommands_listing = false;
        let mut in_usage = false;
        let mut in_global_options = false;
        for line in lines {
            // Use a trailing colon to indicate a heading
            if let Some(heading) = line.strip_suffix(':') {
                if !line.starts_with(' ') {
                    // SCREAMING headers are Main headings
                    if heading.to_ascii_uppercase() == heading {
                        in_subcommands_listing = heading == "SUBCOMMANDS";
                        in_usage = heading == "USAGE";
                        in_global_options = heading == "GLOBAL OPTIONS";

                        writeln!(out, "### {heading}");

                        if in_global_options && !is_full_command {
                            writeln!(
                                out,
                                "This subcommand accepts all the [global options](#global-options)"
                            );
                        }
                    } else {
                        writeln!(out, "### {heading}");
                    }
                    continue;
                }
            }

            if in_global_options && !is_full_command {
                // Skip global options for non-primary commands
                continue;
            }

            if in_subcommands_listing && !line.starts_with("     ") {
                // subcommand names are list items
                let own_subcommand_name = line.trim();
                write!(
                    out,
                    "* [{own_subcommand_name}](#{app_name}-{own_subcommand_name}): "
                );
                continue;
            }
            // The rest is indented, get rid of that
            let line = line.trim();

            // Usage strings get wrapped in full code blocks
            if in_usage && line.starts_with(pretty_app_name) {
                writeln!(out, "```");
                writeln!(out, "{line}");
                writeln!(out, "```");
                continue;
            }

            // argument names are subheadings
            if line.starts_with('-') || line.starts_with('<') {
                writeln!(out, "#### `{line}`");
                continue;
            }

            // escape default/value strings
            if line.starts_with('[') {
                writeln!(out, "\\{line}  ");
                continue;
            }

            // Normal paragraph text
            writeln!(out, "{line}");
        }
        writeln!(out);

        // The todo list is a stack, and processed in reverse-order, append
        // these commands to the end in reverse-order so the first command is
        // processed first (i.e. at the end of the list).
        todo.extend(
            command
                .get_subcommands_mut()
                .filter(|cmd| !cmd.is_hide_set())
                .collect::<Vec<_>>()
                .into_iter()
                .rev(),
        );
        is_full_command = false;
    }

    Ok(())
}

fn cmd_gc(
    out: &Arc<dyn Out>,
    cfg: &PartialConfig,
    sub_args: &GcArgs,
) -> Result<(), miette::Report> {
    let cache = Cache::acquire(cfg)?;

    if sub_args.clean {
        writeln!(
            out,
            "cleaning entire contents of cache directory: {}",
            cfg.cache_dir.display()
        );
        cache.clean_sync().into_diagnostic()?;
        return Ok(());
    }

    if sub_args.max_package_age_days.is_nan() {
        return Err(miette!("max package age cannot be NaN"));
    }
    if sub_args.max_package_age_days < 0.0 {
        return Err(miette!("max package age cannot be negative"));
    }

    cache.gc_sync(DURATION_DAY.mul_f64(sub_args.max_package_age_days));
    Ok(())
}

// Utils

struct UserInfo {
    username: String,
    email: String,
}

fn get_user_info() -> Result<UserInfo, UserInfoError> {
    fn get_git_config(value_name: &str) -> Result<String, CommandError> {
        let out = std::process::Command::new("git")
            .arg("config")
            .arg("--get")
            .arg(value_name)
            .output()
            .map_err(CommandError::CommandFailed)?;

        if !out.status.success() {
            return Err(CommandError::BadStatus(out.status.code().unwrap()));
        }
        String::from_utf8(out.stdout)
            .map(|s| s.trim().to_string())
            .map_err(CommandError::BadOutput)
    }

    let username = get_git_config("user.name").map_err(UserInfoError::UserCommandFailed)?;
    let email = get_git_config("user.email").map_err(UserInfoError::EmailCommandFailed)?;

    Ok(UserInfo { username, email })
}

async fn eula_for_criteria(
    network: Option<&Network>,
    criteria_map: &SortedMap<CriteriaName, CriteriaEntry>,
    criteria: CriteriaStr<'_>,
) -> String {
    let builtin_eulas = [
        (
            format::SAFE_TO_DEPLOY,
            include_str!("criteria/safe-to-deploy.txt"),
        ),
        (
            format::SAFE_TO_RUN,
            include_str!("criteria/safe-to-run.txt"),
        ),
    ]
    .into_iter()
    .collect::<HashMap<_, _>>();

    // Several fallbacks
    // * Try to get the builtin criteria
    // * Try to get the criteria's description
    // * Try to fetch the criteria's url
    // * Just display the url

    // First try the builtins
    let builtin = builtin_eulas.get(criteria).map(|s| s.to_string());
    if let Some(eula) = builtin {
        return eula;
    }

    // ERRORS: the caller should have verified this entry already!
    let criteria_entry = criteria_map
        .get(criteria)
        .unwrap_or_else(|| panic!("no entry for the criteria {criteria}"));
    assert!(
        criteria_entry.description.is_some() || criteria_entry.description_url.is_some(),
        "entry for criteria {criteria} is corrupt!"
    );

    // Now try the description
    if let Some(eula) = criteria_entry.description.clone() {
        return eula;
    }

    // If we get here then there must be a URL, try to fetch it. If it fails, just print the URL
    let url = Url::parse(criteria_entry.description_url.as_ref().unwrap()).unwrap();
    if let Some(network) = network {
        if let Ok(eula) = network.download(url.clone()).await.and_then(|bytes| {
            String::from_utf8(bytes).map_err(|error| DownloadError::InvalidText {
                url: Box::new(url.clone()),
                error,
            })
        }) {
            return eula;
        }
    }

    // If we get here then the download failed, just print the URL
    format!("Could not download criteria description, it should be available at {url}")
}

/// All third-party packages, with the audit-as-crates-io policy applied
fn foreign_packages<'a>(
    metadata: &'a Metadata,
    config: &'a ConfigFile,
) -> impl Iterator<Item = &'a Package> + 'a {
    // Only analyze things from crates.io (no source = path-dep / workspace-member)
    metadata
        .packages
        .iter()
        .filter(|package| package.is_third_party(&config.policy))
}

/// All first-party packages, **without** the audit-as-crates-io policy applied
/// (because it's used for validating that field's value).
fn first_party_packages_strict<'a>(
    metadata: &'a Metadata,
    _config: &'a ConfigFile,
) -> impl Iterator<Item = &'a Package> + 'a {
    metadata
        .packages
        .iter()
        .filter(move |package| !package.is_crates_io())
}

/// All third-party packages, **without** the audit-as-crates-io policy applied (used in crate
/// policy verification).
fn foreign_packages_strict<'a>(
    metadata: &'a Metadata,
    _config: &ConfigFile,
) -> impl Iterator<Item = &'a Package> + 'a {
    metadata
        .packages
        .iter()
        .filter(move |package| package.is_crates_io())
}

async fn check_audit_as_crates_io(
    cfg: &Config,
    store: &Store,
    network: Option<&Network>,
    cache: &mut Cache,
) -> Result<(), AuditAsErrors> {
    let first_party_packages: Vec<_> =
        first_party_packages_strict(&cfg.metadata, &store.config).collect();

    let mut errors = vec![];

    {
        let mut unused_audit_as: SortedSet<(PackageName, Option<VetVersion>)> = store
            .config
            .policy
            .iter()
            .filter(|(_, _, policy)| policy.audit_as_crates_io.is_some())
            .map(|(name, version, _)| (name.clone(), version.cloned()))
            .collect();

        for package in &first_party_packages {
            // Remove both versioned and unversioned entries
            unused_audit_as.remove(&(package.name.clone(), Some(package.vet_version())));
            unused_audit_as.remove(&(package.name.clone(), None));
        }
        if !unused_audit_as.is_empty() {
            errors.push(AuditAsError::UnusedAuditAs(UnusedAuditAsErrors {
                errors: unused_audit_as
                    .into_iter()
                    .map(|(package, version)| PackageError { package, version })
                    .collect(),
            }))
        }
    }

    // We should only check the audit-as-crates-io entries if we have a network, because we
    // shouldn't make recommendations based on potentially stale information.
    if network.is_some() {
        let progress = progress_bar(
            "Validating",
            "audit-as-crates-io specifications",
            first_party_packages.len() as u64,
        );

        enum CheckAction {
            NeedAuditAs,
            ShouldntBeAuditAs,
        }

        let actions: Vec<_> = join_all(first_party_packages.into_iter().map(|package| {
            let progress = &progress;
            let cache = &cache;
            async move {
                let _inc_progress = IncProgressOnDrop(progress, 1);

                let audit_policy = package
                    .policy_entry(&store.config.policy)
                    .and_then(|policy| policy.audit_as_crates_io);
                if audit_policy == Some(false) {
                    // They've explicitly said this is first-party so we don't care about what's in the
                    // registry.
                    return None;
                }

                // To avoid unnecessary metadata lookup, only do so for packages which exist in the
                // index. The case which doesn't work with this logic is if someone is using a
                // package before it has ever been published, and then later it is published (in
                // which case a third-party change causes a warning to unexpectedly come up).
                // However, this case is sufficiently unlikely that for now it's worth the initial
                // lookup to avoid unnecessarily trying to fetch metadata for unpublished crates.
                //
                // The caching logic already does this for us as an optimization, but since we may
                // need to look at the specific versions later, we fetch it anyway.
                let mut matches_crates_io_package = false;
                if let Ok(metadata) = cache.get_crate_metadata(network, &package.name).await {
                    matches_crates_io_package = metadata.consider_as_same(package);
                }

                if matches_crates_io_package && audit_policy.is_none() {
                    // We found a package that has similar metadata to one with the same name
                    // on crates.io: having no policy is an error.
                    return Some((CheckAction::NeedAuditAs, package));
                }
                if !matches_crates_io_package && audit_policy == Some(true) {
                    return Some((CheckAction::ShouldntBeAuditAs, package));
                }
                None
            }
        }))
        .await
        .into_iter()
        .flatten()
        .collect();

        let mut needs_audit_as_entry = vec![];
        let mut shouldnt_be_audit_as = vec![];

        for (action, package) in actions {
            match action {
                CheckAction::NeedAuditAs => {
                    needs_audit_as_entry.push(PackageError {
                        package: package.name.clone(),
                        version: Some(package.vet_version()),
                    });
                }
                CheckAction::ShouldntBeAuditAs => {
                    shouldnt_be_audit_as.push(PackageError {
                        package: package.name.clone(),
                        version: Some(package.vet_version()),
                    });
                }
            }
        }

        if !needs_audit_as_entry.is_empty() {
            errors.push(AuditAsError::NeedsAuditAs(NeedsAuditAsErrors {
                errors: needs_audit_as_entry,
            }));
        }
        if !shouldnt_be_audit_as.is_empty() {
            errors.push(AuditAsError::ShouldntBeAuditAs(ShouldntBeAuditAsErrors {
                errors: shouldnt_be_audit_as,
            }));
        }
    }

    if !errors.is_empty() {
        Err(AuditAsErrors { errors })
    } else {
        Ok(())
    }
}

/// Check crate policies for correctness.
///
/// This verifies two rules:
/// 1. Policies using `dependency-criteria` which relate to third-party crates must have associated
///    version(s). If a crate has any `dependency-criteria` specified and exists as a third-party
///    dependency anywhere in the dependency graph, all versions must be specified.
/// 2. Any versioned policies must correspond to a crate in the graph.
fn check_crate_policies(cfg: &Config, store: &Store) -> Result<(), CratePolicyErrors> {
    // All defined policy package names (to be removed).
    let mut policy_crates: SortedSet<&PackageName> = store.config.policy.package.keys().collect();

    // All defined policy (name, version) pairs (to be visited and removed).
    let mut versioned_policy_crates: SortedSet<(PackageName, VetVersion)> = store
        .config
        .policy
        .iter()
        .filter_map(|(name, version, _)| version.map(|version| (name.clone(), version.clone())))
        .collect();

    // The set of all third-party packages (for lookup of whether a crate has any third-party
    // versions in use).
    let third_party_packages = foreign_packages_strict(&cfg.metadata, &store.config)
        .map(|p| &p.name)
        .collect::<SortedSet<_>>();

    // The set of all packages which have a `dependency-criteria` specified in a policy.
    let dependency_criteria_packages = store
        .config
        .policy
        .iter()
        .filter_map(|(name, _, entry)| (!entry.dependency_criteria.is_empty()).then_some(name))
        .collect::<SortedSet<_>>();

    let mut needs_policy_version_errors = Vec::new();

    for package in &cfg.metadata.packages {
        policy_crates.remove(&package.name);

        let versioned_policy_exists =
            versioned_policy_crates.remove(&(package.name.clone(), package.vet_version()));

        // If a crate has at least one third-party package and some crate policy specifies a
        // `dependency-criteria`, a versioned policy for all used versions must exist.
        if third_party_packages.contains(&package.name)
            && dependency_criteria_packages.contains(&package.name)
            && !versioned_policy_exists
        {
            needs_policy_version_errors.push(PackageError {
                package: package.name.clone(),
                version: Some(package.vet_version()),
            });
        }
    }

    let unused_policy_version_errors: Vec<_> = policy_crates
        .into_iter()
        .map(|name| PackageError {
            package: name.clone(),
            version: None,
        })
        .chain(
            versioned_policy_crates
                .into_iter()
                .map(|(package, version)| PackageError {
                    package,
                    version: Some(version),
                }),
        )
        .collect();

    if !needs_policy_version_errors.is_empty() || !unused_policy_version_errors.is_empty() {
        let mut errors = Vec::new();
        if !needs_policy_version_errors.is_empty() {
            errors.push(CratePolicyError::NeedsVersion(NeedsPolicyVersionErrors {
                errors: needs_policy_version_errors,
            }));
        }
        if !unused_policy_version_errors.is_empty() {
            errors.push(CratePolicyError::UnusedVersion(UnusedPolicyVersionErrors {
                errors: unused_policy_version_errors,
            }));
        }
        Err(CratePolicyErrors { errors })
    } else {
        Ok(())
    }
}
