Skip to main content

is_git_oid

Function is_git_oid 

Source
pub fn is_git_oid(s: &str) -> Result<(), String>
Expand description

Predicate: assert that s is a valid Git commit OID — the canonical shape the typed :fonte (:tipo git …) :rev axis carries. The reproducibility contract :rev carries vs. :tag / :branch (CAIXA-SDLC §V — Substrate; :tag resolves to whatever the upstream has tagged today, :branch to whatever the upstream’s HEAD points at today, :rev to exactly one immutable commit forever — same shape Unison’s content-addressed code identity gives terms by construction: the hash is the address, the address never moves):

  • exactly GIT_OID_SHA1_LEN (40, SHA-1) or GIT_OID_SHA256_LEN (64, SHA-256) characters — the two canonical Git hash-algorithm widths; anything in between is an abbreviated prefix (the canonical git log --short / git rev-parse --short HEAD paste-from-release-notes footgun), which is ambiguous across repository history and surfaces at clone time as an ambiguous argument error far from the source caixa.lisp;
  • every byte in [0-9a-f] (lowercase ASCII hex) — git rev-parse and git show --format=%H both emit lowercase exclusively, so an uppercase-bearing :rev round-trips inconsistently across the resolver’s git fetch <remote> <:rev>git rev-parse HEAD equality-check pipeline and fails the lacre’s content-addressing equality probe with a confusing case-only diff;
  • no whitespace, no control bytes, no non-ASCII, no refname punctuation (~ ^ : ? * [ \), no / separators — every character outside [0-9a-f] is rejected on the same predicate arm, so a :rev "main" (the canonical “I conflated :rev and :branch” footgun) lands at the same gate as a :rev "v0.1.0" (:tag mis-slot) or a :rev "c0ffee:scratch" (refname-shape leak); the typed :rev slot’s valid set intersects the :tag / :branch slot’s valid set at exactly the empty set, structurally — every refname is rejected here, every OID is rejected by is_git_ref_name.
  • not the all-zero null-OID sentinel ("0000…0000" — 40 zeros at SHA-1 width, 64 zeros at SHA-256 width). Git reserves this value as the “no commit” sentinel in git update-ref / pre-receive hook flows (<old-value> for create, <new-value> for delete) and no commit in any object database has this OID, so a :rev "0000…0000" is structurally impossible to resolve. The canonical “I copy-pasted the sentinel out of git update-ref --stdin docs / pre-receive hook example” footgun would otherwise pass every other shape arm (canonical length, lowercase hex) and surface at git fetch <remote> 0000…0000 time with a quoting-confused “couldn’t find remote ref” error far from the source caixa.lisp, with the lacre’s content- address locked to a git:0000…0000 closure that never equals any upstream’s actual HEAD. Mirrors is_git_ref_name’s canonical-OID-shape pre-emption arm (line 1322) — both predicates carry one self-aware arm that catches values structurally valid for the alphabet but operationally meaningless on the typed axis.

Returns the parser-shaped reason on rejection (without wrapping in any error variant) so each per-axis caller — crate::DepError::FontePinShape at validate time on the :fonte :rev axis, the future per-pin gate on lacre.lisp resolved-rev axes, the future M4 per-dep CR materializer’s per-pin validator — wraps the same reason in its own typed *Invalid { axis, reason } variant. The reason wording is axis-agnostic (“git commit OIDs are lowercase hex ([0-9a-f])”) so every call site reading the same diagnostic points at the same rule.

Empty input is rejected here (defensively) and at each call site via the narrower crate::DepError::FontePinEmpty variant — the same empty-first cascade is_dns_1123_label, is_gateway_api_http_path, is_wit_world_ref, is_nats_subject, is_wasi_keyvalue_slot, and is_git_ref_name all carry.

Sibling of is_git_ref_name: the two predicates together bracket the :fonte pin axes — refname-shaped (:tag / :branch) vs. hex-OID-shaped (:rev) — so an authored value lands in exactly one of the two valid sets, and a cross-axis mis-slot (:rev "main" / :tag "deadbeef…") is a build error at the offending axis’s predicate, not a clone-time surprise.

§Errors

Returns the parser-shaped reason naming the specific violation (length / character-class), without wrapping in any error variant — every caller maps the same String into its own typed *Invalid { axis, reason } enum variant.