//! A crate for handling the references stored in various formats in a git repository. //! //! References are also called _refs_ which are used interchangeably. //! //! Refs are the way to keep track of objects and come in two flavors. //! //! * symbolic refs are pointing to another reference //! * peeled refs point to the an object by its [ObjectId][git_hash::ObjectId] //! //! They can be identified by a relative path and stored in various flavors. //! //! * **files** //! * **[loose][file::Store]** //! * one reference maps to a file on disk //! * **packed** //! * references are stored in a single human-readable file, along with their targets if they are symbolic. //! * **ref-table** //! * 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 git_hash::oid; mod store; pub use store::{file, packed}; /// pub mod mutable; /// pub mod name; /// pub mod transaction; /// A validated and potentially partial reference name - it can safely be used for common operations. #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)] pub struct FullName<'a>(&'a BStr); /// A validated complete and fully qualified reference name, safe to use for all operations. #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)] pub struct PartialName<'a>(&'a BStr); /// Denotes the kind of reference. #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)] #[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] pub enum Kind { /// A ref that points to an object id Peeled, /// A ref that points to another reference, adding a level of indirection. /// /// It can be resolved to an id using the [`peel_in_place_to_id()`][file::Reference::peel_to_id_in_place()] method. Symbolic, } /// Denotes a ref target, equivalent to [`Kind`], but with immutable data. #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)] pub enum Target<'a> { /// A ref that points to an object id Peeled(&'a oid), /// A ref that points to another reference by its validated name, adding a level of indirection. 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) } }