diff options
author | Daniel Borkmann <daniel@iogearbox.net> | 2019-09-26 13:47:10 +0200 |
---|---|---|
committer | Daniel Borkmann <daniel@iogearbox.net> | 2019-09-27 15:22:43 +0200 |
commit | 2f1dd11d0268cbd32a0b90637bf528e96c77fb1f (patch) | |
tree | 7bc4475400660e716d5de6c12e5647e3a044341d | |
download | pw-2f1dd11d0268cbd32a0b90637bf528e96c77fb1f.tar.gz |
pw: initial import of pw tools
There it is. See README for more details and setup.
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
-rw-r--r-- | .gitconfig | 38 | ||||
-rw-r--r-- | .l2mdconfig | 14 | ||||
-rw-r--r-- | .mb2q.yaml | 16 | ||||
-rw-r--r-- | Makefile | 8 | ||||
-rw-r--r-- | README | 181 | ||||
-rwxr-xr-x | pw-apply | 70 | ||||
-rwxr-xr-x | pw-backport | 47 | ||||
-rwxr-xr-x | pw-check | 221 | ||||
-rwxr-xr-x | pw-pull | 42 |
9 files changed, 637 insertions, 0 deletions
diff --git a/.gitconfig b/.gitconfig new file mode 100644 index 0000000..f02f45a --- /dev/null +++ b/.gitconfig @@ -0,0 +1,38 @@ +[user] + name = Daniel Borkmann + email = daniel@iogearbox.net + +[sendmail] + smtpserver = smtp.iogearbox.net + suppresscc = all + chainreplyto = false + suppressfrom = true + +[color] + ui = auto + +[diff "default"] + xfuncname = "^[[:alpha:]$_].*[^:]$" + +[credential] + helper = cache + +[diff] + renames = false + +[format] + numbered = auto + thread = shallow + +[log] + mailmap = true + +[url "ssh://git@gitolite.kernel.org"] + insteadOf = https://git.kernel.org + insteadOf = http://git.kernel.org + insteadOf = git://git.kernel.org + +[pw] + server = https://patchwork.ozlabs.org/ + project = netdev + token = xyz diff --git a/.l2mdconfig b/.l2mdconfig new file mode 100644 index 0000000..e747c05 --- /dev/null +++ b/.l2mdconfig @@ -0,0 +1,14 @@ +[general] + maildir = ~/.l2md/maildir/common + period = 30 + +[repo bpf] + url = https://lore.kernel.org/bpf/0 + maildir = ~/.l2md/maildir/bpf + initial_import = 10000 + +[repo netdev] + url = https://lore.kernel.org/netdev/1 + url = https://lore.kernel.org/netdev/0 + maildir = ~/.l2md/maildir/netdev + initial_import = 10000 diff --git a/.mb2q.yaml b/.mb2q.yaml new file mode 100644 index 0000000..6bb4a60 --- /dev/null +++ b/.mb2q.yaml @@ -0,0 +1,16 @@ +committer: Daniel Borkmann <daniel@iogearbox.net> + +nocc_addrs: + - daniel@iogearbox.net + +list_addrs: + - bpf@vger.kernel.org + +drop_from: + - '<MAILER-DAEMON@' + +link_base: https://lore.kernel.org/bpf/ + +dropcc: False + +sob_before_cc: True diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..8958d8f --- /dev/null +++ b/Makefile @@ -0,0 +1,8 @@ +install: + cp pw-apply /usr/bin/pw-apply + cp pw-check /usr/bin/pw-check + cp pw-pull /usr/bin/pw-pull + cp pw-backport /usr/bin/pw-backport + +uninstall: + $(RM) /usr/bin/pw-apply /usr/bin/pw-pull /usr/bin/pw-check /usr/bin/pw-backport @@ -0,0 +1,181 @@ +Kernel patch/review workflow +============================ + +Minimal howto for the tools involved in my daily patch handling and kernel +mailing list interaction. It may be not perfect and the workflow as well +as tooling/scripts can be improved for sure, but I thought I'd document it +here for myself or others in case it's found useful. The example config +is very much bpf and netdev centric and needs to be adapted for other +subsystems. + +Please send patches to Daniel Borkmann <daniel@iogearbox.net>. + +Used tooling: +------------- + +I mainly use git, git-pw, git-send-email, l2md, pw-*, quilttools, msmtp, +mutt and patchwork UI for all my daily list workflow. The command-line +tools themselves can be obtained via: + + - git, git-send-email, msmtp, mutt (available as distro packages) + - git://git.kernel.org/pub/scm/linux/kernel/git/tglx/quilttools.git + - git://git.kernel.org/pub/scm/linux/kernel/git/dborkman/l2md.git + - git://git.kernel.org/pub/scm/linux/kernel/git/dborkman/pw.git + - https://github.com/getpatchwork/git-pw + +Base setup: +----------- + +Example configs for various tools are in this repository as well. + +1. git-pw: +~~~~~~~~~~ + +Configuration of git-pw is straight forward, simply follow the below +steps. The authentication token can be generated from the patchwork +UI from https://patchwork.ozlabs.org/user/. Below example is related +to netdev: + + $ git config --global pw.server 'https://patchwork.ozlabs.org/' + $ git config --global pw.project 'netdev' + $ git config --global pw.token 'API-TOKEN' + +2. quilttools aka mb2q: +~~~~~~~~~~~~~~~~~~~~~~~ + +Example .mb2q.yaml in this repo, needs to be in home directory. More +information on the options can be found in the quilttools repository. + +quilttools as well as git-pw is needed for the pw-apply tool in this +repository. Although I don't use quilt, I really like mb2q's patch +normalization. + +3. l2md: +~~~~~~~~ + +Example .l2mdconfig for lists I follow in this repo, needs to be in home +directory. The l2md repository also has additional information with +regards to mutt integration and a service unit file for letting it run +in the background automatically. I'm using l2md for fetching new emails +and msmtp for sending them. My l2md feeds into mutt, and msmtp is used +for mutt as well as git-send-email. + +Patch handling: +--------------- + +Main tools are pw-apply and pw-pull, both minimal, quick and dirty scripts +to get the job done. pw-check is called from pw-apply. pw-backport for the +backports to the stable tree. Patches for improving them are very welcome. + +1. Initial patch triage: +~~~~~~~~~~~~~~~~~~~~~~~~ + +Patches from netdev and bpf lists land under netdev patchwork project, hence +first manual step is to delegate them accordingly such that they land in the +delegate's todo: + + https://patchwork.ozlabs.org/project/netdev/list/ + +Todo list: + + https://patchwork.ozlabs.org/user/todo/netdev/ + +From public view, the current BPF todo list is accessible via: + + https://patchwork.ozlabs.org/project/netdev/list/?series=&submitter=&state=&q=&archive=&delegate=77147 + +All delegation and setting patches into 'Changes requested' is done through +the web UI. This remains to be improved for more automation. + +2. Applying patches: +~~~~~~~~~~~~~~~~~~~~ + +Applying patches from patchwork, add Tested-by, and Acked-by from others. +Patches are always identified by the series id even if it's just a single +patch. Use -t/-a to propagate tags from the cover letter to individual +patches, multiple people separated by comma: + + $ pw-apply -s 132626 -- -t 'Joe Hacker <j@hack.er>' -a 'Joe Hacker <jh@ack.er>, Acker Jon <ack@er.jon>' + +The pw-apply tool can also handle mboxes directly compressed in gzip or +uncompressed format: + + $ pw-apply -m https://patchwork.ozlabs.org/series/132626/mbox/ -- -t 'Joe Hacker <j@hack.er>' + +Another example without adding optional tags, this time from lore: + + $ pw-apply -m https://lore.kernel.org/bpf/20190925203745.3173184-1-andriin@fb.com/t.mbox.gz + +The pw-apply tool normalizes the patches through mb2q, sorts and groups +tags, adds permanent links to the lore list archive and merges them into +the master branch with the maintainer's SOB added to the chain. + +After they have been applied and sanity checked successfully, mark patches +as accepted in patchwork. The -a before the optional "--" will tell pw-apply +to mark the series as accepted, it does _not_ re-apply the series or do +anything else: + + $ pw-apply -s 132626 -a + +Note that this does not work in combination with the -m parameter since +the stand-alone mailbox does not have any context of patchwork. + +Full workflow: + + $ pw-apply -s 132626 + # Double check if all looks good in the git log + $ pw-apply -s 132626 -a + +Currently, the acceptance email must be sent manually, but this will be +automated in near term and integrated into -a. + +Side-note, manual sanity checking: + + $ pw-check -s e3439af4a339acd7fddbd6d59b8ecefaac07a611 -e d21b06927c8bf8083c64a95f272bc5491682ae24 + Commit: d21b06927c8b ("bpf: Fix bpf_event_output re-entry issue") + Fixes tag: Fixes: ae5a3a828cd0 ("bpf: add perf event notificaton support for sock_ops") + Has these problem(s): + - Target SHA1 does not exist + +Note that pw-check is called automatically for all applied patches through +pw-apply, so above example output is just to demonstrate a manual workflow. + +3. Pull requests: +~~~~~~~~~~~~~~~~~ + +Pull requests together with a consistent format are created as described in +below example. I do like consistency, hence even the pre-cooked template. +The commit sha is the merge base, meaning the last commit that both trees +had before patches have been applied. This could be automated but my own +preference is to explicitly state it here as both {bpf,bpf-next} trees don't +have too many commits piling up. Again, this workflow is mostly bpf specific +and the scripts would need to be adapted for other subsystems. + + $ pw-pull -t bpf -s aef70a1f44c0b570e6345c02c2d240471859f0a4 + PR: pr-bpf-2019-09-26.patch + +Currently the -t option only accepts: bpf, bpf-next + +The resulting file is then edited to describe the changes that the pull-request +contains. It's then sent out same way as other patches through git-send-email: + + $ git send-email --to davem@davemloft.net --cc jakub.kicinski@netronome.com --cc daniel@iogearbox.net --cc ast@kernel.org --cc netdev@vger.kernel.org --cc bpf@vger.kernel.org pr-bpf-2019-09-26.patch + +The PR will then show up the usual way in patchwork and assigned to the higher +level maintainer delegate for pulling. + +4. Backporting to stable: +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Backporting is done through the pw-backport tool which automatically adds the +SOB and upstream commit sha to the commit message. + +It's tailored to https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/. +In the local git clone, the following workflow can be used: + + $ git pull origin master + $ git checkout -b linux-5.3.y origin/linux-5.3.y + $ pw-backport d895a0f16fadb26d22ab531c49768f7642ae5c3e + Applying: d895a0f16fad bpf: fix accessing bpf_sysctl.file_pos on s390 + +The pw-backport can also take multiple shas as command line arguments. diff --git a/pw-apply b/pw-apply new file mode 100755 index 0000000..b8b9dcf --- /dev/null +++ b/pw-apply @@ -0,0 +1,70 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (C) 2019 Daniel Borkmann <daniel@iogearbox.net> + +usage() +{ + cat <<-EOF + usage: pw-apply [-h] [-s SERIES] [-m MBOX] [-a] -- [-C] + [-a ACKEDBY] [-r REVIEWEDBY] [-t TESTEDBY] +EOF + exit +} + +mbox_from_url() +{ + curl $1 | gunzip -f -c > mbox.i +} + +mbox_from_series() +{ + git pw series show $1 -f simple 2> /dev/null | \ + sed ''/Complete/s//$(printf "\033[1mComplete\033[0m")/'' + git pw series download $1 mbox.i 2> /dev/null +} + +accept_series() +{ + for patch in $(git pw series show $1 -f simple 2> /dev/null | \ + sed -n '/^Patches/,$p' | \ + sed -r 's/.* ([0-9]*) .*/\1/g') + do + echo "Accepting $patch:" + git pw patch update --state accepted $patch -f simple 2> /dev/null + done + echo "Done, all accepted!" + rm -f mbox.i + exit +} + +branch="mbox" +series="" +accept="" +mbox="" +head_old=$(git rev-parse --verify HEAD) +while true; do + case "$1" in + -s | --series ) series="$2"; shift 2 ;; + -a | --accept ) accept="1"; shift ;; + -m | --mbox ) mbox="$2"; shift 2 ;; + -h | --help ) usage; break ;; + -- ) shift; break ;; + * ) break ;; + esac +done +[ ! -z "$mbox" ] && [ ! -z "$series" ] && usage +[ -z "$mbox" ] && [ -z "$series" ] && usage +[ ! -z "$accept" ] && [ ! -z "$mbox" ] && usage +[ ! -z "$series" ] && mbox_from_series $series +[ ! -z "$mbox" ] && mbox_from_url $mbox +[ ! -z "$accept" ] && accept_series $series +git checkout -b $branch +mb2q --mboxout mbox.o "$@" mbox.i +git am -3 mbox.o +git checkout master +git merge --stat --ff $branch +git branch -d $branch +rm -f mbox.i mbox.o +head_new=$(git rev-parse --verify HEAD) +pw-check -s $head_old -e $head_new diff --git a/pw-backport b/pw-backport new file mode 100755 index 0000000..59a959d --- /dev/null +++ b/pw-backport @@ -0,0 +1,47 @@ +#!/bin/bash +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (C) 2019 Daniel Borkmann <daniel@iogearbox.net> +# Copyright (C) 2019 Authors of Cilium + +cherry_pick() +{ + REM="origin/master" + CID=$1 + BRANCHES=`git branch -q -r --contains $CID $REM 2> /dev/null` + if ! echo ${BRANCHES} | grep -q ".*master.*"; then + echo "Commit $CID not in $REM!" + exit 1 + fi + TMPF=`mktemp cp.XXXXXX` + FROM=`git show --pretty=email $CID | head -n 2 | grep "From: "` + FULL_ID=`git show $CID | head -n 1 | cut -f 2 -d ' '` + git format-patch -1 $FULL_ID --stdout | sed '/^$/Q' > $TMPF + echo "" >> $TMPF + echo "[ upstream commit $FULL_ID ]" >> $TMPF + git format-patch -1 $FULL_ID --stdout | sed -n '/^$/,$p' >> $TMPF + echo "Applying: $(git log -1 --oneline $FULL_ID)" + git am --quiet -3 --signoff $TMPF + rm $TMPF +} + +main() +{ + for CID in "$@"; do + cherry_pick "$CID" + done +} + +usage() +{ + cat <<-EOF + usage: pw-backport <commit-id> [commit-id ...] +EOF + exit +} + +if [ $# -lt 1 ]; then + usage +fi + +main "$@" diff --git a/pw-check b/pw-check new file mode 100755 index 0000000..0eb8c97 --- /dev/null +++ b/pw-check @@ -0,0 +1,221 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# +# Major parts from verify_fixes.sh and verify_signedoff.sh by +# Stephen and Greg. Only integrated the checks into pw-check. +# +# Copyright (C) 2019 Stephen Rothwell <sfr@canb.auug.org.au> +# Copyright (C) 2019 Greg Kroah-Hartman <gregkh@linuxfoundation.org> +# Copyright (C) 2019 Daniel Borkmann <daniel@iogearbox.net> + +usage() +{ + cat <<-EOF + usage: pw-check [-h] [-s START_COMMIT] [-e END_COMMIT] +EOF + exit +} + +split_re='^([Cc][Oo][Mm][Mm][Ii][Tt])?[[:space:]]*([[:xdigit:]]{5,})([[:space:]]*)(.*)$' +nl=$'\n' +tab=$'\t' + +strip_spaces() +{ + [[ "$1" =~ ^[[:space:]]*(.*[^[:space:]])[[:space:]]*$ ]] + echo "${BASH_REMATCH[1]}" +} + +verify_fixes() +{ + git_range=$1 + error=0 + commits=$(git rev-list --no-merges -i --grep='^[[:space:]]*Fixes:' "${git_range}") + if [ -z "$commits" ]; then + return 0 + fi + + for c in $commits; do + commit_log=$(git log -1 --format='%h ("%s")' "$c") + commit_msg="Commit: $commit_log +" + fixes_lines=$(git log -1 --format='%B' "$c" | + grep -i '^[[:space:]]*Fixes:') + + while read -r fline; do + [[ "$fline" =~ ^[[:space:]]*[Ff][Ii][Xx][Ee][Ss]:[[:space:]]*(.*)$ ]] + f="${BASH_REMATCH[1]}" + fixes_msg=" Fixes tag: $fline + Has these problem(s): +" + sha= + subject= + msg= + if [[ "$f" =~ $split_re ]]; then + first="${BASH_REMATCH[1]}" + sha="${BASH_REMATCH[2]}" + spaces="${BASH_REMATCH[3]}" + subject="${BASH_REMATCH[4]}" + if [ "$first" ]; then + msg="${msg:+${msg}${nl}}${tab}${tab}- leading word '$first' unexpected" + fi + if [ -z "$subject" ]; then + msg="${msg:+${msg}${nl}}${tab}${tab}- missing subject" + elif [ -z "$spaces" ]; then + msg="${msg:+${msg}${nl}}${tab}${tab}- missing space between the SHA1 and the subject" + fi + else + printf '%s%s\t\t- %s\n' "$commit_msg" "$fixes_msg" 'No SHA1 recognised' + commit_msg='' + error=1 + continue + fi + if ! git rev-parse -q --verify "$sha" >/dev/null; then + printf '%s%s\t\t- %s\n' "$commit_msg" "$fixes_msg" 'Target SHA1 does not exist' + commit_msg='' + error=1 + continue + fi + + if [ "${#sha}" -lt 12 ]; then + msg="${msg:+${msg}${nl}}${tab}${tab}- SHA1 should be at least 12 digits long${nl}${tab}${tab} Can be fixed by setting core.abbrev to 12 (or more) or (for git v2.11${nl}${tab}${tab} or later) just making sure it is not set (or set to \"auto\")." + fi + # reduce the subject to the part between () if there + if [[ "$subject" =~ ^\((.*)\) ]]; then + subject="${BASH_REMATCH[1]}" + elif [[ "$subject" =~ ^\((.*) ]]; then + subject="${BASH_REMATCH[1]}" + msg="${msg:+${msg}${nl}}${tab}${tab}- Subject has leading but no trailing parentheses" + fi + + # strip matching quotes at the start and end of the subject + # the unicode characters in the classes are + # U+201C LEFT DOUBLE QUOTATION MARK + # U+201D RIGHT DOUBLE QUOTATION MARK + # U+2018 LEFT SINGLE QUOTATION MARK + # U+2019 RIGHT SINGLE QUOTATION MARK + re1=$'^[\"\u201C](.*)[\"\u201D]$' + re2=$'^[\'\u2018](.*)[\'\u2019]$' + re3=$'^[\"\'\u201C\u2018](.*)$' + + if [[ "$subject" =~ $re1 ]]; then + subject="${BASH_REMATCH[1]}" + elif [[ "$subject" =~ $re2 ]]; then + subject="${BASH_REMATCH[1]}" + elif [[ "$subject" =~ $re3 ]]; then + subject="${BASH_REMATCH[1]}" + msg="${msg:+${msg}${nl}}${tab}${tab}- Subject has leading but no trailing quotes" + fi + + subject=$(strip_spaces "$subject") + + target_subject=$(git log -1 --format='%s' "$sha") + target_subject=$(strip_spaces "$target_subject") + + # match with ellipses + case "$subject" in + *...) subject="${subject%...}" + target_subject="${target_subject:0:${#subject}}" + ;; + ...*) subject="${subject#...}" + target_subject="${target_subject: -${#subject}}" + ;; + *\ ...\ *) + s1="${subject% ... *}" + s2="${subject#* ... }" + subject="$s1 $s2" + t1="${target_subject:0:${#s1}}" + t2="${target_subject: -${#s2}}" + target_subject="$t1 $t2" + ;; + esac + + subject=$(strip_spaces "$subject") + target_subject=$(strip_spaces "$target_subject") + + if [ "$subject" != "${target_subject:0:${#subject}}" ]; then + msg="${msg:+${msg}${nl}}${tab}${tab}- Subject does not match target commit subject${nl}${tab}${tab} Just use${nl}${tab}${tab}${tab}git log -1 --format='Fixes: %h (\"%s\")'" + fi + + lsha=$(git rev-parse -q --verify "$sha") + if [ -z "$lsha" ]; then + count=$(git rev-list --count "$sha".."$c") + if [ "$count" -eq 0 ]; then + msg="${msg:+${msg}${nl}}${tab}${tab}- Target is not an ancestor of this commit" + fi + fi + + if [ "$msg" ]; then + printf '%s%s%s\n' "$commit_msg" "$fixes_msg" "$msg" + commit_msg='' + error=1 + fi + done <<< "$fixes_lines" + done + + if [ ${error} -eq 1 ] ; then + exit 1 + fi +} + +verify_signedoff() +{ + git_range=$1 + error=false + for c in $(git rev-list --no-merges "${git_range}"); do + ae=$(git log -1 --format='%ae' "$c") + aE=$(git log -1 --format='%aE' "$c") + an=$(git log -1 --format='%an' "$c") + aN=$(git log -1 --format='%aN' "$c") + ce=$(git log -1 --format='%ce' "$c") + cE=$(git log -1 --format='%cE' "$c") + cn=$(git log -1 --format='%cn' "$c") + cN=$(git log -1 --format='%cN' "$c") + sob=$(git log -1 --format='%b' "$c" | grep -i '^[[:space:]]*Signed-off-by:') + + am=false + cm=false + grep -i -q "<$ae>" <<<"$sob" || + grep -i -q "<$aE>" <<<"$sob" || + grep -i -q ":[[:space:]]*${an}[[:space:]]*<" <<<"$sob" || + grep -i -q ":[[:space:]]*${aN}[[:space:]]*<" <<<"$sob" || + am=true + grep -i -q "<$ce>" <<<"$sob" || + grep -i -q "<$cE>" <<<"$sob" || + grep -i -q ":[[:space:]]*${cn}[[:space:]]*<" <<<"$sob" || + grep -i -q ":[[:space:]]*${cN}[[:space:]]*<" <<<"$sob" || + cm=true + + if "$am" || "$cm"; then + printf "Commit %s\n" "$(git show -s --abbrev-commit --abbrev=12 --pretty=format:"%h (\"%s\")%n" "${c}")" + "$am" && printf "\tauthor Signed-off-by missing\n" + "$cm" && printf "\tcommitter Signed-off-by missing\n" + printf "\tauthor email: %s\n" "$ae" + printf "\tcommitter email: %s\n" "$ce" + readarray -t s <<< "${sob}" + printf "\t%s\n" "${s[@]}" + printf "\n" + error=true + fi + done + if "$error"; then + echo "Errors in tree with Signed-off-by, please fix!" + exit 1 + fi +} + +from="" +to="" +while true; do + case "$1" in + -s | --start ) from="$2"; shift 2 ;; + -e | --end ) to="$2"; shift 2 ;; + -h | --help ) usage; break ;; + * ) break ;; + esac +done +[ -z "$from" ] && usage +[ -z "$to" ] && usage +verify_signedoff "$from..$to" +verify_fixes "$from..$to" +echo "Checked $from -> $to: OK" @@ -0,0 +1,42 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (C) 2019 Daniel Borkmann <daniel@iogearbox.net> + +usage() +{ + cat <<-EOF + usage: pw-pull [-h] [-t TREE] [-s SINCE_COMMIT] +EOF + exit +} + +remote="" +since="" +tree="" +today=$(date +%Y-%m-%d) +while true; do + case "$1" in + -s | --since ) since="$2"; shift 2 ;; + -t | --tree ) tree="$2"; shift 2 ;; + -h | --help ) usage; break ;; + * ) break ;; + esac +done +[ -z "$since" ] && usage +[ -z "$tree" ] && usage +case $tree in + bpf-next ) remote=(net-next git://git.kernel.org/pub/scm/linux/kernel/git/bpf/$tree.git) ;; + bpf ) remote=(net git://git.kernel.org/pub/scm/linux/kernel/git/bpf/$tree.git) ;; + * ) usage ;; +esac +file="pr-$tree-$today.patch" +git request-pull $since ${remote[1]} > $file +echo -e "Subject: pull-request: $tree $today\n\nHi David,\n\nThe following pull-request contains BPF updates for your *${remote[0]}* tree.\n\nThe main changes are:\n\n1) ..., from XYZ. Among others:\n\n - Blah blah sub item.\n\n2) ..., from ABC.\n\nPlease consider pulling these changes from:\n\n git://git.kernel.org/pub/scm/linux/kernel/git/bpf/$tree.git\n\nThanks a lot!\n\n----------------------------------------------------------------\n\n$(cat $file)" > $file +bug=$(grep -c gitolite $file) +if [ "$bug" -gt "0" ]; then + echo "PR not generated: using gitolite url, not public one!" + rm -f $file +else + echo "PR: $file" +fi |