
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>
482 lines
10 KiB
Bash
Executable File
482 lines
10 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
#
|
|
# Copyright (c) 2018 Wind River Systems, Inc.
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
#
|
|
|
|
#
|
|
# A place for any functions relating to git, or the git hierarchy created
|
|
# by repo manifests.
|
|
#
|
|
|
|
echo_stderr ()
|
|
{
|
|
echo "$@" >&2
|
|
}
|
|
|
|
git_ctx_root_dir () {
|
|
dirname "${MY_REPO}"
|
|
}
|
|
|
|
#
|
|
# git_list <dir>:
|
|
# Return a list of git root directories found under <dir>
|
|
#
|
|
git_list () {
|
|
local DIR=${1}
|
|
|
|
find -L "${DIR}" -maxdepth 5 -type d -name '.git' -exec dirname {} \; | sort -V
|
|
}
|
|
|
|
|
|
# GIT_LIST: A list of root directories for all the gits under $MY_REPO/..
|
|
# as absolute paths.
|
|
export GIT_LIST=$(git_list "$(git_ctx_root_dir)")
|
|
|
|
|
|
# GIT_LIST_REL: A list of root directories for all the gits under $MY_REPO/..
|
|
# as relative paths.
|
|
export GIT_LIST_REL=$(for p in $GIT_LIST; do echo .${p#$(git_ctx_root_dir)}; done)
|
|
|
|
|
|
#
|
|
# git_list_containing_branch <dir> <branch>:
|
|
# Return a list of git root directories found under <dir> and
|
|
# having branch <branch>. The branch need not be current branch.
|
|
#
|
|
|
|
git_list_containing_branch () {
|
|
local DIR="${1}"
|
|
local BRANCH="${2}"
|
|
|
|
local d
|
|
for d in $(git_list "${DIR}"); do
|
|
(
|
|
cd "$d"
|
|
git branch --all | grep -q "$BRANCH"
|
|
if [ $? -eq 0 ]; then
|
|
echo "$d"
|
|
fi
|
|
)
|
|
done
|
|
}
|
|
|
|
|
|
#
|
|
# git_list_containing_tag <dir> <tag>:
|
|
# Return a list of git root directories found under <dir> and
|
|
# having tag <tag>.
|
|
#
|
|
|
|
git_list_containing_tag () {
|
|
local DIR="${1}"
|
|
local TAG="${2}"
|
|
|
|
local d
|
|
for d in $(git_list "${DIR}"); do
|
|
(
|
|
cd "$d"
|
|
git tag | grep -q "$TAG"
|
|
if [ $? -eq 0 ]; then
|
|
echo "$d"
|
|
fi
|
|
)
|
|
done
|
|
}
|
|
|
|
|
|
#
|
|
# 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,
|
|
#
|
|
# Note: all paths are relative to $MY_REPO/..
|
|
#
|
|
|
|
git_context () {
|
|
(
|
|
cd $(git_ctx_root_dir)
|
|
|
|
local d
|
|
for d in $GIT_LIST_REL; do
|
|
(
|
|
cd ${d}
|
|
echo -n "(cd ${d} && git checkout -f "
|
|
echo "$(git rev-list HEAD -1))"
|
|
)
|
|
done
|
|
)
|
|
}
|
|
|
|
#
|
|
# git_test_context <context>:
|
|
#
|
|
# Test if all commits referenced in the context are present
|
|
# in the history of the gits in their current checkout state.
|
|
#
|
|
# Returns: 0 = context is present in git history
|
|
# 1 = At least one element of context is not present
|
|
# 2 = error
|
|
#
|
|
git_test_context () {
|
|
local context="$1"
|
|
local query=""
|
|
local target_hits=0
|
|
local actual_hits=0
|
|
|
|
if [ ! -f "$context" ]; then
|
|
return 2
|
|
fi
|
|
|
|
query=$(mktemp "/tmp/git_test_context_XXXXXX")
|
|
if [ "$query" == "" ]; then
|
|
return 2
|
|
fi
|
|
|
|
# Transform a checkout context into a query that prints
|
|
# all the commits that are found in the git history.
|
|
#
|
|
# Limit search to last 500 commits in the interest of speed.
|
|
# I don't expect to be using contexts more than a few weeks old.
|
|
cat "$context" | \
|
|
sed "s#checkout -f \([a-e0-9]*\)#rev-list --max-count=500 HEAD | \
|
|
grep \1#" > $query
|
|
|
|
target_hits=$(cat "$context" | wc -l)
|
|
actual_hits=$(cd $(git_ctx_root_dir); source $query | wc -l)
|
|
\rm $query
|
|
|
|
if [ $actual_hits -eq $target_hits ]; then
|
|
return 0
|
|
fi
|
|
|
|
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
|
|
}
|