~aleteoryx/muditaos

f0d6d4b641744bf82f312ce6c6881ee1c43e50ab — Adam Dobrowolski 4 years ago 81adfe4
[EGD-5238] Added tidy target to CI to inform about added tidy issues

* Small fixups based on shellceck
* Tool now:
    can:
    * take diffs and pass it to clang-tidy
    cant:
    * set error on warnings/errors (errno)
    * copy compilation_database.json and sanitize it
M .clang-tidy => .clang-tidy +0 -2
@@ 52,8 52,6 @@ CheckOptions:
    value:           '::realloc'
  - key:             cppcoreguidelines-pro-bounds-constant-array-index.GslHeader
    value:           ''
  - key:             cppcoreguidelines-pro-bounds-constant-array-index.IncludeStyle
    value:           '1'
  - key:             cppcoreguidelines-pro-type-member-init.IgnoreArrays
    value:           '0'
  - key:             cppcoreguidelines-special-member-functions.AllowMissingMoveFunctions

M .github/workflows/main.yml => .github/workflows/main.yml +2 -0
@@ 36,6 36,8 @@ jobs:
        run: config/license_header_check.sh --ci --check-only
      - name: Style checking
        run: ./config/style_check_hook.sh --last
      - name: Clang tidy check
        run: ./config/clang_check.sh

  build_rt1051_binary:
    name: build rt1051 binary

A config/clang/clang-common.sh => config/clang/clang-common.sh +68 -0
@@ 0,0 1,68 @@
#!/bin/env bash
# Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

set -eo pipefail

verify_clang_format_version()
{
    # check if clang-format in path is in proper version, version is 3rd column in `clang-format --version`
    local version
    version=$( [[ $(which clang-format) ]] && (clang-format --version | cut -d ' ' -f 3 | cut -d '.' -f 1) || echo "0")
    # check for either clang-format or clang-format-9
    if [[ $version -lt 10 && ! $(which clang-format-10) ]]; then
        cat << EOF >&1
Either install:
    clang-format in at least version 10 and set as default"
    or
    clang-format-10

    Your clang format version in path used:
        $(clang-format --version):
        $(clang-format-10 --version)
    git commit aborted"
EOF
        exit 1
    fi
}

## find `what` from list of directories `arr`
get_tool() {
    local what="$1"; shift
    local arr=("$@")

    local tool="";
    for el in ${arr[*]}; do
        if [[ -f "${el}" ]]; then
            tool=${el}
            break
        fi
    done
    if [[ ${tool} == "" ]]; then
        echo "$what not found in path and: ${arr[*]}" > /dev/stderr
        exit 2
    fi
    echo "${tool}"
}

## Search for clang-format-diff.py
get_clang_format() {
    local searchpaths=(
        "$(which "clang-format-diff.py" 2>/dev/null 1>/dev/null)"  # clang-format-diff in path
        "/usr/share/clang/clang-format-*/clang-format-diff.py"     # clang-format-diff location on Ubuntu/Debian
        "/usr/share/clang/clang-format-diff.py"                    # clang-format_diff location on Arch last resort
    )
    get_tool "clang-format-diff.py" "${searchpaths[@]}"
}

## search for clang-tidy-diff
get_clang_tidy()
{
    local searchpaths=(
        "$(which "clang-tidy-diff.py" 2>/dev/null 1>/dev/null)"  # clang-format-diff in path
        "/usr/bin/clang-tidy-diff-10.py"                         # clang-format-diff location on Ubuntu
        "/usr/share/clang/clang-tidy-*/clang-tidy-diff.py"       # clang-format-diff location on Debian
        "/usr/share/clang/clang-tidy-diff.py"                    # clang-format_diff location on Arch last resort
    )
    get_tool "clang-tidy-diff.py" "${searchpaths[@]}"
}

A config/clang/colors.sh => config/clang/colors.sh +12 -0
@@ 0,0 1,12 @@
#!/bin/env bash
# Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

export RED='\e[38;2;255;13;0m'
export YELLOW="\e[38;2;255;232;0m"
export GREEN="\e[38;2;0;222;27m"
export ORANGE="\e[38;2;255;100;0m"

