Skip to content

Commit a312c55

Browse files
committed
Expand dependency info of cargo --metadata
The old `dependencies` key in `resolve` is deprecated. Instead, the new `deps` key introduced which lists dependencies kinds (dev/build/normal) as well as `extern crate` name for the dep.
1 parent 42f7462 commit a312c55

File tree

2 files changed

+304
-34
lines changed

2 files changed

+304
-34
lines changed

src/cargo/ops/cargo_output_metadata.rs

+81-32
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
use serde::ser::{self, Serialize};
2-
31
use core::resolver::Resolve;
4-
use core::{Package, PackageId, Workspace};
2+
use core::{Package, PackageId, PackageSet, Workspace};
3+
use core::dependency;
54
use ops::{self, Packages};
65
use util::CargoResult;
76

@@ -56,18 +55,19 @@ fn metadata_full(ws: &Workspace, opt: &OutputMetadataOptions) -> CargoResult<Exp
5655
)?;
5756
let (packages, resolve) = deps;
5857

58+
let resolve = MetadataResolve::new(
59+
&packages,
60+
&resolve,
61+
ws.current_opt().map(|pkg| pkg.package_id().clone()),
62+
);
5963
let packages = packages
6064
.package_ids()
6165
.map(|i| packages.get(i).map(|p| p.clone()))
6266
.collect::<CargoResult<Vec<_>>>()?;
63-
6467
Ok(ExportInfo {
6568
packages,
6669
workspace_members: ws.members().map(|pkg| pkg.package_id().clone()).collect(),
67-
resolve: Some(MetadataResolve {
68-
resolve,
69-
root: ws.current_opt().map(|pkg| pkg.package_id().clone()),
70-
}),
70+
resolve: Some(resolve),
7171
target_directory: ws.target_dir().display().to_string(),
7272
version: VERSION,
7373
workspace_root: ws.root().display().to_string(),
@@ -76,42 +76,91 @@ fn metadata_full(ws: &Workspace, opt: &OutputMetadataOptions) -> CargoResult<Exp
7676

7777
#[derive(Serialize)]
7878
pub struct ExportInfo {
79+
/// All packages for this project, with dependencies.
7980
packages: Vec<Package>,
81+
/// Packages which are direct members of the current project.
8082
workspace_members: Vec<PackageId>,
83+
/// A graph of the dependencies between packages.
8184
resolve: Option<MetadataResolve>,
85+
/// The directory where intermediate build artifacts will be stored.
8286
target_directory: String,
87+
/// Version of this JSON format
8388
version: u32,
89+
/// Path to the directory with the project.
8490
workspace_root: String,
8591
}
8692

87-
/// Newtype wrapper to provide a custom `Serialize` implementation.
88-
/// The one from lockfile does not fit because it uses a non-standard
89-
/// format for `PackageId`s
93+
// The serialization format is different from lockfile, because
94+
// here we use different format for `PackageId`s, and give more
95+
// information about dependencies.
9096
#[derive(Serialize)]
9197
struct MetadataResolve {
92-
#[serde(rename = "nodes", serialize_with = "serialize_resolve")]
93-
resolve: Resolve,
98+
/// Dependencies for each package from `ExportInfo::package`.
99+
nodes: Vec<Node>,
100+
/// Deprecated, use `ExportInfo::workspace_members`.
94101
root: Option<PackageId>,
95102
}
96103

97-
fn serialize_resolve<S>(resolve: &Resolve, s: S) -> Result<S::Ok, S::Error>
98-
where
99-
S: ser::Serializer,
100-
{
101-
#[derive(Serialize)]
102-
struct Node<'a> {
103-
id: &'a PackageId,
104-
dependencies: Vec<&'a PackageId>,
105-
features: Vec<&'a str>,
106-
}
104+
/// Describes dependencies of a single package.
105+
#[derive(Serialize)]
106+
struct Node {
107+
/// The id of the package.
108+
id: PackageId,
109+
/// Deprecated, use `deps` field.
110+
dependencies: Vec<PackageId>,
111+
/// Dependencies of this package.
112+
deps: Vec<Dependency>,
113+
/// Features, enabled for this package.
114+
features: Vec<String>,
115+
}
107116

108-
resolve
109-
.iter()
110-
.map(|id| Node {
111-
id,
112-
dependencies: resolve.deps(id).map(|p| p.0).collect(),
113-
features: resolve.features_sorted(id),
114-
})
115-
.collect::<Vec<_>>()
116-
.serialize(s)
117+
/// Describes a single dependency.
118+
#[derive(Serialize)]
119+
struct Dependency {
120+
/// The id of the dependency.
121+
id: PackageId,
122+
/// The name used for `extern crate` declaration of this dependency.
123+
name: String,
124+
/// Is this normal, dev or build dependency
125+
kind: dependency::Kind,
126+
}
127+
128+
impl MetadataResolve {
129+
pub fn new(
130+
packages: &PackageSet,
131+
resolve: &Resolve,
132+
root: Option<PackageId>,
133+
) -> MetadataResolve {
134+
let nodes = resolve
135+
.iter()
136+
.map(|pkg| {
137+
Node {
138+
id: pkg.clone(),
139+
dependencies: resolve.deps(pkg).map(|(dep, _)| dep.clone()).collect(),
140+
deps: resolve
141+
.deps(pkg)
142+
.flat_map(|(id, deps)| {
143+
let dep_name = packages.get(id).unwrap()
144+
.lib_target().unwrap()
145+
.crate_name();
146+
deps.iter().map(|dep| {
147+
Dependency {
148+
id: id.clone(),
149+
name: dep.rename().unwrap_or(&dep_name)
150+
.to_owned(),
151+
kind: dep.kind(),
152+
}
153+
}).collect::<Vec<_>>().into_iter()
154+
})
155+
.collect(),
156+
features: resolve
157+
.features_sorted(pkg)
158+
.into_iter()
159+
.map(|s| s.to_string())
160+
.collect(),
161+
}
162+
})
163+
.collect();
164+
MetadataResolve { nodes, root }
165+
}
117166
}

0 commit comments

Comments
 (0)