06537894b2
Review.opendev.org seem unreliable when hit with a lot of transactions in a short time. This means that an attempt to create a release branch, e.g. r/stx.6.0 failes repeatedly, and requires a lot of manual repair. By adding retires and delays, we greatly improve our odds of success. Closes-bug: 1954536 Signed-off-by: Scott Little <scott.little@windriver.com> Change-Id: Ia03ed58b67c02e6984a7e0ee01c6666027df6cbe
369 lines
11 KiB
Bash
369 lines
11 KiB
Bash
#!/bin/bash
|
|
|
|
#
|
|
# Copyright (c) 2020-2021 Wind River Systems, Inc.
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
#
|
|
|
|
#
|
|
# A collection of utilities relating to 'repo'
|
|
#
|
|
|
|
REPO_UTILS_DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}" )" )"
|
|
|
|
source ${REPO_UTILS_DIR}/utils.sh
|
|
|
|
|
|
#
|
|
# 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_FILE=
|
|
repo_set_manifest_file() {
|
|
REPO_MANIFEST_FILE="$1"
|
|
}
|
|
|
|
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
|
|
|
|
if [[ -n "$REPO_MANIFEST_FILE" ]] ; then
|
|
if [[ "$REPO_MANIFEST_FILE" =~ ^/ ]] ; then
|
|
echo "$REPO_MANIFEST_FILE"
|
|
else
|
|
echo "${root_dir}/.repo/manifests/$REPO_MANIFEST_FILE"
|
|
fi
|
|
return 0
|
|
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_get_revision_of_project <manifest> <project-name>
|
|
#
|
|
# Extract the revision of a project within the manifest.
|
|
# The default revision is supplied in the absence
|
|
# of an explicit project revision.
|
|
#
|
|
# manifest = Path to manifest.
|
|
# project-name = name of project.
|
|
#
|
|
manifest_get_revision_of_project () {
|
|
local manifest="${1}"
|
|
local project="${2}"
|
|
|
|
local default_revision=""
|
|
local revision=""
|
|
|
|
default_revision=$(manifest_get_default_revision "${manifest}")
|
|
revision=$(grep '<project' "${manifest}" | \
|
|
grep -e "name=${project}" -e "name=\"${project}\"" | \
|
|
grep 'revision=' | \
|
|
sed -e 's#.*revision=\([^ ]*\).*#\1#' -e 's#"##g' -e "s#'##g")
|
|
if [ "${revision}" != "" ]; then
|
|
echo "${revision}"
|
|
elif [ "${default_revision}" != "" ]; then
|
|
echo "${default_revision}"
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
#
|
|
# manifest_get_default_revision <manifest>
|
|
#
|
|
# Extract the default revision of the manifest, if any.
|
|
#
|
|
# manifest = Path to manifest.
|
|
#
|
|
manifest_get_default_revision () {
|
|
local manifest="${1}"
|
|
|
|
grep '<default' $manifest |sed -e 's#.*revision=\([^ /]*\).*#\1#' -e 's#"##g' -e "s#'##g"
|
|
}
|
|
|
|
#
|
|
# manifest_set_revision <old_manifest> <new_manifest> <revision> <lock_down> <project-list> <excluded_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,1 or 2. If 2, set a revision on all other non-listed
|
|
# projects to equal the SHA of the current git head.
|
|
# If 1, similar to 2, but only if the project doesn't have
|
|
# some other form of revision specified.
|
|
# project-list = A comma seperated list of projects. Listed projects
|
|
# will have their revision set to the provided revision
|
|
# value.
|
|
# excluded_project-list = A comma seperated list of projects. Listed
|
|
# projects will not be subject to lock-down.
|
|
#
|
|
manifest_set_revision () {
|
|
local old_manifest="${1}"
|
|
local new_manifest="${2}"
|
|
local revision="${3}"
|
|
local lock_down="${4}"
|
|
local set_default="${5}"
|
|
local projects="${6//,/ }"
|
|
local ld_exclude_projects="${7//,/ }"
|
|
|
|
local old_default_revision=""
|
|
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
|
|
|
|
old_default_revision=$(manifest_get_default_revision "${old_manifest}")
|
|
if [ ${set_default} -eq 1 ] && [ "${old_default_revision}" == "" ]; then
|
|
# We only know how to alter an existing default revision, not set a
|
|
# new one, so continue without setting a default.
|
|
set_default=0
|
|
fi
|
|
|
|
while IFS= read -r line; do
|
|
echo "${line}" | grep -q '<project'
|
|
if [ $? -ne 0 ]; then
|
|
# Line does not define a project
|
|
if [ ${set_default} -eq 0 ] || [ "${old_default_revision}" == "" ]; then
|
|
# No further processing, do not modify
|
|
echo "${line}"
|
|
continue
|
|
fi
|
|
|
|
# ok setting the default
|
|
echo "${line}" | grep -q '<default'
|
|
if [ $? -ne 0 ]; then
|
|
# Line does not set defaults, do not modify
|
|
echo "${line}"
|
|
continue
|
|
fi
|
|
|
|
echo "${line}" | sed "s#${old_default_revision}#${revision}#"
|
|
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
|
|
|
|
LD_EXCLUDE_FOUND=0
|
|
for project in ${ld_exclude_projects}; do
|
|
echo "${line}" | grep -q 'name="'${project}'"'
|
|
if [ $? -eq 0 ]; then
|
|
LD_EXCLUDE_FOUND=1
|
|
break
|
|
fi
|
|
done
|
|
|
|
rev=${revision}
|
|
old_rev=$(echo "${line}" | grep 'revision=' | sed -e 's#.*revision=\([^ ]*\).*#\1#' -e 's#"##g' -e "s#'##g")
|
|
if [ $FOUND -eq 0 ]; then
|
|
# A non-selected project
|
|
if [ ${lock_down} -eq 2 ] && [ $LD_EXCLUDE_FOUND -eq 0 ]; then
|
|
# Hard lock-down
|
|
# Set the revision to current HEAD SHA.
|
|
path="${repo_root_dir}/$(echo "${line}" | sed 's#.*path="\([^"]*\)".*#\1#')"
|
|
rev=$(cd "${path}"; git rev-parse HEAD)
|
|
elif [ ${lock_down} -eq 1 ] && [ $LD_EXCLUDE_FOUND -eq 0 ] && [ "${old_rev}" == "" ]; then
|
|
# Soft lock-down but no revision is currently set on the project.
|
|
# Set the revision to current HEAD SHA.
|
|
path="${repo_root_dir}/$(echo "${line}" | sed 's#.*path="\([^"]*\)".*#\1#')"
|
|
rev=$(cd "${path}"; git rev-parse HEAD)
|
|
elif [ ${lock_down} -eq 1 ] && [ $LD_EXCLUDE_FOUND -eq 0 ] && [ "${old_rev}" == "master" ]; then
|
|
# Soft lock-down and project has revision set to 'master' which is definitly unstable.
|
|
# Set the revision to current HEAD SHA.
|
|
path="${repo_root_dir}/$(echo "${line}" | sed 's#.*path="\([^"]*\)".*#\1#')"
|
|
rev=$(cd "${path}"; git rev-parse HEAD)
|
|
else
|
|
if [ ${set_default} -eq 0 ] || [ "${old_default_revision}" == "${revision}" ]; then
|
|
# default revision unchanged, leave it be
|
|
echo "${line}"
|
|
continue
|
|
fi
|
|
|
|
if [ "${old_rev}" != "" ]; then
|
|
# Non-selected project has an explicit revision, leave it be
|
|
echo "${line}"
|
|
continue
|
|
fi
|
|
|
|
# The default revision will change, but this project, which
|
|
# relied on the old default, is not supposed to change,
|
|
# so it's revision must now be explicitly set to point to
|
|
# the old default revision.
|
|
rev="${old_default_revision}"
|
|
fi
|
|
else
|
|
# A selected project
|
|
if [ ${set_default} -eq 1 ]; then
|
|
# Selected project does not need to set a revision.
|
|
# The revision will come from the default
|
|
if [ "${old_rev}" == "" ]; then
|
|
# project has no revision to delete
|
|
echo "${line}"
|
|
continue
|
|
fi
|
|
|
|
# delete any revision present
|
|
echo "${line}" | sed 's#\(.*\)revision=[^ ]*\(.*\)#\1\2#'
|
|
continue
|
|
fi
|
|
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
|
|
}
|
|
|