190 lines
4.2 KiB
Bash
Executable File
190 lines
4.2 KiB
Bash
Executable File
#!/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
|
|
|
|
for m in "${!rq[@]}"; do
|
|
[ "${#modules[@]}" -eq 0 -o -n "${modules[$m]}" ] || continue
|
|
if [ -z "${pq[$m]}" ]; then
|
|
log_info "delete remote request $m"
|
|
if ! git send-pack --force "$push_url" ":refs/heads/update_$m"; then
|
|
echo "failed to push $m update" >&2
|
|
ret=1
|
|
continue
|
|
fi
|
|
did_push=1
|
|
fi
|
|
done
|
|
|
|
if [ -n "$did_push" ]; then
|
|
log_info "Updating remote $PUSH_REMOTE"
|
|
git remote update -p "$PUSH_REMOTE" > /dev/null
|
|
fi
|
|
|
|
exit "$ret"
|