export OK="${GREEN}OK!\e[0m"
export ERROR="${RED}Error!\e[0m"
export FIXED="${YELLOW}Fixed!\e[0m"

A config/clang_check.sh => config/clang_check.sh +72 -0
@@ 0,0 1,72 @@
#!/bin/env bash
# Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

set -euo pipefail

# 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/clang-common.sh
source $L_GIT_DIR/config/clang/colors.sh

help()
{
    cat <<- EOF
clang tidy diff tool used to perform check on our sources uses 2 defaults:
    .clang-tidy                 : configuration file, from the place where command is run
    compile_commands.json   : compile data, as well from the place where command is run
EOF
}

get_files_to_check()
{
    local files
    local endlist=()

    files=$(git diff -U0 --name-only remotes/origin/master...HEAD)
    for file in ${files}; do
        if [[ ${file} =~ ^.*\.(cpp|hpp|c|h|cxx|gcc|cc)$ ]] && shouldnt_ignore "${file}"; then
            endlist+=("$file")
        fi
    done
    echo "${endlist[*]}"
}

# if not exists create
# could be in better place than tmp
get_compile_commands()
{
    [[ -f build-linux-Debug/compile_commands.json ]] || ./configure.sh linux debug -DCMAKE_EXPORT_COMPILE_COMMANDS=1 > /dev/null 2>&1
    cp build-linux-Debug/compile_commands.json /tmp/compile_commands.json
    sed -i 's|-static-libasan||g' /tmp/compile_commands.json
}

