]> git.ipfire.org Git - thirdparty/git.git/blobdiff - git-format-patch.sh
short circuit out of a few places where we would allocate zero bytes
[thirdparty/git.git] / git-format-patch.sh
index 09b635e49256ecf3fb2af7e921da76d8a580e676..daa3caea778e13e946c4ffe53c876f5222ce7dfe 100755 (executable)
@@ -3,12 +3,8 @@
 # Copyright (c) 2005 Junio C Hamano
 #
 
-. git-sh-setup || die "Not a git archive."
-
-usage () {
-    echo >&2 "usage: $0"' [-n] [-o dir | --stdout] [--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.
@@ -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
-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='
@@ -61,6 +59,9 @@ do
     --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.
        ;;
@@ -75,25 +76,78 @@ tt)
        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
 
+# 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
@@ -102,13 +156,6 @@ case "$outdir" in
 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
@@ -130,19 +177,6 @@ whosepatchScript='
        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
-
 process_one () {
        mailScript='
        /./d
@@ -176,6 +210,8 @@ Date: '"$ad"
        }
 
        mailScript="$mailScript"'
+       a\
+
        : body
        p
        n
@@ -199,9 +235,8 @@ Date: '"$ad"
        echo
        git-diff-tree -p $diff_opts "$commit" | git-apply --stat --summary
        echo
-       git-cat-file commit "$commit^" | sed -e 's/^tree /applies-to: /' -e q
        git-diff-tree -p $diff_opts "$commit"
-       echo "---"
+       echo "-- "
        echo "@@GIT_VERSION@@"
 
        case "$mbox" in
@@ -212,6 +247,15 @@ Date: '"$ad"
 }
 
 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
@@ -220,16 +264,13 @@ do
     case "$numbered" in
     '') num= ;;
     *)
-       case $total in
-       1) num= ;;
-       *) num=' '`printf "%d/%d" $i $total` ;;
-       esac
+        num=`printf "$numfmt" $i` ;;
     esac
 
     file=`printf '%04d-%stxt' $i "$title"`
     if test '' = "$stdout"
     then
-           echo "$file"
+           echo "$file"
            process_one >"$outdir$file"
            if test t = "$check"
            then
@@ -240,7 +281,7 @@ do
                :
            fi
     else
-           echo >&2 "$file"
+           echo >&2 "$file"
            process_one
     fi
     i=`expr "$i" + 1`