cargo_options/
metadata.rs

1use std::path::PathBuf;
2use std::process::Command;
3
4use clap::{ArgAction, Parser};
5
6#[cfg(feature = "serde")]
7use serde::{Deserialize, Serialize};
8
9use crate::heading;
10use crate::CommonOptions;
11
12/// Output the resolved dependencies of a package,
13/// the concrete used versions including overrides,
14/// in machine-readable format
15#[derive(Clone, Debug, Default, Parser)]
16#[command(
17    display_order = 1,
18    after_help = "Run `cargo help metadata` for more detailed information."
19)]
20#[group(skip)]
21#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
22pub struct Metadata {
23    /// Do not print cargo log messages
24    #[arg(short = 'q', long)]
25    #[cfg_attr(feature = "serde", serde(default))]
26    pub quiet: bool,
27
28    /// Space or comma separated list of features to activate
29    #[arg(
30        short = 'F',
31        long,
32        action = ArgAction::Append,
33        help_heading = heading::FEATURE_SELECTION,
34        )]
35    #[cfg_attr(feature = "serde", serde(default))]
36    pub features: Vec<String>,
37
38    /// Activate all available features
39    #[arg(long, help_heading = heading::FEATURE_SELECTION)]
40    #[cfg_attr(feature = "serde", serde(default))]
41    pub all_features: bool,
42
43    /// Do not activate the `default` feature
44    #[arg(long, help_heading = heading::FEATURE_SELECTION)]
45    #[cfg_attr(feature = "serde", serde(default))]
46    pub no_default_features: bool,
47
48    /// Use verbose output (-vv very verbose/build.rs output)
49    #[arg(short = 'v', long, action = ArgAction::Count)]
50    #[cfg_attr(feature = "serde", serde(default))]
51    pub verbose: u8,
52
53    /// Only include resolve dependencies matching the given target-triple
54    #[arg(long, value_name = "TRIPLE", action = ArgAction::Append)]
55    #[cfg_attr(feature = "serde", serde(default))]
56    pub filter_platform: Vec<String>,
57
58    /// Output information only about the workspace members
59    /// and don't fetch dependencies
60    #[arg(long)]
61    #[cfg_attr(feature = "serde", serde(default))]
62    pub no_deps: bool,
63
64    /// Path to Cargo.toml
65    #[arg(long, value_name = "PATH")]
66    #[cfg_attr(feature = "serde", serde(default))]
67    pub manifest_path: Option<PathBuf>,
68
69    /// Format version
70    #[arg(long, value_name = "VERSION", value_parser = ["1"])]
71    #[cfg_attr(feature = "serde", serde(default))]
72    pub format_version: Option<String>,
73
74    /// Coloring: auto, always, never
75    #[arg(long, value_name = "WHEN")]
76    #[cfg_attr(feature = "serde", serde(default))]
77    pub color: Option<String>,
78
79    /// Require Cargo.lock and cache are up to date
80    #[arg(long, help_heading = heading::MANIFEST_OPTIONS)]
81    #[cfg_attr(feature = "serde", serde(default))]
82    pub frozen: bool,
83
84    /// Require Cargo.lock is up to date
85    #[arg(long, help_heading = heading::MANIFEST_OPTIONS)]
86    #[cfg_attr(feature = "serde", serde(default))]
87    pub locked: bool,
88
89    /// Run without accessing the network
90    #[arg(long, help_heading = heading::MANIFEST_OPTIONS)]
91    #[cfg_attr(feature = "serde", serde(default))]
92    pub offline: bool,
93
94    /// Override a configuration value (unstable)
95    #[arg(long, value_name = "KEY=VALUE", action = ArgAction::Append)]
96    #[cfg_attr(feature = "serde", serde(default))]
97    pub config: Vec<String>,
98
99    /// Unstable (nightly-only) flags to Cargo, see 'cargo -Z help' for details
100    #[arg(short = 'Z', value_name = "FLAG", action = ArgAction::Append)]
101    #[cfg_attr(feature = "serde", serde(default))]
102    pub unstable_flags: Vec<String>,
103}
104
105impl Metadata {
106    /// Build a `cargo metadata` command
107    pub fn command(&self) -> Command {
108        let mut cmd = CommonOptions::cargo_command();
109        cmd.arg("metadata");
110        if self.quiet {
111            cmd.arg("--quiet");
112        }
113        if self.verbose > 0 {
114            cmd.arg(format!("-{}", "v".repeat(self.verbose.into())));
115        }
116        for feature in &self.features {
117            cmd.arg("--features").arg(feature);
118        }
119        if self.all_features {
120            cmd.arg("--all-features");
121        }
122        if self.no_default_features {
123            cmd.arg("--no-default-features");
124        }
125        for platform in &self.filter_platform {
126            cmd.arg("--filter-platform").arg(platform);
127        }
128        if self.no_deps {
129            cmd.arg("--no-deps");
130        }
131        if let Some(path) = self.manifest_path.as_ref() {
132            cmd.arg("--manifest-path").arg(path);
133        }
134        if let Some(format_version) = self.format_version.as_ref() {
135            cmd.arg("--format-version").arg(format_version);
136        }
137        if let Some(color) = self.color.as_ref() {
138            cmd.arg("--color").arg(color);
139        }
140        if self.frozen {
141            cmd.arg("--frozen");
142        }
143        if self.locked {
144            cmd.arg("--locked");
145        }
146        if self.offline {
147            cmd.arg("--offline");
148        }
149        for config in &self.config {
150            cmd.arg("--config").arg(config);
151        }
152        for flag in &self.unstable_flags {
153            cmd.arg("-Z").arg(flag);
154        }
155        cmd
156    }
157}
158
159#[cfg(test)]
160mod test {
161    use super::Metadata;
162    use clap::CommandFactory;
163
164    #[test]
165    fn verify_cli() {
166        <Metadata as CommandFactory>::command().debug_assert()
167    }
168}