Split and update tools
This commit is contained in:
parent
abff01a7fe
commit
8d9042228c
53
README.md
Normal file
53
README.md
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
Scripts to sync git submodules of a project via pull requests
|
||||||
|
|
||||||
|
The git repo in the current directory is expected to have at least
|
||||||
|
one remote pointing to the target project. If that repo is not
|
||||||
|
writable, another one can be used for pushing.
|
||||||
|
|
||||||
|
create a config file `.settings` in the top level directory of the git submodule project:
|
||||||
|
```
|
||||||
|
# name of the remote to push to as repored by `git remote`
|
||||||
|
PUSH_REMOTE="joesix"
|
||||||
|
# username on gitea
|
||||||
|
PR_SRC_USER="joesix"
|
||||||
|
# target project for pull requests
|
||||||
|
PR_PROJECT="mold"
|
||||||
|
# target repo on gitea
|
||||||
|
PR_REPO="core"
|
||||||
|
# token
|
||||||
|
TOKEN="deadbeef"
|
||||||
|
# the url for cloning the project. Packages may use an url relative
|
||||||
|
to that.
|
||||||
|
PACKAGE_BASE_URL="https://gitea.opensuse.org/mold/core.git"
|
||||||
|
# relative url for new packages
|
||||||
|
PACKAGE_RELATIVE_URL="../../rpm"
|
||||||
|
# remote to to send pull requests to
|
||||||
|
REMOTE="origin"
|
||||||
|
# base branch of the target remote
|
||||||
|
BASE_BRANCH="main"
|
||||||
|
# optional: fixed date or a filename prefixed with @ to get a stable date for testing
|
||||||
|
DATE="@token"
|
||||||
|
# optional: an OBS project with a list of packages
|
||||||
|
OBSPKGLIST="https://api.opensuse.org/public/source/openSUSE:Factory:Rings:0-Bootstrap"
|
||||||
|
```
|
||||||
|
|
||||||
|
Scripts:
|
||||||
|
|
||||||
|
All scripts use getopt, --help may not always be up to date though
|
||||||
|
:-)
|
||||||
|
|
||||||
|
- updatemodules: checks all submodules for updates. For packages
|
||||||
|
that need to be updated creates `refs/pq/$packagename`. The
|
||||||
|
updated refence there updates the submodule commit reference for
|
||||||
|
updates. It also adds or removes entries from/to `.gitmodules` if
|
||||||
|
needed. There's also a `--single` option which produces a single
|
||||||
|
reference for all updates. The `--status` option show the current
|
||||||
|
state.
|
||||||
|
- pusher: compares the references created by the `updatemodules`
|
||||||
|
script with the specified remote. Pushed pending refs to an
|
||||||
|
`update_$packagename` ref. Gitea doesn't seem to support refs in
|
||||||
|
subdirs other than `heads`, that's why. Unless the `--dry` option
|
||||||
|
is specified, the `pusher` script also creates pull requests for
|
||||||
|
pending refs.
|
||||||
|
- gitea-pulls: dialog based script to list, view, merge or close
|
||||||
|
pull requests from the command line.
|
155
gitea-pulls
Executable file
155
gitea-pulls
Executable file
@ -0,0 +1,155 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
# SPDX-FileCopyrightText: Copyright 2023 SUSE LLC
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# config options
|
||||||
|
PR_SRC_USER=
|
||||||
|
PR_PROJECT=
|
||||||
|
PR_REPO=
|
||||||
|
TOKEN=
|
||||||
|
|
||||||
|
# command line only
|
||||||
|
verbose=0
|
||||||
|
cfg_file=
|
||||||
|
|
||||||
|
###################
|
||||||
|
|
||||||
|
requestfile=$(mktemp gitea-pulls.XXXXXX)
|
||||||
|
tmpfile=$(mktemp gitea-pulls.XXXXXX)
|
||||||
|
cleanup()
|
||||||
|
{
|
||||||
|
rm -f "$requestfile" "$tmpfile"
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
helpandquit()
|
||||||
|
{
|
||||||
|
cat <<-EOF
|
||||||
|
Usage: $0 [OPTIONS]
|
||||||
|
OPTIONS:
|
||||||
|
--verbsoe verbose
|
||||||
|
-h help screen
|
||||||
|
EOF
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
log_info()
|
||||||
|
{
|
||||||
|
[ "$verbose" -gt 0 ] || return 0
|
||||||
|
echo "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
d(){
|
||||||
|
local retval=0
|
||||||
|
# Bash makes it a bit annoying to read the output of a different FD into a variable, it
|
||||||
|
# only supports reading stdout by itself. So redirect 3 to stdout and 1 to the real stdout.
|
||||||
|
exec {stdoutfd}>&1
|
||||||
|
result="$(dialog --backtitle "Gita Pull requests" --output-fd 3 "$@" 3>&1 1>&${stdoutfd})" || retval=$?
|
||||||
|
# Word splitting makes it necessary to use eval here.
|
||||||
|
eval "exec ${stdoutfd}>&-"
|
||||||
|
return "$retval"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Given the number of total item pairs, outputs the number of items to display at once
|
||||||
|
menuheight() {
|
||||||
|
local height=$(($1 / 2))
|
||||||
|
[ "$height" -le "$dh_menu" ] || height="$dh_menu"
|
||||||
|
echo "$height"
|
||||||
|
}
|
||||||
|
|
||||||
|
stty_size() {
|
||||||
|
set -- $(stty size)
|
||||||
|
LINES="$1"
|
||||||
|
COLUMNS="$2"
|
||||||
|
# stty size can return zero when not ready or
|
||||||
|
# its a serial console
|
||||||
|
if [ "$COLUMNS" = "0" ] || [ "$LINES" = "0" ]; then
|
||||||
|
LINES=24
|
||||||
|
COLUMNS=80
|
||||||
|
fi
|
||||||
|
|
||||||
|
dh_menu=$((LINES-15))
|
||||||
|
dh_text=$((LINES-5))
|
||||||
|
}
|
||||||
|
stty_size
|
||||||
|
|
||||||
|
getopttmp=$(getopt -o hc:v --long help,config:,verbose -n "${0##*/}" -- "$@")
|
||||||
|
eval set -- "$getopttmp"
|
||||||
|
|
||||||
|
while true ; do
|
||||||
|
case "$1" in
|
||||||
|
-h|--help) helpandquit; shift ;;
|
||||||
|
-v|--verbose) verbose=$((++verbose)); shift ;;
|
||||||
|
-c|--config) cfg_file="$2"; shift 2 ;;
|
||||||
|
--) shift ; break ;;
|
||||||
|
*) echo "Internal error!" ; exit 1 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
. "${cfg_file:-.settings}"
|
||||||
|
|
||||||
|
needed=(PR_SRC_USER PR_PROJECT PR_REPO TOKEN)
|
||||||
|
for i in "${needed[@]}"; do
|
||||||
|
eval test -n "\"\$$i\"" || { echo "The following settings are mandatory: ${needed[*]}"; exit 1; }
|
||||||
|
done
|
||||||
|
|
||||||
|
request()
|
||||||
|
{
|
||||||
|
local urlpart="$1"
|
||||||
|
shift
|
||||||
|
curl -s -f "https://gitea.opensuse.org/api/v1/repos/$PR_PROJECT/$PR_REPO$urlpart" \
|
||||||
|
-H "accept: application/json" \
|
||||||
|
-H "Authorization: token $TOKEN" \
|
||||||
|
-H "Content-Type: application/json" "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch_requests()
|
||||||
|
{
|
||||||
|
request "/pulls?state=open" > "$requestfile"
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch_requests
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
list=()
|
||||||
|
while read -r number _branch _cid owner title; do
|
||||||
|
list+=("$number" "$owner: $title")
|
||||||
|
done < <(jq '.[]|[((.number|tostring)), .head.ref, .head.sha, .head.repo.owner.login, .title]|join(" ")' -r < "$requestfile")
|
||||||
|
if [ "${#list}" = 0 ]; then
|
||||||
|
d --msgbox "No pull requests in $PR_PROJECT/$PR_REPO" 0 0
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
d --no-hot-list --menu "$PR_PROJECT/$PR_REPO pull requests" 0 0 "$(menuheight ${#list[@]})" "${list[@]}" || exit 1
|
||||||
|
prno="$result"
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
list=(raw raw diff diff merge merge close close)
|
||||||
|
d --no-tags --menu "$PR_PROJECT/$PR_REPO #$prno" 0 0 "$(menuheight ${#list[@]})" "${list[@]}" || break
|
||||||
|
action="$result"
|
||||||
|
|
||||||
|
case "$action" in
|
||||||
|
raw)
|
||||||
|
jq ".[]|select(.number==$prno)" < "$requestfile" > "$tmpfile"
|
||||||
|
d --textbox "$tmpfile" 0 0
|
||||||
|
;;
|
||||||
|
diff)
|
||||||
|
request "/pulls/$prno.diff" > "$tmpfile"
|
||||||
|
d --textbox "$tmpfile" 0 0
|
||||||
|
;;
|
||||||
|
merge)
|
||||||
|
request "/pulls/$prno/merge" -d '{ "do": "merge", "delete_branch_after_merge": true}' | jq > "$tmpfile"
|
||||||
|
d --textbox "$tmpfile" 0 0
|
||||||
|
fetch_requests
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
close)
|
||||||
|
request "/pulls/$prno" -d '{ "state": "closed"}' -X PATCH | jq > "$tmpfile"
|
||||||
|
d --textbox "$tmpfile" 0 0
|
||||||
|
fetch_requests
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
done
|
176
pusher
Executable file
176
pusher
Executable file
@ -0,0 +1,176 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# config options
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
declare -A keep
|
||||||
|
PR_SRC_USER=
|
||||||
|
BASE_BRANCH="main"
|
||||||
|
PR_PROJECT=
|
||||||
|
PR_REPO=
|
||||||
|
TOKEN=
|
||||||
|
PUSH_REMOTE="origin"
|
||||||
|
|
||||||
|
# command line only
|
||||||
|
verbose=0
|
||||||
|
cfg_file=
|
||||||
|
dryrun=
|
||||||
|
show_status=
|
||||||
|
|
||||||
|
###################
|
||||||
|
push_url=
|
||||||
|
did_push=
|
||||||
|
|
||||||
|
tmpfile=$(mktemp pusher.XXXXXX)
|
||||||
|
cleanup()
|
||||||
|
{
|
||||||
|
rm -f "$tmpfile"
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
helpandquit()
|
||||||
|
{
|
||||||
|
cat <<-EOF
|
||||||
|
Usage: $0 [OPTIONS] [<module> ...]
|
||||||
|
OPTIONS:
|
||||||
|
-h help screen
|
||||||
|
EOF
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
log_info()
|
||||||
|
{
|
||||||
|
[ "$verbose" -gt 0 ] || return 0
|
||||||
|
echo "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
request_pulls()
|
||||||
|
{
|
||||||
|
curl -s -f "$pr_target?state=open" \
|
||||||
|
-H "accept: application/json" \
|
||||||
|
-H "Authorization: token $TOKEN" \
|
||||||
|
-H "Content-Type: application/json"
|
||||||
|
}
|
||||||
|
|
||||||
|
getopttmp=$(getopt -o hc:v --long help,single,branch:,config:,date:,remote:,status,verbose,dry -n "${0##*/}" -- "$@")
|
||||||
|
eval set -- "$getopttmp"
|
||||||
|
|
||||||
|
while true ; do
|
||||||
|
case "$1" in
|
||||||
|
-h|--help) helpandquit; shift ;;
|
||||||
|
-v|--verbose) verbose=$((++verbose)); shift ;;
|
||||||
|
-c|--config) cfg_file="$2"; shift 2 ;;
|
||||||
|
--status) show_status=1; shift ;;
|
||||||
|
--dry) dryrun=1; shift ;;
|
||||||
|
--) shift ; break ;;
|
||||||
|
*) echo "Internal error!" ; exit 1 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
declare -A modules
|
||||||
|
for m in "$@"; do
|
||||||
|
modules["$m"]=1
|
||||||
|
done
|
||||||
|
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
. "${cfg_file:-.settings}"
|
||||||
|
|
||||||
|
needed=(PR_SRC_USER PR_PROJECT PR_REPO TOKEN)
|
||||||
|
for i in "${needed[@]}"; do
|
||||||
|
eval test -n "\"\$$i\"" || { echo "The following settings are mandatory: ${needed[*]}"; exit 1; }
|
||||||
|
done
|
||||||
|
|
||||||
|
push_url="$(git config --get remote."$PUSH_REMOTE".url)"
|
||||||
|
pr_target="https://gitea.opensuse.org/api/v1/repos/$PR_PROJECT/$PR_REPO/pulls"
|
||||||
|
|
||||||
|
# push queue
|
||||||
|
declare -A pq
|
||||||
|
while read -r cid _c ref; do
|
||||||
|
m="${ref#refs/pq/}"
|
||||||
|
pq["$m"]="$cid"
|
||||||
|
done < <(git for-each-ref 'refs/pq/*')
|
||||||
|
# request queue
|
||||||
|
declare -A rq
|
||||||
|
while read -r cid _c ref; do
|
||||||
|
m="${ref#refs/remotes/"$PUSH_REMOTE"/update_}"
|
||||||
|
[ "$m" != "$ref" ] || continue
|
||||||
|
rq["$m"]="$cid"
|
||||||
|
done < <(git for-each-ref "refs/remotes/$PUSH_REMOTE/*")
|
||||||
|
|
||||||
|
declare -A pr
|
||||||
|
while read -r _id cid ref; do
|
||||||
|
m="${ref#update_}"
|
||||||
|
pr["$m"]="$cid"
|
||||||
|
log_info "pr $m: $cid"
|
||||||
|
done < <(request_pulls | jq ".[]|select(.head.repo.owner.login == \"$PR_SRC_USER\")|[((.number|tostring)), .head.sha, .head.ref]|join(\" \")" -r)
|
||||||
|
|
||||||
|
log_info "to push: ${!pq[*]}"
|
||||||
|
log_info "remote: ${!rq[*]}"
|
||||||
|
|
||||||
|
if [ -n "$show_status" ]; then
|
||||||
|
echo "# local remote pr package"
|
||||||
|
if [ "${#modules[@]}" -eq 0 ]; then
|
||||||
|
for m in "${!pq[@]}" "${!rq[@]}" "${!pr[@]}"; do
|
||||||
|
modules["$m"]=1
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
for m in "${!modules[@]}"; do
|
||||||
|
a=${pq[$m]:0:7}
|
||||||
|
b=${rq[$m]:0:7}
|
||||||
|
c=${pr[$m]:0:7}
|
||||||
|
echo "${a:- } ${b:- } ${c:- } $m"
|
||||||
|
done
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
ret=0
|
||||||
|
for m in "${!pq[@]}"; do
|
||||||
|
[ "${#modules[@]}" -eq 0 -o -n "${modules[$m]}" ] || continue
|
||||||
|
cid="${pq[$m]}"
|
||||||
|
[ -n "$cid" ]
|
||||||
|
if [ -n "${rq[$m]}" ] && [ "$cid" = "${rq[$m]}" ]; then
|
||||||
|
log_info "$m already pushed"
|
||||||
|
else
|
||||||
|
log_info "pushing $m: $cid"
|
||||||
|
if ! git send-pack --force "$push_url" "${cid}:refs/heads/update_$m"; then
|
||||||
|
echo "failed to push $m update" >&2
|
||||||
|
ret=1
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
did_push=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "${pr[$m]}" ]; then
|
||||||
|
if [ "$cid" = "${pr[$m]}" ]; then
|
||||||
|
log_info "pr for $m exists, no update"
|
||||||
|
else
|
||||||
|
echo "Warning: exiting pr for $m with different content"
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
title=$(git log -1 "--format=%s" "$cid")
|
||||||
|
head="update_$m"
|
||||||
|
[ "$PR_PROJECT" = "$PR_SRC_USER" ] || head="$PR_SRC_USER:$head"
|
||||||
|
log_info "Filing pr '$title': $cid at $pr_target"
|
||||||
|
[ -z "$dryrun" ] || continue
|
||||||
|
#https://github.com/go-gitea/gitea/issues/18842
|
||||||
|
if curl -s -f "$pr_target" \
|
||||||
|
-H "accept: application/json" \
|
||||||
|
-H "Authorization: token $TOKEN" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "{ \"base\": \"$BASE_BRANCH\", \"head\": \"$head\", \"title\": \"$title\"}" > "$tmpfile"; then
|
||||||
|
prid=$(jq -r .number < "$tmpfile")
|
||||||
|
echo "filed pr #$prid for $m"
|
||||||
|
else
|
||||||
|
echo "failed to file pr for $m"
|
||||||
|
jq -r .message < "$tmpfile"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -n "$did_push" ]; then
|
||||||
|
log_info "Updating remote $PUSH_REMOTE"
|
||||||
|
git remote update -p "$PUSH_REMOTE" > /dev/null
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit "$ret"
|
262
updatemodules
262
updatemodules
@ -1,100 +1,250 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
allatonce=
|
set -e
|
||||||
pushurl="gitea@gitea.opensuse.org:lnussel/core.git"
|
|
||||||
prsrcusr="lnussel"
|
|
||||||
prtarget="https://gitea.opensuse.org/api/v1/repos/mold/core/pulls"
|
|
||||||
|
|
||||||
if [ "$1" = '--allatonce' ]; then
|
# config options
|
||||||
allatonce=1
|
declare -A keep
|
||||||
|
REMOTE="origin"
|
||||||
|
BASE_BRANCH="main"
|
||||||
|
PACKAGE_BASE_URL=
|
||||||
|
PACKAGE_RELATIVE_URL="../../rpm"
|
||||||
|
# https://api.opensuse.org/public/source/openSUSE:Factory:Rings:0-Bootstrap
|
||||||
|
OBSPKGLIST=
|
||||||
|
DATE="$(date "+%s %z")"
|
||||||
|
keep["dummy-release"]=1
|
||||||
|
|
||||||
|
# command line only
|
||||||
|
single=
|
||||||
|
verbose=0
|
||||||
|
cfg_file=
|
||||||
|
|
||||||
|
###################
|
||||||
|
|
||||||
|
# constant needed to aid quoting
|
||||||
|
nl=$'\n'
|
||||||
|
|
||||||
|
declare -A obs
|
||||||
|
declare -A new
|
||||||
|
declare -A drop
|
||||||
|
declare -A revs
|
||||||
|
gitmodules_rev=
|
||||||
|
|
||||||
|
helpandquit()
|
||||||
|
{
|
||||||
|
cat <<-EOF
|
||||||
|
Usage: $0 [OPTIONS] [<module> ...]
|
||||||
|
OPTIONS:
|
||||||
|
--single create single commit for all changes
|
||||||
|
-h help screen
|
||||||
|
EOF
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
show_status()
|
||||||
|
{
|
||||||
|
git for-each-ref 'refs/pq/*'
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
clear_queue()
|
||||||
|
{
|
||||||
|
while read -r ref; do
|
||||||
|
git update-ref -d "$ref"
|
||||||
|
done < <(git for-each-ref 'refs/pq/*' --format '%(refname)')
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
isnew()
|
||||||
|
{
|
||||||
|
local p="${1:?}"
|
||||||
|
[ -n "${new[$p]}" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
todrop()
|
||||||
|
{
|
||||||
|
local p="${1:?}"
|
||||||
|
[ -n "${drop[$p]}" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
log_info()
|
||||||
|
{
|
||||||
|
[ "$verbose" -gt 0 ] || return 0
|
||||||
|
echo "$@"
|
||||||
|
}
|
||||||
|
|
||||||
|
makedict()
|
||||||
|
{
|
||||||
|
local dict="$1"
|
||||||
shift
|
shift
|
||||||
|
mapfile -t a < <("$@")
|
||||||
|
for k in "${a[@]}"; do
|
||||||
|
eval "$dict"["$k"]=1
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
getopttmp=$(getopt -o hc:v --long help,single,branch:,config:,date:,remote:,status,verbose,clear -n "${0##*/}" -- "$@")
|
||||||
|
eval set -- "$getopttmp"
|
||||||
|
|
||||||
|
while true ; do
|
||||||
|
case "$1" in
|
||||||
|
-h|--help) helpandquit; shift ;;
|
||||||
|
-v|--verbose) verbose=$((++verbose)); shift ;;
|
||||||
|
-c|--config) cfg_file="$2"; shift 2 ;;
|
||||||
|
--single) single=1; shift ;;
|
||||||
|
--remote) REMOTE="$2"; shift 2 ;;
|
||||||
|
--branch) BASE_BRANCH="$2"; shift 2 ;;
|
||||||
|
--status) show_status; exit 0 ;;
|
||||||
|
--clear) clear_queue; exit 0 ;;
|
||||||
|
--date) DATE="$2"; shift 2 ;;
|
||||||
|
--) shift ; break ;;
|
||||||
|
*) echo "Internal error!" ; exit 1 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
modules=("$@")
|
||||||
|
|
||||||
|
PACKAGE_BASE_URL="$(git config --get remote."$REMOTE".url)"
|
||||||
|
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
. "${cfg_file:-.settings}"
|
||||||
|
|
||||||
|
if [ "${DATE:0:1}" = '@' ]; then
|
||||||
|
DATE="$(stat -c %Y "${DATE:1}") +0100"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
modules=($@)
|
|
||||||
origin="$(git config --get remote.origin.url)"
|
|
||||||
now="$(date "+%s %z")"
|
|
||||||
# FIXME: hardcoded to avoid changing commits for now
|
|
||||||
now="$(stat -c %Y token) +0100"
|
|
||||||
export GIT_AUTHOR_NAME="Auto"
|
export GIT_AUTHOR_NAME="Auto"
|
||||||
export GIT_AUTHOR_EMAIL="auto@suse.de"
|
export GIT_AUTHOR_EMAIL="auto@suse.de"
|
||||||
export GIT_AUTHOR_DATE="$now"
|
export GIT_AUTHOR_DATE="$DATE"
|
||||||
export GIT_COMMITTER_NAME="Auto"
|
export GIT_COMMITTER_NAME="Auto"
|
||||||
export GIT_COMMITTER_EMAIL="auto@suse.de"
|
export GIT_COMMITTER_EMAIL="auto@suse.de"
|
||||||
export GIT_COMMITTER_DATE="$now"
|
export GIT_COMMITTER_DATE="$DATE"
|
||||||
|
|
||||||
tmpfile=$(mktemp updatemodules.XXXXXX)
|
tmpfile=$(mktemp updatemodules.XXXXXX)
|
||||||
|
tmpfile2=$(mktemp updatemodules.XXXXXX)
|
||||||
cleanup()
|
cleanup()
|
||||||
{
|
{
|
||||||
rm -f "$tmpfile"
|
rm -f "$tmpfile" "$tmpfile2"
|
||||||
}
|
}
|
||||||
trap cleanup EXIT
|
trap cleanup EXIT
|
||||||
|
|
||||||
read -r token < token || exit 1
|
|
||||||
|
|
||||||
# read all submodules
|
# read all submodules
|
||||||
declare -A revs
|
|
||||||
while read -r m t cid p; do
|
while read -r m t cid p; do
|
||||||
[ "$t" = "commit" ] || continue
|
if [ "$t" = blob ] && [ "$p" = ".gitmodules" ]; then
|
||||||
|
gitmodules_rev="$cid"
|
||||||
|
fi
|
||||||
|
[ "$t" = "commit" ] || continue
|
||||||
revs["$p"]="$cid"
|
revs["$p"]="$cid"
|
||||||
done < <(git cat-file -p "HEAD^{tree}")
|
done < <(git cat-file -p "$REMOTE/$BASE_BRANCH^{tree}")
|
||||||
|
|
||||||
if [ -z "$modules" ]; then
|
if [ -n "$OBSPKGLIST" ]; then
|
||||||
modules=("${!revs[@]}")
|
while read -r p; do
|
||||||
|
obs["$p"]=1
|
||||||
|
[ -n "${revs[$p]}" ] || new["$p"]=1
|
||||||
|
done < <(curl -s -f "$OBSPKGLIST"|sed -ne 's/.*entry name="\([^":]*\).*\/>/\1/p'|sort -u | grep -v AGGR)
|
||||||
|
|
||||||
|
for m in "${!revs[@]}"; do
|
||||||
|
[ -n "${obs[$m]}" -o -n "${keep[$m]}" ] || drop["$m"]=1
|
||||||
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
[ -z "${new[*]}" ] || log_info "new: ${!new[*]}"
|
||||||
|
[ -z "${drop[*]}" ] || log_info "drop: ${!drop[*]}"
|
||||||
|
|
||||||
|
if [ "${#modules[@]}" = 0 ]; then
|
||||||
|
modules=("${!revs[@]}" "${!new[@]}")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# push queue
|
||||||
|
declare -A pq
|
||||||
|
makedict pq git for-each-ref 'refs/pq/*' --format '%(refname)'
|
||||||
|
|
||||||
# check remotes for updates
|
# check remotes for updates
|
||||||
declare -A commits
|
declare -A commits
|
||||||
treetext=$(git cat-file -p "HEAD^{tree}")
|
treetext=$(git cat-file -p "$REMOTE/$BASE_BRANCH^{tree}")
|
||||||
|
git cat-file -p "$REMOTE/$BASE_BRANCH":.gitmodules > "$tmpfile"
|
||||||
|
cat "$tmpfile" > "$tmpfile2"
|
||||||
for m in "${modules[@]}"; do
|
for m in "${modules[@]}"; do
|
||||||
path="$(git config -f .gitmodules --get "submodule.$m.path")"
|
if isnew "$m"; then
|
||||||
url="$(git config -f .gitmodules --get "submodule.$m.url")"
|
path="$m"
|
||||||
branch="$(git config -f .gitmodules --get "submodule.$m.branch")"
|
url="$PACKAGE_RELATIVE_URL/$m"
|
||||||
|
smbranch=
|
||||||
|
git config -f "$tmpfile" --add "submodule.$m.path" "$path"
|
||||||
|
git config -f "$tmpfile" --add "submodule.$m.url" "$url"
|
||||||
|
else
|
||||||
|
path="$(git config -f "$tmpfile" --get "submodule.$m.path")"
|
||||||
|
url="$(git config -f "$tmpfile" --get "submodule.$m.url")"
|
||||||
|
smbranch="$(git config -f "$tmpfile" --get "submodule.$m.branch" || :)"
|
||||||
|
fi
|
||||||
if [ -z "$path" ] || [ -z "$url" ]; then
|
if [ -z "$path" ] || [ -z "$url" ]; then
|
||||||
echo "$m unknown" >&2
|
echo "$m unknown" >&2
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
if [ "${url:0:3}" = '../' ]; then
|
if [ "${url:0:3}" = '../' ]; then
|
||||||
url="$origin/$url"
|
url="$PACKAGE_BASE_URL/$url"
|
||||||
fi
|
fi
|
||||||
read -r cid _d < <(git ls-remote "$url" "${branch:-HEAD}")
|
|
||||||
if [ -z "${revs[$path]}" ]; then
|
cid=
|
||||||
echo "$path unknown" >&2
|
if ! todrop "$m"; then
|
||||||
continue
|
read -r cid _d < <(git ls-remote "$url" "${smbranch:-HEAD}")
|
||||||
|
if [ -z "$cid" ]; then
|
||||||
|
echo "$path not in pool" >&2
|
||||||
|
continue
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# create a new commit for this package
|
# create a new commit for this package
|
||||||
if [ "${revs[$path]}" != "$cid" ]; then
|
if [ "${revs[$path]}" != "$cid" ]; then
|
||||||
echo "Needs update: $path@${revs[$path]} -> $cid"
|
log_info "Needs update: $path@${revs[$path]:-NEW} -> ${cid:-DROP}"
|
||||||
if [ "$allatonce" = 1 ]; then
|
if isnew "$m"; then
|
||||||
treetext="${treetext/${revs[$path]} $path/$cid $path}"
|
newtreetext="$treetext${nl}160000 commit $cid $m"
|
||||||
|
elif todrop "$m"; then
|
||||||
|
newtreetext="${treetext/160000 commit ${revs[$path]} $path$nl/}"
|
||||||
|
git config -f "$tmpfile" --remove-section "submodule.$m"
|
||||||
else
|
else
|
||||||
newtree="$(git cat-file -p "HEAD^{tree}" | sed -e "s/${revs[$path]}\t$path/$cid\t$path/" | git mktree)"
|
newtreetext="${treetext/${revs[$path]} $path/$cid $path}"
|
||||||
newcid="$(git commit-tree -p HEAD -m "Update $m" "$newtree")"
|
|
||||||
commits["$m"]="$newcid"
|
|
||||||
fi
|
fi
|
||||||
|
if isnew "$m" || todrop "$m"; then
|
||||||
|
nh=$(git hash-object -w --path .gitmodules "$tmpfile")
|
||||||
|
newtreetext="${newtreetext/$gitmodules_rev .gitmodules/$nh .gitmodules}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$single" = 1 ]; then
|
||||||
|
if isnew "$m" || todrop "$m"; then
|
||||||
|
gitmodules_rev="$nh"
|
||||||
|
fi
|
||||||
|
treetext="$newtreetext"
|
||||||
|
# fall through
|
||||||
|
else
|
||||||
|
newtree=$(echo "$newtreetext" | git mktree)
|
||||||
|
msg="Update $m"
|
||||||
|
isnew "$m" && msg="Add $m"
|
||||||
|
todrop "$m" && msg="Remove $m"
|
||||||
|
newcid="$(git commit-tree -p "$REMOTE/$BASE_BRANCH" -m "$msg" "$newtree")"
|
||||||
|
commits["$m"]="$newcid"
|
||||||
|
cat "$tmpfile2" > "$tmpfile"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
# fall through
|
||||||
|
fi
|
||||||
|
if [ -n "${pq[refs/pq/$m]}" ]; then
|
||||||
|
log_info "remove pq for $m"
|
||||||
|
git update-ref -d "refs/pq/$m"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ "$allatonce" = 1 ]; then
|
if [ "$single" = 1 ]; then
|
||||||
newtree="$(echo "$treetext" | git mktree)"
|
newtree="$(echo "$treetext" | git mktree)"
|
||||||
newcid="$(git commit-tree -p HEAD -m "Update all" "$newtree")"
|
newcid="$(git commit-tree -p "$REMOTE/$BASE_BRANCH" -m "Update all" "$newtree")"
|
||||||
commits["all"]="$newcid"
|
commits["all"]="$newcid"
|
||||||
|
elif [ -n "${pq[refs/pq/all]}" ]; then
|
||||||
|
log_info "remove pq for single commit"
|
||||||
|
git update-ref -d "refs/pq/all"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
for m in "${!commits[@]}"; do
|
for m in "${!commits[@]}"; do
|
||||||
if git send-pack --force "$pushurl" "${commits[$m]}:refs/heads/update_$m"; then
|
ref="refs/pq/$m"
|
||||||
#https://github.com/go-gitea/gitea/issues/18842
|
if [ -n "${pq[$ref]}" ]; then
|
||||||
if curl -s -f "$prtarget" \
|
cid="$(git rev-parse "$ref")"
|
||||||
-H "accept: application/json" \
|
[ "$cid" = "${commits[$m]}" ] || echo "Warning: previous commit $cid for $m" >&2
|
||||||
-H "Authorization: token $token" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d "{ \"base\": \"main\", \"head\": \"$prsrcusr:update_$m\", \"title\": \"Update $m\"}" > "$tmpfile"; then
|
|
||||||
prid=$(jq .id < "$tmpfile")
|
|
||||||
echo "filed pr #$prid for $m"
|
|
||||||
else
|
|
||||||
echo "failed to file pr for $m"
|
|
||||||
jq .message < "$tmpfile"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "failed to push $m update" >&2
|
|
||||||
jq .message < "$tmpfile"
|
|
||||||
fi
|
fi
|
||||||
|
git update-ref "$ref" "${commits[$m]}"
|
||||||
done
|
done
|
||||||
|
Loading…
Reference in New Issue
Block a user