| #!/bin/bash |
| # SPDX-License-Identifier: GPL-2.0 |
| # |
| # Copyright (C) 2019 Daniel Borkmann <daniel@iogearbox.net> |
| # Copyright (C) 2020 Jakub Kicinski <kuba@kernel.org> |
| |
| # Pull from a pull request in patchwork, add a commit message |
| # based on the contents of the tag or the email if tag was empty. |
| # Optionally, compare if the patches on the branch are identical |
| # to what's posted on the mailing list. |
| |
| source $(dirname $0)/lib.sh |
| |
| usage() |
| { |
| cat <<-EOF |
| usage: pw-pull [-p PULL] [-s SERIES] [-c] [-P PULL_URL] [-h] |
| EOF |
| exit |
| } |
| |
| pull="" |
| pull_url="" |
| cover="" |
| series="" |
| series_branch="tmp" |
| head_old=$(git rev-parse --verify HEAD) |
| while true; do |
| case "$1" in |
| -p | --pull ) pull="$2"; shift 2 ;; |
| -s | --series ) series="$2"; shift 2 ;; |
| -c | --pull-from-cover ) cover="y"; shift ;; |
| -P | --pull-url ) pull_url="$2"; shift 2 ;; |
| -h | --help ) usage; break ;; |
| -- ) shift; break ;; |
| * ) break ;; |
| esac |
| done |
| [ -z "$pull" ] && [ -z "$cover" ] && usage |
| [ ! -z "$pull" ] && [ ! -z "$cover" ] && usage |
| [ ! -z "$pull" ] && [ ! -z "$pull_url" ] && usage |
| |
| srv=$(git config --get pw.server) |
| srv=${srv%/} # strip trailing slash |
| |
| if [ ! -z "$pull" ]; then |
| pull_json=$(curl -s $srv/patches/$pull/) |
| |
| pull_url=$(echo "$pull_json" | jq -r '.pull_url') |
| pull_author=$(echo "$pull_json" | jq -r '.submitter.name') |
| pull_subject=$(echo "$pull_json" | |
| jq -r '.name' | |
| sed -e 's/\[.*\] *//') |
| pull_msgid=$(echo "$pull_json" | jq -r '.msgid' | tr -d '<>') |
| json=$pull_json |
| elif [ ! -z "$cover" ]; then |
| series_json=$(curl -s $srv/series/$series/) |
| |
| pull_author=$(echo "$series_json" | jq -r '.submitter.name') |
| pull_subject=$(echo "$series_json" | |
| jq -r '.name' | |
| sed -e 's/\[.*\] *//') |
| pull_msgid=$(echo "$series_json" | jq -r '.cover_letter.msgid' | tr -d '<>') |
| |
| cover_id=$(echo "$series_json" | jq -r '.cover_letter.id') |
| cover_json=$(curl -s $srv/covers/$cover_id/) |
| |
| pull_msg=$(echo "$pull" | |
| jq -r '.content' | |
| awk 'BEGIN {e=0} |
| /^---/ {e=1} |
| /^Please consider/ {e=1} |
| {if(!e) print}') |
| |
| if [ -z "$pull_url" ]; then |
| pull_url=$(echo "$cover_json" | |
| jq -r '.content' | |
| awk '/^.+$/ { if (n) {n=0; print} } |
| /and are available in the git repository at:/ {n=1}') |
| pull_url=$(echo $pull_url) |
| fi |
| |
| if [ -z "$pull_url" ]; then |
| echo "Unable to parse out pull URL" |
| exit 1 |
| fi |
| |
| json=$cover_json |
| fi |
| |
| # Download the series from ML and make a local branch |
| if [ ! -z "$series" ]; then |
| mbox_from_series $series |
| git checkout -b $series_branch |
| git am -3 mbox.i |
| rm -f mbox.i |
| git checkout master |
| fi |
| |
| git pull --stat --log --no-edit --no-ff $pull_url |
| merge_header=$(git show --format="%s" --no-patch) |
| merge_body=$(git show --format="%b" --no-patch) |
| |
| # count lines until "* tag", ignore empty and gpg output |
| significant_lines=$(echo -e "$merge_body" | |
| awk 'BEGIN {c=0; e=0} |
| /^\* (tag|git|https|'"'"')/ {e=1} |
| /^[^#]/ { if(!e) c++} |
| END {print c}') |
| |
| if [ "$significant_lines" -le 1 ]; then |
| # Construct the message from email body if tag is empty |
| pull_msg=$(echo "$json" | |
| jq -r '.content' | |
| awk 'BEGIN {e=0} |
| /^---/ {e=1} |
| /^The following changes since commit/ {e=1} |
| /^The following are changes since commit/ {e=1} |
| /^Please consider/ {e=1} |
| /^Please, pull these changes/ {e=1} |
| {if(!e) print}') |
| |
| git commit --amend --signoff -F- <<EOF |
| $merge_header |
| |
| $pull_author says: |
| |
| ==================== |
| $pull_subject |
| |
| $pull_msg |
| |
| $merge_body |
| ==================== |
| |
| Link: https://lore.kernel.org/r/$pull_msgid |
| EOF |
| else |
| # Tag has info in it, just use that |
| git commit --amend --signoff -F- <<EOF |
| $merge_header |
| |
| $pull_author says: |
| |
| ==================== |
| $merge_body |
| ==================== |
| |
| Link: https://lore.kernel.org/r/$pull_msgid |
| EOF |
| fi |
| |
| if [ ! -z "$series" ]; then |
| if git diff master..$series_branch --exit-code; then |
| echo -e '\e[0;32mSeries matches PR\e[0m' |
| else |
| echo -e '\n\n\e[1;31mSeries differs!!\e[0m\n' |
| fi |
| git branch -D $series_branch |
| fi |
| |
| git commit --amend |
| |
| # Checks |
| head_new=$(git rev-parse --verify HEAD) |
| pw-check -s $head_old -e $head_new |