1#! /bin/sh 2 3# 'strict' mode 4set -euo pipefail 5 6SOURCE_BRANCH=${1-aosp/metalava-main} 7 8echo -n "Checking status" 9STATUS=$(git status -s | grep -v "??" || true) 10if [[ $STATUS ]]; then 11 echo " - ERROR" 12 echo 13 echo "The following changed files would interfere with merge:" 14 echo "$STATUS" 15 exit 1 16else 17 echo " - OK" 18fi 19 20echo -n "Checking current branch" 21BRANCH=$(git branch --show-current) 22if [[ $BRANCH ]]; then 23 echo " - OK ($BRANCH)" 24else 25 echo " - ERROR" 26 echo 27 echo "No branch found, please run 'repo start <branch>'." 28 exit 1 29fi 30 31echo -n "Current upstream branch" 32CURRENT_BRANCH=$(git rev-parse --abbrev-ref --symbolic-full-name @{u}) 33echo " - ${CURRENT_BRANCH}" 34 35function output_only_on_failure() { 36 set +e 37 OUTPUT=$(eval "$@" 2>&1) 38 EXIT_CODE=$? 39 set -e 40 if [[ $EXIT_CODE != 0 ]]; then 41 echo " - ERROR" 42 echo "Command: $@" 43 echo $OUTPUT 44 exit 1 45 fi 46} 47 48# Make sure that ${SOURCE_BRANCH} is up to date. 49echo -n "Making sure that ${SOURCE_BRANCH} is up to date" 50SPLIT_REPOSITORY_BRANCH=${SOURCE_BRANCH/\// } 51output_only_on_failure git fetch ${SPLIT_REPOSITORY_BRANCH} 52echo " - OK" 53 54echo -n "Checking to see if there is anything to merge" 55MERGE_BASE=$(git merge-base HEAD ${SOURCE_BRANCH}) 56if [[ ${MERGE_BASE} == $(git rev-parse ${SOURCE_BRANCH}) ]]; then 57 echo " - NOTHING TO DO" 58 exit 0 59else 60 echo " - CHANGES FOUND" 61fi 62 63echo -n "Extracting bugs from merged in changes" 64BUGS=$(git log ${MERGE_BASE}..${SOURCE_BRANCH} --no-merges | (grep -E "^ *Bug: *[0-9]+" || true) | sed "s/Bug://" | sort -u -n) 65echo " - DONE" 66 67echo -n "Extracting change list from merged in changes" 68 69# Get the Change-Id from the non-merge changes. 70# This uses the Change-Id rather than the SHA as the Change-Id is consistent 71# across branches but the SHA might not be. 72CHANGE_IDS=$(git log ${MERGE_BASE}..${SOURCE_BRANCH} --no-merges | (grep -E "^ *Change-Id: I*[0-9a-f]+" || true) | sed "s/^ *Change-Id: //") 73 74# Generate a query which will find only those changes which are from metalava-main. 75# All changes to tools/metalava must come from metalava-main or main (build changes). 76QUERY="(branch:metalava-main or branch:main) and ($(echo $CHANGE_IDS | sed 's/ / or /g')) and status:merged" 77 78# Generate a list of changes to insert in the commit message. 79# This queries the Android Gerrit as metalava development is always done in AOSP. 80CHANGE_LIST=$(/google/data/ro/projects/android/gerrit -g android -r --custom_raw_format '{o.number} {o.subject}' search "$QUERY" | while read NUMBER SUBJECT 81do 82 echo "* $SUBJECT" 83 echo " - https://r.android.com/$NUMBER" 84done) 85echo " - DONE" 86 87echo -n "Performing the merge" 88MESSAGE_FILE=$(mktemp) 89trap "rm -f ${MESSAGE_FILE}" EXIT 90 91SCRIPT_PATH=${0##*metalava/} 92 93cat > ${MESSAGE_FILE} <<EOF 94Merge remote-tracking branch '${SOURCE_BRANCH}' into '${CURRENT_BRANCH}' 95 96Merge performed by: 97 ${SCRIPT_PATH}${1+ $@} 98 99Changes includes in this merge (from newest to oldest): 100${CHANGE_LIST} 101 102This merge includes a number of changes so this contains a list of all 103the affected bugs in order from oldest to newest. 104 105$(for BUG in $BUGS; do echo "Bug: $BUG"; done) 106Test: m checkapi 107EOF 108 109output_only_on_failure git merge ${SOURCE_BRANCH} --no-ff -F ${MESSAGE_FILE} 110 111echo " - DONE" 112echo "The merge commit has been created. Please do the following before uploading:" 113echo "1. Verify the commit by running 'm checkapi'" 114echo "2. Review the commit to make sure it includes what is expected" 115 116