update pusher
This commit is contained in:
200
pusher
200
pusher
@@ -1,36 +1,192 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# config options
|
||||
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"
|
||||
echo rm -f "$tmpfile"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
. .settings
|
||||
helpandquit()
|
||||
{
|
||||
cat <<-EOF
|
||||
Usage: $0 [OPTIONS] [<module> ...]
|
||||
OPTIONS:
|
||||
-h help screen
|
||||
EOF
|
||||
exit 0
|
||||
}
|
||||
|
||||
needed=(PUSH_URL PR_SRC_USER PR_TARGET TOKEN)
|
||||
for i in "${needed[@]}"; do
|
||||
eval test -n "\$$i" || { echo "The following settings are mandatory: ${needed[*]}"; exit 1; }
|
||||
log_info()
|
||||
{
|
||||
[ "$verbose" -gt 0 ] || return 0
|
||||
echo "$@"
|
||||
}
|
||||
|
||||
makedict()
|
||||
{
|
||||
local dict="$1"
|
||||
shift
|
||||
mapfile -t a < <("$@")
|
||||
for k in "${a[@]}"; do
|
||||
eval "$dict"["$k"]=1
|
||||
done
|
||||
}
|
||||
|
||||
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 commits
|
||||
declare -A modules
|
||||
for m in "$@"; do
|
||||
modules["$m"]=1
|
||||
done
|
||||
|
||||
for m in "${!commits[@]}"; do
|
||||
if git send-pack --force "$PUSH_URL" "${commits[$m]}:refs/heads/update_$m"; then
|
||||
#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\": \"main\", \"head\": \"$PR_SRC_USER: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
|
||||
# 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
|
||||
if [ -n "${!pq[*]}" ]; then
|
||||
echo "Push queue:"
|
||||
for m in "${!pq[@]}"; do
|
||||
[ "${pq[$m]}" = "${rq[$m]}" ] && continue
|
||||
echo " ${pq[$m]} $m"
|
||||
done
|
||||
fi
|
||||
if [ -n "${!rq[*]}" ]; then
|
||||
echo "Request queue:"
|
||||
for m in "${!rq[@]}"; do
|
||||
[ "${rq[$m]}" = "${pr[$m]}" ] && continue
|
||||
echo " ${rq[$m]} $m"
|
||||
done
|
||||
fi
|
||||
if [ -n "${!pr[*]}" ]; then
|
||||
echo "Requests:"
|
||||
for m in "${!pr[@]}"; do
|
||||
echo " ${pr[$m]} $m"
|
||||
done
|
||||
fi
|
||||
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
|
||||
echo "failed to push $m update" >&2
|
||||
jq .message < "$tmpfile"
|
||||
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 "$PUSH_REMOTE" > /dev/null
|
||||
fi
|
||||
|
||||
exit "$ret"
|
||||
|
||||
Reference in New Issue
Block a user