diff --git a/src/bin/cargo/commands/locate_project.rs b/src/bin/cargo/commands/locate_project.rs index c1c8435e459..4e29c9524b1 100644 --- a/src/bin/cargo/commands/locate_project.rs +++ b/src/bin/cargo/commands/locate_project.rs @@ -1,4 +1,6 @@ use crate::command_prelude::*; +use anyhow::bail; +use cargo::{drop_println, CargoResult}; use serde::Serialize; pub fn cli() -> App { @@ -6,6 +8,13 @@ pub fn cli() -> App { .about("Print a JSON representation of a Cargo.toml file's location") .arg(opt("quiet", "No output printed to stdout").short("q")) .arg_manifest_path() + .arg( + opt( + "message-format", + "Output representation [possible values: json, plain]", + ) + .value_name("FMT"), + ) .after_help("Run `cargo help locate-project` for more detailed information.\n") } @@ -29,6 +38,29 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult { let location = ProjectLocation { root }; - config.shell().print_json(&location); + match MessageFormat::parse(args)? { + MessageFormat::Json => config.shell().print_json(&location), + MessageFormat::Plain => drop_println!(config, "{}", location.root), + } + Ok(()) } + +enum MessageFormat { + Json, + Plain, +} + +impl MessageFormat { + fn parse(args: &ArgMatches<'_>) -> CargoResult { + let fmt = match args.value_of("message-format") { + Some(fmt) => fmt, + None => return Ok(MessageFormat::Json), + }; + match fmt.to_ascii_lowercase().as_str() { + "json" => Ok(MessageFormat::Json), + "plain" => Ok(MessageFormat::Plain), + s => bail!("invalid message format specifier: `{}`", s), + } + } +} diff --git a/src/doc/man/cargo-locate-project.md b/src/doc/man/cargo-locate-project.md index 349e63c5e8d..f5f88af6c7b 100644 --- a/src/doc/man/cargo-locate-project.md +++ b/src/doc/man/cargo-locate-project.md @@ -21,6 +21,14 @@ workspace root. ### Display Options {{#options}} + +{{#option "`--message-format` _fmt_" }} +The representation in which to print the project location. Valid values: + +- `json` (default): JSON object with the path under the key "root". +- `plain`: Just the path. +{{/option}} + {{> options-display }} {{/options}} diff --git a/src/doc/man/generated_txt/cargo-locate-project.txt b/src/doc/man/generated_txt/cargo-locate-project.txt index ec1377fb568..7afd01ddf78 100644 --- a/src/doc/man/generated_txt/cargo-locate-project.txt +++ b/src/doc/man/generated_txt/cargo-locate-project.txt @@ -16,6 +16,14 @@ DESCRIPTION OPTIONS Display Options + --message-format fmt + The representation in which to print the project location. Valid + values: + + o json (default): JSON object with the path under the key "root". + + o plain: Just the path. + -v, --verbose Use verbose output. May be specified twice for "very verbose" output which includes extra output such as dependency warnings and build diff --git a/src/doc/src/commands/cargo-locate-project.md b/src/doc/src/commands/cargo-locate-project.md index dff40101277..8dde35015ba 100644 --- a/src/doc/src/commands/cargo-locate-project.md +++ b/src/doc/src/commands/cargo-locate-project.md @@ -21,6 +21,15 @@ workspace root. ### Display Options
+ +
--message-format fmt
+
The representation in which to print the project location. Valid values:

+
    +
  • json (default): JSON object with the path under the key "root".
  • +
  • plain: Just the path.
  • +
+ +
-v
--verbose
Use verbose output. May be specified twice for "very verbose" output which diff --git a/src/etc/_cargo b/src/etc/_cargo index f906d149168..28c8b081c2f 100644 --- a/src/etc/_cargo +++ b/src/etc/_cargo @@ -160,7 +160,8 @@ _cargo() { ;; locate-project) - _arguments -s -S $common $manifest + _arguments -s -S $common $manifest \ + '--message-format=[specify output representation]:output representation [json]:(json plain)' ;; login) @@ -367,8 +368,7 @@ _cargo_package_names() { # Extracts the values of "name" from the array given in $1 and shows them as # command line options for completion _cargo_names_from_array() { - # strip json from the path - local manifest=${${${"$(cargo locate-project)"}%\"\}}##*\"} + local manifest=$(cargo locate-project --message-format plain) if [[ -z $manifest ]]; then return 0 fi diff --git a/src/etc/cargo.bashcomp.sh b/src/etc/cargo.bashcomp.sh index aa6626f1114..8a3334c4811 100644 --- a/src/etc/cargo.bashcomp.sh +++ b/src/etc/cargo.bashcomp.sh @@ -59,7 +59,7 @@ _cargo() local opt__help="$opt_help" local opt__init="$opt_common $opt_lock --bin --lib --name --vcs --edition --registry" local opt__install="$opt_common $opt_feat $opt_jobs $opt_lock $opt_force --bin --bins --branch --debug --example --examples --git --list --path --rev --root --tag --version --registry --target --profile --no-track" - local opt__locate_project="$opt_common $opt_mani $opt_lock" + local opt__locate_project="$opt_common $opt_mani $opt_lock --message-format" local opt__login="$opt_common $opt_lock --registry" local opt__metadata="$opt_common $opt_feat $opt_mani $opt_lock --format-version=1 --no-deps --filter-platform" local opt__new="$opt_common $opt_lock --vcs --bin --lib --name --edition --registry" @@ -155,9 +155,7 @@ complete -F _cargo cargo __cargo_commands=$(cargo --list 2>/dev/null | awk 'NR>1 {print $1}') _locate_manifest(){ - local manifest=`cargo locate-project 2>/dev/null` - # regexp-replace manifest '\{"root":"|"\}' '' - echo ${manifest:9:${#manifest}-11} + cargo locate-project --message-format plain 2>/dev/null } # Extracts the values of "name" from the array given in $1 and shows them as diff --git a/src/etc/man/cargo-locate-project.1 b/src/etc/man/cargo-locate-project.1 index 29283dde5ac..86fa9ebb36b 100644 --- a/src/etc/man/cargo-locate-project.1 +++ b/src/etc/man/cargo-locate-project.1 @@ -16,6 +16,19 @@ workspace root. .SH "OPTIONS" .SS "Display Options" .sp +\fB\-\-message\-format\fR \fIfmt\fR +.RS 4 +The representation in which to print the project location. Valid values: +.sp +.RS 4 +\h'-04'\(bu\h'+02'\fBjson\fR (default): JSON object with the path under the key "root". +.RE +.sp +.RS 4 +\h'-04'\(bu\h'+02'\fBplain\fR: Just the path. +.RE +.RE +.sp \fB\-v\fR, \fB\-\-verbose\fR .RS 4 diff --git a/tests/testsuite/locate_project.rs b/tests/testsuite/locate_project.rs index 17712a69c24..5ff3677e844 100644 --- a/tests/testsuite/locate_project.rs +++ b/tests/testsuite/locate_project.rs @@ -14,3 +14,23 @@ fn simple() { )) .run(); } + +#[cargo_test] +fn message_format() { + let p = project().build(); + let root_manifest_path = p.root().join("Cargo.toml"); + let root_str = root_manifest_path.to_str().unwrap(); + + p.cargo("locate-project --message-format plain") + .with_stdout(root_str) + .run(); + + p.cargo("locate-project --message-format json") + .with_stdout(format!(r#"{{"root":"{}"}}"#, root_str)) + .run(); + + p.cargo("locate-project --message-format cryptic") + .with_stderr("error: invalid message format specifier: `cryptic`") + .with_status(101) + .run(); +}