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

Formatting for output of locate-project #8683

Closed
wants to merge 6 commits into from
Closed
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
59 changes: 58 additions & 1 deletion src/bin/cargo/commands/locate_project.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
use crate::command_prelude::*;
use anyhow::{bail, Context, Result};
use cargo::drop_println;
use cargo::util::format::{Parser, RawChunk};
use serde::Serialize;
use std::fmt;

pub fn cli() -> App {
subcommand("locate-project")
.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("format", "Format string used for printing project path")
.value_name("FORMAT")
.short("f"),
)
.after_help("Run `cargo help locate-project` for more detailed information.\n")
}

Expand All @@ -29,6 +38,54 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {

let location = ProjectLocation { root };

config.shell().print_json(&location);
match args.value_of("format") {
None => config.shell().print_json(&location),
Some(format) => print_format(config, &location, format)?,
}

Ok(())
}

enum Chunk<'a> {
Raw(&'a str),
Root,
}

fn parse_format(format: &str) -> Result<Vec<Chunk<'_>>> {
let mut chunks = Vec::new();
for raw in Parser::new(format) {
chunks.push(match raw {
RawChunk::Text(text) => Chunk::Raw(text),
RawChunk::Argument("root") => Chunk::Root,
RawChunk::Argument(a) => bail!("unsupported pattern `{}`", a),
RawChunk::Error(err) => bail!("{}", err),
});
}
Ok(chunks)
}

struct Display<'a> {
format: &'a [Chunk<'a>],
location: &'a ProjectLocation<'a>,
}

impl fmt::Display for Display<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for chunk in self.format {
match chunk {
Chunk::Raw(s) => f.write_str(s)?,
Chunk::Root => f.write_str(self.location.root)?,
}
}
Ok(())
}
}

fn print_format(config: &mut Config, location: &ProjectLocation<'_>, format: &str) -> Result<()> {
let ref format = parse_format(format)
.with_context(|| format!("locate-project format `{}` not valid", format))?;

let display = Display { format, location };
drop_println!(config, "{}", display);
Ok(())
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
use self::parse::{Parser, RawChunk};
use super::{Graph, Node};
use crate::util::format::{Parser, RawChunk};
use anyhow::{bail, Error};
use std::fmt;

mod parse;

enum Chunk {
Raw(String),
Package,
Expand Down
File renamed without changes.
1 change: 1 addition & 0 deletions src/cargo/util/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ mod dependency_queue;
pub mod diagnostic_server;
pub mod errors;
mod flock;
pub mod format;
pub mod graph;
mod hasher;
pub mod hex;
Expand Down
20 changes: 20 additions & 0 deletions src/doc/man/cargo-locate-project.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,26 @@ workspace root.

## OPTIONS

### Formatting Options

{{#options}}

{{#option "`-f` _format_" "`--format` _format_" }}
Set the format string for the output representation. The default is a JSON
object holding all of the supported information.

This is an arbitrary string which will be used to display the project location.
The following strings will be replaced with the corresponding value:

- `{root}` — The absolute path of the `Cargo.toml` manifest.

For example you might use `--format '{root}'` or more concisely `-f{root}` to
output just the path and nothing else, or `--format 'root={root}'` to include a
prefix.
{{/option}}

{{/options}}

### Display Options

{{#options}}
Expand Down
15 changes: 15 additions & 0 deletions src/doc/man/generated_txt/cargo-locate-project.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,21 @@ DESCRIPTION
workspace root.

OPTIONS
Formatting Options
-f format, --format format
Set the format string for the output representation. The default is
a JSON object holding all of the supported information.

This is an arbitrary string which will be used to display the
project location. The following strings will be replaced with the
corresponding value:

o {root} — The absolute path of the Cargo.toml manifest.

For example you might use --format '{root}' or more concisely
-f{root} to output just the path and nothing else, or --format
'root={root}' to include a prefix.

Display Options
-v, --verbose
Use verbose output. May be specified twice for "very verbose" output
Expand Down
20 changes: 20 additions & 0 deletions src/doc/src/commands/cargo-locate-project.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,26 @@ workspace root.

## OPTIONS

### Formatting Options

<dl>

<dt class="option-term" id="option-cargo-locate-project--f"><a class="option-anchor" href="#option-cargo-locate-project--f"></a><code>-f</code> <em>format</em></dt>
<dt class="option-term" id="option-cargo-locate-project---format"><a class="option-anchor" href="#option-cargo-locate-project---format"></a><code>--format</code> <em>format</em></dt>
<dd class="option-desc">Set the format string for the output representation. The default is a JSON
object holding all of the supported information.</p>
<p>This is an arbitrary string which will be used to display the project location.
The following strings will be replaced with the corresponding value:</p>
<ul>
<li><code>{root}</code> — The absolute path of the <code>Cargo.toml</code> manifest.</li>
</ul>
<p>For example you might use <code>--format '{root}'</code> or more concisely <code>-f{root}</code> to
output just the path and nothing else, or <code>--format 'root={root}'</code> to include a
prefix.</dd>


</dl>

### Display Options

<dl>
Expand Down
3 changes: 2 additions & 1 deletion src/etc/_cargo
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,8 @@ _cargo() {
;;

locate-project)
_arguments -s -S $common $manifest
_arguments -s -S $common $manifest \
'(-f --format)'{-f,--format=}'[format string]:format'
;;

login)
Expand Down
2 changes: 1 addition & 1 deletion src/etc/cargo.bashcomp.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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 -f --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"
Expand Down
19 changes: 19 additions & 0 deletions src/etc/man/cargo-locate-project.1
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,25 @@ This command will print a JSON object to stdout with the full path to the
See also \fBcargo\-metadata\fR(1) which is capable of returning the path to a
workspace root.
.SH "OPTIONS"
.SS "Formatting Options"
.sp
\fB\-f\fR \fIformat\fR,
\fB\-\-format\fR \fIformat\fR
.RS 4
Set the format string for the output representation. The default is a JSON
object holding all of the supported information.
.sp
This is an arbitrary string which will be used to display the project location.
The following strings will be replaced with the corresponding value:
.sp
.RS 4
\h'-04'\(bu\h'+02'\fB{root}\fR \[em] The absolute path of the \fBCargo.toml\fR manifest.
.RE
.sp
For example you might use \fB\-\-format '{root}'\fR or more concisely \fB\-f{root}\fR to
output just the path and nothing else, or \fB\-\-format 'root={root}'\fR to include a
prefix.
.RE
.SS "Display Options"
.sp
\fB\-v\fR,
Expand Down
31 changes: 31 additions & 0 deletions tests/testsuite/locate_project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,34 @@ fn simple() {
))
.run();
}

#[cargo_test]
fn 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 --format {root}")
.with_stdout(root_str)
.run();

p.cargo("locate-project -f{root}")
.with_stdout(root_str)
.run();

p.cargo("locate-project --format root={root}")
.with_stdout(format!("root={}", root_str))
.run();

p.cargo("locate-project --format {toor}")
.with_stderr(
"\
[ERROR] locate-project format `{toor}` not valid

Caused by:
unsupported pattern `toor`
",
)
.with_status(101)
.run();
}