Skip to content
Snippets Groups Projects
.pre-commit 4.35 KiB
Newer Older
  • Learn to ignore specific revisions
  • #!/bin/sh
    
    # git pre-commit hook that runs an Uncrustify stylecheck.
    # Features:
    #  - abort commit when commit does not comply with the style guidelines
    #  - create a patch of the proposed style changes
    #
    # More info on Uncrustify: http://uncrustify.sourceforge.net/
    
    # This file is part of a set of unofficial pre-commit hooks available
    # at github.
    # Link:    https://github.com/githubbrowser/Pre-commit-hooks
    # Contact: David Martin, david.martin.mailbox@googlemail.com
    
    
    ##################################################################
    # SETTINGS
    # set path to uncrustify binary
    # UNCRUSTIFY="/usr/bin/uncrustify"
    UNCRUSTIFY="uncrustify"
    
    CLANGFORMAT="clang-format"
    
    
    # set uncrustify config location
    # CONFIG="/home/user/.config/uncrustify.cfg"
    CONFIG=".uncrustify.cfg"
    
    # the source language: C, CPP, D, CS, JAVA, PAWN, VALA, OC, OC+
    SOURCE_LANGUAGE="CPP"
    
    # remove any older patches from previous commits. Set to true or false.
    # DELETE_OLD_PATCHES=false
    DELETE_OLD_PATCHES=false
    
    # only parse files with the extensions in FILE_EXTS. Set to true or false.
    # if false every changed file in the commit will be parsed with Uncrustify.
    # if true only files matching one of the extensions are parsed with Uncrustify.
    # PARSE_EXTS=true
    PARSE_EXTS=true
    
    # file types to parse. Only effective when PARSE_EXTS is true.
    # FILE_EXTS=".c .h .cpp .hpp"
    FILE_EXTS=".c .h .cpp .hpp .cxx"
    
    
    ##################################################################
    # check if uncrustify and clang-format exist in PATH
    exec_in_path() {
    	type $1 >/dev/null 2>&1 || { echo >&2 "Require '$1' executable but it was not found in PATH. Aborting."; exit 1; }
    }
    
    exec_in_path "$UNCRUSTIFY"
    exec_in_path "$CLANGFORMAT"
    
    
    ##################################################################
    # There should be no need to change anything below this line.
    
    # check whether the given file matches any of the set extensions
    matches_extension() {
        local filename="$(basename -- "$1")"
        local extension=".${filename##*.}"
        local ext
    
        for ext in $FILE_EXTS; do [ "$ext" = "$extension" ] && return 0; done
    
        return 1
    }
    
    # necessary check for initial commit
    if git rev-parse --verify HEAD >/dev/null 2>&1 ; then
        against=HEAD
    else
        # Initial commit: diff against an empty tree object
        against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
    fi
    
    # make sure the config file and executable are correctly set
    if [ ! -f "$CONFIG" ] ; then
        printf "Error: uncrustify config file not found.\n"
        printf "Set the correct path in $(canonicalize_filename "$0").\n"
        exit 1
    fi
    
    # create a random filename to store our generated patch
    prefix="pre-commit-uncrustify"
    suffix="$(date +%s)"
    patch="/tmp/$prefix-$suffix.patch"
    
    # clean up any older uncrustify patches
    $DELETE_OLD_PATCHES && rm -f /tmp/$prefix*.patch
    
    # create one patch containing all changes to the files
    git diff-index --cached --diff-filter=ACMR --name-only $against -- | while read file;
    do
        # ignore file if we do check for file extensions and the file
        # does not match any of the extensions specified in $FILE_EXTS
        if $PARSE_EXTS && ! matches_extension "$file"; then
            continue;
        fi
    
        # uncrustify our sourcefile, create a patch with diff and append it to our $patch
        # The sed call is necessary to transform the patch from
        #    --- $file timestamp
        #    +++ - timestamp
        # to both lines working on the same file and having a a/ and b/ prefix.
        # Else it can not be applied with 'git apply'.
    
        "$CLANGFORMAT" "$file" | \
    
        "$UNCRUSTIFY" -c "$CONFIG" -l "$SOURCE_LANGUAGE" | \
            diff -u -- "$file" - | \
            sed -e "1s|--- |--- a/|" -e "2s|+++ -|+++ b/$file|" >> "$patch"
    done
    
    # if no patch has been generated all is ok, clean up the file stub and exit
    if [ ! -s "$patch" ] ; then
        printf "Files in this commit comply with the uncrustify rules.\n"
        rm -f "$patch"
    
        # If there are whitespace errors, print the offending file names and fail.
        exec git diff-index --check --cached $against --
    fi
    
    # a patch has been created, notify the user and exit
    printf "\nThe following differences were found between the code to commit "
    printf "and the uncrustify rules:\n\n"
    cat "$patch"
    
    printf "\nYou can apply these changes with:\n git apply $patch\n"
    printf "(may need to be called from the root directory of your repository)\n"
    printf "Aborting commit. Apply changes and commit again or skip checking with"
    printf " --no-verify (not recommended).\n"
    
    exit 1