Branch and tag tools converted from wrgit to repo

Update branching and tagging tools, used by patching, to do things
the 'repo' way.  Repo has replaced wrgit.

This is complicated by ...

1) Not all repos are under our control, and so can't be branched or
tagged by us.  The tools now accepts arguments that list 'remotes' or
'projects' to which branches or tags are to be applied

2) The manifest requires an update to reference the new branch or tag
as it applies to affected projects.  Non-affected projects can
optionally be locked down by converting the revision to a sha.
The tools must now try to generate that manifest.  It might be
sub-optimal.  i.e. a revision is explicitly added to each project,
rather than using the 'default' mechanism.  Perhaps something to address
in a future update.

ORIGINATING_BRANCH=master
ORIGINATING_BUILD=20200220T023000Z
NEW_BRANCH=r/stx.4.0
STX_REMOTES="starlingx"

repo init -u https://opendev.org/starlingx/manifest -b $ORIGINATING_BRANCH
repo sync --force-sync

curl http://mirror.starlingx.cengn.ca/mirror/starlingx/${ORIGINATING_BRANCH}/centos/${ORIGINATING_BUILD}/outputs/CONTEXT.sh > ${ORIGINATING_BUILD}.context

source ${ORIGINATING_BUILD}.context
create_branches_and_tags.sh --branch=$NEW_BRANCH --remotes=$STX_REMOTES --manifest --lockdown
push_branches_tags.sh --branch=$NEW_BRANCH --remotes=$STX_REMOTES --manifest

ORIGINATING_BRANCH=r/stx.4.0
ORIGINATING_BUILD=20200220T023000Z
NEW_STX_TAG=4.0.0
NEW_GIT_HUB_TAG=stx.4.0.0
STX_REMOTES="starlingx"
GIT_HUB_REMOTES="stx-staging"

repo init -u https://opendev.org/starlingx/manifest -b $ORIGINATING_BRANCH
repo sync --force-sync

curl http://mirror.starlingx.cengn.ca/mirror/starlingx/${ORIGINATING_BRANCH}/centos/${ORIGINATING_BUILD}/outputs/CONTEXT.sh > ${ORIGINATING_BUILD}.context

source ${ORIGINATING_BUILD}.context
TAG=TEST_19.10_PATCH_0000
create_tags.sh --tag=$NEW_STX_TAG --remotes=$STX_REMOTES,$GIT_HUB_REMOTES --manifest --manifest-prefix=stx. --lock-down
create_tags.sh --tag=$NEW_GIT_HUB_TAG --remotes=$GIT_HUB_REMOTES
push_tags.sh --tag=$NEW_STX_TAG --remotes=$STX_REMOTES
push_tags.sh --tag=$NEW_GIT_HUB_TAG --remotes=$STX_REMOTES
cd .repo/manifests
git mv $TAG-default.xml stx.$TAG.xml

vi stx.$TAG.xml
   # set revision for all stx-staging projects to refs/tags/stx.4.0.0
   <project remote="stx-staging" ... revision="refs/tags/stx.4.0.0" .

vi stx.$TAG.xml
   # set default revision
   <default remote="starlingx" revision="refs/tags/4.0.0"/>

   # delete 'revision' for all starlingx projects

git add stx.$TAG.xml
git commit -s --amend
    # set title to
    Locked down manifest for StarlingX $TAG

git tag -d $TAG
git review
git tag -s -m "Tag $TAG" $TAG
git push gerrit $TAG

Change-Id: I5ac0c3e44ffda262edb416e877d46c9036cd6e92
Signed-off-by: Scott Little <scott.little@windriver.com>
This commit is contained in:
Scott Little 2019-09-25 14:27:40 -04:00
parent 6afb3e527c
commit d06b9aa763
8 changed files with 1739 additions and 158 deletions

View File

@ -1,76 +0,0 @@
#!/bin/bash
# The purpose of this script is to create branches and tags that follow a convention
# If the desired branch already exists, it is skipped.
# If the desired tag already exists, it is skipped.
OLD_TAG=vCGCS_DEV_0018
NEW_TAG=vCGCS_DEV_0019
OLD_BRANCH=CGCS_DEV_0018
NEW_BRANCH=CGCS_DEV_0019
if [ -z "$MY_REPO" ]; then
echo "MY_REPO is unset"
exit 1
else
echo "MY_REPO is set to '$MY_REPO'"
fi
if [ -d "$MY_REPO" ]; then
cd $MY_REPO
echo "checking out and pulling old branch"
wrgit checkout $OLD_BRANCH
if [ $? -ne 0 ]; then
echo "ERROR: wrgit checkout $OLD_BRANCH"
exit 1
fi
wrgit pull
if [ $? -ne 0 ]; then
echo "ERROR: wrgit pull"
exit 1
fi
else
echo "Could not change to diectory '$MY_REPO'"
exit 1
fi
echo "Finding subgits"
SUBGITS=`find . -type d -name ".git" | sed "s%/\.git$%%"`
# Go through all subgits and create the NEW_BRANCH if it does not already exist
# Go through all subgits and create the NEW_TAG if it does not already exist
for subgit in $SUBGITS; do
echo ""
echo ""
pushd $subgit > /dev/null
git fetch
git fetch --tags
# check if destination branch already exists
echo "$subgit"
branch_check=`git branch -a --list $NEW_BRANCH`
if [ -z "$branch_check" ]; then
echo "Creating $NEW_BRANCH"
git checkout $OLD_BRANCH
git checkout -b $NEW_BRANCH
git push origin $NEW_BRANCH:$NEW_BRANCH
else
echo "$NEW_BRANCH already exists"
fi
tag_check=`git tag -l $NEW_TAG`
if [ -z "$tag_check" ]; then
echo "Creating $NEW_TAG"
# create tag
git checkout $NEW_BRANCH
git pull origin
git tag $NEW_TAG
git push origin $NEW_TAG
else
echo "$NEW_TAG already exists"
fi
popd > /dev/null
done
echo "All done. branches and tags are pushed"

