1 | use crate::directory::Directory; |
2 | use crate::error::Error; |
3 | use crate::inherit::InheritEdition; |
4 | use crate::manifest::Edition; |
5 | use serde::de::value::MapAccessDeserializer; |
6 | use serde::de::value::StrDeserializer; |
7 | use serde::de::{self, Deserialize, Deserializer, Visitor}; |
8 | use serde::ser::{Serialize, Serializer}; |
9 | use serde_derive::{Deserialize, Serialize}; |
10 | use serde_json::Value; |
11 | use std::collections::BTreeMap as Map; |
12 | use std::fmt; |
13 | use std::fs; |
14 | use std::path::PathBuf; |
15 | |
16 | pub fn get_manifest(manifest_dir: &Directory) -> Result<Manifest, Error> { |
17 | let cargo_toml_path = manifest_dir.join("Cargo.toml" ); |
18 | let mut manifest = (|| { |
19 | let manifest_str = fs::read_to_string(&cargo_toml_path)?; |
20 | let manifest: Manifest = basic_toml::from_str(&manifest_str)?; |
21 | Ok(manifest) |
22 | })() |
23 | .map_err(|err| Error::GetManifest(cargo_toml_path, Box::new(err)))?; |
24 | |
25 | fix_dependencies(&mut manifest.dependencies, manifest_dir); |
26 | fix_dependencies(&mut manifest.dev_dependencies, manifest_dir); |
27 | for target in manifest.target.values_mut() { |
28 | fix_dependencies(&mut target.dependencies, manifest_dir); |
29 | fix_dependencies(&mut target.dev_dependencies, manifest_dir); |
30 | } |
31 | |
32 | Ok(manifest) |
33 | } |
34 | |
35 | pub fn get_workspace_manifest(manifest_dir: &Directory) -> WorkspaceManifest { |
36 | try_get_workspace_manifest(manifest_dir).unwrap_or_default() |
37 | } |
38 | |
39 | pub fn try_get_workspace_manifest(manifest_dir: &Directory) -> Result<WorkspaceManifest, Error> { |
40 | let cargo_toml_path = manifest_dir.join("Cargo.toml" ); |
41 | let manifest_str = fs::read_to_string(cargo_toml_path)?; |
42 | let mut manifest: WorkspaceManifest = basic_toml::from_str(&manifest_str)?; |
43 | |
44 | fix_dependencies(&mut manifest.workspace.dependencies, manifest_dir); |
45 | fix_patches(&mut manifest.patch, manifest_dir); |
46 | fix_replacements(&mut manifest.replace, manifest_dir); |
47 | |
48 | Ok(manifest) |
49 | } |
50 | |
51 | fn fix_dependencies(dependencies: &mut Map<String, Dependency>, dir: &Directory) { |
52 | dependencies.remove("trybuild" ); |
53 | for dep in dependencies.values_mut() { |
54 | dep.path = dep.path.as_ref().map(|path| Directory::new(dir.join(path))); |
55 | } |
56 | } |
57 | |
58 | fn fix_patches(patches: &mut Map<String, RegistryPatch>, dir: &Directory) { |
59 | for registry in patches.values_mut() { |
60 | registry.crates.remove("trybuild" ); |
61 | for patch in registry.crates.values_mut() { |
62 | patch.path = patch.path.as_ref().map(|path| dir.join(path)); |
63 | } |
64 | } |
65 | } |
66 | |
67 | fn fix_replacements(replacements: &mut Map<String, Patch>, dir: &Directory) { |
68 | replacements.remove("trybuild" ); |
69 | for replacement in replacements.values_mut() { |
70 | replacement.path = replacement.path.as_ref().map(|path| dir.join(path)); |
71 | } |
72 | } |
73 | |
74 | #[derive(Deserialize, Default, Debug)] |
75 | pub struct WorkspaceManifest { |
76 | #[serde(default)] |
77 | pub workspace: WorkspaceWorkspace, |
78 | #[serde(default)] |
79 | pub patch: Map<String, RegistryPatch>, |
80 | #[serde(default)] |
81 | pub replace: Map<String, Patch>, |
82 | } |
83 | |
84 | #[derive(Deserialize, Default, Debug)] |
85 | pub struct WorkspaceWorkspace { |
86 | #[serde(default)] |
87 | pub package: WorkspacePackage, |
88 | #[serde(default)] |
89 | pub dependencies: Map<String, Dependency>, |
90 | } |
91 | |
92 | #[derive(Deserialize, Default, Debug)] |
93 | pub struct WorkspacePackage { |
94 | pub edition: Option<Edition>, |
95 | } |
96 | |
97 | #[derive(Deserialize, Default, Debug)] |
98 | pub struct Manifest { |
99 | #[serde(default)] |
100 | pub package: Package, |
101 | #[serde(default)] |
102 | pub features: Map<String, Vec<String>>, |
103 | #[serde(default)] |
104 | pub dependencies: Map<String, Dependency>, |
105 | #[serde(default, alias = "dev-dependencies" )] |
106 | pub dev_dependencies: Map<String, Dependency>, |
107 | #[serde(default)] |
108 | pub target: Map<String, TargetDependencies>, |
109 | } |
110 | |
111 | #[derive(Deserialize, Default, Debug)] |
112 | pub struct Package { |
113 | pub name: String, |
114 | #[serde(default)] |
115 | pub edition: EditionOrInherit, |
116 | pub resolver: Option<String>, |
117 | } |
118 | |
119 | #[derive(Debug)] |
120 | pub enum EditionOrInherit { |
121 | Edition(Edition), |
122 | Inherit, |
123 | } |
124 | |
125 | #[derive(Serialize, Deserialize, Clone, Debug)] |
126 | #[serde(remote = "Self" )] |
127 | pub struct Dependency { |
128 | #[serde(skip_serializing_if = "Option::is_none" )] |
129 | pub version: Option<String>, |
130 | #[serde(skip_serializing_if = "Option::is_none" )] |
131 | pub path: Option<Directory>, |
132 | #[serde(default, skip_serializing_if = "is_false" )] |
133 | pub optional: bool, |
134 | #[serde( |
135 | rename = "default-features" , |
136 | default = "get_true" , |
137 | skip_serializing_if = "is_true" |
138 | )] |
139 | pub default_features: bool, |
140 | #[serde(default, skip_serializing_if = "Vec::is_empty" )] |
141 | pub features: Vec<String>, |
142 | #[serde(skip_serializing_if = "Option::is_none" )] |
143 | pub git: Option<String>, |
144 | #[serde(skip_serializing_if = "Option::is_none" )] |
145 | pub branch: Option<String>, |
146 | #[serde(skip_serializing_if = "Option::is_none" )] |
147 | pub tag: Option<String>, |
148 | #[serde(skip_serializing_if = "Option::is_none" )] |
149 | pub rev: Option<String>, |
150 | #[serde(default, skip_serializing_if = "is_false" )] |
151 | pub workspace: bool, |
152 | #[serde(flatten)] |
153 | pub rest: Map<String, Value>, |
154 | } |
155 | |
156 | #[derive(Serialize, Deserialize, Clone, Debug)] |
157 | pub struct TargetDependencies { |
158 | #[serde(default, skip_serializing_if = "Map::is_empty" )] |
159 | pub dependencies: Map<String, Dependency>, |
160 | #[serde( |
161 | default, |
162 | alias = "dev-dependencies" , |
163 | skip_serializing_if = "Map::is_empty" |
164 | )] |
165 | pub dev_dependencies: Map<String, Dependency>, |
166 | } |
167 | |
168 | #[derive(Serialize, Deserialize, Clone, Debug)] |
169 | #[serde(transparent)] |
170 | pub struct RegistryPatch { |
171 | pub crates: Map<String, Patch>, |
172 | } |
173 | |
174 | #[derive(Serialize, Deserialize, Clone, Debug)] |
175 | pub struct Patch { |
176 | #[serde(skip_serializing_if = "Option::is_none" )] |
177 | pub path: Option<PathBuf>, |
178 | #[serde(skip_serializing_if = "Option::is_none" )] |
179 | pub git: Option<String>, |
180 | #[serde(skip_serializing_if = "Option::is_none" )] |
181 | pub branch: Option<String>, |
182 | #[serde(skip_serializing_if = "Option::is_none" )] |
183 | pub tag: Option<String>, |
184 | #[serde(skip_serializing_if = "Option::is_none" )] |
185 | pub rev: Option<String>, |
186 | #[serde(flatten)] |
187 | pub rest: Map<String, Value>, |
188 | } |
189 | |
190 | fn get_true() -> bool { |
191 | true |
192 | } |
193 | |
194 | fn is_true(boolean: &bool) -> bool { |
195 | *boolean |
196 | } |
197 | |
198 | fn is_false(boolean: &bool) -> bool { |
199 | !*boolean |
200 | } |
201 | |
202 | impl Default for EditionOrInherit { |
203 | fn default() -> Self { |
204 | EditionOrInherit::Edition(Edition::default()) |
205 | } |
206 | } |
207 | |
208 | impl<'de> Deserialize<'de> for EditionOrInherit { |
209 | fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> |
210 | where |
211 | D: Deserializer<'de>, |
212 | { |
213 | struct EditionOrInheritVisitor; |
214 | |
215 | impl<'de> Visitor<'de> for EditionOrInheritVisitor { |
216 | type Value = EditionOrInherit; |
217 | |
218 | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { |
219 | formatter.write_str("edition" ) |
220 | } |
221 | |
222 | fn visit_str<E>(self, s: &str) -> Result<Self::Value, E> |
223 | where |
224 | E: de::Error, |
225 | { |
226 | Edition::deserialize(StrDeserializer::new(s)).map(EditionOrInherit::Edition) |
227 | } |
228 | |
229 | fn visit_map<M>(self, map: M) -> Result<Self::Value, M::Error> |
230 | where |
231 | M: de::MapAccess<'de>, |
232 | { |
233 | InheritEdition::deserialize(MapAccessDeserializer::new(map))?; |
234 | Ok(EditionOrInherit::Inherit) |
235 | } |
236 | } |
237 | |
238 | deserializer.deserialize_any(EditionOrInheritVisitor) |
239 | } |
240 | } |
241 | |
242 | impl Serialize for Dependency { |
243 | fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> |
244 | where |
245 | S: Serializer, |
246 | { |
247 | Dependency::serialize(self, serializer) |
248 | } |
249 | } |
250 | |
251 | impl<'de> Deserialize<'de> for Dependency { |
252 | fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> |
253 | where |
254 | D: Deserializer<'de>, |
255 | { |
256 | struct DependencyVisitor; |
257 | |
258 | impl<'de> Visitor<'de> for DependencyVisitor { |
259 | type Value = Dependency; |
260 | |
261 | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { |
262 | formatter.write_str( |
263 | "a version string like \"0.9.8 \" or a \ |
264 | dependency like { version = \"0.9.8 \" }" , |
265 | ) |
266 | } |
267 | |
268 | fn visit_str<E>(self, s: &str) -> Result<Self::Value, E> |
269 | where |
270 | E: de::Error, |
271 | { |
272 | Ok(Dependency { |
273 | version: Some(s.to_owned()), |
274 | path: None, |
275 | optional: false, |
276 | default_features: true, |
277 | features: Vec::new(), |
278 | git: None, |
279 | branch: None, |
280 | tag: None, |
281 | rev: None, |
282 | workspace: false, |
283 | rest: Map::new(), |
284 | }) |
285 | } |
286 | |
287 | fn visit_map<M>(self, map: M) -> Result<Self::Value, M::Error> |
288 | where |
289 | M: de::MapAccess<'de>, |
290 | { |
291 | Dependency::deserialize(MapAccessDeserializer::new(map)) |
292 | } |
293 | } |
294 | |
295 | deserializer.deserialize_any(DependencyVisitor) |
296 | } |
297 | } |
298 | |