33
44use gix_ref:: file:: ReferenceExt ;
55
6- use crate :: { Id , Reference } ;
6+ use crate :: { Blob , Commit , Id , Object , Reference , Tag , Tree } ;
77
88pub mod iter;
99///
@@ -65,19 +65,21 @@ impl<'repo> Reference<'repo> {
6565
6666/// Peeling
6767impl < ' repo > Reference < ' repo > {
68- /// Follow all symbolic targets this reference might point to and peel the underlying object
69- /// to the end of the chain , and return it.
68+ /// Follow all symbolic targets this reference might point to and peel all annotated tags
69+ /// to their first non-tag target , and return it,
7070 ///
71- /// This is useful to learn where this reference is ultimately pointing to.
71+ /// This is useful to learn where this reference is ultimately pointing to after following
72+ /// the chain of symbolic refs and annotated tags.
7273 pub fn peel_to_id_in_place ( & mut self ) -> Result < Id < ' repo > , peel:: Error > {
7374 let oid = self . inner . peel_to_id_in_place ( & self . repo . refs , & self . repo . objects ) ?;
7475 Ok ( Id :: from_id ( oid, self . repo ) )
7576 }
7677
77- /// Follow all symbolic targets this reference might point to and peel the underlying object
78- /// to the end of the chain , and return it, reusing the `packed` buffer if available.
78+ /// Follow all symbolic targets this reference might point to and peel all annotated tags
79+ /// to their first non-tag target , and return it, reusing the `packed` buffer if available.
7980 ///
80- /// This is useful to learn where this reference is ultimately pointing to.
81+ /// This is useful to learn where this reference is ultimately pointing to after following
82+ /// the chain of symbolic refs and annotated tags.
8183 pub fn peel_to_id_in_place_packed (
8284 & mut self ,
8385 packed : Option < & gix_ref:: packed:: Buffer > ,
@@ -88,11 +90,69 @@ impl<'repo> Reference<'repo> {
8890 Ok ( Id :: from_id ( oid, self . repo ) )
8991 }
9092
91- /// Similar to [`peel_to_id_in_place()`][ Reference::peel_to_id_in_place()] , but consumes this instance.
93+ /// Similar to [`peel_to_id_in_place()`]( Reference::peel_to_id_in_place()) , but consumes this instance.
9294 pub fn into_fully_peeled_id ( mut self ) -> Result < Id < ' repo > , peel:: Error > {
9395 self . peel_to_id_in_place ( )
9496 }
9597
98+ /// Follow this reference's target until it points at an object directly, and peel that object until
99+ /// its type matches the given `kind`. It's an error to try to peel to a kind that this ref doesn't point to.
100+ ///
101+ /// Note that this ref will point to the first target object afterward, which may be a tag. This is different
102+ /// from [`peel_to_id_in_place()`](Self::peel_to_id_in_place()) where it will point to the first non-tag object.
103+ #[ doc( alias = "peel" , alias = "git2" ) ]
104+ pub fn peel_to_kind ( & mut self , kind : gix_object:: Kind ) -> Result < Object < ' repo > , peel:: to_kind:: Error > {
105+ let packed = self . repo . refs . cached_packed_buffer ( ) . map_err ( |err| {
106+ peel:: to_kind:: Error :: FollowToObject ( gix_ref:: peel:: to_object:: Error :: Follow (
107+ file:: find:: existing:: Error :: Find ( file:: find:: Error :: PackedOpen ( err) ) ,
108+ ) )
109+ } ) ?;
110+ self . peel_to_kind_packed ( kind, packed. as_ref ( ) . map ( |p| & * * * p) )
111+ }
112+
113+ /// Peel this ref until the first commit.
114+ ///
115+ /// For details, see [`peel_to_kind`()](Self::peel_to_kind()).
116+ pub fn peel_to_commit ( & mut self ) -> Result < Commit < ' repo > , peel:: to_kind:: Error > {
117+ Ok ( self . peel_to_kind ( gix_object:: Kind :: Commit ) ?. into_commit ( ) )
118+ }
119+
120+ /// Peel this ref until the first annotated tag.
121+ ///
122+ /// For details, see [`peel_to_kind`()](Self::peel_to_kind()).
123+ pub fn peel_to_tag ( & mut self ) -> Result < Tag < ' repo > , peel:: to_kind:: Error > {
124+ Ok ( self . peel_to_kind ( gix_object:: Kind :: Tag ) ?. into_tag ( ) )
125+ }
126+
127+ /// Peel this ref until the first tree.
128+ ///
129+ /// For details, see [`peel_to_kind`()](Self::peel_to_kind()).
130+ pub fn peel_to_tree ( & mut self ) -> Result < Tree < ' repo > , peel:: to_kind:: Error > {
131+ Ok ( self . peel_to_kind ( gix_object:: Kind :: Tree ) ?. into_tree ( ) )
132+ }
133+
134+ /// Peel this ref until it points to a blob. Note that this is highly uncommon to happen
135+ /// as it would require an annotated tag to point to a blob, instead of a commit.
136+ ///
137+ /// For details, see [`peel_to_kind`()](Self::peel_to_kind()).
138+ pub fn peel_to_blob ( & mut self ) -> Result < Blob < ' repo > , peel:: to_kind:: Error > {
139+ Ok ( self . peel_to_kind ( gix_object:: Kind :: Blob ) ?. into_blob ( ) )
140+ }
141+
142+ /// Like [`peel_to_kind()`](Self::peel_to_kind), but allows to provide `packed` for best possible performance
143+ /// when peeling many refs.
144+ pub fn peel_to_kind_packed (
145+ & mut self ,
146+ kind : gix_object:: Kind ,
147+ packed : Option < & gix_ref:: packed:: Buffer > ,
148+ ) -> Result < Object < ' repo > , peel:: to_kind:: Error > {
149+ let target = self
150+ . inner
151+ . follow_to_object_in_place_packed ( & self . repo . refs , packed) ?
152+ . attach ( self . repo ) ;
153+ Ok ( target. object ( ) ?. peel_to_kind ( kind) ?)
154+ }
155+
96156 /// Follow this symbolic reference one level and return the ref it refers to.
97157 ///
98158 /// Returns `None` if this is not a symbolic reference, hence the leaf of the chain.
@@ -108,3 +168,4 @@ impl<'repo> Reference<'repo> {
108168
109169mod edits;
110170pub use edits:: { delete, set_target_id} ;
171+ use gix_ref:: file;
0 commit comments