#![cfg(not(doctest))]
use std::env;
use std::path::{Path, PathBuf};
use std::io::{Error as IoError, ErrorKind as IoErrorKind};
use std::process::Command;
pub use model::*;
mod model;
type Error = Box<dyn std::error::Error>;
type Result<T = (), E = self::Error> = std::result::Result<T, E>;
const CARGO_MANIFEST: &str = "Cargo.toml";
const CARGO_MANIFEST_DIR: &str = "CARGO_MANIFEST_DIR";
const CARGO_PKG_NAME: &str = "CARGO_PKG_NAME";
pub fn crate_metadata<Metadata>() -> Result<CargoMetadata<Metadata>>
where for<'de> Metadata: serde::de::Deserialize<'de> {
let path =
PathBuf::from(env::var_os(CARGO_MANIFEST_DIR).ok_or(IoError::new(IoErrorKind::NotFound, CARGO_MANIFEST_DIR))?).join(CARGO_MANIFEST);
let name = env::var(CARGO_PKG_NAME).unwrap();
crate_metadata_for(path, &name)
}
pub fn cargo_metadata<Metadata>() -> Result<CargoMetadata<Metadata>>
where for<'de> Metadata: serde::de::Deserialize<'de> {
let path =
PathBuf::from(env::var_os(CARGO_MANIFEST_DIR).ok_or(IoError::new(IoErrorKind::NotFound, CARGO_MANIFEST_DIR))?).join(CARGO_MANIFEST);
cargo_metadata_for(path)
}
pub fn crate_metadata_for<Metadata, P: AsRef<Path>>(manifest: P, name: &str) -> Result<CargoMetadata<Metadata>>
where for<'de> Metadata: serde::de::Deserialize<'de> {
let mut metadata: CargoMetadata<Metadata> = cargo_metadata_for(&manifest)?;
metadata.packages = metadata.packages.into_iter().filter(|p| p.name == name).collect();
Ok(metadata)
}
pub fn cargo_metadata_for<Metadata, P: AsRef<Path>>(manifest: P) -> Result<CargoMetadata<Metadata>>
where for<'de> Metadata: serde::de::Deserialize<'de> {
let manifest_path_str = manifest.as_ref()
.to_str()
.ok_or(IoError::new(IoErrorKind::InvalidInput, CARGO_MANIFEST))?;
let args = [
"metadata",
"--offline",
"--locked",
"--frozen",
"--no-deps",
"--format-version=1",
"--manifest-path",
manifest_path_str,
];
let cargo = env::var("CARGO").ok().unwrap_or("cargo".to_string());
let metadata_json_raw = Command::new(cargo).args(&args).output()?;
let stdout = std::str::from_utf8(&metadata_json_raw.stdout)?;
serde_json::from_str(stdout).map_err(Into::into)
}