blob: 0f47a10bc0db60d70a4df83f56bed028c8d4e346 [file] [log] [blame]
#!/usr/bin/env python3
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#
import os
import re
import subprocess
import sys
from pathlib import Path
TMP_FOLDER = "/tmp/doxygen_check"
WARN_FILE_NAME = "warnings.log"
allowed_files = [
"nimble/include/nimble/ble.h",
]
def run_cmd(cmd: str) -> list[str]:
out = subprocess.check_output(cmd, text=True, shell=True)
return out.splitlines()
def run_cmd_no_check(cmd: str) -> list[str]:
out = subprocess.run(cmd, text=True, shell=True, stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL).stdout
return out.splitlines()
def is_ignored(filename: str, allowed: list[str]) -> bool:
if Path(filename).suffix != ".h" or "priv" in filename:
return True
if filename in allowed:
return False
if re.search(r"nimble/host.*include.*", filename):
return False
return True
def main() -> bool:
if len(sys.argv) > 1:
commit = sys.argv[1]
else:
commit = "HEAD"
if len(sys.argv) > 2:
upstream = sys.argv[2]
else:
upstream = "origin/master"
mb = run_cmd(f"git merge-base {upstream} {commit}")
upstream = mb[0]
results_ok = []
results_fail = []
results_ign = []
os.makedirs(Path(TMP_FOLDER, WARN_FILE_NAME).parent, mode=0o755,
exist_ok=True)
files = run_cmd(f"git diff --diff-filter=AM --name-only {upstream} {commit}")
for fname in files:
if is_ignored(fname, allowed_files):
results_ign.append(fname)
continue
os.environ['DOXYGEN_INPUT'] = fname
try:
run_cmd_no_check("doxygen")
except subprocess.CalledProcessError as e:
print(f"\033[31m[FAIL] {e.returncode}\033[0m")
return False
with open(os.path.join(TMP_FOLDER, WARN_FILE_NAME)) as warn_log:
warnings = warn_log.read()
if len(warnings) == 0:
results_ok.append(fname)
else:
results_fail.append((fname, warnings))
for fname in results_ign:
print(f"\033[90m[ NA ] {fname}\033[0m")
for fname in results_ok:
print(f"\033[32m[ OK ] {fname}\033[0m")
for fname, warnings in results_fail:
print(f"\033[31m[FAIL] {fname}\033[0m")
print(warnings)
if len(results_fail) > 0:
print(f"\033[31mYour code has documentation style problems, see the logs "
f"for details.\033[0m")
return len(results_fail) == 0
if __name__ == "__main__":
if not main():
sys.exit(1)