|
Option C Tools
|
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 = "" |
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.
|
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.
| 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.
| 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.
|
protected |
Definition at line 59 of file commit_observer.py.
|
protected |
Definition at line 66 of file commit_observer.py.
|
protected |
Definition at line 62 of file commit_observer.py.