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
194 lines
5.2 KiB
Python
Executable File
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()
|