1#!/usr/bin/env bash 2 3REF="HEAD" 4 5# test a url 6function test_url() 7{ 8 url="$1" 9 if ! curl --output /dev/null --max-time 60 \ 10 --silent --head --fail "$url" ; then 11 echo "\"$url\" is unreachable" 12 return 1 13 fi 14 15 return 0 16} 17 18# test commit body for length 19# lines containing urls are exempt for the length limit. 20function test_commit_bodylength() 21{ 22 length="72" 23 body=$(git log -n 1 --pretty=%b "$REF" | grep -Ev "http(s)*://" | grep -E -m 1 ".{$((length + 1))}") 24 if [ -n "$body" ]; then 25 echo "error: commit message body contains line over ${length} characters" 26 return 1 27 fi 28 29 return 0 30} 31 32# check for a tagged line 33function check_tagged_line() 34{ 35 regex='^\s*'"$1"':\s[[:print:]]+\s<[[:graph:]]+>$' 36 foundline=$(git log -n 1 "$REF" | grep -E -m 1 "$regex") 37 if [ -z "$foundline" ]; then 38 echo "error: missing \"$1\"" 39 return 1 40 fi 41 42 return 0 43} 44 45# check for a tagged line and check that the link is valid 46function check_tagged_line_with_url() 47{ 48 regex='^\s*'"$1"':\s\K([[:graph:]]+)$' 49 foundline=$(git log -n 1 "$REF" | grep -Po "$regex") 50 if [ -z "$foundline" ]; then 51 echo "error: missing \"$1\"" 52 return 1 53 fi 54 55 OLDIFS=$IFS 56 IFS=$'\n' 57 for url in $(echo -e "$foundline"); do 58 if ! test_url "$url"; then 59 return 1 60 fi 61 done 62 IFS=$OLDIFS 63 64 return 0 65} 66 67# check commit message for a normal commit 68function new_change_commit() 69{ 70 error=0 71 72 # subject is not longer than 72 characters 73 long_subject=$(git log -n 1 --pretty=%s "$REF" | grep -E -m 1 '.{73}') 74 if [ -n "$long_subject" ]; then 75 echo "error: commit subject over 72 characters" 76 error=1 77 fi 78 79 # need a signed off by 80 if ! check_tagged_line "Signed-off-by" ; then 81 error=1 82 fi 83 84 # ensure that no lines in the body of the commit are over 72 characters 85 if ! test_commit_bodylength ; then 86 error=1 87 fi 88 89 return $error 90} 91 92function is_openzfs_port() 93{ 94 # subject starts with OpenZFS means it's an openzfs port 95 subject=$(git log -n 1 --pretty=%s "$REF" | grep -E -m 1 '^OpenZFS') 96 if [ -n "$subject" ]; then 97 return 0 98 fi 99 100 return 1 101} 102 103function openzfs_port_commit() 104{ 105 error=0 106 107 # subject starts with OpenZFS dddd 108 subject=$(git log -n 1 --pretty=%s "$REF" | grep -E -m 1 '^OpenZFS [[:digit:]]+(, [[:digit:]]+)* - ') 109 if [ -z "$subject" ]; then 110 echo "error: OpenZFS patch ports must have a subject line that starts with \"OpenZFS dddd - \"" 111 error=1 112 fi 113 114 # need an authored by line 115 if ! check_tagged_line "Authored by" ; then 116 error=1 117 fi 118 119 # need a reviewed by line 120 if ! check_tagged_line "Reviewed by" ; then 121 error=1 122 fi 123 124 # need ported by line 125 if ! check_tagged_line "Ported-by" ; then 126 error=1 127 fi 128 129 # need a url to openzfs commit and it should be valid 130 if ! check_tagged_line_with_url "OpenZFS-commit" ; then 131 error=1 132 fi 133 134 # need a url to illumos issue and it should be valid 135 if ! check_tagged_line_with_url "OpenZFS-issue" ; then 136 error=1 137 fi 138 139 return $error 140} 141 142function is_coverity_fix() 143{ 144 # subject starts with Fix coverity defects means it's a coverity fix 145 subject=$(git log -n 1 --pretty=%s "$REF" | grep -E -m 1 '^Fix coverity defects') 146 if [ -n "$subject" ]; then 147 return 0 148 fi 149 150 return 1 151} 152 153function coverity_fix_commit() 154{ 155 error=0 156 157 # subject starts with Fix coverity defects: CID dddd, dddd... 158 subject=$(git log -n 1 --pretty=%s "$REF" | 159 grep -E -m 1 'Fix coverity defects: CID [[:digit:]]+(, [[:digit:]]+)*') 160 if [ -z "$subject" ]; then 161 echo "error: Coverity defect fixes must have a subject line that starts with \"Fix coverity defects: CID dddd\"" 162 error=1 163 fi 164 165 # need a signed off by 166 if ! check_tagged_line "Signed-off-by" ; then 167 error=1 168 fi 169 170 # test each summary line for the proper format 171 OLDIFS=$IFS 172 IFS=$'\n' 173 for line in $(git log -n 1 --pretty=%b "$REF" | grep -E '^CID'); do 174 echo "$line" | grep -E '^CID [[:digit:]]+: ([[:graph:]]+|[[:space:]])+ \(([[:upper:]]|\_)+\)' > /dev/null 175 # shellcheck disable=SC2181 176 if [[ $? -ne 0 ]]; then 177 echo "error: commit message has an improperly formatted CID defect line" 178 error=1 179 fi 180 done 181 IFS=$OLDIFS 182 183 # ensure that no lines in the body of the commit are over 72 characters 184 if ! test_commit_bodylength; then 185 error=1 186 fi 187 188 return $error 189} 190 191if [ -n "$1" ]; then 192 REF="$1" 193fi 194 195# if openzfs port, test against that 196if is_openzfs_port; then 197 if ! openzfs_port_commit ; then 198 exit 1 199 else 200 exit 0 201 fi 202fi 203 204# if coverity fix, test against that 205if is_coverity_fix; then 206 if ! coverity_fix_commit; then 207 exit 1 208 else 209 exit 0 210 fi 211fi 212 213# have a normal commit 214if ! new_change_commit ; then 215 exit 1 216fi 217 218exit 0 219