melodium_repository/
utils.rs1use crate::global::{Author, Package as PackageDetails, Tag, Type as TypeDetails};
2use crate::technical::{Package, Type};
3use cargo_metadata::{CargoOpt, DependencyKind, MetadataCommand};
4use core::fmt::Display;
5use melodium_common::descriptor::PackageRequirement;
6use std::path::PathBuf;
7
8#[derive(Debug)]
9pub enum Error {
10 Melodium(String),
11 Metadata(cargo_metadata::Error),
12}
13
14impl Display for Error {
15 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
16 match self {
17 Error::Melodium(str) => write!(f, "{str}"),
18 Error::Metadata(err) => write!(f, "{err}"),
19 }
20 }
21}
22
23impl std::error::Error for Error {}
24
25impl From<cargo_metadata::Error> for Error {
26 fn from(value: cargo_metadata::Error) -> Self {
27 Error::Metadata(value)
28 }
29}
30
31pub fn cargo_toml(
32 package: &str,
33 path: impl Into<PathBuf>,
34) -> Result<(Package, PackageDetails), Error> {
35 let metadata = MetadataCommand::new()
36 .features(CargoOpt::SomeFeatures(vec!["real".into(), "plugin".into()]))
37 .manifest_path(path)
38 .exec()?;
39
40 let rust_name = format!("{package}-mel");
41
42 if let Some(rust_package) = metadata.packages.iter().find(|p| p.name == rust_name) {
43 Ok((rust_package.into(), rust_package.into()))
44 } else {
45 Err(Error::Melodium(format!(
46 "Package '{package}' not found (looking for '{rust_name}')"
47 )))
48 }
49}
50
51impl From<&cargo_metadata::Package> for Package {
52 fn from(value: &cargo_metadata::Package) -> Self {
53 Package {
54 name: value
55 .name
56 .strip_suffix("-mel")
57 .unwrap_or(&value.name)
58 .to_string(),
59 version: value.version.clone(),
60 requirements: value
61 .dependencies
62 .iter()
63 .filter_map(|dep| {
64 dep.name
65 .strip_suffix("-mel")
66 .filter(|_| dep.kind == DependencyKind::Normal)
67 .map(|name| PackageRequirement {
68 package: name.to_string(),
69 version_requirement: dep.req.clone(),
70 })
71 })
72 .collect(),
73
74 r#type: Type::Compiled {
75 crate_name: value.name.clone(),
76 platforms: vec![],
77 },
78 }
79 }
80}
81
82impl From<&cargo_metadata::Package> for PackageDetails {
83 fn from(value: &cargo_metadata::Package) -> Self {
84 PackageDetails {
85 name: value
86 .name
87 .strip_suffix("-mel")
88 .unwrap_or(&value.name)
89 .to_string(),
90 authors: value.authors.iter().map(|a| Author::new(a)).collect(),
91 publication: chrono::Utc::now(),
92 description: vec![(
93 "en".to_string(),
94 value.description.clone().unwrap_or_default(),
95 )]
96 .into_iter()
97 .collect(),
98 version: value.version.clone(),
99 license: value.license.clone().unwrap_or_default(),
100 homepage: value.homepage.clone(),
101 repository: value.repository.clone(),
102 r#type: TypeDetails::Compiled,
103 tags: vec![Tag::Std],
104 }
105 }
106}