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 22patch-format= format the patch(es) are in 23reject pass it through git-apply 24resolvemsg= override error message when patch failure occurs 25r,resolved to be used after a patch failure 26skip skip the current patch 27abort restore the original branch and abort the patching operation. 28committer-date-is-author-date lie about committer date 29ignore-date use current timestamp for author date 30rebasing* (internal use for git-rebase)" 31 32. git-sh-setup 33prefix=$(git rev-parse --show-prefix) 34set_reflog_action am 35require_work_tree 36cd_to_toplevel 37 38git var GIT_COMMITTER_IDENT >/dev/null || 39 die "You need to set your committer info first" 40 41if git rev-parse --verify -q HEAD >/dev/null 42then 43 HAS_HEAD=yes 44else 45 HAS_HEAD= 46fi 47 48sq() { 49 git rev-parse --sq-quote"$@" 50} 51 52stop_here () { 53echo"$1">"$dotest/next" 54exit1 55} 56 57stop_here_user_resolve () { 58if[-n"$resolvemsg"];then 59printf'%s\n'"$resolvemsg" 60 stop_here $1 61fi 62 cmdline="git am" 63iftest''!="$interactive" 64then 65 cmdline="$cmdline-i" 66fi 67iftest''!="$threeway" 68then 69 cmdline="$cmdline-3" 70fi 71echo"When you have resolved this problem run\"$cmdline--resolved\"." 72echo"If you would prefer to skip this patch, instead run\"$cmdline--skip\"." 73echo"To restore the original branch and stop patching run\"$cmdline--abort\"." 74 75 stop_here $1 76} 77 78go_next () { 79rm-f"$dotest/$msgnum""$dotest/msg""$dotest/msg-clean" \ 80"$dotest/patch""$dotest/info" 81echo"$next">"$dotest/next" 82 this=$next 83} 84 85cannot_fallback () { 86echo"$1" 87echo"Cannot fall back to three-way merge." 88exit1 89} 90 91fall_back_3way () { 92 O_OBJECT=`cd "$GIT_OBJECT_DIRECTORY" && pwd` 93 94rm-fr"$dotest"/patch-merge-* 95mkdir"$dotest/patch-merge-tmp-dir" 96 97# First see if the patch records the index info that we can use. 98 git apply --build-fake-ancestor"$dotest/patch-merge-tmp-index" \ 99"$dotest/patch"&& 100 GIT_INDEX_FILE="$dotest/patch-merge-tmp-index" \ 101 git write-tree>"$dotest/patch-merge-base+"|| 102 cannot_fallback "Repository lacks necessary blobs to fall back on 3-way merge." 103 104 say Using index info to reconstruct a base tree... 105if GIT_INDEX_FILE="$dotest/patch-merge-tmp-index" \ 106 git apply --cached<"$dotest/patch" 107then 108mv"$dotest/patch-merge-base+""$dotest/patch-merge-base" 109mv"$dotest/patch-merge-tmp-index""$dotest/patch-merge-index" 110else 111 cannot_fallback "Did you hand edit your patch? 112It does not apply to blobs recorded in its index." 113fi 114 115test -f"$dotest/patch-merge-index"&& 116 his_tree=$(GIT_INDEX_FILE="$dotest/patch-merge-index" git write-tree)&& 117 orig_tree=$(cat "$dotest/patch-merge-base")&& 118rm-fr"$dotest"/patch-merge-* ||exit1 119 120 say Falling back to patching base and 3-way merge... 121 122# This is not so wrong. Depending on which base we picked, 123# orig_tree may be wildly different from ours, but his_tree 124# has the same set of wildly different changes in parts the 125# patch did not touch, so recursive ends up canceling them, 126# saying that we reverted all those changes. 127 128eval GITHEAD_$his_tree='"$FIRSTLINE"' 129export GITHEAD_$his_tree 130iftest -n"$GIT_QUIET" 131then 132export GIT_MERGE_VERBOSITY=0 133fi 134 git-merge-recursive$orig_tree-- HEAD $his_tree|| { 135 git rerere 136echo Failed to merge in the changes. 137exit1 138} 139unset GITHEAD_$his_tree 140} 141 142clean_abort () { 143test$#=0||echo>&2"$@" 144rm-fr"$dotest" 145exit1 146} 147 148patch_format= 149 150check_patch_format () { 151# early return if patch_format was set from the command line 152iftest -n"$patch_format" 153then 154return0 155fi 156 157# we default to mbox format if input is from stdin and for 158# directories 159iftest$#=0||test"x$1"="x-"||test -d"$1" 160then 161 patch_format=mbox 162return0 163fi 164 165# otherwise, check the first few lines of the first patch to try 166# to detect its format 167{ 168read l1 169read l2 170read l3 171case"$l1"in 172"From "* |"From: "*) 173 patch_format=mbox 174;; 175'# This series applies on GIT commit'*) 176 patch_format=stgit-series 177;; 178"# HG changeset patch") 179 patch_format=hg 180;; 181*) 182# if the second line is empty and the third is 183# a From, Author or Date entry, this is very 184# likely an StGIT patch 185case"$l2,$l3"in 186,"From: "* | ,"Author: "* | ,"Date: "*) 187 patch_format=stgit 188;; 189*) 190;; 191esac 192;; 193esac 194iftest -z"$patch_format"&& 195test -n"$l1"&& 196test -n"$l2"&& 197test -n"$l3" 198then 199# This begins with three non-empty lines. Is this a 200# piece of e-mail a-la RFC2822? Grab all the headers, 201# discarding the indented remainder of folded lines, 202# and see if it looks like that they all begin with the 203# header field names... 204sed-n -e'/^$/q'-e'/^[ ]/d'-e p "$1"| 205egrep-v'^[A-Za-z]+(-[A-Za-z]+)*:'>/dev/null || 206 patch_format=mbox 207fi 208} <"$1"|| clean_abort 209} 210 211split_patches () { 212case"$patch_format"in 213 mbox) 214 git mailsplit -d"$prec"-o"$dotest"-b --"$@">"$dotest/last"|| 215 clean_abort 216;; 217 stgit-series) 218iftest$#-ne1 219then 220 clean_abort "Only one StGIT patch series can be applied at once" 221fi 222 series_dir=`dirname "$1"` 223 series_file="$1" 224shift 225{ 226set x 227whileread filename 228do 229set"$@""$series_dir/$filename" 230done 231# remove the safety x 232shift 233# remove the arg coming from the first-line comment 234shift 235} <"$series_file"|| clean_abort 236# set the patch format appropriately 237 patch_format=stgit 238# now handle the actual StGIT patches 239 split_patches "$@" 240;; 241 stgit) 242 this=0 243for stgit in"$@" 244do 245 this=`expr "$this" + 1` 246 msgnum=`printf "%0${prec}d"$this` 247# Perl version of StGIT parse_patch. The first nonemptyline 248# not starting with Author, From or Date is the 249# subject, and the body starts with the next nonempty 250# line not starting with Author, From or Date 251 perl -ne'BEGIN {$subject= 0 } 252 if ($subject> 1) { print ; } 253 elsif (/^\s+$/) { next ; } 254 elsif (/^Author:/) { print s/Author/From/ ; } 255 elsif (/^(From|Date)/) { print ; } 256 elsif ($subject) { 257$subject= 2 ; 258 print "\n" ; 259 print ; 260 } else { 261 print "Subject: ",$_; 262$subject= 1; 263 } 264 '<"$stgit">"$dotest/$msgnum"|| clean_abort 265done 266echo"$this">"$dotest/last" 267 this= 268 msgnum= 269;; 270*) 271 clean_abort "Patch format$patch_formatis not supported." 272;; 273esac 274} 275 276prec=4 277dotest="$GIT_DIR/rebase-apply" 278sign= utf8=t keep= skip= interactive= resolved= rebasing= abort= 279resolvemsg= resume= 280git_apply_opt= 281committer_date_is_author_date= 282ignore_date= 283 284whiletest$#!=0 285do 286case"$1"in 287-i|--interactive) 288 interactive=t ;; 289-b|--binary) 290: ;; 291-3|--3way) 292 threeway=t ;; 293-s|--signoff) 294 sign=t ;; 295-u|--utf8) 296 utf8=t ;;# this is now default 297--no-utf8) 298 utf8= ;; 299-k|--keep) 300 keep=t ;; 301-r|--resolved) 302 resolved=t ;; 303--skip) 304 skip=t ;; 305--abort) 306 abort=t ;; 307--rebasing) 308 rebasing=t threeway=t keep=t ;; 309-d|--dotest) 310 die "-d option is no longer supported. Do not use." 311;; 312--resolvemsg) 313shift; resolvemsg=$1;; 314--whitespace|--directory) 315 git_apply_opt="$git_apply_opt$(sq "$1=$2")";shift;; 316-C|-p) 317 git_apply_opt="$git_apply_opt$(sq "$1$2")";shift;; 318--patch-format) 319shift; patch_format="$1";; 320--reject) 321 git_apply_opt="$git_apply_opt$1";; 322--committer-date-is-author-date) 323 committer_date_is_author_date=t ;; 324--ignore-date) 325 ignore_date=t ;; 326-q|--quiet) 327 GIT_QUIET=t ;; 328--) 329shift;break;; 330*) 331 usage ;; 332esac 333shift 334done 335 336# If the dotest directory exists, but we have finished applying all the 337# patches in them, clear it out. 338iftest -d"$dotest"&& 339 last=$(cat "$dotest/last")&& 340 next=$(cat "$dotest/next")&& 341test$#!=0&& 342test"$next"-gt"$last" 343then 344rm-fr"$dotest" 345fi 346 347iftest -d"$dotest" 348then 349case"$#,$skip$resolved$abort"in 3500,*t*) 351# Explicit resume command and we do not have file, so 352# we are happy. 353: ;; 3540,) 355# No file input but without resume parameters; catch 356# user error to feed us a patch from standard input 357# when there is already $dotest. This is somewhat 358# unreliable -- stdin could be /dev/null for example 359# and the caller did not intend to feed us a patch but 360# wanted to continue unattended. 361test -t0 362;; 363*) 364 false 365;; 366esac|| 367 die "previous rebase directory$doteststill exists but mbox given." 368 resume=yes 369 370case"$skip,$abort"in 371 t,t) 372 die "Please make up your mind. --skip or --abort?" 373;; 374 t,) 375 git rerere clear 376 git read-tree --reset -u HEAD HEAD 377 orig_head=$(cat "$GIT_DIR/ORIG_HEAD") 378 git reset HEAD 379 git update-ref ORIG_HEAD $orig_head 380;; 381,t) 382iftest -f"$dotest/rebasing" 383then 384exec git rebase --abort 385fi 386 git rerere clear 387test -f"$dotest/dirtyindex"|| { 388 git read-tree --reset -u HEAD ORIG_HEAD 389 git reset ORIG_HEAD 390} 391rm-fr"$dotest" 392exit;; 393esac 394rm-f"$dotest/dirtyindex" 395else 396# Make sure we are not given --skip, --resolved, nor --abort 397test"$skip$resolved$abort"=""|| 398 die "Resolve operation not in progress, we are not resuming." 399 400# Start afresh. 401mkdir-p"$dotest"||exit 402 403iftest -n"$prefix"&&test$#!=0 404then 405 first=t 406for arg 407do 408test -n"$first"&& { 409set x 410 first= 411} 412case"$arg"in 413/*) 414set"$@""$arg";; 415*) 416set"$@""$prefix$arg";; 417esac 418done 419shift 420fi 421 422 check_patch_format "$@" 423 424 split_patches "$@" 425 426# -s, -u, -k, --whitespace, -3, -C, -q and -p flags are kept 427# for the resuming session after a patch failure. 428# -i can and must be given when resuming. 429echo"$git_apply_opt">"$dotest/apply-opt" 430echo"$threeway">"$dotest/threeway" 431echo"$sign">"$dotest/sign" 432echo"$utf8">"$dotest/utf8" 433echo"$keep">"$dotest/keep" 434echo"$GIT_QUIET">"$dotest/quiet" 435echo1>"$dotest/next" 436iftest -n"$rebasing" 437then 438: >"$dotest/rebasing" 439else 440: >"$dotest/applying" 441iftest -n"$HAS_HEAD" 442then 443 git update-ref ORIG_HEAD HEAD 444else 445 git update-ref -d ORIG_HEAD >/dev/null 2>&1 446fi 447fi 448fi 449 450case"$resolved"in 451'') 452case"$HAS_HEAD"in 453'') 454 files=$(git ls-files);; 455 ?*) 456 files=$(git diff-index --cached --name-only HEAD --);; 457esac||exit 458iftest"$files" 459then 460test -n"$HAS_HEAD"&& : >"$dotest/dirtyindex" 461 die "Dirty index: cannot apply patches (dirty:$files)" 462fi 463esac 464 465iftest"$(cat "$dotest/utf8")"= t 466then 467 utf8=-u 468else 469 utf8=-n 470fi 471iftest"$(cat "$dotest/keep")"= t 472then 473 keep=-k 474fi 475iftest"$(cat "$dotest/quiet")"= t 476then 477 GIT_QUIET=t 478fi 479iftest"$(cat "$dotest/threeway")"= t 480then 481 threeway=t 482fi 483git_apply_opt=$(cat "$dotest/apply-opt") 484iftest"$(cat "$dotest/sign")"= t 485then 486 SIGNOFF=`git var GIT_COMMITTER_IDENT | sed -e ' 487 s/>.*/>/ 488 s/^/Signed-off-by: /' 489 ` 490else 491 SIGNOFF= 492fi 493 494last=`cat "$dotest/last"` 495this=`cat "$dotest/next"` 496iftest"$skip"= t 497then 498 this=`expr "$this" + 1` 499 resume= 500fi 501 502iftest"$this"-gt"$last" 503then 504 say Nothing to do. 505rm-fr"$dotest" 506exit 507fi 508 509whiletest"$this"-le"$last" 510do 511 msgnum=`printf "%0${prec}d"$this` 512 next=`expr "$this" + 1` 513test -f"$dotest/$msgnum"|| { 514 resume= 515 go_next 516continue 517} 518 519# If we are not resuming, parse and extract the patch information 520# into separate files: 521# - info records the authorship and title 522# - msg is the rest of commit log message 523# - patch is the patch body. 524# 525# When we are resuming, these files are either already prepared 526# by the user, or the user can tell us to do so by --resolved flag. 527case"$resume"in 528'') 529 git mailinfo $keep $utf8"$dotest/msg""$dotest/patch" \ 530<"$dotest/$msgnum">"$dotest/info"|| 531 stop_here $this 532 533# skip pine's internal folder data 534grep'^Author: Mail System Internal Data$' \ 535<"$dotest"/info >/dev/null && 536 go_next &&continue 537 538test -s"$dotest/patch"|| { 539echo"Patch is empty. Was it split wrong?" 540 stop_here $this 541} 542iftest -f"$dotest/rebasing"&& 543 commit=$(sed -e 's/^From \([0-9a-f]*\) .*/\1/' \ 544 -e q "$dotest/$msgnum") && 545 test "$(git cat-file -t "$commit")" = commit 546 then 547 git cat-file commit "$commit" | 548 sed -e '1,/^$/d' >"$dotest/msg-clean" 549 else 550 SUBJECT="$(sed -n '/^Subject/ s/Subject: //p' "$dotest/info")" 551 case "$keep_subject" in -k) SUBJECT="[PATCH]$SUBJECT" ;; esac 552 553 (printf '%s\n\n' "$SUBJECT"; cat "$dotest/msg") | 554 git stripspace > "$dotest/msg-clean" 555 fi 556 ;; 557 esac 558 559 GIT_AUTHOR_NAME="$(sed -n '/^Author/ s/Author: //p' "$dotest/info")" 560 GIT_AUTHOR_EMAIL="$(sed -n '/^Email/ s/Email: //p' "$dotest/info")" 561 GIT_AUTHOR_DATE="$(sed -n '/^Date/ s/Date: //p' "$dotest/info")" 562 563 if test -z "$GIT_AUTHOR_EMAIL" 564 then 565 echo "Patch does not have a valid e-mail address." 566 stop_here$this 567 fi 568 569 export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE 570 571 case "$resume" in 572 '') 573 if test '' != "$SIGNOFF" 574 then 575 LAST_SIGNED_OFF_BY=` 576 sed -ne '/^Signed-off-by: /p' \ 577 "$dotest/msg-clean" | 578 sed -ne '$p' 579 ` 580 ADD_SIGNOFF=` 581 test "$LAST_SIGNED_OFF_BY" = "$SIGNOFF" || { 582 test '' = "$LAST_SIGNED_OFF_BY" && echo 583 echo "$SIGNOFF" 584 }` 585 else 586 ADD_SIGNOFF= 587 fi 588 { 589 if test -s "$dotest/msg-clean" 590 then 591 cat "$dotest/msg-clean" 592 fi 593 if test '' != "$ADD_SIGNOFF" 594 then 595 echo "$ADD_SIGNOFF" 596 fi 597 } >"$dotest/final-commit" 598 ;; 599 *) 600 case "$resolved$interactive" in 601 tt) 602 # This is used only for interactive view option. 603 git diff-index -p --cached HEAD -- >"$dotest/patch" 604 ;; 605 esac 606 esac 607 608 resume= 609 if test "$interactive" = t 610 then 611 test -t 0 || 612 die "cannot be interactive without stdin connected to a terminal." 613 action=again 614 while test "$action" = again 615 do 616 echo "Commit Body is:" 617 echo "--------------------------" 618 cat "$dotest/final-commit" 619 echo "--------------------------" 620 printf "Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all " 621 read reply 622 case "$reply" in 623 [yY]*) action=yes ;; 624 [aA]*) action=yes interactive= ;; 625 [nN]*) action=skip ;; 626 [eE]*) git_editor "$dotest/final-commit" 627 action=again ;; 628 [vV]*) action=again 629 LESS=-S${PAGER:-less}"$dotest/patch" ;; 630 *) action=again ;; 631 esac 632 done 633 else 634 action=yes 635 fi 636 FIRSTLINE=$(sed 1q "$dotest/final-commit") 637 638 if test$action= skip 639 then 640 go_next 641 continue 642 fi 643 644 if test -x "$GIT_DIR"/hooks/applypatch-msg 645 then 646 "$GIT_DIR"/hooks/applypatch-msg "$dotest/final-commit" || 647 stop_here$this 648 fi 649 650 say "Applying:$FIRSTLINE" 651 652 case "$resolved" in 653 '') 654 # When we are allowed to fall back to 3-way later, don't give 655# false errors during the initial attempt. 656 squelch= 657iftest"$threeway"= t 658then 659 squelch='>/dev/null 2>&1 ' 660fi 661eval"git apply$squelch$git_apply_opt"' --index "$dotest/patch"' 662 apply_status=$? 663;; 664 t) 665# Resolved means the user did all the hard work, and 666# we do not have to do any patch application. Just 667# trust what the user has in the index file and the 668# working tree. 669 resolved= 670 git diff-index --quiet --cached HEAD --&& { 671echo"No changes - did you forget to use 'git add'?" 672 stop_here_user_resolve $this 673} 674 unmerged=$(git ls-files -u) 675iftest -n"$unmerged" 676then 677echo"You still have unmerged paths in your index" 678echo"did you forget to use 'git add'?" 679 stop_here_user_resolve $this 680fi 681 apply_status=0 682 git rerere 683;; 684esac 685 686iftest$apply_status=1&&test"$threeway"= t 687then 688if(fall_back_3way) 689then 690# Applying the patch to an earlier tree and merging the 691# result may have produced the same tree as ours. 692 git diff-index --quiet --cached HEAD --&& { 693 say No changes -- Patch already applied. 694 go_next 695continue 696} 697# clear apply_status -- we have successfully merged. 698 apply_status=0 699fi 700fi 701iftest$apply_status!=0 702then 703printf'Patch failed at %s %s\n'"$msgnum""$FIRSTLINE" 704 stop_here_user_resolve $this 705fi 706 707iftest -x"$GIT_DIR"/hooks/pre-applypatch 708then 709"$GIT_DIR"/hooks/pre-applypatch|| stop_here $this 710fi 711 712 tree=$(git write-tree)&& 713 commit=$( 714iftest -n"$ignore_date" 715then 716 GIT_AUTHOR_DATE= 717fi 718 parent=$(git rev-parse --verify -q HEAD)|| 719 say >&2"applying to an empty history" 720 721iftest -n"$committer_date_is_author_date" 722then 723 GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE" 724export GIT_COMMITTER_DATE 725fi&& 726 git commit-tree$tree ${parent:+-p} $parent<"$dotest/final-commit" 727) && 728 git update-ref -m"$GIT_REFLOG_ACTION:$FIRSTLINE" HEAD $commit $parent|| 729 stop_here $this 730 731iftest -x"$GIT_DIR"/hooks/post-applypatch 732then 733"$GIT_DIR"/hooks/post-applypatch 734fi 735 736 go_next 737done 738 739git gc --auto 740 741rm-fr"$dotest"