Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TEST: update to clap 4.0.0-prerelease #316

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
46 changes: 38 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Expand Up @@ -18,7 +18,7 @@ exclude = [

[dependencies]
cargo_metadata = "0.14.2"
clap = { version = "3.2.6", features = ["derive"] }
clap = { git="https://github.com/clap-rs/clap", features = ["derive"] }
clap-cargo = "0.9.1"
console = "0.15.0"
crates-index = { version = "0.18.8", default-features = false }
Expand Down
53 changes: 49 additions & 4 deletions src/cli.rs
Expand Up @@ -18,7 +18,6 @@ pub enum FakeCli {
#[clap(version)]
#[clap(bin_name = "cargo vet")]
#[clap(args_conflicts_with_subcommands = true)]
#[clap(global_setting(clap::AppSettings::DeriveDisplayOrder))]
/// Supply-chain security for Rust
///
/// When run without a subcommand, `cargo vet` will invoke the `check`
Expand All @@ -30,7 +29,7 @@ pub struct Cli {

// Top-level flags
/// Path to Cargo.toml
#[clap(long, name = "PATH", parse(from_os_str))]
#[clap(long, name = "PATH", value_parser)]
#[clap(help_heading = "GLOBAL OPTIONS", global = true)]
pub manifest_path: Option<PathBuf>,

Expand All @@ -48,7 +47,7 @@ pub struct Cli {
pub no_default_features: bool,

/// Space-separated list of features to activate
#[clap(long, action, require_value_delimiter = true, value_delimiter = ' ')]
#[clap(long, action, value_delimiter = ' ')]
#[clap(help_heading = "GLOBAL OPTIONS", global = true)]
pub features: Vec<String>,

Expand All @@ -73,7 +72,7 @@ pub struct Cli {
/// How verbose logging should be (log level)
#[clap(long, action)]
#[clap(default_value_t = LevelFilter::WARN)]
#[clap(possible_values = ["off", "error", "warn", "info", "debug", "trace"])]
#[clap(value_parser = verbose_value_parser(["off", "error", "warn", "info", "debug", "trace"]))]
#[clap(help_heading = "GLOBAL OPTIONS", global = true)]
pub verbose: LevelFilter,

Expand Down Expand Up @@ -158,6 +157,52 @@ pub struct Cli {
pub check_args: CheckArgs,
}

fn verbose_value_parser(values: impl IntoIterator<Item = &'static str>) -> VerboseValuesParser {
VerboseValuesParser(values.into_iter().collect())
}

#[derive(Clone, Debug)]
pub struct VerboseValuesParser(Vec<&'static str>);

impl clap::builder::TypedValueParser for VerboseValuesParser {
type Value = LevelFilter;

fn parse_ref(
&self,
cmd: &clap::Command,
arg: Option<&clap::Arg>,
value: &std::ffi::OsStr,
) -> Result<Self::Value, clap::Error> {
clap::builder::TypedValueParser::parse(self, cmd, arg, value.to_owned())
}

fn parse(
&self,
_cmd: &clap::Command,
_arg: Option<&clap::Arg>,
value: std::ffi::OsString,
) -> Result<Self::Value, clap::Error> {
let value = value
.into_string()
.map_err(|_| clap::Error::raw(clap::error::ErrorKind::InvalidUtf8, "invalid utf8"))?;

value.parse().map_err(|_e| {
clap::Error::raw(
clap::error::ErrorKind::InvalidValue,
format!("must be one of {:?}", self.0),
)
})
}

fn possible_values(
&self,
) -> Option<Box<dyn Iterator<Item = clap::builder::PossibleValue> + '_>> {
Some(Box::new(
self.0.iter().map(|s| clap::builder::PossibleValue::from(s)),
))
}
}

#[derive(Subcommand)]
pub enum Commands {
// Main commands:
Expand Down
39 changes: 18 additions & 21 deletions src/main.rs
Expand Up @@ -1625,22 +1625,17 @@ fn cmd_help_md(
// Use a trailing colon to indicate a heading
if let Some(heading) = line.strip_suffix(':') {
if !line.starts_with(' ') {
// SCREAMING headers are Main headings
if heading.to_ascii_uppercase() == heading {
in_subcommands_listing = heading == "SUBCOMMANDS";
in_usage = heading == "USAGE";
in_global_options = heading == "GLOBAL OPTIONS";

writeln!(out, "### {heading}");

if in_global_options && !is_full_command {
writeln!(
out,
"This subcommand accepts all the [global options](#global-options)"
);
}
} else {
writeln!(out, "### {heading}");
in_subcommands_listing = heading == "Subcommands";
in_usage = heading == "Usage";
in_global_options = heading == "GLOBAL OPTIONS";

writeln!(out, "### {heading}");

if in_global_options && !is_full_command {
writeln!(
out,
"This subcommand accepts all the [global options](#global-options)"
);
}
continue;
}
Expand All @@ -1654,11 +1649,13 @@ fn cmd_help_md(
if in_subcommands_listing && !line.starts_with(" ") {
// subcommand names are list items
let own_subcommand_name = line.trim();
write!(
out,
"* [{own_subcommand_name}](#{app_name}-{own_subcommand_name}): "
);
continue;
if !own_subcommand_name.is_empty() {
write!(
out,
"* [{own_subcommand_name}](#{app_name}-{own_subcommand_name}): "
);
continue;
}
}
// The rest is indented, get rid of that
let line = line.trim();
Expand Down
66 changes: 33 additions & 33 deletions tests/snapshots/test_cli__long-help.snap
Expand Up @@ -3,17 +3,47 @@ source: tests/test-cli.rs
expression: format_outputs(&output)
---
stdout:
cargo-vet 0.3.0
cargo-vet-vet 0.3.0
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a regression, unclear whose fault it is (see clap-rs/clap#4132 (comment)).

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you set name = cargo in addition to the bin_name, this should be resolved. See https://github.com/clap-rs/clap/blob/master/examples/cargo-example-derive.rs#L4

In clap 3, the user sets bin_name = cargo and we build that up as we recurse down the subcommands. When we then render the "name", we then did a search/replace on it which on windows without an explicit bin_name would end up with foo.exe-bar. So in clap 4, we build up the usage_name from the root command's bin_name + each subcommand's name and the display_name from all command's names.

Supply-chain security for Rust

When run without a subcommand, `cargo vet` will invoke the `check` subcommand. See `cargo vet help
check` for more details.

USAGE:
Usage:
cargo vet [OPTIONS]
cargo vet <SUBCOMMAND>

OPTIONS:
Subcommands:
check
\[default\] Check that the current project has been vetted
suggest
Suggest some low-hanging fruit to review
init
Initialize cargo-vet for your project
inspect
Fetch the source of a package
diff
Yield a diff against the last reviewed version
certify
Mark a package as audited
regenerate
Explicitly regenerate various pieces of information
add-exemption
Mark a package as exempted from review
record-violation
Declare that some versions of a package violate certain audit criteria
fmt
Reformat all of vet's files (in case you hand-edited them)
fetch-imports
Explicitly fetch the imports (foreign audit files)
dump-graph
Print the cargo build graph as understood by `cargo vet`
gc
Clean up old packages from the vet cache
help
Print this message or the help of the given subcommand(s)

Options:
--shallow
Avoid suggesting audits for dependencies of unaudited dependencies.

Expand Down Expand Up @@ -126,35 +156,5 @@ GLOBAL OPTIONS:
* `is_dev_only($bool)`: whether it's only used by dev (test) builds in the original
graph

SUBCOMMANDS:
check
\[default\] Check that the current project has been vetted
suggest
Suggest some low-hanging fruit to review
init
Initialize cargo-vet for your project
inspect
Fetch the source of a package
diff
Yield a diff against the last reviewed version
certify
Mark a package as audited
regenerate
Explicitly regenerate various pieces of information
add-exemption
Mark a package as exempted from review
record-violation
Declare that some versions of a package violate certain audit criteria
fmt
Reformat all of vet's files (in case you hand-edited them)
fetch-imports
Explicitly fetch the imports (foreign audit files)
dump-graph
Print the cargo build graph as understood by `cargo vet`
gc
Clean up old packages from the vet cache
help
Print this message or the help of the given subcommand(s)

stderr: