git-format-patch-scripton commit Teach format-patch, rebase and cherry a..b format (4282c4f)
   1#!/bin/sh
   2#
   3# Copyright (c) 2005 Junio C Hamano
   4#
   5
   6. git-sh-setup-script || die "Not a git archive."
   7
   8usage () {
   9    echo >&2 "usage: $0"' [-n] [-o dir] [--mbox] [--check] [-<diff options>...] upstream [ our-head ]
  10
  11Prepare each commit with its patch since our-head forked from upstream,
  12one file per patch, for e-mail submission.  Each output file is
  13numbered sequentially from 1, and uses the first line of the commit
  14message (massaged for pathname safety) as the filename.
  15
  16When -o is specified, output files are created in that directory; otherwise in
  17the current working directory.
  18
  19When -n is specified, instead of "[PATCH] Subject", the first line is formatted
  20as "[PATCH N/M] Subject", unless you have only one patch.
  21
  22When --mbox is specified, the output is formatted to resemble
  23UNIX mailbox format, and can be concatenated together for processing
  24with applymbox.
  25'
  26    exit 1
  27}
  28
  29diff_opts=
  30IFS='
  31'
  32LF='
  33'
  34
  35outdir=./
  36while case "$#" in 0) break;; esac
  37do
  38    case "$1" in
  39    -a|--a|--au|--aut|--auth|--autho|--author)
  40    author=t ;;
  41    -c|--c|--ch|--che|--chec|--check)
  42    check=t ;;
  43    -d|--d|--da|--dat|--date)
  44    date=t ;;
  45    -m|--m|--mb|--mbo|--mbox)
  46    date=t author=t mbox=t ;;
  47    -n|--n|--nu|--num|--numb|--numbe|--number|--numbere|--numbered)
  48    numbered=t ;;
  49    -o=*|--o=*|--ou=*|--out=*|--outp=*|--outpu=*|--output=*|--output-=*|\
  50    --output-d=*|--output-di=*|--output-dir=*|--output-dire=*|\
  51    --output-direc=*|--output-direct=*|--output-directo=*|\
  52    --output-director=*|--output-directory=*)
  53    outdir=`expr "$1" : '-[^=]*=\(.*\)'` ;;
  54    -o|--o|--ou|--out|--outp|--outpu|--output|--output-|--output-d|\
  55    --output-di|--output-dir|--output-dire|--output-direc|--output-direct|\
  56    --output-directo|--output-director|--output-directory)
  57    case "$#" in 1) usage ;; esac; shift
  58    outdir="$1" ;;
  59    -*) diff_opts="$diff_opts$LF$1" ;;
  60    *) break ;;
  61    esac
  62    shift
  63done
  64
  65revpair=
  66case "$#" in
  672)
  68    revpair="$1..$2" ;;
  691)
  70    case "$1" in
  71    *..*)
  72        revpair="$1";;
  73    *)
  74        revpair="$1..HEAD";;
  75    esac ;;
  76*)
  77    usage ;;
  78esac
  79
  80me=`git-var GIT_AUTHOR_IDENT | sed -e 's/>.*/>/'`
  81
  82case "$outdir" in
  83*/) ;;
  84*) outdir="$outdir/" ;;
  85esac
  86test -d "$outdir" || mkdir -p "$outdir" || exit
  87
  88tmp=.tmp-series$$
  89trap 'rm -f $tmp-*' 0 1 2 3 15
  90
  91series=$tmp-series
  92commsg=$tmp-commsg
  93filelist=$tmp-files
  94
  95titleScript='
  96        /./d
  97        /^$/n
  98        s/^\[PATCH[^]]*\] *//
  99        s/[^-a-z.A-Z_0-9]/-/g
 100        s/\.\.\.*/\./g
 101        s/\.*$//
 102        s/--*/-/g
 103        s/^-//
 104        s/-$//
 105        s/$/./
 106        p
 107        q
 108'
 109
 110whosepatchScript='
 111/^author /{
 112        s/author \(.*>\) \(.*\)$/au='\''\1'\'' ad='\''\2'\''/p
 113        q
 114}'
 115
 116_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
 117_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
 118stripCommitHead='/^'"$_x40"' (from '"$_x40"')$/d'
 119
 120git-rev-list --merge-order $(git-rev-parse --revs-only "$revpair") >$series
 121total=`wc -l <$series | tr -dc "[0-9]"`
 122i=$total
 123while read commit
 124do
 125    git-cat-file commit "$commit" | git-stripspace >$commsg
 126    title=`sed -ne "$titleScript" <$commsg`
 127    case "$numbered" in
 128    '') num= ;;
 129    *)
 130        case $total in
 131        1) num= ;;
 132        *) num=' '`printf "%d/%d" $i $total` ;;
 133        esac
 134    esac
 135
 136    file=`printf '%04d-%stxt' $i "$title"`
 137    i=`expr "$i" - 1`
 138    echo >&2 "* $file"
 139    {
 140        mailScript='
 141        /./d
 142        /^$/n
 143        s|^\[PATCH[^]]*\] *||'
 144
 145        case "$mbox" in
 146        t)
 147            echo 'From nobody Mon Sep 17 00:00:00 2001' ;# UNIX "From" line
 148            mailScript="$mailScript"'
 149            s|^|Subject: [PATCH'"$num"'] |'
 150            ;;
 151        *)
 152            mailScript="$mailScript"'
 153            s|^|[PATCH'"$num"'] |'
 154            ;;
 155        esac
 156
 157        eval "$(sed -ne "$whosepatchScript" $commsg)"
 158        test "$author,$au" = ",$me" || {
 159                mailScript="$mailScript"'
 160        a\
 161From: '"$au"
 162        }
 163        test "$date,$au" = ",$me" || {
 164                mailScript="$mailScript"'
 165        a\
 166Date: '"$ad"
 167        }
 168
 169        mailScript="$mailScript"'
 170        : body
 171        p
 172        n
 173        b body'
 174
 175        sed -ne "$mailScript" <$commsg
 176        echo '---'
 177        echo
 178        git-diff-tree -p $diff_opts "$commit" | git-apply --stat --summary
 179        echo
 180        git-diff-tree -p $diff_opts "$commit" | sed -e "$stripCommitHead"
 181
 182        case "$mbox" in
 183        t)
 184                echo
 185                ;;
 186        esac
 187    } >"$outdir$file"
 188    case "$check" in
 189    t)
 190        # This is slightly modified from Andrew Morton's Perfect Patch.
 191        # Lines you introduce should not have trailing whitespace.
 192        # Also check for an indentation that has SP before a TAB.
 193        grep -n '^+\([  ]*      .*\|.*[         ]\)$' "$outdir$file"
 194
 195        : do not exit with non-zero because we saw no problem in the last one.
 196    esac
 197done <$series