format-code: simplify exclusion filter for clang
The clang-format linter calls have a custom ignore list. Write
a python script for reusable git-ignore-like filtering and switch
the clang-format linter call to use it.
Signed-off-by: Patrick Williams <patrick@stwcx.xyz>
Change-Id: I788c0e3de55fae592318a997b676c73a7f13e74c
diff --git a/config/lib/ignore-filter b/config/lib/ignore-filter
new file mode 100755
index 0000000..3373588
--- /dev/null
+++ b/config/lib/ignore-filter
@@ -0,0 +1,47 @@
+#!/usr/bin/env python3
+
+import argparse
+import fnmatch
+import itertools
+import os
+import pathlib
+import sys
+
+parser = argparse.ArgumentParser(
+ "ignore-filter",
+ description="Filter files from stdin using a .gitignore-style filter file",
+)
+parser.add_argument("filename", nargs="+", help="The filter file", type=str)
+
+args = parser.parse_args()
+
+ignore_patterns = list()
+for f in args.filename:
+ if not os.path.exists(f):
+ raise RuntimeError(f"File {args.filename} does not exist.")
+ with open(f, "r") as ignore_file:
+ for line in [i.strip() for i in ignore_file.readlines()]:
+ # Ignore comments.
+ if line.startswith("#"):
+ continue
+
+ # Drop leading "/" or "./" ( this isn't 100% correct for
+ # .gitignore format) .
+ if line.startswith("/"):
+ line = line[1:]
+ elif line.startswith("./"):
+ line = line[2:]
+
+ ignore_patterns.append(line)
+
+for c in sys.stdin:
+ candidate = c.strip()
+ match = False
+ for seg in itertools.accumulate(
+ pathlib.PurePath(candidate).parts, os.path.join
+ ):
+ if any(fnmatch.fnmatch(seg, i) for i in ignore_patterns):
+ match = True
+ break
+ if not match:
+ print(candidate)
diff --git a/scripts/format-code.sh b/scripts/format-code.sh
index 7fdbc52..83fbcd5 100755
--- a/scripts/format-code.sh
+++ b/scripts/format-code.sh
@@ -159,59 +159,17 @@
LINTER_REQUIRE+=([clang_format]="clang-format;.clang-format")
do_clang_format() {
- IGNORE_FILE=".clang-ignore"
- declare -a IGNORE_LIST
-
- if [[ -f "${IGNORE_FILE}" ]]; then
- readarray -t IGNORE_LIST < "${IGNORE_FILE}"
- fi
-
- ignorepaths=""
- ignorefiles=""
-
- for path in "${IGNORE_LIST[@]}"; do
- # Check for comment, line starting with space, or zero-length string.
- # Checking for [[:space:]] checks all options.
- if [[ -z "${path}" ]] || [[ "${path}" =~ ^(#|[[:space:]]).*$ ]]; then
- continue
- fi
-
- # All paths must start with ./ for find's path prune expectation.
- if [[ "${path}" =~ ^\.\/.+$ ]]; then
- ignorepaths+=" ${path}"
- else
- ignorefiles+=" ${path}"
- fi
- done
-
- searchfiles=""
- while read -r path; do
- # skip ignorefiles
- if [[ $ignorefiles == *"$(basename "${path}")"* ]]; then
- continue
- fi
-
- skip=false
- #skip paths in ingorepaths
- for pathname in $ignorepaths; do
- if [[ "./${path}" == "${pathname}"* ]]; then
- skip=true
- break
- fi
- done
-
- if [ "$skip" = true ]; then
- continue
- fi
- # shellcheck disable=2089
- searchfiles+="\"./${path}\" "
-
- # Get C and C++ files managed by git and skip the mako files
- done <<<"$(git ls-files | grep -e '\.[ch]pp$' -e '\.[ch]$' | grep -v '\.mako\.')"
echo -e " ${BLUE}Running clang-format${NORMAL}"
- # shellcheck disable=SC2090 disable=SC2086
- echo ${searchfiles} | xargs "${CLANG_FORMAT}" -i
+ files=$(git ls-files | \
+ grep -e '\.[ch]pp$' -e '\.[ch]$' | \
+ grep -v '\.mako\.')
+
+ if [ -e .clang-ignore ]; then
+ files=$("${CONFIG_PATH}/lib/ignore-filter" .clang-ignore <<< "${files}")
+ fi
+
+ xargs "${CLANG_FORMAT}" -i <<< "${files}"
}
function check_linter()