1
0
포크 0
MQL5-Google-Onedrive/scripts/ci_validate_repo.py
google-labs-jules[bot] e20653c44f Bolt: optimize repository validation with single-pass chunked reading
Optimized `scripts/ci_validate_repo.py` to improve memory efficiency and execution speed:
1. Combined separate file-scanning passes into a single `validate_files` function.
2. Implemented early size check via `p.stat().st_size` to fail immediately on large files before reading.
3. Switched from `read_bytes()` to chunked binary reading (64KB) to ensure constant memory footprint regardless of file size.
4. Added robust error handling for file access.

These changes prevent the validator from loading large files into memory and reduce redundant I/O operations.
2026-02-18 17:35:29 +00:00

69 lines
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: Single-pass validation for size and NUL bytes with chunked reading."""
for p in files:
# ⚡ Bolt: Check size via stat() first to avoid reading large files into memory.
sz = p.stat().st_size
if sz > 5_000_000:
fail(f"Unexpectedly large source file (>5MB): {p.relative_to(REPO_ROOT)} ({sz} bytes)")
# ⚡ Bolt: Use chunked binary reading (64KB) to detect NUL bytes.
# This keeps memory usage constant regardless of file size.
try:
with open(p, 'rb') as f:
while True:
chunk = f.read(64 * 1024)
if not chunk:
break
if b"\x00" in chunk:
fail(f"NUL byte found in {p.relative_to(REPO_ROOT)}")
except Exception as e:
fail(f"Failed to 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())