| #!/bin/bash |
| |
| # Copyright 2023 Fairphone B.V. |
| # |
| # 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. |
| # |
| |
| # Git helper to compare logs of local vs upstream histories |
| # |
| # This tool is meant during git merge, rebase or cherry-picking longer histories. It will list out |
| # (non-merge) commits unique to the local vs. the upstream history. Depending on the state of the |
| # repository, it will automatically figure out which "upstream history" to compare to: Current |
| # MERGE_HEAD, REBASE_HEAD, CHERRY_PICK_HEAD, or an already merged upstream history. |
| |
| # Environment variables: |
| # MERGE_LOG_LENGTH: Set the maximum number of commits to list out. Defaults to 10. |
| |
| set -e |
| set -u |
| |
| _shortened_logs() { |
| local length="${MERGE_LOG_LENGTH:-10}" |
| local logs |
| logs="$(git --no-pager log --color=always "$@")" |
| local lines |
| lines=$(echo "$logs" | wc -l) |
| echo "$logs" | head -n"${length}" |
| if [ "$lines" -gt "${length}" ]; then |
| echo " ($lines lines in total)" |
| fi |
| } |
| |
| _is_merge_commit() { |
| local sha1="$1" |
| local num_parents |
| num_parents=$(git log -1 --format=%P "${sha1}" | wc -w) |
| |
| if [ "${num_parents}" -gt 2 ]; then |
| echo >&2 "ERROR: Cannot handle n-way merge: ${sha1}. Project: ${PWD}" |
| return 1 |
| fi |
| |
| [ "${num_parents}" -eq 2 ] |
| } |
| |
| _compare_histories() { |
| local file_params=() |
| if [ $# -ge 0 ]; then |
| file_params+=(--) |
| for param in "$@"; do |
| file_params+=("${param}") |
| done |
| fi |
| local current_head=HEAD |
| local new_head |
| if git rev-parse -q MERGE_HEAD >/dev/null 2>/dev/null; then |
| new_head=MERGE_HEAD |
| elif git rev-parse -q CHERRY_PICK_HEAD >/dev/null 2>/dev/null; then |
| new_head=CHERRY_PICK_HEAD |
| elif git rev-parse -q REBASE_HEAD >/dev/null 2>/dev/null; then |
| new_head=REBASE_HEAD |
| elif _is_merge_commit HEAD; then |
| current_head=HEAD^1 |
| new_head=HEAD^2 |
| else |
| echo >&2 "Having neither MERGE_HEAD no CHERRY_PICK_HEAD. Failing." |
| return 1 |
| fi |
| echo "New on ${new_head}:" |
| _shortened_logs "${current_head}..${new_head}" --no-merges --oneline "${file_params[@]}" |
| echo "" |
| echo "New on ${current_head} compared to ${new_head}:" |
| _shortened_logs "${new_head}..${current_head}" --no-merges --oneline "${file_params[@]}" |
| } |
| |
| _compare_histories "$@" |