Code

GIT 1.0.0
[git.git] / git-format-patch.sh
index 2844799535a4c63f61f6c94cf7a66c88d0052656..daa3caea778e13e946c4ffe53c876f5222ce7dfe 100755 (executable)
@@ -3,12 +3,8 @@
 # Copyright (c) 2005 Junio C Hamano
 #
 
 # Copyright (c) 2005 Junio C Hamano
 #
 
-. git-sh-setup || die "Not a git archive."
-
-usage () {
-    echo >&2 "usage: $0"' [-n] [-o dir] [--keep-subject] [--mbox] [--check] [--signoff] [-<diff options>...] upstream [ our-head ]
-
-Prepare each commit with its patch since our-head forked from upstream,
+USAGE='[-n | -k] [-o <dir> | --stdout] [--signoff] [--check] [--mbox] [--diff-options] <upstream> [<our-head>]'
+LONG_USAGE='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.
 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.
@@ -21,10 +17,12 @@ 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
 
 When --mbox is specified, the output is formatted to resemble
 UNIX mailbox format, and can be concatenated together for processing
-with applymbox.
-'
-    exit 1
-}
+with applymbox.'
+. git-sh-setup
+
+# Force diff to run in C locale.
+LANG=C LC_ALL=C
+export LANG LC_ALL
 
 diff_opts=
 LF='
 
 diff_opts=
 LF='
@@ -49,6 +47,8 @@ do
     numbered=t ;;
     -s|--s|--si|--sig|--sign|--signo|--signof|--signoff)
     signoff=t ;;
     numbered=t ;;
     -s|--s|--si|--sig|--sign|--signo|--signof|--signoff)
     signoff=t ;;
+    --st|--std|--stdo|--stdou|--stdout)
+    stdout=t mbox=t date=t author=t ;;
     -o=*|--o=*|--ou=*|--out=*|--outp=*|--outpu=*|--output=*|--output-=*|\
     --output-d=*|--output-di=*|--output-dir=*|--output-dire=*|\
     --output-direc=*|--output-direct=*|--output-directo=*|\
     -o=*|--o=*|--ou=*|--out=*|--outp=*|--outpu=*|--output=*|--output-=*|\
     --output-d=*|--output-di=*|--output-dir=*|--output-dire=*|\
     --output-direc=*|--output-direct=*|--output-directo=*|\
@@ -59,6 +59,9 @@ do
     --output-directo|--output-director|--output-directory)
     case "$#" in 1) usage ;; esac; shift
     outdir="$1" ;;
     --output-directo|--output-director|--output-directory)
     case "$#" in 1) usage ;; esac; shift
     outdir="$1" ;;
+    -h|--h|--he|--hel|--help)
+        usage
+       ;;
     -*' '* | -*"$LF"* | -*'    '*)
        # Ignore diff option that has whitespace for now.
        ;;
     -*' '* | -*"$LF"* | -*'    '*)
        # Ignore diff option that has whitespace for now.
        ;;
@@ -73,25 +76,78 @@ tt)
        die '--keep-subject and --numbered are incompatible.' ;;
 esac
 
        die '--keep-subject and --numbered are incompatible.' ;;
 esac
 
-rev1= rev2=
-case "$#" in
-2)
-    rev1="$1" rev2="$2" ;;
-1)
-    case "$1" in
-    *..*)
-       rev1=`expr "$1" : '\(.*\)\.\.'`
-       rev2=`expr "$1" : '.*\.\.\(.*\)'`
+tmp=.tmp-series$$
+trap 'rm -f $tmp-*' 0 1 2 3 15
+
+series=$tmp-series
+commsg=$tmp-commsg
+filelist=$tmp-files
+
+# Backward compatible argument parsing hack.
+#
+# Historically, we supported:
+# 1. "rev1"            is equivalent to "rev1..HEAD"
+# 2. "rev1..rev2"
+# 3. "rev1" "rev2      is equivalent to "rev1..rev2"
+#
+# We want to take a sequence of "rev1..rev2" in general.
+# Also, "rev1.." should mean "rev1..HEAD"; git-diff users are
+# familiar with that syntax.
+
+case "$#,$1$2" in
+1,?*..?*)
+       # single "rev1..rev2"
        ;;
        ;;
-    *)
-        rev1="$1"
-       rev2="HEAD"
+1,?*..)
+       # single "rev1.." should mean "rev1..HEAD"
+       set x "$1"HEAD
+       shift
+       ;;
+1,*)
+       # single rev1
+       set x "$1..HEAD"
+       shift
+       ;;
+2,?*..?*)
+       # not traditional "rev1" "rev2"
+       ;;
+2,*)
+       set x "$1..$2"
+       shift
        ;;
        ;;
-    esac ;;
-*)
-    usage ;;
 esac
 
 esac
 
