//! The Resolver is the heart of cargo-vet, and does all the work to validate the audits
//! for your current packages and to suggest fixes. This is done in 3 phases:
//!
//! 1. Resolving required criteria based on your policies
//! 2. Searching for audits which satisfy the required criteria
//! 3. Suggesting audits that would make your project pass validation
//!
//! # High-level Usage
//!
//! * [`resolve`] is the main entry point, Validating and Searching and producing a [`ResolveReport`]
//! * [`ResolveReport::compute_suggest`] does Suggesting and produces a [`Suggest`]
//! * various methods on [`ResolveReport`] and [`Suggest`] handle printing
//! * [`update_store`] handles automatically minimizing and generating exemptions and imports
//!
//! # Low-level Design
//!
//!
//! ## Resolve
//!
//! * construct the [`DepGraph`] and [`CriteriaMapper`]
//!     * the DepGraph contains computed facts like whether a node is a third-party or dev-only
//!       and includes a special topological sorting of the packages that prioritizes the normal
//!       build over the dev build (it's complicated...)
//!
//! * resolve_requirements: for each package, resolve what criteria it needs to be audited for
//!     * start with root targets and propagate requirements out towards leaf crates
//!     * policies can override requirements on the target crate and its dependencies
//!
//! * resolve_audits: for each package, resolve what criteria it's audited for
//!     * compute the [`AuditGraph`] and check for violations
//!     * for each criteria, search the for a connected path in the audit graph
//!     * check if the criteria are satisfied
//!         * if they are, record caveats which were required for the criteria
//!         * if they aren't record the criteria which failed, and how to fix them
//!
//!
//! ## Suggest
//!
//! * enumerate the failures and perform a number of diffstats based on the
//!   existing set of criteria, to suggest the best audit and criteria which could
//!   be used to allow the crate to vet successfully.

use cargo_metadata::{DependencyKind, Metadata, Node, PackageId};
use futures_util::future::join_all;
use miette::IntoDiagnostic;
use serde::{Deserialize, Serialize};
use std::cell::RefCell;
use std::cmp::Reverse;
use std::collections::BinaryHeap;
use std::sync::Arc;
use tracing::{trace, trace_span, warn};

use crate::cli::{DumpGraphArgs, GraphFilter, GraphFilterProperty, GraphFilterQuery, OutputFormat};
use crate::criteria::{CriteriaMapper, CriteriaSet};
use crate::errors::SuggestError;
use crate::format::{
    self, AuditEntry, AuditKind, AuditsFile, CratesCacheUser, CratesPublisher, CriteriaName, Delta,
    DiffStat, ExemptedDependency, FastMap, FastSet, ImportName, ImportsFile, JsonPackage,
    JsonReport, JsonReportConclusion, JsonReportFailForVet, JsonReportFailForViolationConflict,
    JsonReportSuccess, JsonSuggest, JsonSuggestItem, JsonVetFailure, PackageName, PackageStr,
    Policy, UnpublishedEntry, VetVersion, WildcardEntry,
};
use crate::format::{SortedMap, SortedSet};
use crate::network::Network;
use crate::out::{progress_bar, IncProgressOnDrop, Out};
use crate::storage::Cache;
use crate::string_format::FormatShortList;
use crate::{Config, PackageExt, Store};

pub struct ResolveReport<'a> {
    /// The Cargo dependency graph as parsed and understood by cargo-vet.
    ///
    /// All [`PackageIdx`][] values are indices into this graph's nodes.
    pub graph: DepGraph<'a>,

    /// Mappings between criteria names and CriteriaSets/Indices.
    pub criteria_mapper: CriteriaMapper,

    /// Low-level results for each package's individual criteria resolving
    /// analysis, indexed by [`PackageIdx`][]. Will be `None` for first-party
    /// crates or crates with violation conflicts.
    pub results: Vec<Option<ResolveResult>>,

    /// The final conclusion of our analysis.
    pub conclusion: Conclusion,
}

#[derive(Debug)]
pub enum Conclusion {
    Success(Success),
    FailForViolationConflict(FailForViolationConflict),
    FailForVet(FailForVet),
}

#[derive(Debug, Clone)]
pub struct Success {
    /// Third-party packages that were successfully vetted using only 'exemptions'
    pub vetted_with_exemptions: Vec<PackageIdx>,
    /// Third-party packages that were successfully vetted using both 'audits' and 'exemptions'
    pub vetted_partially: Vec<PackageIdx>,
    /// Third-party packages that were successfully vetted using only 'audits'
    pub vetted_fully: Vec<PackageIdx>,
}

#[derive(Debug, Clone)]
pub struct FailForViolationConflict {
    pub violations: Vec<(PackageIdx, Vec<ViolationConflict>)>,
}

#[derive(Debug)]
pub struct FailForVet {
    /// These packages are to blame and need to be fixed
    pub failures: Vec<(PackageIdx, AuditFailure)>,
    pub suggest: Option<Suggest>,
}

// FIXME: This format is pretty janky and unstable, so we probably should come
// up with an actually-useful format for this.
#[allow(clippy::large_enum_variant)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum ViolationConflict {
    UnauditedConflict {
        violation_source: Option<ImportName>,
        violation: AuditEntry,
        exemptions: ExemptedDependency,
    },
    AuditConflict {
        violation_source: Option<ImportName>,
        violation: AuditEntry,
        audit_source: Option<ImportName>,
        audit: AuditEntry,
    },
}

#[derive(Debug, Default)]
pub struct Suggest {
    pub suggestions: Vec<SuggestItem>,
    pub suggestions_by_criteria: SortedMap<CriteriaName, Vec<SuggestItem>>,
    pub total_lines: u64,
    pub warnings: Vec<String>,
}

#[derive(Debug, Clone)]
pub struct TrustHint {
    trusted_by: Vec<String>,
    publisher: CratesCacheUser,
    exact_version: bool,
}

#[derive(Debug, Clone)]
pub struct SuggestItem {
    pub package: PackageIdx,
    pub suggested_criteria: CriteriaSet,
    pub suggested_diff: DiffRecommendation,
    pub notable_parents: Vec<String>,
    pub publisher_login: Option<String>,
    pub trust_hint: Option<TrustHint>,
    pub is_sole_publisher: bool,
    pub registry_suggestion: Vec<RegistrySuggestion>,
}

#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
pub struct DiffRecommendation {
    pub from: Option<VetVersion>,
    pub to: VetVersion,
    pub diffstat: DiffStat,
}

#[derive(Debug, Clone)]
pub struct RegistrySuggestion {
    pub name: ImportName,
    pub url: Vec<String>,
    pub diff: DiffRecommendation,
}

/// An "interned" cargo PackageId which is used to uniquely identify packages throughout
/// the code. This is simpler and faster than actually using PackageIds (strings) or name+version.
/// In the current implementation it can be used to directly index into the `graph` or `results`.
pub type PackageIdx = usize;

#[derive(Debug, Clone, Serialize)]
pub struct PackageNode<'a> {
    #[serde(skip_serializing_if = "pkgid_unstable")]
    /// The PackageId that cargo uses to uniquely identify this package
    ///
    /// Prefer using a [`DepGraph`] and its memoized [`PackageIdx`]'s.
    pub package_id: &'a PackageId,
    /// The name of the package
    pub name: PackageStr<'a>,
    /// The version of this package
    pub version: VetVersion,
    /// All normal deps (shipped in the project or a proc-macro it uses)
    pub normal_deps: Vec<PackageIdx>,
    /// All build deps (used for build.rs)
    pub build_deps: Vec<PackageIdx>,
    /// All dev deps (used for tests/benches)
    pub dev_deps: Vec<PackageIdx>,
    /// Just the normal and build deps (deduplicated)
    pub normal_and_build_deps: Vec<PackageIdx>,
    /// All deps combined (deduplicated)
    pub all_deps: Vec<PackageIdx>,
    /// All reverse-deps (mostly just used for contextualizing what uses it)
    pub reverse_deps: SortedSet<PackageIdx>,
    /// Whether this package is a workspace member (can have dev-deps)
    pub is_workspace_member: bool,
    /// Whether this package is third-party (from crates.io)
    pub is_third_party: bool,
    /// Whether this package is a root in the "normal" build graph
    pub is_root: bool,
    /// Whether this package only shows up in dev (test/bench) builds
    pub is_dev_only: bool,
}

/// Don't serialize path package ids, not stable across systems
fn pkgid_unstable(pkgid: &PackageId) -> bool {
    pkgid.repr.contains("(path+file:/")
}

/// The dependency graph in a form we can use more easily.
#[derive(Debug, Clone)]
pub struct DepGraph<'a> {
    pub nodes: Vec<PackageNode<'a>>,
    pub interner_by_pkgid: SortedMap<&'a PackageId, PackageIdx>,
    pub topo_index: Vec<PackageIdx>,
}

/// Results and notes from running vet on a particular package.
#[derive(Debug, Clone)]
pub struct ResolveResult {
    /// Cache of search results for each criteria.
    pub search_results: Vec<Result<Vec<DeltaEdgeOrigin>, SearchFailure>>,
}

#[derive(Debug, Clone)]
pub struct AuditFailure {
    pub criteria_failures: CriteriaSet,
}

/// Value indicating a failure to find a path in the audit graph between two nodes.
#[derive(Debug, Clone)]
pub struct SearchFailure {
    /// Nodes we could reach from "root"
    pub reachable_from_root: SortedSet<Option<VetVersion>>,
    /// Nodes we could reach from the "target"
    pub reachable_from_target: SortedSet<Option<VetVersion>>,
}

type DirectedAuditGraph<'a> = SortedMap<Option<&'a VetVersion>, Vec<DeltaEdge<'a>>>;

/// A graph of the audits for a package.
///
/// The nodes of the graph are Versions and the edges are audits.
/// An AuditGraph is directed, potentially cyclic, and potentially disconnected.
///
/// There are two important versions in each AuditGraph:
///
/// * The "root" version (None) which exists as a dummy node for full-audits
/// * The "target" version which is the current version of the package
///
/// The edges are constructed as follows:
///
/// * Delta Audits desugar directly to edges
/// * Full Audits and Unaudited desugar to None -> Some(Version)
///
/// If there are multiple versions of a package in-tree, we analyze each individually
/// so there is always one root and one target. All we want to know is if there exists
/// a path between the two where every edge on that path has a given criteria. We do this
/// check for every possible criteria in a loop to keep the analysis simple and composable.
///
/// When resolving the audits for a package, we create a "forward" graph and a "backward" graph.
/// These are the same graphs but with the edges reversed. The backward graph is only used if
/// we can't find the desired path in the forward graph, and is used to compute the
/// reachability set of the target version for that criteria. That reachability is
/// used for `suggest`.
#[derive(Debug, Clone)]
pub struct AuditGraph<'a> {
    forward_audits: DirectedAuditGraph<'a>,
    backward_audits: DirectedAuditGraph<'a>,
}

/// The precise origin of an edge in the audit graph.
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
pub enum DeltaEdgeOrigin {
    /// This edge represents an audit from the local audits.toml.
    StoredLocalAudit { audit_index: usize },
    /// This edge represents an audit imported from a peer, potentially stored
    /// in the local imports.lock.
    ImportedAudit {
        import_index: usize,
        audit_index: usize,
    },
    /// This edge represents a reified wildcard audit.
    WildcardAudit {
        import_index: Option<usize>,
        audit_index: usize,
        publisher_index: usize,
    },
    /// This edge represents a trusted publisher.
    Trusted { publisher_index: usize },
    /// This edge represents an exemption from the local config.toml.
    Exemption { exemption_index: usize },
    /// This edge represents an unpublished entry in imports.lock.
    Unpublished { unpublished_index: usize },
    /// This edge represents brand new exemption which didn't previously exist
    /// in the audit graph. Will only ever be produced from
    /// SearchMode::RegenerateExemptions.
    FreshExemption { version: VetVersion },
}

/// An indication of a required imported entry or exemption. Used to compute the
/// minimal set of possible imports for imports.lock.
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
pub enum RequiredEntry {
    Audit {
        import_index: usize,
        audit_index: usize,
    },
    WildcardAudit {
        import_index: usize,
        audit_index: usize,
    },
    Publisher {
        publisher_index: usize,
    },
    Exemption {
        exemption_index: usize,
    },
    Unpublished {
        unpublished_index: usize,
    },
    // NOTE: This variant must come last, as code in `update_store` depends on
    // `FreshExemption` entries sorting after all other entries.
    FreshExemption {
        version: VetVersion,
    },
}

