gix_ref/lib.rs
1//! A crate for handling the references stored in various formats in a git repository.
2//!
3//! References are also called _refs_ which are used interchangeably.
4//!
5//! Refs are the way to keep track of objects and come in two flavors.
6//!
7//! * symbolic refs are pointing to another reference
8//! * peeled refs point to the an object by its [`ObjectId`]
9//!
10//! They can be identified by a relative path and stored in various flavors.
11//!
12//! * **files**
13//! * **[loose][file::Store]**
14//! * one reference maps to a file on disk
15//! * **packed**
16//! * references are stored in a single human-readable file, along with their targets if they are symbolic.
17//!
18//! Concrete recovery signals such as missing references and reflog identities expose classification-only
19//! [`gix_error::ClassificationMarker`] sources. Use `is_not_found()`, `is_corrupted()`, `is_validation()`, or
20//! `classify()` on [`gix_error::Exn`] and [`gix_error::Error`] rather than downcasting these sources to classifier
21//! error types. Callee errors retain their concrete causes. Locally detected failures may use a single classified
22//! [`gix_error::Message`] containing both the diagnostic and its values.
23//! Operations return [`gix_error::Exn`], with diagnostic [`gix_error::Message`] keys documented where they are added.
24//! Inspect these dictionaries with [`metadata()`](gix_error::Exn::metadata), and add context available at the call site.
25//! For recovery, downcast to [`file::find::NotFound`] to distinguish an absent reference from an absent object,
26//! [`file::find::ReferenceDecode`] for loose reference contents that could not be decoded,
27//! [`file::transaction::prepare::ReferenceOutOfDate`] or [`file::transaction::prepare::MustNotExist`] for a failed
28//! update constraint, and [`file::log::create_or_update::MissingCommitter`] for a missing reflog identity.
29//!
30//! ## Feature Flags
31#![cfg_attr(
32 all(doc, feature = "document-features"),
33 doc = ::document_features::document_features!()
34)]
35#![cfg_attr(all(doc, feature = "document-features"), feature(doc_cfg))]
36#![deny(missing_docs, unsafe_code)]
37
38use gix_hash::{ObjectId, oid};
39pub use gix_object::bstr;
40use gix_object::bstr::{BStr, BString};
41
42#[path = "store/mod.rs"]
43mod store_impl;
44pub use store_impl::{file, packed};
45
46mod compare;
47mod fullname;
48///
49pub mod name;
50///
51pub mod namespace;
52///
53pub mod transaction;
54
55mod parse;
56mod raw;
57
58pub use raw::Reference;
59
60mod target;
61
62///
63pub mod log;
64
65///
66pub mod store {
67 ///
68 pub mod init {
69
70 /// Options for use during [initialization](crate::file::Store::at).
71 #[derive(Debug, Copy, Clone, Default)]
72 pub struct Options {
73 /// How to write the ref-log.
74 pub write_reflog: super::WriteReflog,
75 /// The equivalent of `core.precomposeUnicode`.
76 pub precompose_unicode: bool,
77 /// If `true`, we will avoid reading from or writing to references that contains Windows device names
78 /// to avoid side effects. This only needs to be `true` on Windows, but can be `true` on other platforms
79 /// if they need to remain compatible with Windows.
80 pub prohibit_windows_device_names: bool,
81 }
82 }
83 /// The way a file store handles the reflog
84 #[derive(Default, Debug, PartialOrd, PartialEq, Ord, Eq, Hash, Clone, Copy)]
85 pub enum WriteReflog {
86 /// Always write the reflog for all references for ref edits, unconditionally.
87 Always,
88 /// Write a ref log for ref edits according to the standard rules.
89 #[default]
90 Normal,
91 /// Never write a ref log.
92 Disable,
93 }
94
95 /// A thread-local handle for interacting with a [`Store`][crate::Store] to find and iterate references.
96 #[derive(Clone)]
97 #[expect(
98 dead_code,
99 reason = "the general reference-store handle is scaffolding for planned ref-table support"
100 )]
101 pub(crate) struct Handle {
102 /// A way to access shared state with the requirement that interior mutability doesn't leak or is incorporated into error types
103 /// if it could. The latter can't happen if references to said internal aren't ever returned.
104 state: handle::State,
105 }
106
107 #[expect(
108 dead_code,
109 reason = "the general reference-store state is scaffolding for planned ref-table support"
110 )]
111 pub(crate) enum State {
112 Loose { store: file::Store },
113 }
114
115 pub(crate) mod general;
116
117 ///
118 #[path = "general/handle/mod.rs"]
119 mod handle;
120 pub use handle::find;
121
122 use crate::file;
123}
124
125/// The git reference store.
126/// TODO: Figure out if handles are needed at all, which depends on the ref-table implementation.
127#[expect(
128 dead_code,
129 reason = "callers still use file::Store directly while this general store awaits ref-table support"
130)]
131pub(crate) struct Store {
132 inner: store::State,
133}
134
135/// A validated complete and fully qualified reference name, safe to use for all operations.
136#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
137#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
138pub struct FullName(pub(crate) BString);
139
140/// A validated complete and fully qualified reference name, safe to use for all operations.
141#[derive(Hash, Debug, PartialEq, Eq, Ord, PartialOrd)]
142#[repr(transparent)]
143pub struct FullNameRef(BStr);
144
145/// A validated and potentially partial reference name, safe to use for common operations.
146#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd)]
147#[repr(transparent)]
148pub struct PartialNameRef(BStr);
149
150/// A validated and potentially partial reference name, safe to use for common operations.
151#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
152#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
153pub struct PartialName(BString);
154
155/// A _validated_ prefix for references to act as a namespace.
156#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
157#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
158pub struct Namespace(BString);
159
160/// Denotes the kind of reference.
161#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
162#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
163pub enum Kind {
164 /// A ref that points to an object id directly.
165 Object,
166 /// A ref that points to another reference, adding a level of indirection.
167 ///
168 /// It can be resolved to an id using the [`peel_to_id()`][`crate::file::ReferenceExt::peel_to_id()`] method.
169 Symbolic,
170}
171
172/// The various known categories of references.
173///
174/// This translates into a prefix containing all references of a given category.
175#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
176#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
177pub enum Category<'a> {
178 /// A tag in `refs/tags`
179 Tag,
180 /// A branch in `refs/heads`
181 LocalBranch,
182 /// A branch in `refs/remotes`
183 RemoteBranch,
184 /// A tag in `refs/notes`
185 Note,
186 /// Something outside `ref/` in the current worktree, typically `HEAD`.
187 PseudoRef,
188 /// A `PseudoRef`, but referenced so that it will always refer to the main worktree by
189 /// prefixing it with `main-worktree/`.
190 MainPseudoRef,
191 /// Any reference that is prefixed with `main-worktree/refs/`
192 MainRef,
193 /// A `PseudoRef` in another _linked_ worktree, never in the main one, like `worktrees/<id>/HEAD`.
194 LinkedPseudoRef {
195 /// The name of the worktree.
196 #[cfg_attr(feature = "serde", serde(borrow))]
197 name: &'a BStr,
198 },
199 /// Any reference that is prefixed with `worktrees/<id>/refs/`.
200 LinkedRef {
201 /// The name of the worktree.
202 name: &'a BStr,
203 },
204 /// A ref that is private to each worktree (_linked_ or _main_), with `refs/bisect/` prefix
205 Bisect,
206 /// A ref that is private to each worktree (_linked_ or _main_), with `refs/rewritten/` prefix
207 Rewritten,
208 /// A ref that is private to each worktree (_linked_ or _main_), with `refs/worktree/` prefix
209 WorktreePrivate,
210 // REF_TYPE_NORMAL, /* normal/shared refs inside refs/ */
211}
212
213/// Denotes a ref target, equivalent to [`Kind`], but with mutable data.
214#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
215#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
216pub enum Target {
217 /// A ref that points directly to an object id.
218 Object(ObjectId),
219 /// A ref that points to another reference by its validated name, adding a level of indirection.
220 ///
221 /// Note that this is an extension of gitoxide which will be helpful in logging all reference changes.
222 Symbolic(FullName),
223}
224
225/// Denotes a ref target, equivalent to [`Kind`], but with immutable data.
226#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
227pub enum TargetRef<'a> {
228 /// A ref that points directly to an object id.
229 Object(&'a oid),
230 /// A ref that points to another reference by its validated name, adding a level of indirection.
231 Symbolic(&'a FullNameRef),
232}