Skip to main content

crate_seq_ledger/
state.rs

1//! State-machine transitions for [`LedgerStatus`].
2
3use crate::{CrateSeqLedger, Error, LedgerStatus};
4
5impl CrateSeqLedger {
6    /// Marks `version` as [`LedgerStatus::Published`].
7    ///
8    /// Permitted source states: [`LedgerStatus::Pending`], [`LedgerStatus::Skipped`].
9    ///
10    /// # Errors
11    ///
12    /// Returns [`Error::VersionNotFound`] if no entry exists for `version`.
13    /// Returns [`Error::InvalidTransition`] if the entry is [`LedgerStatus::Published`]
14    /// or [`LedgerStatus::Yanked`].
15    pub fn mark_published(&mut self, version: &semver::Version) -> Result<(), Error> {
16        let entry = self
17            .entries
18            .iter_mut()
19            .find(|e| &e.version == version)
20            .ok_or_else(|| Error::VersionNotFound(version.clone()))?;
21
22        match entry.status {
23            LedgerStatus::Pending | LedgerStatus::Skipped => {
24                entry.status = LedgerStatus::Published;
25                Ok(())
26            }
27            LedgerStatus::Published => Err(Error::InvalidTransition(
28                version.clone(),
29                "published",
30                "published",
31            )),
32            LedgerStatus::Yanked => Err(Error::InvalidTransition(
33                version.clone(),
34                "yanked",
35                "published",
36            )),
37        }
38    }
39
40    /// Marks `version` as [`LedgerStatus::Skipped`].
41    ///
42    /// Permitted source states: [`LedgerStatus::Pending`], [`LedgerStatus::Skipped`],
43    /// [`LedgerStatus::Yanked`].
44    ///
45    /// # Errors
46    ///
47    /// Returns [`Error::VersionNotFound`] if no entry exists for `version`.
48    /// Returns [`Error::InvalidTransition`] if the entry is [`LedgerStatus::Published`].
49    pub fn mark_skipped(&mut self, version: &semver::Version) -> Result<(), Error> {
50        let entry = self
51            .entries
52            .iter_mut()
53            .find(|e| &e.version == version)
54            .ok_or_else(|| Error::VersionNotFound(version.clone()))?;
55
56        match entry.status {
57            LedgerStatus::Published => Err(Error::InvalidTransition(
58                version.clone(),
59                "published",
60                "skipped",
61            )),
62            LedgerStatus::Pending | LedgerStatus::Skipped | LedgerStatus::Yanked => {
63                entry.status = LedgerStatus::Skipped;
64                Ok(())
65            }
66        }
67    }
68
69    /// Marks `version` as [`LedgerStatus::Yanked`].
70    ///
71    /// Permitted source state: [`LedgerStatus::Published`].
72    ///
73    /// # Errors
74    ///
75    /// Returns [`Error::VersionNotFound`] if no entry exists for `version`.
76    /// Returns [`Error::InvalidTransition`] if the entry is not [`LedgerStatus::Published`].
77    pub fn mark_yanked(&mut self, version: &semver::Version) -> Result<(), Error> {
78        let entry = self
79            .entries
80            .iter_mut()
81            .find(|e| &e.version == version)
82            .ok_or_else(|| Error::VersionNotFound(version.clone()))?;
83
84        match entry.status {
85            LedgerStatus::Published => {
86                entry.status = LedgerStatus::Yanked;
87                Ok(())
88            }
89            LedgerStatus::Pending => Err(Error::InvalidTransition(
90                version.clone(),
91                "pending",
92                "yanked",
93            )),
94            LedgerStatus::Skipped => Err(Error::InvalidTransition(
95                version.clone(),
96                "skipped",
97                "yanked",
98            )),
99            LedgerStatus::Yanked => Err(Error::InvalidTransition(
100                version.clone(),
101                "yanked",
102                "yanked",
103            )),
104        }
105    }
106}