opensession_git_native/
refs.rs1use base64::engine::general_purpose::URL_SAFE_NO_PAD;
2use base64::Engine;
3
4use crate::BRANCH_LEDGER_REF_PREFIX;
5
6pub fn encode_branch_component(branch: &str) -> String {
8 URL_SAFE_NO_PAD.encode(branch.as_bytes())
9}
10
11pub fn branch_ledger_ref(branch: &str) -> String {
13 let encoded = encode_branch_component(branch);
14 format!("{BRANCH_LEDGER_REF_PREFIX}/{encoded}")
15}
16
17pub fn resolve_ledger_branch(branch: Option<&str>, head: Option<&str>) -> String {
24 let branch = branch.unwrap_or("").trim();
25 if !branch.is_empty() && !branch.eq_ignore_ascii_case("HEAD") {
26 return branch.to_string();
27 }
28
29 let head = head.unwrap_or("").trim();
30 let hex: String = head.chars().filter(|c| c.is_ascii_hexdigit()).collect();
31 if hex.len() >= 8 {
32 return format!("detached@{}", &hex[..8]);
33 }
34
35 "detached".to_string()
36}
37
38#[cfg(test)]
39mod tests {
40 use super::*;
41
42 #[test]
43 fn encode_branch_component_is_deterministic() {
44 let encoded = encode_branch_component("feature/hello-world");
45 assert_eq!(encoded, "ZmVhdHVyZS9oZWxsby13b3JsZA");
46 }
47
48 #[test]
49 fn branch_ledger_ref_builds_hidden_ref() {
50 let ref_name = branch_ledger_ref("main");
51 assert_eq!(ref_name, "refs/opensession/branches/bWFpbg");
52 }
53
54 #[test]
55 fn resolve_ledger_branch_keeps_named_branch() {
56 let branch = resolve_ledger_branch(Some("feature/x"), Some("abcd1234"));
57 assert_eq!(branch, "feature/x");
58 }
59
60 #[test]
61 fn resolve_ledger_branch_uses_detached_with_head_prefix() {
62 let branch = resolve_ledger_branch(Some("HEAD"), Some("aabbccddeeff0011"));
63 assert_eq!(branch, "detached@aabbccdd");
64 }
65
66 #[test]
67 fn resolve_ledger_branch_falls_back_when_head_missing() {
68 let branch = resolve_ledger_branch(Some("HEAD"), None);
69 assert_eq!(branch, "detached");
70 }
71}