1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
|
#!/usr/bin/env bash
# Land a pull request
# Creates a PR-### branch, pulls the commits, opens up an interactive rebase to
# squash, and then annotates the commit with the changelog goobers
#
# Usage:
# pr <url|number> [<upstream remote>=origin]
main () {
if [ "$1" = "finish" ]; then
shift
finish "$@"
return $?
fi
local url="$(prurl "$@")"
local num=$(basename $url)
local prpath="${url#git@github.com:}"
local repo=${prpath%/pull/$num}
local prweb="https://github.com/$prpath"
local root="$(prroot "$url")"
local api="https://api.github.com/repos/${repo}/pulls/${num}"
local user=$(curl -s $api | json user.login)
local ref="$(prref "$url" "$root")"
local curhead="$(git show --no-patch --pretty=%H HEAD)"
local curbranch="$(git rev-parse --abbrev-ref HEAD)"
local cleanlines
IFS=$'\n' cleanlines=($(git status -s -uno))
if [ ${#cleanlines[@]} -ne 0 ]; then
echo "working dir not clean" >&2
IFS=$'\n' echo "${cleanlines[@]}" >&2
echo "aborting PR merge" >&2
fi
# ok, ready to rock
branch=PR-$num
if [ "$curbranch" == "$branch" ]; then
echo "already on $branch, you're on your own" >&2
return 1
fi
me=$(git config github.user || git config user.name)
if [ "$me" == "" ]; then
echo "run 'git config --add github.user <username>'" >&2
return 1
fi
exists=$(git show --no-patch --pretty=%H $branch 2>/dev/null)
if [ "$exists" == "" ]; then
git fetch origin pull/$num/head:$branch
git checkout $branch
else
git checkout $branch
git pull --rebase origin pull/$num/head
fi
git rebase -i $curbranch # squash and test
if [ $? -eq 0 ]; then
finish "${curbranch}"
else
echo "resolve conflicts and run: $0 finish "'"'${curbranch}'"'
fi
}
# add the PR-URL to the last commit, after squashing
finish () {
if [ $# -eq 0 ]; then
echo "Usage: $0 finish <branch> (while on a PR-### branch)" >&2
return 1
fi
local curbranch="$1"
local ref=$(cat .git/HEAD)
local prnum
case $ref in
"ref: refs/heads/PR-"*)
prnum=${ref#ref: refs/heads/PR-}
;;
*)
echo "not on the PR-## branch any more!" >&2
return 1
;;
esac
local me=$(git config github.user || git config user.name)
if [ "$me" == "" ]; then
echo "run 'git config --add github.user <username>'" >&2
return 1
fi
set -x
local url="$(prurl "$prnum")"
local num=$prnum
local prpath="${url#git@github.com:}"
local repo=${prpath%/pull/$num}
local prweb="https://github.com/$prpath"
local root="$(prroot "$url")"
local api="https://api.github.com/repos/${repo}/pulls/${num}"
local user=$(curl -s $api | json user.login)
local lastmsg="$(git log -1 --pretty=%B)"
local newmsg="${lastmsg}
PR-URL: ${prweb}
Credit: @${user}
Close: #${num}
Reviewed-by: @${me}
"
git commit --amend -m "$newmsg"
git checkout $curbranch
git merge PR-${prnum} --ff-only
set +x
}
prurl () {
local url="$1"
if [ "$url" == "" ] && type pbpaste &>/dev/null; then
url="$(pbpaste)"
fi
if [[ "$url" =~ ^[0-9]+$ ]]; then
local us="$2"
if [ "$us" == "" ]; then
us="origin"
fi
local num="$url"
local o="$(git config --get remote.${us}.url)"
url="${o}"
url="${url#(git:\/\/|https:\/\/)}"
url="${url#git@}"
url="${url#github.com[:\/]}"
url="${url%.git}"
url="https://github.com/${url}/pull/$num"
fi
url=${url%/commits}
url=${url%/files}
url="$(echo $url | perl -p -e 's/#issuecomment-[0-9]+$//g')"
local p='^https:\/\/github.com\/[^\/]+\/[^\/]+\/pull\/[0-9]+$'
if ! [[ "$url" =~ $p ]]; then
echo "Usage:"
echo " $0 <pull req url>"
echo " $0 <pull req number> [<remote name>=origin]"
type pbpaste &>/dev/null &&
echo "(will read url/id from clipboard if not specified)"
exit 1
fi
url="${url/https:\/\/github\.com\//git@github.com:}"
echo "$url"
}
prroot () {
local url="$1"
echo "${url/\/pull\/+([0-9])/}"
}
prref () {
local url="$1"
local root="$2"
echo "refs${url:${#root}}/head"
}
main "$@"
|