check.sh 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. #!/bin/bash
  2. # Copyright 2019 Google
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. # Checks that the current state of the tree is sane and optionally auto-fixes
  16. # errors automatically. Meant for interactive use.
  17. function usage() {
  18. cat <<EOF
  19. USAGE: scripts/check.sh [--allow-dirty] [--commit] [<revision>]
  20. Runs auto-formatting scripts, source-tree checks, and linters on any files that
  21. have changed since origin/master.
  22. By default, any changes are left as uncommited changes in the working tree. You
  23. can review them with git diff. Pass --commit to automatically commit any changes.
  24. Pass an alternate revision to use as the basis for checking changes.
  25. OPTIONS:
  26. --allow-dirty
  27. By default, check.sh requires a clean working tree to keep any generated
  28. changes separate from logical changes.
  29. --commit
  30. Commit any auto-generated changes with a message indicating which tool made
  31. the changes.
  32. --amend
  33. Commit any auto-generated changes by amending the HEAD commit.
  34. --fixup
  35. Commit any auto-generated changes with a fixup! message for the HEAD
  36. commit. The next rebase will squash these fixup commits.
  37. --test-only
  38. Run all checks without making any changes to local files.
  39. <revision>
  40. Specifies a starting revision other than the default of origin/master.
  41. EXAMPLES:
  42. check.sh
  43. Runs automated checks and formatters on all changed files since
  44. origin/master. Check for changes with git diff.
  45. check.sh --commit
  46. Runs automated checks and formatters on all changed files since
  47. origin/master and commits the results.
  48. check.sh --amend HEAD
  49. Runs automated checks and formatters on all changed files since the last
  50. commit and amends the last commit with the difference.
  51. check.sh --allow-dirty HEAD
  52. Runs automated checks and formatters on all changed files since the last
  53. commit and intermingles the changes with any pending changes. Useful for
  54. interactive use from an editor.
  55. EOF
  56. }
  57. set -euo pipefail
  58. unset CDPATH
  59. # Change to the top-directory of the working tree
  60. top_dir=$(git rev-parse --show-toplevel)
  61. cd "${top_dir}"
  62. ALLOW_DIRTY=false
  63. COMMIT_METHOD="none"
  64. START_REVISION="origin/master"
  65. TEST_ONLY=false
  66. VERBOSE=false
  67. # Default to verbose operation if this isn't an interactive build.
  68. if [[ ! -t 1 ]]; then
  69. VERBOSE=true
  70. fi
  71. # When travis clones a repo for building, it uses a shallow clone. After the
  72. # first commit on a non-master branch, TRAVIS_COMMIT_RANGE is not set, master
  73. # is not available and we need to compute the START_REVISION from the common
  74. # ancestor of $TRAVIS_COMMIT and origin/master.
  75. if [[ -n "${TRAVIS_COMMIT_RANGE:-}" ]] ; then
  76. START_REVISION="$TRAVIS_COMMIT_RANGE"
  77. elif [[ -n "${TRAVIS_COMMIT:-}" ]] ; then
  78. if ! git rev-parse origin/master >& /dev/null; then
  79. git remote set-branches --add origin master
  80. git fetch origin
  81. fi
  82. START_REVISION=$(git merge-base origin/master "${TRAVIS_COMMIT}")
  83. fi
  84. while [[ $# -gt 0 ]]; do
  85. case "$1" in
  86. --)
  87. # Do nothing: explicitly allow this, but ignore it
  88. ;;
  89. -h | --help)
  90. usage
  91. exit 1
  92. ;;
  93. --allow-dirty)
  94. ALLOW_DIRTY=true
  95. ;;
  96. --amend)
  97. COMMIT_METHOD=amend
  98. ;;
  99. --fixup)
  100. COMMIT_METHOD=fixup
  101. ;;
  102. --commit)
  103. COMMIT_METHOD=message
  104. ;;
  105. --verbose)
  106. VERBOSE=true
  107. ;;
  108. --test-only)
  109. # In test-only mode, no changes are made, so there's no reason to
  110. # require a clean source tree.
  111. ALLOW_DIRTY=true
  112. TEST_ONLY=true
  113. ;;
  114. *)
  115. START_REVISION="$1"
  116. shift
  117. break
  118. ;;
  119. esac
  120. shift
  121. done
  122. if [[ "${TEST_ONLY}" == true && "${COMMIT_METHOD}" != "none" ]]; then
  123. echo "--test-only cannot be combined with --amend, --fixup, or --commit"
  124. exit 1
  125. fi
  126. if [[ "${ALLOW_DIRTY}" == true && "${COMMIT_METHOD}" == "message" ]]; then
  127. echo "--allow-dirty and --commit are mutually exclusive"
  128. exit 1
  129. fi
  130. if ! git diff-index --quiet HEAD --; then
  131. if [[ "${ALLOW_DIRTY}" != true ]]; then
  132. echo "You have local changes that could be overwritten by this script."
  133. echo "Please commit your changes first or pass --allow-dirty."
  134. exit 2
  135. fi
  136. fi
  137. # Show Travis-related environment variables, to help with debuging failures.
  138. if [[ "${VERBOSE}" == true ]]; then
  139. env | egrep '^TRAVIS_(BRANCH|COMMIT|PULL|REPO)' | sort || true
  140. fi
  141. if [[ "${START_REVISION}" == *..* ]]; then
  142. RANGE_START="${START_REVISION/..*/}"
  143. RANGE_END="${START_REVISION/*../}"
  144. # Figure out if we have access to master. If not add it to the repo.
  145. if ! git rev-parse origin/master >& /dev/null; then
  146. git remote set-branches --add origin master
  147. git fetch origin
  148. fi
  149. NEW_RANGE_START=$(git merge-base origin/master "${RANGE_END}")
  150. START_REVISION="${START_REVISION/$RANGE_START/$NEW_RANGE_START}"
  151. START_SHA="${START_REVISION}"
  152. else
  153. START_SHA=$(git rev-parse "${START_REVISION}")
  154. fi
  155. if [[ "${VERBOSE}" == true ]]; then
  156. echo "START_REVISION=$START_REVISION"
  157. echo "START_SHA=$START_SHA"
  158. fi
  159. # If committing --fixup, avoid messages with fixup! fixup! that might come from
  160. # multiple fixup commits.
  161. HEAD_SHA=$(git rev-parse HEAD)
  162. function maybe_commit() {
  163. local message="$1"
  164. if [[ "${COMMIT_METHOD}" == "none" ]]; then
  165. return
  166. fi
  167. echo "${message}"
  168. case "${COMMIT_METHOD}" in
  169. amend)
  170. git commit -a --amend -C "${HEAD_SHA}"
  171. ;;
  172. fixup)
  173. git commit -a --fixup="${HEAD_SHA}"
  174. ;;
  175. message)
  176. git commit -a -m "${message}"
  177. ;;
  178. *)
  179. echo "Unknown commit method ${COMMIT_METHOD}" 1>&2
  180. exit 2
  181. ;;
  182. esac
  183. }
  184. style_cmd=("${top_dir}/scripts/style.sh")
  185. if [[ "${TEST_ONLY}" == true ]]; then
  186. style_cmd+=(test-only)
  187. fi
  188. style_cmd+=("${START_SHA}")
  189. # Restyle and commit any changes
  190. "${style_cmd[@]}"
  191. if ! git diff --quiet; then
  192. maybe_commit "style.sh generated changes"
  193. fi
  194. # If there are changes to the Firestore project, ensure they're ordered
  195. # correctly to minimize conflicts.
  196. if ! git diff --quiet "${START_SHA}" -- Firestore; then
  197. sync_project_cmd=("${top_dir}/scripts/sync_project.rb")
  198. if [[ "${TEST_ONLY}" == true ]]; then
  199. sync_project_cmd+=(--test-only)
  200. fi
  201. "${sync_project_cmd[@]}"
  202. if ! git diff --quiet; then
  203. maybe_commit "sync_project.rb generated changes"
  204. fi
  205. fi
  206. # Check lint errors.
  207. "${top_dir}/scripts/check_whitespace.sh"
  208. "${top_dir}/scripts/check_filename_spaces.sh"
  209. "${top_dir}/scripts/check_copyright.sh"
  210. "${top_dir}/scripts/check_no_module_imports.sh"
  211. "${top_dir}/scripts/check_test_inclusion.py"
  212. "${top_dir}/scripts/check_cmake_files.py"
  213. # Google C++ style
  214. "${top_dir}/scripts/check_lint.py" "${START_SHA}"