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}