xref: /aosp_15_r20/external/libnl/tools/clang-format.sh (revision 4dc78e53d49367fa8e61b07018507c90983a077d)
1#!/bin/bash
2
3set -e
4
5die() {
6    printf '%s\n' "$*" >&2
7    exit 1
8}
9
10EXCLUDE_PATHS_TOPLEVEL=(
11    "include/linux-private"
12)
13
14# The following files are currently not formatted with clang.
15# Exclude them too.
16EXCLUDE_PATHS_TOPLEVEL+=(
17    "include/netlink/addr.h"
18    "include/netlink/attr.h"
19    "include/netlink/cache-api.h"
20    "include/netlink/cache.h"
21    "include/netlink/cli/addr.h"
22    "include/netlink/cli/cls.h"
23    "include/netlink/cli/link.h"
24    "include/netlink/cli/mdb.h"
25    "include/netlink/cli/neigh.h"
26    "include/netlink/cli/qdisc.h"
27    "include/netlink/cli/route.h"
28    "include/netlink/cli/tc.h"
29    "include/netlink/cli/utils.h"
30    "include/netlink/data.h"
31    "include/netlink/errno.h"
32    "include/netlink/fib_lookup/lookup.h"
33    "include/netlink/fib_lookup/request.h"
34    "include/netlink/genl/ctrl.h"
35    "include/netlink/genl/family.h"
36    "include/netlink/genl/genl.h"
37    "include/netlink/genl/mngt.h"
38    "include/netlink/handlers.h"
39    "include/netlink/hash.h"
40    "include/netlink/hashtable.h"
41    "include/netlink/idiag/idiagnl.h"
42    "include/netlink/idiag/meminfo.h"
43    "include/netlink/idiag/msg.h"
44    "include/netlink/idiag/req.h"
45    "include/netlink/idiag/vegasinfo.h"
46    "include/netlink/list.h"
47    "include/netlink/msg.h"
48    "include/netlink/netfilter/ct.h"
49    "include/netlink/netfilter/exp.h"
50    "include/netlink/netfilter/log.h"
51    "include/netlink/netfilter/log_msg.h"
52    "include/netlink/netfilter/netfilter.h"
53    "include/netlink/netfilter/nfnl.h"
54    "include/netlink/netfilter/queue.h"
55    "include/netlink/netfilter/queue_msg.h"
56    "include/netlink/netlink-compat.h"
57    "include/netlink/netlink-kernel.h"
58    "include/netlink/netlink.h"
59    "include/netlink/object.h"
60    "include/netlink/route/act/skbedit.h"
61    "include/netlink/route/action.h"
62    "include/netlink/route/addr.h"
63    "include/netlink/route/class.h"
64    "include/netlink/route/classifier.h"
65    "include/netlink/route/cls/basic.h"
66    "include/netlink/route/cls/cgroup.h"
67    "include/netlink/route/cls/ematch.h"
68    "include/netlink/route/cls/ematch/cmp.h"
69    "include/netlink/route/cls/ematch/meta.h"
70    "include/netlink/route/cls/ematch/nbyte.h"
71    "include/netlink/route/cls/ematch/text.h"
72    "include/netlink/route/cls/flower.h"
73    "include/netlink/route/cls/fw.h"
74    "include/netlink/route/cls/matchall.h"
75    "include/netlink/route/cls/police.h"
76    "include/netlink/route/cls/u32.h"
77    "include/netlink/route/link.h"
78    "include/netlink/route/link/api.h"
79    "include/netlink/route/link/bonding.h"
80    "include/netlink/route/link/bridge.h"
81    "include/netlink/route/link/can.h"
82    "include/netlink/route/link/geneve.h"
83    "include/netlink/route/link/inet.h"
84    "include/netlink/route/link/inet6.h"
85    "include/netlink/route/link/info-api.h"
86    "include/netlink/route/link/ip6gre.h"
87    "include/netlink/route/link/ip6tnl.h"
88    "include/netlink/route/link/ip6vti.h"
89    "include/netlink/route/link/ipgre.h"
90    "include/netlink/route/link/ipip.h"
91    "include/netlink/route/link/ipvlan.h"
92    "include/netlink/route/link/ipvti.h"
93    "include/netlink/route/link/macsec.h"
94    "include/netlink/route/link/macvlan.h"
95    "include/netlink/route/link/macvtap.h"
96    "include/netlink/route/link/ppp.h"
97    "include/netlink/route/link/sit.h"
98    "include/netlink/route/link/sriov.h"
99    "include/netlink/route/link/team.h"
100    "include/netlink/route/link/vlan.h"
101    "include/netlink/route/link/vxlan.h"
102    "include/netlink/route/link/xfrmi.h"
103    "include/netlink/route/mdb.h"
104    "include/netlink/route/neighbour.h"
105    "include/netlink/route/neightbl.h"
106    "include/netlink/route/netconf.h"
107    "include/netlink/route/nexthop.h"
108    "include/netlink/route/pktloc.h"
109    "include/netlink/route/qdisc.h"
110    "include/netlink/route/qdisc/cbq.h"
111    "include/netlink/route/qdisc/dsmark.h"
112    "include/netlink/route/qdisc/fifo.h"
113    "include/netlink/route/qdisc/fq_codel.h"
114    "include/netlink/route/qdisc/hfsc.h"
115    "include/netlink/route/qdisc/htb.h"
116    "include/netlink/route/qdisc/mqprio.h"
117    "include/netlink/route/qdisc/netem.h"
118    "include/netlink/route/qdisc/plug.h"
119    "include/netlink/route/qdisc/prio.h"
120    "include/netlink/route/qdisc/red.h"
121    "include/netlink/route/qdisc/sfq.h"
122    "include/netlink/route/route.h"
123    "include/netlink/route/rtnl.h"
124    "include/netlink/route/rule.h"
125    "include/netlink/route/tc-api.h"
126    "include/netlink/route/tc.h"
127    "include/netlink/socket.h"
128    "include/netlink/types.h"
129    "include/netlink/utils.h"
130    "include/netlink/xfrm/ae.h"
131    "include/netlink/xfrm/lifetime.h"
132    "include/netlink/xfrm/sa.h"
133    "include/netlink/xfrm/selector.h"
134    "include/netlink/xfrm/sp.h"
135    "include/netlink/xfrm/template.h"
136    "include/nl-priv-dynamic-core/cache-api.h"
137    "include/nl-priv-dynamic-core/object-api.h"
138    "lib/addr.c"
139    "lib/attr.c"
140    "lib/cache.c"
141    "lib/cache_mngr.c"
142    "lib/cache_mngt.c"
143    "lib/cli/cls/basic.c"
144    "lib/cli/cls/cgroup.c"
145    "lib/cli/qdisc/bfifo.c"
146    "lib/cli/qdisc/blackhole.c"
147    "lib/cli/qdisc/fq_codel.c"
148    "lib/cli/qdisc/hfsc.c"
149    "lib/cli/qdisc/htb.c"
150    "lib/cli/qdisc/ingress.c"
151    "lib/cli/qdisc/pfifo.c"
152    "lib/cli/qdisc/plug.c"
153    "lib/data.c"
154    "lib/error.c"
155    "lib/fib_lookup/lookup.c"
156    "lib/fib_lookup/request.c"
157    "lib/genl/ctrl.c"
158    "lib/genl/family.c"
159    "lib/genl/genl.c"
160    "lib/genl/mngt.c"
161    "lib/genl/nl-genl.h"
162    "lib/handlers.c"
163    "lib/hash.c"
164    "lib/hashtable.c"
165    "lib/idiag/idiag.c"
166    "lib/idiag/idiag_meminfo_obj.c"
167    "lib/idiag/idiag_msg_obj.c"
168    "lib/idiag/idiag_req_obj.c"
169    "lib/idiag/idiag_vegasinfo_obj.c"
170    "lib/mpls.c"
171    "lib/mpls.h"
172    "lib/msg.c"
173    "lib/netfilter/ct.c"
174    "lib/netfilter/ct_obj.c"
175    "lib/netfilter/exp.c"
176    "lib/netfilter/exp_obj.c"
177    "lib/netfilter/log.c"
178    "lib/netfilter/log_msg.c"
179    "lib/netfilter/log_msg_obj.c"
180    "lib/netfilter/log_obj.c"
181    "lib/netfilter/netfilter.c"
182    "lib/netfilter/nfnl.c"
183    "lib/netfilter/queue.c"
184    "lib/netfilter/queue_msg.c"
185    "lib/netfilter/queue_msg_obj.c"
186    "lib/netfilter/queue_obj.c"
187    "lib/nl-core.h"
188    "lib/nl.c"
189    "lib/object.c"
190    "lib/route/act.c"
191    "lib/route/act/gact.c"
192    "lib/route/act/mirred.c"
193    "lib/route/act/skbedit.c"
194    "lib/route/act/vlan.c"
195    "lib/route/addr.c"
196    "lib/route/class.c"
197    "lib/route/classid.c"
198    "lib/route/cls.c"
199    "lib/route/cls/basic.c"
200    "lib/route/cls/cgroup.c"
201    "lib/route/cls/ematch.c"
202    "lib/route/cls/ematch/cmp.c"
203    "lib/route/cls/ematch/container.c"
204    "lib/route/cls/ematch/meta.c"
205    "lib/route/cls/ematch/nbyte.c"
206    "lib/route/cls/ematch/text.c"
207    "lib/route/cls/flower.c"
208    "lib/route/cls/fw.c"
209    "lib/route/cls/mall.c"
210    "lib/route/cls/police.c"
211    "lib/route/cls/u32.c"
212    "lib/route/link-sriov.h"
213    "lib/route/link.c"
214    "lib/route/link/api.c"
215    "lib/route/link/bonding.c"
216    "lib/route/link/bridge.c"
217    "lib/route/link/can.c"
218    "lib/route/link/dummy.c"
219    "lib/route/link/geneve.c"
220    "lib/route/link/ifb.c"
221    "lib/route/link/inet.c"
222    "lib/route/link/inet6.c"
223    "lib/route/link/ip6gre.c"
224    "lib/route/link/ip6tnl.c"
225    "lib/route/link/ip6vti.c"
226    "lib/route/link/ipgre.c"
227    "lib/route/link/ipip.c"
228    "lib/route/link/ipvlan.c"
229    "lib/route/link/ipvti.c"
230    "lib/route/link/link-api.h"
231    "lib/route/link/macsec.c"
232    "lib/route/link/macvlan.c"
233    "lib/route/link/ppp.c"
234    "lib/route/link/sit.c"
235    "lib/route/link/sriov.c"
236    "lib/route/link/team.c"
237    "lib/route/link/veth.c"
238    "lib/route/link/vlan.c"
239    "lib/route/link/vrf.c"
240    "lib/route/link/vxlan.c"
241    "lib/route/link/xfrmi.c"
242    "lib/route/mdb.c"
243    "lib/route/neigh.c"
244    "lib/route/netconf.c"
245    "lib/route/nexthop-encap.h"
246    "lib/route/nexthop.c"
247    "lib/route/nexthop_encap.c"
248    "lib/route/nh_encap_mpls.c"
249    "lib/route/pktloc.c"
250    "lib/route/qdisc.c"
251    "lib/route/qdisc/blackhole.c"
252    "lib/route/qdisc/cbq.c"
253    "lib/route/qdisc/dsmark.c"
254    "lib/route/qdisc/fifo.c"
255    "lib/route/qdisc/fq_codel.c"
256    "lib/route/qdisc/hfsc.c"
257    "lib/route/qdisc/htb.c"
258    "lib/route/qdisc/ingress.c"
259    "lib/route/qdisc/mqprio.c"
260    "lib/route/qdisc/netem.c"
261    "lib/route/qdisc/plug.c"
262    "lib/route/qdisc/prio.c"
263    "lib/route/qdisc/red.c"
264    "lib/route/qdisc/sfq.c"
265    "lib/route/qdisc/tbf.c"
266    "lib/route/route.c"
267    "lib/route/route_obj.c"
268    "lib/route/route_utils.c"
269    "lib/route/rtnl.c"
270    "lib/route/rule.c"
271    "lib/route/tc-api.h"
272    "lib/route/tc.c"
273    "lib/socket.c"
274    "lib/utils.c"
275    "lib/version.c"
276    "lib/xfrm/ae.c"
277    "lib/xfrm/lifetime.c"
278    "lib/xfrm/sa.c"
279    "lib/xfrm/selector.c"
280    "lib/xfrm/sp.c"
281    "lib/xfrm/template.c"
282    "python/netlink/utils.h"
283    "src/genl-ctrl-list.c"
284    "src/idiag-socket-details.c"
285    "src/lib/addr.c"
286    "src/lib/cls.c"
287    "src/lib/ct.c"
288    "src/lib/exp.c"
289    "src/lib/link.c"
290    "src/lib/neigh.c"
291    "src/lib/route.c"
292    "src/lib/tc.c"
293    "src/lib/utils.c"
294    "src/nf-ct-add.c"
295    "src/nf-ct-events.c"
296    "src/nf-ct-list.c"
297    "src/nf-exp-add.c"
298    "src/nf-exp-delete.c"
299    "src/nf-exp-list.c"
300    "src/nf-log.c"
301    "src/nf-monitor.c"
302    "src/nf-queue.c"
303    "src/nl-addr-add.c"
304    "src/nl-addr-delete.c"
305    "src/nl-addr-list.c"
306    "src/nl-class-add.c"
307    "src/nl-class-delete.c"
308    "src/nl-class-list.c"
309    "src/nl-classid-lookup.c"
310    "src/nl-cls-add.c"
311    "src/nl-cls-delete.c"
312    "src/nl-cls-list.c"
313    "src/nl-fib-lookup.c"
314    "src/nl-link-enslave.c"
315    "src/nl-link-list.c"
316    "src/nl-link-release.c"
317    "src/nl-link-set.c"
318    "src/nl-link-stats.c"
319    "src/nl-list-caches.c"
320    "src/nl-list-sockets.c"
321    "src/nl-monitor.c"
322    "src/nl-neigh-add.c"
323    "src/nl-neigh-delete.c"
324    "src/nl-neigh-list.c"
325    "src/nl-neightbl-list.c"
326    "src/nl-pktloc-lookup.c"
327    "src/nl-qdisc-add.c"
328    "src/nl-qdisc-delete.c"
329    "src/nl-qdisc-list.c"
330    "src/nl-route-add.c"
331    "src/nl-route-delete.c"
332    "src/nl-route-get.c"
333    "src/nl-route-list.c"
334    "src/nl-rule-list.c"
335    "src/nl-tctree-list.c"
336    "src/nl-util-addr.c"
337    "tests/test-cache-mngr.c"
338    "tests/test-complex-HTB-with-hash-filters.c"
339    "tests/test-create-bridge.c"
340    "tests/test-create-geneve.c"
341    "tests/test-create-ip6tnl.c"
342    "tests/test-create-ipgre.c"
343    "tests/test-create-ipgretap.c"
344    "tests/test-create-ipip.c"
345    "tests/test-create-ipvti.c"
346    "tests/test-create-macsec.c"
347    "tests/test-create-macvlan.c"
348    "tests/test-create-macvtap.c"
349    "tests/test-create-sit.c"
350    "tests/test-create-veth.c"
351    "tests/test-create-xfrmi.c"
352    "tests/test-genl.c"
353    "tests/test-nf-cache-mngr.c"
354    "tests/test-socket-creation.c"
355    "tests/test-u32-filter-with-actions.c"
356)
357
358DIR_ROOT="$(git rev-parse --show-toplevel)" || die "not inside a git repository"
359DIR_PREFIX="$(git rev-parse --show-prefix)" || die "not inside a git repository"
360
361if [ ! -f "$DIR_ROOT/.clang-format" ]; then
362    die "Error: the clang-format file in \"$DIR_ROOT\" does not exist"
363fi
364
365if ! command -v clang-format &> /dev/null; then
366    die "Error: clang-format is not installed. On RHEL/Fedora/CentOS run 'dnf install clang-tools-extra'"
367fi
368
369if test -n "$DIR_PREFIX"; then
370    EXCLUDE_PATHS=()
371    for e in "${EXCLUDE_PATHS_TOPLEVEL[@]}"; do
372        REGEX="^$DIR_PREFIX([^/].*)$"
373        if [[ "$e" =~ $REGEX ]]; then
374            EXCLUDE_PATHS+=("${BASH_REMATCH[1]}")
375        fi
376    done
377else
378    EXCLUDE_PATHS=("${EXCLUDE_PATHS_TOPLEVEL[@]}")
379fi
380
381FILES=()
382HAS_EXPLICIT_FILES=0
383SHOW_FILENAMES=0
384TEST_ONLY=0
385CHECK_UPSTREAM=
386
387usage() {
388    printf "Usage: %s [OPTION]... [FILE]...\n" "$(basename "$0")"
389    printf "Reformat source files using clang-format.\n\n"
390    printf "If no file is given the script runs on the whole codebase.\n"
391    printf "OPTIONS:\n"
392    printf "    -h                    Print this help message.\n"
393    printf "    -i                    Reformat files (the default).\n"
394    printf "    -n|--dry-run          Only check the files (contrary to \"-i\").\n"
395    printf "    -a|--all              Check all files (the default).\n"
396    printf "    -u|--upstream COMMIT  Check only files from \`git diff --name-only COMMIT\` (contrary to \"-a\").\n"
397    printf "                          This also affects directories given in the [FILE] list, but not files.\n"
398    printf "                          If this is the last parameter and COMMIT is unspecified/empty, it defaults to \"main\".\n"
399    printf "    -F|--fast             Same as \`-u HEAD^\`.\n"
400    printf "    -l|--show-filenames   Only print the filenames that would be checked/formatted\n"
401    printf "    --                    Separate options from filenames/directories\n"
402    if [ -n "${_LIBNL_CODE_FORMAT_CONTAINER+x}" ] ; then
403        printf "\n"
404        printf "Command runs inside container image \"$_LIBNL_CODE_FORMAT_CONTAINER\".\n"
405        printf "Delete/renew image with \`podman rmi \"$_LIBNL_CODE_FORMAT_CONTAINER\"\`.\n"
406    fi
407}
408
409ls_files_exist() {
410    local OLD_IFS="$IFS"
411    local f
412
413    IFS=$'\n'
414    for f in $(cat) ; do
415        test -f "$f" && printf '%s\n' "$f"
416    done
417    IFS="$OLD_IFS"
418}
419
420ls_files_filter() {
421    local OLD_IFS="$IFS"
422    local f
423
424    IFS=$'\n'
425    for f in $(cat) ; do
426        local found=1
427        local p
428        for p; do
429            [[ "$f" = "$p/"* ]] && found=
430            [[ "$f" = "$p" ]] && found=
431        done
432        test -n "$found" && printf '%s\n' "$f"
433    done
434    IFS="$OLD_IFS"
435}
436
437g_ls_files() {
438    local pattern="$1"
439    shift
440
441    if [ -z "$CHECK_UPSTREAM" ]; then
442        git ls-files -- "$pattern"
443    else
444        git diff --no-renames --name-only "$CHECK_UPSTREAM" -- "$pattern" \
445            | ls_files_exist
446    fi | ls_files_filter "$@"
447}
448
449HAD_DASHDASH=0
450while (( $# )); do
451    if [ "$HAD_DASHDASH" = 0 ]; then
452        case "$1" in
453            -h)
454                usage
455                exit 0
456                ;;
457            -l|--show-filenames)
458                SHOW_FILENAMES=1
459                shift
460                continue
461                ;;
462            -a|--all)
463                CHECK_UPSTREAM=
464                shift
465                continue
466                ;;
467            -u|--upstream)
468                shift
469                CHECK_UPSTREAM="$1"
470                test -n "$CHECK_UPSTREAM" || CHECK_UPSTREAM=main
471                shift || :
472                continue
473                ;;
474            -F|--fast)
475                CHECK_UPSTREAM='HEAD^'
476                shift
477                continue
478                ;;
479            -n|--dry-run)
480                TEST_ONLY=1
481                shift
482                continue
483                ;;
484            -i)
485                TEST_ONLY=0
486                shift
487                continue
488                ;;
489            --)
490                HAD_DASHDASH=1
491                shift
492                continue
493                ;;
494        esac
495    fi
496    if [ -d "$1" ]; then
497        while IFS='' read -r line;
498            do FILES+=("$line")
499        done < <(CHECK_UPSTREAM="$CHECK_UPSTREAM" g_ls_files "${1}/*.[hc]" "${EXCLUDE_PATHS[@]}")
500    elif [ -f "$1" ]; then
501        FILES+=("$1")
502    else
503        usage >&2
504        echo >&2
505        die "Unknown argument \"$1\" which also is neither a file nor a directory."
506    fi
507    shift
508    HAS_EXPLICIT_FILES=1
509done
510
511if [ $HAS_EXPLICIT_FILES = 0 ]; then
512    while IFS='' read -r line; do
513        FILES+=("$line")
514    done < <(CHECK_UPSTREAM="$CHECK_UPSTREAM" g_ls_files '*.[ch]' "${EXCLUDE_PATHS[@]}")
515fi
516
517if [ $SHOW_FILENAMES = 1 ]; then
518    for f in "${FILES[@]}" ; do
519        printf '%s\n' "$f"
520    done
521    exit 0
522fi
523
524if [ "${#FILES[@]}" = 0 ]; then
525    if [ -z "$CHECK_UPSTREAM" ]; then
526        die "Error: no files to check"
527    fi
528    exit 0
529fi
530
531FLAGS_TEST=( --Werror -n --ferror-limit=1 )
532
533if [ $TEST_ONLY = 1 ]; then
534    # We assume that all formatting is correct. In that mode, passing
535    # all filenames to clang-format is significantly faster.
536    #
537    # Only in case of an error, we iterate over the files one by one
538    # until we find the first invalid file.
539    for f in "${FILES[@]}"; do
540        [ -f "$f" ] || die "Error: file \"$f\" does not exist (or is not a regular file)"
541    done
542    clang-format "${FLAGS_TEST[@]}" "${FILES[@]}" &>/dev/null && exit 0
543    for f in "${FILES[@]}"; do
544        [ -f "$f" ] || die "Error: file \"$f\" does not exist (or is not a regular file)"
545        if ! clang-format "${FLAGS_TEST[@]}" "$f" &>/dev/null; then
546            FF="$(mktemp)"
547            trap 'rm -f "$FF"' EXIT
548            clang-format "$f" 2>/dev/null > "$FF"
549            git --no-pager diff "$f" "$FF" || :
550            FEDORA_VERSION="$(sed -n 's/^      image: fedora:\([0-9]\+\)$/\1/p' .github/workflows/ci.yml)"
551            die "Error: file \"$f\" has style issues."$'\n'"Fix it by running \`\"$0\"\` using $(clang-format --version)
552Alternatively, run \`./tools/clang-format-container.sh\` to use a podman container named \"libnl-code-format-f$FEDORA_VERSION\"."
553        fi
554    done
555    die "an unknown error happened."
556fi
557
558clang-format -i "${FILES[@]}"
559