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
//! 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")?;
//! references.transaction(&[RefEdit {
//! name: head.clone(),
//! dereference: true,
//! target: Some(Target::Direct(commit)),
//! expected: Expected::Absent,
//! reflog: Reflog::Append {
//! committer: person,
//! message: b"commit (initial)".to_vec(),
//! },
//! }])?;
//!
//! 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 ;