From 9b00917add30389ed2245d0d347ce17dac04be4a Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 24 Jan 2017 11:16:13 +0100 Subject: [PATCH] initial commit --- .gitignore | 2 + Cargo.toml | 12 ++++++ src/lib.rs | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 124 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 src/lib.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..a9d37c56 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +target +Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 00000000..bf7d37b8 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "cargo_metadata" +version = "0.1.0" +authors = ["Oliver Schneider "] +repository = "https://github.com/oli-obk/cargo_metadata" +description = "structured access to the output of `cargo metadata`" +license = "MIT" + +[dependencies] +serde = "0.9.0-rc3" +serde_json = "0.9.0-rc2" +serde_derive = "0.9.0-rc3" diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 00000000..bd03fdad --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,110 @@ +#![deny(missing_docs)] +//! Structured access to the output of `cargo metadata` +//! Usually used from within a `cargo-*` executable +//! +//! ```rust +//! let manifest_path_arg = std::env::args().skip(2).find(|val| val.starts_with("--manifest-path=")); +//! let mut metadata = cargo::metadata(manifest_path_arg.as_ref().map(AsRef::as_ref)).unwrap(); +//! ``` + +extern crate serde; +extern crate serde_json; +#[macro_use] extern crate serde_derive; + +use std::collections::HashMap; +use std::process::Command; +use std::str::{from_utf8, Utf8Error}; +use std::io; + +#[derive(Deserialize, Debug)] +/// Starting point for metadata returned by `cargo metadata` +pub struct Metadata { + /// A list of all crates referenced by this crate (and the crate itself) + pub packages: Vec, + resolve: Option<()>, + version: usize, +} + +#[derive(Deserialize, Debug)] +/// A crate +pub struct Package { + /// Name as given in the `Cargo.toml` + pub name: String, + /// Version given in the `Cargo.toml` + pub version: String, + id: String, + source: Option, + /// List of dependencies of this particular package + pub dependencies: Vec, + /// Targets provided by the crate (lib, bin, example, test, ...) + pub targets: Vec, + features: HashMap>, + /// path containing the `Cargo.toml` + pub manifest_path: String, +} + +#[derive(Deserialize, Debug)] +/// A dependency of the main crate +pub struct Dependency { + /// Name as given in the `Cargo.toml` + pub name: String, + source: Option, + /// Whether this is required or optional + pub req: String, + kind: Option, + optional: bool, + uses_default_features: bool, + features: Vec, + target: Option, +} + +#[derive(Deserialize, Debug)] +/// A single target (lib, bin, example, ...) provided by a crate +pub struct Target { + /// Name as given in the `Cargo.toml` or generated from the file name + pub name: String, + /// Kind of target ("bin", "example", "test", "bench", "lib") + pub kind: Vec, + src_path: String, +} + +#[derive(Debug)] +/// Possible errors that can occur during metadata parsing. +pub enum Error { + /// Error during execution of `cargo metadata` + Io(io::Error), + /// Output of `cargo metadata` was not valid utf8 + Utf8(Utf8Error), + /// Deserialization error (structure of json did not match expected structure) + Json(serde_json::Error), +} + +impl From for Error { + fn from(err: io::Error) -> Self { + Error::Io(err) + } +} +impl From for Error { + fn from(err: Utf8Error) -> Self { + Error::Utf8(err) + } +} +impl From for Error { + fn from(err: serde_json::Error) -> Self { + Error::Json(err) + } +} + +/// The main entry point to obtaining metadata +pub fn metadata(manifest_path_arg: Option<&str>) -> Result { + let mut cmd = Command::new("cargo"); + cmd.arg("metadata").arg("--no-deps"); + if let Some(mani) = manifest_path_arg { + cmd.arg(mani); + } + let output = cmd.output()?; + let stdout = from_utf8(&output.stdout)?; + let meta: Metadata = serde_json::from_str(&stdout)?; + assert_eq!(meta.version, 1, "please update your `cargo_metadata` dependency to support the new metadata version"); + Ok(meta) +}