Skip to main content

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}