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
//! Git references, conditional transactions and reflogs across files and reftable storage.
//!
//! # Names, reads, and updates
//!
//! - [`RefName`] validates a full reference name. [`References`] reads stored [`Target`] values and
//! resolves symbolic chains without loading their objects. [`References::read_observation`]
//! captures a stored target together with its backend-provided peeled hint.
//! - [`References::transaction`] checks a batch of [`RefEdit`] values before sequential
//! publication. Choose [`Reflog`] policy explicitly and inspect [`RefEditOutcome`] after a
//! partial failure; the no-reflog methods deliberately omit history.
//! - [`References::imported_reflog`] reads existing history for retention or analysis.
//! [`ImportedReflog::is_complete`] distinguishes a full read from recovered records.
//! - [`reftable`] exposes bounded stack snapshots and compaction for repositories using that
//! backend. Files and reftable have different publication and cleanup contracts.
//!
//! The files backend reads loose refs before packed refs and separates symbolic resolution from
//! object lookup.
//! [`References::list_controlled`] bounds files enumeration before a GC inventory retains names;
//! reftable uses its separate stack budgets.
//!
//! [`References::imported_reflog`] reads bounded imported history. [`ImportedRecord`] preserves raw
//! data and separates [`ImportedRecord::fields`] from canonical append validation.
//!
//! # Example
//!
//! Publish a first commit through `HEAD` onto the unborn `main` branch, then resolve it. The
//! transaction checks every expected value before publishing anything:
//!
//! ```
//! use girt::refs::{Expected, RefEdit, RefName, Reflog, Target};
//! use girt::{Commit, CommitFields, InitKind, ObjectFormat, Repository, Signature, Tree};
//!
//! let directory = tempfile::tempdir()?;
//! let repository = Repository::init(
//! ObjectFormat::Sha1,
//! directory.path().join("repo.git"),
//! InitKind::Bare,
//! )?;
//! let loose = repository.loose_objects();
//! let person = Signature {
//! name: b"A. Writer".to_vec(),
//! email: b"writer@example.com".to_vec(),
//! seconds: 1_700_000_000,
//! offset_minutes: 0,
//! };
//! let commit = loose.write_commit(&Commit::new(CommitFields {
//! tree: loose.write_tree(&Tree::new(ObjectFormat::Sha1, vec![])?)?,
//! parents: vec![],
//! author: person.clone(),
//! committer: person.clone(),
//! extra_headers: vec![],
//! message: b"Initial commit\n".to_vec(),
//! })?)?;
//!
//! let references = repository.references()?;
//! let head = RefName::new("HEAD")?;
//! let edit = RefEdit::new(
//! head.clone(),
//! Some(Target::Direct(commit)),
//! Expected::Absent,
//! Reflog::Append {
//! committer: person,
//! message: b"commit (initial)".to_vec(),
//! },
//! );
//! references.transaction(&[edit.with_dereference(girt::refs::Dereference::Follow)])?;
//!
//! let main = RefName::new("refs/heads/main")?;
//! assert_eq!(references.read(&main)?, Some(Target::Direct(commit)));
//! let resolved = references.resolve(&head, 5)?;
//! assert_eq!((resolved.name, resolved.id), (main.clone(), Some(commit)));
//! assert_eq!(references.reflog(&main)?.map(|log| log.len()), Some(1));
//! # Ok::<(), Box<dyn std::error::Error>>(())
//! ```
pub use LOOSE_SCANS;
pub use Reference;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
/// Parses `bytes` as one files-backend format and checks re-encoding where girt encodes it.
///
/// `kind` selects a loose reference, a packed-refs file, a reflog or a reference name; see
/// [`crate::fuzzing::refs`].
pub