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