use std::fmt::Display;
use std::str;
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum GitReference {
Branch(String),
Tag(String),
BranchOrTag(String),
BranchOrTagOrCommit(String),
NamedRef(String),
DefaultBranch,
}
impl GitReference {
pub fn from_rev(rev: String) -> Self {
if rev.starts_with("refs/") {
Self::NamedRef(rev)
} else if looks_like_commit_hash(&rev) {
Self::BranchOrTagOrCommit(rev)
} else {
Self::BranchOrTag(rev)
}
}
pub fn as_str(&self) -> Option<&str> {
match self {
Self::Tag(rev) => Some(rev),
Self::Branch(rev) => Some(rev),
Self::BranchOrTag(rev) => Some(rev),
Self::BranchOrTagOrCommit(rev) => Some(rev),
Self::NamedRef(rev) => Some(rev),
Self::DefaultBranch => None,
}
}
pub fn as_rev(&self) -> &str {
match self {
Self::Tag(rev) => rev,
Self::Branch(rev) => rev,
Self::BranchOrTag(rev) => rev,
Self::BranchOrTagOrCommit(rev) => rev,
Self::NamedRef(rev) => rev,
Self::DefaultBranch => "HEAD",
}
}
pub fn kind_str(&self) -> &str {
match self {
Self::Branch(_) => "branch",
Self::Tag(_) => "tag",
Self::BranchOrTag(_) => "branch or tag",
Self::BranchOrTagOrCommit(_) => "branch, tag, or commit",
Self::NamedRef(_) => "ref",
Self::DefaultBranch => "default branch",
}
}
}
impl Display for GitReference {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.as_str().unwrap_or("HEAD"))
}
}
fn looks_like_commit_hash(rev: &str) -> bool {
rev.len() >= 7 && rev.chars().all(|ch| ch.is_ascii_hexdigit())
}