blob: e91bd9b7aaa50eac7c5d302354d0e1832b8fb191 [file] [edit]
#!/usr/bin/env python
import glob
import os
from pathlib import Path
SCRIPT_DIR = Path(os.path.realpath(__file__)).parent
class Copyright:
# Canonical license body, shared with every generator — see scripts/license_header.txt.
NOTICE = (SCRIPT_DIR / "license_header.txt").read_text(encoding="utf-8").rstrip("\n")
def __init__(self, comment_characters="//", prefix=None):
self._comment_characters = comment_characters
self._prefix = prefix or []
def update(self, files):
for file in files:
with open(file, encoding="utf-8-sig") as f:
lines = f.readlines()
index = -1
for i, line in enumerate(lines):
if line.startswith(self._comment_characters) or self.valid_copyright_notice_line(line, index, file):
index += 1
else:
break
if index == -1:
self.write_update_notice(file, lines)
else:
current = "".join(lines[: index + 1])
if current != self.copyright_notice(file):
self.write_update_notice(file, lines[index + 1 :])
def valid_copyright_notice_line(self, line, index, file):
return index + 1 < len(self.copyright_notice_lines(file)) and line.startswith(
self.copyright_notice_lines(file)[index + 1]
)
def copyright_notice(self, file):
return "".join(self.copyright_notice_lines(file))
def copyright_notice_lines(self, file):
return self.dotnet(file) if file.endswith("cs") else self._prefix + self.commented_notice_lines
def dotnet(self, file):
file_name = os.path.basename(file)
first = f'{self._comment_characters} <copyright file="{file_name}" company="Selenium Committers">\n'
last = f"{self._comment_characters} </copyright>"
return [first] + self.commented_notice_lines + [last]
@property
def commented_notice_lines(self):
return [f"{self._comment_characters} {line}".rstrip() + "\n" for line in self.NOTICE.split("\n")]
def write_update_notice(self, file, lines):
# Build new content
new_content = self.copyright_notice(file) + "\n"
if lines and lines[0] != "\n":
new_content += "\n"
new_content += "".join(line.rstrip() + "\n" for line in lines)
# Only write if different
with open(file, encoding="utf-8-sig") as f:
old_content = f.read()
if new_content == old_content:
return
print(f"Adding notice to {file}")
with open(file, "w") as f:
f.write(new_content)
ROOT = Path(os.path.realpath(__file__)).parent.parent
JS_EXCLUSIONS = [
f"{ROOT}/javascript/**/node_modules/**",
f"{ROOT}/javascript/atoms/test/jquery.min.js",
]
PY_EXCLUSIONS = [
f"{ROOT}/py/generate.py",
f"{ROOT}/py/selenium/webdriver/common/devtools/**/*",
f"{ROOT}/py/venv/**/*",
]
def update_files(file_pattern, exclusions, comment_characters="//", prefix=None):
included = set(glob.glob(file_pattern, recursive=True))
excluded = set()
for pattern in exclusions:
excluded.update(glob.glob(pattern, recursive=True))
files = included - excluded
copyright = Copyright(comment_characters, prefix)
copyright.update(files)
if __name__ == "__main__":
update_files(f"{ROOT}/javascript/**/*.js", JS_EXCLUSIONS)
update_files(f"{ROOT}/javascript/**/*.mjs", JS_EXCLUSIONS)
update_files(f"{ROOT}/javascript/**/*.cjs", JS_EXCLUSIONS)
update_files(f"{ROOT}/javascript/**/*.tsx", JS_EXCLUSIONS)
update_files(f"{ROOT}/javascript/**/*.ts", JS_EXCLUSIONS + [f"{ROOT}/javascript/**/*.d.ts"])
update_files(f"{ROOT}/py/**/*.py", PY_EXCLUSIONS, comment_characters="#")
update_files(f"{ROOT}/py/**/*.pyi", PY_EXCLUSIONS, comment_characters="#")
update_files(
f"{ROOT}/rb/**/*.rb",
[],
comment_characters="#",
prefix=["# frozen_string_literal: true\n", "\n"],
)
update_files(
f"{ROOT}/rb/**/*.rb.erb",
[],
comment_characters="#",
prefix=["# frozen_string_literal: true\n", "\n"],
)
update_files(
f"{ROOT}/rb/**/*.rbs",
[f"{ROOT}/rb/sig/gems/**/*.rbs"],
comment_characters="#",
)
# *.rbs.erb matches neither the *.rb.erb nor the *.rbs pattern, so it needs its own pass.
update_files(
f"{ROOT}/rb/**/*.rbs.erb",
[],
comment_characters="#",
)
update_files(f"{ROOT}/java/**/*.java", [])
update_files(f"{ROOT}/rust/**/*.rs", [])
update_files(f"{ROOT}/dotnet/**/*.cs", [])