forked from rust-lang/cargo
/
locate_project.rs
95 lines (84 loc) · 2.46 KB
/
locate_project.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
use crate::command_prelude::*;
use anyhow::bail;
use cargo::{drop_println, CargoResult};
use serde::Serialize;
pub fn cli() -> Command {
subcommand("locate-project")
.about("Print a JSON representation of a Cargo.toml file's location")
.arg(flag("workspace", "Locate Cargo.toml of the workspace root"))
.arg(
opt(
"message-format",
"Output representation [possible values: json, plain]",
)
.value_name("FMT"),
)
.arg_quiet()
.arg_manifest_path()
.after_help(color_print::cstr!(
"Run `<cyan,bold>cargo help locate-project</>` for more detailed information.\n"
))
}
#[derive(Serialize)]
pub struct ProjectLocation<'a> {
root: &'a str,
}
pub fn exec(config: &mut Config, args: &ArgMatches) -> CliResult {
let root_manifest;
let workspace;
let root = match WhatToFind::parse(args) {
WhatToFind::CurrentManifest => {
root_manifest = args.root_manifest(config)?;
&root_manifest
}
WhatToFind::Workspace => {
workspace = args.workspace(config)?;
workspace.root_manifest()
}
};
let root = root
.to_str()
.ok_or_else(|| {
anyhow::format_err!(
"your package path contains characters \
not representable in Unicode"
)
})
.map_err(|e| CliError::new(e, 1))?;
let location = ProjectLocation { root };
match MessageFormat::parse(args)? {
MessageFormat::Json => config.shell().print_json(&location)?,
MessageFormat::Plain => drop_println!(config, "{}", location.root),
}
Ok(())
}
enum WhatToFind {
CurrentManifest,
Workspace,
}
impl WhatToFind {
fn parse(args: &ArgMatches) -> Self {
if args.flag("workspace") {
WhatToFind::Workspace
} else {
WhatToFind::CurrentManifest
}
}
}
enum MessageFormat {
Json,
Plain,
}
impl MessageFormat {
fn parse(args: &ArgMatches) -> CargoResult<Self> {
let fmt = match args.get_one::<String>("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),
}
}
}