Skip to content

Commit

Permalink
[ref #152] introduce Namespace type
Browse files Browse the repository at this point in the history
  • Loading branch information
Byron committed Aug 9, 2021
1 parent 138be95 commit 67d5c85
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 66 deletions.
69 changes: 7 additions & 62 deletions git-ref/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
//! * supersedes all of the above to allow handling hundreds of thousands of references.
#![forbid(unsafe_code)]
#![deny(missing_docs, rust_2018_idioms)]
use bstr::BStr;
use bstr::{BStr, BString};
use git_hash::oid;

mod store;
Expand All @@ -39,6 +39,10 @@ pub struct FullName<'a>(&'a BStr);
#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
pub struct PartialName<'a>(&'a BStr);

/// A validated prefix for references to act as a namespace.
#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
pub struct Namespace(BString);

/// Denotes the kind of reference.
#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
Expand All @@ -60,64 +64,5 @@ pub enum Target<'a> {
Symbolic(&'a BStr),
}

mod target {
use crate::{Kind, Target};
use bstr::BStr;
use git_hash::oid;

impl<'a> Target<'a> {
/// Returns the kind of the target the ref is pointing to.
pub fn kind(&self) -> Kind {
match self {
Target::Symbolic(_) => Kind::Symbolic,
Target::Peeled(_) => Kind::Peeled,
}
}
/// Interpret this target as object id which maybe `None` if it is symbolic.
pub fn as_id(&self) -> Option<&oid> {
match self {
Target::Symbolic(_) => None,
Target::Peeled(oid) => Some(oid),
}
}
/// Interpret this target as name of the reference it points to which maybe `None` if it an object id.
pub fn as_name(&self) -> Option<&BStr> {
match self {
Target::Symbolic(path) => Some(path),
Target::Peeled(_) => None,
}
}
/// Convert this instance into an owned version, without consuming it.
pub fn to_owned(self) -> crate::mutable::Target {
self.into()
}
}
}

mod parse {
use bstr::{BStr, ByteSlice};
use nom::{
branch::alt,
bytes::complete::{tag, take_while_m_n},
error::ParseError,
IResult,
};

fn is_hex_digit_lc(b: u8) -> bool {
matches!(b, b'0'..=b'9' | b'a'..=b'f')
}

/// Copy from https://github.com/Byron/gitoxide/blob/f270850ff92eab15258023b8e59346ec200303bd/git-object/src/immutable/parse.rs#L64
pub fn hex_hash<'a, E: ParseError<&'a [u8]>>(i: &'a [u8]) -> IResult<&'a [u8], &'a BStr, E> {
take_while_m_n(
git_hash::Kind::shortest().len_in_hex(),
git_hash::Kind::longest().len_in_hex(),
is_hex_digit_lc,
)(i)
.map(|(i, hex)| (i, hex.as_bstr()))
}

pub fn newline<'a, E: ParseError<&'a [u8]>>(i: &'a [u8]) -> IResult<&'a [u8], &'a [u8], E> {
alt((tag(b"\r\n"), tag(b"\n")))(i)
}
}
mod parse;
mod target;
19 changes: 15 additions & 4 deletions git-ref/src/namespace.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
use crate::PartialName;
use bstr::{BString, ByteSlice, ByteVec};
use crate::{Namespace, PartialName};
use bstr::{BStr, BString, ByteSlice, ByteVec};
use std::convert::TryInto;

impl Namespace {
/// Dissolve ourselves into the interior representation
pub fn into_bstring(self) -> BString {
self.0
}
/// Return ourselves as
pub fn as_bstr(&self) -> &BStr {
self.0.as_ref()
}
}

/// Given a `namespace` 'foo we output 'refs/namespaces/foo', and given 'foo/bar' we output 'refs/namespaces/foo/refs/namespaces/bar'.
///
/// For more information, consult the [git namespace documentation](https://git-scm.com/docs/gitnamespaces).
pub fn expand<'a, Name, E>(namespace: Name) -> Result<crate::mutable::FullName, git_validate::refname::Error>
pub fn expand<'a, Name, E>(namespace: Name) -> Result<Namespace, git_validate::refname::Error>
where
Name: TryInto<PartialName<'a>, Error = E>,
git_validate::refname::Error: From<E>,
Expand All @@ -22,5 +33,5 @@ where
git_validate::reference::name(out.as_ref()).is_ok(),
"we always produce valid ref names"
);
Ok(crate::mutable::FullName(out))
Ok(Namespace(out))
}
25 changes: 25 additions & 0 deletions git-ref/src/parse.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use bstr::{BStr, ByteSlice};
use nom::{
branch::alt,
bytes::complete::{tag, take_while_m_n},
error::ParseError,
IResult,
};

fn is_hex_digit_lc(b: u8) -> bool {
matches!(b, b'0'..=b'9' | b'a'..=b'f')
}

/// Copy from https://github.com/Byron/gitoxide/blob/f270850ff92eab15258023b8e59346ec200303bd/git-object/src/immutable/parse.rs#L64
pub fn hex_hash<'a, E: ParseError<&'a [u8]>>(i: &'a [u8]) -> IResult<&'a [u8], &'a BStr, E> {
take_while_m_n(
git_hash::Kind::shortest().len_in_hex(),
git_hash::Kind::longest().len_in_hex(),
is_hex_digit_lc,
)(i)
.map(|(i, hex)| (i, hex.as_bstr()))
}

pub fn newline<'a, E: ParseError<&'a [u8]>>(i: &'a [u8]) -> IResult<&'a [u8], &'a [u8], E> {
alt((tag(b"\r\n"), tag(b"\n")))(i)
}
31 changes: 31 additions & 0 deletions git-ref/src/target.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use crate::{Kind, Target};
use bstr::BStr;
use git_hash::oid;

impl<'a> Target<'a> {
/// Returns the kind of the target the ref is pointing to.
pub fn kind(&self) -> Kind {
match self {
Target::Symbolic(_) => Kind::Symbolic,
Target::Peeled(_) => Kind::Peeled,
}
}
/// Interpret this target as object id which maybe `None` if it is symbolic.
pub fn as_id(&self) -> Option<&oid> {
match self {
Target::Symbolic(_) => None,
Target::Peeled(oid) => Some(oid),
}
}
/// Interpret this target as name of the reference it points to which maybe `None` if it an object id.
pub fn as_name(&self) -> Option<&BStr> {
match self {
Target::Symbolic(path) => Some(path),
Target::Peeled(_) => None,
}
}
/// Convert this instance into an owned version, without consuming it.
pub fn to_owned(self) -> crate::mutable::Target {
self.into()
}
}

0 comments on commit 67d5c85

Please sign in to comment.