Skip to main content

gix_commitgraph/
lib.rs

1//! Read, verify, and traverse git commit graphs.
2//!
3//! A [commit graph][Graph] is an index of commits in the git commit history.
4//! The [Graph] stores commit data in a way that accelerates lookups considerably compared to
5//! traversing the git history by usual means.
6//!
7//! As generating the full commit graph from scratch can take some time, git may write new commits
8//! to separate [files][File] instead of overwriting the original file.
9//! Eventually, git will merge these files together as the number of files grows.
10//! ## Feature Flags
11#![cfg_attr(
12    all(doc, feature = "document-features"),
13    doc = ::document_features::document_features!()
14)]
15#![cfg_attr(all(doc, feature = "document-features"), feature(doc_cfg))]
16#![deny(missing_docs, unsafe_code)]
17
18use gix_error::Result;
19use std::path::Path;
20
21/// A single commit-graph file.
22///
23/// All operations on a `File` are local to that graph file. Since a commit graph can span multiple
24/// files, all interesting graph operations belong on [`Graph`].
25pub struct File {
26    /// Number of base graph files this file depends on, as declared in its header.
27    base_graph_count: u8,
28    /// Byte offset into `data` of the optional BASE chunk containing base graph checksums.
29    base_graphs_list_offset: Option<usize>,
30    /// Byte offset into `data` of the CDAT chunk containing fixed-size commit records.
31    commit_data_offset: usize,
32    /// Read-only memory mapping of the entire commit-graph file, including its checksum trailer.
33    data: memmap2::Mmap,
34    /// Byte range within `data` of the optional EDGE chunk containing additional parent positions.
35    extra_edges_list_range: Option<std::ops::Range<usize>>,
36    /// Decoded OIDF fanout table: entry `i` counts commit IDs whose first byte is at most `i`.
37    /// Entries are nondecreasing, and the last entry is the number of commits in this file.
38    fan: [u32; file::FAN_LEN],
39    /// Byte offset into `data` of the OIDL chunk containing lexicographically sorted commit IDs.
40    oid_lookup_offset: usize,
41    /// Path associated with the mapping, used for diagnostics and filename checksum verification.
42    path: std::path::PathBuf,
43    /// Size in bytes of an object ID or checksum using `object_hash`.
44    hash_len: usize,
45    /// Hash algorithm declared in the file header, used for object IDs and graph checksums.
46    object_hash: gix_hash::Kind,
47    /// Exclusive upper bound for graph-wide parent positions accepted during iteration.
48    /// In a [`Graph`], this counts commits in this file and all preceding base files.
49    /// A standalone file uses its commit count if it has no bases, or [`MAX_COMMITS`] otherwise.
50    parent_position_limit: u32,
51}
52
53/// A complete commit graph.
54///
55/// The data in the commit graph may come from a monolithic `objects/info/commit-graph` file, or it
56/// may come from one or more `objects/info/commit-graphs/graph-*.graph` files. These files are
57/// generated via `git commit-graph write ...` commands.
58pub struct Graph {
59    files: nonempty::NonEmpty<File>,
60}
61
62/// Owned parent commit information collected during traversal.
63///
64/// Shared with traversal buffers so allocation-limit estimates use the same record layout.
65#[derive(Clone, Copy, Debug, Eq, PartialEq)]
66pub struct Parent {
67    /// The object ID of the parent commit.
68    pub commit_id: gix_hash::ObjectId,
69    /// The parent's generation number, or [`GENERATION_NUMBER_INFINITY`] if unavailable.
70    pub generation: u32,
71    /// The parent's committer timestamp, in seconds since the Unix epoch.
72    pub commit_time: i64,
73}
74
75/// Instantiate a commit graph from an `.git/objects/info` directory, or one of the various commit-graph files.
76///
77/// Chain entries and graph files must use `object_hash`, typically the repository's hash kind.
78/// `alloc_limit_bytes` limits parent-buffer capacity estimates as described in [`Graph::at()`].
79/// `None` disables the limit.
80pub fn at(path: impl AsRef<Path>, object_hash: gix_hash::Kind, alloc_limit_bytes: Option<usize>) -> Result<Graph> {
81    Graph::at(path.as_ref(), object_hash, alloc_limit_bytes)
82}
83
84mod access;
85pub mod file;
86///
87pub mod init;
88pub mod verify;
89
90/// The number of generations that are considered 'infinite' commit history.
91pub const GENERATION_NUMBER_INFINITY: u32 = 0xffff_ffff;
92/// The largest valid generation number.
93///
94/// If a commit's real generation number is larger than this, the commit graph will cap the value to
95/// this number.
96/// The largest distinct generation number is `GENERATION_NUMBER_MAX - 1`.
97pub const GENERATION_NUMBER_MAX: u32 = 0x3fff_ffff;
98
99/// The maximum number of commits that can be stored in a commit graph.
100pub const MAX_COMMITS: u32 = (1 << 30) + (1 << 29) + (1 << 28) - 1;
101
102/// A generalized position for use in [`Graph`].
103#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd, Hash)]
104pub struct Position(pub u32);
105
106impl std::fmt::Display for Position {
107    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
108        self.0.fmt(f)
109    }
110}