Skip to content

Commit 5233dbe

Browse files
committed
feat(cargo-util-schemas): Create NormalizedResolve
1 parent eabb4cd commit 5233dbe

File tree

7 files changed

+286
-3
lines changed

7 files changed

+286
-3
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/cargo-util-schemas/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ serde-value.workspace = true
1818
thiserror.workspace = true
1919
toml = { workspace = true, features = ["serde"] }
2020
unicode-xid.workspace = true
21-
url.workspace = true
21+
url = { workspace = true, features = ["serde"] }
2222

2323
[lints]
2424
workspace = true
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
{
2+
"$schema": "https://json-schema.org/draft/2020-12/schema",
3+
"title": "NormalizedResolve",
4+
"type": "object",
5+
"properties": {
6+
"version": {
7+
"type": [
8+
"integer",
9+
"null"
10+
],
11+
"format": "uint32",
12+
"minimum": 0
13+
},
14+
"package": {
15+
"type": [
16+
"array",
17+
"null"
18+
],
19+
"items": {
20+
"$ref": "#/$defs/NormalizedDependency"
21+
}
22+
},
23+
"root": {
24+
"anyOf": [
25+
{
26+
"$ref": "#/$defs/NormalizedDependency"
27+
},
28+
{
29+
"type": "null"
30+
}
31+
]
32+
},
33+
"metadata": {
34+
"type": [
35+
"object",
36+
"null"
37+
],
38+
"additionalProperties": {
39+
"type": "string"
40+
}
41+
},
42+
"patch": {
43+
"$ref": "#/$defs/Patch"
44+
}
45+
},
46+
"$defs": {
47+
"NormalizedDependency": {
48+
"type": "object",
49+
"properties": {
50+
"spec": {
51+
"$ref": "#/$defs/PackageIdSpec"
52+
},
53+
"checksum": {
54+
"type": [
55+
"string",
56+
"null"
57+
]
58+
},
59+
"dependencies": {
60+
"type": [
61+
"array",
62+
"null"
63+
],
64+
"items": {
65+
"$ref": "#/$defs/NormalizedPackageId"
66+
}
67+
},
68+
"replace": {
69+
"anyOf": [
70+
{
71+
"$ref": "#/$defs/NormalizedPackageId"
72+
},
73+
{
74+
"type": "null"
75+
}
76+
]
77+
}
78+
},
79+
"required": [
80+
"spec"
81+
]
82+
},
83+
"PackageIdSpec": {
84+
"type": "string"
85+
},
86+
"NormalizedPackageId": {
87+
"type": "object",
88+
"properties": {
89+
"name": {
90+
"type": "string"
91+
},
92+
"version": {
93+
"type": [
94+
"string",
95+
"null"
96+
]
97+
},
98+
"source": {
99+
"anyOf": [
100+
{
101+
"$ref": "#/$defs/NormalizedSourceId"
102+
},
103+
{
104+
"type": "null"
105+
}
106+
]
107+
}
108+
},
109+
"required": [
110+
"name"
111+
]
112+
},
113+
"NormalizedSourceId": {
114+
"type": "object"
115+
},
116+
"Patch": {
117+
"type": "object",
118+
"properties": {
119+
"unused": {
120+
"type": "array",
121+
"items": {
122+
"$ref": "#/$defs/NormalizedDependency"
123+
}
124+
}
125+
},
126+
"required": [
127+
"unused"
128+
]
129+
}
130+
}
131+
}

crates/cargo-util-schemas/src/core/source_kind.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
use std::cmp::Ordering;
22

