version_manager/
run.rs

1use crate::{
2    VersionError, VersionResult,
3    files::{ModifyTrackedFiles, Package, VersionFile},
4    version::{Operator, PrereleaseWrapper, Scope, SetTypes},
5};
6use semver::{BuildMetadata, Prerelease, Version};
7use serde_json::json;
8use std::path::PathBuf;
9
10pub fn run(scope: Scope, file_path: PathBuf) -> VersionResult<()> {
11    let file = VersionFile::load(file_path.clone())?;
12    let mut ver = process_run(scope, file)?;
13    ver.save(file_path)?;
14    Ok(())
15}
16
17pub fn run_scopes<'a, T>(
18    scope: Scope,
19    version: &'a mut Version,
20    files: &'a mut T,
21) -> VersionResult<(&'a mut Version, &'a mut T, Option<(String, Scope)>)>
22where
23    T: ModifyTrackedFiles,
24{
25    match scope {
26        Scope::Major(getset) => match getset {
27            Operator::Set(set) => match set {
28                SetTypes::Number(value) => version.major = value,
29                SetTypes::AddNumber => version.major += 1,
30                SetTypes::SubNumber => {
31                    if version.major == 0 {
32                        return Err(VersionError::NoNegatives);
33                    }
34                    version.major -= 1
35                }
36                _ => return Err(VersionError::InvalidOperation),
37            },
38            Operator::Get => println!("{}", version.major),
39            Operator::Reset => {
40                version.minor = 0;
41                version.patch = 0;
42                version.pre = Prerelease::EMPTY;
43                version.build = BuildMetadata::EMPTY;
44            }
45            _ => return Err(VersionError::InvalidOperation),
46        },
47        Scope::Minor(getset) => match getset {
48            Operator::Set(set) => match set {
49                SetTypes::Number(value) => version.minor = value,
50                SetTypes::AddNumber => version.minor += 1,
51                SetTypes::SubNumber => {
52                    if version.minor == 0 {
53                        return Err(VersionError::NoNegatives);
54                    }
55                    version.minor -= 1
56                }
57                _ => return Err(VersionError::InvalidOperation),
58            },
59            Operator::Get => println!("{}", version.minor),
60            Operator::Reset => {
61                version.patch = 0;
62                version.pre = Prerelease::EMPTY;
63                version.build = BuildMetadata::EMPTY;
64            }
65            _ => return Err(VersionError::InvalidOperation),
66        },
67        Scope::Patch(getset) => match getset {
68            Operator::Set(set) => match set {
69                SetTypes::Number(value) => version.patch = value,
70                SetTypes::AddNumber => version.patch += 1,
71                SetTypes::SubNumber => {
72                    if version.patch == 0 {
73                        return Err(VersionError::NoNegatives);
74                    }
75                    version.patch -= 1
76                }
77                _ => return Err(VersionError::InvalidOperation),
78            },
79            Operator::Get => println!("{}", version.patch),
80            Operator::Reset => {
81                version.pre = Prerelease::EMPTY;
82                version.build = BuildMetadata::EMPTY;
83            }
84            _ => return Err(VersionError::InvalidOperation),
85        },
86        Scope::Alpha(getsetrm) => match getsetrm {
87            Operator::Set(set) => match set {
88                SetTypes::Number(value) => {
89                    version.pre = Prerelease::new(&format!("alpha.{}", value))?
90                }
91                SetTypes::AddNumber => {
92                    match TryInto::<PrereleaseWrapper>::try_into(version.pre.clone()) {
93                        Ok(mut wrapper) => {
94                            wrapper.num += 1;
95                            version.pre = TryInto::<Prerelease>::try_into(wrapper)?;
96                        }
97                        Err(_) => {
98                            let wrapper = PrereleaseWrapper {
99                                pre: "alpha".to_string(),
100                                num: 0,
101                            };
102                            version.pre = TryInto::<Prerelease>::try_into(wrapper)?;
103                        }
104                    };
105                }
106                SetTypes::SubNumber => {
107                    let mut wrapper = TryInto::<PrereleaseWrapper>::try_into(version.pre.clone())?;
108                    wrapper.num -= 1;
109                    if wrapper.num == 0 {
110                        version.pre = Prerelease::EMPTY;
111                    } else {
112                        version.pre = TryInto::<Prerelease>::try_into(wrapper)?;
113                    }
114                }
115                _ => return Err(VersionError::InvalidOperation),
116            },
117            Operator::Get => println!("{}", version.pre),
118            Operator::Reset => {
119                version.build = BuildMetadata::EMPTY;
120            }
121            Operator::Rm => version.pre = Prerelease::EMPTY,
122            _ => return Err(VersionError::InvalidOperation),
123        },
124        Scope::Pre(getsetrm) => match getsetrm {
125            Operator::Set(set) => match set {
126                SetTypes::Number(value) => {
127                    version.pre = Prerelease::new(&format!("pre.{}", value))?
128                }
129                SetTypes::AddNumber => {
130                    match TryInto::<PrereleaseWrapper>::try_into(version.pre.clone()) {
131                        Ok(mut wrapper) => {
132                            wrapper.num += 1;
133                            version.pre = TryInto::<Prerelease>::try_into(wrapper)?;
134                        }
135                        Err(_) => {
136                            let wrapper = PrereleaseWrapper {
137                                pre: "pre".to_string(),
138                                num: 0,
139                            };
140                            version.pre = TryInto::<Prerelease>::try_into(wrapper)?;
141                        }
142                    };
143                }
144                SetTypes::SubNumber => {
145                    let mut wrapper = TryInto::<PrereleaseWrapper>::try_into(version.pre.clone())?;
146                    wrapper.num -= 1;
147                    if wrapper.num == 0 {
148                        version.pre = Prerelease::EMPTY;
149                    } else {
150                        version.pre = TryInto::<Prerelease>::try_into(wrapper)?;
151                    }
152                }
153                _ => return Err(VersionError::InvalidOperation),
154            },
155            Operator::Get => println!("{}", version.pre),
156            Operator::Reset => {
157                version.build = BuildMetadata::EMPTY;
158            }
159            Operator::Rm => version.pre = Prerelease::EMPTY,
160            _ => return Err(VersionError::InvalidOperation),
161        },
162        Scope::Beta(getsetrm) => match getsetrm {
163            Operator::Set(set) => match set {
164                SetTypes::Number(value) => {
165                    version.pre = Prerelease::new(&format!("beta.{}", value))?
166                }
167                SetTypes::AddNumber => {
168                    match TryInto::<PrereleaseWrapper>::try_into(version.pre.clone()) {
169                        Ok(mut wrapper) => {
170                            wrapper.num += 1;
171                            version.pre = TryInto::<Prerelease>::try_into(wrapper)?;
172                        }
173                        Err(_) => {
174                            let wrapper = PrereleaseWrapper {
175                                pre: "beta".to_string(),
176                                num: 0,
177                            };
178                            version.pre = TryInto::<Prerelease>::try_into(wrapper)?;
179                        }
180                    };
181                }
182                SetTypes::SubNumber => {
183                    let mut wrapper = TryInto::<PrereleaseWrapper>::try_into(version.pre.clone())?;
184                    wrapper.num -= 1;
185                    if wrapper.num == 0 {
186                        version.pre = Prerelease::EMPTY;
187                    } else {
188                        version.pre = TryInto::<Prerelease>::try_into(wrapper)?;
189                    }
190                }
191                _ => return Err(VersionError::InvalidOperation),
192            },
193            Operator::Get => println!("{}", version.pre),
194            Operator::Reset => {
195                version.build = BuildMetadata::EMPTY;
196            }
197            Operator::Rm => version.pre = Prerelease::EMPTY,
198            _ => return Err(VersionError::InvalidOperation),
199        },
200        Scope::RC(getsetrm) => match getsetrm {
201            Operator::Set(set) => match set {
202                SetTypes::Number(value) => version.pre = Prerelease::new(&format!("rc.{}", value))?,
203                SetTypes::AddNumber => {
204                    match TryInto::<PrereleaseWrapper>::try_into(version.pre.clone()) {
205                        Ok(mut wrapper) => {
206                            wrapper.num += 1;
207                            version.pre = TryInto::<Prerelease>::try_into(wrapper)?;
208                        }
209                        Err(_) => {
210                            let wrapper = PrereleaseWrapper {
211                                pre: "rc".to_string(),
212                                num: 0,
213                            };
214                            version.pre = TryInto::<Prerelease>::try_into(wrapper)?;
215                        }
216                    };
217                }
218                SetTypes::SubNumber => {
219                    let mut wrapper = TryInto::<PrereleaseWrapper>::try_into(version.pre.clone())?;
220                    wrapper.num -= 1;
221                    if wrapper.num == 0 {
222                        version.pre = Prerelease::EMPTY;
223                    } else {
224                        version.pre = TryInto::<Prerelease>::try_into(wrapper)?;
225                    }
226                }
227                _ => return Err(VersionError::InvalidOperation),
228            },
229            Operator::Get => println!("{}", version.pre),
230            Operator::Reset => {
231                version.build = BuildMetadata::EMPTY;
232            }
233            Operator::Rm => {
234                version.pre = Prerelease::EMPTY;
235            }
236            _ => return Err(VersionError::InvalidOperation),
237        },
238        Scope::Build(getsetbuild) => match getsetbuild {
239            Operator::Set(set) => match set {
240                SetTypes::String(value) => version.build = BuildMetadata::new(&value)?,
241                _ => return Err(VersionError::InvalidOperation),
242            },
243            Operator::Get => println!("{}", version.build),
244            Operator::Rm => version.build = BuildMetadata::EMPTY,
245            _ => return Err(VersionError::InvalidOperation),
246        },
247        Scope::Get => println!("{}", version.to_string()),
248        Scope::Version => println!("{}.{}.{}", version.major, version.minor, version.patch),
249        Scope::Revision => println!("{}", version.pre),
250        Scope::File(file_cmd) => match file_cmd {
251            Operator::AddFile(set) => match set {
252                SetTypes::NewFile(file) => files.add_tracked_file(file)?,
253                _ => return Err(VersionError::InvalidOperation),
254            },
255            Operator::Update(file) => files.update_file(PathBuf::from(file))?,
256            Operator::RmFile(file) => files.remove_tracked_file(PathBuf::from(file))?,
257            Operator::UpdateAll => files.update_tracked_files()?,
258            Operator::ListFiles => {
259                let files = files.list_tracked_files()?;
260                let file_str = json!(files).to_string();
261                println!("{}", file_str);
262            }
263            _ => return Err(VersionError::InvalidOperation),
264        },
265        Scope::Set(set) => match set {
266            Operator::SetVersion(version_str) => {
267                *version = Version::parse(&version_str)?;
268            }
269            _ => return Err(VersionError::InvalidOperation),
270        },
271        Scope::Package(name, pkg) => return Ok((version, files, Some((name, *pkg)))),
272        _ => return Err(VersionError::InvalidOperation),
273    };
274    files.sync_files()?;
275    Ok((version, files, None))
276}
277
278pub fn process_run(scope: Scope, mut ver: VersionFile) -> VersionResult<VersionFile> {
279    let mut ver_files = ver.clone();
280    let mut ver_version = ver.version.clone();
281    let (version, files, scope) = run_scopes(scope, &mut ver_version, &mut ver_files)?;
282    ver = files.clone();
283    ver.version = version.clone();
284    if let Some((name, scope)) = scope {
285        if scope == Scope::ListPackages {
286            for (name, pkg) in ver.package.iter() {
287                println!("{}: {}", name, pkg.version.to_string());
288            }
289            return Ok(ver);
290        }
291        if !ver.package.contains_key(&name) {
292            ver.package.insert(name.clone(), Package::default());
293        }
294        let pkg = ver.get_package_mut(&name)?;
295        let mut pkg_version = pkg.version.clone();
296        let mut pkg_files = pkg.clone();
297        let (version, files, _) = match scope {
298            Scope::RmPackage => {
299                ver.package.remove(&name);
300                return Ok(ver);
301            }
302            _ => run_scopes(scope, &mut pkg_version, &mut pkg_files)?,
303        };
304        files.version = version.clone();
305        ver.package.insert(name.clone(), files.clone());
306    }
307    Ok(ver)
308}