Repository: yetus Updated Branches: refs/heads/master 3cba0293d -> 88ca00a0d
YETUS-483. shellcheck plugin should be smarter about its queue Signed-off-by: Kengo Seki <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/yetus/repo Commit: http://git-wip-us.apache.org/repos/asf/yetus/commit/88ca00a0 Tree: http://git-wip-us.apache.org/repos/asf/yetus/tree/88ca00a0 Diff: http://git-wip-us.apache.org/repos/asf/yetus/diff/88ca00a0 Branch: refs/heads/master Commit: 88ca00a0d47a689c949efde913dca9d43fcd67e5 Parents: 3cba029 Author: Allen Wittenauer <[email protected]> Authored: Fri May 19 22:04:18 2017 -0700 Committer: Kengo Seki <[email protected]> Committed: Fri May 26 04:53:19 2017 -0400 ---------------------------------------------------------------------- precommit/core.d/00-yetuslib.sh | 89 ++++++++++++++++++++- precommit/test-patch.d/shellcheck.sh | 123 ++++++++++++++++++------------ 2 files changed, 163 insertions(+), 49 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/yetus/blob/88ca00a0/precommit/core.d/00-yetuslib.sh ---------------------------------------------------------------------- diff --git a/precommit/core.d/00-yetuslib.sh b/precommit/core.d/00-yetuslib.sh index 25118cb..983dfe6 100755 --- a/precommit/core.d/00-yetuslib.sh +++ b/precommit/core.d/00-yetuslib.sh @@ -241,4 +241,91 @@ function yetus_comma_to_array oldifs="${IFS}" IFS=',' read -r -a "${var}" <<< "${string}" IFS="${oldifs}" -} \ No newline at end of file +} + +## @description Check if an array has a given value +## @audience public +## @stability stable +## @replaceable yes +## @param element +## @param array +## @returns 0 = yes +## @returns 1 = no +function yetus_array_contains +{ + declare element=$1 + shift + declare val + + if [[ "$#" -eq 0 ]]; then + return 1 + fi + + for val in "${@}"; do + if [[ "${val}" == "${element}" ]]; then + return 0 + fi + done + return 1 +} + +## @description Add the element if it is not +## @description present in the given array +## @audience public +## @stability stable +## @replaceable yes +## @param arrayname +## @param element +function yetus_add_array_element +{ + declare arrname=$1 + declare add=$2 + + declare arrref="${arrname}[@]" + declare array=("${!arrref}") + + if ! yetus_array_contains "${add}" "${array[@]}"; then + # shellcheck disable=SC1083,SC2086 + eval "${arrname}"=\(\"\${array[@]}\" \"${add}\" \) + yetus_debug "$1 accepted $2" + else + yetus_debug "$1 declined $2" + fi +} + +## @description Sort an array by its elements +## @audience public +## @stability stable +## @replaceable yes +## @param arrayvar +function yetus_sort_array +{ + declare arrname=$1 + declare arrref="${arrname}[@]" + declare array=("${!arrref}") + + declare globstatus + declare oifs + declare -a sa + + globstatus=$(set -o | grep noglob | awk '{print $NF}') + + if [[ -n ${IFS} ]]; then + oifs=${IFS} + fi + set -f + # shellcheck disable=SC2034 + IFS=$'\n' sa=($(sort <<<"${array[*]}")) + # shellcheck disable=SC1083 + eval "${arrname}"=\(\"\${sa[@]}\"\) + + if [[ -n "${oifs}" ]]; then + IFS=${oifs} + else + unset IFS + fi + + if [[ "${globstatus}" = off ]]; then + set +f + fi +} http://git-wip-us.apache.org/repos/asf/yetus/blob/88ca00a0/precommit/test-patch.d/shellcheck.sh ---------------------------------------------------------------------- diff --git a/precommit/test-patch.d/shellcheck.sh b/precommit/test-patch.d/shellcheck.sh index dd9783c..61b2cb3 100755 --- a/precommit/test-patch.d/shellcheck.sh +++ b/precommit/test-patch.d/shellcheck.sh @@ -14,6 +14,9 @@ # See the License for the specific language governing permissions and # limitations under the License. +# no public APIs here +# SHELLDOC-IGNORE + add_test_type shellcheck SHELLCHECK_TIMER=0 @@ -21,21 +24,28 @@ SHELLCHECK_X=true SHELLCHECK=${SHELLCHECK:-$(which shellcheck 2>/dev/null)} -SHELLCHECK_SPECIFICFILES="" +# files that are going to get shellcheck'd +SHELLCHECK_CHECKFILES=() + +# files that are going to get shellcheck'd +SHELLCHECK_FILTERFILES=() + # if it ends in an explicit .sh, then this is shell code. -# if it doesn't have an extension, we assume it is shell code too +# if it doesn't have an extension, then assume it is and +# we'll deal with it later function shellcheck_filefilter { - local filename=$1 + declare filename=$1 if [[ ${filename} =~ \.sh$ ]]; then add_test shellcheck - SHELLCHECK_SPECIFICFILES="${SHELLCHECK_SPECIFICFILES} ./${filename}" + yetus_add_array_element SHELLCHECK_FILTERFILES "${filename}" fi if [[ ! ${filename} =~ \. ]]; then add_test shellcheck + yetus_add_array_element SHELLCHECK_FILTERFILES "${filename}" fi } @@ -83,32 +93,70 @@ function shellcheck_precheck fi } -function shellcheck_private_findbash +function shellcheck_criteria +{ + declare fn=$1 + declare text + + if [[ ! -f "${fn}" ]]; then + yetus_debug "Shellcheck rejected (not exist): ${fn}" + return + fi + + text=$(head -n 1 "${fn}") + + # shell check requires either a bangpath or a shell check directive + # on the first line. so check for a leading comment char + # and some sort of reference to 'sh' + if echo "${text}" | "${GREP}" -E -q "^#"; then + if echo "${text}" | "${GREP}" -q sh; then + yetus_add_array_element SHELLCHECK_CHECKFILES "${fn}" + yetus_debug "Shellcheck added: ${fn}" + fi + fi +} + +function shellcheck_findscripts { - local i - local value - local list - - while read -r line; do - value=$(find "${line}" ! -name '*.cmd' -type f \ - | ${GREP} -E -v '(.orig$|.rej$)') - - for i in ${value}; do - if [[ ! ${i} =~ \.sh(\.|$) - && ! $(head -n 1 "${i}") =~ ^#! ]]; then - yetus_debug "Shellcheck skipped: ${i}" - continue - fi - list="${list} ${i}" - done - done < <(find . -type d -name bin -o -type d -name sbin -o -type d -name scripts -o -type d -name libexec -o -type d -name shellprofile.d) - # shellcheck disable=SC2086 - echo ${list} ${SHELLCHECK_SPECIFICFILES} | tr ' ' '\n' | sort -u + declare fn + + # reset + SHELLCHECK_CHECKFILES=() + + # run through the files our filter caught + # this will set SHELLCHECK_CHECKFILES elements + for fn in "${SHELLCHECK_FILTERFILES[@]}"; do + shellcheck_criteria "${fn}" + done + + # finally, sort the array + yetus_sort_array SHELLCHECK_CHECKFILES } -function shellcheck_preapply +function shellcheck_logic { + declare repostatus=$1 declare i + + echo "Running shellcheck against all suspected shell scripts" + pushd "${BASEDIR}" >/dev/null + + # need to run this every time in case patch + # add/removed files + shellcheck_findscripts + + for i in "${SHELLCHECK_CHECKFILES[@]}"; do + if [[ "${SHELLCHECK_X}" = true ]]; then + "${SHELLCHECK}" -x -f gcc "${i}" >> "${PATCH_DIR}/${repostatus}-shellcheck-result.txt" + else + "${SHELLCHECK}" -f gcc "${i}" >> "${PATCH_DIR}/${repostatus}-shellcheck-result.txt" + fi + done + popd > /dev/null +} + +function shellcheck_preapply +{ declare msg if ! verify_needed_test shellcheck; then @@ -119,18 +167,7 @@ function shellcheck_preapply start_clock - echo "Running shellcheck against all identifiable shell scripts" - pushd "${BASEDIR}" >/dev/null - for i in $(shellcheck_private_findbash); do - if [[ -f ${i} ]]; then - if [[ "${SHELLCHECK_X}" = true ]]; then - "${SHELLCHECK}" -x -f gcc "${i}" >> "${PATCH_DIR}/branch-shellcheck-result.txt" - else - "${SHELLCHECK}" -f gcc "${i}" >> "${PATCH_DIR}/branch-shellcheck-result.txt" - fi - fi - done - popd > /dev/null + shellcheck_logic branch msg="v${SHELLCHECK_VERSION}" if [[ ${SHELLCHECK_VERSION} =~ 0.[0-3].[0-5] ]]; then @@ -176,17 +213,7 @@ function shellcheck_postapply # by setting the clock back offset_clock "${SHELLCHECK_TIMER}" - echo "Running shellcheck against all identifiable shell scripts" - # we re-check this in case one has been added - for i in $(shellcheck_private_findbash); do - if [[ -f ${i} ]]; then - if [[ "${SHELLCHECK_X}" = true ]]; then - "${SHELLCHECK}" -x -f gcc "${i}" >> "${PATCH_DIR}/patch-shellcheck-result.txt" - else - "${SHELLCHECK}" -f gcc "${i}" >> "${PATCH_DIR}/patch-shellcheck-result.txt" - fi - fi - done + shellcheck_logic patch calcdiffs \ "${PATCH_DIR}/branch-shellcheck-result.txt" \
