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 32/** 33 * Returns 1 if the file is empty or does not exist, 0 otherwise. 34 */ 35static intis_empty_file(const char*filename) 36{ 37struct stat st; 38 39if(stat(filename, &st) <0) { 40if(errno == ENOENT) 41return1; 42die_errno(_("could not stat%s"), filename); 43} 44 45return!st.st_size; 46} 47 48/** 49 * Returns the length of the first line of msg. 50 */ 51static intlinelen(const char*msg) 52{ 53returnstrchrnul(msg,'\n') - msg; 54} 55 56/** 57 * Returns true if `str` consists of only whitespace, false otherwise. 58 */ 59static intstr_isspace(const char*str) 60{ 61for(; *str; str++) 62if(!isspace(*str)) 63return0; 64 65return1; 66} 67 68enum patch_format { 69 PATCH_FORMAT_UNKNOWN =0, 70 PATCH_FORMAT_MBOX, 71 PATCH_FORMAT_STGIT, 72 PATCH_FORMAT_STGIT_SERIES, 73 PATCH_FORMAT_HG, 74 PATCH_FORMAT_MBOXRD 75}; 76 77enum keep_type { 78 KEEP_FALSE =0, 79 KEEP_TRUE,/* pass -k flag to git-mailinfo */ 80 KEEP_NON_PATCH /* pass -b flag to git-mailinfo */ 81}; 82 83enum scissors_type { 84 SCISSORS_UNSET = -1, 85 SCISSORS_FALSE =0,/* pass --no-scissors to git-mailinfo */ 86 SCISSORS_TRUE /* pass --scissors to git-mailinfo */ 87}; 88 89enum signoff_type { 90 SIGNOFF_FALSE =0, 91 SIGNOFF_TRUE =1, 92 SIGNOFF_EXPLICIT /* --signoff was set on the command-line */ 93}; 94 95struct am_state { 96/* state directory path */ 97char*dir; 98 99/* current and last patch numbers, 1-indexed */ 100int cur; 101int last; 102 103/* commit metadata and message */ 104char*author_name; 105char*author_email; 106char*author_date; 107char*msg; 108size_t msg_len; 109 110/* when --rebasing, records the original commit the patch came from */ 111unsigned char orig_commit[GIT_SHA1_RAWSZ]; 112 113/* number of digits in patch filename */ 114int prec; 115 116/* various operating modes and command line options */ 117int interactive; 118int threeway; 119int quiet; 120int signoff;/* enum signoff_type */ 121int utf8; 122int keep;/* enum keep_type */ 123int message_id; 124int scissors;/* enum scissors_type */ 125struct argv_array git_apply_opts; 126const char*resolvemsg; 127int committer_date_is_author_date; 128int ignore_date; 129int allow_rerere_autoupdate; 130const char*sign_commit; 131int rebasing; 132}; 133 134/** 135 * Initializes am_state with the default values. The state directory is set to 136 * dir. 137 */ 138static voidam_state_init(struct am_state *state,const char*dir) 139{ 140int gpgsign; 141 142memset(state,0,sizeof(*state)); 143 144assert(dir); 145 state->dir =xstrdup(dir); 146 147 state->prec =4; 148 149git_config_get_bool("am.threeway", &state->threeway); 150 151 state->utf8 =1; 152 153git_config_get_bool("am.messageid", &state->message_id); 154 155 state->scissors = SCISSORS_UNSET; 156 157argv_array_init(&state->git_apply_opts); 158 159if(!git_config_get_bool("commit.gpgsign", &gpgsign)) 160 state->sign_commit = gpgsign ?"": NULL; 161} 162 163/** 164 * Releases memory allocated by an am_state. 165 */ 166static voidam_state_release(struct am_state *state) 167{ 168free(state->dir); 169free(state->author_name); 170free(state->author_email); 171free(state->author_date); 172free(state->msg); 173argv_array_clear(&state->git_apply_opts); 174} 175 176/** 177 * Returns path relative to the am_state directory. 178 */ 179staticinlineconst char*am_path(const struct am_state *state,const char*path) 180{ 181returnmkpath("%s/%s", state->dir, path); 182} 183 184/** 185 * For convenience to call write_file() 186 */ 187static intwrite_state_text(const struct am_state *state, 188const char*name,const char*string) 189{ 190returnwrite_file(am_path(state, name),"%s", string); 191} 192 193static intwrite_state_count(const struct am_state *state, 194const char*name,int value) 195{ 196returnwrite_file(am_path(state, name),"%d", value); 197} 198 199static intwrite_state_bool(const struct am_state *state, 200const char*name,int value) 201{ 202returnwrite_state_text(state, name, value ?"t":"f"); 203} 204 205/** 206 * If state->quiet is false, calls fprintf(fp, fmt, ...), and appends a newline 207 * at the end. 208 */ 209static voidsay(const struct am_state *state,FILE*fp,const char*fmt, ...) 210{ 211va_list ap; 212 213va_start(ap, fmt); 214if(!state->quiet) { 215vfprintf(fp, fmt, ap); 216putc('\n', fp); 217} 218va_end(ap); 219} 220 221/** 222 * Returns 1 if there is an am session in progress, 0 otherwise. 223 */ 224static intam_in_progress(const struct am_state *state) 225{ 226struct stat st; 227 228if(lstat(state->dir, &st) <0|| !S_ISDIR(st.st_mode)) 229return0; 230if(lstat(am_path(state,"last"), &st) || !S_ISREG(st.st_mode)) 231return0; 232if(lstat(am_path(state,"next"), &st) || !S_ISREG(st.st_mode)) 233return0; 234return1; 235} 236 237/** 238 * Reads the contents of `file` in the `state` directory into `sb`. Returns the 239 * number of bytes read on success, -1 if the file does not exist. If `trim` is 240 * set, trailing whitespace will be removed. 241 */ 242static intread_state_file(struct strbuf *sb,const struct am_state *state, 243const char*file,int trim) 244{ 245strbuf_reset(sb); 246 247if(strbuf_read_file(sb,am_path(state, file),0) >=0) { 248if(trim) 249strbuf_trim(sb); 250 251return sb->len; 252} 253 254if(errno == ENOENT) 255return-1; 256 257die_errno(_("could not read '%s'"),am_path(state, file)); 258} 259 260/** 261 * Reads a KEY=VALUE shell variable assignment from `fp`, returning the VALUE 262 * as a newly-allocated string. VALUE must be a quoted string, and the KEY must 263 * match `key`. Returns NULL on failure. 264 * 265 * This is used by read_author_script() to read the GIT_AUTHOR_* variables from 266 * the author-script. 267 */ 268static char*read_shell_var(FILE*fp,const char*key) 269{ 270struct strbuf sb = STRBUF_INIT; 271const char*str; 272 273if(strbuf_getline_lf(&sb, fp)) 274goto fail; 275 276if(!skip_prefix(sb.buf, key, &str)) 277goto fail; 278 279if(!skip_prefix(str,"=", &str)) 280goto fail; 281 282strbuf_remove(&sb,0, str - sb.buf); 283 284 str =sq_dequote(sb.buf); 285if(!str) 286goto fail; 287 288returnstrbuf_detach(&sb, NULL); 289 290fail: 291strbuf_release(&sb); 292return NULL; 293} 294 295/** 296 * Reads and parses the state directory's "author-script" file, and sets 297 * state->author_name, state->author_email and state->author_date accordingly. 298 * Returns 0 on success, -1 if the file could not be parsed. 299 * 300 * The author script is of the format: 301 * 302 * GIT_AUTHOR_NAME='$author_name' 303 * GIT_AUTHOR_EMAIL='$author_email' 304 * GIT_AUTHOR_DATE='$author_date' 305 * 306 * where $author_name, $author_email and $author_date are quoted. We are strict 307 * with our parsing, as the file was meant to be eval'd in the old git-am.sh 308 * script, and thus if the file differs from what this function expects, it is 309 * better to bail out than to do something that the user does not expect. 310 */ 311static intread_author_script(struct am_state *state) 312{ 313const char*filename =am_path(state,"author-script"); 314FILE*fp; 315 316assert(!state->author_name); 317assert(!state->author_email); 318assert(!state->author_date); 319 320 fp =fopen(filename,"r"); 321if(!fp) { 322if(errno == ENOENT) 323return0; 324die_errno(_("could not open '%s' for reading"), filename); 325} 326 327 state->author_name =read_shell_var(fp,"GIT_AUTHOR_NAME"); 328if(!state->author_name) { 329fclose(fp); 330return-1; 331} 332 333 state->author_email =read_shell_var(fp,"GIT_AUTHOR_EMAIL"); 334if(!state->author_email) { 335fclose(fp); 336return-1; 337} 338 339 state->author_date =read_shell_var(fp,"GIT_AUTHOR_DATE"); 340if(!state->author_date) { 341fclose(fp); 342return-1; 343} 344 345if(fgetc(fp) != EOF) { 346fclose(fp); 347return-1; 348} 349 350fclose(fp); 351return0; 352} 353 354/** 355 * Saves state->author_name, state->author_email and state->author_date in the 356 * state directory's "author-script" file. 357 */ 358static voidwrite_author_script(const struct am_state *state) 359{ 360struct strbuf sb = STRBUF_INIT; 361 362strbuf_addstr(&sb,"GIT_AUTHOR_NAME="); 363sq_quote_buf(&sb, state->author_name); 364strbuf_addch(&sb,'\n'); 365 366strbuf_addstr(&sb,"GIT_AUTHOR_EMAIL="); 367sq_quote_buf(&sb, state->author_email); 368strbuf_addch(&sb,'\n'); 369 370strbuf_addstr(&sb,"GIT_AUTHOR_DATE="); 371sq_quote_buf(&sb, state->author_date); 372strbuf_addch(&sb,'\n'); 373 374write_state_text(state,"author-script", sb.buf); 375 376strbuf_release(&sb); 377} 378 379/** 380 * Reads the commit message from the state directory's "final-commit" file, 381 * setting state->msg to its contents and state->msg_len to the length of its 382 * contents in bytes. 383 * 384 * Returns 0 on success, -1 if the file does not exist. 385 */ 386static intread_commit_msg(struct am_state *state) 387{ 388struct strbuf sb = STRBUF_INIT; 389 390assert(!state->msg); 391 392if(read_state_file(&sb, state,"final-commit",0) <0) { 393strbuf_release(&sb); 394return-1; 395} 396 397 state->msg =strbuf_detach(&sb, &state->msg_len); 398return0; 399} 400 401/** 402 * Saves state->msg in the state directory's "final-commit" file. 403 */ 404static voidwrite_commit_msg(const struct am_state *state) 405{ 406int fd; 407const char*filename =am_path(state,"final-commit"); 408 409 fd =xopen(filename, O_WRONLY | O_CREAT,0666); 410if(write_in_full(fd, state->msg, state->msg_len) <0) 411die_errno(_("could not write to%s"), filename); 412close(fd); 413} 414 415/** 416 * Loads state from disk. 417 */ 418static voidam_load(struct am_state *state) 419{ 420struct strbuf sb = STRBUF_INIT; 421 422if(read_state_file(&sb, state,"next",1) <0) 423die("BUG: state file 'next' does not exist"); 424 state->cur =strtol(sb.buf, NULL,10); 425 426if(read_state_file(&sb, state,"last",1) <0) 427die("BUG: state file 'last' does not exist"); 428 state->last =strtol(sb.buf, NULL,10); 429 430if(read_author_script(state) <0) 431die(_("could not parse author script")); 432 433read_commit_msg(state); 434 435if(read_state_file(&sb, state,"original-commit",1) <0) 436hashclr(state->orig_commit); 437else if(get_sha1_hex(sb.buf, state->orig_commit) <0) 438die(_("could not parse%s"),am_path(state,"original-commit")); 439 440read_state_file(&sb, state,"threeway",1); 441 state->threeway = !strcmp(sb.buf,"t"); 442 443read_state_file(&sb, state,"quiet",1); 444 state->quiet = !strcmp(sb.buf,"t"); 445 446read_state_file(&sb, state,"sign",1); 447 state->signoff = !strcmp(sb.buf,"t"); 448 449read_state_file(&sb, state,"utf8",1); 450 state->utf8 = !strcmp(sb.buf,"t"); 451 452read_state_file(&sb, state,"keep",1); 453if(!strcmp(sb.buf,"t")) 454 state->keep = KEEP_TRUE; 455else if(!strcmp(sb.buf,"b")) 456 state->keep = KEEP_NON_PATCH; 457else 458 state->keep = KEEP_FALSE; 459 460read_state_file(&sb, state,"messageid",1); 461 state->message_id = !strcmp(sb.buf,"t"); 462 463read_state_file(&sb, state,"scissors",1); 464if(!strcmp(sb.buf,"t")) 465 state->scissors = SCISSORS_TRUE; 466else if(!strcmp(sb.buf,"f")) 467 state->scissors = SCISSORS_FALSE; 468else 469 state->scissors = SCISSORS_UNSET; 470 471read_state_file(&sb, state,"apply-opt",1); 472argv_array_clear(&state->git_apply_opts); 473if(sq_dequote_to_argv_array(sb.buf, &state->git_apply_opts) <0) 474die(_("could not parse%s"),am_path(state,"apply-opt")); 475 476 state->rebasing = !!file_exists(am_path(state,"rebasing")); 477 478strbuf_release(&sb); 479} 480 481/** 482 * Removes the am_state directory, forcefully terminating the current am 483 * session. 484 */ 485static voidam_destroy(const struct am_state *state) 486{ 487struct strbuf sb = STRBUF_INIT; 488 489strbuf_addstr(&sb, state->dir); 490remove_dir_recursively(&sb,0); 491strbuf_release(&sb); 492} 493 494/** 495 * Runs applypatch-msg hook. Returns its exit code. 496 */ 497static intrun_applypatch_msg_hook(struct am_state *state) 498{ 499int ret; 500 501assert(state->msg); 502 ret =run_hook_le(NULL,"applypatch-msg",am_path(state,"final-commit"), NULL); 503 504if(!ret) { 505free(state->msg); 506 state->msg = NULL; 507if(read_commit_msg(state) <0) 508die(_("'%s' was deleted by the applypatch-msg hook"), 509am_path(state,"final-commit")); 510} 511 512return ret; 513} 514 515/** 516 * Runs post-rewrite hook. Returns it exit code. 517 */ 518static intrun_post_rewrite_hook(const struct am_state *state) 519{ 520struct child_process cp = CHILD_PROCESS_INIT; 521const char*hook =find_hook("post-rewrite"); 522int ret; 523 524if(!hook) 525return0; 526 527argv_array_push(&cp.args, hook); 528argv_array_push(&cp.args,"rebase"); 529 530 cp.in =xopen(am_path(state,"rewritten"), O_RDONLY); 531 cp.stdout_to_stderr =1; 532 533 ret =run_command(&cp); 534 535close(cp.in); 536return ret; 537} 538 539/** 540 * Reads the state directory's "rewritten" file, and copies notes from the old 541 * commits listed in the file to their rewritten commits. 542 * 543 * Returns 0 on success, -1 on failure. 544 */ 545static intcopy_notes_for_rebase(const struct am_state *state) 546{ 547struct notes_rewrite_cfg *c; 548struct strbuf sb = STRBUF_INIT; 549const char*invalid_line =_("Malformed input line: '%s'."); 550const char*msg ="Notes added by 'git rebase'"; 551FILE*fp; 552int ret =0; 553 554assert(state->rebasing); 555 556 c =init_copy_notes_for_rewrite("rebase"); 557if(!c) 558return0; 559 560 fp =xfopen(am_path(state,"rewritten"),"r"); 561 562while(!strbuf_getline_lf(&sb, fp)) { 563unsigned char from_obj[GIT_SHA1_RAWSZ], to_obj[GIT_SHA1_RAWSZ]; 564 565if(sb.len != GIT_SHA1_HEXSZ *2+1) { 566 ret =error(invalid_line, sb.buf); 567goto finish; 568} 569 570if(get_sha1_hex(sb.buf, from_obj)) { 571 ret =error(invalid_line, sb.buf); 572goto finish; 573} 574 575if(sb.buf[GIT_SHA1_HEXSZ] !=' ') { 576 ret =error(invalid_line, sb.buf); 577goto finish; 578} 579 580if(get_sha1_hex(sb.buf + GIT_SHA1_HEXSZ +1, to_obj)) { 581 ret =error(invalid_line, sb.buf); 582goto finish; 583} 584 585if(copy_note_for_rewrite(c, from_obj, to_obj)) 586 ret =error(_("Failed to copy notes from '%s' to '%s'"), 587sha1_to_hex(from_obj),sha1_to_hex(to_obj)); 588} 589 590finish: 591finish_copy_notes_for_rewrite(c, msg); 592fclose(fp); 593strbuf_release(&sb); 594return ret; 595} 596 597/** 598 * Determines if the file looks like a piece of RFC2822 mail by grabbing all 599 * non-indented lines and checking if they look like they begin with valid 600 * header field names. 601 * 602 * Returns 1 if the file looks like a piece of mail, 0 otherwise. 603 */ 604static intis_mail(FILE*fp) 605{ 606const char*header_regex ="^[!-9;-~]+:"; 607struct strbuf sb = STRBUF_INIT; 608 regex_t regex; 609int ret =1; 610 611if(fseek(fp,0L, SEEK_SET)) 612die_errno(_("fseek failed")); 613 614if(regcomp(®ex, header_regex, REG_NOSUB | REG_EXTENDED)) 615die("invalid pattern:%s", header_regex); 616 617while(!strbuf_getline(&sb, fp)) { 618if(!sb.len) 619break;/* End of header */ 620 621/* Ignore indented folded lines */ 622if(*sb.buf =='\t'|| *sb.buf ==' ') 623continue; 624 625/* It's a header if it matches header_regex */ 626if(regexec(®ex, sb.buf,0, NULL,0)) { 627 ret =0; 628goto done; 629} 630} 631 632done: 633regfree(®ex); 634strbuf_release(&sb); 635return ret; 636} 637 638/** 639 * Attempts to detect the patch_format of the patches contained in `paths`, 640 * returning the PATCH_FORMAT_* enum value. Returns PATCH_FORMAT_UNKNOWN if 641 * detection fails. 642 */ 643static intdetect_patch_format(const char**paths) 644{ 645enum patch_format ret = PATCH_FORMAT_UNKNOWN; 646struct strbuf l1 = STRBUF_INIT; 647struct strbuf l2 = STRBUF_INIT; 648struct strbuf l3 = STRBUF_INIT; 649FILE*fp; 650 651/* 652 * We default to mbox format if input is from stdin and for directories 653 */ 654if(!*paths || !strcmp(*paths,"-") ||is_directory(*paths)) 655return PATCH_FORMAT_MBOX; 656 657/* 658 * Otherwise, check the first few lines of the first patch, starting 659 * from the first non-blank line, to try to detect its format. 660 */ 661 662 fp =xfopen(*paths,"r"); 663 664while(!strbuf_getline(&l1, fp)) { 665if(l1.len) 666break; 667} 668 669if(starts_with(l1.buf,"From ") ||starts_with(l1.buf,"From: ")) { 670 ret = PATCH_FORMAT_MBOX; 671goto done; 672} 673 674if(starts_with(l1.buf,"# This series applies on GIT commit")) { 675 ret = PATCH_FORMAT_STGIT_SERIES; 676goto done; 677} 678 679if(!strcmp(l1.buf,"# HG changeset patch")) { 680 ret = PATCH_FORMAT_HG; 681goto done; 682} 683 684strbuf_reset(&l2); 685strbuf_getline(&l2, fp); 686strbuf_reset(&l3); 687strbuf_getline(&l3, fp); 688 689/* 690 * If the second line is empty and the third is a From, Author or Date 691 * entry, this is likely an StGit patch. 692 */ 693if(l1.len && !l2.len && 694(starts_with(l3.buf,"From:") || 695starts_with(l3.buf,"Author:") || 696starts_with(l3.buf,"Date:"))) { 697 ret = PATCH_FORMAT_STGIT; 698goto done; 699} 700 701if(l1.len &&is_mail(fp)) { 702 ret = PATCH_FORMAT_MBOX; 703goto done; 704} 705 706done: 707fclose(fp); 708strbuf_release(&l1); 709return ret; 710} 711 712/** 713 * Splits out individual email patches from `paths`, where each path is either 714 * a mbox file or a Maildir. Returns 0 on success, -1 on failure. 715 */ 716static intsplit_mail_mbox(struct am_state *state,const char**paths, 717int keep_cr,int mboxrd) 718{ 719struct child_process cp = CHILD_PROCESS_INIT; 720struct strbuf last = STRBUF_INIT; 721 722 cp.git_cmd =1; 723argv_array_push(&cp.args,"mailsplit"); 724argv_array_pushf(&cp.args,"-d%d", state->prec); 725argv_array_pushf(&cp.args,"-o%s", state->dir); 726argv_array_push(&cp.args,"-b"); 727if(keep_cr) 728argv_array_push(&cp.args,"--keep-cr"); 729if(mboxrd) 730argv_array_push(&cp.args,"--mboxrd"); 731argv_array_push(&cp.args,"--"); 732argv_array_pushv(&cp.args, paths); 733 734if(capture_command(&cp, &last,8)) 735return-1; 736 737 state->cur =1; 738 state->last =strtol(last.buf, NULL,10); 739 740return0; 741} 742 743/** 744 * Callback signature for split_mail_conv(). The foreign patch should be 745 * read from `in`, and the converted patch (in RFC2822 mail format) should be 746 * written to `out`. Return 0 on success, or -1 on failure. 747 */ 748typedefint(*mail_conv_fn)(FILE*out,FILE*in,int keep_cr); 749 750/** 751 * Calls `fn` for each file in `paths` to convert the foreign patch to the 752 * RFC2822 mail format suitable for parsing with git-mailinfo. 753 * 754 * Returns 0 on success, -1 on failure. 755 */ 756static intsplit_mail_conv(mail_conv_fn fn,struct am_state *state, 757const char**paths,int keep_cr) 758{ 759static const char*stdin_only[] = {"-", NULL}; 760int i; 761 762if(!*paths) 763 paths = stdin_only; 764 765for(i =0; *paths; paths++, i++) { 766FILE*in, *out; 767const char*mail; 768int ret; 769 770if(!strcmp(*paths,"-")) 771 in = stdin; 772else 773 in =fopen(*paths,"r"); 774 775if(!in) 776returnerror_errno(_("could not open '%s' for reading"), 777*paths); 778 779 mail =mkpath("%s/%0*d", state->dir, state->prec, i +1); 780 781 out =fopen(mail,"w"); 782if(!out) 783returnerror_errno(_("could not open '%s' for writing"), 784 mail); 785 786 ret =fn(out, in, keep_cr); 787 788fclose(out); 789fclose(in); 790 791if(ret) 792returnerror(_("could not parse patch '%s'"), *paths); 793} 794 795 state->cur =1; 796 state->last = i; 797return0; 798} 799 800/** 801 * A split_mail_conv() callback that converts an StGit patch to an RFC2822 802 * message suitable for parsing with git-mailinfo. 803 */ 804static intstgit_patch_to_mail(FILE*out,FILE*in,int keep_cr) 805{ 806struct strbuf sb = STRBUF_INIT; 807int subject_printed =0; 808 809while(!strbuf_getline_lf(&sb, in)) { 810const char*str; 811 812if(str_isspace(sb.buf)) 813continue; 814else if(skip_prefix(sb.buf,"Author:", &str)) 815fprintf(out,"From:%s\n", str); 816else if(starts_with(sb.buf,"From") ||starts_with(sb.buf,"Date")) 817fprintf(out,"%s\n", sb.buf); 818else if(!subject_printed) { 819fprintf(out,"Subject:%s\n", sb.buf); 820 subject_printed =1; 821}else{ 822fprintf(out,"\n%s\n", sb.buf); 823break; 824} 825} 826 827strbuf_reset(&sb); 828while(strbuf_fread(&sb,8192, in) >0) { 829fwrite(sb.buf,1, sb.len, out); 830strbuf_reset(&sb); 831} 832 833strbuf_release(&sb); 834return0; 835} 836 837/** 838 * This function only supports a single StGit series file in `paths`. 839 * 840 * Given an StGit series file, converts the StGit patches in the series into 841 * RFC2822 messages suitable for parsing with git-mailinfo, and queues them in 842 * the state directory. 843 * 844 * Returns 0 on success, -1 on failure. 845 */ 846static intsplit_mail_stgit_series(struct am_state *state,const char**paths, 847int keep_cr) 848{ 849const char*series_dir; 850char*series_dir_buf; 851FILE*fp; 852struct argv_array patches = ARGV_ARRAY_INIT; 853struct strbuf sb = STRBUF_INIT; 854int ret; 855 856if(!paths[0] || paths[1]) 857returnerror(_("Only one StGIT patch series can be applied at once")); 858 859 series_dir_buf =xstrdup(*paths); 860 series_dir =dirname(series_dir_buf); 861 862 fp =fopen(*paths,"r"); 863if(!fp) 864returnerror_errno(_("could not open '%s' for reading"), *paths); 865 866while(!strbuf_getline_lf(&sb, fp)) { 867if(*sb.buf =='#') 868continue;/* skip comment lines */ 869 870argv_array_push(&patches,mkpath("%s/%s", series_dir, sb.buf)); 871} 872 873fclose(fp); 874strbuf_release(&sb); 875free(series_dir_buf); 876 877 ret =split_mail_conv(stgit_patch_to_mail, state, patches.argv, keep_cr); 878 879argv_array_clear(&patches); 880return ret; 881} 882 883/** 884 * A split_patches_conv() callback that converts a mercurial patch to a RFC2822 885 * message suitable for parsing with git-mailinfo. 886 */ 887static inthg_patch_to_mail(FILE*out,FILE*in,int keep_cr) 888{ 889struct strbuf sb = STRBUF_INIT; 890 891while(!strbuf_getline_lf(&sb, in)) { 892const char*str; 893 894if(skip_prefix(sb.buf,"# User ", &str)) 895fprintf(out,"From:%s\n", str); 896else if(skip_prefix(sb.buf,"# Date ", &str)) { 897unsigned long timestamp; 898long tz, tz2; 899char*end; 900 901 errno =0; 902 timestamp =strtoul(str, &end,10); 903if(errno) 904returnerror(_("invalid timestamp")); 905 906if(!skip_prefix(end," ", &str)) 907returnerror(_("invalid Date line")); 908 909 errno =0; 910 tz =strtol(str, &end,10); 911if(errno) 912returnerror(_("invalid timezone offset")); 913 914if(*end) 915returnerror(_("invalid Date line")); 916 917/* 918 * mercurial's timezone is in seconds west of UTC, 919 * however git's timezone is in hours + minutes east of 920 * UTC. Convert it. 921 */ 922 tz2 =labs(tz) /3600*100+labs(tz) %3600/60; 923if(tz >0) 924 tz2 = -tz2; 925 926fprintf(out,"Date:%s\n",show_date(timestamp, tz2,DATE_MODE(RFC2822))); 927}else if(starts_with(sb.buf,"# ")) { 928continue; 929}else{ 930fprintf(out,"\n%s\n", sb.buf); 931break; 932} 933} 934 935strbuf_reset(&sb); 936while(strbuf_fread(&sb,8192, in) >0) { 937fwrite(sb.buf,1, sb.len, out); 938strbuf_reset(&sb); 939} 940 941strbuf_release(&sb); 942return0; 943} 944 945/** 946 * Splits a list of files/directories into individual email patches. Each path 947 * in `paths` must be a file/directory that is formatted according to 948 * `patch_format`. 949 * 950 * Once split out, the individual email patches will be stored in the state 951 * directory, with each patch's filename being its index, padded to state->prec 952 * digits. 953 * 954 * state->cur will be set to the index of the first mail, and state->last will 955 * be set to the index of the last mail. 956 * 957 * Set keep_cr to 0 to convert all lines ending with \r\n to end with \n, 1 958 * to disable this behavior, -1 to use the default configured setting. 959 * 960 * Returns 0 on success, -1 on failure. 961 */ 962static intsplit_mail(struct am_state *state,enum patch_format patch_format, 963const char**paths,int keep_cr) 964{ 965if(keep_cr <0) { 966 keep_cr =0; 967git_config_get_bool("am.keepcr", &keep_cr); 968} 969 970switch(patch_format) { 971case PATCH_FORMAT_MBOX: 972returnsplit_mail_mbox(state, paths, keep_cr,0); 973case PATCH_FORMAT_STGIT: 974returnsplit_mail_conv(stgit_patch_to_mail, state, paths, keep_cr); 975case PATCH_FORMAT_STGIT_SERIES: 976returnsplit_mail_stgit_series(state, paths, keep_cr); 977case PATCH_FORMAT_HG: 978returnsplit_mail_conv(hg_patch_to_mail, state, paths, keep_cr); 979case PATCH_FORMAT_MBOXRD: 980returnsplit_mail_mbox(state, paths, keep_cr,1); 981default: 982die("BUG: invalid patch_format"); 983} 984return-1; 985} 986 987/** 988 * Setup a new am session for applying patches 989 */ 990static voidam_setup(struct am_state *state,enum patch_format patch_format, 991const char**paths,int keep_cr) 992{ 993unsigned char curr_head[GIT_SHA1_RAWSZ]; 994const char*str; 995struct strbuf sb = STRBUF_INIT; 996 997if(!patch_format) 998 patch_format =detect_patch_format(paths); 9991000if(!patch_format) {1001fprintf_ln(stderr,_("Patch format detection failed."));1002exit(128);1003}10041005if(mkdir(state->dir,0777) <0&& errno != EEXIST)1006die_errno(_("failed to create directory '%s'"), state->dir);10071008if(split_mail(state, patch_format, paths, keep_cr) <0) {1009am_destroy(state);1010die(_("Failed to split patches."));1011}10121013if(state->rebasing)1014 state->threeway =1;10151016write_state_bool(state,"threeway", state->threeway);1017write_state_bool(state,"quiet", state->quiet);1018write_state_bool(state,"sign", state->signoff);1019write_state_bool(state,"utf8", state->utf8);10201021switch(state->keep) {1022case KEEP_FALSE:1023 str ="f";1024break;1025case KEEP_TRUE:1026 str ="t";1027break;1028case KEEP_NON_PATCH:1029 str ="b";1030break;1031default:1032die("BUG: invalid value for state->keep");1033}10341035write_state_text(state,"keep", str);1036write_state_bool(state,"messageid", state->message_id);10371038switch(state->scissors) {1039case SCISSORS_UNSET:1040 str ="";1041break;1042case SCISSORS_FALSE:1043 str ="f";1044break;1045case SCISSORS_TRUE:1046 str ="t";1047break;1048default:1049die("BUG: invalid value for state->scissors");1050}1051write_state_text(state,"scissors", str);10521053sq_quote_argv(&sb, state->git_apply_opts.argv,0);1054write_state_text(state,"apply-opt", sb.buf);10551056if(state->rebasing)1057write_state_text(state,"rebasing","");1058else1059write_state_text(state,"applying","");10601061if(!get_sha1("HEAD", curr_head)) {1062write_state_text(state,"abort-safety",sha1_to_hex(curr_head));1063if(!state->rebasing)1064update_ref("am","ORIG_HEAD", curr_head, NULL,0,1065 UPDATE_REFS_DIE_ON_ERR);1066}else{1067write_state_text(state,"abort-safety","");1068if(!state->rebasing)1069delete_ref("ORIG_HEAD", NULL,0);1070}10711072/*1073 * NOTE: Since the "next" and "last" files determine if an am_state1074 * session is in progress, they should be written last.1075 */10761077write_state_count(state,"next", state->cur);1078write_state_count(state,"last", state->last);10791080strbuf_release(&sb);1081}10821083/**1084 * Increments the patch pointer, and cleans am_state for the application of the1085 * next patch.1086 */1087static voidam_next(struct am_state *state)1088{1089unsigned char head[GIT_SHA1_RAWSZ];10901091free(state->author_name);1092 state->author_name = NULL;10931094free(state->author_email);1095 state->author_email = NULL;10961097free(state->author_date);1098 state->author_date = NULL;10991100free(state->msg);1101 state->msg = NULL;1102 state->msg_len =0;11031104unlink(am_path(state,"author-script"));1105unlink(am_path(state,"final-commit"));11061107hashclr(state->orig_commit);1108unlink(am_path(state,"original-commit"));11091110if(!get_sha1("HEAD", head))1111write_state_text(state,"abort-safety",sha1_to_hex(head));1112else1113write_state_text(state,"abort-safety","");11141115 state->cur++;1116write_state_count(state,"next", state->cur);1117}11181119/**1120 * Returns the filename of the current patch email.1121 */1122static const char*msgnum(const struct am_state *state)1123{1124static struct strbuf sb = STRBUF_INIT;11251126strbuf_reset(&sb);1127strbuf_addf(&sb,"%0*d", state->prec, state->cur);11281129return sb.buf;1130}11311132/**1133 * Refresh and write index.1134 */1135static voidrefresh_and_write_cache(void)1136{1137struct lock_file *lock_file =xcalloc(1,sizeof(struct lock_file));11381139hold_locked_index(lock_file,1);1140refresh_cache(REFRESH_QUIET);1141if(write_locked_index(&the_index, lock_file, COMMIT_LOCK))1142die(_("unable to write index file"));1143}11441145/**1146 * Returns 1 if the index differs from HEAD, 0 otherwise. When on an unborn1147 * branch, returns 1 if there are entries in the index, 0 otherwise. If an1148 * strbuf is provided, the space-separated list of files that differ will be1149 * appended to it.1150 */1151static intindex_has_changes(struct strbuf *sb)1152{1153unsigned char head[GIT_SHA1_RAWSZ];1154int i;11551156if(!get_sha1_tree("HEAD", head)) {1157struct diff_options opt;11581159diff_setup(&opt);1160DIFF_OPT_SET(&opt, EXIT_WITH_STATUS);1161if(!sb)1162DIFF_OPT_SET(&opt, QUICK);1163do_diff_cache(head, &opt);1164diffcore_std(&opt);1165for(i =0; sb && i < diff_queued_diff.nr; i++) {1166if(i)1167strbuf_addch(sb,' ');1168strbuf_addstr(sb, diff_queued_diff.queue[i]->two->path);1169}1170diff_flush(&opt);1171returnDIFF_OPT_TST(&opt, HAS_CHANGES) !=0;1172}else{1173for(i =0; sb && i < active_nr; i++) {1174if(i)1175strbuf_addch(sb,' ');1176strbuf_addstr(sb, active_cache[i]->name);1177}1178return!!active_nr;1179}1180}11811182/**1183 * Dies with a user-friendly message on how to proceed after resolving the1184 * problem. This message can be overridden with state->resolvemsg.1185 */1186static void NORETURN die_user_resolve(const struct am_state *state)1187{1188if(state->resolvemsg) {1189printf_ln("%s", state->resolvemsg);1190}else{1191const char*cmdline = state->interactive ?"git am -i":"git am";11921193printf_ln(_("When you have resolved this problem, run\"%s--continue\"."), cmdline);1194printf_ln(_("If you prefer to skip this patch, run\"%s--skip\"instead."), cmdline);1195printf_ln(_("To restore the original branch and stop patching, run\"%s--abort\"."), cmdline);1196}11971198exit(128);1199}12001201static voidam_signoff(struct strbuf *sb)1202{1203char*cp;1204struct strbuf mine = STRBUF_INIT;12051206/* Does it end with our own sign-off? */1207strbuf_addf(&mine,"\n%s%s\n",1208 sign_off_header,1209fmt_name(getenv("GIT_COMMITTER_NAME"),1210getenv("GIT_COMMITTER_EMAIL")));1211if(mine.len < sb->len &&1212!strcmp(mine.buf, sb->buf + sb->len - mine.len))1213goto exit;/* no need to duplicate */12141215/* Does it have any Signed-off-by: in the text */1216for(cp = sb->buf;1217 cp && *cp && (cp =strstr(cp, sign_off_header)) != NULL;1218 cp =strchr(cp,'\n')) {1219if(sb->buf == cp || cp[-1] =='\n')1220break;1221}12221223strbuf_addstr(sb, mine.buf + !!cp);1224exit:1225strbuf_release(&mine);1226}12271228/**1229 * Appends signoff to the "msg" field of the am_state.1230 */1231static voidam_append_signoff(struct am_state *state)1232{1233struct strbuf sb = STRBUF_INIT;12341235strbuf_attach(&sb, state->msg, state->msg_len, state->msg_len);1236am_signoff(&sb);1237 state->msg =strbuf_detach(&sb, &state->msg_len);1238}12391240/**1241 * Parses `mail` using git-mailinfo, extracting its patch and authorship info.1242 * state->msg will be set to the patch message. state->author_name,1243 * state->author_email and state->author_date will be set to the patch author's1244 * name, email and date respectively. The patch body will be written to the1245 * state directory's "patch" file.1246 *1247 * Returns 1 if the patch should be skipped, 0 otherwise.1248 */1249static intparse_mail(struct am_state *state,const char*mail)1250{1251FILE*fp;1252struct strbuf sb = STRBUF_INIT;1253struct strbuf msg = STRBUF_INIT;1254struct strbuf author_name = STRBUF_INIT;1255struct strbuf author_date = STRBUF_INIT;1256struct strbuf author_email = STRBUF_INIT;1257int ret =0;1258struct mailinfo mi;12591260setup_mailinfo(&mi);12611262if(state->utf8)1263 mi.metainfo_charset =get_commit_output_encoding();1264else1265 mi.metainfo_charset = NULL;12661267switch(state->keep) {1268case KEEP_FALSE:1269break;1270case KEEP_TRUE:1271 mi.keep_subject =1;1272break;1273case KEEP_NON_PATCH:1274 mi.keep_non_patch_brackets_in_subject =1;1275break;1276default:1277die("BUG: invalid value for state->keep");1278}12791280if(state->message_id)1281 mi.add_message_id =1;12821283switch(state->scissors) {1284case SCISSORS_UNSET:1285break;1286case SCISSORS_FALSE:1287 mi.use_scissors =0;1288break;1289case SCISSORS_TRUE:1290 mi.use_scissors =1;1291break;1292default:1293die("BUG: invalid value for state->scissors");1294}12951296 mi.input =fopen(mail,"r");1297if(!mi.input)1298die("could not open input");1299 mi.output =fopen(am_path(state,"info"),"w");1300if(!mi.output)1301die("could not open output 'info'");1302if(mailinfo(&mi,am_path(state,"msg"),am_path(state,"patch")))1303die("could not parse patch");13041305fclose(mi.input);1306fclose(mi.output);13071308/* Extract message and author information */1309 fp =xfopen(am_path(state,"info"),"r");1310while(!strbuf_getline_lf(&sb, fp)) {1311const char*x;13121313if(skip_prefix(sb.buf,"Subject: ", &x)) {1314if(msg.len)1315strbuf_addch(&msg,'\n');1316strbuf_addstr(&msg, x);1317}else if(skip_prefix(sb.buf,"Author: ", &x))1318strbuf_addstr(&author_name, x);1319else if(skip_prefix(sb.buf,"Email: ", &x))1320strbuf_addstr(&author_email, x);1321else if(skip_prefix(sb.buf,"Date: ", &x))1322strbuf_addstr(&author_date, x);1323}1324fclose(fp);13251326/* Skip pine's internal folder data */1327if(!strcmp(author_name.buf,"Mail System Internal Data")) {1328 ret =1;1329goto finish;1330}13311332if(is_empty_file(am_path(state,"patch"))) {1333printf_ln(_("Patch is empty. Was it split wrong?"));1334die_user_resolve(state);1335}13361337strbuf_addstr(&msg,"\n\n");1338strbuf_addbuf(&msg, &mi.log_message);1339strbuf_stripspace(&msg,0);13401341if(state->signoff)1342am_signoff(&msg);13431344assert(!state->author_name);1345 state->author_name =strbuf_detach(&author_name, NULL);13461347assert(!state->author_email);1348 state->author_email =strbuf_detach(&author_email, NULL);13491350assert(!state->author_date);1351 state->author_date =strbuf_detach(&author_date, NULL);13521353assert(!state->msg);1354 state->msg =strbuf_detach(&msg, &state->msg_len);13551356finish:1357strbuf_release(&msg);1358strbuf_release(&author_date);1359strbuf_release(&author_email);1360strbuf_release(&author_name);1361strbuf_release(&sb);1362clear_mailinfo(&mi);1363return ret;1364}13651366/**1367 * Sets commit_id to the commit hash where the mail was generated from.1368 * Returns 0 on success, -1 on failure.1369 */1370static intget_mail_commit_sha1(unsigned char*commit_id,const char*mail)1371{1372struct strbuf sb = STRBUF_INIT;1373FILE*fp =xfopen(mail,"r");1374const char*x;13751376if(strbuf_getline_lf(&sb, fp))1377return-1;13781379if(!skip_prefix(sb.buf,"From ", &x))1380return-1;13811382if(get_sha1_hex(x, commit_id) <0)1383return-1;13841385strbuf_release(&sb);1386fclose(fp);1387return0;1388}13891390/**1391 * Sets state->msg, state->author_name, state->author_email, state->author_date1392 * to the commit's respective info.1393 */1394static voidget_commit_info(struct am_state *state,struct commit *commit)1395{1396const char*buffer, *ident_line, *author_date, *msg;1397size_t ident_len;1398struct ident_split ident_split;1399struct strbuf sb = STRBUF_INIT;14001401 buffer =logmsg_reencode(commit, NULL,get_commit_output_encoding());14021403 ident_line =find_commit_header(buffer,"author", &ident_len);14041405if(split_ident_line(&ident_split, ident_line, ident_len) <0) {1406strbuf_add(&sb, ident_line, ident_len);1407die(_("invalid ident line:%s"), sb.buf);1408}14091410assert(!state->author_name);1411if(ident_split.name_begin) {1412strbuf_add(&sb, ident_split.name_begin,1413 ident_split.name_end - ident_split.name_begin);1414 state->author_name =strbuf_detach(&sb, NULL);1415}else1416 state->author_name =xstrdup("");14171418assert(!state->author_email);1419if(ident_split.mail_begin) {1420strbuf_add(&sb, ident_split.mail_begin,1421 ident_split.mail_end - ident_split.mail_begin);1422 state->author_email =strbuf_detach(&sb, NULL);1423}else1424 state->author_email =xstrdup("");14251426 author_date =show_ident_date(&ident_split,DATE_MODE(NORMAL));1427strbuf_addstr(&sb, author_date);1428assert(!state->author_date);1429 state->author_date =strbuf_detach(&sb, NULL);14301431assert(!state->msg);1432 msg =strstr(buffer,"\n\n");1433if(!msg)1434die(_("unable to parse commit%s"),oid_to_hex(&commit->object.oid));1435 state->msg =xstrdup(msg +2);1436 state->msg_len =strlen(state->msg);1437}14381439/**1440 * Writes `commit` as a patch to the state directory's "patch" file.1441 */1442static voidwrite_commit_patch(const struct am_state *state,struct commit *commit)1443{1444struct rev_info rev_info;1445FILE*fp;14461447 fp =xfopen(am_path(state,"patch"),"w");1448init_revisions(&rev_info, NULL);1449 rev_info.diff =1;1450 rev_info.abbrev =0;1451 rev_info.disable_stdin =1;1452 rev_info.show_root_diff =1;1453 rev_info.diffopt.output_format = DIFF_FORMAT_PATCH;1454 rev_info.no_commit_id =1;1455DIFF_OPT_SET(&rev_info.diffopt, BINARY);1456DIFF_OPT_SET(&rev_info.diffopt, FULL_INDEX);1457 rev_info.diffopt.use_color =0;1458 rev_info.diffopt.file = fp;1459 rev_info.diffopt.close_file =1;1460add_pending_object(&rev_info, &commit->object,"");1461diff_setup_done(&rev_info.diffopt);1462log_tree_commit(&rev_info, commit);1463}14641465/**1466 * Writes the diff of the index against HEAD as a patch to the state1467 * directory's "patch" file.1468 */1469static voidwrite_index_patch(const struct am_state *state)1470{1471struct tree *tree;1472unsigned char head[GIT_SHA1_RAWSZ];1473struct rev_info rev_info;1474FILE*fp;14751476if(!get_sha1_tree("HEAD", head))1477 tree =lookup_tree(head);1478else1479 tree =lookup_tree(EMPTY_TREE_SHA1_BIN);14801481 fp =xfopen(am_path(state,"patch"),"w");1482init_revisions(&rev_info, NULL);1483 rev_info.diff =1;1484 rev_info.disable_stdin =1;1485 rev_info.no_commit_id =1;1486 rev_info.diffopt.output_format = DIFF_FORMAT_PATCH;1487 rev_info.diffopt.use_color =0;1488 rev_info.diffopt.file = fp;1489 rev_info.diffopt.close_file =1;1490add_pending_object(&rev_info, &tree->object,"");1491diff_setup_done(&rev_info.diffopt);1492run_diff_index(&rev_info,1);1493}14941495/**1496 * Like parse_mail(), but parses the mail by looking up its commit ID1497 * directly. This is used in --rebasing mode to bypass git-mailinfo's munging1498 * of patches.1499 *1500 * state->orig_commit will be set to the original commit ID.1501 *1502 * Will always return 0 as the patch should never be skipped.1503 */1504static intparse_mail_rebase(struct am_state *state,const char*mail)1505{1506struct commit *commit;1507unsigned char commit_sha1[GIT_SHA1_RAWSZ];15081509if(get_mail_commit_sha1(commit_sha1, mail) <0)1510die(_("could not parse%s"), mail);15111512 commit =lookup_commit_or_die(commit_sha1, mail);15131514get_commit_info(state, commit);15151516write_commit_patch(state, commit);15171518hashcpy(state->orig_commit, commit_sha1);1519write_state_text(state,"original-commit",sha1_to_hex(commit_sha1));15201521return0;1522}15231524/**1525 * Applies current patch with git-apply. Returns 0 on success, -1 otherwise. If1526 * `index_file` is not NULL, the patch will be applied to that index.1527 */1528static intrun_apply(const struct am_state *state,const char*index_file)1529{1530struct child_process cp = CHILD_PROCESS_INIT;15311532 cp.git_cmd =1;15331534if(index_file)1535argv_array_pushf(&cp.env_array,"GIT_INDEX_FILE=%s", index_file);15361537/*1538 * If we are allowed to fall back on 3-way merge, don't give false1539 * errors during the initial attempt.1540 */1541if(state->threeway && !index_file) {1542 cp.no_stdout =1;1543 cp.no_stderr =1;1544}15451546argv_array_push(&cp.args,"apply");15471548argv_array_pushv(&cp.args, state->git_apply_opts.argv);15491550if(index_file)1551argv_array_push(&cp.args,"--cached");1552else1553argv_array_push(&cp.args,"--index");15541555argv_array_push(&cp.args,am_path(state,"patch"));15561557if(run_command(&cp))1558return-1;15591560/* Reload index as git-apply will have modified it. */1561discard_cache();1562read_cache_from(index_file ? index_file :get_index_file());15631564return0;1565}15661567/**1568 * Builds an index that contains just the blobs needed for a 3way merge.1569 */1570static intbuild_fake_ancestor(const struct am_state *state,const char*index_file)1571{1572struct child_process cp = CHILD_PROCESS_INIT;15731574 cp.git_cmd =1;1575argv_array_push(&cp.args,"apply");1576argv_array_pushv(&cp.args, state->git_apply_opts.argv);1577argv_array_pushf(&cp.args,"--build-fake-ancestor=%s", index_file);1578argv_array_push(&cp.args,am_path(state,"patch"));15791580if(run_command(&cp))1581return-1;15821583return0;1584}15851586/**1587 * Do the three-way merge using fake ancestor, his tree constructed1588 * from the fake ancestor and the postimage of the patch, and our1589 * state.1590 */1591static intrun_fallback_merge_recursive(const struct am_state *state,1592unsigned char*orig_tree,1593unsigned char*our_tree,1594unsigned char*his_tree)1595{1596struct child_process cp = CHILD_PROCESS_INIT;1597int status;15981599 cp.git_cmd =1;16001601argv_array_pushf(&cp.env_array,"GITHEAD_%s=%.*s",1602sha1_to_hex(his_tree),linelen(state->msg), state->msg);1603if(state->quiet)1604argv_array_push(&cp.env_array,"GIT_MERGE_VERBOSITY=0");16051606argv_array_push(&cp.args,"merge-recursive");1607argv_array_push(&cp.args,sha1_to_hex(orig_tree));1608argv_array_push(&cp.args,"--");1609argv_array_push(&cp.args,sha1_to_hex(our_tree));1610argv_array_push(&cp.args,sha1_to_hex(his_tree));16111612 status =run_command(&cp) ? (-1) :0;1613discard_cache();1614read_cache();1615return status;1616}16171618/**1619 * Attempt a threeway merge, using index_path as the temporary index.1620 */1621static intfall_back_threeway(const struct am_state *state,const char*index_path)1622{1623unsigned char orig_tree[GIT_SHA1_RAWSZ], his_tree[GIT_SHA1_RAWSZ],1624 our_tree[GIT_SHA1_RAWSZ];16251626if(get_sha1("HEAD", our_tree) <0)1627hashcpy(our_tree, EMPTY_TREE_SHA1_BIN);16281629if(build_fake_ancestor(state, index_path))1630returnerror("could not build fake ancestor");16311632discard_cache();1633read_cache_from(index_path);16341635if(write_index_as_tree(orig_tree, &the_index, index_path,0, NULL))1636returnerror(_("Repository lacks necessary blobs to fall back on 3-way merge."));16371638say(state, stdout,_("Using index info to reconstruct a base tree..."));16391640if(!state->quiet) {1641/*1642 * List paths that needed 3-way fallback, so that the user can1643 * review them with extra care to spot mismerges.1644 */1645struct rev_info rev_info;1646const char*diff_filter_str ="--diff-filter=AM";16471648init_revisions(&rev_info, NULL);1649 rev_info.diffopt.output_format = DIFF_FORMAT_NAME_STATUS;1650diff_opt_parse(&rev_info.diffopt, &diff_filter_str,1, rev_info.prefix);1651add_pending_sha1(&rev_info,"HEAD", our_tree,0);1652diff_setup_done(&rev_info.diffopt);1653run_diff_index(&rev_info,1);1654}16551656if(run_apply(state, index_path))1657returnerror(_("Did you hand edit your patch?\n"1658"It does not apply to blobs recorded in its index."));16591660if(write_index_as_tree(his_tree, &the_index, index_path,0, NULL))1661returnerror("could not write tree");16621663say(state, stdout,_("Falling back to patching base and 3-way merge..."));16641665discard_cache();1666read_cache();16671668/*1669 * This is not so wrong. Depending on which base we picked, orig_tree1670 * may be wildly different from ours, but his_tree has the same set of1671 * wildly different changes in parts the patch did not touch, so1672 * recursive ends up canceling them, saying that we reverted all those1673 * changes.1674 */16751676if(run_fallback_merge_recursive(state, orig_tree, our_tree, his_tree)) {1677rerere(state->allow_rerere_autoupdate);1678returnerror(_("Failed to merge in the changes."));1679}16801681return0;1682}16831684/**1685 * Commits the current index with state->msg as the commit message and1686 * state->author_name, state->author_email and state->author_date as the author1687 * information.1688 */1689static voiddo_commit(const struct am_state *state)1690{1691unsigned char tree[GIT_SHA1_RAWSZ], parent[GIT_SHA1_RAWSZ],1692 commit[GIT_SHA1_RAWSZ];1693unsigned char*ptr;1694struct commit_list *parents = NULL;1695const char*reflog_msg, *author;1696struct strbuf sb = STRBUF_INIT;16971698if(run_hook_le(NULL,"pre-applypatch", NULL))1699exit(1);17001701if(write_cache_as_tree(tree,0, NULL))1702die(_("git write-tree failed to write a tree"));17031704if(!get_sha1_commit("HEAD", parent)) {1705 ptr = parent;1706commit_list_insert(lookup_commit(parent), &parents);1707}else{1708 ptr = NULL;1709say(state, stderr,_("applying to an empty history"));1710}17111712 author =fmt_ident(state->author_name, state->author_email,1713 state->ignore_date ? NULL : state->author_date,1714 IDENT_STRICT);17151716if(state->committer_date_is_author_date)1717setenv("GIT_COMMITTER_DATE",1718 state->ignore_date ?"": state->author_date,1);17191720if(commit_tree(state->msg, state->msg_len, tree, parents, commit,1721 author, state->sign_commit))1722die(_("failed to write commit object"));17231724 reflog_msg =getenv("GIT_REFLOG_ACTION");1725if(!reflog_msg)1726 reflog_msg ="am";17271728strbuf_addf(&sb,"%s: %.*s", reflog_msg,linelen(state->msg),1729 state->msg);17301731update_ref(sb.buf,"HEAD", commit, ptr,0, UPDATE_REFS_DIE_ON_ERR);17321733if(state->rebasing) {1734FILE*fp =xfopen(am_path(state,"rewritten"),"a");17351736assert(!is_null_sha1(state->orig_commit));1737fprintf(fp,"%s",sha1_to_hex(state->orig_commit));1738fprintf(fp,"%s\n",sha1_to_hex(commit));1739fclose(fp);1740}17411742run_hook_le(NULL,"post-applypatch", NULL);17431744strbuf_release(&sb);1745}17461747/**1748 * Validates the am_state for resuming -- the "msg" and authorship fields must1749 * be filled up.1750 */1751static voidvalidate_resume_state(const struct am_state *state)1752{1753if(!state->msg)1754die(_("cannot resume:%sdoes not exist."),1755am_path(state,"final-commit"));17561757if(!state->author_name || !state->author_email || !state->author_date)1758die(_("cannot resume:%sdoes not exist."),1759am_path(state,"author-script"));1760}17611762/**1763 * Interactively prompt the user on whether the current patch should be1764 * applied.1765 *1766 * Returns 0 if the user chooses to apply the patch, 1 if the user chooses to1767 * skip it.1768 */1769static intdo_interactive(struct am_state *state)1770{1771assert(state->msg);17721773if(!isatty(0))1774die(_("cannot be interactive without stdin connected to a terminal."));17751776for(;;) {1777const char*reply;17781779puts(_("Commit Body is:"));1780puts("--------------------------");1781printf("%s", state->msg);1782puts("--------------------------");17831784/*1785 * TRANSLATORS: Make sure to include [y], [n], [e], [v] and [a]1786 * in your translation. The program will only accept English1787 * input at this point.1788 */1789 reply =git_prompt(_("Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all: "), PROMPT_ECHO);17901791if(!reply) {1792continue;1793}else if(*reply =='y'|| *reply =='Y') {1794return0;1795}else if(*reply =='a'|| *reply =='A') {1796 state->interactive =0;1797return0;1798}else if(*reply =='n'|| *reply =='N') {1799return1;1800}else if(*reply =='e'|| *reply =='E') {1801struct strbuf msg = STRBUF_INIT;18021803if(!launch_editor(am_path(state,"final-commit"), &msg, NULL)) {1804free(state->msg);1805 state->msg =strbuf_detach(&msg, &state->msg_len);1806}1807strbuf_release(&msg);1808}else if(*reply =='v'|| *reply =='V') {1809const char*pager =git_pager(1);1810struct child_process cp = CHILD_PROCESS_INIT;18111812if(!pager)1813 pager ="cat";1814prepare_pager_args(&cp, pager);1815argv_array_push(&cp.args,am_path(state,"patch"));1816run_command(&cp);1817}1818}1819}18201821/**1822 * Applies all queued mail.1823 *1824 * If `resume` is true, we are "resuming". The "msg" and authorship fields, as1825 * well as the state directory's "patch" file is used as-is for applying the1826 * patch and committing it.1827 */1828static voidam_run(struct am_state *state,int resume)1829{1830const char*argv_gc_auto[] = {"gc","--auto", NULL};1831struct strbuf sb = STRBUF_INIT;18321833unlink(am_path(state,"dirtyindex"));18341835refresh_and_write_cache();18361837if(index_has_changes(&sb)) {1838write_state_bool(state,"dirtyindex",1);1839die(_("Dirty index: cannot apply patches (dirty:%s)"), sb.buf);1840}18411842strbuf_release(&sb);18431844while(state->cur <= state->last) {1845const char*mail =am_path(state,msgnum(state));1846int apply_status;18471848if(!file_exists(mail))1849goto next;18501851if(resume) {1852validate_resume_state(state);1853}else{1854int skip;18551856if(state->rebasing)1857 skip =parse_mail_rebase(state, mail);1858else1859 skip =parse_mail(state, mail);18601861if(skip)1862goto next;/* mail should be skipped */18631864write_author_script(state);1865write_commit_msg(state);1866}18671868if(state->interactive &&do_interactive(state))1869goto next;18701871if(run_applypatch_msg_hook(state))1872exit(1);18731874say(state, stdout,_("Applying: %.*s"),linelen(state->msg), state->msg);18751876 apply_status =run_apply(state, NULL);18771878if(apply_status && state->threeway) {1879struct strbuf sb = STRBUF_INIT;18801881strbuf_addstr(&sb,am_path(state,"patch-merge-index"));1882 apply_status =fall_back_threeway(state, sb.buf);1883strbuf_release(&sb);18841885/*1886 * Applying the patch to an earlier tree and merging1887 * the result may have produced the same tree as ours.1888 */1889if(!apply_status && !index_has_changes(NULL)) {1890say(state, stdout,_("No changes -- Patch already applied."));1891goto next;1892}1893}18941895if(apply_status) {1896int advice_amworkdir =1;18971898printf_ln(_("Patch failed at%s%.*s"),msgnum(state),1899linelen(state->msg), state->msg);19001901git_config_get_bool("advice.amworkdir", &advice_amworkdir);19021903if(advice_amworkdir)1904printf_ln(_("The copy of the patch that failed is found in:%s"),1905am_path(state,"patch"));19061907die_user_resolve(state);1908}19091910do_commit(state);19111912next:1913am_next(state);19141915if(resume)1916am_load(state);1917 resume =0;1918}19191920if(!is_empty_file(am_path(state,"rewritten"))) {1921assert(state->rebasing);1922copy_notes_for_rebase(state);1923run_post_rewrite_hook(state);1924}19251926/*1927 * In rebasing mode, it's up to the caller to take care of1928 * housekeeping.1929 */1930if(!state->rebasing) {1931am_destroy(state);1932close_all_packs();1933run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);1934}1935}19361937/**1938 * Resume the current am session after patch application failure. The user did1939 * all the hard work, and we do not have to do any patch application. Just1940 * trust and commit what the user has in the index and working tree.1941 */1942static voidam_resolve(struct am_state *state)1943{1944validate_resume_state(state);19451946say(state, stdout,_("Applying: %.*s"),linelen(state->msg), state->msg);19471948if(!index_has_changes(NULL)) {1949printf_ln(_("No changes - did you forget to use 'git add'?\n"1950"If there is nothing left to stage, chances are that something else\n"1951"already introduced the same changes; you might want to skip this patch."));1952die_user_resolve(state);1953}19541955if(unmerged_cache()) {1956printf_ln(_("You still have unmerged paths in your index.\n"1957"Did you forget to use 'git add'?"));1958die_user_resolve(state);1959}19601961if(state->interactive) {1962write_index_patch(state);1963if(do_interactive(state))1964goto next;1965}19661967rerere(0);19681969do_commit(state);19701971next:1972am_next(state);1973am_load(state);1974am_run(state,0);1975}19761977/**1978 * Performs a checkout fast-forward from `head` to `remote`. If `reset` is1979 * true, any unmerged entries will be discarded. Returns 0 on success, -1 on1980 * failure.1981 */1982static intfast_forward_to(struct tree *head,struct tree *remote,int reset)1983{1984struct lock_file *lock_file;1985struct unpack_trees_options opts;1986struct tree_desc t[2];19871988if(parse_tree(head) ||parse_tree(remote))1989return-1;19901991 lock_file =xcalloc(1,sizeof(struct lock_file));1992hold_locked_index(lock_file,1);19931994refresh_cache(REFRESH_QUIET);19951996memset(&opts,0,sizeof(opts));1997 opts.head_idx =1;1998 opts.src_index = &the_index;1999 opts.dst_index = &the_index;2000 opts.update =1;2001 opts.merge =1;2002 opts.reset = reset;2003 opts.fn = twoway_merge;2004init_tree_desc(&t[0], head->buffer, head->size);2005init_tree_desc(&t[1], remote->buffer, remote->size);20062007if(unpack_trees(2, t, &opts)) {2008rollback_lock_file(lock_file);2009return-1;2010}20112012if(write_locked_index(&the_index, lock_file, COMMIT_LOCK))2013die(_("unable to write new index file"));20142015return0;2016}20172018/**2019 * Merges a tree into the index. The index's stat info will take precedence2020 * over the merged tree's. Returns 0 on success, -1 on failure.2021 */2022static intmerge_tree(struct tree *tree)2023{2024struct lock_file *lock_file;2025struct unpack_trees_options opts;2026struct tree_desc t[1];20272028if(parse_tree(tree))2029return-1;20302031 lock_file =xcalloc(1,sizeof(struct lock_file));2032hold_locked_index(lock_file,1);20332034memset(&opts,0,sizeof(opts));2035 opts.head_idx =1;2036 opts.src_index = &the_index;2037 opts.dst_index = &the_index;2038 opts.merge =1;2039 opts.fn = oneway_merge;2040init_tree_desc(&t[0], tree->buffer, tree->size);20412042if(unpack_trees(1, t, &opts)) {2043rollback_lock_file(lock_file);2044return-1;2045}20462047if(write_locked_index(&the_index, lock_file, COMMIT_LOCK))2048die(_("unable to write new index file"));20492050return0;2051}20522053/**2054 * Clean the index without touching entries that are not modified between2055 * `head` and `remote`.2056 */2057static intclean_index(const unsigned char*head,const unsigned char*remote)2058{2059struct tree *head_tree, *remote_tree, *index_tree;2060unsigned char index[GIT_SHA1_RAWSZ];20612062 head_tree =parse_tree_indirect(head);2063if(!head_tree)2064returnerror(_("Could not parse object '%s'."),sha1_to_hex(head));20652066 remote_tree =parse_tree_indirect(remote);2067if(!remote_tree)2068returnerror(_("Could not parse object '%s'."),sha1_to_hex(remote));20692070read_cache_unmerged();20712072if(fast_forward_to(head_tree, head_tree,1))2073return-1;20742075if(write_cache_as_tree(index,0, NULL))2076return-1;20772078 index_tree =parse_tree_indirect(index);2079if(!index_tree)2080returnerror(_("Could not parse object '%s'."),sha1_to_hex(index));20812082if(fast_forward_to(index_tree, remote_tree,0))2083return-1;20842085if(merge_tree(remote_tree))2086return-1;20872088remove_branch_state();20892090return0;2091}20922093/**2094 * Resets rerere's merge resolution metadata.2095 */2096static voidam_rerere_clear(void)2097{2098struct string_list merge_rr = STRING_LIST_INIT_DUP;2099rerere_clear(&merge_rr);2100string_list_clear(&merge_rr,1);2101}21022103/**2104 * Resume the current am session by skipping the current patch.2105 */2106static voidam_skip(struct am_state *state)2107{2108unsigned char head[GIT_SHA1_RAWSZ];21092110am_rerere_clear();21112112if(get_sha1("HEAD", head))2113hashcpy(head, EMPTY_TREE_SHA1_BIN);21142115if(clean_index(head, head))2116die(_("failed to clean index"));21172118am_next(state);2119am_load(state);2120am_run(state,0);2121}21222123/**2124 * Returns true if it is safe to reset HEAD to the ORIG_HEAD, false otherwise.2125 *2126 * It is not safe to reset HEAD when:2127 * 1. git-am previously failed because the index was dirty.2128 * 2. HEAD has moved since git-am previously failed.2129 */2130static intsafe_to_abort(const struct am_state *state)2131{2132struct strbuf sb = STRBUF_INIT;2133unsigned char abort_safety[GIT_SHA1_RAWSZ], head[GIT_SHA1_RAWSZ];21342135if(file_exists(am_path(state,"dirtyindex")))2136return0;21372138if(read_state_file(&sb, state,"abort-safety",1) >0) {2139if(get_sha1_hex(sb.buf, abort_safety))2140die(_("could not parse%s"),am_path(state,"abort_safety"));2141}else2142hashclr(abort_safety);21432144if(get_sha1("HEAD", head))2145hashclr(head);21462147if(!hashcmp(head, abort_safety))2148return1;21492150error(_("You seem to have moved HEAD since the last 'am' failure.\n"2151"Not rewinding to ORIG_HEAD"));21522153return0;2154}21552156/**2157 * Aborts the current am session if it is safe to do so.2158 */2159static voidam_abort(struct am_state *state)2160{2161unsigned char curr_head[GIT_SHA1_RAWSZ], orig_head[GIT_SHA1_RAWSZ];2162int has_curr_head, has_orig_head;2163char*curr_branch;21642165if(!safe_to_abort(state)) {2166am_destroy(state);2167return;2168}21692170am_rerere_clear();21712172 curr_branch =resolve_refdup("HEAD",0, curr_head, NULL);2173 has_curr_head = !is_null_sha1(curr_head);2174if(!has_curr_head)2175hashcpy(curr_head, EMPTY_TREE_SHA1_BIN);21762177 has_orig_head = !get_sha1("ORIG_HEAD", orig_head);2178if(!has_orig_head)2179hashcpy(orig_head, EMPTY_TREE_SHA1_BIN);21802181clean_index(curr_head, orig_head);21822183if(has_orig_head)2184update_ref("am --abort","HEAD", orig_head,2185 has_curr_head ? curr_head : NULL,0,2186 UPDATE_REFS_DIE_ON_ERR);2187else if(curr_branch)2188delete_ref(curr_branch, NULL, REF_NODEREF);21892190free(curr_branch);2191am_destroy(state);2192}21932194/**2195 * parse_options() callback that validates and sets opt->value to the2196 * PATCH_FORMAT_* enum value corresponding to `arg`.2197 */2198static intparse_opt_patchformat(const struct option *opt,const char*arg,int unset)2199{2200int*opt_value = opt->value;22012202if(!strcmp(arg,"mbox"))2203*opt_value = PATCH_FORMAT_MBOX;2204else if(!strcmp(arg,"stgit"))2205*opt_value = PATCH_FORMAT_STGIT;2206else if(!strcmp(arg,"stgit-series"))2207*opt_value = PATCH_FORMAT_STGIT_SERIES;2208else if(!strcmp(arg,"hg"))2209*opt_value = PATCH_FORMAT_HG;2210else if(!strcmp(arg,"mboxrd"))2211*opt_value = PATCH_FORMAT_MBOXRD;2212else2213returnerror(_("Invalid value for --patch-format:%s"), arg);2214return0;2215}22162217enum resume_mode {2218 RESUME_FALSE =0,2219 RESUME_APPLY,2220 RESUME_RESOLVED,2221 RESUME_SKIP,2222 RESUME_ABORT2223};22242225static intgit_am_config(const char*k,const char*v,void*cb)2226{2227int status;22282229 status =git_gpg_config(k, v, NULL);2230if(status)2231return status;22322233returngit_default_config(k, v, NULL);2234}22352236intcmd_am(int argc,const char**argv,const char*prefix)2237{2238struct am_state state;2239int binary = -1;2240int keep_cr = -1;2241int patch_format = PATCH_FORMAT_UNKNOWN;2242enum resume_mode resume = RESUME_FALSE;2243int in_progress;22442245const char*const usage[] = {2246N_("git am [<options>] [(<mbox>|<Maildir>)...]"),2247N_("git am [<options>] (--continue | --skip | --abort)"),2248 NULL2249};22502251struct option options[] = {2252OPT_BOOL('i',"interactive", &state.interactive,2253N_("run interactively")),2254OPT_HIDDEN_BOOL('b',"binary", &binary,2255N_("historical option -- no-op")),2256OPT_BOOL('3',"3way", &state.threeway,2257N_("allow fall back on 3way merging if needed")),2258OPT__QUIET(&state.quiet,N_("be quiet")),2259OPT_SET_INT('s',"signoff", &state.signoff,2260N_("add a Signed-off-by line to the commit message"),2261 SIGNOFF_EXPLICIT),2262OPT_BOOL('u',"utf8", &state.utf8,2263N_("recode into utf8 (default)")),2264OPT_SET_INT('k',"keep", &state.keep,2265N_("pass -k flag to git-mailinfo"), KEEP_TRUE),2266OPT_SET_INT(0,"keep-non-patch", &state.keep,2267N_("pass -b flag to git-mailinfo"), KEEP_NON_PATCH),2268OPT_BOOL('m',"message-id", &state.message_id,2269N_("pass -m flag to git-mailinfo")),2270{ OPTION_SET_INT,0,"keep-cr", &keep_cr, NULL,2271N_("pass --keep-cr flag to git-mailsplit for mbox format"),2272 PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL,1},2273{ OPTION_SET_INT,0,"no-keep-cr", &keep_cr, NULL,2274N_("do not pass --keep-cr flag to git-mailsplit independent of am.keepcr"),2275 PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL,0},2276OPT_BOOL('c',"scissors", &state.scissors,2277N_("strip everything before a scissors line")),2278OPT_PASSTHRU_ARGV(0,"whitespace", &state.git_apply_opts,N_("action"),2279N_("pass it through git-apply"),22800),2281OPT_PASSTHRU_ARGV(0,"ignore-space-change", &state.git_apply_opts, NULL,2282N_("pass it through git-apply"),2283 PARSE_OPT_NOARG),2284OPT_PASSTHRU_ARGV(0,"ignore-whitespace", &state.git_apply_opts, NULL,2285N_("pass it through git-apply"),2286 PARSE_OPT_NOARG),2287OPT_PASSTHRU_ARGV(0,"directory", &state.git_apply_opts,N_("root"),2288N_("pass it through git-apply"),22890),2290OPT_PASSTHRU_ARGV(0,"exclude", &state.git_apply_opts,N_("path"),2291N_("pass it through git-apply"),22920),2293OPT_PASSTHRU_ARGV(0,"include", &state.git_apply_opts,N_("path"),2294N_("pass it through git-apply"),22950),2296OPT_PASSTHRU_ARGV('C', NULL, &state.git_apply_opts,N_("n"),2297N_("pass it through git-apply"),22980),2299OPT_PASSTHRU_ARGV('p', NULL, &state.git_apply_opts,N_("num"),2300N_("pass it through git-apply"),23010),2302OPT_CALLBACK(0,"patch-format", &patch_format,N_("format"),2303N_("format the patch(es) are in"),2304 parse_opt_patchformat),2305OPT_PASSTHRU_ARGV(0,"reject", &state.git_apply_opts, NULL,2306N_("pass it through git-apply"),2307 PARSE_OPT_NOARG),2308OPT_STRING(0,"resolvemsg", &state.resolvemsg, NULL,2309N_("override error message when patch failure occurs")),2310OPT_CMDMODE(0,"continue", &resume,2311N_("continue applying patches after resolving a conflict"),2312 RESUME_RESOLVED),2313OPT_CMDMODE('r',"resolved", &resume,2314N_("synonyms for --continue"),2315 RESUME_RESOLVED),2316OPT_CMDMODE(0,"skip", &resume,2317N_("skip the current patch"),2318 RESUME_SKIP),2319OPT_CMDMODE(0,"abort", &resume,2320N_("restore the original branch and abort the patching operation."),2321 RESUME_ABORT),2322OPT_BOOL(0,"committer-date-is-author-date",2323&state.committer_date_is_author_date,2324N_("lie about committer date")),2325OPT_BOOL(0,"ignore-date", &state.ignore_date,2326N_("use current timestamp for author date")),2327OPT_RERERE_AUTOUPDATE(&state.allow_rerere_autoupdate),2328{ OPTION_STRING,'S',"gpg-sign", &state.sign_commit,N_("key-id"),2329N_("GPG-sign commits"),2330 PARSE_OPT_OPTARG, NULL, (intptr_t)""},2331OPT_HIDDEN_BOOL(0,"rebasing", &state.rebasing,2332N_("(internal use for git-rebase)")),2333OPT_END()2334};23352336git_config(git_am_config, NULL);23372338am_state_init(&state,git_path("rebase-apply"));23392340 in_progress =am_in_progress(&state);2341if(in_progress)2342am_load(&state);23432344 argc =parse_options(argc, argv, prefix, options, usage,0);23452346if(binary >=0)2347fprintf_ln(stderr,_("The -b/--binary option has been a no-op for long time, and\n"2348"it will be removed. Please do not use it anymore."));23492350/* Ensure a valid committer ident can be constructed */2351git_committer_info(IDENT_STRICT);23522353if(read_index_preload(&the_index, NULL) <0)2354die(_("failed to read the index"));23552356if(in_progress) {2357/*2358 * Catch user error to feed us patches when there is a session2359 * in progress:2360 *2361 * 1. mbox path(s) are provided on the command-line.2362 * 2. stdin is not a tty: the user is trying to feed us a patch2363 * from standard input. This is somewhat unreliable -- stdin2364 * could be /dev/null for example and the caller did not2365 * intend to feed us a patch but wanted to continue2366 * unattended.2367 */2368if(argc || (resume == RESUME_FALSE && !isatty(0)))2369die(_("previous rebase directory%sstill exists but mbox given."),2370 state.dir);23712372if(resume == RESUME_FALSE)2373 resume = RESUME_APPLY;23742375if(state.signoff == SIGNOFF_EXPLICIT)2376am_append_signoff(&state);2377}else{2378struct argv_array paths = ARGV_ARRAY_INIT;2379int i;23802381/*2382 * Handle stray state directory in the independent-run case. In2383 * the --rebasing case, it is up to the caller to take care of2384 * stray directories.2385 */2386if(file_exists(state.dir) && !state.rebasing) {2387if(resume == RESUME_ABORT) {2388am_destroy(&state);2389am_state_release(&state);2390return0;2391}23922393die(_("Stray%sdirectory found.\n"2394"Use\"git am --abort\"to remove it."),2395 state.dir);2396}23972398if(resume)2399die(_("Resolve operation not in progress, we are not resuming."));24002401for(i =0; i < argc; i++) {2402if(is_absolute_path(argv[i]) || !prefix)2403argv_array_push(&paths, argv[i]);2404else2405argv_array_push(&paths,mkpath("%s/%s", prefix, argv[i]));2406}24072408am_setup(&state, patch_format, paths.argv, keep_cr);24092410argv_array_clear(&paths);2411}24122413switch(resume) {2414case RESUME_FALSE:2415am_run(&state,0);2416break;2417case RESUME_APPLY:2418am_run(&state,1);2419break;2420case RESUME_RESOLVED:2421am_resolve(&state);2422break;2423case RESUME_SKIP:2424am_skip(&state);2425break;2426case RESUME_ABORT:2427am_abort(&state);2428break;2429default:2430die("BUG: invalid resume value");2431}24322433am_state_release(&state);24342435return0;2436}