| 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 | |