diff options
| author | Michael Biebl <biebl@debian.org> | 2024-05-05 00:07:30 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2024-05-05 00:07:30 +0200 |
| commit | 34bb501be08aa2b313d88e67d6e0a7e0a3f9cfa6 (patch) | |
| tree | 4e6220877828be4c6f261de09ec0cb2d80e32389 /contrib/scripts/nm-code-format.sh | |
| parent | bba2e4b4de668db525cbfdfc35292e5a0b51671a (diff) | |
New upstream version 1.47.90 upstream/1.47.90
Diffstat (limited to 'contrib/scripts/nm-code-format.sh')
| -rwxr-xr-x | contrib/scripts/nm-code-format.sh | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/contrib/scripts/nm-code-format.sh b/contrib/scripts/nm-code-format.sh new file mode 100755 index 00000000..3c18cd77 --- /dev/null +++ b/contrib/scripts/nm-code-format.sh @@ -0,0 +1,222 @@ +#!/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" + if [ -n "${_NM_CODE_FORMAT_CONTAINER+x}" ] ; then + printf "\n" + printf "Command runs inside container image \"$_NM_CODE_FORMAT_CONTAINER\".\n" + printf "Delete/renew image with \`podman rmi \"$_NM_CODE_FORMAT_CONTAINER\"\`.\n" + fi +} + +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[@]}" |