176 lines
6.7 KiB
Python
176 lines
6.7 KiB
Python
"""Ticket #18 + #24: offline naming-sweep — no old-name strings on surfaces.
|
|
|
|
The fork takes its own name everywhere a user can see it. Anything still
|
|
spelling the old name must be on the allowlist below:
|
|
|
|
- upstream provenance (``VocaHQ/vocalinux`` URLs),
|
|
- the retained internal Python module name (``src/vocalinux`` paths,
|
|
``vocalinux.*`` imports/attributes, ``-m vocalinux.main``),
|
|
- retained internal class names (``VocalinuxEngine*``, ``VocalinuxDBusService``),
|
|
- one-time-legacy import sources (old config/dictionary/bus literals),
|
|
- generated or historical files (``uv.lock``, ``requirements/*.txt``,
|
|
``CHANGELOG.md``),
|
|
- web upstream surfaces (ticket #24): upstream GitHub/raw/nix flake URLs,
|
|
nix flake API identifiers, and the nixos-page fork-status note that names
|
|
the upstream flake as installing Vocalinux rather than Voculinux.
|
|
"""
|
|
|
|
import os
|
|
import re
|
|
|
|
REPO_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
|
|
OLD_NAME = re.compile(r"vocalinux", re.IGNORECASE)
|
|
|
|
SKIP_DIRS = {".git", "__pycache__", ".venv", "venv", "node_modules", ".next", "build", "dist", "out"}
|
|
SKIP_SUFFIXES = (".egg-info",)
|
|
SKIP_FILES = {"uv.lock", "CHANGELOG.md"}
|
|
SKIP_PREFIXES = ("requirements/",)
|
|
BINARY_EXTS = (
|
|
".wav",
|
|
".mp3",
|
|
".ogg",
|
|
".png",
|
|
".svg",
|
|
".ico",
|
|
".icns",
|
|
".bin",
|
|
".onnx",
|
|
".pt",
|
|
".zip",
|
|
".tar",
|
|
".gz",
|
|
".whl",
|
|
".AppImage",
|
|
".zsync",
|
|
".pyc",
|
|
)
|
|
|
|
#: web/ was fully rebranded in ticket #24; only upstream-provenance lines
|
|
#: (matched in _allowed) may still spell the old name there.
|
|
WEB_OWNED = {"web/src/app/page.tsx", "web/package.json"}
|
|
|
|
|
|
def _allowed(path: str, line: str) -> bool:
|
|
"""Return True when an old-name match is an allowlisted surface."""
|
|
low = line.lower()
|
|
if "vocahq/" in low or "jatinkrmalik/vocalinux" in low:
|
|
return True
|
|
if "vocalinux" in low and "voculinux" in low:
|
|
# Migration-compat shims that name both installs at once.
|
|
return True
|
|
if "upstream" in low:
|
|
# Upstream-provenance mentions that explicitly label the old name
|
|
# as upstream (fork-status notes, provenance cards).
|
|
return True
|
|
if "/{name}/vocalinux" in line:
|
|
# Upstream repo-name template (retained provenance).
|
|
return True
|
|
if path == "snap/local/check_runtime.py" and '"vocalinux"' in line:
|
|
# Smoke imports resolve the retained import package.
|
|
return True
|
|
if re.search(r'vocalinux\.["a-z_]', line):
|
|
return True
|
|
if line.strip().rstrip(",").lstrip("/ ") == '"vocalinux"':
|
|
# Retained module-dir path segment element in tests and tooling
|
|
# (single-line and os.path.join element forms).
|
|
return True
|
|
if 'site / "vocalinux"' in line or '"platform/vocalinux"' in line:
|
|
# Fixture module trees named after the retained import package.
|
|
return True
|
|
if '"vocalinux/' in line:
|
|
# Fixture module file paths under the retained package name.
|
|
return True
|
|
if "/vocalinux/" in line or "src/vocalinux" in line:
|
|
return True
|
|
if "-m vocalinux" in line or "import vocalinux" in line:
|
|
return True
|
|
if "VocalinuxEngine" in line or "VocalinuxDBusService" in line:
|
|
return True
|
|
if "cmdline" in line:
|
|
return True
|
|
if " - vocalinux" in line:
|
|
# Log logger names keep the retained module path.
|
|
return True
|
|
if path in (
|
|
"src/vocalinux/legacy_import.py",
|
|
"tests/test_legacy_import.py",
|
|
):
|
|
return True
|
|
if "LEGACY" in line or "legacy" in line:
|
|
return True
|
|
if "~/.config/vocalinux" in line or '".config" / "vocalinux"' in line:
|
|
# Documented one-time-import source (ticket #18).
|
|
return True
|
|
if "from vocalinux" in line:
|
|
return True
|
|
if '"src"' in line and '"vocalinux"' in line:
|
|
# Retained module-dir path segments in tests and tooling.
|
|
return True
|
|
if path == "web/src/app/install/nixos/page.tsx":
|
|
# The Nix flake is upstream's: flake URL, input/output names, module
|
|
# paths, and programs.* options spell the retained upstream API.
|
|
# The page carries a fork-status note stating those snippets install
|
|
# Vocalinux (upstream), not Voculinux.
|
|
return True
|
|
if path == "tests/test_rename_sweep.py":
|
|
return True
|
|
if path == "pyproject.toml" and re.search(r'"vocalinux[."\'\]]', line):
|
|
return True
|
|
if path == "pyproject.toml" and "vocalinux.version" in line:
|
|
return True
|
|
if 'PKG_NAME="vocalinux"' in line:
|
|
# Installer probes the retained import package, not the distribution.
|
|
return True
|
|
if path == "packaging/void/srcpkgs/voculinux/template" and "vocalinux-${version}" in line:
|
|
# Pre-rename release asset root (ticket #27); dropped at the first
|
|
# post-rename release bump.
|
|
return True
|
|
if path == "tests/test_void_app_template.py" and '"vocalinux"' in line:
|
|
# The app-template policy test asserts the old name is gone.
|
|
return True
|
|
if '== "vocalinux"' in line or '.startswith("vocalinux' in line:
|
|
# Retained module identity comparisons in test isolation helpers.
|
|
return True
|
|
return False
|
|
|
|
|
|
def _iter_files():
|
|
for root, dirs, files in os.walk(REPO_ROOT):
|
|
dirs[:] = [d for d in sorted(dirs) if d not in SKIP_DIRS]
|
|
for name in sorted(files):
|
|
if name in SKIP_FILES or name.endswith(BINARY_EXTS):
|
|
continue
|
|
full = os.path.join(root, name)
|
|
rel = os.path.relpath(full, REPO_ROOT)
|
|
if rel.startswith(SKIP_PREFIXES):
|
|
continue
|
|
yield rel, full
|
|
|
|
|
|
def test_naming_sweep_no_old_name_outside_allowlist() -> None:
|
|
"""Every old-name hit must be an allowlisted retained surface."""
|
|
offenders: list[str] = []
|
|
for rel, full in _iter_files():
|
|
if any(part.endswith(SKIP_SUFFIXES) for part in rel.split("/")):
|
|
continue
|
|
try:
|
|
with open(full, encoding="utf-8") as handle:
|
|
text = handle.read()
|
|
except (UnicodeDecodeError, ValueError):
|
|
continue
|
|
for number, line in enumerate(text.splitlines(), 1):
|
|
if OLD_NAME.search(line) and not _allowed(rel, line):
|
|
offenders.append(f"{rel}:{number}:{line.strip()[:160]}")
|
|
assert (
|
|
offenders == []
|
|
), f"{len(offenders)} old-name string(s) outside the allowlist:\n" + "\n".join(offenders[:60])
|
|
|
|
|
|
def test_owned_web_files_carry_new_name() -> None:
|
|
"""The two web rename surfaces name the fork (URLs aside)."""
|
|
for rel in sorted(WEB_OWNED):
|
|
with open(os.path.join(REPO_ROOT, rel), encoding="utf-8") as handle:
|
|
text = handle.read()
|
|
assert "Voculinux" in text or "voculinux" in text, rel
|