mirror of
https://github.com/mpv-player/mpv.git
synced 2025-12-26 21:00:21 +00:00
As normal types started being supported better for type hinting, their alternatives in the typing module would be deprecated.
120 lines
4.1 KiB
Python
Executable File
120 lines
4.1 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
import json
|
|
import os
|
|
import re
|
|
import subprocess
|
|
import sys
|
|
from collections.abc import Callable
|
|
from typing import Optional
|
|
|
|
|
|
def call(cmd) -> str:
|
|
sys.stdout.flush()
|
|
ret = subprocess.run(cmd, check=True, stdout=subprocess.PIPE, text=True)
|
|
return ret.stdout
|
|
|
|
lint_rules: dict[str, tuple[Callable, str]] = {}
|
|
|
|
# A lint rule should return True if everything is okay
|
|
def lint_rule(description: str):
|
|
def f(func):
|
|
assert func.__name__ not in lint_rules
|
|
lint_rules[func.__name__] = (func, description)
|
|
return f
|
|
|
|
def get_commit_range() -> Optional[str]:
|
|
if len(sys.argv) > 1:
|
|
return sys.argv[1]
|
|
# https://github.com/actions/runner/issues/342#issuecomment-590670059
|
|
event_name = os.environ["GITHUB_EVENT_NAME"]
|
|
with open(os.environ["GITHUB_EVENT_PATH"], "rb") as f:
|
|
event = json.load(f)
|
|
if event_name == "push":
|
|
if event["created"] or event["forced"]:
|
|
print("Skipping logic on branch creation or force-push")
|
|
return None
|
|
return event["before"] + "..." + event["after"]
|
|
elif event_name == "pull_request":
|
|
base = event["pull_request"]["base"]["sha"]
|
|
head = event["pull_request"]["head"]["sha"]
|
|
return f"{base}..{head}"
|
|
return None
|
|
|
|
def do_lint(commit_range: str) -> bool:
|
|
commits = call(["git", "log", "--pretty=format:%H %s", commit_range]).splitlines()
|
|
print(f"Linting {len(commits)} commit(s):")
|
|
any_failed = False
|
|
for commit in commits:
|
|
sha, _, _ = commit.partition(" ")
|
|
body = call(["git", "show", "-s", "--format=%B", sha]).splitlines()
|
|
failed = []
|
|
if len(body) == 0:
|
|
failed.append("* Commit message must not be empty")
|
|
else:
|
|
for k, v in lint_rules.items():
|
|
if not v[0](body):
|
|
failed.append(f"* {v[1]} [{k}]")
|
|
if failed:
|
|
any_failed = True
|
|
print("-" * 40)
|
|
sys.stdout.flush()
|
|
subprocess.run(["git", "-P", "show", "-s", sha])
|
|
print("\nhas the following issues:")
|
|
print("\n".join(failed))
|
|
print("-" * 40)
|
|
return any_failed
|
|
|
|
################################################################################
|
|
|
|
NO_PREFIX_WHITELIST = \
|
|
r"^Revert \"(.*)\"|^Reapply \"(.*)\"|^Release [0-9]|^Update MPV_VERSION$"
|
|
|
|
@lint_rule("Subject line must contain a prefix identifying the sub system")
|
|
def subsystem_prefix(body):
|
|
return (re.search(NO_PREFIX_WHITELIST, body[0]) or
|
|
re.search(r"^[\w/\.{},-]+: ", body[0]))
|
|
|
|
@lint_rule("First word after : must be lower case")
|
|
def description_lowercase(body):
|
|
# Allow all caps for acronyms and options with --
|
|
return (re.search(NO_PREFIX_WHITELIST, body[0]) or
|
|
re.search(r": (?:[A-Z]{2,} |--[a-z]|[a-z0-9])", body[0]))
|
|
|
|
@lint_rule("Subject line must not end with a full stop")
|
|
def no_dot(body):
|
|
return not body[0].rstrip().endswith(".")
|
|
|
|
@lint_rule("There must be an empty line between subject and extended description")
|
|
def empty_line(body):
|
|
return len(body) == 1 or body[1].strip() == ""
|
|
|
|
# been seeing this one all over github lately, must be the webshits
|
|
@lint_rule("Do not use 'conventional commits' style")
|
|
def no_cc(body):
|
|
return not re.search(r"(?i)^(feat|fix|chore|refactor)[!:(]", body[0])
|
|
|
|
@lint_rule("History must be linear, no merge commits")
|
|
def no_merge(body):
|
|
return not body[0].startswith("Merge ")
|
|
|
|
@lint_rule("Subject line should be shorter than 72 characters")
|
|
def line_too_long(body):
|
|
revert = re.search(r"^Revert \"(.*)\"|^Reapply \"(.*)\"", body[0])
|
|
return revert or len(body[0]) <= 72
|
|
|
|
@lint_rule(
|
|
"Prefix should not include file extension (use `vo_gpu: ...` not `vo_gpu.c: ...`)",
|
|
)
|
|
def no_file_exts(body):
|
|
return not re.search(r"[a-z0-9]\.([chm]|cpp|swift|py): ", body[0])
|
|
|
|
################################################################################
|
|
|
|
if __name__ == "__main__":
|
|
commit_range = get_commit_range()
|
|
if commit_range is None:
|
|
exit(0)
|
|
print("Commit range:", commit_range)
|
|
any_failed = do_lint(commit_range)
|
|
exit(1 if any_failed else 0)
|