mirror of
https://gitlab.freedesktop.org/xorg/xserver.git
synced 2026-02-14 21:30:37 +01:00
xwayland/ci: Enforce various code style checks
Make sure the code change does not contain tab characters nor stray
newlines.
This is contributed by Peter Hutterer, adapted from the libinput similar
CI check.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2121>
(cherry picked from commit 9c31b4ad8f)
This commit is contained in:
parent
22dcaf44d4
commit
e1cd42dcaa
2 changed files with 140 additions and 0 deletions
|
|
@ -334,6 +334,13 @@ check-commits:
|
|||
junit: results.xml
|
||||
allow_failure: true
|
||||
|
||||
check-whitespace:
|
||||
extends:
|
||||
- .fdo.ci-fairy
|
||||
stage: test
|
||||
script:
|
||||
- .gitlab-ci/whitespace-check.py $(git ls-files hw/xwayland)
|
||||
|
||||
#
|
||||
# Workflow rules needed due to:
|
||||
# https://gitlab.freedesktop.org/freedesktop/freedesktop/-/issues/438
|
||||
|
|
|
|||
133
.gitlab-ci/whitespace-check.py
Executable file
133
.gitlab-ci/whitespace-check.py
Executable file
|
|
@ -0,0 +1,133 @@
|
|||
#!/usr/bin/env python3
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
from pathlib import Path
|
||||
from dataclasses import dataclass
|
||||
|
||||
import argparse
|
||||
import itertools
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
|
||||
@dataclass
|
||||
class WhitespaceError:
|
||||
message: str
|
||||
lineno: int
|
||||
nlines: int = 1
|
||||
column: None | int = None
|
||||
ncolumns: int = 1
|
||||
|
||||
|
||||
def test_tab_indent(lines: list[str]) -> list[WhitespaceError]:
|
||||
errors = []
|
||||
for idx, l in enumerate(lines):
|
||||
if re.match("^\t+.*", l):
|
||||
errors.append(
|
||||
WhitespaceError(
|
||||
"Tab indent", idx, ncolumns=2
|
||||
)
|
||||
)
|
||||
return errors
|
||||
|
||||
|
||||
def test_duplicate_empty_lines(lines: list[str]) -> list[WhitespaceError]:
|
||||
errors = []
|
||||
for idx, (l1, l2) in enumerate(itertools.pairwise(lines)):
|
||||
if not l1 and not l2:
|
||||
errors.append(WhitespaceError("Duplicated empty lines", idx, nlines=2))
|
||||
return errors
|
||||
|
||||
|
||||
def test_tab_after_space(lines: list[str]) -> list[WhitespaceError]:
|
||||
errors = []
|
||||
for idx, l in enumerate(lines):
|
||||
index = l.find(" \t")
|
||||
if index > -1:
|
||||
errors.append(
|
||||
WhitespaceError(
|
||||
"Tab after space", idx, nlines=index, column=index, ncolumns=2
|
||||
)
|
||||
)
|
||||
return errors
|
||||
|
||||
|
||||
def test_trailing_whitespace(lines: list[str]) -> list[WhitespaceError]:
|
||||
errors = []
|
||||
for idx, l in enumerate(lines):
|
||||
if l.rstrip() != l:
|
||||
errors.append(WhitespaceError("Trailing whitespace", idx))
|
||||
return errors
|
||||
|
||||
|
||||
def test_empty_line_between_braces(lines: list[str]) -> list[WhitespaceError]:
|
||||
errors = []
|
||||
for idx in range(len(lines) - 3):
|
||||
l1 = lines[idx]
|
||||
l2 = lines[idx + 1]
|
||||
l3 = lines[idx + 2]
|
||||
if l1.strip() == "}" and l3.strip() == "}" and l2.strip() == "":
|
||||
errors.append(WhitespaceError("Empty line between closing braces", idx + 1))
|
||||
return errors
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Whitespace checker script")
|
||||
parser.add_argument(
|
||||
"files",
|
||||
metavar="FILES",
|
||||
type=Path,
|
||||
nargs="+",
|
||||
help="The files to check",
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
have_errors: bool = False
|
||||
|
||||
if os.isatty(sys.stderr.fileno()):
|
||||
red = "\x1b[0;31m"
|
||||
reset = "\x1b[0m"
|
||||
else:
|
||||
red = ""
|
||||
reset = ""
|
||||
|
||||
for file in args.files:
|
||||
lines = [l.rstrip("\n") for l in file.open().readlines()]
|
||||
|
||||
errors = []
|
||||
errors.extend(test_tab_indent(lines))
|
||||
errors.extend(test_tab_after_space(lines))
|
||||
errors.extend(test_trailing_whitespace(lines))
|
||||
if any(file.name.endswith(suffix) for suffix in [".c", ".h"]):
|
||||
if not file.parts[0] == "include":
|
||||
errors.extend(test_duplicate_empty_lines(lines))
|
||||
errors.extend(test_empty_line_between_braces(lines))
|
||||
|
||||
for e in errors:
|
||||
print(f"{red}ERROR: {e.message} in {file}:{reset}", file=sys.stderr)
|
||||
print(f"{'-' * 72}", file=sys.stderr)
|
||||
lineno = max(0, e.lineno - 5)
|
||||
for idx, l in enumerate(lines[lineno : lineno + 10]):
|
||||
if e.lineno <= lineno + idx < e.lineno + e.nlines:
|
||||
prefix = "->"
|
||||
hl = red
|
||||
nohl = reset
|
||||
else:
|
||||
prefix = " "
|
||||
hl = ""
|
||||
nohl = ""
|
||||
print(f"{hl}{lineno + idx:3d}: {prefix} {l.rstrip()}{nohl}")
|
||||
|
||||
print(f"{'-' * 72}", file=sys.stderr)
|
||||
|
||||
if errors:
|
||||
have_errors = True
|
||||
|
||||
if have_errors:
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Loading…
Add table
Reference in a new issue