blaze_common/
dependency.rs

1use std::{convert::Infallible, str::FromStr};
2
3use serde::{Deserialize, Serialize};
4use strum_macros::{Display, EnumIter};
5
6use crate::{selector::ProjectSelector, unit_enum_deserialize, unit_enum_from_str};
7
8/// A target dependency object.
9#[derive(Debug, Clone, Hash, Serialize)]
10#[serde(rename_all = "camelCase")]
11pub struct Dependency {
12    target: String,
13    #[serde(skip_serializing_if = "Option::is_none")]
14    projects: Option<ProjectSelector>,
15    cache_propagation: CachePropagation,
16    optional: bool,
17}
18
19impl Dependency {
20    pub fn target(&self) -> &str {
21        &self.target
22    }
23
24    pub fn projects(&self) -> Option<&ProjectSelector> {
25        self.projects.as_ref()
26    }
27
28    pub fn cache_propagation(&self) -> CachePropagation {
29        self.cache_propagation
30    }
31
32    pub fn optional(&self) -> bool {
33        self.optional
34    }
35}
36
37impl FromStr for Dependency {
38    type Err = Infallible;
39
40    fn from_str(s: &str) -> std::result::Result<Self, Infallible> {
41        let (project, target) = match s.split_once(':') {
42            Some((project, target)) => (Some(project), target),
43            None => (None, s),
44        };
45
46        Ok(Self {
47            target: target.to_string(),
48            cache_propagation: CachePropagation::default(),
49            optional: false,
50            projects: project.map(|project| ProjectSelector::array([project])),
51        })
52    }
53}
54
55impl<'de> Deserialize<'de> for Dependency {
56    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
57    where
58        D: serde::Deserializer<'de>,
59    {
60        #[derive(Deserialize)]
61        #[serde(rename_all = "camelCase", remote = "Dependency")]
62        struct DependencyObject {
63            target: String,
64            projects: Option<ProjectSelector>,
65            #[serde(default)]
66            cache_propagation: CachePropagation,
67            #[serde(default)]
68            optional: bool,
69        }
70
71        #[derive(Deserialize)]
72        #[serde(untagged)]
73        enum DependencyDeserializationMode {
74            AsString(String),
75            #[serde(with = "DependencyObject")]
76            Full(Dependency),
77        }
78
79        Ok(
80            match DependencyDeserializationMode::deserialize(deserializer)? {
81                DependencyDeserializationMode::AsString(target) => {
82                    Dependency::from_str(target.as_str()).unwrap()
83                }
84                DependencyDeserializationMode::Full(dependency) => dependency,
85            },
86        )
87    }
88}
89
90#[derive(Default, Debug, Clone, Copy, Hash, Serialize, PartialEq, Eq, EnumIter, Display)]
91pub enum CachePropagation {
92    /// Cache will invalidate if:
93    /// - The dependency state changes between success, failure or canceled (can occur only when dependency is optional)
94    /// - The dependency is freshly
95    #[default]
96    Always,
97
98    // Dependencies will not be considered when invalidating cache
99    Never,
100}
101
102unit_enum_from_str!(CachePropagation);
103unit_enum_deserialize!(CachePropagation);