/// A directed edge in the graph of audits. This may be forward or backwards,
/// depending on if we're searching from "roots" (forward) or the target (backward).
/// The source isn't included because that's implicit in the Node.
#[derive(Debug, Clone)]
struct DeltaEdge<'a> {
    /// The version this edge goes to.
    version: Option<&'a VetVersion>,
    /// The criteria that this edge is valid for.
    criteria: CriteriaSet,
    /// The origin of this edge. See `DeltaEdgeOrigin`'s documentation for more
    /// details.
    origin: DeltaEdgeOrigin,
    /// Whether or not the edge is a "fresh import", and should be
    /// de-prioritized to avoid unnecessary imports.lock updates.
    is_fresh_import: bool,
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum SearchMode {
    /// Prefer exemptions over fresh imports when searching.
    PreferExemptions,
    /// Prefer fresh imports over exemptions when searching for paths.
    PreferFreshImports,
    /// Prefer fresh imports over exemptions, and allow introducing new
    /// exemptions or expanding their criteria beyond the written criteria
    /// (unless they are suggest=false).
    RegenerateExemptions,
}

impl<'a> DepGraph<'a> {
    pub fn new(
        metadata: &'a Metadata,
        filter_graph: Option<&Vec<GraphFilter>>,
        policy: Option<&Policy>,
    ) -> Self {
        let default_policy = Policy::default();
        let policy = policy.unwrap_or(&default_policy);
        let package_list = &*metadata.packages;
        let resolve_list = &*metadata
            .resolve
            .as_ref()
            .expect("cargo metadata did not yield resolve!")
            .nodes;
        let package_index_by_pkgid = package_list
            .iter()
            .enumerate()
            .map(|(idx, pkg)| (&pkg.id, idx))
            .collect::<SortedMap<_, _>>();
        let resolve_index_by_pkgid = resolve_list
            .iter()
            .enumerate()
            .map(|(idx, pkg)| (&pkg.id, idx))
            .collect();

        // Do a first-pass where we populate skeletons of the primary nodes
        // and setup the interners, which will only ever refer to these nodes
        let mut interner_by_pkgid = SortedMap::<&PackageId, PackageIdx>::new();
        let mut nodes = vec![];

        // Stub out the initial state of all the nodes
        for resolve_node in resolve_list {
            let package = &package_list[package_index_by_pkgid[&resolve_node.id]];
            nodes.push(PackageNode {
                package_id: &resolve_node.id,
                name: &package.name,
                version: package.vet_version(),
                is_third_party: package.is_third_party(policy),
                // These will get (re)computed later
                normal_deps: vec![],
                build_deps: vec![],
                dev_deps: vec![],
                normal_and_build_deps: vec![],
                all_deps: vec![],
                reverse_deps: SortedSet::new(),
                is_workspace_member: false,
                is_root: false,
                is_dev_only: true,
            });
        }

        // Sort the nodes by package_id to make the graph more stable and to make
        // anything sorted by package_idx to also be approximately sorted by name and version.
        nodes.sort_by_key(|k| k.package_id);

        // Populate the interners based on the new ordering
        for (idx, node) in nodes.iter_mut().enumerate() {
            assert!(interner_by_pkgid.insert(node.package_id, idx).is_none());
        }

        // Do topological sort: just recursively visit all of a node's children, and only add it
        // to the list *after* visiting the children. In this way we have trivially already added
        // all of the dependencies of a node to the list by the time we add itself to the list.
        let mut topo_index = vec![];
        {
            let mut visited = FastMap::new();
            // All of the roots can be found in the workspace_members.
            // First we visit all the workspace members while ignoring dev-deps,
            // this should get us an analysis of the "normal" build graph, which
            // we should compute roots from. Then we will do a second pass on
            // the dev-deps. If we don't do it this way, then dev-dep cycles can
            // confuse us about which nodes are roots or not (potentially resulting
            // in no roots at all!
            for pkgid in &metadata.workspace_members {
                let node_idx = interner_by_pkgid[pkgid];
                nodes[node_idx].is_workspace_member = true;
                visit_node(
                    &mut nodes,
                    &mut topo_index,
                    &mut visited,
                    &interner_by_pkgid,
                    &resolve_index_by_pkgid,
                    resolve_list,
                    node_idx,
                );
            }

            // Anything we visited in the first pass isn't dev-only
            for (&node_idx, ()) in &visited {
                nodes[node_idx].is_dev_only = false;
            }

            // Now that we've visited the normal build graph, mark the nodes that are roots
            for pkgid in &metadata.workspace_members {
                let node = &mut nodes[interner_by_pkgid[pkgid]];
                node.is_root = node.reverse_deps.is_empty();
            }

            // And finally visit workspace-members' dev-deps, safe in the knowledge that
            // we know what all the roots are now.
            for pkgid in &metadata.workspace_members {
                let node_idx = interner_by_pkgid[pkgid];
                let resolve_node = &resolve_list[resolve_index_by_pkgid[pkgid]];
                let dev_deps = deps(
                    resolve_node,
                    &[DependencyKind::Development],
                    &interner_by_pkgid,
                );

                // Now visit all the dev deps
                for &child in &dev_deps {
                    visit_node(
                        &mut nodes,
                        &mut topo_index,
                        &mut visited,
                        &interner_by_pkgid,
                        &resolve_index_by_pkgid,
                        resolve_list,
                        child,
                    );
                    // Note that these edges do not change whether something is a "root"
                    nodes[child].reverse_deps.insert(node_idx);
                }

                let node = &mut nodes[node_idx];
                node.dev_deps = dev_deps;
            }
            fn visit_node<'a>(
                nodes: &mut Vec<PackageNode<'a>>,
                topo_index: &mut Vec<PackageIdx>,
                visited: &mut FastMap<PackageIdx, ()>,
                interner_by_pkgid: &SortedMap<&'a PackageId, PackageIdx>,
                resolve_index_by_pkgid: &SortedMap<&'a PackageId, usize>,
                resolve_list: &'a [cargo_metadata::Node],
                normal_idx: PackageIdx,
            ) {
                // Don't revisit a node we've already seen
                let query = visited.entry(normal_idx);
                if matches!(query, std::collections::hash_map::Entry::Vacant(..)) {
                    query.or_insert(());
                    let resolve_node =
                        &resolve_list[resolve_index_by_pkgid[nodes[normal_idx].package_id]];

                    // Compute the different kinds of dependencies
                    let all_deps = resolve_node
                        .dependencies
                        .iter()
                        .map(|pkgid| interner_by_pkgid[pkgid])
                        .collect::<Vec<_>>();
                    let build_deps =
                        deps(resolve_node, &[DependencyKind::Build], interner_by_pkgid);
                    let normal_deps =
                        deps(resolve_node, &[DependencyKind::Normal], interner_by_pkgid);
                    let normal_and_build_deps = deps(
                        resolve_node,
                        &[DependencyKind::Normal, DependencyKind::Build],
                        interner_by_pkgid,
                    );

                    // Now visit all the normal and build deps
                    for &child in &normal_and_build_deps {
                        visit_node(
                            nodes,
                            topo_index,
                            visited,
                            interner_by_pkgid,
                            resolve_index_by_pkgid,
                            resolve_list,
                            child,
                        );
                        nodes[child].reverse_deps.insert(normal_idx);
                    }

                    // Now visit this node itself
                    topo_index.push(normal_idx);

                    // Now commit all the deps
                    let cur_node = &mut nodes[normal_idx];
                    cur_node.build_deps = build_deps;
                    cur_node.normal_deps = normal_deps;
                    cur_node.normal_and_build_deps = normal_and_build_deps;
                    cur_node.all_deps = all_deps;

                    // dev-deps will be handled in a second pass
                }
            }
            fn deps(
                resolve_node: &Node,
                kinds: &[DependencyKind],
                interner_by_pkgid: &SortedMap<&PackageId, PackageIdx>,
            ) -> Vec<PackageIdx> {
                // Note that dep_kinds has target cfg info. If we want to handle targets
                // we should gather those up with filter/fold instead of just 'any'.
                // TODO: map normal-deps that whose package has a "proc-macro" target to be build-deps
                resolve_node
                    .deps
                    .iter()
                    .filter(|dep| {
                        dep.dep_kinds
                            .iter()
                            .any(|dep_kind| kinds.contains(&dep_kind.kind))
                    })
                    .map(|dep| interner_by_pkgid[&dep.pkg])
                    .collect()
            }
        }

        let result = Self {
            interner_by_pkgid,
            nodes,
            topo_index,
        };

        // Now apply filters, if any
        if let Some(filters) = filter_graph {
            result.filter(filters)
        } else {
            result
        }
    }

    pub fn filter(self, filters: &[GraphFilter]) -> Self {
        use GraphFilter::*;
        use GraphFilterProperty::*;
        use GraphFilterQuery::*;

        fn matches_query(package: &PackageNode, query: &GraphFilterQuery) -> bool {
            match query {
                All(queries) => queries.iter().all(|q| matches_query(package, q)),
                Any(queries) => queries.iter().any(|q| matches_query(package, q)),
                Not(query) => !matches_query(package, query),
                Prop(property) => matches_property(package, property),
            }
        }
        fn matches_property(package: &PackageNode, property: &GraphFilterProperty) -> bool {
            match property {
                Name(val) => package.name == val,
                Version(val) => &package.version == val,
                IsRoot(val) => &package.is_root == val,
                IsWorkspaceMember(val) => &package.is_workspace_member == val,
                IsThirdParty(val) => &package.is_third_party == val,
                IsDevOnly(val) => &package.is_dev_only == val,
            }
        }

        let mut passed_filters = FastSet::new();
        'nodes: for (idx, package) in self.nodes.iter().enumerate() {
            for filter in filters {
                match filter {
                    Include(query) => {
                        if !matches_query(package, query) {
                            continue 'nodes;
                        }
                    }

                    Exclude(query) => {
                        if matches_query(package, query) {
                            continue 'nodes;
                        }
                    }
                }
            }
            // If we pass all the filters, then we get to be included
            passed_filters.insert(idx);
        }

        let mut reachable = FastMap::new();
        for (idx, package) in self.nodes.iter().enumerate() {
            if package.is_workspace_member {
                visit(&mut reachable, &self, &passed_filters, idx);
            }
            fn visit(
                visited: &mut FastMap<PackageIdx, ()>,
                graph: &DepGraph,
                passed_filters: &FastSet<PackageIdx>,
                node_idx: PackageIdx,
            ) {
                if !passed_filters.contains(&node_idx) {
                    return;
                }
                let query = visited.entry(node_idx);
                if matches!(query, std::collections::hash_map::Entry::Vacant(..)) {
                    query.or_insert(());
                    for &child in &graph.nodes[node_idx].all_deps {
                        visit(visited, graph, passed_filters, child);
                    }
                }
            }
        }

        let mut old_to_new = FastMap::new();
        let mut nodes = Vec::new();
        let mut interner_by_pkgid = SortedMap::new();
        let mut topo_index = Vec::new();
        for (old_idx, package) in self.nodes.iter().enumerate() {
            if !reachable.contains_key(&old_idx) {
                continue;
            }
            let new_idx = nodes.len();
            old_to_new.insert(old_idx, new_idx);
            nodes.push(PackageNode {
                package_id: package.package_id,
                name: package.name,
                version: package.version.clone(),
                normal_deps: vec![],
                build_deps: vec![],
                dev_deps: vec![],
                normal_and_build_deps: vec![],
                all_deps: vec![],
                reverse_deps: SortedSet::new(),
                is_workspace_member: package.is_workspace_member,
                is_third_party: package.is_third_party,
                is_root: package.is_root,
                is_dev_only: package.is_dev_only,
            });
            interner_by_pkgid.insert(package.package_id, new_idx);
        }
        for old_idx in &self.topo_index {
            if let Some(&new_idx) = old_to_new.get(old_idx) {
                topo_index.push(new_idx);
            }
        }
        for (old_idx, old_package) in self.nodes.iter().enumerate() {
            if let Some(&new_idx) = old_to_new.get(&old_idx) {
                let new_package = &mut nodes[new_idx];
                for old_dep in &old_package.normal_deps {
                    if let Some(&new_dep) = old_to_new.get(old_dep) {
                        new_package.normal_deps.push(new_dep);
                    }
                }
                for old_dep in &old_package.build_deps {
                    if let Some(&new_dep) = old_to_new.get(old_dep) {
                        new_package.build_deps.push(new_dep);
                    }
                }
                for old_dep in &old_package.dev_deps {
                    if let Some(&new_dep) = old_to_new.get(old_dep) {
                        new_package.dev_deps.push(new_dep);
                    }
                }
                for old_dep in &old_package.normal_and_build_deps {
                    if let Some(&new_dep) = old_to_new.get(old_dep) {
                        new_package.normal_and_build_deps.push(new_dep);
                    }
                }
                for old_dep in &old_package.all_deps {
                    if let Some(&new_dep) = old_to_new.get(old_dep) {
                        new_package.all_deps.push(new_dep);
                    }
                }
                for old_dep in &old_package.reverse_deps {
                    if let Some(&new_dep) = old_to_new.get(old_dep) {
                        new_package.reverse_deps.insert(new_dep);
                    }
                }
            }
        }

        Self {
            nodes,
            interner_by_pkgid,
            topo_index,
        }
    }

    pub fn print_mermaid(
        &self,
        out: &Arc<dyn Out>,
        sub_args: &DumpGraphArgs,
    ) -> Result<(), std::io::Error> {
        use crate::DumpGraphDepth::*;
        let depth = sub_args.depth;

        let mut visible_nodes = SortedSet::new();
        let mut nodes_with_children = SortedSet::new();
        let mut shown = SortedSet::new();

        for (idx, package) in self.nodes.iter().enumerate() {
            if (package.is_root && depth >= Roots)
                || (package.is_workspace_member && depth >= Workspace)
                || (!package.is_third_party && depth >= FirstParty)
                || depth >= Full
            {
                visible_nodes.insert(idx);
                nodes_with_children.insert(idx);

                if depth >= FirstPartyAndDirects {
                    for &dep in &package.all_deps {
                        visible_nodes.insert(dep);
                    }
                }
            }
        }

        writeln!(out, "graph LR");

        writeln!(out, "    subgraph roots");
        for &idx in &visible_nodes {
            let package = &self.nodes[idx];
            if package.is_root && shown.insert(idx) {
                writeln!(
                    out,
                    "        node{idx}{{{}:{}}}",
                    package.name, package.version
                );
            }
        }
        writeln!(out, "    end");

        writeln!(out, "    subgraph workspace-members");
        for &idx in &visible_nodes {
            let package = &self.nodes[idx];
            if package.is_workspace_member && shown.insert(idx) {
                writeln!(
                    out,
                    "        node{idx}[/{}:{}/]",
                    package.name, package.version
                );
            }
        }
        writeln!(out, "    end");

        writeln!(out, "    subgraph first-party");
        for &idx in &visible_nodes {
            let package = &self.nodes[idx];
            if !package.is_third_party && shown.insert(idx) {
                writeln!(
                    out,
                    "        node{idx}[{}:{}]",
                    package.name, package.version
                );
            }
        }
        writeln!(out, "    end");

        writeln!(out, "    subgraph third-party");
        for &idx in &visible_nodes {
            let package = &self.nodes[idx];
            if shown.insert(idx) {
                writeln!(
                    out,
                    "        node{idx}({}:{})",
                    package.name, package.version
                );
            }
        }
        writeln!(out, "    end");

        for &idx in &nodes_with_children {
            let package = &self.nodes[idx];
            for &dep_idx in &package.all_deps {
                if visible_nodes.contains(&dep_idx) {
                    writeln!(out, "    node{idx} --> node{dep_idx}");
                }
            }
        }

        Ok(())
    }
}

