#!/usr/bin/env bash # # Push a branch to the internal git server, without leaving the token behind. # # tools/git-push.sh push the current branch # tools/git-push.sh wj push a named branch # # WHY THIS EXISTS # # The remote is HTTPS and needs a token. The obvious way to do that - rewrite # remote.origin.url to include the token, push, rewrite it back - was how this # was done by hand, and it is worse than it looks: # # - the token is written into .git/config, in plaintext, on every push # - if the push fails, or the terminal is closed mid-push, it STAYS there # - `git remote -v` then prints it, and so does anything that logs the remote # # Passing it in the URL on the command line is no better: the whole argv is # visible in `ps` to every user on the box for the length of the push. # # So the token goes in through GIT_ASKPASS instead. Git asks a helper program # for the password; the helper prints it on stdout and exits. It never touches # the config, never appears in argv, and there is nothing to clean up if this # script dies halfway. set -euo pipefail SECRETS="${SHOPDB_SECRETS:-/home/camp/projects/windows/shopdb/secrets.md}" REMOTE_HOST="gitea.proudtech.net" REMOTE_PATH="ge-aerospace/shopdb-flask.git" USERNAME="cproudlock" BRANCH="${1:-$(git rev-parse --abbrev-ref HEAD)}" if [ "$BRANCH" = "HEAD" ]; then echo "ERROR: detached HEAD. Check out a branch, or name one." >&2 exit 1 fi if ! git show-ref --verify --quiet "refs/heads/$BRANCH"; then echo "ERROR: no such local branch: $BRANCH" >&2 exit 1 fi # Refuse to push a branch that is not what is in front of you. Pushing a stale # branch while your work sits uncommitted looks like a successful push and is # the kind of thing found out much later. if [ -n "$(git status --porcelain)" ]; then echo "Working tree is not clean:" git status --short echo echo "Commit or stash first - a push of a dirty tree pushes the LAST commit," echo "not what you are looking at." exit 1 fi if [ ! -r "$SECRETS" ]; then echo "ERROR: cannot read $SECRETS" >&2 echo "Set SHOPDB_SECRETS to point at it." >&2 exit 1 fi # The proudtech.net section, not the localhost one above it. TOKEN="$(sed -n '/Gitea API (proudtech.net)/,/^## /p' "$SECRETS" \ | grep -i 'token' \ | sed 's/.*`\(.*\)`.*/\1/' \ | head -1)" if [ -z "$TOKEN" ]; then echo "ERROR: no token found in the proudtech.net section of $SECRETS" >&2 exit 1 fi # The askpass helper. Written to a file only this user can read, in a directory # that is removed on exit however this script ends. WORKDIR="$(mktemp -d)" trap 'rm -rf "$WORKDIR"' EXIT INT TERM ASKPASS="$WORKDIR/askpass.sh" umask 077 cat > "$ASKPASS" < itself. git update-ref "refs/remotes/origin/$BRANCH" "refs/heads/$BRANCH" echo "Pushed $BRANCH."