Skip to main content

shipper_core/ops/git/
mod.rs

1//! Git repository operations (cleanliness, context capture).
2//!
3//! Absorbed into `crate::ops::git` from the standalone `shipper-git` microcrate.
4//! The facade is re-exported at `shipper::git` (see `lib.rs`) so external
5//! consumers keep using the historical `shipper::git::*` public API.
6//!
7//! Split:
8//!
9//! - [`cleanliness`] — `is_git_clean` + `ensure_git_clean`, routing through
10//!   [`bin_override`] when `SHIPPER_GIT_BIN` is set.
11//! - [`context`] — commit/branch/tag/changed-files/remote queries + the
12//!   [`collect_git_context`] aggregator.
13//! - [`bin_override`] — parallel helpers that honor `SHIPPER_GIT_BIN`.
14//!
15//! See `CLAUDE.md` in this folder for architectural rules.
16
17use std::env;
18
19pub(crate) mod bin_override;
20pub(crate) mod cleanliness;
21pub(crate) mod context;
22
23// Public-to-crate API re-exports; reachable via `shipper::git::*` through the
24// façade module in `lib.rs`.
25pub use cleanliness::{ensure_git_clean, is_git_clean};
26
27use crate::types::GitContext;
28
29/// Collect a [`GitContext`] for the current working directory.
30///
31/// Returns `None` when the CWD is not inside a git repository.
32///
33/// When `SHIPPER_GIT_BIN` is set, every sub-query is routed through the
34/// `bin_override` helpers — there is no silent fallback to the default
35/// `git` binary. Without the override, queries go through `context`.
36pub fn collect_git_context() -> Option<GitContext> {
37    let repo_root = std::env::current_dir().ok()?;
38
39    let git_program = bin_override::git_program();
40    if !bin_override::is_repo_root(&repo_root, &git_program) {
41        return None;
42    }
43
44    if env::var("SHIPPER_GIT_BIN").is_ok() {
45        let commit = bin_override::get_git_commit(&repo_root, &git_program);
46        let branch = bin_override::get_git_branch(&repo_root, &git_program);
47        let tag = bin_override::get_git_tag(&repo_root, &git_program);
48        let dirty = bin_override::get_git_dirty_status(&repo_root, &git_program);
49        return Some(GitContext {
50            commit,
51            branch,
52            tag,
53            dirty,
54        });
55    }
56
57    if !context::is_git_repo(&repo_root) {
58        return None;
59    }
60
61    Some(context::get_git_context(&repo_root))
62}