 c6f60f991f
			
		
	
	c6f60f991f
	
	
	
		
			
			Sorry, I broke this command completely with the stupid typo. Noticed by Marco Costalba. Signed-off-by: Junio C Hamano <junkio@cox.net>
		
			
				
	
	
		
			213 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			213 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
| #!/bin/sh
 | |
| ##
 | |
| ## applypatch takes four file arguments, and uses those to
 | |
| ## apply the unpacked patch (surprise surprise) that they
 | |
| ## represent to the current tree.
 | |
| ##
 | |
| ## The arguments are:
 | |
| ##	$1 - file with commit message
 | |
| ##	$2 - file with the actual patch
 | |
| ##	$3 - "info" file with Author, email and subject
 | |
| ##	$4 - optional file containing signoff to add
 | |
| ##
 | |
| 
 | |
| USAGE='<msg> <patch> <info> [<signoff>]'
 | |
| . git-sh-setup
 | |
| 
 | |
| case "$#" in 3|4) ;; *) usage ;; esac
 | |
| 
 | |
| final=.dotest/final-commit
 | |
| ##
 | |
| ## If this file exists, we ask before applying
 | |
| ##
 | |
| query_apply=.dotest/.query_apply
 | |
| 
 | |
| ## We do not munge the first line of the commit message too much
 | |
| ## if this file exists.
 | |
| keep_subject=.dotest/.keep_subject
 | |
| 
 | |
| ## We do not attempt the 3-way merge fallback unless this file exists.
 | |
| fall_back_3way=.dotest/.3way
 | |
| 
 | |
| MSGFILE=$1
 | |
| PATCHFILE=$2
 | |
| INFO=$3
 | |
| SIGNOFF=$4
 | |
| EDIT=${VISUAL:-${EDITOR:-vi}}
 | |
| 
 | |
| export GIT_AUTHOR_NAME="$(sed -n '/^Author/ s/Author: //p' "$INFO")"
 | |
| export GIT_AUTHOR_EMAIL="$(sed -n '/^Email/ s/Email: //p' "$INFO")"
 | |
| export GIT_AUTHOR_DATE="$(sed -n '/^Date/ s/Date: //p' "$INFO")"
 | |
| export SUBJECT="$(sed -n '/^Subject/ s/Subject: //p' "$INFO")"
 | |
| 
 | |
| if test '' != "$SIGNOFF"
 | |
| then
 | |
| 	if test -f "$SIGNOFF"
 | |
| 	then
 | |
| 		SIGNOFF=`cat "$SIGNOFF"` || exit
 | |
| 	elif case "$SIGNOFF" in yes | true | me | please) : ;; *) false ;; esac
 | |
| 	then
 | |
| 		SIGNOFF=`git-var GIT_COMMITTER_IDENT | sed -e '
 | |
| 				s/>.*/>/
 | |
| 				s/^/Signed-off-by: /'
 | |
| 		`
 | |
| 	else
 | |
| 		SIGNOFF=
 | |
| 	fi
 | |
| 	if test '' != "$SIGNOFF"
 | |
| 	then
 | |
| 		LAST_SIGNED_OFF_BY=`
 | |
| 			sed -ne '/^Signed-off-by: /p' "$MSGFILE" |
 | |
| 			tail -n 1
 | |
| 		`
 | |
| 		test "$LAST_SIGNED_OFF_BY" = "$SIGNOFF" || {
 | |
| 		    test '' = "$LAST_SIGNED_OFF_BY" && echo
 | |
| 		    echo "$SIGNOFF"
 | |
| 		} >>"$MSGFILE"
 | |
| 	fi
 | |
| fi
 | |
| 
 | |
| patch_header=
 | |
| test -f "$keep_subject" || patch_header='[PATCH] '
 | |
| 
 | |
| {
 | |
| 	echo "$patch_header$SUBJECT"
 | |
| 	if test -s "$MSGFILE"
 | |
| 	then
 | |
| 		echo
 | |
| 		cat "$MSGFILE"
 | |
| 	fi
 | |
| } >"$final"
 | |
| 
 | |
| interactive=yes
 | |
| test -f "$query_apply" || interactive=no
 | |
| 
 | |
| while [ "$interactive" = yes ]; do
 | |
| 	echo "Commit Body is:"
 | |
| 	echo "--------------------------"
 | |
| 	cat "$final"
 | |
| 	echo "--------------------------"
 | |
| 	printf "Apply? [y]es/[n]o/[e]dit/[a]ccept all "
 | |
| 	read reply
 | |
| 	case "$reply" in
 | |
| 		y|Y) interactive=no;;
 | |
| 		n|N) exit 2;;	# special value to tell dotest to keep going
 | |
| 		e|E) "$EDIT" "$final";;
 | |
| 		a|A) rm -f "$query_apply"
 | |
| 		     interactive=no ;;
 | |
| 	esac
 | |
| done
 | |
| 
 | |
| if test -x "$GIT_DIR"/hooks/applypatch-msg
 | |
| then
 | |
| 	"$GIT_DIR"/hooks/applypatch-msg "$final" || exit
 | |
| fi
 | |
| 
 | |
| echo
 | |
| echo Applying "'$SUBJECT'"
 | |
| echo
 | |
| 
 | |
