| #!/usr/bin/env bash |
| # Licensed to the Apache Software Foundation (ASF) under one |
| # or more contributor license agreements. See the NOTICE file |
| # distributed with this work for additional information |
| # regarding copyright ownership. The ASF licenses this file |
| # to you 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. |
| |
| ## |
| ## When working with submodules the top level project (Apache Cassandra) needs to commit all submodule |
| ## changes so the top level knows what SHA to use. When working in a development environment it is |
| ## common that multiple commits will exist in both projects, if the submodule has its history |
| ## rewritten, then historic top level commits are no longer valid unless the SHAs are pushed to a |
| ## remote repo; this is what the script attempts to do, make sure all SHAs added to the |
| ## Apache Cassandra are backed up to a remote repo to make the Cassandra SHA buildable. |
| ## |
| |
| # Redirect output to stderr. |
| exec 1>&2 |
| |
| |
| #set -o xtrace |
| set -o errexit |
| set -o pipefail |
| set -o nounset |
| |
| bin="$(cd "$(dirname "$0")" > /dev/null; pwd)" |
| |
| _log() { |
| echo -e "[pre-commit]\t$*" |
| } |
| |
| error() { |
| _log "$@" 1>&2 |
| exit 1 |
| } |
| |
| # Status Table |
| # A Added |
| # C Copied |
| # D Deleted |
| # M Modified |
| # R Renamed |
| # T Type Changed (i.e. regular file, symlink, submodule, …<200b>) |
| # U Unmerged |
| # X Unknown |
| # B Broken |
| _main() { |
| # In case the usage happens at a different layer, make sure to cd to the toplevel |
| local root_dir |
| root_dir="$(git rev-parse --show-toplevel)" |
| cd "$root_dir" |
| |
| [[ ! -e .gitmodules ]] && return 0 |
| local enabled=$(git config --bool cassandra.pre-commit.verify-submodules.enabled || echo true) |
| [ "$enabled" == "false" ] && return 0 |
| local submodules=( $(git config --file .gitmodules --get-regexp path | awk '{ print $2 }') ) |
| |
| local is_submodule=false |
| local git_sub_dir |
| local git_sha |
| while read status file; do |
| is_submodule=false |
| for to_check in "${submodules[*]}"; do |
| if [[ "$to_check" == "$file" ]]; then |
| is_submodule=true |
| break |
| fi |
| done |
| if $is_submodule; then |
| local enabled=$(git config --bool cassandra.pre-commit.verify-submodule-${file}.enabled || echo true) |
| [ "$enabled" == "false" ] && continue |
| _log "Submodule detected: ${file} with status ${status}; attempting a push" |
| _log "\tTo disable pushes, run" |
| _log "\t\tgit config --local cassandra.pre-commit.verify-submodules.enabled false" |
| _log "\tOr" |
| _log "\t\tgit config --local cassandra.pre-commit.verify-submodule-${file}.enabled false" |
| git_sub_dir="${file}/.git" |
| branch="$(git config -f .gitmodules "submodule.${file}.branch")" |
| [[ -z "${branch:-}" ]] && error "Submodule ${file} does not define a branch" |
| git_sha="$(git --git-dir "${git_sub_dir}" rev-parse HEAD)" |
| local remote="$(git --git-dir "${git_sub_dir}" config --get "branch.${branch}.remote" || error "Git branch ${branch} is not set up to track any remote in submodule ${file}")" |
| git --git-dir "${git_sub_dir}" fetch "${remote}" |
| git --git-dir "${git_sub_dir}" branch "${remote}/${branch}" --contains "${git_sha}" || error "Git commit ${git_sha} not found in $(git remote get-url "${remote}") on branch ${branch}" |
| fi |
| done < <(git diff --cached --name-status) |
| } |
| |
| _main "$@" |