use crate::config::{LayerPolicy, ProfileLayer};
use crate::errors::Result;
use super::packages::filter_rejected;
use super::policy::{has_content, policy_items_to_spec};
use super::record::{record_policy_conflicts, record_rejections};
use super::{CompositionInput, ConflictResolution, ResolutionType};
pub(super) fn build_source_layers(
input: &CompositionInput,
conflicts: &mut Vec<ConflictResolution>,
) -> Result<Vec<ProfileLayer>> {
let mut layers = Vec::new();
let policy = &input.policy;
if has_content(&policy.locked) {
let spec = policy_items_to_spec(&policy.locked);
layers.push(ProfileLayer {
source: input.source_name.clone(),
profile_name: format!("{}/locked", input.source_name),
priority: u32::MAX, policy: LayerPolicy::Required, spec,
});
record_policy_conflicts(
&input.source_name,
&policy.locked,
ResolutionType::Locked,
conflicts,
);
}
if has_content(&policy.required) {
let spec = policy_items_to_spec(&policy.required);
layers.push(ProfileLayer {
source: input.source_name.clone(),
profile_name: format!("{}/required", input.source_name),
priority: input.priority + 1000, policy: LayerPolicy::Required,
spec,
});
record_policy_conflicts(
&input.source_name,
&policy.required,
ResolutionType::Required,
conflicts,
);
}
if has_content(&policy.recommended) && input.subscription.accept_recommended {
let filtered = filter_rejected(&policy.recommended, &input.subscription.reject);
if has_content(&filtered) {
let spec = policy_items_to_spec(&filtered);
layers.push(ProfileLayer {
source: input.source_name.clone(),
profile_name: format!("{}/recommended", input.source_name),
priority: input.priority,
policy: LayerPolicy::Recommended,
spec,
});
}
record_rejections(
&input.source_name,
&policy.recommended,
&input.subscription.reject,
conflicts,
);
}
for opt_profile in &input.subscription.opt_in {
if policy.optional.profiles.contains(opt_profile) {
for source_layer in &input.layers {
if source_layer.profile_name == *opt_profile {
layers.push(ProfileLayer {
source: input.source_name.clone(),
profile_name: source_layer.profile_name.clone(),
priority: input.priority,
policy: LayerPolicy::Optional,
spec: source_layer.spec.clone(),
});
}
}
}
}
for source_layer in &input.layers {
let already_added = layers
.iter()
.any(|l| l.profile_name == source_layer.profile_name);
if !already_added {
layers.push(ProfileLayer {
source: input.source_name.clone(),
profile_name: source_layer.profile_name.clone(),
priority: input.priority,
policy: LayerPolicy::Recommended,
spec: source_layer.spec.clone(),
});
}
}
Ok(layers)
}
pub(super) struct FileOwner {
pub(super) source: String,
pub(super) policy: LayerPolicy,
pub(super) priority: u32,
}