root/build-tools/branching/create_branches_and_tags.sh

344 lines
10 KiB
Bash
Executable File

#!/bin/bash
#
# Copyright (c) 2020 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
#
# Create a git branch from the current heads on a subset of git projects
# within a manifest. A tag is also created to mark the commit where
# the branch was forked from. The subset of projects affected can be
# identified by project name or remote name.
#
# Optionally a new manifest (<branch>.xml) can be created that selects
# the new branch for the affected projects. As a further option,
# projects that are not branched can me 'locked down' within the new
# manifest by setting the sha of the current head as the revision.
#
# See also: push_branches_tags.sh
CREATE_BRANCHES_AND_TAGS_SH_DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}" )" )"
source "${CREATE_BRANCHES_AND_TAGS_SH_DIR}/../git-repo-utils.sh"
usage () {
echo "create_branches_and_tags.sh --branch=<branch> [--tag=<tag>] [ --remotes=<remotes> ] [ --projects=<projects> ] [ --gitreview-default ] [ --manifest [ --lock-down | --soft-lock-down ] [ --default-revision ]]"
echo ""
echo "Create a branch and a tag in all listed projects, and all"
echo "projects hosted by all listed remotes. Lists are comma separated."
echo ""
echo "The branch name must be provided. The tag name can also be provided."
echo "If the tag is omitted, one is automativally generate by adding the"
echo "prefix 'v' to the branch name."
echo ""
echo "If a manifest is requested, the current manifest is modified."
echo "to specify the new branch for all select remotes and projects."
echo "If lockdown is requested, all other projects get the current"
echo "HEAD's sha set as the revision."
echo "If default-revision is selected, then the manifest default revision"
wcho "will be set."
echo ""
echo "If a gitreview-default is selected, then all branched projects"
echo "with a .gitreview file will have a defaultbranch entry added"
echo "or updated."
}
TEMP=$(getopt -o h --long remotes:,projects:,branch:,tag:,manifest,lock-down,hard-lock-down,soft-lock-down,default-revision,gitreview-default,help -n 'create_branches_and_tags.sh' -- "$@")
if [ $? -ne 0 ]; then
usage
exit 1
fi
eval set -- "$TEMP"
HELP=0
MANIFEST=0
LOCK_DOWN=0
GITREVIEW_DEFAULT=0
SET_DEFAULT_REVISION=0
remotes=""
projects=""
branch=""
tag=""
manifest=""
new_manifest=""
repo_root_dir=""
while true ; do
case "$1" in
-h|--help) HELP=1 ; shift ;;
--remotes) remotes+=$(echo "$2 " | tr ',' ' '); shift 2;;
--projects) projects+=$(echo "$2 " | tr ',' ' '); shift 2;;
--branch) branch=$2; shift 2;;
--tag) tag=$2; shift 2;;
--manifest) MANIFEST=1 ; shift ;;
--lock-down) LOCK_DOWN=2 ; shift ;;
--hard-lock-down) LOCK_DOWN=2 ; shift ;;
--soft-lock-down) LOCK_DOWN=1 ; shift ;;
--default-revision) SET_DEFAULT_REVISION=1 ; shift ;;
--gitreview-default) GITREVIEW_DEFAULT=1 ; shift ;;
--) shift ; break ;;
*) usage; exit 1 ;;
esac
done
if [ $HELP -eq 1 ]; then
usage
exit 0
fi
if [ "$branch" == "" ] ; then
echo_stderr "ERROR: You must specify a branch"
usage
exit 1
fi
repo_root_dir=$(repo_root)
if [ $? -ne 0 ]; then
echo_stderr "Current directory is not managed by repo."
exit 1
fi
update_gitreview () {
local DIR=$1
(
cd $DIR || exit 1
if [ $GITREVIEW_DEFAULT -eq 1 ] && [ -f .gitreview ]; then
if ! grep -q "^defaultbranch=$branch$" .gitreview; then
echo "Updating defaultbranch in ${DIR}/.gitreview"
if grep -q defaultbranch= .gitreview; then
sed "s#\(defaultbranch=\).*#\1$branch#" -i .gitreview
else
echo "defaultbranch=$branch" >> .gitreview
fi
git add .gitreview
if [ $? != 0 ] ; then
echo_stderr "ERROR: failed to add .gitreview in ${DIR}"
exit 1
fi
git commit -s -m "Update .gitreview for $branch"
if [ $? != 0 ] ; then
echo_stderr "ERROR: failed to commit .gitreview in ${DIR}"
exit 1
fi
else
echo "defaultbranch in ${DIR}/.gitreview already set"
fi
fi
)
}
if [ $MANIFEST -eq 1 ]; then
manifest=$(repo_manifest $repo_root_dir)
if [ $? -ne 0 ]; then
echo_stderr "failed to find current manifest."
exit 1
fi
if [ ! -f $manifest ]; then
echo_stderr "manifest file missing '$manifest'."
exit 1
fi
# String the leading feature (f/) or branch (b/) from the
# branch name so we have a valid branch prefix
if [[ ${branch} =~ .*/.*$ ]]; then
manifest_prefix="$(basename ${branch})"
else
manifest_prefix="${branch}"
fi
new_manifest="$(dirname $manifest)/$manifest_prefix-$(basename $manifest)"
if [ -f $new_manifest ]; then
echo_stderr "branched manifest file already present '$new_manifest'."
exit 1
fi
fi
for project in $projects; do
if ! repo_is_project $project; then
echo_stderr "Invalid project: $project"
echo_stderr "Valid projects are: $(repo_project_list | tr '\n' ' ')"
exit 1
fi
done
for remote in $remotes; do
if ! repo_is_remote $remote; then
echo_stderr "Invalid remote: $remote"
echo_stderr "Valid remotes are: $(repo_remote_list | tr '\n' ' ')"
exit 1
fi
done
# Add projects from listed remotes
if [ "$remotes" != "" ]; then
projects+="$(repo_project_list $remotes | tr '\n' ' ')"
fi
# If no projects or remotes specified, process ALL projects
if [ "$projects" == "" ] && [ "$remotes" == "" ]; then
projects="$(repo_project_list)"
fi
if [ "$projects" == "" ]; then
echo_stderr "No projects found"
exit 1
fi
# Provide a default tag name if not otherwise provided
if [ "$tag" == "" ]; then
tag="v$branch"
fi
echo "Finding subgits"
SUBGITS=$(repo forall $projects -c 'echo '"$repo_root_dir"'/$REPO_PATH')
# Go through all subgits and create the branch and tag if they does not already exist
echo "Applying branched and tags"
(
for subgit in $SUBGITS; do
(
cd $subgit
review_method=$(git_repo_review_method)
if [ -f .gitreview ] && [ "${review_method}" == "gerrit" ] ; then
git review -s > /dev/null
if [ $? != 0 ] ; then
echo_stderr "ERROR: failed to setup git review in ${subgit}"
exit 1
fi
fi
remote=$(git_repo_remote)
if [ "${remote}" == "" ]; then
remote=$(git_remote)
if [ "${remote}" == "" ]; then
echo_stderr "ERROR: Failed to determine remote in ${subgit}"
exit 1
fi
fi
remote_branch=$(git_repo_remote_branch)
if [ "${remote_branch}" == "" ]; then
remote_branch=$(git_remote_branch)
if [ "${remote_branch}" == "" ]; then
echo_stderr "ERROR: failed to determine remote branch in ${subgit}"
exit 1
fi
fi
# check if destination branch already exists
branch_check=$(git branch -a --list $branch)
if [ -z "$branch_check" ]; then
echo "Creating branch $branch in $subgit"
echo " git checkout -t ${remote}/${remote_branch} -b $branch"
git checkout -t ${remote}/${remote_branch} -b $branch
if [ $? != 0 ] ; then
echo_stderr "ERROR: failed to create branch '$branch' in ${subgit}"
exit 1
fi
else
echo "Branch $branch already exists in $subgit"
git checkout $branch
fi
# check if destination tag already exists
tag_check=$(git tag -l $tag)
if [ -z "$tag_check" ]; then
echo "Creating tag $tag in ${subgit}"
git tag -s -m "Branch $branch" $tag
if [ $? != 0 ] ; then
echo "ERROR: failed to create tag '$tag' in ${subgit}"
exit 1
fi
else
echo "Tag '$tag' already exists in ${subgit}"
fi
update_gitreview ${subgit} || exit 1
) || exit 1
done
) || exit 1
if [ $MANIFEST -eq 1 ]; then
(
new_manifest_name=$(basename "${new_manifest}")
new_manifest_dir=$(dirname "${new_manifest}")
manifest_name=$(basename "${manifest}")
manifest_dir=$(dirname "${manifest}")
cd "${new_manifest_dir}" || exit 1
review_method=$(git_review_method)
if [ -f .gitreview ] && [ "${review_method}" == "gerrit" ] ; then
git review -s > /dev/null
if [ $? != 0 ] ; then
echo_stderr "ERROR: failed to setup git review in ${new_manifest_dir}"
exit 1
fi
fi
branch_check=$(git branch -a --list $branch)
if [ ! -z "$branch_check" ]; then
echo "Branch $branch already exists in ${new_manifest_dir}"
exit 1
fi
tag_check=$(git tag -l $tag)
if [ ! -z "$tag_check" ]; then
echo "Tag '$tag' already exists in ${new_manifest_dir}"
exit 1
fi
remote=$(git_remote)
if [ "${remote}" == "" ]; then
echo_stderr "ERROR: Failed to determine remote in ${new_manifest_dir}"
exit 1
fi
remote_branch=$(git_remote_branch)
if [ "${remote_branch}" == "" ]; then
echo_stderr "ERROR: failed to determine remote branch in ${new_manifest_dir}"
exit 1
fi
echo "Creating branch '$branch' in ${new_manifest_dir}"
git checkout -t ${remote}/${remote_branch} -b $branch
if [ $? != 0 ] ; then
echo_stderr "ERROR: failed to create branch '$branch' in ${new_manifest_dir}"
exit 1
fi
echo "Creating tag '$tag' in ${new_manifest_dir}"
git tag -s -m "Branch $branch" $tag
if [ $? != 0 ] ; then
echo "ERROR: failed to create tag '$tag' in ${new_manifest_dir}"
exit 1
fi
update_gitreview ${manifest_dir} || exit 1
echo "Creating manifest ${new_manifest_name}"
manifest_set_revision "${manifest}" "${new_manifest}" "$branch" ${LOCK_DOWN} ${SET_DEFAULT_REVISION} $projects || exit 1
echo "Move manifest ${new_manifest_name}, overwriting ${manifest_name}"
\cp -f "${manifest}" "${manifest}.save"
\mv -f "${new_manifest}" "${manifest}"
echo "Committing ${manifest_name} in ${manifest_dir}"
git add ${manifest_name} || exit 1
git commit -s -m "Modified manifest ${manifest_name} for branch ${branch}"
if [ $? != 0 ] ; then
echo_stderr "ERROR: failed to commit new manifest ${manifest_name} in ${manifest_dir}"
exit 1
fi
) || exit 1
fi