#!/usr/bin/env bash set_colors() { RED="\033[31m" RESET_COLOR="\033[m" } set_colors panic() { local reason="$1" echo -e "${RED}[Invalid Commit Message]${RESET_COLOR}" echo -e "------------------------" echo -e "Reason: ${RED}$reason${RESET_COLOR}" exit 1 } enabled=""$X_GIT_HOOK_CONVENTIONAL_COMMITS_ENABLED; if [[ "$enabled" == "" ]]; then enabled=true fi if [[ "$enabled" == 0 || ! $enabled ]]; then exit 0 fi min_length=""$X_GIT_HOOK_CONVENTIONAL_COMMITS_MIN_LENGTH; if [[ "$min_length" != 0 && ! "$min_length" ]]; then min_length=1 fi max_length=""$X_GIT_HOOK_CONVENTIONAL_COMMITS_MAX_LENGTH; if [[ "$max_length" != 0 && ! "$max_length" ]]; then max_length=52 fi get_casing() { local casing="$1" if [[ ! "$casing" ]]; then casing=""$X_GIT_HOOK_CONVENTIONAL_COMMITS_CASING fi if [[ ! "$casing" ]]; then casing="all-lower-ascii" fi echo "$casing"; } check_casing() { local string="$1" local casing="$(get_casing "$2")" if [[ $casing == "ascii" && $string =~ ^[a-zA-Z0-9]+$ ]]; then true elif [[ $casing == "all-lower-ascii" && $string =~ ^[a-z0-9]+$ ]]; then true elif [[ $casing == "all-upper-ascii" && $string =~ ^[A-Z0-9]+$ ]]; then true else false fi } check_type() { local revert="$X_GIT_HOOK_CONVENTIONAL_COMMITS_REVERT"; local input_type="$1" local revert=""; if [[ ! "$revert" ]]; then revert="$X_GIT_HOOK_CONVENTIONAL_COMMITS_REVERT" fi if [[ ! "$revert" ]]; then revert="true" fi if [[ "$revert" != false && ! "$revert" ]]; then revert=true fi IFS=',' read -r -a types <<< "$X_GIT_HOOK_CONVENTIONAL_COMMITS_TYPES"; unset IFS if [[ "${types[0]}" == "" ]]; then types=( "build" "ci" "docs" "feat" "fix" "perf" "refactor" "style" "test" "chore" ); fi if "$revert"; then types["${#types[@]}" + 1]="revert" fi for type in "${types[@]}"; do [[ "$type" == "$input_type" ]] && return 0 done panic "Message \"$input_type\" is not valid" } check_prefix() { local type="$1" local scope=""; if [[ $type == *'('* ]]; then local parts=(); IFS='(' read -r -a parts <<< "$type" type="${parts[0]}" scope="${parts[1]}" scope="${scope/!}" scope="${scope/\)}" if check_casing "$scope"; then false else panic "[optional scope] \"$scope\" is not in correct casing ($(get_casing))"; fi fi if check_casing "$type"; then check_type "$(echo "$type" | tr '[:upper:]' '[:lower:]')" else panic " \"$type\" is not in correct casing ($(get_casing))"; fi echo "$type $scope" } check_header() { local header="$1" echo "$header" if [[ $header != *':'* ]]; then panic "Message doesn't contain a :" fi local parts=(); IFS=':' read -r -a parts <<< "$header" if [[ ${#parts[@]} < 2 || ! ${parts[0]} || ! ${parts[1]} ]]; then panic "Message doesn't contain : \n${parts[@]}" fi check_prefix "${parts[0]}" } check_msg() { local message="$1" local header="$(echo "$message" | head -1 -)" check_header "$1" } if [[ -f "$1" || "$1" == "-" ]]; then check_msg "$(cat "$1")" else check_msg "$1" fi