]> git.proxmox.com Git - rustc.git/blame - src/vendor/cargo_metadata/src/lib.rs
New upstream version 1.23.0+dfsg1
[rustc.git] / src / vendor / cargo_metadata / src / lib.rs
CommitLineData
abe05a73
XL
1#![deny(missing_docs)]
2//! Structured access to the output of `cargo metadata`
3//! Usually used from within a `cargo-*` executable
4//!
5//! ```rust
6//! # extern crate cargo_metadata;
7//! let manifest_path_arg = std::env::args().skip(2).find(|val| val.starts_with("--manifest-path="));
8//! let metadata = cargo_metadata::metadata(manifest_path_arg.as_ref().map(AsRef::as_ref)).unwrap();
9//! ```
10
11extern crate serde;
12extern crate serde_json;
13#[macro_use] extern crate serde_derive;
14
15use std::collections::HashMap;
16use std::env;
17use std::process::Command;
18use std::str::{from_utf8, Utf8Error};
19use std::io;
20
21#[derive(Clone, Deserialize, Debug)]
22/// Starting point for metadata returned by `cargo metadata`
23pub struct Metadata {
24 /// A list of all crates referenced by this crate (and the crate itself)
25 pub packages: Vec<Package>,
26 /// A list of all workspace members
27 #[serde(default)]
28 pub workspace_members: Vec<String>,
29 /// Dependencies graph
30 pub resolve: Option<Resolve>,
31 version: usize,
32}
33
34#[derive(Clone, Deserialize, Debug)]
35/// A dependency graph
36pub struct Resolve {
37 /// Nodes in a dependencies graph
38 pub nodes: Vec<Node>,
39}
40
41#[derive(Clone, Deserialize, Debug)]
42/// A node in a dependencies graph
43pub struct Node {
44 /// An opaque identifier for a package
45 pub id: String,
46 /// List of opaque identifiers for this node's dependencies
47 pub dependencies: Vec<String>,
48}
49
50#[derive(Clone, Deserialize, Debug)]
51/// A crate
52pub struct Package {
53 /// Name as given in the `Cargo.toml`
54 pub name: String,
55 /// Version given in the `Cargo.toml`
56 pub version: String,
57 /// An opaque identifier for a package
58 pub id: String,
59 source: Option<String>,
60 /// List of dependencies of this particular package
61 pub dependencies: Vec<Dependency>,
62 /// Targets provided by the crate (lib, bin, example, test, ...)
63 pub targets: Vec<Target>,
64 features: HashMap<String, Vec<String>>,
65 /// Path containing the `Cargo.toml`
66 pub manifest_path: String,
67}
68
69#[derive(Clone, Deserialize, Debug)]
70/// A dependency of the main crate
71pub struct Dependency {
72 /// Name as given in the `Cargo.toml`
73 pub name: String,
74 source: Option<String>,
75 /// Whether this is required or optional
76 pub req: String,
77 kind: Option<String>,
78 optional: bool,
79 uses_default_features: bool,
80 features: Vec<String>,
81 target: Option<String>,
82}
83
84#[derive(Clone, Deserialize, Debug)]
85/// A single target (lib, bin, example, ...) provided by a crate
86pub struct Target {
87 /// Name as given in the `Cargo.toml` or generated from the file name
88 pub name: String,
89 /// Kind of target ("bin", "example", "test", "bench", "lib")
90 pub kind: Vec<String>,
91 /// Almost the same as `kind`, except when an example is a library instad of an executable.
92 /// In that case `crate_types` contains things like `rlib` and `dylib` while `kind` is `example`
93 #[serde(default)]
94 pub crate_types: Vec<String>,
95 /// Path to the main source file of the target
96 pub src_path: String,
97}
98
99#[derive(Debug)]
100/// Possible errors that can occur during metadata parsing.
101pub enum Error {
102 /// Error during execution of `cargo metadata`
103 Io(io::Error),
104 /// Output of `cargo metadata` was not valid utf8
105 Utf8(Utf8Error),
106 /// Deserialization error (structure of json did not match expected structure)
107 Json(serde_json::Error),
108}
109
110impl From<io::Error> for Error {
111 fn from(err: io::Error) -> Self {
112 Error::Io(err)
113 }
114}
115impl From<Utf8Error> for Error {
116 fn from(err: Utf8Error) -> Self {
117 Error::Utf8(err)
118 }
119}
120impl From<serde_json::Error> for Error {
121 fn from(err: serde_json::Error) -> Self {
122 Error::Json(err)
123 }
124}
125
126/// Obtain metadata only about the root package and don't fetch dependencies
127///
128/// # Parameters
129///
130/// - `manifest_path_arg`: Path to the manifest.
131pub fn metadata(manifest_path_arg: Option<&str>) -> Result<Metadata, Error> {
132 metadata_deps(manifest_path_arg, false)
133}
134
135/// The main entry point to obtaining metadata
136///
137/// # Parameters
138///
139/// - `manifest_path_arg`: Path to the manifest.
140/// - `deps`: Whether to include dependencies.
141pub fn metadata_deps(manifest_path_arg: Option<&str>, deps: bool) -> Result<Metadata, Error> {
142 let cargo = env::var("CARGO").unwrap_or_else(|_| String::from("cargo"));
143 let mut cmd = Command::new(cargo);
144 cmd.arg("metadata");
145
146 if !deps {
147 cmd.arg("--no-deps");
148 }
149
150 cmd.arg("--format-version").arg("1");
151 if let Some(mani) = manifest_path_arg {
152 cmd.arg(mani);
153 }
154 let output = cmd.output()?;
155 let stdout = from_utf8(&output.stdout)?;
156 let meta: Metadata = serde_json::from_str(stdout)?;
157 Ok(meta)
158}