1#[derive(Debug, Clone)]
2pub struct ParsedRef {
3 pub original_ref: String,
4 pub normalized_for_semver: String,
5 pub previous_ref: String,
6 pub has_refs_tags_prefix: bool,
7}
8
9pub fn normalize_semver(tag: &str) -> String {
10 let (core, suffix) = tag
11 .find(|c| ['-', '+'].contains(&c))
12 .map(|idx| (&tag[..idx], &tag[idx..]))
13 .unwrap_or((tag, ""));
14 if core.is_empty() {
15 return tag.to_string();
16 }
17 let dot_count = core.matches('.').count();
18 let normalized_core = match dot_count {
19 0 => format!("{core}.0.0"),
20 1 => format!("{core}.0"),
21 _ => core.to_string(),
22 };
23 format!("{normalized_core}{suffix}")
24}
25
26pub fn parse_ref(raw: &str, default_refs_tags_prefix: bool) -> ParsedRef {
27 fn strip_until_char(s: &str, c: char) -> Option<String> {
28 s.find(c).map(|index| s[index + 1..].to_string())
29 }
30
31 let mut maybe_version = raw.to_string();
32 let mut previous_ref = String::new();
33 let mut has_refs_tags_prefix = default_refs_tags_prefix;
34
35 if let Some(normalized_version) = maybe_version.strip_prefix("refs/tags/") {
36 has_refs_tags_prefix = true;
37 previous_ref = maybe_version.clone();
38 maybe_version = normalized_version.to_string();
39 }
40
41 if let Some(normalized_version) = maybe_version.strip_prefix('v') {
42 previous_ref = maybe_version.clone();
43 maybe_version = normalized_version.to_string();
44 }
45
46 if let Some(normalized_version) = strip_until_char(&maybe_version, '-') {
47 previous_ref = maybe_version.clone();
48 maybe_version = normalized_version.to_string();
49 }
50
51 if previous_ref.is_empty() {
52 previous_ref = maybe_version.clone();
53 }
54
55 ParsedRef {
56 original_ref: raw.to_string(),
57 normalized_for_semver: normalize_semver(&maybe_version),
58 previous_ref,
59 has_refs_tags_prefix,
60 }
61}