Files
lda Verified 038e152bbc
Checks / tests (ubuntu-latest, 3.11) (push) Canceled after 0s
Checks / tests (ubuntu-latest, 3.14) (push) Canceled after 0s
Checks / tests (windows-latest, 3.11) (push) Canceled after 0s
Checks / tests (windows-latest, 3.14) (push) Canceled after 0s
Checks / package (push) Canceled after 0s
Add MX-T40 BLE desktop controller and protocol documentation
2026-10-25 04:43:47 +07:00

84 lines
2.7 KiB
Python

"""Copy an explicit source allowlist into a new repository directory.
This workspace also holds firmware research. Exporting from an allowlist,
rather than recursively copying the workspace and subtracting known inputs,
prevents newly added vendor artifacts from silently entering a release.
The destination must be empty; existing content is never replaced.
"""
import argparse
import shutil
from pathlib import Path
ROOT_FILES = (
"README.md",
"CONTRIBUTING.md",
"LICENSE",
"LICENSE.txt",
"pyproject.toml",
"uv.lock",
"MANIFEST.in",
"requirements.txt",
"requirements-diagnostics.txt",
".gitignore",
)
TREES = {
"controller": {".py"},
"tests": {".py"},
"docs": {".md"},
"scripts": {".py"},
".github": {".yml", ".yaml"},
}
def source_files(root):
root = Path(root).resolve()
selected = [root / name for name in ROOT_FILES if (root / name).is_file()]
for folder, suffixes in TREES.items():
selected.extend(
path
for path in (root / folder).rglob("*")
if path.is_file() and path.suffix in suffixes and "__pycache__" not in path.parts
)
for path in selected:
if path.is_symlink() or not path.resolve().is_relative_to(root):
raise ValueError(
f"Export refuses symlinked or external source: {path.relative_to(root)}"
)
return sorted(selected)
def export_project(root, destination):
root = Path(root).resolve()
destination = Path(destination)
if destination.is_symlink():
raise ValueError("Export destination cannot be a symlink")
destination = destination.resolve()
if destination == root or any(destination.is_relative_to(root / folder) for folder in TREES):
raise ValueError("Choose a destination outside the included source folders")
if destination.exists() and (not destination.is_dir() or any(destination.iterdir())):
raise ValueError("Export destination must be a new or empty directory")
files = source_files(root)
destination.mkdir(parents=True, exist_ok=True)
for source in files:
target = destination / source.relative_to(root)
target.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(source, target)
return len(files)
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("destination", type=Path)
args = parser.parse_args()
root = Path(__file__).resolve().parents[1]
try:
count = export_project(root, args.destination)
except ValueError as exc:
parser.error(str(exc))
print(f"Exported {count} source/documentation files to {args.destination}")
if __name__ == "__main__":
main()