1#[cfg(feature = "proptest1")]
9pub mod proptest;
10
11use clap::{ArgEnum, Parser};
12use color_eyre::eyre::Result;
13use guppy::{
14 graph::{
15 cargo::{CargoResolverVersion, InitialsPlatform},
16 feature::{named_feature_filter, FeatureSet, StandardFeatures},
17 PackageGraph,
18 },
19 platform::{Platform, PlatformSpec, TargetFeatures},
20 MetadataCommand,
21};
22use std::{env, path::PathBuf};
23
24#[derive(Debug, Parser)]
28pub struct PackagesAndFeatures {
29 #[clap(long = "package", short = 'p')]
30 pub packages: Vec<String>,
32
33 #[clap(long = "features-only")]
34 pub features_only: Vec<String>,
36
37 #[clap(long = "features", use_value_delimiter = true)]
40 pub features: Vec<String>,
41
42 #[clap(long = "all-features")]
44 pub all_features: bool,
45
46 #[clap(long = "no-default-features")]
48 pub no_default_features: bool,
49}
50
51impl PackagesAndFeatures {
52 pub fn make_feature_sets<'g>(
55 &self,
56 graph: &'g PackageGraph,
57 ) -> Result<(FeatureSet<'g>, FeatureSet<'g>)> {
58 let package_set = if self.packages.is_empty() {
59 graph.resolve_workspace()
60 } else {
61 graph.resolve_workspace_names(self.packages.iter())?
62 };
63 let features_only_set = if self.features_only.is_empty() {
64 graph.resolve_none()
65 } else {
66 graph.resolve_workspace_names(self.features_only.iter())?
67 };
68
69 let base_filter = match (self.all_features, self.no_default_features) {
70 (true, _) => StandardFeatures::All,
71 (false, false) => StandardFeatures::Default,
72 (false, true) => StandardFeatures::None,
73 };
74 let mut feature_filter =
77 named_feature_filter(base_filter, self.features.iter().map(|s| s.as_str()));
78
79 Ok((
80 package_set.to_feature_set(&mut feature_filter),
81 features_only_set.to_feature_set(&mut feature_filter),
82 ))
83 }
84}
85
86#[derive(ArgEnum, Clone, Copy, Debug)]
89pub enum CargoResolverVersionCmd {
90 V1,
91 V1Install,
92 V2,
93 V3,
94}
95
96#[derive(ArgEnum, Clone, Copy, Debug)]
97pub enum InitialsPlatformCmd {
98 Host,
99 Standard,
100 ProcMacrosOnTarget,
101}
102
103#[derive(Clone, Debug, Parser)]
105pub struct CargoResolverOpts {
106 #[clap(long = "include-dev")]
107 pub include_dev: bool,
109
110 #[clap(long = "initials-platform")]
111 #[clap(arg_enum, default_value_t = InitialsPlatformCmd::Standard)]
112 pub initials_platform: InitialsPlatformCmd,
114
115 #[clap(long = "resolver-version")]
116 #[clap(arg_enum, default_value_t = CargoResolverVersionCmd::V1)]
117 pub resolver_version: CargoResolverVersionCmd,
119}
120
121impl CargoResolverVersionCmd {
122 pub fn to_guppy(self) -> CargoResolverVersion {
124 match self {
125 CargoResolverVersionCmd::V1 => CargoResolverVersion::V1,
126 CargoResolverVersionCmd::V1Install => CargoResolverVersion::V1Install,
127 CargoResolverVersionCmd::V2 => CargoResolverVersion::V2,
128 CargoResolverVersionCmd::V3 => CargoResolverVersion::V3,
129 }
130 }
131}
132
133impl InitialsPlatformCmd {
134 pub fn to_guppy(self) -> InitialsPlatform {
136 match self {
137 InitialsPlatformCmd::Host => InitialsPlatform::Host,
138 InitialsPlatformCmd::Standard => InitialsPlatform::Standard,
139 InitialsPlatformCmd::ProcMacrosOnTarget => InitialsPlatform::ProcMacrosOnTarget,
140 }
141 }
142}
143
144#[derive(Clone, Debug, Parser)]
148pub struct CargoMetadataOptions {
149 #[clap(long)]
151 pub manifest_path: Option<PathBuf>,
152}
153
154impl CargoMetadataOptions {
155 pub fn current_dir(&self) -> Result<PathBuf> {
157 Ok(env::current_dir()?)
158 }
159
160 pub fn abs_manifest_path(&self) -> Result<PathBuf> {
162 let cwd = self.current_dir()?;
163 let path = match &self.manifest_path {
164 Some(path) => cwd.join(path),
165 None => cwd.join("Cargo.toml"),
166 };
167 Ok(path.canonicalize()?)
168 }
169
170 pub fn make_command(&self) -> MetadataCommand {
172 let mut command = MetadataCommand::new();
173 if let Some(manifest_path) = &self.manifest_path {
174 command.manifest_path(manifest_path);
175 }
176 command
177 }
178}
179
180pub fn string_to_platform_spec(s: Option<&str>) -> Result<PlatformSpec> {
184 match s {
185 Some("current") => Ok(PlatformSpec::build_target()?),
186 Some("always") => Ok(PlatformSpec::Always),
187 Some("any") => Ok(PlatformSpec::Any),
188 Some(triple) => Ok(Platform::new(triple.to_owned(), TargetFeatures::Unknown)?.into()),
189 None => Ok(PlatformSpec::Any),
190 }
191}