Files
TheRock/rocm-libraries/shared/rocroller/scripts/update_licenses
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

194 lines
5.2 KiB
Python
Executable File

#!/usr/bin/env python3
# Copyright Advanced Micro Devices, Inc., or its affiliates.
# SPDX-License-Identifier: MIT
"""
Add SPDX license headers to source files that don't have them.
This script adds the short SPDX license format to files tracked by git
that don't already contain a license header.
"""
import argparse
import sys
from pathlib import Path
repo_dir = Path(__file__).resolve().parent.parent
sys.path.append(str(repo_dir / "scripts" / "lib"))
from rrperf import git # noqa: E402
# New license text for different file types
LICENSE_CPP = """\
// Copyright Advanced Micro Devices, Inc., or its affiliates.
// SPDX-License-Identifier: MIT
"""
LICENSE_HASH = """\
# Copyright Advanced Micro Devices, Inc., or its affiliates.
# SPDX-License-Identifier: MIT
"""
# Files that should never have licenses added
EXCLUDE_NAMES = [
"CODEOWNERS",
"CppCheckSuppressions.txt",
"requirements.txt",
".clang-format",
".gitignore",
".gitattributes",
"LICENSE.md",
]
# Paths containing these substrings should be excluded
EXCLUDE_PATHS = [
"cmake/CMakeRC.cmake", # External: vector-of-bool
"GPUArchitectureGenerator/isa_spec_manager/tinyxml2", # External: Lee Thomason
"GPUArchitectureGenerator/isa_spec_manager/amdisa_", # Different AMD project
"GPUArchitectureGenerator/isa_spec_manager/isa_xml_reader", # Different AMD project
"_deps/",
]
# Extensions that can have licenses added
EXTENSIONS_CPP = [".hpp", ".cpp", ".h", ".c", ".in", ".cl", ".ql", ".qll"]
EXTENSIONS_HASH = [".py", ".sh", ".cmake", ".txt"]
def should_exclude(path: Path) -> bool:
"""Check if a file should be excluded from processing."""
if path.name in EXCLUDE_NAMES:
return True
path_str = str(path)
for exclude in EXCLUDE_PATHS:
if exclude in path_str:
return True
return False
def get_license_format(path: Path) -> str | None:
"""Determine license format for file, or None if not applicable."""
if path.suffix in EXTENSIONS_CPP:
return "cpp"
elif path.suffix in EXTENSIONS_HASH:
return "hash"
elif "dockerfile" in path.name.lower():
# Dockerfiles use # comments but have no extension
return "hash"
elif "doxyfile" in path.name.lower():
# Doxyfiles use # comments
return "hash"
elif path.suffix == "" and path.name not in EXCLUDE_NAMES:
# Scripts without extension - check for shebang
try:
with open(path, "r") as f:
first_line = f.readline()
if first_line.startswith("#!"):
return "hash"
except (IOError, UnicodeDecodeError):
pass
return None
def has_license(text: str) -> bool:
"""Check if file already has a license."""
return "SPDX-License-Identifier" in text or "Copyright" in text
def prepend_license(text: str, license_format: str) -> str:
"""Prepend license to file content, preserving shebang and encoding lines."""
lines = text.split("\n")
insert_index = 0
# Preserve shebang
if lines and lines[0].startswith("#!"):
insert_index = 1
# Preserve encoding declaration
if len(lines) > insert_index and "coding:" in lines[insert_index]:
insert_index += 1
license_text = LICENSE_CPP if license_format == "cpp" else LICENSE_HASH
license_lines = license_text.rstrip("\n").split("\n")
# Insert license and blank line
lines[insert_index:insert_index] = license_lines + [""]
return "\n".join(lines)
def process_file(path: Path, dry_run: bool = False) -> bool:
"""Process a single file, returning True if it was modified."""
if should_exclude(path):
return False
license_format = get_license_format(path)
if license_format is None:
return False
try:
text = path.read_text()
except (IOError, UnicodeDecodeError) as e:
print(f"Error reading {path}: {e}")
return False
if has_license(text):
return False
new_text = prepend_license(text, license_format)
if dry_run:
print(f"Would add license: {path}")
else:
print(f"Adding license: {path}")
path.write_text(new_text)
return True
def main():
parser = argparse.ArgumentParser(
description="Add SPDX license headers to source files"
)
parser.add_argument(
"dir",
type=Path,
default=repo_dir,
nargs="?",
help="Directory to process (default: repo root)",
)
parser.add_argument(
"--dry-run",
action="store_true",
help="Show what would be changed without making changes",
)
args = parser.parse_args()
updated = 0
errors = []
for x in git.ls_tree(args.dir):
path = args.dir / Path(x)
if path.is_file():
try:
if process_file(path, args.dry_run):
updated += 1
except Exception as e:
print(f"Error processing {path}: {e}")
errors.append(path)
print(
f"\n{'Would add license to' if args.dry_run else 'Added license to'} {updated} files"
)
if errors:
print(f"\nErrors in {len(errors)} files:")
for e in errors:
print(f" {e}")
if __name__ == "__main__":
main()