Skip to main content

git_closure/snapshot/
mod.rs

1/// Core snapshot types shared across the build, serialization, hash, and
2/// materialize layers.  Deliberately kept as a types-only module to keep
3/// the dependency graph acyclic.
4pub mod build;
5pub mod diff;
6pub mod hash;
7pub mod render;
8pub mod serial;
9pub mod summary;
10
11use crate::error::GitClosureError;
12
13pub(crate) type Result<T> = std::result::Result<T, GitClosureError>;
14
15/// An individual file record within a `.gcl` snapshot.
16///
17/// Invariants:
18/// - `symlink_target.is_some()` ⟺ `sha256.is_empty() && content.is_empty() && mode == "120000"`
19/// - `encoding == Some("base64")` ⟺ `content` contains non-UTF-8 bytes
20/// - `content.len() as u64 == size` for all regular files
21#[derive(Debug, Clone, PartialEq, Eq)]
22pub struct SnapshotFile {
23    pub path: String,
24    pub sha256: String,
25    pub mode: String,
26    pub size: u64,
27    pub encoding: Option<String>,
28    pub symlink_target: Option<String>,
29    pub content: Vec<u8>,
30}
31
32/// Parsed representation of the `;;`-comment header block at the top of a
33/// `.gcl` file.
34#[derive(Debug, Default, Clone, PartialEq, Eq)]
35pub struct SnapshotHeader {
36    pub snapshot_hash: String,
37    pub file_count: usize,
38    /// SHA-1 / SHA-256 revision captured from the source git repository at
39    /// build time.  Informational only — not included in `snapshot_hash`.
40    pub git_rev: Option<String>,
41    /// Short branch name captured from the source git repository at build time.
42    /// Informational only — not included in `snapshot_hash`.
43    pub git_branch: Option<String>,
44    /// Unknown `;; key: value` comments preserved for forward compatibility.
45    pub extra_headers: Vec<(String, String)>,
46}
47
48/// Options that influence which files are included in a snapshot build.
49#[derive(Debug, Clone, Default, PartialEq, Eq)]
50pub struct BuildOptions {
51    /// Include files not tracked by git (mirrors `git ls-files --others`).
52    pub include_untracked: bool,
53    /// Abort the build if the working tree is dirty (uncommitted changes).
54    pub require_clean: bool,
55    /// Optional provenance annotation for remote-origin snapshots.
56    ///
57    /// Stored as `(source_uri, source_provider)` and serialized into header
58    /// comments as `source-uri` and `source-provider`.
59    pub source_annotation: Option<(String, String)>,
60}
61
62/// Summary returned by [`crate::verify_snapshot`].
63#[derive(Debug, Clone, PartialEq, Eq)]
64pub struct VerifyReport {
65    pub file_count: usize,
66}
67
68/// A single entry returned by [`crate::list_snapshot`].
69#[derive(Debug, Clone, PartialEq, Eq)]
70pub struct ListEntry {
71    /// Slash-delimited path relative to the snapshot root.
72    pub path: String,
73    /// `true` for symlinks, `false` for regular files.
74    pub is_symlink: bool,
75    /// Symlink target string (only set when `is_symlink == true`).
76    pub symlink_target: Option<String>,
77    /// Hex-encoded SHA-256 of file content (empty for symlinks).
78    pub sha256: String,
79    /// Octal permission bits as a string (e.g. `"644"`, `"755"`, `"120000"`).
80    pub mode: String,
81    /// Byte size of file content (0 for symlinks).
82    pub size: u64,
83}
84
85/// Aggregated metadata derived from a snapshot file.
86#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
87pub struct SnapshotSummary {
88    pub snapshot_hash: String,
89    pub file_count: usize,
90    pub regular_count: usize,
91    pub symlink_count: usize,
92    pub total_bytes: u64,
93    pub git_rev: Option<String>,
94    pub git_branch: Option<String>,
95    pub largest_files: Vec<(String, u64)>,
96}