use std::collections::HashSet;
use pact_models::generators::{Generator, Generators};
use pact_models::matchingrules::{MatchingRule, MatchingRules};
use pact_models::pact::Pact;
use pact_plugin_driver::field::{find_field_generator, find_field_matcher};
use tracing::warn;
pub(crate) fn record_plugins_for_rules(pact: &mut (dyn Pact + Send + Sync)) {
let mut names: HashSet<String> = HashSet::new();
for interaction in pact.interactions() {
if let Some(http) = interaction.as_v4_http() {
collect_from_rules(&http.request.matching_rules, &mut names);
collect_from_generators(&http.request.generators, &mut names);
collect_from_rules(&http.response.matching_rules, &mut names);
collect_from_generators(&http.response.generators, &mut names);
} else if let Some(message) = interaction.as_v4_async_message() {
collect_from_rules(&message.contents.matching_rules, &mut names);
collect_from_generators(&message.contents.generators, &mut names);
} else if let Some(message) = interaction.as_v4_sync_message() {
collect_from_rules(&message.request.matching_rules, &mut names);
collect_from_generators(&message.request.generators, &mut names);
for response in &message.response {
collect_from_rules(&response.matching_rules, &mut names);
collect_from_generators(&response.generators, &mut names);
}
}
}
for name in names {
if let Some(manifest) = plugin_for(name.as_str()) {
if let Err(err) = pact.add_plugin(manifest.0.as_str(), manifest.1.as_str(), None) {
warn!("Could not record the plugin providing '{}' in the Pact metadata - {}", name, err);
}
}
}
}
fn collect_from_rules(rules: &MatchingRules, names: &mut HashSet<String>) {
for category in rules.rules.values() {
for rule_list in category.rules.values() {
for rule in &rule_list.rules {
if let MatchingRule::Plugin { name, .. } = rule {
names.insert(name.clone());
}
}
}
}
}
fn collect_from_generators(generators: &Generators, names: &mut HashSet<String>) {
for category in generators.categories.values() {
for generator in category.values() {
if let Generator::Plugin { name, .. } = generator {
names.insert(name.clone());
}
}
}
}
fn plugin_for(name: &str) -> Option<(String, String)> {
find_field_matcher(name).ok()
.and_then(|matcher| matcher.plugin())
.or_else(|| find_field_generator(name).ok().and_then(|generator| generator.plugin()))
.map(|manifest| (manifest.name.clone(), manifest.version.clone()))
}