def changes(*, files=None, staged=False, context=3, max_bytes=200_000, clip=False):
"""
Returns a unified diff of all recent textual changes in the git repo.
- Shows added/removed lines (ignores binary files).
- Includes unstaged (working directory) by default. Use staged=True to see only staged.
- 'files': Optionally filter by path(s) or file glob(s).
- 'context': Number of context lines in the diff (default 3).
- 'max_bytes': Truncate diff if too large (default 200,000).
"""
import subprocess
cmd = ["git", "diff", "--unified=%d" % context]
if staged:
cmd.insert(2, "--staged")
if files:
if isinstance(files, str):
files = [files]
cmd += list(files)
try:
diff = subprocess.check_output(cmd, encoding="utf-8", errors="replace")
except subprocess.CalledProcessError as e:
return f"[ERROR] Unable to get git diff: {e}"
except FileNotFoundError:
return "[ERROR] git command not found. Are you in a git repo?"
# Remove any diff blocks for binary files
filtered = []
skip = False
for line in diff.splitlines(keepends=True):
# Exclude blocks marking a binary difference
if line.startswith("Binary files "):
continue
if line.startswith("diff --git"):
skip = False # new file block
if "GIT binary patch" in line:
skip = True
if skip:
continue
filtered.append(line)
result = "".join(filtered)
if len(result) > max_bytes:
return result[:max_bytes] + "\n[...Diff truncated at %d bytes...]" % max_bytes
if clip:
gw.clip.copy(result)
if not gw.silent:
return result or "[No changes detected]"