diff --git a/src/main.rs b/src/main.rs index ff412ca..01c1da2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,6 +19,8 @@ mod parsing; mod project; mod util; +mod save; + #[derive(Parser)] #[command(name = "cargo")] #[command(bin_name = "cargo")] diff --git a/src/parsing/dependency.rs b/src/parsing/dependency.rs index 5614095..244d9e7 100644 --- a/src/parsing/dependency.rs +++ b/src/parsing/dependency.rs @@ -24,7 +24,7 @@ pub fn parse_dependency( let deps = get_item_from_doc(&get_path(&kind, &dependency.target), document)?; let deps = deps.as_table().context(format!( - "could not parse dependency as a table - {}", + "could not parse dependencies as a table - {}", package.name ))?; diff --git a/src/parsing/workspace.rs b/src/parsing/workspace.rs index 9e8e159..cff1d5c 100644 --- a/src/parsing/workspace.rs +++ b/src/parsing/workspace.rs @@ -19,12 +19,12 @@ pub fn parse_workspace( return Ok(None); }; - let Some(dependencies) = workspace.get("dependency") else { + let Some(dependencies) = workspace.get("dependencies") else { return Ok(None); }; let dependencies_table = dependencies.as_table_like().ok_or(eyre!( - "failed to parse workspace.dependency - not a table" + "failed to parse workspace.dependencies - not a table" ))?; let dependencies: Result> = dependencies_table diff --git a/src/project/dependency/util.rs b/src/project/dependency/util.rs index 8d9e597..652d4ea 100644 --- a/src/project/dependency/util.rs +++ b/src/project/dependency/util.rs @@ -5,11 +5,11 @@ use std::str::FromStr; pub fn get_path(kind: &DependencyType, target: &Option) -> String { let path = match kind { - DependencyType::Normal => "dependency", - DependencyType::Development => "dev-dependency", - DependencyType::Build => "build-dependency", - DependencyType::Workspace => "workspace.dependency", - DependencyType::Unknown => "dependency", + DependencyType::Normal => "dependencies", + DependencyType::Development => "dev-dependencies", + DependencyType::Build => "build-dependencies", + DependencyType::Workspace => "workspace.dependencies", + DependencyType::Unknown => "dependencies", }; if let Some(target) = target { @@ -71,6 +71,9 @@ pub fn get_item_from_doc<'a>( ) -> color_eyre::Result<&'a toml_edit::Item> { let mut item = document.as_item(); + println!("{}", item); + println!("{}", document); + let mut is_target = false; 'outer: for key in path.split('.') { diff --git a/src/project/document.rs b/src/project/document.rs index 55133e5..f6b8e7e 100644 --- a/src/project/document.rs +++ b/src/project/document.rs @@ -1,19 +1,12 @@ -use color_eyre::eyre::{bail, eyre, ContextCompat, Error}; -use std::cmp::PartialEq; -use std::fs; +use color_eyre::eyre::{bail, eyre, ContextCompat}; use color_eyre::Result; use itertools::Itertools; -use toml_edit::{Array, Formatted, InlineTable, Item, Value}; - use crate::parsing::package::get_packages; use crate::project::dependency::feature::EnabledState; -use crate::project::dependency::util::{get_mut_item_from_doc, get_path}; use crate::project::package::Package; -use crate::util::toml_document_from_path; - pub struct Document { packages: Vec, workspace_index: Option, @@ -30,7 +23,7 @@ impl Document { .dependencies .is_empty() { - bail!("no dependency were found") + bail!("no dependencies were found") } let mut workspace_index = None; @@ -51,7 +44,7 @@ impl Document { Ok(document) } - fn update_workspace_deps(&mut self) -> Result<()> { + pub fn update_workspace_deps(&mut self) -> Result<()> { let Some(workspace_index) = self.workspace_index else { return Ok(()); }; @@ -136,126 +129,8 @@ impl Document { .context(format!("no package with name {} found", package)) } - //todo extract writing - pub fn write_dep(&mut self, package: &str, name: &str) -> Result<()> { - let (index, _) = self - .get_package(package)? - .get_deps() - .iter() - .enumerate() - .find(|(_index, dep)| dep.get_name().eq(name)) - .ok_or(eyre!("could not find dependency with name {}", name))?; - - self.write_dep_raw(package, index) - } - - fn write_dep_raw(&mut self, package_name: &str, dep_index: usize) -> Result<()> { - let package = self - .packages - .iter_mut() - .find(|pkg| pkg.name == package_name) - .context("package not found")?; - - let dependency = package - .dependencies - .get(dep_index) - .context("dependency not found")?; - - let features_to_enable = dependency.get_features_to_enable(); - - let mut doc = toml_document_from_path(&package.manifest_path)?; - let deps = - get_mut_item_from_doc(&get_path(&dependency.kind, &dependency.target), &mut doc)?; - - let deps = deps.as_table_mut().context(format!( - "could not parse dependency as a table - {}", - package.name - ))?; - - let table = match deps - .get_mut(dependency.rename.as_ref().unwrap_or(&dependency.name)) - .context("dependency not found")? - .as_table_like_mut() - { - None => { - deps.insert( - &dependency.name, - Item::Value(Value::InlineTable(InlineTable::new())), - ); - - deps.get_mut(&dependency.name) - .context(format!( - "could not find {} in dependency", - dependency.get_name() - ))? - .as_table_like_mut() - .context(format!( - "could not parse {} as a table", - dependency.get_name() - ))? - } - Some(table) => table, - }; - - let has_custom_attributes = table - .get_values() - .iter() - .map(|(name, _)| name.first().map(|key| key.to_string()).unwrap_or_default()) - .any(|name| !["features", "default-features", "version"].contains(&&*name)); - - //check if entry has to be table or can just be string with version - if dependency.can_use_default() && features_to_enable.is_empty() && !has_custom_attributes { - deps.insert( - &dependency.name, - Item::Value(Value::String(Formatted::new(dependency.get_version()))), - ); - } else { - //version - if !dependency.version.is_empty() && !table.contains_key("git") && !dependency.workspace - { - table.insert( - "version", - Item::Value(Value::String(Formatted::new(dependency.get_version()))), - ); - } - - //features - let mut features = Array::new(); - - for name in features_to_enable { - features.push(Value::String(Formatted::new(name))); - } - - if features.is_empty() { - table.remove("features"); - } else { - table.insert("features", Item::Value(Value::Array(features))); - } - - //default-feature - if dependency.can_use_default() || dependency.workspace { - table.remove("default-features"); - } else { - table.insert( - "default-features", - Item::Value(Value::Boolean(Formatted::new(false))), - ); - } - } - - // update workspace deps - if let Some(workspace_index) = self.workspace_index { - let workspace = self.get_package_by_id(workspace_index)?; - - if workspace.name == package_name { - self.update_workspace_deps()?; - } - } - - //write updates - let package = self.get_package(package_name)?; - - fs::write(&package.manifest_path, doc.to_string()).map_err(Error::from) + pub fn workspace_index(&self) -> Option { + self.workspace_index } pub fn is_workspace(&self) -> bool { self.packages.len() > 1 diff --git a/src/prune.rs b/src/prune.rs index 20ea514..639c071 100644 --- a/src/prune.rs +++ b/src/prune.rs @@ -8,6 +8,7 @@ use std::ops::Not; use std::path::Path; use crate::project::document::Document; +use crate::save::save_dependency; use color_eyre::eyre::eyre; use std::process::{Command, Stdio}; use toml::Table; @@ -105,7 +106,8 @@ fn prune_package( .get_package_mut(package_name)? .get_dep_mut(name)? .disable_feature(feature)?; - document.write_dep(package_name, name)?; + + save_dependency(document, package_name, name)?; if check()? { to_be_disabled.push(feature.to_string()); @@ -118,7 +120,8 @@ fn prune_package( .get_dep_mut(name)? .enable_feature(feature)?; } - document.write_dep(package_name, name)?; + + save_dependency(document, package_name, name)?; term.move_cursor_up(2)?; term.clear_line()?; @@ -161,7 +164,7 @@ fn prune_package( .disable_feature(&feature)?; } - document.write_dep(package_name, name)?; + save_dependency(document, package_name, name)?; } } Ok(()) diff --git a/src/rendering/display.rs b/src/rendering/display.rs index 524397d..8009249 100644 --- a/src/rendering/display.rs +++ b/src/rendering/display.rs @@ -1,6 +1,7 @@ use crate::project::dependency::feature::EnabledState; use crate::project::document::Document; use crate::rendering::filter_view::FilterView; +use crate::save::save_dependency; use color_eyre::eyre::{Context, ContextCompat}; use color_eyre::Result; use console::{style, Emoji, Key, Term}; @@ -357,8 +358,11 @@ impl Display { dep.toggle_feature(self.feature_selector.get_selected()?.name())?; - self.document - .write_dep(self.package_selector.get_selected()?.name(), dep_name)?; + save_dependency( + &mut self.document, + self.package_selector.get_selected()?.name(), + dep_name, + )?; } } diff --git a/src/save.rs b/src/save.rs new file mode 100644 index 0000000..43fccff --- /dev/null +++ b/src/save.rs @@ -0,0 +1,109 @@ +use crate::project::dependency::util::{get_mut_item_from_doc, get_path}; +use crate::project::document::Document; +use crate::util::toml_document_from_path; +use color_eyre::eyre::{ContextCompat, Error}; +use std::fs; +use toml_edit::{Array, Formatted, InlineTable, Item, Value}; + +pub fn save_dependency( + document: &mut Document, + package_name: &str, + dep_name: &str, +) -> color_eyre::Result<()> { + let package = document.get_package_mut(package_name)?; + let dependency = package.get_dep(dep_name)?; + + let features_to_enable = dependency.get_features_to_enable(); + + let mut doc = toml_document_from_path(&package.manifest_path)?; + let deps = get_mut_item_from_doc(&get_path(&dependency.kind, &dependency.target), &mut doc)?; + + let deps = deps.as_table_mut().context(format!( + "could not parse dependencies as a table - {}", + package.name + ))?; + + let table = match deps + .get_mut(dependency.rename.as_ref().unwrap_or(&dependency.name)) + .context("dependency not found")? + .as_table_like_mut() + { + None => { + deps.insert( + &dependency.name, + Item::Value(Value::InlineTable(InlineTable::new())), + ); + + deps.get_mut(&dependency.name) + .context(format!( + "could not find {} in dependency", + dependency.get_name() + ))? + .as_table_like_mut() + .context(format!( + "could not parse {} as a table", + dependency.get_name() + ))? + } + Some(table) => table, + }; + + let has_custom_attributes = table + .get_values() + .iter() + .map(|(name, _)| name.first().map(|key| key.to_string()).unwrap_or_default()) + .any(|name| !["features", "default-features", "version"].contains(&&*name)); + + //check if entry has to be table or can just be string with version + if dependency.can_use_default() && features_to_enable.is_empty() && !has_custom_attributes { + deps.insert( + &dependency.name, + Item::Value(Value::String(Formatted::new(dependency.get_version()))), + ); + } else { + //version + if !dependency.version.is_empty() && !table.contains_key("git") && !dependency.workspace { + table.insert( + "version", + Item::Value(Value::String(Formatted::new(dependency.get_version()))), + ); + } + + //features + let mut features = Array::new(); + + for name in features_to_enable { + features.push(Value::String(Formatted::new(name))); + } + + if features.is_empty() { + table.remove("features"); + } else { + table.insert("features", Item::Value(Value::Array(features))); + } + + //default-feature + if dependency.can_use_default() || dependency.workspace { + table.remove("default-features"); + } else { + table.insert( + "default-features", + Item::Value(Value::Boolean(Formatted::new(false))), + ); + } + } + + // update workspace deps + if let Some(workspace_index) = document.workspace_index() { + let workspace = document.get_package_by_id(workspace_index)?; + + if workspace.name == package_name { + document.update_workspace_deps()?; + } + } + + //write updates + let package = document.get_package(package_name)?; + + fs::write(&package.manifest_path, doc.to_string()).map_err(Error::from) +}