1/* 2 * Builtin "git am" 3 * 4 * Based on git-am.sh by Junio C Hamano. 5 */ 6#include"cache.h" 7#include"builtin.h" 8#include"exec_cmd.h" 9#include"parse-options.h" 10#include"dir.h" 11#include"run-command.h" 12#include"quote.h" 13#include"tempfile.h" 14#include"lockfile.h" 15#include"cache-tree.h" 16#include"refs.h" 17#include"commit.h" 18#include"diff.h" 19#include"diffcore.h" 20#include"unpack-trees.h" 21#include"branch.h" 22#include"sequencer.h" 23#include"revision.h" 24#include"merge-recursive.h" 25#include"revision.h" 26#include"log-tree.h" 27#include"notes-utils.h" 28#include"rerere.h" 29#include"prompt.h" 30#include"mailinfo.h" 31#include"apply.h" 32#include"string-list.h" 33 34/** 35 * Returns 1 if the file is empty or does not exist, 0 otherwise. 36 */ 37static intis_empty_file(const char*filename) 38{ 39struct stat st; 40 41if(stat(filename, &st) <0) { 42if(errno == ENOENT) 43return1; 44die_errno(_("could not stat%s"), filename); 45} 46 47return!st.st_size; 48} 49 50/** 51 * Returns the length of the first line of msg. 52 */ 53static intlinelen(const char*msg) 54{ 55returnstrchrnul(msg,'\n') - msg; 56} 57 58/** 59 * Returns true if `str` consists of only whitespace, false otherwise. 60 */ 61static intstr_isspace(const char*str) 62{ 63for(; *str; str++) 64if(!isspace(*str)) 65return0; 66 67return1; 68} 69 70enum patch_format { 71 PATCH_FORMAT_UNKNOWN =0, 72 PATCH_FORMAT_MBOX, 73 PATCH_FORMAT_STGIT, 74 PATCH_FORMAT_STGIT_SERIES, 75 PATCH_FORMAT_HG, 76 PATCH_FORMAT_MBOXRD 77}; 78 79enum keep_type { 80 KEEP_FALSE =0, 81 KEEP_TRUE,/* pass -k flag to git-mailinfo */ 82 KEEP_NON_PATCH /* pass -b flag to git-mailinfo */ 83}; 84 85enum scissors_type { 86 SCISSORS_UNSET = -1, 87 SCISSORS_FALSE =0,/* pass --no-scissors to git-mailinfo */ 88 SCISSORS_TRUE /* pass --scissors to git-mailinfo */ 89}; 90 91enum signoff_type { 92 SIGNOFF_FALSE =0, 93 SIGNOFF_TRUE =1, 94 SIGNOFF_EXPLICIT /* --signoff was set on the command-line */ 95}; 96 97struct am_state { 98/* state directory path */ 99char*dir; 100 101/* current and last patch numbers, 1-indexed */ 102int cur; 103int last; 104 105/* commit metadata and message */ 106char*author_name; 107char*author_email; 108char*author_date; 109char*msg; 110size_t msg_len; 111 112/* when --rebasing, records the original commit the patch came from */ 113struct object_id orig_commit; 114 115/* number of digits in patch filename */ 116int prec; 117 118/* various operating modes and command line options */ 119int interactive; 120int threeway; 121int quiet; 122int signoff;/* enum signoff_type */ 123int utf8; 124int keep;/* enum keep_type */ 125int message_id; 126int scissors;/* enum scissors_type */ 127struct argv_array git_apply_opts; 128const char*resolvemsg; 129int committer_date_is_author_date; 130int ignore_date; 131int allow_rerere_autoupdate; 132const char*sign_commit; 133int rebasing; 134}; 135 136/** 137 * Initializes am_state with the default values. The state directory is set to 138 * dir. 139 */ 140static voidam_state_init(struct am_state *state,const char*dir) 141{ 142int gpgsign; 143 144memset(state,0,sizeof(*state)); 145 146assert(dir); 147 state->dir =xstrdup(dir); 148 149 state->prec =4; 150 151git_config_get_bool("am.threeway", &state->threeway); 152 153 state->utf8 =1; 154 155git_config_get_bool("am.messageid", &state->message_id); 156 157 state->scissors = SCISSORS_UNSET; 158 159argv_array_init(&state->git_apply_opts); 160 161if(!git_config_get_bool("commit.gpgsign", &gpgsign)) 162 state->sign_commit = gpgsign ?"": NULL; 163} 164 165/** 166 * Releases memory allocated by an am_state. 167 */ 168static voidam_state_release(struct am_state *state) 169{ 170free(state->dir); 171free(state->author_name); 172free(state->author_email); 173free(state->author_date); 174free(state->msg); 175argv_array_clear(&state->git_apply_opts); 176} 177 178/** 179 * Returns path relative to the am_state directory. 180 */ 181staticinlineconst char*am_path(const struct am_state *state,const char*path) 182{ 183returnmkpath("%s/%s", state->dir, path); 184} 185 186/** 187 * For convenience to call write_file() 188 */ 189static voidwrite_state_text(const struct am_state *state, 190const char*name,const char*string) 191{ 192write_file(am_path(state, name),"%s", string); 193} 194 195static voidwrite_state_count(const struct am_state *state, 196const char*name,int value) 197{ 198write_file(am_path(state, name),"%d", value); 199} 200 201static voidwrite_state_bool(const struct am_state *state, 202const char*name,int value) 203{ 204write_state_text(state, name, value ?"t":"f"); 205} 206 207/** 208 * If state->quiet is false, calls fprintf(fp, fmt, ...), and appends a newline 209 * at the end. 210 */ 211static voidsay(const struct am_state *state,FILE*fp,const char*fmt, ...) 212{ 213va_list ap; 214 215va_start(ap, fmt); 216if(!state->quiet) { 217vfprintf(fp, fmt, ap); 218putc('\n', fp); 219} 220va_end(ap); 221} 222 223/** 224 * Returns 1 if there is an am session in progress, 0 otherwise. 225 */ 226static intam_in_progress(const struct am_state *state) 227{ 228struct stat st; 229 230if(lstat(state->dir, &st) <0|| !S_ISDIR(st.st_mode)) 231return0; 232if(lstat(am_path(state,"last"), &st) || !S_ISREG(st.st_mode)) 233return0; 234if(lstat(am_path(state,"next"), &st) || !S_ISREG(st.st_mode)) 235return0; 236return1; 237} 238 239/** 240 * Reads the contents of `file` in the `state` directory into `sb`. Returns the 241 * number of bytes read on success, -1 if the file does not exist. If `trim` is 242 * set, trailing whitespace will be removed. 243 */ 244static intread_state_file(struct strbuf *sb,const struct am_state *state, 245const char*file,int trim) 246{ 247strbuf_reset(sb); 248 249if(strbuf_read_file(sb,am_path(state, file),0) >=0) { 250if(trim) 251strbuf_trim(sb); 252 253return sb->len; 254} 255 256if(errno == ENOENT) 257return-1; 258 259die_errno(_("could not read '%s'"),am_path(state, file)); 260} 261 262/** 263 * Take a series of KEY='VALUE' lines where VALUE part is 264 * sq-quoted, and append <KEY, VALUE> at the end of the string list 265 */ 266static intparse_key_value_squoted(char*buf,struct string_list *list) 267{ 268while(*buf) { 269struct string_list_item *item; 270char*np; 271char*cp =strchr(buf,'='); 272if(!cp) 273return-1; 274 np =strchrnul(cp,'\n'); 275*cp++ ='\0'; 276 item =string_list_append(list, buf); 277 278 buf = np + (*np =='\n'); 279*np ='\0'; 280 cp =sq_dequote(cp); 281if(!cp) 282return-1; 283 item->util =xstrdup(cp); 284} 285return0; 286} 287 288/** 289 * Reads and parses the state directory's "author-script" file, and sets 290 * state->author_name, state->author_email and state->author_date accordingly. 291 * Returns 0 on success, -1 if the file could not be parsed. 292 * 293 * The author script is of the format: 294 * 295 * GIT_AUTHOR_NAME='$author_name' 296 * GIT_AUTHOR_EMAIL='$author_email' 297 * GIT_AUTHOR_DATE='$author_date' 298 * 299 * where $author_name, $author_email and $author_date are quoted. We are strict 300 * with our parsing, as the file was meant to be eval'd in the old git-am.sh 301 * script, and thus if the file differs from what this function expects, it is 302 * better to bail out than to do something that the user does not expect. 303 */ 304static intread_author_script(struct am_state *state) 305{ 306const char*filename =am_path(state,"author-script"); 307struct strbuf buf = STRBUF_INIT; 308struct string_list kv = STRING_LIST_INIT_DUP; 309int retval = -1;/* assume failure */ 310int fd; 311 312assert(!state->author_name); 313assert(!state->author_email); 314assert(!state->author_date); 315 316 fd =open(filename, O_RDONLY); 317if(fd <0) { 318if(errno == ENOENT) 319return0; 320die_errno(_("could not open '%s' for reading"), filename); 321} 322strbuf_read(&buf, fd,0); 323close(fd); 324if(parse_key_value_squoted(buf.buf, &kv)) 325goto finish; 326 327if(kv.nr !=3|| 328strcmp(kv.items[0].string,"GIT_AUTHOR_NAME") || 329strcmp(kv.items[1].string,"GIT_AUTHOR_EMAIL") || 330strcmp(kv.items[2].string,"GIT_AUTHOR_DATE")) 331goto finish; 332 state->author_name = kv.items[0].util; 333 state->author_email = kv.items[1].util; 334 state->author_date = kv.items[2].util; 335 retval =0; 336finish: 337string_list_clear(&kv, !!retval); 338strbuf_release(&buf); 339return retval; 340} 341 342/** 343 * Saves state->author_name, state->author_email and state->author_date in the 344 * state directory's "author-script" file. 345 */ 346static voidwrite_author_script(const struct am_state *state) 347{ 348struct strbuf sb = STRBUF_INIT; 349 350strbuf_addstr(&sb,"GIT_AUTHOR_NAME="); 351sq_quote_buf(&sb, state->author_name); 352strbuf_addch(&sb,'\n'); 353 354strbuf_addstr(&sb,"GIT_AUTHOR_EMAIL="); 355sq_quote_buf(&sb, state->author_email); 356strbuf_addch(&sb,'\n'); 357 358strbuf_addstr(&sb,"GIT_AUTHOR_DATE="); 359sq_quote_buf(&sb, state->author_date); 360strbuf_addch(&sb,'\n'); 361 362write_state_text(state,"author-script", sb.buf); 363 364strbuf_release(&sb); 365} 366 367/** 368 * Reads the commit message from the state directory's "final-commit" file, 369 * setting state->msg to its contents and state->msg_len to the length of its 370 * contents in bytes. 371 * 372 * Returns 0 on success, -1 if the file does not exist. 373 */ 374static intread_commit_msg(struct am_state *state) 375{ 376struct strbuf sb = STRBUF_INIT; 377 378assert(!state->msg); 379 380if(read_state_file(&sb, state,"final-commit",0) <0) { 381strbuf_release(&sb); 382return-1; 383} 384 385 state->msg =strbuf_detach(&sb, &state->msg_len); 386return0; 387} 388 389/** 390 * Saves state->msg in the state directory's "final-commit" file. 391 */ 392static voidwrite_commit_msg(const struct am_state *state) 393{ 394const char*filename =am_path(state,"final-commit"); 395write_file_buf(filename, state->msg, state->msg_len); 396} 397 398/** 399 * Loads state from disk. 400 */ 401static voidam_load(struct am_state *state) 402{ 403struct strbuf sb = STRBUF_INIT; 404 405if(read_state_file(&sb, state,"next",1) <0) 406die("BUG: state file 'next' does not exist"); 407 state->cur =strtol(sb.buf, NULL,10); 408 409if(read_state_file(&sb, state,"last",1) <0) 410die("BUG: state file 'last' does not exist"); 411 state->last =strtol(sb.buf, NULL,10); 412 413if(read_author_script(state) <0) 414die(_("could not parse author script")); 415 416read_commit_msg(state); 417 418if(read_state_file(&sb, state,"original-commit",1) <0) 419oidclr(&state->orig_commit); 420else if(get_oid_hex(sb.buf, &state->orig_commit) <0) 421die(_("could not parse%s"),am_path(state,"original-commit")); 422 423read_state_file(&sb, state,"threeway",1); 424 state->threeway = !strcmp(sb.buf,"t"); 425 426read_state_file(&sb, state,"quiet",1); 427 state->quiet = !strcmp(sb.buf,"t"); 428 429read_state_file(&sb, state,"sign",1); 430 state->signoff = !strcmp(sb.buf,"t"); 431 432read_state_file(&sb, state,"utf8",1); 433 state->utf8 = !strcmp(sb.buf,"t"); 434 435read_state_file(&sb, state,"keep",1); 436if(!strcmp(sb.buf,"t")) 437 state->keep = KEEP_TRUE; 438else if(!strcmp(sb.buf,"b")) 439 state->keep = KEEP_NON_PATCH; 440else 441 state->keep = KEEP_FALSE; 442 443read_state_file(&sb, state,"messageid",1); 444 state->message_id = !strcmp(sb.buf,"t"); 445 446read_state_file(&sb, state,"scissors",1); 447if(!strcmp(sb.buf,"t")) 448 state->scissors = SCISSORS_TRUE; 449else if(!strcmp(sb.buf,"f")) 450 state->scissors = SCISSORS_FALSE; 451else 452 state->scissors = SCISSORS_UNSET; 453 454read_state_file(&sb, state,"apply-opt",1); 455argv_array_clear(&state->git_apply_opts); 456if(sq_dequote_to_argv_array(sb.buf, &state->git_apply_opts) <0) 457die(_("could not parse%s"),am_path(state,"apply-opt")); 458 459 state->rebasing = !!file_exists(am_path(state,"rebasing")); 460 461strbuf_release(&sb); 462} 463 464/** 465 * Removes the am_state directory, forcefully terminating the current am 466 * session. 467 */ 468static voidam_destroy(const struct am_state *state) 469{ 470struct strbuf sb = STRBUF_INIT; 471 472strbuf_addstr(&sb, state->dir); 473remove_dir_recursively(&sb,0); 474strbuf_release(&sb); 475} 476 477/** 478 * Runs applypatch-msg hook. Returns its exit code. 479 */ 480static intrun_applypatch_msg_hook(struct am_state *state) 481{ 482int ret; 483 484assert(state->msg); 485 ret =run_hook_le(NULL,"applypatch-msg",am_path(state,"final-commit"), NULL); 486 487if(!ret) { 488free(state->msg); 489 state->msg = NULL; 490if(read_commit_msg(state) <0) 491die(_("'%s' was deleted by the applypatch-msg hook"), 492am_path(state,"final-commit")); 493} 494 495return ret; 496} 497 498/** 499 * Runs post-rewrite hook. Returns it exit code. 500 */ 501static intrun_post_rewrite_hook(const struct am_state *state) 502{ 503struct child_process cp = CHILD_PROCESS_INIT; 504const char*hook =find_hook("post-rewrite"); 505int ret; 506 507if(!hook) 508return0; 509 510argv_array_push(&cp.args, hook); 511argv_array_push(&cp.args,"rebase"); 512 513 cp.in =xopen(am_path(state,"rewritten"), O_RDONLY); 514 cp.stdout_to_stderr =1; 515 516 ret =run_command(&cp); 517 518close(cp.in); 519return ret; 520} 521 522/** 523 * Reads the state directory's "rewritten" file, and copies notes from the old 524 * commits listed in the file to their rewritten commits. 525 * 526 * Returns 0 on success, -1 on failure. 527 */ 528static intcopy_notes_for_rebase(const struct am_state *state) 529{ 530struct notes_rewrite_cfg *c; 531struct strbuf sb = STRBUF_INIT; 532const char*invalid_line =_("Malformed input line: '%s'."); 533const char*msg ="Notes added by 'git rebase'"; 534FILE*fp; 535int ret =0; 536 537assert(state->rebasing); 538 539 c =init_copy_notes_for_rewrite("rebase"); 540if(!c) 541return0; 542 543 fp =xfopen(am_path(state,"rewritten"),"r"); 544 545while(!strbuf_getline_lf(&sb, fp)) { 546struct object_id from_obj, to_obj; 547 548if(sb.len != GIT_SHA1_HEXSZ *2+1) { 549 ret =error(invalid_line, sb.buf); 550goto finish; 551} 552 553if(get_oid_hex(sb.buf, &from_obj)) { 554 ret =error(invalid_line, sb.buf); 555goto finish; 556} 557 558if(sb.buf[GIT_SHA1_HEXSZ] !=' ') { 559 ret =error(invalid_line, sb.buf); 560goto finish; 561} 562 563if(get_oid_hex(sb.buf + GIT_SHA1_HEXSZ +1, &to_obj)) { 564 ret =error(invalid_line, sb.buf); 565goto finish; 566} 567 568if(copy_note_for_rewrite(c, from_obj.hash, to_obj.hash)) 569 ret =error(_("Failed to copy notes from '%s' to '%s'"), 570oid_to_hex(&from_obj),oid_to_hex(&to_obj)); 571} 572 573finish: 574finish_copy_notes_for_rewrite(c, msg); 575fclose(fp); 576strbuf_release(&sb); 577return ret; 578} 579 580/** 581 * Determines if the file looks like a piece of RFC2822 mail by grabbing all 582 * non-indented lines and checking if they look like they begin with valid 583 * header field names. 584 * 585 * Returns 1 if the file looks like a piece of mail, 0 otherwise. 586 */ 587static intis_mail(FILE*fp) 588{ 589const char*header_regex ="^[!-9;-~]+:"; 590struct strbuf sb = STRBUF_INIT; 591 regex_t regex; 592int ret =1; 593 594if(fseek(fp,0L, SEEK_SET)) 595die_errno(_("fseek failed")); 596 597if(regcomp(®ex, header_regex, REG_NOSUB | REG_EXTENDED)) 598die("invalid pattern:%s", header_regex); 599 600while(!strbuf_getline(&sb, fp)) { 601if(!sb.len) 602break;/* End of header */ 603 604/* Ignore indented folded lines */ 605if(*sb.buf =='\t'|| *sb.buf ==' ') 606continue; 607 608/* It's a header if it matches header_regex */ 609if(regexec(®ex, sb.buf,0, NULL,0)) { 610 ret =0; 611goto done; 612} 613} 614 615done: 616regfree(®ex); 617strbuf_release(&sb); 618return ret; 619} 620 621/** 622 * Attempts to detect the patch_format of the patches contained in `paths`, 623 * returning the PATCH_FORMAT_* enum value. Returns PATCH_FORMAT_UNKNOWN if 624 * detection fails. 625 */ 626static intdetect_patch_format(const char**paths) 627{ 628enum patch_format ret = PATCH_FORMAT_UNKNOWN; 629struct strbuf l1 = STRBUF_INIT; 630struct strbuf l2 = STRBUF_INIT; 631struct strbuf l3 = STRBUF_INIT; 632FILE*fp; 633 634/* 635 * We default to mbox format if input is from stdin and for directories 636 */ 637if(!*paths || !strcmp(*paths,"-") ||is_directory(*paths)) 638return PATCH_FORMAT_MBOX; 639 640/* 641 * Otherwise, check the first few lines of the first patch, starting 642 * from the first non-blank line, to try to detect its format. 643 */ 644 645 fp =xfopen(*paths,"r"); 646 647while(!strbuf_getline(&l1, fp)) { 648if(l1.len) 649break; 650} 651 652if(starts_with(l1.buf,"From ") ||starts_with(l1.buf,"From: ")) { 653 ret = PATCH_FORMAT_MBOX; 654goto done; 655} 656 657if(starts_with(l1.buf,"# This series applies on GIT commit")) { 658 ret = PATCH_FORMAT_STGIT_SERIES; 659goto done; 660} 661 662if(!strcmp(l1.buf,"# HG changeset patch")) { 663 ret = PATCH_FORMAT_HG; 664goto done; 665} 666 667strbuf_reset(&l2); 668strbuf_getline(&l2, fp); 669strbuf_reset(&l3); 670strbuf_getline(&l3, fp); 671 672/* 673 * If the second line is empty and the third is a From, Author or Date 674 * entry, this is likely an StGit patch. 675 */ 676if(l1.len && !l2.len && 677(starts_with(l3.buf,"From:") || 678starts_with(l3.buf,"Author:") || 679starts_with(l3.buf,"Date:"))) { 680 ret = PATCH_FORMAT_STGIT; 681goto done; 682} 683 684if(l1.len &&is_mail(fp)) { 685 ret = PATCH_FORMAT_MBOX; 686goto done; 687} 688 689done: 690fclose(fp); 691strbuf_release(&l1); 692return ret; 693} 694 695/** 696 * Splits out individual email patches from `paths`, where each path is either 697 * a mbox file or a Maildir. Returns 0 on success, -1 on failure. 698 */ 699static intsplit_mail_mbox(struct am_state *state,const char**paths, 700int keep_cr,int mboxrd) 701{ 702struct child_process cp = CHILD_PROCESS_INIT; 703struct strbuf last = STRBUF_INIT; 704 705 cp.git_cmd =1; 706argv_array_push(&cp.args,"mailsplit"); 707argv_array_pushf(&cp.args,"-d%d", state->prec); 708argv_array_pushf(&cp.args,"-o%s", state->dir); 709argv_array_push(&cp.args,"-b"); 710if(keep_cr) 711argv_array_push(&cp.args,"--keep-cr"); 712if(mboxrd) 713argv_array_push(&cp.args,"--mboxrd"); 714argv_array_push(&cp.args,"--"); 715argv_array_pushv(&cp.args, paths); 716 717if(capture_command(&cp, &last,8)) 718return-1; 719 720 state->cur =1; 721 state->last =strtol(last.buf, NULL,10); 722 723return0; 724} 725 726/** 727 * Callback signature for split_mail_conv(). The foreign patch should be 728 * read from `in`, and the converted patch (in RFC2822 mail format) should be 729 * written to `out`. Return 0 on success, or -1 on failure. 730 */ 731typedefint(*mail_conv_fn)(FILE*out,FILE*in,int keep_cr); 732 733/** 734 * Calls `fn` for each file in `paths` to convert the foreign patch to the 735 * RFC2822 mail format suitable for parsing with git-mailinfo. 736 * 737 * Returns 0 on success, -1 on failure. 738 */ 739static intsplit_mail_conv(mail_conv_fn fn,struct am_state *state, 740const char**paths,int keep_cr) 741{ 742static const char*stdin_only[] = {"-", NULL}; 743int i; 744 745if(!*paths) 746 paths = stdin_only; 747 748for(i =0; *paths; paths++, i++) { 749FILE*in, *out; 750const char*mail; 751int ret; 752 753if(!strcmp(*paths,"-")) 754 in = stdin; 755else 756 in =fopen(*paths,"r"); 757 758if(!in) 759returnerror_errno(_("could not open '%s' for reading"), 760*paths); 761 762 mail =mkpath("%s/%0*d", state->dir, state->prec, i +1); 763 764 out =fopen(mail,"w"); 765if(!out) { 766if(in != stdin) 767fclose(in); 768returnerror_errno(_("could not open '%s' for writing"), 769 mail); 770} 771 772 ret =fn(out, in, keep_cr); 773 774fclose(out); 775if(in != stdin) 776fclose(in); 777 778if(ret) 779returnerror(_("could not parse patch '%s'"), *paths); 780} 781 782 state->cur =1; 783 state->last = i; 784return0; 785} 786 787/** 788 * A split_mail_conv() callback that converts an StGit patch to an RFC2822 789 * message suitable for parsing with git-mailinfo. 790 */ 791static intstgit_patch_to_mail(FILE*out,FILE*in,int keep_cr) 792{ 793struct strbuf sb = STRBUF_INIT; 794int subject_printed =0; 795 796while(!strbuf_getline_lf(&sb, in)) { 797const char*str; 798 799if(str_isspace(sb.buf)) 800continue; 801else if(skip_prefix(sb.buf,"Author:", &str)) 802fprintf(out,"From:%s\n", str); 803else if(starts_with(sb.buf,"From") ||starts_with(sb.buf,"Date")) 804fprintf(out,"%s\n", sb.buf); 805else if(!subject_printed) { 806fprintf(out,"Subject:%s\n", sb.buf); 807 subject_printed =1; 808}else{ 809fprintf(out,"\n%s\n", sb.buf); 810break; 811} 812} 813 814strbuf_reset(&sb); 815while(strbuf_fread(&sb,8192, in) >0) { 816fwrite(sb.buf,1, sb.len, out); 817strbuf_reset(&sb); 818} 819 820strbuf_release(&sb); 821return0; 822} 823 824/** 825 * This function only supports a single StGit series file in `paths`. 826 * 827 * Given an StGit series file, converts the StGit patches in the series into 828 * RFC2822 messages suitable for parsing with git-mailinfo, and queues them in 829 * the state directory. 830 * 831 * Returns 0 on success, -1 on failure. 832 */ 833static intsplit_mail_stgit_series(struct am_state *state,const char**paths, 834int keep_cr) 835{ 836const char*series_dir; 837char*series_dir_buf; 838FILE*fp; 839struct argv_array patches = ARGV_ARRAY_INIT; 840struct strbuf sb = STRBUF_INIT; 841int ret; 842 843if(!paths[0] || paths[1]) 844returnerror(_("Only one StGIT patch series can be applied at once")); 845 846 series_dir_buf =xstrdup(*paths); 847 series_dir =dirname(series_dir_buf); 848 849 fp =fopen(*paths,"r"); 850if(!fp) 851returnerror_errno(_("could not open '%s' for reading"), *paths); 852 853while(!strbuf_getline_lf(&sb, fp)) { 854if(*sb.buf =='#') 855continue;/* skip comment lines */ 856 857argv_array_push(&patches,mkpath("%s/%s", series_dir, sb.buf)); 858} 859 860fclose(fp); 861strbuf_release(&sb); 862free(series_dir_buf); 863 864 ret =split_mail_conv(stgit_patch_to_mail, state, patches.argv, keep_cr); 865 866argv_array_clear(&patches); 867return ret; 868} 869 870/** 871 * A split_patches_conv() callback that converts a mercurial patch to a RFC2822 872 * message suitable for parsing with git-mailinfo. 873 */ 874static inthg_patch_to_mail(FILE*out,FILE*in,int keep_cr) 875{ 876struct strbuf sb = STRBUF_INIT; 877 878while(!strbuf_getline_lf(&sb, in)) { 879const char*str; 880 881if(skip_prefix(sb.buf,"# User ", &str)) 882fprintf(out,"From:%s\n", str); 883else if(skip_prefix(sb.buf,"# Date ", &str)) { 884unsigned long timestamp; 885long tz, tz2; 886char*end; 887 888 errno =0; 889 timestamp =strtoul(str, &end,10); 890if(errno) 891returnerror(_("invalid timestamp")); 892 893if(!skip_prefix(end," ", &str)) 894returnerror(_("invalid Date line")); 895 896 errno =0; 897 tz =strtol(str, &end,10); 898if(errno) 899returnerror(_("invalid timezone offset")); 900 901if(*end) 902returnerror(_("invalid Date line")); 903 904/* 905 * mercurial's timezone is in seconds west of UTC, 906 * however git's timezone is in hours + minutes east of 907 * UTC. Convert it. 908 */ 909 tz2 =labs(tz) /3600*100+labs(tz) %3600/60; 910if(tz >0) 911 tz2 = -tz2; 912 913fprintf(out,"Date:%s\n",show_date(timestamp, tz2,DATE_MODE(RFC2822))); 914}else if(starts_with(sb.buf,"# ")) { 915continue; 916}else{ 917fprintf(out,"\n%s\n", sb.buf); 918break; 919} 920} 921 922strbuf_reset(&sb); 923while(strbuf_fread(&sb,8192, in) >0) { 924fwrite(sb.buf,1, sb.len, out); 925strbuf_reset(&sb); 926} 927 928strbuf_release(&sb); 929return0; 930} 931 932/** 933 * Splits a list of files/directories into individual email patches. Each path 934 * in `paths` must be a file/directory that is formatted according to 935 * `patch_format`. 936 * 937 * Once split out, the individual email patches will be stored in the state 938 * directory, with each patch's filename being its index, padded to state->prec 939 * digits. 940 * 941 * state->cur will be set to the index of the first mail, and state->last will 942 * be set to the index of the last mail. 943 * 944 * Set keep_cr to 0 to convert all lines ending with \r\n to end with \n, 1 945 * to disable this behavior, -1 to use the default configured setting. 946 * 947 * Returns 0 on success, -1 on failure. 948 */ 949static intsplit_mail(struct am_state *state,enum patch_format patch_format, 950const char**paths,int keep_cr) 951{ 952if(keep_cr <0) { 953 keep_cr =0; 954git_config_get_bool("am.keepcr", &keep_cr); 955} 956 957switch(patch_format) { 958case PATCH_FORMAT_MBOX: 959returnsplit_mail_mbox(state, paths, keep_cr,0); 960case PATCH_FORMAT_STGIT: 961returnsplit_mail_conv(stgit_patch_to_mail, state, paths, keep_cr); 962case PATCH_FORMAT_STGIT_SERIES: 963returnsplit_mail_stgit_series(state, paths, keep_cr); 964case PATCH_FORMAT_HG: 965returnsplit_mail_conv(hg_patch_to_mail, state, paths, keep_cr); 966case PATCH_FORMAT_MBOXRD: 967returnsplit_mail_mbox(state, paths, keep_cr,1); 968default: 969die("BUG: invalid patch_format"); 970} 971return-1; 972} 973 974/** 975 * Setup a new am session for applying patches 976 */ 977static voidam_setup(struct am_state *state,enum patch_format patch_format, 978const char**paths,int keep_cr) 979{ 980struct object_id curr_head; 981const char*str; 982struct strbuf sb = STRBUF_INIT; 983 984if(!patch_format) 985 patch_format =detect_patch_format(paths); 986 987if(!patch_format) { 988fprintf_ln(stderr,_("Patch format detection failed.")); 989exit(128); 990} 991 992if(mkdir(state->dir,0777) <0&& errno != EEXIST) 993die_errno(_("failed to create directory '%s'"), state->dir); 994 995if(split_mail(state, patch_format, paths, keep_cr) <0) { 996am_destroy(state); 997die(_("Failed to split patches.")); 998} 9991000if(state->rebasing)1001 state->threeway =1;10021003write_state_bool(state,"threeway", state->threeway);1004write_state_bool(state,"quiet", state->quiet);1005write_state_bool(state,"sign", state->signoff);1006write_state_bool(state,"utf8", state->utf8);10071008switch(state->keep) {1009case KEEP_FALSE:1010 str ="f";1011break;1012case KEEP_TRUE:1013 str ="t";1014break;1015case KEEP_NON_PATCH:1016 str ="b";1017break;1018default:1019die("BUG: invalid value for state->keep");1020}10211022write_state_text(state,"keep", str);1023write_state_bool(state,"messageid", state->message_id);10241025switch(state->scissors) {1026case SCISSORS_UNSET:1027 str ="";1028break;1029case SCISSORS_FALSE:1030 str ="f";1031break;1032case SCISSORS_TRUE:1033 str ="t";1034break;1035default:1036die("BUG: invalid value for state->scissors");1037}1038write_state_text(state,"scissors", str);10391040sq_quote_argv(&sb, state->git_apply_opts.argv,0);1041write_state_text(state,"apply-opt", sb.buf);10421043if(state->rebasing)1044write_state_text(state,"rebasing","");1045else1046write_state_text(state,"applying","");10471048if(!get_oid("HEAD", &curr_head)) {1049write_state_text(state,"abort-safety",oid_to_hex(&curr_head));1050if(!state->rebasing)1051update_ref_oid("am","ORIG_HEAD", &curr_head, NULL,0,1052 UPDATE_REFS_DIE_ON_ERR);1053}else{1054write_state_text(state,"abort-safety","");1055if(!state->rebasing)1056delete_ref(NULL,"ORIG_HEAD", NULL,0);1057}10581059/*1060 * NOTE: Since the "next" and "last" files determine if an am_state1061 * session is in progress, they should be written last.1062 */10631064write_state_count(state,"next", state->cur);1065write_state_count(state,"last", state->last);10661067strbuf_release(&sb);1068}10691070/**1071 * Increments the patch pointer, and cleans am_state for the application of the1072 * next patch.1073 */1074static voidam_next(struct am_state *state)1075{1076struct object_id head;10771078free(state->author_name);1079 state->author_name = NULL;10801081free(state->author_email);1082 state->author_email = NULL;10831084free(state->author_date);1085 state->author_date = NULL;10861087free(state->msg);1088 state->msg = NULL;1089 state->msg_len =0;10901091unlink(am_path(state,"author-script"));1092unlink(am_path(state,"final-commit"));10931094oidclr(&state->orig_commit);1095unlink(am_path(state,"original-commit"));10961097if(!get_oid("HEAD", &head))1098write_state_text(state,"abort-safety",oid_to_hex(&head));1099else1100write_state_text(state,"abort-safety","");11011102 state->cur++;1103write_state_count(state,"next", state->cur);1104}11051106/**1107 * Returns the filename of the current patch email.1108 */1109static const char*msgnum(const struct am_state *state)1110{1111static struct strbuf sb = STRBUF_INIT;11121113strbuf_reset(&sb);1114strbuf_addf(&sb,"%0*d", state->prec, state->cur);11151116return sb.buf;1117}11181119/**1120 * Refresh and write index.1121 */1122static voidrefresh_and_write_cache(void)1123{1124struct lock_file *lock_file =xcalloc(1,sizeof(struct lock_file));11251126hold_locked_index(lock_file, LOCK_DIE_ON_ERROR);1127refresh_cache(REFRESH_QUIET);1128if(write_locked_index(&the_index, lock_file, COMMIT_LOCK))1129die(_("unable to write index file"));1130}11311132/**1133 * Returns 1 if the index differs from HEAD, 0 otherwise. When on an unborn1134 * branch, returns 1 if there are entries in the index, 0 otherwise. If an1135 * strbuf is provided, the space-separated list of files that differ will be1136 * appended to it.1137 */1138static intindex_has_changes(struct strbuf *sb)1139{1140struct object_id head;1141int i;11421143if(!get_sha1_tree("HEAD", head.hash)) {1144struct diff_options opt;11451146diff_setup(&opt);1147DIFF_OPT_SET(&opt, EXIT_WITH_STATUS);1148if(!sb)1149DIFF_OPT_SET(&opt, QUICK);1150do_diff_cache(head.hash, &opt);1151diffcore_std(&opt);1152for(i =0; sb && i < diff_queued_diff.nr; i++) {1153if(i)1154strbuf_addch(sb,' ');1155strbuf_addstr(sb, diff_queued_diff.queue[i]->two->path);1156}1157diff_flush(&opt);1158returnDIFF_OPT_TST(&opt, HAS_CHANGES) !=0;1159}else{1160for(i =0; sb && i < active_nr; i++) {1161if(i)1162strbuf_addch(sb,' ');1163strbuf_addstr(sb, active_cache[i]->name);1164}1165return!!active_nr;1166}1167}11681169/**1170 * Dies with a user-friendly message on how to proceed after resolving the1171 * problem. This message can be overridden with state->resolvemsg.1172 */1173static void NORETURN die_user_resolve(const struct am_state *state)1174{1175if(state->resolvemsg) {1176printf_ln("%s", state->resolvemsg);1177}else{1178const char*cmdline = state->interactive ?"git am -i":"git am";11791180printf_ln(_("When you have resolved this problem, run\"%s--continue\"."), cmdline);1181printf_ln(_("If you prefer to skip this patch, run\"%s--skip\"instead."), cmdline);1182printf_ln(_("To restore the original branch and stop patching, run\"%s--abort\"."), cmdline);1183}11841185exit(128);1186}11871188static voidam_signoff(struct strbuf *sb)1189{1190char*cp;1191struct strbuf mine = STRBUF_INIT;11921193/* Does it end with our own sign-off? */1194strbuf_addf(&mine,"\n%s%s\n",1195 sign_off_header,1196fmt_name(getenv("GIT_COMMITTER_NAME"),1197getenv("GIT_COMMITTER_EMAIL")));1198if(mine.len < sb->len &&1199!strcmp(mine.buf, sb->buf + sb->len - mine.len))1200goto exit;/* no need to duplicate */12011202/* Does it have any Signed-off-by: in the text */1203for(cp = sb->buf;1204 cp && *cp && (cp =strstr(cp, sign_off_header)) != NULL;1205 cp =strchr(cp,'\n')) {1206if(sb->buf == cp || cp[-1] =='\n')1207break;1208}12091210strbuf_addstr(sb, mine.buf + !!cp);1211exit:1212strbuf_release(&mine);1213}12141215/**1216 * Appends signoff to the "msg" field of the am_state.1217 */1218static voidam_append_signoff(struct am_state *state)1219{1220struct strbuf sb = STRBUF_INIT;12211222strbuf_attach(&sb, state->msg, state->msg_len, state->msg_len);1223am_signoff(&sb);1224 state->msg =strbuf_detach(&sb, &state->msg_len);1225}12261227/**1228 * Parses `mail` using git-mailinfo, extracting its patch and authorship info.1229 * state->msg will be set to the patch message. state->author_name,1230 * state->author_email and state->author_date will be set to the patch author's1231 * name, email and date respectively. The patch body will be written to the1232 * state directory's "patch" file.1233 *1234 * Returns 1 if the patch should be skipped, 0 otherwise.1235 */1236static intparse_mail(struct am_state *state,const char*mail)1237{1238FILE*fp;1239struct strbuf sb = STRBUF_INIT;1240struct strbuf msg = STRBUF_INIT;1241struct strbuf author_name = STRBUF_INIT;1242struct strbuf author_date = STRBUF_INIT;1243struct strbuf author_email = STRBUF_INIT;1244int ret =0;1245struct mailinfo mi;12461247setup_mailinfo(&mi);12481249if(state->utf8)1250 mi.metainfo_charset =get_commit_output_encoding();1251else1252 mi.metainfo_charset = NULL;12531254switch(state->keep) {1255case KEEP_FALSE:1256break;1257case KEEP_TRUE:1258 mi.keep_subject =1;1259break;1260case KEEP_NON_PATCH:1261 mi.keep_non_patch_brackets_in_subject =1;1262break;1263default:1264die("BUG: invalid value for state->keep");1265}12661267if(state->message_id)1268 mi.add_message_id =1;12691270switch(state->scissors) {1271case SCISSORS_UNSET:1272break;1273case SCISSORS_FALSE:1274 mi.use_scissors =0;1275break;1276case SCISSORS_TRUE:1277 mi.use_scissors =1;1278break;1279default:1280die("BUG: invalid value for state->scissors");1281}12821283 mi.input =fopen(mail,"r");1284if(!mi.input)1285die("could not open input");1286 mi.output =fopen(am_path(state,"info"),"w");1287if(!mi.output)1288die("could not open output 'info'");1289if(mailinfo(&mi,am_path(state,"msg"),am_path(state,"patch")))1290die("could not parse patch");12911292fclose(mi.input);1293fclose(mi.output);12941295/* Extract message and author information */1296 fp =xfopen(am_path(state,"info"),"r");1297while(!strbuf_getline_lf(&sb, fp)) {1298const char*x;12991300if(skip_prefix(sb.buf,"Subject: ", &x)) {1301if(msg.len)1302strbuf_addch(&msg,'\n');1303strbuf_addstr(&msg, x);1304}else if(skip_prefix(sb.buf,"Author: ", &x))1305strbuf_addstr(&author_name, x);1306else if(skip_prefix(sb.buf,"Email: ", &x))1307strbuf_addstr(&author_email, x);1308else if(skip_prefix(sb.buf,"Date: ", &x))1309strbuf_addstr(&author_date, x);1310}1311fclose(fp);13121313/* Skip pine's internal folder data */1314if(!strcmp(author_name.buf,"Mail System Internal Data")) {1315 ret =1;1316goto finish;1317}13181319if(is_empty_file(am_path(state,"patch"))) {1320printf_ln(_("Patch is empty. Was it split wrong?"));1321die_user_resolve(state);1322}13231324strbuf_addstr(&msg,"\n\n");1325strbuf_addbuf(&msg, &mi.log_message);1326strbuf_stripspace(&msg,0);13271328if(state->signoff)1329am_signoff(&msg);13301331assert(!state->author_name);1332 state->author_name =strbuf_detach(&author_name, NULL);13331334assert(!state->author_email);1335 state->author_email =strbuf_detach(&author_email, NULL);13361337assert(!state->author_date);1338 state->author_date =strbuf_detach(&author_date, NULL);13391340assert(!state->msg);1341 state->msg =strbuf_detach(&msg, &state->msg_len);13421343finish:1344strbuf_release(&msg);1345strbuf_release(&author_date);1346strbuf_release(&author_email);1347strbuf_release(&author_name);1348strbuf_release(&sb);1349clear_mailinfo(&mi);1350return ret;1351}13521353/**1354 * Sets commit_id to the commit hash where the mail was generated from.1355 * Returns 0 on success, -1 on failure.1356 */1357static intget_mail_commit_oid(struct object_id *commit_id,const char*mail)1358{1359struct strbuf sb = STRBUF_INIT;1360FILE*fp =xfopen(mail,"r");1361const char*x;13621363if(strbuf_getline_lf(&sb, fp))1364return-1;13651366if(!skip_prefix(sb.buf,"From ", &x))1367return-1;13681369if(get_oid_hex(x, commit_id) <0)1370return-1;13711372strbuf_release(&sb);1373fclose(fp);1374return0;1375}13761377/**1378 * Sets state->msg, state->author_name, state->author_email, state->author_date1379 * to the commit's respective info.1380 */1381static voidget_commit_info(struct am_state *state,struct commit *commit)1382{1383const char*buffer, *ident_line, *author_date, *msg;1384size_t ident_len;1385struct ident_split ident_split;1386struct strbuf sb = STRBUF_INIT;13871388 buffer =logmsg_reencode(commit, NULL,get_commit_output_encoding());13891390 ident_line =find_commit_header(buffer,"author", &ident_len);13911392if(split_ident_line(&ident_split, ident_line, ident_len) <0) {1393strbuf_add(&sb, ident_line, ident_len);1394die(_("invalid ident line:%s"), sb.buf);1395}13961397assert(!state->author_name);1398if(ident_split.name_begin) {1399strbuf_add(&sb, ident_split.name_begin,1400 ident_split.name_end - ident_split.name_begin);1401 state->author_name =strbuf_detach(&sb, NULL);1402}else1403 state->author_name =xstrdup("");14041405assert(!state->author_email);1406if(ident_split.mail_begin) {1407strbuf_add(&sb, ident_split.mail_begin,1408 ident_split.mail_end - ident_split.mail_begin);1409 state->author_email =strbuf_detach(&sb, NULL);1410}else1411 state->author_email =xstrdup("");14121413 author_date =show_ident_date(&ident_split,DATE_MODE(NORMAL));1414strbuf_addstr(&sb, author_date);1415assert(!state->author_date);1416 state->author_date =strbuf_detach(&sb, NULL);14171418assert(!state->msg);1419 msg =strstr(buffer,"\n\n");1420if(!msg)1421die(_("unable to parse commit%s"),oid_to_hex(&commit->object.oid));1422 state->msg =xstrdup(msg +2);1423 state->msg_len =strlen(state->msg);1424}14251426/**1427 * Writes `commit` as a patch to the state directory's "patch" file.1428 */1429static voidwrite_commit_patch(const struct am_state *state,struct commit *commit)1430{1431struct rev_info rev_info;1432FILE*fp;14331434 fp =xfopen(am_path(state,"patch"),"w");1435init_revisions(&rev_info, NULL);1436 rev_info.diff =1;1437 rev_info.abbrev =0;1438 rev_info.disable_stdin =1;1439 rev_info.show_root_diff =1;1440 rev_info.diffopt.output_format = DIFF_FORMAT_PATCH;1441 rev_info.no_commit_id =1;1442DIFF_OPT_SET(&rev_info.diffopt, BINARY);1443DIFF_OPT_SET(&rev_info.diffopt, FULL_INDEX);1444 rev_info.diffopt.use_color =0;1445 rev_info.diffopt.file = fp;1446 rev_info.diffopt.close_file =1;1447add_pending_object(&rev_info, &commit->object,"");1448diff_setup_done(&rev_info.diffopt);1449log_tree_commit(&rev_info, commit);1450}14511452/**1453 * Writes the diff of the index against HEAD as a patch to the state1454 * directory's "patch" file.1455 */1456static voidwrite_index_patch(const struct am_state *state)1457{1458struct tree *tree;1459struct object_id head;1460struct rev_info rev_info;1461FILE*fp;14621463if(!get_sha1_tree("HEAD", head.hash))1464 tree =lookup_tree(head.hash);1465else1466 tree =lookup_tree(EMPTY_TREE_SHA1_BIN);14671468 fp =xfopen(am_path(state,"patch"),"w");1469init_revisions(&rev_info, NULL);1470 rev_info.diff =1;1471 rev_info.disable_stdin =1;1472 rev_info.no_commit_id =1;1473 rev_info.diffopt.output_format = DIFF_FORMAT_PATCH;1474 rev_info.diffopt.use_color =0;1475 rev_info.diffopt.file = fp;1476 rev_info.diffopt.close_file =1;1477add_pending_object(&rev_info, &tree->object,"");1478diff_setup_done(&rev_info.diffopt);1479run_diff_index(&rev_info,1);1480}14811482/**1483 * Like parse_mail(), but parses the mail by looking up its commit ID1484 * directly. This is used in --rebasing mode to bypass git-mailinfo's munging1485 * of patches.1486 *1487 * state->orig_commit will be set to the original commit ID.1488 *1489 * Will always return 0 as the patch should never be skipped.1490 */1491static intparse_mail_rebase(struct am_state *state,const char*mail)1492{1493struct commit *commit;1494struct object_id commit_oid;14951496if(get_mail_commit_oid(&commit_oid, mail) <0)1497die(_("could not parse%s"), mail);14981499 commit =lookup_commit_or_die(commit_oid.hash, mail);15001501get_commit_info(state, commit);15021503write_commit_patch(state, commit);15041505oidcpy(&state->orig_commit, &commit_oid);1506write_state_text(state,"original-commit",oid_to_hex(&commit_oid));15071508return0;1509}15101511/**1512 * Applies current patch with git-apply. Returns 0 on success, -1 otherwise. If1513 * `index_file` is not NULL, the patch will be applied to that index.1514 */1515static intrun_apply(const struct am_state *state,const char*index_file)1516{1517struct argv_array apply_paths = ARGV_ARRAY_INIT;1518struct argv_array apply_opts = ARGV_ARRAY_INIT;1519struct apply_state apply_state;1520int res, opts_left;1521static struct lock_file lock_file;1522int force_apply =0;1523int options =0;15241525if(init_apply_state(&apply_state, NULL, &lock_file))1526die("BUG: init_apply_state() failed");15271528argv_array_push(&apply_opts,"apply");1529argv_array_pushv(&apply_opts, state->git_apply_opts.argv);15301531 opts_left =apply_parse_options(apply_opts.argc, apply_opts.argv,1532&apply_state, &force_apply, &options,1533 NULL);15341535if(opts_left !=0)1536die("unknown option passed through to git apply");15371538if(index_file) {1539 apply_state.index_file = index_file;1540 apply_state.cached =1;1541}else1542 apply_state.check_index =1;15431544/*1545 * If we are allowed to fall back on 3-way merge, don't give false1546 * errors during the initial attempt.1547 */1548if(state->threeway && !index_file)1549 apply_state.apply_verbosity = verbosity_silent;15501551if(check_apply_state(&apply_state, force_apply))1552die("BUG: check_apply_state() failed");15531554argv_array_push(&apply_paths,am_path(state,"patch"));15551556 res =apply_all_patches(&apply_state, apply_paths.argc, apply_paths.argv, options);15571558argv_array_clear(&apply_paths);1559argv_array_clear(&apply_opts);1560clear_apply_state(&apply_state);15611562if(res)1563return res;15641565if(index_file) {1566/* Reload index as apply_all_patches() will have modified it. */1567discard_cache();1568read_cache_from(index_file);1569}15701571return0;1572}15731574/**1575 * Builds an index that contains just the blobs needed for a 3way merge.1576 */1577static intbuild_fake_ancestor(const struct am_state *state,const char*index_file)1578{1579struct child_process cp = CHILD_PROCESS_INIT;15801581 cp.git_cmd =1;1582argv_array_push(&cp.args,"apply");1583argv_array_pushv(&cp.args, state->git_apply_opts.argv);1584argv_array_pushf(&cp.args,"--build-fake-ancestor=%s", index_file);1585argv_array_push(&cp.args,am_path(state,"patch"));15861587if(run_command(&cp))1588return-1;15891590return0;1591}15921593/**1594 * Attempt a threeway merge, using index_path as the temporary index.1595 */1596static intfall_back_threeway(const struct am_state *state,const char*index_path)1597{1598struct object_id orig_tree, their_tree, our_tree;1599const struct object_id *bases[1] = { &orig_tree };1600struct merge_options o;1601struct commit *result;1602char*their_tree_name;16031604if(get_oid("HEAD", &our_tree) <0)1605hashcpy(our_tree.hash, EMPTY_TREE_SHA1_BIN);16061607if(build_fake_ancestor(state, index_path))1608returnerror("could not build fake ancestor");16091610discard_cache();1611read_cache_from(index_path);16121613if(write_index_as_tree(orig_tree.hash, &the_index, index_path,0, NULL))1614returnerror(_("Repository lacks necessary blobs to fall back on 3-way merge."));16151616say(state, stdout,_("Using index info to reconstruct a base tree..."));16171618if(!state->quiet) {1619/*1620 * List paths that needed 3-way fallback, so that the user can1621 * review them with extra care to spot mismerges.1622 */1623struct rev_info rev_info;1624const char*diff_filter_str ="--diff-filter=AM";16251626init_revisions(&rev_info, NULL);1627 rev_info.diffopt.output_format = DIFF_FORMAT_NAME_STATUS;1628diff_opt_parse(&rev_info.diffopt, &diff_filter_str,1, rev_info.prefix);1629add_pending_sha1(&rev_info,"HEAD", our_tree.hash,0);1630diff_setup_done(&rev_info.diffopt);1631run_diff_index(&rev_info,1);1632}16331634if(run_apply(state, index_path))1635returnerror(_("Did you hand edit your patch?\n"1636"It does not apply to blobs recorded in its index."));16371638if(write_index_as_tree(their_tree.hash, &the_index, index_path,0, NULL))1639returnerror("could not write tree");16401641say(state, stdout,_("Falling back to patching base and 3-way merge..."));16421643discard_cache();1644read_cache();16451646/*1647 * This is not so wrong. Depending on which base we picked, orig_tree1648 * may be wildly different from ours, but their_tree has the same set of1649 * wildly different changes in parts the patch did not touch, so1650 * recursive ends up canceling them, saying that we reverted all those1651 * changes.1652 */16531654init_merge_options(&o);16551656 o.branch1 ="HEAD";1657 their_tree_name =xstrfmt("%.*s",linelen(state->msg), state->msg);1658 o.branch2 = their_tree_name;16591660if(state->quiet)1661 o.verbosity =0;16621663if(merge_recursive_generic(&o, &our_tree, &their_tree,1, bases, &result)) {1664rerere(state->allow_rerere_autoupdate);1665free(their_tree_name);1666returnerror(_("Failed to merge in the changes."));1667}16681669free(their_tree_name);1670return0;1671}16721673/**1674 * Commits the current index with state->msg as the commit message and1675 * state->author_name, state->author_email and state->author_date as the author1676 * information.1677 */1678static voiddo_commit(const struct am_state *state)1679{1680struct object_id tree, parent, commit;1681const struct object_id *old_oid;1682struct commit_list *parents = NULL;1683const char*reflog_msg, *author;1684struct strbuf sb = STRBUF_INIT;16851686if(run_hook_le(NULL,"pre-applypatch", NULL))1687exit(1);16881689if(write_cache_as_tree(tree.hash,0, NULL))1690die(_("git write-tree failed to write a tree"));16911692if(!get_sha1_commit("HEAD", parent.hash)) {1693 old_oid = &parent;1694commit_list_insert(lookup_commit(parent.hash), &parents);1695}else{1696 old_oid = NULL;1697say(state, stderr,_("applying to an empty history"));1698}16991700 author =fmt_ident(state->author_name, state->author_email,1701 state->ignore_date ? NULL : state->author_date,1702 IDENT_STRICT);17031704if(state->committer_date_is_author_date)1705setenv("GIT_COMMITTER_DATE",1706 state->ignore_date ?"": state->author_date,1);17071708if(commit_tree(state->msg, state->msg_len, tree.hash, parents, commit.hash,1709 author, state->sign_commit))1710die(_("failed to write commit object"));17111712 reflog_msg =getenv("GIT_REFLOG_ACTION");1713if(!reflog_msg)1714 reflog_msg ="am";17151716strbuf_addf(&sb,"%s: %.*s", reflog_msg,linelen(state->msg),1717 state->msg);17181719update_ref_oid(sb.buf,"HEAD", &commit, old_oid,0,1720 UPDATE_REFS_DIE_ON_ERR);17211722if(state->rebasing) {1723FILE*fp =xfopen(am_path(state,"rewritten"),"a");17241725assert(!is_null_oid(&state->orig_commit));1726fprintf(fp,"%s",oid_to_hex(&state->orig_commit));1727fprintf(fp,"%s\n",oid_to_hex(&commit));1728fclose(fp);1729}17301731run_hook_le(NULL,"post-applypatch", NULL);17321733strbuf_release(&sb);1734}17351736/**1737 * Validates the am_state for resuming -- the "msg" and authorship fields must1738 * be filled up.1739 */1740static voidvalidate_resume_state(const struct am_state *state)1741{1742if(!state->msg)1743die(_("cannot resume:%sdoes not exist."),1744am_path(state,"final-commit"));17451746if(!state->author_name || !state->author_email || !state->author_date)1747die(_("cannot resume:%sdoes not exist."),1748am_path(state,"author-script"));1749}17501751/**1752 * Interactively prompt the user on whether the current patch should be1753 * applied.1754 *1755 * Returns 0 if the user chooses to apply the patch, 1 if the user chooses to1756 * skip it.1757 */1758static intdo_interactive(struct am_state *state)1759{1760assert(state->msg);17611762if(!isatty(0))1763die(_("cannot be interactive without stdin connected to a terminal."));17641765for(;;) {1766const char*reply;17671768puts(_("Commit Body is:"));1769puts("--------------------------");1770printf("%s", state->msg);1771puts("--------------------------");17721773/*1774 * TRANSLATORS: Make sure to include [y], [n], [e], [v] and [a]1775 * in your translation. The program will only accept English1776 * input at this point.1777 */1778 reply =git_prompt(_("Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all: "), PROMPT_ECHO);17791780if(!reply) {1781continue;1782}else if(*reply =='y'|| *reply =='Y') {1783return0;1784}else if(*reply =='a'|| *reply =='A') {1785 state->interactive =0;1786return0;1787}else if(*reply =='n'|| *reply =='N') {1788return1;1789}else if(*reply =='e'|| *reply =='E') {1790struct strbuf msg = STRBUF_INIT;17911792if(!launch_editor(am_path(state,"final-commit"), &msg, NULL)) {1793free(state->msg);1794 state->msg =strbuf_detach(&msg, &state->msg_len);1795}1796strbuf_release(&msg);1797}else if(*reply =='v'|| *reply =='V') {1798const char*pager =git_pager(1);1799struct child_process cp = CHILD_PROCESS_INIT;18001801if(!pager)1802 pager ="cat";1803prepare_pager_args(&cp, pager);1804argv_array_push(&cp.args,am_path(state,"patch"));1805run_command(&cp);1806}1807}1808}18091810/**1811 * Applies all queued mail.1812 *1813 * If `resume` is true, we are "resuming". The "msg" and authorship fields, as1814 * well as the state directory's "patch" file is used as-is for applying the1815 * patch and committing it.1816 */1817static voidam_run(struct am_state *state,int resume)1818{1819const char*argv_gc_auto[] = {"gc","--auto", NULL};1820struct strbuf sb = STRBUF_INIT;18211822unlink(am_path(state,"dirtyindex"));18231824refresh_and_write_cache();18251826if(index_has_changes(&sb)) {1827write_state_bool(state,"dirtyindex",1);1828die(_("Dirty index: cannot apply patches (dirty:%s)"), sb.buf);1829}18301831strbuf_release(&sb);18321833while(state->cur <= state->last) {1834const char*mail =am_path(state,msgnum(state));1835int apply_status;18361837reset_ident_date();18381839if(!file_exists(mail))1840goto next;18411842if(resume) {1843validate_resume_state(state);1844}else{1845int skip;18461847if(state->rebasing)1848 skip =parse_mail_rebase(state, mail);1849else1850 skip =parse_mail(state, mail);18511852if(skip)1853goto next;/* mail should be skipped */18541855write_author_script(state);1856write_commit_msg(state);1857}18581859if(state->interactive &&do_interactive(state))1860goto next;18611862if(run_applypatch_msg_hook(state))1863exit(1);18641865say(state, stdout,_("Applying: %.*s"),linelen(state->msg), state->msg);18661867 apply_status =run_apply(state, NULL);18681869if(apply_status && state->threeway) {1870struct strbuf sb = STRBUF_INIT;18711872strbuf_addstr(&sb,am_path(state,"patch-merge-index"));1873 apply_status =fall_back_threeway(state, sb.buf);1874strbuf_release(&sb);18751876/*1877 * Applying the patch to an earlier tree and merging1878 * the result may have produced the same tree as ours.1879 */1880if(!apply_status && !index_has_changes(NULL)) {1881say(state, stdout,_("No changes -- Patch already applied."));1882goto next;1883}1884}18851886if(apply_status) {1887int advice_amworkdir =1;18881889printf_ln(_("Patch failed at%s%.*s"),msgnum(state),1890linelen(state->msg), state->msg);18911892git_config_get_bool("advice.amworkdir", &advice_amworkdir);18931894if(advice_amworkdir)1895printf_ln(_("The copy of the patch that failed is found in:%s"),1896am_path(state,"patch"));18971898die_user_resolve(state);1899}19001901do_commit(state);19021903next:1904am_next(state);19051906if(resume)1907am_load(state);1908 resume =0;1909}19101911if(!is_empty_file(am_path(state,"rewritten"))) {1912assert(state->rebasing);1913copy_notes_for_rebase(state);1914run_post_rewrite_hook(state);1915}19161917/*1918 * In rebasing mode, it's up to the caller to take care of1919 * housekeeping.1920 */1921if(!state->rebasing) {1922am_destroy(state);1923close_all_packs();1924run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);1925}1926}19271928/**1929 * Resume the current am session after patch application failure. The user did1930 * all the hard work, and we do not have to do any patch application. Just1931 * trust and commit what the user has in the index and working tree.1932 */1933static voidam_resolve(struct am_state *state)1934{1935validate_resume_state(state);19361937say(state, stdout,_("Applying: %.*s"),linelen(state->msg), state->msg);19381939if(!index_has_changes(NULL)) {1940printf_ln(_("No changes - did you forget to use 'git add'?\n"1941"If there is nothing left to stage, chances are that something else\n"1942"already introduced the same changes; you might want to skip this patch."));1943die_user_resolve(state);1944}19451946if(unmerged_cache()) {1947printf_ln(_("You still have unmerged paths in your index.\n"1948"Did you forget to use 'git add'?"));1949die_user_resolve(state);1950}19511952if(state->interactive) {1953write_index_patch(state);1954if(do_interactive(state))1955goto next;1956}19571958rerere(0);19591960do_commit(state);19611962next:1963am_next(state);1964am_load(state);1965am_run(state,0);1966}19671968/**1969 * Performs a checkout fast-forward from `head` to `remote`. If `reset` is1970 * true, any unmerged entries will be discarded. Returns 0 on success, -1 on1971 * failure.1972 */1973static intfast_forward_to(struct tree *head,struct tree *remote,int reset)1974{1975struct lock_file *lock_file;1976struct unpack_trees_options opts;1977struct tree_desc t[2];19781979if(parse_tree(head) ||parse_tree(remote))1980return-1;19811982 lock_file =xcalloc(1,sizeof(struct lock_file));1983hold_locked_index(lock_file, LOCK_DIE_ON_ERROR);19841985refresh_cache(REFRESH_QUIET);19861987memset(&opts,0,sizeof(opts));1988 opts.head_idx =1;1989 opts.src_index = &the_index;1990 opts.dst_index = &the_index;1991 opts.update =1;1992 opts.merge =1;1993 opts.reset = reset;1994 opts.fn = twoway_merge;1995init_tree_desc(&t[0], head->buffer, head->size);1996init_tree_desc(&t[1], remote->buffer, remote->size);19971998if(unpack_trees(2, t, &opts)) {1999rollback_lock_file(lock_file);2000return-1;2001}20022003if(write_locked_index(&the_index, lock_file, COMMIT_LOCK))2004die(_("unable to write new index file"));20052006return0;2007}20082009/**2010 * Merges a tree into the index. The index's stat info will take precedence2011 * over the merged tree's. Returns 0 on success, -1 on failure.2012 */2013static intmerge_tree(struct tree *tree)2014{2015struct lock_file *lock_file;2016struct unpack_trees_options opts;2017struct tree_desc t[1];20182019if(parse_tree(tree))2020return-1;20212022 lock_file =xcalloc(1,sizeof(struct lock_file));2023hold_locked_index(lock_file, LOCK_DIE_ON_ERROR);20242025memset(&opts,0,sizeof(opts));2026 opts.head_idx =1;2027 opts.src_index = &the_index;2028 opts.dst_index = &the_index;2029 opts.merge =1;2030 opts.fn = oneway_merge;2031init_tree_desc(&t[0], tree->buffer, tree->size);20322033if(unpack_trees(1, t, &opts)) {2034rollback_lock_file(lock_file);2035return-1;2036}20372038if(write_locked_index(&the_index, lock_file, COMMIT_LOCK))2039die(_("unable to write new index file"));20402041return0;2042}20432044/**2045 * Clean the index without touching entries that are not modified between2046 * `head` and `remote`.2047 */2048static intclean_index(const struct object_id *head,const struct object_id *remote)2049{2050struct tree *head_tree, *remote_tree, *index_tree;2051struct object_id index;20522053 head_tree =parse_tree_indirect(head->hash);2054if(!head_tree)2055returnerror(_("Could not parse object '%s'."),oid_to_hex(head));20562057 remote_tree =parse_tree_indirect(remote->hash);2058if(!remote_tree)2059returnerror(_("Could not parse object '%s'."),oid_to_hex(remote));20602061read_cache_unmerged();20622063if(fast_forward_to(head_tree, head_tree,1))2064return-1;20652066if(write_cache_as_tree(index.hash,0, NULL))2067return-1;20682069 index_tree =parse_tree_indirect(index.hash);2070if(!index_tree)2071returnerror(_("Could not parse object '%s'."),oid_to_hex(&index));20722073if(fast_forward_to(index_tree, remote_tree,0))2074return-1;20752076if(merge_tree(remote_tree))2077return-1;20782079remove_branch_state();20802081return0;2082}20832084/**2085 * Resets rerere's merge resolution metadata.2086 */2087static voidam_rerere_clear(void)2088{2089struct string_list merge_rr = STRING_LIST_INIT_DUP;2090rerere_clear(&merge_rr);2091string_list_clear(&merge_rr,1);2092}20932094/**2095 * Resume the current am session by skipping the current patch.2096 */2097static voidam_skip(struct am_state *state)2098{2099struct object_id head;21002101am_rerere_clear();21022103if(get_oid("HEAD", &head))2104hashcpy(head.hash, EMPTY_TREE_SHA1_BIN);21052106if(clean_index(&head, &head))2107die(_("failed to clean index"));21082109am_next(state);2110am_load(state);2111am_run(state,0);2112}21132114/**2115 * Returns true if it is safe to reset HEAD to the ORIG_HEAD, false otherwise.2116 *2117 * It is not safe to reset HEAD when:2118 * 1. git-am previously failed because the index was dirty.2119 * 2. HEAD has moved since git-am previously failed.2120 */2121static intsafe_to_abort(const struct am_state *state)2122{2123struct strbuf sb = STRBUF_INIT;2124struct object_id abort_safety, head;21252126if(file_exists(am_path(state,"dirtyindex")))2127return0;21282129if(read_state_file(&sb, state,"abort-safety",1) >0) {2130if(get_oid_hex(sb.buf, &abort_safety))2131die(_("could not parse%s"),am_path(state,"abort-safety"));2132}else2133oidclr(&abort_safety);21342135if(get_oid("HEAD", &head))2136oidclr(&head);21372138if(!oidcmp(&head, &abort_safety))2139return1;21402141warning(_("You seem to have moved HEAD since the last 'am' failure.\n"2142"Not rewinding to ORIG_HEAD"));21432144return0;2145}21462147/**2148 * Aborts the current am session if it is safe to do so.2149 */2150static voidam_abort(struct am_state *state)2151{2152struct object_id curr_head, orig_head;2153int has_curr_head, has_orig_head;2154char*curr_branch;21552156if(!safe_to_abort(state)) {2157am_destroy(state);2158return;2159}21602161am_rerere_clear();21622163 curr_branch =resolve_refdup("HEAD",0, curr_head.hash, NULL);2164 has_curr_head = !is_null_oid(&curr_head);2165if(!has_curr_head)2166hashcpy(curr_head.hash, EMPTY_TREE_SHA1_BIN);21672168 has_orig_head = !get_oid("ORIG_HEAD", &orig_head);2169if(!has_orig_head)2170hashcpy(orig_head.hash, EMPTY_TREE_SHA1_BIN);21712172clean_index(&curr_head, &orig_head);21732174if(has_orig_head)2175update_ref_oid("am --abort","HEAD", &orig_head,2176 has_curr_head ? &curr_head : NULL,0,2177 UPDATE_REFS_DIE_ON_ERR);2178else if(curr_branch)2179delete_ref(NULL, curr_branch, NULL, REF_NODEREF);21802181free(curr_branch);2182am_destroy(state);2183}21842185/**2186 * parse_options() callback that validates and sets opt->value to the2187 * PATCH_FORMAT_* enum value corresponding to `arg`.2188 */2189static intparse_opt_patchformat(const struct option *opt,const char*arg,int unset)2190{2191int*opt_value = opt->value;21922193if(!strcmp(arg,"mbox"))2194*opt_value = PATCH_FORMAT_MBOX;2195else if(!strcmp(arg,"stgit"))2196*opt_value = PATCH_FORMAT_STGIT;2197else if(!strcmp(arg,"stgit-series"))2198*opt_value = PATCH_FORMAT_STGIT_SERIES;2199else if(!strcmp(arg,"hg"))2200*opt_value = PATCH_FORMAT_HG;2201else if(!strcmp(arg,"mboxrd"))2202*opt_value = PATCH_FORMAT_MBOXRD;2203else2204returnerror(_("Invalid value for --patch-format:%s"), arg);2205return0;2206}22072208enum resume_mode {2209 RESUME_FALSE =0,2210 RESUME_APPLY,2211 RESUME_RESOLVED,2212 RESUME_SKIP,2213 RESUME_ABORT2214};22152216static intgit_am_config(const char*k,const char*v,void*cb)2217{2218int status;22192220 status =git_gpg_config(k, v, NULL);2221if(status)2222return status;22232224returngit_default_config(k, v, NULL);2225}22262227intcmd_am(int argc,const char**argv,const char*prefix)2228{2229struct am_state state;2230int binary = -1;2231int keep_cr = -1;2232int patch_format = PATCH_FORMAT_UNKNOWN;2233enum resume_mode resume = RESUME_FALSE;2234int in_progress;22352236const char*const usage[] = {2237N_("git am [<options>] [(<mbox> | <Maildir>)...]"),2238N_("git am [<options>] (--continue | --skip | --abort)"),2239 NULL2240};22412242struct option options[] = {2243OPT_BOOL('i',"interactive", &state.interactive,2244N_("run interactively")),2245OPT_HIDDEN_BOOL('b',"binary", &binary,2246N_("historical option -- no-op")),2247OPT_BOOL('3',"3way", &state.threeway,2248N_("allow fall back on 3way merging if needed")),2249OPT__QUIET(&state.quiet,N_("be quiet")),2250OPT_SET_INT('s',"signoff", &state.signoff,2251N_("add a Signed-off-by line to the commit message"),2252 SIGNOFF_EXPLICIT),2253OPT_BOOL('u',"utf8", &state.utf8,2254N_("recode into utf8 (default)")),2255OPT_SET_INT('k',"keep", &state.keep,2256N_("pass -k flag to git-mailinfo"), KEEP_TRUE),2257OPT_SET_INT(0,"keep-non-patch", &state.keep,2258N_("pass -b flag to git-mailinfo"), KEEP_NON_PATCH),2259OPT_BOOL('m',"message-id", &state.message_id,2260N_("pass -m flag to git-mailinfo")),2261{ OPTION_SET_INT,0,"keep-cr", &keep_cr, NULL,2262N_("pass --keep-cr flag to git-mailsplit for mbox format"),2263 PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL,1},2264{ OPTION_SET_INT,0,"no-keep-cr", &keep_cr, NULL,2265N_("do not pass --keep-cr flag to git-mailsplit independent of am.keepcr"),2266 PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL,0},2267OPT_BOOL('c',"scissors", &state.scissors,2268N_("strip everything before a scissors line")),2269OPT_PASSTHRU_ARGV(0,"whitespace", &state.git_apply_opts,N_("action"),2270N_("pass it through git-apply"),22710),2272OPT_PASSTHRU_ARGV(0,"ignore-space-change", &state.git_apply_opts, NULL,2273N_("pass it through git-apply"),2274 PARSE_OPT_NOARG),2275OPT_PASSTHRU_ARGV(0,"ignore-whitespace", &state.git_apply_opts, NULL,2276N_("pass it through git-apply"),2277 PARSE_OPT_NOARG),2278OPT_PASSTHRU_ARGV(0,"directory", &state.git_apply_opts,N_("root"),2279N_("pass it through git-apply"),22800),2281OPT_PASSTHRU_ARGV(0,"exclude", &state.git_apply_opts,N_("path"),2282N_("pass it through git-apply"),22830),2284OPT_PASSTHRU_ARGV(0,"include", &state.git_apply_opts,N_("path"),2285N_("pass it through git-apply"),22860),2287OPT_PASSTHRU_ARGV('C', NULL, &state.git_apply_opts,N_("n"),2288N_("pass it through git-apply"),22890),2290OPT_PASSTHRU_ARGV('p', NULL, &state.git_apply_opts,N_("num"),2291N_("pass it through git-apply"),22920),2293OPT_CALLBACK(0,"patch-format", &patch_format,N_("format"),2294N_("format the patch(es) are in"),2295 parse_opt_patchformat),2296OPT_PASSTHRU_ARGV(0,"reject", &state.git_apply_opts, NULL,2297N_("pass it through git-apply"),2298 PARSE_OPT_NOARG),2299OPT_STRING(0,"resolvemsg", &state.resolvemsg, NULL,2300N_("override error message when patch failure occurs")),2301OPT_CMDMODE(0,"continue", &resume,2302N_("continue applying patches after resolving a conflict"),2303 RESUME_RESOLVED),2304OPT_CMDMODE('r',"resolved", &resume,2305N_("synonyms for --continue"),2306 RESUME_RESOLVED),2307OPT_CMDMODE(0,"skip", &resume,2308N_("skip the current patch"),2309 RESUME_SKIP),2310OPT_CMDMODE(0,"abort", &resume,2311N_("restore the original branch and abort the patching operation."),2312 RESUME_ABORT),2313OPT_BOOL(0,"committer-date-is-author-date",2314&state.committer_date_is_author_date,2315N_("lie about committer date")),2316OPT_BOOL(0,"ignore-date", &state.ignore_date,2317N_("use current timestamp for author date")),2318OPT_RERERE_AUTOUPDATE(&state.allow_rerere_autoupdate),2319{ OPTION_STRING,'S',"gpg-sign", &state.sign_commit,N_("key-id"),2320N_("GPG-sign commits"),2321 PARSE_OPT_OPTARG, NULL, (intptr_t)""},2322OPT_HIDDEN_BOOL(0,"rebasing", &state.rebasing,2323N_("(internal use for git-rebase)")),2324OPT_END()2325};23262327git_config(git_am_config, NULL);23282329am_state_init(&state,git_path("rebase-apply"));23302331 in_progress =am_in_progress(&state);2332if(in_progress)2333am_load(&state);23342335 argc =parse_options(argc, argv, prefix, options, usage,0);23362337if(binary >=0)2338fprintf_ln(stderr,_("The -b/--binary option has been a no-op for long time, and\n"2339"it will be removed. Please do not use it anymore."));23402341/* Ensure a valid committer ident can be constructed */2342git_committer_info(IDENT_STRICT);23432344if(read_index_preload(&the_index, NULL) <0)2345die(_("failed to read the index"));23462347if(in_progress) {2348/*2349 * Catch user error to feed us patches when there is a session2350 * in progress:2351 *2352 * 1. mbox path(s) are provided on the command-line.2353 * 2. stdin is not a tty: the user is trying to feed us a patch2354 * from standard input. This is somewhat unreliable -- stdin2355 * could be /dev/null for example and the caller did not2356 * intend to feed us a patch but wanted to continue2357 * unattended.2358 */2359if(argc || (resume == RESUME_FALSE && !isatty(0)))2360die(_("previous rebase directory%sstill exists but mbox given."),2361 state.dir);23622363if(resume == RESUME_FALSE)2364 resume = RESUME_APPLY;23652366if(state.signoff == SIGNOFF_EXPLICIT)2367am_append_signoff(&state);2368}else{2369struct argv_array paths = ARGV_ARRAY_INIT;2370int i;23712372/*2373 * Handle stray state directory in the independent-run case. In2374 * the --rebasing case, it is up to the caller to take care of2375 * stray directories.2376 */2377if(file_exists(state.dir) && !state.rebasing) {2378if(resume == RESUME_ABORT) {2379am_destroy(&state);2380am_state_release(&state);2381return0;2382}23832384die(_("Stray%sdirectory found.\n"2385"Use\"git am --abort\"to remove it."),2386 state.dir);2387}23882389if(resume)2390die(_("Resolve operation not in progress, we are not resuming."));23912392for(i =0; i < argc; i++) {2393if(is_absolute_path(argv[i]) || !prefix)2394argv_array_push(&paths, argv[i]);2395else2396argv_array_push(&paths,mkpath("%s/%s", prefix, argv[i]));2397}23982399am_setup(&state, patch_format, paths.argv, keep_cr);24002401argv_array_clear(&paths);2402}24032404switch(resume) {2405case RESUME_FALSE:2406am_run(&state,0);2407break;2408case RESUME_APPLY:2409am_run(&state,1);2410break;2411case RESUME_RESOLVED:2412am_resolve(&state);2413break;2414case RESUME_SKIP:2415am_skip(&state);2416break;2417case RESUME_ABORT:2418am_abort(&state);2419break;2420default:2421die("BUG: invalid resume value");2422}24232424am_state_release(&state);24252426return0;2427}