From: Junio C Hamano Date: Thu, 3 Dec 2009 21:54:03 +0000 (-0800) Subject: Merge branch 'jc/maint-am-keep' into maint X-Git-Tag: v1.6.5.5~10 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/78b77c491ff21e27dbaf1381268aeb380f0607b8?ds=inline;hp=-c Merge branch 'jc/maint-am-keep' into maint * jc/maint-am-keep: Remove dead code from "git am" --- 78b77c491ff21e27dbaf1381268aeb380f0607b8 diff --combined git-am.sh index 185ea23af6,9050cc9076..f48620d5bc --- a/git-am.sh +++ b/git-am.sh @@@ -8,29 -8,21 +8,29 @@@ OPTIONS_SPEC=" git am [options] [|...] git am [options] (--resolved | --skip | --abort) -- -d,dotest= (removed -- do not use) i,interactive run interactively -b,binary (historical option -- no-op) +b,binary* (historical option -- no-op) 3,3way allow fall back on 3way merging if needed +q,quiet be quiet s,signoff add a Signed-off-by line to the commit message u,utf8 recode into utf8 (default) k,keep pass -k flag to git-mailinfo +c,scissors strip everything before a scissors line whitespace= pass it through git-apply +ignore-space-change pass it through git-apply +ignore-whitespace pass it through git-apply +directory= pass it through git-apply C= pass it through git-apply p= pass it through git-apply +patch-format= format the patch(es) are in +reject pass it through git-apply resolvemsg= override error message when patch failure occurs r,resolved to be used after a patch failure skip skip the current patch abort restore the original branch and abort the patching operation. -rebasing (internal use for git-rebase)" +committer-date-is-author-date lie about committer date +ignore-date use current timestamp for author date +rebasing* (internal use for git-rebase)" . git-sh-setup prefix=$(git rev-parse --show-prefix) @@@ -41,17 -33,6 +41,17 @@@ cd_to_topleve git var GIT_COMMITTER_IDENT >/dev/null || die "You need to set your committer info first" +if git rev-parse --verify -q HEAD >/dev/null +then + HAS_HEAD=yes +else + HAS_HEAD= +fi + +sq () { + git rev-parse --sq-quote "$@" +} + stop_here () { echo "$1" >"$dotest/next" exit 1 @@@ -104,7 -85,7 +104,7 @@@ fall_back_3way () git write-tree >"$dotest/patch-merge-base+" || cannot_fallback "Repository lacks necessary blobs to fall back on 3-way merge." - echo Using index info to reconstruct a base tree... + say Using index info to reconstruct a base tree... if GIT_INDEX_FILE="$dotest/patch-merge-tmp-index" \ git apply --cached <"$dotest/patch" then @@@ -120,7 -101,7 +120,7 @@@ It does not apply to blobs recorded in orig_tree=$(cat "$dotest/patch-merge-base") && rm -fr "$dotest"/patch-merge-* || exit 1 - echo Falling back to patching base and 3-way merge... + say Falling back to patching base and 3-way merge... # This is not so wrong. Depending on which base we picked, # orig_tree may be wildly different from ours, but his_tree @@@ -130,10 -111,6 +130,10 @@@ eval GITHEAD_$his_tree='"$FIRSTLINE"' export GITHEAD_$his_tree + if test -n "$GIT_QUIET" + then + export GIT_MERGE_VERBOSITY=0 + fi git-merge-recursive $orig_tree -- HEAD $his_tree || { git rerere echo Failed to merge in the changes. @@@ -142,157 -119,11 +142,157 @@@ unset GITHEAD_$his_tree } +clean_abort () { + test $# = 0 || echo >&2 "$@" + rm -fr "$dotest" + exit 1 +} + +patch_format= + +check_patch_format () { + # early return if patch_format was set from the command line + if test -n "$patch_format" + then + return 0 + fi + + # we default to mbox format if input is from stdin and for + # directories + if test $# = 0 || test "x$1" = "x-" || test -d "$1" + then + patch_format=mbox + return 0 + fi + + # otherwise, check the first few lines of the first patch to try + # to detect its format + { + read l1 + read l2 + read l3 + case "$l1" in + "From "* | "From: "*) + patch_format=mbox + ;; + '# This series applies on GIT commit'*) + patch_format=stgit-series + ;; + "# HG changeset patch") + patch_format=hg + ;; + *) + # if the second line is empty and the third is + # a From, Author or Date entry, this is very + # likely an StGIT patch + case "$l2,$l3" in + ,"From: "* | ,"Author: "* | ,"Date: "*) + patch_format=stgit + ;; + *) + ;; + esac + ;; + esac + if test -z "$patch_format" && + test -n "$l1" && + test -n "$l2" && + test -n "$l3" + then + # This begins with three non-empty lines. Is this a + # piece of e-mail a-la RFC2822? Grab all the headers, + # discarding the indented remainder of folded lines, + # and see if it looks like that they all begin with the + # header field names... + sed -n -e '/^$/q' -e '/^[ ]/d' -e p "$1" | + sane_egrep -v '^[!-9;-~]+:' >/dev/null || + patch_format=mbox + fi + } < "$1" || clean_abort +} + +split_patches () { + case "$patch_format" in + mbox) + case "$rebasing" in + '') + keep_cr= ;; + ?*) + keep_cr=--keep-cr ;; + esac + git mailsplit -d"$prec" -o"$dotest" -b $keep_cr -- "$@" > "$dotest/last" || + clean_abort + ;; + stgit-series) + if test $# -ne 1 + then + clean_abort "Only one StGIT patch series can be applied at once" + fi + series_dir=`dirname "$1"` + series_file="$1" + shift + { + set x + while read filename + do + set "$@" "$series_dir/$filename" + done + # remove the safety x + shift + # remove the arg coming from the first-line comment + shift + } < "$series_file" || clean_abort + # set the patch format appropriately + patch_format=stgit + # now handle the actual StGIT patches + split_patches "$@" + ;; + stgit) + this=0 + for stgit in "$@" + do + this=`expr "$this" + 1` + msgnum=`printf "%0${prec}d" $this` + # Perl version of StGIT parse_patch. The first nonemptyline + # not starting with Author, From or Date is the + # subject, and the body starts with the next nonempty + # line not starting with Author, From or Date + perl -ne 'BEGIN { $subject = 0 } + if ($subject > 1) { print ; } + elsif (/^\s+$/) { next ; } + elsif (/^Author:/) { print s/Author/From/ ; } + elsif (/^(From|Date)/) { print ; } + elsif ($subject) { + $subject = 2 ; + print "\n" ; + print ; + } else { + print "Subject: ", $_ ; + $subject = 1; + } + ' < "$stgit" > "$dotest/$msgnum" || clean_abort + done + echo "$this" > "$dotest/last" + this= + msgnum= + ;; + *) + if test -n "$parse_patch" ; then + clean_abort "Patch format $patch_format is not supported." + else + clean_abort "Patch format detection failed." + fi + ;; + esac +} + prec=4 dotest="$GIT_DIR/rebase-apply" sign= utf8=t keep= skip= interactive= resolved= rebasing= abort= -resolvemsg= resume= +resolvemsg= resume= scissors= no_inbody_headers= git_apply_opt= +committer_date_is_author_date= +ignore_date= while test $# != 0 do @@@ -311,10 -142,6 +311,10 @@@ utf8= ;; -k|--keep) keep=t ;; + -c|--scissors) + scissors=t ;; + --no-scissors) + scissors=f ;; -r|--resolved) resolved=t ;; --skip) @@@ -322,26 -149,16 +322,26 @@@ --abort) abort=t ;; --rebasing) - rebasing=t threeway=t keep=t ;; + rebasing=t threeway=t keep=t scissors=f no_inbody_headers=t ;; -d|--dotest) die "-d option is no longer supported. Do not use." ;; --resolvemsg) shift; resolvemsg=$1 ;; - --whitespace) - git_apply_opt="$git_apply_opt $1=$2"; shift ;; + --whitespace|--directory) + git_apply_opt="$git_apply_opt $(sq "$1=$2")"; shift ;; -C|-p) - git_apply_opt="$git_apply_opt $1$2"; shift ;; + git_apply_opt="$git_apply_opt $(sq "$1$2")"; shift ;; + --patch-format) + shift ; patch_format="$1" ;; + --reject|--ignore-whitespace|--ignore-space-change) + git_apply_opt="$git_apply_opt $1" ;; + --committer-date-is-author-date) + committer_date_is_author_date=t ;; + --ignore-date) + ignore_date=t ;; + -q|--quiet) + GIT_QUIET=t ;; --) shift; break ;; *) @@@ -375,7 -192,7 +375,7 @@@ the # unreliable -- stdin could be /dev/null for example # and the caller did not intend to feed us a patch but # wanted to continue unattended. - tty -s + test -t 0 ;; *) false @@@ -385,9 -202,6 +385,9 @@@ resume=yes case "$skip,$abort" in + t,t) + die "Please make up your mind. --skip or --abort?" + ;; t,) git rerere clear git read-tree --reset -u HEAD HEAD @@@ -396,19 -210,12 +396,19 @@@ git update-ref ORIG_HEAD $orig_head ;; ,t) + if test -f "$dotest/rebasing" + then + exec git rebase --abort + fi git rerere clear - git read-tree --reset -u HEAD ORIG_HEAD - git reset ORIG_HEAD + test -f "$dotest/dirtyindex" || { + git read-tree --reset -u HEAD ORIG_HEAD + git reset ORIG_HEAD + } rm -fr "$dotest" exit ;; esac + rm -f "$dotest/dirtyindex" else # Make sure we are not given --skip, --resolved, nor --abort test "$skip$resolved$abort" = "" || @@@ -435,48 -242,34 +435,48 @@@ done shift fi - git mailsplit -d"$prec" -o"$dotest" -b -- "$@" > "$dotest/last" || { - rm -fr "$dotest" - exit 1 - } - # -s, -u, -k and --whitespace flags are kept for the - # resuming session after a patch failure. - # -3 and -i can and must be given when resuming. - echo " $ws" >"$dotest/whitespace" + check_patch_format "$@" + + split_patches "$@" + + # -i can and must be given when resuming; everything + # else is kept + echo " $git_apply_opt" >"$dotest/apply-opt" + echo "$threeway" >"$dotest/threeway" echo "$sign" >"$dotest/sign" echo "$utf8" >"$dotest/utf8" echo "$keep" >"$dotest/keep" + echo "$scissors" >"$dotest/scissors" + echo "$no_inbody_headers" >"$dotest/no_inbody_headers" + echo "$GIT_QUIET" >"$dotest/quiet" echo 1 >"$dotest/next" if test -n "$rebasing" then : >"$dotest/rebasing" else : >"$dotest/applying" - git update-ref ORIG_HEAD HEAD + if test -n "$HAS_HEAD" + then + git update-ref ORIG_HEAD HEAD + else + git update-ref -d ORIG_HEAD >/dev/null 2>&1 + fi fi fi case "$resolved" in '') - files=$(git diff-index --cached --name-only HEAD --) || exit - if [ "$files" ]; then - echo "Dirty index: cannot apply patches (dirty: $files)" >&2 - exit 1 + case "$HAS_HEAD" in + '') + files=$(git ls-files) ;; + ?*) + files=$(git diff-index --cached --name-only HEAD --) ;; + esac || exit + if test "$files" + then + test -n "$HAS_HEAD" && : >"$dotest/dirtyindex" + die "Dirty index: cannot apply patches (dirty: $files)" fi esac @@@ -490,27 -283,7 +490,27 @@@ if test "$(cat "$dotest/keep")" = then keep=-k fi -ws=`cat "$dotest/whitespace"` +case "$(cat "$dotest/scissors")" in +t) + scissors=--scissors ;; +f) + scissors=--no-scissors ;; +esac +if test "$(cat "$dotest/no_inbody_headers")" = t +then + no_inbody_headers=--no-inbody-headers +else + no_inbody_headers= +fi +if test "$(cat "$dotest/quiet")" = t +then + GIT_QUIET=t +fi +if test "$(cat "$dotest/threeway")" = t +then + threeway=t +fi +git_apply_opt=$(cat "$dotest/apply-opt") if test "$(cat "$dotest/sign")" = t then SIGNOFF=`git var GIT_COMMITTER_IDENT | sed -e ' @@@ -531,7 -304,7 +531,7 @@@ f if test "$this" -gt "$last" then - echo Nothing to do. + say Nothing to do. rm -fr "$dotest" exit fi @@@ -556,12 -329,12 +556,12 @@@ d # by the user, or the user can tell us to do so by --resolved flag. case "$resume" in '') - git mailinfo $keep $utf8 "$dotest/msg" "$dotest/patch" \ + git mailinfo $keep $no_inbody_headers $scissors $utf8 "$dotest/msg" "$dotest/patch" \ <"$dotest/$msgnum" >"$dotest/info" || stop_here $this # skip pine's internal folder data - grep '^Author: Mail System Internal Data$' \ + sane_grep '^Author: Mail System Internal Data$' \ <"$dotest"/info >/dev/null && go_next && continue @@@ -577,11 -350,12 +577,12 @@@ git cat-file commit "$commit" | sed -e '1,/^$/d' >"$dotest/msg-clean" else - SUBJECT="$(sed -n '/^Subject/ s/Subject: //p' "$dotest/info")" - case "$keep_subject" in -k) SUBJECT="[PATCH] $SUBJECT" ;; esac - - (printf '%s\n\n' "$SUBJECT"; cat "$dotest/msg") | - git stripspace > "$dotest/msg-clean" + { + sed -n '/^Subject/ s/Subject: //p' "$dotest/info" + echo + cat "$dotest/msg" + } | + git stripspace > "$dotest/msg-clean" fi ;; esac @@@ -677,18 -451,11 +678,18 @@@ stop_here $this fi - printf 'Applying: %s\n' "$FIRSTLINE" + say "Applying: $FIRSTLINE" case "$resolved" in '') - git apply $git_apply_opt --index "$dotest/patch" + # When we are allowed to fall back to 3-way later, don't give + # false errors during the initial attempt. + squelch= + if test "$threeway" = t + then + squelch='>/dev/null 2>&1 ' + fi + eval "git apply $squelch$git_apply_opt"' --index "$dotest/patch"' apply_status=$? ;; t) @@@ -720,7 -487,7 +721,7 @@@ # Applying the patch to an earlier tree and merging the # result may have produced the same tree as ours. git diff-index --quiet --cached HEAD -- && { - echo No changes -- Patch already applied. + say No changes -- Patch already applied. go_next continue } @@@ -730,7 -497,7 +731,7 @@@ fi if test $apply_status != 0 then - echo Patch failed at $msgnum. + printf 'Patch failed at %s %s\n' "$msgnum" "$FIRSTLINE" stop_here_user_resolve $this fi @@@ -740,21 -507,8 +741,21 @@@ fi tree=$(git write-tree) && - parent=$(git rev-parse --verify HEAD) && - commit=$(git commit-tree $tree -p $parent <"$dotest/final-commit") && + commit=$( + if test -n "$ignore_date" + then + GIT_AUTHOR_DATE= + fi + parent=$(git rev-parse --verify -q HEAD) || + say >&2 "applying to an empty history" + + if test -n "$committer_date_is_author_date" + then + GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE" + export GIT_COMMITTER_DATE + fi && + git commit-tree $tree ${parent:+-p} $parent <"$dotest/final-commit" + ) && git update-ref -m "$GIT_REFLOG_ACTION: $FIRSTLINE" HEAD $commit $parent || stop_here $this