diff --git a/code_format/git-hooks/install-client-side-hooks b/code_format/git-hooks/install-client-side-hooks new file mode 100755 index 0000000..8c1ef5b --- /dev/null +++ b/code_format/git-hooks/install-client-side-hooks @@ -0,0 +1,47 @@ +#!/bin/bash + +# Install client side hooks into all TDE local repositories + +# Note: this is /scripts/code_format/git-hooks +SCRIPT_DIR=`dirname $(readlink -f "$0")` +TDE_DIR="${SCRIPT_DIR}/../../.." + +if [[ ! -f "${TDE_DIR}/.gitmodules" ]]; then + echo " --- Unable to find repository list (.gitmodules). Aborting." + exit 1 +fi + +sed -n "s|^\[submodule \"\([^\"]*\)\"\]$|\1|p" <"${TDE_DIR}/.gitmodules" | \ +grep "^main/" | \ +while read MODULE; do + cd "${TDE_DIR}/${MODULE}" + GIT_COMMON_DIR=`git rev-parse --git-common-dir` + if [[ "${GIT_COMMON_DIR}" == ".git" ]]; then + # Normal repository + HOOK_DIR="${TDE_DIR}/${MODULE}/${GIT_COMMON_DIR}/hooks" + else + # Worktree repository + HOOK_DIR="${GIT_COMMON_DIR}/hooks" + fi + # Check hook folder exists + if [ ! -d "${HOOK_DIR}" ]; then + echo " --- Unable to find the hook folder for the repository ${MODULE}" + echo " Skipping module." + continue + fi + # Check whether the pre-commit hook already exists. Warn users unless the + # script was invoked with "-f" parameter. + if [ -e "${HOOK_DIR}/pre-commit" -a "$1" != "-f" ]; then + echo " --- Pre-commit hook already exists for the repository ${MODULE}" + echo " Rerun this script with '-f' to force hook overwriting." + echo " Skipping module." + continue + fi + cp "${SCRIPT_DIR}/pre-commit" "${HOOK_DIR}/" + chmod a+x "${HOOK_DIR}/pre-commit" + if [ -e "${HOOK_DIR}/pre-commit" ]; then + echo " Installed pre-commit hook for the repository ${MODULE}" + else + echo " --- Something went wrong when installing the pre-commit hook for the repository ${MODULE}" + fi +done diff --git a/code_format/git-hooks/pre-commit b/code_format/git-hooks/pre-commit new file mode 100755 index 0000000..01a3472 --- /dev/null +++ b/code_format/git-hooks/pre-commit @@ -0,0 +1,91 @@ +#!/bin/bash + +# Hook called before a commit is created. It will try to format each file which +# has been added/copy/modified/renamed up to a maximum of 5 times and if a +# stable code formatting can be achieved, the commit operation will be allowed +# to proceed. If no stable code formatting is achieved in 5 passes, the commit +# operation will be aborted. + +# Note on amended commits. Amending a commit can add/modify/remove files to/from an +# original commit. The pre-commit hook was already run against the original commit files +# when that commit was created. The pre-commit hook ran on an amended commit will only +# check those files which have actually been added/modified compared to the original commit. +# Files that were not touched by the amending operation, will not be tested again. + + +# set default encoding to UTF-8 +export LANG=C.UTF-8 +export LC_ALL=C.UTF-8 + +SCRIPT_DIR=`dirname $(readlink -f "$0")` + +# Check code format information exists +MOD_ROOT_DIR=`git rev-parse --show-toplevel 2>/dev/null` +CONFIG_INDEX_FILE=${MOD_ROOT_DIR}/.repo_settings/code_format.txt +if [ ! -e "${CONFIG_INDEX_FILE}" ]; then + echo "No code format version information file found for repository." + exit 0 +fi + +# Get TDE root folder +REMOTE_URL=$(git config --get remote.origin.url) +if [ "$REMOTE_URL" != "${REMOTE_URL%/tde}" ]; then + echo " --- This script can only be run on valid TDE repositories. Aborting." + exit 1 +fi + +TDE_ROOT_DIR=$( cd `git rev-parse --show-toplevel 2>/dev/null` && cd .. && + cd `git rev-parse --show-toplevel 2>/dev/null` && pwd ) +if [[ "$TDE_ROOT_DIR" != */tde ]]; then + echo " --- Unable to find TDE root folder. Aborting." + exit 2 +fi + +# Find code format version and configuration file +MOD_CFG_ENTRY=`grep "Version" "${CONFIG_INDEX_FILE}" | grep -v "^\s*#"` +if [ -z "${MOD_CFG_ENTRY}" ]; then + echo " --- Unable to find the format version information. Aborting." + exit 4 +fi +if [ `echo "${MOD_CFG_ENTRY}" | wc -l` != 1 ]; then + echo " --- Multiple entries found in the format configuration file. Aborting." + exit 5 +fi +MOD_CFG_VERSION=`echo "${MOD_CFG_ENTRY}" | sed "s|^\s*Version\s\+\([0-9]\+\)\s*$|\1|"` +MOD_CFG_FILE=${TDE_ROOT_DIR}/scripts/code-format/uncrustify_cfg_files/uncrustify_tde_${MOD_CFG_VERSION}.cfg +if [ ! -e "${MOD_CFG_FILE}" ]; then + echo " --- Unable to find the specified format configuration version file. Aborting." + exit 6 +fi + +echo "-----------------" +echo "Formatting code before committing" +echo "-----------------" + +# Check whether files adhere to the required code format +VALID_EXTENSIONS=".h .cpp .c .h.cmake .cpp.cmake .c.cmake .hpp .hxx .hh .cxx .cc .hpp.cmake" +while read -r FILE_AND_STATUS; do + if [[ "${FILE_AND_STATUS}" =~ ([ACMR])[[:space:]]+(.*) ]]; then + FILE_STATUS="${BASH_REMATCH[1]}" + FILE_NAME="${BASH_REMATCH[2]}" + # Only check files of the proper type + for FILE_EXT in $VALID_EXTENSIONS; do + if [[ "${FILE_NAME}" = *${FILE_EXT} ]]; then + echo "File: ${FILE_NAME} --- Git status: ${FILE_STATUS}" + MOD_CFG_FILE="${MOD_CFG_FILE}" ${TDE_ROOT_DIR}/scripts/code-format/format_file ${FILE_NAME} + if [ $? -ne 0 ]; then + echo -e "\n--------------------------------------------------------" + echo " Process aborted due to failed code format verification " + echo -e "--------------------------------------------------------\n" + exit 1 + fi + echo "------" + break + fi + done + fi +done < <(git diff --name-status --cached --diff-filter=ACMR) + +echo -e "\n----------------------------------------------" +echo " All files adhere to the required code format " +echo "----------------------------------------------" diff --git a/code_format/git-hooks/remove-client-side-hooks b/code_format/git-hooks/remove-client-side-hooks new file mode 100755 index 0000000..5d9bd9e --- /dev/null +++ b/code_format/git-hooks/remove-client-side-hooks @@ -0,0 +1,44 @@ +#!/bin/bash + +# Remove client side hooks from all TDE local repositories + +# Note: this is /scripts/code_format/git-hooks +SCRIPT_DIR=`dirname $(readlink -f "$0")` +TDE_DIR="${SCRIPT_DIR}/../../.." + +if [[ ! -f "${TDE_DIR}/.gitmodules" ]]; then + echo " --- Unable to find repository list (.gitmodules). Aborting." + exit 1 +fi + +sed -n "s|^\[submodule \"\([^\"]*\)\"\]$|\1|p" <"${TDE_DIR}/.gitmodules" | \ +grep "^main/" | \ +while read MODULE; do + cd "${TDE_DIR}/${MODULE}" + GIT_COMMON_DIR=`git rev-parse --git-common-dir` + if [[ "${GIT_COMMON_DIR}" == ".git" ]]; then + # Normal repository + HOOK_DIR="${TDE_DIR}/${MODULE}/${GIT_COMMON_DIR}/hooks" + else + # Worktree repository + HOOK_DIR="${GIT_COMMON_DIR}/hooks" + fi + # Check hook folder exists + if [ ! -d "${HOOK_DIR}" ]; then + echo " --- Unable to find the hook folder for the repository ${MODULE}" + echo " Skipping module." + continue + fi + # Check whether the pre-commit hook exists + if [ ! -e "${HOOK_DIR}/pre-commit" ]; then + echo " --- Pre-commit hook not found for the repository ${MODULE}" + echo " Skipping module." + continue + fi + rm "${HOOK_DIR}/pre-commit" + if [ ! -e "${HOOK_DIR}/pre-commit" ]; then + echo "Pre-commit hook removed for the repository ${MODULE}" + else + echo " --- Something went wrong when removing the pre-commit hook for the repositoty ${MODULE}" + fi +done