use crate::check_ref_format::{check_refname_format, RefNameOptions};
use crate::environment::Environment;
#[must_use]
pub fn raw_git_namespace_from_env(env: &Environment) -> Option<String> {
let v = env.git_namespace.as_deref()?;
let t = v.trim();
if t.is_empty() {
None
} else {
Some(t.to_owned())
}
}
#[must_use]
pub fn ref_storage_prefix(env: &Environment) -> Option<String> {
let raw = raw_git_namespace_from_env(env)?;
let mut buf = String::new();
for part in raw.split('/') {
if part.is_empty() {
continue;
}
buf.push_str("refs/namespaces/");
buf.push_str(part);
buf.push('/');
}
while buf.ends_with('/') && buf.len() > 1 {
buf.pop();
}
if !buf.is_empty() {
let opts = RefNameOptions::default();
if check_refname_format(&buf, &opts).is_err() {
return None;
}
buf.push('/');
}
if buf.is_empty() {
None
} else {
Some(buf)
}
}
#[must_use]
pub fn storage_ref_name(logical: &str) -> String {
storage_ref_name_env(&Environment::empty(), logical)
}
#[must_use]
pub fn ref_skips_namespace_prefix(logical: &str) -> bool {
logical == "HEAD"
|| (!logical.is_empty()
&& !logical.contains('/')
&& logical
.chars()
.all(|c| c.is_ascii_uppercase() || c == '-' || c == '_'))
}
#[must_use]
pub fn storage_ref_name_with_prefix(prefix: Option<&str>, logical: &str) -> String {
if prefix.is_some() && ref_skips_namespace_prefix(logical) {
return logical.to_owned();
}
match prefix {
Some(p) if logical.starts_with(p) => logical.to_owned(),
Some(p) => format!("{p}{logical}"),
None => logical.to_owned(),
}
}
#[must_use]
pub fn logical_ref_name_with_prefix(prefix: Option<&str>, storage: &str) -> String {
match prefix {
Some(p) if storage.starts_with(p) => storage[p.len()..].to_owned(),
_ => storage.to_owned(),
}
}
#[must_use]
pub fn storage_ref_name_env(env: &Environment, logical: &str) -> String {
match ref_storage_prefix(env) {
Some(p) if logical.starts_with(&p) => logical.to_owned(),
Some(p) => format!("{p}{logical}"),
None => logical.to_owned(),
}
}
#[must_use]
pub fn ref_storage_prefix_default() -> Option<String> {
ref_storage_prefix(&Environment::empty())
}
#[must_use]
pub fn logical_ref_name_from_storage(storage: &str) -> Option<String> {
logical_ref_name_from_storage_env(&Environment::empty(), storage)
}
#[must_use]
pub fn logical_ref_name_from_storage_env(env: &Environment, storage: &str) -> Option<String> {
let p = ref_storage_prefix(env)?;
storage.strip_prefix(&p).map(str::to_owned)
}
#[must_use]
pub fn strip_namespace_prefix(refname: &str) -> String {
strip_namespace_prefix_env(&Environment::empty(), refname)
}
#[must_use]
pub fn strip_namespace_prefix_env(env: &Environment, refname: &str) -> String {
match ref_storage_prefix(env) {
Some(p) if refname.starts_with(&p) => refname[p.len()..].to_owned(),
_ => refname.to_owned(),
}
}