racer_cargo_metadata/
lib.rs1extern crate racer_interner;
2#[macro_use]
3extern crate serde;
4extern crate serde_json;
5
6pub mod mapping;
7pub mod metadata;
8
9use crate::metadata::Metadata;
10use std::env;
11use std::error::Error;
12use std::fmt;
13use std::io;
14use std::path::{Path, PathBuf};
15use std::process::Command;
16use std::str::Utf8Error;
17
18#[derive(Debug)]
19pub enum ErrorKind {
20 Encode(Utf8Error),
21 Json(serde_json::Error),
22 Io(io::Error),
23 Subprocess(String),
24}
25
26impl fmt::Display for ErrorKind {
27 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
28 match self {
29 ErrorKind::Encode(e) => fmt::Display::fmt(e, f),
30 ErrorKind::Json(e) => fmt::Display::fmt(e, f),
31 ErrorKind::Io(e) => fmt::Display::fmt(e, f),
32 ErrorKind::Subprocess(s) => write!(f, "stderr: {}", s),
33 }
34 }
35}
36
37impl Error for ErrorKind {}
38
39impl From<Utf8Error> for ErrorKind {
40 fn from(e: Utf8Error) -> ErrorKind {
41 ErrorKind::Encode(e)
42 }
43}
44
45impl From<serde_json::Error> for ErrorKind {
46 fn from(e: serde_json::Error) -> ErrorKind {
47 ErrorKind::Json(e)
48 }
49}
50
51impl From<io::Error> for ErrorKind {
52 fn from(e: io::Error) -> ErrorKind {
53 ErrorKind::Io(e)
54 }
55}
56
57pub fn find_manifest(mut current: &Path) -> Option<PathBuf> {
58 let file = "Cargo.toml";
59 if current.is_dir() {
60 let manifest = current.join(file);
61 if manifest.exists() {
62 return Some(manifest);
63 }
64 }
65 while let Some(parent) = current.parent() {
66 let manifest = parent.join(file);
67 if manifest.exists() {
68 return Some(manifest);
69 }
70 current = parent;
71 }
72 None
73}
74
75pub fn run(manifest_path: &Path, frozen: bool) -> Result<Metadata, ErrorKind> {
76 let cargo = env::var("CARGO").unwrap_or_else(|_| "cargo".to_owned());
77 let mut cmd = Command::new(cargo);
78 cmd.arg("metadata");
79 cmd.arg("--all-features");
80 cmd.args(&["--format-version", "1"]);
81 cmd.args(&["--color", "never"]);
82 cmd.arg("--manifest-path");
83 cmd.arg(manifest_path.as_os_str());
84 if frozen {
85 cmd.arg("--frozen");
86 }
87 let op = cmd.output()?;
88 if !op.status.success() {
89 let stderr = String::from_utf8(op.stderr).map_err(|e| e.utf8_error())?;
90 return Err(ErrorKind::Subprocess(stderr));
91 }
92 serde_json::from_slice(&op.stdout).map_err(From::from)
93}