~aleteoryx/muditaos

muditaos/config/style_check_hook.sh -rwxr-xr-x 6.5 KiB
a405cad6Aleteoryx trim readme 5 days ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
#!/usr/bin/env bash
# Copyright (c) 2017-2024, Mudita Sp. z.o.o. All rights reserved.
# For licensing, see https://github.com/mudita/MuditaOS/blob/master/LICENSE.md

set -e
set -o pipefail
# trap 'echo ERROR on line: $LINENO running command: $BASH_COMMAND ; trap - EXIT; exit $?' EXIT

# Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. 
# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

# taken from: https://raw.githubusercontent.com/andrewseidl/githook-clang-format/master/clang-format.hook
# - with just added check for cpp file & check for proper version of clang-format
# - with use of clang-format diff.py - for changed chunk changes only
# might be worth to consider: https://github.com/Sarcasm/run-clang-format

# shellcheck source=../config/format-config.sh
# shellcheck source=../config/clang/colors.sh
# shellcheck source=../config/clang/common.sh

L_GIT_DIR=$(git rev-parse --show-toplevel)
source $L_GIT_DIR/config/format-config.sh
source $L_GIT_DIR/config/clang/colors.sh
source $L_GIT_DIR/config/clang/clang-common.sh
CHANGE_TARGET=${CHANGE_TARGET:-master}


# if autoformatting was disabled by user - then ignore this commit hook
if [ "$DISABLE_AUTO_FORMATTING" -eq 1 ]; then
    [[ $VERBOSE ]] && echo "auto formatting is disabled"
    exit 0
fi

verify_clang_format_version

L_CLANG_TOOL=$(get_clang_format)
if ! [[ $L_CLANG_TOOL ]] || [[ $L_CLANG_TOOL == "" ]]; then
    [[ $VERBOSE ]] && echo "clang-format not found"
    exit 1
fi

L_CLANG_DIFF_TOOL=$(get_clang_format_diff)
if ! [[ $L_CLANG_DIFF_TOOL ]] || [[ $L_CLANG_DIFF_TOOL == "" ]]; then
    [[ $VERBOSE ]] && echo "clang-format-diff not found"
    exit 1
fi


check_file() {
    file="${1}"
    last_commit="${2}"
    if [ -f "${file}" ]; then
        #[[ $VERBOSE ]] && echo -en "Checking: \e[33m${file}\e[0m :\t"
        results["${file}"]="${OK}"
        case ${last_commit} in
        "True")
            if [[ ${FIX,,} == "true" ]]; then
                git diff -U0 --no-color remotes/origin/"${CHANGE_TARGET}"...HEAD "${file}" | ${L_CLANG_DIFF_TOOL} -style file -p1 -i
                STATUS=$(git status --short -- "${file}")
                if [ -n "${STATUS}" ]; then
                    git add "${file}"
                    results["${file}"]="${FIXED}";
                fi
            else
                OUT=$(git diff -U0 --no-color remotes/origin/"${CHANGE_TARGET}"...HEAD "${file}" | ${L_CLANG_DIFF_TOOL} -style file -p1 )
                if [ -n "${OUT}" ]; then
                    results["${file}"]="${ERROR}"
                    return 1
                fi
            fi
            ;;
        "Stage")
            if [[ ${FIX,,} == "true" ]]; then
                git diff -U0 --no-color --cached "${file}" | ${L_CLANG_DIFF_TOOL} -style file -p1 -i
                STATUS=$(git status --short -- "${file}")
                if [ -n "${STATUS}" ]; then
                    git add "${file}"
                    results["${file}"]="${FIXED}";
                fi
            else
                OUT=$(git diff -U0 --no-color --cached "${file}" | ${L_CLANG_DIFF_TOOL} -style file -p1)
                if [ -n "${OUT}" ]; then
                    results["${file}"]="${ERROR}"
                    return 1
                fi
            fi
            ;;
        "All")
            if [[ ${FIX,,} == "true" ]]; then
                ${L_CLANG_TOOL} -style file -i ${file}
                STATUS=$(git status --short -- "${file}")
                if [ -n "${STATUS}" ]; then
                    git add "${file}"
                    results["${file}"]="${FIXED}";
                fi
            else
                OUT=$(${L_CLANG_TOOL} -style file ${file})
                if [ -n "${OUT}" ]; then
                    results["${file}"]="${ERROR}"
                    return 1
                fi
            fi
            ;;
        *)
            OUT=$(git diff -U0 --no-color --cached "${file}" | ${L_CLANG_DIFF_TOOL} -style file -p1 )
            if [[ -n ${OUT} ]]; then
                results["${file}"]="${ERROR}"
                return 1
            fi
            ;;
        esac
    fi
    return 0
}

function help() {
        echo "Runs clang-format on source files"
        cat <<- EOM
		usage:
		   $0 [option]
		        --about             does nothing
		        --last              checks current branch against origin/master - doesn't fix
		        --branch-fix        checks current branch against origin/master and fixes errors - you have to 'git add' and 'git commit' them
		        --fix               fix style in currently staged files (ignores user.fixinstage variale), this is usefull for manual style applying
		        --all               check style in all files
		        --fix-all           fix style in all files
		
		If you would like to automatically fix style before commit
		add to your git config "user.fixinstage" variable with value "True"
		by calling:
		    git config user.fixinstage True
		EOM
}


case "${1}" in
    --about|--help )
        help
        FILES=''
        LAST=""
        exit 0
        ;;
    --last)
        FILES=$(git diff --name-only remotes/origin/"${CHANGE_TARGET}"...HEAD)
        LAST="True"
        FIX="false"
        ;;
    --branch-fix)
        FILES=$(git diff --name-only remotes/origin/"${CHANGE_TARGET}"...HEAD)
        LAST="True"
        FIX="true"
        ;;
    --fix)
        FILES=$(git diff-index --cached --name-only HEAD)
        LAST="Stage" 
        FIX="true"
        ;;
    --all)
        FILES=$(find $L_GIT_DIR -type f -name '*.cpp' -o -name '*.hpp' -o -name '*.c' -o -name '*.h' -o -name '*.cxx' -o -name '*.gcc' -o -name '*.cc')
        LAST="All" 
        FIX="false"
        ;;
    --fix-all)
        FILES=$(find $L_GIT_DIR -type f -name '*.cpp' -o -name '*.hpp' -o -name '*.c' -o -name '*.h' -o -name '*.cxx' -o -name '*.gcc' -o -name '*.cc')
        LAST="All" 
        FIX="true"
        ;;
    *)
        if [[ $# -ne 0 ]]; then
            echo "unknown parameters: '$*'"
            help
            exit 1
        fi
        FILES=$(git diff-index --cached --name-only HEAD)
        LAST="Stage" 
        FIX=$([[ $(git config user.fixinstage) ]] && git config user.fixinstage || echo "false")
        FIX=${FIX:-false}
        ;;
esac

declare -A results

EXIT_CODE=0
for file in ${FILES}; do
    if [[ ${file} =~ ^.*\.(cpp|hpp|c|h|cxx|gcc|cc)$ ]] && shouldnt_ignore ${file}; then
        check_file "${file}" ${LAST} || RESULT=$?
        if [[ ${RESULT} -eq 1 ]]; then
            EXIT_CODE=1
        fi
    fi
done

for FILE in "${!results[@]}"
do
    echo -e "  ${FILE} : ${results[${FILE}]}"
done

echo "exit: ${EXIT_CODE}"
exit ${EXIT_CODE}