mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager
synced 2024-10-14 20:18:39 +00:00
cae2011b08
The actual formatting depends on the version of clang-format. Print the used version, which is in particular interesting when we get an error in our gitlab-ci check (which uses the correct version).
218 lines
6 KiB
Bash
Executable file
218 lines
6 KiB
Bash
Executable file
#!/bin/bash
|
|
|
|
set -e
|
|
|
|
die() {
|
|
printf '%s\n' "$*" >&2
|
|
exit 1
|
|
}
|
|
|
|
EXCLUDE_PATHS_TOPLEVEL=(
|
|
"src/c-list"
|
|
"src/c-rbtree"
|
|
"src/c-siphash"
|
|
"src/c-stdaux"
|
|
"src/libnm-std-aux/unaligned-fundamental.h"
|
|
"src/libnm-std-aux/unaligned.h"
|
|
"src/libnm-systemd-core/src"
|
|
"src/libnm-systemd-shared/src"
|
|
"src/linux-headers"
|
|
"src/n-acd"
|
|
"src/n-dhcp4"
|
|
)
|
|
|
|
NM_ROOT="$(git rev-parse --show-toplevel)" || die "not inside a git repository"
|
|
NM_PREFIX="$(git rev-parse --show-prefix)" || die "not inside a git repository"
|
|
|
|
if [ ! -f "$NM_ROOT/.clang-format" ]; then
|
|
die "Error: the clang-format file in \"$NM_ROOT\" does not exist"
|
|
fi
|
|
|
|
if ! command -v clang-format &> /dev/null; then
|
|
die "Error: clang-format is not installed. On RHEL/Fedora/CentOS run 'dnf install clang-tools-extra'"
|
|
fi
|
|
|
|
if test -n "$NM_PREFIX"; then
|
|
EXCLUDE_PATHS=()
|
|
for e in "${EXCLUDE_PATHS_TOPLEVEL[@]}"; do
|
|
REGEX="^$NM_PREFIX([^/].*)$"
|
|
if [[ "$e" =~ $REGEX ]]; then
|
|
EXCLUDE_PATHS+=("${BASH_REMATCH[1]}")
|
|
fi
|
|
done
|
|
else
|
|
EXCLUDE_PATHS=("${EXCLUDE_PATHS_TOPLEVEL[@]}")
|
|
fi
|
|
|
|
FILES=()
|
|
HAS_EXPLICIT_FILES=0
|
|
SHOW_FILENAMES=0
|
|
TEST_ONLY=0
|
|
CHECK_UPSTREAM=
|
|
|
|
usage() {
|
|
printf "Usage: %s [OPTION]... [FILE]...\n" "$(basename "$0")"
|
|
printf "Reformat source files using NetworkManager's code-style.\n\n"
|
|
printf "If no file is given the script runs on the whole codebase.\n"
|
|
printf "OPTIONS:\n"
|
|
printf " -h Print this help message.\n"
|
|
printf " -i Reformat files (the default).\n"
|
|
printf " -n|--dry-run Only check the files (contrary to \"-i\").\n"
|
|
printf " -a|--all Check all files (the default).\n"
|
|
printf " -u|--upstream COMMIT Check only files from \`git diff --name-only COMMIT\` (contrary to \"-a\").\n"
|
|
printf " This also affects directories given in the [FILE] list, but not files.\n"
|
|
printf " If this is the last parameter and COMMIT is unspecified/empty, it defaults to \"main\".\n"
|
|
printf " -F|--fast Same as \`-u HEAD^\`.\n"
|
|
printf " --show-filenames Only print the filenames that would be checked/formatted\n"
|
|
printf " -- Separate options from filenames/directories\n"
|
|
}
|
|
|
|
ls_files_exist() {
|
|
local OLD_IFS="$IFS"
|
|
local f
|
|
|
|
IFS=$'\n'
|
|
for f in $(cat) ; do
|
|
test -f "$f" && printf '%s\n' "$f"
|
|
done
|
|
IFS="$OLD_IFS"
|
|
}
|
|
|
|
ls_files_filter() {
|
|
local OLD_IFS="$IFS"
|
|
local f
|
|
|
|
IFS=$'\n'
|
|
for f in $(cat) ; do
|
|
local found=1
|
|
local p
|
|
for p; do
|
|
[[ "$f" = "$p/"* ]] && found=
|
|
[[ "$f" = "$p" ]] && found=
|
|
done
|
|
test -n "$found" && printf '%s\n' "$f"
|
|
done
|
|
IFS="$OLD_IFS"
|
|
}
|
|
|
|
g_ls_files() {
|
|
local pattern="$1"
|
|
shift
|
|
|
|
if [ -z "$CHECK_UPSTREAM" ]; then
|
|
git ls-files -- "$pattern"
|
|
else
|
|
git diff --no-renames --name-only "$CHECK_UPSTREAM" -- "$pattern" \
|
|
| ls_files_exist
|
|
fi | ls_files_filter "$@"
|
|
}
|
|
|
|
HAD_DASHDASH=0
|
|
while (( $# )); do
|
|
if [ "$HAD_DASHDASH" = 0 ]; then
|
|
case "$1" in
|
|
-h)
|
|
usage
|
|
exit 0
|
|
;;
|
|
--show-filenames)
|
|
SHOW_FILENAMES=1
|
|
shift
|
|
continue
|
|
;;
|
|
-a|--all)
|
|
CHECK_UPSTREAM=
|
|
shift
|
|
continue
|
|
;;
|
|
-u|--upstream)
|
|
shift
|
|
CHECK_UPSTREAM="$1"
|
|
test -n "$CHECK_UPSTREAM" || CHECK_UPSTREAM=main
|
|
shift || :
|
|
continue
|
|
;;
|
|
-F|--fast)
|
|
CHECK_UPSTREAM='HEAD^'
|
|
shift
|
|
continue
|
|
;;
|
|
-n|--dry-run)
|
|
TEST_ONLY=1
|
|
shift
|
|
continue
|
|
;;
|
|
-i)
|
|
TEST_ONLY=0
|
|
shift
|
|
continue
|
|
;;
|
|
--)
|
|
HAD_DASHDASH=1
|
|
shift
|
|
continue
|
|
;;
|
|
esac
|
|
fi
|
|
if [ -d "$1" ]; then
|
|
while IFS='' read -r line;
|
|
do FILES+=("$line")
|
|
done < <(CHECK_UPSTREAM="$CHECK_UPSTREAM" g_ls_files "${1}/*.[hc]" "${EXCLUDE_PATHS[@]}")
|
|
elif [ -f "$1" ]; then
|
|
FILES+=("$1")
|
|
else
|
|
usage >&2
|
|
echo >&2
|
|
die "Unknown argument \"$1\" which also is neither a file nor a directory."
|
|
fi
|
|
shift
|
|
HAS_EXPLICIT_FILES=1
|
|
done
|
|
|
|
if [ $HAS_EXPLICIT_FILES = 0 ]; then
|
|
while IFS='' read -r line; do
|
|
FILES+=("$line")
|
|
done < <(CHECK_UPSTREAM="$CHECK_UPSTREAM" g_ls_files '*.[ch]' "${EXCLUDE_PATHS[@]}")
|
|
fi
|
|
|
|
if [ $SHOW_FILENAMES = 1 ]; then
|
|
for f in "${FILES[@]}" ; do
|
|
printf '%s\n' "$f"
|
|
done
|
|
exit 0
|
|
fi
|
|
|
|
if [ "${#FILES[@]}" = 0 ]; then
|
|
if [ -z "$CHECK_UPSTREAM" ]; then
|
|
die "Error: no files to check"
|
|
fi
|
|
exit 0
|
|
fi
|
|
|
|
FLAGS_TEST=( --Werror -n --ferror-limit=1 )
|
|
|
|
if [ $TEST_ONLY = 1 ]; then
|
|
# We assume that all formatting is correct. In that mode, passing
|
|
# all filenames to clang-format is significantly faster.
|
|
#
|
|
# Only in case of an error, we iterate over the files one by one
|
|
# until we find the first invalid file.
|
|
for f in "${FILES[@]}"; do
|
|
[ -f "$f" ] || die "Error: file \"$f\" does not exist (or is not a regular file)"
|
|
done
|
|
clang-format "${FLAGS_TEST[@]}" "${FILES[@]}" &>/dev/null && exit 0
|
|
for f in "${FILES[@]}"; do
|
|
[ -f "$f" ] || die "Error: file \"$f\" does not exist (or is not a regular file)"
|
|
if ! clang-format "${FLAGS_TEST[@]}" "$f" &>/dev/null; then
|
|
FF="$(mktemp)"
|
|
trap 'rm -f "$FF"' EXIT
|
|
clang-format "$f" 2>/dev/null > "$FF"
|
|
git --no-pager diff "$f" "$FF" || :
|
|
die "Error: file \"$f\" has style issues."$'\n'"Fix it by running \`\"$0\" -i \"$f\"\` using $(clang-format --version)"
|
|
fi
|
|
done
|
|
die "an unknown error happened."
|
|
fi
|
|
|
|
clang-format -i "${FILES[@]}"
|