+# Now we have what we want in $@
+for revpair
+do
+       case "$revpair" in
+       ?*..?*)
+               rev1=`expr "$revpair" : '\(.*\)\.\.'`
+               rev2=`expr "$revpair" : '.*\.\.\(.*\)'`
+               ;;
+       *)
+               rev1="$revpair^"
+               rev2="$revpair"
+               ;;
+       esac
+       git-rev-parse --verify "$rev1^0" >/dev/null 2>&1 ||
+               die "Not a valid rev $rev1 ($revpair)"
+       git-rev-parse --verify "$rev2^0" >/dev/null 2>&1 ||
+               die "Not a valid rev $rev2 ($revpair)"
+       git-cherry -v "$rev1" "$rev2" |
+       while read sign rev comment
+       do
+               case "$sign" in
+               '-')
+                       echo >&2 "Merged already: $comment"
+                       ;;
+               *)
+                       echo $rev
+                       ;;
+               esac
+       done
+done >$series
+
 me=`git-var GIT_AUTHOR_IDENT | sed -e 's/>.*/>/'`
 
 case "$outdir" in
 me=`git-var GIT_AUTHOR_IDENT | sed -e 's/>.*/>/'`
 
 case "$outdir" in
@@ -100,13 +156,6 @@ case "$outdir" in
 esac
 test -d "$outdir" || mkdir -p "$outdir" || exit
 
 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
 titleScript='
        /./d
        /^$/n
@@ -128,38 +177,7 @@ whosepatchScript='
        q
 }'
 
        q
 }'
 
-git-cherry -v "$rev1" "$rev2" |
-while read sign rev comment
-do
-       case "$sign" in
-       '-')
-               echo >&2 "Merged already: $comment"
-               ;;
-       *)
-               echo $rev
-               ;;
-       esac
-done >$series
-
-total=`wc -l <$series | tr -dc "[0-9]"`
-i=1
-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 "* $file"
-    {
+process_one () {
        mailScript='
        /./d
        /^$/n'
        mailScript='
        /./d
        /^$/n'
@@ -178,6 +196,7 @@ do
            echo 'From nobody Mon Sep 17 00:00:00 2001' ;# UNIX "From" line
            ;;
        esac
            echo 'From nobody Mon Sep 17 00:00:00 2001' ;# UNIX "From" line
            ;;
        esac
+
        eval "$(sed -ne "$whosepatchScript" $commsg)"
        test "$author,$au" = ",$me" || {
                mailScript="$mailScript"'
        eval "$(sed -ne "$whosepatchScript" $commsg)"
        test "$author,$au" = ",$me" || {
                mailScript="$mailScript"'
@@ -191,12 +210,16 @@ Date: '"$ad"
        }
 
        mailScript="$mailScript"'
        }
 
        mailScript="$mailScript"'
+       a\
+
        : body
        p
        n
        b body'
 
        : body
        p
        n
        b body'
 
-       sed -ne "$mailScript" <$commsg
+       (cat $commsg ; echo; echo) |
+       sed -ne "$mailScript" |
+       git-stripspace
 
        test "$signoff" = "t" && {
                offsigner=`git-var GIT_COMMITTER_IDENT | sed -e 's/>.*/>/'`
 
        test "$signoff" = "t" && {
                offsigner=`git-var GIT_COMMITTER_IDENT | sed -e 's/>.*/>/'`
@@ -213,20 +236,53 @@ Date: '"$ad"
        git-diff-tree -p $diff_opts "$commit" | git-apply --stat --summary
        echo
        git-diff-tree -p $diff_opts "$commit"
        git-diff-tree -p $diff_opts "$commit" | git-apply --stat --summary
        echo
        git-diff-tree -p $diff_opts "$commit"
+       echo "-- "
+       echo "@@GIT_VERSION@@"
 
        case "$mbox" in
        t)
                echo
                ;;
        esac
 
        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.
+}
+
+total=`wc -l <$series | tr -dc "[0-9]"`
+case "$total,$numbered" in
+1,*)
+       numfmt='' ;;
+*,t)
+       numfmt=`echo "$total" | wc -c`
+       numfmt=$(($numfmt-1))
+       numfmt=" %0${numfmt}d/$total"
+esac
+
+i=1
+while read commit
+do
+    git-cat-file commit "$commit" | git-stripspace >$commsg
+    title=`sed -ne "$titleScript" <$commsg`
+    case "$numbered" in
+    '') num= ;;
+    *)
+        num=`printf "$numfmt" $i` ;;
     esac
     esac
+
+    file=`printf '%04d-%stxt' $i "$title"`
+    if test '' = "$stdout"
+    then
+           echo "$file"
+           process_one >"$outdir$file"
+           if test t = "$check"
+           then
+               # 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"
+               :
+           fi
+    else
+           echo >&2 "$file"
+           process_one
+    fi
+    i=`expr "$i" + 1`
 done <$series
 done <$series