winbrew_models\install/
installed.rs

1use core::str::FromStr;
2use serde::{Deserialize, Serialize};
3
4use super::engine::{EngineKind, EngineMetadata};
5use super::installer::InstallerType;
6use crate::shared::{DeploymentKind, ModelError};
7
8/// The persisted status of an installed package row.
9#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Copy)]
10#[serde(rename_all = "lowercase")]
11pub enum PackageStatus {
12    /// The package is currently being installed.
13    Installing,
14    /// The package is installed and healthy.
15    Ok,
16    /// The package is installed but an update is available.
17    Updating,
18    /// The package is known to be broken or failed.
19    Failed,
20}
21
22impl PackageStatus {
23    /// Return the canonical lowercase string used in persistence.
24    pub fn as_str(&self) -> &'static str {
25        match self {
26            Self::Installing => "installing",
27            Self::Ok => "ok",
28            Self::Updating => "updating",
29            Self::Failed => "failed",
30        }
31    }
32}
33
34impl FromStr for PackageStatus {
35    type Err = ModelError;
36
37    fn from_str(status: &str) -> Result<Self, Self::Err> {
38        match status.trim().to_ascii_lowercase().as_str() {
39            "installing" => Ok(Self::Installing),
40            "ok" => Ok(Self::Ok),
41            "updating" => Ok(Self::Updating),
42            "failed" => Ok(Self::Failed),
43            other => Err(ModelError::invalid_enum_value("package.status", other)),
44        }
45    }
46}
47
48impl std::fmt::Display for PackageStatus {
49    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50        f.write_str(self.as_str())
51    }
52}
53
54#[cfg(test)]
55mod tests {
56    use super::PackageStatus;
57    use core::str::FromStr;
58
59    #[test]
60    fn package_status_rejects_unknown_value() {
61        let err = PackageStatus::from_str("mystery").expect_err("unknown status should fail");
62
63        assert!(err.to_string().contains("invalid package.status: mystery"));
64    }
65}
66
67/// The installed-package row persisted in Winbrew storage.
68#[derive(Debug, Clone, Serialize, Deserialize)]
69pub struct InstalledPackage {
70    /// Package name.
71    pub name: String,
72    /// Package version.
73    pub version: String,
74    /// Installer format that produced the installation.
75    pub kind: InstallerType,
76    /// Semantic deployment outcome recorded for the installed row.
77    #[serde(default = "default_deployment_kind")]
78    pub deployment_kind: DeploymentKind,
79    /// Engine kind that performed the install.
80    pub engine_kind: EngineKind,
81    /// Engine-specific metadata for repair and removal flows.
82    pub engine_metadata: Option<EngineMetadata>,
83    /// Final install directory.
84    pub install_dir: String,
85    /// Serialized dependency ids.
86    pub dependencies: Vec<String>,
87    /// Current package status.
88    pub status: PackageStatus,
89    /// Timestamp when the install was finalized.
90    pub installed_at: String,
91}
92
93fn default_deployment_kind() -> DeploymentKind {
94    DeploymentKind::Installed
95}