~jplatte/cargo-depgraph

ref: a97143d0912da0e2beb39a44168233bf24e4b4fd cargo-depgraph/src/cli.rs -rw-r--r-- 6.8 KiB
a97143d0 — Jonas Platte Fix CLI help strings 2 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
use clap::{App, AppSettings, Arg, SubCommand};

pub struct Config {
    pub build_deps: bool,
    pub dev_deps: bool,
    pub target_deps: bool,
    pub dedup_transitive_deps: bool,
    pub exclude: Vec<String>,
    pub focus: Vec<String>,

    pub features: Vec<String>,
    pub all_features: bool,
    pub no_default_features: bool,
    pub filter_platform: Vec<String>,
    pub manifest_path: Option<String>,
    pub frozen: bool,
    pub locked: bool,
    pub offline: bool,
    pub unstable_flags: Vec<String>,
}

pub fn parse_options() -> Config {
    let matches = App::new("cargo-depgraph")
        .bin_name("cargo")
        .version(env!("CARGO_PKG_VERSION"))
        .subcommand(
            SubCommand::with_name("depgraph")
                .settings(&[AppSettings::DeriveDisplayOrder, AppSettings::UnifiedHelpMessage])
                .arg(Arg::with_name("all_deps").long("all-deps").help(
                    "Include all dependencies in the graph \
                    (shorthand for --build-deps --dev-deps --target-deps)",
                ))
                .arg(
                    Arg::with_name("build_deps")
                        .long("build-deps")
                        .help("Include build-dependencies in the graph"),
                )
                .arg(
                    Arg::with_name("dev_deps")
                        .long("dev-deps")
                        .help("Include dev-dependencies in the graph"),
                )
                .arg(
                    Arg::with_name("target_deps")
                        .long("target-deps")
                        .help("Include cfg() dependencies in the graph"),
                )
                .arg(Arg::with_name("dedup_transitive_deps").long("dedup-transitive-deps").help(
                    "Remove direct dependency edges where there's at \
                    least one transitive dependency of the same kind.",
                ))
                .arg(
                    Arg::with_name("exclude")
                        .long("exclude")
                        .multiple(true)
                        .use_delimiter(true)
                        .help(
                            "Package name(s) to ignore; can be given as a \
                            comma-separated list or as multiple arguments",
                        ),
                )
                .arg(Arg::with_name("focus").long("focus").multiple(true).use_delimiter(true).help(
                    "Package name(s) to focus on: only the given packages, the workspace members \
                    that depend on them and any intermediate dependencies are going to be present \
                    in the output; can be given as a comma-separated list or as multiple arguments",
                ))
                // Options to pass through to `cargo metadata`
                .arg(
                    Arg::with_name("features")
                        .long("features")
                        .help("Space-separated list of features to activate")
                        .multiple(true)
                        .number_of_values(1)
                        .value_name("FEATURES"),
                )
                .arg(
                    Arg::with_name("all_features")
                        .long("all-features")
                        .help("Activate all available features"),
                )
                .arg(
                    Arg::with_name("no_default_features")
                        .long("no-default-features")
                        .help("Do not activate the `default` feature"),
                )
                .arg(
                    Arg::with_name("filter_platform")
                        .long("filter-platform")
                        .help("Only include resolve dependencies matching the given target-triple")
                        .multiple(true)
                        .number_of_values(1)
                        .value_name("TRIPLE"),
                )
                .arg(
                    Arg::with_name("manifest_path")
                        .long("manifest-path")
                        .help("Path to Cargo.toml")
                        .value_name("PATH"),
                )
                .arg(
                    Arg::with_name("frozen")
                        .long("frozen")
                        .help("Require Cargo.lock and cache are up to date"),
                )
                .arg(
                    Arg::with_name("locked")
                        .long("locked")
                        .help("Require Cargo.lock is up to date"),
                )
                .arg(
                    Arg::with_name("offline")
                        .long("offline")
                        .help("Run without accessing the network"),
                )
                .arg(
                    Arg::with_name("unstable_flags")
                        .short("Z")
                        .help(
                            "Unstable (nightly-only) flags to Cargo, see \
                            'cargo -Z help' for details",
                        )
                        .value_name("FLAG")
                        .multiple(true)
                        .number_of_values(1),
                ),
        )
        .get_matches();

    let matches = matches.subcommand_matches("depgraph").unwrap();

    let all_deps = matches.is_present("all_deps");
    let build_deps = all_deps || matches.is_present("build_deps");
    let dev_deps = all_deps || matches.is_present("dev_deps");
    let target_deps = all_deps || matches.is_present("target_deps");
    let dedup_transitive_deps = matches.is_present("dedup_transitive_deps");
    let exclude = matches.values_of("exclude").map_or_else(Vec::new, collect_owned);
    let focus = matches.values_of("focus").map_or_else(Vec::new, collect_owned);

    let features = matches.values_of("features").map_or_else(Vec::new, collect_owned);
    let all_features = matches.is_present("all_features");
    let no_default_features = matches.is_present("no_default_features");
    let filter_platform = matches.values_of("filter_platform").map_or_else(Vec::new, collect_owned);
    let manifest_path = matches.value_of("manifest_path").map(ToOwned::to_owned);
    let frozen = matches.is_present("frozen");
    let locked = matches.is_present("locked");
    let offline = matches.is_present("offline");
    let unstable_flags = matches.values_of("unstable_flags").map_or_else(Vec::new, collect_owned);

    Config {
        build_deps,
        dev_deps,
        target_deps,
        dedup_transitive_deps,
        exclude,
        focus,
        features,
        all_features,
        no_default_features,
        filter_platform,
        manifest_path,
        frozen,
        locked,
        offline,
        unstable_flags,
    }
}

fn collect_owned<'a, T>(iter: impl Iterator<Item = &'a T>) -> Vec<T::Owned>
where
    T: ?Sized + ToOwned + 'a,
{
    iter.map(ToOwned::to_owned).collect()
}