pub fn resolve<'a>(
    metadata: &'a Metadata,
    filter_graph: Option<&Vec<GraphFilter>>,
    store: &Store,
) -> ResolveReport<'a> {
    // A large part of our algorithm is unioning and intersecting criteria, so we map all
    // the criteria into indexed boolean sets (*whispers* an integer with lots of bits).
    let graph = DepGraph::new(metadata, filter_graph, Some(&store.config.policy));
    // trace!("built DepGraph: {:#?}", graph);
    trace!("built DepGraph!");

    let criteria_mapper = CriteriaMapper::new(&store.audits.criteria);
    trace!("built CriteriaMapper!");

    let requirements = resolve_requirements(&graph, &store.config.policy, &criteria_mapper);

    let (results, conclusion) = resolve_audits(&graph, store, &criteria_mapper, &requirements);

    ResolveReport {
        graph,
        criteria_mapper,
        results,
        conclusion,
    }
}

fn resolve_requirements(
    graph: &DepGraph<'_>,
    policy: &Policy,
    criteria_mapper: &CriteriaMapper,
) -> Vec<CriteriaSet> {
    let _resolve_requirements = trace_span!("resolve_requirements").entered();

    let mut requirements = vec![criteria_mapper.no_criteria(); graph.nodes.len()];

    // For any packages which have dev-dependencies, apply policy-specified
    // dependency-criteria or dev-criteria to those dependencies.
    for package in &graph.nodes {
        if package.dev_deps.is_empty() {
            continue;
        }

        let policy = policy.get(package.name, &package.version);
        let dev_criteria = if let Some(c) = policy.and_then(|p| p.dev_criteria.as_ref()) {
            criteria_mapper.criteria_from_list(c)
        } else {
            criteria_mapper.criteria_from_list([format::DEFAULT_POLICY_DEV_CRITERIA])
        };

        for &depidx in &package.dev_deps {
            let dep_package = &graph.nodes[depidx];
            let dependency_criteria = policy
                .and_then(|policy| policy.dependency_criteria.get(dep_package.name))
                .map(|criteria| criteria_mapper.criteria_from_list(criteria));
            requirements[depidx]
                .unioned_with(dependency_criteria.as_ref().unwrap_or(&dev_criteria));
        }
    }

    // Walk the topo graph in reverse, so that we visit each package before any
    // dependencies.
    for &pkgidx in graph.topo_index.iter().rev() {
        let package = &graph.nodes[pkgidx];
        let policy = policy.get(package.name, &package.version);

        if let Some(c) = policy.and_then(|p| p.criteria.as_ref()) {
            // If we specify a policy on ourselves, override any requirements we've
            // had placed on us by reverse-dependencies.
            requirements[pkgidx] = criteria_mapper.criteria_from_list(c);
        } else if package.is_root {
            // If this is a root crate, it will require at least
            // `DEFAULT_POLICY_CRITERIA` by default, unless overridden.
            requirements[pkgidx].unioned_with(
                &criteria_mapper.criteria_from_list([format::DEFAULT_POLICY_CRITERIA]),
            );
        }
        let normal_criteria = requirements[pkgidx].clone();

        // For each dependency, elaborate the dependency criteria from the configured policy and add it to the dependency requirements.
        for &depidx in &package.normal_and_build_deps {
            let dep_package = &graph.nodes[depidx];
            let dependency_criteria = policy
                .and_then(|policy| policy.dependency_criteria.get(dep_package.name))
                .map(|criteria| criteria_mapper.criteria_from_list(criteria));
            requirements[depidx]
                .unioned_with(dependency_criteria.as_ref().unwrap_or(&normal_criteria));
        }
    }

    requirements
}

fn resolve_audits(
    graph: &DepGraph<'_>,
    store: &Store,
    criteria_mapper: &CriteriaMapper,
    requirements: &[CriteriaSet],
) -> (Vec<Option<ResolveResult>>, Conclusion) {
    let _resolve_audits = trace_span!("resolve_audits").entered();
    let mut violations = Vec::new();
    let mut failures = Vec::new();
    let mut vetted_with_exemptions = Vec::new();
    let mut vetted_partially = Vec::new();
    let mut vetted_fully = Vec::new();
    let results: Vec<_> = requirements
        .iter()
        .enumerate()
        .map(|(pkgidx, required_criteria)| {
            let package = &graph.nodes[pkgidx];
            if !package.is_third_party {
                return None; // first-party crates don't need audits
            }

            let audit_graph = AuditGraph::build(store, criteria_mapper, package.name, None)
                .map_err(|v| violations.push((pkgidx, v)))
                .ok()?;

            // NOTE: We currently always compute all search results even if we
            // only need those in `req_criteria` because some later passes using
            // the resolver results might need that information. We might want
            // to look into simplifying this in the future.
            let search_results: Vec<_> = (0..criteria_mapper.len())
                .map(|criteria_idx| {
                    audit_graph.search(criteria_idx, &package.version, SearchMode::PreferExemptions)
                })
                .collect();

            let mut needed_exemptions = false;
            let mut directly_exempted = false;
            let mut criteria_failures = criteria_mapper.no_criteria();
            for criteria_idx in required_criteria.indices() {
                match &search_results[criteria_idx] {
                    Ok(path) => {
                        needed_exemptions |= path
                            .iter()
                            .any(|o| matches!(o, DeltaEdgeOrigin::Exemption { .. }));
                        // Ignore `Unpublished` entries when deciding if a crate
                        // is directly exempted.
                        directly_exempted |= path.iter().all(|o| {
                            matches!(
                                o,
                                DeltaEdgeOrigin::Exemption { .. }
                                    | DeltaEdgeOrigin::Unpublished { .. }
                            )
                        });
                    }
                    Err(_) => criteria_failures.set_criteria(criteria_idx),
                }
            }

            if !criteria_failures.is_empty() {
                failures.push((pkgidx, AuditFailure { criteria_failures }));
            }

            // XXX: Callers using these fields in success should perhaps be
            // changed to instead walk the results?
            if !needed_exemptions {
                vetted_fully.push(pkgidx);
            } else if directly_exempted {
                vetted_with_exemptions.push(pkgidx);
            } else {
                vetted_partially.push(pkgidx);
            }

            Some(ResolveResult { search_results })
        })
        .collect();

    let conclusion = if !violations.is_empty() {
        Conclusion::FailForViolationConflict(FailForViolationConflict { violations })
    } else if !failures.is_empty() {
        Conclusion::FailForVet(FailForVet {
            failures,
            suggest: None,
        })
    } else {
        Conclusion::Success(Success {
            vetted_with_exemptions,
            vetted_partially,
            vetted_fully,
        })
    };

    (results, conclusion)
}

