YETUS-858. Add support for Golang (#57)
diff --git a/asf-site-src/source/documentation/in-progress/precommit-basic.md b/asf-site-src/source/documentation/in-progress/precommit-basic.md
index 67a6b3a..9b8be39 100644
--- a/asf-site-src/source/documentation/in-progress/precommit-basic.md
+++ b/asf-site-src/source/documentation/in-progress/precommit-basic.md
@@ -108,17 +108,28 @@
* [JUnit](http://junit.org/)
* [TAP](https://testanything.org/)
+Compiler Support:
+
+* C/C++
+* Go
+* Java
+* Scala
+
Language Support, Licensing, and more:
-* [Apache Creadur Rat](http://creadur.apache.org/rat/) entries in build system
+* [Apache Creadur Rat](http://creadur.apache.org/rat/) entries in build system or installed
+* [checkmake](https://github.com/mrtazz/checkmake) installed
* [checkstyle](http://checkstyle.sourceforge.net/) entries in build system (ant and maven only)
* [FindBugs](http://findbugs.sourceforge.net/) entries in build system and 3.x executables
* NOTE: only one of FindBugs or SpotBugs may be used at a time.
-* [jshint](https://jshint.com) installed
+* [golangci-lint](https://github.com/golangci/golangci-lint)
+ * NOTE: only Go modules are supported
* [hadolint](https://github.com/hadolint/hadolint) installed
+* [jshint](https://jshint.com) installed
* [markdownlint-cli](https://github.com/igorshubovych/markdownlint-cli) installed
* [Perl::Critic](http://perlcritic.com/) installed
* [pylint](http://www.pylint.org/) installed
+* [revive](https://github.com/mgechev/revive) installed
* [rubocop](http://batsov.com/rubocop/) installed
* [shellcheck](https://github.com/koalaman/shellcheck) installed, preferably 0.3.6 or higher
*[SpotBugs](https://spotbugs.github.io/)) entries in build system and 3.x executables
diff --git a/precommit/src/main/shell/core.d/00-yetuslib.sh b/precommit/src/main/shell/core.d/00-yetuslib.sh
index c86bc71..780dc2a 100755
--- a/precommit/src/main/shell/core.d/00-yetuslib.sh
+++ b/precommit/src/main/shell/core.d/00-yetuslib.sh
@@ -464,6 +464,38 @@
fi
}
+## @description find the deepest entry of a directory array
+## @description NOTE: array and filename MUST be absolute paths
+## @audience public
+## @stability stable
+## @replaceable no
+## @param array
+## @param fn
+## @return dir if match
+function yetus_find_deepest_directory
+{
+ declare arrname=$1
+ declare arrref="${arrname}[@]"
+ declare array=("${!arrref}")
+ declare fn=$2
+
+ declare d
+ declare tvalsize
+ declare val
+ declare valsize
+
+ for d in "${array[@]}"; do
+ if yetus_relative_dir "${d}" "${fn}" >/dev/null; then
+ tvalsize=${d//[^/]/}
+ if [[ ${#tvalsize} -gt ${valsize} ]]; then
+ valsize=${#tvalsize}
+ val=${d}
+ fi
+ fi
+ done
+ echo "${val}"
+}
+
## @description Get the date in ctime format
## @audience public
## @stability stable
@@ -472,8 +504,7 @@
{
if [[ "${BASH_VERSINFO[0]}" -gt 4 ]] \
|| [[ "${BASH_VERSINFO[0]}" -eq 4 && "${BASH_VERSINFO[1]}" -gt 1 ]]; then
- # shellcheck disable=SC2183
- printf "%(%s)T"
+ printf "%(%s)T" -1
else
date +"%s"
fi
diff --git a/precommit/src/main/shell/test-patch-docker/Dockerfile b/precommit/src/main/shell/test-patch-docker/Dockerfile
index 52ba190..09bac9b 100644
--- a/precommit/src/main/shell/test-patch-docker/Dockerfile
+++ b/precommit/src/main/shell/test-patch-docker/Dockerfile
@@ -247,6 +247,21 @@
&& rm -rf /var/lib/apt/lists/* && \
npm install -g jshint@2.10.2 markdownlint-cli@0.15.0
+###
+# Install golang and supported helpers
+###
+# hadolint ignore=DL3008
+RUN add-apt-repository -y ppa:longsleep/golang-backports \
+ && apt-get -q update \
+ && apt-get -q install --no-install-recommends -y golang-go \
+ && apt-get clean \
+ && rm -rf /var/lib/apt/lists/*
+RUN go get -u github.com/mgechev/revive \
+ && go get -u github.com/mrtazz/checkmake \
+ && (GO111MODULE=on go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.16.0) \
+ && mv /root/go/bin/* /usr/local/bin \
+ && rm -rf /root/go
+
####
# YETUS CUT HERE
# Anthing after the above line is ignored by Yetus, so could
diff --git a/precommit/src/main/shell/test-patch.d/checkmake.sh b/precommit/src/main/shell/test-patch.d/checkmake.sh
new file mode 100755
index 0000000..da570d0
--- /dev/null
+++ b/precommit/src/main/shell/test-patch.d/checkmake.sh
@@ -0,0 +1,186 @@
+#!/usr/bin/env bash
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# SHELLDOC-IGNORE
+
+add_test_type checkmake
+
+CHECKMAKE_TIMER=0
+
+CHECKMAKE=${CHECKMAKE:-$(command -v checkmake 2>/dev/null)}
+
+function checkmake_usage
+{
+ yetus_add_option "--checkmake=<path>" "path to checkmake executable"
+ yetus_add_option "--checkmake-config=<path>" "relative path to checkmake config in source tree [default: none]"
+}
+
+function checkmake_parse_args
+{
+ local i
+
+ for i in "$@"; do
+ case ${i} in
+ --checkmake=*)
+ CHECKMAKE=${i#*=}
+ ;;
+ --checkmake-config=*)
+ CHECKMAKE_CONFIG=${i#*=}
+ ;;
+ esac
+ done
+}
+
+function checkmake_filefilter
+{
+ local filename=$1
+
+ if [[ ${filename} =~ /Makefile$ ]] || [[ ${filename} =~ ^Makefile$ ]]; then
+ add_test checkmake
+ fi
+}
+
+function checkmake_precheck
+{
+ if ! verify_command checkmake "${CHECKMAKE}"; then
+ add_vote_table 0 checkmake "checkmake was not available."
+ delete_test checkmake
+ fi
+}
+
+function checkmake_exec
+{
+ declare i
+ declare repostatus=$1
+ declare -a args
+
+ echo "Running checkmake against identified Makefiles."
+ pushd "${BASEDIR}" >/dev/null || return 1
+
+
+ args=('--format={{.LineNumber}}:{{.Rule}}:{{.Violation}}')
+ if [[ -f "${CHECKMAKE_CONFIG}" ]]; then
+ args+=("--config=${CHECKMAKE_CONFIG}")
+ fi
+
+ for i in "${CHANGED_FILES[@]}"; do
+ if [[ ${i} =~ /Makefile$ ]] || [[ ${i} =~ ^Makefile$ ]]; then
+ if [[ -f ${i} ]]; then
+ while read -r; do
+ echo "${i}:${REPLY}" >> "${PATCH_DIR}/${repostatus}-checkmake-result.txt"
+ done < <("${CHECKMAKE}" "${args[@]}" "${i}")
+ fi
+ fi
+ done
+
+ popd >/dev/null || return 1
+ return 0
+}
+
+function checkmake_preapply
+{
+ declare i
+ declare -a args
+
+ if ! verify_needed_test checkmake; then
+ return 0
+ fi
+
+ big_console_header "checkmake plugin: ${PATCH_BRANCH}"
+
+ start_clock
+
+ checkmake_exec branch
+
+ CHECKMAKE_TIMER=$(stop_clock)
+ return 0
+}
+
+## @description Wrapper to call column_calcdiffs
+## @audience private
+## @stability evolving
+## @replaceable no
+## @param branchlog
+## @param patchlog
+## @return differences
+function checkmake_calcdiffs
+{
+ column_calcdiffs "$@"
+}
+
+function checkmake_postapply
+{
+ declare i
+ declare numPrepatch
+ declare numPostpatch
+ declare diffPostpatch
+ declare fixedpatch
+ declare statstring
+
+ if ! verify_needed_test checkmake; then
+ return 0
+ fi
+
+ big_console_header "checkmake plugin: ${BUILDMODE}"
+
+ start_clock
+
+ # add our previous elapsed to our new timer
+ # by setting the clock back
+ offset_clock "${CHECKMAKE_TIMER}"
+
+ checkmake_exec patch
+
+ calcdiffs \
+ "${PATCH_DIR}/branch-checkmake-result.txt" \
+ "${PATCH_DIR}/patch-checkmake-result.txt" \
+ checkmake \
+ > "${PATCH_DIR}/diff-patch-checkmake.txt"
+ diffPostpatch=$("${AWK}" -F: 'BEGIN {sum=0} 3<NF {sum+=1} END {print sum}' "${PATCH_DIR}/diff-patch-checkmake.txt")
+
+ # shellcheck disable=SC2016
+ numPrepatch=$("${AWK}" -F: 'BEGIN {sum=0} 3<NF {sum+=1} END {print sum}' "${PATCH_DIR}/branch-checkmake-result.txt")
+
+ # shellcheck disable=SC2016
+ numPostpatch=$("${AWK}" -F: 'BEGIN {sum=0} 3<NF {sum+=1} END {print sum}' "${PATCH_DIR}/patch-checkmake-result.txt")
+
+ ((fixedpatch=numPrepatch-numPostpatch+diffPostpatch))
+
+ statstring=$(generic_calcdiff_status "${numPrepatch}" "${numPostpatch}" "${diffPostpatch}" )
+
+ if [[ ${diffPostpatch} -gt 0 ]] ; then
+ add_vote_table -1 checkmake "${BUILDMODEMSG} ${statstring}"
+ add_footer_table checkmake "@@BASE@@/diff-patch-checkmake.txt"
+ return 1
+ elif [[ ${fixedpatch} -gt 0 ]]; then
+ add_vote_table +1 checkmake "${BUILDMODEMSG} ${statstring}"
+ return 0
+ fi
+
+ add_vote_table +1 checkmake "There were no new checkmake issues."
+ return 0
+}
+
+function checkmake_postcompile
+{
+ declare repostatus=$1
+
+ if [[ "${repostatus}" = branch ]]; then
+ checkmake_preapply
+ else
+ checkmake_postapply
+ fi
+}
diff --git a/precommit/src/main/shell/test-patch.d/golang.sh b/precommit/src/main/shell/test-patch.d/golang.sh
new file mode 100755
index 0000000..2b67365
--- /dev/null
+++ b/precommit/src/main/shell/test-patch.d/golang.sh
@@ -0,0 +1,178 @@
+#!/usr/bin/env bash
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+add_test_type golang
+
+GOEXE=$(command -v go 2>/dev/null)
+
+declare -a GOMOD_DIRS
+GOMOD_DIRS_CONTROL=reset
+
+## @description Usage info for go plugin
+## @audience private
+## @stability evolving
+## @replaceable no
+function golang_usage
+{
+ yetus_add_option "--golang-go=<cmd>" "Location of the go binary (default: \"${GOEXE:-not found}\")"
+}
+
+## @description Option parsing for go plugin
+## @audience private
+## @stability evolving
+## @replaceable no
+function golang_parse_args
+{
+ declare i
+
+ for i in "$@"; do
+ case ${i} in
+ --golang-go=*)
+ GOEXE=${i#*=}
+ ;;
+ esac
+ done
+}
+
+## @description find all non-vendor directories that have a go.mod file
+## @audience public
+## @stability evolving
+## @replaceable yes
+function golang_gomod_find
+{
+ declare input
+
+ if [[ "${GOMOD_DIRS_CONTROL}" == reset ]]; then
+ GOMOD_DIRS=()
+ while read -r; do
+ if [[ ! "${REPLY}" =~ /vendor/ ]] &&
+ [[ ! "${REPLY}" =~ ^vendor ]]; then
+ input=${REPLY%%/go.mod}
+ GOMOD_DIRS+=("${input}")
+ fi
+ done < <(find "${BASEDIR}" -name go.mod)
+ GOMOD_DIRS_CONTROL=filled
+ fi
+}
+
+
+## @description Determine if a file is in GOMOD_DIRS[@]
+## @audience public
+## @stability evolving
+## @replaceable yes
+## @return all matching dirs
+function golang_gomod_file
+{
+ declare fn=${1}
+
+ yetus_find_deepest_directory GOMOD_DIRS "${BASEDIR}/${fn}"
+}
+
+
+## @description discover files to check
+## @audience private
+## @stability stable
+## @replaceable yes
+function golang_filefilter
+{
+ declare filename=$1
+
+ golang_gomod_find
+
+ if [[ "${filename}" =~ \.(c|h|go|s|cc)$ ]] ||
+ [[ "${filename}" =~ go.mod$ ]]; then
+ if golang_gomod_file "${filename}" >/dev/null; then
+ yetus_debug "tests/golang: ${filename}"
+ add_test golang
+ add_test compile
+ fi
+ fi
+}
+
+## @description check for golang compiler errors
+## @audience private
+## @stability stable
+## @replaceable no
+function golang_precompile
+{
+ GOMOD_DIRS_CONTROL=reset
+}
+
+## @description check for golang compiler errors
+## @audience private
+## @stability stable
+## @replaceable no
+function golang_compile
+{
+ declare codebase=$1
+ declare multijdkmode=$2
+
+ if ! verify_needed_test golang; then
+ return 0
+ fi
+
+ if [[ ${codebase} = patch ]]; then
+ generic_postlog_compare compile golang "${multijdkmode}"
+ fi
+}
+
+## @description Helper for generic_logfilter
+## @audience private
+## @stability evolving
+## @replaceable yes
+function golang_logfilter
+{
+ declare input=$1
+ declare output=$2
+
+ #shellcheck disable=SC1117
+ "${GREP}" -i -E "^.*\.go\:[[:digit:]]*\:" "${input}" > "${output}"
+}
+
+## @description go post
+## @audience private
+## @stability evolving
+## @replaceable yes
+function golang_postapply
+{
+ if [[ -z "${GOEXE}" ]]; then
+ # shellcheck disable=SC2016
+ version=$("${GOEXE}" version 2>&1 | "${AWK}" '{print $3}' 2>&1)
+ add_version_data golang "${version#* }"
+ fi
+}
+
+## @description set volumes and options as appropriate for maven
+## @audience private
+## @stability evolving
+## @replaceable yes
+function golang_docker_support
+{
+ add_docker_env CGO_LDFLAGS
+ add_docker_env CGO_ENABLED
+ add_docker_env GO111MODULE
+ add_docker_env GOPATH
+}
+
+
+## @description set volumes and options as appropriate for maven
+## @audience private
+## @stability evolving
+## @replaceable yes
+function golang_clean
+{
+ git_checkout_force
+}
\ No newline at end of file
diff --git a/precommit/src/main/shell/test-patch.d/golangci.sh b/precommit/src/main/shell/test-patch.d/golangci.sh
new file mode 100644
index 0000000..462dbb0
--- /dev/null
+++ b/precommit/src/main/shell/test-patch.d/golangci.sh
@@ -0,0 +1,201 @@
+#!/usr/bin/env bash
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# SHELLDOC-IGNORE
+
+add_test_type golangcilint
+
+GOLANGCI_TIMER=0
+GOLANGCI_LINT=$(command -v golangci-lint 2>/dev/null)
+
+## @description Usage info for slack plugin
+## @audience private
+## @stability evolving
+## @replaceable no
+function golangcilint_usage
+{
+ yetus_add_option "--golangcilint=<cmd>" "Location of the go binary (default: \"${GOLANGCI_LINT:-not found}\")"
+ yetus_add_option "--golangcilint-config=<cmd>" "Location of the config file"
+}
+
+## @description Option parsing for slack plugin
+## @audience private
+## @stability evolving
+## @replaceable no
+function golangcilint_parse_args
+{
+ declare i
+
+ for i in "$@"; do
+ case ${i} in
+ --golangcilint=*)
+ GOLANGCI_LINT=${i#*=}
+ ;;
+ --golangcilint-config=*)
+ GOLANGCI_CONFIG=${i#*=}
+ ;;
+ esac
+ done
+}
+
+function golangcilint_filefilter
+{
+ declare filename=$1
+
+ if [[ ${filename} =~ \.go$ ]]; then
+ add_test golangcilint
+ fi
+}
+
+function golangcilint_precheck
+{
+ if [[ -z "${GOLANGCI_LINT}" ]]; then
+ add_vote_table 0 golangcilint "golangci-lint was not found."
+ delete_test golangcilint
+ fi
+}
+
+function golangcilint_exec
+{
+ declare i
+ declare repostatus=$1
+ declare -a args
+ declare -a gargs
+
+ if [[ -f "${EXCLUDE_PATHS_FILE}" ]]; then
+ gargs=("${GREP}" "-v" "-E" "-f" "${EXCLUDE_PATHS_FILE}")
+ else
+ gargs=("cat")
+ fi
+
+ args=("--color=never")
+ args+=("--out-format=line-number")
+ args+=("--print-issued-lines=false")
+
+ if [[ -f "${GOLANGCI_CONFIG}" ]]; then
+ args+=("--config" "${GOLANGCI_CONFIG}")
+ fi
+
+ golang_gomod_find
+
+ for d in "${GOMOD_DIRS[@]}"; do
+ pushd "${d}" >/dev/null || return 1
+ while read -r; do
+ p=$(yetus_relative_dir "${BASEDIR}" "${d}")
+ if [[ -n "${p}" ]]; then
+ p="${p}/"
+ fi
+ echo "${p}${REPLY}" >> "${PATCH_DIR}/${repostatus}-golangcilint-result.txt"
+ done < <("${GOLANGCI_LINT}" run "${args[@]}" ./... 2>&1 \
+ | "${gargs[@]}" \
+ | sort -t : -k 1,1 -k 2,2n -k 3,3n)
+ popd >/dev/null || return 1
+ done
+ return 0
+}
+
+function golangcilint_preapply
+{
+ declare i
+
+ if ! verify_needed_test golangcilint; then
+ return 0
+ fi
+
+ big_console_header "golangcilint plugin: ${PATCH_BRANCH}"
+
+ start_clock
+
+ golangcilint_exec branch
+ GOLANGCI_TIMER=$(stop_clock)
+ return 0
+}
+
+## @description Wrapper to call column_calcdiffs
+## @audience private
+## @stability evolving
+## @replaceable no
+## @param branchlog
+## @param patchlog
+## @return differences
+function golangcilint_calcdiffs
+{
+ column_calcdiffs "$@"
+}
+
+function golangcilint_postapply
+{
+ declare i
+ declare numPrepatch
+ declare numPostpatch
+ declare diffPostpatch
+ declare fixedpatch
+ declare statstring
+
+ if ! verify_needed_test golangcilint; then
+ return 0
+ fi
+
+ big_console_header "golangcilint plugin: ${BUILDMODE}"
+
+ start_clock
+
+ # add our previous elapsed to our new timer
+ # by setting the clock back
+ offset_clock "${GOLANGCI_TIMER}"
+
+ golangcilint_exec patch
+
+ calcdiffs \
+ "${PATCH_DIR}/branch-golangcilint-result.txt" \
+ "${PATCH_DIR}/patch-golangcilint-result.txt" \
+ golangcilint \
+ > "${PATCH_DIR}/diff-patch-golangcilint.txt"
+ diffPostpatch=$("${AWK}" -F: 'BEGIN {sum=0} 3<NF {sum+=1} END {print sum}' "${PATCH_DIR}/diff-patch-golangcilint.txt")
+
+ # shellcheck disable=SC2016
+ numPrepatch=$("${AWK}" -F: 'BEGIN {sum=0} 3<NF {sum+=1} END {print sum}' "${PATCH_DIR}/branch-golangcilint-result.txt")
+
+ # shellcheck disable=SC2016
+ numPostpatch=$("${AWK}" -F: 'BEGIN {sum=0} 3<NF {sum+=1} END {print sum}' "${PATCH_DIR}/patch-golangcilint-result.txt")
+
+ ((fixedpatch=numPrepatch-numPostpatch+diffPostpatch))
+
+ statstring=$(generic_calcdiff_status "${numPrepatch}" "${numPostpatch}" "${diffPostpatch}" )
+
+ if [[ ${diffPostpatch} -gt 0 ]] ; then
+ add_vote_table -1 golangcilint "${BUILDMODEMSG} ${statstring}"
+ add_footer_table golangcilint "@@BASE@@/diff-patch-golangcilint.txt"
+ return 1
+ elif [[ ${fixedpatch} -gt 0 ]]; then
+ add_vote_table +1 golangcilint "${BUILDMODEMSG} ${statstring}"
+ return 0
+ fi
+
+ add_vote_table +1 golangcilint "There were no new golangcilint issues."
+ return 0
+}
+
+function golangcilint_postcompile
+{
+ declare repostatus=$1
+
+ if [[ "${repostatus}" = branch ]]; then
+ golangcilint_preapply
+ else
+ golangcilint_postapply
+ fi
+}
diff --git a/precommit/src/main/shell/test-patch.d/make.sh b/precommit/src/main/shell/test-patch.d/make.sh
index 35bbb1a..2dff730 100755
--- a/precommit/src/main/shell/test-patch.d/make.sh
+++ b/precommit/src/main/shell/test-patch.d/make.sh
@@ -116,7 +116,7 @@
;;
distclean)
if [[ ${MAKE_GITCLEAN} = true ]];then
- git clean -x -f -d
+ git_clean
else
modules_workers "${repostatus}" distclean clean
fi
diff --git a/precommit/src/main/shell/test-patch.d/revive.sh b/precommit/src/main/shell/test-patch.d/revive.sh
new file mode 100755
index 0000000..5486123
--- /dev/null
+++ b/precommit/src/main/shell/test-patch.d/revive.sh
@@ -0,0 +1,181 @@
+#!/usr/bin/env bash
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# SHELLDOC-IGNORE
+
+add_test_type revive
+
+REVIVE_TIMER=0
+
+REVIVE=${REVIVE:-$(command -v revive 2>/dev/null)}
+
+function revive_usage
+{
+ yetus_add_option "--revive=<path>" "path to revive executable"
+ yetus_add_option "--revive-config=<path>" "relative path to revive config in source tree [default: none]"
+}
+
+function revive_parse_args
+{
+ local i
+
+ for i in "$@"; do
+ case ${i} in
+ --revive=*)
+ REVIVE=${i#*=}
+ ;;
+ --revive-config=*)
+ REVIVE_CONFIG=${i#*=}
+ ;;
+ esac
+ done
+}
+
+function revive_filefilter
+{
+ local filename=$1
+
+ if [[ ${filename} =~ \.go$ ]]; then
+ add_test revive
+ fi
+}
+
+function revive_precheck
+{
+ if ! verify_command revive "${REVIVE}"; then
+ add_vote_table 0 revive "revive was not available."
+ delete_test revive
+ fi
+}
+
+function revive_exec
+{
+ declare i
+ declare repostatus=$1
+ declare -a args
+
+ echo "Running revive against identified go files."
+ pushd "${BASEDIR}" >/dev/null || return 1
+
+ args=('-formatter' 'default')
+ if [[ -f "${REVIVE_CONFIG}" ]]; then
+ args+=('-config' "${REVIVE_CONFIG}")
+ fi
+
+ for i in "${CHANGED_FILES[@]}"; do
+ if [[ ${i} =~ \.go$ && -f ${i} ]]; then
+ "${REVIVE}" "${args[@]}" "${i}" | sort -t : -k1,1 -k2,2n -k3,3n >> "${PATCH_DIR}/${repostatus}-revive-result.txt"
+ fi
+ done
+
+ popd >/dev/null || return 1
+ return 0
+}
+
+function revive_preapply
+{
+ declare i
+ declare -a args
+
+ if ! verify_needed_test revive; then
+ return 0
+ fi
+
+ big_console_header "revive plugin: ${PATCH_BRANCH}"
+
+ start_clock
+
+ revive_exec branch
+
+ REVIVE_TIMER=$(stop_clock)
+ return 0
+}
+
+## @description Wrapper to call column_calcdiffs
+## @audience private
+## @stability evolving
+## @replaceable no
+## @param branchlog
+## @param patchlog
+## @return differences
+function revive_calcdiffs
+{
+ column_calcdiffs "$@"
+}
+
+function revive_postapply
+{
+ declare i
+ declare numPrepatch
+ declare numPostpatch
+ declare diffPostpatch
+ declare fixedpatch
+ declare statstring
+
+ if ! verify_needed_test revive; then
+ return 0
+ fi
+
+ big_console_header "revive plugin: ${BUILDMODE}"
+
+ start_clock
+
+ # add our previous elapsed to our new timer
+ # by setting the clock back
+ offset_clock "${REVIVE_TIMER}"
+
+ revive_exec patch
+
+ calcdiffs \
+ "${PATCH_DIR}/branch-revive-result.txt" \
+ "${PATCH_DIR}/patch-revive-result.txt" \
+ revive \
+ > "${PATCH_DIR}/diff-patch-revive.txt"
+ diffPostpatch=$("${AWK}" -F: 'BEGIN {sum=0} 3<NF {sum+=1} END {print sum}' "${PATCH_DIR}/diff-patch-revive.txt")
+
+ # shellcheck disable=SC2016
+ numPrepatch=$("${AWK}" -F: 'BEGIN {sum=0} 3<NF {sum+=1} END {print sum}' "${PATCH_DIR}/branch-revive-result.txt")
+
+ # shellcheck disable=SC2016
+ numPostpatch=$("${AWK}" -F: 'BEGIN {sum=0} 3<NF {sum+=1} END {print sum}' "${PATCH_DIR}/patch-revive-result.txt")
+
+ ((fixedpatch=numPrepatch-numPostpatch+diffPostpatch))
+
+ statstring=$(generic_calcdiff_status "${numPrepatch}" "${numPostpatch}" "${diffPostpatch}" )
+
+ if [[ ${diffPostpatch} -gt 0 ]] ; then
+ add_vote_table -1 revive "${BUILDMODEMSG} ${statstring}"
+ add_footer_table revive "@@BASE@@/diff-patch-revive.txt"
+ return 1
+ elif [[ ${fixedpatch} -gt 0 ]]; then
+ add_vote_table +1 revive "${BUILDMODEMSG} ${statstring}"
+ return 0
+ fi
+
+ add_vote_table +1 revive "There were no new revive issues."
+ return 0
+}
+
+function revive_postcompile
+{
+ declare repostatus=$1
+
+ if [[ "${repostatus}" = branch ]]; then
+ revive_preapply
+ else
+ revive_postapply
+ fi
+}
diff --git a/precommit/src/main/shell/test-patch.d/whitespace.sh b/precommit/src/main/shell/test-patch.d/whitespace.sh
index 6d3b682..29963f9 100755
--- a/precommit/src/main/shell/test-patch.d/whitespace.sh
+++ b/precommit/src/main/shell/test-patch.d/whitespace.sh
@@ -17,7 +17,7 @@
# SHELLDOC-IGNORE
WHITESPACE_EOL_IGNORE_LIST=
-WHITESPACE_TABS_IGNORE_LIST='.*Makefile.*','.*\.go'
+WHITESPACE_TABS_IGNORE_LIST='.*Makefile.*','.*\.go','.*go\.mod'
add_test_type whitespace
diff --git a/precommit/src/main/shell/test-patch.sh b/precommit/src/main/shell/test-patch.sh
index 27d5f98..eb1ebb4 100755
--- a/precommit/src/main/shell/test-patch.sh
+++ b/precommit/src/main/shell/test-patch.sh
@@ -1136,6 +1136,45 @@
return 0
}
+## @description git clean the repository
+## @audience public
+## @stability stable
+## @replaceable no
+## @return 0 on success
+function git_clean
+{
+ declare exemptdir
+
+ if [[ ${RESETREPO} == "true" ]]; then
+ # if PATCH_DIR is in BASEDIR, then we don't want
+ # git wiping it out.
+ exemptdir=$(yetus_relative_dir "${BASEDIR}" "${PATCH_DIR}")
+ if [[ $? == 1 ]]; then
+ "${GIT}" clean -xdf
+ else
+ # we do, however, want it emptied of all _files_.
+ # we need to leave _directories_ in case we are in
+ # re-exec mode (which places a directory full of stuff in it)
+ yetus_debug "Exempting ${exemptdir} from clean"
+ "${GIT}" clean -xdf -e "${exemptdir}"
+ fi
+ fi
+}
+
+## @description Forcibly reset the tree back to it's original state
+## @audience public
+## @stability stable
+## @replaceable no
+## @return 0 on success
+function git_checkout_force
+{
+ declare exemptdir
+
+ if [[ ${RESETREPO} == "true" ]]; then
+ git_clean && "${GIT}" checkout --force "${PATCH_BRANCH}"
+ fi
+}
+
## @description git checkout the appropriate branch to test. Additionally, this calls
## @description 'determine_branch' based upon the context provided
## @description in ${PATCH_DIR} and in git after checkout.
@@ -1177,26 +1216,19 @@
cleanup_and_exit 1
fi
+ if ! git_clean; then
+ yetus_error "ERROR: git clean is failing"
+ cleanup_and_exit 1
+ fi
+
# if PATCH_DIR is in BASEDIR, then we don't want
# git wiping it out.
- exemptdir=$(yetus_relative_dir "${BASEDIR}" "${PATCH_DIR}")
- if [[ $? == 1 ]]; then
- "${GIT}" clean -xdf
- status=$?
-
- else
- # we do, however, want it emptied of all _files_.
- # we need to leave _directories_ in case we are in
+ if yetus_relative_dir "${BASEDIR}" "${PATCH_DIR}" >/dev/null; then
+ # we need to empty out PATCH_DIR, but
+ # leave _directories_ in case we are in
# re-exec mode (which places a directory full of stuff in it)
yetus_debug "Exempting ${exemptdir} from clean"
rm "${PATCH_DIR}/*" 2>/dev/null
- "${GIT}" clean -xdf -e "${exemptdir}"
- status=$?
- fi
-
- if [[ ${status} != 0 ]]; then
- yetus_error "ERROR: git clean is failing"
- cleanup_and_exit 1
fi
if [[ "${GIT_SHALLOW}" == false ]]; then
@@ -1244,7 +1276,7 @@
fi
fi
- if ! "${GIT}" clean -df; then
+ if ! git_clean; then
yetus_error "ERROR: git clean is failing"
cleanup_and_exit 1
fi
@@ -2971,7 +3003,7 @@
for plugin in "${TESTTYPES[@]}" "${TESTFORMATS[@]}"; do
if declare -f "${plugin}_clean" >/dev/null 2>&1; then
- yetus_debug "Running ${plugin}_distclean"
+ yetus_debug "Running ${plugin}_clean"
if ! "${plugin}_clean"; then
((result = result+1))
fi