]> git.proxmox.com Git - rustc.git/blame - vendor/gix/src/id.rs
New upstream version 1.74.1+dfsg1
[rustc.git] / vendor / gix / src / id.rs
CommitLineData
0a29b90c
FG
1//!
2use std::ops::Deref;
3
4use gix_hash::{oid, ObjectId};
5
781aab86 6use crate::{object::find, Id, Object};
0a29b90c 7
781aab86 8/// An [object id][ObjectId] infused with a [`Repository`][crate::Repository].
0a29b90c
FG
9impl<'repo> Id<'repo> {
10 /// Find the [`Object`] associated with this object id, and consider it an error if it doesn't exist.
11 ///
12 /// # Note
13 ///
14 /// There can only be one `ObjectRef` per `Easy`. To increase that limit, clone the `Easy`.
15 pub fn object(&self) -> Result<Object<'repo>, find::existing::Error> {
16 self.repo.find_object(self.inner)
17 }
18
781aab86
FG
19 /// Find the [`header`][gix_odb::find::Header] associated with this object id, or an error if it doesn't exist.
20 ///
21 /// Use this method if there is no interest in the contents of the object, which generally is much faster to obtain.
22 pub fn header(&self) -> Result<gix_odb::find::Header, find::existing::Error> {
23 self.repo.find_header(self.inner)
24 }
25
0a29b90c
FG
26 /// Try to find the [`Object`] associated with this object id, and return `None` if it's not available locally.
27 ///
28 /// # Note
29 ///
30 /// There can only be one `ObjectRef` per `Easy`. To increase that limit, clone the `Easy`.
31 pub fn try_object(&self) -> Result<Option<Object<'repo>>, find::Error> {
32 self.repo.try_find_object(self.inner)
33 }
34
781aab86
FG
35 /// Find the [`header`][gix_odb::find::Header] associated with this object id, or return `None` if it doesn't exist.
36 ///
37 /// Use this method if there is no interest in the contents of the object, which generally is much faster to obtain.
38 pub fn try_header(&self) -> Result<Option<gix_odb::find::Header>, find::Error> {
39 self.repo.try_find_header(self.inner)
40 }
41
0a29b90c
FG
42 /// Turn this object id into a shortened id with a length in hex as configured by `core.abbrev`.
43 pub fn shorten(&self) -> Result<gix_hash::Prefix, shorten::Error> {
44 let hex_len = self.repo.config.hex_len.map_or_else(
45 || self.repo.objects.packed_object_count().map(calculate_auto_hex_len),
46 Ok,
47 )?;
48
49 let prefix = gix_odb::store::prefix::disambiguate::Candidate::new(self.inner, hex_len)
50 .expect("BUG: internal hex-len must always be valid");
51 self.repo
52 .objects
53 .disambiguate_prefix(prefix)?
54 .ok_or(shorten::Error::NotFound { oid: self.inner })
55 }
56
57 /// Turn this object id into a shortened id with a length in hex as configured by `core.abbrev`, or default
58 /// to a prefix which equals our id in the unlikely error case.
59 pub fn shorten_or_id(&self) -> gix_hash::Prefix {
60 self.shorten().unwrap_or_else(|_| self.inner.into())
61 }
62}
63
64fn calculate_auto_hex_len(num_packed_objects: u64) -> usize {
65 let mut len = 64 - num_packed_objects.leading_zeros();
66 len = (len + 1) / 2;
67 len.max(7) as usize
68}
69
70///
71pub mod shorten {
72 /// Returned by [`Id::prefix()`][super::Id::shorten()].
73 #[derive(Debug, thiserror::Error)]
74 #[allow(missing_docs)]
75 pub enum Error {
76 #[error(transparent)]
77 PackedObjectsCount(#[from] gix_odb::store::load_index::Error),
78 #[error(transparent)]
79 DisambiguatePrefix(#[from] gix_odb::store::prefix::disambiguate::Error),
80 #[error("Id could not be shortened as the object with id {} could not be found", .oid)]
81 NotFound { oid: gix_hash::ObjectId },
82 }
83}
84
85impl<'repo> Deref for Id<'repo> {
86 type Target = oid;
87
88 fn deref(&self) -> &Self::Target {
89 &self.inner
90 }
91}
92
93impl<'repo> Id<'repo> {
94 pub(crate) fn from_id(id: impl Into<ObjectId>, repo: &'repo crate::Repository) -> Self {
95 Id { inner: id.into(), repo }
96 }
97
fe692bf9 98 /// Turn this instance into its bare [`ObjectId`].
0a29b90c
FG
99 pub fn detach(self) -> ObjectId {
100 self.inner
101 }
102}
103
104impl<'repo> Id<'repo> {
105 /// Obtain a platform for traversing ancestors of this commit.
781aab86
FG
106 pub fn ancestors(&self) -> crate::revision::walk::Platform<'repo> {
107 crate::revision::walk::Platform::new(Some(self.inner), self.repo)
0a29b90c
FG
108 }
109}
110
111mod impls {
112 use std::{cmp::Ordering, hash::Hasher};
113
114 use gix_hash::{oid, ObjectId};
115
116 use crate::{Id, Object, ObjectDetached};
117
118 // Eq, Hash, Ord, PartialOrd,
119
120 impl<'a> std::hash::Hash for Id<'a> {
121 fn hash<H: Hasher>(&self, state: &mut H) {
122 self.inner.hash(state)
123 }
124 }
125
126 impl<'a> PartialOrd<Id<'a>> for Id<'a> {
127 fn partial_cmp(&self, other: &Id<'a>) -> Option<Ordering> {
128 self.inner.partial_cmp(&other.inner)
129 }
130 }
131
132 impl<'repo> PartialEq<Id<'repo>> for Id<'repo> {
133 fn eq(&self, other: &Id<'repo>) -> bool {
134 self.inner == other.inner
135 }
136 }
137
138 impl<'repo> PartialEq<ObjectId> for Id<'repo> {
139 fn eq(&self, other: &ObjectId) -> bool {
140 &self.inner == other
141 }
142 }
143
144 impl<'repo> PartialEq<Id<'repo>> for ObjectId {
145 fn eq(&self, other: &Id<'repo>) -> bool {
146 self == &other.inner
147 }
148 }
149
150 impl<'repo> PartialEq<oid> for Id<'repo> {
151 fn eq(&self, other: &oid) -> bool {
152 self.inner == other
153 }
154 }
155
156 impl<'repo> PartialEq<Object<'repo>> for Id<'repo> {
157 fn eq(&self, other: &Object<'repo>) -> bool {
158 self.inner == other.id
159 }
160 }
161
162 impl<'repo> PartialEq<ObjectDetached> for Id<'repo> {
163 fn eq(&self, other: &ObjectDetached) -> bool {
164 self.inner == other.id
165 }
166 }
167
168 impl<'repo> std::fmt::Debug for Id<'repo> {
169 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
170 self.inner.fmt(f)
171 }
172 }
173
174 impl<'repo> std::fmt::Display for Id<'repo> {
175 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
176 self.inner.fmt(f)
177 }
178 }
179
180 impl<'repo> AsRef<oid> for Id<'repo> {
181 fn as_ref(&self) -> &oid {
182 &self.inner
183 }
184 }
185
186 impl<'repo> From<Id<'repo>> for ObjectId {
187 fn from(v: Id<'repo>) -> Self {
188 v.inner
189 }
190 }
191}
192
193#[cfg(test)]
194mod tests {
195 use super::*;
196
197 #[test]
198 fn size_of_oid() {
49aad941
FG
199 let actual = std::mem::size_of::<Id<'_>>();
200 let ceiling = 32;
201 assert!(
202 actual <= ceiling,
203 "size of oid shouldn't change without notice: {actual} <= {ceiling}"
0a29b90c
FG
204 )
205 }
206}