hakari/cli_ops/
manage_deps.rsuse crate::{
cli_ops::{WorkspaceOp, WorkspaceOps},
hakari::DepFormatVersion,
HakariBuilder, WorkspaceHackLineStyle,
};
use guppy::{
graph::{DependencyDirection, PackageLink, PackageMetadata, PackageSet},
VersionReq,
};
impl<'g> HakariBuilder<'g> {
pub fn manage_dep_ops(&self, workspace_set: &PackageSet<'g>) -> Option<WorkspaceOps<'g, '_>> {
let graph = self.graph();
let hakari_package = self.hakari_package()?;
let (add_to, remove_from) =
workspace_set.filter_partition(DependencyDirection::Reverse, |package| {
let link_opt = package
.link_to(hakari_package.id())
.expect("valid package ID");
let should_be_included = !self.is_excluded(package.id()).expect("valid package ID");
match (link_opt, should_be_included) {
(None, true) => Some(true),
(Some(_), false) => Some(false),
(Some(link), true) => match self.dep_format_version {
DepFormatVersion::V1 => None,
DepFormatVersion::V2 | DepFormatVersion::V3 | DepFormatVersion::V4 => {
needs_update_v2(hakari_package, link, self.workspace_hack_line_style)
.then_some(true)
}
},
(None, false) => None,
}
});
let mut ops = Vec::with_capacity(2);
if !add_to.is_empty() {
ops.push(WorkspaceOp::AddDependency {
name: hakari_package.name(),
crate_path: hakari_package
.source()
.workspace_path()
.expect("hakari package is in workspace"),
version: hakari_package.version(),
dep_format: self.dep_format_version,
line_style: self.workspace_hack_line_style,
add_to,
});
}
if !remove_from.is_empty() {
ops.push(WorkspaceOp::RemoveDependency {
name: hakari_package.name(),
remove_from,
});
}
Some(WorkspaceOps::new(graph, ops))
}
pub fn add_dep_ops(
&self,
workspace_set: &PackageSet<'g>,
force: bool,
) -> Option<WorkspaceOps<'g, '_>> {
let graph = self.graph();
let hakari_package = self.hakari_package()?;
let add_to = if force {
workspace_set.clone()
} else {
workspace_set.filter(DependencyDirection::Reverse, |package| {
let link_opt = package
.link_to(hakari_package.id())
.expect("valid package ID");
match link_opt {
Some(link) => {
needs_update_v2(hakari_package, link, self.workspace_hack_line_style)
}
None => true,
}
})
};
let op = if !add_to.is_empty() {
Some(WorkspaceOp::AddDependency {
name: hakari_package.name(),
version: hakari_package.version(),
crate_path: hakari_package
.source()
.workspace_path()
.expect("hakari package is in workspace"),
dep_format: self.dep_format_version,
line_style: self.workspace_hack_line_style,
add_to,
})
} else {
None
};
Some(WorkspaceOps::new(graph, op))
}
pub fn remove_dep_ops(
&self,
workspace_set: &PackageSet<'g>,
force: bool,
) -> Option<WorkspaceOps<'g, '_>> {
let graph = self.graph();
let hakari_package = self.hakari_package()?;
let remove_from = if force {
workspace_set.clone()
} else {
workspace_set.filter(DependencyDirection::Reverse, |package| {
graph
.directly_depends_on(package.id(), hakari_package.id())
.expect("valid package ID")
})
};
let op = if !remove_from.is_empty() {
Some(WorkspaceOp::RemoveDependency {
name: hakari_package.name(),
remove_from,
})
} else {
None
};
Some(WorkspaceOps::new(graph, op))
}
}
#[allow(clippy::if_same_then_else, clippy::needless_bool)]
fn needs_update_v2(
hakari_package: &PackageMetadata<'_>,
link: PackageLink<'_>,
line_style: WorkspaceHackLineStyle,
) -> bool {
if !link.version_req().matches(hakari_package.version()) {
true
} else if link.version_req() == &VersionReq::STAR {
match line_style {
WorkspaceHackLineStyle::Full | WorkspaceHackLineStyle::VersionOnly => true,
WorkspaceHackLineStyle::WorkspaceDotted => false,
}
} else {
false
}
}