Skip to main content

propel_core/
project.rs

1use serde::Deserialize;
2use std::path::Path;
3
4/// Metadata extracted from the user's Cargo.toml
5#[derive(Debug, Clone)]
6pub struct ProjectMeta {
7    pub name: String,
8    pub version: String,
9    pub binary_name: String,
10}
11
12#[derive(Deserialize)]
13struct CargoToml {
14    package: Option<PackageSection>,
15    bin: Option<Vec<BinSection>>,
16}
17
18#[derive(Deserialize)]
19struct PackageSection {
20    name: Option<String>,
21    version: Option<String>,
22}
23
24#[derive(Deserialize)]
25struct BinSection {
26    name: Option<String>,
27}
28
29impl ProjectMeta {
30    /// Extract project metadata from a Cargo.toml file.
31    pub fn from_cargo_toml(project_dir: &Path) -> crate::Result<Self> {
32        let cargo_path = project_dir.join("Cargo.toml");
33        tracing::debug!(path = %cargo_path.display(), "reading Cargo.toml");
34
35        let content =
36            std::fs::read_to_string(&cargo_path).map_err(|e| crate::Error::CargoTomlRead {
37                path: cargo_path.clone(),
38                source: e,
39            })?;
40
41        let parsed: CargoToml =
42            toml::from_str(&content).map_err(|e| crate::Error::CargoTomlParse {
43                path: cargo_path.clone(),
44                source: e,
45            })?;
46
47        let package = parsed
48            .package
49            .ok_or_else(|| crate::Error::MissingPackageSection(cargo_path.clone()))?;
50
51        let name = package
52            .name
53            .ok_or_else(|| crate::Error::MissingPackageName(cargo_path.clone()))?;
54
55        let version = package.version.unwrap_or_else(|| "0.1.0".to_owned());
56
57        // Binary name: first [[bin]] entry, or package name
58        let binary_name = parsed
59            .bin
60            .and_then(|bins| bins.into_iter().next())
61            .and_then(|b| b.name)
62            .unwrap_or_else(|| name.clone());
63
64        tracing::debug!(
65            name = %name,
66            version = %version,
67            binary = %binary_name,
68            "project metadata resolved"
69        );
70
71        Ok(Self {
72            name,
73            version,
74            binary_name,
75        })
76    }
77}