1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
use crate::config::Config;
use crate::EXPECTED_CONFIG_FILE_NAME;
use colored::Colorize;
use std::fs::OpenOptions;
use std::io::Write;

/// Enum representing the different version designations
pub enum VersionDesignation {
    Major,
    Minor,
    Patch,
}
/// Struct representing the version
#[derive(Clone)]
pub struct Version {
    pub major: i32,
    pub minor: i32,
    pub patch: i32,
}
impl Version {
    /// Creates a new instance of the Version struct from a string
    /// # Arguments
    /// * `version` - The version string ex. "0.0.1"
    pub fn new(version: String) -> Self {
        let version = version.split(".").collect::<Vec<&str>>();
        Version {
            major: version[0].parse().unwrap(), // if unwrap fails, the program will panic w
            minor: version[1].parse().unwrap(),
            patch: version[2].parse().unwrap(),
        }
    }
}
impl std::fmt::Display for Version {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{}.{}.{}", self.major, self.minor, self.patch)
    }
}

/// Increments the version based on the version designation
/// # Arguments
/// * `config` - The config struct
/// * `version_designation` - The version designation
/// # Returns
/// * The new version
pub fn increment_version(config: &Config, version_designation: VersionDesignation) -> Version {
    let mut version = Version::new(config.version.clone());
    match version_designation {
        VersionDesignation::Major => {
            version.major += 1;
            version.minor = 0;
            version.patch = 0;
        }
        VersionDesignation::Minor => {
            version.minor += 1;
            version.patch = 0;
        }
        VersionDesignation::Patch => {
            version.patch += 1;
        }
    }

    println!(
        "{} {}.{}.{}",
        "New version:".underline(),
        version.major.to_string().green(),
        version.minor.to_string().green(),
        version.patch.to_string().green()
    );

    version
}

/// Writes the new version to the config file and returns the new config
/// # Arguments
/// * `config` - The config struct
/// * `version` - The new version
/// # Returns
/// * The new config
pub fn write_new_version_to_file(config: Config, version: Version) -> Config {
    // write new version of config to config file
    let mut new_config = config;
    new_config.version = format!("{}.{}.{}", version.major, version.minor, version.patch);
    let new_config_string = serde_json::to_string_pretty(&new_config).unwrap();
    let file = OpenOptions::new()
        .write(true)
        .truncate(true)
        .open(EXPECTED_CONFIG_FILE_NAME);

    match file {
        Ok(mut file) => {
            file.write_all(new_config_string.as_bytes())
                .unwrap_or_else(|_| {
                    println!("Failed to write to file");
                });
        }
        Err(_) => {
            println!("Failed to open file");
        }
    }

    new_config
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_version() {
        let version = Version::new("0.0.1".to_string());
        assert_eq!(version.major, 0);
        assert_eq!(version.minor, 0);
        assert_eq!(version.patch, 1);
    }

    #[test]
    fn test_increment_version_patch() {
        let config = Config::create_default();
        let version = increment_version(&config, VersionDesignation::Patch);
        assert_eq!(version.major, 0);
        assert_eq!(version.minor, 0);
        assert_eq!(version.patch, 2);
    }

    #[test]
    fn test_increment_version_minor() {
        let config = Config::create_default();
        let version = increment_version(&config, VersionDesignation::Minor);
        assert_eq!(version.major, 0);
        assert_eq!(version.minor, 1);
        assert_eq!(version.patch, 0);
    }

    #[test]
    fn test_increment_version_major() {
        let mut config = Config::create_default();
        config.version = "0.1.1".to_string();
        let version = increment_version(&config, VersionDesignation::Major);
        assert_eq!(version.major, 1);
        assert_eq!(version.minor, 0);
        assert_eq!(version.patch, 0);
    }
}