Option C Tools
Loading...
Searching...
No Matches
oct.git.commit_observer Namespace Reference

Functions

str _hash_file (Path path)
dict[str, str] snapshot_unstaged_tracked (Path repo_root, set[str]|None staged_set=None)
list[str] diff_snapshots (dict[str, str] before, dict[str, str] after)

Variables

int _MAX_HASH_BYTES = 10 * 1024 * 1024
str _OVERSIZE_SENTINEL = "OVERSIZE"
str _MISSING_SENTINEL = ""

Detailed Description

Purpose
-------
Detect silent mutations of tracked-but-unstaged files during the
``oct git commit`` pipeline (B1.0). Snapshots the working-tree state
of every tracked file outside the staged set at the start of the
commit, then compares again right before and right after the
underlying ``git commit`` invocation. Any byte-level change is
reported as either a warning or a hard abort, depending on the
``git.observe_unstaged_mutation`` octrc setting.

Responsibilities
----------------
- Provide :func:`snapshot_unstaged_tracked` — returns a mapping of
  project-relative path -> sha256 hex digest for every tracked file
  *not* in the staged set.
- Provide :func:`diff_snapshots` — returns the list of paths whose
  hash changed (new file, deleted file, or content drift) between two
  snapshots.
- Be defensive: large files (> :data:`_MAX_HASH_BYTES`) are recorded
  with the sentinel digest ``"OVERSIZE"`` so they don't dominate
  commit latency, and a missing/unreadable file maps to ``""`` so the
  diff path treats it consistently.

Diagnostics
-----------
Domain: GIT
Levels:
    L1 — errors: file IO failures during snapshot
    L2 — lifecycle: snapshot start / snapshot complete
    L3 — details: file count, total bytes hashed
    L4 — deep trace: per-file hash + size

Contracts
---------
- This module is pure: no Click, no subprocess of its own. It uses
  :func:`oct.core.git.git_run` to enumerate tracked files.
- Snapshot calls must never raise on individual-file IO errors —
  they record the file as unreadable and continue.
- The hash digest is content-only (no metadata). Renames are detected
  via the path key, not the digest.

Function Documentation

◆ _hash_file()

str oct.git.commit_observer._hash_file ( Path path)
protected
Return the sha256 hex digest of *path*, or a sentinel.

Returns :data:`_OVERSIZE_SENTINEL` when the file is larger than
:data:`_MAX_HASH_BYTES`, and :data:`_MISSING_SENTINEL` when the
file is missing or unreadable. Never raises.

Definition at line 69 of file commit_observer.py.

Here is the caller graph for this function:

◆ diff_snapshots()

list[str] oct.git.commit_observer.diff_snapshots ( dict[str, str] before,
dict[str, str] after )
Return the list of paths whose digest changed between snapshots.

Includes:
  - Paths present in both with different digests (mutation).
  - Paths present in *before* but missing from *after* (deletion or
    unreadable).
  - Paths newly tracked in *after* (rare; would only appear if
    ``git add`` ran during the commit pipeline).

A path with the same :data:`_OVERSIZE_SENTINEL` on both sides is
NOT flagged — we cannot tell whether the content of an oversize
file changed without a full hash. Document this caveat to the
caller via the per-file payload (omitted from the simple list
return; see :func:`diff_snapshots_detail` for the verbose form).

Definition at line 156 of file commit_observer.py.

◆ snapshot_unstaged_tracked()

dict[str, str] oct.git.commit_observer.snapshot_unstaged_tracked ( Path repo_root,
set[str] | None staged_set = None )
Return ``{rel_path: sha256_hex}`` for every tracked-but-unstaged file.

*repo_root* must be the actual git repository root (not the OCT
project root in monorepo layouts). *staged_set* is a set of
repo-relative path strings already in the index; those files are
excluded from the snapshot because their mutations are caller
intent, not silent regression.

The snapshot includes:
  - Tracked files that are clean (working tree == HEAD).
  - Tracked files modified but not staged (``M`` in
    ``git status -s`` second column).

The snapshot excludes:
  - Files in *staged_set*.
  - Untracked files (``??``).
  - Submodules and worktree symlinks pointing outside *repo_root*.

Definition at line 103 of file commit_observer.py.

Here is the call graph for this function:

Variable Documentation

◆ _MAX_HASH_BYTES

int oct.git.commit_observer._MAX_HASH_BYTES = 10 * 1024 * 1024
protected

Definition at line 59 of file commit_observer.py.

◆ _MISSING_SENTINEL

str oct.git.commit_observer._MISSING_SENTINEL = ""
protected

Definition at line 66 of file commit_observer.py.

◆ _OVERSIZE_SENTINEL

str oct.git.commit_observer._OVERSIZE_SENTINEL = "OVERSIZE"
protected

Definition at line 62 of file commit_observer.py.