+init() {
+ set -a
+ readonly ORIGINAL="$1"
+ readonly REVISED="$(mktemp "$ORIGINAL.XXXXXX")"
+ readonly SAVE="$(basename $ORIGINAL).$(date +%Y%m%d.%H%M%S)"
+ readonly SIGNOFF="Signed-off-by:"
+ readonly CHANGEID="Change-Id:"
+ readonly TESTPARAMS="Test-Parameters:"
+ readonly INNOCUOUS=$(echo \
+ Acked-by \
+ Tested-by \
+ Reported-by \
+ Reviewed-by \
+ CC \
+ | tr ' ' '|')
+ readonly WIDTH_SUM=62
+ readonly WIDTH_REG=70
+ readonly JIRA_FMT_A="^[A-Z]\{2,5\}-[0-9]\{1,5\} [-a-z0-9]\{2,11\}: "
+ readonly JIRA_FMT_B="^[A-Z]\{2,5\}-[0-9]\{1,5\} "
+
+ # Identify a name followed by an email address.
+ #
+ readonly EMAILPAT=$'[ \t]*[^<> ]* [^<>]* <[^@ \t>]+@[a-zA-Z0-9.-]+\.[a-z]+>'
+
+ HAS_ERROR=false
+ HAS_SUMMARY=false
+ HAS_LAST_BLANK=false
+ HAS_BODY=false
+ HAS_SIGNOFF=false
+ HAS_CHANGEID=false
+
+ IS_WRAPPING_UP=false
+
+ LINE=""
+ NUM=0
+ set +a
+}
+
+# die: commit-msg fatal error: script error or empty input message
+# All output redirected to stderr.
+#
+die() {
+ echo "commit-msg fatal error: $*"
+ test -f "$REVISED" && rm -f "$REVISED"
+ exit 1
+} 1>&2
+
+# Called when doing the final "wrap up" clause because we've found
+# one of the tagged lines that belongs in the final section.
+#
+function ck_wrapup() {
+ $IS_WRAPPING_UP && return
+
+ $HAS_LAST_BLANK || error "blank line must preceed signoff section"
+ $HAS_SUMMARY || error "missing commit summary line."
+ $HAS_BODY || error "missing commit description."
+
+ HAS_LAST_BLANK=false
+ IS_WRAPPING_UP=true
+}
+
+function do_signoff() {
+ ck_wrapup
+ # Signed-off-by: First Last <email@host.domain>
+ local txt=$(echo "${LINE#*: }" | grep -E "${EMAILPAT}")
+ if (( ${#txt} == 0 )); then
+ error "$SIGNOFF line requires name and email address"
+ else
+ HAS_SIGNOFF=true # require at least one
+ fi
+}
+
+function do_changeid() {
+ ck_wrapup
+ $HAS_CHANGEID && error "multiple $CHANGEID lines are not allowed"
+
+ # Change-Id: I1234567890123456789012345678901234567890
+ # capital "I" plus 40 hex digits
+ #
+ local txt=$(echo "$LINE" | grep "^$CHANGEID I[0-9a-fA-F]\{40\}\$")
+ (( ${#txt} > 0 )) ||
+ error "has invalid $CHANGEID line for Gerrit tracking"
+
+ HAS_CHANGEID=true
+}
+
+# All "innocuous" lines specify a person and email address
+#
+function do_innocuous() {
+ ck_wrapup
+ local txt=$(echo "${LINE#*: }" | grep -E "${EMAILPAT}")
+ (( ${#txt} == 0 )) && error "invalid name and address"
+}
+
+function do_default_line() {
+ $IS_WRAPPING_UP && {
+ error "invalid signoff section line"
+ return
+ }
+ if (( NUM == 1 )); then
+ HAS_JIRA_COMPONENT=$(echo "$LINE" | grep "$JIRA_FMT_A")
+
+ if (( ${#HAS_JIRA_COMPONENT} == 0 )); then
+ HAS_JIRA=$(echo "$LINE" | grep "$JIRA_FMT_B")
+ if (( ${#HAS_JIRA} > 0 )); then
+ error "has no component in summary."
+ else
+ error "missing JIRA ticket number."
+ fi
+ elif (( ${#LINE} > WIDTH_SUM )); then
+ error "summary longer than $WIDTH_SUM columns."
+ else
+ HAS_SUMMARY=true
+ fi
+
+ elif (( ${#LINE} > WIDTH_REG )); then
+ error "has line longer than $WIDTH_REG columns."
+ elif ! $HAS_BODY && ! $HAS_LAST_BLANK; then
+ error "has no blank line after summary."
+ else
+ HAS_BODY=true
+ fi
+ HAS_LAST_BLANK=false
+}
+
+# Add a new unique Change-Id
+#