124 lines
3.2 KiB
Python
124 lines
3.2 KiB
Python
#!/usr/bin/env python3
|
|
"""Reject UI, Windows, SQLite, and app-layer imports from the core module."""
|
|
|
|
import json
|
|
import os
|
|
import pathlib
|
|
import subprocess
|
|
import sys
|
|
|
|
|
|
FORBIDDEN_IMPORT_PREFIXES = (
|
|
"gioui.org",
|
|
"golang.org/x/sys/windows",
|
|
"github.com/mattn/go-sqlite3",
|
|
"modernc.org/sqlite",
|
|
"softbox.local/app-modern",
|
|
"softbox.local/app-win7",
|
|
)
|
|
|
|
|
|
def is_forbidden(import_path):
|
|
return any(
|
|
import_path == prefix or import_path.startswith(prefix + "/")
|
|
for prefix in FORBIDDEN_IMPORT_PREFIXES
|
|
)
|
|
|
|
|
|
def decode_json_stream(text):
|
|
decoder = json.JSONDecoder()
|
|
index = 0
|
|
while index < len(text):
|
|
while index < len(text) and text[index].isspace():
|
|
index += 1
|
|
if index >= len(text):
|
|
return
|
|
value, index = decoder.raw_decode(text, index)
|
|
yield value
|
|
|
|
|
|
def list_core_packages(repo_root):
|
|
environment = os.environ.copy()
|
|
environment["GOWORK"] = "off"
|
|
result = subprocess.run(
|
|
["go", "list", "-json", "./..."],
|
|
cwd=str(repo_root / "core"),
|
|
env=environment,
|
|
check=False,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE,
|
|
universal_newlines=True,
|
|
)
|
|
if result.returncode != 0:
|
|
print(result.stderr, file=sys.stderr, end="")
|
|
raise SystemExit(result.returncode)
|
|
return list(decode_json_stream(result.stdout))
|
|
|
|
|
|
def run_self_test():
|
|
cases = (
|
|
("gioui.org/layout", True),
|
|
("golang.org/x/sys/windows/registry", True),
|
|
("modernc.org/sqlite/lib", True),
|
|
("softbox.local/app-modern/ui/gio", True),
|
|
("context", False),
|
|
("crypto/sha256", False),
|
|
)
|
|
failures = [
|
|
import_path
|
|
for import_path, expected in cases
|
|
if is_forbidden(import_path) != expected
|
|
]
|
|
if failures:
|
|
print(
|
|
"ERROR: boundary matcher self-test failed for {}".format(
|
|
", ".join(failures)
|
|
),
|
|
file=sys.stderr,
|
|
)
|
|
raise SystemExit(1)
|
|
print("core boundary matcher self-test passed.")
|
|
|
|
|
|
def main():
|
|
if sys.argv[1:] == ["--self-test"]:
|
|
run_self_test()
|
|
return
|
|
if len(sys.argv) != 1:
|
|
print(
|
|
"usage: python scripts/check_core_boundaries.py [--self-test]",
|
|
file=sys.stderr,
|
|
)
|
|
raise SystemExit(2)
|
|
|
|
repo_root = pathlib.Path(__file__).resolve().parents[1]
|
|
violations = []
|
|
|
|
for package in list_core_packages(repo_root):
|
|
imports = set(package.get("Imports", []))
|
|
imports.update(package.get("TestImports", []))
|
|
imports.update(package.get("XTestImports", []))
|
|
for import_path in sorted(imports):
|
|
if is_forbidden(import_path):
|
|
violations.append((package["ImportPath"], import_path))
|
|
|
|
if violations:
|
|
for package, import_path in violations:
|
|
print(
|
|
"ERROR: {} imports forbidden dependency {}".format(
|
|
package, import_path
|
|
),
|
|
file=sys.stderr,
|
|
)
|
|
raise SystemExit(1)
|
|
|
|
print(
|
|
"core boundary check passed: {} forbidden prefixes absent.".format(
|
|
len(FORBIDDEN_IMPORT_PREFIXES)
|
|
)
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|