JFIF  ` ` ;CREATOR: gd-jpeg v1.0 (using IJG JPEG v62), quality = 85 C   !"$"$ C hh"       } !1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz      w !1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz   ? .(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((+QI3L( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( @y -#yIޚXP2$袊 ( ( ( ( ( ( ( ( ( ( ( ( ( ( 3FE a(dN^M4GӁMoO$dssYz4]4+HM9վ2#OL@ܟH O@}LYW=p3! 7'Z&;" zםg|Ij~DǶr^2sI🆒TS(2?y}xmux#sھ[Cqg0mr\ ҏĺҋ{d^Rrr#mOŬ]\>uKcq*?ɯL񆥥Ƕ[ĆlO b[2+'c9Yl{I`:R fڽ;g8jc}ZC)ʑX匌J@:(P Hzh@#֌6Y$ʹ -ڛhJۆqi7s^{|c)]zyۿP+𗈬MaH_?LfG/U ( ( ( ( ( ( ( ("iX1?.ቨ.a?6I"|O+<.2H]aizhV3G8v|t".RcR7t+d(E~0 zD$r2ۜ~oC+Qsvx~%8 ~_|@Nկ81\gNMI#x ÞƠ W Cidlu;$1G5xh\NM#oL Zv6u+fd$HbaKiܻN?ʥt0F۟+g ]Q+r{8"28S4.ofXɑ|֗ x&s_Мp{W.14h~RME;XVX`q֡|:֢oB1fSBP_ WI~Ծ<04%ar UΉ>cy ~1b5w|Iϊ1ٯ4D`A y{-+N SkڲVCXR)M^ѠSc^3! }b}VBَ'9ִ/j~!]/DY_'׿} UQDRBͲ>GLsSnJQ(W Cx`rbF }G:~çivZ1Q =V&,gߥI}kdsѻ4RVEPEPEPEPEPEPH)I1@ (;=7JkO8j_ ٛVr\Q0 "=_Z;-8*ᛯ[ino ZU>#/9]x0]> 3u&%S9/PQVҭtIbxP ==*9 jPX7uMr3<`Z\g:^qV \WKg.잹ȩZ]][Pi۬h=V'O2VK0 TI`z'_֚CH/G Է4V 5, up쇖?夿w5j9]APn<:cs[V57 ]vAl*բp֖Z Pu{ _N]6@ȫaՏ@6sX+W1q@ tX 鴫`I8h3D Gm vCċiҝzRzP!Ҕ`p:P }>5|4VR!-䝒I,O98(=e"|ۦuK *pl?B k@u=$ Mz%%Sr~SsW۴ͧ1;Lg99qw:)Ծ~Ǟ+|7s]Md 9)V5"ھ;/?p MLGN=ҾÈ67c&XL1#}0瞾o};^̠yJ}}ǡǾ%!<zbfEe}I]ֽ NzZ-T0I WiiehRin-lPN׉bgfIìh% $L vˆ*n.Kr{waҷRnGz<+d63G <M4Ҽ' m4H ǪՅ$qpxZZ)gڊ(((((( W|sZ|akmD:rJELr~wkMCX _v4E|!e u.W%1zu?θߎ b%#QB#ApN9^78R ᭭DdA&ӶJ:h9>ct`lҝQ+9 erGn"  0=*(((((&4u+`=cpoōj:-pwp~Q*%*nH/=6a#4׎cÚwyC޾W})ǚEEQ4w_JȨÔjf5>Ϟ[<t(c ~m1K#SI1S@ Z@5F)E0 ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( )8;qzj6:s3yv ӥ b|J ͭj'*"㔃Ty ėc^lb=$7 N4a. R#!{\ts '᳣xj ao% T9ڔ4|QwZ|Z20k G>xO^;]o..tn7h ֆ[\y5/glKv:xu^)-_ۏLwOY5y` 6gҴ/ɬi[X~77O_ x>}NU =?=6;XDa+XSHRlA Q<7ֺ8@ԊzSA7qB Z(AEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP^WZ#GkM-] eRH-##0'TH( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ^cef6b88lr1ڀ< &[^dB>ץYYh#0JpP c4  QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE QE #!/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 [=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 '" >&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 (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 '" >&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 " echo " $0 [=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 "$@"