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
#![warn(missing_docs)]
use std::{env, io, path::{PathBuf}, process, string};
pub fn locate_manifest() -> Result<PathBuf, LocateManifestError> {
let cargo = env::var("CARGO").unwrap_or("cargo".to_owned());
let output = process::Command::new(cargo).arg("locate-project").output()?;
if !output.status.success() {
return Err(LocateManifestError::CargoExecution{ stderr: output.stderr});
}
let output = String::from_utf8(output.stdout)?;
let parsed = json::parse(&output)?;
let root = parsed["root"].as_str().ok_or(LocateManifestError::NoRoot)?;
Ok(PathBuf::from(root))
}
#[derive(Debug)]
pub enum LocateManifestError {
Io(io::Error),
CargoExecution{
stderr: Vec<u8>,
},
StringConversion(string::FromUtf8Error),
ParseJson(json::Error),
NoRoot,
}
impl From<io::Error> for LocateManifestError {
fn from(err: io::Error) -> Self {
LocateManifestError::Io(err)
}
}
impl From<string::FromUtf8Error> for LocateManifestError {
fn from(err: string::FromUtf8Error) -> Self {
LocateManifestError::StringConversion(err)
}
}
impl From<json::Error> for LocateManifestError {
fn from(err: json::Error) -> Self {
LocateManifestError::ParseJson(err)
}
}
#[test]
fn test_manifest_path() {
use std::path::Path;
let manifest_path = locate_manifest().expect("failed to retrieve cargo manifest path");
let manual_path = Path::new(file!()).parent().unwrap().join("../Cargo.toml").canonicalize().unwrap();
assert_eq!(manifest_path, manual_path);
}