-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgit_integration.py
More file actions
66 lines (51 loc) · 2.04 KB
/
Copy pathgit_integration.py
File metadata and controls
66 lines (51 loc) · 2.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
"""Thin wrappers around `git` for scanning what's about to be committed, not the working tree."""
import subprocess
from dataclasses import dataclass
class NotAGitRepositoryError(RuntimeError):
pass
@dataclass(frozen=True)
class StagedFile:
path: str
content: str
def _run_git(args: list[str], cwd: str) -> str:
result = subprocess.run(
["git", *args],
cwd=cwd,
capture_output=True,
text=True,
encoding="utf-8",
errors="replace",
)
if result.returncode != 0:
raise NotAGitRepositoryError(result.stderr.strip() or f"git {' '.join(args)} failed")
return result.stdout
def repository_root(start_dir: str) -> str:
return _run_git(["rev-parse", "--show-toplevel"], cwd=start_dir).strip()
def index_file_content(repo_root: str, path: str) -> str | None:
"""Returns a path's content as staged in the git index, or None if it isn't in the index.
Lets `--staged` read configuration (the `.credscanignore` allowlist) from the same place it
reads scanned content: an untracked or unstaged file appears in no diff, so honouring the
working-tree copy would let a suppression take effect without ever being reviewable.
"""
try:
return _run_git(["show", f":{path}"], cwd=repo_root)
except NotAGitRepositoryError:
return None
def staged_files(repo_root: str) -> list[StagedFile]:
"""Returns each staged file's path and its *staged* content (the git index blob), not the
working-tree copy — that's what will actually land in the commit."""
names = [
name
for name in _run_git(
["diff", "--cached", "--name-only", "--diff-filter=ACM"], cwd=repo_root
).splitlines()
if name
]
files = []
for name in names:
try:
content = _run_git(["show", f":{name}"], cwd=repo_root)
except NotAGitRepositoryError:
continue # e.g. a staged submodule pointer or a path git show can't blob
files.append(StagedFile(path=name, content=content))
return files