123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 |
- #!/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 "$@"
|