This repository has been archived by the owner on Dec 25, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 102
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Meta: Add minimalistic formatting/style checks
This patch adds a modified copy of the Serenity repo style checking scripts.
- Loading branch information
Showing
5 changed files
with
310 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
#!/usr/bin/env python3 | ||
|
||
import os | ||
import re | ||
import subprocess | ||
import sys | ||
|
||
|
||
RE_RELEVANT_FILE_EXTENSION = re.compile('\\.(cpp|h|gml|html|js|css|sh|py|json|txt)$') | ||
|
||
|
||
def should_check_file(filename): | ||
if not RE_RELEVANT_FILE_EXTENSION.search(filename): | ||
return False | ||
if filename.endswith('.txt'): | ||
return 'CMake' in filename | ||
return True | ||
|
||
|
||
def find_files_here_or_argv(): | ||
if len(sys.argv) > 1: | ||
raw_list = sys.argv[1:] | ||
else: | ||
process = subprocess.run(["git", "ls-files"], check=True, capture_output=True) | ||
raw_list = process.stdout.decode().strip('\n').split('\n') | ||
|
||
return filter(should_check_file, raw_list) | ||
|
||
|
||
def run(): | ||
"""Check files checked in to git for trailing newlines at end of file.""" | ||
no_newline_at_eof_errors = [] | ||
blank_lines_at_eof_errors = [] | ||
|
||
did_fail = False | ||
for filename in find_files_here_or_argv(): | ||
with open(filename, "r") as f: | ||
f.seek(0, os.SEEK_END) | ||
|
||
f.seek(f.tell() - 1, os.SEEK_SET) | ||
if f.read(1) != '\n': | ||
did_fail = True | ||
no_newline_at_eof_errors.append(filename) | ||
continue | ||
|
||
while True: | ||
f.seek(f.tell() - 2, os.SEEK_SET) | ||
char = f.read(1) | ||
if not char.isspace(): | ||
break | ||
if char == '\n': | ||
did_fail = True | ||
blank_lines_at_eof_errors.append(filename) | ||
break | ||
|
||
if no_newline_at_eof_errors: | ||
print("Files with no newline at the end:", " ".join(no_newline_at_eof_errors)) | ||
if blank_lines_at_eof_errors: | ||
print("Files that have blank lines at the end:", " ".join(blank_lines_at_eof_errors)) | ||
|
||
if did_fail: | ||
sys.exit(1) | ||
|
||
|
||
if __name__ == '__main__': | ||
os.chdir(os.path.dirname(__file__) + "/..") | ||
run() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
#!/usr/bin/env python3 | ||
|
||
import os | ||
import re | ||
import subprocess | ||
import sys | ||
|
||
# Ensure copyright headers match this format and are followed by a blank line: | ||
# /* | ||
# * Copyright (c) YYYY(-YYYY), Whatever | ||
# * ... more of these ... | ||
# * | ||
# * SPDX-License-Identifier: BSD-2-Clause | ||
# */ | ||
GOOD_LICENSE_HEADER_PATTERN = re.compile( | ||
'^/\\*\n' + | ||
'( \\* Copyright \\(c\\) [0-9]{4}(-[0-9]{4})?, .*\n)+' + | ||
' \\*\n' + | ||
' \\* SPDX-License-Identifier: BSD-2-Clause\n' + | ||
' \\*/\n' + | ||
'\n') | ||
LICENSE_HEADER_CHECK_EXCLUDES = {} | ||
|
||
# We check that "#pragma once" is present | ||
PRAGMA_ONCE_STRING = '#pragma once' | ||
PRAGMA_ONCE_CHECK_EXCLUDES = {} | ||
|
||
# We make sure that there's a blank line before and after pragma once | ||
GOOD_PRAGMA_ONCE_PATTERN = re.compile('(^|\\S\n\n)#pragma once(\n\n\\S.|$)') | ||
|
||
|
||
def should_check_file(filename): | ||
if not filename.endswith('.cpp') and not filename.endswith('.h'): | ||
return False | ||
return True | ||
|
||
|
||
def find_files_here_or_argv(): | ||
if len(sys.argv) > 1: | ||
raw_list = sys.argv[1:] | ||
else: | ||
process = subprocess.run(["git", "ls-files"], check=True, capture_output=True) | ||
raw_list = process.stdout.decode().strip('\n').split('\n') | ||
|
||
return filter(should_check_file, raw_list) | ||
|
||
|
||
def run(): | ||
errors_license = [] | ||
errors_pragma_once_bad = [] | ||
errors_pragma_once_missing = [] | ||
|
||
for filename in find_files_here_or_argv(): | ||
with open(filename, "r") as f: | ||
file_content = f.read() | ||
if not any(filename.startswith(forbidden_prefix) for forbidden_prefix in LICENSE_HEADER_CHECK_EXCLUDES): | ||
if not GOOD_LICENSE_HEADER_PATTERN.search(file_content): | ||
errors_license.append(filename) | ||
if filename.endswith('.h'): | ||
if any(filename.startswith(forbidden_prefix) for forbidden_prefix in PRAGMA_ONCE_CHECK_EXCLUDES): | ||
# File was excluded | ||
pass | ||
elif GOOD_PRAGMA_ONCE_PATTERN.search(file_content): | ||
# Excellent, the formatting is correct. | ||
pass | ||
elif PRAGMA_ONCE_STRING in file_content: | ||
# Bad, the '#pragma once' is present but it's formatted wrong. | ||
errors_pragma_once_bad.append(filename) | ||
else: | ||
# Bad, the '#pragma once' is missing completely. | ||
errors_pragma_once_missing.append(filename) | ||
|
||
if errors_license: | ||
print("Files with bad licenses:", " ".join(errors_license)) | ||
if errors_pragma_once_missing: | ||
print("Files without #pragma once:", " ".join(errors_pragma_once_missing)) | ||
if errors_pragma_once_bad: | ||
print("Files with a bad #pragma once:", " ".join(errors_pragma_once_bad)) | ||
|
||
if errors_license or errors_pragma_once_missing or errors_pragma_once_bad: | ||
sys.exit(1) | ||
|
||
|
||
if __name__ == '__main__': | ||
os.chdir(os.path.dirname(__file__) + "/..") | ||
run() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
#!/usr/bin/env bash | ||
|
||
set -e | ||
|
||
script_path=$(cd -P -- "$(dirname -- "$0")" && pwd -P) | ||
cd "${script_path}/.." || exit 1 | ||
|
||
ports=true | ||
if [ "$1" == "--no-ports" ]; then | ||
ports=false | ||
shift | ||
fi | ||
|
||
RED='\033[0;31m' | ||
GREEN='\033[0;32m' | ||
NC='\033[0m' # No Color | ||
|
||
FAILURES=0 | ||
|
||
set +e | ||
|
||
for cmd in \ | ||
Meta/check-newlines-at-eof.py \ | ||
Meta/check-style.py; do | ||
echo "Running ${cmd}" | ||
if time "${cmd}" "$@"; then | ||
echo -e "[${GREEN}OK${NC}]: ${cmd}" | ||
else | ||
echo -e "[${RED}FAIL${NC}]: ${cmd}" | ||
((FAILURES+=1)) | ||
fi | ||
done | ||
|
||
echo "Running Meta/lint-clang-format.sh" | ||
if time Meta/lint-clang-format.sh --overwrite-inplace "$@" && git diff --exit-code; then | ||
echo -e "[${GREEN}OK${NC}]: Meta/lint-clang-format.sh" | ||
else | ||
echo -e "[${RED}FAIL${NC}]: Meta/lint-clang-format.sh" | ||
((FAILURES+=1)) | ||
fi | ||
|
||
exit "${FAILURES}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
#!/usr/bin/env bash | ||
|
||
set -e | ||
|
||
script_path=$(cd -P -- "$(dirname -- "$0")" && pwd -P) | ||
cd "${script_path}/.." || exit 1 | ||
|
||
if [ "$#" -eq "1" ]; then | ||
mapfile -t files < <( | ||
git ls-files -- \ | ||
'*.cpp' \ | ||
'*.h' | ||
) | ||
else | ||
files=() | ||
for file in "${@:2}"; do | ||
if [[ "${file}" == *".cpp" || "${file}" == *".h" ]]; then | ||
files+=("${file}") | ||
fi | ||
done | ||
fi | ||
|
||
if (( ${#files[@]} )); then | ||
CLANG_FORMAT=false | ||
if command -v clang-format-14 >/dev/null 2>&1 ; then | ||
CLANG_FORMAT=clang-format-14 | ||
elif command -v clang-format >/dev/null 2>&1 ; then | ||
CLANG_FORMAT=clang-format | ||
if ! "${CLANG_FORMAT}" --version | awk '{ if (substr($NF, 1, index($NF, ".") - 1) < 14) exit 1; }'; then | ||
echo "You are using '$("${CLANG_FORMAT}" --version)', which appears to not be clang-format 14 or later." | ||
echo "It is very likely that the resulting changes are not what you wanted." | ||
fi | ||
else | ||
echo "clang-format-14 is not available, but C or C++ files need linting! Either skip this script, or install clang-format-14." | ||
echo "(If you install a package 'clang-format', please make sure it's version 14 or later.)" | ||
exit 1 | ||
fi | ||
|
||
if [ "$#" -gt "0" ] && [ "--overwrite-inplace" = "$1" ] ; then | ||
true # The only way to run this script. | ||
else | ||
# Note that this branch also covers --help, -h, -help, -?, etc. | ||
echo "USAGE: $0 --overwrite-inplace" | ||
echo "The argument is necessary to make you aware that this *will* overwrite your local files." | ||
exit 1 | ||
fi | ||
|
||
echo "Using ${CLANG_FORMAT}" | ||
|
||
"${CLANG_FORMAT}" -style=file -i "${files[@]}" | ||
echo "Maybe some files have changed. Sorry, but clang-format doesn't indicate what happened." | ||
else | ||
echo "No .cpp or .h files to check." | ||
fi |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
#!/usr/bin/env bash | ||
|
||
# the file containing the commit message is passed as the first argument | ||
commit_file="$1" | ||
commit_message=$(cat "$commit_file") | ||
|
||
error() { | ||
echo -e "\033[0;31m$1:\033[0m" | ||
echo "$commit_message" | ||
exit 1 | ||
} | ||
|
||
# fail if the commit message contains windows style line breaks (carriage returns) | ||
if grep -q -U $'\x0D' "$commit_file"; then | ||
error "Commit message contains CRLF line breaks (only unix-style LF linebreaks are allowed)" | ||
fi | ||
|
||
line_number=0 | ||
while read -r line; do | ||
# break on git cut line, used by git commit --verbose | ||
if [[ "$line" == "# ------------------------ >8 ------------------------" ]]; then | ||
break | ||
fi | ||
|
||
# ignore comment lines | ||
[[ "$line" =~ ^#.* ]] && continue | ||
# ignore overlong 'fixup!' commit descriptions | ||
[[ "$line" =~ ^fixup!\ .* ]] && continue | ||
|
||
((line_number += 1)) | ||
line_length=${#line} | ||
|
||
if [[ $line_number -eq 2 ]] && [[ $line_length -ne 0 ]]; then | ||
error "Empty line between commit title and body is missing" | ||
fi | ||
|
||
category_pattern='^(Revert "|\S+: )' | ||
if [[ $line_number -eq 1 ]] && (echo "$line" | grep -E -v -q "$category_pattern"); then | ||
error "Missing category in commit title (if this is a fix up of a previous commit, it should be squashed)" | ||
fi | ||
|
||
title_case_pattern="^\S.*?: [A-Z0-9]" | ||
if [[ $line_number -eq 1 ]] && (echo "$line" | grep -E -v -q "$title_case_pattern"); then | ||
error "First word of commit after the subsystem is not capitalized" | ||
fi | ||
|
||
if [[ $line_number -eq 1 ]] && [[ "$line" =~ \.$ ]]; then | ||
error "Commit title ends in a period" | ||
fi | ||
|
||
url_pattern="([a-z]+:\/\/)?(([a-zA-Z0-9_]|-)+\.)+[a-z]{2,}(:\d+)?([a-zA-Z_0-9@:%\+.~\?&\/=]|-)+" | ||
if [[ $line_length -gt 72 ]] && (echo "$line" | grep -E -v -q "$url_pattern"); then | ||
error "Commit message lines are too long (maximum allowed is 72 characters)" | ||
fi | ||
|
||
if [[ "$line" == "Signed-off-by: "* ]]; then | ||
error "Commit body contains a Signed-off-by tag" | ||
fi | ||
|
||
done <"$commit_file" | ||
exit 0 |