impl<'a> AuditGraph<'a> {
    /// Given the store, and a package name, builds up an audit graph. This can
    /// then be searched in order to find a specific path which satisfies a
    /// given criteria.
    pub fn build(
        store: &'a Store,
        criteria_mapper: &CriteriaMapper,
        package: PackageStr<'_>,
        extra_audits_file: Option<&'a AuditsFile>,
    ) -> Result<Self, Vec<ViolationConflict>> {
        // Pre-build the namespaces for each audit so that we can take a reference
        // to each one as-needed rather than cloning the name each time.
        let foreign_namespaces: Vec<Option<ImportName>> = store
            .imported_audits()
            .keys()
            .map(|import_name| Some(import_name.clone()))
            .collect();

        // Iterator over every audits file, including imported audits.
        let all_audits_files = store
            .imported_audits()
            .values()
            .enumerate()
            .map(|(import_index, audits_file)| {
                (
                    Some(import_index),
                    &foreign_namespaces[import_index],
                    audits_file,
                )
            })
            .chain([(None, &None, &store.audits)])
            .chain(
                // Consider extra audits as local for now - we don't care about
                // how the audits from it are prioritized.
                extra_audits_file
                    .iter()
                    .map(|&audits_file| (None, &None, audits_file)),
            );

        // Iterator over every normal audit.
        let all_audits =
            all_audits_files
                .clone()
                .flat_map(|(import_index, namespace, audits_file)| {
                    audits_file
                        .audits
                        .get(package)
                        .map(|v| &v[..])
                        .unwrap_or(&[])
                        .iter()
                        .enumerate()
                        .map(move |(audit_index, audit)| {
                            (
                                namespace,
                                match import_index {
                                    Some(import_index) => DeltaEdgeOrigin::ImportedAudit {
                                        import_index,
                                        audit_index,
                                    },
                                    None => DeltaEdgeOrigin::StoredLocalAudit { audit_index },
                                },
                                audit,
                            )
                        })
                });

        // Iterator over every wildcard audit.
        let all_wildcard_audits =
            all_audits_files
                .clone()
                .flat_map(|(import_index, namespace, audits_file)| {
                    audits_file
                        .wildcard_audits
                        .get(package)
                        .map(|v| &v[..])
                        .unwrap_or(&[])
                        .iter()
                        .enumerate()
                        .map(move |(audit_index, audit)| {
                            (namespace, import_index, audit_index, audit)
                        })
                });

        // Iterator over every trusted entry.
        let trusteds = store
            .audits
            .trusted
            .get(package)
            .map(|v| &v[..])
            .unwrap_or(&[]);

        let publishers = store
            .publishers()
            .get(package)
            .map(|v| &v[..])
            .unwrap_or(&[]);

        let unpublished = store
            .unpublished()
            .get(package)
            .map(|v| &v[..])
            .unwrap_or(&[]);

        let exemptions = store.config.exemptions.get(package);

        let mut forward_audits = DirectedAuditGraph::new();
        let mut backward_audits = DirectedAuditGraph::new();
        let mut violation_nodes = Vec::new();

        // Collect up all the deltas, and their criteria
        for (namespace, origin, entry) in all_audits.clone() {
            // For uniformity, model a Full Audit as `None -> x.y.z`
            let (from_ver, to_ver) = match &entry.kind {
                AuditKind::Full { version } => (None, version),
                AuditKind::Delta { from, to } => (Some(from), to),
                AuditKind::Violation { .. } => {
                    violation_nodes.push((namespace.clone(), entry));
                    continue;
                }
            };

            let criteria = criteria_mapper.criteria_from_list(&entry.criteria);

            forward_audits.entry(from_ver).or_default().push(DeltaEdge {
                version: Some(to_ver),
                criteria: criteria.clone(),
                origin: origin.clone(),
                is_fresh_import: entry.is_fresh_import,
            });
            backward_audits
                .entry(Some(to_ver))
                .or_default()
                .push(DeltaEdge {
                    version: from_ver,
                    criteria,
                    origin,
                    is_fresh_import: entry.is_fresh_import,
                });
        }

        // For each published version of the crate we're aware of, check if any
        // wildcard audits apply and add full-audits to those versions if they
        // do.
        for (publisher_index, publisher) in publishers.iter().enumerate() {
            for (_, import_index, audit_index, entry) in all_wildcard_audits.clone() {
                if entry.user_id == publisher.user_id
                    && *entry.start <= publisher.when
                    && publisher.when < *entry.end
                {
                    let from_ver = None;
                    let to_ver = Some(&publisher.version);
                    let criteria = criteria_mapper.criteria_from_list(&entry.criteria);
                    let origin = DeltaEdgeOrigin::WildcardAudit {
                        import_index,
                        audit_index,
                        publisher_index,
                    };
                    let is_fresh_import = entry.is_fresh_import || publisher.is_fresh_import;

                    forward_audits.entry(from_ver).or_default().push(DeltaEdge {
                        version: to_ver,
                        criteria: criteria.clone(),
                        origin: origin.clone(),
                        is_fresh_import,
                    });
                    backward_audits.entry(to_ver).or_default().push(DeltaEdge {
                        version: from_ver,
                        criteria,
                        origin,
                        is_fresh_import,
                    });
                }
            }

            for entry in trusteds {
                if entry.user_id == publisher.user_id
                    && *entry.start <= publisher.when
                    && publisher.when < *entry.end
                {
                    let from_ver = None;
                    let to_ver = Some(&publisher.version);
                    let criteria = criteria_mapper.criteria_from_list(&entry.criteria);
                    let origin = DeltaEdgeOrigin::Trusted { publisher_index };

                    forward_audits.entry(from_ver).or_default().push(DeltaEdge {
                        version: to_ver,
                        criteria: criteria.clone(),
                        origin: origin.clone(),
                        is_fresh_import: publisher.is_fresh_import,
                    });
                    backward_audits.entry(to_ver).or_default().push(DeltaEdge {
                        version: from_ver,
                        criteria,
                        origin,
                        is_fresh_import: publisher.is_fresh_import,
                    });
                }
            }
        }

        // For each unpublished entry for the crate we're aware of, generate a delta audit for that edge.
        for (unpublished_index, unpublished) in unpublished.iter().enumerate() {
            let from_ver = Some(&unpublished.audited_as);
            let to_ver = Some(&unpublished.version);
            let criteria = criteria_mapper.all_criteria();
            let origin = DeltaEdgeOrigin::Unpublished { unpublished_index };
            let is_fresh_import = unpublished.is_fresh_import;

            forward_audits.entry(from_ver).or_default().push(DeltaEdge {
                version: to_ver,
                criteria: criteria.clone(),
                origin: origin.clone(),
                is_fresh_import,
            });
            backward_audits.entry(to_ver).or_default().push(DeltaEdge {
                version: from_ver,
                criteria,
                origin,
                is_fresh_import,
            });
        }

        // Exempted entries are equivalent to full-audits
        if let Some(alloweds) = exemptions {
            for (exemption_index, allowed) in alloweds.iter().enumerate() {
                let from_ver = None;
                let to_ver = Some(&allowed.version);
                let criteria = criteria_mapper.criteria_from_list(&allowed.criteria);
                let origin = DeltaEdgeOrigin::Exemption { exemption_index };

                // For simplicity, turn 'exemptions' entries into deltas from None.
                forward_audits.entry(from_ver).or_default().push(DeltaEdge {
                    version: to_ver,
                    criteria: criteria.clone(),
                    origin: origin.clone(),
                    is_fresh_import: false,
                });
                backward_audits.entry(to_ver).or_default().push(DeltaEdge {
                    version: from_ver,
                    criteria,
                    origin,
                    is_fresh_import: false,
                });
            }
        }

        // Reject forbidden packages (violations)
        let mut violations = Vec::new();
        for (violation_source, violation_entry) in &violation_nodes {
            // Ok this is kind of weird. We want to reject any audits which contain any of these criteria.
            // Normally we would slap all the criteria in this entry into a set and do some kind of set
            // comparison, but that's not quite right. Here are the cases we want to work:
            //
            // * violation: safe-to-deploy, audit: safe-to-deploy -- ERROR!
            // * violation: safe-to-deploy, audit: safe-to-run    -- OK!
            // * violation: safe-to-run,    audit: safe-to-deploy -- ERROR!
            // * violation: [a, b],         audit: [a, c]         -- ERROR!
            //
            // The first 3 cases are correctly handled by audit.contains(violation)
            // but the last one isn't. I think the correct solution to this is to
            // *for each individual entry in the violation* do audit.contains(violation).
            // If any of those queries trips, then it's an ERROR.
            //
            // Note that this would also more correctly handle [safe-to-deploy, safe-to-run]
            // as a violation entry because it would effectively become safe-to-run instead
            // of safe-to-deploy, which is the correct and desirable behaviour!
            //
            // So here we make a criteria set for each entry in the violation.
            let violation_criterias = violation_entry
                .criteria
                .iter()
                .map(|c| criteria_mapper.criteria_from_list([&c]))
                .collect::<Vec<_>>();
            let violation_range = if let AuditKind::Violation { violation } = &violation_entry.kind
            {
                violation
            } else {
                unreachable!("violation_entry wasn't a Violation?");
            };

            // Note if this entry conflicts with any exemptions
            if let Some(alloweds) = exemptions {
                for allowed in alloweds {
                    let audit_criteria = criteria_mapper.criteria_from_list(&allowed.criteria);
                    let has_violation = violation_criterias
                        .iter()
                        .any(|v| audit_criteria.contains(v));
                    if !has_violation {
                        continue;
                    }
                    if violation_range.matches(&allowed.version) {
                        violations.push(ViolationConflict::UnauditedConflict {
                            violation_source: violation_source.clone(),
                            violation: (*violation_entry).clone(),
                            exemptions: allowed.clone(),
                        });
                    }
                }
            }

            // Note if this entry conflicts with any audits
            for (namespace, _origin, audit) in all_audits.clone() {
                let audit_criteria = criteria_mapper.criteria_from_list(&audit.criteria);
                let has_violation = violation_criterias
                    .iter()
                    .any(|v| audit_criteria.contains(v));
                if !has_violation {
                    continue;
                }
                match &audit.kind {
                    AuditKind::Full { version, .. } => {
                        if violation_range.matches(version) {
                            violations.push(ViolationConflict::AuditConflict {
                                violation_source: violation_source.clone(),
                                violation: (*violation_entry).clone(),
                                audit_source: namespace.clone(),
                                audit: audit.clone(),
                            });
                        }
                    }
                    AuditKind::Delta { from, to, .. } => {
                        if violation_range.matches(from) || violation_range.matches(to) {
                            violations.push(ViolationConflict::AuditConflict {
                                violation_source: violation_source.clone(),
                                violation: (*violation_entry).clone(),
                                audit_source: namespace.clone(),
                                audit: audit.clone(),
                            });
                        }
                    }
                    AuditKind::Violation { .. } => {
                        // don't care
                    }
                }
            }
        }

        // If we enountered any violations, report them.
        if !violations.is_empty() {
            return Err(violations);
        }

        Ok(AuditGraph {
            forward_audits,
            backward_audits,
        })
    }

    /// Search for a path in this AuditGraph which indicates that the given
    /// version of the crate satisfies the given criteria. Returns the path used
    /// for that proof if successful, and information about the versions which
    /// could be reached from both the target and root if unsuccessful.
    pub fn search(
        &self,
        criteria_idx: usize,
        version: &VetVersion,
        mode: SearchMode,
    ) -> Result<Vec<DeltaEdgeOrigin>, SearchFailure> {
        // First, search backwards, starting from the target, as that's more
        // likely to have a limited graph to traverse.
        // This also interacts well with the search ordering from
        // search_for_path, which prefers edges closer to `None` when
        // traversing.
        search_for_path(
            &self.backward_audits,
            criteria_idx,
            Some(version),
            None,
            mode,
        )
        .map_err(|reachable_from_target| {
            assert!(
                mode != SearchMode::RegenerateExemptions,
                "RegenerateExemptions search mode cannot fail"
            );

            // The search failed, perform the search in the other direction
            // in order to also get the set of nodes reachable from the
            // root. We can `unwrap_err()` here, as we'll definitely fail.
            let reachable_from_root = search_for_path(
                &self.forward_audits,
                criteria_idx,
                None,
                Some(version),
                mode,
            )
            .unwrap_err();
            SearchFailure {
                reachable_from_root,
                reachable_from_target,
            }
        })
    }
}

