feat: strengthen BSP and PSP validation and handoff
This commit is contained in:
1 parent
bcea35a91e
commit
1641fac631
39 files changed
+2695
-90
No files matched your search
@@ -87,10 +87,33 @@ def under(path: Path, root: Path) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
def iter_regular_files(root: Path) -> Iterator[Path]:
|
||||
"""Yield repository files without following runtime or Git directory links."""
|
||||
for current, dirnames, filenames in os.walk(root, followlinks=False):
|
||||
current_path = Path(current)
|
||||
dirnames[:] = sorted(
|
||||
name
|
||||
for name in dirnames
|
||||
if name != ".git" and not (current_path / name).is_symlink()
|
||||
)
|
||||
for name in sorted(filenames):
|
||||
path = current_path / name
|
||||
if path.is_symlink() or not path.is_file():
|
||||
continue
|
||||
yield path
|
||||
|
||||
|
||||
def probe_path_exists(path: Path) -> tuple[bool, str | None]:
|
||||
try:
|
||||
return path.exists(), None
|
||||
except OSError as exc:
|
||||
return False, str(exc)
|
||||
|
||||
|
||||
def collect_json(root: Path, errors: list[str]) -> dict[str, Any]:
|
||||
payloads: dict[str, Any] = {}
|
||||
for path in sorted(root.rglob("*.json")):
|
||||
if ".git" in path.parts:
|
||||
for path in iter_regular_files(root):
|
||||
if path.suffix.lower() != ".json":
|
||||
continue
|
||||
relative = path.relative_to(root).as_posix()
|
||||
try:
|
||||
@@ -102,8 +125,8 @@ def collect_json(root: Path, errors: list[str]) -> dict[str, Any]:
|
||||
|
||||
def validate_ini(root: Path, errors: list[str]) -> int:
|
||||
count = 0
|
||||
for path in sorted(root.rglob("*.ini")):
|
||||
if ".git" in path.parts:
|
||||
for path in iter_regular_files(root):
|
||||
if path.suffix.lower() != ".ini":
|
||||
continue
|
||||
parser = configparser.ConfigParser(interpolation=None, strict=False)
|
||||
try:
|
||||
@@ -200,11 +223,9 @@ def validate_sensor_baseline(
|
||||
errors.append("非 CV181X/CV184X 项目不应提供 CV18 Sensor 枚举校验参数")
|
||||
return result
|
||||
|
||||
candidates = sorted(
|
||||
path
|
||||
for path in psp_root.rglob("sensor_cfg.ini")
|
||||
if ".git" not in path.parts and path.is_file() and not path.is_symlink()
|
||||
)
|
||||
candidates = [
|
||||
path for path in iter_regular_files(psp_root) if path.name == "sensor_cfg.ini"
|
||||
]
|
||||
if len(candidates) != 1:
|
||||
errors.append(
|
||||
f"CV18 PSP 必须唯一定位一个 sensor_cfg.ini,实际 {len(candidates)} 个"
|
||||
@@ -320,8 +341,8 @@ def validate_sensor_baseline(
|
||||
|
||||
def validate_shell(root: Path, errors: list[str]) -> int:
|
||||
count = 0
|
||||
for path in sorted(root.rglob("*.sh")):
|
||||
if ".git" in path.parts:
|
||||
for path in iter_regular_files(root):
|
||||
if path.suffix.lower() != ".sh":
|
||||
continue
|
||||
result = subprocess.run(
|
||||
["bash", "-n", str(path)],
|
||||
@@ -346,12 +367,9 @@ def path_risk(path: Path) -> str | None:
|
||||
|
||||
|
||||
def text_absolute_paths(root: Path) -> Iterator[tuple[str, str, str]]:
|
||||
for path in sorted(root.rglob("*")):
|
||||
for path in iter_regular_files(root):
|
||||
if (
|
||||
not path.is_file()
|
||||
or path.is_symlink()
|
||||
or ".git" in path.parts
|
||||
or path.suffix.lower() not in TEXT_PATH_SUFFIXES
|
||||
path.suffix.lower() not in TEXT_PATH_SUFFIXES
|
||||
or path.stat().st_size > 4 * 1024 * 1024
|
||||
):
|
||||
continue
|
||||
@@ -409,7 +427,7 @@ def validate_absolute_paths(
|
||||
continue
|
||||
seen.add(key)
|
||||
path = Path(value).resolve(strict=False)
|
||||
exists = path.exists()
|
||||
exists, access_error = probe_path_exists(path)
|
||||
allowed_by = next((item for item in normalized_allowed if under(path, item)), None)
|
||||
risk_root = None if allowed_by is not None else path_risk(path)
|
||||
build_input = source in BUILD_INPUT_JSONS
|
||||
@@ -419,12 +437,19 @@ def validate_absolute_paths(
|
||||
"path": value,
|
||||
"resolved_path": str(path),
|
||||
"exists": exists,
|
||||
"access_error": access_error,
|
||||
"build_input": build_input,
|
||||
"allowed_by": str(allowed_by) if allowed_by else None,
|
||||
"personal_or_temporary_root": risk_root,
|
||||
}
|
||||
entries.append(entry)
|
||||
if not exists:
|
||||
if access_error:
|
||||
message = (
|
||||
f"外部绝对路径无法在当前主机检查 {source}:{location}: "
|
||||
f"{value}: {access_error}"
|
||||
)
|
||||
(errors if build_input else warnings).append(message)
|
||||
elif not exists:
|
||||
message = f"外部绝对路径不存在 {source}:{location}: {value}"
|
||||
if build_input:
|
||||
errors.append(f"外部绝对路径不存在 {source}:{location}: {value}")
|
||||
@@ -503,7 +528,7 @@ def scan_overrides(
|
||||
if not psp_dir.is_dir():
|
||||
errors.append(f"PSP 配置目录不存在: {psp_dir}")
|
||||
continue
|
||||
for app_path in sorted(path for path in app_dir.rglob("*") if path.is_file()):
|
||||
for app_path in iter_regular_files(app_dir):
|
||||
relative = app_path.relative_to(app_dir)
|
||||
psp_path = psp_dir / relative
|
||||
if not psp_path.is_file():
|
||||
@@ -533,6 +558,10 @@ def scan_overrides(
|
||||
|
||||
|
||||
def build_bsp_lock(dependency: dict[str, object], warnings: list[str]) -> dict[str, object]:
|
||||
permissions = dependency.get("output_permissions")
|
||||
permissions = permissions if isinstance(permissions, dict) else {}
|
||||
live_check = permissions.get("current_check")
|
||||
live_check = live_check if isinstance(live_check, dict) else {}
|
||||
return {
|
||||
"schema_version": 1,
|
||||
"handoff_path": dependency.get("manifest_path"),
|
||||
@@ -548,6 +577,13 @@ def build_bsp_lock(dependency: dict[str, object], warnings: list[str]) -> dict[s
|
||||
"imgs_version_path": dependency.get("imgs_version_path"),
|
||||
"artifacts": dependency.get("artifacts", []),
|
||||
"image_partition_margin": dependency.get("image_partition_margin"),
|
||||
"output_permissions": {
|
||||
"policy": permissions.get("policy"),
|
||||
"evidence_path": dependency.get("output_permissions_path"),
|
||||
"output_root": permissions.get("output_root"),
|
||||
"imgs_version_path": permissions.get("imgs_version_path"),
|
||||
"passed": live_check.get("passed") is True,
|
||||
},
|
||||
"mixed_build": None,
|
||||
"warnings": warnings,
|
||||
}
|
||||
@@ -736,6 +772,7 @@ def validate_psp(
|
||||
expected_sdk=expected_bsp_sdk,
|
||||
expected_build_type=expected_build_type,
|
||||
expected_system_form=expected_system_form,
|
||||
repair_output_permissions=True,
|
||||
)
|
||||
if bsp_result.get("passed") is not True:
|
||||
errors.extend(f"BSP handoff: {item}" for item in bsp_result.get("errors", []))
|
||||
|
||||
Reference in new issue
Block a user