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

Update clap to 3.0.0-beta.4 #59

Merged
merged 2 commits into from
Aug 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ anyhow = "1.0.34"
atty = "0.2.11"
camino = "1.0.3"
cargo_metadata = "0.14"
clap = "=3.0.0-beta.2"
clap = "=3.0.0-beta.4"
dirs-next = "2"
duct = "0.13.1"
fs-err = "2.5"
Expand Down
17 changes: 9 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,25 @@ brew install taiki-e/tap/cargo-llvm-cov
```console
$ cargo llvm-cov --help
cargo-llvm-cov

Cargo subcommand for LLVM source-based code coverage (-Z instrument-coverage).

Use -h for short descriptions and --help for more details.

USAGE:
cargo llvm-cov [OPTIONS] [-- <args>...]
cargo llvm-cov [OPTIONS] [-- <ARGS>...]

ARGS:
<args>...
<ARGS>...
Arguments for the test binary

OPTIONS:
-h, --help
Print help information

-V, --version
Print version information

--json
Export coverage data in "json" format

Expand Down Expand Up @@ -187,12 +194,6 @@ OPTIONS:

-Z <FLAG>...
Unstable (nightly-only) flags to Cargo

-h, --help
Prints help information

-V, --version
Prints version information
```
<!-- readme-long-help:end -->

Expand Down
153 changes: 113 additions & 40 deletions src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use anyhow::Result;
use camino::Utf8PathBuf;
use clap::{AppSettings, Clap};
use clap::{AppSettings, ArgSettings, Clap};
use serde::Deserialize;

pub(crate) fn from_args() -> Result<Args> {
Expand All @@ -17,24 +17,24 @@ const MAX_TERM_WIDTH: usize = 100;
#[derive(Debug, Clap)]
#[clap(
bin_name = "cargo",
max_term_width = MAX_TERM_WIDTH,
setting = AppSettings::DeriveDisplayOrder,
setting = AppSettings::StrictUtf8,
setting = AppSettings::UnifiedHelpMessage,
max_term_width(MAX_TERM_WIDTH),
setting(AppSettings::DeriveDisplayOrder),
setting(AppSettings::StrictUtf8),
setting(AppSettings::UnifiedHelpMessage)
)]
enum Opts {
#[clap(about = ABOUT)]
#[clap(about(ABOUT))]
LlvmCov(Args),
}

#[derive(Debug, Clap)]
#[clap(
bin_name = "cargo llvm-cov",
about = ABOUT,
max_term_width = MAX_TERM_WIDTH,
setting = AppSettings::DeriveDisplayOrder,
setting = AppSettings::StrictUtf8,
setting = AppSettings::UnifiedHelpMessage,
about(ABOUT),
max_term_width(MAX_TERM_WIDTH),
setting(AppSettings::DeriveDisplayOrder),
setting(AppSettings::StrictUtf8),
setting(AppSettings::UnifiedHelpMessage)
)]
pub(crate) struct Args {
#[clap(subcommand)]
Expand Down Expand Up @@ -63,44 +63,57 @@ pub(crate) struct Args {
///
/// This internally calls `llvm-cov show -format=text`.
/// See <https://llvm.org/docs/CommandGuide/llvm-cov.html#llvm-cov-show> for more.
#[clap(long, conflicts_with_all = &["json", "lcov"])]
#[clap(long, conflicts_with = "json", conflicts_with = "lcov")]
pub(crate) text: bool,
/// Generate coverage reports in "html" format.
////
/// If --output-dir is not specified, the report will be generated in `target/llvm-cov` directory.
///
/// This internally calls `llvm-cov show -format=html`.
/// See <https://llvm.org/docs/CommandGuide/llvm-cov.html#llvm-cov-show> for more.
#[clap(long, conflicts_with_all = &["json", "lcov", "text"])]
#[clap(long, conflicts_with = "json", conflicts_with = "lcov", conflicts_with = "text")]
pub(crate) html: bool,
/// Generate coverage reports in "html" format and open them in a browser after the operation.
///
/// See --html for more.
#[clap(long, conflicts_with_all = &["json", "lcov", "text"])]
#[clap(long, conflicts_with = "json", conflicts_with = "lcov", conflicts_with = "text")]
pub(crate) open: bool,

/// Export only summary information for each file in the coverage data.
///
/// This flag can only be used together with either --json or --lcov.
// If the format flag is not specified, this flag is no-op because the only summary is displayed anyway.
#[clap(long, conflicts_with_all = &["text", "html", "open"])]
#[clap(long, conflicts_with = "text", conflicts_with = "html", conflicts_with = "open")]
pub(crate) summary_only: bool,
/// Specify a file to write coverage data into.
///
/// This flag can only be used together with --json, --lcov, or --text.
/// See --output-dir for --html and --open.
#[clap(long, value_name = "PATH", conflicts_with_all = &["html", "open"])]
#[clap(
long,
value_name = "PATH",
conflicts_with = "html",
conflicts_with = "open",
setting(ArgSettings::ForbidEmptyValues)
)]
pub(crate) output_path: Option<Utf8PathBuf>,
/// Specify a directory to write coverage reports into (default to `target/llvm-cov`).
///
/// This flag can only be used together with --text, --html, or --open.
/// See also --output-path.
// If the format flag is not specified, this flag is no-op.
#[clap(long, value_name = "DIRECTORY", conflicts_with_all = &["json", "lcov", "output-path"])]
#[clap(
long,
value_name = "DIRECTORY",
conflicts_with = "json",
conflicts_with = "lcov",
conflicts_with = "output-path",
setting(ArgSettings::ForbidEmptyValues)
)]
pub(crate) output_dir: Option<Utf8PathBuf>,

