Files
Nexus/scripts/check_text_eol.py
T

112 lines
2.9 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
"""Fail if git-indexed deploy-critical files contain CR (CRLF).
Checks blobs in the git index (what Ubuntu gets on git pull), not the working tree.
Usage:
python scripts/check_text_eol.py
python scripts/check_text_eol.py --fix-hint
"""
from __future__ import annotations
import argparse
import subprocess
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
# Paths that must be LF-only in the repository (Ubuntu bash / Python shebang)
GLOB_PATTERNS = [
"*.sh",
"server/**/*.py",
"deploy/**/*.py",
"scripts/**/*.py",
"web/agent/**/*.py",
"web/agent/**/*.json",
"tests/**/*.py",
"mcp/**/*.py",
"frontend/src/**/*.vue",
"frontend/src/**/*.ts",
"frontend/src/**/*.css",
"frontend/e2e/**/*.mjs",
".cursor/rules/**/*.mdc",
"web/agent/**/*.py",
".gitattributes",
".env.example",
"ruff.toml",
"requirements*.txt",
]
def git_ls_files(pattern: str) -> list[str]:
r = subprocess.run(
["git", "ls-files", pattern],
cwd=ROOT,
capture_output=True,
text=True,
check=False,
)
if r.returncode != 0:
return []
return [line for line in r.stdout.splitlines() if line.strip()]
def blob_has_cr(path: str) -> bool:
r = subprocess.run(
["git", "show", f":{path}"],
cwd=ROOT,
capture_output=True,
check=False,
)
if r.returncode != 0:
return False
return b"\r" in r.stdout
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
"--fix-hint",
action="store_true",
help="Print git renormalize commands on failure",
)
args = parser.parse_args()
if subprocess.run(["git", "rev-parse", "--is-inside-work-tree"], cwd=ROOT, capture_output=True).returncode != 0:
print("check_text_eol: not a git repository", file=sys.stderr)
return 1
seen: set[str] = set()
bad: list[str] = []
for pattern in GLOB_PATTERNS:
for path in git_ls_files(pattern):
if path in seen:
continue
seen.add(path)
if blob_has_cr(path):
bad.append(path)
bad.sort()
if bad:
print(f"CR byte in git index ({len(bad)} file(s)):", file=sys.stderr)
for p in bad:
print(f" {p}", file=sys.stderr)
if args.fix_hint:
print(
"\nFix:\n"
" git config core.autocrlf false\n"
" git add --renormalize '*.sh' 'server/' 'deploy/' 'scripts/' 'web/agent/' 'frontend/src/'\n"
" git commit -m 'chore: normalize line endings to LF'",
file=sys.stderr,
)
return 1
print(f"check_text_eol: OK ({len(seen)} tracked paths, LF-only in git index)")
return 0
if __name__ == "__main__":
sys.exit(main())