blob: 07517c5a2cddb74bf4a062c59634de81b8e47f8d [file] [log] [blame] [edit]
#!/bin/bash
# Copyright 2025 Google LLC
#
# 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.
# Script to run gofmt, golint, and gazelle before committing.
# To install, use the following command:
# ./scripts/install_precommit.sh
set -e
SCRIPT_DIR=$(dirname "${BASH_SOURCE[0]}")
source "${SCRIPT_DIR}/infra/common.sh" || exit $?
source "${SCRIPT_DIR}/license_exemptions.sh" || exit $?
cd "$(get_workspace_root)"
# License header check.
echo "Checking for license headers..."
MISSING_LICENSE_HEADER_FILES=()
DUPLICATE_COPYRIGHT_FILES=()
MISSING_BLANK_LINE_FILES=()
for file in $(git ls-files); do
if [ ! -f "$file" ]; then
continue
fi
if ! requires_license_header "$file"; then
continue
fi
HEADER=$(head -n 15 "$file")
# Check 1 & 2: Header content
if ! echo "$HEADER" | grep -q "Licensed under the Apache License, Version 2.0" || ! echo "$HEADER" | grep -q "Copyright.*Google LLC"; then
MISSING_LICENSE_HEADER_FILES+=("$file")
continue # Next file
fi
# Check 3: Duplicate copyright
if [ $(grep -c -E "^(#|//)\s*Copyright" "$file") -gt 1 ]; then
DUPLICATE_COPYRIGHT_FILES+=("$file")
continue # Next file
fi
# Check 4: Blank line after header
end_line_num=$(grep -n -E "(#|//) limitations under the License." "$file" | head -n 1 | cut -d: -f1)
if [ -n "$end_line_num" ]; then
line_num_after=$((end_line_num + 1))
# Check if we are not at the end of the file
if [ "$line_num_after" -le $(wc -l < "$file") ]; then
line_after=$(sed -n "${line_num_after}p" "$file")
# Check if the line contains any non-whitespace characters
if [[ "$line_after" =~ [^[:space:]] ]]; then
MISSING_BLANK_LINE_FILES+=("$file")
continue # Next file
fi
fi
fi
done
FAILING_FILES=()
if [ ${#MISSING_LICENSE_HEADER_FILES[@]} -ne 0 ]; then
echo -e "\033[0;31mError: License header or copyright notice is missing or incorrect in the following files:\033[0m"
for file in "${MISSING_LICENSE_HEADER_FILES[@]}"; do
echo " $file"
FAILING_FILES+=("$file")
done
fi
if [ ${#DUPLICATE_COPYRIGHT_FILES[@]} -ne 0 ]; then
echo -e "\033[0;31mError: Duplicate copyright notice in the following files:\033[0m"
for file in "${DUPLICATE_COPYRIGHT_FILES[@]}"; do
echo " $file"
FAILING_FILES+=("$file")
done
fi
if [ ${#MISSING_BLANK_LINE_FILES[@]} -ne 0 ]; then
echo -e "\033[0;31mError: Missing blank line after license header in the following files:\033[0m"
for file in "${MISSING_BLANK_LINE_FILES[@]}"; do
echo " $file"
FAILING_FILES+=("$file")
done
fi
if [ ${#FAILING_FILES[@]} -ne 0 ]; then
echo -e "\033[0;33mTo fix these issues, run the following script, which will prompt to apply the necessary changes:\033[0m"
echo " ${SCRIPT_DIR}/fix_license_headers.sh ${FAILING_FILES[*]}"
exit 1
fi
echo "License header check passed."
STAGED_GO_FILES=$(git diff --cached --name-only --diff-filter=d | grep ".go$" || true)
# Ensures that non-interactive shell sessions can run Go tools
if command -v go &>/dev/null; then
export PATH="$PATH:$(go env GOPATH)/bin"
fi
# Use downloaded version of bazel.
./scripts/infra/bootstrap_prebuilts.sh
# Run go mod tidy
run_go_mod_tidy
GAZELLEPASS=true
echo Running Gazelle...
if ! run_bazel_tool //:gazelle; then
GAZELLEPASS=false
fi
LINTPASS=true
echo Running gofmt...
run_bazel_tool @io_bazel_rules_go//go -- fmt ./...
PASS=true
if ! $LINTPASS; then
printf "\033[0;30m\033[41mThere are lint errors. Please fix!\033[0m\n"
PASS=false
fi
if ! $GAZELLEPASS; then
printf "\033[0;30m\033[41mbazel run //:gazelle failed. Please fix the errors and try again.\033[0m\n"
PASS=false
fi
SKIP_DIFF_CHECK=false
for arg in "$@"; do
if [[ "$arg" == "--skip-diff-check" ]]; then
SKIP_DIFF_CHECK=true
break
fi
done
if [ "$SKIP_DIFF_CHECK" = false ]; then
if ! git diff --exit-code &> /dev/null; then
printf "\033[0;30m\033[41mPrecommit made changes to source. Please check the changes and re-stage files.\033[0m\n"
echo "To bypass this git-diff check, pass --skip-diff-check to this script."
PASS=false
fi
fi
if ! $PASS; then
printf "\033[0;30m\033[41mCOMMIT FAILED\033[0m\n"
exit 1
else
printf "\033[0;30m\033[42mCOMMIT SUCCEEDED\033[0m\n"
fi