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 })
}
}