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}