mirror of
https://github.com/Llewellynvdm/conky.git
synced 2024-11-18 02:55:12 +00:00
164 lines
5.0 KiB
Python
164 lines
5.0 KiB
Python
|
#!/usr/bin/env python
|
||
|
|
||
|
import argparse
|
||
|
import os
|
||
|
import sys
|
||
|
import subprocess
|
||
|
|
||
|
|
||
|
def check_file(filename, excludes, extensions):
|
||
|
"""
|
||
|
Check if a file should be included in our check
|
||
|
"""
|
||
|
name, ext = os.path.splitext(filename)
|
||
|
|
||
|
if len(ext) > 0 and ext in extensions:
|
||
|
if len(excludes) == 0:
|
||
|
return True
|
||
|
|
||
|
for exclude in excludes:
|
||
|
if exclude in filename:
|
||
|
return False
|
||
|
|
||
|
return True
|
||
|
|
||
|
return False
|
||
|
|
||
|
|
||
|
def check_directory(directory, excludes, extensions):
|
||
|
output = []
|
||
|
|
||
|
if len(excludes) > 0:
|
||
|
for exclude in excludes:
|
||
|
if exclude in directory:
|
||
|
directory_excluded = False
|
||
|
return output
|
||
|
|
||
|
for root, _, files in os.walk(directory):
|
||
|
for file in files:
|
||
|
filename = os.path.join(root, file)
|
||
|
if check_file(filename, excludes, extensions):
|
||
|
print("Will check file [{}]".format(filename))
|
||
|
output.append(filename)
|
||
|
return output
|
||
|
|
||
|
def get_git_root(git_bin):
|
||
|
cmd = [git_bin, "rev-parse", "--show-toplevel"]
|
||
|
try:
|
||
|
return subprocess.check_output(cmd).strip()
|
||
|
except subprocess.CalledProcessError, e:
|
||
|
print("Error calling git [{}]".format(e))
|
||
|
raise
|
||
|
|
||
|
def clean_git_filename(line):
|
||
|
"""
|
||
|
Takes a line from git status --porcelain and returns the filename
|
||
|
"""
|
||
|
file = None
|
||
|
git_status = line[:2]
|
||
|
# Not an exhaustive list of git status output but should
|
||
|
# be enough for this case
|
||
|
# check if this is a delete
|
||
|
if 'D' in git_status:
|
||
|
return None
|
||
|
# ignored file
|
||
|
if '!' in git_status:
|
||
|
return None
|
||
|
# Covers renamed files
|
||
|
if '->' in line:
|
||
|
file = line[3:].split('->')[-1].strip()
|
||
|
else:
|
||
|
file = line[3:].strip()
|
||
|
|
||
|
return file
|
||
|
|
||
|
|
||
|
def get_changed_files(git_bin, excludes, file_extensions):
|
||
|
"""
|
||
|
Run git status and return the list of changed files
|
||
|
"""
|
||
|
extensions = file_extensions.split(",")
|
||
|
# arguments coming from cmake will be *.xx. We want to remove the *
|
||
|
for i, extension in enumerate(extensions):
|
||
|
if extension[0] == '*':
|
||
|
extensions[i] = extension[1:]
|
||
|
|
||
|
git_root = get_git_root(git_bin)
|
||
|
|
||
|
cmd = [git_bin, "status", "--porcelain", "--ignore-submodules"]
|
||
|
print("git cmd = {}".format(cmd))
|
||
|
output = []
|
||
|
returncode = 0
|
||
|
try:
|
||
|
cmd_output = subprocess.check_output(cmd)
|
||
|
for line in cmd_output.split('\n'):
|
||
|
if len(line) > 0:
|
||
|
file = clean_git_filename(line)
|
||
|
if not file:
|
||
|
continue
|
||
|
file = os.path.join(git_root, file)
|
||
|
|
||
|
if file[-1] == "/":
|
||
|
directory_files = check_directory(
|
||
|
file, excludes, file_extensions)
|
||
|
output = output + directory_files
|
||
|
else:
|
||
|
if check_file(file, excludes, file_extensions):
|
||
|
print("Will check file [{}]".format(file))
|
||
|
output.append(file)
|
||
|
|
||
|
except subprocess.CalledProcessError, e:
|
||
|
print("Error calling git [{}]".format(e))
|
||
|
returncode = e.returncode
|
||
|
|
||
|
return output, returncode
|
||
|
|
||
|
|
||
|
def run_clang_format(clang_format_bin, changed_files):
|
||
|
"""
|
||
|
Run clang format on a list of files
|
||
|
@return 0 if formatted correctly.
|
||
|
"""
|
||
|
if len(changed_files) == 0:
|
||
|
return 0
|
||
|
cmd = [clang_format_bin, "-style=file",
|
||
|
"-output-replacements-xml"] + changed_files
|
||
|
print("clang-format cmd = {}".format(cmd))
|
||
|
try:
|
||
|
cmd_output = subprocess.check_output(cmd)
|
||
|
if "replacement offset" in cmd_output:
|
||
|
print("ERROR: Changed files don't match format")
|
||
|
return 1
|
||
|
except subprocess.CalledProcessError, e:
|
||
|
print("Error calling clang-format [{}]".format(e))
|
||
|
return e.returncode
|
||
|
|
||
|
return 0
|
||
|
|
||
|
|
||
|
def cli():
|
||
|
# global params
|
||
|
parser = argparse.ArgumentParser(prog='clang-format-check-changed',
|
||
|
description='Checks if files chagned in git match the .clang-format specification')
|
||
|
parser.add_argument("--file-extensions", type=str,
|
||
|
default=".cpp,.h,.cxx,.hxx,.hpp,.cc,.ipp",
|
||
|
help="Comma seperated list of file extensions to check")
|
||
|
parser.add_argument('--exclude', action='append', default=[],
|
||
|
help='Will not match the files / directories with these in the name')
|
||
|
parser.add_argument('--clang-format-bin', type=str, default="clang-format",
|
||
|
help="The clang format binary")
|
||
|
parser.add_argument('--git-bin', type=str, default="git",
|
||
|
help="The git binary")
|
||
|
args = parser.parse_args()
|
||
|
|
||
|
# Run gcovr to get the .gcda files form .gcno
|
||
|
changed_files, returncode = get_changed_files(
|
||
|
args.git_bin, args.exclude, args.file_extensions)
|
||
|
if returncode != 0:
|
||
|
return returncode
|
||
|
|
||
|
return run_clang_format(args.clang_format_bin, changed_files)
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
sys.exit(cli())
|