1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
//! A crate for handling the references stored in various formats in a git repository.
//!
//! References are also called _refs_ which are used interchangeably.
//!
//! Refs are the way to keep track of objects and come in two flavors.
//!
//! * symbolic refs are pointing to another reference
//! * peeled refs point to the an object by its [`ObjectId`]
//!
//! They can be identified by a relative path and stored in various flavors.
//!
//! * **files**
//!   * **[loose][file::Store]**
//!     * one reference maps to a file on disk
//!   * **packed**
//!     * references are stored in a single human-readable file, along with their targets if they are symbolic.
//!
//! ## Feature Flags
#![cfg_attr(
    all(doc, feature = "document-features"),
    doc = ::document_features::document_features!()
)]
#![cfg_attr(all(doc, feature = "document-features"), feature(doc_cfg, doc_auto_cfg))]
#![deny(missing_docs, rust_2018_idioms, unsafe_code)]

use std::borrow::Cow;

use gix_hash::{oid, ObjectId};
pub use gix_object::bstr;
use gix_object::bstr::{BStr, BString};

#[path = "store/mod.rs"]
mod store_impl;
pub use store_impl::{file, packed};

mod fullname;
///
#[allow(clippy::empty_docs)]
pub mod name;
///
#[allow(clippy::empty_docs)]
pub mod namespace;
///
#[allow(clippy::empty_docs)]
pub mod transaction;

mod parse;
mod raw;

pub use raw::Reference;

mod target;

///
#[allow(clippy::empty_docs)]
pub mod log;

///
#[allow(clippy::empty_docs)]
pub mod peel;

///
#[allow(clippy::empty_docs)]
pub mod store {
    ///
    #[allow(clippy::empty_docs)]
    pub mod init {

        /// Options for use during [initialization](crate::file::Store::at).
        #[derive(Debug, Copy, Clone, Default)]
        pub struct Options {
            /// How to write the ref-log.
            pub write_reflog: super::WriteReflog,
            /// The kind of hash to expect in
            pub object_hash: gix_hash::Kind,
            /// The equivalent of `core.precomposeUnicode`.
            pub precompose_unicode: bool,
            /// If `true`, we will avoid reading from or writing to references that contains Windows device names
            /// to avoid side effects. This only needs to be `true` on Windows, but can be `true` on other platforms
            /// if they need to remain compatible with Windows.
            pub prohibit_windows_device_names: bool,
        }
    }
    /// The way a file store handles the reflog
    #[derive(Default, Debug, PartialOrd, PartialEq, Ord, Eq, Hash, Clone, Copy)]
    pub enum WriteReflog {
        /// Always write the reflog for all references for ref edits, unconditionally.
        Always,
        /// Write a ref log for ref edits according to the standard rules.
        #[default]
        Normal,
        /// Never write a ref log.
        Disable,
    }

    /// A thread-local handle for interacting with a [`Store`][crate::Store] to find and iterate references.
    #[derive(Clone)]
    #[allow(dead_code)]
    pub(crate) struct Handle {
        /// A way to access shared state with the requirement that interior mutability doesn't leak or is incorporated into error types
        /// if it could. The latter can't happen if references to said internal aren't ever returned.
        state: handle::State,
    }

    #[allow(dead_code)]
    pub(crate) enum State {
        Loose { store: file::Store },
    }

    pub(crate) mod general;

    ///
    #[path = "general/handle/mod.rs"]
    mod handle;
    use crate::file;
    pub use handle::find;
}

/// The git reference store.
/// TODO: Figure out if handles are needed at all, which depends on the ref-table implementation.
#[allow(dead_code)]
pub(crate) struct Store {
    inner: store::State,
}

/// A validated complete and fully qualified referenced reference name, safe to use for all operations.
#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct FullName(pub(crate) BString);

/// A validated complete and fully qualified referenced reference name, safe to use for all operations.
#[derive(Hash, Debug, PartialEq, Eq, Ord, PartialOrd)]
#[repr(transparent)]
pub struct FullNameRef(BStr);

/// A validated and potentially partial reference name, safe to use for common operations.
#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
pub struct PartialNameCow<'a>(Cow<'a, BStr>);

/// A validated and potentially partial reference name, safe to use for common operations.
#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd)]
#[repr(transparent)]
pub struct PartialNameRef(BStr);

/// A validated and potentially partial reference name, safe to use for common operations.
#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
pub struct PartialName(BString);

/// A _validated_ prefix for references to act as a namespace.
#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
pub struct Namespace(BString);

/// Denotes the kind of reference.
#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Kind {
    /// A ref that points to an object id
    Peeled,
    /// A ref that points to another reference, adding a level of indirection.
    ///
    /// It can be resolved to an id using the [`peel_in_place_to_id()`][`crate::file::ReferenceExt::peel_to_id_in_place()`] method.
    Symbolic,
}

/// The various known categories of references.
///
/// This translates into a prefix containing all references of a given category.
#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
pub enum Category<'a> {
    /// A tag in `refs/tags`
    Tag,
    /// A branch in `refs/heads`
    LocalBranch,
    /// A branch in `refs/remotes`
    RemoteBranch,
    /// A tag in `refs/notes`
    Note,
    /// Something outside of `ref/` in the current worktree, typically `HEAD`.
    PseudoRef,
    /// A `PseudoRef`, but referenced so that it will always refer to the main worktree by
    /// prefixing it with `main-worktree/`.
    MainPseudoRef,
    /// Any reference that is prefixed with `main-worktree/refs/`
    MainRef,
    /// A `PseudoRef` in another _linked_ worktree, never in the main one, like `worktrees/<id>/HEAD`.
    LinkedPseudoRef {
        /// The name of the worktree.
        name: &'a BStr,
    },
    /// Any reference that is prefixed with `worktrees/<id>/refs/`.
    LinkedRef {
        /// The name of the worktree.
        name: &'a BStr,
    },
    /// A ref that is private to each worktree (_linked_ or _main_), with `refs/bisect/` prefix
    Bisect,
    /// A ref that is private to each worktree (_linked_ or _main_), with `refs/rewritten/` prefix
    Rewritten,
    /// A ref that is private to each worktree (_linked_ or _main_), with `refs/worktree/` prefix
    WorktreePrivate,
    // REF_TYPE_NORMAL,	  /* normal/shared refs inside refs/        */
}

/// Denotes a ref target, equivalent to [`Kind`], but with mutable data.
#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Target {
    /// A ref that points to an object id
    Peeled(ObjectId),
    /// A ref that points to another reference by its validated name, adding a level of indirection.
    ///
    /// Note that this is an extension of gitoxide which will be helpful in logging all reference changes.
    Symbolic(FullName),
}

/// Denotes a ref target, equivalent to [`Kind`], but with immutable data.
#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
pub enum TargetRef<'a> {
    /// A ref that points to an object id
    Peeled(&'a oid),
    /// A ref that points to another reference by its validated name, adding a level of indirection.
    Symbolic(&'a FullNameRef),
}