Merge branch 'seq-builtin-dev' into mymaster
[git/sbeyer.git] / git-am.sh
blobd2ce616bedf33ec473e15014f15c292c2f62ed59
1 #!/bin/sh
3 # Copyright (c) 2005, 2006 Junio C Hamano
5 SUBDIRECTORY_OK=Yes
6 OPTIONS_KEEPDASHDASH=
7 OPTIONS_SPEC="\
8 git am [options] [<mbox>|<Maildir>...]
9 git am [options] (--resolved | --skip | --abort)
11 i,interactive run interactively
12 b,binary* (historical option -- no-op)
13 3,3way allow fall back on 3way merging if needed
14 q,quiet be quiet
15 s,signoff add a Signed-off-by line to the commit message
16 u,utf8 recode into utf8 (default)
17 k,keep pass -k flag to git-mailinfo
18 whitespace= pass it through git-apply
19 directory= pass it through git-apply
20 C= pass it through git-apply
21 p= pass it through git-apply
22 patch-format= format the patch(es) are in
23 reject pass it through git-apply
24 resolvemsg= override error message when patch failure occurs
25 r,resolved to be used after a patch failure
26 skip skip the current patch
27 abort restore the original branch and abort the patching operation.
28 committer-date-is-author-date lie about committer date
29 ignore-date use current timestamp for author date
30 rebasing* (internal use for git-rebase)"
32 . git-sh-setup
33 prefix=$(git rev-parse --show-prefix)
34 set_reflog_action am
35 require_work_tree
36 cd_to_toplevel
38 git var GIT_COMMITTER_IDENT >/dev/null ||
39 die "You need to set your committer info first"
41 cleanup () {
42 git gc --auto
43 rm -fr "$dotest"
46 die_abort () {
47 cleanup
48 die "$1"
51 stop_here_user_resolve () {
52 if [ -n "$resolvemsg" ]; then
53 printf '%s\n' "$resolvemsg"
54 exit 1
56 cmdline="git am"
57 if test '' != "$interactive"
58 then
59 cmdline="$cmdline -i"
61 if test '' != "$threeway"
62 then
63 cmdline="$cmdline -3"
65 echo "When you have resolved this problem run \"$cmdline --resolved\"."
66 echo "If you would prefer to skip this patch, instead run \"$cmdline --skip\"."
67 echo "To restore the original branch and stop patching run \"$cmdline --abort\"."
69 exit 1
73 be_interactive () {
74 msg="$GIT_DIR/sequencer/message"
75 patch="$GIT_DIR/sequencer/patch"
76 # we rely on sequencer here
78 test -t 0 ||
79 die "cannot be interactive without stdin connected to a terminal."
80 action=$(cat "$dotest/interactive")
81 while test "$action" = again
83 echo
84 echo "Commit Body is:"
85 echo "--------------------------"
86 cat "$msg"
87 echo "--------------------------"
88 if test -z "$1"
89 then
90 printf "Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all "
91 else
92 echo 'Patch does not apply cleanly!'
93 printf "Apply+fix? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all "
96 read reply
97 case "$reply" in
98 [yY]*)
99 return 0
101 [nN]*)
102 # pretend we never tried to apply
103 to=HEAD
104 test conflict = "$1" ||
105 to=HEAD^
106 git read-tree -m -u HEAD $to
107 git reset -q $to >/dev/null
108 return 1
110 [eE]*)
111 git_editor "$msg"
112 git commit --amend --file="$msg" --no-verify >/dev/null
114 [vV]*)
115 LESS=-S ${PAGER:-less} "$patch"
117 [aA]*)
118 echo 'accept' >"$dotest/interactive"
119 return 0
124 esac
125 done
126 test "$action" = accept &&
127 sed -n -e '1s/^/Applying &/p' <"$msg"
128 return 0
131 run_sequencer () {
132 output=$(git sequencer $seqopts \
133 --caller='git am|--abort|--resolved|--skip' "$@")
134 ret=$?
135 test -z "$output" || printf '%s\n' "$output"
136 # we want this "printf" stuff to suppress sequencer's
137 # "Sequencing..." messages
138 case "$ret" in
140 cleanup
141 exit 0
143 2|3)
144 stop_here_user_resolve
147 die_abort 'git-sequencer died unexpected. Aborting.'
149 esac
152 run_sequencer_i () {
153 command="$1"
154 while true
156 output=$(git sequencer $seqopts \
157 --caller='git am -i|--abort|--resolved|--skip' \
158 $command 2>&1)
159 case "$?" in
161 cleanup
162 exit 0
165 if test -f "$dotest/conflict"
166 then
167 rm "$dotest/conflict"
168 else
169 be_interactive
173 : >"$dotest/conflict"
174 be_interactive conflict
175 if test $? -eq 0
176 then
177 printf '%s\n' "$output" 1>&2
178 stop_here_user_resolve
182 die_abort "$output"
184 esac
185 seqopts=
186 command=--continue
187 done
190 escape_double_quotes () {
191 printf %s "$*" | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g'
194 clean_abort () {
195 test $# = 0 || echo >&2 "$@"
196 rm -fr "$dotest"
197 exit 1
200 patch_format=
202 check_patch_format () {
203 # early return if patch_format was set from the command line
204 if test -n "$patch_format"
205 then
206 return 0
209 # we default to mbox format if input is from stdin and for
210 # directories
211 if test $# = 0 || test "x$1" = "x-" || test -d "$1"
212 then
213 patch_format=mbox
214 return 0
217 # otherwise, check the first few lines of the first patch to try
218 # to detect its format
220 read l1
221 read l2
222 read l3
223 case "$l1" in
224 "From "* | "From: "*)
225 patch_format=mbox
227 '# This series applies on GIT commit'*)
228 patch_format=stgit-series
230 "# HG changeset patch")
231 patch_format=hg
234 # if the second line is empty and the third is
235 # a From, Author or Date entry, this is very
236 # likely an StGIT patch
237 case "$l2,$l3" in
238 ,"From: "* | ,"Author: "* | ,"Date: "*)
239 patch_format=stgit
243 esac
245 esac
246 } < "$1" || clean_abort
249 split_patches () {
250 case "$patch_format" in
251 mbox)
252 git mailsplit -d"$prec" -o"$dotest" -b -- "$@" > "$dotest/last" ||
253 clean_abort
255 stgit-series)
256 if test $# -ne 1
257 then
258 clean_abort "Only one StGIT patch series can be applied at once"
260 series_dir=`dirname "$1"`
261 series_file="$1"
262 shift
264 set x
265 while read filename
267 set "$@" "$series_dir/$filename"
268 done
269 # remove the safety x
270 shift
271 # remove the arg coming from the first-line comment
272 shift
273 } < "$series_file" || clean_abort
274 # set the patch format appropriately
275 patch_format=stgit
276 # now handle the actual StGIT patches
277 split_patches "$@"
279 stgit)
280 this=0
281 for stgit in "$@"
283 this=`expr "$this" + 1`
284 msgnum=`printf "%0${prec}d" $this`
285 # Perl version of StGIT parse_patch. The first nonemptyline
286 # not starting with Author, From or Date is the
287 # subject, and the body starts with the next nonempty
288 # line not starting with Author, From or Date
289 perl -ne 'BEGIN { $subject = 0 }
290 if ($subject > 1) { print ; }
291 elsif (/^\s+$/) { next ; }
292 elsif (/^Author:/) { print s/Author/From/ ; }
293 elsif (/^(From|Date)/) { print ; }
294 elsif ($subject) {
295 $subject = 2 ;
296 print "\n" ;
297 print ;
298 } else {
299 print "Subject: ", $_ ;
300 $subject = 1;
302 ' < "$stgit" > "$dotest/$msgnum" || clean_abort
303 done
304 echo "$this" > "$dotest/last"
305 this=
306 msgnum=
309 clean_abort "Patch format $patch_format is not supported."
311 esac
314 prec=4
315 dotest="$GIT_DIR/rebase-apply"
316 todofile="$dotest/todo"
317 sign= utf8=t keep= skip= interactive= resolved= rebasing= abort=
318 resolvemsg=
319 opts=
320 committer_date_is_author_date=
321 ignore_date=
323 while test $# != 0
325 case "$1" in
326 -i|--interactive)
327 interactive=_i ;;
328 -b|--binary)
329 : ;;
330 -3|--3way)
331 threeway=t ;;
332 -s|--signoff)
333 sign=t ;;
334 -u|--utf8)
335 utf8=t ;; # this is now default
336 --no-utf8)
337 utf8= ;;
338 -k|--keep)
339 keep=t ;;
340 -r|--resolved)
341 resolved=t ;;
342 --skip)
343 skip=t ;;
344 --abort)
345 abort=t ;;
346 --rebasing)
347 rebasing=t threeway=t keep=t ;;
348 -d|--dotest)
349 die "-d option is no longer supported. Do not use."
351 --resolvemsg)
352 shift; resolvemsg=$1 ;;
353 --whitespace|--directory)
354 opts="$opts $1=\"$(escape_double_quotes $2)\""; shift ;;
356 opts="$opts --context=$2" ; shift ;;
358 opts="$opts $1$2"; shift ;;
359 --patch-format)
360 shift ; patch_format="$1" ;;
361 --reject)
362 opts="$opts $1" ;;
363 --committer-date-is-author-date)
364 committer_date_is_author_date=t ;;
365 --ignore-date)
366 ignore_date=t ;;
367 -q|--quiet)
368 GIT_QUIET=--quiet ;;
370 shift; break ;;
372 usage ;;
373 esac
374 shift
375 done
377 if test -d "$dotest"
378 then
379 test "$#" != 0 &&
380 die "previous rebase directory $dotest still exists but mbox given."
382 test -f "$dotest/interactive" &&
383 interactive=_i action=$(cat "$dotest/interactive")
385 case "$skip,$abort,$resolved" in
386 t*t*)
387 die "Please make up your mind. --skip, --resolved or --abort?"
389 t,,)
390 run_sequencer$interactive --skip
392 ,t,)
393 run_sequencer$interactive --abort
395 ,,t)
396 run_sequencer$interactive --continue
399 # No file input but without resume parameters; catch
400 # user error to feed us a patch from standard input
401 # when there is already $dotest. This is somewhat
402 # unreliable -- stdin could be /dev/null for example
403 # and the caller did not intend to feed us a patch but
404 # wanted to continue unattended.
405 tty -s
407 esac
409 die "$dotest still exists. Use git am --abort/--skip/--resolved."
412 # Make sure we are not given --skip, --resolved, nor --abort
413 test -z "$abort$resolved$skip" ||
414 die 'git-am is not in progress. You cannot use --abort/--skip/--resolved then.'
416 # sequencer running?
417 git sequencer --status >/dev/null 2>&1 &&
418 die "Sequencer already started. Cannot run git-am."
420 # Start afresh.
421 mkdir -p "$dotest" ||
422 die "Could not create $dotest directory."
424 if test -n "$prefix" && test $# != 0
425 then
426 first=t
427 for arg
429 test -n "$first" && {
430 set x
431 first=
433 case "$arg" in
435 set "$@" "$arg" ;;
437 set "$@" "$prefix$arg" ;;
438 esac
439 done
440 shift
442 last=$(git mailsplit -d"$prec" -o"$dotest" -b -- "$@") || {
443 cleanup
444 exit 1
446 this=1
448 files=$(git diff-index --cached --name-only HEAD --) || exit
449 if [ "$files" ]; then
450 echo "Dirty index: cannot apply patches (dirty: $files)" >&2
451 exit 1
454 test -n "$interactive" && echo 'again' >"$dotest/interactive"
456 # converting our options to git-sequencer file insn options
457 test -n "$utf8" || opts="$opts -n"
458 test -n "$keep" && opts="$opts -k"
459 test -n "$sign" && opts="$opts --signoff"
460 test -n "$threeway" && opts="$opts -3"
462 # these files are created for tab completion scripts
463 if test -n "$rebasing"
464 then
465 : >"$dotest/rebasing"
466 else
467 : >"$dotest/applying"
468 git update-ref ORIG_HEAD HEAD
471 # create todofile
472 : > "$todofile" ||
473 die_abort "Cannot create $todofile"
474 while test "$this" -le "$last"
476 msgnum=$(printf "%0${prec}d" $this)
477 this=$(($this+1))
479 # This ignores every mail that does not contain a patch.
480 grep '^diff' "$dotest/$msgnum" >/dev/null ||
481 continue
483 extra=
484 test -n "$rebasing" &&
485 commit=$(sed -e 's/^From \([0-9a-f]*\) .*/\1/' \
486 -e q "$dotest/$msgnum") &&
487 test "$(git cat-file -t "$commit")" = commit &&
488 extra=" -C $commit"
490 subject=$(sed -n '1,/^Subject:/s/Subject: *\(\[.*\]\)\{0,1\} *//p' \
491 <"$dotest/$msgnum")
492 test -n "$GIT_QUIET" -o -n "$interactive" ||
493 printf 'run -- printf "Applying: %%s\\\\n" "%s"\n' \
494 "$(escape_double_quotes "$subject")" >>"$todofile"
495 printf 'patch%s%s "%s" # %s\n' "$opts" "$extra" \
496 "$(escape_double_quotes "$dotest/$msgnum")" \
497 "$subject" >>"$todofile"
498 test -z "$interactive" || echo 'pause' >>"$todofile"
499 done
501 seqopts="--no-advice --allow-dirty"
502 run_sequencer$interactive $GIT_QUIET "$todofile"