use std::cmp::Reverse; use crate::gitea_client::Tag; use semver::Version; pub fn get_most_significant_version<'a>(tags: Vec<&'a Tag>) -> Option<&'a Tag> { let mut versions: Vec<(&'a Tag, Version)> = tags .into_iter() .filter_map(|c| { if let Ok(version) = c.name.trim_start_matches('v').parse::() { Some((c, version)) } else { None } }) .collect(); versions.sort_unstable_by_key(|(_, version)| Reverse(version.clone())); let tag = versions.first().map(|(tag, _)| *tag); if let Some(tag) = tag { tracing::trace!(name = &tag.name, "found most significant tag with version"); } tag } #[cfg(test)] mod test { use tracing_test::traced_test; use crate::{ gitea_client::{Tag, TagCommit}, versioning::semver::get_most_significant_version, }; fn create_tag(version: impl Into) -> Tag { let version = version.into(); Tag { id: "some-id".into(), message: version.clone(), name: version, commit: TagCommit { created: "date".into(), sha: "sha".into(), url: "url".into(), }, } } #[test] #[traced_test] fn gets_most_significant_version() { let most_significant = create_tag("3.1.1"); let tags = vec![ create_tag("1.0.1"), create_tag("1.2.1"), most_significant.clone(), create_tag("0.0.1"), create_tag("0.0.2"), ]; let actual = get_most_significant_version(tags.iter().collect()).unwrap(); assert_eq!(&most_significant, actual) } #[test] #[traced_test] fn gets_most_significant_version_patch() { let most_significant = create_tag("0.0.8"); let tags = vec![ create_tag("0.0.1"), create_tag("0.0.7"), create_tag("0.0.2"), most_significant.clone(), create_tag("0.0.0"), ]; let actual = get_most_significant_version(tags.iter().collect()).unwrap(); assert_eq!(&most_significant, actual) } #[test] #[traced_test] fn gets_most_significant_version_minor() { let most_significant = create_tag("0.8.0"); let tags = vec![ create_tag("0.1.1"), create_tag("0.2.7"), create_tag("0.7.2"), most_significant.clone(), create_tag("0.3.0"), ]; let actual = get_most_significant_version(tags.iter().collect()).unwrap(); assert_eq!(&most_significant, actual) } #[test] #[traced_test] fn gets_most_significant_version_major() { let most_significant = create_tag("7.8.0"); let tags = vec![ create_tag("6.1.1"), create_tag("1.2.7"), create_tag("2.7.2"), most_significant.clone(), create_tag("3.3.0"), ]; let actual = get_most_significant_version(tags.iter().collect()).unwrap(); assert_eq!(&most_significant, actual) } #[test] #[traced_test] fn ignored_invalid_tags() { let tags = vec![ create_tag("something-3.3.0"), create_tag("bla bla bla"), create_tag("main"), create_tag("master"), create_tag("develop"), ]; let actual = get_most_significant_version(tags.iter().collect()).is_none(); assert!(actual) } #[test] #[traced_test] fn mix_v_prefix() { let most_significant = create_tag("v7.8.0"); let tags = vec![ create_tag("6.1.1"), create_tag("v1.2.7"), create_tag("2.7.2"), most_significant.clone(), create_tag("v3.3.0"), ]; let actual = get_most_significant_version(tags.iter().collect()).unwrap(); assert_eq!(&most_significant, actual) } #[test] #[traced_test] fn mix_v_prefix_2() { let most_significant = create_tag("7.8.0"); let tags = vec![ create_tag("6.1.1"), create_tag("v1.2.7"), create_tag("2.7.2"), most_significant.clone(), create_tag("v3.3.0"), ]; let actual = get_most_significant_version(tags.iter().collect()).unwrap(); assert_eq!(&most_significant, actual) } }