Sebastian Thielrefactor (#364)b1b98714 years agoHistory
181 lines · 5.5 KB · Rust
RawDownload
use std::{    convert::{Infallible, TryFrom},    ffi::OsStr,    path::Path,}; use git_object::bstr::{BStr, BString, ByteSlice, ByteVec}; use crate::{Category, FullNameRef, PartialNameRef}; /// The error used in the [`PartialNameRef`][super::PartialNameRef]::try_from(…) implementations.pub type Error = git_validate::reference::name::Error; impl Category {    /// Return the prefix that would contain all references of our kind.    pub fn prefix(&self) -> &BStr {        match self {            Category::Tag => b"refs/tags/".as_bstr(),            Category::LocalBranch => b"refs/heads/".as_bstr(),            Category::RemoteBranch => b"refs/remotes/".as_bstr(),            Category::Note => b"refs/notes/".as_bstr(),        }    }} impl<'a> FullNameRef<'a> {    /// Convert this name into the relative path identifying the reference location.    pub fn to_path(self) -> &'a Path {        git_features::path::from_byte_slice_or_panic_on_windows(self.0)    }     /// Return ourselves as byte string which is a valid refname    pub fn as_bstr(&self) -> &'a BStr {        self.0    }     /// Strip well-known prefixes from the name and return it.    ///    /// If there is no such prefix, the original name is returned.    pub fn shorten(&self) -> &'a BStr {        let n = self.as_bstr();        n.strip_prefix(b"refs/tags/")            .or_else(|| n.strip_prefix(b"refs/heads/"))            .or_else(|| n.strip_prefix(b"refs/remotes/"))            .or_else(|| n.strip_prefix(b"refs/"))            .map(|n| n.as_bstr())            .unwrap_or(n)    }     /// Classify this name, or return `None` if it's unclassified.    pub fn category(&self) -> Option<Category> {        for kind in &[            Category::Tag,            Category::LocalBranch,            Category::RemoteBranch,            Category::Note,        ] {            if self.0.starts_with(kind.prefix()) {                return (*kind).into();            }        }        None    }} impl<'a> PartialNameRef<'a> {    /// Convert this name into the relative path possibly identifying the reference location.    /// Note that it may be only a partial path though.    pub fn to_partial_path(&'a self) -> &'a Path {        git_features::path::from_byte_slice_or_panic_on_windows(self.0.as_ref())    }     /// Provide the name as binary string which is known to be a valid partial ref name.    pub fn as_bstr(&'a self) -> &'a BStr {        self.0.as_ref()    }} impl PartialNameRef<'static> {    /// Append the `component` to ourselves and validate the newly created partial path.    ///    /// Note that this method is meant to have an owned starting point as this is considered    /// the typical usecase.    pub fn join(self, component: impl AsRef<[u8]>) -> Result<Self, crate::name::Error> {        let mut b = self.0.into_owned();        b.push_byte(b'/');        b.extend(component.as_ref());        git_validate::reference::name_partial(b.as_ref())?;        Ok(PartialNameRef(b.into()))    }} impl<'a> TryFrom<&'a BStr> for FullNameRef<'a> {    type Error = Error;     fn try_from(v: &'a BStr) -> Result<Self, Self::Error> {        Ok(FullNameRef(git_validate::reference::name(v)?))    }} impl<'a> TryFrom<FullNameRef<'a>> for PartialNameRef<'a> {    type Error = Infallible;     fn try_from(v: FullNameRef<'a>) -> Result<Self, Self::Error> {        Ok(PartialNameRef(v.0.into()))    }} impl<'a> TryFrom<&'a OsStr> for PartialNameRef<'a> {    type Error = Error;     fn try_from(v: &'a OsStr) -> Result<Self, Self::Error> {        let v = git_features::path::os_str_into_bytes(v)            .map_err(|_| Error::Tag(git_validate::tag::name::Error::InvalidByte("<unknown encoding>".into())))?;        Ok(PartialNameRef(            git_validate::reference::name_partial(v.as_bstr())?.into(),        ))    }} impl<'a> TryFrom<&'a BStr> for PartialNameRef<'a> {    type Error = Error;     fn try_from(v: &'a BStr) -> Result<Self, Self::Error> {        Ok(PartialNameRef(git_validate::reference::name_partial(v)?.into()))    }} impl<'a> TryFrom<&'a str> for FullNameRef<'a> {    type Error = Error;     fn try_from(v: &'a str) -> Result<Self, Self::Error> {        let v = v.as_bytes().as_bstr();        Ok(FullNameRef(git_validate::reference::name(v)?))    }} impl<'a> TryFrom<&'a str> for PartialNameRef<'a> {    type Error = Error;     fn try_from(v: &'a str) -> Result<Self, Self::Error> {        let v = v.as_bytes().as_bstr();        Ok(PartialNameRef(git_validate::reference::name_partial(v)?.into()))    }} impl<'a> TryFrom<&'a String> for FullNameRef<'a> {    type Error = Error;     fn try_from(v: &'a String) -> Result<Self, Self::Error> {        let v = v.as_bytes().as_bstr();        Ok(FullNameRef(git_validate::reference::name(v)?))    }} impl<'a> TryFrom<&'a String> for PartialNameRef<'a> {    type Error = Error;     fn try_from(v: &'a String) -> Result<Self, Self::Error> {        let v = v.as_bytes().as_bstr();        Ok(PartialNameRef(git_validate::reference::name_partial(v)?.into()))    }} impl TryFrom<String> for PartialNameRef<'static> {    type Error = Error;     fn try_from(v: String) -> Result<Self, Self::Error> {        git_validate::reference::name_partial(v.as_bytes().as_bstr())?;        Ok(PartialNameRef(BString::from(v).into()))    }} impl TryFrom<BString> for PartialNameRef<'static> {    type Error = Error;     fn try_from(v: BString) -> Result<Self, Self::Error> {        git_validate::reference::name_partial(v.as_ref())?;        Ok(PartialNameRef(v.into()))    }}