use crate::public_api_mod::{GREEN, RED, RESET, YELLOW};
use crate::{
error_mod::{Error, Result},
utils_mod::*,
};
enum VersionPart {
Patch,
Minor,
}
pub fn auto_semver_increment_patch() -> Result<()> {
increment_part(VersionPart::Patch, false)
}
pub fn auto_semver_increment_patch_forced() -> Result<()> {
increment_part(VersionPart::Patch, true)
}
pub fn auto_semver_increment_minor() -> Result<()> {
increment_part(VersionPart::Minor, false)
}
pub fn auto_semver_increment_minor_forced() -> Result<()> {
increment_part(VersionPart::Minor, true)
}
fn increment_part(part: VersionPart, force_version: bool) -> Result<()> {
let mut vec_of_metadata = crate::auto_version_from_date_mod::read_file_metadata()?;
let is_files_equal = if force_version {
false
} else {
let js_struct = crate::auto_version_from_date_mod::read_json_file(".automation_tasks_rs_file_hashes.json")?;
crate::auto_version_from_date_mod::are_files_equal(&vec_of_metadata, &js_struct.vec_file_metadata)
};
if !is_files_equal {
let cargo_toml_filename = "Cargo.toml";
let cargo_toml_text = std::fs::read_to_string(cargo_toml_filename)?;
if cargo_toml_text.contains("\r\n") {
return Err(Error::ErrorFromString(format!(
"{RED}Error: {cargo_toml_filename} has CRLF line endings instead of LF. Correct the file! {RESET}"
)));
}
if let Ok(pos_start_data) = find_pos_start_data_after_delimiter(&cargo_toml_text, 0, r#"version = ""#) {
if let Ok(pos_end_data) = find_pos_end_data_before_delimiter(&cargo_toml_text, pos_start_data, r#"""#) {
let version = cargo_toml_text[pos_start_data..pos_end_data].to_string();
println!(r#" {YELLOW}old version: "{version}"{RESET}"#);
let pos = pos_start_data;
let (major, pos) = parse_next_number(&cargo_toml_text, pos)?;
let pos = pos + 1;
let (mut minor, pos) = parse_next_number(&cargo_toml_text, pos)?;
let pos = pos + 1;
let (mut patch, pos) = parse_next_number(&cargo_toml_text, pos)?;
let pos_at_the_end_of_semver = pos;
match part {
VersionPart::Patch => {
patch += 1;
}
VersionPart::Minor => {
minor += 1;
patch = 0;
}
}
let new_semver = format!("{}.{}.{}", major, minor, patch);
println!("{GREEN}new version: '{}'{RESET}", &new_semver);
let new_cargo_toml_text = format!(
"{}{}{}",
&cargo_toml_text[..pos_start_data],
&new_semver,
&cargo_toml_text[pos_at_the_end_of_semver..]
);
let _x = std::fs::write(cargo_toml_filename, new_cargo_toml_text);
crate::auto_version_from_date_mod::correct_file_metadata_for_cargo_tom_inside_vec(&mut vec_of_metadata)?;
crate::auto_version_from_date_mod::save_json_file_for_file_meta_data(vec_of_metadata)?;
} else {
return Err(Error::ErrorFromString(format!("{RED}no end quote for version{RESET}")));
}
} else {
return Err(Error::ErrorFromString(format!("{RED}Cargo.toml has no version{RESET}")));
}
}
Ok(())
}
fn parse_next_number(cargo_toml_text: &str, pos: usize) -> Result<(usize, usize)> {
let mut pos = pos;
let mut number = "".to_string();
let mut one_char = cargo_toml_text[pos..pos + 1]
.chars()
.next()
.ok_or(Error::ErrorFromStr("error chars().next()"))?;
while one_char.is_numeric() {
number.push(one_char);
pos += 1;
one_char = cargo_toml_text[pos..pos + 1]
.chars()
.next()
.ok_or(Error::ErrorFromStr("error chars().next()"))?;
}
let number: usize = number.parse()?;
Ok((number, pos))
}