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();
+}