fn do_aggregate_audits()

in src/main.rs [2488:2606]


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

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

    aggregate.tidy();

    if errors.is_empty() {
        Ok(aggregate)
    } else {
        Err(AggregateErrors { errors })
    }
}