/// Skip source code files with file paths that match the given regular expression.
#[clap(long, value_name = "PATTERN")]
#[clap(long, value_name = "PATTERN", setting(ArgSettings::ForbidEmptyValues))]
pub(crate) ignore_filename_regex: Option<String>,
// For debugging (unstable)
#[clap(long, hidden = true)]
Expand Down Expand Up @@ -129,13 +142,26 @@ pub(crate) struct Args {
/// Package to run tests for
// cargo allows the combination of --package and --workspace, but we reject
// it because the situation where both flags are specified is odd.
#[clap(short, long, value_name = "SPEC", conflicts_with = "workspace")]
#[clap(
short,
long,
multiple_occurrences = true,
value_name = "SPEC",
conflicts_with = "workspace",
setting(ArgSettings::ForbidEmptyValues)
)]
pub(crate) package: Vec<String>,
/// Test all packages in the workspace
#[clap(long, visible_alias = "all")]
pub(crate) workspace: bool,
/// Exclude packages from the test
#[clap(long, value_name = "SPEC", requires = "workspace")]
#[clap(
long,
multiple_occurrences = true,
value_name = "SPEC",
requires = "workspace",
setting(ArgSettings::ForbidEmptyValues)
)]
pub(crate) exclude: Vec<String>,
// TODO: Should this only work for cargo's --jobs? Or should it also work
// for llvm-cov's -num-threads?
Expand All @@ -146,7 +172,12 @@ pub(crate) struct Args {
#[clap(long)]
pub(crate) release: bool,
/// Space or comma separated list of features to activate
#[clap(long, value_name = "FEATURES")]
#[clap(
long,
multiple_occurrences = true,
value_name = "FEATURES",
setting(ArgSettings::ForbidEmptyValues)
)]
pub(crate) features: Vec<String>,
/// Activate all available features
#[clap(long)]
Expand All @@ -158,7 +189,7 @@ pub(crate) struct Args {
///
/// When this option is used, coverage for proc-macro and build script will
/// not be displayed because cargo does not pass RUSTFLAGS to them.
#[clap(long, value_name = "TRIPLE")]
#[clap(long, value_name = "TRIPLE", setting(ArgSettings::ForbidEmptyValues))]
pub(crate) target: Option<String>,
// TODO: Currently, we are using a subdirectory of the target directory as
// the actual target directory. What effect should this option have
Expand All @@ -167,7 +198,7 @@ pub(crate) struct Args {
// #[clap(long, value_name = "DIRECTORY")]
// target_dir: Option<Utf8PathBuf>,
/// Path to Cargo.toml
#[clap(long, value_name = "PATH")]
#[clap(long, value_name = "PATH", setting(ArgSettings::ForbidEmptyValues))]
pub(crate) manifest_path: Option<Utf8PathBuf>,
/// Use verbose output (-vv/-vvv propagate verbosity to cargo)
#[clap(short, long, parse(from_occurrences))]
Expand All @@ -184,11 +215,16 @@ pub(crate) struct Args {
pub(crate) locked: bool,

/// Unstable (nightly-only) flags to Cargo
#[clap(short = 'Z', value_name = "FLAG")]
#[clap(
short = 'Z',
multiple_occurrences = true,
value_name = "FLAG",
setting(ArgSettings::ForbidEmptyValues)
)]
pub(crate) unstable_flags: Vec<String>,

/// Arguments for the test binary
#[clap(last = true)]
#[clap(last = true, setting(ArgSettings::ForbidEmptyValues))]
pub(crate) args: Vec<String>,
}

Expand Down Expand Up @@ -221,13 +257,8 @@ pub(crate) enum Coloring {
}

