Git Patch All Applicable Repositories

Script to apply patch files to applicable repositories via Git. Changes should then be confirmed via GitHub Pull Requests for the pushed branches.

#!/bin/bash

##
# SETTINGS
##

LOG_FILE='/Users/michelleb/Desktop/bulk-git-patch.log'

##
# USER INPUT
##

echo 'Patch file:'
read PATCH_FILE

if [[ -z "$PATCH_FILE" ]]; then
	echo 'ERROR: No patch file specified.'
	exit 1
elif [[ ! -f "$PATCH_FILE" ]]; then
	echo 'ERROR: That patch file does not exist.'
	exit 1
fi

echo 'Branch name (ie. fix/12345):'
read BRANCH_NAME

if [[ -z "$BRANCH_NAME" ]]; then
	echo 'ERROR: You must specify a branch name on which to safely apply the patch.'
	exit 1
fi

echo 'Commit message:'
read COMMIT_MESSAGE

if [[ -z "$COMMIT_MESSAGE" ]]; then
	echo 'ERROR: You must provide a commit message for applying the patch.'
	exit 1
fi

echo
echo '---------------------------------------'
echo 'Please review and reply YES to confirm.'
echo
echo 'To watch progress, follow the log:'
echo "    tail -f $LOG_FILE"
echo '---------------------------------------'
echo 'Patch file:' "$PATCH_FILE"
echo 'Branch name:' "$BRANCH_NAME"
echo 'Commit message:' "$COMMIT_MESSAGE"
echo '---------------------------------------'
read APPROVED

if [[ 'YES' != "$APPROVED" ]]; then
	echo 'Okay. Patch was not applied.'
	exit 1
fi

##
# HELPERS
##

git-default-branch() {
	git symbolic-ref refs/remotes/origin/HEAD | sed 's@^refs/remotes/origin/@@'
}

git-update() {
	git checkout `git-default-branch` && git fetch --prune && git pull && git restore wp-config-sample.php
}

##
# PROCESSING
##

echo
echo 'Applying patch to applicable site repositories...'
echo

START_DATE=`date`

for SITE_DIR in /Users/michelleb/Documents/sites/*; do
	cd "$SITE_DIR"

	# Go into repo dir, which is assumed to be the only immediate child directory.
	## TODO: Get dir path where .git database is located. THAT is a Git repo.
	cd `find . -maxdepth 1 -type d ! -path . | sed 1q`

	{
		# Log section header.
		echo '======================================='
		echo 'Working directory:' `pwd`
		echo '---------------------------------------'
		# Checkout default branch and ensure it's current.
		git-update
	} &> "$LOG_FILE"

	# Quietly check if patch applies.
	git apply --check "$PATCH_FILE" &> /dev/null
	if [[ $? != 0 ]]; then
		echo 'Patch does not apply:' `pwd`
		continue
	fi

	# Perform patch.
	echo "Patching" `basename "$SITE_DIR"`

	{
		# Create branch for patch.
		git checkout -b "$BRANCH_NAME"
		# Apply patch.
		git apply --whitespace=fix "$PATCH_FILE"
		# Commit changes.
		git add .
		git commit -m "$COMMIT_MESSAGE"
		# Push branch to origin.
		git push --set-upstream origin "$BRANCH_NAME"
	} &> "$LOG_FILE"

done

echo
echo 'Done! Patch has been committed where applicable.'
echo
echo 'Start time:' "$START_DATE"
echo 'End time:  ' `date`