shellcheck.sh 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. #!/usr/bin/env bash
  2. # Licensed to the Apache Software Foundation (ASF) under one or more
  3. # contributor license agreements. See the NOTICE file distributed with
  4. # this work for additional information regarding copyright ownership.
  5. # The ASF licenses this file to You under the Apache License, Version 2.0
  6. # (the "License"); you may not use this file except in compliance with
  7. # the License. You may obtain a copy of the License at
  8. #
  9. # http://www.apache.org/licenses/LICENSE-2.0
  10. #
  11. # Unless required by applicable law or agreed to in writing, software
  12. # distributed under the License is distributed on an "AS IS" BASIS,
  13. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. # See the License for the specific language governing permissions and
  15. # limitations under the License.
  16. add_plugin shellcheck
  17. SHELLCHECK_TIMER=0
  18. SHELLCHECK=${SHELLCHECK:-$(which shellcheck 2>/dev/null)}
  19. SHELLCHECK_SPECIFICFILES=""
  20. # if it ends in an explicit .sh, then this is shell code.
  21. # if it doesn't have an extension, we assume it is shell code too
  22. function shellcheck_filefilter
  23. {
  24. local filename=$1
  25. if [[ ${filename} =~ \.sh$ ]]; then
  26. add_test shellcheck
  27. SHELLCHECK_SPECIFICFILES="${SHELLCHECK_SPECIFICFILES} ./${filename}"
  28. fi
  29. if [[ ! ${filename} =~ \. ]]; then
  30. add_test shellcheck
  31. fi
  32. }
  33. function shellcheck_private_findbash
  34. {
  35. local i
  36. local value
  37. local list
  38. while read line; do
  39. value=$(find "${line}" ! -name '*.cmd' -type f \
  40. | ${GREP} -E -v '(.orig$|.rej$)')
  41. list="${list} ${value}"
  42. done < <(find . -type d -name bin -o -type d -name sbin -o -type d -name libexec -o -type d -name shellprofile.d)
  43. # shellcheck disable=SC2086
  44. echo ${list} ${SHELLCHECK_SPECIFICFILES} | tr ' ' '\n' | sort -u
  45. }
  46. function shellcheck_preapply
  47. {
  48. local i
  49. verify_needed_test shellcheck
  50. if [[ $? == 0 ]]; then
  51. return 0
  52. fi
  53. big_console_header "shellcheck plugin: prepatch"
  54. if [[ ! -x "${SHELLCHECK}" ]]; then
  55. hadoop_error "shellcheck is not available."
  56. return 0
  57. fi
  58. start_clock
  59. # shellcheck disable=SC2016
  60. SHELLCHECK_VERSION=$(${SHELLCHECK} --version | ${GREP} version: | ${AWK} '{print $NF}')
  61. echo "Running shellcheck against all identifiable shell scripts"
  62. pushd "${BASEDIR}" >/dev/null
  63. for i in $(shellcheck_private_findbash); do
  64. if [[ -f ${i} ]]; then
  65. ${SHELLCHECK} -f gcc "${i}" >> "${PATCH_DIR}/${PATCH_BRANCH}shellcheck-result.txt"
  66. fi
  67. done
  68. popd > /dev/null
  69. # keep track of how much as elapsed for us already
  70. SHELLCHECK_TIMER=$(stop_clock)
  71. return 0
  72. }
  73. function shellcheck_calcdiffs
  74. {
  75. local orig=$1
  76. local new=$2
  77. local diffout=$3
  78. local tmp=${PATCH_DIR}/sc.$$.${RANDOM}
  79. local count=0
  80. local j
  81. # first, pull out just the errors
  82. # shellcheck disable=SC2016
  83. ${AWK} -F: '{print $NF}' "${orig}" >> "${tmp}.branch"
  84. # shellcheck disable=SC2016
  85. ${AWK} -F: '{print $NF}' "${new}" >> "${tmp}.patch"
  86. # compare the errors, generating a string of line
  87. # numbers. Sorry portability: GNU diff makes this too easy
  88. ${DIFF} --unchanged-line-format="" \
  89. --old-line-format="" \
  90. --new-line-format="%dn " \
  91. "${tmp}.branch" \
  92. "${tmp}.patch" > "${tmp}.lined"
  93. # now, pull out those lines of the raw output
  94. # shellcheck disable=SC2013
  95. for j in $(cat "${tmp}.lined"); do
  96. # shellcheck disable=SC2086
  97. head -${j} "${new}" | tail -1 >> "${diffout}"
  98. done
  99. if [[ -f "${diffout}" ]]; then
  100. # shellcheck disable=SC2016
  101. count=$(wc -l "${diffout}" | ${AWK} '{print $1}' )
  102. fi
  103. rm "${tmp}.branch" "${tmp}.patch" "${tmp}.lined" 2>/dev/null
  104. echo "${count}"
  105. }
  106. function shellcheck_postapply
  107. {
  108. local i
  109. verify_needed_test shellcheck
  110. if [[ $? == 0 ]]; then
  111. return 0
  112. fi
  113. big_console_header "shellcheck plugin: postpatch"
  114. if [[ ! -x "${SHELLCHECK}" ]]; then
  115. hadoop_error "shellcheck is not available."
  116. add_jira_table 0 shellcheck "Shellcheck was not available."
  117. return 0
  118. fi
  119. start_clock
  120. # add our previous elapsed to our new timer
  121. # by setting the clock back
  122. offset_clock "${SHELLCHECK_TIMER}"
  123. echo "Running shellcheck against all identifiable shell scripts"
  124. # we re-check this in case one has been added
  125. for i in $(shellcheck_private_findbash); do
  126. ${SHELLCHECK} -f gcc "${i}" >> "${PATCH_DIR}/patchshellcheck-result.txt"
  127. done
  128. # shellcheck disable=SC2016
  129. numPrepatch=$(wc -l "${PATCH_DIR}/${PATCH_BRANCH}shellcheck-result.txt" | ${AWK} '{print $1}')
  130. # shellcheck disable=SC2016
  131. numPostpatch=$(wc -l "${PATCH_DIR}/patchshellcheck-result.txt" | ${AWK} '{print $1}')
  132. diffPostpatch=$(shellcheck_calcdiffs \
  133. "${PATCH_DIR}/${PATCH_BRANCH}shellcheck-result.txt" \
  134. "${PATCH_DIR}/patchshellcheck-result.txt" \
  135. "${PATCH_DIR}/diffpatchshellcheck.txt"
  136. )
  137. if [[ ${diffPostpatch} -gt 0 ]] ; then
  138. add_jira_table -1 shellcheck "The applied patch generated "\
  139. "${diffPostpatch} new shellcheck (v${SHELLCHECK_VERSION}) issues (total was ${numPrepatch}, now ${numPostpatch})."
  140. add_jira_footer shellcheck "@@BASE@@/diffpatchshellcheck.txt"
  141. return 1
  142. fi
  143. add_jira_table +1 shellcheck "There were no new shellcheck (v${SHELLCHECK_VERSION}) issues."
  144. return 0
  145. }