use log::debug;
use crate::tree_traversal::{PackageAndDeps, PackageAndDepsNodes, TomlParser};
#[derive(Debug)]
pub struct VersionUpdate<'a> {
pub package_name: Option<&'a str>,
pub current_version: &'a str,
pub new_version: &'a str,
}
impl<'a> VersionUpdate<'a> {
pub fn update_all_pkg_and_deps(&self, source: &str) -> String {
debug!(
"Starting version update from '{}' to '{}'",
self.current_version, self.new_version
);
let mut updated_source = source.to_owned();
let mut iteration = 1;
loop {
debug!("\n--- Iteration {} ---", iteration);
iteration += 1;
match self.update_pass(&updated_source) {
Some(new_source) => updated_source = new_source,
None => {
debug!("No more versions to update in this iteration");
break;
}
}
}
debug!("\nVersion update completed");
updated_source
}
}
impl<'a> VersionUpdate<'a> {
pub fn update_pass(&self, source: &str) -> Option<String> {
let mut updated_source = source.to_owned();
let version_finder = match TomlParser::new(&updated_source) {
Ok(vf) => {
debug!("Successfully initialized TomlParser");
vf
}
Err(e) => {
debug!("Error initializing TomlParser: {:?}", e);
return None;
}
};
let new_version_quoted = format!("\"{}\"", self.new_version);
if let Some(pkg_and_deps) = version_finder.find_package_and_deps() {
let filtered = self.filter_package_and_deps(pkg_and_deps);
if let Some((pkg_node, pkg_info)) = filtered.package {
debug!(
"Updating package {} from version {} to {}",
pkg_info.name, pkg_info.version, new_version_quoted
);
updated_source = version_finder.edit_node(pkg_node, &new_version_quoted);
return Some(updated_source);
}
debug!("Checking {} dependencies...", filtered.dependencies.len());
if let Some((dep_node, dep_info)) = filtered.dependencies.iter().next() {
debug!(
"Updating dependency '{}' from version '{}' to '{}'",
dep_info.name, dep_info.version, new_version_quoted
);
updated_source = version_finder.edit_node(*dep_node, &new_version_quoted);
return Some(updated_source);
}
} else {
debug!("No package/dependency information found");
}
None
}
}
impl<'a> VersionUpdate<'a> {
pub fn filtered_pkg_and_deps(&self, source: &str) -> Option<PackageAndDeps> {
debug!("Starting filtered_pkg_and_deps update: {:?}", self);
let version_finder = match TomlParser::new(source) {
Ok(vf) => {
debug!("Successfully initialized TomlParser");
vf
}
Err(e) => {
debug!("Error initializing TomlParser: {:?}", e);
return None;
}
};
debug!("Looking for package and dependency information...");
if let Some(pkg_and_deps) = version_finder.find_package_and_deps() {
debug!("Filtering package and dependencies for display");
let filtered = self.filter_package_and_deps(pkg_and_deps);
debug!("Filtered result: {:?}", filtered);
return Some(filtered.into());
} else {
debug!("No package/dependency information found");
}
debug!("Returning None - no valid package/dependency information found");
None
}
}
impl<'a> VersionUpdate<'a> {
pub fn filter_package_and_deps(
&self,
pkg_and_deps: PackageAndDepsNodes<'a>,
) -> PackageAndDepsNodes<'a> {
let filtered_package = match (pkg_and_deps.package, self.package_name) {
(Some((pkg_node, pkg_info)), Some(pkg_name))
if pkg_info.name == pkg_name && pkg_info.version == self.current_version =>
{
Some((pkg_node, pkg_info))
}
(Some((pkg_node, pkg_info)), None) if pkg_info.version == self.current_version => {
Some((pkg_node, pkg_info))
}
_ => None,
};
let filtered_dependencies = pkg_and_deps
.dependencies
.into_iter()
.filter(|(_, dep_info)| match self.package_name {
Some(pkg_name) => {
dep_info.name == pkg_name && dep_info.version == self.current_version
}
None => dep_info.version == self.current_version,
})
.collect();
PackageAndDepsNodes {
package: filtered_package,
dependencies: filtered_dependencies,
}
}
}