View File

@ -1,54 +1,287 @@
#!/bin/bash
if [ x"$1" = x ] ; then
echo "ERROR: You must specify a name to create branches and tags"
#
# 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> ] [ --manifest [ --lock-down ]]"
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, it will recieve the name '<branch>.xml' and"
echo "it will specify the branch as the revision for all tagged projects."
echo "If lockdown is requested, all other projects get the current"
echo "HEAD's sha set as the revision."
}
TEMP=$(getopt -o h --long remotes:,projects:,branch:,tag:,manifest,lock-down,help -n 'create_branches_and_tags.sh' -- "$@")
if [ $? -ne 0 ]; then
usage
exit 1
fi
branch=$1
tag="v$branch"
eval set -- "$TEMP"
HELP=0
MANIFEST=0
LOCK_DOWN=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=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
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
new_manifest="$(dirname $manifest)/${branch}-$(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=`find . -type d -name ".git" | sed "s%/\.git$%%"`
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
echo ""
echo ""
pushd $subgit > /dev/null
(
cd $subgit
# check if destination branch already exists
echo "$subgit"
branch_check=`git branch -a --list $branch`
if [ -z "$branch_check" ]; then
echo "Creating branch $branch"
git checkout -b $branch
review_method=$(git_repo_review_method)
if [ -f .gitreview ] && [ "${review_method}" == "gerrit" ] ; then
git review -s > /dev/null
if [ $? != 0 ] ; then
echo "ERROR: Could not exec: git checkout -b $branch"
popd > /dev/null
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
# git push origin $branch:$branch
else
echo "Branch $branch already exists"
echo "Branch $branch already exists in $subgit"
git checkout $branch
fi
tag_check=`git tag -l $tag`
tag_check=$(git tag -l $tag)
if [ -z "$tag_check" ]; then
echo "Creating tag $tag"
git tag $tag
echo "Creating tag $tag in ${subgit}"
git tag -s -m "Branch $branch" $tag
if [ $? != 0 ] ; then
echo "ERROR: Could not exec: git tag $tag"
popd > /dev/null
echo "ERROR: failed to create tag '$tag' in ${subgit}"
exit 1
fi
# git push origin $tag
else
echo "Tag $tag already exists"
echo "Tag '$tag' already exists in ${subgit}"
fi
) || 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
popd > /dev/null
done
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
echo "Creating manifest ${new_manifest_name}"
manifest_set_revision "${manifest}" "${new_manifest}" "$branch" ${LOCK_DOWN} $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

View File

