From 708fc5abd8af4dd7459f388c7092bf35915c6662 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 26 Aug 2021 13:28:52 +0800 Subject: [PATCH 01/18] Release git-object v0.13.0 --- Cargo.lock | 2 +- git-diff/Cargo.toml | 2 +- git-object/Cargo.toml | 2 +- git-odb/Cargo.toml | 2 +- git-pack/Cargo.toml | 2 +- git-ref/Cargo.toml | 2 +- git-repository/Cargo.toml | 2 +- git-traverse/Cargo.toml | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 06af5eee446..a6db1c6a981 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1079,7 +1079,7 @@ dependencies = [ [[package]] name = "git-object" -version = "0.12.2" +version = "0.13.0" dependencies = [ "bstr", "git-actor", diff --git a/git-diff/Cargo.toml b/git-diff/Cargo.toml index 41082f880f3..4bfd81c0ebd 100644 --- a/git-diff/Cargo.toml +++ b/git-diff/Cargo.toml @@ -15,7 +15,7 @@ doctest = false [dependencies] git-hash = { version = "^0.5.0", path = "../git-hash" } -git-object = { version ="0.12.0", path = "../git-object" } +git-object = { version ="^0.13.0", path = "../git-object" } quick-error = "2.0.0" [dev-dependencies] diff --git a/git-object/Cargo.toml b/git-object/Cargo.toml index 11fb434e006..e5066684842 100644 --- a/git-object/Cargo.toml +++ b/git-object/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "git-object" -version = "0.12.2" +version = "0.13.0" description = "Immutable and mutable git objects with decoding and encoding support" authors = ["Sebastian Thiel "] repository = "https://github.com/Byron/gitoxide" diff --git a/git-odb/Cargo.toml b/git-odb/Cargo.toml index 3c71ce5b21c..c1d6b112d51 100644 --- a/git-odb/Cargo.toml +++ b/git-odb/Cargo.toml @@ -30,7 +30,7 @@ all-features = true [dependencies] git-features = { version = "^0.16.0", path = "../git-features", features = ["rustsha1", "walkdir", "zlib"] } git-hash = { version = "^0.5.0", path = "../git-hash" } -git-object = { version ="0.12.0", path = "../git-object" } +git-object = { version ="^0.13.0", path = "../git-object" } git-pack = { version ="^0.9.0", path = "../git-pack" } btoi = "0.4.2" diff --git a/git-pack/Cargo.toml b/git-pack/Cargo.toml index d6c236f702e..b3821c031a8 100644 --- a/git-pack/Cargo.toml +++ b/git-pack/Cargo.toml @@ -34,7 +34,7 @@ all-features = true [dependencies] git-features = { version = "^0.16.0", path = "../git-features", features = ["crc32", "rustsha1", "progress", "zlib"] } git-hash = { version = "^0.5.0", path = "../git-hash" } -git-object = { version ="0.12.0", path = "../git-object" } +git-object = { version ="^0.13.0", path = "../git-object" } git-traverse = { version ="0.7.0", path = "../git-traverse" } git-diff = { version ="0.8.0", path = "../git-diff" } git-tempfile = { version ="^1.0.0", path = "../git-tempfile" } diff --git a/git-ref/Cargo.toml b/git-ref/Cargo.toml index 0f1f7e081c3..43139a4607d 100644 --- a/git-ref/Cargo.toml +++ b/git-ref/Cargo.toml @@ -26,7 +26,7 @@ required-features = ["internal-testing-git-features-parallel"] [dependencies] git-features = { version = "^0.16.0", path = "../git-features", features = ["walkdir"]} git-hash = { version = "^0.5.0", path = "../git-hash" } -git-object = { version ="0.12.0", path = "../git-object" } +git-object = { version ="^0.13.0", path = "../git-object" } git-validate = { version = "^0.5.0", path = "../git-validate" } git-actor = { version ="^0.5.0", path = "../git-actor" } git-lock = { version ="^1.0.0", path = "../git-lock" } diff --git a/git-repository/Cargo.toml b/git-repository/Cargo.toml index b80b91c7c53..473f1102498 100644 --- a/git-repository/Cargo.toml +++ b/git-repository/Cargo.toml @@ -41,7 +41,7 @@ git-validate = { version = "^0.5.0", path = "../git-validate" } git-odb = { version ="0.20.0", path = "../git-odb" } git-hash = { version = "^0.5.0", path = "../git-hash" } -git-object = { version ="0.12.0", path = "../git-object" } +git-object = { version ="^0.13.0", path = "../git-object" } git-actor = { version ="^0.5.0", path = "../git-actor" } git-pack = { version ="^0.9.0", path = "../git-pack" } diff --git a/git-traverse/Cargo.toml b/git-traverse/Cargo.toml index 03f45027e56..b14b15590da 100644 --- a/git-traverse/Cargo.toml +++ b/git-traverse/Cargo.toml @@ -15,7 +15,7 @@ doctest = false [dependencies] git-hash = { version = "^0.5.0", path = "../git-hash" } -git-object = { version ="0.12.0", path = "../git-object" } +git-object = { version ="^0.13.0", path = "../git-object" } quick-error = "2.0.0" [dev-dependencies] From 6deb01291fb382b7fb9206682e319afa81bacc05 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 26 Aug 2021 13:38:40 +0800 Subject: [PATCH 02/18] [object #177] rename immutable::* to immutable::*Ref --- git-object/src/commit.rs | 4 +- git-object/src/immutable/blob.rs | 8 +- git-object/src/immutable/commit/decode.rs | 8 +- git-object/src/immutable/commit/iter.rs | 12 +- git-object/src/immutable/commit/mod.rs | 6 +- git-object/src/immutable/mod.rs | 8 +- git-object/src/immutable/object.rs | 116 +++++++++--------- git-object/src/immutable/tag.rs | 24 ++-- git-object/src/mutable/convert.rs | 28 ++--- git-object/src/mutable/mod.rs | 4 +- git-object/tests/immutable/commit.rs | 65 +++++----- git-object/tests/immutable/tag.rs | 43 ++++--- git-object/tests/mutable/mod.rs | 8 +- git-odb/tests/odb/store/loose/backend.rs | 6 +- git-pack/src/data/object.rs | 20 +-- git-pack/src/data/output/count/objects.rs | 10 +- git-pack/src/find.rs | 19 +-- git-pack/src/index/verify.rs | 2 +- .../src/store/file/loose/reference/peel.rs | 2 +- git-ref/src/store/packed/transaction.rs | 2 +- git-repository/src/easy/object/mod.rs | 4 +- git-repository/src/ext/object_id.rs | 4 +- git-traverse/src/commit.rs | 6 +- gitoxide-core/src/hours.rs | 4 +- 24 files changed, 212 insertions(+), 201 deletions(-) diff --git a/git-object/src/commit.rs b/git-object/src/commit.rs index d932c07eda5..c66d387eccc 100644 --- a/git-object/src/commit.rs +++ b/git-object/src/commit.rs @@ -30,8 +30,8 @@ where /// /// A merge tag is a tag object embedded within the respective header field of a commit, making /// it a child object of sorts. - pub fn mergetags(self) -> impl Iterator, immutable::object::decode::Error>> { - self.find_all("mergetag").map(|b| immutable::Tag::from_bytes(b)) + pub fn mergetags(self) -> impl Iterator, immutable::object::decode::Error>> { + self.find_all("mergetag").map(|b| immutable::TagRef::from_bytes(b)) } /// Return the cryptographic signature provided by gpg/pgp verbatim. diff --git a/git-object/src/immutable/blob.rs b/git-object/src/immutable/blob.rs index e5ea698116d..7097140bb96 100644 --- a/git-object/src/immutable/blob.rs +++ b/git-object/src/immutable/blob.rs @@ -3,14 +3,14 @@ use std::convert::Infallible; /// A chunk of any [`data`][Blob::data]. #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] #[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] -pub struct Blob<'a> { +pub struct BlobRef<'a> { /// The bytes themselves. pub data: &'a [u8], } -impl<'a> Blob<'a> { +impl<'a> BlobRef<'a> { /// Instantiate a `Blob` from the given `data`, which is used as-is. - pub fn from_bytes(data: &[u8]) -> Result, Infallible> { - Ok(Blob { data }) + pub fn from_bytes(data: &[u8]) -> Result, Infallible> { + Ok(BlobRef { data }) } } diff --git a/git-object/src/immutable/commit/decode.rs b/git-object/src/immutable/commit/decode.rs index 812ba761d5e..4be0d6c1d3b 100644 --- a/git-object/src/immutable/commit/decode.rs +++ b/git-object/src/immutable/commit/decode.rs @@ -11,7 +11,7 @@ use nom::{ use smallvec::SmallVec; use crate::{ - immutable::{parse, parse::NL, Commit}, + immutable::{parse, parse::NL, CommitRef}, BStr, ByteSlice, }; @@ -28,7 +28,9 @@ pub fn message<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(i: &'a [u8] Ok((&[], i.as_bstr())) } -pub fn commit<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(i: &'a [u8]) -> IResult<&'a [u8], Commit<'_>, E> { +pub fn commit<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>( + i: &'a [u8], +) -> IResult<&'a [u8], CommitRef<'_>, E> { let (i, tree) = context("tree <40 lowercase hex char>", |i| { parse::header_field(i, b"tree", parse::hex_hash) })(i)?; @@ -59,7 +61,7 @@ pub fn commit<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(i: &'a [u8]) Ok(( i, - Commit { + CommitRef { tree, parents: SmallVec::from(parents), author, diff --git a/git-object/src/immutable/commit/iter.rs b/git-object/src/immutable/commit/iter.rs index 37134bb3754..05e4bc5fac4 100644 --- a/git-object/src/immutable/commit/iter.rs +++ b/git-object/src/immutable/commit/iter.rs @@ -37,15 +37,15 @@ impl Default for State { /// Like [`signature_ref::Commit`][super::Commit], but as `Iterator` to support (up to) entirely allocation free parsing. /// It's particularly useful to traverse the commit graph without ever allocating arrays for parents. -pub struct Iter<'a> { +pub struct RefIter<'a> { data: &'a [u8], state: State, } -impl<'a> Iter<'a> { +impl<'a> RefIter<'a> { /// Create a commit iterator from data. - pub fn from_bytes(data: &'a [u8]) -> Iter<'a> { - Iter { + pub fn from_bytes(data: &'a [u8]) -> RefIter<'a> { + RefIter { data, state: State::default(), } @@ -77,7 +77,7 @@ impl<'a> Iter<'a> { } } -impl<'a> Iter<'a> { +impl<'a> RefIter<'a> { fn next_inner(i: &'a [u8], state: &mut State) -> Result<(&'a [u8], Token<'a>), object::decode::Error> { use State::*; Ok(match state { @@ -176,7 +176,7 @@ impl<'a> Iter<'a> { } } -impl<'a> Iterator for Iter<'a> { +impl<'a> Iterator for RefIter<'a> { type Item = Result, object::decode::Error>; fn next(&mut self) -> Option { diff --git a/git-object/src/immutable/commit/mod.rs b/git-object/src/immutable/commit/mod.rs index f5498e69a99..21661b3cda4 100644 --- a/git-object/src/immutable/commit/mod.rs +++ b/git-object/src/immutable/commit/mod.rs @@ -15,7 +15,7 @@ pub mod iter; /// change which is documented in the commit `message`. #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] #[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] -pub struct Commit<'a> { +pub struct CommitRef<'a> { /// HEX hash of tree object we point to. Usually 40 bytes long. /// /// Use [`tree()`][Commit::tree()] to obtain a decoded version of it. @@ -38,9 +38,9 @@ pub struct Commit<'a> { pub extra_headers: Vec<(&'a BStr, Cow<'a, BStr>)>, } -impl<'a> Commit<'a> { +impl<'a> CommitRef<'a> { /// Deserialize a commit from the given `data` bytes while avoiding most allocations. - pub fn from_bytes(data: &'a [u8]) -> Result, object::decode::Error> { + pub fn from_bytes(data: &'a [u8]) -> Result, object::decode::Error> { decode::commit(data) .map(|(_, t)| t) .map_err(object::decode::Error::from) diff --git a/git-object/src/immutable/mod.rs b/git-object/src/immutable/mod.rs index 64b9ccc648f..e9419203fc8 100644 --- a/git-object/src/immutable/mod.rs +++ b/git-object/src/immutable/mod.rs @@ -5,19 +5,19 @@ //! which support mutation and serialization. mod blob; -pub use blob::Blob; +pub use blob::BlobRef; /// pub mod commit; -pub use commit::{iter::Iter as CommitIter, Commit}; +pub use commit::{iter::RefIter as CommitRefIter, CommitRef}; /// pub mod object; -pub use object::Object; +pub use object::ObjectRef; /// pub mod tag; -pub use tag::{iter::Iter as TagIter, Tag}; +pub use tag::{iter::RefIter as TagRefIter, TagRef}; /// pub mod tree; diff --git a/git-object/src/immutable/object.rs b/git-object/src/immutable/object.rs index ffb25d7f626..7f546013483 100644 --- a/git-object/src/immutable/object.rs +++ b/git-object/src/immutable/object.rs @@ -1,6 +1,6 @@ use crate::{ immutable, - immutable::{Blob, Commit, Tag, Tree}, + immutable::{BlobRef, CommitRef, TagRef, Tree}, Kind, }; @@ -8,22 +8,22 @@ use crate::{ #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] #[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] #[allow(missing_docs)] -pub enum Object<'a> { +pub enum ObjectRef<'a> { #[cfg_attr(feature = "serde1", serde(borrow))] Tree(Tree<'a>), - Blob(Blob<'a>), - Commit(Commit<'a>), - Tag(Tag<'a>), + Blob(BlobRef<'a>), + Commit(CommitRef<'a>), + Tag(TagRef<'a>), } -impl<'a> Object<'a> { +impl<'a> ObjectRef<'a> { /// Deserialize an object of `kind` from the given `data`. - pub fn from_bytes(kind: Kind, data: &'a [u8]) -> Result, decode::Error> { + pub fn from_bytes(kind: Kind, data: &'a [u8]) -> Result, decode::Error> { Ok(match kind { - Kind::Tree => Object::Tree(Tree::from_bytes(data)?), - Kind::Blob => Object::Blob(Blob { data }), - Kind::Commit => Object::Commit(Commit::from_bytes(data)?), - Kind::Tag => Object::Tag(Tag::from_bytes(data)?), + Kind::Tree => ObjectRef::Tree(Tree::from_bytes(data)?), + Kind::Blob => ObjectRef::Blob(BlobRef { data }), + Kind::Commit => ObjectRef::Commit(CommitRef::from_bytes(data)?), + Kind::Tag => ObjectRef::Tag(TagRef::from_bytes(data)?), }) } @@ -43,70 +43,70 @@ impl<'a> Object<'a> { } /// Convenient access to contained objects. -impl<'a> Object<'a> { +impl<'a> ObjectRef<'a> { /// Interpret this object as blob. - pub fn as_blob(&self) -> Option<&immutable::Blob<'a>> { + pub fn as_blob(&self) -> Option<&immutable::BlobRef<'a>> { match self { - Object::Blob(v) => Some(v), + ObjectRef::Blob(v) => Some(v), _ => None, } } /// Interpret this object as blob, chainable. - pub fn into_blob(self) -> Option> { + pub fn into_blob(self) -> Option> { match self { - Object::Blob(v) => Some(v), + ObjectRef::Blob(v) => Some(v), _ => None, } } /// Interpret this object as commit. - pub fn as_commit(&self) -> Option<&immutable::Commit<'a>> { + pub fn as_commit(&self) -> Option<&immutable::CommitRef<'a>> { match self { - Object::Commit(v) => Some(v), + ObjectRef::Commit(v) => Some(v), _ => None, } } /// Interpret this object as commit, chainable. - pub fn into_commit(self) -> Option> { + pub fn into_commit(self) -> Option> { match self { - Object::Commit(v) => Some(v), + ObjectRef::Commit(v) => Some(v), _ => None, } } /// Interpret this object as tree. pub fn as_tree(&self) -> Option<&immutable::Tree<'a>> { match self { - Object::Tree(v) => Some(v), + ObjectRef::Tree(v) => Some(v), _ => None, } } /// Interpret this object as tree, chainable pub fn into_tree(self) -> Option> { match self { - Object::Tree(v) => Some(v), + ObjectRef::Tree(v) => Some(v), _ => None, } } /// Interpret this object as tag. - pub fn as_tag(&self) -> Option<&immutable::Tag<'a>> { + pub fn as_tag(&self) -> Option<&immutable::TagRef<'a>> { match self { - Object::Tag(v) => Some(v), + ObjectRef::Tag(v) => Some(v), _ => None, } } /// Interpret this object as tag, chainable. - pub fn into_tag(self) -> Option> { + pub fn into_tag(self) -> Option> { match self { - Object::Tag(v) => Some(v), + ObjectRef::Tag(v) => Some(v), _ => None, } } /// Return the kind of object. pub fn kind(&self) -> Kind { match self { - Object::Tree(_) => Kind::Tree, - Object::Blob(_) => Kind::Blob, - Object::Commit(_) => Kind::Commit, - Object::Tag(_) => Kind::Tag, + ObjectRef::Tree(_) => Kind::Tree, + ObjectRef::Blob(_) => Kind::Blob, + ObjectRef::Commit(_) => Kind::Commit, + ObjectRef::Tag(_) => Kind::Tag, } } } @@ -114,71 +114,71 @@ impl<'a> Object<'a> { mod convert { use std::convert::TryFrom; - use crate::immutable::{Blob, Commit, Object, Tag, Tree}; + use crate::immutable::{BlobRef, CommitRef, ObjectRef, TagRef, Tree}; - impl<'a> From> for Object<'a> { - fn from(v: Tag<'a>) -> Self { - Object::Tag(v) + impl<'a> From> for ObjectRef<'a> { + fn from(v: TagRef<'a>) -> Self { + ObjectRef::Tag(v) } } - impl<'a> From> for Object<'a> { - fn from(v: Commit<'a>) -> Self { - Object::Commit(v) + impl<'a> From> for ObjectRef<'a> { + fn from(v: CommitRef<'a>) -> Self { + ObjectRef::Commit(v) } } - impl<'a> From> for Object<'a> { + impl<'a> From> for ObjectRef<'a> { fn from(v: Tree<'a>) -> Self { - Object::Tree(v) + ObjectRef::Tree(v) } } - impl<'a> From> for Object<'a> { - fn from(v: Blob<'a>) -> Self { - Object::Blob(v) + impl<'a> From> for ObjectRef<'a> { + fn from(v: BlobRef<'a>) -> Self { + ObjectRef::Blob(v) } } - impl<'a> TryFrom> for Tag<'a> { - type Error = Object<'a>; + impl<'a> TryFrom> for TagRef<'a> { + type Error = ObjectRef<'a>; - fn try_from(value: Object<'a>) -> Result { + fn try_from(value: ObjectRef<'a>) -> Result { Ok(match value { - Object::Tag(v) => v, + ObjectRef::Tag(v) => v, _ => return Err(value), }) } } - impl<'a> TryFrom> for Commit<'a> { - type Error = Object<'a>; + impl<'a> TryFrom> for CommitRef<'a> { + type Error = ObjectRef<'a>; - fn try_from(value: Object<'a>) -> Result { + fn try_from(value: ObjectRef<'a>) -> Result { Ok(match value { - Object::Commit(v) => v, + ObjectRef::Commit(v) => v, _ => return Err(value), }) } } - impl<'a> TryFrom> for Tree<'a> { - type Error = Object<'a>; + impl<'a> TryFrom> for Tree<'a> { + type Error = ObjectRef<'a>; - fn try_from(value: Object<'a>) -> Result { + fn try_from(value: ObjectRef<'a>) -> Result { Ok(match value { - Object::Tree(v) => v, + ObjectRef::Tree(v) => v, _ => return Err(value), }) } } - impl<'a> TryFrom> for Blob<'a> { - type Error = Object<'a>; + impl<'a> TryFrom> for BlobRef<'a> { + type Error = ObjectRef<'a>; - fn try_from(value: Object<'a>) -> Result { + fn try_from(value: ObjectRef<'a>) -> Result { Ok(match value { - Object::Blob(v) => v, + ObjectRef::Blob(v) => v, _ => return Err(value), }) } diff --git a/git-object/src/immutable/tag.rs b/git-object/src/immutable/tag.rs index 70d7c42fa49..ae5a1ad02fb 100644 --- a/git-object/src/immutable/tag.rs +++ b/git-object/src/immutable/tag.rs @@ -3,7 +3,7 @@ use crate::{immutable::object, BStr}; /// Represents a git tag, commonly indicating a software release. #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] #[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] -pub struct Tag<'a> { +pub struct TagRef<'a> { /// The hash in hexadecimal being the object this tag points to. Use [`target()`][Tag::target()] to obtain a byte representation. #[cfg_attr(feature = "serde1", serde(borrow))] pub target: &'a BStr, @@ -19,9 +19,9 @@ pub struct Tag<'a> { pub pgp_signature: Option<&'a BStr>, } -impl<'a> Tag<'a> { +impl<'a> TagRef<'a> { /// Deserialize a tag from `data`. - pub fn from_bytes(data: &'a [u8]) -> Result, object::decode::Error> { + pub fn from_bytes(data: &'a [u8]) -> Result, object::decode::Error> { decode::git_tag(data) .map(|(_, t)| t) .map_err(object::decode::Error::from) @@ -44,11 +44,11 @@ mod decode { }; use crate::{ - immutable::{parse, parse::NL, Tag}, + immutable::{parse, parse::NL, TagRef}, BStr, ByteSlice, }; - pub fn git_tag<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(i: &'a [u8]) -> IResult<&[u8], Tag<'a>, E> { + pub fn git_tag<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(i: &'a [u8]) -> IResult<&[u8], TagRef<'a>, E> { let (i, target) = context("object <40 lowercase hex char>", |i| { parse::header_field(i, b"object", parse::hex_hash) })(i)?; @@ -70,7 +70,7 @@ mod decode { let (i, (message, pgp_signature)) = all_consuming(message)(i)?; Ok(( i, - Tag { + TagRef { target, name: tag_version.as_bstr(), target_kind: kind, @@ -160,15 +160,15 @@ pub mod iter { /// Like [`signature_ref::Tag`][super::Tag], but as `Iterator` to support entirely allocation free parsing. /// It's particularly useful to dereference only the target chain. - pub struct Iter<'a> { + pub struct RefIter<'a> { data: &'a [u8], state: State, } - impl<'a> Iter<'a> { + impl<'a> RefIter<'a> { /// Create a tag iterator from data. - pub fn from_bytes(data: &'a [u8]) -> Iter<'a> { - Iter { + pub fn from_bytes(data: &'a [u8]) -> RefIter<'a> { + RefIter { data, state: State::default(), } @@ -186,7 +186,7 @@ pub mod iter { } } - impl<'a> Iter<'a> { + impl<'a> RefIter<'a> { fn next_inner(i: &'a [u8], state: &mut State) -> Result<(&'a [u8], Token<'a>), object::decode::Error> { use State::*; Ok(match state { @@ -240,7 +240,7 @@ pub mod iter { } } - impl<'a> Iterator for Iter<'a> { + impl<'a> Iterator for RefIter<'a> { type Item = Result, object::decode::Error>; fn next(&mut self) -> Option { diff --git a/git-object/src/mutable/convert.rs b/git-object/src/mutable/convert.rs index e5325324772..f15e04fb95d 100644 --- a/git-object/src/mutable/convert.rs +++ b/git-object/src/mutable/convert.rs @@ -1,8 +1,8 @@ use crate::{immutable, mutable}; -impl From> for mutable::Tag { - fn from(other: immutable::Tag<'_>) -> mutable::Tag { - let immutable::Tag { +impl From> for mutable::Tag { + fn from(other: immutable::TagRef<'_>) -> mutable::Tag { + let immutable::TagRef { target, name, target_kind, @@ -21,9 +21,9 @@ impl From> for mutable::Tag { } } -impl From> for mutable::Commit { - fn from(other: immutable::Commit<'_>) -> mutable::Commit { - let immutable::Commit { +impl From> for mutable::Commit { + fn from(other: immutable::CommitRef<'_>) -> mutable::Commit { + let immutable::CommitRef { tree, parents, author, @@ -50,8 +50,8 @@ impl From> for mutable::Commit { } } -impl<'a> From> for mutable::Blob { - fn from(v: immutable::Blob<'a>) -> Self { +impl<'a> From> for mutable::Blob { + fn from(v: immutable::BlobRef<'a>) -> Self { mutable::Blob { data: v.data.to_owned(), } @@ -78,13 +78,13 @@ impl From> for mutable::tree::Entry { } } -impl<'a> From> for mutable::Object { - fn from(v: immutable::Object<'_>) -> Self { +impl<'a> From> for mutable::Object { + fn from(v: immutable::ObjectRef<'_>) -> Self { match v { - immutable::Object::Tree(v) => mutable::Object::Tree(v.into()), - immutable::Object::Blob(v) => mutable::Object::Blob(v.into()), - immutable::Object::Commit(v) => mutable::Object::Commit(v.into()), - immutable::Object::Tag(v) => mutable::Object::Tag(v.into()), + immutable::ObjectRef::Tree(v) => mutable::Object::Tree(v.into()), + immutable::ObjectRef::Blob(v) => mutable::Object::Blob(v.into()), + immutable::ObjectRef::Commit(v) => mutable::Object::Commit(v.into()), + immutable::ObjectRef::Tag(v) => mutable::Object::Tag(v.into()), } } } diff --git a/git-object/src/mutable/mod.rs b/git-object/src/mutable/mod.rs index a685298ac95..e15f66aa0da 100644 --- a/git-object/src/mutable/mod.rs +++ b/git-object/src/mutable/mod.rs @@ -1,8 +1,8 @@ //! Mutable objects with each field being separately allocated and changeable. //! //! Mutable objects are Commits, Trees, Blobs and Tags that can be changed and serialized. -//! They either created using object [construction][Object] or by [deserializing existing objects][crate::immutable::Object::from_bytes()] -//! and converting these [into mutable copies][crate::immutable::Object::into_mutable()] for adjustments. +//! They either created using object [construction][Object] or by [deserializing existing objects][crate::immutable::ObjectRef::from_bytes()] +//! and converting these [into mutable copies][crate::immutable::ObjectRef::into_mutable()] for adjustments. const NL: &[u8; 1] = b"\n"; const SPACE: &[u8; 1] = b" "; diff --git a/git-object/tests/immutable/commit.rs b/git-object/tests/immutable/commit.rs index 377d84b4187..4bbc67fd578 100644 --- a/git-object/tests/immutable/commit.rs +++ b/git-object/tests/immutable/commit.rs @@ -131,7 +131,7 @@ dS3aXZhRfaPqpdsWrMB9fY7ll+oyfw== =T+RI -----END PGP SIGNATURE-----"; mod method { - use git_object::immutable::Commit; + use git_object::immutable::CommitRef; use pretty_assertions::assert_eq; use crate::{hex_to_id, immutable::fixture_bytes}; @@ -139,7 +139,7 @@ mod method { #[test] fn tree() -> crate::Result { let fixture = fixture_bytes("commit", "unsigned.txt"); - let commit = Commit::from_bytes(&fixture)?; + let commit = CommitRef::from_bytes(&fixture)?; assert_eq!(commit.tree(), hex_to_id("1b2dfb4ac5e42080b682fc676e9738c94ce6d54d")); assert_eq!(commit.tree, "1b2dfb4ac5e42080b682fc676e9738c94ce6d54d"); Ok(()) @@ -149,7 +149,7 @@ mod method { mod iter { use git_object::{ bstr::ByteSlice, - immutable::{commit::iter::Token, CommitIter}, + immutable::{commit::iter::Token, CommitRefIter}, }; use crate::{ @@ -163,7 +163,7 @@ mod iter { #[test] fn newline_right_after_signature_multiline_header() -> crate::Result { let data = fixture_bytes("commit", "signed-whitespace.txt"); - let tokens = CommitIter::from_bytes(&data).collect::, _>>()?; + let tokens = CommitRefIter::from_bytes(&data).collect::, _>>()?; assert_eq!(tokens.len(), 7, "mainly a parsing exercise"); match tokens.last().expect("there are tokens") { Token::Message(msg) => { @@ -177,7 +177,7 @@ mod iter { #[test] fn signed_with_encoding() -> crate::Result { assert_eq!( - CommitIter::from_bytes(&fixture_bytes("commit", "signed-with-encoding.txt")) + CommitRefIter::from_bytes(&fixture_bytes("commit", "signed-with-encoding.txt")) .collect::, _>>()?, vec![ Token::Tree { @@ -203,7 +203,7 @@ mod iter { #[test] fn whitespace() -> crate::Result { assert_eq!( - CommitIter::from_bytes(&fixture_bytes("commit", "whitespace.txt")).collect::, _>>()?, + CommitRefIter::from_bytes(&fixture_bytes("commit", "whitespace.txt")).collect::, _>>()?, vec![ Token::Tree { id: hex_to_id("9bed6275068a0575243ba8409253e61af81ab2ff") @@ -226,7 +226,7 @@ mod iter { #[test] fn unsigned() -> crate::Result { assert_eq!( - CommitIter::from_bytes(&fixture_bytes("commit", "unsigned.txt")).collect::, _>>()?, + CommitRefIter::from_bytes(&fixture_bytes("commit", "unsigned.txt")).collect::, _>>()?, vec![ Token::Tree { id: hex_to_id("1b2dfb4ac5e42080b682fc676e9738c94ce6d54d") @@ -246,7 +246,8 @@ mod iter { #[test] fn signed_singleline() -> crate::Result { assert_eq!( - CommitIter::from_bytes(&fixture_bytes("commit", "signed-singleline.txt")).collect::, _>>()?, + CommitRefIter::from_bytes(&fixture_bytes("commit", "signed-singleline.txt")) + .collect::, _>>()?, vec![ Token::Tree { id: hex_to_id("00fc39317701176e326974ce44f5bd545a32ec0b") @@ -270,7 +271,7 @@ mod iter { #[test] fn error_handling() -> crate::Result { let data = fixture_bytes("commit", "unsigned.txt"); - let iter = CommitIter::from_bytes(&data[..data.len() / 2]); + let iter = CommitRefIter::from_bytes(&data[..data.len() / 2]); let tokens = iter.collect::>(); assert!( tokens.last().expect("at least the errored token").is_err(), @@ -282,7 +283,7 @@ mod iter { #[test] fn mergetag() -> crate::Result { assert_eq!( - CommitIter::from_bytes(&fixture_bytes("commit", "mergetag.txt")).collect::, _>>()?, + CommitRefIter::from_bytes(&fixture_bytes("commit", "mergetag.txt")).collect::, _>>()?, vec![ Token::Tree { id: hex_to_id("1c61918031bf2c7fab9e17dde3c52a6a9884fcb5") @@ -307,7 +308,7 @@ mod iter { } mod method { - use git_object::immutable::CommitIter; + use git_object::immutable::CommitRefIter; use crate::{ hex_to_id, @@ -317,11 +318,11 @@ mod iter { #[test] fn tree_id() -> crate::Result { assert_eq!( - CommitIter::from_bytes(&fixture_bytes("commit", "unsigned.txt")).tree_id(), + CommitRefIter::from_bytes(&fixture_bytes("commit", "unsigned.txt")).tree_id(), Some(hex_to_id("1b2dfb4ac5e42080b682fc676e9738c94ce6d54d")) ); assert_eq!( - CommitIter::from_bytes(&fixture_bytes("commit", "unsigned.txt")) + CommitRefIter::from_bytes(&fixture_bytes("commit", "unsigned.txt")) .signatures() .collect::>(), vec![signature(1592437401), signature(1592437401)] @@ -332,7 +333,7 @@ mod iter { #[test] fn signatures() -> crate::Result { assert_eq!( - CommitIter::from_bytes(&fixture_bytes("commit", "unsigned.txt")) + CommitRefIter::from_bytes(&fixture_bytes("commit", "unsigned.txt")) .signatures() .collect::>(), vec![signature(1592437401), signature(1592437401)] @@ -343,7 +344,7 @@ mod iter { } mod from_bytes { - use git_object::{bstr::ByteSlice, immutable::Commit}; + use git_object::{bstr::ByteSlice, immutable::CommitRef}; use smallvec::SmallVec; use crate::immutable::{ @@ -354,8 +355,8 @@ mod from_bytes { #[test] fn unsigned() -> crate::Result { assert_eq!( - Commit::from_bytes(&fixture_bytes("commit", "unsigned.txt"))?, - Commit { + CommitRef::from_bytes(&fixture_bytes("commit", "unsigned.txt"))?, + CommitRef { tree: b"1b2dfb4ac5e42080b682fc676e9738c94ce6d54d".as_bstr(), parents: SmallVec::default(), author: signature(1592437401), @@ -371,8 +372,8 @@ mod from_bytes { #[test] fn whitespace() -> crate::Result { assert_eq!( - Commit::from_bytes(&fixture_bytes("commit", "whitespace.txt"))?, - Commit { + CommitRef::from_bytes(&fixture_bytes("commit", "whitespace.txt"))?, + CommitRef { tree: b"9bed6275068a0575243ba8409253e61af81ab2ff".as_bstr(), parents: SmallVec::from(vec![b"26b4df046d1776c123ac69d918f5aec247b58cc6".as_bstr()]), author: signature(1592448450), @@ -388,8 +389,8 @@ mod from_bytes { #[test] fn signed_singleline() -> crate::Result { assert_eq!( - Commit::from_bytes(&fixture_bytes("commit", "signed-singleline.txt"))?, - Commit { + CommitRef::from_bytes(&fixture_bytes("commit", "signed-singleline.txt"))?, + CommitRef { tree: b"00fc39317701176e326974ce44f5bd545a32ec0b".as_bstr(), parents: SmallVec::from(vec![b"09d8d3a12e161a7f6afb522dbe8900a9c09bce06".as_bstr()]), author: signature(1592391367), @@ -405,7 +406,7 @@ mod from_bytes { #[test] fn mergetag() -> crate::Result { let fixture = fixture_bytes("commit", "mergetag.txt"); - let commit = Commit { + let commit = CommitRef { tree: b"1c61918031bf2c7fab9e17dde3c52a6a9884fcb5".as_bstr(), parents: SmallVec::from(vec![ b"44ebe016df3aad96e3be8f95ec52397728dd7701".as_bstr(), @@ -420,7 +421,7 @@ mod from_bytes { std::borrow::Cow::Owned(MERGE_TAG.as_bytes().into()), )], }; - assert_eq!(Commit::from_bytes(&fixture)?, commit); + assert_eq!(CommitRef::from_bytes(&fixture)?, commit); assert_eq!(commit.extra_headers().find_all("mergetag").count(), 1); assert_eq!(commit.extra_headers().mergetags().count(), 1); Ok(()) @@ -429,8 +430,8 @@ mod from_bytes { #[test] fn signed() -> crate::Result { assert_eq!( - Commit::from_bytes(&fixture_bytes("commit", "signed.txt"))?, - Commit { + CommitRef::from_bytes(&fixture_bytes("commit", "signed.txt"))?, + CommitRef { tree: b"00fc39317701176e326974ce44f5bd545a32ec0b".as_bstr(), parents: SmallVec::from(vec![b"09d8d3a12e161a7f6afb522dbe8900a9c09bce06".as_bstr()]), author: signature(1592391367), @@ -446,8 +447,8 @@ mod from_bytes { #[test] fn signed_with_encoding() -> crate::Result { assert_eq!( - Commit::from_bytes(&fixture_bytes("commit", "signed-with-encoding.txt"))?, - Commit { + CommitRef::from_bytes(&fixture_bytes("commit", "signed-with-encoding.txt"))?, + CommitRef { tree: b"1973afa74d87b2bb73fa884aaaa8752aec43ea88".as_bstr(), parents: SmallVec::from(vec![b"79c51cc86923e2b8ca0ee5c4eb75e48027133f9a".as_bstr()]), author: signature(1592448995), @@ -463,8 +464,8 @@ mod from_bytes { #[test] fn with_encoding() -> crate::Result { assert_eq!( - Commit::from_bytes(&fixture_bytes("commit", "with-encoding.txt"))?, - Commit { + CommitRef::from_bytes(&fixture_bytes("commit", "with-encoding.txt"))?, + CommitRef { tree: b"4a1c03029e7407c0afe9fc0320b3258e188b115e".as_bstr(), parents: SmallVec::from(vec![b"7ca98aad461a5c302cb4c9e3acaaa6053cc67a62".as_bstr()]), author: signature(1592438199), @@ -480,8 +481,8 @@ mod from_bytes { #[test] fn merge() -> crate::Result { assert_eq!( - Commit::from_bytes(&fixture_bytes("commit", "merge.txt"))?, - Commit { + CommitRef::from_bytes(&fixture_bytes("commit", "merge.txt"))?, + CommitRef { tree: b"0cf16ce8e229b59a761198975f0c0263229faf82".as_bstr(), parents: SmallVec::from(vec![ b"6a6054db4ce3c1e4e6a37f8c4d7acb63a4d6ad71".as_bstr(), @@ -512,7 +513,7 @@ iyBBl69jASy41Ug/BlFJbw4+ItkShpXwkJKuBBV/JExChmvbxYWaS7QnyYC9UO0= #[test] fn newline_right_after_signature_multiline_header() -> crate::Result { let fixture = fixture_bytes("commit", "signed-whitespace.txt"); - let commit = Commit::from_bytes(&fixture)?; + let commit = CommitRef::from_bytes(&fixture)?; let pgp_sig = OTHER_SIGNATURE.as_bstr(); assert_eq!(commit.extra_headers[0].1.as_ref(), pgp_sig); assert_eq!(commit.extra_headers().pgp_signature(), Some(pgp_sig)); diff --git a/git-object/tests/immutable/tag.rs b/git-object/tests/immutable/tag.rs index 76aa22633c9..17e3fce158c 100644 --- a/git-object/tests/immutable/tag.rs +++ b/git-object/tests/immutable/tag.rs @@ -1,7 +1,7 @@ -use git_object::{bstr::ByteSlice, immutable::Tag, Kind}; +use git_object::{bstr::ByteSlice, immutable::TagRef, Kind}; mod method { - use git_object::immutable::Tag; + use git_object::immutable::TagRef; use pretty_assertions::assert_eq; use crate::{hex_to_id, immutable::fixture_bytes}; @@ -9,7 +9,7 @@ mod method { #[test] fn target() -> crate::Result { let fixture = fixture_bytes("tag", "signed.txt"); - let tag = Tag::from_bytes(&fixture)?; + let tag = TagRef::from_bytes(&fixture)?; assert_eq!(tag.target(), hex_to_id("ffa700b4aca13b80cb6b98a078e7c96804f8e0ec")); assert_eq!(tag.target, "ffa700b4aca13b80cb6b98a078e7c96804f8e0ec".as_bytes()); Ok(()) @@ -19,7 +19,7 @@ mod method { mod iter { use git_object::{ bstr::ByteSlice, - immutable::{tag::iter::Token, TagIter}, + immutable::{tag::iter::Token, TagRefIter}, Kind, }; @@ -31,7 +31,7 @@ mod iter { #[test] fn empty() -> crate::Result { assert_eq!( - TagIter::from_bytes(&fixture_bytes("tag", "empty.txt")).collect::, _>>()?, + TagRefIter::from_bytes(&fixture_bytes("tag", "empty.txt")).collect::, _>>()?, vec![ Token::Target { id: hex_to_id("01dd4e2a978a9f5bd773dae6da7aa4a5ac1cdbbc") @@ -47,7 +47,7 @@ mod iter { #[test] fn no_tagger() -> crate::Result { assert_eq!( - TagIter::from_bytes(&fixture_bytes("tag", "no-tagger.txt")).collect::, _>>()?, + TagRefIter::from_bytes(&fixture_bytes("tag", "no-tagger.txt")).collect::, _>>()?, vec![ Token::Target { id: hex_to_id("c39ae07f393806ccf406ef966e9a15afc43cc36a") @@ -83,7 +83,7 @@ KLMHist5yj0sw1E4hDTyQa0= #[test] fn whitespace() -> crate::Result { assert_eq!( - TagIter::from_bytes(&fixture_bytes("tag", "whitespace.txt")).collect::, _>>()?, + TagRefIter::from_bytes(&fixture_bytes("tag", "whitespace.txt")).collect::, _>>()?, vec![ Token::Target { id: hex_to_id("01dd4e2a978a9f5bd773dae6da7aa4a5ac1cdbbc") @@ -103,7 +103,7 @@ KLMHist5yj0sw1E4hDTyQa0= #[test] fn error_handling() -> crate::Result { let data = fixture_bytes("tag", "empty.txt"); - let iter = TagIter::from_bytes(&data[..data.len() / 2]); + let iter = TagRefIter::from_bytes(&data[..data.len() / 2]); let tokens = iter.collect::>(); assert!( tokens.last().expect("at least the errored token").is_err(), @@ -114,21 +114,24 @@ KLMHist5yj0sw1E4hDTyQa0= } mod from_bytes { - use git_object::{bstr::ByteSlice, immutable::Tag, Kind}; + use git_object::{bstr::ByteSlice, immutable::TagRef, Kind}; use crate::immutable::{fixture_bytes, signature, tag::tag_fixture}; #[test] fn signed() -> crate::Result { - assert_eq!(Tag::from_bytes(&fixture_bytes("tag", "signed.txt"))?, tag_fixture(9000)); + assert_eq!( + TagRef::from_bytes(&fixture_bytes("tag", "signed.txt"))?, + tag_fixture(9000) + ); Ok(()) } #[test] fn empty() -> crate::Result { assert_eq!( - Tag::from_bytes(&fixture_bytes("tag", "empty.txt"))?, - Tag { + TagRef::from_bytes(&fixture_bytes("tag", "empty.txt"))?, + TagRef { target: b"01dd4e2a978a9f5bd773dae6da7aa4a5ac1cdbbc".as_bstr(), name: b"empty".as_bstr(), target_kind: Kind::Commit, @@ -143,8 +146,8 @@ mod from_bytes { #[test] fn with_newlines() -> crate::Result { assert_eq!( - Tag::from_bytes(&fixture_bytes("tag", "with-newlines.txt"))?, - Tag { + TagRef::from_bytes(&fixture_bytes("tag", "with-newlines.txt"))?, + TagRef { target: b"ebdf205038b66108c0331aa590388431427493b7".as_bstr(), name: b"baz".as_bstr(), target_kind: Kind::Commit, @@ -159,8 +162,8 @@ mod from_bytes { #[test] fn no_tagger() -> crate::Result { assert_eq!( - Tag::from_bytes(&fixture_bytes("tag", "no-tagger.txt"))?, - Tag { + TagRef::from_bytes(&fixture_bytes("tag", "no-tagger.txt"))?, + TagRef { target: b"c39ae07f393806ccf406ef966e9a15afc43cc36a".as_bstr(), name: b"v2.6.11-tree".as_bstr(), target_kind: Kind::Tree, @@ -191,8 +194,8 @@ KLMHist5yj0sw1E4hDTyQa0= #[test] fn whitespace() -> crate::Result { assert_eq!( - Tag::from_bytes(&fixture_bytes("tag", "whitespace.txt"))?, - Tag { + TagRef::from_bytes(&fixture_bytes("tag", "whitespace.txt"))?, + TagRef { target: b"01dd4e2a978a9f5bd773dae6da7aa4a5ac1cdbbc".as_bstr(), name: b"whitespace".as_bstr(), target_kind: Kind::Commit, @@ -205,8 +208,8 @@ KLMHist5yj0sw1E4hDTyQa0= } } -fn tag_fixture(offset: i32) -> Tag<'static> { - Tag { +fn tag_fixture(offset: i32) -> TagRef<'static> { + TagRef { target: b"ffa700b4aca13b80cb6b98a078e7c96804f8e0ec".as_bstr(), name: b"1.0.0".as_bstr(), target_kind: Kind::Commit, diff --git a/git-object/tests/mutable/mod.rs b/git-object/tests/mutable/mod.rs index f7644c8ca2f..d28ed07416a 100644 --- a/git-object/tests/mutable/mod.rs +++ b/git-object/tests/mutable/mod.rs @@ -16,7 +16,7 @@ macro_rules! round_trip { assert_eq!(output.as_bstr(), input.as_bstr()); // Test the parse->borrowed->owned->write chain for the top-level objects - let item: mutable::Object = immutable::Object::from(<$borrowed>::from_bytes(&input)?).into(); + let item: mutable::Object = immutable::ObjectRef::from(<$borrowed>::from_bytes(&input)?).into(); output.clear(); item.write_to(&mut output)?; assert_eq!(output.as_bstr(), input.as_bstr()); @@ -30,7 +30,7 @@ mod object; mod tag { round_trip!( mutable::Tag, - immutable::Tag, + immutable::TagRef, "tag/empty.txt", "tag/no-tagger.txt", "tag/whitespace.txt", @@ -42,7 +42,7 @@ mod tag { mod commit { round_trip!( mutable::Commit, - immutable::Commit, + immutable::CommitRef, "commit/signed-whitespace.txt", "commit/two-multiline-headers.txt", "commit/mergetag.txt", @@ -62,5 +62,5 @@ mod tree { mod blob { // It doesn't matter which data we use - it's not interpreted. - round_trip!(mutable::Blob, immutable::Blob, "tree/everything.tree"); + round_trip!(mutable::Blob, immutable::BlobRef, "tree/everything.tree"); } diff --git a/git-odb/tests/odb/store/loose/backend.rs b/git-odb/tests/odb/store/loose/backend.rs index f94c8749f26..1c30ec3094e 100644 --- a/git-odb/tests/odb/store/loose/backend.rs +++ b/git-odb/tests/odb/store/loose/backend.rs @@ -75,7 +75,7 @@ mod locate { let o = locate("722fe60ad4f0276d5a8121970b5bb9dccdad4ef9", &mut buf); assert_eq!(o.kind, Kind::Tag); assert_eq!(o.data.len(), 1024); - let expected = immutable::Tag { + let expected = immutable::TagRef { target: b"ffa700b4aca13b80cb6b98a078e7c96804f8e0ec".as_bstr(), name: b"1.0.0".as_bstr(), target_kind: Kind::Commit, @@ -113,7 +113,7 @@ cjHJZXWmV4CcRfmLsXzU8s2cR9A0DBvOxhPD1TlKC2JhBFXigjuL9U4Rbq9tdegB let o = locate("ffa700b4aca13b80cb6b98a078e7c96804f8e0ec", &mut buf); assert_eq!(o.kind, Kind::Commit); assert_eq!(o.data.len(), 1084); - let expected = immutable::Commit { + let expected = immutable::CommitRef { tree: b"6ba2a0ded519f737fd5b8d5ccfb141125ef3176f".as_bstr(), parents: vec![].into(), author: signature(1528473303), @@ -141,7 +141,7 @@ cjHJZXWmV4CcRfmLsXzU8s2cR9A0DBvOxhPD1TlKC2JhBFXigjuL9U4Rbq9tdegB let o = locate("37d4e6c5c48ba0d245164c4e10d5f41140cab980", &mut buf); assert_eq!( o.decode()?.as_blob().expect("blob"), - &immutable::Blob { + &immutable::BlobRef { data: &[104, 105, 32, 116, 104, 101, 114, 101, 10] }, "small blobs are treated similarly to other object types and are read into memory at once when the header is read" diff --git a/git-pack/src/data/object.rs b/git-pack/src/data/object.rs index fe1433e6c18..d86e72ba9e9 100644 --- a/git-pack/src/data/object.rs +++ b/git-pack/src/data/object.rs @@ -26,13 +26,13 @@ impl<'a> Object<'a> { /// conveniently. The cost of parsing an object is negligible. /// /// **Note** that [mutable, decoded objects][git_object::mutable::Object] can be created from a [`crate::data::Object`] - /// using [`git_object::immutable::Object::into_mutable()`]. - pub fn decode(&self) -> Result, immutable::object::decode::Error> { + /// using [`git_object::immutable::ObjectRef::into_mutable()`]. + pub fn decode(&self) -> Result, immutable::object::decode::Error> { Ok(match self.kind { - git_object::Kind::Tree => immutable::Object::Tree(immutable::Tree::from_bytes(self.data)?), - git_object::Kind::Blob => immutable::Object::Blob(immutable::Blob { data: self.data }), - git_object::Kind::Commit => immutable::Object::Commit(immutable::Commit::from_bytes(self.data)?), - git_object::Kind::Tag => immutable::Object::Tag(immutable::Tag::from_bytes(self.data)?), + git_object::Kind::Tree => immutable::ObjectRef::Tree(immutable::Tree::from_bytes(self.data)?), + git_object::Kind::Blob => immutable::ObjectRef::Blob(immutable::BlobRef { data: self.data }), + git_object::Kind::Commit => immutable::ObjectRef::Commit(immutable::CommitRef::from_bytes(self.data)?), + git_object::Kind::Tag => immutable::ObjectRef::Tag(immutable::TagRef::from_bytes(self.data)?), }) } @@ -47,18 +47,18 @@ impl<'a> Object<'a> { /// Returns this object as commit iterator to parse tokens one at a time to avoid allocations, or /// `None` if this is not a commit object. - pub fn into_commit_iter(self) -> Option> { + pub fn into_commit_iter(self) -> Option> { match self.kind { - git_object::Kind::Commit => Some(immutable::CommitIter::from_bytes(self.data)), + git_object::Kind::Commit => Some(immutable::CommitRefIter::from_bytes(self.data)), _ => None, } } /// Returns this object as tag iterator to parse tokens one at a time to avoid allocations, or /// `None` if this is not a tag object. - pub fn into_tag_iter(self) -> Option> { + pub fn into_tag_iter(self) -> Option> { match self.kind { - git_object::Kind::Tag => Some(immutable::TagIter::from_bytes(self.data)), + git_object::Kind::Tag => Some(immutable::TagRefIter::from_bytes(self.data)), _ => None, } } diff --git a/git-pack/src/data/output/count/objects.rs b/git-pack/src/data/output/count/objects.rs index 87bd0aa661e..24817c6c8b5 100644 --- a/git-pack/src/data/output/count/objects.rs +++ b/git-pack/src/data/output/count/objects.rs @@ -179,7 +179,7 @@ where match obj.kind { Tree | Blob => break, Tag => { - id = immutable::TagIter::from_bytes(obj.data) + id = immutable::TagRefIter::from_bytes(obj.data) .target_id() .expect("every tag has a target"); obj = db.find_existing(id, buf1, cache)?; @@ -188,7 +188,7 @@ where } Commit => { let current_tree_iter = { - let mut commit_iter = immutable::CommitIter::from_bytes(obj.data); + let mut commit_iter = immutable::CommitRefIter::from_bytes(obj.data); let tree_id = commit_iter.tree_id().expect("every commit has a tree"); parent_commit_ids.clear(); for token in commit_iter { @@ -238,7 +238,7 @@ where stats, true, ); - immutable::CommitIter::from_bytes(parent_commit_obj.data) + immutable::CommitRefIter::from_bytes(parent_commit_obj.data) .tree_id() .expect("every commit has a tree") }; @@ -312,7 +312,7 @@ where break; } Commit => { - id = immutable::CommitIter::from_bytes(obj.data) + id = immutable::CommitRefIter::from_bytes(obj.data) .tree_id() .expect("every commit has a tree"); stats.expanded_objects += 1; @@ -321,7 +321,7 @@ where } Blob => break, Tag => { - id = immutable::TagIter::from_bytes(obj.data) + id = immutable::TagRefIter::from_bytes(obj.data) .target_id() .expect("every tag has a target"); stats.expanded_objects += 1; diff --git a/git-pack/src/find.rs b/git-pack/src/find.rs index 68e91547a1c..9568e0b07f6 100644 --- a/git-pack/src/find.rs +++ b/git-pack/src/find.rs @@ -125,27 +125,32 @@ mod ext { make_obj_lookup!( find_existing_commit, - immutable::Object::Commit, + immutable::ObjectRef::Commit, Kind::Commit, - immutable::Commit<'a> + immutable::CommitRef<'a> ); make_obj_lookup!( find_existing_tree, - immutable::Object::Tree, + immutable::ObjectRef::Tree, Kind::Tree, immutable::Tree<'a> ); - make_obj_lookup!(find_existing_tag, immutable::Object::Tag, Kind::Tag, immutable::Tag<'a>); + make_obj_lookup!( + find_existing_tag, + immutable::ObjectRef::Tag, + Kind::Tag, + immutable::TagRef<'a> + ); make_obj_lookup!( find_existing_blob, - immutable::Object::Blob, + immutable::ObjectRef::Blob, Kind::Blob, - immutable::Blob<'a> + immutable::BlobRef<'a> ); make_iter_lookup!( find_existing_commit_iter, Kind::Blob, - immutable::CommitIter<'a>, + immutable::CommitRefIter<'a>, into_commit_iter ); make_iter_lookup!( diff --git a/git-pack/src/index/verify.rs b/git-pack/src/index/verify.rs index ad554eb8eaf..1e9897b4d72 100644 --- a/git-pack/src/index/verify.rs +++ b/git-pack/src/index/verify.rs @@ -181,7 +181,7 @@ impl index::File { match object_kind { Tree | Commit | Tag => { let borrowed_object = - git_object::immutable::Object::from_bytes(object_kind, buf).map_err(|err| { + git_object::immutable::ObjectRef::from_bytes(object_kind, buf).map_err(|err| { Error::ObjectDecode { source: err, kind: object_kind, diff --git a/git-ref/src/store/file/loose/reference/peel.rs b/git-ref/src/store/file/loose/reference/peel.rs index 70b00f91b46..8e7c8795d20 100644 --- a/git-ref/src/store/file/loose/reference/peel.rs +++ b/git-ref/src/store/file/loose/reference/peel.rs @@ -157,7 +157,7 @@ pub mod to_id { })?; match kind { git_object::Kind::Tag => { - oid = git_object::immutable::TagIter::from_bytes(data) + oid = git_object::immutable::TagRefIter::from_bytes(data) .target_id() .ok_or_else(|| Error::NotFound { oid, diff --git a/git-ref/src/store/packed/transaction.rs b/git-ref/src/store/packed/transaction.rs index ad214e44d08..0cf583cb33f 100644 --- a/git-ref/src/store/packed/transaction.rs +++ b/git-ref/src/store/packed/transaction.rs @@ -77,7 +77,7 @@ impl packed::Transaction { let kind = find(next_id, &mut buf)?; match kind { Some(kind) if kind == git_object::Kind::Tag => { - next_id = git_object::immutable::TagIter::from_bytes(&buf) + next_id = git_object::immutable::TagRefIter::from_bytes(&buf) .target_id() .ok_or_else(|| { prepare::Error::Resolve( diff --git a/git-repository/src/easy/object/mod.rs b/git-repository/src/easy/object/mod.rs index 6dd04a646a2..d4ea73e7f6f 100644 --- a/git-repository/src/easy/object/mod.rs +++ b/git-repository/src/easy/object/mod.rs @@ -141,11 +141,11 @@ impl<'repo, A> ObjectRef<'repo, A> where A: easy::Access + Sized, { - pub fn to_commit_iter(&self) -> Option> { + pub fn to_commit_iter(&self) -> Option> { odb::data::Object::new(self.kind, &self.data).into_commit_iter() } - pub fn to_tag_iter(&self) -> Option> { + pub fn to_tag_iter(&self) -> Option> { odb::data::Object::new(self.kind, &self.data).into_tag_iter() } } diff --git a/git-repository/src/ext/object_id.rs b/git-repository/src/ext/object_id.rs index 6e0985de318..faa4249224f 100644 --- a/git-repository/src/ext/object_id.rs +++ b/git-repository/src/ext/object_id.rs @@ -13,7 +13,7 @@ pub trait ObjectIdExt: Sealed { #[cfg(feature = "git-traverse")] fn ancestors_iter(self, find: Find) -> Ancestors bool, State> where - Find: for<'a> FnMut(&git_hash::oid, &'a mut Vec) -> Option>; + Find: for<'a> FnMut(&git_hash::oid, &'a mut Vec) -> Option>; fn attach(self, access: &A) -> easy::Oid<'_, A>; } @@ -24,7 +24,7 @@ impl ObjectIdExt for ObjectId { #[cfg(feature = "git-traverse")] fn ancestors_iter(self, find: Find) -> Ancestors bool, State> where - Find: for<'a> FnMut(&git_hash::oid, &'a mut Vec) -> Option>, + Find: for<'a> FnMut(&git_hash::oid, &'a mut Vec) -> Option>, { Ancestors::new(Some(self), State::default(), find) } diff --git a/git-traverse/src/commit.rs b/git-traverse/src/commit.rs index 191625dc2c1..b9c707d4e17 100644 --- a/git-traverse/src/commit.rs +++ b/git-traverse/src/commit.rs @@ -50,7 +50,7 @@ pub mod ancestors { impl Ancestors bool, StateMut> where - Find: for<'a> FnMut(&oid, &'a mut Vec) -> Option>, + Find: for<'a> FnMut(&oid, &'a mut Vec) -> Option>, StateMut: BorrowMut, { /// Create a new instance. @@ -72,7 +72,7 @@ pub mod ancestors { impl Ancestors where - Find: for<'a> FnMut(&oid, &'a mut Vec) -> Option>, + Find: for<'a> FnMut(&oid, &'a mut Vec) -> Option>, Predicate: FnMut(&oid) -> bool, StateMut: BorrowMut, { @@ -114,7 +114,7 @@ pub mod ancestors { impl Iterator for Ancestors where - Find: for<'a> FnMut(&oid, &'a mut Vec) -> Option>, + Find: for<'a> FnMut(&oid, &'a mut Vec) -> Option>, Predicate: FnMut(&oid) -> bool, StateMut: BorrowMut, { diff --git a/gitoxide-core/src/hours.rs b/gitoxide-core/src/hours.rs index 4149843a7db..2bdc24d1fef 100644 --- a/gitoxide-core/src/hours.rs +++ b/gitoxide-core/src/hours.rs @@ -68,7 +68,7 @@ where progress.inc(); repo.odb.find_existing(oid, buf, &mut pack_cache).ok().map(|o| { commits.push(o.data.to_owned()); - objs::immutable::CommitIter::from_bytes(o.data) + objs::immutable::CommitRefIter::from_bytes(o.data) }) }), || anyhow!("Cancelled by user"), @@ -84,7 +84,7 @@ where let mut all_commits: Vec = all_commits .into_par_iter() .map(|commit_data: Vec| { - objs::immutable::CommitIter::from_bytes(&commit_data) + objs::immutable::CommitRefIter::from_bytes(&commit_data) .signatures() .next() .map(|author| actor::Signature::from(author)) From 461dc53ba3bc07d55fdb4aad7570ba9176a8b360 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 26 Aug 2021 15:16:37 +0800 Subject: [PATCH 03/18] [object #177] move immutable::* to crate::*Ref, start `iter` adjustments --- experiments/diffing/src/main.rs | 7 +- experiments/traversal/src/main.rs | 10 +- git-diff/src/tree/changes.rs | 24 ++--- git-diff/src/tree/mod.rs | 6 +- git-diff/tests/visit/mod.rs | 4 +- git-object/src/commit.rs | 8 +- git-object/src/immutable/blob.rs | 9 +- git-object/src/immutable/commit/decode.rs | 4 +- git-object/src/immutable/commit/mod.rs | 35 +------ git-object/src/immutable/mod.rs | 5 - git-object/src/immutable/object.rs | 45 +++------ git-object/src/immutable/tag.rs | 25 +---- git-object/src/immutable/tree.rs | 53 +++++------ git-object/src/lib.rs | 91 ++++++++++++++++++- git-object/src/mutable/convert.rs | 42 ++++----- git-object/src/mutable/mod.rs | 4 +- git-object/src/tag.rs | 1 + git-object/src/tree.rs | 28 ++++++ git-object/src/types.rs | 30 ------ git-object/tests/immutable/commit.rs | 32 +++---- git-object/tests/immutable/tag.rs | 20 ++-- git-object/tests/immutable/tree.rs | 54 +++++------ git-object/tests/mutable/mod.rs | 12 +-- git-odb/tests/odb/store/loose/backend.rs | 14 +-- git-pack/src/data/object.rs | 26 +++--- git-pack/src/data/output/count/objects.rs | 24 ++--- git-pack/src/find.rs | 39 ++------ git-pack/src/index/verify.rs | 10 +- .../src/store/file/loose/reference/peel.rs | 13 +-- git-ref/src/store/packed/transaction.rs | 12 +-- git-repository/src/easy/object/mod.rs | 6 +- git-repository/src/easy/object/tree.rs | 2 +- git-repository/src/ext/object_id.rs | 7 +- git-repository/src/ext/tree.rs | 18 ++-- git-traverse/src/commit.rs | 8 +- git-traverse/src/tree/breadthfirst.rs | 4 +- git-traverse/src/tree/recorder.rs | 6 +- git-traverse/src/tree/visit.rs | 4 +- gitoxide-core/src/hours.rs | 4 +- 39 files changed, 353 insertions(+), 393 deletions(-) create mode 100644 git-object/src/tag.rs create mode 100644 git-object/src/tree.rs diff --git a/experiments/diffing/src/main.rs b/experiments/diffing/src/main.rs index 1d329ca113c..75adc133bec 100644 --- a/experiments/diffing/src/main.rs +++ b/experiments/diffing/src/main.rs @@ -2,11 +2,12 @@ use std::time::Instant; use anyhow::anyhow; use diff::tree::visit::{Action, Change}; +use git_repository::objs::tree; use git_repository::{ diff, easy::object, hash::{oid, ObjectId}, - objs::{bstr::BStr, immutable}, + objs::bstr::BStr, odb, prelude::*, refs::file::loose::reference::peel, @@ -254,14 +255,14 @@ where } }; - fn find_tree_iter<'b, L>(id: &oid, buf: &'b mut Vec, mut find: L) -> Option> + fn find_tree_iter<'b, L>(id: &oid, buf: &'b mut Vec, mut find: L) -> Option> where L: for<'a> FnMut(&oid, &'a mut Vec) -> Option>, { find(id, buf).and_then(|o| o.into_tree_iter()) } - fn tree_iter_by_commit<'b, L>(id: &oid, buf: &'b mut Vec, mut find: L) -> immutable::TreeIter<'b> + fn tree_iter_by_commit<'b, L>(id: &oid, buf: &'b mut Vec, mut find: L) -> tree::RefIter<'b> where L: for<'a> FnMut(&oid, &'a mut Vec) -> Option>, { diff --git a/experiments/traversal/src/main.rs b/experiments/traversal/src/main.rs index 8e62722722a..65d91350678 100644 --- a/experiments/traversal/src/main.rs +++ b/experiments/traversal/src/main.rs @@ -7,7 +7,7 @@ use anyhow::anyhow; use dashmap::DashSet; use git_repository::{ hash::ObjectId, - objs::{bstr::BStr, immutable::tree::Entry}, + objs::{bstr::BStr, immutable::tree::EntryRef}, odb, prelude::*, refs::file::loose::reference::peel, @@ -186,7 +186,7 @@ where fn push_back_tracked_path_component(&mut self, _component: &BStr) {} fn push_path_component(&mut self, _component: &BStr) {} fn pop_path_component(&mut self) {} - fn visit_tree(&mut self, entry: &Entry<'_>) -> Action { + fn visit_tree(&mut self, entry: &EntryRef<'_>) -> Action { self.entries += 1; let inserted = self.seen.insert(entry.oid.to_owned()); if !inserted { @@ -195,7 +195,7 @@ where tree::visit::Action::Continue } } - fn visit_nontree(&mut self, entry: &Entry<'_>) -> Action { + fn visit_nontree(&mut self, entry: &EntryRef<'_>) -> Action { self.entries += 1; self.seen.insert(entry.oid.to_owned()); tree::visit::Action::Continue @@ -241,7 +241,7 @@ where fn push_back_tracked_path_component(&mut self, _component: &BStr) {} fn push_path_component(&mut self, _component: &BStr) {} fn pop_path_component(&mut self) {} - fn visit_tree(&mut self, entry: &Entry<'_>) -> Action { + fn visit_tree(&mut self, entry: &EntryRef<'_>) -> Action { self.entries += 1; let inserted = self.seen.insert(entry.oid.to_owned()); if !inserted { @@ -250,7 +250,7 @@ where tree::visit::Action::Continue } } - fn visit_nontree(&mut self, entry: &Entry<'_>) -> Action { + fn visit_nontree(&mut self, entry: &EntryRef<'_>) -> Action { self.entries += 1; self.seen.insert(entry.oid.to_owned()); tree::visit::Action::Continue diff --git a/git-diff/src/tree/changes.rs b/git-diff/src/tree/changes.rs index e52dce8f79c..099242c5d20 100644 --- a/git-diff/src/tree/changes.rs +++ b/git-diff/src/tree/changes.rs @@ -54,13 +54,13 @@ impl<'a> tree::Changes<'a> { /// [git_cmp_rs]: https://github.com/Byron/gitoxide/blob/a4d5f99c8dc99bf814790928a3bf9649cd99486b/git-object/src/mutable/tree.rs#L52-L55 pub fn needed_to_obtain( mut self, - other: immutable::TreeIter<'_>, + other: git_object::tree::RefIter<'_>, mut state: StateMut, mut find: FindFn, delegate: &mut R, ) -> Result<(), Error> where - FindFn: for<'b> FnMut(&oid, &'b mut Vec) -> Option>, + FindFn: for<'b> FnMut(&oid, &'b mut Vec) -> Option>, R: tree::Visit, StateMut: BorrowMut, { @@ -120,7 +120,7 @@ impl<'a> tree::Changes<'a> { } fn delete_entry_schedule_recursion( - entry: immutable::tree::Entry<'_>, + entry: immutable::tree::EntryRef<'_>, queue: &mut VecDeque, delegate: &mut R, ) -> Result<(), Error> { @@ -143,7 +143,7 @@ fn delete_entry_schedule_recursion( } fn add_entry_schedule_recursion( - entry: immutable::tree::Entry<'_>, + entry: immutable::tree::EntryRef<'_>, queue: &mut VecDeque, delegate: &mut R, ) -> Result<(), Error> { @@ -165,9 +165,9 @@ fn add_entry_schedule_recursion( Ok(()) } fn catchup_rhs_with_lhs( - rhs_entries: &mut IteratorType>, - lhs: immutable::tree::Entry<'_>, - rhs: immutable::tree::Entry<'_>, + rhs_entries: &mut IteratorType>, + lhs: git_object::tree::EntryRef<'_>, + rhs: git_object::tree::EntryRef<'_>, queue: &mut VecDeque, delegate: &mut R, ) -> Result<(), Error> { @@ -205,9 +205,9 @@ fn catchup_rhs_with_lhs( } fn catchup_lhs_with_rhs( - lhs_entries: &mut IteratorType>, - lhs: immutable::tree::Entry<'_>, - rhs: immutable::tree::Entry<'_>, + lhs_entries: &mut IteratorType>, + lhs: git_object::tree::EntryRef<'_>, + rhs: git_object::tree::EntryRef<'_>, queue: &mut VecDeque, delegate: &mut R, ) -> Result<(), Error> { @@ -245,8 +245,8 @@ fn catchup_lhs_with_rhs( } fn handle_lhs_and_rhs_with_equal_filenames( - lhs: immutable::tree::Entry<'_>, - rhs: immutable::tree::Entry<'_>, + lhs: immutable::tree::EntryRef<'_>, + rhs: immutable::tree::EntryRef<'_>, queue: &mut VecDeque, delegate: &mut R, ) -> Result<(), Error> { diff --git a/git-diff/src/tree/mod.rs b/git-diff/src/tree/mod.rs index 254cfdb938f..7489e4dc565 100644 --- a/git-diff/src/tree/mod.rs +++ b/git-diff/src/tree/mod.rs @@ -1,7 +1,7 @@ use std::collections::VecDeque; use git_hash::ObjectId; -use git_object::immutable; +use git_object::tree; /// The state required to visit [Changes] to be instantiated with `State::default()`. #[derive(Default, Clone)] @@ -22,11 +22,11 @@ impl State { } /// An iterator over changes of a tree, instantiated using `Changes::from(…)`. -pub struct Changes<'a>(Option>); +pub struct Changes<'a>(Option>); impl<'a, T> From for Changes<'a> where - T: Into>>, + T: Into>>, { fn from(v: T) -> Self { Changes(v.into()) diff --git a/git-diff/tests/visit/mod.rs b/git-diff/tests/visit/mod.rs index 4890cfdaed7..7be49d9e6c6 100644 --- a/git-diff/tests/visit/mod.rs +++ b/git-diff/tests/visit/mod.rs @@ -2,7 +2,7 @@ mod changes { mod to_obtain_tree { use git_diff::tree::{recorder, recorder::Change::*}; use git_hash::{oid, ObjectId}; - use git_object::{bstr::ByteSlice, immutable, tree::EntryMode}; + use git_object::{bstr::ByteSlice, tree, tree::EntryMode}; use git_odb::{linked, pack, Find}; use crate::hex_to_id; @@ -22,7 +22,7 @@ mod changes { db: &linked::Store, commit: &oid, buf: &'a mut Vec, - ) -> crate::Result> { + ) -> crate::Result> { let tree_id = db .find(commit, buf, &mut pack::cache::Never)? .ok_or_else(|| format!("start commit {:?} to be present", commit))? diff --git a/git-object/src/commit.rs b/git-object/src/commit.rs index c66d387eccc..e7a37ba5843 100644 --- a/git-object/src/commit.rs +++ b/git-object/src/commit.rs @@ -1,6 +1,8 @@ use bstr::{BStr, ByteSlice}; -use crate::immutable; +use crate::{immutable, TagRef}; + +pub use crate::immutable::commit::iter::RefIter; /// An iterator over extra headers in [owned][crate::mutable::Commit] and [borrowed][immutable::Commit] commits. pub struct ExtraHeaders { @@ -30,8 +32,8 @@ where /// /// A merge tag is a tag object embedded within the respective header field of a commit, making /// it a child object of sorts. - pub fn mergetags(self) -> impl Iterator, immutable::object::decode::Error>> { - self.find_all("mergetag").map(|b| immutable::TagRef::from_bytes(b)) + pub fn mergetags(self) -> impl Iterator, immutable::object::decode::Error>> { + self.find_all("mergetag").map(|b| TagRef::from_bytes(b)) } /// Return the cryptographic signature provided by gpg/pgp verbatim. diff --git a/git-object/src/immutable/blob.rs b/git-object/src/immutable/blob.rs index 7097140bb96..fec651e2d37 100644 --- a/git-object/src/immutable/blob.rs +++ b/git-object/src/immutable/blob.rs @@ -1,13 +1,6 @@ +use crate::BlobRef; use std::convert::Infallible; -/// A chunk of any [`data`][Blob::data]. -#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] -#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] -pub struct BlobRef<'a> { - /// The bytes themselves. - pub data: &'a [u8], -} - impl<'a> BlobRef<'a> { /// Instantiate a `Blob` from the given `data`, which is used as-is. pub fn from_bytes(data: &[u8]) -> Result, Infallible> { diff --git a/git-object/src/immutable/commit/decode.rs b/git-object/src/immutable/commit/decode.rs index 4be0d6c1d3b..5f47a805f73 100644 --- a/git-object/src/immutable/commit/decode.rs +++ b/git-object/src/immutable/commit/decode.rs @@ -11,8 +11,8 @@ use nom::{ use smallvec::SmallVec; use crate::{ - immutable::{parse, parse::NL, CommitRef}, - BStr, ByteSlice, + immutable::{parse, parse::NL}, + BStr, ByteSlice, CommitRef, }; pub fn message<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(i: &'a [u8]) -> IResult<&'a [u8], &'a BStr, E> { diff --git a/git-object/src/immutable/commit/mod.rs b/git-object/src/immutable/commit/mod.rs index 21661b3cda4..f786d2169c9 100644 --- a/git-object/src/immutable/commit/mod.rs +++ b/git-object/src/immutable/commit/mod.rs @@ -1,43 +1,10 @@ -use std::borrow::Cow; - -use smallvec::SmallVec; - -use crate::{immutable::object, BStr}; +use crate::{immutable::object, BStr, CommitRef}; mod decode; /// pub mod iter; -/// A git commit parsed using [`from_bytes()`][Commit::from_bytes()]. -/// -/// A commit encapsulates information about a point in time at which the state of the repository is recorded, usually after a -/// change which is documented in the commit `message`. -#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] -#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] -pub struct CommitRef<'a> { - /// HEX hash of tree object we point to. Usually 40 bytes long. - /// - /// Use [`tree()`][Commit::tree()] to obtain a decoded version of it. - #[cfg_attr(feature = "serde1", serde(borrow))] - pub tree: &'a BStr, - /// HEX hash of each parent commit. Empty for first commit in repository. - pub parents: SmallVec<[&'a BStr; 2]>, - /// Who wrote this commit. - pub author: git_actor::SignatureRef<'a>, - /// Who committed this commit. - /// - /// This may be different from the `author` in case the author couldn't write to the repository themselves and - /// is commonly encountered with contributed commits. - pub committer: git_actor::SignatureRef<'a>, - /// The name of the message encoding, otherwise [UTF-8 should be assumed](https://github.com/git/git/blob/e67fbf927dfdf13d0b21dc6ea15dc3c7ef448ea0/commit.c#L1493:L1493). - pub encoding: Option<&'a BStr>, - /// The commit message documenting the change. - pub message: &'a BStr, - /// Extra header fields, in order of them being encountered, made accessible with the iterator returned by [`extra_headers()`][Commit::extra_headers()]. - pub extra_headers: Vec<(&'a BStr, Cow<'a, BStr>)>, -} - impl<'a> CommitRef<'a> { /// Deserialize a commit from the given `data` bytes while avoiding most allocations. pub fn from_bytes(data: &'a [u8]) -> Result, object::decode::Error> { diff --git a/git-object/src/immutable/mod.rs b/git-object/src/immutable/mod.rs index e9419203fc8..d661afc2ea1 100644 --- a/git-object/src/immutable/mod.rs +++ b/git-object/src/immutable/mod.rs @@ -5,22 +5,17 @@ //! which support mutation and serialization. mod blob; -pub use blob::BlobRef; /// pub mod commit; -pub use commit::{iter::RefIter as CommitRefIter, CommitRef}; /// pub mod object; -pub use object::ObjectRef; /// pub mod tag; -pub use tag::{iter::RefIter as TagRefIter, TagRef}; /// pub mod tree; -pub use tree::{Tree, TreeIter}; mod parse; diff --git a/git-object/src/immutable/object.rs b/git-object/src/immutable/object.rs index 7f546013483..9077f607f85 100644 --- a/git-object/src/immutable/object.rs +++ b/git-object/src/immutable/object.rs @@ -1,26 +1,10 @@ -use crate::{ - immutable, - immutable::{BlobRef, CommitRef, TagRef, Tree}, - Kind, -}; - -/// An signature_ref object representing [`Trees`][Tree], [`Blobs`][Blob], [`Commits`][Commit], or [`Tags`][Tag]. -#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] -#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] -#[allow(missing_docs)] -pub enum ObjectRef<'a> { - #[cfg_attr(feature = "serde1", serde(borrow))] - Tree(Tree<'a>), - Blob(BlobRef<'a>), - Commit(CommitRef<'a>), - Tag(TagRef<'a>), -} +use crate::{BlobRef, CommitRef, Kind, ObjectRef, TagRef, TreeRef}; impl<'a> ObjectRef<'a> { /// Deserialize an object of `kind` from the given `data`. pub fn from_bytes(kind: Kind, data: &'a [u8]) -> Result, decode::Error> { Ok(match kind { - Kind::Tree => ObjectRef::Tree(Tree::from_bytes(data)?), + Kind::Tree => ObjectRef::Tree(TreeRef::from_bytes(data)?), Kind::Blob => ObjectRef::Blob(BlobRef { data }), Kind::Commit => ObjectRef::Commit(CommitRef::from_bytes(data)?), Kind::Tag => ObjectRef::Tag(TagRef::from_bytes(data)?), @@ -45,56 +29,56 @@ impl<'a> ObjectRef<'a> { /// Convenient access to contained objects. impl<'a> ObjectRef<'a> { /// Interpret this object as blob. - pub fn as_blob(&self) -> Option<&immutable::BlobRef<'a>> { + pub fn as_blob(&self) -> Option<&BlobRef<'a>> { match self { ObjectRef::Blob(v) => Some(v), _ => None, } } /// Interpret this object as blob, chainable. - pub fn into_blob(self) -> Option> { + pub fn into_blob(self) -> Option> { match self { ObjectRef::Blob(v) => Some(v), _ => None, } } /// Interpret this object as commit. - pub fn as_commit(&self) -> Option<&immutable::CommitRef<'a>> { + pub fn as_commit(&self) -> Option<&CommitRef<'a>> { match self { ObjectRef::Commit(v) => Some(v), _ => None, } } /// Interpret this object as commit, chainable. - pub fn into_commit(self) -> Option> { + pub fn into_commit(self) -> Option> { match self { ObjectRef::Commit(v) => Some(v), _ => None, } } /// Interpret this object as tree. - pub fn as_tree(&self) -> Option<&immutable::Tree<'a>> { + pub fn as_tree(&self) -> Option<&TreeRef<'a>> { match self { ObjectRef::Tree(v) => Some(v), _ => None, } } /// Interpret this object as tree, chainable - pub fn into_tree(self) -> Option> { + pub fn into_tree(self) -> Option> { match self { ObjectRef::Tree(v) => Some(v), _ => None, } } /// Interpret this object as tag. - pub fn as_tag(&self) -> Option<&immutable::TagRef<'a>> { + pub fn as_tag(&self) -> Option<&TagRef<'a>> { match self { ObjectRef::Tag(v) => Some(v), _ => None, } } /// Interpret this object as tag, chainable. - pub fn into_tag(self) -> Option> { + pub fn into_tag(self) -> Option> { match self { ObjectRef::Tag(v) => Some(v), _ => None, @@ -114,7 +98,8 @@ impl<'a> ObjectRef<'a> { mod convert { use std::convert::TryFrom; - use crate::immutable::{BlobRef, CommitRef, ObjectRef, TagRef, Tree}; + use crate::ObjectRef; + use crate::{BlobRef, CommitRef, TagRef, TreeRef}; impl<'a> From> for ObjectRef<'a> { fn from(v: TagRef<'a>) -> Self { @@ -128,8 +113,8 @@ mod convert { } } - impl<'a> From> for ObjectRef<'a> { - fn from(v: Tree<'a>) -> Self { + impl<'a> From> for ObjectRef<'a> { + fn from(v: TreeRef<'a>) -> Self { ObjectRef::Tree(v) } } @@ -162,7 +147,7 @@ mod convert { } } - impl<'a> TryFrom> for Tree<'a> { + impl<'a> TryFrom> for TreeRef<'a> { type Error = ObjectRef<'a>; fn try_from(value: ObjectRef<'a>) -> Result { diff --git a/git-object/src/immutable/tag.rs b/git-object/src/immutable/tag.rs index ae5a1ad02fb..3ce5920b7a5 100644 --- a/git-object/src/immutable/tag.rs +++ b/git-object/src/immutable/tag.rs @@ -1,23 +1,4 @@ -use crate::{immutable::object, BStr}; - -/// Represents a git tag, commonly indicating a software release. -#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] -#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] -pub struct TagRef<'a> { - /// The hash in hexadecimal being the object this tag points to. Use [`target()`][Tag::target()] to obtain a byte representation. - #[cfg_attr(feature = "serde1", serde(borrow))] - pub target: &'a BStr, - /// The kind of object that `target` points to. - pub target_kind: crate::Kind, - /// The name of the tag, e.g. "v1.0". - pub name: &'a BStr, - /// The author of the tag. - pub tagger: Option>, - /// The message describing this release. - pub message: &'a BStr, - /// A cryptographic signature over the entire content of the serialized tag object thus far. - pub pgp_signature: Option<&'a BStr>, -} +use crate::{immutable::object, TagRef}; impl<'a> TagRef<'a> { /// Deserialize a tag from `data`. @@ -44,8 +25,8 @@ mod decode { }; use crate::{ - immutable::{parse, parse::NL, TagRef}, - BStr, ByteSlice, + immutable::{parse, parse::NL}, + BStr, ByteSlice, TagRef, }; pub fn git_tag<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(i: &'a [u8]) -> IResult<&[u8], TagRef<'a>, E> { diff --git a/git-object/src/immutable/tree.rs b/git-object/src/immutable/tree.rs index 70fa4277872..a58028d958e 100644 --- a/git-object/src/immutable/tree.rs +++ b/git-object/src/immutable/tree.rs @@ -2,37 +2,28 @@ use std::convert::TryFrom; use bstr::BStr; -use crate::{immutable::object, tree}; - -/// A directory snapshot containing files (blobs), directories (trees) and submodules (commits). -#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] -#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] -pub struct Tree<'a> { - /// The directories and files contained in this tree. - #[cfg_attr(feature = "serde1", serde(borrow))] - pub entries: Vec>, -} +use crate::{immutable::object, tree, TreeRef}; /// A directory snapshot containing files (blobs), directories (trees) and submodules (commits), lazily evaluated. #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] #[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] -pub struct TreeIter<'a> { +pub struct RefIter<'a> { /// The directories and files contained in this tree. #[cfg_attr(feature = "serde1", serde(borrow))] data: &'a [u8], } -impl<'a> TreeIter<'a> { +impl<'a> RefIter<'a> { /// Instantiate an iterator from the given tree data. - pub fn from_bytes(data: &'a [u8]) -> TreeIter<'a> { - TreeIter { data } + pub fn from_bytes(data: &'a [u8]) -> RefIter<'a> { + RefIter { data } } } /// An element of a [`Tree`][Tree::entries]. #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] #[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] -pub struct Entry<'a> { +pub struct EntryRef<'a> { /// The kind of object to which `oid` is pointing. pub mode: tree::EntryMode, /// The name of the file in the parent tree. @@ -44,35 +35,35 @@ pub struct Entry<'a> { pub oid: &'a git_hash::oid, } -impl<'a> Tree<'a> { +impl<'a> TreeRef<'a> { /// Deserialize a Tree from `data`. - pub fn from_bytes(data: &'a [u8]) -> Result, object::decode::Error> { + pub fn from_bytes(data: &'a [u8]) -> Result, object::decode::Error> { decode::tree(data).map(|(_, t)| t).map_err(object::decode::Error::from) } /// Create an instance of the empty tree. /// /// It's particularly useful as static part of a program. - pub const fn empty() -> Tree<'static> { - Tree { entries: Vec::new() } + pub const fn empty() -> TreeRef<'static> { + TreeRef { entries: Vec::new() } } } -impl<'a> TreeIter<'a> { +impl<'a> RefIter<'a> { /// Consume self and return all parsed entries. - pub fn entries(self) -> Result>, object::decode::Error> { + pub fn entries(self) -> Result>, object::decode::Error> { self.collect() } } -impl<'a> Default for TreeIter<'a> { +impl<'a> Default for RefIter<'a> { fn default() -> Self { - TreeIter { data: &[] } + RefIter { data: &[] } } } -impl<'a> Iterator for TreeIter<'a> { - type Item = Result, object::decode::Error>; +impl<'a> Iterator for RefIter<'a> { + type Item = Result, object::decode::Error>; fn next(&mut self) -> Option { if self.data.is_empty() { @@ -123,13 +114,13 @@ mod decode { }; use crate::{ - immutable::{parse::SPACE, tree::Entry, Tree}, - tree, + immutable::{parse::SPACE, tree::EntryRef}, + tree, TreeRef, }; const NULL: &[u8] = b"\0"; - pub fn entry<'a, E: ParseError<&'a [u8]>>(i: &'a [u8]) -> IResult<&[u8], Entry<'_>, E> { + pub fn entry<'a, E: ParseError<&'a [u8]>>(i: &'a [u8]) -> IResult<&[u8], EntryRef<'_>, E> { let (i, mode) = terminated(take_while_m_n(5, 6, is_digit), tag(SPACE))(i)?; let mode = tree::EntryMode::try_from(mode) .map_err(|invalid| nom::Err::Error(E::from_error_kind(invalid, nom::error::ErrorKind::MapRes)))?; @@ -138,7 +129,7 @@ mod decode { Ok(( i, - Entry { + EntryRef { mode, filename: filename.as_bstr(), oid: git_hash::oid::try_from(oid).expect("we counted exactly 20 bytes"), @@ -146,8 +137,8 @@ mod decode { )) } - pub fn tree<'a, E: ParseError<&'a [u8]>>(i: &'a [u8]) -> IResult<&'a [u8], Tree<'a>, E> { + pub fn tree<'a, E: ParseError<&'a [u8]>>(i: &'a [u8]) -> IResult<&'a [u8], TreeRef<'a>, E> { let (i, entries) = all_consuming(many0(entry))(i)?; - Ok((i, Tree { entries })) + Ok((i, TreeRef { entries })) } } diff --git a/git-object/src/lib.rs b/git-object/src/lib.rs index ea719bc4a17..2d894ca8d2d 100644 --- a/git-object/src/lib.rs +++ b/git-object/src/lib.rs @@ -3,15 +3,102 @@ #![forbid(unsafe_code)] #![deny(rust_2018_idioms, missing_docs)] +use std::borrow::Cow; + /// For convenience to allow using `bstr` without adding it to own cargo manifest. pub use bstr; use bstr::{BStr, BString, ByteSlice}; +use smallvec::SmallVec; + +pub use types::{Error, Kind}; + +use crate::immutable::tree::EntryRef; pub mod immutable; pub mod mutable; +/// +pub mod commit; +/// +pub mod tag; +/// +pub mod tree; + mod types; -pub use types::{tree, Error, Kind}; +/// A chunk of any [`data`][Blob::data]. +#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] +#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] +pub struct BlobRef<'a> { + /// The bytes themselves. + pub data: &'a [u8], +} + +/// A git commit parsed using [`from_bytes()`][Commit::from_bytes()]. /// -pub mod commit; +/// A commit encapsulates information about a point in time at which the state of the repository is recorded, usually after a +/// change which is documented in the commit `message`. +#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] +#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] +pub struct CommitRef<'a> { + /// HEX hash of tree object we point to. Usually 40 bytes long. + /// + /// Use [`tree()`][Commit::tree()] to obtain a decoded version of it. + #[cfg_attr(feature = "serde1", serde(borrow))] + pub tree: &'a BStr, + /// HEX hash of each parent commit. Empty for first commit in repository. + pub parents: SmallVec<[&'a BStr; 2]>, + /// Who wrote this commit. + pub author: git_actor::SignatureRef<'a>, + /// Who committed this commit. + /// + /// This may be different from the `author` in case the author couldn't write to the repository themselves and + /// is commonly encountered with contributed commits. + pub committer: git_actor::SignatureRef<'a>, + /// The name of the message encoding, otherwise [UTF-8 should be assumed](https://github.com/git/git/blob/e67fbf927dfdf13d0b21dc6ea15dc3c7ef448ea0/commit.c#L1493:L1493). + pub encoding: Option<&'a BStr>, + /// The commit message documenting the change. + pub message: &'a BStr, + /// Extra header fields, in order of them being encountered, made accessible with the iterator returned by [`extra_headers()`][Commit::extra_headers()]. + pub extra_headers: Vec<(&'a BStr, Cow<'a, BStr>)>, +} + +/// Represents a git tag, commonly indicating a software release. +#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] +#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] +pub struct TagRef<'a> { + /// The hash in hexadecimal being the object this tag points to. Use [`target()`][Tag::target()] to obtain a byte representation. + #[cfg_attr(feature = "serde1", serde(borrow))] + pub target: &'a BStr, + /// The kind of object that `target` points to. + pub target_kind: crate::Kind, + /// The name of the tag, e.g. "v1.0". + pub name: &'a BStr, + /// The author of the tag. + pub tagger: Option>, + /// The message describing this release. + pub message: &'a BStr, + /// A cryptographic signature over the entire content of the serialized tag object thus far. + pub pgp_signature: Option<&'a BStr>, +} + +/// An signature_ref object representing [`Trees`][Tree], [`Blobs`][Blob], [`Commits`][Commit], or [`Tags`][Tag]. +#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] +#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] +#[allow(missing_docs)] +pub enum ObjectRef<'a> { + #[cfg_attr(feature = "serde1", serde(borrow))] + Tree(TreeRef<'a>), + Blob(BlobRef<'a>), + Commit(CommitRef<'a>), + Tag(TagRef<'a>), +} + +/// A directory snapshot containing files (blobs), directories (trees) and submodules (commits). +#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] +#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] +pub struct TreeRef<'a> { + /// The directories and files contained in this tree. + #[cfg_attr(feature = "serde1", serde(borrow))] + pub entries: Vec>, +} diff --git a/git-object/src/mutable/convert.rs b/git-object/src/mutable/convert.rs index f15e04fb95d..02c709edd54 100644 --- a/git-object/src/mutable/convert.rs +++ b/git-object/src/mutable/convert.rs @@ -1,8 +1,8 @@ -use crate::{immutable, mutable}; +use crate::{immutable, mutable, BlobRef, CommitRef, ObjectRef, TagRef, TreeRef}; -impl From> for mutable::Tag { - fn from(other: immutable::TagRef<'_>) -> mutable::Tag { - let immutable::TagRef { +impl From> for mutable::Tag { + fn from(other: TagRef<'_>) -> mutable::Tag { + let TagRef { target, name, target_kind, @@ -21,9 +21,9 @@ impl From> for mutable::Tag { } } -impl From> for mutable::Commit { - fn from(other: immutable::CommitRef<'_>) -> mutable::Commit { - let immutable::CommitRef { +impl From> for mutable::Commit { + fn from(other: CommitRef<'_>) -> mutable::Commit { + let CommitRef { tree, parents, author, @@ -50,26 +50,26 @@ impl From> for mutable::Commit { } } -impl<'a> From> for mutable::Blob { - fn from(v: immutable::BlobRef<'a>) -> Self { +impl<'a> From> for mutable::Blob { + fn from(v: BlobRef<'a>) -> Self { mutable::Blob { data: v.data.to_owned(), } } } -impl From> for mutable::Tree { - fn from(other: immutable::Tree<'_>) -> mutable::Tree { - let immutable::Tree { entries } = other; +impl From> for mutable::Tree { + fn from(other: TreeRef<'_>) -> mutable::Tree { + let TreeRef { entries } = other; mutable::Tree { entries: entries.into_iter().map(Into::into).collect(), } } } -impl From> for mutable::tree::Entry { - fn from(other: immutable::tree::Entry<'_>) -> mutable::tree::Entry { - let immutable::tree::Entry { mode, filename, oid } = other; +impl From> for mutable::tree::Entry { + fn from(other: immutable::tree::EntryRef<'_>) -> mutable::tree::Entry { + let immutable::tree::EntryRef { mode, filename, oid } = other; mutable::tree::Entry { mode, filename: filename.to_owned(), @@ -78,13 +78,13 @@ impl From> for mutable::tree::Entry { } } -impl<'a> From> for mutable::Object { - fn from(v: immutable::ObjectRef<'_>) -> Self { +impl<'a> From> for mutable::Object { + fn from(v: ObjectRef<'_>) -> Self { match v { - immutable::ObjectRef::Tree(v) => mutable::Object::Tree(v.into()), - immutable::ObjectRef::Blob(v) => mutable::Object::Blob(v.into()), - immutable::ObjectRef::Commit(v) => mutable::Object::Commit(v.into()), - immutable::ObjectRef::Tag(v) => mutable::Object::Tag(v.into()), + ObjectRef::Tree(v) => mutable::Object::Tree(v.into()), + ObjectRef::Blob(v) => mutable::Object::Blob(v.into()), + ObjectRef::Commit(v) => mutable::Object::Commit(v.into()), + ObjectRef::Tag(v) => mutable::Object::Tag(v.into()), } } } diff --git a/git-object/src/mutable/mod.rs b/git-object/src/mutable/mod.rs index e15f66aa0da..b77f76b7176 100644 --- a/git-object/src/mutable/mod.rs +++ b/git-object/src/mutable/mod.rs @@ -1,8 +1,8 @@ //! Mutable objects with each field being separately allocated and changeable. //! //! Mutable objects are Commits, Trees, Blobs and Tags that can be changed and serialized. -//! They either created using object [construction][Object] or by [deserializing existing objects][crate::immutable::ObjectRef::from_bytes()] -//! and converting these [into mutable copies][crate::immutable::ObjectRef::into_mutable()] for adjustments. +//! They either created using object [construction][Object] or by [deserializing existing objects][crate::ObjectRef::from_bytes()] +//! and converting these [into mutable copies][crate::ObjectRef::into_mutable()] for adjustments. const NL: &[u8; 1] = b"\n"; const SPACE: &[u8; 1] = b" "; diff --git a/git-object/src/tag.rs b/git-object/src/tag.rs new file mode 100644 index 00000000000..2e59f03f1f9 --- /dev/null +++ b/git-object/src/tag.rs @@ -0,0 +1 @@ +pub use crate::immutable::tag::iter::RefIter; diff --git a/git-object/src/tree.rs b/git-object/src/tree.rs new file mode 100644 index 00000000000..9b0aca4c381 --- /dev/null +++ b/git-object/src/tree.rs @@ -0,0 +1,28 @@ +/// The mode of items storable in a tree, similar to the file mode on a unix file system. +/// +/// Used in [mutable::Entry][crate::mutable::tree::Entry] and [tree::Entry][crate::immutable::tree::Entry]. +#[derive(Clone, Copy, PartialEq, Eq, Debug, Ord, PartialOrd, Hash)] +#[repr(u16)] +#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] +#[allow(missing_docs)] +pub enum EntryMode { + Tree = 0o040000u16, + Blob = 0o100644, + BlobExecutable = 0o100755, + Link = 0o120000, + Commit = 0o160000, +} + +impl EntryMode { + /// Return true if this entry mode represents a Tree/directory + pub fn is_tree(&self) -> bool { + *self == EntryMode::Tree + } + + /// Return true if this entry mode represents anything BUT Tree/directory + pub fn is_no_tree(&self) -> bool { + *self != EntryMode::Tree + } +} + +pub use crate::immutable::tree::{EntryRef, RefIter}; diff --git a/git-object/src/types.rs b/git-object/src/types.rs index 73212d7d27d..77d0b32f721 100644 --- a/git-object/src/types.rs +++ b/git-object/src/types.rs @@ -51,33 +51,3 @@ impl fmt::Display for Kind { f.write_str(std::str::from_utf8(self.as_bytes()).expect("Converting Kind name to utf8")) } } - -/// -pub mod tree { - /// The mode of items storable in a tree, similar to the file mode on a unix file system. - /// - /// Used in [mutable::Entry][crate::mutable::tree::Entry] and [tree::Entry][crate::immutable::tree::Entry]. - #[derive(Clone, Copy, PartialEq, Eq, Debug, Ord, PartialOrd, Hash)] - #[repr(u16)] - #[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] - #[allow(missing_docs)] - pub enum EntryMode { - Tree = 0o040000u16, - Blob = 0o100644, - BlobExecutable = 0o100755, - Link = 0o120000, - Commit = 0o160000, - } - - impl EntryMode { - /// Return true if this entry mode represents a Tree/directory - pub fn is_tree(&self) -> bool { - *self == EntryMode::Tree - } - - /// Return true if this entry mode represents anything BUT Tree/directory - pub fn is_no_tree(&self) -> bool { - *self != EntryMode::Tree - } - } -} diff --git a/git-object/tests/immutable/commit.rs b/git-object/tests/immutable/commit.rs index 4bbc67fd578..30353debf55 100644 --- a/git-object/tests/immutable/commit.rs +++ b/git-object/tests/immutable/commit.rs @@ -131,7 +131,7 @@ dS3aXZhRfaPqpdsWrMB9fY7ll+oyfw== =T+RI -----END PGP SIGNATURE-----"; mod method { - use git_object::immutable::CommitRef; + use git_object::CommitRef; use pretty_assertions::assert_eq; use crate::{hex_to_id, immutable::fixture_bytes}; @@ -147,10 +147,7 @@ mod method { } mod iter { - use git_object::{ - bstr::ByteSlice, - immutable::{commit::iter::Token, CommitRefIter}, - }; + use git_object::{bstr::ByteSlice, commit, immutable::commit::iter::Token}; use crate::{ hex_to_id, @@ -163,7 +160,7 @@ mod iter { #[test] fn newline_right_after_signature_multiline_header() -> crate::Result { let data = fixture_bytes("commit", "signed-whitespace.txt"); - let tokens = CommitRefIter::from_bytes(&data).collect::, _>>()?; + let tokens = commit::RefIter::from_bytes(&data).collect::, _>>()?; assert_eq!(tokens.len(), 7, "mainly a parsing exercise"); match tokens.last().expect("there are tokens") { Token::Message(msg) => { @@ -177,7 +174,7 @@ mod iter { #[test] fn signed_with_encoding() -> crate::Result { assert_eq!( - CommitRefIter::from_bytes(&fixture_bytes("commit", "signed-with-encoding.txt")) + commit::RefIter::from_bytes(&fixture_bytes("commit", "signed-with-encoding.txt")) .collect::, _>>()?, vec![ Token::Tree { @@ -203,7 +200,7 @@ mod iter { #[test] fn whitespace() -> crate::Result { assert_eq!( - CommitRefIter::from_bytes(&fixture_bytes("commit", "whitespace.txt")).collect::, _>>()?, + commit::RefIter::from_bytes(&fixture_bytes("commit", "whitespace.txt")).collect::, _>>()?, vec![ Token::Tree { id: hex_to_id("9bed6275068a0575243ba8409253e61af81ab2ff") @@ -226,7 +223,7 @@ mod iter { #[test] fn unsigned() -> crate::Result { assert_eq!( - CommitRefIter::from_bytes(&fixture_bytes("commit", "unsigned.txt")).collect::, _>>()?, + commit::RefIter::from_bytes(&fixture_bytes("commit", "unsigned.txt")).collect::, _>>()?, vec![ Token::Tree { id: hex_to_id("1b2dfb4ac5e42080b682fc676e9738c94ce6d54d") @@ -246,7 +243,7 @@ mod iter { #[test] fn signed_singleline() -> crate::Result { assert_eq!( - CommitRefIter::from_bytes(&fixture_bytes("commit", "signed-singleline.txt")) + commit::RefIter::from_bytes(&fixture_bytes("commit", "signed-singleline.txt")) .collect::, _>>()?, vec![ Token::Tree { @@ -271,7 +268,7 @@ mod iter { #[test] fn error_handling() -> crate::Result { let data = fixture_bytes("commit", "unsigned.txt"); - let iter = CommitRefIter::from_bytes(&data[..data.len() / 2]); + let iter = commit::RefIter::from_bytes(&data[..data.len() / 2]); let tokens = iter.collect::>(); assert!( tokens.last().expect("at least the errored token").is_err(), @@ -283,7 +280,7 @@ mod iter { #[test] fn mergetag() -> crate::Result { assert_eq!( - CommitRefIter::from_bytes(&fixture_bytes("commit", "mergetag.txt")).collect::, _>>()?, + commit::RefIter::from_bytes(&fixture_bytes("commit", "mergetag.txt")).collect::, _>>()?, vec![ Token::Tree { id: hex_to_id("1c61918031bf2c7fab9e17dde3c52a6a9884fcb5") @@ -308,21 +305,20 @@ mod iter { } mod method { - use git_object::immutable::CommitRefIter; - use crate::{ hex_to_id, immutable::{fixture_bytes, signature}, }; + use git_object::commit; #[test] fn tree_id() -> crate::Result { assert_eq!( - CommitRefIter::from_bytes(&fixture_bytes("commit", "unsigned.txt")).tree_id(), + commit::RefIter::from_bytes(&fixture_bytes("commit", "unsigned.txt")).tree_id(), Some(hex_to_id("1b2dfb4ac5e42080b682fc676e9738c94ce6d54d")) ); assert_eq!( - CommitRefIter::from_bytes(&fixture_bytes("commit", "unsigned.txt")) + commit::RefIter::from_bytes(&fixture_bytes("commit", "unsigned.txt")) .signatures() .collect::>(), vec![signature(1592437401), signature(1592437401)] @@ -333,7 +329,7 @@ mod iter { #[test] fn signatures() -> crate::Result { assert_eq!( - CommitRefIter::from_bytes(&fixture_bytes("commit", "unsigned.txt")) + commit::RefIter::from_bytes(&fixture_bytes("commit", "unsigned.txt")) .signatures() .collect::>(), vec![signature(1592437401), signature(1592437401)] @@ -344,7 +340,7 @@ mod iter { } mod from_bytes { - use git_object::{bstr::ByteSlice, immutable::CommitRef}; + use git_object::{bstr::ByteSlice, CommitRef}; use smallvec::SmallVec; use crate::immutable::{ diff --git a/git-object/tests/immutable/tag.rs b/git-object/tests/immutable/tag.rs index 17e3fce158c..7db7288f008 100644 --- a/git-object/tests/immutable/tag.rs +++ b/git-object/tests/immutable/tag.rs @@ -1,7 +1,7 @@ -use git_object::{bstr::ByteSlice, immutable::TagRef, Kind}; +use git_object::{bstr::ByteSlice, Kind, TagRef}; mod method { - use git_object::immutable::TagRef; + use git_object::TagRef; use pretty_assertions::assert_eq; use crate::{hex_to_id, immutable::fixture_bytes}; @@ -17,11 +17,7 @@ mod method { } mod iter { - use git_object::{ - bstr::ByteSlice, - immutable::{tag::iter::Token, TagRefIter}, - Kind, - }; + use git_object::{bstr::ByteSlice, immutable::tag::iter::Token, tag, Kind}; use crate::{ hex_to_id, @@ -31,7 +27,7 @@ mod iter { #[test] fn empty() -> crate::Result { assert_eq!( - TagRefIter::from_bytes(&fixture_bytes("tag", "empty.txt")).collect::, _>>()?, + tag::RefIter::from_bytes(&fixture_bytes("tag", "empty.txt")).collect::, _>>()?, vec![ Token::Target { id: hex_to_id("01dd4e2a978a9f5bd773dae6da7aa4a5ac1cdbbc") @@ -47,7 +43,7 @@ mod iter { #[test] fn no_tagger() -> crate::Result { assert_eq!( - TagRefIter::from_bytes(&fixture_bytes("tag", "no-tagger.txt")).collect::, _>>()?, + tag::RefIter::from_bytes(&fixture_bytes("tag", "no-tagger.txt")).collect::, _>>()?, vec![ Token::Target { id: hex_to_id("c39ae07f393806ccf406ef966e9a15afc43cc36a") @@ -83,7 +79,7 @@ KLMHist5yj0sw1E4hDTyQa0= #[test] fn whitespace() -> crate::Result { assert_eq!( - TagRefIter::from_bytes(&fixture_bytes("tag", "whitespace.txt")).collect::, _>>()?, + tag::RefIter::from_bytes(&fixture_bytes("tag", "whitespace.txt")).collect::, _>>()?, vec![ Token::Target { id: hex_to_id("01dd4e2a978a9f5bd773dae6da7aa4a5ac1cdbbc") @@ -103,7 +99,7 @@ KLMHist5yj0sw1E4hDTyQa0= #[test] fn error_handling() -> crate::Result { let data = fixture_bytes("tag", "empty.txt"); - let iter = TagRefIter::from_bytes(&data[..data.len() / 2]); + let iter = tag::RefIter::from_bytes(&data[..data.len() / 2]); let tokens = iter.collect::>(); assert!( tokens.last().expect("at least the errored token").is_err(), @@ -114,7 +110,7 @@ KLMHist5yj0sw1E4hDTyQa0= } mod from_bytes { - use git_object::{bstr::ByteSlice, immutable::TagRef, Kind}; + use git_object::{bstr::ByteSlice, Kind, TagRef}; use crate::immutable::{fixture_bytes, signature, tag::tag_fixture}; diff --git a/git-object/tests/immutable/tree.rs b/git-object/tests/immutable/tree.rs index 37bf5f60789..1040f032003 100644 --- a/git-object/tests/immutable/tree.rs +++ b/git-object/tests/immutable/tree.rs @@ -1,21 +1,21 @@ mod iter { - use git_object::{ - bstr::ByteSlice, - immutable::{tree::Entry, TreeIter}, - tree, - }; + use git_object::{bstr::ByteSlice, immutable::tree::EntryRef, tree}; use crate::{hex_to_id, immutable::fixture_bytes}; #[test] fn empty() { - assert_eq!(TreeIter::from_bytes(&[]).count(), 0, "empty trees are definitely ok"); + assert_eq!( + tree::RefIter::from_bytes(&[]).count(), + 0, + "empty trees are definitely ok" + ); } #[test] fn error_handling() { let data = fixture_bytes("tree", "everything.tree"); - let iter = TreeIter::from_bytes(&data[..data.len() / 2]); + let iter = tree::RefIter::from_bytes(&data[..data.len() / 2]); let entries = iter.collect::>(); assert!( entries.last().expect("at least one token").is_err(), @@ -26,29 +26,29 @@ mod iter { #[test] fn everything() -> crate::Result { assert_eq!( - TreeIter::from_bytes(&fixture_bytes("tree", "everything.tree")).collect::, _>>()?, + tree::RefIter::from_bytes(&fixture_bytes("tree", "everything.tree")).collect::, _>>()?, vec![ - Entry { + EntryRef { mode: tree::EntryMode::BlobExecutable, filename: b"exe".as_bstr(), oid: &hex_to_id("e69de29bb2d1d6434b8b29ae775ad8c2e48c5391") }, - Entry { + EntryRef { mode: tree::EntryMode::Blob, filename: b"file".as_bstr(), oid: &hex_to_id("e69de29bb2d1d6434b8b29ae775ad8c2e48c5391") }, - Entry { + EntryRef { mode: tree::EntryMode::Commit, filename: b"grit-submodule".as_bstr(), oid: &hex_to_id("b2d1b5d684bdfda5f922b466cc13d4ce2d635cf8") }, - Entry { + EntryRef { mode: tree::EntryMode::Tree, filename: b"subdir".as_bstr(), oid: &hex_to_id("4d5fcadc293a348e88f777dc0920f11e7d71441c") }, - Entry { + EntryRef { mode: tree::EntryMode::Link, filename: b"symlink".as_bstr(), oid: &hex_to_id("1a010b1c0f081b2e8901d55307a15c29ff30af0e") @@ -60,19 +60,15 @@ mod iter { } mod from_bytes { - use git_object::{ - bstr::ByteSlice, - immutable::{tree::Entry, Tree}, - tree, - }; + use git_object::{bstr::ByteSlice, immutable::tree::EntryRef, tree, TreeRef}; use crate::{hex_to_id, immutable::fixture_bytes}; #[test] fn empty() -> crate::Result { assert_eq!( - Tree::from_bytes(&[])?, - Tree { entries: vec![] }, + TreeRef::from_bytes(&[])?, + TreeRef { entries: vec![] }, "empty trees are valid despite usually rare in the wild" ); Ok(()) @@ -81,30 +77,30 @@ mod from_bytes { #[test] fn everything() -> crate::Result { assert_eq!( - Tree::from_bytes(&fixture_bytes("tree", "everything.tree"))?, - Tree { + TreeRef::from_bytes(&fixture_bytes("tree", "everything.tree"))?, + TreeRef { entries: vec![ - Entry { + EntryRef { mode: tree::EntryMode::BlobExecutable, filename: b"exe".as_bstr(), oid: &hex_to_id("e69de29bb2d1d6434b8b29ae775ad8c2e48c5391") }, - Entry { + EntryRef { mode: tree::EntryMode::Blob, filename: b"file".as_bstr(), oid: &hex_to_id("e69de29bb2d1d6434b8b29ae775ad8c2e48c5391") }, - Entry { + EntryRef { mode: tree::EntryMode::Commit, filename: b"grit-submodule".as_bstr(), oid: &hex_to_id("b2d1b5d684bdfda5f922b466cc13d4ce2d635cf8") }, - Entry { + EntryRef { mode: tree::EntryMode::Tree, filename: b"subdir".as_bstr(), oid: &hex_to_id("4d5fcadc293a348e88f777dc0920f11e7d71441c") }, - Entry { + EntryRef { mode: tree::EntryMode::Link, filename: b"symlink".as_bstr(), oid: &hex_to_id("1a010b1c0f081b2e8901d55307a15c29ff30af0e") @@ -118,7 +114,7 @@ mod from_bytes { #[test] fn maybe_special() -> crate::Result { assert_eq!( - Tree::from_bytes(&fixture_bytes("tree", "maybe-special.tree"))? + TreeRef::from_bytes(&fixture_bytes("tree", "maybe-special.tree"))? .entries .len(), 160 @@ -129,7 +125,7 @@ mod from_bytes { #[test] fn definitely_special() -> crate::Result { assert_eq!( - Tree::from_bytes(&fixture_bytes("tree", "definitely-special.tree"))? + TreeRef::from_bytes(&fixture_bytes("tree", "definitely-special.tree"))? .entries .len(), 19 diff --git a/git-object/tests/mutable/mod.rs b/git-object/tests/mutable/mod.rs index d28ed07416a..2df650ceacc 100644 --- a/git-object/tests/mutable/mod.rs +++ b/git-object/tests/mutable/mod.rs @@ -3,7 +3,7 @@ macro_rules! round_trip { #[test] fn round_trip() -> Result<(), Box> { use crate::fixture_bytes; - use git_object::{mutable, immutable}; + use git_object::{ObjectRef, mutable}; use bstr::ByteSlice; for input in &[ $( $files ),* @@ -16,7 +16,7 @@ macro_rules! round_trip { assert_eq!(output.as_bstr(), input.as_bstr()); // Test the parse->borrowed->owned->write chain for the top-level objects - let item: mutable::Object = immutable::ObjectRef::from(<$borrowed>::from_bytes(&input)?).into(); + let item: mutable::Object = ObjectRef::from(<$borrowed>::from_bytes(&input)?).into(); output.clear(); item.write_to(&mut output)?; assert_eq!(output.as_bstr(), input.as_bstr()); @@ -30,7 +30,7 @@ mod object; mod tag { round_trip!( mutable::Tag, - immutable::TagRef, + git_object::TagRef, "tag/empty.txt", "tag/no-tagger.txt", "tag/whitespace.txt", @@ -42,7 +42,7 @@ mod tag { mod commit { round_trip!( mutable::Commit, - immutable::CommitRef, + git_object::CommitRef, "commit/signed-whitespace.txt", "commit/two-multiline-headers.txt", "commit/mergetag.txt", @@ -57,10 +57,10 @@ mod commit { } mod tree { - round_trip!(mutable::Tree, immutable::Tree, "tree/everything.tree"); + round_trip!(mutable::Tree, git_object::TreeRef, "tree/everything.tree"); } mod blob { // It doesn't matter which data we use - it's not interpreted. - round_trip!(mutable::Blob, immutable::BlobRef, "tree/everything.tree"); + round_trip!(mutable::Blob, git_object::BlobRef, "tree/everything.tree"); } diff --git a/git-odb/tests/odb/store/loose/backend.rs b/git-odb/tests/odb/store/loose/backend.rs index 1c30ec3094e..31846b30cfc 100644 --- a/git-odb/tests/odb/store/loose/backend.rs +++ b/git-odb/tests/odb/store/loose/backend.rs @@ -55,7 +55,7 @@ mod write { } mod locate { - use git_object::{bstr::ByteSlice, immutable, immutable::tree, tree::EntryMode, Kind}; + use git_object::{bstr::ByteSlice, immutable::tree, tree::EntryMode, BlobRef, CommitRef, Kind, TagRef, TreeRef}; use crate::{ hex_to_id, @@ -75,7 +75,7 @@ mod locate { let o = locate("722fe60ad4f0276d5a8121970b5bb9dccdad4ef9", &mut buf); assert_eq!(o.kind, Kind::Tag); assert_eq!(o.data.len(), 1024); - let expected = immutable::TagRef { + let expected = TagRef { target: b"ffa700b4aca13b80cb6b98a078e7c96804f8e0ec".as_bstr(), name: b"1.0.0".as_bstr(), target_kind: Kind::Commit, @@ -113,7 +113,7 @@ cjHJZXWmV4CcRfmLsXzU8s2cR9A0DBvOxhPD1TlKC2JhBFXigjuL9U4Rbq9tdegB let o = locate("ffa700b4aca13b80cb6b98a078e7c96804f8e0ec", &mut buf); assert_eq!(o.kind, Kind::Commit); assert_eq!(o.data.len(), 1084); - let expected = immutable::CommitRef { + let expected = CommitRef { tree: b"6ba2a0ded519f737fd5b8d5ccfb141125ef3176f".as_bstr(), parents: vec![].into(), author: signature(1528473303), @@ -141,7 +141,7 @@ cjHJZXWmV4CcRfmLsXzU8s2cR9A0DBvOxhPD1TlKC2JhBFXigjuL9U4Rbq9tdegB let o = locate("37d4e6c5c48ba0d245164c4e10d5f41140cab980", &mut buf); assert_eq!( o.decode()?.as_blob().expect("blob"), - &immutable::BlobRef { + &BlobRef { data: &[104, 105, 32, 116, 104, 101, 114, 101, 10] }, "small blobs are treated similarly to other object types and are read into memory at once when the header is read" @@ -182,16 +182,16 @@ cjHJZXWmV4CcRfmLsXzU8s2cR9A0DBvOxhPD1TlKC2JhBFXigjuL9U4Rbq9tdegB assert_eq!(o.kind, Kind::Tree); assert_eq!(o.data.len(), 66); - let expected = immutable::Tree { + let expected = TreeRef { entries: vec![ - tree::Entry { + tree::EntryRef { mode: EntryMode::Tree, filename: b"dir".as_bstr(), oid: as_id(&[ 150, 174, 134, 139, 53, 57, 245, 81, 200, 143, 213, 240, 35, 148, 208, 34, 88, 27, 17, 176, ]), }, - tree::Entry { + tree::EntryRef { mode: EntryMode::Blob, filename: b"file.txt".as_bstr(), oid: as_id(&[ diff --git a/git-pack/src/data/object.rs b/git-pack/src/data/object.rs index d86e72ba9e9..8ef98bc5b76 100644 --- a/git-pack/src/data/object.rs +++ b/git-pack/src/data/object.rs @@ -1,6 +1,6 @@ //! Contains a borrowed Object bound to a buffer holding its decompressed data. -use git_object::immutable; +use git_object::{commit, immutable, tag, tree, BlobRef, CommitRef, ObjectRef, TagRef, TreeRef}; /// A borrowed object using a borrowed slice as backing buffer. #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] @@ -26,39 +26,39 @@ impl<'a> Object<'a> { /// conveniently. The cost of parsing an object is negligible. /// /// **Note** that [mutable, decoded objects][git_object::mutable::Object] can be created from a [`crate::data::Object`] - /// using [`git_object::immutable::ObjectRef::into_mutable()`]. - pub fn decode(&self) -> Result, immutable::object::decode::Error> { + /// using [`git_object::ObjectRef::into_mutable()`]. + pub fn decode(&self) -> Result, immutable::object::decode::Error> { Ok(match self.kind { - git_object::Kind::Tree => immutable::ObjectRef::Tree(immutable::Tree::from_bytes(self.data)?), - git_object::Kind::Blob => immutable::ObjectRef::Blob(immutable::BlobRef { data: self.data }), - git_object::Kind::Commit => immutable::ObjectRef::Commit(immutable::CommitRef::from_bytes(self.data)?), - git_object::Kind::Tag => immutable::ObjectRef::Tag(immutable::TagRef::from_bytes(self.data)?), + git_object::Kind::Tree => ObjectRef::Tree(TreeRef::from_bytes(self.data)?), + git_object::Kind::Blob => ObjectRef::Blob(BlobRef { data: self.data }), + git_object::Kind::Commit => ObjectRef::Commit(CommitRef::from_bytes(self.data)?), + git_object::Kind::Tag => ObjectRef::Tag(TagRef::from_bytes(self.data)?), }) } /// Returns this object as tree iterator to parse entries one at a time to avoid allocations, or /// `None` if this is not a tree object. - pub fn into_tree_iter(self) -> Option> { + pub fn into_tree_iter(self) -> Option> { match self.kind { - git_object::Kind::Tree => Some(immutable::TreeIter::from_bytes(self.data)), + git_object::Kind::Tree => Some(tree::RefIter::from_bytes(self.data)), _ => None, } } /// Returns this object as commit iterator to parse tokens one at a time to avoid allocations, or /// `None` if this is not a commit object. - pub fn into_commit_iter(self) -> Option> { + pub fn into_commit_iter(self) -> Option> { match self.kind { - git_object::Kind::Commit => Some(immutable::CommitRefIter::from_bytes(self.data)), + git_object::Kind::Commit => Some(commit::RefIter::from_bytes(self.data)), _ => None, } } /// Returns this object as tag iterator to parse tokens one at a time to avoid allocations, or /// `None` if this is not a tag object. - pub fn into_tag_iter(self) -> Option> { + pub fn into_tag_iter(self) -> Option> { match self.kind { - git_object::Kind::Tag => Some(immutable::TagRefIter::from_bytes(self.data)), + git_object::Kind::Tag => Some(tag::RefIter::from_bytes(self.data)), _ => None, } } diff --git a/git-pack/src/data/output/count/objects.rs b/git-pack/src/data/output/count/objects.rs index 24817c6c8b5..2cf12646be0 100644 --- a/git-pack/src/data/output/count/objects.rs +++ b/git-pack/src/data/output/count/objects.rs @@ -5,7 +5,7 @@ use std::sync::{ use git_features::{parallel, progress::Progress}; use git_hash::{oid, ObjectId}; -use git_object::immutable; +use git_object::{commit, immutable, tag}; use crate::{data::output, find, FindExt}; @@ -179,7 +179,7 @@ where match obj.kind { Tree | Blob => break, Tag => { - id = immutable::TagRefIter::from_bytes(obj.data) + id = tag::RefIter::from_bytes(obj.data) .target_id() .expect("every tag has a target"); obj = db.find_existing(id, buf1, cache)?; @@ -188,7 +188,7 @@ where } Commit => { let current_tree_iter = { - let mut commit_iter = immutable::CommitRefIter::from_bytes(obj.data); + let mut commit_iter = commit::RefIter::from_bytes(obj.data); let tree_id = commit_iter.tree_id().expect("every commit has a tree"); parent_commit_ids.clear(); for token in commit_iter { @@ -200,7 +200,7 @@ where } let obj = db.find_existing(tree_id, buf1, cache)?; push_obj_count_unique(&mut out, seen_objs, &tree_id, &obj, progress, stats, true); - immutable::TreeIter::from_bytes(obj.data) + git_object::tree::RefIter::from_bytes(obj.data) }; let objects = if parent_commit_ids.is_empty() { @@ -238,7 +238,7 @@ where stats, true, ); - immutable::CommitRefIter::from_bytes(parent_commit_obj.data) + commit::RefIter::from_bytes(parent_commit_obj.data) .tree_id() .expect("every commit has a tree") }; @@ -253,7 +253,7 @@ where stats, true, ); - immutable::TreeIter::from_bytes(parent_tree_obj.data) + git_object::tree::RefIter::from_bytes(parent_tree_obj.data) }; changes_delegate.clear(); @@ -289,7 +289,7 @@ where Tree => { traverse_delegate.clear(); git_traverse::tree::breadthfirst( - git_object::immutable::TreeIter::from_bytes(obj.data), + git_object::tree::RefIter::from_bytes(obj.data), &mut tree_traversal_state, |oid, buf| { stats.decoded_objects += 1; @@ -312,7 +312,7 @@ where break; } Commit => { - id = immutable::CommitRefIter::from_bytes(obj.data) + id = commit::RefIter::from_bytes(obj.data) .tree_id() .expect("every commit has a tree"); stats.expanded_objects += 1; @@ -321,7 +321,7 @@ where } Blob => break, Tag => { - id = immutable::TagRefIter::from_bytes(obj.data) + id = tag::RefIter::from_bytes(obj.data) .target_id() .expect("every tag has a target"); stats.expanded_objects += 1; @@ -397,7 +397,7 @@ mod tree { pub mod traverse { use git_hash::ObjectId; - use git_object::{bstr::BStr, immutable::tree::Entry}; + use git_object::{bstr::BStr, immutable::tree::EntryRef}; use git_traverse::tree::visit::{Action, Visit}; use crate::data::output::count::objects::util::InsertImmutable; @@ -434,7 +434,7 @@ mod tree { fn pop_path_component(&mut self) {} - fn visit_tree(&mut self, entry: &Entry<'_>) -> Action { + fn visit_tree(&mut self, entry: &EntryRef<'_>) -> Action { let inserted = self.all_seen.insert(entry.oid.to_owned()); if inserted { Action::Continue @@ -443,7 +443,7 @@ mod tree { } } - fn visit_nontree(&mut self, entry: &Entry<'_>) -> Action { + fn visit_nontree(&mut self, entry: &EntryRef<'_>) -> Action { let inserted = self.all_seen.insert(entry.oid.to_owned()); if inserted { self.non_trees.push(entry.oid.to_owned()); diff --git a/git-pack/src/find.rs b/git-pack/src/find.rs index 9568e0b07f6..aa8a5b3bc36 100644 --- a/git-pack/src/find.rs +++ b/git-pack/src/find.rs @@ -49,7 +49,7 @@ pub trait Find { } mod ext { - use git_object::{immutable, Kind}; + use git_object::{commit, tree, BlobRef, CommitRef, Kind, ObjectRef, TagRef, TreeRef}; use crate::{data, find}; @@ -123,42 +123,17 @@ mod ext { }) } - make_obj_lookup!( - find_existing_commit, - immutable::ObjectRef::Commit, - Kind::Commit, - immutable::CommitRef<'a> - ); - make_obj_lookup!( - find_existing_tree, - immutable::ObjectRef::Tree, - Kind::Tree, - immutable::Tree<'a> - ); - make_obj_lookup!( - find_existing_tag, - immutable::ObjectRef::Tag, - Kind::Tag, - immutable::TagRef<'a> - ); - make_obj_lookup!( - find_existing_blob, - immutable::ObjectRef::Blob, - Kind::Blob, - immutable::BlobRef<'a> - ); + make_obj_lookup!(find_existing_commit, ObjectRef::Commit, Kind::Commit, CommitRef<'a>); + make_obj_lookup!(find_existing_tree, ObjectRef::Tree, Kind::Tree, TreeRef<'a>); + make_obj_lookup!(find_existing_tag, ObjectRef::Tag, Kind::Tag, TagRef<'a>); + make_obj_lookup!(find_existing_blob, ObjectRef::Blob, Kind::Blob, BlobRef<'a>); make_iter_lookup!( find_existing_commit_iter, Kind::Blob, - immutable::CommitRefIter<'a>, + commit::RefIter<'a>, into_commit_iter ); - make_iter_lookup!( - find_existing_tree_iter, - Kind::Tree, - immutable::TreeIter<'a>, - into_tree_iter - ); + make_iter_lookup!(find_existing_tree_iter, Kind::Tree, tree::RefIter<'a>, into_tree_iter); } impl FindExt for T {} diff --git a/git-pack/src/index/verify.rs b/git-pack/src/index/verify.rs index 1e9897b4d72..305f6d73add 100644 --- a/git-pack/src/index/verify.rs +++ b/git-pack/src/index/verify.rs @@ -181,12 +181,10 @@ impl index::File { match object_kind { Tree | Commit | Tag => { let borrowed_object = - git_object::immutable::ObjectRef::from_bytes(object_kind, buf).map_err(|err| { - Error::ObjectDecode { - source: err, - kind: object_kind, - id: index_entry.oid, - } + git_object::ObjectRef::from_bytes(object_kind, buf).map_err(|err| Error::ObjectDecode { + source: err, + kind: object_kind, + id: index_entry.oid, })?; if let Mode::Sha1Crc32DecodeEncode = mode { let object = mutable::Object::from(borrowed_object); diff --git a/git-ref/src/store/file/loose/reference/peel.rs b/git-ref/src/store/file/loose/reference/peel.rs index 8e7c8795d20..fdedb6b5947 100644 --- a/git-ref/src/store/file/loose/reference/peel.rs +++ b/git-ref/src/store/file/loose/reference/peel.rs @@ -157,12 +157,13 @@ pub mod to_id { })?; match kind { git_object::Kind::Tag => { - oid = git_object::immutable::TagRefIter::from_bytes(data) - .target_id() - .ok_or_else(|| Error::NotFound { - oid, - name: self.name.0.clone(), - })?; + oid = + git_object::tag::RefIter::from_bytes(data) + .target_id() + .ok_or_else(|| Error::NotFound { + oid, + name: self.name.0.clone(), + })?; } _ => break oid, }; diff --git a/git-ref/src/store/packed/transaction.rs b/git-ref/src/store/packed/transaction.rs index 0cf583cb33f..72c77cc0840 100644 --- a/git-ref/src/store/packed/transaction.rs +++ b/git-ref/src/store/packed/transaction.rs @@ -77,13 +77,11 @@ impl packed::Transaction { let kind = find(next_id, &mut buf)?; match kind { Some(kind) if kind == git_object::Kind::Tag => { - next_id = git_object::immutable::TagRefIter::from_bytes(&buf) - .target_id() - .ok_or_else(|| { - prepare::Error::Resolve( - format!("Couldn't get target object id from tag {}", next_id).into(), - ) - })?; + next_id = git_object::tag::RefIter::from_bytes(&buf).target_id().ok_or_else(|| { + prepare::Error::Resolve( + format!("Couldn't get target object id from tag {}", next_id).into(), + ) + })?; } Some(_) => { break if next_id == new { None } else { Some(next_id) }; diff --git a/git-repository/src/easy/object/mod.rs b/git-repository/src/easy/object/mod.rs index d4ea73e7f6f..d1458ff1f2d 100644 --- a/git-repository/src/easy/object/mod.rs +++ b/git-repository/src/easy/object/mod.rs @@ -8,7 +8,7 @@ use crate::{ easy::{Object, ObjectRef, TreeRef}, }; use git_hash::ObjectId; -use git_object::immutable; +use git_object::{commit, tag}; use git_odb as odb; mod impls; @@ -141,11 +141,11 @@ impl<'repo, A> ObjectRef<'repo, A> where A: easy::Access + Sized, { - pub fn to_commit_iter(&self) -> Option> { + pub fn to_commit_iter(&self) -> Option> { odb::data::Object::new(self.kind, &self.data).into_commit_iter() } - pub fn to_tag_iter(&self) -> Option> { + pub fn to_tag_iter(&self) -> Option> { odb::data::Object::new(self.kind, &self.data).into_tag_iter() } } diff --git a/git-repository/src/easy/object/tree.rs b/git-repository/src/easy/object/tree.rs index 84ddbb3aef0..c02169618f6 100644 --- a/git-repository/src/easy/object/tree.rs +++ b/git-repository/src/easy/object/tree.rs @@ -18,7 +18,7 @@ where // let mut out = None; let mut path = path.into_iter().peekable(); while let Some(component) = path.next() { - match immutable::tree::TreeIter::from_bytes(&self.data) + match immutable::tree::RefIter::from_bytes(&self.data) .filter_map(Result::ok) .find(|entry| component.eq(entry.filename)) { diff --git a/git-repository/src/ext/object_id.rs b/git-repository/src/ext/object_id.rs index faa4249224f..15fa00acb88 100644 --- a/git-repository/src/ext/object_id.rs +++ b/git-repository/src/ext/object_id.rs @@ -1,11 +1,10 @@ #![allow(missing_docs)] use git_hash::ObjectId; #[cfg(feature = "git-traverse")] -use git_object::immutable; -#[cfg(feature = "git-traverse")] use git_traverse::commit::ancestors::{Ancestors, State}; use crate::easy; +use git_object::commit; pub trait Sealed {} @@ -13,7 +12,7 @@ pub trait ObjectIdExt: Sealed { #[cfg(feature = "git-traverse")] fn ancestors_iter(self, find: Find) -> Ancestors bool, State> where - Find: for<'a> FnMut(&git_hash::oid, &'a mut Vec) -> Option>; + Find: for<'a> FnMut(&git_hash::oid, &'a mut Vec) -> Option>; fn attach(self, access: &A) -> easy::Oid<'_, A>; } @@ -24,7 +23,7 @@ impl ObjectIdExt for ObjectId { #[cfg(feature = "git-traverse")] fn ancestors_iter(self, find: Find) -> Ancestors bool, State> where - Find: for<'a> FnMut(&git_hash::oid, &'a mut Vec) -> Option>, + Find: for<'a> FnMut(&git_hash::oid, &'a mut Vec) -> Option>, { Ancestors::new(Some(self), State::default(), find) } diff --git a/git-repository/src/ext/tree.rs b/git-repository/src/ext/tree.rs index 3d989ce2232..3be17b8c3cb 100644 --- a/git-repository/src/ext/tree.rs +++ b/git-repository/src/ext/tree.rs @@ -4,7 +4,7 @@ use std::borrow::BorrowMut; #[cfg(feature = "git-diff")] use git_hash::oid; -use git_object::immutable; +use git_object::{immutable, tree}; #[cfg(feature = "git-traverse")] use git_traverse::tree::breadthfirst; @@ -14,13 +14,13 @@ pub trait TreeIterExt: Sealed { #[cfg(feature = "git-diff")] fn changes_needed( &self, - other: immutable::TreeIter<'_>, + other: tree::RefIter<'_>, state: StateMut, find: FindFn, delegate: &mut R, ) -> Result<(), git_diff::tree::changes::Error> where - FindFn: for<'b> FnMut(&oid, &'b mut Vec) -> Option>, + FindFn: for<'b> FnMut(&oid, &'b mut Vec) -> Option>, R: git_diff::tree::Visit, StateMut: BorrowMut; @@ -33,24 +33,24 @@ pub trait TreeIterExt: Sealed { delegate: &mut V, ) -> Result<(), breadthfirst::Error> where - Find: for<'a> FnMut(&oid, &'a mut Vec) -> Option>, + Find: for<'a> FnMut(&oid, &'a mut Vec) -> Option>, StateMut: BorrowMut, V: git_traverse::tree::Visit; } -impl<'d> Sealed for immutable::TreeIter<'d> {} +impl<'d> Sealed for tree::RefIter<'d> {} -impl<'d> TreeIterExt for immutable::TreeIter<'d> { +impl<'d> TreeIterExt for tree::RefIter<'d> { #[cfg(feature = "git-diff")] fn changes_needed( &self, - other: immutable::TreeIter<'_>, + other: tree::RefIter<'_>, state: StateMut, find: FindFn, delegate: &mut R, ) -> Result<(), git_diff::tree::changes::Error> where - FindFn: for<'b> FnMut(&oid, &'b mut Vec) -> Option>, + FindFn: for<'b> FnMut(&oid, &'b mut Vec) -> Option>, R: git_diff::tree::Visit, StateMut: BorrowMut, { @@ -65,7 +65,7 @@ impl<'d> TreeIterExt for immutable::TreeIter<'d> { delegate: &mut V, ) -> Result<(), breadthfirst::Error> where - Find: for<'a> FnMut(&oid, &'a mut Vec) -> Option>, + Find: for<'a> FnMut(&oid, &'a mut Vec) -> Option>, StateMut: BorrowMut, V: git_traverse::tree::Visit, { diff --git a/git-traverse/src/commit.rs b/git-traverse/src/commit.rs index b9c707d4e17..2fa8306dcd9 100644 --- a/git-traverse/src/commit.rs +++ b/git-traverse/src/commit.rs @@ -6,7 +6,7 @@ pub mod ancestors { }; use git_hash::{oid, ObjectId}; - use git_object::immutable; + use git_object::{commit, immutable}; use quick_error::quick_error; quick_error! { @@ -50,7 +50,7 @@ pub mod ancestors { impl Ancestors bool, StateMut> where - Find: for<'a> FnMut(&oid, &'a mut Vec) -> Option>, + Find: for<'a> FnMut(&oid, &'a mut Vec) -> Option>, StateMut: BorrowMut, { /// Create a new instance. @@ -72,7 +72,7 @@ pub mod ancestors { impl Ancestors where - Find: for<'a> FnMut(&oid, &'a mut Vec) -> Option>, + Find: for<'a> FnMut(&oid, &'a mut Vec) -> Option>, Predicate: FnMut(&oid) -> bool, StateMut: BorrowMut, { @@ -114,7 +114,7 @@ pub mod ancestors { impl Iterator for Ancestors where - Find: for<'a> FnMut(&oid, &'a mut Vec) -> Option>, + Find: for<'a> FnMut(&oid, &'a mut Vec) -> Option>, Predicate: FnMut(&oid) -> bool, StateMut: BorrowMut, { diff --git a/git-traverse/src/tree/breadthfirst.rs b/git-traverse/src/tree/breadthfirst.rs index e51fc0310c5..68e7caa3f2e 100644 --- a/git-traverse/src/tree/breadthfirst.rs +++ b/git-traverse/src/tree/breadthfirst.rs @@ -52,13 +52,13 @@ impl State { /// be escalated into a more specific error if its encountered by the caller. /// * `delegate` - A way to observe entries and control the iteration while allowing the optimizer to let you pay only for what you use. pub fn traverse( - root: immutable::TreeIter<'_>, + root: tree::RefIter<'_>, mut state: StateMut, mut find: Find, delegate: &mut V, ) -> Result<(), Error> where - Find: for<'a> FnMut(&oid, &'a mut Vec) -> Option>, + Find: for<'a> FnMut(&oid, &'a mut Vec) -> Option>, StateMut: BorrowMut, V: Visit, { diff --git a/git-traverse/src/tree/recorder.rs b/git-traverse/src/tree/recorder.rs index 1273c4767d3..c99cc34172c 100644 --- a/git-traverse/src/tree/recorder.rs +++ b/git-traverse/src/tree/recorder.rs @@ -23,7 +23,7 @@ pub struct Entry { } impl Entry { - fn new(entry: &immutable::tree::Entry<'_>, filepath: BString) -> Self { + fn new(entry: &immutable::tree::EntryRef<'_>, filepath: BString) -> Self { Entry { filepath, oid: entry.oid.to_owned(), @@ -83,12 +83,12 @@ impl visit::Visit for Recorder { self.pop_element(); } - fn visit_tree(&mut self, entry: &immutable::tree::Entry<'_>) -> Action { + fn visit_tree(&mut self, entry: &immutable::tree::EntryRef<'_>) -> Action { self.records.push(Entry::new(entry, self.path_clone())); Action::Continue } - fn visit_nontree(&mut self, entry: &immutable::tree::Entry<'_>) -> Action { + fn visit_nontree(&mut self, entry: &immutable::tree::EntryRef<'_>) -> Action { self.records.push(Entry::new(entry, self.path_clone())); Action::Continue } diff --git a/git-traverse/src/tree/visit.rs b/git-traverse/src/tree/visit.rs index c64bf708419..5384ab6fbbe 100644 --- a/git-traverse/src/tree/visit.rs +++ b/git-traverse/src/tree/visit.rs @@ -34,11 +34,11 @@ pub trait Visit { /// [`Action::Skip`] can be used to prevent traversing it, for example if it's known to the caller already. /// /// The implementation may use the current path to learn where in the tree the change is located. - fn visit_tree(&mut self, entry: &immutable::tree::Entry<'_>) -> Action; + fn visit_tree(&mut self, entry: &immutable::tree::EntryRef<'_>) -> Action; /// Observe a tree entry that is NO tree and return an instruction whether to continue or not. /// [`Action::Skip`] has no effect here. /// /// The implementation may use the current path to learn where in the tree the change is located. - fn visit_nontree(&mut self, entry: &immutable::tree::Entry<'_>) -> Action; + fn visit_nontree(&mut self, entry: &immutable::tree::EntryRef<'_>) -> Action; } diff --git a/gitoxide-core/src/hours.rs b/gitoxide-core/src/hours.rs index 2bdc24d1fef..9a42a42b475 100644 --- a/gitoxide-core/src/hours.rs +++ b/gitoxide-core/src/hours.rs @@ -68,7 +68,7 @@ where progress.inc(); repo.odb.find_existing(oid, buf, &mut pack_cache).ok().map(|o| { commits.push(o.data.to_owned()); - objs::immutable::CommitRefIter::from_bytes(o.data) + objs::commit::RefIter::from_bytes(o.data) }) }), || anyhow!("Cancelled by user"), @@ -84,7 +84,7 @@ where let mut all_commits: Vec = all_commits .into_par_iter() .map(|commit_data: Vec| { - objs::immutable::CommitRefIter::from_bytes(&commit_data) + objs::commit::RefIter::from_bytes(&commit_data) .signatures() .next() .map(|author| actor::Signature::from(author)) From 07be6611d1742633815566443f71eef8b85ad5c0 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 26 Aug 2021 15:34:50 +0800 Subject: [PATCH 04/18] [object #177] fix docs --- git-object/src/commit.rs | 2 +- git-object/src/immutable/commit/iter.rs | 4 ++-- git-object/src/immutable/mod.rs | 4 ++-- git-object/src/immutable/tag.rs | 4 ++-- git-object/src/immutable/tree.rs | 2 +- git-object/src/lib.rs | 14 +++++++------- git-object/src/tree.rs | 2 +- git-pack/src/data/object.rs | 2 +- git-traverse/src/tree/recorder.rs | 2 +- 9 files changed, 18 insertions(+), 18 deletions(-) diff --git a/git-object/src/commit.rs b/git-object/src/commit.rs index e7a37ba5843..26806344321 100644 --- a/git-object/src/commit.rs +++ b/git-object/src/commit.rs @@ -4,7 +4,7 @@ use crate::{immutable, TagRef}; pub use crate::immutable::commit::iter::RefIter; -/// An iterator over extra headers in [owned][crate::mutable::Commit] and [borrowed][immutable::Commit] commits. +/// An iterator over extra headers in [owned][crate::mutable::Commit] and [borrowed][crate::CommitRef] commits. pub struct ExtraHeaders { inner: I, } diff --git a/git-object/src/immutable/commit/iter.rs b/git-object/src/immutable/commit/iter.rs index 05e4bc5fac4..ffbfe16ae6b 100644 --- a/git-object/src/immutable/commit/iter.rs +++ b/git-object/src/immutable/commit/iter.rs @@ -35,7 +35,7 @@ impl Default for State { } } -/// Like [`signature_ref::Commit`][super::Commit], but as `Iterator` to support (up to) entirely allocation free parsing. +/// Like [`CommitRef`][crate::CommitRef], but as `Iterator` to support (up to) entirely allocation free parsing. /// It's particularly useful to traverse the commit graph without ever allocating arrays for parents. pub struct RefIter<'a> { data: &'a [u8], @@ -196,7 +196,7 @@ impl<'a> Iterator for RefIter<'a> { } } -/// A token returned by the [commit iterator][Iter]. +/// A token returned by the [commit iterator][RefIter]. #[allow(missing_docs)] #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] pub enum Token<'a> { diff --git a/git-object/src/immutable/mod.rs b/git-object/src/immutable/mod.rs index d661afc2ea1..4d2e5d2af1c 100644 --- a/git-object/src/immutable/mod.rs +++ b/git-object/src/immutable/mod.rs @@ -1,7 +1,7 @@ -//! Immutable objects are read-only structures referencing most data from [a byte slice][Object::from_bytes()]. +//! Immutable objects are read-only structures referencing most data from [a byte slice][crate::ObjectRef::from_bytes()]. //! //! Immutable objects are expected to be deserialized from bytes that acts as backing store, and they -//! cannot be mutated or serialized. Instead, one will [convert][Object::into_mutable()] them into their [`mutable`][crate::mutable] counterparts +//! cannot be mutated or serialized. Instead, one will [convert][crate::ObjectRef::into_mutable()] them into their [`mutable`][crate::mutable] counterparts //! which support mutation and serialization. mod blob; diff --git a/git-object/src/immutable/tag.rs b/git-object/src/immutable/tag.rs index 3ce5920b7a5..6ca3015440c 100644 --- a/git-object/src/immutable/tag.rs +++ b/git-object/src/immutable/tag.rs @@ -139,7 +139,7 @@ pub mod iter { } } - /// Like [`signature_ref::Tag`][super::Tag], but as `Iterator` to support entirely allocation free parsing. + /// Like [`TagRef`][crate::TagRef], but as `Iterator` to support entirely allocation free parsing. /// It's particularly useful to dereference only the target chain. pub struct RefIter<'a> { data: &'a [u8], @@ -241,7 +241,7 @@ pub mod iter { } } - /// A token returned by the [commit iterator][Iter]. + /// A token returned by the [commit iterator][RefIter]. #[allow(missing_docs)] #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] pub enum Token<'a> { diff --git a/git-object/src/immutable/tree.rs b/git-object/src/immutable/tree.rs index a58028d958e..1a09ff9c78d 100644 --- a/git-object/src/immutable/tree.rs +++ b/git-object/src/immutable/tree.rs @@ -20,7 +20,7 @@ impl<'a> RefIter<'a> { } } -/// An element of a [`Tree`][Tree::entries]. +/// An element of a [`TreeRef`][TreeRef::entries]. #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] #[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] pub struct EntryRef<'a> { diff --git a/git-object/src/lib.rs b/git-object/src/lib.rs index 2d894ca8d2d..076d156c3f6 100644 --- a/git-object/src/lib.rs +++ b/git-object/src/lib.rs @@ -1,4 +1,4 @@ -//! This crate provides types for [read-only git objects][immutable::Object] backed by bytes provided in git's serialization format +//! This crate provides types for [read-only git objects][crate::ObjectRef] backed by bytes provided in git's serialization format //! as well as [mutable versions][mutable::Object] of these. The latter can be serialized into git's serialization format for objects. #![forbid(unsafe_code)] #![deny(rust_2018_idioms, missing_docs)] @@ -26,7 +26,7 @@ pub mod tree; mod types; -/// A chunk of any [`data`][Blob::data]. +/// A chunk of any [`data`][BlobRef::data]. #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] #[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] pub struct BlobRef<'a> { @@ -34,7 +34,7 @@ pub struct BlobRef<'a> { pub data: &'a [u8], } -/// A git commit parsed using [`from_bytes()`][Commit::from_bytes()]. +/// A git commit parsed using [`from_bytes()`][CommitRef::from_bytes()]. /// /// A commit encapsulates information about a point in time at which the state of the repository is recorded, usually after a /// change which is documented in the commit `message`. @@ -43,7 +43,7 @@ pub struct BlobRef<'a> { pub struct CommitRef<'a> { /// HEX hash of tree object we point to. Usually 40 bytes long. /// - /// Use [`tree()`][Commit::tree()] to obtain a decoded version of it. + /// Use [`tree()`][CommitRef::tree()] to obtain a decoded version of it. #[cfg_attr(feature = "serde1", serde(borrow))] pub tree: &'a BStr, /// HEX hash of each parent commit. Empty for first commit in repository. @@ -59,7 +59,7 @@ pub struct CommitRef<'a> { pub encoding: Option<&'a BStr>, /// The commit message documenting the change. pub message: &'a BStr, - /// Extra header fields, in order of them being encountered, made accessible with the iterator returned by [`extra_headers()`][Commit::extra_headers()]. + /// Extra header fields, in order of them being encountered, made accessible with the iterator returned by [`extra_headers()`][CommitRef::extra_headers()]. pub extra_headers: Vec<(&'a BStr, Cow<'a, BStr>)>, } @@ -67,7 +67,7 @@ pub struct CommitRef<'a> { #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] #[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] pub struct TagRef<'a> { - /// The hash in hexadecimal being the object this tag points to. Use [`target()`][Tag::target()] to obtain a byte representation. + /// The hash in hexadecimal being the object this tag points to. Use [`target()`][TagRef::target()] to obtain a byte representation. #[cfg_attr(feature = "serde1", serde(borrow))] pub target: &'a BStr, /// The kind of object that `target` points to. @@ -82,7 +82,7 @@ pub struct TagRef<'a> { pub pgp_signature: Option<&'a BStr>, } -/// An signature_ref object representing [`Trees`][Tree], [`Blobs`][Blob], [`Commits`][Commit], or [`Tags`][Tag]. +/// An signature_ref object representing [`Trees`][TreeRef], [`Blobs`][BlobRef], [`Commits`][CommitRef], or [`Tags`][TagRef]. #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] #[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] #[allow(missing_docs)] diff --git a/git-object/src/tree.rs b/git-object/src/tree.rs index 9b0aca4c381..2143a0c93f2 100644 --- a/git-object/src/tree.rs +++ b/git-object/src/tree.rs @@ -1,6 +1,6 @@ /// The mode of items storable in a tree, similar to the file mode on a unix file system. /// -/// Used in [mutable::Entry][crate::mutable::tree::Entry] and [tree::Entry][crate::immutable::tree::Entry]. +/// Used in [mutable::Entry][crate::mutable::tree::Entry] and [EntryRef]. #[derive(Clone, Copy, PartialEq, Eq, Debug, Ord, PartialOrd, Hash)] #[repr(u16)] #[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] diff --git a/git-pack/src/data/object.rs b/git-pack/src/data/object.rs index 8ef98bc5b76..5e137fe7243 100644 --- a/git-pack/src/data/object.rs +++ b/git-pack/src/data/object.rs @@ -22,7 +22,7 @@ impl<'a> Object<'a> { pack_location: None, } } - /// Decodes the data in the backing slice into a [`git_object::immutable::Object`], allowing to access all of its data + /// Decodes the data in the backing slice into a [`git_object::ObjectRef`], allowing to access all of its data /// conveniently. The cost of parsing an object is negligible. /// /// **Note** that [mutable, decoded objects][git_object::mutable::Object] can be created from a [`crate::data::Object`] diff --git a/git-traverse/src/tree/recorder.rs b/git-traverse/src/tree/recorder.rs index c99cc34172c..342a6f9f2a5 100644 --- a/git-traverse/src/tree/recorder.rs +++ b/git-traverse/src/tree/recorder.rs @@ -9,7 +9,7 @@ use git_object::{ use crate::tree::{visit, visit::Action}; /// An owned entry as observed by a call to [`visit_(tree|nontree)(…)`][visit::Visit::visit_tree()], enhanced with the full path to it. -/// Otherwise similar to [`signature_ref::tree::Entry`][git_object::immutable::tree::Entry]. +/// Otherwise similar to [`git_object::tree::EntryRef`]. #[derive(Clone, Debug, PartialEq, Eq)] pub struct Entry { /// The kind of entry, similar to entries in a unix directory tree. From fa5cd0648d5c855060ab2b75ee933851987c2dcf Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 26 Aug 2021 15:46:34 +0800 Subject: [PATCH 05/18] [object #177] migrate immutable::tree to crate::tree --- .../src/command/release/git.rs | 3 +- experiments/diffing/src/main.rs | 7 ++- experiments/traversal/src/main.rs | 2 +- git-diff/src/tree/changes.rs | 16 +++---- git-diff/src/tree/mod.rs | 6 +-- git-diff/tests/visit/mod.rs | 4 +- git-object/src/commit.rs | 3 +- git-object/src/immutable/blob.rs | 3 +- git-object/src/immutable/mod.rs | 5 +- git-object/src/immutable/object.rs | 3 +- git-object/src/lib.rs | 12 ++++- git-object/src/mutable/convert.rs | 8 ++-- git-object/src/{tree.rs => tree/mod.rs} | 19 +++++++- .../{immutable/tree.rs => tree/ref_iter.rs} | 47 ++++--------------- git-object/tests/immutable/commit.rs | 3 +- git-object/tests/immutable/tree.rs | 14 ++---- git-odb/tests/odb/store/loose/backend.rs | 6 +-- git-pack/src/data/object.rs | 6 +-- git-pack/src/data/output/count/objects.rs | 8 ++-- git-pack/src/find.rs | 4 +- git-ref/src/store/file/log/iter.rs | 6 ++- git-ref/src/store/file/log/line.rs | 3 +- git-ref/src/store/file/log/mod.rs | 1 - git-ref/src/target.rs | 3 +- git-ref/tests/file/transaction/mod.rs | 1 - git-repository/src/easy/ext/object.rs | 2 +- git-repository/src/easy/ext/reference.rs | 12 ++--- git-repository/src/easy/mod.rs | 3 +- git-repository/src/easy/object/mod.rs | 10 ++-- git-repository/src/easy/object/tree.rs | 7 +-- git-repository/src/easy/oid.rs | 3 +- git-repository/src/easy/reference.rs | 13 ++--- git-repository/src/easy/state.rs | 3 +- git-repository/src/ext/object_id.rs | 2 +- git-repository/src/ext/tree.rs | 18 +++---- git-traverse/src/tree/breadthfirst.rs | 6 +-- git-traverse/src/tree/recorder.rs | 8 ++-- git-traverse/src/tree/visit.rs | 6 +-- 38 files changed, 139 insertions(+), 147 deletions(-) rename git-object/src/{tree.rs => tree/mod.rs} (53%) rename git-object/src/{immutable/tree.rs => tree/ref_iter.rs} (68%) diff --git a/cargo-smart-release/src/command/release/git.rs b/cargo-smart-release/src/command/release/git.rs index 0048edd93a4..28e34819c68 100644 --- a/cargo-smart-release/src/command/release/git.rs +++ b/cargo-smart-release/src/command/release/git.rs @@ -6,10 +6,9 @@ use cargo_metadata::{ camino::{Utf8Component, Utf8Path}, Package, }; -use git_repository::easy::object; +use git_repository::{easy::object, prelude::ReferenceAccessExt, refs}; use super::{tag_name_for, utils::will, Context, Oid, Options}; -use git_repository::{prelude::ReferenceAccessExt, refs}; fn is_top_level_package(manifest_path: &Utf8Path, shared: &git_repository::Easy) -> bool { manifest_path diff --git a/experiments/diffing/src/main.rs b/experiments/diffing/src/main.rs index 75adc133bec..d2e99d0951a 100644 --- a/experiments/diffing/src/main.rs +++ b/experiments/diffing/src/main.rs @@ -2,12 +2,11 @@ use std::time::Instant; use anyhow::anyhow; use diff::tree::visit::{Action, Change}; -use git_repository::objs::tree; use git_repository::{ diff, easy::object, hash::{oid, ObjectId}, - objs::bstr::BStr, + objs::{bstr::BStr, TreeRefIter}, odb, prelude::*, refs::file::loose::reference::peel, @@ -255,14 +254,14 @@ where } }; - fn find_tree_iter<'b, L>(id: &oid, buf: &'b mut Vec, mut find: L) -> Option> + fn find_tree_iter<'b, L>(id: &oid, buf: &'b mut Vec, mut find: L) -> Option> where L: for<'a> FnMut(&oid, &'a mut Vec) -> Option>, { find(id, buf).and_then(|o| o.into_tree_iter()) } - fn tree_iter_by_commit<'b, L>(id: &oid, buf: &'b mut Vec, mut find: L) -> tree::RefIter<'b> + fn tree_iter_by_commit<'b, L>(id: &oid, buf: &'b mut Vec, mut find: L) -> TreeRefIter<'b> where L: for<'a> FnMut(&oid, &'a mut Vec) -> Option>, { diff --git a/experiments/traversal/src/main.rs b/experiments/traversal/src/main.rs index 65d91350678..f919b599149 100644 --- a/experiments/traversal/src/main.rs +++ b/experiments/traversal/src/main.rs @@ -7,7 +7,7 @@ use anyhow::anyhow; use dashmap::DashSet; use git_repository::{ hash::ObjectId, - objs::{bstr::BStr, immutable::tree::EntryRef}, + objs::{bstr::BStr, tree::EntryRef}, odb, prelude::*, refs::file::loose::reference::peel, diff --git a/git-diff/src/tree/changes.rs b/git-diff/src/tree/changes.rs index 099242c5d20..0d95e17b281 100644 --- a/git-diff/src/tree/changes.rs +++ b/git-diff/src/tree/changes.rs @@ -54,13 +54,13 @@ impl<'a> tree::Changes<'a> { /// [git_cmp_rs]: https://github.com/Byron/gitoxide/blob/a4d5f99c8dc99bf814790928a3bf9649cd99486b/git-object/src/mutable/tree.rs#L52-L55 pub fn needed_to_obtain( mut self, - other: git_object::tree::RefIter<'_>, + other: git_object::TreeRefIter<'_>, mut state: StateMut, mut find: FindFn, delegate: &mut R, ) -> Result<(), Error> where - FindFn: for<'b> FnMut(&oid, &'b mut Vec) -> Option>, + FindFn: for<'b> FnMut(&oid, &'b mut Vec) -> Option>, R: tree::Visit, StateMut: BorrowMut, { @@ -120,7 +120,7 @@ impl<'a> tree::Changes<'a> { } fn delete_entry_schedule_recursion( - entry: immutable::tree::EntryRef<'_>, + entry: git_object::tree::EntryRef<'_>, queue: &mut VecDeque, delegate: &mut R, ) -> Result<(), Error> { @@ -143,7 +143,7 @@ fn delete_entry_schedule_recursion( } fn add_entry_schedule_recursion( - entry: immutable::tree::EntryRef<'_>, + entry: git_object::tree::EntryRef<'_>, queue: &mut VecDeque, delegate: &mut R, ) -> Result<(), Error> { @@ -165,7 +165,7 @@ fn add_entry_schedule_recursion( Ok(()) } fn catchup_rhs_with_lhs( - rhs_entries: &mut IteratorType>, + rhs_entries: &mut IteratorType>, lhs: git_object::tree::EntryRef<'_>, rhs: git_object::tree::EntryRef<'_>, queue: &mut VecDeque, @@ -205,7 +205,7 @@ fn catchup_rhs_with_lhs( } fn catchup_lhs_with_rhs( - lhs_entries: &mut IteratorType>, + lhs_entries: &mut IteratorType>, lhs: git_object::tree::EntryRef<'_>, rhs: git_object::tree::EntryRef<'_>, queue: &mut VecDeque, @@ -245,8 +245,8 @@ fn catchup_lhs_with_rhs( } fn handle_lhs_and_rhs_with_equal_filenames( - lhs: immutable::tree::EntryRef<'_>, - rhs: immutable::tree::EntryRef<'_>, + lhs: git_object::tree::EntryRef<'_>, + rhs: git_object::tree::EntryRef<'_>, queue: &mut VecDeque, delegate: &mut R, ) -> Result<(), Error> { diff --git a/git-diff/src/tree/mod.rs b/git-diff/src/tree/mod.rs index 7489e4dc565..7d6ca8cef42 100644 --- a/git-diff/src/tree/mod.rs +++ b/git-diff/src/tree/mod.rs @@ -1,7 +1,7 @@ use std::collections::VecDeque; use git_hash::ObjectId; -use git_object::tree; +use git_object::TreeRefIter; /// The state required to visit [Changes] to be instantiated with `State::default()`. #[derive(Default, Clone)] @@ -22,11 +22,11 @@ impl State { } /// An iterator over changes of a tree, instantiated using `Changes::from(…)`. -pub struct Changes<'a>(Option>); +pub struct Changes<'a>(Option>); impl<'a, T> From for Changes<'a> where - T: Into>>, + T: Into>>, { fn from(v: T) -> Self { Changes(v.into()) diff --git a/git-diff/tests/visit/mod.rs b/git-diff/tests/visit/mod.rs index 7be49d9e6c6..bd41eb5448a 100644 --- a/git-diff/tests/visit/mod.rs +++ b/git-diff/tests/visit/mod.rs @@ -2,7 +2,7 @@ mod changes { mod to_obtain_tree { use git_diff::tree::{recorder, recorder::Change::*}; use git_hash::{oid, ObjectId}; - use git_object::{bstr::ByteSlice, tree, tree::EntryMode}; + use git_object::{bstr::ByteSlice, tree::EntryMode, TreeRefIter}; use git_odb::{linked, pack, Find}; use crate::hex_to_id; @@ -22,7 +22,7 @@ mod changes { db: &linked::Store, commit: &oid, buf: &'a mut Vec, - ) -> crate::Result> { + ) -> crate::Result> { let tree_id = db .find(commit, buf, &mut pack::cache::Never)? .ok_or_else(|| format!("start commit {:?} to be present", commit))? diff --git a/git-object/src/commit.rs b/git-object/src/commit.rs index 26806344321..491968ba380 100644 --- a/git-object/src/commit.rs +++ b/git-object/src/commit.rs @@ -1,8 +1,7 @@ use bstr::{BStr, ByteSlice}; -use crate::{immutable, TagRef}; - pub use crate::immutable::commit::iter::RefIter; +use crate::{immutable, TagRef}; /// An iterator over extra headers in [owned][crate::mutable::Commit] and [borrowed][crate::CommitRef] commits. pub struct ExtraHeaders { diff --git a/git-object/src/immutable/blob.rs b/git-object/src/immutable/blob.rs index fec651e2d37..b739473bdf1 100644 --- a/git-object/src/immutable/blob.rs +++ b/git-object/src/immutable/blob.rs @@ -1,6 +1,7 @@ -use crate::BlobRef; use std::convert::Infallible; +use crate::BlobRef; + impl<'a> BlobRef<'a> { /// Instantiate a `Blob` from the given `data`, which is used as-is. pub fn from_bytes(data: &[u8]) -> Result, Infallible> { diff --git a/git-object/src/immutable/mod.rs b/git-object/src/immutable/mod.rs index 4d2e5d2af1c..531ab2bc13d 100644 --- a/git-object/src/immutable/mod.rs +++ b/git-object/src/immutable/mod.rs @@ -15,7 +15,4 @@ pub mod object; /// pub mod tag; -/// -pub mod tree; - -mod parse; +pub(crate) mod parse; diff --git a/git-object/src/immutable/object.rs b/git-object/src/immutable/object.rs index 9077f607f85..7d6797f261d 100644 --- a/git-object/src/immutable/object.rs +++ b/git-object/src/immutable/object.rs @@ -98,8 +98,7 @@ impl<'a> ObjectRef<'a> { mod convert { use std::convert::TryFrom; - use crate::ObjectRef; - use crate::{BlobRef, CommitRef, TagRef, TreeRef}; + use crate::{BlobRef, CommitRef, ObjectRef, TagRef, TreeRef}; impl<'a> From> for ObjectRef<'a> { fn from(v: TagRef<'a>) -> Self { diff --git a/git-object/src/lib.rs b/git-object/src/lib.rs index 076d156c3f6..c896cfcb864 100644 --- a/git-object/src/lib.rs +++ b/git-object/src/lib.rs @@ -9,10 +9,9 @@ use std::borrow::Cow; pub use bstr; use bstr::{BStr, BString, ByteSlice}; use smallvec::SmallVec; - pub use types::{Error, Kind}; -use crate::immutable::tree::EntryRef; +use crate::tree::EntryRef; pub mod immutable; pub mod mutable; @@ -102,3 +101,12 @@ pub struct TreeRef<'a> { #[cfg_attr(feature = "serde1", serde(borrow))] pub entries: Vec>, } + +/// A directory snapshot containing files (blobs), directories (trees) and submodules (commits), lazily evaluated. +#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] +#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] +pub struct TreeRefIter<'a> { + /// The directories and files contained in this tree. + #[cfg_attr(feature = "serde1", serde(borrow))] + data: &'a [u8], +} diff --git a/git-object/src/mutable/convert.rs b/git-object/src/mutable/convert.rs index 02c709edd54..e4e83b5200a 100644 --- a/git-object/src/mutable/convert.rs +++ b/git-object/src/mutable/convert.rs @@ -1,4 +1,4 @@ -use crate::{immutable, mutable, BlobRef, CommitRef, ObjectRef, TagRef, TreeRef}; +use crate::{mutable, tree, BlobRef, CommitRef, ObjectRef, TagRef, TreeRef}; impl From> for mutable::Tag { fn from(other: TagRef<'_>) -> mutable::Tag { @@ -67,9 +67,9 @@ impl From> for mutable::Tree { } } -impl From> for mutable::tree::Entry { - fn from(other: immutable::tree::EntryRef<'_>) -> mutable::tree::Entry { - let immutable::tree::EntryRef { mode, filename, oid } = other; +impl From> for mutable::tree::Entry { + fn from(other: tree::EntryRef<'_>) -> mutable::tree::Entry { + let tree::EntryRef { mode, filename, oid } = other; mutable::tree::Entry { mode, filename: filename.to_owned(), diff --git a/git-object/src/tree.rs b/git-object/src/tree/mod.rs similarity index 53% rename from git-object/src/tree.rs rename to git-object/src/tree/mod.rs index 2143a0c93f2..7650726f534 100644 --- a/git-object/src/tree.rs +++ b/git-object/src/tree/mod.rs @@ -1,3 +1,5 @@ +use crate::{bstr::BStr, tree}; + /// The mode of items storable in a tree, similar to the file mode on a unix file system. /// /// Used in [mutable::Entry][crate::mutable::tree::Entry] and [EntryRef]. @@ -25,4 +27,19 @@ impl EntryMode { } } -pub use crate::immutable::tree::{EntryRef, RefIter}; +/// An element of a [`TreeRef`][TreeRef::entries]. +#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] +#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] +pub struct EntryRef<'a> { + /// The kind of object to which `oid` is pointing. + pub mode: tree::EntryMode, + /// The name of the file in the parent tree. + pub filename: &'a BStr, + /// The id of the object representing the entry. + // TODO: figure out how these should be called. id or oid? It's inconsistent around the codebase. + // Answer: make it 'id', as in `git2` + #[cfg_attr(feature = "serde1", serde(borrow))] + pub oid: &'a git_hash::oid, +} + +mod ref_iter; diff --git a/git-object/src/immutable/tree.rs b/git-object/src/tree/ref_iter.rs similarity index 68% rename from git-object/src/immutable/tree.rs rename to git-object/src/tree/ref_iter.rs index 1a09ff9c78d..bddca8a7a28 100644 --- a/git-object/src/immutable/tree.rs +++ b/git-object/src/tree/ref_iter.rs @@ -1,40 +1,14 @@ use std::convert::TryFrom; -use bstr::BStr; +use crate::{immutable::object, tree, tree::EntryRef, TreeRef, TreeRefIter}; -use crate::{immutable::object, tree, TreeRef}; - -/// A directory snapshot containing files (blobs), directories (trees) and submodules (commits), lazily evaluated. -#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] -#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] -pub struct RefIter<'a> { - /// The directories and files contained in this tree. - #[cfg_attr(feature = "serde1", serde(borrow))] - data: &'a [u8], -} - -impl<'a> RefIter<'a> { +impl<'a> TreeRefIter<'a> { /// Instantiate an iterator from the given tree data. - pub fn from_bytes(data: &'a [u8]) -> RefIter<'a> { - RefIter { data } + pub fn from_bytes(data: &'a [u8]) -> TreeRefIter<'a> { + TreeRefIter { data } } } -/// An element of a [`TreeRef`][TreeRef::entries]. -#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] -#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] -pub struct EntryRef<'a> { - /// The kind of object to which `oid` is pointing. - pub mode: tree::EntryMode, - /// The name of the file in the parent tree. - pub filename: &'a BStr, - /// The id of the object representing the entry. - // TODO: figure out how these should be called. id or oid? It's inconsistent around the codebase. - // Answer: make it 'id', as in `git2` - #[cfg_attr(feature = "serde1", serde(borrow))] - pub oid: &'a git_hash::oid, -} - impl<'a> TreeRef<'a> { /// Deserialize a Tree from `data`. pub fn from_bytes(data: &'a [u8]) -> Result, object::decode::Error> { @@ -49,20 +23,20 @@ impl<'a> TreeRef<'a> { } } -impl<'a> RefIter<'a> { +impl<'a> TreeRefIter<'a> { /// Consume self and return all parsed entries. pub fn entries(self) -> Result>, object::decode::Error> { self.collect() } } -impl<'a> Default for RefIter<'a> { +impl<'a> Default for TreeRefIter<'a> { fn default() -> Self { - RefIter { data: &[] } + TreeRefIter { data: &[] } } } -impl<'a> Iterator for RefIter<'a> { +impl<'a> Iterator for TreeRefIter<'a> { type Item = Result, object::decode::Error>; fn next(&mut self) -> Option { @@ -113,10 +87,7 @@ mod decode { IResult, }; - use crate::{ - immutable::{parse::SPACE, tree::EntryRef}, - tree, TreeRef, - }; + use crate::{immutable::parse::SPACE, tree, tree::EntryRef, TreeRef}; const NULL: &[u8] = b"\0"; diff --git a/git-object/tests/immutable/commit.rs b/git-object/tests/immutable/commit.rs index 30353debf55..2c996addeb3 100644 --- a/git-object/tests/immutable/commit.rs +++ b/git-object/tests/immutable/commit.rs @@ -305,11 +305,12 @@ mod iter { } mod method { + use git_object::commit; + use crate::{ hex_to_id, immutable::{fixture_bytes, signature}, }; - use git_object::commit; #[test] fn tree_id() -> crate::Result { diff --git a/git-object/tests/immutable/tree.rs b/git-object/tests/immutable/tree.rs index 1040f032003..24d210dd062 100644 --- a/git-object/tests/immutable/tree.rs +++ b/git-object/tests/immutable/tree.rs @@ -1,21 +1,17 @@ mod iter { - use git_object::{bstr::ByteSlice, immutable::tree::EntryRef, tree}; + use git_object::{bstr::ByteSlice, tree, tree::EntryRef, TreeRefIter}; use crate::{hex_to_id, immutable::fixture_bytes}; #[test] fn empty() { - assert_eq!( - tree::RefIter::from_bytes(&[]).count(), - 0, - "empty trees are definitely ok" - ); + assert_eq!(TreeRefIter::from_bytes(&[]).count(), 0, "empty trees are definitely ok"); } #[test] fn error_handling() { let data = fixture_bytes("tree", "everything.tree"); - let iter = tree::RefIter::from_bytes(&data[..data.len() / 2]); + let iter = TreeRefIter::from_bytes(&data[..data.len() / 2]); let entries = iter.collect::>(); assert!( entries.last().expect("at least one token").is_err(), @@ -26,7 +22,7 @@ mod iter { #[test] fn everything() -> crate::Result { assert_eq!( - tree::RefIter::from_bytes(&fixture_bytes("tree", "everything.tree")).collect::, _>>()?, + TreeRefIter::from_bytes(&fixture_bytes("tree", "everything.tree")).collect::, _>>()?, vec![ EntryRef { mode: tree::EntryMode::BlobExecutable, @@ -60,7 +56,7 @@ mod iter { } mod from_bytes { - use git_object::{bstr::ByteSlice, immutable::tree::EntryRef, tree, TreeRef}; + use git_object::{bstr::ByteSlice, tree, tree::EntryRef, TreeRef}; use crate::{hex_to_id, immutable::fixture_bytes}; diff --git a/git-odb/tests/odb/store/loose/backend.rs b/git-odb/tests/odb/store/loose/backend.rs index 31846b30cfc..649392c7cb6 100644 --- a/git-odb/tests/odb/store/loose/backend.rs +++ b/git-odb/tests/odb/store/loose/backend.rs @@ -55,7 +55,7 @@ mod write { } mod locate { - use git_object::{bstr::ByteSlice, immutable::tree, tree::EntryMode, BlobRef, CommitRef, Kind, TagRef, TreeRef}; + use git_object::{bstr::ByteSlice, tree::EntryMode, BlobRef, CommitRef, Kind, TagRef, TreeRef}; use crate::{ hex_to_id, @@ -184,14 +184,14 @@ cjHJZXWmV4CcRfmLsXzU8s2cR9A0DBvOxhPD1TlKC2JhBFXigjuL9U4Rbq9tdegB let expected = TreeRef { entries: vec![ - tree::EntryRef { + git_object::tree::EntryRef { mode: EntryMode::Tree, filename: b"dir".as_bstr(), oid: as_id(&[ 150, 174, 134, 139, 53, 57, 245, 81, 200, 143, 213, 240, 35, 148, 208, 34, 88, 27, 17, 176, ]), }, - tree::EntryRef { + git_object::tree::EntryRef { mode: EntryMode::Blob, filename: b"file.txt".as_bstr(), oid: as_id(&[ diff --git a/git-pack/src/data/object.rs b/git-pack/src/data/object.rs index 5e137fe7243..b53bf2c46e2 100644 --- a/git-pack/src/data/object.rs +++ b/git-pack/src/data/object.rs @@ -1,6 +1,6 @@ //! Contains a borrowed Object bound to a buffer holding its decompressed data. -use git_object::{commit, immutable, tag, tree, BlobRef, CommitRef, ObjectRef, TagRef, TreeRef}; +use git_object::{commit, immutable, tag, BlobRef, CommitRef, ObjectRef, TagRef, TreeRef, TreeRefIter}; /// A borrowed object using a borrowed slice as backing buffer. #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] @@ -38,9 +38,9 @@ impl<'a> Object<'a> { /// Returns this object as tree iterator to parse entries one at a time to avoid allocations, or /// `None` if this is not a tree object. - pub fn into_tree_iter(self) -> Option> { + pub fn into_tree_iter(self) -> Option> { match self.kind { - git_object::Kind::Tree => Some(tree::RefIter::from_bytes(self.data)), + git_object::Kind::Tree => Some(TreeRefIter::from_bytes(self.data)), _ => None, } } diff --git a/git-pack/src/data/output/count/objects.rs b/git-pack/src/data/output/count/objects.rs index 2cf12646be0..dd854ec9f9c 100644 --- a/git-pack/src/data/output/count/objects.rs +++ b/git-pack/src/data/output/count/objects.rs @@ -200,7 +200,7 @@ where } let obj = db.find_existing(tree_id, buf1, cache)?; push_obj_count_unique(&mut out, seen_objs, &tree_id, &obj, progress, stats, true); - git_object::tree::RefIter::from_bytes(obj.data) + git_object::TreeRefIter::from_bytes(obj.data) }; let objects = if parent_commit_ids.is_empty() { @@ -253,7 +253,7 @@ where stats, true, ); - git_object::tree::RefIter::from_bytes(parent_tree_obj.data) + git_object::TreeRefIter::from_bytes(parent_tree_obj.data) }; changes_delegate.clear(); @@ -289,7 +289,7 @@ where Tree => { traverse_delegate.clear(); git_traverse::tree::breadthfirst( - git_object::tree::RefIter::from_bytes(obj.data), + git_object::TreeRefIter::from_bytes(obj.data), &mut tree_traversal_state, |oid, buf| { stats.decoded_objects += 1; @@ -397,7 +397,7 @@ mod tree { pub mod traverse { use git_hash::ObjectId; - use git_object::{bstr::BStr, immutable::tree::EntryRef}; + use git_object::{bstr::BStr, tree::EntryRef}; use git_traverse::tree::visit::{Action, Visit}; use crate::data::output::count::objects::util::InsertImmutable; diff --git a/git-pack/src/find.rs b/git-pack/src/find.rs index aa8a5b3bc36..d2955c78bd4 100644 --- a/git-pack/src/find.rs +++ b/git-pack/src/find.rs @@ -49,7 +49,7 @@ pub trait Find { } mod ext { - use git_object::{commit, tree, BlobRef, CommitRef, Kind, ObjectRef, TagRef, TreeRef}; + use git_object::{commit, BlobRef, CommitRef, Kind, ObjectRef, TagRef, TreeRef, TreeRefIter}; use crate::{data, find}; @@ -133,7 +133,7 @@ mod ext { commit::RefIter<'a>, into_commit_iter ); - make_iter_lookup!(find_existing_tree_iter, Kind::Tree, tree::RefIter<'a>, into_tree_iter); + make_iter_lookup!(find_existing_tree_iter, Kind::Tree, TreeRefIter<'a>, into_tree_iter); } impl FindExt for T {} diff --git a/git-ref/src/store/file/log/iter.rs b/git-ref/src/store/file/log/iter.rs index 9b40387a949..f50aebcb246 100644 --- a/git-ref/src/store/file/log/iter.rs +++ b/git-ref/src/store/file/log/iter.rs @@ -1,7 +1,9 @@ use bstr::ByteSlice; -use crate::store::file; -use crate::store::file::{log, log::iter::decode::LineNumber}; +use crate::store::{ + file, + file::{log, log::iter::decode::LineNumber}, +}; /// pub mod decode { diff --git a/git-ref/src/store/file/log/line.rs b/git-ref/src/store/file/log/line.rs index 4b693b6d968..3c7cd67b06e 100644 --- a/git-ref/src/store/file/log/line.rs +++ b/git-ref/src/store/file/log/line.rs @@ -1,7 +1,6 @@ use git_hash::ObjectId; -use crate::store::file::log::Line; -use crate::store::file::log::LineRef; +use crate::store::file::log::{Line, LineRef}; impl<'a> LineRef<'a> { /// Convert this instance into its mutable counterpart diff --git a/git-ref/src/store/file/log/mod.rs b/git-ref/src/store/file/log/mod.rs index 9d53a15fd23..c4630a72484 100644 --- a/git-ref/src/store/file/log/mod.rs +++ b/git-ref/src/store/file/log/mod.rs @@ -1,5 +1,4 @@ use bstr::BStr; - use git_hash::ObjectId; use git_object::bstr::BString; diff --git a/git-ref/src/target.rs b/git-ref/src/target.rs index c24dce50936..34b9f5bf705 100644 --- a/git-ref/src/target.rs +++ b/git-ref/src/target.rs @@ -1,6 +1,7 @@ +use std::fmt; + use bstr::{BStr, ByteSlice}; use git_hash::{oid, ObjectId}; -use std::fmt; use crate::{FullName, Kind, Target, TargetRef}; diff --git a/git-ref/tests/file/transaction/mod.rs b/git-ref/tests/file/transaction/mod.rs index 29b01c83249..b5c52b83d58 100644 --- a/git-ref/tests/file/transaction/mod.rs +++ b/git-ref/tests/file/transaction/mod.rs @@ -1,6 +1,5 @@ mod prepare_and_commit { use bstr::BString; - use git_actor::{Sign, Time}; use git_hash::ObjectId; use git_ref::file; diff --git a/git-repository/src/easy/ext/object.rs b/git-repository/src/easy/ext/object.rs index 8fe7804d26a..8c090f99606 100644 --- a/git-repository/src/easy/ext/object.rs +++ b/git-repository/src/easy/ext/object.rs @@ -1,12 +1,12 @@ use std::ops::DerefMut; use git_hash::ObjectId; +use git_odb::{Find, FindExt}; use crate::{ easy, easy::{object, ObjectRef}, }; -use git_odb::{Find, FindExt}; pub fn find_object( access: &A, diff --git a/git-repository/src/easy/ext/reference.rs b/git-repository/src/easy/ext/reference.rs index 745e3ed2986..203487b5997 100644 --- a/git-repository/src/easy/ext/reference.rs +++ b/git-repository/src/easy/ext/reference.rs @@ -1,12 +1,7 @@ use std::convert::TryInto; -use git_hash::ObjectId; - -use crate::{ - easy, - easy::{reference, Reference}, -}; use git_actor as actor; +use git_hash::ObjectId; use git_lock as lock; use git_ref::{ file::find::Error, @@ -14,6 +9,11 @@ use git_ref::{ PartialNameRef, Target, }; +use crate::{ + easy, + easy::{reference, Reference}, +}; + /// Obtain and alter references comfortably pub trait ReferenceAccessExt: easy::Access + Sized { fn tag( diff --git a/git-repository/src/easy/mod.rs b/git-repository/src/easy/mod.rs index 4c1af267f10..491c8eedf83 100644 --- a/git-repository/src/easy/mod.rs +++ b/git-repository/src/easy/mod.rs @@ -18,12 +18,13 @@ use std::{ time::SystemTime, }; -use crate::Repository; use git_hash::ObjectId; use git_object as objs; use git_odb as odb; use git_ref as refs; +use crate::Repository; + mod impls; pub(crate) mod ext; diff --git a/git-repository/src/easy/object/mod.rs b/git-repository/src/easy/object/mod.rs index d1458ff1f2d..aae66676c29 100644 --- a/git-repository/src/easy/object/mod.rs +++ b/git-repository/src/easy/object/mod.rs @@ -1,15 +1,15 @@ #![allow(missing_docs)] use std::{cell::Ref, convert::TryInto}; +use git_hash::ObjectId; pub use git_object::Kind; +use git_object::{commit, tag}; +use git_odb as odb; use crate::{ easy, easy::{Object, ObjectRef, TreeRef}, }; -use git_hash::ObjectId; -use git_object::{commit, tag}; -use git_odb as odb; mod impls; mod tree; @@ -59,10 +59,10 @@ where } pub mod find { + use git_odb as odb; use quick_error::quick_error; use crate::easy; - use git_odb as odb; quick_error! { #[derive(Debug)] @@ -86,10 +86,10 @@ pub mod find { pub(crate) type OdbError = odb::compound::find::Error; pub mod existing { + use git_odb as odb; use quick_error::quick_error; use crate::easy; - use git_odb as odb; quick_error! { #[derive(Debug)] diff --git a/git-repository/src/easy/object/tree.rs b/git-repository/src/easy/object/tree.rs index c02169618f6..4168af77b51 100644 --- a/git-repository/src/easy/object/tree.rs +++ b/git-repository/src/easy/object/tree.rs @@ -1,9 +1,10 @@ +use git_object as objs; +use git_object::{bstr::BStr, TreeRefIter}; + use crate::{ easy, easy::{object::find, TreeRef}, }; -use git_object as objs; -use git_object::{bstr::BStr, immutable}; impl<'repo, A> TreeRef<'repo, A> where @@ -18,7 +19,7 @@ where // let mut out = None; let mut path = path.into_iter().peekable(); while let Some(component) = path.next() { - match immutable::tree::RefIter::from_bytes(&self.data) + match TreeRefIter::from_bytes(&self.data) .filter_map(Result::ok) .find(|entry| component.eq(entry.filename)) { diff --git a/git-repository/src/easy/oid.rs b/git-repository/src/easy/oid.rs index 76b985639ea..1dbedaf5450 100644 --- a/git-repository/src/easy/oid.rs +++ b/git-repository/src/easy/oid.rs @@ -1,8 +1,9 @@ +use git_hash::{oid, ObjectId}; + use crate::{ easy, easy::{object::find, Object, ObjectRef, Oid}, }; -use git_hash::{oid, ObjectId}; impl<'repo, A, B> PartialEq> for Oid<'repo, B> { fn eq(&self, other: &Oid<'repo, A>) -> bool { diff --git a/git-repository/src/easy/reference.rs b/git-repository/src/easy/reference.rs index 0dcd1b89ef8..0f24baea7dc 100644 --- a/git-repository/src/easy/reference.rs +++ b/git-repository/src/easy/reference.rs @@ -1,13 +1,14 @@ #![allow(missing_docs)] use std::ops::DerefMut; +use git_hash::ObjectId; +use git_odb::Find; +use git_ref as refs; + use crate::{ easy, easy::{Oid, Reference}, }; -use git_hash::ObjectId; -use git_odb::Find; -use git_ref as refs; pub(crate) enum Backing { OwnedPacked { @@ -23,10 +24,10 @@ pub(crate) enum Backing { } pub mod edit { + use git_ref as refs; use quick_error::quick_error; use crate::easy; - use git_ref as refs; quick_error! { #[derive(Debug)] @@ -55,10 +56,10 @@ pub mod edit { } pub mod peel_to_oid_in_place { + use git_ref as refs; use quick_error::quick_error; use crate::easy; - use git_ref as refs; quick_error! { #[derive(Debug)] @@ -163,10 +164,10 @@ where } pub mod find { + use git_ref as refs; use quick_error::quick_error; use crate::easy; - use git_ref as refs; pub mod existing { use quick_error::quick_error; diff --git a/git-repository/src/easy/state.rs b/git-repository/src/easy/state.rs index 11418385c7e..353045686d5 100644 --- a/git-repository/src/easy/state.rs +++ b/git-repository/src/easy/state.rs @@ -1,11 +1,12 @@ #![allow(missing_docs)] use std::cell::{Ref, RefMut}; +use git_ref::{file, packed}; + use crate::{ easy, easy::{borrow, PackCache}, }; -use git_ref::{file, packed}; impl Clone for easy::State { fn clone(&self) -> Self { diff --git a/git-repository/src/ext/object_id.rs b/git-repository/src/ext/object_id.rs index 15fa00acb88..d33db6c9732 100644 --- a/git-repository/src/ext/object_id.rs +++ b/git-repository/src/ext/object_id.rs @@ -1,10 +1,10 @@ #![allow(missing_docs)] use git_hash::ObjectId; +use git_object::commit; #[cfg(feature = "git-traverse")] use git_traverse::commit::ancestors::{Ancestors, State}; use crate::easy; -use git_object::commit; pub trait Sealed {} diff --git a/git-repository/src/ext/tree.rs b/git-repository/src/ext/tree.rs index 3be17b8c3cb..0615201ce59 100644 --- a/git-repository/src/ext/tree.rs +++ b/git-repository/src/ext/tree.rs @@ -4,7 +4,7 @@ use std::borrow::BorrowMut; #[cfg(feature = "git-diff")] use git_hash::oid; -use git_object::{immutable, tree}; +use git_object::TreeRefIter; #[cfg(feature = "git-traverse")] use git_traverse::tree::breadthfirst; @@ -14,13 +14,13 @@ pub trait TreeIterExt: Sealed { #[cfg(feature = "git-diff")] fn changes_needed( &self, - other: tree::RefIter<'_>, + other: TreeRefIter<'_>, state: StateMut, find: FindFn, delegate: &mut R, ) -> Result<(), git_diff::tree::changes::Error> where - FindFn: for<'b> FnMut(&oid, &'b mut Vec) -> Option>, + FindFn: for<'b> FnMut(&oid, &'b mut Vec) -> Option>, R: git_diff::tree::Visit, StateMut: BorrowMut; @@ -33,24 +33,24 @@ pub trait TreeIterExt: Sealed { delegate: &mut V, ) -> Result<(), breadthfirst::Error> where - Find: for<'a> FnMut(&oid, &'a mut Vec) -> Option>, + Find: for<'a> FnMut(&oid, &'a mut Vec) -> Option>, StateMut: BorrowMut, V: git_traverse::tree::Visit; } -impl<'d> Sealed for tree::RefIter<'d> {} +impl<'d> Sealed for TreeRefIter<'d> {} -impl<'d> TreeIterExt for tree::RefIter<'d> { +impl<'d> TreeIterExt for TreeRefIter<'d> { #[cfg(feature = "git-diff")] fn changes_needed( &self, - other: tree::RefIter<'_>, + other: TreeRefIter<'_>, state: StateMut, find: FindFn, delegate: &mut R, ) -> Result<(), git_diff::tree::changes::Error> where - FindFn: for<'b> FnMut(&oid, &'b mut Vec) -> Option>, + FindFn: for<'b> FnMut(&oid, &'b mut Vec) -> Option>, R: git_diff::tree::Visit, StateMut: BorrowMut, { @@ -65,7 +65,7 @@ impl<'d> TreeIterExt for tree::RefIter<'d> { delegate: &mut V, ) -> Result<(), breadthfirst::Error> where - Find: for<'a> FnMut(&oid, &'a mut Vec) -> Option>, + Find: for<'a> FnMut(&oid, &'a mut Vec) -> Option>, StateMut: BorrowMut, V: git_traverse::tree::Visit, { diff --git a/git-traverse/src/tree/breadthfirst.rs b/git-traverse/src/tree/breadthfirst.rs index 68e7caa3f2e..6bbdbccdd53 100644 --- a/git-traverse/src/tree/breadthfirst.rs +++ b/git-traverse/src/tree/breadthfirst.rs @@ -1,7 +1,7 @@ use std::{borrow::BorrowMut, collections::VecDeque}; use git_hash::{oid, ObjectId}; -use git_object::{immutable, tree}; +use git_object::{immutable, tree, TreeRefIter}; use quick_error::quick_error; use crate::tree::visit::Visit; @@ -52,13 +52,13 @@ impl State { /// be escalated into a more specific error if its encountered by the caller. /// * `delegate` - A way to observe entries and control the iteration while allowing the optimizer to let you pay only for what you use. pub fn traverse( - root: tree::RefIter<'_>, + root: TreeRefIter<'_>, mut state: StateMut, mut find: Find, delegate: &mut V, ) -> Result<(), Error> where - Find: for<'a> FnMut(&oid, &'a mut Vec) -> Option>, + Find: for<'a> FnMut(&oid, &'a mut Vec) -> Option>, StateMut: BorrowMut, V: Visit, { diff --git a/git-traverse/src/tree/recorder.rs b/git-traverse/src/tree/recorder.rs index 342a6f9f2a5..e3fed20ee03 100644 --- a/git-traverse/src/tree/recorder.rs +++ b/git-traverse/src/tree/recorder.rs @@ -3,7 +3,7 @@ use std::collections::VecDeque; use git_hash::ObjectId; use git_object::{ bstr::{BStr, BString, ByteSlice, ByteVec}, - immutable, tree, + tree, }; use crate::tree::{visit, visit::Action}; @@ -23,7 +23,7 @@ pub struct Entry { } impl Entry { - fn new(entry: &immutable::tree::EntryRef<'_>, filepath: BString) -> Self { + fn new(entry: &tree::EntryRef<'_>, filepath: BString) -> Self { Entry { filepath, oid: entry.oid.to_owned(), @@ -83,12 +83,12 @@ impl visit::Visit for Recorder { self.pop_element(); } - fn visit_tree(&mut self, entry: &immutable::tree::EntryRef<'_>) -> Action { + fn visit_tree(&mut self, entry: &tree::EntryRef<'_>) -> Action { self.records.push(Entry::new(entry, self.path_clone())); Action::Continue } - fn visit_nontree(&mut self, entry: &immutable::tree::EntryRef<'_>) -> Action { + fn visit_nontree(&mut self, entry: &tree::EntryRef<'_>) -> Action { self.records.push(Entry::new(entry, self.path_clone())); Action::Continue } diff --git a/git-traverse/src/tree/visit.rs b/git-traverse/src/tree/visit.rs index 5384ab6fbbe..2476acb1e0a 100644 --- a/git-traverse/src/tree/visit.rs +++ b/git-traverse/src/tree/visit.rs @@ -1,4 +1,4 @@ -use git_object::{bstr::BStr, immutable}; +use git_object::{bstr::BStr, tree}; /// What to do after an entry was [recorded][Visit::visit_tree()]. #[derive(Clone, Copy, PartialOrd, PartialEq, Ord, Eq, Hash)] @@ -34,11 +34,11 @@ pub trait Visit { /// [`Action::Skip`] can be used to prevent traversing it, for example if it's known to the caller already. /// /// The implementation may use the current path to learn where in the tree the change is located. - fn visit_tree(&mut self, entry: &immutable::tree::EntryRef<'_>) -> Action; + fn visit_tree(&mut self, entry: &tree::EntryRef<'_>) -> Action; /// Observe a tree entry that is NO tree and return an instruction whether to continue or not. /// [`Action::Skip`] has no effect here. /// /// The implementation may use the current path to learn where in the tree the change is located. - fn visit_nontree(&mut self, entry: &immutable::tree::EntryRef<'_>) -> Action; + fn visit_nontree(&mut self, entry: &tree::EntryRef<'_>) -> Action; } From c551c0236c64f3237cb9be7f35159f753d4b871f Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 26 Aug 2021 16:07:08 +0800 Subject: [PATCH 06/18] [object #177] move mutable objects to crate::* --- git-object/src/{immutable => }/blob.rs | 11 ++- git-object/src/immutable/mod.rs | 2 - git-object/src/immutable/object.rs | 6 +- git-object/src/lib.rs | 73 ++++++++++++++++++ git-object/src/mutable/commit.rs | 28 +------ git-object/src/mutable/convert.rs | 40 +++++----- git-object/src/mutable/mod.rs | 31 +------- git-object/src/mutable/object.rs | 34 +++------ git-object/src/mutable/tag.rs | 21 +---- git-object/src/mutable/tree.rs | 101 ------------------------- git-object/src/tree/mod.rs | 47 ++++++++++++ git-object/src/tree/write.rs | 53 +++++++++++++ git-object/tests/mutable/mod.rs | 12 +-- git-object/tests/mutable/object.rs | 2 +- git-odb/src/store/compound/write.rs | 4 +- git-odb/src/store/linked/write.rs | 4 +- git-odb/src/write.rs | 6 +- git-pack/src/index/verify.rs | 3 +- git-repository/src/easy/object/tree.rs | 3 +- 19 files changed, 240 insertions(+), 241 deletions(-) rename git-object/src/{immutable => }/blob.rs (55%) delete mode 100644 git-object/src/mutable/tree.rs create mode 100644 git-object/src/tree/write.rs diff --git a/git-object/src/immutable/blob.rs b/git-object/src/blob.rs similarity index 55% rename from git-object/src/immutable/blob.rs rename to git-object/src/blob.rs index b739473bdf1..2deb903c5dd 100644 --- a/git-object/src/immutable/blob.rs +++ b/git-object/src/blob.rs @@ -1,6 +1,15 @@ +use crate::Blob; +use crate::BlobRef; + use std::convert::Infallible; +use std::io; -use crate::BlobRef; +impl Blob { + /// Write the blobs data to `out` verbatim. + pub fn write_to(&self, mut out: impl io::Write) -> io::Result<()> { + out.write_all(&self.data) + } +} impl<'a> BlobRef<'a> { /// Instantiate a `Blob` from the given `data`, which is used as-is. diff --git a/git-object/src/immutable/mod.rs b/git-object/src/immutable/mod.rs index 531ab2bc13d..e8423ceb3f9 100644 --- a/git-object/src/immutable/mod.rs +++ b/git-object/src/immutable/mod.rs @@ -4,8 +4,6 @@ //! cannot be mutated or serialized. Instead, one will [convert][crate::ObjectRef::into_mutable()] them into their [`mutable`][crate::mutable] counterparts //! which support mutation and serialization. -mod blob; - /// pub mod commit; diff --git a/git-object/src/immutable/object.rs b/git-object/src/immutable/object.rs index 7d6797f261d..c13abdd30bb 100644 --- a/git-object/src/immutable/object.rs +++ b/git-object/src/immutable/object.rs @@ -1,4 +1,4 @@ -use crate::{BlobRef, CommitRef, Kind, ObjectRef, TagRef, TreeRef}; +use crate::{BlobRef, CommitRef, Kind, Object, ObjectRef, TagRef, TreeRef}; impl<'a> ObjectRef<'a> { /// Deserialize an object of `kind` from the given `data`. @@ -14,14 +14,14 @@ impl<'a> ObjectRef<'a> { /// Convert the signature_ref object into a mutable version, consuming the source in the process. /// /// Note that this is an expensive operation. - pub fn into_mutable(self) -> crate::mutable::Object { + pub fn into_mutable(self) -> Object { self.into() } /// Convert this signature_ref object into its mutable counterpart. /// /// Note that this is an expensive operation. - pub fn to_mutable(&self) -> crate::mutable::Object { + pub fn to_mutable(&self) -> Object { self.clone().into() } } diff --git a/git-object/src/lib.rs b/git-object/src/lib.rs index c896cfcb864..317e33ffc90 100644 --- a/git-object/src/lib.rs +++ b/git-object/src/lib.rs @@ -9,9 +9,11 @@ use std::borrow::Cow; pub use bstr; use bstr::{BStr, BString, ByteSlice}; use smallvec::SmallVec; + pub use types::{Error, Kind}; use crate::tree::EntryRef; +use tree::Entry; pub mod immutable; pub mod mutable; @@ -23,6 +25,8 @@ pub mod tag; /// pub mod tree; +mod blob; + mod types; /// A chunk of any [`data`][BlobRef::data]. @@ -110,3 +114,72 @@ pub struct TreeRefIter<'a> { #[cfg_attr(feature = "serde1", serde(borrow))] data: &'a [u8], } + +/// A mutable git tag. +#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] +#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] +pub struct Tag { + /// The hash this tag is pointing to. + pub target: git_hash::ObjectId, + /// The kind of object this tag is pointing to. + pub target_kind: crate::Kind, + /// The name of the tag, e.g. "v1.0". + pub name: BString, + /// The message describing the tag. + pub message: BString, + /// The tags author. + pub signature: Option, + /// A pgp signature over all bytes of the encoded tag, excluding the pgp signature itself. + pub pgp_signature: Option, +} + +/// A mutable Tree, containing other trees, blobs or commits. +#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] +#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] +pub struct Tree { + /// The directories and files contained in this tree. They must be and remain sorted by [`filename`][Entry::filename]. + pub entries: Vec, +} + +/// A mutable git commit, representing an annotated state of a working tree along with a reference to its historical commits. +#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] +#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] +pub struct Commit { + /// The hash of recorded working tree state. + pub tree: git_hash::ObjectId, + /// Hash of each parent commit. Empty for the first commit in repository. + pub parents: SmallVec<[git_hash::ObjectId; 1]>, + /// Who wrote this commit. + pub author: git_actor::Signature, + /// Who committed this commit. + /// + /// This may be different from the `author` in case the author couldn't write to the repository themselves and + /// is commonly encountered with contributed commits. + pub committer: git_actor::Signature, + /// The name of the message encoding, otherwise [UTF-8 should be assumed](https://github.com/git/git/blob/e67fbf927dfdf13d0b21dc6ea15dc3c7ef448ea0/commit.c#L1493:L1493). + pub encoding: Option, + /// The commit message documenting the change. + pub message: BString, + /// Extra header fields, in order of them being encountered, made accessible with the iterator returned + /// by [`extra_headers()`][Commit::extra_headers()]. + pub extra_headers: Vec<(BString, BString)>, +} + +/// A mutable chunk of any [`data`][Blob::data]. +#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] +#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] +pub struct Blob { + /// The data itself. + pub data: Vec, +} + +/// A mutable object representing [`Trees`][Tree], [`Blobs`][Blob], [`Commits`][Commit] or [`Tags`][Tag]. +#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] +#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] +#[allow(clippy::large_enum_variant, missing_docs)] +pub enum Object { + Tree(Tree), + Blob(Blob), + Commit(Commit), + Tag(Tag), +} diff --git a/git-object/src/mutable/commit.rs b/git-object/src/mutable/commit.rs index a52e7687034..87ef346b86f 100644 --- a/git-object/src/mutable/commit.rs +++ b/git-object/src/mutable/commit.rs @@ -1,37 +1,13 @@ use std::io; -use bstr::{BStr, BString, ByteSlice}; -use smallvec::SmallVec; +use bstr::{BStr, ByteSlice}; use crate::{ commit, mutable::{encode, NL}, + Commit, }; -/// A mutable git commit, representing an annotated state of a working tree along with a reference to its historical commits. -#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] -#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] -pub struct Commit { - /// The hash of recorded working tree state. - pub tree: git_hash::ObjectId, - /// Hash of each parent commit. Empty for the first commit in repository. - pub parents: SmallVec<[git_hash::ObjectId; 1]>, - /// Who wrote this commit. - pub author: git_actor::Signature, - /// Who committed this commit. - /// - /// This may be different from the `author` in case the author couldn't write to the repository themselves and - /// is commonly encountered with contributed commits. - pub committer: git_actor::Signature, - /// The name of the message encoding, otherwise [UTF-8 should be assumed](https://github.com/git/git/blob/e67fbf927dfdf13d0b21dc6ea15dc3c7ef448ea0/commit.c#L1493:L1493). - pub encoding: Option, - /// The commit message documenting the change. - pub message: BString, - /// Extra header fields, in order of them being encountered, made accessible with the iterator returned - /// by [`extra_headers()`][Commit::extra_headers()]. - pub extra_headers: Vec<(BString, BString)>, -} - impl Commit { /// Returns a convenient iterator over all extra headers. pub fn extra_headers(&self) -> commit::ExtraHeaders> { diff --git a/git-object/src/mutable/convert.rs b/git-object/src/mutable/convert.rs index e4e83b5200a..dd6c208bbe2 100644 --- a/git-object/src/mutable/convert.rs +++ b/git-object/src/mutable/convert.rs @@ -1,7 +1,7 @@ -use crate::{mutable, tree, BlobRef, CommitRef, ObjectRef, TagRef, TreeRef}; +use crate::{tree, Blob, BlobRef, Commit, CommitRef, Object, ObjectRef, Tag, TagRef, Tree, TreeRef}; -impl From> for mutable::Tag { - fn from(other: TagRef<'_>) -> mutable::Tag { +impl From> for Tag { + fn from(other: TagRef<'_>) -> Tag { let TagRef { target, name, @@ -10,7 +10,7 @@ impl From> for mutable::Tag { tagger: signature, pgp_signature, } = other; - mutable::Tag { + Tag { target: git_hash::ObjectId::from_hex(target).expect("40 bytes hex sha1"), name: name.to_owned(), target_kind, @@ -21,8 +21,8 @@ impl From> for mutable::Tag { } } -impl From> for mutable::Commit { - fn from(other: CommitRef<'_>) -> mutable::Commit { +impl From> for Commit { + fn from(other: CommitRef<'_>) -> Commit { let CommitRef { tree, parents, @@ -32,7 +32,7 @@ impl From> for mutable::Commit { message, extra_headers, } = other; - mutable::Commit { + Commit { tree: git_hash::ObjectId::from_hex(tree).expect("40 bytes hex sha1"), parents: parents .iter() @@ -50,27 +50,27 @@ impl From> for mutable::Commit { } } -impl<'a> From> for mutable::Blob { +impl<'a> From> for Blob { fn from(v: BlobRef<'a>) -> Self { - mutable::Blob { + Blob { data: v.data.to_owned(), } } } -impl From> for mutable::Tree { - fn from(other: TreeRef<'_>) -> mutable::Tree { +impl From> for Tree { + fn from(other: TreeRef<'_>) -> Tree { let TreeRef { entries } = other; - mutable::Tree { + Tree { entries: entries.into_iter().map(Into::into).collect(), } } } -impl From> for mutable::tree::Entry { - fn from(other: tree::EntryRef<'_>) -> mutable::tree::Entry { +impl From> for tree::Entry { + fn from(other: tree::EntryRef<'_>) -> tree::Entry { let tree::EntryRef { mode, filename, oid } = other; - mutable::tree::Entry { + tree::Entry { mode, filename: filename.to_owned(), oid: oid.into(), @@ -78,13 +78,13 @@ impl From> for mutable::tree::Entry { } } -impl<'a> From> for mutable::Object { +impl<'a> From> for Object { fn from(v: ObjectRef<'_>) -> Self { match v { - ObjectRef::Tree(v) => mutable::Object::Tree(v.into()), - ObjectRef::Blob(v) => mutable::Object::Blob(v.into()), - ObjectRef::Commit(v) => mutable::Object::Commit(v.into()), - ObjectRef::Tag(v) => mutable::Object::Tag(v.into()), + ObjectRef::Tree(v) => Object::Tree(v.into()), + ObjectRef::Blob(v) => Object::Blob(v.into()), + ObjectRef::Commit(v) => Object::Commit(v.into()), + ObjectRef::Tag(v) => Object::Tag(v.into()), } } } diff --git a/git-object/src/mutable/mod.rs b/git-object/src/mutable/mod.rs index b77f76b7176..ed88d0c4c51 100644 --- a/git-object/src/mutable/mod.rs +++ b/git-object/src/mutable/mod.rs @@ -4,41 +4,14 @@ //! They either created using object [construction][Object] or by [deserializing existing objects][crate::ObjectRef::from_bytes()] //! and converting these [into mutable copies][crate::ObjectRef::into_mutable()] for adjustments. -const NL: &[u8; 1] = b"\n"; -const SPACE: &[u8; 1] = b" "; +pub(crate) const NL: &[u8; 1] = b"\n"; +pub(crate) const SPACE: &[u8; 1] = b" "; mod convert; mod encode; mod tag; -pub use tag::Tag; - -/// -pub mod tree; -pub use tree::Tree; mod commit; -pub use commit::Commit; - -mod blob { - use std::io; - - /// A mutable chunk of any [`data`][Blob::data]. - #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] - #[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] - pub struct Blob { - /// The data itself. - pub data: Vec, - } - - impl Blob { - /// Write the blobs data to `out` verbatim. - pub fn write_to(&self, mut out: impl io::Write) -> io::Result<()> { - out.write_all(&self.data) - } - } -} -pub use blob::Blob; mod object; -pub use object::Object; diff --git a/git-object/src/mutable/object.rs b/git-object/src/mutable/object.rs index 3314df648d0..c694f08aa29 100644 --- a/git-object/src/mutable/object.rs +++ b/git-object/src/mutable/object.rs @@ -1,43 +1,32 @@ use std::io; -use crate::mutable; - -/// A mutable object representing [`Trees`][mutable::Tree], [`Blobs`][mutable::Blob], [`Commits`][mutable::Commit] or [`Tags`][mutable::Tag]. -#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] -#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] -#[allow(clippy::large_enum_variant, missing_docs)] -pub enum Object { - Tree(mutable::Tree), - Blob(mutable::Blob), - Commit(mutable::Commit), - Tag(mutable::Tag), -} +use crate::{Blob, Commit, Object, Tag, Tree}; /// Convenient extraction of typed object. impl Object { - /// Returns a [`Blob`][mutable::Blob] if it is one. - pub fn as_blob(&self) -> Option<&mutable::Blob> { + /// Returns a [`Blob`][Blob] if it is one. + pub fn as_blob(&self) -> Option<&Blob> { match self { Object::Blob(v) => Some(v), _ => None, } } - /// Returns a [`Commit`][mutable::Commit] if it is one. - pub fn as_commit(&self) -> Option<&mutable::Commit> { + /// Returns a [`Commit`][Commit] if it is one. + pub fn as_commit(&self) -> Option<&Commit> { match self { Object::Commit(v) => Some(v), _ => None, } } - /// Returns a [`Tree`][mutable::Tree] if it is one. - pub fn as_tree(&self) -> Option<&mutable::Tree> { + /// Returns a [`Tree`][Tree] if it is one. + pub fn as_tree(&self) -> Option<&Tree> { match self { Object::Tree(v) => Some(v), _ => None, } } - /// Returns a [`Tag`][mutable::Tag] if it is one. - pub fn as_tag(&self) -> Option<&mutable::Tag> { + /// Returns a [`Tag`][Tag] if it is one. + pub fn as_tag(&self) -> Option<&Tag> { match self { Object::Tag(v) => Some(v), _ => None, @@ -58,7 +47,7 @@ impl Object { impl Object { /// Write the contained object to `out` in the git serialization format. pub fn write_to(&self, out: impl io::Write) -> io::Result<()> { - use Object::*; + use crate::Object::*; match self { Tree(v) => v.write_to(out), Blob(v) => v.write_to(out), @@ -71,7 +60,8 @@ impl Object { mod convert { use std::convert::TryFrom; - use crate::mutable::{Blob, Commit, Object, Tag, Tree}; + use crate::Object; + use crate::{Blob, Commit, Tag, Tree}; impl From for Object { fn from(v: Tag) -> Self { diff --git a/git-object/src/mutable/tag.rs b/git-object/src/mutable/tag.rs index 1c7e769384f..43fa87016f2 100644 --- a/git-object/src/mutable/tag.rs +++ b/git-object/src/mutable/tag.rs @@ -1,9 +1,10 @@ use std::io; -use bstr::{BStr, BString}; +use bstr::BStr; use quick_error::quick_error; use crate::mutable::{encode, NL}; +use crate::Tag; quick_error! { /// An Error used in [`Tag::write_to()`]. @@ -26,24 +27,6 @@ impl From for io::Error { } } -/// A mutable git tag. -#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] -#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] -pub struct Tag { - /// The hash this tag is pointing to. - pub target: git_hash::ObjectId, - /// The kind of object this tag is pointing to. - pub target_kind: crate::Kind, - /// The name of the tag, e.g. "v1.0". - pub name: BString, - /// The message describing the tag. - pub message: BString, - /// The tags author. - pub signature: Option, - /// A pgp signature over all bytes of the encoded tag, excluding the pgp signature itself. - pub pgp_signature: Option, -} - impl Tag { /// Writes the encoded tag to `out`. pub fn write_to(&self, mut out: impl io::Write) -> io::Result<()> { diff --git a/git-object/src/mutable/tree.rs b/git-object/src/mutable/tree.rs deleted file mode 100644 index 477b0e00ca0..00000000000 --- a/git-object/src/mutable/tree.rs +++ /dev/null @@ -1,101 +0,0 @@ -use std::{cmp::Ordering, io}; - -use bstr::{BString, ByteSlice}; -use quick_error::quick_error; - -use crate::{mutable::SPACE, tree::EntryMode}; - -quick_error! { - /// The Error used in [`Tree::write_to()`]. - #[derive(Debug)] - #[allow(missing_docs)] - pub enum Error { - NewlineInFilename(name: BString) { - display("Newlines are invalid in file paths: {:?}", name) - } - } -} - -impl From for io::Error { - fn from(err: Error) -> Self { - io::Error::new(io::ErrorKind::Other, err) - } -} - -/// A mutable Tree, containing other trees, blobs or commits. -#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] -#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] -pub struct Tree { - /// The directories and files contained in this tree. They must be and remain sorted by [`filename`][Entry::filename]. - pub entries: Vec, -} - -/// An entry in a [`Tree`], similar to an entry in a directory. -#[derive(PartialEq, Eq, Debug, Hash, Clone)] -#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] -pub struct Entry { - /// The kind of object to which `oid` is pointing to. - pub mode: EntryMode, - /// The name of the file in the parent tree. - pub filename: BString, - /// The id of the object representing the entry. - pub oid: git_hash::ObjectId, -} - -impl PartialOrd for Entry { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl Ord for Entry { - /// Entries compare by the common portion of the filename. This is critical for proper functioning of algorithms working on trees. - fn cmp(&self, other: &Self) -> Ordering { - let len = self.filename.len().min(other.filename.len()); - self.filename[..len].cmp(&other.filename[..len]) - } -} - -/// Serialization -impl EntryMode { - /// Return the representation as used in the git internal format. - pub fn as_bytes(&self) -> &'static [u8] { - use EntryMode::*; - match self { - Tree => b"40000", - Blob => b"100644", - BlobExecutable => b"100755", - Link => b"120000", - Commit => b"160000", - } - } -} - -/// Serialization -impl Tree { - /// Serialize this tree to `out` in the git internal format. - pub fn write_to(&self, mut out: impl io::Write) -> io::Result<()> { - debug_assert_eq!( - &{ - let mut entries_sorted = self.entries.clone(); - entries_sorted.sort(); - entries_sorted - }, - &self.entries, - "entries for serialization must be sorted by filename" - ); - for Entry { mode, filename, oid } in &self.entries { - out.write_all(mode.as_bytes())?; - out.write_all(SPACE)?; - - if filename.find_byte(b'\n').is_some() { - return Err(Error::NewlineInFilename(filename.to_owned()).into()); - } - out.write_all(filename)?; - out.write_all(&[b'\0'])?; - - out.write_all(oid.as_bytes())?; - } - Ok(()) - } -} diff --git a/git-object/src/tree/mod.rs b/git-object/src/tree/mod.rs index 7650726f534..5f48ccef7bf 100644 --- a/git-object/src/tree/mod.rs +++ b/git-object/src/tree/mod.rs @@ -1,3 +1,6 @@ +use std::cmp::Ordering; + +use crate::bstr::BString; use crate::{bstr::BStr, tree}; /// The mode of items storable in a tree, similar to the file mode on a unix file system. @@ -43,3 +46,47 @@ pub struct EntryRef<'a> { } mod ref_iter; + +/// An entry in a [`Tree`], similar to an entry in a directory. +#[derive(PartialEq, Eq, Debug, Hash, Clone)] +#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] +pub struct Entry { + /// The kind of object to which `oid` is pointing to. + pub mode: EntryMode, + /// The name of the file in the parent tree. + pub filename: BString, + /// The id of the object representing the entry. + pub oid: git_hash::ObjectId, +} + +impl PartialOrd for Entry { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Entry { + /// Entries compare by the common portion of the filename. This is critical for proper functioning of algorithms working on trees. + fn cmp(&self, other: &Self) -> Ordering { + let len = self.filename.len().min(other.filename.len()); + self.filename[..len].cmp(&other.filename[..len]) + } +} + +/// Serialization +impl EntryMode { + /// Return the representation as used in the git internal format. + pub fn as_bytes(&self) -> &'static [u8] { + use EntryMode::*; + match self { + Tree => b"40000", + Blob => b"100644", + BlobExecutable => b"100755", + Link => b"120000", + Commit => b"160000", + } + } +} + +/// +pub mod write; diff --git a/git-object/src/tree/write.rs b/git-object/src/tree/write.rs new file mode 100644 index 00000000000..af793a92562 --- /dev/null +++ b/git-object/src/tree/write.rs @@ -0,0 +1,53 @@ +use std::io; + +use bstr::{BString, ByteSlice}; +use quick_error::quick_error; + +use crate::tree::Entry; +use crate::{mutable::SPACE, Tree}; + +quick_error! { + /// The Error used in [`Tree::write_to()`]. + #[derive(Debug)] + #[allow(missing_docs)] + pub enum Error { + NewlineInFilename(name: BString) { + display("Newlines are invalid in file paths: {:?}", name) + } + } +} + +impl From for io::Error { + fn from(err: Error) -> Self { + io::Error::new(io::ErrorKind::Other, err) + } +} + +/// Serialization +impl Tree { + /// Serialize this tree to `out` in the git internal format. + pub fn write_to(&self, mut out: impl io::Write) -> io::Result<()> { + debug_assert_eq!( + &{ + let mut entries_sorted = self.entries.clone(); + entries_sorted.sort(); + entries_sorted + }, + &self.entries, + "entries for serialization must be sorted by filename" + ); + for Entry { mode, filename, oid } in &self.entries { + out.write_all(mode.as_bytes())?; + out.write_all(SPACE)?; + + if filename.find_byte(b'\n').is_some() { + return Err(Error::NewlineInFilename(filename.to_owned()).into()); + } + out.write_all(filename)?; + out.write_all(&[b'\0'])?; + + out.write_all(oid.as_bytes())?; + } + Ok(()) + } +} diff --git a/git-object/tests/mutable/mod.rs b/git-object/tests/mutable/mod.rs index 2df650ceacc..0d3e2bb8436 100644 --- a/git-object/tests/mutable/mod.rs +++ b/git-object/tests/mutable/mod.rs @@ -3,7 +3,7 @@ macro_rules! round_trip { #[test] fn round_trip() -> Result<(), Box> { use crate::fixture_bytes; - use git_object::{ObjectRef, mutable}; + use git_object::{ObjectRef, Object}; use bstr::ByteSlice; for input in &[ $( $files ),* @@ -16,7 +16,7 @@ macro_rules! round_trip { assert_eq!(output.as_bstr(), input.as_bstr()); // Test the parse->borrowed->owned->write chain for the top-level objects - let item: mutable::Object = ObjectRef::from(<$borrowed>::from_bytes(&input)?).into(); + let item: Object = ObjectRef::from(<$borrowed>::from_bytes(&input)?).into(); output.clear(); item.write_to(&mut output)?; assert_eq!(output.as_bstr(), input.as_bstr()); @@ -29,7 +29,7 @@ macro_rules! round_trip { mod object; mod tag { round_trip!( - mutable::Tag, + git_object::Tag, git_object::TagRef, "tag/empty.txt", "tag/no-tagger.txt", @@ -41,7 +41,7 @@ mod tag { mod commit { round_trip!( - mutable::Commit, + git_object::Commit, git_object::CommitRef, "commit/signed-whitespace.txt", "commit/two-multiline-headers.txt", @@ -57,10 +57,10 @@ mod commit { } mod tree { - round_trip!(mutable::Tree, git_object::TreeRef, "tree/everything.tree"); + round_trip!(git_object::Tree, git_object::TreeRef, "tree/everything.tree"); } mod blob { // It doesn't matter which data we use - it's not interpreted. - round_trip!(mutable::Blob, git_object::BlobRef, "tree/everything.tree"); + round_trip!(git_object::Blob, git_object::BlobRef, "tree/everything.tree"); } diff --git a/git-object/tests/mutable/object.rs b/git-object/tests/mutable/object.rs index 49758394315..6a934aa0207 100644 --- a/git-object/tests/mutable/object.rs +++ b/git-object/tests/mutable/object.rs @@ -1,4 +1,4 @@ -use git_object::mutable::Object; +use git_object::Object; #[test] fn size_in_memory() { diff --git a/git-odb/src/store/compound/write.rs b/git-odb/src/store/compound/write.rs index 3716387a90b..bbaa7e845b3 100644 --- a/git-odb/src/store/compound/write.rs +++ b/git-odb/src/store/compound/write.rs @@ -1,13 +1,13 @@ use std::io::Read; -use git_object::{mutable, Kind}; +use git_object::{Kind, Object}; use crate::store::{compound, loose}; impl crate::write::Write for compound::Store { type Error = loose::write::Error; - fn write(&self, object: &mutable::Object, hash: git_hash::Kind) -> Result { + fn write(&self, object: &Object, hash: git_hash::Kind) -> Result { self.loose.write(object, hash) } diff --git a/git-odb/src/store/linked/write.rs b/git-odb/src/store/linked/write.rs index 6f17b5a13a1..8a34f787a02 100644 --- a/git-odb/src/store/linked/write.rs +++ b/git-odb/src/store/linked/write.rs @@ -1,13 +1,13 @@ use std::io::Read; -use git_object::{mutable, Kind}; +use git_object::{Kind, Object}; use crate::store::{linked, loose}; impl crate::write::Write for linked::Store { type Error = loose::write::Error; - fn write(&self, object: &mutable::Object, hash: git_hash::Kind) -> Result { + fn write(&self, object: &Object, hash: git_hash::Kind) -> Result { self.dbs[0].loose.write(object, hash) } diff --git a/git-odb/src/write.rs b/git-odb/src/write.rs index 67c96874aa7..bb35723908a 100644 --- a/git-odb/src/write.rs +++ b/git-odb/src/write.rs @@ -1,6 +1,6 @@ use std::io; -use git_object::mutable; +use git_object::Object; /// Describe the capability to write git objects into an object store. pub trait Write { @@ -9,9 +9,9 @@ pub trait Write { /// _Note_ the default implementations require the `From` bound. type Error: std::error::Error + From; - /// Write [`object`][mutable::Object] using the given kind of [`hash`][git_hash::Kind] into the database, + /// Write [`object`][Object] using the given kind of [`hash`][git_hash::Kind] into the database, /// returning id to reference it in subsequent reads. - fn write(&self, object: &mutable::Object, hash: git_hash::Kind) -> Result { + fn write(&self, object: &Object, hash: git_hash::Kind) -> Result { let mut buf = Vec::with_capacity(2048); object.write_to(&mut buf)?; self.write_stream(object.kind(), buf.len() as u64, buf.as_slice(), hash) diff --git a/git-pack/src/index/verify.rs b/git-pack/src/index/verify.rs index 305f6d73add..cc0ca50af73 100644 --- a/git-pack/src/index/verify.rs +++ b/git-pack/src/index/verify.rs @@ -5,7 +5,6 @@ use git_hash::SIZE_OF_SHA1_DIGEST as SHA1_SIZE; use git_object::{ bstr::{BString, ByteSlice}, immutable::object, - mutable, }; use crate::index; @@ -187,7 +186,7 @@ impl index::File { id: index_entry.oid, })?; if let Mode::Sha1Crc32DecodeEncode = mode { - let object = mutable::Object::from(borrowed_object); + let object = git_object::Object::from(borrowed_object); encode_buf.clear(); object.write_to(&mut *encode_buf)?; if encode_buf.as_slice() != buf { diff --git a/git-repository/src/easy/object/tree.rs b/git-repository/src/easy/object/tree.rs index 4168af77b51..cc51a605b56 100644 --- a/git-repository/src/easy/object/tree.rs +++ b/git-repository/src/easy/object/tree.rs @@ -1,4 +1,3 @@ -use git_object as objs; use git_object::{bstr::BStr, TreeRefIter}; use crate::{ @@ -11,7 +10,7 @@ where A: easy::Access + Sized, { // TODO: move implementation to git-object, tests. - pub fn lookup_path(mut self, path: I) -> Result, find::existing::Error> + pub fn lookup_path(mut self, path: I) -> Result, find::existing::Error> where I: IntoIterator, P: PartialEq, From 25d8e7b1862bd05489359b162a32c6ad45ecdf9a Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 26 Aug 2021 16:10:34 +0800 Subject: [PATCH 07/18] [object #177] fix docs --- git-object/src/commit.rs | 2 +- git-object/src/lib.rs | 123 +++++++++++++++++----------------- git-object/src/mutable/mod.rs | 2 +- git-object/src/tree/mod.rs | 6 +- git-pack/src/data/object.rs | 2 +- 5 files changed, 67 insertions(+), 68 deletions(-) diff --git a/git-object/src/commit.rs b/git-object/src/commit.rs index 491968ba380..a3ffba6103b 100644 --- a/git-object/src/commit.rs +++ b/git-object/src/commit.rs @@ -3,7 +3,7 @@ use bstr::{BStr, ByteSlice}; pub use crate::immutable::commit::iter::RefIter; use crate::{immutable, TagRef}; -/// An iterator over extra headers in [owned][crate::mutable::Commit] and [borrowed][crate::CommitRef] commits. +/// An iterator over extra headers in [owned][crate::Commit] and [borrowed][crate::CommitRef] commits. pub struct ExtraHeaders { inner: I, } diff --git a/git-object/src/lib.rs b/git-object/src/lib.rs index 317e33ffc90..f6ac95d28f6 100644 --- a/git-object/src/lib.rs +++ b/git-object/src/lib.rs @@ -1,5 +1,5 @@ //! This crate provides types for [read-only git objects][crate::ObjectRef] backed by bytes provided in git's serialization format -//! as well as [mutable versions][mutable::Object] of these. The latter can be serialized into git's serialization format for objects. +//! as well as [mutable versions][Object] of these. The latter can be serialized into git's serialization format for objects. #![forbid(unsafe_code)] #![deny(rust_2018_idioms, missing_docs)] @@ -37,6 +37,14 @@ pub struct BlobRef<'a> { pub data: &'a [u8], } +/// A mutable chunk of any [`data`][Blob::data]. +#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] +#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] +pub struct Blob { + /// The data itself. + pub data: Vec, +} + /// A git commit parsed using [`from_bytes()`][CommitRef::from_bytes()]. /// /// A commit encapsulates information about a point in time at which the state of the repository is recorded, usually after a @@ -66,6 +74,30 @@ pub struct CommitRef<'a> { pub extra_headers: Vec<(&'a BStr, Cow<'a, BStr>)>, } +/// A mutable git commit, representing an annotated state of a working tree along with a reference to its historical commits. +#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] +#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] +pub struct Commit { + /// The hash of recorded working tree state. + pub tree: git_hash::ObjectId, + /// Hash of each parent commit. Empty for the first commit in repository. + pub parents: SmallVec<[git_hash::ObjectId; 1]>, + /// Who wrote this commit. + pub author: git_actor::Signature, + /// Who committed this commit. + /// + /// This may be different from the `author` in case the author couldn't write to the repository themselves and + /// is commonly encountered with contributed commits. + pub committer: git_actor::Signature, + /// The name of the message encoding, otherwise [UTF-8 should be assumed](https://github.com/git/git/blob/e67fbf927dfdf13d0b21dc6ea15dc3c7ef448ea0/commit.c#L1493:L1493). + pub encoding: Option, + /// The commit message documenting the change. + pub message: BString, + /// Extra header fields, in order of them being encountered, made accessible with the iterator returned + /// by [`extra_headers()`][Commit::extra_headers()]. + pub extra_headers: Vec<(BString, BString)>, +} + /// Represents a git tag, commonly indicating a software release. #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] #[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] @@ -85,6 +117,24 @@ pub struct TagRef<'a> { pub pgp_signature: Option<&'a BStr>, } +/// A mutable git tag. +#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] +#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] +pub struct Tag { + /// The hash this tag is pointing to. + pub target: git_hash::ObjectId, + /// The kind of object this tag is pointing to. + pub target_kind: crate::Kind, + /// The name of the tag, e.g. "v1.0". + pub name: BString, + /// The message describing the tag. + pub message: BString, + /// The tags author. + pub signature: Option, + /// A pgp signature over all bytes of the encoded tag, excluding the pgp signature itself. + pub pgp_signature: Option, +} + /// An signature_ref object representing [`Trees`][TreeRef], [`Blobs`][BlobRef], [`Commits`][CommitRef], or [`Tags`][TagRef]. #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] #[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] @@ -97,6 +147,16 @@ pub enum ObjectRef<'a> { Tag(TagRef<'a>), } +/// A mutable object representing [`Trees`][Tree], [`Blobs`][Blob], [`Commits`][Commit] or [`Tags`][Tag]. +#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] +#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] +#[allow(clippy::large_enum_variant, missing_docs)] +pub enum Object { + Tree(Tree), + Blob(Blob), + Commit(Commit), + Tag(Tag), +} /// A directory snapshot containing files (blobs), directories (trees) and submodules (commits). #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] #[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] @@ -115,24 +175,6 @@ pub struct TreeRefIter<'a> { data: &'a [u8], } -/// A mutable git tag. -#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] -#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] -pub struct Tag { - /// The hash this tag is pointing to. - pub target: git_hash::ObjectId, - /// The kind of object this tag is pointing to. - pub target_kind: crate::Kind, - /// The name of the tag, e.g. "v1.0". - pub name: BString, - /// The message describing the tag. - pub message: BString, - /// The tags author. - pub signature: Option, - /// A pgp signature over all bytes of the encoded tag, excluding the pgp signature itself. - pub pgp_signature: Option, -} - /// A mutable Tree, containing other trees, blobs or commits. #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] #[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] @@ -140,46 +182,3 @@ pub struct Tree { /// The directories and files contained in this tree. They must be and remain sorted by [`filename`][Entry::filename]. pub entries: Vec, } - -/// A mutable git commit, representing an annotated state of a working tree along with a reference to its historical commits. -#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] -#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] -pub struct Commit { - /// The hash of recorded working tree state. - pub tree: git_hash::ObjectId, - /// Hash of each parent commit. Empty for the first commit in repository. - pub parents: SmallVec<[git_hash::ObjectId; 1]>, - /// Who wrote this commit. - pub author: git_actor::Signature, - /// Who committed this commit. - /// - /// This may be different from the `author` in case the author couldn't write to the repository themselves and - /// is commonly encountered with contributed commits. - pub committer: git_actor::Signature, - /// The name of the message encoding, otherwise [UTF-8 should be assumed](https://github.com/git/git/blob/e67fbf927dfdf13d0b21dc6ea15dc3c7ef448ea0/commit.c#L1493:L1493). - pub encoding: Option, - /// The commit message documenting the change. - pub message: BString, - /// Extra header fields, in order of them being encountered, made accessible with the iterator returned - /// by [`extra_headers()`][Commit::extra_headers()]. - pub extra_headers: Vec<(BString, BString)>, -} - -/// A mutable chunk of any [`data`][Blob::data]. -#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] -#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] -pub struct Blob { - /// The data itself. - pub data: Vec, -} - -/// A mutable object representing [`Trees`][Tree], [`Blobs`][Blob], [`Commits`][Commit] or [`Tags`][Tag]. -#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] -#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] -#[allow(clippy::large_enum_variant, missing_docs)] -pub enum Object { - Tree(Tree), - Blob(Blob), - Commit(Commit), - Tag(Tag), -} diff --git a/git-object/src/mutable/mod.rs b/git-object/src/mutable/mod.rs index ed88d0c4c51..76ff3f7a198 100644 --- a/git-object/src/mutable/mod.rs +++ b/git-object/src/mutable/mod.rs @@ -1,7 +1,7 @@ //! Mutable objects with each field being separately allocated and changeable. //! //! Mutable objects are Commits, Trees, Blobs and Tags that can be changed and serialized. -//! They either created using object [construction][Object] or by [deserializing existing objects][crate::ObjectRef::from_bytes()] +//! They either created using object [construction][crate::Object] or by [deserializing existing objects][crate::ObjectRef::from_bytes()] //! and converting these [into mutable copies][crate::ObjectRef::into_mutable()] for adjustments. pub(crate) const NL: &[u8; 1] = b"\n"; diff --git a/git-object/src/tree/mod.rs b/git-object/src/tree/mod.rs index 5f48ccef7bf..02aab006429 100644 --- a/git-object/src/tree/mod.rs +++ b/git-object/src/tree/mod.rs @@ -5,7 +5,7 @@ use crate::{bstr::BStr, tree}; /// The mode of items storable in a tree, similar to the file mode on a unix file system. /// -/// Used in [mutable::Entry][crate::mutable::tree::Entry] and [EntryRef]. +/// Used in [mutable::Entry][crate::tree::Entry] and [EntryRef]. #[derive(Clone, Copy, PartialEq, Eq, Debug, Ord, PartialOrd, Hash)] #[repr(u16)] #[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] @@ -30,7 +30,7 @@ impl EntryMode { } } -/// An element of a [`TreeRef`][TreeRef::entries]. +/// An element of a [`TreeRef`][crate::TreeRef::entries]. #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] #[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] pub struct EntryRef<'a> { @@ -47,7 +47,7 @@ pub struct EntryRef<'a> { mod ref_iter; -/// An entry in a [`Tree`], similar to an entry in a directory. +/// An entry in a [`Tree`][crate::Tree], similar to an entry in a directory. #[derive(PartialEq, Eq, Debug, Hash, Clone)] #[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] pub struct Entry { diff --git a/git-pack/src/data/object.rs b/git-pack/src/data/object.rs index b53bf2c46e2..79c40bfe5d1 100644 --- a/git-pack/src/data/object.rs +++ b/git-pack/src/data/object.rs @@ -25,7 +25,7 @@ impl<'a> Object<'a> { /// Decodes the data in the backing slice into a [`git_object::ObjectRef`], allowing to access all of its data /// conveniently. The cost of parsing an object is negligible. /// - /// **Note** that [mutable, decoded objects][git_object::mutable::Object] can be created from a [`crate::data::Object`] + /// **Note** that [mutable, decoded objects][git_object::Object] can be created from a [`crate::data::Object`] /// using [`git_object::ObjectRef::into_mutable()`]. pub fn decode(&self) -> Result, immutable::object::decode::Error> { Ok(match self.kind { From 7e701ce49efe5d40327770a988aae88692d88219 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 26 Aug 2021 16:11:45 +0800 Subject: [PATCH 08/18] [object #177] into_mutable() -> into_owned() --- git-object/src/immutable/mod.rs | 2 +- git-object/src/immutable/object.rs | 4 ++-- git-object/src/mutable/mod.rs | 2 +- git-pack/src/data/object.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/git-object/src/immutable/mod.rs b/git-object/src/immutable/mod.rs index e8423ceb3f9..0f69a70d1b7 100644 --- a/git-object/src/immutable/mod.rs +++ b/git-object/src/immutable/mod.rs @@ -1,7 +1,7 @@ //! Immutable objects are read-only structures referencing most data from [a byte slice][crate::ObjectRef::from_bytes()]. //! //! Immutable objects are expected to be deserialized from bytes that acts as backing store, and they -//! cannot be mutated or serialized. Instead, one will [convert][crate::ObjectRef::into_mutable()] them into their [`mutable`][crate::mutable] counterparts +//! cannot be mutated or serialized. Instead, one will [convert][crate::ObjectRef::into_owned()] them into their [`mutable`][crate::mutable] counterparts //! which support mutation and serialization. /// diff --git a/git-object/src/immutable/object.rs b/git-object/src/immutable/object.rs index c13abdd30bb..31a9eed8612 100644 --- a/git-object/src/immutable/object.rs +++ b/git-object/src/immutable/object.rs @@ -14,14 +14,14 @@ impl<'a> ObjectRef<'a> { /// Convert the signature_ref object into a mutable version, consuming the source in the process. /// /// Note that this is an expensive operation. - pub fn into_mutable(self) -> Object { + pub fn into_owned(self) -> Object { self.into() } /// Convert this signature_ref object into its mutable counterpart. /// /// Note that this is an expensive operation. - pub fn to_mutable(&self) -> Object { + pub fn to_owned(&self) -> Object { self.clone().into() } } diff --git a/git-object/src/mutable/mod.rs b/git-object/src/mutable/mod.rs index 76ff3f7a198..658b1ce065b 100644 --- a/git-object/src/mutable/mod.rs +++ b/git-object/src/mutable/mod.rs @@ -2,7 +2,7 @@ //! //! Mutable objects are Commits, Trees, Blobs and Tags that can be changed and serialized. //! They either created using object [construction][crate::Object] or by [deserializing existing objects][crate::ObjectRef::from_bytes()] -//! and converting these [into mutable copies][crate::ObjectRef::into_mutable()] for adjustments. +//! and converting these [into mutable copies][crate::ObjectRef::into_owned()] for adjustments. pub(crate) const NL: &[u8; 1] = b"\n"; pub(crate) const SPACE: &[u8; 1] = b" "; diff --git a/git-pack/src/data/object.rs b/git-pack/src/data/object.rs index 79c40bfe5d1..98a6700ab7a 100644 --- a/git-pack/src/data/object.rs +++ b/git-pack/src/data/object.rs @@ -26,7 +26,7 @@ impl<'a> Object<'a> { /// conveniently. The cost of parsing an object is negligible. /// /// **Note** that [mutable, decoded objects][git_object::Object] can be created from a [`crate::data::Object`] - /// using [`git_object::ObjectRef::into_mutable()`]. + /// using [`git_object::ObjectRef::into_owned()`]. pub fn decode(&self) -> Result, immutable::object::decode::Error> { Ok(match self.kind { git_object::Kind::Tree => ObjectRef::Tree(TreeRef::from_bytes(self.data)?), From 28587c691eb74e5cb097afb2b63f9d9e2561c45d Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 26 Aug 2021 16:23:37 +0800 Subject: [PATCH 09/18] [object #177] tag::RefIter -> TagRefIter --- git-object/src/blob.rs | 6 +- git-object/src/immutable/mod.rs | 3 - git-object/src/immutable/tag.rs | 277 ------------------ git-object/src/lib.rs | 10 +- git-object/src/mutable/object.rs | 3 +- git-object/src/mutable/tag.rs | 6 +- git-object/src/tag.rs | 1 - git-object/src/tag/decode.rs | 92 ++++++ git-object/src/tag/mod.rs | 18 ++ git-object/src/tag/ref_iter.rs | 158 ++++++++++ git-object/src/tree/mod.rs | 6 +- git-object/src/tree/write.rs | 3 +- git-object/tests/immutable/tag.rs | 10 +- git-pack/src/data/object.rs | 6 +- git-pack/src/data/output/count/objects.rs | 6 +- .../src/store/file/loose/reference/peel.rs | 13 +- git-ref/src/store/packed/transaction.rs | 2 +- git-repository/src/easy/object/mod.rs | 4 +- 18 files changed, 308 insertions(+), 316 deletions(-) delete mode 100644 git-object/src/immutable/tag.rs delete mode 100644 git-object/src/tag.rs create mode 100644 git-object/src/tag/decode.rs create mode 100644 git-object/src/tag/mod.rs create mode 100644 git-object/src/tag/ref_iter.rs diff --git a/git-object/src/blob.rs b/git-object/src/blob.rs index 2deb903c5dd..f1e11fff50d 100644 --- a/git-object/src/blob.rs +++ b/git-object/src/blob.rs @@ -1,8 +1,6 @@ -use crate::Blob; -use crate::BlobRef; +use std::{convert::Infallible, io}; -use std::convert::Infallible; -use std::io; +use crate::{Blob, BlobRef}; impl Blob { /// Write the blobs data to `out` verbatim. diff --git a/git-object/src/immutable/mod.rs b/git-object/src/immutable/mod.rs index 0f69a70d1b7..99ffc51ae45 100644 --- a/git-object/src/immutable/mod.rs +++ b/git-object/src/immutable/mod.rs @@ -10,7 +10,4 @@ pub mod commit; /// pub mod object; -/// -pub mod tag; - pub(crate) mod parse; diff --git a/git-object/src/immutable/tag.rs b/git-object/src/immutable/tag.rs deleted file mode 100644 index 6ca3015440c..00000000000 --- a/git-object/src/immutable/tag.rs +++ /dev/null @@ -1,277 +0,0 @@ -use crate::{immutable::object, TagRef}; - -impl<'a> TagRef<'a> { - /// Deserialize a tag from `data`. - pub fn from_bytes(data: &'a [u8]) -> Result, object::decode::Error> { - decode::git_tag(data) - .map(|(_, t)| t) - .map_err(object::decode::Error::from) - } - /// The object this tag points to as `Id`. - pub fn target(&self) -> git_hash::ObjectId { - git_hash::ObjectId::from_hex(self.target).expect("prior validation") - } -} - -mod decode { - use nom::{ - branch::alt, - bytes::complete::{tag, take_until, take_while, take_while1}, - character::is_alphabetic, - combinator::{all_consuming, opt, recognize}, - error::{context, ContextError, ParseError}, - sequence::{preceded, tuple}, - IResult, - }; - - use crate::{ - immutable::{parse, parse::NL}, - BStr, ByteSlice, TagRef, - }; - - pub fn git_tag<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(i: &'a [u8]) -> IResult<&[u8], TagRef<'a>, E> { - let (i, target) = context("object <40 lowercase hex char>", |i| { - parse::header_field(i, b"object", parse::hex_hash) - })(i)?; - - let (i, kind) = context("type ", |i| { - parse::header_field(i, b"type", take_while1(is_alphabetic)) - })(i)?; - let kind = crate::Kind::from_bytes(kind) - .map_err(|_| nom::Err::Error(E::from_error_kind(i, nom::error::ErrorKind::MapRes)))?; - - let (i, tag_version) = context("tag ", |i| { - parse::header_field(i, b"tag", take_while1(|b| b != NL[0])) - })(i)?; - - let (i, signature) = context( - "tagger ", - opt(|i| parse::header_field(i, b"tagger", parse::signature)), - )(i)?; - let (i, (message, pgp_signature)) = all_consuming(message)(i)?; - Ok(( - i, - TagRef { - target, - name: tag_version.as_bstr(), - target_kind: kind, - message, - tagger: signature, - pgp_signature, - }, - )) - } - - pub fn message<'a, E: ParseError<&'a [u8]>>(i: &'a [u8]) -> IResult<&'a [u8], (&'a BStr, Option<&'a BStr>), E> { - const PGP_SIGNATURE_BEGIN: &[u8] = b"\n-----BEGIN PGP SIGNATURE-----"; - const PGP_SIGNATURE_END: &[u8] = b"-----END PGP SIGNATURE-----"; - - if i.is_empty() { - return Ok((i, (i.as_bstr(), None))); - } - let (i, _) = tag(NL)(i)?; - fn all_to_end<'a, E: ParseError<&'a [u8]>>(i: &'a [u8]) -> IResult<&'a [u8], (&'a [u8], &'a [u8]), E> { - if i.is_empty() { - return Err(nom::Err::Error(E::from_error_kind(i, nom::error::ErrorKind::Eof))); - } - // an empty signature message signals that there is none - the function signature is needed - // to work with 'alt(…)'. PGP signatures are never empty - Ok((&[], (i, &[]))) - } - let (i, (message, signature)) = alt(( - tuple(( - take_until(PGP_SIGNATURE_BEGIN), - preceded( - tag(NL), - recognize(tuple(( - tag(&PGP_SIGNATURE_BEGIN[1..]), - take_until(PGP_SIGNATURE_END), - tag(PGP_SIGNATURE_END), - take_while(|_| true), - ))), - ), - )), - all_to_end, - ))(i)?; - let (i, _) = opt(tag(NL))(i)?; - Ok(( - i, - ( - message.as_bstr(), - if signature.is_empty() { - None - } else { - Some(signature.as_bstr()) - }, - ), - )) - } -} - -/// -pub mod iter { - use bstr::BStr; - use git_hash::{oid, ObjectId}; - use nom::{ - bytes::complete::take_while1, - character::is_alphabetic, - combinator::{all_consuming, opt}, - error::{context, ParseError}, - }; - - use crate::{ - bstr::ByteSlice, - immutable::{object, parse, parse::NL, tag::decode}, - Kind, - }; - - enum State { - Target, - TargetKind, - Name, - Tagger, - Message, - } - - impl Default for State { - fn default() -> Self { - State::Target - } - } - - /// Like [`TagRef`][crate::TagRef], but as `Iterator` to support entirely allocation free parsing. - /// It's particularly useful to dereference only the target chain. - pub struct RefIter<'a> { - data: &'a [u8], - state: State, - } - - impl<'a> RefIter<'a> { - /// Create a tag iterator from data. - pub fn from_bytes(data: &'a [u8]) -> RefIter<'a> { - RefIter { - data, - state: State::default(), - } - } - - /// Returns the target id of this tag if it is the first function called and if there is no error in decoding - /// the data. - /// - /// Note that this method must only be called once or else will always return None while consuming a single token. - /// Errors are coerced into options, hiding whether there was an error or not. The caller should assume an error if they - /// call the method as intended. Such a squelched error cannot be recovered unless the objects data is retrieved and parsed again. - /// `next()`. - pub fn target_id(&mut self) -> Option { - self.next().and_then(Result::ok).and_then(Token::into_id) - } - } - - impl<'a> RefIter<'a> { - fn next_inner(i: &'a [u8], state: &mut State) -> Result<(&'a [u8], Token<'a>), object::decode::Error> { - use State::*; - Ok(match state { - Target => { - let (i, target) = context("object <40 lowercase hex char>", |i| { - parse::header_field(i, b"object", parse::hex_hash) - })(i)?; - *state = State::TargetKind; - ( - i, - Token::Target { - id: ObjectId::from_hex(target).expect("parsing validation"), - }, - ) - } - TargetKind => { - let (i, kind) = context("type ", |i| { - parse::header_field(i, b"type", take_while1(is_alphabetic)) - })(i)?; - let kind = crate::Kind::from_bytes(kind).map_err(|_| { - let err = object::decode::ParseError::from_error_kind(i, nom::error::ErrorKind::MapRes); - nom::Err::Error(err) - })?; - *state = State::Name; - (i, Token::TargetKind(kind)) - } - Name => { - let (i, tag_version) = context("tag ", |i| { - parse::header_field(i, b"tag", take_while1(|b| b != NL[0])) - })(i)?; - *state = State::Tagger; - (i, Token::Name(tag_version.as_bstr())) - } - Tagger => { - let (i, signature) = context( - "tagger ", - opt(|i| parse::header_field(i, b"tagger", parse::signature)), - )(i)?; - *state = State::Message; - (i, Token::Tagger(signature)) - } - Message => { - let (i, (message, pgp_signature)) = all_consuming(decode::message)(i)?; - debug_assert!( - i.is_empty(), - "we should have consumed all data - otherwise iter may go forever" - ); - return Ok((i, Token::Body { message, pgp_signature })); - } - }) - } - } - - impl<'a> Iterator for RefIter<'a> { - type Item = Result, object::decode::Error>; - - fn next(&mut self) -> Option { - if self.data.is_empty() { - return None; - } - match Self::next_inner(self.data, &mut self.state) { - Ok((data, token)) => { - self.data = data; - Some(Ok(token)) - } - Err(err) => { - self.data = &[]; - Some(Err(err)) - } - } - } - } - - /// A token returned by the [commit iterator][RefIter]. - #[allow(missing_docs)] - #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] - pub enum Token<'a> { - Target { - id: ObjectId, - }, - TargetKind(Kind), - Name(&'a BStr), - Tagger(Option>), - Body { - message: &'a BStr, - pgp_signature: Option<&'a BStr>, - }, - } - - impl<'a> Token<'a> { - /// Return the object id of this token if its a [Target][Token::Target]. - pub fn id(&self) -> Option<&oid> { - match self { - Token::Target { id } => Some(id.as_ref()), - _ => None, - } - } - - /// Return the owned object id of this token if its a [Target][Token::Target]. - pub fn into_id(self) -> Option { - match self { - Token::Target { id } => Some(id), - _ => None, - } - } - } -} diff --git a/git-object/src/lib.rs b/git-object/src/lib.rs index f6ac95d28f6..cd302678d3a 100644 --- a/git-object/src/lib.rs +++ b/git-object/src/lib.rs @@ -9,11 +9,10 @@ use std::borrow::Cow; pub use bstr; use bstr::{BStr, BString, ByteSlice}; use smallvec::SmallVec; - +use tree::Entry; pub use types::{Error, Kind}; use crate::tree::EntryRef; -use tree::Entry; pub mod immutable; pub mod mutable; @@ -117,6 +116,13 @@ pub struct TagRef<'a> { pub pgp_signature: Option<&'a BStr>, } +/// Like [`TagRef`], but as `Iterator` to support entirely allocation free parsing. +/// It's particularly useful to dereference only the target chain. +pub struct TagRefIter<'a> { + data: &'a [u8], + state: tag::ref_iter::State, +} + /// A mutable git tag. #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] #[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] diff --git a/git-object/src/mutable/object.rs b/git-object/src/mutable/object.rs index c694f08aa29..9f696685376 100644 --- a/git-object/src/mutable/object.rs +++ b/git-object/src/mutable/object.rs @@ -60,8 +60,7 @@ impl Object { mod convert { use std::convert::TryFrom; - use crate::Object; - use crate::{Blob, Commit, Tag, Tree}; + use crate::{Blob, Commit, Object, Tag, Tree}; impl From for Object { fn from(v: Tag) -> Self { diff --git a/git-object/src/mutable/tag.rs b/git-object/src/mutable/tag.rs index 43fa87016f2..434b0a02e75 100644 --- a/git-object/src/mutable/tag.rs +++ b/git-object/src/mutable/tag.rs @@ -3,8 +3,10 @@ use std::io; use bstr::BStr; use quick_error::quick_error; -use crate::mutable::{encode, NL}; -use crate::Tag; +use crate::{ + mutable::{encode, NL}, + Tag, +}; quick_error! { /// An Error used in [`Tag::write_to()`]. diff --git a/git-object/src/tag.rs b/git-object/src/tag.rs deleted file mode 100644 index 2e59f03f1f9..00000000000 --- a/git-object/src/tag.rs +++ /dev/null @@ -1 +0,0 @@ -pub use crate::immutable::tag::iter::RefIter; diff --git a/git-object/src/tag/decode.rs b/git-object/src/tag/decode.rs new file mode 100644 index 00000000000..fd25a6c1d71 --- /dev/null +++ b/git-object/src/tag/decode.rs @@ -0,0 +1,92 @@ +use nom::{ + branch::alt, + bytes::complete::{tag, take_until, take_while, take_while1}, + character::is_alphabetic, + combinator::{all_consuming, opt, recognize}, + error::{context, ContextError, ParseError}, + sequence::{preceded, tuple}, + IResult, +}; + +use crate::{ + immutable::{parse, parse::NL}, + BStr, ByteSlice, TagRef, +}; + +pub fn git_tag<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(i: &'a [u8]) -> IResult<&[u8], TagRef<'a>, E> { + let (i, target) = context("object <40 lowercase hex char>", |i| { + parse::header_field(i, b"object", parse::hex_hash) + })(i)?; + + let (i, kind) = context("type ", |i| { + parse::header_field(i, b"type", take_while1(is_alphabetic)) + })(i)?; + let kind = crate::Kind::from_bytes(kind) + .map_err(|_| nom::Err::Error(E::from_error_kind(i, nom::error::ErrorKind::MapRes)))?; + + let (i, tag_version) = context("tag ", |i| { + parse::header_field(i, b"tag", take_while1(|b| b != NL[0])) + })(i)?; + + let (i, signature) = context( + "tagger ", + opt(|i| parse::header_field(i, b"tagger", parse::signature)), + )(i)?; + let (i, (message, pgp_signature)) = all_consuming(message)(i)?; + Ok(( + i, + TagRef { + target, + name: tag_version.as_bstr(), + target_kind: kind, + message, + tagger: signature, + pgp_signature, + }, + )) +} + +pub fn message<'a, E: ParseError<&'a [u8]>>(i: &'a [u8]) -> IResult<&'a [u8], (&'a BStr, Option<&'a BStr>), E> { + const PGP_SIGNATURE_BEGIN: &[u8] = b"\n-----BEGIN PGP SIGNATURE-----"; + const PGP_SIGNATURE_END: &[u8] = b"-----END PGP SIGNATURE-----"; + + if i.is_empty() { + return Ok((i, (i.as_bstr(), None))); + } + let (i, _) = tag(NL)(i)?; + fn all_to_end<'a, E: ParseError<&'a [u8]>>(i: &'a [u8]) -> IResult<&'a [u8], (&'a [u8], &'a [u8]), E> { + if i.is_empty() { + return Err(nom::Err::Error(E::from_error_kind(i, nom::error::ErrorKind::Eof))); + } + // an empty signature message signals that there is none - the function signature is needed + // to work with 'alt(…)'. PGP signatures are never empty + Ok((&[], (i, &[]))) + } + let (i, (message, signature)) = alt(( + tuple(( + take_until(PGP_SIGNATURE_BEGIN), + preceded( + tag(NL), + recognize(tuple(( + tag(&PGP_SIGNATURE_BEGIN[1..]), + take_until(PGP_SIGNATURE_END), + tag(PGP_SIGNATURE_END), + take_while(|_| true), + ))), + ), + )), + all_to_end, + ))(i)?; + let (i, _) = opt(tag(NL))(i)?; + Ok(( + i, + ( + message.as_bstr(), + if signature.is_empty() { + None + } else { + Some(signature.as_bstr()) + }, + ), + )) +} diff --git a/git-object/src/tag/mod.rs b/git-object/src/tag/mod.rs new file mode 100644 index 00000000000..4f26168eb6f --- /dev/null +++ b/git-object/src/tag/mod.rs @@ -0,0 +1,18 @@ +use crate::{immutable::object, TagRef}; + +mod decode; +/// +pub mod ref_iter; + +impl<'a> TagRef<'a> { + /// Deserialize a tag from `data`. + pub fn from_bytes(data: &'a [u8]) -> Result, object::decode::Error> { + decode::git_tag(data) + .map(|(_, t)| t) + .map_err(object::decode::Error::from) + } + /// The object this tag points to as `Id`. + pub fn target(&self) -> git_hash::ObjectId { + git_hash::ObjectId::from_hex(self.target).expect("prior validation") + } +} diff --git a/git-object/src/tag/ref_iter.rs b/git-object/src/tag/ref_iter.rs new file mode 100644 index 00000000000..079c1f26e5d --- /dev/null +++ b/git-object/src/tag/ref_iter.rs @@ -0,0 +1,158 @@ +use bstr::BStr; +use git_hash::{oid, ObjectId}; +use nom::{ + bytes::complete::take_while1, + character::is_alphabetic, + combinator::{all_consuming, opt}, + error::{context, ParseError}, +}; + +use crate::{ + bstr::ByteSlice, + immutable::{object, parse, parse::NL}, + tag::decode, + Kind, TagRefIter, +}; + +pub(crate) enum State { + Target, + TargetKind, + Name, + Tagger, + Message, +} + +impl Default for State { + fn default() -> Self { + State::Target + } +} + +impl<'a> TagRefIter<'a> { + /// Create a tag iterator from data. + pub fn from_bytes(data: &'a [u8]) -> TagRefIter<'a> { + TagRefIter { + data, + state: State::default(), + } + } + + /// Returns the target id of this tag if it is the first function called and if there is no error in decoding + /// the data. + /// + /// Note that this method must only be called once or else will always return None while consuming a single token. + /// Errors are coerced into options, hiding whether there was an error or not. The caller should assume an error if they + /// call the method as intended. Such a squelched error cannot be recovered unless the objects data is retrieved and parsed again. + /// `next()`. + pub fn target_id(&mut self) -> Option { + self.next().and_then(Result::ok).and_then(Token::into_id) + } +} + +impl<'a> TagRefIter<'a> { + fn next_inner(i: &'a [u8], state: &mut State) -> Result<(&'a [u8], Token<'a>), object::decode::Error> { + use State::*; + Ok(match state { + Target => { + let (i, target) = context("object <40 lowercase hex char>", |i| { + parse::header_field(i, b"object", parse::hex_hash) + })(i)?; + *state = State::TargetKind; + ( + i, + Token::Target { + id: ObjectId::from_hex(target).expect("parsing validation"), + }, + ) + } + TargetKind => { + let (i, kind) = context("type ", |i| { + parse::header_field(i, b"type", take_while1(is_alphabetic)) + })(i)?; + let kind = crate::Kind::from_bytes(kind).map_err(|_| { + let err = object::decode::ParseError::from_error_kind(i, nom::error::ErrorKind::MapRes); + nom::Err::Error(err) + })?; + *state = State::Name; + (i, Token::TargetKind(kind)) + } + Name => { + let (i, tag_version) = context("tag ", |i| { + parse::header_field(i, b"tag", take_while1(|b| b != NL[0])) + })(i)?; + *state = State::Tagger; + (i, Token::Name(tag_version.as_bstr())) + } + Tagger => { + let (i, signature) = context( + "tagger ", + opt(|i| parse::header_field(i, b"tagger", parse::signature)), + )(i)?; + *state = State::Message; + (i, Token::Tagger(signature)) + } + Message => { + let (i, (message, pgp_signature)) = all_consuming(decode::message)(i)?; + debug_assert!( + i.is_empty(), + "we should have consumed all data - otherwise iter may go forever" + ); + return Ok((i, Token::Body { message, pgp_signature })); + } + }) + } +} + +impl<'a> Iterator for TagRefIter<'a> { + type Item = Result, object::decode::Error>; + + fn next(&mut self) -> Option { + if self.data.is_empty() { + return None; + } + match Self::next_inner(self.data, &mut self.state) { + Ok((data, token)) => { + self.data = data; + Some(Ok(token)) + } + Err(err) => { + self.data = &[]; + Some(Err(err)) + } + } + } +} + +/// A token returned by the [tag iterator][TagRefIter]. +#[allow(missing_docs)] +#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] +pub enum Token<'a> { + Target { + id: ObjectId, + }, + TargetKind(Kind), + Name(&'a BStr), + Tagger(Option>), + Body { + message: &'a BStr, + pgp_signature: Option<&'a BStr>, + }, +} + +impl<'a> Token<'a> { + /// Return the object id of this token if its a [Target][Token::Target]. + pub fn id(&self) -> Option<&oid> { + match self { + Token::Target { id } => Some(id.as_ref()), + _ => None, + } + } + + /// Return the owned object id of this token if its a [Target][Token::Target]. + pub fn into_id(self) -> Option { + match self { + Token::Target { id } => Some(id), + _ => None, + } + } +} diff --git a/git-object/src/tree/mod.rs b/git-object/src/tree/mod.rs index 02aab006429..09ca3d8901d 100644 --- a/git-object/src/tree/mod.rs +++ b/git-object/src/tree/mod.rs @@ -1,7 +1,9 @@ use std::cmp::Ordering; -use crate::bstr::BString; -use crate::{bstr::BStr, tree}; +use crate::{ + bstr::{BStr, BString}, + tree, +}; /// The mode of items storable in a tree, similar to the file mode on a unix file system. /// diff --git a/git-object/src/tree/write.rs b/git-object/src/tree/write.rs index af793a92562..e2d6447e622 100644 --- a/git-object/src/tree/write.rs +++ b/git-object/src/tree/write.rs @@ -3,8 +3,7 @@ use std::io; use bstr::{BString, ByteSlice}; use quick_error::quick_error; -use crate::tree::Entry; -use crate::{mutable::SPACE, Tree}; +use crate::{mutable::SPACE, tree::Entry, Tree}; quick_error! { /// The Error used in [`Tree::write_to()`]. diff --git a/git-object/tests/immutable/tag.rs b/git-object/tests/immutable/tag.rs index 7db7288f008..07c5d7f017c 100644 --- a/git-object/tests/immutable/tag.rs +++ b/git-object/tests/immutable/tag.rs @@ -17,7 +17,7 @@ mod method { } mod iter { - use git_object::{bstr::ByteSlice, immutable::tag::iter::Token, tag, Kind}; + use git_object::{bstr::ByteSlice, tag::ref_iter::Token, Kind, TagRefIter}; use crate::{ hex_to_id, @@ -27,7 +27,7 @@ mod iter { #[test] fn empty() -> crate::Result { assert_eq!( - tag::RefIter::from_bytes(&fixture_bytes("tag", "empty.txt")).collect::, _>>()?, + TagRefIter::from_bytes(&fixture_bytes("tag", "empty.txt")).collect::, _>>()?, vec![ Token::Target { id: hex_to_id("01dd4e2a978a9f5bd773dae6da7aa4a5ac1cdbbc") @@ -43,7 +43,7 @@ mod iter { #[test] fn no_tagger() -> crate::Result { assert_eq!( - tag::RefIter::from_bytes(&fixture_bytes("tag", "no-tagger.txt")).collect::, _>>()?, + TagRefIter::from_bytes(&fixture_bytes("tag", "no-tagger.txt")).collect::, _>>()?, vec![ Token::Target { id: hex_to_id("c39ae07f393806ccf406ef966e9a15afc43cc36a") @@ -79,7 +79,7 @@ KLMHist5yj0sw1E4hDTyQa0= #[test] fn whitespace() -> crate::Result { assert_eq!( - tag::RefIter::from_bytes(&fixture_bytes("tag", "whitespace.txt")).collect::, _>>()?, + TagRefIter::from_bytes(&fixture_bytes("tag", "whitespace.txt")).collect::, _>>()?, vec![ Token::Target { id: hex_to_id("01dd4e2a978a9f5bd773dae6da7aa4a5ac1cdbbc") @@ -99,7 +99,7 @@ KLMHist5yj0sw1E4hDTyQa0= #[test] fn error_handling() -> crate::Result { let data = fixture_bytes("tag", "empty.txt"); - let iter = tag::RefIter::from_bytes(&data[..data.len() / 2]); + let iter = TagRefIter::from_bytes(&data[..data.len() / 2]); let tokens = iter.collect::>(); assert!( tokens.last().expect("at least the errored token").is_err(), diff --git a/git-pack/src/data/object.rs b/git-pack/src/data/object.rs index 98a6700ab7a..a40ab1f86ab 100644 --- a/git-pack/src/data/object.rs +++ b/git-pack/src/data/object.rs @@ -1,6 +1,6 @@ //! Contains a borrowed Object bound to a buffer holding its decompressed data. -use git_object::{commit, immutable, tag, BlobRef, CommitRef, ObjectRef, TagRef, TreeRef, TreeRefIter}; +use git_object::{commit, immutable, BlobRef, CommitRef, ObjectRef, TagRef, TagRefIter, TreeRef, TreeRefIter}; /// A borrowed object using a borrowed slice as backing buffer. #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] @@ -56,9 +56,9 @@ impl<'a> Object<'a> { /// Returns this object as tag iterator to parse tokens one at a time to avoid allocations, or /// `None` if this is not a tag object. - pub fn into_tag_iter(self) -> Option> { + pub fn into_tag_iter(self) -> Option> { match self.kind { - git_object::Kind::Tag => Some(tag::RefIter::from_bytes(self.data)), + git_object::Kind::Tag => Some(TagRefIter::from_bytes(self.data)), _ => None, } } diff --git a/git-pack/src/data/output/count/objects.rs b/git-pack/src/data/output/count/objects.rs index dd854ec9f9c..7d120dc4ecc 100644 --- a/git-pack/src/data/output/count/objects.rs +++ b/git-pack/src/data/output/count/objects.rs @@ -5,7 +5,7 @@ use std::sync::{ use git_features::{parallel, progress::Progress}; use git_hash::{oid, ObjectId}; -use git_object::{commit, immutable, tag}; +use git_object::{commit, immutable, TagRefIter}; use crate::{data::output, find, FindExt}; @@ -179,7 +179,7 @@ where match obj.kind { Tree | Blob => break, Tag => { - id = tag::RefIter::from_bytes(obj.data) + id = TagRefIter::from_bytes(obj.data) .target_id() .expect("every tag has a target"); obj = db.find_existing(id, buf1, cache)?; @@ -321,7 +321,7 @@ where } Blob => break, Tag => { - id = tag::RefIter::from_bytes(obj.data) + id = TagRefIter::from_bytes(obj.data) .target_id() .expect("every tag has a target"); stats.expanded_objects += 1; diff --git a/git-ref/src/store/file/loose/reference/peel.rs b/git-ref/src/store/file/loose/reference/peel.rs index fdedb6b5947..865ebd8af71 100644 --- a/git-ref/src/store/file/loose/reference/peel.rs +++ b/git-ref/src/store/file/loose/reference/peel.rs @@ -157,13 +157,12 @@ pub mod to_id { })?; match kind { git_object::Kind::Tag => { - oid = - git_object::tag::RefIter::from_bytes(data) - .target_id() - .ok_or_else(|| Error::NotFound { - oid, - name: self.name.0.clone(), - })?; + oid = git_object::TagRefIter::from_bytes(data) + .target_id() + .ok_or_else(|| Error::NotFound { + oid, + name: self.name.0.clone(), + })?; } _ => break oid, }; diff --git a/git-ref/src/store/packed/transaction.rs b/git-ref/src/store/packed/transaction.rs index 72c77cc0840..0d2454bb7af 100644 --- a/git-ref/src/store/packed/transaction.rs +++ b/git-ref/src/store/packed/transaction.rs @@ -77,7 +77,7 @@ impl packed::Transaction { let kind = find(next_id, &mut buf)?; match kind { Some(kind) if kind == git_object::Kind::Tag => { - next_id = git_object::tag::RefIter::from_bytes(&buf).target_id().ok_or_else(|| { + next_id = git_object::TagRefIter::from_bytes(&buf).target_id().ok_or_else(|| { prepare::Error::Resolve( format!("Couldn't get target object id from tag {}", next_id).into(), ) diff --git a/git-repository/src/easy/object/mod.rs b/git-repository/src/easy/object/mod.rs index aae66676c29..2ec9c468281 100644 --- a/git-repository/src/easy/object/mod.rs +++ b/git-repository/src/easy/object/mod.rs @@ -3,7 +3,7 @@ use std::{cell::Ref, convert::TryInto}; use git_hash::ObjectId; pub use git_object::Kind; -use git_object::{commit, tag}; +use git_object::{commit, TagRefIter}; use git_odb as odb; use crate::{ @@ -145,7 +145,7 @@ where odb::data::Object::new(self.kind, &self.data).into_commit_iter() } - pub fn to_tag_iter(&self) -> Option> { + pub fn to_tag_iter(&self) -> Option> { odb::data::Object::new(self.kind, &self.data).into_tag_iter() } } From 7f1955916ae9d7e17be971170c853487e3755169 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 26 Aug 2021 16:33:44 +0800 Subject: [PATCH 10/18] [object #177] refactor tag write_to --- git-object/src/{mutable => }/encode.rs | 5 +++-- git-object/src/lib.rs | 1 + git-object/src/mutable/commit.rs | 7 ++----- git-object/src/mutable/mod.rs | 6 ------ git-object/src/tag/mod.rs | 4 ++++ git-object/src/{mutable/tag.rs => tag/write.rs} | 7 +++---- git-object/src/{mutable/tag => tag/write}/tests.rs | 0 git-object/src/tree/mod.rs | 9 ++++----- git-object/src/tree/write.rs | 3 ++- 9 files changed, 19 insertions(+), 23 deletions(-) rename git-object/src/{mutable => }/encode.rs (96%) rename git-object/src/{mutable/tag.rs => tag/write.rs} (95%) rename git-object/src/{mutable/tag => tag/write}/tests.rs (100%) diff --git a/git-object/src/mutable/encode.rs b/git-object/src/encode.rs similarity index 96% rename from git-object/src/mutable/encode.rs rename to git-object/src/encode.rs index df564825557..8cc2f7e3f10 100644 --- a/git-object/src/mutable/encode.rs +++ b/git-object/src/encode.rs @@ -3,8 +3,6 @@ use std::io; use bstr::{BString, ByteSlice}; use quick_error::quick_error; -use crate::mutable::{NL, SPACE}; - quick_error! { #[derive(Debug)] enum Error { @@ -71,3 +69,6 @@ pub fn header_field(name: &[u8], value: &[u8], out: impl io::Write) -> io::Resul } trusted_header_field(name, value, out) } + +pub(crate) const NL: &[u8; 1] = b"\n"; +pub(crate) const SPACE: &[u8; 1] = b" "; diff --git a/git-object/src/lib.rs b/git-object/src/lib.rs index cd302678d3a..f151d88600c 100644 --- a/git-object/src/lib.rs +++ b/git-object/src/lib.rs @@ -26,6 +26,7 @@ pub mod tree; mod blob; +mod encode; mod types; /// A chunk of any [`data`][BlobRef::data]. diff --git a/git-object/src/mutable/commit.rs b/git-object/src/mutable/commit.rs index 87ef346b86f..08719c43c28 100644 --- a/git-object/src/mutable/commit.rs +++ b/git-object/src/mutable/commit.rs @@ -2,11 +2,8 @@ use std::io; use bstr::{BStr, ByteSlice}; -use crate::{ - commit, - mutable::{encode, NL}, - Commit, -}; +use crate::encode::NL; +use crate::{commit, encode, Commit}; impl Commit { /// Returns a convenient iterator over all extra headers. diff --git a/git-object/src/mutable/mod.rs b/git-object/src/mutable/mod.rs index 658b1ce065b..cb5544b56df 100644 --- a/git-object/src/mutable/mod.rs +++ b/git-object/src/mutable/mod.rs @@ -4,13 +4,7 @@ //! They either created using object [construction][crate::Object] or by [deserializing existing objects][crate::ObjectRef::from_bytes()] //! and converting these [into mutable copies][crate::ObjectRef::into_owned()] for adjustments. -pub(crate) const NL: &[u8; 1] = b"\n"; -pub(crate) const SPACE: &[u8; 1] = b" "; - mod convert; -mod encode; - -mod tag; mod commit; diff --git a/git-object/src/tag/mod.rs b/git-object/src/tag/mod.rs index 4f26168eb6f..86c153b8829 100644 --- a/git-object/src/tag/mod.rs +++ b/git-object/src/tag/mod.rs @@ -1,6 +1,10 @@ use crate::{immutable::object, TagRef}; mod decode; + +/// +pub mod write; + /// pub mod ref_iter; diff --git a/git-object/src/mutable/tag.rs b/git-object/src/tag/write.rs similarity index 95% rename from git-object/src/mutable/tag.rs rename to git-object/src/tag/write.rs index 434b0a02e75..d39a7aa9385 100644 --- a/git-object/src/mutable/tag.rs +++ b/git-object/src/tag/write.rs @@ -3,14 +3,13 @@ use std::io; use bstr::BStr; use quick_error::quick_error; -use crate::{ - mutable::{encode, NL}, - Tag, -}; +use crate::encode::NL; +use crate::{encode, Tag}; quick_error! { /// An Error used in [`Tag::write_to()`]. #[derive(Debug)] + #[allow(missing_docs)] pub enum Error { StartsWithDash { display("Tags must not start with a dash: '-'") diff --git a/git-object/src/mutable/tag/tests.rs b/git-object/src/tag/write/tests.rs similarity index 100% rename from git-object/src/mutable/tag/tests.rs rename to git-object/src/tag/write/tests.rs diff --git a/git-object/src/tree/mod.rs b/git-object/src/tree/mod.rs index 09ca3d8901d..4479f1bb7c3 100644 --- a/git-object/src/tree/mod.rs +++ b/git-object/src/tree/mod.rs @@ -5,6 +5,10 @@ use crate::{ tree, }; +mod ref_iter; +/// +pub mod write; + /// The mode of items storable in a tree, similar to the file mode on a unix file system. /// /// Used in [mutable::Entry][crate::tree::Entry] and [EntryRef]. @@ -47,8 +51,6 @@ pub struct EntryRef<'a> { pub oid: &'a git_hash::oid, } -mod ref_iter; - /// An entry in a [`Tree`][crate::Tree], similar to an entry in a directory. #[derive(PartialEq, Eq, Debug, Hash, Clone)] #[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] @@ -89,6 +91,3 @@ impl EntryMode { } } } - -/// -pub mod write; diff --git a/git-object/src/tree/write.rs b/git-object/src/tree/write.rs index e2d6447e622..d9426ce22b8 100644 --- a/git-object/src/tree/write.rs +++ b/git-object/src/tree/write.rs @@ -3,7 +3,8 @@ use std::io; use bstr::{BString, ByteSlice}; use quick_error::quick_error; -use crate::{mutable::SPACE, tree::Entry, Tree}; +use crate::encode::SPACE; +use crate::{tree::Entry, Tree}; quick_error! { /// The Error used in [`Tree::write_to()`]. From 45d393438eac2c7ecd47670922437dd0de4cd69b Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 26 Aug 2021 16:37:20 +0800 Subject: [PATCH 11/18] [object #177] migrate immutable::commit into crate::commit --- .../src/{immutable => }/commit/decode.rs | 0 git-object/src/{commit.rs => commit/mod.rs} | 34 ++++++++++++++++++- .../commit/iter.rs => commit/ref_iter.rs} | 18 +++++----- git-object/src/immutable/commit/mod.rs | 31 ----------------- git-object/src/immutable/mod.rs | 3 -- git-object/tests/immutable/commit.rs | 32 ++++++++++------- git-pack/src/data/object.rs | 4 +-- git-pack/src/data/output/count/objects.rs | 12 ++++--- git-repository/src/easy/object/mod.rs | 2 +- git-repository/src/ext/object_id.rs | 4 +-- git-traverse/src/commit.rs | 2 +- 11 files changed, 75 insertions(+), 67 deletions(-) rename git-object/src/{immutable => }/commit/decode.rs (100%) rename git-object/src/{commit.rs => commit/mod.rs} (56%) rename git-object/src/{immutable/commit/iter.rs => commit/ref_iter.rs} (96%) delete mode 100644 git-object/src/immutable/commit/mod.rs diff --git a/git-object/src/immutable/commit/decode.rs b/git-object/src/commit/decode.rs similarity index 100% rename from git-object/src/immutable/commit/decode.rs rename to git-object/src/commit/decode.rs diff --git a/git-object/src/commit.rs b/git-object/src/commit/mod.rs similarity index 56% rename from git-object/src/commit.rs rename to git-object/src/commit/mod.rs index a3ffba6103b..60f81131c1b 100644 --- a/git-object/src/commit.rs +++ b/git-object/src/commit/mod.rs @@ -1,7 +1,39 @@ use bstr::{BStr, ByteSlice}; -pub use crate::immutable::commit::iter::RefIter; +pub use ref_iter::RefIter; + use crate::{immutable, TagRef}; +use crate::{immutable::object, CommitRef}; + +mod decode; + +/// +pub mod ref_iter; + +impl<'a> CommitRef<'a> { + /// Deserialize a commit from the given `data` bytes while avoiding most allocations. + pub fn from_bytes(data: &'a [u8]) -> Result, object::decode::Error> { + decode::commit(data) + .map(|(_, t)| t) + .map_err(object::decode::Error::from) + } + /// Return the `tree` fields hash digest. + pub fn tree(&self) -> git_hash::ObjectId { + git_hash::ObjectId::from_hex(self.tree).expect("prior validation of tree hash during parsing") + } + + /// Returns an iterator of parent object ids + pub fn parents(&self) -> impl Iterator + '_ { + self.parents + .iter() + .map(|hex_hash| git_hash::ObjectId::from_hex(hex_hash).expect("prior validation of hashes during parsing")) + } + + /// Returns a convenient iterator over all extra headers. + pub fn extra_headers(&self) -> crate::commit::ExtraHeaders> { + crate::commit::ExtraHeaders::new(self.extra_headers.iter().map(|(k, v)| (*k, v.as_ref()))) + } +} /// An iterator over extra headers in [owned][crate::Commit] and [borrowed][crate::CommitRef] commits. pub struct ExtraHeaders { diff --git a/git-object/src/immutable/commit/iter.rs b/git-object/src/commit/ref_iter.rs similarity index 96% rename from git-object/src/immutable/commit/iter.rs rename to git-object/src/commit/ref_iter.rs index ffbfe16ae6b..a6ad1ea21d3 100644 --- a/git-object/src/immutable/commit/iter.rs +++ b/git-object/src/commit/ref_iter.rs @@ -1,7 +1,6 @@ use std::borrow::Cow; use bstr::BStr; -use git_hash::{oid, ObjectId}; use nom::{ branch::alt, bytes::complete::is_not, @@ -9,9 +8,12 @@ use nom::{ error::context, }; +use git_hash::{oid, ObjectId}; + +use crate::commit::decode; use crate::{ bstr::ByteSlice, - immutable::{commit::decode, object, parse, parse::NL}, + immutable::{object, parse, parse::NL}, }; #[derive(Copy, Clone)] @@ -37,15 +39,15 @@ impl Default for State { /// Like [`CommitRef`][crate::CommitRef], but as `Iterator` to support (up to) entirely allocation free parsing. /// It's particularly useful to traverse the commit graph without ever allocating arrays for parents. -pub struct RefIter<'a> { +pub struct CommitRefIter<'a> { data: &'a [u8], state: State, } -impl<'a> RefIter<'a> { +impl<'a> CommitRefIter<'a> { /// Create a commit iterator from data. - pub fn from_bytes(data: &'a [u8]) -> RefIter<'a> { - RefIter { + pub fn from_bytes(data: &'a [u8]) -> CommitRefIter<'a> { + CommitRefIter { data, state: State::default(), } @@ -77,7 +79,7 @@ impl<'a> RefIter<'a> { } } -impl<'a> RefIter<'a> { +impl<'a> CommitRefIter<'a> { fn next_inner(i: &'a [u8], state: &mut State) -> Result<(&'a [u8], Token<'a>), object::decode::Error> { use State::*; Ok(match state { @@ -176,7 +178,7 @@ impl<'a> RefIter<'a> { } } -impl<'a> Iterator for RefIter<'a> { +impl<'a> Iterator for CommitRefIter<'a> { type Item = Result, object::decode::Error>; fn next(&mut self) -> Option { diff --git a/git-object/src/immutable/commit/mod.rs b/git-object/src/immutable/commit/mod.rs deleted file mode 100644 index f786d2169c9..00000000000 --- a/git-object/src/immutable/commit/mod.rs +++ /dev/null @@ -1,31 +0,0 @@ -use crate::{immutable::object, BStr, CommitRef}; - -mod decode; - -/// -pub mod iter; - -impl<'a> CommitRef<'a> { - /// Deserialize a commit from the given `data` bytes while avoiding most allocations. - pub fn from_bytes(data: &'a [u8]) -> Result, object::decode::Error> { - decode::commit(data) - .map(|(_, t)| t) - .map_err(object::decode::Error::from) - } - /// Return the `tree` fields hash digest. - pub fn tree(&self) -> git_hash::ObjectId { - git_hash::ObjectId::from_hex(self.tree).expect("prior validation of tree hash during parsing") - } - - /// Returns an iterator of parent object ids - pub fn parents(&self) -> impl Iterator + '_ { - self.parents - .iter() - .map(|hex_hash| git_hash::ObjectId::from_hex(hex_hash).expect("prior validation of hashes during parsing")) - } - - /// Returns a convenient iterator over all extra headers. - pub fn extra_headers(&self) -> crate::commit::ExtraHeaders> { - crate::commit::ExtraHeaders::new(self.extra_headers.iter().map(|(k, v)| (*k, v.as_ref()))) - } -} diff --git a/git-object/src/immutable/mod.rs b/git-object/src/immutable/mod.rs index 99ffc51ae45..52bfa62d9f6 100644 --- a/git-object/src/immutable/mod.rs +++ b/git-object/src/immutable/mod.rs @@ -4,9 +4,6 @@ //! cannot be mutated or serialized. Instead, one will [convert][crate::ObjectRef::into_owned()] them into their [`mutable`][crate::mutable] counterparts //! which support mutation and serialization. -/// -pub mod commit; - /// pub mod object; diff --git a/git-object/tests/immutable/commit.rs b/git-object/tests/immutable/commit.rs index 2c996addeb3..3962248d725 100644 --- a/git-object/tests/immutable/commit.rs +++ b/git-object/tests/immutable/commit.rs @@ -131,9 +131,10 @@ dS3aXZhRfaPqpdsWrMB9fY7ll+oyfw== =T+RI -----END PGP SIGNATURE-----"; mod method { - use git_object::CommitRef; use pretty_assertions::assert_eq; + use git_object::CommitRef; + use crate::{hex_to_id, immutable::fixture_bytes}; #[test] @@ -147,7 +148,8 @@ mod method { } mod iter { - use git_object::{bstr::ByteSlice, commit, immutable::commit::iter::Token}; + use git_object::commit::ref_iter::Token; + use git_object::{bstr::ByteSlice, commit}; use crate::{ hex_to_id, @@ -160,7 +162,7 @@ mod iter { #[test] fn newline_right_after_signature_multiline_header() -> crate::Result { let data = fixture_bytes("commit", "signed-whitespace.txt"); - let tokens = commit::RefIter::from_bytes(&data).collect::, _>>()?; + let tokens = commit::CommitRefIter::from_bytes(&data).collect::, _>>()?; assert_eq!(tokens.len(), 7, "mainly a parsing exercise"); match tokens.last().expect("there are tokens") { Token::Message(msg) => { @@ -174,7 +176,7 @@ mod iter { #[test] fn signed_with_encoding() -> crate::Result { assert_eq!( - commit::RefIter::from_bytes(&fixture_bytes("commit", "signed-with-encoding.txt")) + commit::CommitRefIter::from_bytes(&fixture_bytes("commit", "signed-with-encoding.txt")) .collect::, _>>()?, vec![ Token::Tree { @@ -200,7 +202,8 @@ mod iter { #[test] fn whitespace() -> crate::Result { assert_eq!( - commit::RefIter::from_bytes(&fixture_bytes("commit", "whitespace.txt")).collect::, _>>()?, + commit::CommitRefIter::from_bytes(&fixture_bytes("commit", "whitespace.txt")) + .collect::, _>>()?, vec![ Token::Tree { id: hex_to_id("9bed6275068a0575243ba8409253e61af81ab2ff") @@ -223,7 +226,8 @@ mod iter { #[test] fn unsigned() -> crate::Result { assert_eq!( - commit::RefIter::from_bytes(&fixture_bytes("commit", "unsigned.txt")).collect::, _>>()?, + commit::CommitRefIter::from_bytes(&fixture_bytes("commit", "unsigned.txt")) + .collect::, _>>()?, vec![ Token::Tree { id: hex_to_id("1b2dfb4ac5e42080b682fc676e9738c94ce6d54d") @@ -243,7 +247,7 @@ mod iter { #[test] fn signed_singleline() -> crate::Result { assert_eq!( - commit::RefIter::from_bytes(&fixture_bytes("commit", "signed-singleline.txt")) + commit::CommitRefIter::from_bytes(&fixture_bytes("commit", "signed-singleline.txt")) .collect::, _>>()?, vec![ Token::Tree { @@ -268,7 +272,7 @@ mod iter { #[test] fn error_handling() -> crate::Result { let data = fixture_bytes("commit", "unsigned.txt"); - let iter = commit::RefIter::from_bytes(&data[..data.len() / 2]); + let iter = commit::CommitRefIter::from_bytes(&data[..data.len() / 2]); let tokens = iter.collect::>(); assert!( tokens.last().expect("at least the errored token").is_err(), @@ -280,7 +284,8 @@ mod iter { #[test] fn mergetag() -> crate::Result { assert_eq!( - commit::RefIter::from_bytes(&fixture_bytes("commit", "mergetag.txt")).collect::, _>>()?, + commit::CommitRefIter::from_bytes(&fixture_bytes("commit", "mergetag.txt")) + .collect::, _>>()?, vec![ Token::Tree { id: hex_to_id("1c61918031bf2c7fab9e17dde3c52a6a9884fcb5") @@ -315,11 +320,11 @@ mod iter { #[test] fn tree_id() -> crate::Result { assert_eq!( - commit::RefIter::from_bytes(&fixture_bytes("commit", "unsigned.txt")).tree_id(), + commit::CommitRefIter::from_bytes(&fixture_bytes("commit", "unsigned.txt")).tree_id(), Some(hex_to_id("1b2dfb4ac5e42080b682fc676e9738c94ce6d54d")) ); assert_eq!( - commit::RefIter::from_bytes(&fixture_bytes("commit", "unsigned.txt")) + commit::CommitRefIter::from_bytes(&fixture_bytes("commit", "unsigned.txt")) .signatures() .collect::>(), vec![signature(1592437401), signature(1592437401)] @@ -330,7 +335,7 @@ mod iter { #[test] fn signatures() -> crate::Result { assert_eq!( - commit::RefIter::from_bytes(&fixture_bytes("commit", "unsigned.txt")) + commit::CommitRefIter::from_bytes(&fixture_bytes("commit", "unsigned.txt")) .signatures() .collect::>(), vec![signature(1592437401), signature(1592437401)] @@ -341,9 +346,10 @@ mod iter { } mod from_bytes { - use git_object::{bstr::ByteSlice, CommitRef}; use smallvec::SmallVec; + use git_object::{bstr::ByteSlice, CommitRef}; + use crate::immutable::{ commit::{LONG_MESSAGE, MERGE_TAG, SIGNATURE}, fixture_bytes, linus_signature, signature, diff --git a/git-pack/src/data/object.rs b/git-pack/src/data/object.rs index a40ab1f86ab..6f1567282ce 100644 --- a/git-pack/src/data/object.rs +++ b/git-pack/src/data/object.rs @@ -47,9 +47,9 @@ impl<'a> Object<'a> { /// Returns this object as commit iterator to parse tokens one at a time to avoid allocations, or /// `None` if this is not a commit object. - pub fn into_commit_iter(self) -> Option> { + pub fn into_commit_iter(self) -> Option> { match self.kind { - git_object::Kind::Commit => Some(commit::RefIter::from_bytes(self.data)), + git_object::Kind::Commit => Some(commit::CommitRefIter::from_bytes(self.data)), _ => None, } } diff --git a/git-pack/src/data/output/count/objects.rs b/git-pack/src/data/output/count/objects.rs index 7d120dc4ecc..1cca54e2ff5 100644 --- a/git-pack/src/data/output/count/objects.rs +++ b/git-pack/src/data/output/count/objects.rs @@ -5,7 +5,7 @@ use std::sync::{ use git_features::{parallel, progress::Progress}; use git_hash::{oid, ObjectId}; -use git_object::{commit, immutable, TagRefIter}; +use git_object::{commit, TagRefIter}; use crate::{data::output, find, FindExt}; @@ -188,12 +188,14 @@ where } Commit => { let current_tree_iter = { - let mut commit_iter = commit::RefIter::from_bytes(obj.data); + let mut commit_iter = commit::CommitRefIter::from_bytes(obj.data); let tree_id = commit_iter.tree_id().expect("every commit has a tree"); parent_commit_ids.clear(); for token in commit_iter { match token { - Ok(immutable::commit::iter::Token::Parent { id }) => parent_commit_ids.push(id), + Ok(git_object::commit::ref_iter::Token::Parent { id }) => { + parent_commit_ids.push(id) + } Ok(_) => break, Err(err) => return Err(Error::CommitDecode(err)), } @@ -238,7 +240,7 @@ where stats, true, ); - commit::RefIter::from_bytes(parent_commit_obj.data) + commit::CommitRefIter::from_bytes(parent_commit_obj.data) .tree_id() .expect("every commit has a tree") }; @@ -312,7 +314,7 @@ where break; } Commit => { - id = commit::RefIter::from_bytes(obj.data) + id = commit::CommitRefIter::from_bytes(obj.data) .tree_id() .expect("every commit has a tree"); stats.expanded_objects += 1; diff --git a/git-repository/src/easy/object/mod.rs b/git-repository/src/easy/object/mod.rs index 2ec9c468281..97f9c6496a2 100644 --- a/git-repository/src/easy/object/mod.rs +++ b/git-repository/src/easy/object/mod.rs @@ -141,7 +141,7 @@ impl<'repo, A> ObjectRef<'repo, A> where A: easy::Access + Sized, { - pub fn to_commit_iter(&self) -> Option> { + pub fn to_commit_iter(&self) -> Option> { odb::data::Object::new(self.kind, &self.data).into_commit_iter() } diff --git a/git-repository/src/ext/object_id.rs b/git-repository/src/ext/object_id.rs index d33db6c9732..7f9d6cdef15 100644 --- a/git-repository/src/ext/object_id.rs +++ b/git-repository/src/ext/object_id.rs @@ -12,7 +12,7 @@ pub trait ObjectIdExt: Sealed { #[cfg(feature = "git-traverse")] fn ancestors_iter(self, find: Find) -> Ancestors bool, State> where - Find: for<'a> FnMut(&git_hash::oid, &'a mut Vec) -> Option>; + Find: for<'a> FnMut(&git_hash::oid, &'a mut Vec) -> Option>; fn attach(self, access: &A) -> easy::Oid<'_, A>; } @@ -23,7 +23,7 @@ impl ObjectIdExt for ObjectId { #[cfg(feature = "git-traverse")] fn ancestors_iter(self, find: Find) -> Ancestors bool, State> where - Find: for<'a> FnMut(&git_hash::oid, &'a mut Vec) -> Option>, + Find: for<'a> FnMut(&git_hash::oid, &'a mut Vec) -> Option>, { Ancestors::new(Some(self), State::default(), find) } diff --git a/git-traverse/src/commit.rs b/git-traverse/src/commit.rs index 2fa8306dcd9..8637351267f 100644 --- a/git-traverse/src/commit.rs +++ b/git-traverse/src/commit.rs @@ -131,7 +131,7 @@ pub mod ancestors { } for token in commit_iter { match token { - Ok(immutable::commit::iter::Token::Parent { id }) => { + Ok(git_object::commit::ref_iter::Token::Parent { id }) => { let was_inserted = state.seen.insert(id); if was_inserted && (self.predicate)(&id) { state.next.push_back(id); From e603306e81f392af97aa5afd232653de56bf3ce9 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 26 Aug 2021 16:40:08 +0800 Subject: [PATCH 12/18] [object #177] commit::RefIter -> CommitRefIter --- git-object/src/commit/mod.rs | 6 ++---- git-object/src/commit/ref_iter.rs | 19 ++++++------------- git-object/src/lib.rs | 7 +++++++ git-object/src/mutable/commit.rs | 3 +-- git-object/src/tag/write.rs | 3 +-- git-object/src/tree/write.rs | 3 +-- git-object/tests/immutable/commit.rs | 9 +++------ git-pack/src/find.rs | 2 +- git-traverse/src/commit.rs | 6 +++--- gitoxide-core/src/hours.rs | 4 ++-- 10 files changed, 27 insertions(+), 35 deletions(-) diff --git a/git-object/src/commit/mod.rs b/git-object/src/commit/mod.rs index 60f81131c1b..1dde8350d72 100644 --- a/git-object/src/commit/mod.rs +++ b/git-object/src/commit/mod.rs @@ -1,9 +1,7 @@ use bstr::{BStr, ByteSlice}; -pub use ref_iter::RefIter; - -use crate::{immutable, TagRef}; -use crate::{immutable::object, CommitRef}; +pub use crate::CommitRefIter; +use crate::{immutable, immutable::object, CommitRef, TagRef}; mod decode; diff --git a/git-object/src/commit/ref_iter.rs b/git-object/src/commit/ref_iter.rs index a6ad1ea21d3..85dff173c57 100644 --- a/git-object/src/commit/ref_iter.rs +++ b/git-object/src/commit/ref_iter.rs @@ -1,6 +1,7 @@ use std::borrow::Cow; use bstr::BStr; +use git_hash::{oid, ObjectId}; use nom::{ branch::alt, bytes::complete::is_not, @@ -8,21 +9,20 @@ use nom::{ error::context, }; -use git_hash::{oid, ObjectId}; - -use crate::commit::decode; use crate::{ bstr::ByteSlice, + commit::decode, immutable::{object, parse, parse::NL}, + CommitRefIter, }; #[derive(Copy, Clone)] -enum SignatureKind { +pub(crate) enum SignatureKind { Author, Committer, } -enum State { +pub(crate) enum State { Tree, Parents, Signature { of: SignatureKind }, @@ -37,13 +37,6 @@ impl Default for State { } } -/// Like [`CommitRef`][crate::CommitRef], but as `Iterator` to support (up to) entirely allocation free parsing. -/// It's particularly useful to traverse the commit graph without ever allocating arrays for parents. -pub struct CommitRefIter<'a> { - data: &'a [u8], - state: State, -} - impl<'a> CommitRefIter<'a> { /// Create a commit iterator from data. pub fn from_bytes(data: &'a [u8]) -> CommitRefIter<'a> { @@ -198,7 +191,7 @@ impl<'a> Iterator for CommitRefIter<'a> { } } -/// A token returned by the [commit iterator][RefIter]. +/// A token returned by the [commit iterator][CommitRefIter]. #[allow(missing_docs)] #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] pub enum Token<'a> { diff --git a/git-object/src/lib.rs b/git-object/src/lib.rs index f151d88600c..c3da2f23e24 100644 --- a/git-object/src/lib.rs +++ b/git-object/src/lib.rs @@ -74,6 +74,13 @@ pub struct CommitRef<'a> { pub extra_headers: Vec<(&'a BStr, Cow<'a, BStr>)>, } +/// Like [`CommitRef`][crate::CommitRef], but as `Iterator` to support (up to) entirely allocation free parsing. +/// It's particularly useful to traverse the commit graph without ever allocating arrays for parents. +pub struct CommitRefIter<'a> { + data: &'a [u8], + state: commit::ref_iter::State, +} + /// A mutable git commit, representing an annotated state of a working tree along with a reference to its historical commits. #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] #[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] diff --git a/git-object/src/mutable/commit.rs b/git-object/src/mutable/commit.rs index 08719c43c28..010ecff6e4d 100644 --- a/git-object/src/mutable/commit.rs +++ b/git-object/src/mutable/commit.rs @@ -2,8 +2,7 @@ use std::io; use bstr::{BStr, ByteSlice}; -use crate::encode::NL; -use crate::{commit, encode, Commit}; +use crate::{commit, encode, encode::NL, Commit}; impl Commit { /// Returns a convenient iterator over all extra headers. diff --git a/git-object/src/tag/write.rs b/git-object/src/tag/write.rs index d39a7aa9385..e39c80e57d6 100644 --- a/git-object/src/tag/write.rs +++ b/git-object/src/tag/write.rs @@ -3,8 +3,7 @@ use std::io; use bstr::BStr; use quick_error::quick_error; -use crate::encode::NL; -use crate::{encode, Tag}; +use crate::{encode, encode::NL, Tag}; quick_error! { /// An Error used in [`Tag::write_to()`]. diff --git a/git-object/src/tree/write.rs b/git-object/src/tree/write.rs index d9426ce22b8..5f7e6fa9787 100644 --- a/git-object/src/tree/write.rs +++ b/git-object/src/tree/write.rs @@ -3,8 +3,7 @@ use std::io; use bstr::{BString, ByteSlice}; use quick_error::quick_error; -use crate::encode::SPACE; -use crate::{tree::Entry, Tree}; +use crate::{encode::SPACE, tree::Entry, Tree}; quick_error! { /// The Error used in [`Tree::write_to()`]. diff --git a/git-object/tests/immutable/commit.rs b/git-object/tests/immutable/commit.rs index 3962248d725..f8a0598f830 100644 --- a/git-object/tests/immutable/commit.rs +++ b/git-object/tests/immutable/commit.rs @@ -131,9 +131,8 @@ dS3aXZhRfaPqpdsWrMB9fY7ll+oyfw== =T+RI -----END PGP SIGNATURE-----"; mod method { - use pretty_assertions::assert_eq; - use git_object::CommitRef; + use pretty_assertions::assert_eq; use crate::{hex_to_id, immutable::fixture_bytes}; @@ -148,8 +147,7 @@ mod method { } mod iter { - use git_object::commit::ref_iter::Token; - use git_object::{bstr::ByteSlice, commit}; + use git_object::{bstr::ByteSlice, commit, commit::ref_iter::Token}; use crate::{ hex_to_id, @@ -346,9 +344,8 @@ mod iter { } mod from_bytes { - use smallvec::SmallVec; - use git_object::{bstr::ByteSlice, CommitRef}; + use smallvec::SmallVec; use crate::immutable::{ commit::{LONG_MESSAGE, MERGE_TAG, SIGNATURE}, diff --git a/git-pack/src/find.rs b/git-pack/src/find.rs index d2955c78bd4..4a710ebf492 100644 --- a/git-pack/src/find.rs +++ b/git-pack/src/find.rs @@ -130,7 +130,7 @@ mod ext { make_iter_lookup!( find_existing_commit_iter, Kind::Blob, - commit::RefIter<'a>, + commit::CommitRefIter<'a>, into_commit_iter ); make_iter_lookup!(find_existing_tree_iter, Kind::Tree, TreeRefIter<'a>, into_tree_iter); diff --git a/git-traverse/src/commit.rs b/git-traverse/src/commit.rs index 8637351267f..358882c44d1 100644 --- a/git-traverse/src/commit.rs +++ b/git-traverse/src/commit.rs @@ -50,7 +50,7 @@ pub mod ancestors { impl Ancestors bool, StateMut> where - Find: for<'a> FnMut(&oid, &'a mut Vec) -> Option>, + Find: for<'a> FnMut(&oid, &'a mut Vec) -> Option>, StateMut: BorrowMut, { /// Create a new instance. @@ -72,7 +72,7 @@ pub mod ancestors { impl Ancestors where - Find: for<'a> FnMut(&oid, &'a mut Vec) -> Option>, + Find: for<'a> FnMut(&oid, &'a mut Vec) -> Option>, Predicate: FnMut(&oid) -> bool, StateMut: BorrowMut, { @@ -114,7 +114,7 @@ pub mod ancestors { impl Iterator for Ancestors where - Find: for<'a> FnMut(&oid, &'a mut Vec) -> Option>, + Find: for<'a> FnMut(&oid, &'a mut Vec) -> Option>, Predicate: FnMut(&oid) -> bool, StateMut: BorrowMut, { diff --git a/gitoxide-core/src/hours.rs b/gitoxide-core/src/hours.rs index 9a42a42b475..483b280a8ee 100644 --- a/gitoxide-core/src/hours.rs +++ b/gitoxide-core/src/hours.rs @@ -68,7 +68,7 @@ where progress.inc(); repo.odb.find_existing(oid, buf, &mut pack_cache).ok().map(|o| { commits.push(o.data.to_owned()); - objs::commit::RefIter::from_bytes(o.data) + objs::commit::CommitRefIter::from_bytes(o.data) }) }), || anyhow!("Cancelled by user"), @@ -84,7 +84,7 @@ where let mut all_commits: Vec = all_commits .into_par_iter() .map(|commit_data: Vec| { - objs::commit::RefIter::from_bytes(&commit_data) + objs::commit::CommitRefIter::from_bytes(&commit_data) .signatures() .next() .map(|author| actor::Signature::from(author)) From 60b936553bef3c9126d46ece9779f08b5eef9a95 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 26 Aug 2021 16:47:23 +0800 Subject: [PATCH 13/18] [object #177] Commit::write_to migration --- git-object/src/commit/mod.rs | 11 ++++++++++- git-object/src/{mutable/commit.rs => commit/write.rs} | 8 ++------ git-object/src/mutable/mod.rs | 2 -- 3 files changed, 12 insertions(+), 9 deletions(-) rename git-object/src/{mutable/commit.rs => commit/write.rs} (75%) diff --git a/git-object/src/commit/mod.rs b/git-object/src/commit/mod.rs index 1dde8350d72..878e5d3f5f3 100644 --- a/git-object/src/commit/mod.rs +++ b/git-object/src/commit/mod.rs @@ -1,13 +1,15 @@ use bstr::{BStr, ByteSlice}; pub use crate::CommitRefIter; -use crate::{immutable, immutable::object, CommitRef, TagRef}; +use crate::{immutable, immutable::object, Commit, CommitRef, TagRef}; mod decode; /// pub mod ref_iter; +mod write; + impl<'a> CommitRef<'a> { /// Deserialize a commit from the given `data` bytes while avoiding most allocations. pub fn from_bytes(data: &'a [u8]) -> Result, object::decode::Error> { @@ -33,6 +35,13 @@ impl<'a> CommitRef<'a> { } } +impl Commit { + /// Returns a convenient iterator over all extra headers. + pub fn extra_headers(&self) -> ExtraHeaders> { + ExtraHeaders::new(self.extra_headers.iter().map(|(k, v)| (k.as_bstr(), v.as_bstr()))) + } +} + /// An iterator over extra headers in [owned][crate::Commit] and [borrowed][crate::CommitRef] commits. pub struct ExtraHeaders { inner: I, diff --git a/git-object/src/mutable/commit.rs b/git-object/src/commit/write.rs similarity index 75% rename from git-object/src/mutable/commit.rs rename to git-object/src/commit/write.rs index 010ecff6e4d..1ce29176712 100644 --- a/git-object/src/mutable/commit.rs +++ b/git-object/src/commit/write.rs @@ -1,14 +1,10 @@ use std::io; -use bstr::{BStr, ByteSlice}; +use bstr::ByteSlice; -use crate::{commit, encode, encode::NL, Commit}; +use crate::{encode, encode::NL, Commit}; impl Commit { - /// Returns a convenient iterator over all extra headers. - pub fn extra_headers(&self) -> commit::ExtraHeaders> { - commit::ExtraHeaders::new(self.extra_headers.iter().map(|(k, v)| (k.as_bstr(), v.as_bstr()))) - } /// Serializes this instance to `out` in the git serialization format. pub fn write_to(&self, mut out: impl io::Write) -> io::Result<()> { encode::trusted_header_id(b"tree", &self.tree, &mut out)?; diff --git a/git-object/src/mutable/mod.rs b/git-object/src/mutable/mod.rs index cb5544b56df..53d7b447ef2 100644 --- a/git-object/src/mutable/mod.rs +++ b/git-object/src/mutable/mod.rs @@ -6,6 +6,4 @@ mod convert; -mod commit; - mod object; From 472e13b27e97a196c644d716cad1801bd62fac71 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 26 Aug 2021 16:51:17 +0800 Subject: [PATCH 14/18] [object #177] refactor --- git-object/src/commit/decode.rs | 5 +---- git-object/src/commit/ref_iter.rs | 7 +------ git-object/src/immutable/mod.rs | 2 -- git-object/src/lib.rs | 1 + git-object/src/{immutable => }/parse.rs | 0 git-object/src/tag/decode.rs | 5 +---- git-object/src/tag/ref_iter.rs | 7 +------ git-object/src/tree/ref_iter.rs | 2 +- 8 files changed, 6 insertions(+), 23 deletions(-) rename git-object/src/{immutable => }/parse.rs (100%) diff --git a/git-object/src/commit/decode.rs b/git-object/src/commit/decode.rs index 5f47a805f73..92933773f99 100644 --- a/git-object/src/commit/decode.rs +++ b/git-object/src/commit/decode.rs @@ -10,10 +10,7 @@ use nom::{ }; use smallvec::SmallVec; -use crate::{ - immutable::{parse, parse::NL}, - BStr, ByteSlice, CommitRef, -}; +use crate::{parse, parse::NL, BStr, ByteSlice, CommitRef}; pub fn message<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(i: &'a [u8]) -> IResult<&'a [u8], &'a BStr, E> { if i.is_empty() { diff --git a/git-object/src/commit/ref_iter.rs b/git-object/src/commit/ref_iter.rs index 85dff173c57..3e476451295 100644 --- a/git-object/src/commit/ref_iter.rs +++ b/git-object/src/commit/ref_iter.rs @@ -9,12 +9,7 @@ use nom::{ error::context, }; -use crate::{ - bstr::ByteSlice, - commit::decode, - immutable::{object, parse, parse::NL}, - CommitRefIter, -}; +use crate::{bstr::ByteSlice, commit::decode, immutable::object, parse, parse::NL, CommitRefIter}; #[derive(Copy, Clone)] pub(crate) enum SignatureKind { diff --git a/git-object/src/immutable/mod.rs b/git-object/src/immutable/mod.rs index 52bfa62d9f6..df752f00744 100644 --- a/git-object/src/immutable/mod.rs +++ b/git-object/src/immutable/mod.rs @@ -6,5 +6,3 @@ /// pub mod object; - -pub(crate) mod parse; diff --git a/git-object/src/lib.rs b/git-object/src/lib.rs index c3da2f23e24..1f741da8b7a 100644 --- a/git-object/src/lib.rs +++ b/git-object/src/lib.rs @@ -27,6 +27,7 @@ pub mod tree; mod blob; mod encode; +pub(crate) mod parse; mod types; /// A chunk of any [`data`][BlobRef::data]. diff --git a/git-object/src/immutable/parse.rs b/git-object/src/parse.rs similarity index 100% rename from git-object/src/immutable/parse.rs rename to git-object/src/parse.rs diff --git a/git-object/src/tag/decode.rs b/git-object/src/tag/decode.rs index fd25a6c1d71..655e5009af8 100644 --- a/git-object/src/tag/decode.rs +++ b/git-object/src/tag/decode.rs @@ -8,10 +8,7 @@ use nom::{ IResult, }; -use crate::{ - immutable::{parse, parse::NL}, - BStr, ByteSlice, TagRef, -}; +use crate::{parse, parse::NL, BStr, ByteSlice, TagRef}; pub fn git_tag<'a, E: ParseError<&'a [u8]> + ContextError<&'a [u8]>>(i: &'a [u8]) -> IResult<&[u8], TagRef<'a>, E> { let (i, target) = context("object <40 lowercase hex char>", |i| { diff --git a/git-object/src/tag/ref_iter.rs b/git-object/src/tag/ref_iter.rs index 079c1f26e5d..b4c0e85466c 100644 --- a/git-object/src/tag/ref_iter.rs +++ b/git-object/src/tag/ref_iter.rs @@ -7,12 +7,7 @@ use nom::{ error::{context, ParseError}, }; -use crate::{ - bstr::ByteSlice, - immutable::{object, parse, parse::NL}, - tag::decode, - Kind, TagRefIter, -}; +use crate::{bstr::ByteSlice, immutable::object, parse, parse::NL, tag::decode, Kind, TagRefIter}; pub(crate) enum State { Target, diff --git a/git-object/src/tree/ref_iter.rs b/git-object/src/tree/ref_iter.rs index bddca8a7a28..7627902d9f5 100644 --- a/git-object/src/tree/ref_iter.rs +++ b/git-object/src/tree/ref_iter.rs @@ -87,7 +87,7 @@ mod decode { IResult, }; - use crate::{immutable::parse::SPACE, tree, tree::EntryRef, TreeRef}; + use crate::{parse::SPACE, tree, tree::EntryRef, TreeRef}; const NULL: &[u8] = b"\0"; From 216dd0f10add7a11ebdf96732ed7649d74815d64 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 26 Aug 2021 16:54:06 +0800 Subject: [PATCH 15/18] [object #177] refactor --- git-object/src/lib.rs | 1 + git-object/src/mutable/mod.rs | 2 -- git-object/src/{mutable => object}/convert.rs | 0 git-object/src/object/mod.rs | 1 + 4 files changed, 2 insertions(+), 2 deletions(-) rename git-object/src/{mutable => object}/convert.rs (100%) create mode 100644 git-object/src/object/mod.rs diff --git a/git-object/src/lib.rs b/git-object/src/lib.rs index 1f741da8b7a..a044ef53c5f 100644 --- a/git-object/src/lib.rs +++ b/git-object/src/lib.rs @@ -19,6 +19,7 @@ pub mod mutable; /// pub mod commit; +mod object; /// pub mod tag; /// diff --git a/git-object/src/mutable/mod.rs b/git-object/src/mutable/mod.rs index 53d7b447ef2..6f83f4697dd 100644 --- a/git-object/src/mutable/mod.rs +++ b/git-object/src/mutable/mod.rs @@ -4,6 +4,4 @@ //! They either created using object [construction][crate::Object] or by [deserializing existing objects][crate::ObjectRef::from_bytes()] //! and converting these [into mutable copies][crate::ObjectRef::into_owned()] for adjustments. -mod convert; - mod object; diff --git a/git-object/src/mutable/convert.rs b/git-object/src/object/convert.rs similarity index 100% rename from git-object/src/mutable/convert.rs rename to git-object/src/object/convert.rs diff --git a/git-object/src/object/mod.rs b/git-object/src/object/mod.rs new file mode 100644 index 00000000000..bb13da4f1cf --- /dev/null +++ b/git-object/src/object/mod.rs @@ -0,0 +1 @@ +mod convert; From b201b3260e3eec98ed71716c1aab1ba4a06ab829 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 26 Aug 2021 16:58:23 +0800 Subject: [PATCH 16/18] [object #177] resolve 'mutable' module --- git-object/src/lib.rs | 7 +- git-object/src/mutable/mod.rs | 7 -- git-object/src/mutable/object.rs | 132 ------------------------------- git-object/src/object/convert.rs | 69 ++++++++++++++++ git-object/src/object/mod.rs | 63 +++++++++++++++ 5 files changed, 138 insertions(+), 140 deletions(-) delete mode 100644 git-object/src/mutable/mod.rs delete mode 100644 git-object/src/mutable/object.rs diff --git a/git-object/src/lib.rs b/git-object/src/lib.rs index a044ef53c5f..44830e8bc58 100644 --- a/git-object/src/lib.rs +++ b/git-object/src/lib.rs @@ -15,7 +15,6 @@ pub use types::{Error, Kind}; use crate::tree::EntryRef; pub mod immutable; -pub mod mutable; /// pub mod commit; @@ -163,6 +162,12 @@ pub enum ObjectRef<'a> { Tag(TagRef<'a>), } +/// Mutable objects with each field being separately allocated and changeable. +/// +/// Mutable objects are Commits, Trees, Blobs and Tags that can be changed and serialized. +/// +/// They either created using object [construction][Object] or by [deserializing existing objects][ObjectRef::from_bytes()] +/// and converting these [into mutable copies][ObjectRef::into_owned()] for adjustments. /// A mutable object representing [`Trees`][Tree], [`Blobs`][Blob], [`Commits`][Commit] or [`Tags`][Tag]. #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] #[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] diff --git a/git-object/src/mutable/mod.rs b/git-object/src/mutable/mod.rs deleted file mode 100644 index 6f83f4697dd..00000000000 --- a/git-object/src/mutable/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -//! Mutable objects with each field being separately allocated and changeable. -//! -//! Mutable objects are Commits, Trees, Blobs and Tags that can be changed and serialized. -//! They either created using object [construction][crate::Object] or by [deserializing existing objects][crate::ObjectRef::from_bytes()] -//! and converting these [into mutable copies][crate::ObjectRef::into_owned()] for adjustments. - -mod object; diff --git a/git-object/src/mutable/object.rs b/git-object/src/mutable/object.rs deleted file mode 100644 index 9f696685376..00000000000 --- a/git-object/src/mutable/object.rs +++ /dev/null @@ -1,132 +0,0 @@ -use std::io; - -use crate::{Blob, Commit, Object, Tag, Tree}; - -/// Convenient extraction of typed object. -impl Object { - /// Returns a [`Blob`][Blob] if it is one. - pub fn as_blob(&self) -> Option<&Blob> { - match self { - Object::Blob(v) => Some(v), - _ => None, - } - } - /// Returns a [`Commit`][Commit] if it is one. - pub fn as_commit(&self) -> Option<&Commit> { - match self { - Object::Commit(v) => Some(v), - _ => None, - } - } - /// Returns a [`Tree`][Tree] if it is one. - pub fn as_tree(&self) -> Option<&Tree> { - match self { - Object::Tree(v) => Some(v), - _ => None, - } - } - /// Returns a [`Tag`][Tag] if it is one. - pub fn as_tag(&self) -> Option<&Tag> { - match self { - Object::Tag(v) => Some(v), - _ => None, - } - } - /// Returns the kind of object stored in this instance. - pub fn kind(&self) -> crate::Kind { - match self { - Object::Tree(_) => crate::Kind::Tree, - Object::Blob(_) => crate::Kind::Blob, - Object::Commit(_) => crate::Kind::Commit, - Object::Tag(_) => crate::Kind::Tag, - } - } -} - -/// Serialization -impl Object { - /// Write the contained object to `out` in the git serialization format. - pub fn write_to(&self, out: impl io::Write) -> io::Result<()> { - use crate::Object::*; - match self { - Tree(v) => v.write_to(out), - Blob(v) => v.write_to(out), - Commit(v) => v.write_to(out), - Tag(v) => v.write_to(out), - } - } -} - -mod convert { - use std::convert::TryFrom; - - use crate::{Blob, Commit, Object, Tag, Tree}; - - impl From for Object { - fn from(v: Tag) -> Self { - Object::Tag(v) - } - } - - impl From for Object { - fn from(v: Commit) -> Self { - Object::Commit(v) - } - } - - impl From for Object { - fn from(v: Tree) -> Self { - Object::Tree(v) - } - } - - impl From for Object { - fn from(v: Blob) -> Self { - Object::Blob(v) - } - } - - impl TryFrom for Tag { - type Error = Object; - - fn try_from(value: Object) -> Result { - Ok(match value { - Object::Tag(v) => v, - _ => return Err(value), - }) - } - } - - impl TryFrom for Commit { - type Error = Object; - - fn try_from(value: Object) -> Result { - Ok(match value { - Object::Commit(v) => v, - _ => return Err(value), - }) - } - } - - impl TryFrom for Tree { - type Error = Object; - - fn try_from(value: Object) -> Result { - Ok(match value { - Object::Tree(v) => v, - _ => return Err(value), - }) - } - } - - impl TryFrom for Blob { - type Error = Object; - - fn try_from(value: Object) -> Result { - Ok(match value { - Object::Blob(v) => v, - _ => return Err(value), - }) - } - } -} diff --git a/git-object/src/object/convert.rs b/git-object/src/object/convert.rs index dd6c208bbe2..2879e5543de 100644 --- a/git-object/src/object/convert.rs +++ b/git-object/src/object/convert.rs @@ -1,4 +1,5 @@ use crate::{tree, Blob, BlobRef, Commit, CommitRef, Object, ObjectRef, Tag, TagRef, Tree, TreeRef}; +use std::convert::TryFrom; impl From> for Tag { fn from(other: TagRef<'_>) -> Tag { @@ -88,3 +89,71 @@ impl<'a> From> for Object { } } } + +impl From for Object { + fn from(v: Tag) -> Self { + Object::Tag(v) + } +} + +impl From for Object { + fn from(v: Commit) -> Self { + Object::Commit(v) + } +} + +impl From for Object { + fn from(v: Tree) -> Self { + Object::Tree(v) + } +} + +impl From for Object { + fn from(v: Blob) -> Self { + Object::Blob(v) + } +} + +impl TryFrom for Tag { + type Error = Object; + + fn try_from(value: Object) -> Result { + Ok(match value { + Object::Tag(v) => v, + _ => return Err(value), + }) + } +} + +impl TryFrom for Commit { + type Error = Object; + + fn try_from(value: Object) -> Result { + Ok(match value { + Object::Commit(v) => v, + _ => return Err(value), + }) + } +} + +impl TryFrom for Tree { + type Error = Object; + + fn try_from(value: Object) -> Result { + Ok(match value { + Object::Tree(v) => v, + _ => return Err(value), + }) + } +} + +impl TryFrom for Blob { + type Error = Object; + + fn try_from(value: Object) -> Result { + Ok(match value { + Object::Blob(v) => v, + _ => return Err(value), + }) + } +} diff --git a/git-object/src/object/mod.rs b/git-object/src/object/mod.rs index bb13da4f1cf..baf448dfbbf 100644 --- a/git-object/src/object/mod.rs +++ b/git-object/src/object/mod.rs @@ -1 +1,64 @@ +use crate::{Blob, Commit, Object, Tag, Tree}; + mod convert; + +mod write { + use std::io; + + use crate::Object; + + /// Serialization + impl Object { + /// Write the contained object to `out` in the git serialization format. + pub fn write_to(&self, out: impl io::Write) -> io::Result<()> { + use crate::Object::*; + match self { + Tree(v) => v.write_to(out), + Blob(v) => v.write_to(out), + Commit(v) => v.write_to(out), + Tag(v) => v.write_to(out), + } + } + } +} + +/// Convenient extraction of typed object. +impl Object { + /// Returns a [`Blob`][Blob] if it is one. + pub fn as_blob(&self) -> Option<&Blob> { + match self { + Object::Blob(v) => Some(v), + _ => None, + } + } + /// Returns a [`Commit`][Commit] if it is one. + pub fn as_commit(&self) -> Option<&Commit> { + match self { + Object::Commit(v) => Some(v), + _ => None, + } + } + /// Returns a [`Tree`][Tree] if it is one. + pub fn as_tree(&self) -> Option<&Tree> { + match self { + Object::Tree(v) => Some(v), + _ => None, + } + } + /// Returns a [`Tag`][Tag] if it is one. + pub fn as_tag(&self) -> Option<&Tag> { + match self { + Object::Tag(v) => Some(v), + _ => None, + } + } + /// Returns the kind of object stored in this instance. + pub fn kind(&self) -> crate::Kind { + match self { + Object::Tree(_) => crate::Kind::Tree, + Object::Blob(_) => crate::Kind::Blob, + Object::Commit(_) => crate::Kind::Commit, + Object::Tag(_) => crate::Kind::Tag, + } + } +} From 2fd23ed9ad556b8e46cf650e23f0c6726e304708 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 26 Aug 2021 17:03:02 +0800 Subject: [PATCH 17/18] [object #177] fix docs --- git-actor/src/lib.rs | 2 +- git-actor/src/signature/mod.rs | 2 +- git-config/src/file/git_config.rs | 2 +- git-object/src/immutable/mod.rs | 6 ------ git-object/src/immutable/object.rs | 4 ++-- git-object/src/lib.rs | 9 ++++++++- git-ref/src/lib.rs | 2 +- git-repository/src/easy/mod.rs | 2 +- 8 files changed, 15 insertions(+), 14 deletions(-) diff --git a/git-actor/src/lib.rs b/git-actor/src/lib.rs index d0a5eed386c..25a26df59a8 100644 --- a/git-actor/src/lib.rs +++ b/git-actor/src/lib.rs @@ -1,4 +1,4 @@ -//! This crate provides ways of identifying an actor within the git repository both in shared/signature_ref and mutable variants. +//! This crate provides ways of identifying an actor within the git repository both in shared/mutable and mutable variants. #![forbid(unsafe_code)] #![deny(rust_2018_idioms, missing_docs)] use bstr::{BStr, BString}; diff --git a/git-actor/src/signature/mod.rs b/git-actor/src/signature/mod.rs index 283069b1154..55a4db1426c 100644 --- a/git-actor/src/signature/mod.rs +++ b/git-actor/src/signature/mod.rs @@ -41,7 +41,7 @@ mod convert { } impl Signature { - /// Borrow this instance as signature_ref + /// Borrow this instance as immutable pub fn to_ref(&self) -> SignatureRef<'_> { SignatureRef { name: self.name.as_ref(), diff --git a/git-config/src/file/git_config.rs b/git-config/src/file/git_config.rs index 2a1d6644553..46345f0b51b 100644 --- a/git-config/src/file/git_config.rs +++ b/git-config/src/file/git_config.rs @@ -306,7 +306,7 @@ impl<'event> GitConfig<'event> { .map_err(|_| GitConfigError::FailedConversion) } - /// Returns an signature_ref section reference. + /// Returns an immutable section reference. /// /// # Errors /// diff --git a/git-object/src/immutable/mod.rs b/git-object/src/immutable/mod.rs index df752f00744..a2e4db2dbbf 100644 --- a/git-object/src/immutable/mod.rs +++ b/git-object/src/immutable/mod.rs @@ -1,8 +1,2 @@ -//! Immutable objects are read-only structures referencing most data from [a byte slice][crate::ObjectRef::from_bytes()]. -//! -//! Immutable objects are expected to be deserialized from bytes that acts as backing store, and they -//! cannot be mutated or serialized. Instead, one will [convert][crate::ObjectRef::into_owned()] them into their [`mutable`][crate::mutable] counterparts -//! which support mutation and serialization. - /// pub mod object; diff --git a/git-object/src/immutable/object.rs b/git-object/src/immutable/object.rs index 31a9eed8612..b4f3060566d 100644 --- a/git-object/src/immutable/object.rs +++ b/git-object/src/immutable/object.rs @@ -11,14 +11,14 @@ impl<'a> ObjectRef<'a> { }) } - /// Convert the signature_ref object into a mutable version, consuming the source in the process. + /// Convert the immutable object into a mutable version, consuming the source in the process. /// /// Note that this is an expensive operation. pub fn into_owned(self) -> Object { self.into() } - /// Convert this signature_ref object into its mutable counterpart. + /// Convert this immutable object into its mutable counterpart. /// /// Note that this is an expensive operation. pub fn to_owned(&self) -> Object { diff --git a/git-object/src/lib.rs b/git-object/src/lib.rs index 44830e8bc58..52fa1a9e732 100644 --- a/git-object/src/lib.rs +++ b/git-object/src/lib.rs @@ -14,6 +14,7 @@ pub use types::{Error, Kind}; use crate::tree::EntryRef; +/// pub mod immutable; /// @@ -150,7 +151,13 @@ pub struct Tag { pub pgp_signature: Option, } -/// An signature_ref object representing [`Trees`][TreeRef], [`Blobs`][BlobRef], [`Commits`][CommitRef], or [`Tags`][TagRef]. +/// Immutable objects are read-only structures referencing most data from [a byte slice][crate::ObjectRef::from_bytes()]. +/// +/// Immutable objects are expected to be deserialized from bytes that acts as backing store, and they +/// cannot be mutated or serialized. Instead, one will [convert][crate::ObjectRef::into_owned()] them into their [`mutable`][crate::mutable] counterparts +/// which support mutation and serialization. +/// +/// An object is representing [`Trees`][TreeRef], [`Blobs`][BlobRef], [`Commits`][CommitRef], or [`Tags`][TagRef]. #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] #[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] #[allow(missing_docs)] diff --git a/git-ref/src/lib.rs b/git-ref/src/lib.rs index 63b4288f593..8b9f7163a38 100644 --- a/git-ref/src/lib.rs +++ b/git-ref/src/lib.rs @@ -71,7 +71,7 @@ pub enum Target { Symbolic(FullName), } -/// Denotes a ref target, equivalent to [`Kind`], but with signature_ref data. +/// Denotes a ref target, equivalent to [`Kind`], but with immutable data. #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)] pub enum TargetRef<'a> { /// A ref that points to an object id diff --git a/git-repository/src/easy/mod.rs b/git-repository/src/easy/mod.rs index 491c8eedf83..3e6cc25af2c 100644 --- a/git-repository/src/easy/mod.rs +++ b/git-repository/src/easy/mod.rs @@ -113,7 +113,7 @@ pub struct State { /// A utility trait to represent access to a repository. /// -/// It provides signature_ref and possibly mutable access. Both types of access are validated at runtime, which may fail +/// It provides immutable and possibly mutable access. Both types of access are validated at runtime, which may fail /// or may block, depending on the implementation. /// /// Furthermore it provides access to additional state for use with the [`Repository`]. It is designed for thread-local From 70e11c21b0637cd250f54381d5490e9976880ad9 Mon Sep 17 00:00:00 2001 From: Sebastian Thiel Date: Thu, 26 Aug 2021 17:13:39 +0800 Subject: [PATCH 18/18] [object #177] dissolve 'immutable' module --- git-diff/src/tree/changes.rs | 3 +- git-object/src/commit/mod.rs | 10 +- git-object/src/commit/ref_iter.rs | 6 +- git-object/src/immutable/mod.rs | 2 - git-object/src/immutable/object.rs | 248 ---------------------- git-object/src/lib.rs | 88 +++++++- git-object/src/object/convert.rs | 68 ++++++ git-object/src/object/mod.rs | 97 +++++++++ git-object/src/tag/mod.rs | 6 +- git-object/src/tag/ref_iter.rs | 8 +- git-object/src/tree/ref_iter.rs | 10 +- git-pack/src/data/object.rs | 4 +- git-pack/src/data/output/count/objects.rs | 2 +- git-pack/src/find.rs | 3 +- git-pack/src/index/verify.rs | 7 +- git-traverse/src/commit.rs | 4 +- git-traverse/src/tree/breadthfirst.rs | 4 +- 17 files changed, 277 insertions(+), 293 deletions(-) delete mode 100644 git-object/src/immutable/mod.rs delete mode 100644 git-object/src/immutable/object.rs diff --git a/git-diff/src/tree/changes.rs b/git-diff/src/tree/changes.rs index 0d95e17b281..5fb66c70093 100644 --- a/git-diff/src/tree/changes.rs +++ b/git-diff/src/tree/changes.rs @@ -1,7 +1,6 @@ use std::{borrow::BorrowMut, collections::VecDeque}; use git_hash::{oid, ObjectId}; -use git_object::immutable; use quick_error::quick_error; use crate::{ @@ -20,7 +19,7 @@ quick_error! { Cancelled { display("The delegate cancelled the operation") } - EntriesDecode(err: immutable::object::decode::Error) { + EntriesDecode(err: git_object::decode::Error) { display("tree entries could not be decoded.") from() source(err) diff --git a/git-object/src/commit/mod.rs b/git-object/src/commit/mod.rs index 878e5d3f5f3..84bcb734a17 100644 --- a/git-object/src/commit/mod.rs +++ b/git-object/src/commit/mod.rs @@ -1,7 +1,7 @@ use bstr::{BStr, ByteSlice}; pub use crate::CommitRefIter; -use crate::{immutable, immutable::object, Commit, CommitRef, TagRef}; +use crate::{Commit, CommitRef, TagRef}; mod decode; @@ -12,10 +12,8 @@ mod write; impl<'a> CommitRef<'a> { /// Deserialize a commit from the given `data` bytes while avoiding most allocations. - pub fn from_bytes(data: &'a [u8]) -> Result, object::decode::Error> { - decode::commit(data) - .map(|(_, t)| t) - .map_err(object::decode::Error::from) + pub fn from_bytes(data: &'a [u8]) -> Result, crate::decode::Error> { + decode::commit(data).map(|(_, t)| t).map_err(crate::decode::Error::from) } /// Return the `tree` fields hash digest. pub fn tree(&self) -> git_hash::ObjectId { @@ -70,7 +68,7 @@ where /// /// A merge tag is a tag object embedded within the respective header field of a commit, making /// it a child object of sorts. - pub fn mergetags(self) -> impl Iterator, immutable::object::decode::Error>> { + pub fn mergetags(self) -> impl Iterator, crate::decode::Error>> { self.find_all("mergetag").map(|b| TagRef::from_bytes(b)) } diff --git a/git-object/src/commit/ref_iter.rs b/git-object/src/commit/ref_iter.rs index 3e476451295..29ee69475ba 100644 --- a/git-object/src/commit/ref_iter.rs +++ b/git-object/src/commit/ref_iter.rs @@ -9,7 +9,7 @@ use nom::{ error::context, }; -use crate::{bstr::ByteSlice, commit::decode, immutable::object, parse, parse::NL, CommitRefIter}; +use crate::{bstr::ByteSlice, commit::decode, parse, parse::NL, CommitRefIter}; #[derive(Copy, Clone)] pub(crate) enum SignatureKind { @@ -68,7 +68,7 @@ impl<'a> CommitRefIter<'a> { } impl<'a> CommitRefIter<'a> { - fn next_inner(i: &'a [u8], state: &mut State) -> Result<(&'a [u8], Token<'a>), object::decode::Error> { + fn next_inner(i: &'a [u8], state: &mut State) -> Result<(&'a [u8], Token<'a>), crate::decode::Error> { use State::*; Ok(match state { Tree => { @@ -167,7 +167,7 @@ impl<'a> CommitRefIter<'a> { } impl<'a> Iterator for CommitRefIter<'a> { - type Item = Result, object::decode::Error>; + type Item = Result, crate::decode::Error>; fn next(&mut self) -> Option { if self.data.is_empty() { diff --git a/git-object/src/immutable/mod.rs b/git-object/src/immutable/mod.rs deleted file mode 100644 index a2e4db2dbbf..00000000000 --- a/git-object/src/immutable/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -/// -pub mod object; diff --git a/git-object/src/immutable/object.rs b/git-object/src/immutable/object.rs deleted file mode 100644 index b4f3060566d..00000000000 --- a/git-object/src/immutable/object.rs +++ /dev/null @@ -1,248 +0,0 @@ -use crate::{BlobRef, CommitRef, Kind, Object, ObjectRef, TagRef, TreeRef}; - -impl<'a> ObjectRef<'a> { - /// Deserialize an object of `kind` from the given `data`. - pub fn from_bytes(kind: Kind, data: &'a [u8]) -> Result, decode::Error> { - Ok(match kind { - Kind::Tree => ObjectRef::Tree(TreeRef::from_bytes(data)?), - Kind::Blob => ObjectRef::Blob(BlobRef { data }), - Kind::Commit => ObjectRef::Commit(CommitRef::from_bytes(data)?), - Kind::Tag => ObjectRef::Tag(TagRef::from_bytes(data)?), - }) - } - - /// Convert the immutable object into a mutable version, consuming the source in the process. - /// - /// Note that this is an expensive operation. - pub fn into_owned(self) -> Object { - self.into() - } - - /// Convert this immutable object into its mutable counterpart. - /// - /// Note that this is an expensive operation. - pub fn to_owned(&self) -> Object { - self.clone().into() - } -} - -/// Convenient access to contained objects. -impl<'a> ObjectRef<'a> { - /// Interpret this object as blob. - pub fn as_blob(&self) -> Option<&BlobRef<'a>> { - match self { - ObjectRef::Blob(v) => Some(v), - _ => None, - } - } - /// Interpret this object as blob, chainable. - pub fn into_blob(self) -> Option> { - match self { - ObjectRef::Blob(v) => Some(v), - _ => None, - } - } - /// Interpret this object as commit. - pub fn as_commit(&self) -> Option<&CommitRef<'a>> { - match self { - ObjectRef::Commit(v) => Some(v), - _ => None, - } - } - /// Interpret this object as commit, chainable. - pub fn into_commit(self) -> Option> { - match self { - ObjectRef::Commit(v) => Some(v), - _ => None, - } - } - /// Interpret this object as tree. - pub fn as_tree(&self) -> Option<&TreeRef<'a>> { - match self { - ObjectRef::Tree(v) => Some(v), - _ => None, - } - } - /// Interpret this object as tree, chainable - pub fn into_tree(self) -> Option> { - match self { - ObjectRef::Tree(v) => Some(v), - _ => None, - } - } - /// Interpret this object as tag. - pub fn as_tag(&self) -> Option<&TagRef<'a>> { - match self { - ObjectRef::Tag(v) => Some(v), - _ => None, - } - } - /// Interpret this object as tag, chainable. - pub fn into_tag(self) -> Option> { - match self { - ObjectRef::Tag(v) => Some(v), - _ => None, - } - } - /// Return the kind of object. - pub fn kind(&self) -> Kind { - match self { - ObjectRef::Tree(_) => Kind::Tree, - ObjectRef::Blob(_) => Kind::Blob, - ObjectRef::Commit(_) => Kind::Commit, - ObjectRef::Tag(_) => Kind::Tag, - } - } -} - -mod convert { - use std::convert::TryFrom; - - use crate::{BlobRef, CommitRef, ObjectRef, TagRef, TreeRef}; - - impl<'a> From> for ObjectRef<'a> { - fn from(v: TagRef<'a>) -> Self { - ObjectRef::Tag(v) - } - } - - impl<'a> From> for ObjectRef<'a> { - fn from(v: CommitRef<'a>) -> Self { - ObjectRef::Commit(v) - } - } - - impl<'a> From> for ObjectRef<'a> { - fn from(v: TreeRef<'a>) -> Self { - ObjectRef::Tree(v) - } - } - - impl<'a> From> for ObjectRef<'a> { - fn from(v: BlobRef<'a>) -> Self { - ObjectRef::Blob(v) - } - } - - impl<'a> TryFrom> for TagRef<'a> { - type Error = ObjectRef<'a>; - - fn try_from(value: ObjectRef<'a>) -> Result { - Ok(match value { - ObjectRef::Tag(v) => v, - _ => return Err(value), - }) - } - } - - impl<'a> TryFrom> for CommitRef<'a> { - type Error = ObjectRef<'a>; - - fn try_from(value: ObjectRef<'a>) -> Result { - Ok(match value { - ObjectRef::Commit(v) => v, - _ => return Err(value), - }) - } - } - - impl<'a> TryFrom> for TreeRef<'a> { - type Error = ObjectRef<'a>; - - fn try_from(value: ObjectRef<'a>) -> Result { - Ok(match value { - ObjectRef::Tree(v) => v, - _ => return Err(value), - }) - } - } - - impl<'a> TryFrom> for BlobRef<'a> { - type Error = ObjectRef<'a>; - - fn try_from(value: ObjectRef<'a>) -> Result { - Ok(match value { - ObjectRef::Blob(v) => v, - _ => return Err(value), - }) - } - } -} - -/// -#[cfg(feature = "verbose-object-parsing-errors")] -pub mod decode { - use crate::bstr::{BString, ByteSlice}; - - /// The type to be used for parse errors. - pub type ParseError<'a> = nom::error::VerboseError<&'a [u8]>; - /// The owned type to be used for parse errors. - pub type ParseErrorOwned = nom::error::VerboseError; - - /// A type to indicate errors during parsing and to abstract away details related to `nom`. - #[derive(Debug, Clone)] - pub struct Error { - /// The actual error - pub inner: ParseErrorOwned, - } - - impl<'a> From>> for Error { - fn from(v: nom::Err>) -> Self { - Error { - inner: match v { - nom::Err::Error(err) | nom::Err::Failure(err) => nom::error::VerboseError { - errors: err - .errors - .into_iter() - .map(|(i, v)| (i.as_bstr().to_owned(), v)) - .collect(), - }, - nom::Err::Incomplete(_) => unreachable!("we don't have streaming parsers"), - }, - } - } - } - - impl std::fmt::Display for Error { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.inner.fmt(f) - } - } - - impl std::error::Error for Error {} -} - -/// -#[cfg(not(feature = "verbose-object-parsing-errors"))] -pub mod decode { - /// The type to be used for parse errors, discards everything and is zero size - pub type ParseError<'a> = (); - /// The owned type to be used for parse errors, discards everything and is zero size - pub type ParseErrorOwned = (); - - /// A type to indicate errors during parsing and to abstract away details related to `nom`. - #[derive(Debug, Clone)] - pub struct Error { - /// The actual error - pub inner: ParseErrorOwned, - } - - impl<'a> From>> for Error { - fn from(v: nom::Err>) -> Self { - Error { - inner: match v { - nom::Err::Error(err) | nom::Err::Failure(err) => err, - nom::Err::Incomplete(_) => unreachable!("we don't have streaming parsers"), - }, - } - } - } - - impl std::fmt::Display for Error { - fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - Ok(()) - } - } - - impl std::error::Error for Error {} -} diff --git a/git-object/src/lib.rs b/git-object/src/lib.rs index 52fa1a9e732..e58b34ef01b 100644 --- a/git-object/src/lib.rs +++ b/git-object/src/lib.rs @@ -14,9 +14,6 @@ pub use types::{Error, Kind}; use crate::tree::EntryRef; -/// -pub mod immutable; - /// pub mod commit; mod object; @@ -154,10 +151,10 @@ pub struct Tag { /// Immutable objects are read-only structures referencing most data from [a byte slice][crate::ObjectRef::from_bytes()]. /// /// Immutable objects are expected to be deserialized from bytes that acts as backing store, and they -/// cannot be mutated or serialized. Instead, one will [convert][crate::ObjectRef::into_owned()] them into their [`mutable`][crate::mutable] counterparts +/// cannot be mutated or serialized. Instead, one will [convert][crate::ObjectRef::into_owned()] them into their [`mutable`][Object] counterparts /// which support mutation and serialization. /// -/// An object is representing [`Trees`][TreeRef], [`Blobs`][BlobRef], [`Commits`][CommitRef], or [`Tags`][TagRef]. +/// An `ObjectRef` is representing [`Trees`][TreeRef], [`Blobs`][BlobRef], [`Commits`][CommitRef], or [`Tags`][TagRef]. #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] #[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] #[allow(missing_docs)] @@ -175,7 +172,8 @@ pub enum ObjectRef<'a> { /// /// They either created using object [construction][Object] or by [deserializing existing objects][ObjectRef::from_bytes()] /// and converting these [into mutable copies][ObjectRef::into_owned()] for adjustments. -/// A mutable object representing [`Trees`][Tree], [`Blobs`][Blob], [`Commits`][Commit] or [`Tags`][Tag]. +/// +/// An `Object` is representing [`Trees`][Tree], [`Blobs`][Blob], [`Commits`][Commit] or [`Tags`][Tag]. #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] #[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))] #[allow(clippy::large_enum_variant, missing_docs)] @@ -210,3 +208,81 @@ pub struct Tree { /// The directories and files contained in this tree. They must be and remain sorted by [`filename`][Entry::filename]. pub entries: Vec, } + +/// +#[cfg(feature = "verbose-object-parsing-errors")] +pub mod decode { + use crate::bstr::{BString, ByteSlice}; + + /// The type to be used for parse errors. + pub type ParseError<'a> = nom::error::VerboseError<&'a [u8]>; + /// The owned type to be used for parse errors. + pub type ParseErrorOwned = nom::error::VerboseError; + + /// A type to indicate errors during parsing and to abstract away details related to `nom`. + #[derive(Debug, Clone)] + pub struct Error { + /// The actual error + pub inner: ParseErrorOwned, + } + + impl<'a> From>> for Error { + fn from(v: nom::Err>) -> Self { + Error { + inner: match v { + nom::Err::Error(err) | nom::Err::Failure(err) => nom::error::VerboseError { + errors: err + .errors + .into_iter() + .map(|(i, v)| (i.as_bstr().to_owned(), v)) + .collect(), + }, + nom::Err::Incomplete(_) => unreachable!("we don't have streaming parsers"), + }, + } + } + } + + impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.inner.fmt(f) + } + } + + impl std::error::Error for Error {} +} + +/// +#[cfg(not(feature = "verbose-object-parsing-errors"))] +pub mod decode { + /// The type to be used for parse errors, discards everything and is zero size + pub type ParseError<'a> = (); + /// The owned type to be used for parse errors, discards everything and is zero size + pub type ParseErrorOwned = (); + + /// A type to indicate errors during parsing and to abstract away details related to `nom`. + #[derive(Debug, Clone)] + pub struct Error { + /// The actual error + pub inner: ParseErrorOwned, + } + + impl<'a> From>> for Error { + fn from(v: nom::Err>) -> Self { + Error { + inner: match v { + nom::Err::Error(err) | nom::Err::Failure(err) => err, + nom::Err::Incomplete(_) => unreachable!("we don't have streaming parsers"), + }, + } + } + } + + impl std::fmt::Display for Error { + fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + Ok(()) + } + } + + impl std::error::Error for Error {} +} diff --git a/git-object/src/object/convert.rs b/git-object/src/object/convert.rs index 2879e5543de..60e2e58d6ee 100644 --- a/git-object/src/object/convert.rs +++ b/git-object/src/object/convert.rs @@ -157,3 +157,71 @@ impl TryFrom for Blob { }) } } + +impl<'a> From> for ObjectRef<'a> { + fn from(v: TagRef<'a>) -> Self { + ObjectRef::Tag(v) + } +} + +impl<'a> From> for ObjectRef<'a> { + fn from(v: CommitRef<'a>) -> Self { + ObjectRef::Commit(v) + } +} + +impl<'a> From> for ObjectRef<'a> { + fn from(v: TreeRef<'a>) -> Self { + ObjectRef::Tree(v) + } +} + +impl<'a> From> for ObjectRef<'a> { + fn from(v: BlobRef<'a>) -> Self { + ObjectRef::Blob(v) + } +} + +impl<'a> TryFrom> for TagRef<'a> { + type Error = ObjectRef<'a>; + + fn try_from(value: ObjectRef<'a>) -> Result { + Ok(match value { + ObjectRef::Tag(v) => v, + _ => return Err(value), + }) + } +} + +impl<'a> TryFrom> for CommitRef<'a> { + type Error = ObjectRef<'a>; + + fn try_from(value: ObjectRef<'a>) -> Result { + Ok(match value { + ObjectRef::Commit(v) => v, + _ => return Err(value), + }) + } +} + +impl<'a> TryFrom> for TreeRef<'a> { + type Error = ObjectRef<'a>; + + fn try_from(value: ObjectRef<'a>) -> Result { + Ok(match value { + ObjectRef::Tree(v) => v, + _ => return Err(value), + }) + } +} + +impl<'a> TryFrom> for BlobRef<'a> { + type Error = ObjectRef<'a>; + + fn try_from(value: ObjectRef<'a>) -> Result { + Ok(match value { + ObjectRef::Blob(v) => v, + _ => return Err(value), + }) + } +} diff --git a/git-object/src/object/mod.rs b/git-object/src/object/mod.rs index baf448dfbbf..6ec2b263ec8 100644 --- a/git-object/src/object/mod.rs +++ b/git-object/src/object/mod.rs @@ -62,3 +62,100 @@ impl Object { } } } + +use crate::{BlobRef, CommitRef, Kind, ObjectRef, TagRef, TreeRef}; + +impl<'a> ObjectRef<'a> { + /// Deserialize an object of `kind` from the given `data`. + pub fn from_bytes(kind: Kind, data: &'a [u8]) -> Result, crate::decode::Error> { + Ok(match kind { + Kind::Tree => ObjectRef::Tree(TreeRef::from_bytes(data)?), + Kind::Blob => ObjectRef::Blob(BlobRef { data }), + Kind::Commit => ObjectRef::Commit(CommitRef::from_bytes(data)?), + Kind::Tag => ObjectRef::Tag(TagRef::from_bytes(data)?), + }) + } + + /// Convert the immutable object into a mutable version, consuming the source in the process. + /// + /// Note that this is an expensive operation. + pub fn into_owned(self) -> Object { + self.into() + } + + /// Convert this immutable object into its mutable counterpart. + /// + /// Note that this is an expensive operation. + pub fn to_owned(&self) -> Object { + self.clone().into() + } +} + +/// Convenient access to contained objects. +impl<'a> ObjectRef<'a> { + /// Interpret this object as blob. + pub fn as_blob(&self) -> Option<&BlobRef<'a>> { + match self { + ObjectRef::Blob(v) => Some(v), + _ => None, + } + } + /// Interpret this object as blob, chainable. + pub fn into_blob(self) -> Option> { + match self { + ObjectRef::Blob(v) => Some(v), + _ => None, + } + } + /// Interpret this object as commit. + pub fn as_commit(&self) -> Option<&CommitRef<'a>> { + match self { + ObjectRef::Commit(v) => Some(v), + _ => None, + } + } + /// Interpret this object as commit, chainable. + pub fn into_commit(self) -> Option> { + match self { + ObjectRef::Commit(v) => Some(v), + _ => None, + } + } + /// Interpret this object as tree. + pub fn as_tree(&self) -> Option<&TreeRef<'a>> { + match self { + ObjectRef::Tree(v) => Some(v), + _ => None, + } + } + /// Interpret this object as tree, chainable + pub fn into_tree(self) -> Option> { + match self { + ObjectRef::Tree(v) => Some(v), + _ => None, + } + } + /// Interpret this object as tag. + pub fn as_tag(&self) -> Option<&TagRef<'a>> { + match self { + ObjectRef::Tag(v) => Some(v), + _ => None, + } + } + /// Interpret this object as tag, chainable. + pub fn into_tag(self) -> Option> { + match self { + ObjectRef::Tag(v) => Some(v), + _ => None, + } + } + /// Return the kind of object. + pub fn kind(&self) -> Kind { + match self { + ObjectRef::Tree(_) => Kind::Tree, + ObjectRef::Blob(_) => Kind::Blob, + ObjectRef::Commit(_) => Kind::Commit, + ObjectRef::Tag(_) => Kind::Tag, + } + } +} diff --git a/git-object/src/tag/mod.rs b/git-object/src/tag/mod.rs index 86c153b8829..0d82598f587 100644 --- a/git-object/src/tag/mod.rs +++ b/git-object/src/tag/mod.rs @@ -1,4 +1,4 @@ -use crate::{immutable::object, TagRef}; +use crate::TagRef; mod decode; @@ -10,10 +10,10 @@ pub mod ref_iter; impl<'a> TagRef<'a> { /// Deserialize a tag from `data`. - pub fn from_bytes(data: &'a [u8]) -> Result, object::decode::Error> { + pub fn from_bytes(data: &'a [u8]) -> Result, crate::decode::Error> { decode::git_tag(data) .map(|(_, t)| t) - .map_err(object::decode::Error::from) + .map_err(crate::decode::Error::from) } /// The object this tag points to as `Id`. pub fn target(&self) -> git_hash::ObjectId { diff --git a/git-object/src/tag/ref_iter.rs b/git-object/src/tag/ref_iter.rs index b4c0e85466c..7cf5250417e 100644 --- a/git-object/src/tag/ref_iter.rs +++ b/git-object/src/tag/ref_iter.rs @@ -7,7 +7,7 @@ use nom::{ error::{context, ParseError}, }; -use crate::{bstr::ByteSlice, immutable::object, parse, parse::NL, tag::decode, Kind, TagRefIter}; +use crate::{bstr::ByteSlice, parse, parse::NL, tag::decode, Kind, TagRefIter}; pub(crate) enum State { Target, @@ -45,7 +45,7 @@ impl<'a> TagRefIter<'a> { } impl<'a> TagRefIter<'a> { - fn next_inner(i: &'a [u8], state: &mut State) -> Result<(&'a [u8], Token<'a>), object::decode::Error> { + fn next_inner(i: &'a [u8], state: &mut State) -> Result<(&'a [u8], Token<'a>), crate::decode::Error> { use State::*; Ok(match state { Target => { @@ -65,7 +65,7 @@ impl<'a> TagRefIter<'a> { parse::header_field(i, b"type", take_while1(is_alphabetic)) })(i)?; let kind = crate::Kind::from_bytes(kind).map_err(|_| { - let err = object::decode::ParseError::from_error_kind(i, nom::error::ErrorKind::MapRes); + let err = crate::decode::ParseError::from_error_kind(i, nom::error::ErrorKind::MapRes); nom::Err::Error(err) })?; *state = State::Name; @@ -99,7 +99,7 @@ impl<'a> TagRefIter<'a> { } impl<'a> Iterator for TagRefIter<'a> { - type Item = Result, object::decode::Error>; + type Item = Result, crate::decode::Error>; fn next(&mut self) -> Option { if self.data.is_empty() { diff --git a/git-object/src/tree/ref_iter.rs b/git-object/src/tree/ref_iter.rs index 7627902d9f5..8e859ce522b 100644 --- a/git-object/src/tree/ref_iter.rs +++ b/git-object/src/tree/ref_iter.rs @@ -1,6 +1,6 @@ use std::convert::TryFrom; -use crate::{immutable::object, tree, tree::EntryRef, TreeRef, TreeRefIter}; +use crate::{tree, tree::EntryRef, TreeRef, TreeRefIter}; impl<'a> TreeRefIter<'a> { /// Instantiate an iterator from the given tree data. @@ -11,8 +11,8 @@ impl<'a> TreeRefIter<'a> { impl<'a> TreeRef<'a> { /// Deserialize a Tree from `data`. - pub fn from_bytes(data: &'a [u8]) -> Result, object::decode::Error> { - decode::tree(data).map(|(_, t)| t).map_err(object::decode::Error::from) + pub fn from_bytes(data: &'a [u8]) -> Result, crate::decode::Error> { + decode::tree(data).map(|(_, t)| t).map_err(crate::decode::Error::from) } /// Create an instance of the empty tree. @@ -25,7 +25,7 @@ impl<'a> TreeRef<'a> { impl<'a> TreeRefIter<'a> { /// Consume self and return all parsed entries. - pub fn entries(self) -> Result>, object::decode::Error> { + pub fn entries(self) -> Result>, crate::decode::Error> { self.collect() } } @@ -37,7 +37,7 @@ impl<'a> Default for TreeRefIter<'a> { } impl<'a> Iterator for TreeRefIter<'a> { - type Item = Result, object::decode::Error>; + type Item = Result, crate::decode::Error>; fn next(&mut self) -> Option { if self.data.is_empty() { diff --git a/git-pack/src/data/object.rs b/git-pack/src/data/object.rs index 6f1567282ce..cd6392232a1 100644 --- a/git-pack/src/data/object.rs +++ b/git-pack/src/data/object.rs @@ -1,6 +1,6 @@ //! Contains a borrowed Object bound to a buffer holding its decompressed data. -use git_object::{commit, immutable, BlobRef, CommitRef, ObjectRef, TagRef, TagRefIter, TreeRef, TreeRefIter}; +use git_object::{commit, BlobRef, CommitRef, ObjectRef, TagRef, TagRefIter, TreeRef, TreeRefIter}; /// A borrowed object using a borrowed slice as backing buffer. #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] @@ -27,7 +27,7 @@ impl<'a> Object<'a> { /// /// **Note** that [mutable, decoded objects][git_object::Object] can be created from a [`crate::data::Object`] /// using [`git_object::ObjectRef::into_owned()`]. - pub fn decode(&self) -> Result, immutable::object::decode::Error> { + pub fn decode(&self) -> Result, git_object::decode::Error> { Ok(match self.kind { git_object::Kind::Tree => ObjectRef::Tree(TreeRef::from_bytes(self.data)?), git_object::Kind::Blob => ObjectRef::Blob(BlobRef { data: self.data }), diff --git a/git-pack/src/data/output/count/objects.rs b/git-pack/src/data/output/count/objects.rs index 1cca54e2ff5..f766ca8f533 100644 --- a/git-pack/src/data/output/count/objects.rs +++ b/git-pack/src/data/output/count/objects.rs @@ -643,7 +643,7 @@ mod types { IterErr: std::error::Error + 'static, { #[error(transparent)] - CommitDecode(git_object::immutable::object::decode::Error), + CommitDecode(git_object::decode::Error), #[error(transparent)] FindExisting(#[from] FindErr), #[error(transparent)] diff --git a/git-pack/src/find.rs b/git-pack/src/find.rs index 4a710ebf492..a95c27b8e6d 100644 --- a/git-pack/src/find.rs +++ b/git-pack/src/find.rs @@ -158,7 +158,6 @@ pub mod existing { /// pub mod existing_object { use git_hash::ObjectId; - use git_object::immutable; /// The error returned by the various [`find_existing_*`][crate::FindExt::find_existing_commit()] trait methods. #[derive(Debug, thiserror::Error)] @@ -167,7 +166,7 @@ pub mod existing_object { #[error(transparent)] Find(T), #[error(transparent)] - Decode(immutable::object::decode::Error), + Decode(git_object::decode::Error), #[error("An object with id {} could not be found", .oid)] NotFound { oid: ObjectId }, #[error("Expected object of kind {} something else", .expected)] diff --git a/git-pack/src/index/verify.rs b/git-pack/src/index/verify.rs index cc0ca50af73..e9f0802882f 100644 --- a/git-pack/src/index/verify.rs +++ b/git-pack/src/index/verify.rs @@ -2,10 +2,7 @@ use std::sync::{atomic::AtomicBool, Arc}; use git_features::progress::{self, Progress}; use git_hash::SIZE_OF_SHA1_DIGEST as SHA1_SIZE; -use git_object::{ - bstr::{BString, ByteSlice}, - immutable::object, -}; +use git_object::bstr::{BString, ByteSlice}; use crate::index; @@ -20,7 +17,7 @@ pub enum Error { }, #[error("{kind} object {id} could not be decoded")] ObjectDecode { - source: object::decode::Error, + source: git_object::decode::Error, kind: git_object::Kind, id: git_hash::ObjectId, }, diff --git a/git-traverse/src/commit.rs b/git-traverse/src/commit.rs index 358882c44d1..89c3be058ef 100644 --- a/git-traverse/src/commit.rs +++ b/git-traverse/src/commit.rs @@ -6,7 +6,7 @@ pub mod ancestors { }; use git_hash::{oid, ObjectId}; - use git_object::{commit, immutable}; + use git_object::commit; use quick_error::quick_error; quick_error! { @@ -17,7 +17,7 @@ pub mod ancestors { NotFound{oid: ObjectId} { display("The commit {} could not be found", oid) } - ObjectDecode(err: immutable::object::decode::Error) { + ObjectDecode(err: git_object::decode::Error) { display("An object could not be decoded") source(err) from() diff --git a/git-traverse/src/tree/breadthfirst.rs b/git-traverse/src/tree/breadthfirst.rs index 6bbdbccdd53..1a1161910fe 100644 --- a/git-traverse/src/tree/breadthfirst.rs +++ b/git-traverse/src/tree/breadthfirst.rs @@ -1,7 +1,7 @@ use std::{borrow::BorrowMut, collections::VecDeque}; use git_hash::{oid, ObjectId}; -use git_object::{immutable, tree, TreeRefIter}; +use git_object::{tree, TreeRefIter}; use quick_error::quick_error; use crate::tree::visit::Visit; @@ -17,7 +17,7 @@ quick_error! { Cancelled { display("The delegate cancelled the operation") } - ObjectDecode(err: immutable::object::decode::Error) { + ObjectDecode(err: git_object::decode::Error) { display("An object could not be decoded") source(err) from()