callisto-graph 0.3.1

Dependency graph, cascade, aggregation, and config resolution for callisto.
Documentation
use std::collections::BTreeSet;

use callisto_model::{
    DeclaredEdge, DeclaredEdgeKind, Diagnostic, DiagnosticCode, DiagnosticSeverity, StrictFlag,
};

use crate::resolver::ManifestWalkResolver;

pub fn crosscheck_declared_edges(
    graph: &ManifestWalkResolver,
    declared: &[DeclaredEdge],
) -> Vec<Diagnostic> {
    let mut diagnostics = Vec::new();

    let mut filtered_declared = BTreeSet::new();
    for edge in declared {
        if edge.kind == DeclaredEdgeKind::Root {
            continue;
        }
        if graph.get(&edge.from).is_some() && graph.get(&edge.to).is_some() {
            filtered_declared.insert((edge.from.clone(), edge.to.clone()));
        }
    }

    let mut graph_pairs = BTreeSet::new();
    for edge in graph.edges() {
        if edge.kind == callisto_model::DepKind::Dev {
            continue;
        }
        if graph.get(&edge.from).is_some() && graph.get(&edge.to).is_some() {
            graph_pairs.insert((edge.from.clone(), edge.to.clone()));
        }
    }

    for (from, to) in filtered_declared.difference(&graph_pairs) {
        diagnostics.push(Diagnostic {
            code: DiagnosticCode::GraphEdgeDisagreement,
            severity: DiagnosticSeverity::Warning,
            message: format!(
                "moon declares {} -> {} but no manifest declares it",
                from.display_name(),
                to.display_name()
            ),
            package: Some(from.clone()),
            path: None,
            governed_by: None,
            escalated_by: Some(StrictFlag::StrictGraph),
        });
    }

    for (from, to) in graph_pairs.difference(&filtered_declared) {
        diagnostics.push(Diagnostic {
            code: DiagnosticCode::GraphEdgeDisagreement,
            severity: DiagnosticSeverity::Warning,
            message: format!(
                "manifest declares {} -> {} but moon does not declare it",
                from.display_name(),
                to.display_name()
            ),
            package: Some(from.clone()),
            path: None,
            governed_by: None,
            escalated_by: Some(StrictFlag::StrictGraph),
        });
    }

    diagnostics
}