3+
use serde::{Deserialize, Serialize};
4+
35
/// The possible kinds of code source.
4-
#[derive(Debug, Clone, PartialEq, Eq)]
6+
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
7+
#[cfg_attr(feature = "unstable-schema", derive(schemars::JsonSchema))]
58
pub enum SourceKind {
69
/// A git repository.
710
Git(GitReference),
@@ -83,7 +86,8 @@ impl PartialOrd for SourceKind {
8386
}
8487

8588
/// Information to find a specific commit in a Git repository.
86-
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
89+
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
90+
#[cfg_attr(feature = "unstable-schema", derive(schemars::JsonSchema))]
8791
pub enum GitReference {
8892
/// From a tag.
8993
Tag(String),

crates/cargo-util-schemas/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
//! > ecosystem. This crate follows semver compatibility for its APIs.
1010
1111
pub mod core;
12+
pub mod resolve;
1213
pub mod manifest;
1314
pub mod messages;
1415
#[cfg(feature = "unstable-schema")]
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
//! `Cargo.lock` / Lock file schema definition
2+
3+
use std::collections::BTreeMap;
4+
5+
use serde::{Deserialize, Serialize};
6+
use url::Url;
7+
8+
use crate::core::{PackageIdSpec, SourceKind};
9+
10+
#[derive(Serialize, Deserialize, Debug)]
11+
#[serde(rename_all = "kebab-case")]
12+
#[cfg_attr(feature = "unstable-schema", derive(schemars::JsonSchema))]
13+
pub struct NormalizedResolve {
14+
#[serde(skip_serializing_if = "Option::is_none")]
15+
pub version: Option<u32>,
16+
#[serde(skip_serializing_if = "Option::is_none")]
17+
pub package: Option<Vec<NormalizedDependency>>,
18+
#[serde(skip_serializing_if = "Option::is_none")]
19+
pub root: Option<NormalizedDependency>,
20+
#[serde(skip_serializing_if = "Option::is_none")]
21+
pub metadata: Option<Metadata>,
22+
#[serde(default, skip_serializing_if = "NormalizedPatch::is_empty")]
23+
pub patch: NormalizedPatch,
24+
}
25+
26+
pub type Metadata = BTreeMap<String, String>;
27+
28+
#[derive(Serialize, Deserialize, Debug, Default)]
29+
#[serde(rename_all = "kebab-case")]
30+
#[cfg_attr(feature = "unstable-schema", derive(schemars::JsonSchema))]
31+
pub struct NormalizedPatch {
32+
pub unused: Vec<NormalizedDependency>,
33+
}
34+
35+
impl NormalizedPatch {
36+
fn is_empty(&self) -> bool {
37+
self.unused.is_empty()
38+
}
39+
}
40+
41+
#[derive(Serialize, Deserialize, Debug)]
42+
#[serde(rename_all = "kebab-case")]
43+
#[cfg_attr(feature = "unstable-schema", derive(schemars::JsonSchema))]
44+
pub struct NormalizedDependency {
45+
pub id: PackageIdSpec,
46+
#[serde(skip_serializing_if = "Option::is_none")]
47+
pub checksum: Option<String>,
48+
#[serde(skip_serializing_if = "Option::is_none")]
49+
pub dependencies: Option<Vec<NormalizedPackageId>>,
50+
#[serde(skip_serializing_if = "Option::is_none")]
51+
pub replace: Option<NormalizedPackageId>,
52+
}
53+
54+
#[derive(Serialize, Deserialize, Debug)]
55+
#[serde(rename_all = "kebab-case")]
56+
#[cfg_attr(feature = "unstable-schema", derive(schemars::JsonSchema))]
57+
pub struct NormalizedPackageId {
58+
pub name: String,
59+
#[serde(skip_serializing_if = "Option::is_none")]
60+
pub version: Option<String>,
61+
#[serde(skip_serializing_if = "Option::is_none")]
62+
pub source: Option<NormalizedSourceId>,
63+
}
64+
65+
#[derive(Serialize, Deserialize, Debug)]
66+
#[serde(rename_all = "kebab-case")]
67+
#[cfg_attr(feature = "unstable-schema", derive(schemars::JsonSchema))]
68+
pub struct NormalizedSourceId {
69+
#[cfg_attr(feature = "unstable-schema", schemars(with = "String"))]
70+
pub url: Url,
71+
pub kind: SourceKind,
72+
}
73+
74+
#[cfg(feature = "unstable-schema")]
75+
#[test]
76+
fn dump_resolve_schema() {
77+
let schema = schemars::schema_for!(crate::resolve::NormalizedResolve);
78+
let dump = serde_json::to_string_pretty(&schema).unwrap();
79+
snapbox::assert_data_eq!(dump, snapbox::file!("../resolve.schema.json").raw());
80+
}

src/cargo/core/resolver/encode.rs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,8 @@ use crate::util::errors::CargoResult;
117117
use crate::util::interning::InternedString;
118118
use crate::util::{Graph, internal};
119119
use anyhow::{Context as _, bail};
120+
use cargo_util_schemas::core::PackageIdSpec;
121+
use cargo_util_schemas::resolve::{NormalizedDependency, NormalizedPackageId, NormalizedPatch, NormalizedResolve, NormalizedSourceId};
120122
use serde::de;
121123
use serde::ser;
122124
use serde::{Deserialize, Serialize};
@@ -142,6 +144,14 @@ struct Patch {
142144
unused: Vec<EncodableDependency>,
143145
}
144146

147+
impl Patch {
148+
pub fn into_normalized(self) -> NormalizedPatch {
149+
NormalizedPatch {
150+
unused: self.unused.into_iter().map(|d| d.into_normalized()).collect()
151+
}
152+
}
153+
}
154+
145155
pub type Metadata = BTreeMap<String, String>;
146156

147157
impl EncodableResolve {
@@ -436,6 +446,24 @@ impl EncodableResolve {
436446
})
437447
}
438448
}
449+
450+
pub fn into_normalized(self) -> NormalizedResolve {
451+
let root = self.root.map(|r| r.into_normalized());
452+
453+
let package = self.package.map(|ps| {
454+
ps.into_iter().map(|p| p.into_normalized()).collect()
455+
});
456+
457+
let patch = self.patch.into_normalized();
458+
459+
NormalizedResolve {
460+
root,
461+
version: self.version,
462+
metadata: self.metadata,
463+
package,
464+
patch,
465+
}
466+
}
439467
}
440468