@ -1,35 +1,238 @@
#!/bin/bash
if [ x"$1" = x ] ; then
echo "ERROR: You must specify a name to create tags"
#
# Copyright (c) 2020 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
#
# Create a git tag from the current heads on a subset of git projects
# within a manifest. The subset of projects affected can be
# identified by project name or remote name.
#
# Optionally a new manifest (<tag>.xml) can be created that selects
# the new tag 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_tags.sh
CREATE_TAGS_SH_DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}" )" )"
source "${CREATE_TAGS_SH_DIR}/../git-repo-utils.sh"
usage () {
echo "create_tags.sh --tag=<tag> [ --remotes=<remotes> ] [ --projects=<projects> ] [ --manifest [ --manifest-prefix <prefix> ] [ --lock-down ]]"
echo " "
echo "Create a git tag in all listed projects, and all projects"
echo "hosted by all listed remotes. Lists are comma separated."
echo ""
echo "If a manifest is requested, it will recieve the name '<prefix><tag>.xml' and"
echo "it will specify the tag as the revision for all tagged projects."
echo "If lockdown is requested, all non-tagged projects get the current"
echo "HEAD's sha set as the revision."
}
TEMP=$(getopt -o h --long remotes:,projects:,tag:,manifest,manifest-prefix:,lock-down,help -n 'create_tags.sh' -- "$@")
if [ $? -ne 0 ]; then
usage
exit 1
fi
eval set -- "$TEMP"
HELP=0
MANIFEST=0
LOCK_DOWN=0
remotes=""
projects=""
tag=""
manifest=""
new_manifest=""
manifest_prefix=""
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;;
--tag) tag=$2; shift 2;;
--manifest) MANIFEST=1 ; shift ;;
--manifest-prefix) manifest_prefix=$2; shift 2;;
--lock-down) LOCK_DOWN=1 ; shift ;;
--) shift ; break ;;
*) usage; exit 1 ;;
esac
done
if [ $HELP -eq 1 ]; then
usage
exit 0
fi
if [ "$tag" == "" ] ; then
echo_stderr "ERROR: You must specify a tag"
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
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
new_manifest="$(dirname $manifest)/${manifest_prefix}${tag}-$(basename $manifest)"
if [ -f $new_manifest ]; then
echo_stderr "tagged 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
tag=$1
echo "Finding subgits"
SUBGITS=`find . -type d -name ".git" | sed "s%/\.git$%%"`
SUBGITS=$(repo forall $projects -c 'echo '"$repo_root_dir"'/$REPO_PATH')
# Go through all subgits and create the tag if it does not already exist
echo "Applying branched and tags"
(
for subgit in $SUBGITS; do
echo ""
echo ""
pushd $subgit > /dev/null
(
cd $subgit
tag_check=`git tag -l $tag`
if [ -z "$tag_check" ]; then
echo "Creating tag $tag"
git tag $tag
review_method=$(git_repo_review_method)
if [ -f .gitreview ] && [ "${review_method}" == "gerrit" ] ; then
git review -s > /dev/null
if [ $? != 0 ] ; then
echo "ERROR: Could not exec: git tag $tag"
popd > /dev/null
echo_stderr "ERROR: failed to setup git review in ${subgit}"
exit 1
fi
# git push origin $tag
else
echo "Tag $tag already exists"
fi
popd > /dev/null
tag_check=$(git tag -l $tag)
if [ -z "$tag_check" ]; then
echo "Creating tag '$tag' in ${subgit}"
git tag -s -m "Tag $tag" $tag
if [ $? != 0 ] ; then
echo_stderr "ERROR: failed to create tag '$tag' in ${subgit}"
exit 1
fi
else
echo "Tag '$tag' already exists in ${subgit}"
fi
) || exit 1
done
) || exit 1
if [ $MANIFEST -eq 1 ]; then
(
new_manifest_name=$(basename "${new_manifest}")
new_manifest_dir=$(dirname "${new_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
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
new_branch="create_manifest_for_tag_${tag}"
# check if destination branch already exists
branch_check=$(git branch -a --list $new_branch)
if [ -z "$branch_check" ]; then
echo "Creating branch ${new_branch} in ${new_manifest_dir}"
git checkout -t ${remote}/${remote_branch} -b "${new_branch}"
if [ $? != 0 ] ; then
echo_stderr "ERROR: failed to create branch '${new_branch}' in ${new_manifest_dir}"
exit 1
fi
else
echo "Branch ${branch} already exists in $subgit"
git checkout ${new_branch}
fi
echo "Creating manifest ${new_manifest_name}"
manifest_set_revision "${manifest}" "${new_manifest}" "refs/tags/$tag" ${LOCK_DOWN} $projects || exit 1
echo "Committing ${new_manifest_name} in ${new_manifest_dir}"
git add ${new_manifest_name} || exit 1
git commit -s -m "Create new manifest ${new_manifest_name}"
if [ $? != 0 ] ; then
echo_stderr "ERROR: failed to commit new manifest ${new_manifest_name} in ${new_manifest_dir}"
exit 1
fi
echo "Creating tag '$tag' in ${new_manifest_dir}"
git tag -s -m "Tag $tag" $tag
if [ $? != 0 ] ; then
echo_stderr "ERROR: failed to create tag '$tag' in ${new_manifest_dir}"
exit 1
fi
) || exit 1
fi

View File

@ -1,42 +1,255 @@
#!/bin/bash
if [ x"$1" = x ] ; then
echo "ERROR: You must specify a name to create branches and tags"
#
# Copyright (c) 2020 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
#
# A tool to push the branches, tags, and optional manifest created by
# create_branches_and_tags.sh to the upstream source.
#
# Arguemens should match those passed to create_branches_and_tags.sh
# with the exception of '--lockdown'.
#
PUSH_BRANCHES_TAGS_SH_DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}" )" )"
source "${PUSH_BRANCHES_TAGS_SH_DIR}/../git-repo-utils.sh"
usage () {
echo "push_branches_tags.sh --branch=<branch> [--tag=<tag>] [ --remotes=<remotes> ] [ --projects=<projects> ] [ --manifest ]"
echo ""
echo "Push a pre-existing branch and tag into 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 "A manifest push can also be requested.vision."
}
TEMP=$(getopt -o h --long remotes:,projects:,branch:,tag:,manifest,help -n 'push_branches_tags.sh' -- "$@")
if [ $? -ne 0 ]; then
usage
exit 1
fi
branch=$1
tag="v$branch"
eval set -- "$TEMP"
HELP=0
MANIFEST=0
remotes=""
projects=""
branch=""
tag=""
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 ;;
--) 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
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
if [ ! -f "${manifest}.save" ]; then
echo_stderr "manifest file missing '${manifest}.save'."
exit 1
fi
# The new manifest referes to branches that are not yet available on the remotes.
# This will break some repo commands, e.g repo forall'.
#
# To get arround this we swap in the old manifest until we get passed the
# problematic commands.
\cp -f "${manifest}" "${manifest}.new"
\cp -f "${manifest}.save" "${manifest}"
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=`find . -type d -name ".git" | sed "s%/\.git$%%"`
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
(
for subgit in $SUBGITS; do
echo ""
echo ""
pushd $subgit > /dev/null
(
cd $subgit
# check if destination branch already exists
echo "$subgit"
echo "Pushing branch $branch"
git push origin $branch:$branch
if [ $? != 0 ] ; then
echo "ERROR: Could not exec: git push origin $branch:$branch"
popd > /dev/null
branch_check=$(git branch -a --list $branch)
if [ -z "$branch_check" ]; then
echo_stderr "ERROR: Expected branch '$branch' to exist in ${subgit}"
exit 1
fi
echo "Pushing tag $tag"
git push origin $tag
if [ $? != 0 ] ; then
echo "ERROR: Could not exec: git push origin $tag"
popd > /dev/null
tag_check=$(git tag -l $tag)
if [ "${tag_check}" == "" ]; then
echo_stderr "ERROR: Expected tag '$tag' to exist in ${subgit}"
exit 1
fi
popd > /dev/null
review_method=$(git_repo_review_method)
if [ "${review_method}" == "" ]; then
echo_stderr "ERROR: Failed to determine review method in ${subgit}"
exit 1
fi
if [ "${review_method}" == "gerrit" ]; then
remote=$(git_repo_review_remote)
else
remote=$(git_repo_remote)
fi
if [ "${remote}" == "" ]; then
echo_stderr "ERROR: Failed to determine remote in ${subgit}"
exit 1
fi
echo "Pushing branch $branch in ${subgit}"
if [ "${review_method}" == "gerrit" ]; then
echo "git push --tags ${remote} ${branch}"
git push --tags ${remote} ${branch}
else
echo "git push --tags --set-upstream ${remote} ${branch}"
git push --tags --set-upstream ${remote} ${branch}
fi
if [ $? != 0 ] ; then
echo_stderr "ERROR: Failed to push branch '${branch}' to remote '${remote}' in ${subgit}"
exit 1
fi
)
done
) || exit 1
if [ $MANIFEST -eq 1 ]; then
# restore manifest
\cp -f "${manifest}.new" "${manifest}"
fi
if [ $MANIFEST -eq 1 ]; then
(
manifest_name=$(basename "${manifest}")
manifest_dir=$(dirname "${manifest}")
cd "${manifest_dir}" || exit 1
if [ ! -f ${manifest_name} ]; then
echo_stderr "ERROR: Expected file '${manifest_name} to exist in ${manifest_dir}"
exit 1
fi
branch_check=$(git branch -a --list $branch)
if [ -z "$branch_check" ]; then
echo_stderr "ERROR: Expected branch '$branch' to exist in ${manifest_dir}"
exit 1
fi
tag_check=$(git tag -l $tag)
if [ "${tag_check}" == "" ]; then
echo_stderr "ERROR: Expected tag '$tag' to exist in ${manifest_dir}"
exit 1
fi
review_method=$(git_review_method)
if [ "${review_method}" == "" ]; then
echo_stderr "ERROR: Failed to determine review method in ${manifest_dir}"
exit 1
fi
remote=$(git_review_remote)
if [ "${remote}" == "" ]; then
echo_stderr "ERROR: Failed to determine remote in ${manifest_dir}"
exit 1
fi
echo "Pushing branch $branch in ${manifest_dir}"
if [ "${review_method}" == "gerrit" ]; then
# Is a reviewless push possible as part of creating a new branch in gerrit?
git push --tags ${remote} ${branch}
else
git push --tags --set-upstream ${remote} ${branch}
fi
if [ $? != 0 ] ; then
echo_stderr "ERROR: Failed to push tag '${tag}' to remote '${remote}' in ${manifest_dir}"
exit 1
fi
) || exit 1
fi

