#!/bin/sh # # Copyright (c) 2005 Junio C Hamano # . git-sh-setup-script || die "Not a git archive." usage () { echo >&2 "usage: $0"' [-n] [-o dir] [--mbox] [--check] [--sign] [-...] upstream [ our-head ] Prepare each commit with its patch since our-head forked from upstream, one file per patch, for e-mail submission. Each output file is numbered sequentially from 1, and uses the first line of the commit message (massaged for pathname safety) as the filename. When -o is specified, output files are created in that directory; otherwise in the current working directory. When -n is specified, instead of "[PATCH] Subject", the first line is formatted as "[PATCH N/M] Subject", unless you have only one patch. When --mbox is specified, the output is formatted to resemble UNIX mailbox format, and can be concatenated together for processing with applymbox. ' exit 1 } diff_opts= IFS=' ' LF=' ' outdir=./ while case "$#" in 0) break;; esac do case "$1" in -a|--a|--au|--aut|--auth|--autho|--author) author=t ;; -c|--c|--ch|--che|--chec|--check) check=t ;; -d|--d|--da|--dat|--date) date=t ;; -m|--m|--mb|--mbo|--mbox) date=t author=t mbox=t ;; -n|--n|--nu|--num|--numb|--numbe|--number|--numbere|--numbered) numbered=t ;; -s|--s|--si|--sig|--sign) signoff=t ;; -o=*|--o=*|--ou=*|--out=*|--outp=*|--outpu=*|--output=*|--output-=*|\ --output-d=*|--output-di=*|--output-dir=*|--output-dire=*|\ --output-direc=*|--output-direct=*|--output-directo=*|\ --output-director=*|--output-directory=*) outdir=`expr "$1" : '-[^=]*=\(.*\)'` ;; -o|--o|--ou|--out|--outp|--outpu|--output|--output-|--output-d|\ --output-di|--output-dir|--output-dire|--output-direc|--output-direct|\ --output-directo|--output-director|--output-directory) case "$#" in 1) usage ;; esac; shift outdir="$1" ;; -*) diff_opts="$diff_opts$LF$1" ;; *) break ;; esac shift done revpair= case "$#" in 2) revpair="$1..$2" ;; 1) case "$1" in *..*) revpair="$1";; *) revpair="$1..HEAD";; esac ;; *) usage ;; esac me=`git-var GIT_AUTHOR_IDENT | sed -e 's/>.*/>/'` case "$outdir" in */) ;; *) outdir="$outdir/" ;; esac test -d "$outdir" || mkdir -p "$outdir" || exit tmp=.tmp-series$$ trap 'rm -f $tmp-*' 0 1 2 3 15 series=$tmp-series commsg=$tmp-commsg filelist=$tmp-files titleScript=' /./d /^$/n s/^\[PATCH[^]]*\] *// s/[^-a-z.A-Z_0-9]/-/g s/\.\.\.*/\./g s/\.*$// s/--*/-/g s/^-// s/-$// s/$/./ p q ' whosepatchScript=' /^author /{ s/author \(.*>\) \(.*\)$/au='\''\1'\'' ad='\''\2'\''/p q }' _x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]' _x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40" stripCommitHead='/^'"$_x40"' (from '"$_x40"')$/d' git-rev-list --no-merges --merge-order \ $(git-rev-parse --revs-only "$revpair") >$series total=`wc -l <$series | tr -dc "[0-9]"` i=$total while read commit do git-cat-file commit "$commit" | git-stripspace >$commsg title=`sed -ne "$titleScript" <$commsg` case "$numbered" in '') num= ;; *) case $total in 1) num= ;; *) num=' '`printf "%d/%d" $i $total` ;; esac esac file=`printf '%04d-%stxt' $i "$title"` i=`expr "$i" - 1` echo >&2 "* $file" { mailScript=' /./d /^$/n s|^\[PATCH[^]]*\] *||' case "$mbox" in t) echo 'From nobody Mon Sep 17 00:00:00 2001' ;# UNIX "From" line mailScript="$mailScript"' s|^|Subject: [PATCH'"$num"'] |' ;; *) mailScript="$mailScript"' s|^|[PATCH'"$num"'] |' ;; esac eval "$(sed -ne "$whosepatchScript" $commsg)" test "$author,$au" = ",$me" || { mailScript="$mailScript"' a\ From: '"$au" } test "$date,$au" = ",$me" || { mailScript="$mailScript"' a\ Date: '"$ad" } mailScript="$mailScript"' : body p n b body' sed -ne "$mailScript" <$commsg test "$signoff" = "t" && { offsigner=`git-var GIT_COMMITTER_IDENT | sed -e 's/>.*/>/'` echo echo "Signed-off-by: $offsigner" echo } echo '---' echo git-diff-tree -p $diff_opts "$commit" | git-apply --stat --summary echo git-diff-tree -p $diff_opts "$commit" | sed -e "$stripCommitHead" case "$mbox" in t) echo ;; esac } >"$outdir$file" case "$check" in t) # This is slightly modified from Andrew Morton's Perfect Patch. # Lines you introduce should not have trailing whitespace. # Also check for an indentation that has SP before a TAB. grep -n '^+\([ ]* .*\|.*[ ]\)$' "$outdir$file" : do not exit with non-zero because we saw no problem in the last one. esac done <$series