[go: up one dir, main page]

gix/object/
mod.rs

1//!
2#![allow(clippy::empty_docs)]
3use gix_hash::ObjectId;
4pub use gix_object::Kind;
5
6use crate::{Blob, Commit, Id, Object, ObjectDetached, Tag, Tree};
7
8mod errors;
9pub(crate) mod cache {
10    pub use gix_pack::cache::object::MemoryCappedHashmap;
11}
12pub use errors::{conversion, find, write};
13///
14pub mod blob;
15///
16pub mod commit;
17mod impls;
18pub mod peel;
19mod tag;
20///
21pub mod tree;
22
23///
24pub mod try_into {
25    #[derive(thiserror::Error, Debug)]
26    #[allow(missing_docs)]
27    #[error("Object named {id} was supposed to be of kind {expected}, but was kind {actual}.")]
28    pub struct Error {
29        pub actual: gix_object::Kind,
30        pub expected: gix_object::Kind,
31        pub id: gix_hash::ObjectId,
32    }
33}
34
35impl ObjectDetached {
36    /// Infuse this owned object with `repo` access.
37    pub fn attach(self, repo: &crate::Repository) -> Object<'_> {
38        Object {
39            id: self.id,
40            kind: self.kind,
41            data: self.data,
42            repo,
43        }
44    }
45}
46
47impl std::fmt::Debug for ObjectDetached {
48    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49        use gix_object::Kind::*;
50        let type_name = match self.kind {
51            Blob => "Blob",
52            Commit => "Commit",
53            Tree => "Tree",
54            Tag => "Tag",
55        };
56        write!(f, "{}({})", type_name, self.id)
57    }
58}
59
60/// Consuming conversions to attached object kinds.
61impl<'repo> Object<'repo> {
62    pub(crate) fn from_data(
63        id: impl Into<ObjectId>,
64        kind: Kind,
65        data: Vec<u8>,
66        repo: &'repo crate::Repository,
67    ) -> Self {
68        Object {
69            id: id.into(),
70            kind,
71            data,
72            repo,
73        }
74    }
75
76    /// Transform this object into a blob, or panic if it is none.
77    pub fn into_blob(self) -> Blob<'repo> {
78        match self.try_into() {
79            Ok(blob) => blob,
80            Err(this) => panic!("Tried to use {} as blob, but was {}", this.id, this.kind),
81        }
82    }
83
84    /// Transform this object into a tree, or panic if it is none.
85    pub fn into_tree(self) -> Tree<'repo> {
86        match self.try_into() {
87            Ok(tree) => tree,
88            Err(this) => panic!("Tried to use {} as tree, but was {}", this.id, this.kind),
89        }
90    }
91
92    /// Transform this object into a commit, or panic if it is none.
93    pub fn into_commit(self) -> Commit<'repo> {
94        match self.try_into() {
95            Ok(commit) => commit,
96            Err(this) => panic!("Tried to use {} as commit, but was {}", this.id, this.kind),
97        }
98    }
99
100    /// Transform this object into a tag, or panic if it is none.
101    pub fn into_tag(self) -> Tag<'repo> {
102        match self.try_into() {
103            Ok(tag) => tag,
104            Err(this) => panic!("Tried to use {} as tag, but was {}", this.id, this.kind),
105        }
106    }
107
108    /// Transform this object into a commit, or return it as part of the `Err` if it is no commit.
109    pub fn try_into_commit(self) -> Result<Commit<'repo>, try_into::Error> {
110        self.try_into().map_err(|this: Self| try_into::Error {
111            id: this.id,
112            actual: this.kind,
113            expected: gix_object::Kind::Commit,
114        })
115    }
116
117    /// Transform this object into a tag, or return it as part of the `Err` if it is no commit.
118    pub fn try_into_tag(self) -> Result<Tag<'repo>, try_into::Error> {
119        self.try_into().map_err(|this: Self| try_into::Error {
120            id: this.id,
121            actual: this.kind,
122            expected: gix_object::Kind::Commit,
123        })
124    }
125
126    /// Transform this object into a tree, or return it as part of the `Err` if it is no tree.
127    pub fn try_into_tree(self) -> Result<Tree<'repo>, try_into::Error> {
128        self.try_into().map_err(|this: Self| try_into::Error {
129            id: this.id,
130            actual: this.kind,
131            expected: gix_object::Kind::Tree,
132        })
133    }
134
135    /// Transform this object into a blob, or return it as part of the `Err` if it is no blob.
136    pub fn try_into_blob(self) -> Result<Blob<'repo>, try_into::Error> {
137        self.try_into().map_err(|this: Self| try_into::Error {
138            id: this.id,
139            actual: this.kind,
140            expected: gix_object::Kind::Blob,
141        })
142    }
143}
144
145impl Object<'_> {
146    /// Create an owned instance of this object, copying our data in the process.
147    pub fn detached(&self) -> ObjectDetached {
148        ObjectDetached {
149            id: self.id,
150            kind: self.kind,
151            data: self.data.clone(),
152        }
153    }
154
155    /// Sever the connection to the `Repository` and turn this instance into a standalone object.
156    pub fn detach(self) -> ObjectDetached {
157        self.into()
158    }
159}
160
161/// Conversions to detached, lower-level object types.
162impl<'repo> Object<'repo> {
163    /// Obtain a fully parsed commit whose fields reference our data buffer,
164    ///
165    /// # Panic
166    ///
167    /// - this object is not a commit
168    /// - the commit could not be decoded
169    pub fn to_commit_ref(&self) -> gix_object::CommitRef<'_> {
170        self.try_to_commit_ref().expect("BUG: need a commit")
171    }
172
173    /// Obtain a fully parsed commit whose fields reference our data buffer.
174    pub fn try_to_commit_ref(&self) -> Result<gix_object::CommitRef<'_>, conversion::Error> {
175        gix_object::Data::new(self.kind, &self.data)
176            .decode()?
177            .into_commit()
178            .ok_or(conversion::Error::UnexpectedType {
179                expected: gix_object::Kind::Commit,
180                actual: self.kind,
181            })
182    }
183
184    /// Obtain an iterator over commit tokens like in [`to_commit_iter()`][Object::try_to_commit_ref_iter()].
185    ///
186    /// # Panic
187    ///
188    /// - this object is not a commit
189    pub fn to_commit_ref_iter(&self) -> gix_object::CommitRefIter<'_> {
190        gix_object::Data::new(self.kind, &self.data)
191            .try_into_commit_iter()
192            .expect("BUG: This object must be a commit")
193    }
194
195    /// Obtain a commit token iterator from the data in this instance, if it is a commit.
196    pub fn try_to_commit_ref_iter(&self) -> Option<gix_object::CommitRefIter<'_>> {
197        gix_object::Data::new(self.kind, &self.data).try_into_commit_iter()
198    }
199
200    /// Obtain a tag token iterator from the data in this instance.
201    ///
202    /// # Panic
203    ///
204    /// - this object is not a tag
205    pub fn to_tag_ref_iter(&self) -> gix_object::TagRefIter<'_> {
206        gix_object::Data::new(self.kind, &self.data)
207            .try_into_tag_iter()
208            .expect("BUG: this object must be a tag")
209    }
210
211    /// Obtain a tag token iterator from the data in this instance.
212    ///
213    /// # Panic
214    ///
215    /// - this object is not a tag
216    pub fn try_to_tag_ref_iter(&self) -> Option<gix_object::TagRefIter<'_>> {
217        gix_object::Data::new(self.kind, &self.data).try_into_tag_iter()
218    }
219
220    /// Obtain a tag object from the data in this instance.
221    ///
222    /// # Panic
223    ///
224    /// - this object is not a tag
225    /// - the tag could not be decoded
226    pub fn to_tag_ref(&self) -> gix_object::TagRef<'_> {
227        self.try_to_tag_ref().expect("BUG: need tag")
228    }
229
230    /// Obtain a fully parsed tag object whose fields reference our data buffer.
231    pub fn try_to_tag_ref(&self) -> Result<gix_object::TagRef<'_>, conversion::Error> {
232        gix_object::Data::new(self.kind, &self.data)
233            .decode()?
234            .into_tag()
235            .ok_or(conversion::Error::UnexpectedType {
236                expected: gix_object::Kind::Tag,
237                actual: self.kind,
238            })
239    }
240
241    /// Return the attached id of this object.
242    pub fn id(&self) -> Id<'repo> {
243        Id::from_id(self.id, self.repo)
244    }
245}