Files
Nexus/scripts/check_worktree_eol.py
T
2026-07-08 22:31:31 +08:00

108 lines
2.7 KiB
Python

#!/usr/bin/env python3
"""Warn when the working tree has CR bytes but git index is LF-only.
Tarballs copied from Windows often have CRLF on disk while `git pull` on Ubuntu
deploys LF from the index. Run after unpack:
python3 scripts/check_worktree_eol.py
bash scripts/normalize_worktree_lf.sh # optional fix
"""
from __future__ import annotations
import subprocess
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
# Same critical paths as check_text_eol.py
PATTERNS = [
"*.sh",
"server/**/*.py",
"scripts/**/*.py",
"deploy/**/*.sh",
"docker/**/*.py",
"web/agent/**/*.py",
"frontend/src/**/*.vue",
"frontend/src/**/*.ts",
".cursor/rules/**/*.mdc",
]
def git_ls_files(pattern: str) -> list[str]:
r = subprocess.run(
["git", "ls-files", pattern],
cwd=ROOT,
capture_output=True,
text=True,
check=False,
)
return [p for p in r.stdout.splitlines() if p.strip()]
def index_has_cr(path: str) -> bool:
r = subprocess.run(
["git", "show", f":{path}"],
cwd=ROOT,
capture_output=True,
check=False,
)
return r.returncode == 0 and b"\r" in r.stdout
def worktree_has_cr(path: str) -> bool:
full = ROOT / path
if not full.is_file():
return False
return b"\r" in full.read_bytes()
def main() -> int:
seen: set[str] = set()
mismatch: list[str] = []
worktree_only: list[str] = []
for pattern in PATTERNS:
for path in git_ls_files(pattern):
if path in seen:
continue
seen.add(path)
wt = worktree_has_cr(path)
if not wt:
continue
if index_has_cr(path):
worktree_only.append(path)
else:
mismatch.append(path)
if not mismatch and not worktree_only:
print(f"check_worktree_eol: OK ({len(seen)} paths, working tree matches LF index)")
return 0
if mismatch:
print(
f"CRLF in working tree but LF in git index ({len(mismatch)} file(s)) — "
"bash/scripts may fail on Ubuntu:",
file=sys.stderr,
)
for p in sorted(mismatch)[:50]:
print(f" {p}", file=sys.stderr)
if len(mismatch) > 50:
print(f" ... and {len(mismatch) - 50} more", file=sys.stderr)
if worktree_only:
print(f"CR in both worktree and index ({len(worktree_only)} file(s)) — run check_text_eol.py", file=sys.stderr)
print(
"\nFix tracked files:\n"
" git config core.autocrlf false\n"
" bash scripts/normalize_worktree_lf.sh",
file=sys.stderr,
)
return 1
if __name__ == "__main__":
sys.exit(main())