View File

@ -1,29 +1,238 @@
#!/bin/bash
if [ x"$1" = x ] ; then
echo "ERROR: You must specify a name to push tags"
#
# Copyright (c) 2020 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
#
# A tool to push the tags, and optional manifest created by
# create_tags.sh to the upstream source.
#
# Arguemens should match those passed to create_tags.sh
# with the exception of '--lockdown'.
#
PUSH_TAGS_SH_DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}" )" )"
source "${PUSH_TAGS_SH_DIR}/../git-repo-utils.sh"
usage () {
echo "push_tags.sh --tag=<tag> [ --remotes=<remotes> ] [ --projects=<projects> ] [ --manifest [--manifest-prefix <prefix>]]"
echo " "
echo "Push a pre-existing git tag into all listed projects, and all projects"
echo "hosted by all listed remotes. Lists are comma separated."
echo ""
echo "A manifest push can also be requested."
}
TEMP=$(getopt -o h --long remotes:,projects:,tag:,manifest,manifest-prefix:,help -n 'push_tags.sh' -- "$@")
if [ $? -ne 0 ]; then
usage
exit 1
fi
tag=$1
eval set -- "$TEMP"
HELP=0
MANIFEST=0
remotes=""
projects=""
tag=""
manifest=""
manifest_prefix=""
new_manifest=""
repo_root_dir=""
echo "Finding subgits"
SUBGITS=`find . -type d -name ".git" | sed "s%/\.git$%%"`
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;;
--tag) tag=$2; shift 2;;
--manifest) MANIFEST=1 ; shift ;;
--manifest-prefix) manifest_prefix=$2; shift 2;;
--) shift ; break ;;
*) usage; exit 1 ;;
esac
done
# Go through all subgits and create the tag if it does not already exist
for subgit in $SUBGITS; do
echo ""
echo ""
pushd $subgit > /dev/null
if [ $HELP -eq 1 ]; then
usage
exit 0
fi
echo "Creating tag $tag"
git push origin $tag
if [ $? != 0 ] ; then
echo "ERROR: Could not exec: git push origin $tag"
popd > /dev/null
if [ "$tag" == "" ] ; then
echo_stderr "ERROR: You must specify a tags"
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
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
popd > /dev/null
if [ ! -f $manifest ]; then
echo_stderr "manifest file missing '$manifest'."
exit 1
fi
new_manifest="$(dirname $manifest)/${manifest_prefix}${tag}-$(basename $manifest)"
if [ ! -f $new_manifest ]; then
echo_stderr "Expected a tagged 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
echo "Finding subgits"
SUBGITS=$(repo forall $projects -c 'echo '"$repo_root_dir"'/$REPO_PATH')
# Go through all subgits and create the tag if it does not already exist
(
for subgit in $SUBGITS; do
(
cd $subgit
tag_check=$(git tag -l $tag)
if [ "${tag_check}" == "" ]; then
echo_stderr "ERROR: Expected tag '$tag' to exist in ${subgit}"
exit 1
fi
review_method=$(git_repo_review_method)
if [ "${review_method}" == "" ]; then
echo_stderr "ERROR: Failed to determine review method in ${subgit}"
exit 1
fi
if [ "${review_method}" == "gerrit" ]; then
remote=$(git_repo_review_remote)
else
remote=$(git_repo_remote)
fi
if [ "${remote}" == "" ]; then
echo_stderr "ERROR: Failed to determine remote in ${subgit}"
exit 1
fi
echo "Pushing tag $tag in ${subgit}"
if [ "${review_method}" == "gerrit" ]; then
echo "git push ${remote} ${tag}"
git push ${remote} ${tag}
else
echo "git push ${remote} ${tag}"
git push ${remote} ${tag}
fi
if [ $? != 0 ] ; then
echo_stderr "ERROR: Failed to push tag '${tag}' to remote '${remote}' in ${subgit}"
exit 1
fi
)
done
) || exit 1
if [ $MANIFEST -eq 1 ]; then
(
new_manifest_name=$(basename "${new_manifest}")
new_manifest_dir=$(dirname "${new_manifest}")
cd "${new_manifest_dir}" || exit 1
local_branch=$(git_local_branch)
if [ "${local_branch}" == "" ]; then
echo_stderr "ERROR: failed to determine local branch 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
if [ ! -f ${new_manifest_name} ]; then
echo_stderr "ERROR: Expected file '${new_manifest_name}' to exist in ${new_manifest_dir}"
exit 1
fi
tag_check=$(git tag -l $tag)
if [ "${tag_check}" == "" ]; then
echo_stderr "ERROR: Expected tag '$tag' to exist in ${new_manifest_dir}"
exit 1
fi
review_method=$(git_review_method)
if [ "${review_method}" == "" ]; then
echo_stderr "ERROR: Failed to determine review method in ${new_manifest_dir}"
exit 1
fi
remote=$(git_review_remote)
if [ "${remote}" == "" ]; then
echo_stderr "ERROR: Failed to determine remote in ${new_manifest_dir}"
exit 1
fi
echo "Pushing tag $tag in ${new_manifest_dir}"
if [ "${review_method}" == "gerrit" ]; then
git review
if [ $? != 0 ] ; then
echo_stderr "ERROR: Failed to create git review from ${new_manifest_dir}"
exit 1
fi
echo "When review is merged: please run ..."
echo " cd ${new_manifest_dir}"
echo " git push ${remote} ${tag}"
else
git push ${remote} ${local_branch}:${remote_branch}
git push ${remote} ${tag}:${tag}
fi
if [ $? != 0 ] ; then
echo_stderr "ERROR: Failed to push tag '${tag}' to branch ${remote_branch} on remote '${remote}' from ${new_manifest_dir}"
exit 1
fi
) || exit 1
fi

