Skip to main content

stern4rust/
args.rs

1// Copyright 2025 Umberto Gotti <umberto.gotti@umbertogotti.dev>
2// Licensed under the MIT License
3// SPDX-License-Identifier: MIT
4
5use std::path::PathBuf;
6
7use clap::Parser;
8
9#[derive(Debug, Parser)]
10#[command(name = "cargo-stern4rust")]
11#[command(bin_name = "cargo stern4rust")]
12#[command(version)]
13#[command(about = "Check Rust packages and fail the build when the rule is broken")]
14pub struct Args {
15    #[arg(long)]
16    pub manifest_path: Option<PathBuf>,
17
18    #[arg(long = "package")]
19    pub packages: Vec<String>,
20}
21
22impl Args {
23    pub fn parse_args() -> Self {
24        Self::parse_from(Self::without_cargo_subcommand(std::env::args()))
25    }
26
27    /// Cargo invokes `cargo stern4rust` as `cargo-stern4rust stern4rust ...`, so
28    /// the subcommand name arrives as an extra leading argument that clap would
29    /// otherwise reject. Running the binary directly does not repeat it, which
30    /// is why the strip is conditional rather than unconditional.
31    pub fn without_cargo_subcommand<I>(args: I) -> Vec<String>
32    where
33        I: IntoIterator<Item = String>,
34    {
35        let args: Vec<String> = args.into_iter().collect();
36        if args.get(1).map(String::as_str) != Some("stern4rust") {
37            return args;
38        }
39        let mut forwarded = Vec::with_capacity(args.len() - 1);
40        forwarded.extend(args.iter().take(1).cloned());
41        forwarded.extend(args.into_iter().skip(2));
42        forwarded
43    }
44}