Real git subprocess wrapper for ancestor/ahead-behind containment evidence.
A small, real wrapper (subprocess-based, real git calls -- Chicago
discipline, no libgit2 binding needed for this scope): ancestor?/2 (is
commit A an ancestor of ref B), ahead_behind/2 (returns
%{ahead: n, behind: n} for two refs, matching the "55 commits ahead, 0
behind" shape every receipt reports), and containment_receipt/3 (base,
qualified_head, final_ref -- returns a receipted map combining both checks,
directly usable as evidence in a caller's own standing computation).
No algorithm is reimplemented here -- every call shells out to the real
git binary and parses its real output. Classification: pat-wrapper-over-
collaborator (matching beam4pm's own BeamPM.Petgraph/Tract/Rust4pm
precedent).
Summary
Functions
Returns %{ahead: n, behind: n} for base_ref...target_ref, computed from
a real git rev-list --left-right --count <base_ref>...<target_ref> call
in opts[:cwd] (default File.cwd!()).
Returns true if commit is a real ancestor of ref, false if it is
not. Runs git merge-base --is-ancestor <commit> <ref> in opts[:cwd]
(default File.cwd!()).
Combines ancestor?/2 and ahead_behind/2 into one real evidence map,
directly usable as evidence in a caller's own standing computation.
Functions
@spec ahead_behind(String.t(), String.t(), keyword()) :: %{ ahead: non_neg_integer(), behind: non_neg_integer() }
Returns %{ahead: n, behind: n} for base_ref...target_ref, computed from
a real git rev-list --left-right --count <base_ref>...<target_ref> call
in opts[:cwd] (default File.cwd!()).
Matches git's own --left-right semantics for base...target: the left
(base-only) count is behind, the right (target-only) count is ahead.
Returns true if commit is a real ancestor of ref, false if it is
not. Runs git merge-base --is-ancestor <commit> <ref> in opts[:cwd]
(default File.cwd!()).
Exit code 0 means ancestor (true); exit code 1 means not-an-ancestor
(false) -- both are well-defined outcomes per git-merge-base(1). Any
other exit code (e.g. one of the refs does not exist) raises, since that is
a real git error and must never be silently coerced to false.
Combines ancestor?/2 and ahead_behind/2 into one real evidence map,
directly usable as evidence in a caller's own standing computation.
contained is true iff qualified_head is a real ancestor of
final_ref AND ahead_behind(qualified_head, final_ref).behind == 0
(i.e. nothing on qualified_head is missing from final_ref).