/// Core algorithm used to search for a path between two versions within a
/// DirectedAuditGraph. A path with the fewest "caveats" will be used in order
/// to minimize dependence on exemptions and freshly imported audits.
fn search_for_path(
    audit_graph: &DirectedAuditGraph<'_>,
    criteria_idx: usize,
    from_version: Option<&VetVersion>,
    to_version: Option<&VetVersion>,
    mode: SearchMode,
) -> Result<Vec<DeltaEdgeOrigin>, SortedSet<Option<VetVersion>>> {
    assert!(
        mode != SearchMode::RegenerateExemptions || to_version.is_none(),
        "RegenerateExemptions requires searching towards root"
    );

    // Search for any path through the graph with edges that satisfy criteria.
    // Finding any path validates that we satisfy that criteria.
    //
    // All full-audits and exemptions have been "desugarred" to a delta from
    // None, meaning our graph now has exactly one source and one sink,
    // significantly simplifying the start and end conditions.
    //
    // Some edges have caveats which we want to avoid requiring, so we defer
    // edges with caveats to be checked later, after all edges without caveats
    // have been visited. This is done by storing work to do in a BinaryHeap,
    // sorted by the caveats which apply to each node. This means that if we
    // find a patch without using a node with caveats, it's unambiguous proof we
    // don't need edges with caveats.
    #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
    enum CaveatLevel {
        None,
        PreferredExemption,
        PreferredUnpublished,
        FreshImport,
        Exemption,
        Unpublished,
        FreshExemption,
    }

    #[derive(Debug)]
    struct Node<'a> {
        version: Option<&'a VetVersion>,
        origin_version: Option<&'a VetVersion>,
        path: Vec<DeltaEdgeOrigin>,
        caveat_level: CaveatLevel,
    }

    impl Node<'_> {
        fn key(&self) -> impl Ord + '_ {
            // Nodes are compared by caveat level. A lower caveat level makes
            // the node sort higher, as it will be stored in a max heap.
            //
            // Once we've sorted by all caveats, we sort by the version
            // (preferring lower versions), exemption origin version (preferring
            // smaller exemptions), the length of the path (preferring short
            // paths), and then the most recently added DeltaEdgeOrigin
            // (preferring more-local audits).
            //
            // NOTE: This ordering logic priorities assume `to_version == None`,
            // as we will only be searched in the other direction if the search
            // is guaranteed to fail, in which case ordering doesn't matter (as
            // we're going to visit every node).
            Reverse((
                self.caveat_level,
                self.version,
                self.exemption_origin_version(),
                self.path.len(),
                self.path.last(),
            ))
        }

        // To make better decisions when selecting exemptions, exemption edges
        // with lower origin versions are preferred over those with higher
        // origin versions. This is checked before path length, as a longer path
        // which uses a smaller exemption is generally preferred to a short one
        // which uses a full-exemption. This is ignored for other edge types.
        fn exemption_origin_version(&self) -> Option<&VetVersion> {
            if matches!(
                self.caveat_level,
                CaveatLevel::PreferredExemption
                    | CaveatLevel::Exemption
                    | CaveatLevel::FreshExemption
            ) {
                self.origin_version
            } else {
                None
            }
        }
    }
    impl<'a> PartialEq for Node<'a> {
        fn eq(&self, other: &Self) -> bool {
            self.key() == other.key()
        }
    }
    impl<'a> Eq for Node<'a> {}
    impl<'a> PartialOrd for Node<'a> {
        fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
            Some(self.cmp(other))
        }
    }
    impl<'a> Ord for Node<'a> {
        fn cmp(&self, other: &Self) -> std::cmp::Ordering {
            self.key().cmp(&other.key())
        }
    }

    let mut queue = BinaryHeap::new();
    queue.push(Node {
        version: from_version,
        origin_version: from_version,
        path: Vec::new(),
        caveat_level: CaveatLevel::None,
    });

    let mut visited = SortedSet::new();
    while let Some(Node {
        version,
        origin_version: _,
        path,
        caveat_level,
    }) = queue.pop()
    {
        // If We've been to a version before, We're not going to get a better
        // result revisiting it, as we visit the "best" edges first.
        if !visited.insert(version) {
            continue;
        }

        // We found a path! Return a search result reflecting what we
        // discovered.
        if version == to_version {
            return Ok(path);
        }

        // Apply deltas to move along to the next layer of the search, adding it
        // to our queue.
        let edges = audit_graph.get(&version).map(|v| &v[..]).unwrap_or(&[]);
        for edge in edges {
            // We'll allow any criteria if we're regenerating exemption edges.
            let allow_any_criteria = mode == SearchMode::RegenerateExemptions
                && matches!(edge.origin, DeltaEdgeOrigin::Exemption { .. });
            if !allow_any_criteria && !edge.criteria.has_criteria(criteria_idx) {
                // This edge never would have been useful to us.
                continue;
            }
            if visited.contains(&edge.version) {
                // We've been to the target of this edge already.
                continue;
            }

            // Compute the level of caveats which are being added by the current edge
            let edge_caveat_level = match &edge.origin {
                DeltaEdgeOrigin::Exemption { .. } if mode == SearchMode::PreferExemptions => {
                    CaveatLevel::PreferredExemption
                }
                DeltaEdgeOrigin::Exemption { .. } => CaveatLevel::Exemption,
                DeltaEdgeOrigin::FreshExemption { .. } => unreachable!(),
                DeltaEdgeOrigin::Unpublished { .. } => match mode {
                    // When preferring exemptions, prefer existing unpublished
                    // entries to avoid imports.lock churn.
                    SearchMode::PreferExemptions if !edge.is_fresh_import => {
                        CaveatLevel::PreferredUnpublished
                    }
                    SearchMode::PreferExemptions => CaveatLevel::Unpublished,
                    // Otherwise, prefer fresh to avoid outdated versions.
                    _ if edge.is_fresh_import => CaveatLevel::PreferredUnpublished,
                    _ => CaveatLevel::Unpublished,
                },
                _ if edge.is_fresh_import => CaveatLevel::FreshImport,
                _ => CaveatLevel::None,
            };

            queue.push(Node {
                version: edge.version,
                origin_version: version,
                path: path.iter().cloned().chain([edge.origin.clone()]).collect(),
                caveat_level: caveat_level.max(edge_caveat_level),
            });
        }

        // If we're regenerating exemptions, add a fresh exemption edge which
        // directly leads to the root version.
        if mode == SearchMode::RegenerateExemptions {
            queue.push(Node {
                version: None,
                origin_version: version,
                path: path
                    .iter()
                    .cloned()
                    .chain([DeltaEdgeOrigin::FreshExemption {
                        version: version
                            .expect("RegenerateExemptions requires searching towards None")
                            .clone(),
                    }])
                    .collect(),
                caveat_level: caveat_level.max(CaveatLevel::FreshExemption),
            })
        }
    }

    // Complete failure, we need more audits for this package, so all that
    // matters is what nodes were reachable.
    Err(visited.into_iter().map(|v| v.cloned()).collect())
}

impl<'a> ResolveReport<'a> {
    pub fn has_errors(&self) -> bool {
        // Just check the conclusion
        !matches!(self.conclusion, Conclusion::Success(_))
    }

    pub fn _has_warnings(&self) -> bool {
        false
    }

    pub fn compute_suggest(
        &self,
        cfg: &Config,
        store: &Store,
        network: Option<&Network>,
    ) -> Result<Option<Suggest>, SuggestError> {
        let _suggest_span = trace_span!("suggest").entered();
        let fail = if let Conclusion::FailForVet(fail) = &self.conclusion {
            fail
        } else {
            // Nothing to suggest unless we failed for vet
            return Ok(None);
        };

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

        let warnings = RefCell::new(Vec::new());

        let mut store = store.clone_for_suggest(false);
        let registry = if let (false, OutputFormat::Human, Some(network)) = (
            cfg.cli.no_registry_suggestions,
            cfg.cli.output_format,
            network,
        ) {
            tokio::runtime::Handle::current()
                .block_on(store.fetch_registry_audits(cfg, network, &cache))
                .map_err(|error| warnings.borrow_mut().push(error.to_string()))
                .ok()
        } else {
            None
        };

        const THIS_PROJECT: &str = "this project";

        let mut trusted_publishers: FastMap<u64, SortedSet<ImportName>> = FastMap::new();
        for trusted_entry in store.audits.trusted.values().flatten() {
            trusted_publishers
                .entry(trusted_entry.user_id)
                .or_default()
                .insert(THIS_PROJECT.to_owned());
        }
        for (import_name, audits_file) in store.imported_audits() {
            for trusted_entry in audits_file.trusted.values().flatten() {
                trusted_publishers
                    .entry(trusted_entry.user_id)
                    .or_default()
                    .insert(import_name.clone());
            }
        }

        let suggest_progress =
            progress_bar("Suggesting", "relevant audits", fail.failures.len() as u64);

        let mut suggestions = tokio::runtime::Handle::current()
            .block_on(join_all(fail.failures.iter().map(
                |(failure_idx, audit_failure)| async {
                    let _guard = IncProgressOnDrop(&suggest_progress, 1);

                    let failure_idx = *failure_idx;
                    let package = &self.graph.nodes[failure_idx];
                    let result = self.results[failure_idx]
                        .as_ref()
                        .expect("failed package without ResolveResults?");

                    // Precompute some "notable" parents
                    let notable_parents: Vec<_> = self.graph.nodes[failure_idx]
                        .reverse_deps
                        .iter()
                        .map(|&parent| self.graph.nodes[parent].name.to_string())
                        .collect();

                    let Some((suggested_diff, extra_suggested_diff)) = suggest_delta(
                        &cfg.metadata,
                        network,
                        &cache,
                        package.name,
                        &package.version,
                        audit_failure
                            .criteria_failures
                            .indices()
                            .map(|criteria_idx| {
                                result.search_results[criteria_idx].as_ref().unwrap_err()
                            }),
                        &warnings,
                    )
                    .await else {
                        return vec![];
                    };

                    // Attempt to look up the publisher of the target version
                    // for the suggested diff, and also record whether the given
                    // package has a sole publisher.
                    let mut is_sole_publisher = false;
                    let publisher_id =
                        if let (Some(network), None) = (&network, &suggested_diff.to.git_rev) {
                            let versions = cache
                                .get_publishers(
                                    Some(network),
                                    package.name,
                                    [&suggested_diff.to.semver].into_iter().collect(),
                                )
                                .await
                                .unwrap_or_default();
                            let publisher_count = versions
                                .iter()
                                .flat_map(|(_, details)| &details.published_by)
                                .collect::<FastSet<_>>()
                                .len();
                            is_sole_publisher = publisher_count == 1;
                            versions
                                .into_iter()
                                .find(|(v, _)| v == &suggested_diff.to.semver)
                                .and_then(|(_, d)| d.published_by)
                        } else {
                            None
                        };

                    // Compute the trust hint, which is the information used to generate "consider
                    // cargo trust FOO" messages. There can be multiple potential hints, but we
                    // only provide the most relevant one. If the publisher of the in-use version
                    // of the crate is potentially trustworthy, we suggest that. If not (and we
                    // don't already have at least one trusted entry for this crate), we iterate
                    // over the crate releases in reverse order to see if another version was
                    // published by a potentially-trustworth author. We pick the first one of
                    // those we find, if any.
                    let trust_hint = {
                        let mut exact_version = false;
                        let id_for_hint = if publisher_id
                            .map_or(false, |i| trusted_publishers.contains_key(&i))
                        {
                            exact_version = true;
                            publisher_id
                        } else if store.audits.trusted.get(package.name).is_none() {
                            cache
                                .get_cached_publishers(package.name)
                                .iter()
                                .rev()
                                .filter_map(|(_, details)| details.published_by)
                                .find(|i| trusted_publishers.contains_key(i))
                        } else {
                            None
                        };

                        id_for_hint.map(|id| {
                            let mut trusted_by: Vec<String> = trusted_publishers
                                .get(&id)
                                .unwrap()
                                .iter()
                                .cloned()
                                .collect();
                            // If we're already trusted by this project, don't
                            // bother listing anyone else.
                            if trusted_by.iter().any(|s| s == THIS_PROJECT) {
                                trusted_by.retain(|s| s == THIS_PROJECT);
                            }
                            let publisher = cache.get_crates_user_info(id).unwrap();
                            TrustHint {
                                trusted_by,
                                publisher,
                                exact_version,
                            }
                        })
                    };

                    let publisher_login = publisher_id
                        .and_then(|user_id| cache.get_crates_user_info(user_id))
                        .map(|pi| pi.login);

                    let mut registry_suggestion: Vec<_> = join_all(registry.iter().flatten().map(
                        |(name, entry, audits)| async {
                            // Don't search for git deltas in the registry.
                            if suggested_diff.to.git_rev.is_some() {
                                return None;
                            }

                            let audit_graph = AuditGraph::build(
                                &store,
                                &self.criteria_mapper,
                                package.name,
                                Some(audits),
                            )
                            .ok()?;

                            // If we have an extra diff, only try to search for
                            // a path to the "from" version in that diff, to
                            // make the results more comparable.
                            let target_version = extra_suggested_diff
                                .as_ref()
                                .and_then(|d| d.from.as_ref())
                                .unwrap_or(&package.version);

                            let failures: Vec<_> = audit_failure
                                .criteria_failures
                                .indices()
                                .filter_map(|criteria_idx| {
                                    audit_graph
                                        .search(
                                            criteria_idx,
                                            target_version,
                                            SearchMode::PreferExemptions,
                                        )
                                        .err()
                                })
                                .collect();

                            let (registry_suggested_diff, _) = suggest_delta(
                                &cfg.metadata,
                                network,
                                &cache,
                                package.name,
                                target_version,
                                failures.iter(),
                                &warnings,
                            )
                            .await?;

                            if registry_suggested_diff.diffstat.count()
                                < suggested_diff.diffstat.count()
                            {
                                Some(RegistrySuggestion {
                                    name: name.clone(),
                                    url: entry.url.clone(),
                                    diff: registry_suggested_diff,
                                })
                            } else {
                                None
                            }
                        },
                    ))
                    .await
                    .into_iter()
                    .flatten()
                    .collect();
                    registry_suggestion.sort_by_key(|suggestion| suggestion.diff.diffstat.count());

                    extra_suggested_diff
                        .into_iter()
                        .map(|suggested_diff| SuggestItem {
                            package: failure_idx,
                            suggested_diff,
                            suggested_criteria: audit_failure.criteria_failures.clone(),
                            notable_parents: notable_parents.clone(),
                            publisher_login: None,
                            trust_hint: None,
                            is_sole_publisher: false,
                            registry_suggestion: vec![],
                        })
                        .chain([SuggestItem {
                            package: failure_idx,
                            suggested_diff,
                            suggested_criteria: audit_failure.criteria_failures.clone(),
                            notable_parents: notable_parents.clone(),
                            publisher_login,
                            trust_hint,
                            is_sole_publisher,
                            registry_suggestion,
                        }])
                        .collect()
                },
            )))
            .into_iter()
            .flatten()
            .collect::<Vec<_>>();

        // First sort by diff size (ascending), then package name, then version
        // being certified, to have stable output ordering.
        suggestions.sort_by_key(|item| {
            (
                item.suggested_diff.diffstat.count(),
                self.graph.nodes[item.package].name,
                item.suggested_diff.to.clone(),
            )
        });

        // If we have duplicate suggestions in the output, e.g. due to multiple
        // versions of the same crate requiring the same new audit, deduplicate
        // them in the output to avoid clutter.
        suggestions.dedup_by(|a, b| {
            if self.graph.nodes[a.package].name == self.graph.nodes[b.package].name
                && a.suggested_diff == b.suggested_diff
            {
                // Per the `dedup_by` documentation, if true is returned, `a`
                // will be removed. Preserve its notable parents.
                b.notable_parents.extend_from_slice(&a.notable_parents);
                true
            } else {
                false
            }
        });

        // Sort and remove any duplicate entries from `notable_parents`.
        for s in &mut suggestions {
            s.notable_parents.sort();
            s.notable_parents.dedup();
        }

        let total_lines = suggestions
            .iter()
            .map(|s| s.suggested_diff.diffstat.count())
            .sum();

        let mut suggestions_by_criteria = SortedMap::<CriteriaName, Vec<SuggestItem>>::new();
        for s in suggestions.clone().into_iter() {
            let criteria_names = self
                .criteria_mapper
                .criteria_names(&s.suggested_criteria)
                .collect::<Vec<_>>()
                .join(", ");

            suggestions_by_criteria
                .entry(criteria_names)
                .or_default()
                .push(s);
        }

        Ok(Some(Suggest {
            suggestions,
            suggestions_by_criteria,
            total_lines,
            warnings: warnings.into_inner(),
        }))
    }

