]> git.ipfire.org Git - thirdparty/git.git/blame - git-applypatch.sh
Use symbolic name SHORT_NAME_AMBIGUOUS as error return value
[thirdparty/git.git] / git-applypatch.sh
CommitLineData
853916ff
LT
1#!/bin/sh
2##
3## applypatch takes four file arguments, and uses those to
4## apply the unpacked patch (surprise surprise) that they
5## represent to the current tree.
6##
7## The arguments are:
8## $1 - file with commit message
9## $2 - file with the actual patch
a196d8d4
LT
10## $3 - "info" file with Author, email and subject
11## $4 - optional file containing signoff to add
853916ff 12##
6cf6193b
FK
13
14USAGE='<msg> <patch> <info> [<signoff>]'
ae2b0f15 15. git-sh-setup
4426ac70 16
c6f60f99 17case "$#" in 3|4) ;; *) usage ;; esac
6cf6193b 18
ad4e9ce4
JB
19final=.dotest/final-commit
20##
21## If this file exists, we ask before applying
22##
23query_apply=.dotest/.query_apply
4426ac70
JH
24
25## We do not munge the first line of the commit message too much
26## if this file exists.
6bff6a60 27keep_subject=.dotest/.keep_subject
4426ac70 28
47f0b6d5
JH
29## We do not attempt the 3-way merge fallback unless this file exists.
30fall_back_3way=.dotest/.3way
4426ac70 31
853916ff
LT
32MSGFILE=$1
33PATCHFILE=$2
a196d8d4 34INFO=$3
4426ac70
JH
35SIGNOFF=$4
36EDIT=${VISUAL:-${EDITOR:-vi}}
ad4e9ce4 37
a567d315
JH
38export GIT_AUTHOR_NAME="$(sed -n '/^Author/ s/Author: //p' "$INFO")"
39export GIT_AUTHOR_EMAIL="$(sed -n '/^Email/ s/Email: //p' "$INFO")"
40export GIT_AUTHOR_DATE="$(sed -n '/^Date/ s/Date: //p' "$INFO")"
41export SUBJECT="$(sed -n '/^Subject/ s/Subject: //p' "$INFO")"
853916ff 42
4426ac70
JH
43if test '' != "$SIGNOFF"
44then
45 if test -f "$SIGNOFF"
46 then
47 SIGNOFF=`cat "$SIGNOFF"` || exit
48 elif case "$SIGNOFF" in yes | true | me | please) : ;; *) false ;; esac
49 then
50 SIGNOFF=`git-var GIT_COMMITTER_IDENT | sed -e '
51 s/>.*/>/
52 s/^/Signed-off-by: /'
53 `
54 else
55 SIGNOFF=
56 fi
57 if test '' != "$SIGNOFF"
58 then
59 LAST_SIGNED_OFF_BY=`
60 sed -ne '/^Signed-off-by: /p' "$MSGFILE" |
61 tail -n 1
62 `
a567d315
JH
63 test "$LAST_SIGNED_OFF_BY" = "$SIGNOFF" || {
64 test '' = "$LAST_SIGNED_OFF_BY" && echo
65 echo "$SIGNOFF"
66 } >>"$MSGFILE"
4426ac70 67 fi
ad4e9ce4 68fi
4426ac70 69
6bff6a60
JH
70patch_header=
71test -f "$keep_subject" || patch_header='[PATCH] '
ad4e9ce4 72
4426ac70
JH
73{
74 echo "$patch_header$SUBJECT"
75 if test -s "$MSGFILE"
76 then
77 echo
78 cat "$MSGFILE"
79 fi
80} >"$final"
ad4e9ce4 81
4426ac70
JH
82interactive=yes
83test -f "$query_apply" || interactive=no
ad4e9ce4 84
4426ac70 85while [ "$interactive" = yes ]; do
ad4e9ce4
JB
86 echo "Commit Body is:"
87 echo "--------------------------"
4426ac70 88 cat "$final"
ad4e9ce4 89 echo "--------------------------"
9754563c 90 printf "Apply? [y]es/[n]o/[e]dit/[a]ccept all "
ad4e9ce4 91 read reply
4426ac70
JH
92 case "$reply" in
93 y|Y) interactive=no;;
ad4e9ce4 94 n|N) exit 2;; # special value to tell dotest to keep going
4426ac70
JH
95 e|E) "$EDIT" "$final";;
96 a|A) rm -f "$query_apply"
97 interactive=no ;;
ad4e9ce4
JB
98 esac
99done
100
4426ac70
JH
101if test -x "$GIT_DIR"/hooks/applypatch-msg
102then
103 "$GIT_DIR"/hooks/applypatch-msg "$final" || exit
104fi
105
853916ff 106echo
61096819 107echo Applying "'$SUBJECT'"
853916ff
LT
108echo
109
a567d315 110git-apply --index "$PATCHFILE" || {
47f0b6d5
JH
111
112 # git-apply exits with status 1 when the patch does not apply,
113 # but it die()s with other failures, most notably upon corrupt
114 # patch. In the latter case, there is no point to try applying
115 # it to another tree and do 3-way merge.
116 test $? = 1 || exit 1
117
118 test -f "$fall_back_3way" || exit 1
119
a567d315
JH
120 # Here if we know which revision the patch applies to,
121 # we create a temporary working tree and index, apply the
122 # patch, and attempt 3-way merge with the resulting tree.
47f0b6d5
JH
123
124 O_OBJECT=`cd "$GIT_OBJECT_DIRECTORY" && pwd`
125 rm -fr .patch-merge-*
126
bf3e2748
JH
127 if git-apply -z --index-info "$PATCHFILE" \
128 >.patch-merge-index-info 2>/dev/null &&
129 GIT_INDEX_FILE=.patch-merge-tmp-index \
130 git-update-index -z --index-info <.patch-merge-index-info &&
131 GIT_INDEX_FILE=.patch-merge-tmp-index \
132 git-write-tree >.patch-merge-tmp-base &&
133 (
134 mkdir .patch-merge-tmp-dir &&
135 cd .patch-merge-tmp-dir &&
136 GIT_INDEX_FILE="../.patch-merge-tmp-index" \
137 GIT_OBJECT_DIRECTORY="$O_OBJECT" \
138 git-apply $binary --index
139 ) <"$PATCHFILE"
140 then
141 echo Using index info to reconstruct a base tree...
142 mv .patch-merge-tmp-base .patch-merge-base
143 mv .patch-merge-tmp-index .patch-merge-index
144 else
47f0b6d5
JH
145 (
146 N=10
147
bf3e2748
JH
148 # Otherwise, try nearby trees that can be used to apply the
149 # patch.
47f0b6d5
JH
150 git-rev-list --max-count=$N HEAD
151
152 # or hoping the patch is against known tags...
153 git-ls-remote --tags .
154 ) |
bf3e2748
JH
155 while read base junk
156 do
47f0b6d5
JH
157 # Try it if we have it as a tree.
158 git-cat-file tree "$base" >/dev/null 2>&1 || continue
159
160 rm -fr .patch-merge-tmp-* &&
161 mkdir .patch-merge-tmp-dir || break
162 (
163 cd .patch-merge-tmp-dir &&
164 GIT_INDEX_FILE=../.patch-merge-tmp-index &&
165 GIT_OBJECT_DIRECTORY="$O_OBJECT" &&
166 export GIT_INDEX_FILE GIT_OBJECT_DIRECTORY &&
167 git-read-tree "$base" &&
168 git-apply --index &&
169 mv ../.patch-merge-tmp-index ../.patch-merge-index &&
170 echo "$base" >../.patch-merge-base
171 ) <"$PATCHFILE" 2>/dev/null && break
bf3e2748
JH
172 done
173 fi
47f0b6d5
JH
174
175 test -f .patch-merge-index &&
176 his_tree=$(GIT_INDEX_FILE=.patch-merge-index git-write-tree) &&
177 orig_tree=$(cat .patch-merge-base) &&
178 rm -fr .patch-merge-* || exit 1
179
180 echo Falling back to patching base and 3-way merge using $orig_tree...
181
182 # This is not so wrong. Depending on which base we picked,
183 # orig_tree may be wildly different from ours, but his_tree
184 # has the same set of wildly different changes in parts the
185 # patch did not touch, so resolve ends up cancelling them,
186 # saying that we reverted all those changes.
187
188 if git-merge-resolve $orig_tree -- HEAD $his_tree
189 then
190 echo Done.
191 else
192 echo Failed to merge in the changes.
193 exit 1
194 fi
a567d315 195}
4426ac70
JH
196
197if test -x "$GIT_DIR"/hooks/pre-applypatch
198then
199 "$GIT_DIR"/hooks/pre-applypatch || exit
200fi
201
50eb31d1 202tree=$(git-write-tree) || exit 1
853916ff 203echo Wrote tree $tree
bf7960eb
JH
204parent=$(git-rev-parse --verify HEAD) &&
205commit=$(git-commit-tree $tree -p $parent <"$final") || exit 1
853916ff 206echo Committed: $commit
bf7960eb 207git-update-ref HEAD $commit $parent || exit
4426ac70
JH
208
209if test -x "$GIT_DIR"/hooks/post-applypatch
210then
211 "$GIT_DIR"/hooks/post-applypatch
212fi