crate-seq-git
Overview
crate-seq-git provides a pure-Rust git interface via gix for tag discovery, tree checkout, annotated tag creation/deletion, and tag date extraction. It is consumed primarily by crate-seq-core for version discovery and source resolution.
Tag discovery — discover.rs
discover_tags
pub fn discover_tags(
repo_path: &Path,
pattern: &str,
) -> Result<Vec<TagRef>, Error>Discovers all git tags in repo_path matching pattern and parses their SemVer. Tags that don't match or whose suffix fails semver::Version::parse are silently skipped. Results are sorted ascending by SemVer.
TagRef
pub struct TagRef {
pub name: String, // e.g. "v1.0.3" or "foo-v1.0.3"
pub semver: semver::Version,
}Tree checkout — checkout.rs
checkout_tag
pub fn checkout_tag(
repo_path: &Path,
tag_name: &str,
) -> Result<tempfile::TempDir, Error>Checks out the tree of tag_name into a fresh temporary directory. Only git-tracked files at the tagged commit's tree are written. The TempDir is cleaned up on drop.
Symlinks and submodules are skipped (unsupported in v1). Blobs and executable blobs are written as regular files; subtrees become directories.
Tag creation & deletion — tag_create.rs
create_annotated_tag
pub fn create_annotated_tag(
repo_path: &Path,
tag_name: &str,
version: &semver::Version,
) -> Result<(), Error>Creates an annotated git tag at HEAD via the git subprocess. Tag message is "crate-seq: version {version}". Returns Error::TagCreate if the subprocess exits non-zero, Error::TempDir if it cannot be spawned.
delete_tag
pub fn delete_tag(
repo_path: &Path,
tag_name: &str,
) -> Result<(), Error>Deletes a tag from the repository. Used for rollback if a ledger write succeeds but subsequent tag creation fails. Same error behavior as create_annotated_tag.
Why subprocess?
Tag creation and deletion use the git CLI rather than gix because annotated tag creation with custom messages is simpler via the subprocess. Discovery and checkout use gix for performance and no-subprocess safety.
Tag date extraction — date.rs
tag_date
pub fn tag_date(
repo_path: &Path,
tag_name: &str,
) -> Result<chrono::DateTime<chrono::Utc>, Error>Resolves the author/tagger timestamp for tag_name:
- Annotated tags → returns the tagger date from the tag object's
taggerfield - Lightweight tags (pointing directly to a commit) → returns the committer date
- Other object types → peels to commit and uses committer time as fallback
Returns Error::TagNotFound if the tag doesn't exist, Error::Object if the timestamp cannot be decoded or produces an invalid timestamp_opt.
Error type — error.rs
#[derive(Debug, thiserror::Error)]
pub enum Error {
OpenRepo { path: PathBuf, source: Box<gix::discover::Error> },
References(#[from] gix::reference::iter::Error),
ReferencesInit(#[from] gix::reference::iter::init::Error),
Peel(String),
TagObject(String),
TagNotFound(String),
Object(String),
TreeTraversal(String),
TempDir(#[from] std::io::Error),
TagCreate(String),
}Key design choices:
OpenRepowraps thegix::discover::Errorin aBoxto keep the enum size smallReferencesandReferencesInituse#[from]for automatic conversion- String-based variants (
Peel,Object,TreeTraversal,TagCreate) are used where the upstream error types are notSend/Syncor are too complex to wrap
Source files
| File | Responsibility |
|---|---|
discover.rs |
Tag discovery with glob-pattern filtering and SemVer parsing |
checkout.rs |
Temp-directory tree checkout via recursive tree walking |
tag_create.rs |
Annotated tag creation and deletion via git subprocess |
date.rs |
Tag date extraction from annotated and lightweight tags |
error.rs |
Crate error enum |
lib.rs |
Module declarations and re-exports |