blob: 2df0642576829952471320e5ed0a1aef9c85c37a [file] [log] [blame]
#!/bin/sh
# Copyright 2018-2020 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.
#
#
# Exported globals:
# DEBUG
# DRY_RUN
# SHELL_LIBS
# TARGET_GERRIT_NAME
# TARGET_GERRIT_URL
# TARGET_GERRIT_PORT
# TARGET_GERRIT_PARENT_PROJECT
# VERBOSE
set -e
export SHELL_LIBS="$(dirname $(readlink -f $0))/../shell-libs"
. "${SHELL_LIBS}/utils.sh"
TARGET_GERRIT_NAME="fairphone"
TARGET_GERRIT_URL="review.fairphone.software"
TARGET_GERRIT_PORT="29418"
TARGET_GERRIT_PARENT_PROJECT="Marshmallow"
_usage() {
cat <<heredoc
Fetch branches and tags from a source remote gerrit and push to projects in a
target gerrit. Missing projects will be created if needed.
Locally defined branches and tags based on the remote's manifest project
revisions can also be created and pushed to the target remote.
Usage:
$0 [-m|--manifest MANIFEST] [-nb|--new-branch NEW_BRANCH]
[-rb|--remote-branch REMOTE_BRANCH TARGET_BRANCH] [-nt|--new-tag NEW_TAG]
[-rt|--remote-tag REMOTE_TAG] [-g|--groups "<group1>,..."]
[-p|--projects "project1 project2"] [-d|--debug] [-v|--verbose]
[-n|--dry-run] [-s|--skip-init] [--push-skip-validation] [-h|--help]
Options:
-m, --manifest MANIFEST : Local hosted remote manifest found in
".repo/manifests/". Used for initialising the
local tree (see also --skip-init).
-gn, --target-gerrit-name NAME : Git remote name of the target gerrit.
Default: "${TARGET_GERRIT_NAME}"
-gu, --target-gerrit-url URL : URL of the target gerrit. Only access via ssh
is supported at the moment.
Default: "${TARGET_GERRIT_URL}"
-gp, --target-gerrit-port PORT : Port of the target gerrit.
Default: ${TARGET_GERRIT_PORT}
-pp, --target-gerrit-parent-project PARENT_PROJECT
Parent for project that need to be created on
the target gerrit.
Default: "${TARGET_GERRIT_PARENT_PROJECT}"
-nb, --new-branch NEW_BRANCH : New branch to create and push.
-rb, --remote-branch REMOTE_BRANCH TARGET_BRANCH
: Names of remote branch to fetch and target
branch to push to target gerrit.
-nt, --new-tag NEW_TAG : Name of a new tag to create and push.
-rt, --remote-tag REMOTE_TAG : Name of remote tag to fetch and import.
-pc, --push-current-remote-rev : Push the remote revisions (tags or branchs)
that the manifest is currently pointing on per
project. This allows to push the current state
when different tags or branches are used
across projects.
-g, --groups "<group>,..." : Quote enclosed, comma separated, manifest
groups.
Default: "all"
E.g. "pdk,pdk-qcom"
-p, --projects "project ..." : Quote enclosed, space separated, list of
projects to work on. When undefined script
will run commands on all projects allowed by
MANIFEST_GROUPS.
E.g. -p "cts dalvik"
-cp, --create-projects : Create missing projects on the target Gerrit.
By default, the script assumes that all
relevant projects exist already.
--dry-run : Run git and ssh commands but do not modify
remote.
-d, --debug : Show commands being run. I.e. set -x.
-v, --verbose : Show additional logging.
-s, --skip-init : Skip 'repo init' and 'repo sync' commands.
Only set this if you are sure all projects
have been synced and point to the correct
remote and revision.
--push-skip-validation : Add '-o skip-validation' to git push calls.
This can be necessary when pushing new
histories with a lot of commits that get
otherwise rejected by Gerrit. Requires
extended permissions, see the Gerrit docs.
-h, --help : Print this help message
Examples:
$0 -m aosp/aosp-9.0.0_r8.xml -rb pie-r2-s1-release aosp/pie-r2-s1-release -rt android-9.0.0_r8
$0 -m caf/default_LA.UM.7.6.2.r1-03400-89xx.0.xml -nb staging/arima/fp3/p/r0
Publishing sources for a Fairphone Open release:
$0 -m default.xml -gn code_fp -gu gerrit-public.fairphone.software -gp 29418 -pc --create-projects -pp "All-Projects"
$0 -m rel/p/fp2/20.10.1-beta/20.10.1-beta.0-public.xml -gn code_fp -gu gerrit-public.fairphone.software -gp 29418 -rb rel/p/fp2/20.10.1-beta rel/p/fp2/20.10.1-beta -rt 20.10.1-beta.0
heredoc
}
# Perform a repo init and sync on a specified remote manifest
#
# Globals:
# REPO_PROJECTS
# Arguments:
# manifest Remote manifest to use.
# groups repo groups to use.
# platform repo platform to use.
# Returns:
# None
_init_projects()
{
local manifest="$1"
local groups="${2:-"all"}"
# Manifest must be set and point to a valid file
if [ -z "${manifest}" ] || [ ! -f ".repo/manifests/${manifest}" ] ; then
log_e "Cannot find reference remote manifest \
$(pwd)/.repo/manifests/${manifest}"
fi
log_bold "Repo init:"
repo init \
--manifest-name="${manifest}" \
--groups="${groups}" \
log_bold "Repo sync:"
repo sync --current-branch --detach --no-tags ${REPO_PROJECTS}
}
repo_forall='repo --no-pager forall --abort-on-errors --verbose'
# Add target remote and create new remote projects if needed.
#
# Globals:
# REPO_FORALL_FUNCTIONS
# REPO_PROJECTS
# TARGET_GERRIT_NAME
# TARGET_GERRIT_PORT
# TARGET_GERRIT_URL
# TARGET_GERRIT_PARENT_PROJECT
# Arguments:
# None
# Returns:
# None
_prepare_projects()
{
log_bold "Preparing projects:"
if [ "${CREATE_PROJECTS}" ]; then
create_projects_cmd="add_project_to_gerrit"
else
create_projects_cmd=""
fi
${repo_forall} ${REPO_PROJECTS} --command \
'. $1; \
add_git_remote; \
$2' \
"${REPO_FORALL_FUNCTIONS}" \
"${create_projects_cmd}"
}
# Create a local branch at the manifest revisions and push to the target gerrit.
#
# Globals:
# PUSH_SKIP_VALIDATION
# REPO_FORALL_FUNCTIONS
# REPO_PROJECTS
# TARGET_GERRIT_NAME
# Arguments:
# new_branch Name of the branch to create and push.
# Returns:
# None
_import_new_branch()
{
local new_branch="$1"
log_bold "BRANCH: Create and push ${new_branch}:"
# Create the branch
repo start "${new_branch}" ${REPO_PROJECTS:-"--all"}
# Push branch to the project in the target gerrit.
${repo_forall} ${REPO_PROJECTS} --command \
'. $1; \
remove_shallow_clone; \
push_branch_to_gerrit $2 $2' \
"${REPO_FORALL_FUNCTIONS}" "${new_branch}"
}
# Fetch a remote branch and push to the target gerrit.
#
# Globals:
# PUSH_SKIP_VALIDATION
# REPO_FORALL_FUNCTIONS
# REPO_PROJECTS
# TARGET_GERRIT_NAME
# Arguments:
# remote_branch Name of the remote branch to fetch.
# target_branch Name of the target branch to push to.
# Returns:
# None
_import_remote_branch()
{
local remote_branch="$1"
local target_branch="$2"
log_bold "BRANCH: Fetch ${remote_branch} and push ${target_branch}:"
# Fetch remote branch and push to the target gerrit.
${repo_forall} $REPO_PROJECTS --command \
'. $1; \
fetch_remote_branch $2; \
push_branch_to_gerrit $2 $3' \
"${REPO_FORALL_FUNCTIONS}" "${remote_branch}" "${target_branch}"
}
# Create a new tag at the manifest revisions and push to the target gerrit.
#
# Globals:
# PUSH_SKIP_VALIDATION
# REPO_FORALL_FUNCTIONS
# REPO_PROJECTS
# TARGET_GERRIT_NAME
# Arguments:
# new_tag Name of the tag to create and push
# Returns:
# None
_import_new_tag()
{
local new_tag="$1"
log_bold "TAG: Create and push ${new_tag}:"
${repo_forall} ${REPO_PROJECTS} --command \
'. $1; \
git tag $2; \
remove_shallow_clone; \
push_tag_to_gerrit $2;' \
"${REPO_FORALL_FUNCTIONS}" "${new_tag}"
}
# Fetch a remote tag and push to the target gerrit.
#
# Globals:
# PUSH_SKIP_VALIDATION
# REPO_FORALL_FUNCTIONS
# REPO_PROJECTS
# Arguments:
# remote_tag - Name of the remote tag to fetch and push
# Returns:
# None
_import_remote_tag()
{
local remote_tag="$1"
log_bold "TAG: Fetch and push ${remote_tag}:"
${repo_forall} ${REPO_PROJECTS} --command \
'. $1; \
fetch_remote_tag $2; \
push_tag_to_gerrit $2' \
"${REPO_FORALL_FUNCTIONS}" "${remote_tag}"
}
# Push current remote revisions to the target gerrit
#
# Globals:
# PUSH_SKIP_VALIDATION
# REPO_FORALL_FUNCTIONS
# REPO_PROJECTS
# TARGET_GERRIT_NAME
# Arguments:
# None
# Returns:
# None
_push_current_remote_revisions()
{
log_bold "REVISIONS: Pushing current remote revisions:"
${repo_forall} ${REPO_PROJECTS} --command \
'. $1; \
remove_shallow_clone; \
push_current_remote_revision' \
"${REPO_FORALL_FUNCTIONS}"
}
while [ $# -gt 0 ]; do
case "$1" in
-m|--manifest)
if [ $# -lt 2 ]; then
_usage >&2
exit 1
fi
MANIFEST="$2"
shift 2
;;
-gn|--target-gerrit-name)
if [ $# -lt 2 ]; then
_usage >&2
exit 1
fi
TARGET_GERRIT_NAME="$2"
shift 2
;;
-gu|--target-gerrit-url)
if [ $# -lt 2 ]; then
_usage >&2
exit 1
fi
TARGET_GERRIT_URL="$2"
shift 2
;;
-gp|--target-gerrit-port)
if [ $# -lt 2 ]; then
_usage >&2
exit 1
fi
TARGET_GERRIT_PORT="$2"
shift 2
;;
-pp|--target-gerrit-parent-project)
if [ $# -lt 2 ]; then
_usage >&2
exit 1
fi
TARGET_GERRIT_PARENT_PROJECT="$2"
shift 2
;;
-nb|--new-branch)
if [ $# -lt 2 ]; then
_usage >&2
exit 1
fi
NEW_BRANCH="$2"
shift 2
;;
-rb|--remote-branch)
if [ $# -lt 3 ]; then
_usage >&2
exit 1
fi
REMOTE_BRANCH="$2"
TARGET_BRANCH="$3"
shift 3
;;
-nt|--new-tag)
if [ $# -lt 2 ]; then
_usage >&2
exit 1
fi
NEW_TAG="$2"
shift 2
;;
-rt|--remote-tag)
if [ $# -lt 2 ]; then
_usage >&2
exit 1
fi
REMOTE_TAG="$2"
shift 2
;;
-pc|--push-current-remote-rev)
export PUSH_CURRENT_REMOTE_REVISIONS=true
shift 1
;;
-g|--groups)
if [ $# -lt 2 ]; then
_usage >&2
exit 1
fi
MANIFEST_GROUPS="$2"
shift 2
;;
-p|--projects)
if [ $# -lt 2 ]; then
_usage >&2
exit 1
fi
REPO_PROJECTS="$2"
shift 2
;;
-cp|--create-projects)
export CREATE_PROJECTS=true
shift 1
;;
--dry-run)
export DRY_RUN="--dry-run"
shift 1
;;
-v|--verbose)
export VERBOSE="--verbose"
shift 1
;;
-d|--debug)
set -x
export DEBUG="true"
shift 1
;;
-s|--skip-init)
SKIP_INIT=true
shift 1
;;
--push-skip-validation)
PUSH_SKIP_VALIDATION=true
shift 1
;;
-h|--help)
_usage
exit 0
;;
*)
echo "Unknown option $*" >&2
_usage >&2
exit 1
;;
esac
done
export PUSH_SKIP_VALIDATION
export TARGET_GERRIT_NAME
export TARGET_GERRIT_URL
export TARGET_GERRIT_PORT
export TARGET_GERRIT_PARENT_PROJECT
REPO_FORALL_FUNCTIONS="${SHELL_LIBS}/repo-forall-functions.sh"
if [ ! -f "${REPO_FORALL_FUNCTIONS}" ] ; then
log_e "Unable to find repo-forall-functions.sh" || _usage >&2
exit 1
fi
# Navigate to the Android's root
croot
# Initialize Android tree
if [ -z "${SKIP_INIT}" ] ; then
_init_projects "${MANIFEST}" "${MANIFEST_GROUPS}"
fi
_prepare_projects
if [ -n "${NEW_BRANCH}" ] ; then
_import_new_branch "${NEW_BRANCH}"
fi
if [ -n "${REMOTE_BRANCH}" ] && [ -n "${TARGET_BRANCH}" ] ; then
_import_remote_branch "${REMOTE_BRANCH}" "${TARGET_BRANCH}"
fi
if [ -n "${NEW_TAG}" ] ; then
_import_new_tag "${NEW_TAG}"
fi
if [ -n "${REMOTE_TAG}" ] ; then
_import_remote_tag "${REMOTE_TAG}"
fi
if [ "${PUSH_CURRENT_REMOTE_REVISIONS}" = true ]; then
_push_current_remote_revisions
fi