use crate::config;
use crate::group::Group;
use guppy::graph::PackageGraph;
use guppy::PackageId;
fn get_group(id: &PackageId, graph: &PackageGraph, config: &config::BuildConfig) -> Option<Group> {
let name = graph.metadata(id).unwrap().name();
config.per_crate_config.get(name)?.group
}
pub fn find_inherited_privilege_group(
id: &PackageId,
root: &PackageId,
graph: &PackageGraph,
config: &config::BuildConfig,
) -> Group {
let mut ancestor_groups = Vec::<Group>::new();
let mut dependency_groups = Vec::<Group>::new();
for package in graph.packages() {
let each_id = package.id();
let found_group = get_group(each_id, graph, config).or_else(|| {
if graph.directly_depends_on(root, each_id).unwrap() {
Some(Group::Safe)
} else {
None
}
});
if let Some(group) = found_group {
if graph.depends_on(each_id, id).unwrap() {
log::debug!("{id} ancestor {each_id} ({group:?})");
ancestor_groups.push(group);
} else if graph.depends_on(id, each_id).unwrap() {
log::debug!("{id} dependency {each_id} ({group:?})");
dependency_groups.push(group);
}
};
}
if let Some(self_group) = get_group(id, graph, config) {
ancestor_groups.clear();
ancestor_groups.push(self_group);
}
let ancestor_privilege = ancestor_groups.into_iter().fold(Group::Test, std::cmp::max);
let depedency_privilege = dependency_groups.into_iter().fold(Group::Safe, std::cmp::min);
let privilege = std::cmp::min(ancestor_privilege, depedency_privilege);
log::debug!("privilege = {privilege:?}");
privilege
}
fn find_inherited_bool_flag(
id: &PackageId,
root: &PackageId,
graph: &PackageGraph,
config: &config::BuildConfig,
mut get_flag: impl FnMut(&PackageId) -> Option<bool>,
mut get_flag_for_top_level: impl FnMut(Option<Group>) -> Option<bool>,
) -> Option<bool> {
let mut inherited_flag = None;
for package in graph.packages() {
let each_id = package.id();
let group = get_group(each_id, graph, config);
if let Some(flag) = get_flag(each_id).or_else(|| {
if graph.directly_depends_on(root, each_id).unwrap() {
get_flag_for_top_level(group)
} else {
None
}
}) {
if graph.depends_on(each_id, id).unwrap() {
log::debug!("{id} ancestor {each_id} ({flag:?})");
inherited_flag = Some(inherited_flag.unwrap_or_default() || flag);
}
};
}
inherited_flag
}
pub fn find_inherited_security_critical_flag(
id: &PackageId,
root: &PackageId,
graph: &PackageGraph,
config: &config::BuildConfig,
) -> Option<bool> {
let get_security_critical = |id: &PackageId| {
let name = graph.metadata(id).unwrap().name();
config.per_crate_config.get(name).and_then(|config| config.security_critical)
};
let get_top_level_security_critical = |group: Option<Group>| {
match group {
Some(Group::Safe) | Some(Group::Sandbox) | None => Some(true),
Some(Group::Test) => None,
}
};
let inherited_flag = find_inherited_bool_flag(
id,
root,
graph,
config,
get_security_critical,
get_top_level_security_critical,
);
log::debug!("{id} security_critical {inherited_flag:?}");
inherited_flag
}
pub fn find_inherited_shipped_flag(
id: &PackageId,
root: &PackageId,
graph: &PackageGraph,
config: &config::BuildConfig,
) -> Option<bool> {
let get_shipped = |id: &PackageId| {
let name = graph.metadata(id).unwrap().name();
config.per_crate_config.get(name).and_then(|config| config.shipped)
};
let get_top_level_shipped = |group: Option<Group>| {
match group {
Some(Group::Safe) | Some(Group::Sandbox) | None => Some(true),
Some(Group::Test) => None,
}
};
let inherited_flag =
find_inherited_bool_flag(id, root, graph, config, get_shipped, get_top_level_shipped);
log::debug!("{id} shipped {inherited_flag:?}");
inherited_flag
}