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