MCPcopy Create free account
hub / github.com/anthropics/claude-code / get_git_diff

Function get_git_diff

plugins/security-guidance/hooks/gitutil.py:391–427  ·  view source on GitHub ↗

Get the git diff between the baseline SHA and the current working tree, including untracked (new) files. Uses a temporary copy of the git index (GIT_INDEX_FILE) so the user's real index is never modified. The temp index gets intent-to-add entries for untracked files, making the

(cwd, baseline_sha, full_context=False, paths=None, untracked_paths=None)

Source from the content-addressed store, hash-verified

389
390
391def get_git_diff(cwd, baseline_sha, full_context=False, paths=None, untracked_paths=None):
392 """
393 Get the git diff between the baseline SHA and the current working tree,
394 including untracked (new) files.
395
396 Uses a temporary copy of the git index (GIT_INDEX_FILE) so the user's
397 real index is never modified. The temp index gets intent-to-add entries
398 for untracked files, making them visible in the diff output. Cleanup
399 is just deleting the temp file in a finally block.
400
401 If `paths` is given, the diff is restricted to those paths (relative to
402 cwd; absolute paths are converted, paths outside cwd are dropped).
403 `untracked_paths` (repo-root-relative) is forwarded to _temp_index so it
404 can add only those files instead of scanning the whole worktree.
405 """
406 pathspec = _diff_pathspec(cwd, paths)
407 if paths and not pathspec:
408 # Caller restricted to specific paths but none are inside this repo
409 # (e.g. only ~/.claude/... edits). Returning "" flows to skip(6); an
410 # empty pathspec would mean an UNRESTRICTED diff — the bug this whole
411 # change exists to fix.
412 return ""
413
414 cmd = [*GIT_CMD, "diff", "--no-color", "--no-ext-diff", baseline_sha] + (["--unified=99999"] if full_context else []) + pathspec
415 try:
416 with _temp_index(cwd, untracked_paths) as env:
417 # env is None when no index could be found (bare repo / not a
418 # repo) — diff still runs, just without untracked-file support.
419 result = subprocess.run(cmd, cwd=cwd, capture_output=True, timeout=30, env=env)
420 if result.returncode != 0:
421 debug_log(f"git diff failed: {result.stderr[:200].decode('utf-8', errors='replace')}")
422 return None
423 # Decode with errors='replace' so binary diffs don't crash
424 return result.stdout.decode("utf-8", errors="replace")
425 except (subprocess.TimeoutExpired, FileNotFoundError, OSError) as e:
426 debug_log(f"git diff error: {e}")
427 return None
428
429
430# Source file extensions worth reviewing for security

Callers 1

handle_stop_hookFunction · 0.90

Calls 3

debug_logFunction · 0.90
_diff_pathspecFunction · 0.85
_temp_indexFunction · 0.85

Tested by

no test coverage detected