main()
{
    if [[ $# -ne 0 ]]; then
        help
        exit 0
    fi
    local tool
    tool=$(get_clang_tidy)

    local files_to_check
    files_to_check=$(get_files_to_check)

    if [[ -z $files_to_check ]]; then
        echo "no files to check"
        exit 0
    fi

    # get the stage
    verify_clang_format_version
    get_compile_commands
    # run tidy
    git diff -U0 --no-color remotes/origin/master...HEAD "$files_to_check" | ${tool[*]} -p 1 -path=/tmp/
}

main

M config/format-config.sh => config/format-config.sh +16 -3
@@ 6,14 6,14 @@
# ignore file for clang-format autoformating

# set this variable in your shell if you wish to disable autoformatting on commit for time being
#DISABLE_AUTO_FORMATTING=1
export DISABLE_AUTO_FORMATTING=0

# set this variable to get more verbose output
VERBOSE=1
export VERBOSE=1

# ignore_paths for formatter - these are regex matched with filenames to be formated
# if you don't wish to format i.e one file - just pass whole path to this file from git root directory
declare ignore_paths=(
export declare ignore_paths=(
    '.*/catch.hpp'
    '.*/lib/'
    'build'


@@ 57,3 57,16 @@ declare ignore_paths=(
    'module-vfs/drivers/include/thirdparty/fatfs/ffconf.h'
    'module-vfs/thirdparty/*'
)

# bash function using above config function
shouldnt_ignore() {
    # change full name path to path relative to root git dir
    local fname=${1/"$L_GIT_DIR"/"./"}
    for el in ${ignore_paths[@]}; do
        if [[ ${fname}  =~ ^${el}.* ]]; then
            [[ $VERBOSE ]] && echo "Ignore: ${fname} formatting due to: $el match!"
            return 1
        fi
    done
    return 0
}

M config/style_check_hook.sh => config/style_check_hook.sh +28 -74
@@ 1,4 1,11 @@
#!/bin/bash 
# Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
# For licensing, see https://github.com/mudita/MuditaOS/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



@@ 7,86 14,47 @@
# - 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

RED='\e[38;2;255;13;0m'
YELLOW="\e[38;2;255;232;0m"
GREEN="\e[38;2;0;222;27m"
ORANGE="\e[38;2;255;100;0m"

OK="${GREEN}OK!\e[0m"
ERROR="${RED}Error!\e[0m"
FIXED="${YELLOW}Fixed!\e[0m"

source $L_GIT_DIR/config/clang/colors.sh
source $L_GIT_DIR/config/clang/clang-common.sh

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

# check if clang-format in path is in proper version, version is 3rd column in `clang-format --version`
CVER=$( [[ $(which clang-format) ]] && echo $(clang-format --version | cut -d ' ' -f 3 | cut -d '.' -f 1) || echo "0")
# check for either clang-format or clang-format-9
if [[ $CVER -lt 10 && ! $(which clang-format-10) ]]; then
    cat << EOF >&1
Either install:
    clang-format in at least version 10 and set as default"
    or
    clang-format-10

    Your clang format version in path used:
        $(clang-format --version):
        $(clang-format-10 --version)
    git commit aborted"
EOF
    exit 1
fi
verify_clang_format_version

get_clang_format_script() {
    local declare searchpaths=(
        $(which "clang-format-diff.py")                                 # clang-format-diff in path
        "/usr/share/clang/clang-format-10/clang-format-diff.py"          # clang-format-diff location for clang format 9 Ubuntu/Debian 18.04
        "/usr/share/clang/clang-format-${CVER}/clang-format-diff.py"    # clang-format-diff location on Ubuntu/Debian
        "/usr/share/clang/clang-format-diff.py"                         # clang-format_diff location on Arch last resort
    )
    local tool=""
    for el in ${searchpaths[@]}; do
        if [[ -f ${el} ]]; then
            tool=${el}
            break
        fi
    done
    if [[ ${tool} == "" ]]; then
        echo clang-format-diff not found in path and: ${sarchpaths[@]} >2
    fi
    echo "${tool}"
}

L_CLANG_DIFF_TOOL=$(get_clang_format_script)
L_CLANG_DIFF_TOOL=$(get_clang_format)
if ! [[ $L_CLANG_DIFF_TOOL ]] || [[ $L_CLANG_DIFF_TOOL == "" ]]; then
    [[ $VERBOSE ]] && echo "clang tool not found"
    exit 1
fi


check_file() {
    file="${1}"
    last_commit="${2}"
    if [ -f $file ]; then
    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/master...HEAD ${file} | ${L_CLANG_DIFF_TOOL} -style file -p1 -i
                STATUS=$(git status --short -- ${file})
                git diff -U0 --no-color remotes/origin/master...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/master...HEAD ${file} | ${L_CLANG_DIFF_TOOL} -style file -p1 )
                OUT=$(git diff -U0 --no-color remotes/origin/master...HEAD "${file}" | ${L_CLANG_DIFF_TOOL} -style file -p1 )
                if [ -n "${OUT}" ]; then
                    results["${file}"]="${ERROR}"
                    return 1


@@ 95,14 63,14 @@ check_file() {
            ;;
        "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})
                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)
                OUT=$(git diff -U0 --no-color --cached "${file}" | ${L_CLANG_DIFF_TOOL} -style file -p1)
                if [ -n "${OUT}" ]; then
                    results["${file}"]="${ERROR}"
                    return 1


@@ 110,8 78,8 @@ check_file() {
            fi
            ;;
        *)
            OUT=$(git diff -U0 --no-color --cached ${file} | ${L_CLANG_DIFF_TOOL} -style file -p1 )
            if [ -n ${OUT} ]; then
            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


@@ 121,19 89,6 @@ check_file() {
    return 0
}

# bash function using above config function
shouldnt_ignore() {
    # change full name path to path relative to root git dir
    local fname=${1/"$L_GIT_DIR"/"./"}
    for el in ${ignore_paths[@]}; do
        if [[ ${fname}  =~ ^${el}.* ]]; then
            [[ $VERBOSE ]] && echo "Ignore: ${fname} formatting due to: $el match!"
            return 1
        fi
    done
    return 0
}

function help() {
        echo "Runs clang-format on source files"
        cat <<- EOM


@@ 176,14 131,13 @@ case "${1}" in
        ;;
    *)
        if [[ $# -ne 0 ]]; then
            echo "unknown parameters: '$@'"
            echo "unknown parameters: '$*'"
            help
            exit 1
        fi
        FILES=$(git diff-index --cached --name-only HEAD)
        LAST="Stage" 
        FIX=$(git config user.fixinstage)
        FIX=${FIX:-false}
        FIX=$([[ $(git config user.fixinstage) == "true" ]] && echo "true" || echo "false")
        ;;
esac