impl Coloring {
// TODO: use clap::ArgEnum::as_arg instead once new version of clap released.
pub(crate) fn cargo_color(self) -> &'static str {
match self {
Self::Auto => "auto",
Self::Always => "always",
Self::Never => "never",
}
clap::ArgEnum::as_arg(&self).unwrap()
}
}

Expand All @@ -236,22 +267,18 @@ mod tests {
use std::{env, panic, path::Path, process::Command};

use anyhow::Result;
use clap::IntoApp;
use clap::{Clap, IntoApp};
use fs_err as fs;
use tempfile::Builder;

use super::{Args, MAX_TERM_WIDTH};
use super::{Args, Opts, MAX_TERM_WIDTH};

// https://github.com/clap-rs/clap/issues/751
#[cfg(unix)]
#[test]
fn non_utf8_arg() {
use std::{ffi::OsStr, os::unix::prelude::OsStrExt};

use clap::Clap;

use super::Opts;

// `cargo llvm-cov -- $'fo\x80o'`
Opts::try_parse_from(&[
"cargo".as_ref(),
Expand All @@ -262,6 +289,55 @@ mod tests {
.unwrap_err();
}

// https://github.com/clap-rs/clap/issues/1772
#[test]
fn multiple_occurrences() {
let Opts::LlvmCov(args) =
Opts::try_parse_from(&["cargo", "llvm-cov", "--features", "a", "--features", "b"])
.unwrap();
assert_eq!(args.features, ["a", "b"]);

let Opts::LlvmCov(args) =
Opts::try_parse_from(&["cargo", "llvm-cov", "--package", "a", "--package", "b"])
.unwrap();
assert_eq!(args.package, ["a", "b"]);

let Opts::LlvmCov(args) = Opts::try_parse_from(&[
"cargo",
"llvm-cov",
"--exclude",
"a",
"--exclude",
"b",
"--all",
])
.unwrap();
assert_eq!(args.exclude, ["a", "b"]);

let Opts::LlvmCov(args) =
Opts::try_parse_from(&["cargo", "llvm-cov", "-Z", "a", "-Zb"]).unwrap();
assert_eq!(args.unstable_flags, ["a", "b"]);

let Opts::LlvmCov(args) =
Opts::try_parse_from(&["cargo", "llvm-cov", "--", "a", "b"]).unwrap();
assert_eq!(args.args, ["a", "b"]);
}

// https://github.com/clap-rs/clap/issues/1740
#[test]
fn empty_value() {
Opts::try_parse_from(&["cargo", "llvm-cov", "--output-path", ""]).unwrap_err();
Opts::try_parse_from(&["cargo", "llvm-cov", "--output-dir", ""]).unwrap_err();
Opts::try_parse_from(&["cargo", "llvm-cov", "--ignore-filename-regex", ""]).unwrap_err();
Opts::try_parse_from(&["cargo", "llvm-cov", "--package", ""]).unwrap_err();
Opts::try_parse_from(&["cargo", "llvm-cov", "--exclude", ""]).unwrap_err();
Opts::try_parse_from(&["cargo", "llvm-cov", "--features", ""]).unwrap_err();
Opts::try_parse_from(&["cargo", "llvm-cov", "--target", ""]).unwrap_err();
Opts::try_parse_from(&["cargo", "llvm-cov", "--manifest-path", ""]).unwrap_err();
Opts::try_parse_from(&["cargo", "llvm-cov", "-Z", ""]).unwrap_err();
Opts::try_parse_from(&["cargo", "llvm-cov", "--", ""]).unwrap_err();
}

fn get_help(long: bool) -> Result<String> {
let mut buf = vec![];
if long {
Expand All @@ -277,9 +353,6 @@ mod tests {
out.push_str(line.trim_end());
out.push('\n');
}
if long {
out.pop();
}
Ok(out)
}

Expand Down
12 changes: 6 additions & 6 deletions tests/fixtures/coverage-reports/merge/merge.full.json
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@
9,
3,
13,
1,
0,
0,
0,
0
Expand All @@ -201,7 +201,7 @@
9,
5,
14,
0,
1,
0,
0,
0
Expand Down Expand Up @@ -229,7 +229,7 @@
[
10,
1,
14,
12,
23,
1,
0,
Expand Down Expand Up @@ -311,7 +311,7 @@
9,
3,
13,
0,
1,
0,
0,
0
Expand All @@ -321,7 +321,7 @@
9,
5,
14,
1,
0,
0,
0,
0
Expand Down Expand Up @@ -349,7 +349,7 @@
[
10,
1,
12,
14,
23,
1,
0,
Expand Down
Loading