git_stub/lib.rs
1// Copyright 2026 Oxide Computer Company
2
3// This line is automatically updated by cargo-release.
4#![doc(html_root_url = "https://docs.rs/git-stub/1.0.0")]
5
6//! Parsing types for Git stubs.
7//!
8//! A *Git stub* (e.g., `foo.json.gitstub`) contains a reference to a file
9//! stored in Git history, in the format `commit:path`. This allows storing a
10//! pointer to a file's contents without duplicating the actual data in the
11//! working tree.
12//!
13//! Git stubs are useful in case you have several different versions of a file
14//! that must be stored side by side, but the files aren't large enough to be
15//! stored through a mechanism like [Git LFS](https://git-lfs.com/). Git stubs
16//! are similar to [LFS pointer
17//! files](https://github.com/git-lfs/git-lfs/blob/main/docs/spec.md#the-pointer),
18//! with the difference being that the canonical versions are stored in old
19//! versions of Git history rather than on an external server.
20//!
21//! For more about the motivation and design decisions behind Git stubs, see
22//! [RFD 634 Git stub files for Dropshot versioned
23//! APIs](https://rfd.shared.oxide.computer/rfd/0634).
24//!
25//! The main entry point is [`GitStub`].
26//!
27//! # Examples
28//!
29//! ```
30//! use git_stub::{GitCommitHash, GitStub};
31//!
32//! // A Git stub contains a single line in the format "commit:path\n".
33//! let file_contents =
34//! "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2:openapi/api-v1.json\n";
35//! let stub: GitStub = file_contents.parse().unwrap();
36//!
37//! // Inspect the parsed commit hash and path.
38//! assert!(matches!(stub.commit(), GitCommitHash::Sha1(_)));
39//! assert_eq!(stub.path().as_str(), "openapi/api-v1.json");
40//!
41//! // Canonical input: needs_rewrite is false.
42//! assert!(!stub.needs_rewrite());
43//!
44//! // Round-trip back to canonical file contents.
45//! assert_eq!(stub.to_file_contents(), file_contents);
46//!
47//! // Parsing from non-canonical input (e.g., missing trailing newline)
48//! // sets needs_rewrite to true.
49//! let stub2: GitStub =
50//! "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2:openapi/api-v1.json"
51//! .parse()
52//! .unwrap();
53//! assert!(stub2.needs_rewrite());
54//!
55//! // To retrieve the actual file from Git history, use
56//! // `git_stub_vcs::Vcs` to read the contents.
57//! ```
58//!
59//! # Related crates
60//!
61//! For materializing files from version control systems like Git or Jujutsu,
62//! see [`git-stub-vcs`](https://crates.io/crates/git-stub-vcs) ([source
63//! tree](https://github.com/oxidecomputer/git-stub/tree/main/crates/git-stub-vcs)).
64
65#![deny(missing_docs)]
66
67mod errors;
68mod git_stub;
69mod hash;
70
71pub use errors::{CommitHashParseError, GitStubParseError};
72pub use git_stub::GitStub;
73pub use hash::GitCommitHash;