racer_cargo_metadata/
lib.rs

1extern 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}