git_meta_lib/lib.rs
1//! # gmeta
2//!
3//! A library for storing and exchanging structured metadata in Git repositories.
4//! This is the reference implementation of the [gmeta spec](https://git-meta.com/).
5//!
6//! ## Core Concepts
7//!
8//! gmeta attaches key-value metadata to **targets** in a Git project:
9//!
10//! - **Commits** — attach agent info, review status, provenance to specific commits
11//! - **Paths** — attach code ownership, agent rules to directories or files
12//! - **Branches** — attach review comments, CI status to branches
13//! - **Change IDs** — attach metadata to logical changesets (for tools like Jujutsu)
14//! - **Project** — global project-wide metadata (configuration, ownership)
15//!
16//! Values can be **strings** (single values), **lists** (ordered, append-friendly),
17//! or **sets** (unordered, unique members).
18//!
19//! ## Quick Start
20//!
21//! ```no_run
22//! use git_meta_lib::{Session, Target, MetaValue};
23//!
24//! // Open a session for the current git repository
25//! let session = Session::discover()?;
26//!
27//! // Write metadata
28//! let commit = session.target(&Target::commit("abc123")?);
29//! commit.set("agent:model", "claude-4.6")?;
30//! commit.set("review:status", "approved")?;
31//!
32//! // Read metadata
33//! if let Some(model) = commit.get_value("agent:model")? {
34//! println!("Model: {model}");
35//! }
36//!
37//! // Sync with remote
38//! session.serialize()?;
39//! session.push_once(None)?;
40//! # Ok::<(), git_meta_lib::Error>(())
41//! ```
42//!
43//! If you already have a [`gix::Repository`] (e.g. in a host application like
44//! GitButler), clone it cheaply and pass it in:
45//!
46//! ```no_run
47//! # use git_meta_lib::Session;
48//! let repo = gix::open(".")?;
49//! let session = Session::open(repo.clone())?;
50//! // `repo` is still fully usable here
51//! # Ok::<(), Box<dyn std::error::Error>>(())
52//! ```
53//!
54//! ## Data Exchange
55//!
56//! Metadata is stored locally in SQLite for fast reads/writes, and exchanged
57//! via Git's object format and transfer protocols:
58//!
59//! - [`Session::serialize()`] writes local metadata to a Git tree and commit
60//! - [`Session::materialize()`] reads remote metadata and merges it locally
61//! - [`Session::pull()`] fetches + materializes in one step
62//! - [`Session::push_once()`] serializes + pushes to the remote
63//!
64//! The exchange format uses Git trees with a deterministic path layout, enabling
65//! standard Git merge strategies. See the [spec](https://git-meta.com/)
66//! for the full format description.
67//!
68//! ## Blobless Clone Support
69//!
70//! For large metadata histories (e.g., AI transcripts), gmeta supports Git's
71//! partial/blobless clone feature. Only tree objects are fetched initially;
72//! blob data is fetched on demand when accessed. The [`Session::pull()`] method
73//! automatically indexes historical keys for lazy loading.
74
75/// Typed error types for all gmeta operations.
76pub mod error;
77
78/// The library entry point: a session combining a git repo with a metadata store.
79pub mod session;
80/// Session-scoped target handle with automatic email and timestamp.
81pub mod session_handle;
82/// Core metadata types: targets, value types, and path-building helpers.
83pub mod types;
84
85// Modules that are `pub(crate)` by default, `pub` with the `internal` feature.
86// The CLI enables this feature; library consumers do not.
87
88#[cfg(not(feature = "internal"))]
89pub(crate) mod db;
90#[cfg(feature = "internal")]
91pub mod db;
92
93#[cfg(not(feature = "internal"))]
94pub(crate) mod git_utils;
95#[cfg(feature = "internal")]
96pub mod git_utils;
97
98#[cfg(not(feature = "internal"))]
99pub(crate) mod list_value;
100#[cfg(feature = "internal")]
101pub mod list_value;
102
103#[cfg(not(feature = "internal"))]
104pub(crate) mod materialize;
105#[cfg(feature = "internal")]
106pub mod materialize;
107
108#[cfg(not(feature = "internal"))]
109pub(crate) mod prune;
110#[cfg(feature = "internal")]
111pub mod prune;
112
113#[cfg(not(feature = "internal"))]
114pub(crate) mod pull;
115#[cfg(feature = "internal")]
116pub mod pull;
117
118#[cfg(not(feature = "internal"))]
119pub(crate) mod push;
120#[cfg(feature = "internal")]
121pub mod push;
122
123#[cfg(not(feature = "internal"))]
124pub(crate) mod serialize;
125#[cfg(feature = "internal")]
126pub mod serialize;
127
128#[cfg(not(feature = "internal"))]
129pub(crate) mod sync;
130#[cfg(feature = "internal")]
131pub mod sync;
132
133#[cfg(not(feature = "internal"))]
134pub(crate) mod tree;
135#[cfg(feature = "internal")]
136pub mod tree;
137
138#[cfg(not(feature = "internal"))]
139pub(crate) mod tree_paths;
140#[cfg(feature = "internal")]
141pub mod tree_paths;
142
143// Public API re-exports: these are visible regardless of feature flags.
144// The `pub use` makes specific types public even when the source module
145// is `pub(crate)`.
146
147pub use error::{Error, Result};
148pub use list_value::ListEntry;
149pub use session::Session;
150pub use session_handle::SessionTargetHandle;
151pub use types::{MetaValue, Target, TargetType, ValueType};
152
153// Workflow output types
154pub use materialize::{MaterializeOutput, MaterializeRefResult, MaterializeStrategy};
155pub use pull::PullOutput;
156pub use push::PushOutput;
157pub use serialize::SerializeOutput;