use crate::Repository;
use crate::refs::RefName;
#[derive(Debug, Clone, Default)]
pub(crate) struct HideRules(Vec<(Vec<u8>, bool)>);
impl HideRules {
pub(crate) fn parse(repository: &Repository, service: &str) -> Result<Self, &'static str> {
let mut rules = Vec::new();
for entry in repository.config().entries() {
if entry.subsection.is_some()
|| !entry.name.eq_ignore_ascii_case(b"hiderefs")
|| !(entry.section.eq_ignore_ascii_case(b"transfer")
|| entry.section.eq_ignore_ascii_case(service.as_bytes()))
{
continue;
}
let value = entry.value.as_deref().ok_or("implicit hideRefs pattern")?;
let (visible, pattern) = if let Some(pattern) = value.strip_prefix(b"!") {
(true, pattern)
} else {
(false, value)
};
let pattern = pattern.strip_prefix(b"^").unwrap_or(pattern);
if pattern.is_empty() {
return Err("empty hideRefs pattern");
}
rules.push((pattern.to_vec(), visible));
}
Ok(Self(rules))
}
pub(crate) fn matches(&self, name: &RefName) -> bool {
let mut hidden = false;
for (pattern, visible) in &self.0 {
let pattern = pattern.strip_suffix(b"/").unwrap_or(pattern);
let rest = name.as_bytes().strip_prefix(pattern);
if rest.is_some_and(|rest| rest.is_empty() || rest.starts_with(b"/")) {
hidden = !visible;
}
}
hidden
}
}