use clayers_xml::ContentHash;
use crate::error::Result;
use crate::store::RefStore;
pub const HEADS_PREFIX: &str = "refs/heads/";
pub const TAGS_PREFIX: &str = "refs/tags/";
pub const HEAD: &str = "HEAD";
#[must_use]
pub fn branch_ref(name: &str) -> String {
format!("{HEADS_PREFIX}{name}")
}
#[must_use]
pub fn tag_ref(name: &str) -> String {
format!("{TAGS_PREFIX}{name}")
}
pub async fn resolve_head(store: &dyn RefStore) -> Result<Option<ContentHash>> {
store.get_ref(HEAD).await
}
pub async fn set_head(store: &dyn RefStore, hash: ContentHash) -> Result<()> {
store.set_ref(HEAD, hash).await
}
pub async fn get_branch(store: &dyn RefStore, name: &str) -> Result<Option<ContentHash>> {
store.get_ref(&branch_ref(name)).await
}
pub async fn list_branches(store: &dyn RefStore) -> Result<Vec<(String, ContentHash)>> {
let refs = store.list_refs(HEADS_PREFIX).await?;
Ok(refs
.into_iter()
.map(|(full, hash)| {
let name = full
.strip_prefix(HEADS_PREFIX)
.unwrap_or(&full)
.to_string();
(name, hash)
})
.collect())
}
pub async fn list_tags(store: &dyn RefStore) -> Result<Vec<(String, ContentHash)>> {
let refs = store.list_refs(TAGS_PREFIX).await?;
Ok(refs
.into_iter()
.map(|(full, hash)| {
let name = full
.strip_prefix(TAGS_PREFIX)
.unwrap_or(&full)
.to_string();
(name, hash)
})
.collect())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn branch_ref_path() {
assert_eq!(branch_ref("main"), "refs/heads/main");
assert_eq!(branch_ref("feature/x"), "refs/heads/feature/x");
}
#[test]
fn tag_ref_path() {
assert_eq!(tag_ref("v1.0"), "refs/tags/v1.0");
}
}