View File

@ -0,0 +1,229 @@
#!/bin/bash
#
# Copyright (c) 2020 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
#
# A collection of utilities that stradle the divide between
# between git and repo.
#
# These utilites are often the most reliable to use. They will
# try to get the answer from repo, and will fall back to git
# of repo isn't providing a satisfactory answer. A prime example
# is the repo's manifest, which isn't fully managed by repo,
# but isn't a fully independent git either.
#
GIT_REPO_UTILS_DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}" )" )"
source ${GIT_REPO_UTILS_DIR}/repo-utils.sh
source ${GIT_REPO_UTILS_DIR}/git-utils.sh
#
# git_repo_rel_dir [<dir>]:
# Return the relative directory of a git within a repo.
#
git_repo_rel_dir () {
local DIR="${1:-${PWD}}"
local GIT_DIR=""
local REPO_DIR=""
local GIT_RELATIVE_DIR=""
GIT_DIR=$(git_root ${DIR})
REPO_DIR=$(readlink -f $(repo_root ${DIR}))
GIT_RELATIVE_DIR=${GIT_DIR#${REPO_DIR}/}
echo ${GIT_RELATIVE_DIR}
}
#
# git_repo_project [<dir>]:
# Return the repo 'project' of a git.
#
git_repo_project() {
local DIR="${1:-${PWD}}"
(
cd ${DIR}
GIT_RELATIVE_DIR=$(git_repo_rel_dir)
repo forall -c "if [ \$REPO_PATH == ${GIT_RELATIVE_DIR} ]; then echo \$REPO_PROJECT; fi"
)
}
#
# git_repo_remote [<dir>]:
# Return the repo 'remote' of a git.
#
git_repo_remote() {
local DIR="${1:-${PWD}}"
(
cd ${DIR}
GIT_RELATIVE_DIR=$(git_repo_rel_dir)
repo forall -c "if [ \$REPO_PATH == ${GIT_RELATIVE_DIR} ]; then echo \$REPO_REMOTE; fi"
)
}
#
# git_repo_remote_branch [<dir>]:
# Return the repo 'remote branch' of a git.
#
git_repo_remote_branch() {
local DIR="${1:-${PWD}}"
(
cd ${DIR}
GIT_RELATIVE_DIR=$(git_repo_rel_dir)
REF=$(repo forall -c "if [ \$REPO_PATH == ${GIT_RELATIVE_DIR} ]; then echo \$REPO_RREV; fi")
if git_is_branch ${REF} ; then
echo ${REF}
else
return 1
fi
)
}
#
# git_repo_remote_ref [<dir>]:
# Return the repo 'remote branch' of a git.
#
git_repo_remote_ref() {
local DIR="${1:-${PWD}}"
(
cd ${DIR}
GIT_RELATIVE_DIR=$(git_repo_rel_dir)
repo forall -c "if [ \$REPO_PATH == ${GIT_RELATIVE_DIR} ]; then echo \$REPO_RREV; fi"
)
}
git_repo_remote_url () {
local remote=""
remote=$(git_repo_remote) || return 1
git config remote.$remote.url
}
url_to_host () {
local URL="${1}"
# Strip protocol, path, user/pwd, port
echo "${URL}" | sed -e 's#^[^:]*://##' -e 's#/.*$##' -e 's#^[^@]*@##' -e 's#:.*$##'
}
host_to_domain () {
local host="${1}"
local elements=0
elements=$(echo "${host}" | sed 's#[^.]##g' | wc --chars)
if [ $elements -gt 2 ]; then
# strip lead element
echo "${host}" | sed 's#^[^.]*.##'
else
echo "${host}"
fi
}
git_repo_review_method () {
local DIR="${1:-${PWD}}"
local GIT_DIR=""
local remote_url=""
local review_host=""
local remote_host=""
GIT_DIR=$(git_root ${DIR}) || return 1
if [ ! -f ${GIT_DIR}/.gitreview ]; then
# No .gitreview file
echo 'default'
return 0
fi
if ! grep -q '\[gerrit\]' ${GIT_DIR}/.gitreview; then
# .gitreview file has no gerrit entry
echo 'default'
return 0
fi
review_host="$(grep host= ${GIT_DIR}/.gitreview | sed 's#^host=##' | head -n 1)"
remote_url="$(git_repo_remote_url)" || return 1
remote_host="$(url_to_host "${remote_url}")"
if [ "${review_host}" == "{remote_host}" ]; then
# Will review against same host as we pulled from. All is well
echo 'gerrit'
return 0
else
review_domain="$(host_to_domain "${review_host}")"
remote_domain="$(host_to_domain "${remote_host}")"
if [ "${review_domain}" == "${remote_domain}" ]; then
# Will review and remote hosts share a commom domain. Close enough
echo 'gerrit'
return 0
else
# Domains don't match. Not close enough to say gerrit is safe.
# Did someone forget to update .gitreview?
# Are we not pulling from the authoritative source?
echo 'default'
return 0
fi
fi
# Shouldn't get here
return 1
}
git_repo_review_remote () {
local method=""
method=$(git_repo_review_method)
if [ "${method}" == "gerrit" ]; then
git config remote.gerrit.url > /dev/null
if [ $? -ne 0 ]; then
# Perhaps we need to run git review -s' and try again
# echo a blank line into git in case it prompts for a username
echo | git review -s > /dev/null || return 1
git config remote.gerrit.url > /dev/null || return 1
fi
echo "gerrit"
else
git_repo_remote
fi
}
git_repo_review_url () {
local DIR="${1:-${PWD}}"
local GIT_DIR=""
GIT_DIR=$(git_root ${DIR})
local method=""
method=$(git_repo_review_method)
if [ "${method}" == "gerrit" ]; then
git config remote.gerrit.url
if [ $? -ne 0 ]; then
# Perhaps we need to run git review -s' and try again
# echo a blank line into git in case it prompts for a username
echo | git review -s > /dev/null || return 1
git config remote.gerrit.url || return 1
fi
else
return 1
fi
}

View File

@ -1,3 +1,5 @@
#!/bin/bash
#
# Copyright (c) 2018 Wind River Systems, Inc.
#
@ -9,6 +11,11 @@
# by repo manifests.
#
echo_stderr ()
{
echo "$@" >&2
}
git_ctx_root_dir () {
dirname "${MY_REPO}"
}
@ -80,6 +87,243 @@ git_list_containing_tag () {
}
#
# git_root [<dir>]:
# Return the root directory of a git
# Note: symlinks are fully expanded.
#
git_root () {
local DIR="${1:-${PWD}}"
if [ ! -d "${DIR}" ]; then
echo_stderr "No such directory: ${DIR}"
return 1
fi
(
cd "${DIR}"
ROOT_DIR="$(git rev-parse --show-toplevel)" || exit 1
readlink -f "${ROOT_DIR}"
)
}
#
# git_list_tags [<dir>]:
# Return a list of all git tags.
# Either specify a directory <dir> in the git,
# or use current directory if unspecified.
#
git_list_tags () {
local DIR="${1:-${PWD}}"
(
cd "$DIR"
git tag
)
}
#
# git_list_branches [<dir>]:
# Return a list of all git branches.
# Non-local branches will be prefixed by 'remote/<remote-name>'
# Either specify a directory <dir> in the git,
# or use current directory if unspecified.
#
git_list_branches () {
local DIR="${1:-${PWD}}"
(
cd "$DIR"
git branch --list --all | sed 's#^..##'
)
}
#
# git_list_remote_branches <remote> [<dir>]:
# Return a list of all git branches defined for <remote>.
# Either specify a directory <dir> in the git,
# or use current directory if unspecified.
#
git_list_remote_branches () {
local REMOTE="${1}"
local DIR="${2:-${PWD}}"
(
cd "$DIR"
git branch --list --all "${REMOTE}/*" | sed "s#^.*/${REMOTE}/##"
)
}
#
# git_is_tag <tag> [<dir>]:
# Test if a <tag> is defined within a git.
# Either specify a directory <dir> in the git,
# or use current directory if unspecified.
#
git_is_tag () {
local TAG="${1}"
local DIR="${2:-${PWD}}"
# remove a trailing ^0 if present
TAG=${TAG%^0}
if [ "$TAG" == "" ]; then
return 1;
fi
(
cd "$DIR"
git show-ref ${TAG} | cut -d ' ' -f 2 | grep -q '^refs/tags/'
)
}
#
# git_is_local_branch <branch> [<dir>]:
# Test if a <branch> is defined locally within a git.
# Either specify a directory <dir> in the git,
# or use current directory if unspecified.
#
git_is_local_branch () {
local BRANCH="${1}"
local DIR="${2:-${PWD}}"
if [ "$BRANCH" == "" ]; then
return 1;
fi
(
cd "$DIR"
git show-ref ${BRANCH} | cut -d ' ' -f 2 | grep -q '^refs/heads/'
)
}
#
# git_is_remote_branch <branch> [<dir>]:
# Test if a <branch> is defined in any of the remotes of the git.
# The branche does NOT need to be prefixed by the remore name.
# Either specify a directory <dir> in the git,
# or use current directory if unspecified.
#
git_is_remote_branch () {
local BRANCH="${1}"
local DIR="${2:-${PWD}}"
if [ "$BRANCH" == "" ]; then
return 1;
fi
(
cd "$DIR"
git show-ref ${BRANCH} | cut -d ' ' -f 2 | grep -q '^refs/remotes/'
)
}
#
# git_is_branch <branch> [<dir>]:
# Test if a <branch> is defined in the git.
# The branch can be local or remote.
# Remote branches do NOT need to be prefixed by the remore name.
# Either specify a directory <dir> in the git,
# or use current directory if unspecified.
#
git_is_branch () {
local BRANCH="${1}"
local DIR="${2:-${PWD}}"
if [ "$BRANCH" == "" ]; then
return 1;
fi
git_is_local_branch ${BRANCH} "${DIR}" || git_is_remote_branch ${BRANCH} "${DIR}"
}
#
# git_is_ref <ref> [<dir>]:
# Test if a <ref> is a valid name for a commit.
# The reference can be a sha, tag, or branch.
# Remote branches must be prefixed by the remore name,
# as in <remote-name>/<branch> .
# Either specify a directory <dir> in the git,
# or use current directory if unspecified.
#
git_is_ref () {
local REF="${1}"
local DIR="${2:-${PWD}}"
if [ "$REF" == "" ]; then
return 1;
fi
# test "$(git cat-file -t ${REF})" == "commit"
local TYPE=""
TYPE="$(git cat-file -t ${REF} 2> /dev/null)" && test "${TYPE}" == "commit"
}
#
# git_is_sha <sha> [<dir>]:
# Test if a <sha> is defined in the git. The sha can be abreviated.
# Either specify a directory <dir> in the git,
# or use current directory if unspecified.
#
git_is_sha () {
local SHA="${1}"
local DIR="${2:-${PWD}}"
if [ "$SHA" == "" ]; then
return 1;
fi
git_is_ref ${SHA} "${DIR}" && ! ( git_is_branch ${SHA} "${DIR}" || git_is_tag ${SHA} "${DIR}")
}
#
# git_ref_type <ref> [<dir>]:
# Determine the type of the git reference <ref>.
# The result, via stdout, will be one of ("sha", "tag", "branch" or "invalid")
# Remote branches do NOT need to be prefixed by the remore name.
# Either specify a directory <dir> in the git,
# or use current directory if unspecified.
git_ref_type () {
local REF="${1}"
local DIR="${2:-${PWD}}"
if git_is_branch ${REF} ${DIR}; then
echo 'branch'
return 0
fi
if git_is_tag ${REF} ${DIR}; then
echo 'tag'
return 0
fi
if git_is_sha ${REF} ${DIR}; then
echo 'sha'
return 0
fi
echo 'invalid'
return 1
}
#
#
# git_context:
# Returns a bash script that can be used to recreate the current git context,
@ -146,3 +390,92 @@ git_test_context () {
return 1
}
git_local_branch () {
local result=""
result=$(git name-rev --name-only HEAD)
if [ "$result" == "" ] || [ "$result" == "undefined" ]; then
return 1
fi
# handle the case where a tag is returned by looking at the parent.
# This weird case when a local commit is tagged and we were in
# detached head state, or on 'default' branch.
while git_is_tag $result; do
result=$(git name-rev --name-only $result^1 )
if [ "$result" == "" ] || [ "$result" == "undefined" ]; then
return 1
fi
done
echo $result
}
git_list_remotes () {
git remote | grep -v gerrit
}
git_remote () {
local DIR="${1:-${PWD}}"
(
cd ${DIR}
local_branch=$(git_local_branch) || return 1
# Return remote of current local branch, else default remote.
git config branch.${local_branch}.remote || git_list_remotes
)
}
git_remote_url () {
local remote=""
remote=$(git_remote) || return 1
git config remote.$remote.url
}
git_remote_branch () {
local local_branch=""
local_branch=$(git_local_branch) || return 1
git config branch.${local_branch}.merge | sed 's#^refs/heads/##'
}
git_review_method () {
local url=""
url=$(git_remote_url) || exit 1
if [[ "${url}" =~ "/git.starlingx.io/" || "${url}" =~ "/opendev.org/" ]]; then
echo 'gerrit'
else
echo 'default'
fi
}
git_review_url () {
local method=""
method=$(git_review_method)
if [ "${method}" == "gerrit" ]; then
git config remote.gerrit.url
if [ $? -ne 0 ]; then
# Perhaps we need to run git review -s' and try again
git review -s > /dev/null || return 1
git config remote.gerrit.url
fi
else
git_remote_url
fi
}
git_review_remote () {
local method=""
method=$(git_review_method)
if [ "${method}" == "gerrit" ]; then
git config remote.gerrit.url > /dev/null
if [ $? -ne 0 ]; then
# Perhaps we need to run git review -s' and try again
git review -s > /dev/null || return 1
git config remote.gerrit.url > /dev/null || return 1
fi
echo "gerrit"
else
git_remote
fi
}

237
build-tools/repo-utils.sh Normal file
View File

@ -0,0 +1,237 @@
#!/bin/bash
#
# Copyright (c) 2020 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
#
# A collection of utilities relating to 'repo'
#
#
# Echo to stderr
# echo_stderr [any text you want]
#
echo_stderr ()
{
echo "$@" >&2
}
#
# Get the root dir of a repo managed repository
# repo_root [<dir_path>]
#
repo_root () {
local query_dir="${1:-${PWD}}"
local work_dir
if [ ! -d "${query_dir}" ]; then
echo_stderr "not a valid directory: ${query_dir}"
return 1
fi
if [ "${query_dir:0:1}" != "/" ]; then
query_dir=$(readlink -f ${query_dir})
if [ $? -ne 0 ]; then
return 1
fi
fi
work_dir="${query_dir}"
while true; do
if [ -d "$work_dir/.repo/manifests" ]; then
echo $work_dir
return 0
fi
if [ "${work_dir}" == "/" ]; then
break
fi
work_dir="$(dirname "${work_dir}")"
done
echo_stderr "directory is not controlled by repo: ${query_dir}"
return 1
}
#
# Get the active manifest file of a repo managed repository
# repo_manifest [<dir_path>]
#
repo_manifest () {
local query_dir="${1:-${PWD}}"
local root_dir=""
local repo_manifest=""
root_dir="$(repo_root "${query_dir}")"
if [ $? -ne 0 ]; then
return 1
fi
repo_manifest="${root_dir}/.repo/manifest.xml"
# Depending on repo version, ${repo_manifest} is either a symlink to
# the real manifest, or a wrapper manifest that includes the real manifest
if [ -L "${repo_manifest}" ]; then
readlink -f "${repo_manifest}"
else
grep "<include " ${repo_manifest} | head -n 1 | sed "s#^.*name=\"\([^\"]*\)\".*#${root_dir}/.repo/manifests/\1#"
fi
}
#
# Get a list of repo remotes.
# repo_manifest
#
# Current directory must be withing the repo.
repo_remote_list () {
repo forall -c 'echo $REPO_REMOTE' | sort --unique
}
repo_is_remote () {
local query_remote=$1
local remote
for remote in $(repo_remote_list); do
if [ "$query_remote" == "$remote" ]; then
return 0
fi
done
return 1
}
#
# Get a list of repo projects.
# Optionally restrict the list to projects from listed remotes.
# repo_manifest [remote_1 remote_2 ...]
#
# Current directory must be withing the repo.
repo_project_list () {
local remote_list=( $@ )
if [ ${#remote_list[@]} -eq 0 ]; then
repo forall -c 'echo $REPO_PROJECT' | sort --unique
else
for remote in ${remote_list[@]}; do
repo forall -c \
'if [ "$REPO_REMOTE" == "'${remote}'" ]; then echo $REPO_PROJECT; fi' \
| sort --unique
done
fi
}
repo_is_project () {
local query_project=$1
local project
for project in $(repo_project_list); do
if [ "$query_project" == "$project" ]; then
return 0
fi
done
return 1
}
#
# manifest_set_revision <old_manifest> <new_manifest> <revision> <lock_down> <project-list>
#
# old_manifest = Path to original manifest.
# new_manifest = Path to modified manifest. It will not overwrite an
# existing file.
# revision = A branch, tag ,or sha. Branch and SHA can be used
# directly, but repo requires that a tag be in the form
# "refs/tags/<tag-name>".
# lock_down = 0 or 1. If 1, set a revision on all other non-listed
# projects to equal the SHA of the current git head.
# project-list = A space seperated list of projects. Listed projects
# will have their revision set to the provided revision
# value.
#
manifest_set_revision () {
local old_manifest="${1}"
local new_manifest="${2}"
local revision="${3}"
local lock_down="${4}"
shift 4
local projects="${@}"
local repo_root_dir=""
local line=""
local FOUND=0
local path=""
local project=""
local rev=""
repo_root_dir=$(repo_root)
if [ $? -ne 0 ]; then
echo_stderr "Current directory is not managed by repo."
return 1
fi
if [ ! -f "${old_manifest}" ]; then
echo_stderr "Old manifest file is missing '${old_manifest}'."
return 1
fi
if [ -f "${new_manifest}" ]; then
echo_stderr "New manifest file already present '${new_manifest}'."
return 1
fi
mkdir -p "$(dirname "${new_manifest}")"
if [ $? -ne 0 ]; then
echo_stderr "Failed to create directory '$(dirname "${new_manifest}")'"
return 1
fi
while IFS= read -r line; do
echo "${line}" | grep -q '<project'
if [ $? -ne 0 ]; then
# Line does not define a project, do not modify
echo "${line}"
continue
fi
# check if project name is selected
FOUND=0
for project in ${projects}; do
echo "${line}" | grep -q 'name="'${project}'"'
if [ $? -eq 0 ]; then
FOUND=1
break
fi
done
rev=${revision}
if [ $FOUND -eq 0 ]; then
# A non-selected project
if [ ${lock_down} -eq 0 ]; then
echo "${line}"
continue
fi
path="${repo_root_dir}/$(echo "${line}" | sed 's#.*path="\([^"]*\)".*#\1#')"
rev=$(cd "${path}"; git rev-parse HEAD)
fi
# Need to set revision on selected project
if echo "${line}" | grep -q 'revision='; then
echo "${line}" | sed "s#revision=\"[^\"]*\"#revision=\"${rev}\"#"
else
# No prior revision
# Set revision prior to name
echo "${line}" | sed "s#name=#revision=\"${rev}\" name=#"
fi
done < "${old_manifest}" > "${new_manifest}"
return 0
}