#!/bin/bash if [ -z "$(git remote)" ] ; then # Ignore non-public repositories exit 0 fi . ~/.bash.d/identity # Get the list of non-publish branches public_branches=() private_branches=() for branch in $(git branch | tr -d '*') ; do case "$branch" in (github) private_branches+=("$branch") ;; (githubgithub) private_branches+=("$branch") ;; *) if publish="$(git config --bool "branch.$branch.publish")" && [ "x$publish" = xfalse ] ; then private_branches+=("$branch") else public_branches+=("$branch") fi ;; esac done # Check if there are any local commits shopt -s lastpipe git rev-list --count --branches --not --remotes "${private_branches[@]}" | read -r local_commits # Decide if the remote repo needs publishing or deleting if [ "$local_commits" -eq 0 ] ; then action=delete else action=publish fi set_variables () { case "$remote" in https://github.com/*|ssh://github.com/*|git@github.com:*) user="$(git config publish.github.com.user)" project=${remote#https://github.com/} project=${project#ssh://github.com/} project=${project#git@github.com:} project=${project%.git} project=${project%/} repo=${project#*/} slug=$user/$repo remote=ssh://github.com/$slug.git type=github ;; https://salsa.debian.org/*|ssh://salsa.debian.org/*|git@salsa.debian.org:*) user="$(git config publish.salsa.debian.org.user)" project=${remote#https://salsa.debian.org/} project=${project#ssh://salsa.debian.org/} project=${project#git@salsa.debian.org:} project=${project%.git} project=${project%/} repo=${project#*/} slug=$user/$repo remote=git@salsa.debian.org:$slug.git type=gitlab ;; https://gitlab.softwareheritage.org/*|ssh://gitlab.softwareheritage.org/*|git@gitlab.softwareheritage.org:*) user="$(git config publish.gitlab.softwareheritage.org.user)" project=${remote#https://gitlab.softwareheritage.org/} project=${project#ssh://gitlab.softwareheritage.org/} project=${project#git@gitlab.softwareheritage.org:} project=${project%.git} project=${project%/} repo=${project#*/} slug=$user/$repo remote=git@gitlab.softwareheritage.org:$slug.git type=gitlab ;; ssh://git@git2.debian.org/*) user="$(git config publish.git2.debian.org.user)" project=${remote#ssh://git@git2.debian.org/} project=${project%.git} project=${project%/} project=${project#*/} repo=$project project=dsa-team/mirror/$project slug=$user/$repo remote=git@salsa.debian.org:$slug.git type=gitlab ;; https://gitlab.com/*|ssh://gitlab.com/*|git@gitlab.com:*) user="$(git config publish.gitlab.com.user)" project=${remote#https://gitlab.com/} project=${project#ssh://gitlab.com/} project=${project#git@gitlab.com:} project=${project%.git} project=${project%/} repo=${project#*/} slug=$user/$repo remote=git@gitlab.com:$slug.git type=gitlab ;; https://bitbucket.org/*|git@bitbucket.org:*) user="$(git config publish.bitbucket.org.user)" project=${remote#https://bitbucket.org/} project=${project#ssh://bitbucket.org/} project=${project#git@bitbucket.org:} project=${project%.git} project=${project%/} repo=${project#*/} slug=$user/$repo remote=git@bitbucket.org:$slug.git type=bitbucket ;; esac } if ! remote="$(git config publish.remote)" && [ $action = publish ] && [ "x$AUTOPUBLISH" != x1 ] ; then branch="$(git rev-parse --abbrev-ref HEAD)" remote="$(git config "branch.$branch.remote")" remote="$(git remote get-url "$remote")" set_variables # Ask where to publish, using the fork location as the default read -p 'Enter URL to repo to publish in: ' -r -e -i "$remote" remote if [ -n "$remote" ] ; then case "$type" in github) echo "Forking to $remote..." hub fork --no-remote && git config publish.remote "$remote" ;; gitlab) echo "Forking to $remote..." gitlab-api-v4 fork-project "$project" && git config publish.remote "$remote" ;; *) echo "Please fork $remote manually" echo "Please run this afterwards (fix the URL): git config publish.remote $remote " if [ "x$AUTOPUBLISH" != x1 ] ; then echo "Please exit the shell afterwards" bash -i fi ;; esac fi fi if [ -n "$remote" ] && [ -z "$NO_MIRROR" ]; then if [ -z "$type" ] ; then set_variables fi if true ; then publish_branches="$(git config --bool publish.branches)" else publish_branches=false fi if true ; then publish_tags="$(git config --bool publish.tags)" else publish_tags=false fi # Publish/delete only when user chooses to do so if [ $action = publish ] ; then if [ "${#private_branches[@]}" -eq 0 ]; then branch_push=(--all "$remote") # --prune --all does it for us delete_refs=false else branch_push=("$remote") for branch in "${public_branches[@]}" ; do branch_push+=("$branch:$branch") done # FIXME: # --prune does nothing with a refspec # so delete all refs before pushing delete_refs=true fi # --all and --tags are incompatible so # these have to be done separately :( { if [ "$(git config --bool publish.unprotect)" != false ] ; then case "$type" in gitlab) echo -n Unprotecting... gitlab-api-v4 protected-branches "$slug" | jq -r .[].name | xargs -r -d '\n' -n1 gitlab-api-v4 unprotect-branch "$slug" gitlab-api-v4 protected-tags "$slug" | jq -r .[].name | xargs -r -d '\n' -n1 gitlab-api-v4 unprotect-tag "$slug" echo ;; esac fi ci=$(git config --bool publish.ci || echo false) case "$type" in gitlab) echo -n Updating CI... gitlab-api-v4 edit-project "$slug" jobs_enabled:"$ci" > /dev/null echo ;; esac if [ "$delete_refs" != false ] ; then git ls-remote "$remote" | cut -f2 | grep -v '\^{}$' | grep -v '^HEAD$' | xargs -d '\n' git push --delete "$remote" fi if [ "$publish_branches" != false ] ; then git push --force --prune "${branch_push[@]}" fi if [ "$publish_tags" != false ] ; then git push --force --prune --tags "$remote" fi } |& grep -vF 'Everything up-to-date' || true elif [ $action = delete ] ; then case "$type" in github) hub delete "$slug" && git config --unset publish.remote ;; gitlab) gitlab-api-v4 delete-project "$slug" && git config --unset publish.remote ;; *) echo "Please delete repo $remote manually" echo "Please run this afterwards: git config --unset publish.remote" if [ "x$AUTOPUBLISH" != x1 ] ; then echo "Please exit the shell afterwards" bash -i fi ;; esac else echo "Please complete action $action manually for $remote" if [ "x$AUTOPUBLISH" != x1 ] ; then echo "Please exit the shell afterwards" bash -i fi fi fi