    /// Given a package name and a delta to be certified, determine the set of
    /// additional criteria for that delta/version pair which would have a
    /// healing impact on the audit graph.
    ///
    /// This is more reliable than running a suggest and looking for a matching
    /// output, as it will also select criteria for non-suggested audits.
    pub fn compute_suggested_criteria(
        &self,
        package_name: PackageStr<'_>,
        from: Option<&VetVersion>,
        to: &VetVersion,
    ) -> Vec<CriteriaName> {
        let fail = if let Conclusion::FailForVet(fail) = &self.conclusion {
            fail
        } else {
            return Vec::new();
        };

        let mut criteria = self.criteria_mapper.no_criteria();

        // Make owned versions of the `Version` types, such that we can look
        // them up in search results more easily.
        let from = from.cloned();
        let to = Some(to.clone());

        // Enumerate over the recorded failures, adding any criteria for this
        // delta which would connect that package version into the audit graph.
        for (failure_idx, audit_failure) in &fail.failures {
            let package = &self.graph.nodes[*failure_idx];
            if package.name != package_name {
                continue;
            }

            let result = &self.results[*failure_idx]
                .as_ref()
                .expect("failure without ResolveResults?");
            for criteria_idx in audit_failure.criteria_failures.indices() {
                let search_result = &result.search_results[criteria_idx];
                if let Err(SearchFailure {
                    reachable_from_root,
                    reachable_from_target,
                }) = search_result
                {
                    if reachable_from_target.contains(&to) && reachable_from_root.contains(&from) {
                        criteria.set_criteria(criteria_idx);
                    }
                }
            }
        }

        self.criteria_mapper
            .criteria_names(&criteria)
            .map(str::to_owned)
            .collect()
    }

    /// Print a full human-readable report
    pub fn print_human(
        &self,
        out: &Arc<dyn Out>,
        cfg: &Config,
        suggest: Option<&Suggest>,
    ) -> Result<(), std::io::Error> {
        match &self.conclusion {
            Conclusion::Success(res) => res.print_human(out, self, cfg),
            Conclusion::FailForViolationConflict(res) => res.print_human(out, self, cfg),
            Conclusion::FailForVet(res) => res.print_human(out, self, cfg, suggest),
        }
    }

    /// Print only the suggest portion of a human-readable report
    pub fn print_suggest_human(
        &self,
        out: &Arc<dyn Out>,
        _cfg: &Config,
        suggest: Option<&Suggest>,
    ) -> Result<(), std::io::Error> {
        if let Some(suggest) = suggest {
            suggest.print_human(out, self)?;
        } else {
            // This API is only used for vet-suggest
            writeln!(out, "Nothing to suggest, you're fully audited!");
        }
        Ok(())
    }

    /// Print a full json report
    pub fn print_json(
        &self,
        out: &Arc<dyn Out>,
        suggest: Option<&Suggest>,
    ) -> Result<(), miette::Report> {
        let result = JsonReport {
            conclusion: match &self.conclusion {
                Conclusion::Success(success) => {
                    let json_package = |pkgidx: &PackageIdx| {
                        let package = &self.graph.nodes[*pkgidx];
                        JsonPackage {
                            name: package.name.to_owned(),
                            version: package.version.clone(),
                        }
                    };
                    JsonReportConclusion::Success(JsonReportSuccess {
                        vetted_fully: success.vetted_fully.iter().map(json_package).collect(),
                        vetted_partially: success
                            .vetted_partially
                            .iter()
                            .map(json_package)
                            .collect(),
                        vetted_with_exemptions: success
                            .vetted_with_exemptions
                            .iter()
                            .map(json_package)
                            .collect(),
                    })
                }
                Conclusion::FailForViolationConflict(fail) => {
                    JsonReportConclusion::FailForViolationConflict(
                        JsonReportFailForViolationConflict {
                            violations: fail
                                .violations
                                .iter()
                                .map(|(pkgidx, violations)| {
                                    let package = &self.graph.nodes[*pkgidx];
                                    let key = format!("{}:{}", package.name, package.version);
                                    (key, violations.clone())
                                })
                                .collect(),
                        },
                    )
                }
                Conclusion::FailForVet(fail) => {
                    // FIXME: How to report confidence for suggested criteria?
                    let json_suggest_item = |item: &SuggestItem| {
                        let package = &self.graph.nodes[item.package];
                        JsonSuggestItem {
                            name: package.name.to_owned(),
                            notable_parents: FormatShortList::string(item.notable_parents.clone()),
                            suggested_criteria: self
                                .criteria_mapper
                                .criteria_names(&item.suggested_criteria)
                                .map(|s| s.to_owned())
                                .collect(),
                            suggested_diff: item.suggested_diff.clone(),
                        }
                    };
                    JsonReportConclusion::FailForVet(JsonReportFailForVet {
                        failures: fail
                            .failures
                            .iter()
                            .map(|(pkgidx, audit_fail)| {
                                let package = &self.graph.nodes[*pkgidx];
                                JsonVetFailure {
                                    name: package.name.to_owned(),
                                    version: package.version.clone(),
                                    missing_criteria: self
                                        .criteria_mapper
                                        .criteria_names(&audit_fail.criteria_failures)
                                        .map(|s| s.to_owned())
                                        .collect(),
                                }
                            })
                            .collect(),
                        suggest: suggest.as_ref().map(|suggest| JsonSuggest {
                            suggestions: suggest
                                .suggestions
                                .iter()
                                .map(json_suggest_item)
                                .collect(),
                            suggest_by_criteria: suggest
                                .suggestions_by_criteria
                                .iter()
                                .map(|(criteria, items)| {
                                    (
                                        criteria.to_owned(),
                                        items.iter().map(json_suggest_item).collect::<Vec<_>>(),
                                    )
                                })
                                .collect(),
                            total_lines: suggest.total_lines,
                        }),
                    })
                }
            },
        };

        serde_json::to_writer_pretty(&**out, &result).into_diagnostic()?;

        Ok(())
    }
}

impl Success {
    pub fn print_human(
        &self,
        out: &Arc<dyn Out>,
        _report: &ResolveReport<'_>,
        _cfg: &Config,
    ) -> Result<(), std::io::Error> {
        let fully_audited_count = self.vetted_fully.len();
        let partially_audited_count: usize = self.vetted_partially.len();
        let exemptions_count = self.vetted_with_exemptions.len();

        // Figure out how many entries we're going to print
        let mut count_count = (fully_audited_count != 0) as usize
            + (partially_audited_count != 0) as usize
            + (exemptions_count != 0) as usize;

        // Print out a summary of how we succeeded
        if count_count == 0 {
            writeln!(
                out,
                "Vetting Succeeded (because you have no third-party dependencies)"
            );
        } else {
            write!(out, "Vetting Succeeded (");

            if fully_audited_count != 0 {
                write!(out, "{fully_audited_count} fully audited");
                count_count -= 1;
                if count_count > 0 {
                    write!(out, ", ");
                }
            }
            if partially_audited_count != 0 {
                write!(out, "{partially_audited_count} partially audited");
                count_count -= 1;
                if count_count > 0 {
                    write!(out, ", ");
                }
            }
            if exemptions_count != 0 {
                write!(out, "{exemptions_count} exempted");
                count_count -= 1;
                if count_count > 0 {
                    write!(out, ", ");
                }
            }

            writeln!(out, ")");
        }
        Ok(())
    }
}

impl Suggest {
    pub fn print_human(
        &self,
        out: &Arc<dyn Out>,
        report: &ResolveReport<'_>,
    ) -> Result<(), std::io::Error> {
        for (criteria, suggestions) in &self.suggestions_by_criteria {
            writeln!(out, "recommended audits for {criteria}:");

            let mut strings = suggestions
                .iter()
                .map(|item| {
                    let package = &report.graph.nodes[item.package];
                    let cmd = match &item.suggested_diff.from {
                        Some(from) => format!(
                            "cargo vet diff {} {} {}",
                            package.name, from, item.suggested_diff.to
                        ),
                        None => format!(
                            "cargo vet inspect {} {}",
                            package.name, item.suggested_diff.to
                        ),
                    };
                    let publisher = item
                        .publisher_login
                        .clone()
                        .unwrap_or_else(|| "UNKNOWN".into());
                    let parents = FormatShortList::string(item.notable_parents.clone());
                    let diffstat = match &item.suggested_diff.from {
                        Some(_) => format!("{}", item.suggested_diff.diffstat),
                        None => format!("{} lines", item.suggested_diff.diffstat.count()),
                    };
                    (cmd, publisher, parents, diffstat, item)
                })
                .collect::<Vec<_>>();

            let (h0, h1, h2, h3) = ("Command", "Publisher", "Used By", "Audit Size");
            let mut max0 = console::measure_text_width(h0);
            let mut max1 = console::measure_text_width(h1);
            let mut max2 = console::measure_text_width(h2);
            for (s0, s1, s2, ..) in &mut strings {
                // If the command is too long (happens occasionally, particularly with @git
                // version specifiers), wrap subsequent columns to the next line.
                const MAX_COMMAND_CHARS: usize = 52;
                let command_width = console::measure_text_width(s0);
                if command_width > MAX_COMMAND_CHARS {
                    s0.push('\n');
                    s0.push_str(&" ".repeat(MAX_COMMAND_CHARS + 4));
                }
                max0 = max0.max(command_width.min(MAX_COMMAND_CHARS));
                max1 = max1.max(console::measure_text_width(s1));
                max2 = max2.max(console::measure_text_width(s2));
            }

            writeln!(
                out,
                "{}",
                out.style()
                    .bold()
                    .dim()
                    .apply_to(format_args!("    {h0:max0$}  {h1:max1$}  {h2:max2$}  {h3}"))
            );
            for (s0, s1, s2, s3, item) in strings {
                let package = &report.graph.nodes[item.package];

                write!(
                    out,
                    "{}",
                    out.style()
                        .cyan()
                        .bold()
                        .apply_to(format_args!("    {s0:max0$}"))
                );
                writeln!(out, "  {s1:max1$}  {s2:max2$}  {s3}");

                let dim = out.style().dim();
                for suggestion in &item.registry_suggestion {
                    writeln!(
                        out,
                        "      {} {} {}",
                        dim.clone().apply_to("NOTE:"),
                        dim.clone()
                            .cyan()
                            .bold()
                            .apply_to(format_args!("cargo vet import {}", suggestion.name)),
                        dim.clone()
                            .apply_to(match suggestion.diff.diffstat.count() {
                                0 => "would eliminate this".to_owned(),
                                n => format!("would reduce this to a {n}-line diff"),
                            }),
                    );
                }
                if let Some(hint) = &item.trust_hint {
                    let trust = if hint.trusted_by.len() == 1 {
                        "trusts"
                    } else {
                        "trust"
                    };
                    let caveat = if !hint.exact_version {
                        ", who published another version of this crate"
                    } else {
                        ""
                    };
                    let publisher = hint.publisher.clone();
                    let trusted_by = FormatShortList::new(hint.trusted_by.clone());
                    writeln!(
                        out,
                        "      {} {}",
                        dim.clone().apply_to(format_args!(
                            "NOTE: {trusted_by} {trust} {publisher}{caveat} - consider",
                        )),
                        if item.is_sole_publisher {
                            let this_cmd = format!("cargo vet trust {}", package.name);
                            let all_cmd = format!("cargo vet trust --all {}", publisher.login);
                            format!(
                                "{} {} {}",
                                dim.clone().cyan().apply_to(this_cmd),
                                dim.clone().apply_to("or"),
                                dim.clone().cyan().apply_to(all_cmd),
                            )
                        } else {
                            let cmd =
                                format!("cargo vet trust {} {}", package.name, publisher.login);
                            dim.clone().cyan().apply_to(cmd).to_string()
                        }
                    );
                }
            }

            writeln!(out);
        }

        writeln!(out, "estimated audit backlog: {} lines", self.total_lines);

        if !self.warnings.is_empty() {
            writeln!(out);
            for warning in &self.warnings {
                writeln!(
                    out,
                    "{}: {warning}",
                    out.style().yellow().apply_to("WARNING"),
                );
            }
        }

        writeln!(out);
        writeln!(out, "Use |cargo vet certify| to record the audits.");

        Ok(())
    }
}

