blob: 1038ed70939f3f5f71e8094dbd2cedb6625617b7 [file] [log] [blame]
#!/bin/sh
# Copyright 2018 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.
#
# There are only a limited amount of valid situations:
# 1- The project is not pointing to AOSP, ignore it;
# 2- The AOSP-Partner reference did not move from the AOSP reference;
# 3- The AOSP-Partner reference is a direct child of the AOSP reference, the
# project can be fast-forwarded to it;
# 4- The AOSP-Partner reference is *not* a direct child of the AOSP reference,
# the AOSP-Partner has to be merged in and the new commit submitted for
# review.
# The latest AOSP reference we want to merge on top of
AOSP_REF=${AOSP_REF:-android-7.1.2_r36}
# The latest AOSP-Partner reference we want to merge
AOSP_PARTNER_REF=${AOSP_PARTNER_REF:-security-aosp-nyc-mr2-release}
# Current Security Patch Level from the AOSP-Partner reference
AOSP_PARTNER_SPL=${AOSP_PARTNER_SPL:-2018-05-05}
AOSP_BASE_URL=https://android.googlesource.com
CAF_REF=${CAF_REF:-LA.UM.5.8.r1-02900-8x98.0}
INTEGRATION_BRANCH=${INTEGRATION_BRANCH:-int/n/fp2}
STAGING_BRANCH=${STAGING_BRANCH:-staging/n/fp2}
PUSH_TO_REMOTE=${PUSH_TO_REMOTE:-0}
REVIEW_TOPIC=${REVIEW_TOPIC:-}
PUBLIC_REVIEW=${PUBLIC_REVIEW:-0}
ALLOW_FAST_FORWARD=${ALLOW_FAST_FORWARD:-0}
fast_forward_to_aosp_partner() {
local head_commit
head_commit="$1"
local on_branch
on_branch="$2"
echo "INFO: Fast-forwarding to the AOSP-Partner ref.…"
git merge --quiet --ff HEAD ${AOSP_PARTNER_REF}
if test $? -ne 0; then
echo "ERROR: Could not fast-forward to the AOSP-Partner ref. (${AOSP_PARTNER_REF})." >&2
exit 1
fi
# Check for last part: Is there a branch to push to?
if test ${on_branch} = false; then
echo "ERROR: Fast-forward was successful but we are not on a branch. Investigate this manually!" >&2
exit 1
fi
if test 1 -eq ${PUSH_TO_REMOTE}; then
echo "INFO: Updating the remote…"
git push --quiet origin HEAD:${target_branch}
if test $? -ne 0; then
echo "ERROR: Could not push the merged HEAD to the remote (${target_branch})." >&2
exit 1
fi
else
echo "INFO: PUSH_TO_REMOTE is not set to 1. Rolling back to the previous ref.…"
# Abandon the change
git checkout --quiet ${head_commit}
fi
# If the fast-forward succeeds, there is nothing more to do.
return 0
}
# Merge or fast-forward the AOSP-Partner reference on HEAD.
# Fast-forward is only done if allowed. It would be pushed directly to the
# origin. Merges are pushed for review. If we are not actually on a branch, the
# merge/fast-forward is done anyways and the repo is left as it is afterwards.
merge_aosp_partner_on_head() {
local head_commit
head_commit="$1"
local target_branch
target_branch="$2"
if [ -z "${head_commit}" -o -z "${target_branch}" ]; then
echo "USAGE ERROR: merge_aosp_partner_on_head <head_commit> <target_branch>" >&2
exit 1
fi
can_fast_forward=true
on_branch=true
git merge-base --is-ancestor HEAD ${AOSP_PARTNER_REF} || can_fast_forward=false
git show-ref --verify refs/remotes/origin/${target_branch} 1>/dev/null || on_branch=false
# If enabled, check if we can fast-forward.
if test 1 -eq ${ALLOW_FAST_FORWARD} -a ${can_fast_forward} = true; then
fast_forward_to_aosp_partner ${head_commit} ${on_branch}
return 0
fi
# Fast-forward is not enabled or is not possible. So try to merge!
echo "INFO: Merging the latest AOSP-Partner ref. (${AOSP_PARTNER_REF})…"
if test ${can_fast_forward} = true; then
echo "INFO: Could fast-forward to the AOSP-Partner ref., but will still create a merge commit."
fi
old_head=$(git rev-parse HEAD)
merge_result=0
git merge --quiet -m "Merge the ${AOSP_PARTNER_SPL} SPL branch from AOSP-Partner" --log --no-ff ${AOSP_PARTNER_REF} || merge_result=$?
new_head=$(git rev-parse HEAD)
if test 0 -ne ${merge_result}; then
echo "ERROR: Could not merge the AOSP-Partner ref. (${AOSP_PARTNER_REF})." >&2
exit 1
fi
if test "_${old_head}" = "_${new_head}"; then
echo "INFO: Security branch is already merged. Nothing to do."
return 0
fi
# Amend the commit message to get the Change-Id line
gitdir=$(git rev-parse --git-dir)
scp -p -P 29418 review.fairphone.software:hooks/commit-msg ${gitdir}/hooks/
git commit --quiet --amend --no-edit
if test ${on_branch} = false; then
echo "ERROR: Merge was successful but we are not on a branch. Investigate this manually!" >&2
exit 1
fi
if test 1 -eq ${PUSH_TO_REMOTE}; then
echo "INFO: Pushing for review…"
local topic_postfix=""
if [ "${REVIEW_TOPIC}" ]; then
topic_postfix="/${REVIEW_TOPIC}"
fi
local reference="drafts"
if [ "${PUBLIC_REVIEW}" -eq 1 ]; then
reference="for"
fi
git push --quiet origin HEAD:refs/${reference}/${target_branch}${topic_postfix}
if test $? -ne 0; then
echo "ERROR: Could not push the merged HEAD to the remote (${target_branch})." >&2
exit 1
fi
else
echo "INFO: Rolling back to the previous ref. (abandoning $(git rev-parse HEAD))…"
# Abandon the change
git checkout --quiet ${head_commit}
fi
}
is_shallow=0
head_commit=$(git rev-parse HEAD)
aosp_ref_commit=$(git rev-parse --quiet --verify "${AOSP_REF}^{commit}")
integration_branch_commit=$(git rev-parse --quiet --verify "remotes/origin/${INTEGRATION_BRANCH}")
staging_branch_commit=$(git rev-parse --quiet --verify "remotes/origin/${STAGING_BRANCH}")
# Make sure we are on the integration or staging branch or on CAF
current_known_branch=""
if test "_${head_commit}" = "_${integration_branch_commit}"; then
echo "INFO: Currently pointing to the integration branch."
current_known_branch="${INTEGRATION_BRANCH}"
elif test "_${head_commit}" = "_${staging_branch_commit}"; then
echo "INFO: Currently pointing to the staging branch."
current_known_branch="${STAGING_BRANCH}"
elif test "_${head_commit}" = "_$(git rev-parse --quiet --verify "${CAF_REF}^{commit}")"; then
echo "INFO: Pointing to the CAF ref."
current_known_branch="${CAF_REF}"
else
echo "ERROR: HEAD is not pointing to the integration or staging branch, or CAF (${INTEGRATION_BRANCH}, ${STAGING_BRANCH}, ${CAF_REF})." >&2
exit 1
fi
# Make sure we are aware of the latest AOSP reference
if test -z "${aosp_ref_commit}"; then
# If the project is a prebuilt one, we might have a shallow checkout.
# Double check the reference from the remote.
git fetch --no-tags --quiet origin ${AOSP_REF}
aosp_ref_commit=$(git rev-parse --quiet --verify 'FETCH_HEAD^{commit}')
if test -z "${aosp_ref_commit}"; then
echo "ERROR: Cannot find the latest AOSP ref. (${AOSP_REF})." >&2
exit 1
else
is_shallow=1
echo "INFO: Current checkout is shallow."
fi
fi
# Check if we have the partner ref in the repository
git ls-remote --exit-code origin ${AOSP_PARTNER_REF} > /dev/null 2>&1
case $? in
0)
echo "INFO: Creating local branch for AOSP-Partner ref. fetched from origin (${AOSP_PARTNER_REF})…"
git fetch --no-tags --quiet origin ${AOSP_PARTNER_REF}:${AOSP_PARTNER_REF}
if test $? -ne 0; then
echo "ERROR: Could not fetch the AOSP-Partner ref." >&2
exit 1
fi
aosp_partner_ref_commit=$(git rev-list -n1 ${AOSP_PARTNER_REF} 2> /dev/null)
;;
2)
echo "WARNING: The AOSP-Partner ref. ${AOSP_PARTNER_REF} does not exist on remote, ignoring project." >&2
exit 0
;;
*)
echo "ERROR: Could not fetch the AOSP-Partner ref. ${AOSP_PARTNER_REF} from origin." >&2
exit 1
;;
esac
# Are we currently pointing to the AOSP reference?
if test "_${head_commit}" = "_${aosp_ref_commit}"; then
# Is there something to update?
if test "_${aosp_ref_commit}" = "_${aosp_partner_ref_commit}"; then
echo "INFO: Currently pointing to the AOSP-Partner ref. (which is also the AOSP ref.)."
else
# Let's merge!
merge_aosp_partner_on_head "${head_commit}" "${current_known_branch}"
fi
exit 0
# Why are not pointing to the AOSP reference?
elif test "_${head_commit}" = "_${aosp_partner_ref_commit}"; then
# 1- Because we could fast-forward to the AOSP-Partner reference
echo "INFO: Currently pointing to the AOSP-Partner ref."
elif test 0 -eq ${is_shallow} \
-a "_${head_commit}" = "_$(git rev-list --quiet --merges -1 HEAD)" \
-a "_${aosp_ref_commit}" = "_$(git rev-parse --quiet --verify 'HEAD^1')" \
-a "_${aosp_partner_ref_commit}" = "_$(git rev-parse --quiet --verify 'HEAD^2')"; then
#2- Because we already merged the AOSP-Partner reference
echo "INFO: Already merged the AOSP-Partner ref. on the AOSP ref."
elif test 1 -eq ${is_shallow}; then
echo "WARNING: Shallow checkout, could not check if we merged the AOSP-Partner ref." >&2
else
echo "WARNING: We are on ${current_known_branch} which is not tracking AOSP. Still trying to merge…" >&2
merge_aosp_partner_on_head "${head_commit}" "${current_known_branch}"
fi