1#!/bin/sh 2# 3# Copyright (c) 2005, 2006 Junio C Hamano 4 5SUBDIRECTORY_OK=Yes 6OPTIONS_KEEPDASHDASH= 7OPTIONS_SPEC="\ 8git am [options] [<mbox>|<Maildir>...] 9git am [options] (--resolved | --skip | --abort) 10-- 11i,interactive run interactively 12b,binary* (historical option -- no-op) 133,3way allow fall back on 3way merging if needed 14q,quiet be quiet 15s,signoff add a Signed-off-by line to the commit message 16u,utf8 recode into utf8 (default) 17k,keep pass -k flag to git-mailinfo 18whitespace= pass it through git-apply 19directory= pass it through git-apply 20C= pass it through git-apply 21p= pass it through git-apply 22reject pass it through git-apply 23resolvemsg= override error message when patch failure occurs 24r,resolved to be used after a patch failure 25skip skip the current patch 26abort restore the original branch and abort the patching operation. 27committer-date-is-author-date lie about committer date 28ignore-date use current timestamp for author date 29rebasing* (internal use for git-rebase)" 30 31. git-sh-setup 32prefix=$(git rev-parse --show-prefix) 33set_reflog_action am 34require_work_tree 35cd_to_toplevel 36 37git var GIT_COMMITTER_IDENT >/dev/null || 38 die "You need to set your committer info first" 39 40if git rev-parse --verify -q HEAD >/dev/null 41then 42 HAS_HEAD=yes 43else 44 HAS_HEAD= 45fi 46 47sq() { 48 git rev-parse --sq-quote"$@" 49} 50 51stop_here () { 52echo"$1">"$dotest/next" 53exit1 54} 55 56stop_here_user_resolve () { 57if[-n"$resolvemsg"];then 58printf'%s\n'"$resolvemsg" 59 stop_here $1 60fi 61 cmdline="git am" 62iftest''!="$interactive" 63then 64 cmdline="$cmdline-i" 65fi 66iftest''!="$threeway" 67then 68 cmdline="$cmdline-3" 69fi 70echo"When you have resolved this problem run\"$cmdline--resolved\"." 71echo"If you would prefer to skip this patch, instead run\"$cmdline--skip\"." 72echo"To restore the original branch and stop patching run\"$cmdline--abort\"." 73 74 stop_here $1 75} 76 77go_next () { 78rm-f"$dotest/$msgnum""$dotest/msg""$dotest/msg-clean" \ 79"$dotest/patch""$dotest/info" 80echo"$next">"$dotest/next" 81 this=$next 82} 83 84cannot_fallback () { 85echo"$1" 86echo"Cannot fall back to three-way merge." 87exit1 88} 89 90fall_back_3way () { 91 O_OBJECT=`cd "$GIT_OBJECT_DIRECTORY" && pwd` 92 93rm-fr"$dotest"/patch-merge-* 94mkdir"$dotest/patch-merge-tmp-dir" 95 96# First see if the patch records the index info that we can use. 97 git apply --build-fake-ancestor"$dotest/patch-merge-tmp-index" \ 98"$dotest/patch"&& 99 GIT_INDEX_FILE="$dotest/patch-merge-tmp-index" \ 100 git write-tree>"$dotest/patch-merge-base+"|| 101 cannot_fallback "Repository lacks necessary blobs to fall back on 3-way merge." 102 103 say Using index info to reconstruct a base tree... 104if GIT_INDEX_FILE="$dotest/patch-merge-tmp-index" \ 105 git apply --cached<"$dotest/patch" 106then 107mv"$dotest/patch-merge-base+""$dotest/patch-merge-base" 108mv"$dotest/patch-merge-tmp-index""$dotest/patch-merge-index" 109else 110 cannot_fallback "Did you hand edit your patch? 111It does not apply to blobs recorded in its index." 112fi 113 114test -f"$dotest/patch-merge-index"&& 115 his_tree=$(GIT_INDEX_FILE="$dotest/patch-merge-index" git write-tree)&& 116 orig_tree=$(cat "$dotest/patch-merge-base")&& 117rm-fr"$dotest"/patch-merge-* ||exit1 118 119 say Falling back to patching base and 3-way merge... 120 121# This is not so wrong. Depending on which base we picked, 122# orig_tree may be wildly different from ours, but his_tree 123# has the same set of wildly different changes in parts the 124# patch did not touch, so recursive ends up canceling them, 125# saying that we reverted all those changes. 126 127eval GITHEAD_$his_tree='"$FIRSTLINE"' 128export GITHEAD_$his_tree 129iftest -n"$GIT_QUIET" 130then 131export GIT_MERGE_VERBOSITY=0 132fi 133 git-merge-recursive$orig_tree-- HEAD $his_tree|| { 134 git rerere 135echo Failed to merge in the changes. 136exit1 137} 138unset GITHEAD_$his_tree 139} 140 141prec=4 142dotest="$GIT_DIR/rebase-apply" 143sign= utf8=t keep= skip= interactive= resolved= rebasing= abort= 144resolvemsg= resume= 145git_apply_opt= 146committer_date_is_author_date= 147ignore_date= 148 149whiletest$#!=0 150do 151case"$1"in 152-i|--interactive) 153 interactive=t ;; 154-b|--binary) 155: ;; 156-3|--3way) 157 threeway=t ;; 158-s|--signoff) 159 sign=t ;; 160-u|--utf8) 161 utf8=t ;;# this is now default 162--no-utf8) 163 utf8= ;; 164-k|--keep) 165 keep=t ;; 166-r|--resolved) 167 resolved=t ;; 168--skip) 169 skip=t ;; 170--abort) 171 abort=t ;; 172--rebasing) 173 rebasing=t threeway=t keep=t ;; 174-d|--dotest) 175 die "-d option is no longer supported. Do not use." 176;; 177--resolvemsg) 178shift; resolvemsg=$1;; 179--whitespace|--directory) 180 git_apply_opt="$git_apply_opt$(sq "$1=$2")";shift;; 181-C|-p) 182 git_apply_opt="$git_apply_opt$(sq "$1$2")";shift;; 183--reject) 184 git_apply_opt="$git_apply_opt$1";; 185--committer-date-is-author-date) 186 committer_date_is_author_date=t ;; 187--ignore-date) 188 ignore_date=t ;; 189-q|--quiet) 190 GIT_QUIET=t ;; 191--) 192shift;break;; 193*) 194 usage ;; 195esac 196shift 197done 198 199# If the dotest directory exists, but we have finished applying all the 200# patches in them, clear it out. 201iftest -d"$dotest"&& 202 last=$(cat "$dotest/last")&& 203 next=$(cat "$dotest/next")&& 204test$#!=0&& 205test"$next"-gt"$last" 206then 207rm-fr"$dotest" 208fi 209 210iftest -d"$dotest" 211then 212case"$#,$skip$resolved$abort"in 2130,*t*) 214# Explicit resume command and we do not have file, so 215# we are happy. 216: ;; 2170,) 218# No file input but without resume parameters; catch 219# user error to feed us a patch from standard input 220# when there is already $dotest. This is somewhat 221# unreliable -- stdin could be /dev/null for example 222# and the caller did not intend to feed us a patch but 223# wanted to continue unattended. 224test -t0 225;; 226*) 227 false 228;; 229esac|| 230 die "previous rebase directory$doteststill exists but mbox given." 231 resume=yes 232 233case"$skip,$abort"in 234 t,t) 235 die "Please make up your mind. --skip or --abort?" 236;; 237 t,) 238 git rerere clear 239 git read-tree --reset -u HEAD HEAD 240 orig_head=$(cat "$GIT_DIR/ORIG_HEAD") 241 git reset HEAD 242 git update-ref ORIG_HEAD $orig_head 243;; 244,t) 245iftest -f"$dotest/rebasing" 246then 247exec git rebase --abort 248fi 249 git rerere clear 250test -f"$dotest/dirtyindex"|| { 251 git read-tree --reset -u HEAD ORIG_HEAD 252 git reset ORIG_HEAD 253} 254rm-fr"$dotest" 255exit;; 256esac 257rm-f"$dotest/dirtyindex" 258else 259# Make sure we are not given --skip, --resolved, nor --abort 260test"$skip$resolved$abort"=""|| 261 die "Resolve operation not in progress, we are not resuming." 262 263# Start afresh. 264mkdir-p"$dotest"||exit 265 266iftest -n"$prefix"&&test$#!=0 267then 268 first=t 269for arg 270do 271test -n"$first"&& { 272set x 273 first= 274} 275case"$arg"in 276/*) 277set"$@""$arg";; 278*) 279set"$@""$prefix$arg";; 280esac 281done 282shift 283fi 284 git mailsplit -d"$prec"-o"$dotest"-b --"$@">"$dotest/last"|| { 285rm-fr"$dotest" 286exit1 287} 288 289# -s, -u, -k, --whitespace, -3, -C, -q and -p flags are kept 290# for the resuming session after a patch failure. 291# -i can and must be given when resuming. 292echo"$git_apply_opt">"$dotest/apply-opt" 293echo"$threeway">"$dotest/threeway" 294echo"$sign">"$dotest/sign" 295echo"$utf8">"$dotest/utf8" 296echo"$keep">"$dotest/keep" 297echo"$GIT_QUIET">"$dotest/quiet" 298echo1>"$dotest/next" 299iftest -n"$rebasing" 300then 301: >"$dotest/rebasing" 302else 303: >"$dotest/applying" 304iftest -n"$HAS_HEAD" 305then 306 git update-ref ORIG_HEAD HEAD 307else 308 git update-ref -d ORIG_HEAD >/dev/null 2>&1 309fi 310fi 311fi 312 313case"$resolved"in 314'') 315case"$HAS_HEAD"in 316'') 317 files=$(git ls-files);; 318 ?*) 319 files=$(git diff-index --cached --name-only HEAD --);; 320esac||exit 321iftest"$files" 322then 323test -n"$HAS_HEAD"&& : >"$dotest/dirtyindex" 324 die "Dirty index: cannot apply patches (dirty:$files)" 325fi 326esac 327 328iftest"$(cat "$dotest/utf8")"= t 329then 330 utf8=-u 331else 332 utf8=-n 333fi 334iftest"$(cat "$dotest/keep")"= t 335then 336 keep=-k 337fi 338iftest"$(cat "$dotest/quiet")"= t 339then 340 GIT_QUIET=t 341fi 342iftest"$(cat "$dotest/threeway")"= t 343then 344 threeway=t 345fi 346git_apply_opt=$(cat "$dotest/apply-opt") 347iftest"$(cat "$dotest/sign")"= t 348then 349 SIGNOFF=`git var GIT_COMMITTER_IDENT | sed -e ' 350 s/>.*/>/ 351 s/^/Signed-off-by: /' 352 ` 353else 354 SIGNOFF= 355fi 356 357last=`cat "$dotest/last"` 358this=`cat "$dotest/next"` 359iftest"$skip"= t 360then 361 this=`expr "$this" + 1` 362 resume= 363fi 364 365iftest"$this"-gt"$last" 366then 367 say Nothing to do. 368rm-fr"$dotest" 369exit 370fi 371 372whiletest"$this"-le"$last" 373do 374 msgnum=`printf "%0${prec}d"$this` 375 next=`expr "$this" + 1` 376test -f"$dotest/$msgnum"|| { 377 resume= 378 go_next 379continue 380} 381 382# If we are not resuming, parse and extract the patch information 383# into separate files: 384# - info records the authorship and title 385# - msg is the rest of commit log message 386# - patch is the patch body. 387# 388# When we are resuming, these files are either already prepared 389# by the user, or the user can tell us to do so by --resolved flag. 390case"$resume"in 391'') 392 git mailinfo $keep $utf8"$dotest/msg""$dotest/patch" \ 393<"$dotest/$msgnum">"$dotest/info"|| 394 stop_here $this 395 396# skip pine's internal folder data 397grep'^Author: Mail System Internal Data$' \ 398<"$dotest"/info >/dev/null && 399 go_next &&continue 400 401test -s"$dotest/patch"|| { 402echo"Patch is empty. Was it split wrong?" 403 stop_here $this 404} 405iftest -f"$dotest/rebasing"&& 406 commit=$(sed -e 's/^From \([0-9a-f]*\) .*/\1/' \ 407 -e q "$dotest/$msgnum") && 408 test "$(git cat-file -t "$commit")" = commit 409 then 410 git cat-file commit "$commit" | 411 sed -e '1,/^$/d' >"$dotest/msg-clean" 412 else 413 SUBJECT="$(sed -n '/^Subject/ s/Subject: //p' "$dotest/info")" 414 case "$keep_subject" in -k) SUBJECT="[PATCH]$SUBJECT" ;; esac 415 416 (printf '%s\n\n' "$SUBJECT"; cat "$dotest/msg") | 417 git stripspace > "$dotest/msg-clean" 418 fi 419 ;; 420 esac 421 422 GIT_AUTHOR_NAME="$(sed -n '/^Author/ s/Author: //p' "$dotest/info")" 423 GIT_AUTHOR_EMAIL="$(sed -n '/^Email/ s/Email: //p' "$dotest/info")" 424 GIT_AUTHOR_DATE="$(sed -n '/^Date/ s/Date: //p' "$dotest/info")" 425 426 if test -z "$GIT_AUTHOR_EMAIL" 427 then 428 echo "Patch does not have a valid e-mail address." 429 stop_here$this 430 fi 431 432 export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE 433 434 case "$resume" in 435 '') 436 if test '' != "$SIGNOFF" 437 then 438 LAST_SIGNED_OFF_BY=` 439 sed -ne '/^Signed-off-by: /p' \ 440 "$dotest/msg-clean" | 441 sed -ne '$p' 442 ` 443 ADD_SIGNOFF=` 444 test "$LAST_SIGNED_OFF_BY" = "$SIGNOFF" || { 445 test '' = "$LAST_SIGNED_OFF_BY" && echo 446 echo "$SIGNOFF" 447 }` 448 else 449 ADD_SIGNOFF= 450 fi 451 { 452 if test -s "$dotest/msg-clean" 453 then 454 cat "$dotest/msg-clean" 455 fi 456 if test '' != "$ADD_SIGNOFF" 457 then 458 echo "$ADD_SIGNOFF" 459 fi 460 } >"$dotest/final-commit" 461 ;; 462 *) 463 case "$resolved$interactive" in 464 tt) 465 # This is used only for interactive view option. 466 git diff-index -p --cached HEAD -- >"$dotest/patch" 467 ;; 468 esac 469 esac 470 471 resume= 472 if test "$interactive" = t 473 then 474 test -t 0 || 475 die "cannot be interactive without stdin connected to a terminal." 476 action=again 477 while test "$action" = again 478 do 479 echo "Commit Body is:" 480 echo "--------------------------" 481 cat "$dotest/final-commit" 482 echo "--------------------------" 483 printf "Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all " 484 read reply 485 case "$reply" in 486 [yY]*) action=yes ;; 487 [aA]*) action=yes interactive= ;; 488 [nN]*) action=skip ;; 489 [eE]*) git_editor "$dotest/final-commit" 490 action=again ;; 491 [vV]*) action=again 492 LESS=-S${PAGER:-less}"$dotest/patch" ;; 493 *) action=again ;; 494 esac 495 done 496 else 497 action=yes 498 fi 499 FIRSTLINE=$(sed 1q "$dotest/final-commit") 500 501 if test$action= skip 502 then 503 go_next 504 continue 505 fi 506 507 if test -x "$GIT_DIR"/hooks/applypatch-msg 508 then 509 "$GIT_DIR"/hooks/applypatch-msg "$dotest/final-commit" || 510 stop_here$this 511 fi 512 513 say "Applying:$FIRSTLINE" 514 515 case "$resolved" in 516 '') 517 # When we are allowed to fall back to 3-way later, don't give 518# false errors during the initial attempt. 519 squelch= 520iftest"$threeway"= t 521then 522 squelch='>/dev/null 2>&1 ' 523fi 524eval"git apply$squelch$git_apply_opt"' --index "$dotest/patch"' 525 apply_status=$? 526;; 527 t) 528# Resolved means the user did all the hard work, and 529# we do not have to do any patch application. Just 530# trust what the user has in the index file and the 531# working tree. 532 resolved= 533 git diff-index --quiet --cached HEAD --&& { 534echo"No changes - did you forget to use 'git add'?" 535 stop_here_user_resolve $this 536} 537 unmerged=$(git ls-files -u) 538iftest -n"$unmerged" 539then 540echo"You still have unmerged paths in your index" 541echo"did you forget to use 'git add'?" 542 stop_here_user_resolve $this 543fi 544 apply_status=0 545 git rerere 546;; 547esac 548 549iftest$apply_status=1&&test"$threeway"= t 550then 551if(fall_back_3way) 552then 553# Applying the patch to an earlier tree and merging the 554# result may have produced the same tree as ours. 555 git diff-index --quiet --cached HEAD --&& { 556 say No changes -- Patch already applied. 557 go_next 558continue 559} 560# clear apply_status -- we have successfully merged. 561 apply_status=0 562fi 563fi 564iftest$apply_status!=0 565then 566printf'Patch failed at %s %s\n'"$msgnum""$FIRSTLINE" 567 stop_here_user_resolve $this 568fi 569 570iftest -x"$GIT_DIR"/hooks/pre-applypatch 571then 572"$GIT_DIR"/hooks/pre-applypatch|| stop_here $this 573fi 574 575 tree=$(git write-tree)&& 576 commit=$( 577iftest -n"$ignore_date" 578then 579 GIT_AUTHOR_DATE= 580fi 581 parent=$(git rev-parse --verify -q HEAD)|| 582 say >&2"applying to an empty history" 583 584iftest -n"$committer_date_is_author_date" 585then 586 GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE" 587export GIT_COMMITTER_DATE 588fi&& 589 git commit-tree$tree ${parent:+-p} $parent<"$dotest/final-commit" 590) && 591 git update-ref -m"$GIT_REFLOG_ACTION:$FIRSTLINE" HEAD $commit $parent|| 592 stop_here $this 593 594iftest -x"$GIT_DIR"/hooks/post-applypatch 595then 596"$GIT_DIR"/hooks/post-applypatch 597fi 598 599 go_next 600done 601 602git gc --auto 603 604rm-fr"$dotest"