impl FailForVet {
    fn print_human(
        &self,
        out: &Arc<dyn Out>,
        report: &ResolveReport<'_>,
        _cfg: &Config,
        suggest: Option<&Suggest>,
    ) -> Result<(), std::io::Error> {
        writeln!(out, "Vetting Failed!");
        writeln!(out);
        writeln!(out, "{} unvetted dependencies:", self.failures.len());
        let mut failures = self
            .failures
            .iter()
            .map(|(failed_idx, failure)| (&report.graph.nodes[*failed_idx], failure))
            .collect::<Vec<_>>();
        failures.sort_by_key(|(failed, _)| &failed.version);
        failures.sort_by_key(|(failed, _)| failed.name);
        for (failed_package, failed_audit) in failures {
            let criteria = report
                .criteria_mapper
                .criteria_names(&failed_audit.criteria_failures)
                .collect::<Vec<_>>();

            let label = format!("  {}:{}", failed_package.name, failed_package.version);
            writeln!(out, "{label} missing {criteria:?}");
        }

        // Suggest output generally requires hitting the network.
        if let Some(suggest) = suggest {
            writeln!(out);
            suggest.print_human(out, report)?;
        }

        Ok(())
    }
}

impl FailForViolationConflict {
    fn print_human(
        &self,
        out: &Arc<dyn Out>,
        report: &ResolveReport<'_>,
        _cfg: &Config,
    ) -> Result<(), std::io::Error> {
        writeln!(out, "Violations Found!");

        for (pkgidx, violations) in &self.violations {
            let package = &report.graph.nodes[*pkgidx];
            writeln!(out, "  {}:{}", package.name, package.version);
            for violation in violations {
                match violation {
                    ViolationConflict::UnauditedConflict {
                        violation_source,
                        violation,
                        exemptions,
                    } => {
                        write!(out, "    the ");
                        print_exemption(out, exemptions)?;
                        write!(out, "    conflicts with ");
                        print_entry(out, violation_source, violation)?;
                    }
                    ViolationConflict::AuditConflict {
                        violation_source,
                        violation,
                        audit_source,
                        audit,
                    } => {
                        write!(out, "    the ");
                        print_entry(out, audit_source, audit)?;
                        write!(out, "    conflicts with ");
                        print_entry(out, violation_source, violation)?;
                    }
                }
                writeln!(out);
            }
        }

        fn print_exemption(
            out: &Arc<dyn Out>,
            entry: &ExemptedDependency,
        ) -> Result<(), std::io::Error> {
            writeln!(out, "exemption {}", entry.version);
            writeln!(out, "      criteria: {:?}", entry.criteria);
            if let Some(notes) = &entry.notes {
                writeln!(out, "      notes: {notes}");
            }
            Ok(())
        }

        fn print_entry(
            out: &Arc<dyn Out>,
            source: &Option<ImportName>,
            entry: &AuditEntry,
        ) -> Result<(), std::io::Error> {
            match source {
                None => write!(out, "own "),
                Some(name) => write!(out, "foreign ({name}) "),
            }
            match &entry.kind {
                AuditKind::Full { version, .. } => {
                    writeln!(out, "audit {version}");
                }
                AuditKind::Delta { from, to, .. } => {
                    writeln!(out, "audit {from} -> {to}");
                }
                AuditKind::Violation { violation } => {
                    writeln!(out, "violation against {violation}");
                }
            }
            writeln!(out, "      criteria: {:?}", entry.criteria);
            for (idx, who) in entry.who.iter().enumerate() {
                if idx == 0 {
                    write!(out, "      who: {who}");
                } else {
                    write!(out, ", {who}");
                }
            }
            if !entry.who.is_empty() {
                writeln!(out);
            }
            if let Some(notes) = &entry.notes {
                writeln!(out, "      notes: {notes}");
            }
            Ok(())
        }

        Ok(())
    }
}

async fn suggest_delta(
    metadata: &cargo_metadata::Metadata,
    network: Option<&Network>,
    cache: &Cache,
    package_name: PackageStr<'_>,
    package_version: &VetVersion,
    failures: impl Iterator<Item = &SearchFailure>,
    warnings: &RefCell<Vec<String>>,
) -> Option<(DiffRecommendation, Option<DiffRecommendation>)> {
    // Fetch the set of known versions from crates.io so we know which versions
    // we'll have sources for.
    let known_versions = cache.get_versions(network, package_name).await.ok();

    // Collect up the details of how we failed
    struct Reachable<'a> {
        from_root: SortedSet<&'a Option<VetVersion>>,
        from_target: SortedSet<&'a Option<VetVersion>>,
    }
    let mut reachable = None::<Reachable<'_>>;
    for SearchFailure {
        reachable_from_root,
        reachable_from_target,
    } in failures
    {
        if let Some(Reachable {
            from_root,
            from_target,
        }) = reachable.as_mut()
        {
            // This does the right thing in the common cases, by restricting
            // ourselves to the reachable nodes that are common to all failures,
            // so that we can suggest just one change that will fix everything.
            from_root.retain(|ver| reachable_from_root.contains(ver));
            from_target.retain(|ver| reachable_from_target.contains(ver));
        } else {
            let version_has_sources = |ver: &&Option<VetVersion>| -> bool {
                // We always have sources for an empty crate.
                let Some(ver) = ver else { return true; };
                // We only have git sources for the package itself.
                if ver.git_rev.is_some() {
                    return ver == package_version;
                }
                // We have sources if the version has been published to crates.io.
                //
                // For testing fallbacks, assume we always have sources if the
                // index is unavailable.
                known_versions
                    .as_ref()
                    .map_or(true, |versions| versions.contains(&ver.semver))
            };
            reachable = Some(Reachable {
                from_root: reachable_from_root
                    .iter()
                    .filter(version_has_sources)
                    .collect(),
                from_target: reachable_from_target
                    .iter()
                    .filter(version_has_sources)
                    .collect(),
            });
        }
    }

    let Some(Reachable { from_root, from_target }) = &mut reachable else {
        // Nothing failed, return a dummy suggestion for an empty diff.
        return Some((
            DiffRecommendation {
                from: Some(package_version.clone()),
                to: package_version.clone(),
                diffstat: DiffStat { insertions: 0, deletions: 0, files_changed: 0 },
            },
            None,
        ));
    };

    // If we have a git revision, we want to ensure the nearest published
    // version has been audited before we suggest an audit for the git revision
    // itself.
    let published_version;
    let mut extra_delta = None;
    if package_version.git_rev.is_some() {
        // Find the largest published revision with an equal or lower semver
        // than the git revision. This will be the published version we
        // encourage auditing first.
        let closest_below = if let Some(known_versions) = &known_versions {
            known_versions
                .iter()
                .filter(|&v| v <= &package_version.semver)
                .max()
        } else {
            // For testing fallbacks, assume the bare version has been published
            // to crates.io.
            Some(&package_version.semver)
        };
        published_version = closest_below.map(|semver| VetVersion {
            semver: semver.clone(),
            git_rev: None,
        });
        // If the closest published version is not already audited, replace the
        // target version with `published_version` in the reachable from target
        // set, ensuring that a delta to that version is suggested rather than a
        // full audit for the git revision.
        if !from_root.contains(&published_version) {
            from_target.remove(&Some(package_version.clone()));
            if from_target.insert(&published_version) {
                extra_delta = Some(Delta {
                    from: published_version.clone(),
                    to: package_version.clone(),
                });
            }
        }
    }

    // Now suggest solutions of those failures
    let mut candidates = Vec::new();
    for &dest in &*from_target {
        let closest_above = from_root.range::<&Option<VetVersion>, _>(dest..).next();
        let closest_below = from_root
            .range::<&Option<VetVersion>, _>(..dest)
            .next_back();

        for &closest in closest_below.into_iter().chain(closest_above) {
            candidates.push(Delta {
                from: closest.clone(),
                to: dest.clone().unwrap(),
            });
        }
    }

    let do_fetch_and_diffstat = |delta| async move {
        match cache
            .fetch_and_diffstat_package(metadata, network, package_name, &delta)
            .await
        {
            Ok(diffstat) => Some(DiffRecommendation {
                diffstat,
                from: delta.from.clone(),
                to: delta.to.clone(),
            }),
            Err(err) => {
                // We don't want to actually error out completely here,
                // as other packages might still successfully diff!
                warnings
                    .borrow_mut()
                    .push(format!("error diffing {}:{}: {}", package_name, delta, err));
                None
            }
        }
    };

    let diffstats = join_all(candidates.into_iter().map(do_fetch_and_diffstat)).await;

    // If we need an "extra delta" due to a git revision, also get the diffstat
    // for that entry.
    let extra_diffstat = if let Some(delta) = extra_delta {
        do_fetch_and_diffstat(delta).await
    } else {
        None
    };

    let recommendation = diffstats
        .into_iter()
        .flatten()
        .min_by_key(|diff| diff.diffstat.count())?;

    Some((recommendation, extra_diffstat))
}

