#!/bin/bash # SPDX-License-Identifier: MIT set -e SELF=${BASH_SOURCE[0]} SELF_DIR="$( cd "$( dirname "$SELF" )" && pwd )" source $SELF_DIR/cascading-pr-lib.sh trap "rm -fr $TMPDIR" EXIT function repo_login() { local repo="$1" ( export DOT=$TMPDIR/$repo forgejo-curl.sh logout forgejo-curl.sh --token "${options[destination_token]}" login "${options[destination_url]}" ) } function repo_curl() { local repo=$1 shift DOT=$TMPDIR/$repo forgejo-curl.sh "$@" } function upsert_branch() { local repo_api=${options[destination_url]}/api/v1/repos/${options[destination_repo]} if repo_curl ${options[destination_repo]} api_json $repo_api/branches/${options[destination_head]} >& /dev/null ; then log_info "branch ${options[destination_head]} already exists" return fi repo_curl ${options[destination_repo]} api_json --data-raw '{"new_branch_name":"'${options[destination_head]}'","old_branch_name":"'${options[destination_base]}'"}' $repo_api/branches log_info "branch ${options[destination_head]} created" } function upsert_pr() { local repo_api=${options[destination_url]}/api/v1/repos/${options[destination_repo]} local title="cascading-pr from ${options[origin_url]}/${options[origin_repo]}/pulls/${options[origin_pr]}" repo_curl ${options[destination_repo]} api --get --data state=open --data type=pulls --data-urlencode q="$title" $repo_api/issues | jq --raw-output .[0] > $TMPDIR/destination-pr.json url=$(jq --raw-output .url < $TMPDIR/destination-pr.json) if test "$url" != "null"; then log_info "PR already exists $url" return fi repo_curl ${options[destination_repo]} api_json --data-raw '{"title":"'"$title"'","base":"'${options[destination_base]}'","head":"'${options[destination_head]}'"}' $repo_api/pulls > $TMPDIR/destination-pr.json url=$(jq --raw-output .url < $TMPDIR/destination-pr.json) log_info "PR created $url" } function origin_pr_head() { local repo_api=${options[origin_url]}/api/v1/repos/${options[origin_repo]} repo_curl ${options[origin_repo]} api_json $repo_api/pulls/${options[origin_pr]} > $TMPDIR/origin-pr.json jq --raw-output .head.ref < $TMPDIR/origin-pr.json } function upsert_clone() { local direction=$1 branch=$2 clone=$3 local fetch=true if ! test -d $TMPDIR/$direction; then git clone $clone -b $branch $TMPDIR/$direction fetch=false fi ( cd $TMPDIR/$direction if $fetch; then git fetch $direction fi git config user.email cascading-pr@example.com git config user.name cascading-pr ) } function push() { local direction=$1 branch=$2 clone=$3 ( cd $TMPDIR/$direction git add . if git commit -m 'cascading-pr update'; then git push --force origin $branch git rev-parse HEAD > ../$direction.sha log_info "pushed" else log_info "nothing to push" fi ) } function wait_destination_ci() { local sha="$1" local repo_api=${options[destination_url]}/api/v1/repos/${options[destination_repo]} wait_success $repo_api $sha } function update() { upsert_clone origin ${options[origin_head]} ${options[origin_clone]} upsert_clone destination ${options[destination_head]} ${options[destination_clone]} ( cd $TMPDIR/origin ls -l $TMPDIR/destination ${options[update]} $TMPDIR/destination ) push destination ${options[destination_head]} ${options[destination_clone]} } function finalize_options() { options[origin_scheme]=$(scheme ${options[origin_url]}) options[origin_host_port]=$(host_port ${options[origin_url]}) options[origin_clone]=${options[origin_scheme]}://any:${options[origin_token]}@${options[origin_host_port]}/${options[origin_repo]} options[origin_head]=$(origin_pr_head) options[destination_scheme]=$(scheme ${options[destination_url]}) options[destination_host_port]=$(host_port ${options[destination_url]}) options[destination_clone]=${options[destination_scheme]}://any:${options[destination_token]}@${options[destination_host_port]}/${options[destination_repo]} options[destination_base]=${options[destination_branch]} : ${options[prefix]:=${options[origin_repo]}} options[destination_head]=${options[prefix]}-${options[origin_pr]} } function run() { dependencies repo_login ${options[destination_repo]} upsert_branch upsert_pr repo_login ${options[origin_repo]} update wait_destination_ci $(cat $TMPDIR/destination.sha) } function main() { while true; do case "$1" in --verbose) shift verbose ;; --debug) shift debug ;; --origin-url) shift options[origin_url]=$1 shift ;; --origin-repo) shift options[origin_repo]=$1 shift ;; --origin-token) shift options[origin_token]=$1 shift ;; --origin-pr) shift options[origin_pr]=$1 shift ;; --destination-url) shift options[destination_url]=$1 shift ;; --destination-repo) shift options[destination_repo]=$1 shift ;; --destination-token) shift options[destination_token]=$1 shift ;; --destination-branch) shift options[destination_branch]=$1 shift ;; --update) shift options[update]=$1 shift ;; --prefix) shift options[prefix]=$1 shift ;; *) finalize_options "${1:-run}" return 0 ;; esac done } if echo "${@}" | grep --quiet -e '--debug' ; then main "${@}" else stash_debug "${@}" fi