의 미러
https://github.com/A6-9V/MQL5-Google-Onedrive.git
synced 2026-04-11 06:10:57 +00:00
Optimized `scripts/ci_validate_repo.py` for better performance and lower memory usage: - Combined NUL byte and size checks into a single pass over files. - Implemented chunked binary reading (64KB chunks) for NUL byte detection, avoiding full file loads into RAM. - Reused `stat()` results to minimize redundant system calls. - Added early exit for large files before performing content checks. These changes make the repository validation process faster and more efficient, especially in CI environments.
77 lines
2.2 KiB
Python
Executable file
77 lines
2.2 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
"""
|
|
Lightweight repository sanity checks suitable for GitHub Actions.
|
|
This is intentionally NOT a compiler for MQL5 (MetaEditor isn't available on CI).
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
|
|
REPO_ROOT = Path(__file__).resolve().parents[1]
|
|
MQL5_DIR = REPO_ROOT / "mt5" / "MQL5"
|
|
|
|
|
|
def fail(msg: str) -> None:
|
|
print(f"ERROR: {msg}", file=sys.stderr)
|
|
raise SystemExit(1)
|
|
|
|
|
|
def iter_source_files() -> list[Path]:
|
|
if not MQL5_DIR.exists():
|
|
fail(f"Missing directory: {MQL5_DIR}")
|
|
files: list[Path] = []
|
|
for p in MQL5_DIR.rglob("*"):
|
|
if p.is_file() and p.suffix.lower() in {".mq5", ".mqh"}:
|
|
files.append(p)
|
|
if not files:
|
|
fail(f"No .mq5/.mqh files found under {MQL5_DIR}")
|
|
return sorted(files)
|
|
|
|
|
|
def validate_files(files: list[Path]) -> None:
|
|
"""
|
|
⚡ Bolt: Optimized validation in a single pass.
|
|
Uses chunked reading to minimize memory footprint and stat() reuse.
|
|
"""
|
|
for p in files:
|
|
# 1. Size check (cheapest)
|
|
# Avoid redundant stat() calls by doing this first.
|
|
try:
|
|
sz = p.stat().st_size
|
|
except OSError as e:
|
|
fail(f"Could not stat {p.relative_to(REPO_ROOT)}: {e}")
|
|
|
|
if sz > 5_000_000:
|
|
fail(f"Unexpectedly large source file (>5MB): {p.relative_to(REPO_ROOT)} ({sz} bytes)")
|
|
|
|
# 2. NUL byte check (chunked to save memory)
|
|
# ⚡ Bolt: Reading in 64KB chunks is efficient and avoids loading huge files into RAM.
|
|
try:
|
|
with p.open("rb") as f:
|
|
while True:
|
|
chunk = f.read(65536)
|
|
if not chunk:
|
|
break
|
|
if b"\x00" in chunk:
|
|
fail(f"NUL byte found in {p.relative_to(REPO_ROOT)}")
|
|
except OSError as e:
|
|
fail(f"Could not read {p.relative_to(REPO_ROOT)}: {e}")
|
|
|
|
|
|
def main() -> int:
|
|
files = iter_source_files()
|
|
validate_files(files)
|
|
|
|
rel = [str(p.relative_to(REPO_ROOT)) for p in files]
|
|
print("OK: found source files:")
|
|
for r in rel:
|
|
print(f"- {r}")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|
|
|