/// Resolve which entries in the store and imports.lock are required to
/// successfully audit this package. May return `None` if the package cannot
/// successfully vet given the restrictions placed upon it.
///
/// NOTE: A package which does not exist in the dependency will return the empty
/// set, as it does not have any audit requirements.
///
/// [`SearchMode`] controls how edges are selected when searching for paths.
#[tracing::instrument(skip(graph, criteria_mapper, requirements, store))]
fn resolve_package_required_entries(
    graph: &DepGraph<'_>,
    criteria_mapper: &CriteriaMapper,
    requirements: &[CriteriaSet],
    store: &Store,
    package_name: PackageStr<'_>,
    search_mode: SearchMode,
) -> Option<SortedMap<RequiredEntry, CriteriaSet>> {
    assert_eq!(graph.nodes.len(), requirements.len());

    // Collect the list of third-party packages with the given name, along with
    // their requirements.
    let packages: Vec<_> = graph
        .nodes
        .iter()
        .zip(requirements)
        .filter(|(package, _)| package.name == package_name && package.is_third_party)
        .collect();

    // If there are no third-party packages with the name, we definitely don't
    // need any entries.
    if packages.is_empty() {
        return Some(SortedMap::new());
    }

    let Ok(audit_graph) = AuditGraph::build(store, criteria_mapper, package_name, None) else {
        // There were violations when building the audit graph, return `None` to
        // indicate that this package is failing.
        return None;
    };

    let mut required_entries = SortedMap::new();
    for &(package, reqs) in &packages {
        // Do the minimal set of searches to validate that the required criteria
        // are matched.
        for criteria_idx in criteria_mapper.minimal_indices(reqs) {
            let Ok(path) = audit_graph.search(criteria_idx, &package.version, search_mode) else {
                // This package failed to vet, return `None`.
                return None;
            };

            let mut add_entry = |entry: RequiredEntry| {
                required_entries
                    .entry(entry)
                    .or_insert_with(|| criteria_mapper.no_criteria())
                    .set_criteria(criteria_idx);
            };

            for origin in path {
                match origin {
                    DeltaEdgeOrigin::Exemption { exemption_index } => {
                        add_entry(RequiredEntry::Exemption { exemption_index });
                    }
                    DeltaEdgeOrigin::FreshExemption { version } => {
                        add_entry(RequiredEntry::FreshExemption { version });
                    }
                    DeltaEdgeOrigin::ImportedAudit {
                        import_index,
                        audit_index,
                    } => {
                        add_entry(RequiredEntry::Audit {
                            import_index,
                            audit_index,
                        });
                    }
                    DeltaEdgeOrigin::WildcardAudit {
                        import_index,
                        audit_index,
                        publisher_index,
                    } => {
                        if let Some(import_index) = import_index {
                            add_entry(RequiredEntry::WildcardAudit {
                                import_index,
                                audit_index,
                            })
                        }
                        add_entry(RequiredEntry::Publisher { publisher_index })
                    }
                    DeltaEdgeOrigin::Trusted { publisher_index } => {
                        add_entry(RequiredEntry::Publisher { publisher_index })
                    }
                    DeltaEdgeOrigin::Unpublished { unpublished_index } => {
                        add_entry(RequiredEntry::Unpublished { unpublished_index })
                    }
                    DeltaEdgeOrigin::StoredLocalAudit { .. } => {}
                }
            }
        }
        continue;
    }

    Some(required_entries)
}

/// Per-package options to control store pruning.
#[derive(Copy, Clone)]
pub struct UpdateMode {
    pub search_mode: SearchMode,
    pub prune_exemptions: bool,
    pub prune_imports: bool,
}

/// Refresh the state of the store, importing required audits, and optionally
/// pruning unnecessary exemptions and/or imports.
pub fn update_store(
    cfg: &Config,
    store: &mut Store,
    mode: impl FnMut(PackageStr<'_>) -> UpdateMode,
) {
    let (new_imports, new_exemptions) = get_store_updates(cfg, store, mode);

    // Update the store to reflect the new imports and exemptions files.
    store.imports = new_imports;
    store.config.exemptions = new_exemptions;
}

/// The non-mutating core of `update_store` for use in non-mutating situations.
pub(crate) fn get_store_updates(
    cfg: &Config,
    store: &Store,
    mut mode: impl FnMut(PackageStr<'_>) -> UpdateMode,
) -> (ImportsFile, SortedMap<PackageName, Vec<ExemptedDependency>>) {
    // Compute the set of required entries from the store for all packages in
    // the dependency graph.
    let graph = DepGraph::new(
        &cfg.metadata,
        cfg.cli.filter_graph.as_ref(),
        Some(&store.config.policy),
    );
    let criteria_mapper = CriteriaMapper::new(&store.audits.criteria);
    let requirements = resolve_requirements(&graph, &store.config.policy, &criteria_mapper);

    let mut required_entries = SortedMap::new();
    for package in &graph.nodes {
        required_entries.entry(package.name).or_insert_with(|| {
            resolve_package_required_entries(
                &graph,
                &criteria_mapper,
                &requirements,
                store,
                package.name,
                mode(package.name).search_mode,
            )
        });
    }

    // Dummy value to use if a package isn't found in `required_entries` - no
    // edges will be required.
    let no_required_entries = Some(SortedMap::new());

    let mut new_imports = ImportsFile {
        unpublished: SortedMap::new(),
        publisher: SortedMap::new(),
        audits: SortedMap::new(),
    };

    // Determine which live imports to keep in the imports.lock file.
    for (import_index, (import_name, live_audits_file)) in
        store.imported_audits().iter().enumerate()
    {
        let new_audits_file = AuditsFile {
            criteria: live_audits_file.criteria.clone(),

            wildcard_audits: live_audits_file
                .wildcard_audits
                .iter()
                .map(|(pkgname, wildcard_audits)| {
                    let prune_imports = mode(&pkgname[..]).prune_imports;
                    let required_entries = required_entries
                        .get(&pkgname[..])
                        .unwrap_or(&no_required_entries);
                    (
                        pkgname,
                        wildcard_audits
                            .iter()
                            .enumerate()
                            .filter(|&(audit_index, entry)| {
                                // Keep existing if we're not pruning imports.
                                if !prune_imports && !entry.is_fresh_import {
                                    return true;
                                }

                                if let Some(required_entries) = required_entries {
                                    required_entries.contains_key(&RequiredEntry::WildcardAudit {
                                        import_index,
                                        audit_index,
                                    })
                                } else {
                                    !entry.is_fresh_import
                                }
                            })
                            .map(|(_, entry)| WildcardEntry {
                                is_fresh_import: false,
                                ..entry.clone()
                            })
                            .collect::<Vec<_>>(),
                    )
                })
                .filter(|(_, l)| !l.is_empty())
                .map(|(n, mut l)| {
                    l.sort();
                    (n.clone(), l)
                })
                .collect(),

            audits: live_audits_file
                .audits
                .iter()
                .map(|(pkgname, audits)| {
                    let prune_imports = mode(&pkgname[..]).prune_imports;
                    let (uses_package, required_entries) = match required_entries.get(&pkgname[..])
                    {
                        Some(e) => (true, e),
                        None => (false, &no_required_entries),
                    };
                    (
                        pkgname,
                        audits
                            .iter()
                            .enumerate()
                            .filter(|&(audit_index, entry)| {
                                // Keep existing if we're not pruning imports.
                                if !prune_imports && !entry.is_fresh_import {
                                    return true;
                                }

                                // Keep violations if the package is used in the graph.
                                if matches!(entry.kind, AuditKind::Violation { .. }) {
                                    return uses_package;
                                }

                                if let Some(required_entries) = required_entries {
                                    required_entries.contains_key(&RequiredEntry::Audit {
                                        import_index,
                                        audit_index,
                                    })
                                } else {
                                    !entry.is_fresh_import
                                }
                            })
                            .map(|(_, entry)| AuditEntry {
                                is_fresh_import: false,
                                ..entry.clone()
                            })
                            .collect::<Vec<_>>(),
                    )
                })
                .filter(|(_, l)| !l.is_empty())
                .map(|(n, mut l)| {
                    l.sort();
                    (n.clone(), l)
                })
                .collect(),

            // We never import trusted entries in imports.lock.
            trusted: SortedMap::new(),
        };
        new_imports
            .audits
            .insert(import_name.clone(), new_audits_file);
    }

    // Determine which live publisher information to keep in the imports.lock file.
    for (pkgname, publishers) in store.publishers() {
        let prune_imports = mode(&pkgname[..]).prune_imports;
        let required_entries = required_entries
            .get(&pkgname[..])
            .unwrap_or(&no_required_entries);
        let mut publishers: Vec<_> = publishers
            .iter()
            .enumerate()
            .filter(|&(publisher_index, entry)| {
                // Keep existing if we're not pruning imports.
                if !prune_imports && !entry.is_fresh_import {
                    return true;
                }

                if let Some(required_entries) = required_entries {
                    required_entries.contains_key(&RequiredEntry::Publisher { publisher_index })
                } else {
                    !entry.is_fresh_import
                }
            })
            .map(|(_, entry)| CratesPublisher {
                is_fresh_import: false,
                ..entry.clone()
            })
            .collect();
        publishers.sort();
        if !publishers.is_empty() {
            new_imports.publisher.insert(pkgname.clone(), publishers);
        }
    }

    // Determine which live publisher information to keep in the imports.lock file.
    for (pkgname, unpublished) in store.unpublished() {
        // Although `unpublished` entries are stored in imports.lock, they're
        // more like automatically-managed delta-exemptions than imports, so
        // we'll prune them when pruning exemptions.
        let prune_exemptions = mode(&pkgname[..]).prune_exemptions;
        let required_entries = required_entries
            .get(&pkgname[..])
            .unwrap_or(&no_required_entries);
        let mut unpublished: Vec<_> = unpublished
            .iter()
            .enumerate()
            .filter(|&(unpublished_index, entry)| {
                // Keep existing if we're not pruning exemptions.
                if !prune_exemptions && !entry.is_fresh_import {
                    return true;
                }

                if let Some(required_entries) = required_entries {
                    required_entries.contains_key(&RequiredEntry::Unpublished { unpublished_index })
                } else {
                    !entry.is_fresh_import
                }
            })
            .map(|(_, entry)| UnpublishedEntry {
                is_fresh_import: false,
                ..entry.clone()
            })
            .collect();
        unpublished.sort();
        // Clean up any duplicate Unpublished entries now that `is_fresh_import`
        // has been cleared.  This ensures that even if we end up using
        // `PreferFreshImports` when not pruning exemptions, we won't end up
        // with duplicate unpublished entries.
        unpublished.dedup();
        if !unpublished.is_empty() {
            new_imports.unpublished.insert(pkgname.clone(), unpublished);
        }
    }

    let mut all_new_exemptions = SortedMap::new();

    // Enumerate existing exemptions to check for criteria changes.
    for (pkgname, exemptions) in &store.config.exemptions {
        let prune_exemptions = mode(pkgname).prune_exemptions;
        let required_entries = required_entries
            .get(&pkgname[..])
            .unwrap_or(&no_required_entries);

        let mut new_exemptions = Vec::with_capacity(exemptions.len());
        for (exemption_index, entry) in exemptions.iter().enumerate() {
            let original_criteria = criteria_mapper.criteria_from_list(&entry.criteria);

            // Determine the set of useful criteria from required_entries,
            // falling back to `original_criteria` if it failed to audit.
            let mut useful_criteria = if let Some(required_entries) = required_entries {
                required_entries
                    .get(&RequiredEntry::Exemption { exemption_index })
                    .cloned()
                    .unwrap_or_else(|| criteria_mapper.no_criteria())
            } else {
                original_criteria.clone()
            };

            // If we're not pruning exemptions, maintain all existing criteria.
            if !prune_exemptions {
                useful_criteria.unioned_with(&original_criteria);
            }
            if useful_criteria.is_empty() {
                continue; // Skip this exemption
            }

            // If we're expanding the criteria set and are `suggest = false`, we
            // can't update the existing entry, so try adding a new one, and
            // reset the existing node to the original criteria.
            // XXX: The behaviour around suggest here is a bit jank, we might
            // want to change it.
            if !entry.suggest && !original_criteria.contains(&useful_criteria) {
                let mut extra_criteria = useful_criteria.clone();
                extra_criteria.clear_criteria(&original_criteria);
                new_exemptions.push(ExemptedDependency {
                    version: entry.version.clone(),
                    criteria: criteria_mapper
                        .criteria_names(&extra_criteria)
                        .map(|n| n.to_owned().into())
                        .collect(),
                    suggest: true,
                    notes: None,
                });
                useful_criteria = original_criteria;
            }

            // Add the exemption with the determined minimal useful criteria.
            new_exemptions.push(ExemptedDependency {
                version: entry.version.clone(),
                criteria: criteria_mapper
                    .criteria_names(&useful_criteria)
                    .map(|n| n.to_owned().into())
                    .collect(),
                suggest: entry.suggest,
                notes: entry.notes.clone(),
            });
        }
        if !new_exemptions.is_empty() {
            all_new_exemptions.insert(pkgname.clone(), new_exemptions);
        }
    }

    // Check if we have any FreshExemption entries which should be converted
    // into new exemptions.
    for (&pkgname, required_entries) in &required_entries {
        let Some(required_entries) = required_entries else { continue };

        for (entry, criteria) in required_entries.iter().rev() {
            let RequiredEntry::FreshExemption { version } = entry else {
                // FreshExemption entries always sort last in the BTreeMap, so
                // we can rely on there being no more FreshExemption entries
                // after we've seen one.
                break;
            };

            all_new_exemptions
                .entry(pkgname.to_owned())
                .or_default()
                .push(ExemptedDependency {
                    version: version.clone(),
                    criteria: criteria_mapper
                        .criteria_names(criteria)
                        .map(|n| n.to_owned().into())
                        .collect(),
                    suggest: true,
                    notes: None,
                });
        }
    }

    for exemptions in all_new_exemptions.values_mut() {
        exemptions.sort();
    }

    (new_imports, all_new_exemptions)
}
