Skip to main content

git_workflow/state/
mod.rs

1//! State types for gw CLI
2
3pub mod next_action;
4pub mod repo;
5pub mod sync;
6pub mod working_dir;
7
8pub use next_action::NextAction;
9pub use repo::RepoType;
10pub use sync::SyncState;
11pub use working_dir::WorkingDirState;
12
13use std::marker::PhantomData;
14
15use crate::error::{GwError, Result};
16use crate::git;
17
18/// Marker type for protected branches (main, master, home)
19pub struct Protected;
20
21/// Marker type for deletable branches
22pub struct Deletable;
23
24/// A branch with compile-time safety for deletion
25#[derive(Debug)]
26pub struct Branch<Status> {
27    name: String,
28    _status: PhantomData<Status>,
29}
30
31impl<S> Branch<S> {
32    /// Get the branch name
33    pub fn name(&self) -> &str {
34        &self.name
35    }
36}
37
38impl Branch<Protected> {
39    /// Create a protected branch (for main, master, home branches)
40    pub fn protected(name: String) -> Self {
41        Branch {
42            name,
43            _status: PhantomData,
44        }
45    }
46}
47
48impl Branch<Deletable> {
49    /// Create a deletable branch
50    pub fn deletable(name: String) -> Self {
51        Branch {
52            name,
53            _status: PhantomData,
54        }
55    }
56
57    /// Delete this branch (only possible for Deletable branches)
58    pub fn delete(self, verbose: bool) -> Result<()> {
59        git::delete_branch(&self.name, verbose)
60    }
61}
62
63/// Classify a branch as protected or deletable
64pub fn classify_branch(branch: &str, repo_type: &RepoType) -> BranchClassification {
65    if repo_type.is_protected(branch) {
66        BranchClassification::Protected(Branch::protected(branch.to_string()))
67    } else {
68        BranchClassification::Deletable(Branch::deletable(branch.to_string()))
69    }
70}
71
72/// Result of classifying a branch
73pub enum BranchClassification {
74    Protected(Branch<Protected>),
75    Deletable(Branch<Deletable>),
76}
77
78impl BranchClassification {
79    /// Get the branch name regardless of classification
80    pub fn name(&self) -> &str {
81        match self {
82            BranchClassification::Protected(b) => b.name(),
83            BranchClassification::Deletable(b) => b.name(),
84        }
85    }
86
87    /// Try to get as deletable, returning error if protected
88    pub fn try_deletable(self) -> Result<Branch<Deletable>> {
89        match self {
90            BranchClassification::Protected(b) => {
91                Err(GwError::ProtectedBranch(b.name().to_string()))
92            }
93            BranchClassification::Deletable(b) => Ok(b),
94        }
95    }
96}