diff --git a/cargo-geiger/src/args.rs b/cargo-geiger/src/args.rs index b36752d0..2803ebce 100644 --- a/cargo-geiger/src/args.rs +++ b/cargo-geiger/src/args.rs @@ -1,6 +1,8 @@ use crate::format::print_config::OutputFormat; use crate::format::Charset; +use cargo::core::shell::ColorChoice; +use cargo::{CliResult, Config}; use pico_args::Arguments; use std::path::PathBuf; @@ -144,6 +146,29 @@ impl Args { }; Ok(args) } + + pub fn update_config(&self, config: &mut Config) -> CliResult { + let target_dir = None; // Doesn't add any value for cargo-geiger. + config.configure( + self.verbose, + self.quiet, + self.color.as_deref(), + self.frozen, + self.locked, + self.offline, + &target_dir, + &self.unstable_flags, + &[], // Some cargo API change, TODO: Look closer at this later. + )?; + + match config.shell().color_choice() { + ColorChoice::Always => colored::control::set_override(true), + ColorChoice::Never => colored::control::set_override(false), + ColorChoice::CargoAuto => {} + } + + Ok(()) + } } #[derive(Default)] @@ -181,6 +206,8 @@ fn parse_features(raw_features: Option) -> Vec { pub mod args_tests { use super::*; + use cargo::core::shell::ColorChoice; + use cargo::core::Verbosity; use rstest::*; use std::ffi::OsString; @@ -268,4 +295,97 @@ pub mod args_tests { ) { assert_eq!(parse_features(input_raw_features), expected_features); } + + #[rstest( + input_quiet, + input_verbose, + expected_extra_verbose, + expected_shell_verbosity, + case(true, 0, false, Verbosity::Quiet), + case(false, 0, false, Verbosity::Normal), + case(false, 1, false, Verbosity::Verbose), + case(false, 2, true, Verbosity::Verbose) + )] + fn update_config_test_verbosity( + input_quiet: bool, + input_verbose: u32, + expected_extra_verbose: bool, + expected_shell_verbosity: Verbosity, + ) { + let offline = rand::random(); + let args = Args { + offline, + quiet: input_quiet, + verbose: input_verbose, + ..Default::default() + }; + let mut config = Config::default().unwrap(); + let update_config_result = args.update_config(&mut config); + + assert!(update_config_result.is_ok()); + assert_eq!(config.extra_verbose(), expected_extra_verbose); + assert_eq!(config.shell().verbosity(), expected_shell_verbosity); + assert_eq!(config.offline(), offline); + assert!(config.target_dir().unwrap().is_none()); + } + + #[rstest( + input_color, + expected_shell_color_choice, + case(Some(String::from("always")), ColorChoice::Always), + case(Some(String::from("auto")), ColorChoice::CargoAuto), + case(Some(String::from("never")), ColorChoice::Never), + case(None, ColorChoice::CargoAuto) + )] + fn update_config_test_color_choice( + input_color: Option, + expected_shell_color_choice: ColorChoice, + ) { + let offline = rand::random(); + let args = Args { + color: input_color, + offline, + ..Default::default() + }; + let mut config = Config::default().unwrap(); + let update_config_result = args.update_config(&mut config); + + assert!(update_config_result.is_ok()); + assert_eq!(config.shell().color_choice(), expected_shell_color_choice); + assert_eq!(config.offline(), offline); + assert!(config.target_dir().unwrap().is_none()); + } + + #[rstest( + input_frozen, + input_locked, + expected_frozen, + expected_lock_update_allowed, + case(true, true, true, false), + case(true, false, true, false), + case(false, true, false, false), + case(false, false, false, true) + )] + fn update_config_test_frozen_locked( + input_frozen: bool, + input_locked: bool, + expected_frozen: bool, + expected_lock_update_allowed: bool, + ) { + let offline = rand::random(); + let args = Args { + frozen: input_frozen, + locked: input_locked, + offline, + ..Default::default() + }; + let mut config = Config::default().unwrap(); + let update_config_result = args.update_config(&mut config); + + assert!(update_config_result.is_ok()); + assert_eq!(config.frozen(), expected_frozen); + assert_eq!(config.lock_update_allowed(), expected_lock_update_allowed); + assert_eq!(config.offline(), offline); + assert!(config.target_dir().unwrap().is_none()); + } } diff --git a/cargo-geiger/src/main.rs b/cargo-geiger/src/main.rs index 22e7ea0b..8ef19d9f 100644 --- a/cargo-geiger/src/main.rs +++ b/cargo-geiger/src/main.rs @@ -23,12 +23,10 @@ use crate::cli::{ get_cargo_metadata, get_krates, get_registry, get_workspace, resolve, }; use crate::graph::build_graph; +use crate::mapping::{CargoMetadataParameters, QueryResolve}; use crate::scan::scan; -use crate::mapping::{ - CargoMetadataParameters, ToCargoMetadataPackage, ToCargoMetadataPackageId, -}; -use cargo::core::shell::{ColorChoice, Shell}; +use cargo::core::shell::Shell; use cargo::{CliResult, Config}; const VERSION: Option<&'static str> = option_env!("CARGO_PKG_VERSION"); @@ -43,24 +41,7 @@ fn real_main(args: &Args, config: &mut Config) -> CliResult { return Ok(()); } - let target_dir = None; // Doesn't add any value for cargo-geiger. - config.configure( - args.verbose, - args.quiet, - args.color.as_deref(), - args.frozen, - args.locked, - args.offline, - &target_dir, - &args.unstable_flags, - &[], // Some cargo API change, TODO: Look closer at this later. - )?; - - match config.shell().color_choice() { - ColorChoice::Always => colored::control::set_override(true), - ColorChoice::Never => colored::control::set_override(false), - ColorChoice::CargoAuto => {} - } + args.update_config(config)?; let cargo_metadata = get_cargo_metadata(&args, config)?; let krates = get_krates(&cargo_metadata)?; @@ -74,11 +55,8 @@ fn real_main(args: &Args, config: &mut Config) -> CliResult { let root_package = workspace.current()?; let mut registry = get_registry(config, &root_package)?; - // `cargo_metadata.root_package()` will return `None` when called on a virtual - // manifest - let cargo_metadata_root_package_id = root_package - .to_cargo_metadata_package(cargo_metadata_parameters.metadata) - .id; + let cargo_metadata_root_package_id = + cargo_metadata.root_package().unwrap().id.clone(); let (package_set, resolve) = resolve( &args.features_args, @@ -90,29 +68,28 @@ fn real_main(args: &Args, config: &mut Config) -> CliResult { let package_ids = package_set.package_ids().collect::>(); let package_set = registry.get(&package_ids)?; - let root_package_id = match args.package { - Some(ref pkg) => resolve.query(pkg)?, - None => root_package.package_id(), - }; - let graph = build_graph( args, &cargo_metadata_parameters, config, &resolve, &package_set, - cargo_metadata_root_package_id, + cargo_metadata_root_package_id.clone(), &workspace, )?; + let cargo_metadata_root_package_id = match args.package { + Some(ref package_query) => krates.query_resolve(package_query), + None => cargo_metadata_root_package_id, + }; + scan( args, &cargo_metadata_parameters, config, &graph, &package_set, - root_package_id - .to_cargo_metadata_package_id(cargo_metadata_parameters.metadata), + cargo_metadata_root_package_id, &workspace, ) } diff --git a/cargo-geiger/src/mapping.rs b/cargo-geiger/src/mapping.rs index 3c3507ca..4bca4eed 100644 --- a/cargo-geiger/src/mapping.rs +++ b/cargo-geiger/src/mapping.rs @@ -67,6 +67,10 @@ pub trait MatchesIgnoringSource { ) -> bool; } +pub trait QueryResolve { + fn query_resolve(&self, query: &str) -> cargo_metadata::PackageId; +} + pub trait Replacement { fn replace( &self, diff --git a/cargo-geiger/src/mapping/core.rs b/cargo-geiger/src/mapping/core.rs index 62710c8f..4ee98c81 100644 --- a/cargo-geiger/src/mapping/core.rs +++ b/cargo-geiger/src/mapping/core.rs @@ -62,8 +62,10 @@ impl ToCargoMetadataPackageId for PackageId { mod core_tests { use super::*; - use crate::cli::get_workspace; + use crate::cli::{get_registry, get_workspace}; + use cargo::core::registry::PackageRegistry; + use cargo::core::Workspace; use cargo::Config; use cargo_metadata::{CargoOpt, Metadata, MetadataCommand}; use krates::Builder as KratesBuilder; @@ -91,9 +93,8 @@ mod core_tests { #[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 (package, _, _) = + construct_package_registry_workspace_tuple(&config); let (_, metadata) = construct_krates_and_metadata(); @@ -113,9 +114,8 @@ mod core_tests { #[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 (package, _, _) = + construct_package_registry_workspace_tuple(&config); let (_, metadata) = construct_krates_and_metadata(); let cargo_metadata_package_id = @@ -137,4 +137,15 @@ mod core_tests { (krates, metadata) } + + fn construct_package_registry_workspace_tuple( + config: &Config, + ) -> (Package, PackageRegistry, Workspace) { + let manifest_path: Option = None; + let workspace = get_workspace(config, manifest_path).unwrap(); + let package = workspace.current().unwrap().clone(); + let registry = get_registry(&config, &package).unwrap(); + + (package, registry, workspace) + } } diff --git a/cargo-geiger/src/mapping/krates.rs b/cargo-geiger/src/mapping/krates.rs index 623019da..500b2647 100644 --- a/cargo-geiger/src/mapping/krates.rs +++ b/cargo-geiger/src/mapping/krates.rs @@ -2,10 +2,11 @@ use crate::mapping::{ GetLicenceFromCargoMetadataPackageId, GetPackageNameFromCargoMetadataPackageId, GetPackageVersionFromCargoMetadataPackageId, - GetRepositoryFromCargoMetadataPackageId, + GetRepositoryFromCargoMetadataPackageId, QueryResolve, }; -use krates::Krates; +use krates::{Krates, PkgSpec}; +use std::str::FromStr; impl GetLicenceFromCargoMetadataPackageId for Krates { fn get_licence_from_cargo_metadata_package_id( @@ -47,11 +48,24 @@ impl GetRepositoryFromCargoMetadataPackageId for Krates { } } +impl QueryResolve for Krates { + fn query_resolve(&self, query: &str) -> cargo_metadata::PackageId { + let package_spec = PkgSpec::from_str(query).unwrap(); + self.krates_by_name(package_spec.name.as_str()) + .filter(|(_, node)| package_spec.matches(&node.krate)) + .map(|(_, node)| node.krate.clone()) + .collect::>() + .pop() + .unwrap() + .id + } +} + #[cfg(test)] mod krates_tests { use super::*; - use cargo_metadata::{CargoOpt, Metadata, MetadataCommand}; + use cargo_metadata::{CargoOpt, Metadata, MetadataCommand, Version}; use krates::Builder as KratesBuilder; use rstest::*; @@ -98,6 +112,54 @@ mod krates_tests { ); } + #[rstest( + input_query_string, + expected_package_name, + expected_package_version, + case( + "cargo_metadata:0.12.0", + "cargo_metadata", + Version { + major: 0, + minor: 12, + patch: 0, + pre: vec![], + build: vec![] + } + ), + case( + "cargo_metadata:0.12.0", + "cargo_metadata", + Version { + major: 0, + minor: 12, + patch: 0, + pre: vec![], + build: vec![] + } + ) + )] + fn query_resolve_test( + input_query_string: &str, + expected_package_name: &str, + expected_package_version: Version, + ) { + let (krates, _) = construct_krates_and_metadata(); + let package_id = krates.query_resolve(input_query_string); + + assert_eq!( + krates.get_package_name_from_cargo_metadata_package_id(&package_id), + expected_package_name + ); + + assert_eq!( + krates.get_package_version_from_cargo_metadata_package_id( + &package_id + ), + expected_package_version + ); + } + fn construct_krates_and_metadata() -> (Krates, Metadata) { let metadata = MetadataCommand::new() .manifest_path("./Cargo.toml") diff --git a/cargo-geiger/src/mapping/metadata.rs b/cargo-geiger/src/mapping/metadata.rs index 5e611118..eea550ea 100644 --- a/cargo-geiger/src/mapping/metadata.rs +++ b/cargo-geiger/src/mapping/metadata.rs @@ -188,6 +188,8 @@ mod metadata_tests { use crate::args::FeaturesArgs; use crate::cli::{get_registry, get_workspace, resolve}; + use cargo::core::registry::PackageRegistry; + use cargo::core::Workspace; use cargo::Config; use cargo_metadata::{CargoOpt, Metadata, MetadataCommand}; use krates::Builder as KratesBuilder; @@ -198,10 +200,8 @@ mod metadata_tests { fn deps_not_replaced_test() { let args = FeaturesArgs::default(); let config = Config::default().unwrap(); - let manifest_path: Option = None; - let workspace = get_workspace(&config, manifest_path).unwrap(); - let package = workspace.current().unwrap(); - let mut registry = get_registry(&config, &package).unwrap(); + let (package, mut registry, workspace) = + construct_package_registry_workspace_tuple(&config); let (package_set, resolve) = resolve(&args, package.package_id(), &mut registry, &workspace) @@ -280,10 +280,8 @@ mod metadata_tests { fn replace_test() { let args = FeaturesArgs::default(); let config = Config::default().unwrap(); - let manifest_path: Option = None; - let workspace = get_workspace(&config, manifest_path).unwrap(); - let package = workspace.current().unwrap(); - let mut registry = get_registry(&config, &package).unwrap(); + let (package, mut registry, workspace) = + construct_package_registry_workspace_tuple(&config); let (package_set, resolve) = resolve(&args, package.package_id(), &mut registry, &workspace) @@ -328,10 +326,8 @@ mod metadata_tests { fn to_cargo_geiger_package_id_test() { let args = FeaturesArgs::default(); let config = Config::default().unwrap(); - let manifest_path: Option = None; - let workspace = get_workspace(&config, manifest_path).unwrap(); - let package = workspace.current().unwrap(); - let mut registry = get_registry(&config, &package).unwrap(); + let (package, mut registry, workspace) = + construct_package_registry_workspace_tuple(&config); let (package_set, _) = resolve(&args, package.package_id(), &mut registry, &workspace) @@ -365,10 +361,8 @@ mod metadata_tests { fn to_package_id_test() { let args = FeaturesArgs::default(); let config = Config::default().unwrap(); - let manifest_path: Option = None; - let workspace = get_workspace(&config, manifest_path).unwrap(); - let package = workspace.current().unwrap(); - let mut registry = get_registry(&config, &package).unwrap(); + let (package, mut registry, workspace) = + construct_package_registry_workspace_tuple(&config); let (package_set, _) = resolve(&args, package.package_id(), &mut registry, &workspace) @@ -398,4 +392,15 @@ mod metadata_tests { (krates, metadata) } + + fn construct_package_registry_workspace_tuple( + config: &Config, + ) -> (Package, PackageRegistry, Workspace) { + let manifest_path: Option = None; + let workspace = get_workspace(config, manifest_path).unwrap(); + let package = workspace.current().unwrap().clone(); + let registry = get_registry(&config, &package).unwrap(); + + (package, registry, workspace) + } }