| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300 |
- #!/bin/bash
- # Copyright 2019 Google
- #
- # Licensed 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.
- # Checks that the current state of the tree is sane and optionally auto-fixes
- # errors automatically. Meant for interactive use.
- function usage() {
- cat <<EOF
- USAGE: scripts/check.sh [--allow-dirty] [--commit] [<revision>]
- Runs auto-formatting scripts, source-tree checks, and linters on any files that
- have changed since origin/main.
- By default, any changes are left as uncommitted changes in the working tree. You
- can review them with git diff. Pass --commit to automatically commit any changes.
- Pass an alternate revision to use as the basis for checking changes.
- OPTIONS:
- --allow-dirty
- By default, check.sh requires a clean working tree to keep any generated
- changes separate from logical changes.
- --commit
- Commit any auto-generated changes with a message indicating which tool made
- the changes.
- --amend
- Commit any auto-generated changes by amending the HEAD commit.
- --fixup
- Commit any auto-generated changes with a fixup! message for the HEAD
- commit. The next rebase will squash these fixup commits.
- --test-only
- Run all checks without making any changes to local files.
- <revision>
- Specifies a starting revision other than the default of origin/main.
- EXAMPLES:
- check.sh
- Runs automated checks and formatters on all changed files since
- origin/main. Check for changes with git diff.
- check.sh --commit
- Runs automated checks and formatters on all changed files since
- origin/main and commits the results.
- check.sh --amend HEAD
- Runs automated checks and formatters on all changed files since the last
- commit and amends the last commit with the difference.
- check.sh --allow-dirty HEAD
- Runs automated checks and formatters on all changed files since the last
- commit and intermingles the changes with any pending changes. Useful for
- interactive use from an editor.
- EOF
- }
- set -euo pipefail
- unset CDPATH
- # Change to the top-directory of the working tree
- top_dir=$(git rev-parse --show-toplevel)
- cd "${top_dir}"
- ALLOW_DIRTY=false
- COMMIT_METHOD="none"
- CHECK_DIFF=true
- START_REVISION="origin/main"
- TEST_ONLY=false
- VERBOSE=false
- # Default to verbose operation if this isn't an interactive build.
- if [[ ! -t 1 ]]; then
- VERBOSE=true
- fi
- # When travis clones a repo for building, it uses a shallow clone. After the
- # first commit on a non-main branch, TRAVIS_COMMIT_RANGE is not set, main
- # is not available and we need to compute the START_REVISION from the common
- # ancestor of $TRAVIS_COMMIT and origin/main.
- if [[ -n "${TRAVIS_COMMIT_RANGE:-}" ]] ; then
- CHECK_DIFF=true
- START_REVISION="$TRAVIS_COMMIT_RANGE"
- elif [[ -n "${TRAVIS_COMMIT:-}" ]] ; then
- if ! git rev-parse origin/main >& /dev/null; then
- git remote set-branches --add origin main
- git fetch origin
- fi
- CHECK_DIFF=true
- START_REVISION=$(git merge-base origin/main "${TRAVIS_COMMIT}")
- fi
- while [[ $# -gt 0 ]]; do
- case "$1" in
- --)
- # Do nothing: explicitly allow this, but ignore it
- ;;
- -h | --help)
- usage
- exit 1
- ;;
- --allow-dirty)
- ALLOW_DIRTY=true
- ;;
- --amend)
- COMMIT_METHOD=amend
- ;;
- --fixup)
- COMMIT_METHOD=fixup
- ;;
- --commit)
- COMMIT_METHOD=message
- ;;
- --verbose)
- VERBOSE=true
- ;;
- --test-only)
- # In test-only mode, no changes are made, so there's no reason to
- # require a clean source tree.
- ALLOW_DIRTY=true
- TEST_ONLY=true
- ;;
- *)
- START_REVISION="$1"
- shift
- break
- ;;
- esac
- shift
- done
- if [[ "${TEST_ONLY}" == true && "${COMMIT_METHOD}" != "none" ]]; then
- echo "--test-only cannot be combined with --amend, --fixup, or --commit"
- exit 1
- fi
- if [[ "${ALLOW_DIRTY}" == true && "${COMMIT_METHOD}" == "message" ]]; then
- echo "--allow-dirty and --commit are mutually exclusive"
- exit 1
- fi
- if ! git diff-index --quiet HEAD --; then
- if [[ "${ALLOW_DIRTY}" != true ]]; then
- echo "You have local changes that could be overwritten by this script."
- echo "Please commit your changes first or pass --allow-dirty."
- exit 2
- fi
- fi
- # Show Travis-related environment variables, to help with debugging failures.
- if [[ "${VERBOSE}" == true ]]; then
- env | egrep '^TRAVIS_(BRANCH|COMMIT|PULL|REPO)' | sort || true
- fi
- if [[ "${START_REVISION}" == *..* ]]; then
- RANGE_START="${START_REVISION/..*/}"
- RANGE_END="${START_REVISION/*../}"
- # Figure out if we have access to main. If not add it to the repo.
- if ! git rev-parse origin/main >& /dev/null; then
- git remote set-branches --add origin main
- git fetch origin
- fi
- # Try to come up with a more accurate representation of the merge, so that
- # checks will operate on just the differences the PR would merge into main.
- # The start of the revision range that Travis supplies can sometimes be a
- # seemingly random value.
- NEW_RANGE_START=$(git merge-base origin/main "${RANGE_END}" || echo "")
- if [[ -n "$NEW_RANGE_START" ]]; then
- START_REVISION="${NEW_RANGE_START}..${RANGE_END}"
- START_SHA="${START_REVISION}"
- else
- # In the shallow clone that Travis has created there's no merge base
- # between the PR and main. In this case just fall back on checking
- # everything.
- echo "Unable to detect base commit for change detection."
- echo "Falling back on just checking everything."
- CHECK_DIFF=false
- START_REVISION="origin/main"
- START_SHA="origin/main"
- fi
- else
- START_SHA=$(git rev-parse "${START_REVISION}")
- fi
- if [[ "${VERBOSE}" == true ]]; then
- echo "START_REVISION=$START_REVISION"
- echo "START_SHA=$START_SHA"
- fi
- # If committing --fixup, avoid messages with fixup! fixup! that might come from
- # multiple fixup commits.
- HEAD_SHA=$(git rev-parse HEAD)
- function maybe_commit() {
- local message="$1"
- if [[ "${COMMIT_METHOD}" == "none" ]]; then
- return
- fi
- echo "${message}"
- case "${COMMIT_METHOD}" in
- amend)
- git commit -a --amend -C "${HEAD_SHA}"
- ;;
- fixup)
- git commit -a --fixup="${HEAD_SHA}"
- ;;
- message)
- git commit -a -m "${message}"
- ;;
- *)
- echo "Unknown commit method ${COMMIT_METHOD}" 1>&2
- exit 2
- ;;
- esac
- }
- style_cmd=("${top_dir}/scripts/style.sh")
- if [[ "${TEST_ONLY}" == true ]]; then
- style_cmd+=(test-only)
- fi
- if [[ "$CHECK_DIFF" == true ]]; then
- style_cmd+=("${START_SHA}")
- fi
- # Restyle and commit any changes
- "${style_cmd[@]}"
- if ! git diff --quiet; then
- maybe_commit "style.sh generated changes"
- fi
- # If there are changes to the Firestore project, ensure they're ordered
- # correctly to minimize conflicts.
- if [ -z "${GITHUB_WORKFLOW-}" ]; then
- if [[ "$CHECK_DIFF" == "false" ]] || \
- ! git diff --quiet "${START_SHA}" -- Firestore; then
- sync_project_cmd=("${top_dir}/scripts/sync_project.rb")
- if [[ "${TEST_ONLY}" == true ]]; then
- sync_project_cmd+=(--test-only)
- fi
- "${sync_project_cmd[@]}"
- if ! git diff --quiet; then
- maybe_commit "sync_project.rb generated changes"
- fi
- fi
- fi
- set -x
- # Print the versions of tools being used.
- python --version
- # Check lint errors.
- "${top_dir}/scripts/check_whitespace.sh"
- "${top_dir}/scripts/check_filename_spaces.sh"
- "${top_dir}/scripts/check_copyright.sh"
- "${top_dir}/scripts/check_test_inclusion.py"
- swift "${top_dir}/scripts/check_imports.swift"
- # Google C++ style
- lint_cmd=("${top_dir}/scripts/check_lint.py")
- if [[ "$CHECK_DIFF" == true ]]; then
- lint_cmd+=("${START_SHA}")
- fi
- "${lint_cmd[@]}"
|