441469
fn build_path_deps(
@@ -528,6 +556,27 @@ pub struct EncodableDependency {
528556
replace: Option<EncodablePackageId>,
529557
}
530558

559+
impl EncodableDependency {
560+
pub fn into_normalized(self) -> NormalizedDependency {
561+
let mut spec = PackageIdSpec::new(self.name)
562+
.with_version(self.version.parse().unwrap());
563+
564+
if let Some(source) = self.source.clone() {
565+
spec.set_url(source.url().clone());
566+
spec.set_kind(source.kind().clone());
567+
}
568+
569+
NormalizedDependency {
570+
id: spec,
571+
replace: self.replace.map(|r| r.into_normalized()),
572+
checksum: self.checksum,
573+
dependencies: self.dependencies.map(|deps| {
574+
deps.into_iter().map(|dep| dep.into_normalized()).collect()
575+
}),
576+
}
577+
}
578+
}
579+
531580
/// Pretty much equivalent to [`SourceId`] with a different serialization method.
532581
///
533582
/// The serialization for `SourceId` doesn't do URL encode for parameters.
@@ -571,6 +620,13 @@ impl EncodableSourceId {
571620
self.inner.as_url()
572621
}
573622
}
623+
624+
pub fn into_normalized(self) -> NormalizedSourceId {
625+
NormalizedSourceId {
626+
url: self.url().clone(),
627+
kind: self.kind().clone(),
628+
}
629+
}
574630
}
575631

576632
impl std::ops::Deref for EncodableSourceId {
@@ -611,6 +667,16 @@ pub struct EncodablePackageId {
611667
source: Option<EncodableSourceId>,
612668
}
613669

670+
impl EncodablePackageId {
671+
pub fn into_normalized(self) -> NormalizedPackageId {
672+
NormalizedPackageId {
673+
name: self.name,
674+
version: self.version,
675+
source: self.source.map(|s| s.into_normalized()),
676+
}
677+
}
678+
}
679+
614680
impl fmt::Display for EncodablePackageId {
615681
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
616682
write!(f, "{}", self.name)?;

0 commit comments

Comments
 (0)