562 lines
16 KiB
Bash
562 lines
16 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
set -euo pipefail
|
|
|
|
usage() {
|
|
cat <<EOF
|
|
$0 [-n|--dry-run] [--dirty] [-u|--usage|-h|--help] [-fj|--forgejo] [--list] [--root] [-u2|--umbrella2] [--sat|--satellite] [--repo] [--xo-clone] [--xo-add-fj-remote] [--xo-push-remote] [--verify-satellite-list] [--u2-subrepo-status] [--u2-fix-xobuild-subsystem-list] [--u2-fix-cmake-bootstrap-macros] [--u2-subrepo-clone|--u2-push-satellite-remote|--u2-pull-satellite-remote] [--xoname=XONAME|XONAME]
|
|
EOF
|
|
}
|
|
|
|
help() {
|
|
usage
|
|
|
|
cat <<EOF
|
|
|
|
SLDC support for XO
|
|
|
|
Options:
|
|
-u | --usage brief help message
|
|
-h | --help this longer help message
|
|
-n | --dry-run print what would be done without making changes
|
|
--list list known xo subsystems
|
|
--root print project root directory XO_ROOT
|
|
-u2 | --umbrella2 print xo-umbrella2 directory XO_UMBRELLA2
|
|
--sat | --satellite print xo satellite root XO_SATELLITE_ROOT
|
|
--repo print repo URL for NAME
|
|
-fj | --forgejo with --repo or --xo-clone: use forgejo URL instead of github URL
|
|
--verify-satellite-list audit subsystem-list against XO_SATELLITE_ROOT and XO_UMBRELLA2
|
|
--xo-clone clone NAME into XO_SATELLITE_ROOT
|
|
--xo-add-fj-remote add forgejo remote to XO_SATELLITE_ROOT/NAME
|
|
--xo-push-remote push XO_SATELLITE_ROOT/NAME (with -fj: push to forgejo remote)
|
|
--u2-fix-xobuild-subsystem-list append xo-* dirs present in XO_UMBRELLA2 but missing from xobuild subsystem-list
|
|
--u2-fix-cmake-bootstrap-macros copy xo-cmake bootstrap macros to NAME (or --all) if not already matching
|
|
--u2-subrepo-clone clone satellite into XO_UMBRELLA2 as subrepo (NAME)
|
|
--u2-push-satellite-remote push satellite to upstream remote (NAME or --all; with --dirty: skip clean)
|
|
--dirty with --u2-push-satellite-remote --all: only push subrepos with outgoing commits
|
|
--u2-pull-satellite-remote pull satellite from upstream remote (NAME or --all with .gitrepo)
|
|
--u2-subrepo-status show git subrepo status for all satellites
|
|
--xoname=NAME satellite name for remote operations
|
|
EOF
|
|
}
|
|
|
|
cmd=
|
|
dry_run=0
|
|
xoname=
|
|
all_flag=0
|
|
dirty_flag=0
|
|
fj_flag=0
|
|
|
|
while [[ $# > 0 ]]; do
|
|
case "$1" in
|
|
-n | --dry-run)
|
|
dry_run=1
|
|
;;
|
|
-u | --usage)
|
|
cmd='usage'
|
|
;;
|
|
-h | --help)
|
|
cmd='help'
|
|
;;
|
|
--list)
|
|
cmd='list'
|
|
;;
|
|
--root)
|
|
cmd='root'
|
|
;;
|
|
-u2 | --umbrella2)
|
|
cmd='umbrella2'
|
|
;;
|
|
--sat | --satellite)
|
|
cmd='satellite'
|
|
;;
|
|
--repo)
|
|
cmd='repo'
|
|
;;
|
|
--xo-clone)
|
|
cmd='xo-clone'
|
|
;;
|
|
--xo-add-fj-remote)
|
|
cmd='xo-add-fj-remote'
|
|
;;
|
|
--xo-push-remote)
|
|
cmd='xo-push-remote'
|
|
;;
|
|
-fj | --forgejo)
|
|
fj_flag=1
|
|
;;
|
|
--verify-satellite-list)
|
|
cmd='verify-satellite-list'
|
|
;;
|
|
--u2-fix-xobuild-subsystem-list)
|
|
cmd='u2-fix-xobuild-subsystem-list'
|
|
;;
|
|
--u2-fix-cmake-bootstrap-macros)
|
|
cmd='u2-fix-cmake-bootstrap-macros'
|
|
;;
|
|
--u2-subrepo-clone)
|
|
cmd='u2-subrepo-clone'
|
|
;;
|
|
--u2-push-satellite-remote)
|
|
cmd='u2-push-satellite-remote'
|
|
;;
|
|
--u2-pull-satellite-remote)
|
|
cmd='u2-pull-satellite-remote'
|
|
;;
|
|
--u2-subrepo-status)
|
|
cmd='u2-subrepo-status'
|
|
;;
|
|
--all)
|
|
all_flag=1
|
|
;;
|
|
--dirty)
|
|
dirty_flag=1
|
|
;;
|
|
--xoname=*)
|
|
xoname="${1#*=}"
|
|
;;
|
|
xo-*)
|
|
xoname="$1"
|
|
;;
|
|
*)
|
|
usage
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
shift
|
|
done
|
|
|
|
XO_ROOT=@XO_ROOT@
|
|
XO_UMBRELLA2=@XO_UMBRELLA2@
|
|
XO_SATELLITE_ROOT=@XO_SATELLITE_ROOT@
|
|
|
|
SUBSYSTEMLIST_FILE=@CMAKE_INSTALL_FULL_DATADIR@/etc/xo/sdlc/subsystem-list
|
|
XOBUILD_SUBSYSTEMLIST_FILE=${XO_UMBRELLA2}/xo-cmake/etc/xo/subsystem-list
|
|
|
|
XO_REPO_STEM=
|
|
if [[ $(whoami) == "roland" ]]; then
|
|
XO_REPO_STEM="git@github.com:Rconybea"
|
|
else
|
|
XO_REPO_STEM="https://github.com/Rconybea"
|
|
fi
|
|
|
|
subsystem_list() {
|
|
cat ${SUBSYSTEMLIST_FILE}
|
|
}
|
|
|
|
FJ_REPO_STEM="ssh://forgejo@conybeare.us:2222/roland"
|
|
|
|
print_forgejo_repo() {
|
|
local name=$1
|
|
if grep -qx "${name}" "${XOBUILD_SUBSYSTEMLIST_FILE}" || grep -qx "${name}" "${SUBSYSTEMLIST_FILE}"; then
|
|
echo "${FJ_REPO_STEM}/${name}.git"
|
|
else
|
|
>&2 echo "xo-sdlc: unknown xo component [${name}]"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
print_github_repo() {
|
|
local name=$1
|
|
|
|
case "${name}" in
|
|
xo-indentlog) echo "${XO_REPO_STEM}/indentlog.git" ;;
|
|
xo-refcnt) echo "${XO_REPO_STEM}/refcnt.git" ;;
|
|
xo-subsys) echo "${XO_REPO_STEM}/subsys.git" ;;
|
|
xo-randomgen) echo "${XO_REPO_STEM}/randomgen.git" ;;
|
|
xo-reflect) echo "${XO_REPO_STEM}/reflect.git" ;;
|
|
*)
|
|
if grep -qx "${name}" "${XOBUILD_SUBSYSTEMLIST_FILE}"; then
|
|
echo "${XO_REPO_STEM}/${name}.git"
|
|
else
|
|
>&2 echo "xo-sdlc: unknown xo component [${name}]"
|
|
return 1
|
|
fi
|
|
;;
|
|
esac
|
|
}
|
|
|
|
|
|
u2_push_one() {
|
|
local name=$1
|
|
local cmd="git -C ${XO_UMBRELLA2} subrepo push ${name}"
|
|
|
|
if [[ ${dry_run} == 1 ]]; then
|
|
echo "${cmd}"
|
|
else
|
|
echo -n "pushing ${name}..."
|
|
local t0=$SECONDS
|
|
${cmd}
|
|
local rc=$?
|
|
echo " $((SECONDS - t0))s"
|
|
return ${rc}
|
|
fi
|
|
}
|
|
|
|
u2_push_satellite_remote() {
|
|
if [[ ${all_flag} == 1 ]]; then
|
|
local rc=0
|
|
for dir in "${XO_UMBRELLA2}"/xo-*/; do
|
|
local name
|
|
name=$(basename "${dir}")
|
|
[[ -f "${XO_UMBRELLA2}/${name}/.gitrepo" ]] || continue
|
|
if [[ ${dirty_flag} == 1 ]]; then
|
|
local outgoing
|
|
outgoing=$(u2_subrepo_outgoing "${name}")
|
|
[[ -n "${outgoing}" ]] || continue
|
|
fi
|
|
u2_push_one "${name}" || rc=$?
|
|
done
|
|
return ${rc}
|
|
fi
|
|
|
|
if [[ -z "${xoname}" ]]; then
|
|
>&2 echo "xo-sdlc: --u2-push-satellite-remote requires --xoname=NAME or --all"
|
|
return 1
|
|
fi
|
|
|
|
u2_push_one "${xoname}"
|
|
}
|
|
|
|
u2_pull_one() {
|
|
local name=$1
|
|
local cmd="git -C ${XO_UMBRELLA2} subrepo pull ${name}"
|
|
|
|
if [[ ${dry_run} == 1 ]]; then
|
|
echo "${cmd}"
|
|
else
|
|
${cmd}
|
|
fi
|
|
}
|
|
|
|
u2_pull_satellite_remote() {
|
|
if [[ ${all_flag} == 1 ]]; then
|
|
local rc=0
|
|
for dir in "${XO_UMBRELLA2}"/xo-*/; do
|
|
local name
|
|
name=$(basename "${dir}")
|
|
[[ -f "${XO_UMBRELLA2}/${name}/.gitrepo" ]] || continue
|
|
u2_pull_one "${name}" || rc=$?
|
|
done
|
|
return ${rc}
|
|
fi
|
|
|
|
if [[ -z "${xoname}" ]]; then
|
|
>&2 echo "xo-sdlc: --u2-pull-satellite-remote requires --xoname=NAME or --all"
|
|
return 1
|
|
fi
|
|
|
|
u2_pull_one "${xoname}"
|
|
}
|
|
|
|
u2_subrepo_outgoing() {
|
|
local name=$1
|
|
[[ -f "${XO_UMBRELLA2}/${name}/.gitrepo" ]] || return 1
|
|
local parent
|
|
parent=$(git -C "${XO_UMBRELLA2}" config -f "${name}/.gitrepo" subrepo.parent)
|
|
git -C "${XO_UMBRELLA2}" log --oneline --grep="^git subrepo " --invert-grep "${parent}..HEAD" -- "${name}"
|
|
}
|
|
|
|
u2_subrepo_status_one() {
|
|
local name=$1
|
|
if [[ ! -f "${XO_UMBRELLA2}/${name}/.gitrepo" ]]; then
|
|
>&2 echo "xo-sdlc: ${name} is not a subrepo"
|
|
return 1
|
|
fi
|
|
local commits
|
|
commits=$(u2_subrepo_outgoing "${name}")
|
|
if [[ -z "${commits}" ]]; then
|
|
printf "%-32s (clean)\n" "${name}"
|
|
else
|
|
printf "%-32s\n" "${name}"
|
|
while IFS= read -r line; do
|
|
printf " %s\n" "${line}"
|
|
done <<< "${commits}"
|
|
fi
|
|
}
|
|
|
|
u2_subrepo_status() {
|
|
if [[ -n "${xoname}" ]]; then
|
|
u2_subrepo_status_one "${xoname}"
|
|
return $?
|
|
fi
|
|
|
|
for dir in "${XO_UMBRELLA2}"/xo-*/; do
|
|
local name
|
|
name=$(basename "${dir}")
|
|
u2_subrepo_status_one "${name}" 2>/dev/null
|
|
done
|
|
}
|
|
|
|
u2_subrepo_clone() {
|
|
if [[ -z "${xoname}" ]]; then
|
|
>&2 echo "xo-sdlc: --u2-subrepo-clone requires --xoname=NAME"
|
|
return 1
|
|
fi
|
|
|
|
local url
|
|
url=$(print_github_repo "${xoname}") || return 1
|
|
|
|
local cmd="git -C ${XO_UMBRELLA2} subrepo clone ${url} ${xoname}"
|
|
|
|
if [[ ${dry_run} == 1 ]]; then
|
|
echo "${cmd}"
|
|
else
|
|
${cmd}
|
|
fi
|
|
}
|
|
|
|
verify_satellite_list() {
|
|
local rc=0
|
|
|
|
# collect union of names from all sources
|
|
local all_names
|
|
all_names=$(
|
|
# nullglob: an empty/missing dir yields nothing rather than a literal '*'
|
|
shopt -s nullglob
|
|
{
|
|
cat "${SUBSYSTEMLIST_FILE}"
|
|
cat "${XOBUILD_SUBSYSTEMLIST_FILE}"
|
|
for dir in "${XO_SATELLITE_ROOT}"/*/ "${XO_UMBRELLA2}"/xo-*/; do
|
|
basename "${dir}"
|
|
done
|
|
} | sed '/^[[:space:]]*$/d' | sort -u
|
|
)
|
|
|
|
local boot_ref="${XO_UMBRELLA2}/xo-cmake/share/xo-macros/xo-bootstrap-macros.cmake"
|
|
|
|
printf "%-32s %s %s %s %s %s %s %s\n" "name" "u2" "sr" "xo" "fj" "sdlc" "bld" "boot"
|
|
printf "%-32s %s %s %s %s %s %s %s\n" "----" "--" "--" "--" "--" "----" "---" "----"
|
|
|
|
while IFS= read -r name; do
|
|
local in_u2=0 in_sr=0 in_xo=0 in_fj=0 in_sdlc=0 in_bld=0 in_boot=0
|
|
[[ -d "${XO_UMBRELLA2}/${name}" ]] && in_u2=1
|
|
[[ -f "${XO_UMBRELLA2}/${name}/.gitrepo" ]] && in_sr=1
|
|
[[ -d "${XO_SATELLITE_ROOT}/${name}" ]] && in_xo=1
|
|
if [[ ${in_xo} == 1 ]]; then
|
|
git -C "${XO_SATELLITE_ROOT}/${name}" remote | grep -qx "forgejo" && in_fj=1
|
|
fi
|
|
if [[ ${in_u2} == 1 ]]; then
|
|
local sat_boot="${XO_UMBRELLA2}/${name}/cmake/xo-bootstrap-macros.cmake"
|
|
if [[ -f "${sat_boot}" ]] && diff -q "${boot_ref}" "${sat_boot}" &>/dev/null; then
|
|
in_boot=1
|
|
fi
|
|
fi
|
|
grep -qx "${name}" "${SUBSYSTEMLIST_FILE}" && in_sdlc=1
|
|
grep -qx "${name}" "${XOBUILD_SUBSYSTEMLIST_FILE}" && in_bld=1
|
|
printf "%-32s %2d %2d %2d %2d %4d %3d %4d\n" "${name}" "${in_u2}" "${in_sr}" "${in_xo}" "${in_fj}" "${in_sdlc}" "${in_bld}" "${in_boot}"
|
|
if [[ ${in_u2} == 0 || ${in_sr} == 0 || ${in_xo} == 0 || ${in_fj} == 0 || ${in_sdlc} == 0 || ${in_bld} == 0 || ${in_boot} == 0 ]]; then
|
|
rc=1
|
|
fi
|
|
done <<< "${all_names}"
|
|
|
|
return ${rc}
|
|
}
|
|
|
|
u2_fix_xobuild_subsystem_list() {
|
|
local added=0
|
|
|
|
for dir in "${XO_UMBRELLA2}"/xo-*/; do
|
|
local name
|
|
name=$(basename "${dir}")
|
|
if ! grep -qx "${name}" "${XOBUILD_SUBSYSTEMLIST_FILE}"; then
|
|
if [[ ${dry_run} == 1 ]]; then
|
|
echo "echo ${name} >> ${XOBUILD_SUBSYSTEMLIST_FILE}"
|
|
else
|
|
echo "${name}" >> "${XOBUILD_SUBSYSTEMLIST_FILE}"
|
|
fi
|
|
added=1
|
|
fi
|
|
done
|
|
|
|
if [[ ${added} == 0 ]]; then
|
|
echo "xo-sdlc: xobuild subsystem-list already up to date"
|
|
fi
|
|
}
|
|
|
|
fix_cmake_bootstrap_macros_one() {
|
|
local name=$1
|
|
local boot_ref="${XO_UMBRELLA2}/xo-cmake/share/xo-macros/xo-bootstrap-macros.cmake"
|
|
local repo_dir="${XO_UMBRELLA2}/${name}"
|
|
local dest_dir="${repo_dir}/cmake"
|
|
local dest="${dest_dir}/xo-bootstrap-macros.cmake"
|
|
|
|
# require the subrepo dir to exist (do not create it); but create cmake/ if needed
|
|
if [[ ! -d "${repo_dir}" ]]; then
|
|
>&2 echo "xo-sdlc: --u2-fix-cmake-bootstrap-macros: no such subrepo: ${repo_dir}"
|
|
return 1
|
|
fi
|
|
|
|
if [[ ! -f "${dest}" ]] || ! diff -q "${boot_ref}" "${dest}" &>/dev/null; then
|
|
if [[ ${dry_run} == 1 ]]; then
|
|
[[ -d "${dest_dir}" ]] || echo "mkdir -p ${dest_dir}"
|
|
echo "cp ${boot_ref} ${dest}"
|
|
else
|
|
mkdir -p "${dest_dir}"
|
|
cp "${boot_ref}" "${dest}"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
u2_fix_cmake_bootstrap_macros() {
|
|
if [[ ${all_flag} == 1 ]]; then
|
|
local rc=0
|
|
for dir in "${XO_UMBRELLA2}"/xo-*/; do
|
|
local name
|
|
name=$(basename "${dir}")
|
|
[[ "${name}" == "xo-cmake" ]] && continue
|
|
fix_cmake_bootstrap_macros_one "${name}" || rc=$?
|
|
done
|
|
return ${rc}
|
|
fi
|
|
|
|
if [[ -z "${xoname}" ]]; then
|
|
>&2 echo "xo-sdlc: --u2-fix-cmake-bootstrap-macros requires --xoname=NAME or --all"
|
|
return 1
|
|
fi
|
|
|
|
fix_cmake_bootstrap_macros_one "${xoname}"
|
|
}
|
|
|
|
if [[ $cmd == 'usage' ]]; then
|
|
echo -n "usage: "
|
|
usage
|
|
exit 0
|
|
fi
|
|
|
|
if [[ $cmd == 'help' ]]; then
|
|
help
|
|
exit 0
|
|
fi
|
|
|
|
if [[ $cmd == 'list' ]]; then
|
|
subsystem_list
|
|
exit 0
|
|
fi
|
|
|
|
if [[ -z ${XO_ROOT} ]]; then
|
|
2>&1 echo "xo-sdlc: expected non-empty XO_ROOT path"
|
|
exit 1
|
|
fi
|
|
|
|
if [[ -z ${XO_UMBRELLA2} ]]; then
|
|
2>&1 echo "xo-sdlc: expected non-empty XO_UMBRELLA2 path"
|
|
exit 1
|
|
fi
|
|
|
|
if [[ $cmd == 'root' ]]; then
|
|
echo ${XO_ROOT}
|
|
exit 0
|
|
fi
|
|
|
|
if [[ $cmd == 'umbrella2' ]]; then
|
|
echo ${XO_UMBRELLA2}
|
|
exit 0
|
|
fi
|
|
|
|
if [[ $cmd == 'satellite' ]]; then
|
|
echo ${XO_SATELLITE_ROOT}
|
|
exit 0
|
|
fi
|
|
|
|
if [[ $cmd == 'repo' ]]; then
|
|
if [[ -z "${xoname}" ]]; then
|
|
>&2 echo "xo-sdlc: --repo requires --xoname=NAME or a NAME argument"
|
|
exit 1
|
|
fi
|
|
if [[ ${fj_flag} -eq 1 ]]; then
|
|
print_forgejo_repo "${xoname}"
|
|
else
|
|
print_github_repo "${xoname}"
|
|
fi
|
|
exit $?
|
|
fi
|
|
|
|
if [[ $cmd == 'xo-clone' ]]; then
|
|
if [[ -z "${xoname}" ]]; then
|
|
>&2 echo "xo-sdlc: --xo-clone requires --xoname=NAME or a NAME argument"
|
|
exit 1
|
|
fi
|
|
if [[ ${fj_flag} -eq 1 ]]; then
|
|
clone_url=$(print_forgejo_repo "${xoname}") || exit 1
|
|
else
|
|
clone_url=$(print_github_repo "${xoname}") || exit 1
|
|
fi
|
|
clone_dest="${XO_SATELLITE_ROOT}/${xoname}"
|
|
clone_cmd="git clone ${clone_url} ${clone_dest}"
|
|
if [[ ${dry_run} -eq 1 ]]; then
|
|
echo "${clone_cmd}"
|
|
else
|
|
${clone_cmd}
|
|
fi
|
|
exit $?
|
|
fi
|
|
|
|
if [[ $cmd == 'xo-add-fj-remote' ]]; then
|
|
if [[ -z "${xoname}" ]]; then
|
|
>&2 echo "xo-sdlc: --xo-add-fj-remote requires --xoname=NAME or a NAME argument"
|
|
exit 1
|
|
fi
|
|
fj_url=$(print_forgejo_repo "${xoname}") || exit 1
|
|
fj_cmd="git -C ${XO_SATELLITE_ROOT}/${xoname} remote add forgejo ${fj_url}"
|
|
if [[ ${dry_run} -eq 1 ]]; then
|
|
echo "${fj_cmd}"
|
|
else
|
|
${fj_cmd}
|
|
fi
|
|
exit $?
|
|
fi
|
|
|
|
if [[ $cmd == 'xo-push-remote' ]]; then
|
|
if [[ -z "${xoname}" ]]; then
|
|
>&2 echo "xo-sdlc: --xo-push-remote requires --xoname=NAME or a NAME argument"
|
|
exit 1
|
|
fi
|
|
if [[ ${fj_flag} -eq 1 ]]; then
|
|
push_cmd="git -C ${XO_SATELLITE_ROOT}/${xoname} push forgejo"
|
|
else
|
|
push_cmd="git -C ${XO_SATELLITE_ROOT}/${xoname} push"
|
|
fi
|
|
if [[ ${dry_run} -eq 1 ]]; then
|
|
echo "${push_cmd}"
|
|
else
|
|
${push_cmd}
|
|
fi
|
|
exit $?
|
|
fi
|
|
|
|
if [[ $cmd == 'verify-satellite-list' ]]; then
|
|
verify_satellite_list
|
|
exit $?
|
|
fi
|
|
|
|
if [[ $cmd == 'u2-fix-xobuild-subsystem-list' ]]; then
|
|
u2_fix_xobuild_subsystem_list
|
|
exit $?
|
|
fi
|
|
|
|
if [[ $cmd == 'u2-fix-cmake-bootstrap-macros' ]]; then
|
|
u2_fix_cmake_bootstrap_macros
|
|
exit $?
|
|
fi
|
|
|
|
if [[ $cmd == 'u2-subrepo-clone' ]]; then
|
|
u2_subrepo_clone
|
|
exit $?
|
|
fi
|
|
|
|
if [[ $cmd == 'u2-push-satellite-remote' ]]; then
|
|
u2_push_satellite_remote
|
|
exit $?
|
|
fi
|
|
|
|
if [[ $cmd == 'u2-pull-satellite-remote' ]]; then
|
|
u2_pull_satellite_remote
|
|
exit $?
|
|
fi
|
|
|
|
if [[ $cmd == 'u2-subrepo-status' ]]; then
|
|
u2_subrepo_status
|
|
exit $?
|
|
fi
|