| git-apply --index "$PATCHFILE" || {
 | |
| 
 | |
| 	# git-apply exits with status 1 when the patch does not apply,
 | |
| 	# but it die()s with other failures, most notably upon corrupt
 | |
| 	# patch.  In the latter case, there is no point to try applying
 | |
| 	# it to another tree and do 3-way merge.
 | |
| 	test $? = 1 || exit 1
 | |
| 
 | |
| 	test -f "$fall_back_3way" || exit 1
 | |
| 
 | |
| 	# Here if we know which revision the patch applies to,
 | |
| 	# we create a temporary working tree and index, apply the
 | |
| 	# patch, and attempt 3-way merge with the resulting tree.
 | |
| 
 | |
| 	O_OBJECT=`cd "$GIT_OBJECT_DIRECTORY" && pwd`
 | |
| 	rm -fr .patch-merge-*
 | |
| 
 | |
| 	if git-apply -z --index-info "$PATCHFILE" \
 | |
| 		>.patch-merge-index-info 2>/dev/null &&
 | |
| 		GIT_INDEX_FILE=.patch-merge-tmp-index \
 | |
| 		git-update-index -z --index-info <.patch-merge-index-info &&
 | |
| 		GIT_INDEX_FILE=.patch-merge-tmp-index \
 | |
| 		git-write-tree >.patch-merge-tmp-base &&
 | |
| 		(
 | |
| 			mkdir .patch-merge-tmp-dir &&
 | |
| 			cd .patch-merge-tmp-dir &&
 | |
| 			GIT_INDEX_FILE="../.patch-merge-tmp-index" \
 | |
| 			GIT_OBJECT_DIRECTORY="$O_OBJECT" \
 | |
| 			git-apply $binary --index
 | |
| 		) <"$PATCHFILE"
 | |
| 	then
 | |
| 		echo Using index info to reconstruct a base tree...
 | |
| 		mv .patch-merge-tmp-base .patch-merge-base
 | |
| 		mv .patch-merge-tmp-index .patch-merge-index
 | |
| 	else
 | |
| 	(
 | |
| 		N=10
 | |
| 
 | |
| 		# Otherwise, try nearby trees that can be used to apply the
 | |
| 		# patch.
 | |
| 		git-rev-list --max-count=$N HEAD
 | |
| 
 | |
| 		# or hoping the patch is against known tags...
 | |
| 		git-ls-remote --tags .
 | |
| 	) |
 | |
| 	    while read base junk
 | |
| 	    do
 | |
| 		# Try it if we have it as a tree.
 | |
| 		git-cat-file tree "$base" >/dev/null 2>&1 || continue
 | |
| 
 | |
| 		rm -fr .patch-merge-tmp-* &&
 | |
| 		mkdir .patch-merge-tmp-dir || break
 | |
| 		(
 | |
| 			cd .patch-merge-tmp-dir &&
 | |
| 			GIT_INDEX_FILE=../.patch-merge-tmp-index &&
 | |
| 			GIT_OBJECT_DIRECTORY="$O_OBJECT" &&
 | |
| 			export GIT_INDEX_FILE GIT_OBJECT_DIRECTORY &&
 | |
| 			git-read-tree "$base" &&
 | |
| 			git-apply --index &&
 | |
| 			mv ../.patch-merge-tmp-index ../.patch-merge-index &&
 | |
| 			echo "$base" >../.patch-merge-base
 | |
| 		) <"$PATCHFILE"  2>/dev/null && break
 | |
| 	    done
 | |
| 	fi
 | |
| 
 | |
| 	test -f .patch-merge-index &&
 | |
| 	his_tree=$(GIT_INDEX_FILE=.patch-merge-index git-write-tree) &&
 | |
| 	orig_tree=$(cat .patch-merge-base) &&
 | |
| 	rm -fr .patch-merge-* || exit 1
 | |
| 
 | |
| 	echo Falling back to patching base and 3-way merge using $orig_tree...
 | |
| 
 | |
| 	# This is not so wrong.  Depending on which base we picked,
 | |
| 	# orig_tree may be wildly different from ours, but his_tree
 | |
| 	# has the same set of wildly different changes in parts the
 | |
| 	# patch did not touch, so resolve ends up cancelling them,
 | |
| 	# saying that we reverted all those changes.
 | |
| 
 | |
| 	if git-merge-resolve $orig_tree -- HEAD $his_tree
 | |
| 	then
 | |
| 		echo Done.
 | |
| 	else
 | |
| 		echo Failed to merge in the changes.
 | |
| 		exit 1
 | |
| 	fi
 | |
| }
 | |
| 
 | |
| if test -x "$GIT_DIR"/hooks/pre-applypatch
 | |
| then
 | |
| 	"$GIT_DIR"/hooks/pre-applypatch || exit
 | |
| fi
 | |
| 
 | |
| tree=$(git-write-tree) || exit 1
 | |
| echo Wrote tree $tree
 | |
| parent=$(git-rev-parse --verify HEAD) &&
 | |
| commit=$(git-commit-tree $tree -p $parent <"$final") || exit 1
 | |
| echo Committed: $commit
 | |
| git-update-ref HEAD $commit $parent || exit
 | |
| 
 | |
| if test -x "$GIT_DIR"/hooks/post-applypatch
 | |
| then
 | |
| 	"$GIT_DIR"/hooks/post-applypatch
 | |
| fi
 |