diff --git a/cargo-geiger/src/format/display.rs b/cargo-geiger/src/format/display.rs index b2461937..83e8ae00 100644 --- a/cargo-geiger/src/format/display.rs +++ b/cargo-geiger/src/format/display.rs @@ -1,13 +1,17 @@ use crate::format::pattern::Pattern; use crate::format::Chunk; +use crate::utils::{ + CargoMetadataParameters, GetPackageNameFromCargoMetadataPackageId, + GetPackageVersionFromCargoMetadataPackageId, +}; use cargo::core::manifest::ManifestMetadata; -use cargo::core::PackageId; use std::fmt; pub struct Display<'a> { + pub cargo_metadata_parameters: &'a CargoMetadataParameters<'a>, pub pattern: &'a Pattern, - pub package: &'a PackageId, + pub package: &'a cargo_metadata::PackageId, pub metadata: &'a ManifestMetadata, } @@ -24,8 +28,16 @@ impl<'a> fmt::Display for Display<'a> { (write!( fmt, "{} {}", - self.package.name(), - self.package.version() + self.cargo_metadata_parameters + .krates + .get_package_name_from_cargo_metadata_package_id( + self.package + ), + self.cargo_metadata_parameters + .krates + .get_package_version_from_cargo_metadata_package_id( + self.package + ) ))? } Chunk::Raw(ref s) => (fmt.write_str(s))?, @@ -48,8 +60,8 @@ pub mod display_tests { use crate::format::Chunk; use cargo::core::manifest::ManifestMetadata; - use cargo::core::{PackageId, SourceId}; - use cargo::util::ToSemver; + use cargo_metadata::{CargoOpt, MetadataCommand}; + use krates::Builder; use rstest::*; #[rstest( @@ -61,7 +73,7 @@ pub mod display_tests { ), case( Pattern(vec![Chunk::Package]), - "package_name 1.2.3" + "cargo-geiger 0.10.2" ), case( Pattern(vec![Chunk::Raw(String::from("chunk_value"))]), @@ -76,15 +88,17 @@ pub mod display_tests { input_pattern: Pattern, expected_formatted_string: &str, ) { - let package_id = PackageId::new( - "package_name", - "1.2.3".to_semver().unwrap(), - SourceId::from_url( - "git+https://github.com/rust-secure-code/cargo-geiger", - ) - .unwrap(), - ) - .unwrap(); + let metadata = MetadataCommand::new() + .manifest_path("./Cargo.toml") + .features(CargoOpt::AllFeatures) + .exec() + .unwrap(); + + let krates = Builder::new() + .build_with_metadata(metadata.clone(), |_| ()) + .unwrap(); + + let package_id = metadata.root_package().unwrap().id.clone(); let manifest_metadata = ManifestMetadata { authors: vec![], @@ -102,6 +116,10 @@ pub mod display_tests { }; let display = Display { + cargo_metadata_parameters: &CargoMetadataParameters { + krates: &krates, + metadata: &metadata, + }, pattern: &input_pattern, package: &package_id, metadata: &manifest_metadata, diff --git a/cargo-geiger/src/format/pattern.rs b/cargo-geiger/src/format/pattern.rs index 98380130..104aa286 100644 --- a/cargo-geiger/src/format/pattern.rs +++ b/cargo-geiger/src/format/pattern.rs @@ -3,8 +3,8 @@ use crate::format::{Chunk, RawChunk}; use super::display::Display; +use crate::utils::CargoMetadataParameters; use cargo::core::manifest::ManifestMetadata; -use cargo::core::PackageId; use std::error::Error; #[derive(Debug, PartialEq)] @@ -13,10 +13,12 @@ pub struct Pattern(pub Vec); impl Pattern { pub fn display<'a>( &'a self, - package: &'a PackageId, + cargo_metadata_parameters: &'a CargoMetadataParameters, metadata: &'a ManifestMetadata, + package: &'a cargo_metadata::PackageId, ) -> Display<'a> { Display { + cargo_metadata_parameters, pattern: self, package, metadata, diff --git a/cargo-geiger/src/format/table.rs b/cargo-geiger/src/format/table.rs index 9e62cc31..caf2cbcf 100644 --- a/cargo-geiger/src/format/table.rs +++ b/cargo-geiger/src/format/table.rs @@ -13,6 +13,7 @@ use handle_text_tree_line::{ }; use total_package_counts::TotalPackageCounts; +use crate::utils::CargoMetadataParameters; use cargo::core::package::PackageSet; use cargo_geiger_serde::{Count, CounterBlock}; use std::collections::HashSet; @@ -31,6 +32,7 @@ pub const UNSAFE_COUNTERS_HEADER: [&str; 6] = [ ]; pub fn create_table_from_text_tree_lines( + cargo_metadata_parameters: &CargoMetadataParameters, package_set: &PackageSet, table_parameters: &TableParameters, text_tree_lines: Vec, @@ -61,6 +63,7 @@ pub fn create_table_from_text_tree_lines( id: package_id, tree_vines, } => handle_text_tree_line_package( + cargo_metadata_parameters, &emoji_symbols, &mut handle_package_parameters, package_id, diff --git a/cargo-geiger/src/format/table/handle_text_tree_line.rs b/cargo-geiger/src/format/table/handle_text_tree_line.rs index c94a7b26..91e958df 100644 --- a/cargo-geiger/src/format/table/handle_text_tree_line.rs +++ b/cargo-geiger/src/format/table/handle_text_tree_line.rs @@ -1,20 +1,20 @@ +use crate::format::emoji_symbols::EmojiSymbols; use crate::format::print_config::colorize; use crate::format::{get_kind_group_name, CrateDetectionStatus, SymbolKind}; use crate::scan::unsafe_stats; +use crate::utils::{CargoMetadataParameters, ToPackage}; use super::total_package_counts::TotalPackageCounts; use super::TableParameters; use super::{table_row, table_row_empty}; -use crate::format::emoji_symbols::EmojiSymbols; use cargo::core::dependency::DepKind; use cargo::core::package::PackageSet; -use cargo::core::PackageId; use std::collections::HashSet; pub struct HandlePackageParameters<'a> { pub total_package_counts: &'a mut TotalPackageCounts, - pub visited_package_ids: &'a mut HashSet, + pub visited_package_ids: &'a mut HashSet, pub warning_count: &'a mut u64, } @@ -33,10 +33,12 @@ pub fn handle_text_tree_line_extra_deps_group( table_lines.push(format!("{}{}{}", table_row_empty(), tree_vines, name)); } +#[allow(clippy::too_many_arguments)] pub fn handle_text_tree_line_package( + cargo_metadata_parameters: &CargoMetadataParameters, emoji_symbols: &EmojiSymbols, handle_package_parameters: &mut HandlePackageParameters, - package_id: PackageId, + package_id: cargo_metadata::PackageId, package_set: &PackageSet, table_lines: &mut Vec, table_parameters: &TableParameters, @@ -44,11 +46,11 @@ pub fn handle_text_tree_line_package( ) { let package_is_new = handle_package_parameters .visited_package_ids - .insert(package_id); - let package = package_set.get_one(package_id).unwrap_or_else(|_| { - // TODO: Avoid panic, return Result. - panic!("Expected to find package by id: {}", package_id); - }); + .insert(package_id.clone()); + + let package = + package_id.to_package(cargo_metadata_parameters.krates, package_set); + let package_metrics = match table_parameters .geiger_context .package_id_to_metrics @@ -97,10 +99,11 @@ pub fn handle_text_tree_line_package( let package_name = colorize( format!( "{}", - table_parameters - .print_config - .format - .display(&package_id, package.manifest().metadata()) + table_parameters.print_config.format.display( + cargo_metadata_parameters, + package.manifest().metadata(), + &package_id + ) ), &crate_detection_status, ); diff --git a/cargo-geiger/src/graph.rs b/cargo-geiger/src/graph.rs index d2a1b21a..95cf3076 100644 --- a/cargo-geiger/src/graph.rs +++ b/cargo-geiger/src/graph.rs @@ -1,6 +1,6 @@ use crate::args::{Args, DepsArgs, TargetArgs}; use crate::cli::get_cfgs; -use crate::krates_utils::{ +use crate::utils::{ CargoMetadataParameters, DepsNotReplaced, MatchesIgnoringSource, Replacement, }; diff --git a/cargo-geiger/src/main.rs b/cargo-geiger/src/main.rs index 275e77f0..02060f88 100644 --- a/cargo-geiger/src/main.rs +++ b/cargo-geiger/src/main.rs @@ -14,9 +14,9 @@ mod args; mod cli; mod format; mod graph; -mod krates_utils; mod scan; mod tree; +mod utils; use crate::args::{Args, HELP}; use crate::cli::{ @@ -25,7 +25,9 @@ use crate::cli::{ use crate::graph::build_graph; use crate::scan::scan; -use crate::krates_utils::{CargoMetadataParameters, ToCargoMetadataPackage}; +use crate::utils::{ + CargoMetadataParameters, ToCargoMetadataPackage, ToCargoMetadataPackageId, +}; use cargo::core::shell::{ColorChoice, Shell}; use cargo::{CliResult, Config}; @@ -109,7 +111,8 @@ fn real_main(args: &Args, config: &mut Config) -> CliResult { config, &graph, &package_set, - root_package_id, + root_package_id + .to_cargo_metadata_package_id(cargo_metadata_parameters.metadata), &workspace, ) } diff --git a/cargo-geiger/src/scan.rs b/cargo-geiger/src/scan.rs index 05e4723e..c24162fd 100644 --- a/cargo-geiger/src/scan.rs +++ b/cargo-geiger/src/scan.rs @@ -6,18 +6,15 @@ mod rs_file; use crate::args::Args; use crate::format::print_config::PrintConfig; use crate::graph::Graph; +use crate::utils::{CargoMetadataParameters, ToCargoCoreDepKind, ToPackageId}; pub use rs_file::RsFileMetricsWrapper; use default::scan_unsafe; use forbid::scan_forbid_unsafe; -use crate::krates_utils::{ - CargoMetadataParameters, ToCargoCoreDepKind, ToCargoMetadataPackageId, - ToPackageId, -}; use cargo::core::dependency::DepKind; -use cargo::core::{PackageId, PackageSet, Workspace}; +use cargo::core::{PackageSet, Workspace}; use cargo::{CliResult, Config}; use cargo_geiger_serde::{ CounterBlock, DependencyKind, PackageInfo, UnsafeInfo, @@ -30,7 +27,8 @@ use url::Url; /// Provides a more terse and searchable name for the wrapped generic /// collection. pub struct GeigerContext { - pub package_id_to_metrics: HashMap, + pub package_id_to_metrics: + HashMap, } #[derive(Clone, Debug, Default)] @@ -61,7 +59,7 @@ pub fn scan( config: &Config, graph: &Graph, package_set: &PackageSet, - root_package_id: PackageId, + root_package_id: cargo_metadata::PackageId, workspace: &Workspace, ) -> CliResult { let print_config = PrintConfig::new(args)?; @@ -170,30 +168,32 @@ fn package_metrics( geiger_context: &GeigerContext, graph: &Graph, package_set: &PackageSet, - root_package_id: PackageId, + root_package_id: cargo_metadata::PackageId, ) -> Vec<(PackageInfo, Option)> { let mut package_metrics = Vec::<(PackageInfo, Option)>::new(); - let root_index = graph.nodes[&root_package_id - .to_cargo_metadata_package_id(cargo_metadata_parameters.metadata)]; + let root_index = graph.nodes[&root_package_id]; let mut indices = vec![root_index]; let mut visited = HashSet::new(); while !indices.is_empty() { let i = indices.pop().unwrap(); - let package_id = graph.graph[i] - .to_package_id(cargo_metadata_parameters.krates, package_set); - let mut package = PackageInfo::new(from_cargo_package_id(package_id)); + let package_id = graph.graph[i].clone(); + let mut package = PackageInfo::new(from_cargo_package_id( + cargo_metadata_parameters, + package_id.clone(), + package_set, + )); for edge in graph.graph.edges(i) { let dep_index = edge.target(); if visited.insert(dep_index) { indices.push(dep_index); } - let dep = - from_cargo_package_id(graph.graph[dep_index].to_package_id( - cargo_metadata_parameters.krates, - package_set, - )); + let dep = from_cargo_package_id( + cargo_metadata_parameters, + graph.graph[dep_index].clone(), + package_set, + ); package.add_dependency( dep, from_cargo_dependency_kind( @@ -216,8 +216,14 @@ fn package_metrics( package_metrics } -fn from_cargo_package_id(id: PackageId) -> cargo_geiger_serde::PackageId { - let source = id.source_id(); +fn from_cargo_package_id( + cargo_metadata_parameters: &CargoMetadataParameters, + cargo_metadata_package_id: cargo_metadata::PackageId, + package_set: &PackageSet, +) -> cargo_geiger_serde::PackageId { + let package_id = cargo_metadata_package_id + .to_package_id(cargo_metadata_parameters.krates, package_set); + let source = package_id.source_id(); let source_url = source.url(); // Canonicalize paths as cargo does not seem to do so on all platforms. let source_url = if source_url.scheme() == "file" { @@ -253,8 +259,8 @@ fn from_cargo_package_id(id: PackageId) -> cargo_geiger_serde::PackageId { panic!("Unsupported source type: {:?}", source) }; cargo_geiger_serde::PackageId { - name: id.name().to_string(), - version: id.version().clone(), + name: package_id.name().to_string(), + version: package_id.version().clone(), source, } } diff --git a/cargo-geiger/src/scan/default.rs b/cargo-geiger/src/scan/default.rs index ea6d7085..94a13154 100644 --- a/cargo-geiger/src/scan/default.rs +++ b/cargo-geiger/src/scan/default.rs @@ -3,8 +3,8 @@ mod table; use crate::args::FeaturesArgs; use crate::format::print_config::OutputFormat; use crate::graph::Graph; -use crate::krates_utils::CargoMetadataParameters; use crate::scan::rs_file::resolve_rs_file_deps; +use crate::utils::CargoMetadataParameters; use super::find::find_unsafe; use super::{ @@ -15,7 +15,7 @@ use super::{ use table::scan_to_table; use cargo::core::compiler::CompileMode; -use cargo::core::{PackageId, PackageSet, Workspace}; +use cargo::core::{PackageSet, Workspace}; use cargo::ops::CompileOptions; use cargo::{CliError, CliResult, Config}; use cargo_geiger_serde::{ReportEntry, SafetyReport}; @@ -24,7 +24,7 @@ pub fn scan_unsafe( cargo_metadata_parameters: &CargoMetadataParameters, graph: &Graph, package_set: &PackageSet, - root_package_id: PackageId, + root_package_id: cargo_metadata::PackageId, scan_parameters: &ScanParameters, workspace: &Workspace, ) -> CliResult { @@ -117,7 +117,7 @@ fn scan_to_report( graph: &Graph, output_format: OutputFormat, package_set: &PackageSet, - root_package_id: PackageId, + root_package_id: cargo_metadata::PackageId, scan_parameters: &ScanParameters, workspace: &Workspace, ) -> CliResult { diff --git a/cargo-geiger/src/scan/default/table.rs b/cargo-geiger/src/scan/default/table.rs index fc2c0061..59804f19 100644 --- a/cargo-geiger/src/scan/default/table.rs +++ b/cargo-geiger/src/scan/default/table.rs @@ -12,9 +12,9 @@ use super::super::{ }; use super::scan; -use crate::krates_utils::{CargoMetadataParameters, ToCargoMetadataPackageId}; +use crate::utils::CargoMetadataParameters; use cargo::core::shell::Verbosity; -use cargo::core::{PackageId, PackageSet, Workspace}; +use cargo::core::{PackageSet, Workspace}; use cargo::{CliError, CliResult}; use colored::Colorize; use std::error::Error; @@ -24,7 +24,7 @@ pub fn scan_to_table( cargo_metadata_parameters: &CargoMetadataParameters, graph: &Graph, package_set: &PackageSet, - root_package_id: PackageId, + root_package_id: cargo_metadata::PackageId, scan_parameters: &ScanParameters, workspace: &Workspace, ) -> CliResult { @@ -55,8 +55,7 @@ pub fn scan_to_table( &graph, package_set, &scan_parameters.print_config, - root_package_id - .to_cargo_metadata_package_id(cargo_metadata_parameters.metadata), + root_package_id, ); let table_parameters = TableParameters { geiger_context: &geiger_context, @@ -66,6 +65,7 @@ pub fn scan_to_table( let (mut table_lines, mut warning_count) = create_table_from_text_tree_lines( + cargo_metadata_parameters, package_set, &table_parameters, text_tree_lines, diff --git a/cargo-geiger/src/scan/find.rs b/cargo-geiger/src/scan/find.rs index 199efe76..a3faa35a 100644 --- a/cargo-geiger/src/scan/find.rs +++ b/cargo-geiger/src/scan/find.rs @@ -1,17 +1,14 @@ use crate::format::print_config::PrintConfig; -use crate::krates_utils::{ - CargoMetadataParameters, GetRoot, ToCargoMetadataPackage, ToPackageId, -}; use crate::scan::rs_file::{ into_is_entry_point_and_path_buf, into_rs_code_file, into_target_kind, is_file_with_ext, RsFile, RsFileMetricsWrapper, }; use crate::scan::PackageMetrics; +use crate::utils::{CargoMetadataParameters, GetRoot, ToCargoMetadataPackage}; use super::{GeigerContext, ScanMode}; use cargo::core::package::PackageSet; -use cargo::core::PackageId; use cargo::util::CargoResult; use cargo::{CliError, Config}; use geiger::{find_unsafe_in_file, IncludeTests, RsFileMetrics, ScanFileError}; @@ -96,15 +93,9 @@ where let cargo_core_package_metrics = package_id_to_metrics .iter() .map(|(cargo_metadata_package_id, package_metrics)| { - ( - cargo_metadata_package_id.clone().to_package_id( - cargo_metadata_parameters.krates, - package_set, - ), - package_metrics.clone(), - ) + (cargo_metadata_package_id.clone(), package_metrics.clone()) }) - .collect::>(); + .collect::>(); GeigerContext { package_id_to_metrics: cargo_core_package_metrics, diff --git a/cargo-geiger/src/scan/forbid.rs b/cargo-geiger/src/scan/forbid.rs index 961f22bf..240955c0 100644 --- a/cargo-geiger/src/scan/forbid.rs +++ b/cargo-geiger/src/scan/forbid.rs @@ -8,8 +8,8 @@ use super::{package_metrics, ScanMode, ScanParameters}; use table::scan_forbid_to_table; -use crate::krates_utils::CargoMetadataParameters; -use cargo::core::{PackageId, PackageSet}; +use crate::utils::CargoMetadataParameters; +use cargo::core::PackageSet; use cargo::{CliResult, Config}; use cargo_geiger_serde::{QuickReportEntry, QuickSafetyReport}; @@ -17,7 +17,7 @@ pub fn scan_forbid_unsafe( cargo_metadata_parameters: &CargoMetadataParameters, graph: &Graph, package_set: &PackageSet, - root_package_id: PackageId, + root_package_id: cargo_metadata::PackageId, scan_parameters: &ScanParameters, ) -> CliResult { match scan_parameters.args.output_format { @@ -48,7 +48,7 @@ fn scan_forbid_to_report( output_format: OutputFormat, package_set: &PackageSet, print_config: &PrintConfig, - root_package_id: PackageId, + root_package_id: cargo_metadata::PackageId, ) -> CliResult { let geiger_context = find_unsafe( cargo_metadata_parameters, diff --git a/cargo-geiger/src/scan/forbid/table.rs b/cargo-geiger/src/scan/forbid/table.rs index 1da19565..7780dc0a 100644 --- a/cargo-geiger/src/scan/forbid/table.rs +++ b/cargo-geiger/src/scan/forbid/table.rs @@ -3,15 +3,17 @@ use crate::format::pattern::Pattern; use crate::format::print_config::PrintConfig; use crate::format::{get_kind_group_name, SymbolKind}; use crate::graph::Graph; -use crate::krates_utils::{CargoMetadataParameters, ToCargoMetadataPackageId}; use crate::tree::traversal::walk_dependency_tree; use crate::tree::TextTreeLine; +use crate::utils::{ + CargoMetadataParameters, GetManifestMetadataFromCargoMetadataPackageId, +}; use super::super::find::find_unsafe; use super::super::ScanMode; use crate::scan::GeigerContext; -use cargo::core::{Package, PackageId, PackageSet}; +use cargo::core::PackageSet; use cargo::{CliResult, Config}; use colored::Colorize; @@ -21,7 +23,7 @@ pub fn scan_forbid_to_table( graph: &Graph, package_set: &PackageSet, print_config: &PrintConfig, - root_package_id: PackageId, + root_package_id: cargo_metadata::PackageId, ) -> CliResult { let mut scan_output_lines = Vec::::new(); let emoji_symbols = EmojiSymbols::new(print_config.charset); @@ -34,9 +36,9 @@ pub fn scan_forbid_to_table( &graph, package_set, &print_config, - root_package_id - .to_cargo_metadata_package_id(cargo_metadata_parameters.metadata), + root_package_id, ); + for tree_line in tree_lines { match tree_line { TextTreeLine::ExtraDepsGroup { kind, tree_vines } => { @@ -61,6 +63,7 @@ pub fn scan_forbid_to_table( )?; handle_package_text_tree_line( + cargo_metadata_parameters, &emoji_symbols, &geiger_ctx, package_id, @@ -106,17 +109,33 @@ fn construct_key_lines(emoji_symbols: &EmojiSymbols) -> Vec { output_key_lines } -fn format_package_name(package: &Package, pattern: &Pattern) -> String { +fn format_package_name( + cargo_metadata_parameters: &CargoMetadataParameters, + package_id: &cargo_metadata::PackageId, + package_set: &PackageSet, + pattern: &Pattern, +) -> String { format!( "{}", - pattern.display(&package.package_id(), package.manifest().metadata()) + pattern.display( + cargo_metadata_parameters, + &cargo_metadata_parameters + .krates + .get_manifest_metadata_from_cargo_metadata_package_id( + package_id, + package_set + ), + &package_id + ) ) } +#[allow(clippy::too_many_arguments)] fn handle_package_text_tree_line( + cargo_metadata_parameters: &CargoMetadataParameters, emoji_symbols: &EmojiSymbols, geiger_ctx: &GeigerContext, - package_id: PackageId, + package_id: cargo_metadata::PackageId, package_set: &PackageSet, print_config: &PrintConfig, scan_output_lines: &mut Vec, @@ -125,8 +144,18 @@ fn handle_package_text_tree_line( let sym_lock = emoji_symbols.emoji(SymbolKind::Lock); let sym_qmark = emoji_symbols.emoji(SymbolKind::QuestionMark); - let package = package_set.get_one(package_id).unwrap(); // FIXME - let name = format_package_name(package, &print_config.format); + /*let package = package_set + .get_one( + package_id + .to_package_id(cargo_metadata_parameters.krates, package_set), + ) + .unwrap(); // FIXME*/ + let name = format_package_name( + cargo_metadata_parameters, + &package_id, + package_set, + &print_config.format, + ); let package_metrics = geiger_ctx.package_id_to_metrics.get(&package_id); let package_forbids_unsafe = match package_metrics { None => false, // no metrics available, .rs parsing failed? @@ -149,11 +178,7 @@ fn handle_package_text_tree_line( #[cfg(test)] mod forbid_tests { use super::*; - use crate::format::Charset; - - use cargo::core::Workspace; - use cargo::util::important_paths; use rstest::*; #[rstest] @@ -163,22 +188,4 @@ mod forbid_tests { assert_eq!(output_key_lines.len(), 5); } - - #[rstest] - fn format_package_name_test() { - let pattern = Pattern::try_build("{p}").unwrap(); - - let config = Config::default().unwrap(); - let workspace = Workspace::new( - &important_paths::find_root_manifest_for_wd(config.cwd()).unwrap(), - &config, - ) - .unwrap(); - - let package = workspace.current().unwrap(); - - let formatted_package_name = format_package_name(&package, &pattern); - - assert_eq!(formatted_package_name, "cargo-geiger 0.10.2"); - } } diff --git a/cargo-geiger/src/tree.rs b/cargo-geiger/src/tree.rs index 908723d2..e5ddac36 100644 --- a/cargo-geiger/src/tree.rs +++ b/cargo-geiger/src/tree.rs @@ -4,14 +4,16 @@ use crate::format::print_config::{Prefix, PrintConfig}; use crate::format::Charset; use cargo::core::dependency::DepKind; -use cargo::core::PackageId; /// A step towards decoupling some parts of the table-tree printing from the /// dependency graph traversal. #[derive(Debug, PartialEq)] pub enum TextTreeLine { /// A text line for a package - Package { id: PackageId, tree_vines: String }, + Package { + id: cargo_metadata::PackageId, + tree_vines: String, + }, /// There are extra dependencies coming and we should print a group header, /// eg. "[build-dependencies]". ExtraDepsGroup { kind: DepKind, tree_vines: String }, diff --git a/cargo-geiger/src/tree/traversal.rs b/cargo-geiger/src/tree/traversal.rs index e0f2c623..d3fded15 100644 --- a/cargo-geiger/src/tree/traversal.rs +++ b/cargo-geiger/src/tree/traversal.rs @@ -3,21 +3,21 @@ mod dependency_node; use crate::format::print_config::PrintConfig; use crate::graph::Graph; -use crate::krates_utils::{CargoMetadataParameters, ToPackageId}; use crate::tree::TextTreeLine; +use crate::utils::CargoMetadataParameters; use super::construct_tree_vines_string; use dependency_kind::walk_dependency_kind; use dependency_node::walk_dependency_node; -use cargo::core::{PackageId, PackageSet}; +use cargo::core::PackageSet; use std::collections::HashSet; pub struct WalkDependencyParameters<'a> { pub graph: &'a Graph, pub levels_continue: &'a mut Vec, pub print_config: &'a PrintConfig, - pub visited_deps: &'a mut HashSet, + pub visited_deps: &'a mut HashSet, } /// Printing the returned TextTreeLines in order is expected to produce a nice @@ -46,7 +46,7 @@ pub fn walk_dependency_tree( let node = &graph.graph[graph.nodes[&root_package_id]]; walk_dependency_node( cargo_metadata_parameters, - &node.to_package_id(cargo_metadata_parameters.krates, package_set), + &node, package_set, &mut walk_dependency_paramters, ) diff --git a/cargo-geiger/src/tree/traversal/dependency_kind.rs b/cargo-geiger/src/tree/traversal/dependency_kind.rs index c4afa765..fa40191a 100644 --- a/cargo-geiger/src/tree/traversal/dependency_kind.rs +++ b/cargo-geiger/src/tree/traversal/dependency_kind.rs @@ -4,16 +4,16 @@ use crate::tree::{get_tree_symbols, TextTreeLine, TreeSymbols}; use super::dependency_node::walk_dependency_node; -use crate::krates_utils::CargoMetadataParameters; +use crate::utils::CargoMetadataParameters; use cargo::core::dependency::DepKind; -use cargo::core::{PackageId, PackageSet}; +use cargo::core::PackageSet; use std::iter::Peekable; use std::slice::Iter; pub fn walk_dependency_kind( cargo_metadata_parameters: &CargoMetadataParameters, dep_kind: DepKind, - deps: &mut Vec, + deps: &mut Vec, package_set: &PackageSet, walk_dependency_parameters: &mut WalkDependencyParameters, ) -> Vec { @@ -22,7 +22,7 @@ pub fn walk_dependency_kind( } // Resolve uses Hash data types internally but we want consistent output ordering - deps.sort_by_key(|n| *n); + deps.sort_by_key(|n| n.clone()); let tree_symbols = get_tree_symbols(walk_dependency_parameters.print_config.charset); @@ -52,8 +52,8 @@ pub fn walk_dependency_kind( fn handle_walk_dependency_node( cargo_metadata_parameters: &CargoMetadataParameters, - dependency: &PackageId, - node_iterator: &mut Peekable>, + dependency: &cargo_metadata::PackageId, + node_iterator: &mut Peekable>, package_set: &PackageSet, text_tree_lines: &mut Vec, walk_dependency_parameters: &mut WalkDependencyParameters, diff --git a/cargo-geiger/src/tree/traversal/dependency_node.rs b/cargo-geiger/src/tree/traversal/dependency_node.rs index 1e9e8481..4eb8c016 100644 --- a/cargo-geiger/src/tree/traversal/dependency_node.rs +++ b/cargo-geiger/src/tree/traversal/dependency_node.rs @@ -1,36 +1,35 @@ use crate::format::print_config::PrintConfig; use crate::graph::Graph; -use crate::krates_utils::{ - CargoMetadataParameters, ToCargoCoreDepKind, ToCargoMetadataPackageId, - ToPackageId, -}; use crate::tree::traversal::WalkDependencyParameters; use crate::tree::TextTreeLine; +use crate::utils::{CargoMetadataParameters, ToCargoCoreDepKind}; use super::construct_tree_vines_string; use super::walk_dependency_kind; use cargo::core::dependency::DepKind; -use cargo::core::{PackageId, PackageSet}; +use cargo::core::PackageSet; use petgraph::visit::EdgeRef; use petgraph::EdgeDirection; use std::collections::HashMap; pub fn walk_dependency_node( cargo_metadata_parameters: &CargoMetadataParameters, - package: &PackageId, + package: &cargo_metadata::PackageId, package_set: &PackageSet, walk_dependency_parameters: &mut WalkDependencyParameters, ) -> Vec { let new = walk_dependency_parameters.print_config.all - || walk_dependency_parameters.visited_deps.insert(*package); + || walk_dependency_parameters + .visited_deps + .insert(package.clone()); let tree_vines = construct_tree_vines_string( walk_dependency_parameters.levels_continue, walk_dependency_parameters.print_config, ); let mut all_out_text_tree_lines = vec![TextTreeLine::Package { - id: *package, + id: package.clone(), tree_vines, }]; @@ -40,22 +39,15 @@ pub fn walk_dependency_node( let mut dependency_type_nodes = construct_dependency_type_nodes_hashmap( walk_dependency_parameters.graph, - &package - .to_cargo_metadata_package_id(cargo_metadata_parameters.metadata), + &package, walk_dependency_parameters.print_config, ); for (dep_kind, nodes) in dependency_type_nodes.iter_mut() { - let mut cargo_core_nodes = nodes - .iter() - .map(|n| { - n.to_package_id(cargo_metadata_parameters.krates, package_set) - }) - .collect::>(); let mut dep_kind_out = walk_dependency_kind( cargo_metadata_parameters, *dep_kind, - &mut cargo_core_nodes, + nodes, package_set, walk_dependency_parameters, ); diff --git a/cargo-geiger/src/utils.rs b/cargo-geiger/src/utils.rs new file mode 100644 index 00000000..59cbcfed --- /dev/null +++ b/cargo-geiger/src/utils.rs @@ -0,0 +1,106 @@ +mod core; +mod krates; +mod metadata; + +use ::krates::Krates; +use cargo::core::dependency::DepKind; +use cargo::core::manifest::ManifestMetadata; +use cargo::core::{Package, PackageId, PackageSet, Resolve}; +use cargo_metadata::{DependencyKind, Metadata}; +use std::collections::HashSet; +use std::path::PathBuf; + +pub struct CargoMetadataParameters<'a> { + pub krates: &'a Krates, + pub metadata: &'a Metadata, +} + +pub trait DepsNotReplaced { + fn deps_not_replaced( + &self, + krates: &Krates, + package_id: cargo_metadata::PackageId, + package_set: &PackageSet, + resolve: &Resolve, + ) -> Vec<( + cargo_metadata::PackageId, + HashSet, + )>; +} + +pub trait GetManifestMetadataFromCargoMetadataPackageId { + fn get_manifest_metadata_from_cargo_metadata_package_id( + &self, + package_id: &cargo_metadata::PackageId, + package_set: &PackageSet, + ) -> ManifestMetadata; +} + +pub trait GetPackageNameFromCargoMetadataPackageId { + fn get_package_name_from_cargo_metadata_package_id( + &self, + package_id: &cargo_metadata::PackageId, + ) -> String; +} + +pub trait GetPackageVersionFromCargoMetadataPackageId { + fn get_package_version_from_cargo_metadata_package_id( + &self, + package_id: &cargo_metadata::PackageId, + ) -> cargo_metadata::Version; +} + +pub trait GetRoot { + fn get_root(&self) -> PathBuf; +} + +pub trait MatchesIgnoringSource { + fn matches_ignoring_source( + &self, + krates: &Krates, + package_id: cargo_metadata::PackageId, + ) -> bool; +} + +pub trait Replacement { + fn replace( + &self, + cargo_metadata_parameters: &CargoMetadataParameters, + package_set: &PackageSet, + resolve: &Resolve, + ) -> cargo_metadata::PackageId; +} + +pub trait ToCargoCoreDepKind { + fn to_cargo_core_dep_kind(&self) -> DepKind; +} + +pub trait ToCargoMetadataDependencyKind { + fn to_cargo_metadata_dependency_kind(&self) -> DependencyKind; +} + +pub trait ToCargoMetadataPackage { + fn to_cargo_metadata_package( + &self, + metadata: &Metadata, + ) -> cargo_metadata::Package; +} + +pub trait ToCargoMetadataPackageId { + fn to_cargo_metadata_package_id( + &self, + metadata: &Metadata, + ) -> cargo_metadata::PackageId; +} + +pub trait ToPackage { + fn to_package(&self, krates: &Krates, package_set: &PackageSet) -> Package; +} + +pub trait ToPackageId { + fn to_package_id( + &self, + krates: &Krates, + package_set: &PackageSet, + ) -> PackageId; +} diff --git a/cargo-geiger/src/utils/core.rs b/cargo-geiger/src/utils/core.rs new file mode 100644 index 00000000..8c4139d5 --- /dev/null +++ b/cargo-geiger/src/utils/core.rs @@ -0,0 +1,139 @@ +use super::ToCargoMetadataDependencyKind; + +use crate::utils::{ToCargoMetadataPackage, ToCargoMetadataPackageId}; + +use cargo::core::dependency::DepKind; +use cargo::core::{Package, PackageId}; +use cargo_metadata::{DependencyKind, Metadata}; + +impl ToCargoMetadataDependencyKind for DepKind { + fn to_cargo_metadata_dependency_kind(&self) -> DependencyKind { + match self { + DepKind::Build => DependencyKind::Build, + DepKind::Development => DependencyKind::Development, + DepKind::Normal => DependencyKind::Normal, + } + } +} + +impl ToCargoMetadataPackage for Package { + fn to_cargo_metadata_package( + &self, + metadata: &Metadata, + ) -> cargo_metadata::Package { + metadata + .packages + .iter() + .filter(|p| { + p.name == self.name().to_string() + && p.version.major == self.version().major + && p.version.minor == self.version().minor + && p.version.patch == self.version().patch + }) + .cloned() + .collect::>() + .pop() + .unwrap() + } +} + +impl ToCargoMetadataPackageId for PackageId { + fn to_cargo_metadata_package_id( + &self, + metadata: &Metadata, + ) -> cargo_metadata::PackageId { + metadata + .packages + .iter() + .filter(|p| { + p.name == self.name().to_string() + && p.version.major == self.version().major + && p.version.minor == self.version().minor + && p.version.patch == self.version().patch + }) + .map(|p| p.id.clone()) + .collect::>() + .pop() + .unwrap() + } +} + +#[cfg(test)] +mod core_tests { + use super::*; + + use crate::cli::get_workspace; + + use cargo::Config; + use cargo_metadata::{CargoOpt, Metadata, MetadataCommand}; + use krates::{Builder, Krates}; + use rstest::*; + use std::path::PathBuf; + + #[rstest( + input_dep_kind, + expected_dependency_kind, + case(DepKind::Build, DependencyKind::Build), + case(DepKind::Development, DependencyKind::Development), + case(DepKind::Normal, DependencyKind::Normal) + )] + fn to_cargo_metadata_dependency_kind_test( + input_dep_kind: DepKind, + expected_dependency_kind: DependencyKind, + ) { + assert_eq!( + input_dep_kind.to_cargo_metadata_dependency_kind(), + expected_dependency_kind + ); + } + + #[rstest] + fn to_cargo_metadata_package_test() { + let config = Config::default().unwrap(); + let manifest_path: Option = None; + let workspace = get_workspace(&config, manifest_path).unwrap(); + let package = workspace.current().unwrap(); + + let (_, metadata) = construct_krates_and_metadata(); + + let cargo_metadata_package = + package.to_cargo_metadata_package(&metadata); + + assert_eq!(cargo_metadata_package.name, package.name().to_string()); + assert!( + cargo_metadata_package.version.major == package.version().major + && cargo_metadata_package.version.minor + == package.version().minor + && cargo_metadata_package.version.patch + == package.version().patch + ); + } + + #[rstest] + fn to_cargo_metadata_package_id_test() { + let config = Config::default().unwrap(); + let manifest_path: Option = None; + let workspace = get_workspace(&config, manifest_path).unwrap(); + let package = workspace.current().unwrap(); + + let (_, metadata) = construct_krates_and_metadata(); + let cargo_metadata_package_id = + package.package_id().to_cargo_metadata_package_id(&metadata); + + assert!(cargo_metadata_package_id.repr.contains("cargo-geiger")); + } + + fn construct_krates_and_metadata() -> (Krates, Metadata) { + let metadata = MetadataCommand::new() + .manifest_path("./Cargo.toml") + .features(CargoOpt::AllFeatures) + .exec() + .unwrap(); + + let krates = Builder::new() + .build_with_metadata(metadata.clone(), |_| ()) + .unwrap(); + + (krates, metadata) + } +} diff --git a/cargo-geiger/src/utils/krates.rs b/cargo-geiger/src/utils/krates.rs new file mode 100644 index 00000000..194d1784 --- /dev/null +++ b/cargo-geiger/src/utils/krates.rs @@ -0,0 +1,81 @@ +use crate::utils::{ + GetManifestMetadataFromCargoMetadataPackageId, + GetPackageNameFromCargoMetadataPackageId, + GetPackageVersionFromCargoMetadataPackageId, ToPackage, +}; + +use cargo::core::manifest::ManifestMetadata; +use cargo::core::PackageSet; +use krates::Krates; + +impl GetManifestMetadataFromCargoMetadataPackageId for Krates { + fn get_manifest_metadata_from_cargo_metadata_package_id( + &self, + package_id: &cargo_metadata::PackageId, + package_set: &PackageSet, + ) -> ManifestMetadata { + let package = package_id.to_package(self, package_set); + package.manifest().metadata().clone() + } +} + +impl GetPackageNameFromCargoMetadataPackageId for Krates { + fn get_package_name_from_cargo_metadata_package_id( + &self, + package_id: &cargo_metadata::PackageId, + ) -> String { + let package = self.node_for_kid(package_id); + package.unwrap().krate.clone().name + } +} + +impl GetPackageVersionFromCargoMetadataPackageId for Krates { + fn get_package_version_from_cargo_metadata_package_id( + &self, + package_id: &cargo_metadata::PackageId, + ) -> cargo_metadata::Version { + let package = self.node_for_kid(package_id); + package.unwrap().krate.clone().version + } +} + +#[cfg(test)] +mod krates_tests { + use super::*; + + use cargo_metadata::{CargoOpt, Metadata, MetadataCommand}; + use krates::Builder; + use rstest::*; + + #[rstest] + fn get_package_name_from_cargo_metadata_package_id_test() { + let (krates, metadata) = construct_krates_and_metadata(); + let package = metadata.root_package().unwrap(); + let package_name = + krates.get_package_name_from_cargo_metadata_package_id(&package.id); + assert_eq!(package_name, package.name); + } + + #[rstest] + fn get_package_version_from_cargo_metadata_package_id_test() { + let (krates, metadata) = construct_krates_and_metadata(); + let package = metadata.root_package().unwrap(); + let package_version = krates + .get_package_version_from_cargo_metadata_package_id(&package.id); + assert_eq!(package_version, package.version); + } + + fn construct_krates_and_metadata() -> (Krates, Metadata) { + let metadata = MetadataCommand::new() + .manifest_path("./Cargo.toml") + .features(CargoOpt::AllFeatures) + .exec() + .unwrap(); + + let krates = Builder::new() + .build_with_metadata(metadata.clone(), |_| ()) + .unwrap(); + + (krates, metadata) + } +} diff --git a/cargo-geiger/src/krates_utils.rs b/cargo-geiger/src/utils/metadata.rs similarity index 57% rename from cargo-geiger/src/krates_utils.rs rename to cargo-geiger/src/utils/metadata.rs index 0978c084..458b1c90 100644 --- a/cargo-geiger/src/krates_utils.rs +++ b/cargo-geiger/src/utils/metadata.rs @@ -1,15 +1,19 @@ +use super::{ + CargoMetadataParameters, DepsNotReplaced, + GetPackageNameFromCargoMetadataPackageId, + GetPackageVersionFromCargoMetadataPackageId, GetRoot, + MatchesIgnoringSource, Replacement, ToCargoCoreDepKind, + ToCargoMetadataPackageId, ToPackageId, +}; + +use crate::utils::ToPackage; use cargo::core::dependency::DepKind; use cargo::core::{Package, PackageId, PackageSet, Resolve}; -use cargo_metadata::{DependencyKind, Metadata}; +use cargo_metadata::DependencyKind; use krates::Krates; use std::collections::HashSet; use std::path::PathBuf; -pub struct CargoMetadataParameters<'a> { - pub krates: &'a Krates, - pub metadata: &'a Metadata, -} - impl DepsNotReplaced for cargo_metadata::Metadata { fn deps_not_replaced( &self, @@ -39,26 +43,6 @@ impl DepsNotReplaced for cargo_metadata::Metadata { } } -impl GetPackageNameFromCargoMetadataPackageId for Krates { - fn get_package_name_from_cargo_metadata_package_id( - &self, - package_id: &cargo_metadata::PackageId, - ) -> String { - let package = self.node_for_kid(package_id); - package.unwrap().krate.clone().name - } -} - -impl GetPackageVersionFromCargoMetadataPackageId for Krates { - fn get_package_version_from_cargo_metadata_package_id( - &self, - package_id: &cargo_metadata::PackageId, - ) -> cargo_metadata::Version { - let package = self.node_for_kid(package_id); - package.unwrap().krate.clone().version - } -} - impl GetRoot for cargo_metadata::Package { fn get_root(&self) -> PathBuf { self.manifest_path.parent().unwrap().to_path_buf() @@ -111,55 +95,16 @@ impl ToCargoCoreDepKind for DependencyKind { } } -impl ToCargoMetadataDependencyKind for DepKind { - fn to_cargo_metadata_dependency_kind(&self) -> DependencyKind { - match self { - DepKind::Build => DependencyKind::Build, - DepKind::Development => DependencyKind::Development, - DepKind::Normal => DependencyKind::Normal, - } - } -} - -impl ToCargoMetadataPackage for Package { - fn to_cargo_metadata_package( - &self, - metadata: &Metadata, - ) -> cargo_metadata::Package { - metadata - .packages - .iter() - .filter(|p| { - p.name == self.name().to_string() - && p.version.major == self.version().major - && p.version.minor == self.version().minor - && p.version.patch == self.version().patch - }) - .cloned() - .collect::>() - .pop() - .unwrap() - } -} - -impl ToCargoMetadataPackageId for PackageId { - fn to_cargo_metadata_package_id( - &self, - metadata: &Metadata, - ) -> cargo_metadata::PackageId { - metadata - .packages - .iter() - .filter(|p| { - p.name == self.name().to_string() - && p.version.major == self.version().major - && p.version.minor == self.version().minor - && p.version.patch == self.version().patch +impl ToPackage for cargo_metadata::PackageId { + fn to_package(&self, krates: &Krates, package_set: &PackageSet) -> Package { + let package_id = self.to_package_id(krates, package_set); + package_set + .get_one(package_id) + .unwrap_or_else(|_| { + // TODO: Avoid panic, return Result. + panic!("Expected to find package by id: {}", package_id); }) - .map(|p| p.id.clone()) - .collect::>() - .pop() - .unwrap() + .clone() } } @@ -184,88 +129,12 @@ impl ToPackageId for cargo_metadata::PackageId { } } -pub trait DepsNotReplaced { - fn deps_not_replaced( - &self, - krates: &Krates, - package_id: cargo_metadata::PackageId, - package_set: &PackageSet, - resolve: &Resolve, - ) -> Vec<( - cargo_metadata::PackageId, - HashSet, - )>; -} - -pub trait GetPackageNameFromCargoMetadataPackageId { - fn get_package_name_from_cargo_metadata_package_id( - &self, - package_id: &cargo_metadata::PackageId, - ) -> String; -} - -pub trait GetPackageVersionFromCargoMetadataPackageId { - fn get_package_version_from_cargo_metadata_package_id( - &self, - package_id: &cargo_metadata::PackageId, - ) -> cargo_metadata::Version; -} - -pub trait GetRoot { - fn get_root(&self) -> PathBuf; -} - -pub trait MatchesIgnoringSource { - fn matches_ignoring_source( - &self, - krates: &Krates, - package_id: cargo_metadata::PackageId, - ) -> bool; -} - -pub trait Replacement { - fn replace( - &self, - cargo_metadata_parameters: &CargoMetadataParameters, - package_set: &PackageSet, - resolve: &Resolve, - ) -> cargo_metadata::PackageId; -} - -pub trait ToCargoCoreDepKind { - fn to_cargo_core_dep_kind(&self) -> DepKind; -} - -pub trait ToCargoMetadataDependencyKind { - fn to_cargo_metadata_dependency_kind(&self) -> DependencyKind; -} - -pub trait ToCargoMetadataPackage { - fn to_cargo_metadata_package( - &self, - metadata: &Metadata, - ) -> cargo_metadata::Package; -} - -pub trait ToCargoMetadataPackageId { - fn to_cargo_metadata_package_id( - &self, - metadata: &Metadata, - ) -> cargo_metadata::PackageId; -} - -pub trait ToPackageId { - fn to_package_id( - &self, - krates: &Krates, - package_set: &PackageSet, - ) -> PackageId; -} - #[cfg(test)] -mod krates_utils_tests { +mod metadata_tests { use super::*; + use super::super::GetPackageNameFromCargoMetadataPackageId; + use crate::args::FeaturesArgs; use crate::cli::{get_registry, get_workspace, resolve}; @@ -317,24 +186,6 @@ mod krates_utils_tests { assert_eq!(cargo_core_package_names, cargo_metadata_package_names); } - #[rstest] - fn get_package_name_from_cargo_metadata_package_id_test() { - let (krates, metadata) = construct_krates_and_metadata(); - let package = metadata.root_package().unwrap(); - let package_name = - krates.get_package_name_from_cargo_metadata_package_id(&package.id); - assert_eq!(package_name, package.name); - } - - #[rstest] - fn get_package_version_from_cargo_metadata_package_id_test() { - let (krates, metadata) = construct_krates_and_metadata(); - let package = metadata.root_package().unwrap(); - let package_version = krates - .get_package_version_from_cargo_metadata_package_id(&package.id); - assert_eq!(package_version, package.version); - } - #[rstest] fn get_root_test() { let (_, metadata) = construct_krates_and_metadata(); @@ -423,59 +274,6 @@ mod krates_utils_tests { ) } - #[rstest( - input_dep_kind, - expected_dependency_kind, - case(DepKind::Build, DependencyKind::Build), - case(DepKind::Development, DependencyKind::Development), - case(DepKind::Normal, DependencyKind::Normal) - )] - fn to_cargo_metadata_dependency_kind_test( - input_dep_kind: DepKind, - expected_dependency_kind: DependencyKind, - ) { - assert_eq!( - input_dep_kind.to_cargo_metadata_dependency_kind(), - expected_dependency_kind - ); - } - - #[rstest] - fn to_cargo_metadata_package_test() { - let config = Config::default().unwrap(); - let manifest_path: Option = None; - let workspace = get_workspace(&config, manifest_path).unwrap(); - let package = workspace.current().unwrap(); - - let (_, metadata) = construct_krates_and_metadata(); - - let cargo_metadata_package = - package.to_cargo_metadata_package(&metadata); - - assert_eq!(cargo_metadata_package.name, package.name().to_string()); - assert!( - cargo_metadata_package.version.major == package.version().major - && cargo_metadata_package.version.minor - == package.version().minor - && cargo_metadata_package.version.patch - == package.version().patch - ); - } - - #[rstest] - fn to_cargo_metadata_package_id_test() { - let config = Config::default().unwrap(); - let manifest_path: Option = None; - let workspace = get_workspace(&config, manifest_path).unwrap(); - let package = workspace.current().unwrap(); - - let (_, metadata) = construct_krates_and_metadata(); - let cargo_metadata_package_id = - package.package_id().to_cargo_metadata_package_id(&metadata); - - assert!(cargo_metadata_package_id.repr.contains("cargo-geiger")); - } - #[rstest] fn to_package_id_test() { let args = FeaturesArgs::default();