mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-02-09 20:04:20 +00:00
health-check: Add copyright header check
New files will require a copyright header, which is checked by CI and locally. BUG=b:242605601 TEST=touch foo.rs && ./tools/health-check; ./tools/health-check --fix Change-Id: I31bf299bd636a5da4f806c32ca8bdf9cfd4c01f3 Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/3832787 Reviewed-by: Daniel Verkamp <dverkamp@chromium.org> Tested-by: Dennis Kempin <denniskempin@google.com> Commit-Queue: Dennis Kempin <denniskempin@google.com>
This commit is contained in:
parent
7b5f6b198f
commit
34a4ee662f
2 changed files with 76 additions and 9 deletions
|
@ -3,11 +3,22 @@
|
|||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
import re
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
import sys
|
||||
from impl.common import CROSVM_ROOT, parallel, run_main, cmd, chdir, argh, cwd_context
|
||||
|
||||
from impl.check_code_hygiene import has_crlf_line_endings
|
||||
from impl.common import (
|
||||
CROSVM_ROOT,
|
||||
argh,
|
||||
chdir,
|
||||
cmd,
|
||||
cwd_context,
|
||||
parallel,
|
||||
run_main,
|
||||
)
|
||||
from impl.health_check import Check, CheckContext, run_checks
|
||||
|
||||
|
||||
|
@ -74,8 +85,55 @@ def check_rust_lockfiles(_: CheckContext):
|
|||
raise Exception("Cargo.lock out of date")
|
||||
|
||||
|
||||
LICENSE_HEADER_RE = (
|
||||
# Line 1 - copyright.
|
||||
r".*Copyright(?P<copyright> \(c\))? (?P<year>20[0-9]{2})(?:-20[0-9]{2})? "
|
||||
r"The Chromium(?P<chromium_space_os> )?OS Authors\."
|
||||
r"(?P<rights_reserved> All rights reserved\.)?\n"
|
||||
# Line 2 - License.
|
||||
r".*Use of this source code is governed by a BSD-style license that can "
|
||||
r"be\n"
|
||||
# Line 3 - License continuation.
|
||||
r".*found in the LICENSE file\.\n"
|
||||
)
|
||||
|
||||
NEW_LICENSE_HEADER = [
|
||||
f"Copyright {datetime.now().year} The ChromiumOS Authors.",
|
||||
"Use of this source code is governed by a BSD-style license that can be",
|
||||
"found in the LICENSE file.",
|
||||
]
|
||||
|
||||
|
||||
def new_licence_header(file_suffix: str):
|
||||
if file_suffix == ".py" or file_suffix == "":
|
||||
prefix = "#"
|
||||
else:
|
||||
prefix = "//"
|
||||
return "\n".join(f"{prefix} {line}" for line in NEW_LICENSE_HEADER) + "\n\n"
|
||||
|
||||
|
||||
def check_copyright_header(context: CheckContext):
|
||||
"Checks copyright header on new files only. Can 'fix' them if needed."
|
||||
license_re = re.compile(LICENSE_HEADER_RE, re.MULTILINE)
|
||||
for file in context.new_files:
|
||||
header = file.open("r").read(256)
|
||||
license_match = license_re.search(header)
|
||||
if license_match:
|
||||
continue
|
||||
if context.fix:
|
||||
contents = file.read_text()
|
||||
file.write_text(new_licence_header(file.suffix) + contents)
|
||||
else:
|
||||
raise Exception(f"Bad copyright header: {file}")
|
||||
|
||||
|
||||
# List of all checks and on which files they should run.
|
||||
CHECKS: List[Check] = [
|
||||
Check(
|
||||
check_copyright_header,
|
||||
files=["**.rs", "**.py"],
|
||||
python_tools=True,
|
||||
),
|
||||
Check(
|
||||
check_rust_format,
|
||||
files=["**.rs"],
|
||||
|
|
|
@ -3,13 +3,13 @@
|
|||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
from dataclasses import dataclass
|
||||
from fnmatch import fnmatch
|
||||
from pathlib import Path
|
||||
from time import time
|
||||
from typing import Callable, List, NamedTuple
|
||||
from pathlib import Path
|
||||
from impl.common import all_tracked_files, cmd, verbose
|
||||
|
||||
from dataclasses import dataclass
|
||||
from impl.common import all_tracked_files, cmd, verbose
|
||||
|
||||
git = cmd("git")
|
||||
|
||||
|
@ -30,6 +30,9 @@ class CheckContext(object):
|
|||
# Those files of all_files that were modified locally.
|
||||
modified_files: List[Path]
|
||||
|
||||
# Files that do not exist upstream and have been added locally.
|
||||
new_files: List[Path]
|
||||
|
||||
|
||||
class Check(NamedTuple):
|
||||
"Metadata for each check, definining on which files it should run."
|
||||
|
@ -53,7 +56,7 @@ class Check(NamedTuple):
|
|||
return name
|
||||
|
||||
|
||||
def list_modified_files():
|
||||
def list_file_diff():
|
||||
"""
|
||||
Lists files there were modified compared to the upstream branch.
|
||||
|
||||
|
@ -61,10 +64,13 @@ def list_modified_files():
|
|||
"""
|
||||
upstream = git("rev-parse @{u}").stdout(check=False)
|
||||
if upstream:
|
||||
return (Path(f) for f in git("diff --name-only", upstream).lines())
|
||||
for line in git("diff --name-status", upstream).lines():
|
||||
parts = line.split("\t", 1)
|
||||
yield (parts[0].strip(), Path(parts[1].strip()))
|
||||
else:
|
||||
print("WARNING: Not tracking a branch. Checking all files.")
|
||||
return all_tracked_files()
|
||||
for file in all_tracked_files():
|
||||
yield ("M", file)
|
||||
|
||||
|
||||
def should_run_check_on_file(check: Check, file: Path):
|
||||
|
@ -129,10 +135,12 @@ def run_checks(
|
|||
nightly: Use nightly version of rust tooling.
|
||||
"""
|
||||
all_files = [*all_tracked_files()]
|
||||
file_diff = [*list_file_diff()]
|
||||
new_files = [f for (s, f) in file_diff if s == "A"]
|
||||
if run_on_all_files:
|
||||
modified_files = all_files
|
||||
else:
|
||||
modified_files = [*list_modified_files()]
|
||||
modified_files = [f for (s, f) in file_diff if s in ("M", "A")]
|
||||
|
||||
success = True
|
||||
for check in checks_list:
|
||||
|
@ -141,6 +149,7 @@ def run_checks(
|
|||
nightly=nightly,
|
||||
all_files=[f for f in all_files if should_run_check_on_file(check, f)],
|
||||
modified_files=[f for f in modified_files if should_run_check_on_file(check, f)],
|
||||
new_files=[f for f in new_files if should_run_check_on_file(check, f)],
|
||||
)
|
||||
if context.modified_files:
|
||||
if not run_check(check, context):
|
||||
|
|
Loading…
Reference in a new issue