1#![cfg(not(doctest))]
2use std::env;
10use std::path::{Path, PathBuf};
11use std::io::{Error as IoError, ErrorKind as IoErrorKind};
12use std::process::Command;
13
14pub use model::*;
15mod model;
16
17type Error = Box<dyn std::error::Error>;
18type Result<T = (), E = self::Error> = std::result::Result<T, E>;
19
20const CARGO_MANIFEST: &str = "Cargo.toml";
21const CARGO_MANIFEST_DIR: &str = "CARGO_MANIFEST_DIR";
22const CARGO_PKG_NAME: &str = "CARGO_PKG_NAME";
23
24
25pub fn crate_metadata<Metadata>() -> Result<CargoMetadata<Metadata>>
29 where for<'de> Metadata: serde::de::Deserialize<'de> {
30 let path =
31 PathBuf::from(env::var_os(CARGO_MANIFEST_DIR).ok_or(IoError::new(IoErrorKind::NotFound, CARGO_MANIFEST_DIR))?).join(CARGO_MANIFEST);
32 let name = env::var(CARGO_PKG_NAME).unwrap();
33 crate_metadata_for(path, &name)
34}
35
36pub fn cargo_metadata<Metadata>() -> Result<CargoMetadata<Metadata>>
39 where for<'de> Metadata: serde::de::Deserialize<'de> {
40 let path =
41 PathBuf::from(env::var_os(CARGO_MANIFEST_DIR).ok_or(IoError::new(IoErrorKind::NotFound, CARGO_MANIFEST_DIR))?).join(CARGO_MANIFEST);
42 cargo_metadata_for(path)
43}
44
45
46pub fn crate_metadata_for<Metadata, P: AsRef<Path>>(manifest: P, name: &str) -> Result<CargoMetadata<Metadata>>
56 where for<'de> Metadata: serde::de::Deserialize<'de> {
57 let mut metadata: CargoMetadata<Metadata> = cargo_metadata_for(&manifest)?;
58 metadata.packages = metadata.packages.into_iter().filter(|p| p.name == name).collect();
59
60 Ok(metadata)
61}
62
63
64pub fn cargo_metadata_for<Metadata, P: AsRef<Path>>(manifest: P) -> Result<CargoMetadata<Metadata>>
71 where for<'de> Metadata: serde::de::Deserialize<'de> {
72 let manifest_path_str = manifest.as_ref()
73 .to_str()
74 .ok_or(IoError::new(IoErrorKind::InvalidInput, CARGO_MANIFEST))?;
75 let args = [
76 "metadata",
77 "--offline",
78 "--locked",
79 "--frozen",
80 "--no-deps",
81 "--format-version=1",
82 "--manifest-path",
83 manifest_path_str,
84 ];
85
86 let cargo = env::var("CARGO").ok().unwrap_or("cargo".to_string());
87 let metadata_json_raw = Command::new(cargo).args(&args).output()?;
88 let stdout = std::str::from_utf8(&metadata_json_raw.stdout)?;
89
90 serde_json::from_str(stdout).map_err(Into::into)
91}