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 * Like strbuf_getline(), but treats both '\n' and "\r\n" as line terminators. 50 */ 51static intstrbuf_getline_crlf(struct strbuf *sb,FILE*fp) 52{ 53if(strbuf_getwholeline(sb, fp,'\n')) 54return EOF; 55if(sb->buf[sb->len -1] =='\n') { 56strbuf_setlen(sb, sb->len -1); 57if(sb->len >0&& sb->buf[sb->len -1] =='\r') 58strbuf_setlen(sb, sb->len -1); 59} 60return0; 61} 62 63/** 64 * Returns the length of the first line of msg. 65 */ 66static intlinelen(const char*msg) 67{ 68returnstrchrnul(msg,'\n') - msg; 69} 70 71/** 72 * Returns true if `str` consists of only whitespace, false otherwise. 73 */ 74static intstr_isspace(const char*str) 75{ 76for(; *str; str++) 77if(!isspace(*str)) 78return0; 79 80return1; 81} 82 83enum patch_format { 84 PATCH_FORMAT_UNKNOWN =0, 85 PATCH_FORMAT_MBOX, 86 PATCH_FORMAT_STGIT, 87 PATCH_FORMAT_STGIT_SERIES, 88 PATCH_FORMAT_HG 89}; 90 91enum keep_type { 92 KEEP_FALSE =0, 93 KEEP_TRUE,/* pass -k flag to git-mailinfo */ 94 KEEP_NON_PATCH /* pass -b flag to git-mailinfo */ 95}; 96 97enum scissors_type { 98 SCISSORS_UNSET = -1, 99 SCISSORS_FALSE =0,/* pass --no-scissors to git-mailinfo */ 100 SCISSORS_TRUE /* pass --scissors to git-mailinfo */ 101}; 102 103enum signoff_type { 104 SIGNOFF_FALSE =0, 105 SIGNOFF_TRUE =1, 106 SIGNOFF_EXPLICIT /* --signoff was set on the command-line */ 107}; 108 109struct am_state { 110/* state directory path */ 111char*dir; 112 113/* current and last patch numbers, 1-indexed */ 114int cur; 115int last; 116 117/* commit metadata and message */ 118char*author_name; 119char*author_email; 120char*author_date; 121char*msg; 122size_t msg_len; 123 124/* when --rebasing, records the original commit the patch came from */ 125unsigned char orig_commit[GIT_SHA1_RAWSZ]; 126 127/* number of digits in patch filename */ 128int prec; 129 130/* various operating modes and command line options */ 131int interactive; 132int threeway; 133int quiet; 134int signoff;/* enum signoff_type */ 135int utf8; 136int keep;/* enum keep_type */ 137int message_id; 138int scissors;/* enum scissors_type */ 139struct argv_array git_apply_opts; 140const char*resolvemsg; 141int committer_date_is_author_date; 142int ignore_date; 143int allow_rerere_autoupdate; 144const char*sign_commit; 145int rebasing; 146}; 147 148/** 149 * Initializes am_state with the default values. The state directory is set to 150 * dir. 151 */ 152static voidam_state_init(struct am_state *state,const char*dir) 153{ 154int gpgsign; 155 156memset(state,0,sizeof(*state)); 157 158assert(dir); 159 state->dir =xstrdup(dir); 160 161 state->prec =4; 162 163git_config_get_bool("am.threeway", &state->threeway); 164 165 state->utf8 =1; 166 167git_config_get_bool("am.messageid", &state->message_id); 168 169 state->scissors = SCISSORS_UNSET; 170 171argv_array_init(&state->git_apply_opts); 172 173if(!git_config_get_bool("commit.gpgsign", &gpgsign)) 174 state->sign_commit = gpgsign ?"": NULL; 175} 176 177/** 178 * Releases memory allocated by an am_state. 179 */ 180static voidam_state_release(struct am_state *state) 181{ 182free(state->dir); 183free(state->author_name); 184free(state->author_email); 185free(state->author_date); 186free(state->msg); 187argv_array_clear(&state->git_apply_opts); 188} 189 190/** 191 * Returns path relative to the am_state directory. 192 */ 193staticinlineconst char*am_path(const struct am_state *state,const char*path) 194{ 195returnmkpath("%s/%s", state->dir, path); 196} 197 198/** 199 * For convenience to call write_file() 200 */ 201static intwrite_state_text(const struct am_state *state, 202const char*name,const char*string) 203{ 204returnwrite_file(am_path(state, name),"%s", string); 205} 206 207static intwrite_state_count(const struct am_state *state, 208const char*name,int value) 209{ 210returnwrite_file(am_path(state, name),"%d", value); 211} 212 213static intwrite_state_bool(const struct am_state *state, 214const char*name,int value) 215{ 216returnwrite_state_text(state, name, value ?"t":"f"); 217} 218 219/** 220 * If state->quiet is false, calls fprintf(fp, fmt, ...), and appends a newline 221 * at the end. 222 */ 223static voidsay(const struct am_state *state,FILE*fp,const char*fmt, ...) 224{ 225va_list ap; 226 227va_start(ap, fmt); 228if(!state->quiet) { 229vfprintf(fp, fmt, ap); 230putc('\n', fp); 231} 232va_end(ap); 233} 234 235/** 236 * Returns 1 if there is an am session in progress, 0 otherwise. 237 */ 238static intam_in_progress(const struct am_state *state) 239{ 240struct stat st; 241 242if(lstat(state->dir, &st) <0|| !S_ISDIR(st.st_mode)) 243return0; 244if(lstat(am_path(state,"last"), &st) || !S_ISREG(st.st_mode)) 245return0; 246if(lstat(am_path(state,"next"), &st) || !S_ISREG(st.st_mode)) 247return0; 248return1; 249} 250 251/** 252 * Reads the contents of `file` in the `state` directory into `sb`. Returns the 253 * number of bytes read on success, -1 if the file does not exist. If `trim` is 254 * set, trailing whitespace will be removed. 255 */ 256static intread_state_file(struct strbuf *sb,const struct am_state *state, 257const char*file,int trim) 258{ 259strbuf_reset(sb); 260 261if(strbuf_read_file(sb,am_path(state, file),0) >=0) { 262if(trim) 263strbuf_trim(sb); 264 265return sb->len; 266} 267 268if(errno == ENOENT) 269return-1; 270 271die_errno(_("could not read '%s'"),am_path(state, file)); 272} 273 274/** 275 * Reads a KEY=VALUE shell variable assignment from `fp`, returning the VALUE 276 * as a newly-allocated string. VALUE must be a quoted string, and the KEY must 277 * match `key`. Returns NULL on failure. 278 * 279 * This is used by read_author_script() to read the GIT_AUTHOR_* variables from 280 * the author-script. 281 */ 282static char*read_shell_var(FILE*fp,const char*key) 283{ 284struct strbuf sb = STRBUF_INIT; 285const char*str; 286 287if(strbuf_getline(&sb, fp,'\n')) 288goto fail; 289 290if(!skip_prefix(sb.buf, key, &str)) 291goto fail; 292 293if(!skip_prefix(str,"=", &str)) 294goto fail; 295 296strbuf_remove(&sb,0, str - sb.buf); 297 298 str =sq_dequote(sb.buf); 299if(!str) 300goto fail; 301 302returnstrbuf_detach(&sb, NULL); 303 304fail: 305strbuf_release(&sb); 306return NULL; 307} 308 309/** 310 * Reads and parses the state directory's "author-script" file, and sets 311 * state->author_name, state->author_email and state->author_date accordingly. 312 * Returns 0 on success, -1 if the file could not be parsed. 313 * 314 * The author script is of the format: 315 * 316 * GIT_AUTHOR_NAME='$author_name' 317 * GIT_AUTHOR_EMAIL='$author_email' 318 * GIT_AUTHOR_DATE='$author_date' 319 * 320 * where $author_name, $author_email and $author_date are quoted. We are strict 321 * with our parsing, as the file was meant to be eval'd in the old git-am.sh 322 * script, and thus if the file differs from what this function expects, it is 323 * better to bail out than to do something that the user does not expect. 324 */ 325static intread_author_script(struct am_state *state) 326{ 327const char*filename =am_path(state,"author-script"); 328FILE*fp; 329 330assert(!state->author_name); 331assert(!state->author_email); 332assert(!state->author_date); 333 334 fp =fopen(filename,"r"); 335if(!fp) { 336if(errno == ENOENT) 337return0; 338die_errno(_("could not open '%s' for reading"), filename); 339} 340 341 state->author_name =read_shell_var(fp,"GIT_AUTHOR_NAME"); 342if(!state->author_name) { 343fclose(fp); 344return-1; 345} 346 347 state->author_email =read_shell_var(fp,"GIT_AUTHOR_EMAIL"); 348if(!state->author_email) { 349fclose(fp); 350return-1; 351} 352 353 state->author_date =read_shell_var(fp,"GIT_AUTHOR_DATE"); 354if(!state->author_date) { 355fclose(fp); 356return-1; 357} 358 359if(fgetc(fp) != EOF) { 360fclose(fp); 361return-1; 362} 363 364fclose(fp); 365return0; 366} 367 368/** 369 * Saves state->author_name, state->author_email and state->author_date in the 370 * state directory's "author-script" file. 371 */ 372static voidwrite_author_script(const struct am_state *state) 373{ 374struct strbuf sb = STRBUF_INIT; 375 376strbuf_addstr(&sb,"GIT_AUTHOR_NAME="); 377sq_quote_buf(&sb, state->author_name); 378strbuf_addch(&sb,'\n'); 379 380strbuf_addstr(&sb,"GIT_AUTHOR_EMAIL="); 381sq_quote_buf(&sb, state->author_email); 382strbuf_addch(&sb,'\n'); 383 384strbuf_addstr(&sb,"GIT_AUTHOR_DATE="); 385sq_quote_buf(&sb, state->author_date); 386strbuf_addch(&sb,'\n'); 387 388write_state_text(state,"author-script", sb.buf); 389 390strbuf_release(&sb); 391} 392 393/** 394 * Reads the commit message from the state directory's "final-commit" file, 395 * setting state->msg to its contents and state->msg_len to the length of its 396 * contents in bytes. 397 * 398 * Returns 0 on success, -1 if the file does not exist. 399 */ 400static intread_commit_msg(struct am_state *state) 401{ 402struct strbuf sb = STRBUF_INIT; 403 404assert(!state->msg); 405 406if(read_state_file(&sb, state,"final-commit",0) <0) { 407strbuf_release(&sb); 408return-1; 409} 410 411 state->msg =strbuf_detach(&sb, &state->msg_len); 412return0; 413} 414 415/** 416 * Saves state->msg in the state directory's "final-commit" file. 417 */ 418static voidwrite_commit_msg(const struct am_state *state) 419{ 420int fd; 421const char*filename =am_path(state,"final-commit"); 422 423 fd =xopen(filename, O_WRONLY | O_CREAT,0666); 424if(write_in_full(fd, state->msg, state->msg_len) <0) 425die_errno(_("could not write to%s"), filename); 426close(fd); 427} 428 429/** 430 * Loads state from disk. 431 */ 432static voidam_load(struct am_state *state) 433{ 434struct strbuf sb = STRBUF_INIT; 435 436if(read_state_file(&sb, state,"next",1) <0) 437die("BUG: state file 'next' does not exist"); 438 state->cur =strtol(sb.buf, NULL,10); 439 440if(read_state_file(&sb, state,"last",1) <0) 441die("BUG: state file 'last' does not exist"); 442 state->last =strtol(sb.buf, NULL,10); 443 444if(read_author_script(state) <0) 445die(_("could not parse author script")); 446 447read_commit_msg(state); 448 449if(read_state_file(&sb, state,"original-commit",1) <0) 450hashclr(state->orig_commit); 451else if(get_sha1_hex(sb.buf, state->orig_commit) <0) 452die(_("could not parse%s"),am_path(state,"original-commit")); 453 454read_state_file(&sb, state,"threeway",1); 455 state->threeway = !strcmp(sb.buf,"t"); 456 457read_state_file(&sb, state,"quiet",1); 458 state->quiet = !strcmp(sb.buf,"t"); 459 460read_state_file(&sb, state,"sign",1); 461 state->signoff = !strcmp(sb.buf,"t"); 462 463read_state_file(&sb, state,"utf8",1); 464 state->utf8 = !strcmp(sb.buf,"t"); 465 466read_state_file(&sb, state,"keep",1); 467if(!strcmp(sb.buf,"t")) 468 state->keep = KEEP_TRUE; 469else if(!strcmp(sb.buf,"b")) 470 state->keep = KEEP_NON_PATCH; 471else 472 state->keep = KEEP_FALSE; 473 474read_state_file(&sb, state,"messageid",1); 475 state->message_id = !strcmp(sb.buf,"t"); 476 477read_state_file(&sb, state,"scissors",1); 478if(!strcmp(sb.buf,"t")) 479 state->scissors = SCISSORS_TRUE; 480else if(!strcmp(sb.buf,"f")) 481 state->scissors = SCISSORS_FALSE; 482else 483 state->scissors = SCISSORS_UNSET; 484 485read_state_file(&sb, state,"apply-opt",1); 486argv_array_clear(&state->git_apply_opts); 487if(sq_dequote_to_argv_array(sb.buf, &state->git_apply_opts) <0) 488die(_("could not parse%s"),am_path(state,"apply-opt")); 489 490 state->rebasing = !!file_exists(am_path(state,"rebasing")); 491 492strbuf_release(&sb); 493} 494 495/** 496 * Removes the am_state directory, forcefully terminating the current am 497 * session. 498 */ 499static voidam_destroy(const struct am_state *state) 500{ 501struct strbuf sb = STRBUF_INIT; 502 503strbuf_addstr(&sb, state->dir); 504remove_dir_recursively(&sb,0); 505strbuf_release(&sb); 506} 507 508/** 509 * Runs applypatch-msg hook. Returns its exit code. 510 */ 511static intrun_applypatch_msg_hook(struct am_state *state) 512{ 513int ret; 514 515assert(state->msg); 516 ret =run_hook_le(NULL,"applypatch-msg",am_path(state,"final-commit"), NULL); 517 518if(!ret) { 519free(state->msg); 520 state->msg = NULL; 521if(read_commit_msg(state) <0) 522die(_("'%s' was deleted by the applypatch-msg hook"), 523am_path(state,"final-commit")); 524} 525 526return ret; 527} 528 529/** 530 * Runs post-rewrite hook. Returns it exit code. 531 */ 532static intrun_post_rewrite_hook(const struct am_state *state) 533{ 534struct child_process cp = CHILD_PROCESS_INIT; 535const char*hook =find_hook("post-rewrite"); 536int ret; 537 538if(!hook) 539return0; 540 541argv_array_push(&cp.args, hook); 542argv_array_push(&cp.args,"rebase"); 543 544 cp.in =xopen(am_path(state,"rewritten"), O_RDONLY); 545 cp.stdout_to_stderr =1; 546 547 ret =run_command(&cp); 548 549close(cp.in); 550return ret; 551} 552 553/** 554 * Reads the state directory's "rewritten" file, and copies notes from the old 555 * commits listed in the file to their rewritten commits. 556 * 557 * Returns 0 on success, -1 on failure. 558 */ 559static intcopy_notes_for_rebase(const struct am_state *state) 560{ 561struct notes_rewrite_cfg *c; 562struct strbuf sb = STRBUF_INIT; 563const char*invalid_line =_("Malformed input line: '%s'."); 564const char*msg ="Notes added by 'git rebase'"; 565FILE*fp; 566int ret =0; 567 568assert(state->rebasing); 569 570 c =init_copy_notes_for_rewrite("rebase"); 571if(!c) 572return0; 573 574 fp =xfopen(am_path(state,"rewritten"),"r"); 575 576while(!strbuf_getline(&sb, fp,'\n')) { 577unsigned char from_obj[GIT_SHA1_RAWSZ], to_obj[GIT_SHA1_RAWSZ]; 578 579if(sb.len != GIT_SHA1_HEXSZ *2+1) { 580 ret =error(invalid_line, sb.buf); 581goto finish; 582} 583 584if(get_sha1_hex(sb.buf, from_obj)) { 585 ret =error(invalid_line, sb.buf); 586goto finish; 587} 588 589if(sb.buf[GIT_SHA1_HEXSZ] !=' ') { 590 ret =error(invalid_line, sb.buf); 591goto finish; 592} 593 594if(get_sha1_hex(sb.buf + GIT_SHA1_HEXSZ +1, to_obj)) { 595 ret =error(invalid_line, sb.buf); 596goto finish; 597} 598 599if(copy_note_for_rewrite(c, from_obj, to_obj)) 600 ret =error(_("Failed to copy notes from '%s' to '%s'"), 601sha1_to_hex(from_obj),sha1_to_hex(to_obj)); 602} 603 604finish: 605finish_copy_notes_for_rewrite(c, msg); 606fclose(fp); 607strbuf_release(&sb); 608return ret; 609} 610 611/** 612 * Determines if the file looks like a piece of RFC2822 mail by grabbing all 613 * non-indented lines and checking if they look like they begin with valid 614 * header field names. 615 * 616 * Returns 1 if the file looks like a piece of mail, 0 otherwise. 617 */ 618static intis_mail(FILE*fp) 619{ 620const char*header_regex ="^[!-9;-~]+:"; 621struct strbuf sb = STRBUF_INIT; 622 regex_t regex; 623int ret =1; 624 625if(fseek(fp,0L, SEEK_SET)) 626die_errno(_("fseek failed")); 627 628if(regcomp(®ex, header_regex, REG_NOSUB | REG_EXTENDED)) 629die("invalid pattern:%s", header_regex); 630 631while(!strbuf_getline_crlf(&sb, fp)) { 632if(!sb.len) 633break;/* End of header */ 634 635/* Ignore indented folded lines */ 636if(*sb.buf =='\t'|| *sb.buf ==' ') 637continue; 638 639/* It's a header if it matches header_regex */ 640if(regexec(®ex, sb.buf,0, NULL,0)) { 641 ret =0; 642goto done; 643} 644} 645 646done: 647regfree(®ex); 648strbuf_release(&sb); 649return ret; 650} 651 652/** 653 * Attempts to detect the patch_format of the patches contained in `paths`, 654 * returning the PATCH_FORMAT_* enum value. Returns PATCH_FORMAT_UNKNOWN if 655 * detection fails. 656 */ 657static intdetect_patch_format(const char**paths) 658{ 659enum patch_format ret = PATCH_FORMAT_UNKNOWN; 660struct strbuf l1 = STRBUF_INIT; 661struct strbuf l2 = STRBUF_INIT; 662struct strbuf l3 = STRBUF_INIT; 663FILE*fp; 664 665/* 666 * We default to mbox format if input is from stdin and for directories 667 */ 668if(!*paths || !strcmp(*paths,"-") ||is_directory(*paths)) 669return PATCH_FORMAT_MBOX; 670 671/* 672 * Otherwise, check the first few lines of the first patch, starting 673 * from the first non-blank line, to try to detect its format. 674 */ 675 676 fp =xfopen(*paths,"r"); 677 678while(!strbuf_getline_crlf(&l1, fp)) { 679if(l1.len) 680break; 681} 682 683if(starts_with(l1.buf,"From ") ||starts_with(l1.buf,"From: ")) { 684 ret = PATCH_FORMAT_MBOX; 685goto done; 686} 687 688if(starts_with(l1.buf,"# This series applies on GIT commit")) { 689 ret = PATCH_FORMAT_STGIT_SERIES; 690goto done; 691} 692 693if(!strcmp(l1.buf,"# HG changeset patch")) { 694 ret = PATCH_FORMAT_HG; 695goto done; 696} 697 698strbuf_reset(&l2); 699strbuf_getline_crlf(&l2, fp); 700strbuf_reset(&l3); 701strbuf_getline_crlf(&l3, fp); 702 703/* 704 * If the second line is empty and the third is a From, Author or Date 705 * entry, this is likely an StGit patch. 706 */ 707if(l1.len && !l2.len && 708(starts_with(l3.buf,"From:") || 709starts_with(l3.buf,"Author:") || 710starts_with(l3.buf,"Date:"))) { 711 ret = PATCH_FORMAT_STGIT; 712goto done; 713} 714 715if(l1.len &&is_mail(fp)) { 716 ret = PATCH_FORMAT_MBOX; 717goto done; 718} 719 720done: 721fclose(fp); 722strbuf_release(&l1); 723return ret; 724} 725 726/** 727 * Splits out individual email patches from `paths`, where each path is either 728 * a mbox file or a Maildir. Returns 0 on success, -1 on failure. 729 */ 730static intsplit_mail_mbox(struct am_state *state,const char**paths,int keep_cr) 731{ 732struct child_process cp = CHILD_PROCESS_INIT; 733struct strbuf last = STRBUF_INIT; 734 735 cp.git_cmd =1; 736argv_array_push(&cp.args,"mailsplit"); 737argv_array_pushf(&cp.args,"-d%d", state->prec); 738argv_array_pushf(&cp.args,"-o%s", state->dir); 739argv_array_push(&cp.args,"-b"); 740if(keep_cr) 741argv_array_push(&cp.args,"--keep-cr"); 742argv_array_push(&cp.args,"--"); 743argv_array_pushv(&cp.args, paths); 744 745if(capture_command(&cp, &last,8)) 746return-1; 747 748 state->cur =1; 749 state->last =strtol(last.buf, NULL,10); 750 751return0; 752} 753 754/** 755 * Callback signature for split_mail_conv(). The foreign patch should be 756 * read from `in`, and the converted patch (in RFC2822 mail format) should be 757 * written to `out`. Return 0 on success, or -1 on failure. 758 */ 759typedefint(*mail_conv_fn)(FILE*out,FILE*in,int keep_cr); 760 761/** 762 * Calls `fn` for each file in `paths` to convert the foreign patch to the 763 * RFC2822 mail format suitable for parsing with git-mailinfo. 764 * 765 * Returns 0 on success, -1 on failure. 766 */ 767static intsplit_mail_conv(mail_conv_fn fn,struct am_state *state, 768const char**paths,int keep_cr) 769{ 770static const char*stdin_only[] = {"-", NULL}; 771int i; 772 773if(!*paths) 774 paths = stdin_only; 775 776for(i =0; *paths; paths++, i++) { 777FILE*in, *out; 778const char*mail; 779int ret; 780 781if(!strcmp(*paths,"-")) 782 in = stdin; 783else 784 in =fopen(*paths,"r"); 785 786if(!in) 787returnerror(_("could not open '%s' for reading:%s"), 788*paths,strerror(errno)); 789 790 mail =mkpath("%s/%0*d", state->dir, state->prec, i +1); 791 792 out =fopen(mail,"w"); 793if(!out) 794returnerror(_("could not open '%s' for writing:%s"), 795 mail,strerror(errno)); 796 797 ret =fn(out, in, keep_cr); 798 799fclose(out); 800fclose(in); 801 802if(ret) 803returnerror(_("could not parse patch '%s'"), *paths); 804} 805 806 state->cur =1; 807 state->last = i; 808return0; 809} 810 811/** 812 * A split_mail_conv() callback that converts an StGit patch to an RFC2822 813 * message suitable for parsing with git-mailinfo. 814 */ 815static intstgit_patch_to_mail(FILE*out,FILE*in,int keep_cr) 816{ 817struct strbuf sb = STRBUF_INIT; 818int subject_printed =0; 819 820while(!strbuf_getline(&sb, in,'\n')) { 821const char*str; 822 823if(str_isspace(sb.buf)) 824continue; 825else if(skip_prefix(sb.buf,"Author:", &str)) 826fprintf(out,"From:%s\n", str); 827else if(starts_with(sb.buf,"From") ||starts_with(sb.buf,"Date")) 828fprintf(out,"%s\n", sb.buf); 829else if(!subject_printed) { 830fprintf(out,"Subject:%s\n", sb.buf); 831 subject_printed =1; 832}else{ 833fprintf(out,"\n%s\n", sb.buf); 834break; 835} 836} 837 838strbuf_reset(&sb); 839while(strbuf_fread(&sb,8192, in) >0) { 840fwrite(sb.buf,1, sb.len, out); 841strbuf_reset(&sb); 842} 843 844strbuf_release(&sb); 845return0; 846} 847 848/** 849 * This function only supports a single StGit series file in `paths`. 850 * 851 * Given an StGit series file, converts the StGit patches in the series into 852 * RFC2822 messages suitable for parsing with git-mailinfo, and queues them in 853 * the state directory. 854 * 855 * Returns 0 on success, -1 on failure. 856 */ 857static intsplit_mail_stgit_series(struct am_state *state,const char**paths, 858int keep_cr) 859{ 860const char*series_dir; 861char*series_dir_buf; 862FILE*fp; 863struct argv_array patches = ARGV_ARRAY_INIT; 864struct strbuf sb = STRBUF_INIT; 865int ret; 866 867if(!paths[0] || paths[1]) 868returnerror(_("Only one StGIT patch series can be applied at once")); 869 870 series_dir_buf =xstrdup(*paths); 871 series_dir =dirname(series_dir_buf); 872 873 fp =fopen(*paths,"r"); 874if(!fp) 875returnerror(_("could not open '%s' for reading:%s"), *paths, 876strerror(errno)); 877 878while(!strbuf_getline(&sb, fp,'\n')) { 879if(*sb.buf =='#') 880continue;/* skip comment lines */ 881 882argv_array_push(&patches,mkpath("%s/%s", series_dir, sb.buf)); 883} 884 885fclose(fp); 886strbuf_release(&sb); 887free(series_dir_buf); 888 889 ret =split_mail_conv(stgit_patch_to_mail, state, patches.argv, keep_cr); 890 891argv_array_clear(&patches); 892return ret; 893} 894 895/** 896 * A split_patches_conv() callback that converts a mercurial patch to a RFC2822 897 * message suitable for parsing with git-mailinfo. 898 */ 899static inthg_patch_to_mail(FILE*out,FILE*in,int keep_cr) 900{ 901struct strbuf sb = STRBUF_INIT; 902 903while(!strbuf_getline(&sb, in,'\n')) { 904const char*str; 905 906if(skip_prefix(sb.buf,"# User ", &str)) 907fprintf(out,"From:%s\n", str); 908else if(skip_prefix(sb.buf,"# Date ", &str)) { 909unsigned long timestamp; 910long tz, tz2; 911char*end; 912 913 errno =0; 914 timestamp =strtoul(str, &end,10); 915if(errno) 916returnerror(_("invalid timestamp")); 917 918if(!skip_prefix(end," ", &str)) 919returnerror(_("invalid Date line")); 920 921 errno =0; 922 tz =strtol(str, &end,10); 923if(errno) 924returnerror(_("invalid timezone offset")); 925 926if(*end) 927returnerror(_("invalid Date line")); 928 929/* 930 * mercurial's timezone is in seconds west of UTC, 931 * however git's timezone is in hours + minutes east of 932 * UTC. Convert it. 933 */ 934 tz2 =labs(tz) /3600*100+labs(tz) %3600/60; 935if(tz >0) 936 tz2 = -tz2; 937 938fprintf(out,"Date:%s\n",show_date(timestamp, tz2,DATE_MODE(RFC2822))); 939}else if(starts_with(sb.buf,"# ")) { 940continue; 941}else{ 942fprintf(out,"\n%s\n", sb.buf); 943break; 944} 945} 946 947strbuf_reset(&sb); 948while(strbuf_fread(&sb,8192, in) >0) { 949fwrite(sb.buf,1, sb.len, out); 950strbuf_reset(&sb); 951} 952 953strbuf_release(&sb); 954return0; 955} 956 957/** 958 * Splits a list of files/directories into individual email patches. Each path 959 * in `paths` must be a file/directory that is formatted according to 960 * `patch_format`. 961 * 962 * Once split out, the individual email patches will be stored in the state 963 * directory, with each patch's filename being its index, padded to state->prec 964 * digits. 965 * 966 * state->cur will be set to the index of the first mail, and state->last will 967 * be set to the index of the last mail. 968 * 969 * Set keep_cr to 0 to convert all lines ending with \r\n to end with \n, 1 970 * to disable this behavior, -1 to use the default configured setting. 971 * 972 * Returns 0 on success, -1 on failure. 973 */ 974static intsplit_mail(struct am_state *state,enum patch_format patch_format, 975const char**paths,int keep_cr) 976{ 977if(keep_cr <0) { 978 keep_cr =0; 979git_config_get_bool("am.keepcr", &keep_cr); 980} 981 982switch(patch_format) { 983case PATCH_FORMAT_MBOX: 984returnsplit_mail_mbox(state, paths, keep_cr); 985case PATCH_FORMAT_STGIT: 986returnsplit_mail_conv(stgit_patch_to_mail, state, paths, keep_cr); 987case PATCH_FORMAT_STGIT_SERIES: 988returnsplit_mail_stgit_series(state, paths, keep_cr); 989case PATCH_FORMAT_HG: 990returnsplit_mail_conv(hg_patch_to_mail, state, paths, keep_cr); 991default: 992die("BUG: invalid patch_format"); 993} 994return-1; 995} 996 997/** 998 * Setup a new am session for applying patches 999 */1000static voidam_setup(struct am_state *state,enum patch_format patch_format,1001const char**paths,int keep_cr)1002{1003unsigned char curr_head[GIT_SHA1_RAWSZ];1004const char*str;1005struct strbuf sb = STRBUF_INIT;10061007if(!patch_format)1008 patch_format =detect_patch_format(paths);10091010if(!patch_format) {1011fprintf_ln(stderr,_("Patch format detection failed."));1012exit(128);1013}10141015if(mkdir(state->dir,0777) <0&& errno != EEXIST)1016die_errno(_("failed to create directory '%s'"), state->dir);10171018if(split_mail(state, patch_format, paths, keep_cr) <0) {1019am_destroy(state);1020die(_("Failed to split patches."));1021}10221023if(state->rebasing)1024 state->threeway =1;10251026write_state_bool(state,"threeway", state->threeway);1027write_state_bool(state,"quiet", state->quiet);1028write_state_bool(state,"sign", state->signoff);1029write_state_bool(state,"utf8", state->utf8);10301031switch(state->keep) {1032case KEEP_FALSE:1033 str ="f";1034break;1035case KEEP_TRUE:1036 str ="t";1037break;1038case KEEP_NON_PATCH:1039 str ="b";1040break;1041default:1042die("BUG: invalid value for state->keep");1043}10441045write_state_text(state,"keep", str);1046write_state_bool(state,"messageid", state->message_id);10471048switch(state->scissors) {1049case SCISSORS_UNSET:1050 str ="";1051break;1052case SCISSORS_FALSE:1053 str ="f";1054break;1055case SCISSORS_TRUE:1056 str ="t";1057break;1058default:1059die("BUG: invalid value for state->scissors");1060}1061write_state_text(state,"scissors", str);10621063sq_quote_argv(&sb, state->git_apply_opts.argv,0);1064write_state_text(state,"apply-opt", sb.buf);10651066if(state->rebasing)1067write_state_text(state,"rebasing","");1068else1069write_state_text(state,"applying","");10701071if(!get_sha1("HEAD", curr_head)) {1072write_state_text(state,"abort-safety",sha1_to_hex(curr_head));1073if(!state->rebasing)1074update_ref("am","ORIG_HEAD", curr_head, NULL,0,1075 UPDATE_REFS_DIE_ON_ERR);1076}else{1077write_state_text(state,"abort-safety","");1078if(!state->rebasing)1079delete_ref("ORIG_HEAD", NULL,0);1080}10811082/*1083 * NOTE: Since the "next" and "last" files determine if an am_state1084 * session is in progress, they should be written last.1085 */10861087write_state_count(state,"next", state->cur);1088write_state_count(state,"last", state->last);10891090strbuf_release(&sb);1091}10921093/**1094 * Increments the patch pointer, and cleans am_state for the application of the1095 * next patch.1096 */1097static voidam_next(struct am_state *state)1098{1099unsigned char head[GIT_SHA1_RAWSZ];11001101free(state->author_name);1102 state->author_name = NULL;11031104free(state->author_email);1105 state->author_email = NULL;11061107free(state->author_date);1108 state->author_date = NULL;11091110free(state->msg);1111 state->msg = NULL;1112 state->msg_len =0;11131114unlink(am_path(state,"author-script"));1115unlink(am_path(state,"final-commit"));11161117hashclr(state->orig_commit);1118unlink(am_path(state,"original-commit"));11191120if(!get_sha1("HEAD", head))1121write_state_text(state,"abort-safety",sha1_to_hex(head));1122else1123write_state_text(state,"abort-safety","");11241125 state->cur++;1126write_state_count(state,"next", state->cur);1127}11281129/**1130 * Returns the filename of the current patch email.1131 */1132static const char*msgnum(const struct am_state *state)1133{1134static struct strbuf sb = STRBUF_INIT;11351136strbuf_reset(&sb);1137strbuf_addf(&sb,"%0*d", state->prec, state->cur);11381139return sb.buf;1140}11411142/**1143 * Refresh and write index.1144 */1145static voidrefresh_and_write_cache(void)1146{1147struct lock_file *lock_file =xcalloc(1,sizeof(struct lock_file));11481149hold_locked_index(lock_file,1);1150refresh_cache(REFRESH_QUIET);1151if(write_locked_index(&the_index, lock_file, COMMIT_LOCK))1152die(_("unable to write index file"));1153}11541155/**1156 * Returns 1 if the index differs from HEAD, 0 otherwise. When on an unborn1157 * branch, returns 1 if there are entries in the index, 0 otherwise. If an1158 * strbuf is provided, the space-separated list of files that differ will be1159 * appended to it.1160 */1161static intindex_has_changes(struct strbuf *sb)1162{1163unsigned char head[GIT_SHA1_RAWSZ];1164int i;11651166if(!get_sha1_tree("HEAD", head)) {1167struct diff_options opt;11681169diff_setup(&opt);1170DIFF_OPT_SET(&opt, EXIT_WITH_STATUS);1171if(!sb)1172DIFF_OPT_SET(&opt, QUICK);1173do_diff_cache(head, &opt);1174diffcore_std(&opt);1175for(i =0; sb && i < diff_queued_diff.nr; i++) {1176if(i)1177strbuf_addch(sb,' ');1178strbuf_addstr(sb, diff_queued_diff.queue[i]->two->path);1179}1180diff_flush(&opt);1181returnDIFF_OPT_TST(&opt, HAS_CHANGES) !=0;1182}else{1183for(i =0; sb && i < active_nr; i++) {1184if(i)1185strbuf_addch(sb,' ');1186strbuf_addstr(sb, active_cache[i]->name);1187}1188return!!active_nr;1189}1190}11911192/**1193 * Dies with a user-friendly message on how to proceed after resolving the1194 * problem. This message can be overridden with state->resolvemsg.1195 */1196static void NORETURN die_user_resolve(const struct am_state *state)1197{1198if(state->resolvemsg) {1199printf_ln("%s", state->resolvemsg);1200}else{1201const char*cmdline = state->interactive ?"git am -i":"git am";12021203printf_ln(_("When you have resolved this problem, run\"%s--continue\"."), cmdline);1204printf_ln(_("If you prefer to skip this patch, run\"%s--skip\"instead."), cmdline);1205printf_ln(_("To restore the original branch and stop patching, run\"%s--abort\"."), cmdline);1206}12071208exit(128);1209}12101211static voidam_signoff(struct strbuf *sb)1212{1213char*cp;1214struct strbuf mine = STRBUF_INIT;12151216/* Does it end with our own sign-off? */1217strbuf_addf(&mine,"\n%s%s\n",1218 sign_off_header,1219fmt_name(getenv("GIT_COMMITTER_NAME"),1220getenv("GIT_COMMITTER_EMAIL")));1221if(mine.len < sb->len &&1222!strcmp(mine.buf, sb->buf + sb->len - mine.len))1223goto exit;/* no need to duplicate */12241225/* Does it have any Signed-off-by: in the text */1226for(cp = sb->buf;1227 cp && *cp && (cp =strstr(cp, sign_off_header)) != NULL;1228 cp =strchr(cp,'\n')) {1229if(sb->buf == cp || cp[-1] =='\n')1230break;1231}12321233strbuf_addstr(sb, mine.buf + !!cp);1234exit:1235strbuf_release(&mine);1236}12371238/**1239 * Appends signoff to the "msg" field of the am_state.1240 */1241static voidam_append_signoff(struct am_state *state)1242{1243struct strbuf sb = STRBUF_INIT;12441245strbuf_attach(&sb, state->msg, state->msg_len, state->msg_len);1246am_signoff(&sb);1247 state->msg =strbuf_detach(&sb, &state->msg_len);1248}12491250/**1251 * Parses `mail` using git-mailinfo, extracting its patch and authorship info.1252 * state->msg will be set to the patch message. state->author_name,1253 * state->author_email and state->author_date will be set to the patch author's1254 * name, email and date respectively. The patch body will be written to the1255 * state directory's "patch" file.1256 *1257 * Returns 1 if the patch should be skipped, 0 otherwise.1258 */1259static intparse_mail(struct am_state *state,const char*mail)1260{1261FILE*fp;1262struct strbuf sb = STRBUF_INIT;1263struct strbuf msg = STRBUF_INIT;1264struct strbuf author_name = STRBUF_INIT;1265struct strbuf author_date = STRBUF_INIT;1266struct strbuf author_email = STRBUF_INIT;1267int ret =0;1268struct mailinfo mi;12691270setup_mailinfo(&mi);12711272if(state->utf8)1273 mi.metainfo_charset =get_commit_output_encoding();1274else1275 mi.metainfo_charset = NULL;12761277switch(state->keep) {1278case KEEP_FALSE:1279break;1280case KEEP_TRUE:1281 mi.keep_subject =1;1282break;1283case KEEP_NON_PATCH:1284 mi.keep_non_patch_brackets_in_subject =1;1285break;1286default:1287die("BUG: invalid value for state->keep");1288}12891290if(state->message_id)1291 mi.add_message_id =1;12921293switch(state->scissors) {1294case SCISSORS_UNSET:1295break;1296case SCISSORS_FALSE:1297 mi.use_scissors =0;1298break;1299case SCISSORS_TRUE:1300 mi.use_scissors =1;1301break;1302default:1303die("BUG: invalid value for state->scissors");1304}13051306 mi.input =fopen(mail,"r");1307if(!mi.input)1308die("could not open input");1309 mi.output =fopen(am_path(state,"info"),"w");1310if(!mi.output)1311die("could not open output 'info'");1312if(mailinfo(&mi,am_path(state,"msg"),am_path(state,"patch")))1313die("could not parse patch");13141315fclose(mi.input);1316fclose(mi.output);13171318/* Extract message and author information */1319 fp =xfopen(am_path(state,"info"),"r");1320while(!strbuf_getline(&sb, fp,'\n')) {1321const char*x;13221323if(skip_prefix(sb.buf,"Subject: ", &x)) {1324if(msg.len)1325strbuf_addch(&msg,'\n');1326strbuf_addstr(&msg, x);1327}else if(skip_prefix(sb.buf,"Author: ", &x))1328strbuf_addstr(&author_name, x);1329else if(skip_prefix(sb.buf,"Email: ", &x))1330strbuf_addstr(&author_email, x);1331else if(skip_prefix(sb.buf,"Date: ", &x))1332strbuf_addstr(&author_date, x);1333}1334fclose(fp);13351336/* Skip pine's internal folder data */1337if(!strcmp(author_name.buf,"Mail System Internal Data")) {1338 ret =1;1339goto finish;1340}13411342if(is_empty_file(am_path(state,"patch"))) {1343printf_ln(_("Patch is empty. Was it split wrong?"));1344die_user_resolve(state);1345}13461347strbuf_addstr(&msg,"\n\n");1348strbuf_addbuf(&msg, &mi.log_message);1349strbuf_stripspace(&msg,0);13501351if(state->signoff)1352am_signoff(&msg);13531354assert(!state->author_name);1355 state->author_name =strbuf_detach(&author_name, NULL);13561357assert(!state->author_email);1358 state->author_email =strbuf_detach(&author_email, NULL);13591360assert(!state->author_date);1361 state->author_date =strbuf_detach(&author_date, NULL);13621363assert(!state->msg);1364 state->msg =strbuf_detach(&msg, &state->msg_len);13651366finish:1367strbuf_release(&msg);1368strbuf_release(&author_date);1369strbuf_release(&author_email);1370strbuf_release(&author_name);1371strbuf_release(&sb);1372clear_mailinfo(&mi);1373return ret;1374}13751376/**1377 * Sets commit_id to the commit hash where the mail was generated from.1378 * Returns 0 on success, -1 on failure.1379 */1380static intget_mail_commit_sha1(unsigned char*commit_id,const char*mail)1381{1382struct strbuf sb = STRBUF_INIT;1383FILE*fp =xfopen(mail,"r");1384const char*x;13851386if(strbuf_getline(&sb, fp,'\n'))1387return-1;13881389if(!skip_prefix(sb.buf,"From ", &x))1390return-1;13911392if(get_sha1_hex(x, commit_id) <0)1393return-1;13941395strbuf_release(&sb);1396fclose(fp);1397return0;1398}13991400/**1401 * Sets state->msg, state->author_name, state->author_email, state->author_date1402 * to the commit's respective info.1403 */1404static voidget_commit_info(struct am_state *state,struct commit *commit)1405{1406const char*buffer, *ident_line, *author_date, *msg;1407size_t ident_len;1408struct ident_split ident_split;1409struct strbuf sb = STRBUF_INIT;14101411 buffer =logmsg_reencode(commit, NULL,get_commit_output_encoding());14121413 ident_line =find_commit_header(buffer,"author", &ident_len);14141415if(split_ident_line(&ident_split, ident_line, ident_len) <0) {1416strbuf_add(&sb, ident_line, ident_len);1417die(_("invalid ident line:%s"), sb.buf);1418}14191420assert(!state->author_name);1421if(ident_split.name_begin) {1422strbuf_add(&sb, ident_split.name_begin,1423 ident_split.name_end - ident_split.name_begin);1424 state->author_name =strbuf_detach(&sb, NULL);1425}else1426 state->author_name =xstrdup("");14271428assert(!state->author_email);1429if(ident_split.mail_begin) {1430strbuf_add(&sb, ident_split.mail_begin,1431 ident_split.mail_end - ident_split.mail_begin);1432 state->author_email =strbuf_detach(&sb, NULL);1433}else1434 state->author_email =xstrdup("");14351436 author_date =show_ident_date(&ident_split,DATE_MODE(NORMAL));1437strbuf_addstr(&sb, author_date);1438assert(!state->author_date);1439 state->author_date =strbuf_detach(&sb, NULL);14401441assert(!state->msg);1442 msg =strstr(buffer,"\n\n");1443if(!msg)1444die(_("unable to parse commit%s"),oid_to_hex(&commit->object.oid));1445 state->msg =xstrdup(msg +2);1446 state->msg_len =strlen(state->msg);1447}14481449/**1450 * Writes `commit` as a patch to the state directory's "patch" file.1451 */1452static voidwrite_commit_patch(const struct am_state *state,struct commit *commit)1453{1454struct rev_info rev_info;1455FILE*fp;14561457 fp =xfopen(am_path(state,"patch"),"w");1458init_revisions(&rev_info, NULL);1459 rev_info.diff =1;1460 rev_info.abbrev =0;1461 rev_info.disable_stdin =1;1462 rev_info.show_root_diff =1;1463 rev_info.diffopt.output_format = DIFF_FORMAT_PATCH;1464 rev_info.no_commit_id =1;1465DIFF_OPT_SET(&rev_info.diffopt, BINARY);1466DIFF_OPT_SET(&rev_info.diffopt, FULL_INDEX);1467 rev_info.diffopt.use_color =0;1468 rev_info.diffopt.file = fp;1469 rev_info.diffopt.close_file =1;1470add_pending_object(&rev_info, &commit->object,"");1471diff_setup_done(&rev_info.diffopt);1472log_tree_commit(&rev_info, commit);1473}14741475/**1476 * Writes the diff of the index against HEAD as a patch to the state1477 * directory's "patch" file.1478 */1479static voidwrite_index_patch(const struct am_state *state)1480{1481struct tree *tree;1482unsigned char head[GIT_SHA1_RAWSZ];1483struct rev_info rev_info;1484FILE*fp;14851486if(!get_sha1_tree("HEAD", head))1487 tree =lookup_tree(head);1488else1489 tree =lookup_tree(EMPTY_TREE_SHA1_BIN);14901491 fp =xfopen(am_path(state,"patch"),"w");1492init_revisions(&rev_info, NULL);1493 rev_info.diff =1;1494 rev_info.disable_stdin =1;1495 rev_info.no_commit_id =1;1496 rev_info.diffopt.output_format = DIFF_FORMAT_PATCH;1497 rev_info.diffopt.use_color =0;1498 rev_info.diffopt.file = fp;1499 rev_info.diffopt.close_file =1;1500add_pending_object(&rev_info, &tree->object,"");1501diff_setup_done(&rev_info.diffopt);1502run_diff_index(&rev_info,1);1503}15041505/**1506 * Like parse_mail(), but parses the mail by looking up its commit ID1507 * directly. This is used in --rebasing mode to bypass git-mailinfo's munging1508 * of patches.1509 *1510 * state->orig_commit will be set to the original commit ID.1511 *1512 * Will always return 0 as the patch should never be skipped.1513 */1514static intparse_mail_rebase(struct am_state *state,const char*mail)1515{1516struct commit *commit;1517unsigned char commit_sha1[GIT_SHA1_RAWSZ];15181519if(get_mail_commit_sha1(commit_sha1, mail) <0)1520die(_("could not parse%s"), mail);15211522 commit =lookup_commit_or_die(commit_sha1, mail);15231524get_commit_info(state, commit);15251526write_commit_patch(state, commit);15271528hashcpy(state->orig_commit, commit_sha1);1529write_state_text(state,"original-commit",sha1_to_hex(commit_sha1));15301531return0;1532}15331534/**1535 * Applies current patch with git-apply. Returns 0 on success, -1 otherwise. If1536 * `index_file` is not NULL, the patch will be applied to that index.1537 */1538static intrun_apply(const struct am_state *state,const char*index_file)1539{1540struct child_process cp = CHILD_PROCESS_INIT;15411542 cp.git_cmd =1;15431544if(index_file)1545argv_array_pushf(&cp.env_array,"GIT_INDEX_FILE=%s", index_file);15461547/*1548 * If we are allowed to fall back on 3-way merge, don't give false1549 * errors during the initial attempt.1550 */1551if(state->threeway && !index_file) {1552 cp.no_stdout =1;1553 cp.no_stderr =1;1554}15551556argv_array_push(&cp.args,"apply");15571558argv_array_pushv(&cp.args, state->git_apply_opts.argv);15591560if(index_file)1561argv_array_push(&cp.args,"--cached");1562else1563argv_array_push(&cp.args,"--index");15641565argv_array_push(&cp.args,am_path(state,"patch"));15661567if(run_command(&cp))1568return-1;15691570/* Reload index as git-apply will have modified it. */1571discard_cache();1572read_cache_from(index_file ? index_file :get_index_file());15731574return0;1575}15761577/**1578 * Builds an index that contains just the blobs needed for a 3way merge.1579 */1580static intbuild_fake_ancestor(const struct am_state *state,const char*index_file)1581{1582struct child_process cp = CHILD_PROCESS_INIT;15831584 cp.git_cmd =1;1585argv_array_push(&cp.args,"apply");1586argv_array_pushv(&cp.args, state->git_apply_opts.argv);1587argv_array_pushf(&cp.args,"--build-fake-ancestor=%s", index_file);1588argv_array_push(&cp.args,am_path(state,"patch"));15891590if(run_command(&cp))1591return-1;15921593return0;1594}15951596/**1597 * Do the three-way merge using fake ancestor, his tree constructed1598 * from the fake ancestor and the postimage of the patch, and our1599 * state.1600 */1601static intrun_fallback_merge_recursive(const struct am_state *state,1602unsigned char*orig_tree,1603unsigned char*our_tree,1604unsigned char*his_tree)1605{1606struct child_process cp = CHILD_PROCESS_INIT;1607int status;16081609 cp.git_cmd =1;16101611argv_array_pushf(&cp.env_array,"GITHEAD_%s=%.*s",1612sha1_to_hex(his_tree),linelen(state->msg), state->msg);1613if(state->quiet)1614argv_array_push(&cp.env_array,"GIT_MERGE_VERBOSITY=0");16151616argv_array_push(&cp.args,"merge-recursive");1617argv_array_push(&cp.args,sha1_to_hex(orig_tree));1618argv_array_push(&cp.args,"--");1619argv_array_push(&cp.args,sha1_to_hex(our_tree));1620argv_array_push(&cp.args,sha1_to_hex(his_tree));16211622 status =run_command(&cp) ? (-1) :0;1623discard_cache();1624read_cache();1625return status;1626}16271628/**1629 * Attempt a threeway merge, using index_path as the temporary index.1630 */1631static intfall_back_threeway(const struct am_state *state,const char*index_path)1632{1633unsigned char orig_tree[GIT_SHA1_RAWSZ], his_tree[GIT_SHA1_RAWSZ],1634 our_tree[GIT_SHA1_RAWSZ];16351636if(get_sha1("HEAD", our_tree) <0)1637hashcpy(our_tree, EMPTY_TREE_SHA1_BIN);16381639if(build_fake_ancestor(state, index_path))1640returnerror("could not build fake ancestor");16411642discard_cache();1643read_cache_from(index_path);16441645if(write_index_as_tree(orig_tree, &the_index, index_path,0, NULL))1646returnerror(_("Repository lacks necessary blobs to fall back on 3-way merge."));16471648say(state, stdout,_("Using index info to reconstruct a base tree..."));16491650if(!state->quiet) {1651/*1652 * List paths that needed 3-way fallback, so that the user can1653 * review them with extra care to spot mismerges.1654 */1655struct rev_info rev_info;1656const char*diff_filter_str ="--diff-filter=AM";16571658init_revisions(&rev_info, NULL);1659 rev_info.diffopt.output_format = DIFF_FORMAT_NAME_STATUS;1660diff_opt_parse(&rev_info.diffopt, &diff_filter_str,1);1661add_pending_sha1(&rev_info,"HEAD", our_tree,0);1662diff_setup_done(&rev_info.diffopt);1663run_diff_index(&rev_info,1);1664}16651666if(run_apply(state, index_path))1667returnerror(_("Did you hand edit your patch?\n"1668"It does not apply to blobs recorded in its index."));16691670if(write_index_as_tree(his_tree, &the_index, index_path,0, NULL))1671returnerror("could not write tree");16721673say(state, stdout,_("Falling back to patching base and 3-way merge..."));16741675discard_cache();1676read_cache();16771678/*1679 * This is not so wrong. Depending on which base we picked, orig_tree1680 * may be wildly different from ours, but his_tree has the same set of1681 * wildly different changes in parts the patch did not touch, so1682 * recursive ends up canceling them, saying that we reverted all those1683 * changes.1684 */16851686if(run_fallback_merge_recursive(state, orig_tree, our_tree, his_tree)) {1687rerere(state->allow_rerere_autoupdate);1688returnerror(_("Failed to merge in the changes."));1689}16901691return0;1692}16931694/**1695 * Commits the current index with state->msg as the commit message and1696 * state->author_name, state->author_email and state->author_date as the author1697 * information.1698 */1699static voiddo_commit(const struct am_state *state)1700{1701unsigned char tree[GIT_SHA1_RAWSZ], parent[GIT_SHA1_RAWSZ],1702 commit[GIT_SHA1_RAWSZ];1703unsigned char*ptr;1704struct commit_list *parents = NULL;1705const char*reflog_msg, *author;1706struct strbuf sb = STRBUF_INIT;17071708if(run_hook_le(NULL,"pre-applypatch", NULL))1709exit(1);17101711if(write_cache_as_tree(tree,0, NULL))1712die(_("git write-tree failed to write a tree"));17131714if(!get_sha1_commit("HEAD", parent)) {1715 ptr = parent;1716commit_list_insert(lookup_commit(parent), &parents);1717}else{1718 ptr = NULL;1719say(state, stderr,_("applying to an empty history"));1720}17211722 author =fmt_ident(state->author_name, state->author_email,1723 state->ignore_date ? NULL : state->author_date,1724 IDENT_STRICT);17251726if(state->committer_date_is_author_date)1727setenv("GIT_COMMITTER_DATE",1728 state->ignore_date ?"": state->author_date,1);17291730if(commit_tree(state->msg, state->msg_len, tree, parents, commit,1731 author, state->sign_commit))1732die(_("failed to write commit object"));17331734 reflog_msg =getenv("GIT_REFLOG_ACTION");1735if(!reflog_msg)1736 reflog_msg ="am";17371738strbuf_addf(&sb,"%s: %.*s", reflog_msg,linelen(state->msg),1739 state->msg);17401741update_ref(sb.buf,"HEAD", commit, ptr,0, UPDATE_REFS_DIE_ON_ERR);17421743if(state->rebasing) {1744FILE*fp =xfopen(am_path(state,"rewritten"),"a");17451746assert(!is_null_sha1(state->orig_commit));1747fprintf(fp,"%s",sha1_to_hex(state->orig_commit));1748fprintf(fp,"%s\n",sha1_to_hex(commit));1749fclose(fp);1750}17511752run_hook_le(NULL,"post-applypatch", NULL);17531754strbuf_release(&sb);1755}17561757/**1758 * Validates the am_state for resuming -- the "msg" and authorship fields must1759 * be filled up.1760 */1761static voidvalidate_resume_state(const struct am_state *state)1762{1763if(!state->msg)1764die(_("cannot resume:%sdoes not exist."),1765am_path(state,"final-commit"));17661767if(!state->author_name || !state->author_email || !state->author_date)1768die(_("cannot resume:%sdoes not exist."),1769am_path(state,"author-script"));1770}17711772/**1773 * Interactively prompt the user on whether the current patch should be1774 * applied.1775 *1776 * Returns 0 if the user chooses to apply the patch, 1 if the user chooses to1777 * skip it.1778 */1779static intdo_interactive(struct am_state *state)1780{1781assert(state->msg);17821783if(!isatty(0))1784die(_("cannot be interactive without stdin connected to a terminal."));17851786for(;;) {1787const char*reply;17881789puts(_("Commit Body is:"));1790puts("--------------------------");1791printf("%s", state->msg);1792puts("--------------------------");17931794/*1795 * TRANSLATORS: Make sure to include [y], [n], [e], [v] and [a]1796 * in your translation. The program will only accept English1797 * input at this point.1798 */1799 reply =git_prompt(_("Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all: "), PROMPT_ECHO);18001801if(!reply) {1802continue;1803}else if(*reply =='y'|| *reply =='Y') {1804return0;1805}else if(*reply =='a'|| *reply =='A') {1806 state->interactive =0;1807return0;1808}else if(*reply =='n'|| *reply =='N') {1809return1;1810}else if(*reply =='e'|| *reply =='E') {1811struct strbuf msg = STRBUF_INIT;18121813if(!launch_editor(am_path(state,"final-commit"), &msg, NULL)) {1814free(state->msg);1815 state->msg =strbuf_detach(&msg, &state->msg_len);1816}1817strbuf_release(&msg);1818}else if(*reply =='v'|| *reply =='V') {1819const char*pager =git_pager(1);1820struct child_process cp = CHILD_PROCESS_INIT;18211822if(!pager)1823 pager ="cat";1824argv_array_push(&cp.args, pager);1825argv_array_push(&cp.args,am_path(state,"patch"));1826run_command(&cp);1827}1828}1829}18301831/**1832 * Applies all queued mail.1833 *1834 * If `resume` is true, we are "resuming". The "msg" and authorship fields, as1835 * well as the state directory's "patch" file is used as-is for applying the1836 * patch and committing it.1837 */1838static voidam_run(struct am_state *state,int resume)1839{1840const char*argv_gc_auto[] = {"gc","--auto", NULL};1841struct strbuf sb = STRBUF_INIT;18421843unlink(am_path(state,"dirtyindex"));18441845refresh_and_write_cache();18461847if(index_has_changes(&sb)) {1848write_state_bool(state,"dirtyindex",1);1849die(_("Dirty index: cannot apply patches (dirty:%s)"), sb.buf);1850}18511852strbuf_release(&sb);18531854while(state->cur <= state->last) {1855const char*mail =am_path(state,msgnum(state));1856int apply_status;18571858if(!file_exists(mail))1859goto next;18601861if(resume) {1862validate_resume_state(state);1863}else{1864int skip;18651866if(state->rebasing)1867 skip =parse_mail_rebase(state, mail);1868else1869 skip =parse_mail(state, mail);18701871if(skip)1872goto next;/* mail should be skipped */18731874write_author_script(state);1875write_commit_msg(state);1876}18771878if(state->interactive &&do_interactive(state))1879goto next;18801881if(run_applypatch_msg_hook(state))1882exit(1);18831884say(state, stdout,_("Applying: %.*s"),linelen(state->msg), state->msg);18851886 apply_status =run_apply(state, NULL);18871888if(apply_status && state->threeway) {1889struct strbuf sb = STRBUF_INIT;18901891strbuf_addstr(&sb,am_path(state,"patch-merge-index"));1892 apply_status =fall_back_threeway(state, sb.buf);1893strbuf_release(&sb);18941895/*1896 * Applying the patch to an earlier tree and merging1897 * the result may have produced the same tree as ours.1898 */1899if(!apply_status && !index_has_changes(NULL)) {1900say(state, stdout,_("No changes -- Patch already applied."));1901goto next;1902}1903}19041905if(apply_status) {1906int advice_amworkdir =1;19071908printf_ln(_("Patch failed at%s%.*s"),msgnum(state),1909linelen(state->msg), state->msg);19101911git_config_get_bool("advice.amworkdir", &advice_amworkdir);19121913if(advice_amworkdir)1914printf_ln(_("The copy of the patch that failed is found in:%s"),1915am_path(state,"patch"));19161917die_user_resolve(state);1918}19191920do_commit(state);19211922next:1923am_next(state);19241925if(resume)1926am_load(state);1927 resume =0;1928}19291930if(!is_empty_file(am_path(state,"rewritten"))) {1931assert(state->rebasing);1932copy_notes_for_rebase(state);1933run_post_rewrite_hook(state);1934}19351936/*1937 * In rebasing mode, it's up to the caller to take care of1938 * housekeeping.1939 */1940if(!state->rebasing) {1941am_destroy(state);1942run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);1943}1944}19451946/**1947 * Resume the current am session after patch application failure. The user did1948 * all the hard work, and we do not have to do any patch application. Just1949 * trust and commit what the user has in the index and working tree.1950 */1951static voidam_resolve(struct am_state *state)1952{1953validate_resume_state(state);19541955say(state, stdout,_("Applying: %.*s"),linelen(state->msg), state->msg);19561957if(!index_has_changes(NULL)) {1958printf_ln(_("No changes - did you forget to use 'git add'?\n"1959"If there is nothing left to stage, chances are that something else\n"1960"already introduced the same changes; you might want to skip this patch."));1961die_user_resolve(state);1962}19631964if(unmerged_cache()) {1965printf_ln(_("You still have unmerged paths in your index.\n"1966"Did you forget to use 'git add'?"));1967die_user_resolve(state);1968}19691970if(state->interactive) {1971write_index_patch(state);1972if(do_interactive(state))1973goto next;1974}19751976rerere(0);19771978do_commit(state);19791980next:1981am_next(state);1982am_load(state);1983am_run(state,0);1984}19851986/**1987 * Performs a checkout fast-forward from `head` to `remote`. If `reset` is1988 * true, any unmerged entries will be discarded. Returns 0 on success, -1 on1989 * failure.1990 */1991static intfast_forward_to(struct tree *head,struct tree *remote,int reset)1992{1993struct lock_file *lock_file;1994struct unpack_trees_options opts;1995struct tree_desc t[2];19961997if(parse_tree(head) ||parse_tree(remote))1998return-1;19992000 lock_file =xcalloc(1,sizeof(struct lock_file));2001hold_locked_index(lock_file,1);20022003refresh_cache(REFRESH_QUIET);20042005memset(&opts,0,sizeof(opts));2006 opts.head_idx =1;2007 opts.src_index = &the_index;2008 opts.dst_index = &the_index;2009 opts.update =1;2010 opts.merge =1;2011 opts.reset = reset;2012 opts.fn = twoway_merge;2013init_tree_desc(&t[0], head->buffer, head->size);2014init_tree_desc(&t[1], remote->buffer, remote->size);20152016if(unpack_trees(2, t, &opts)) {2017rollback_lock_file(lock_file);2018return-1;2019}20202021if(write_locked_index(&the_index, lock_file, COMMIT_LOCK))2022die(_("unable to write new index file"));20232024return0;2025}20262027/**2028 * Merges a tree into the index. The index's stat info will take precedence2029 * over the merged tree's. Returns 0 on success, -1 on failure.2030 */2031static intmerge_tree(struct tree *tree)2032{2033struct lock_file *lock_file;2034struct unpack_trees_options opts;2035struct tree_desc t[1];20362037if(parse_tree(tree))2038return-1;20392040 lock_file =xcalloc(1,sizeof(struct lock_file));2041hold_locked_index(lock_file,1);20422043memset(&opts,0,sizeof(opts));2044 opts.head_idx =1;2045 opts.src_index = &the_index;2046 opts.dst_index = &the_index;2047 opts.merge =1;2048 opts.fn = oneway_merge;2049init_tree_desc(&t[0], tree->buffer, tree->size);20502051if(unpack_trees(1, t, &opts)) {2052rollback_lock_file(lock_file);2053return-1;2054}20552056if(write_locked_index(&the_index, lock_file, COMMIT_LOCK))2057die(_("unable to write new index file"));20582059return0;2060}20612062/**2063 * Clean the index without touching entries that are not modified between2064 * `head` and `remote`.2065 */2066static intclean_index(const unsigned char*head,const unsigned char*remote)2067{2068struct tree *head_tree, *remote_tree, *index_tree;2069unsigned char index[GIT_SHA1_RAWSZ];20702071 head_tree =parse_tree_indirect(head);2072if(!head_tree)2073returnerror(_("Could not parse object '%s'."),sha1_to_hex(head));20742075 remote_tree =parse_tree_indirect(remote);2076if(!remote_tree)2077returnerror(_("Could not parse object '%s'."),sha1_to_hex(remote));20782079read_cache_unmerged();20802081if(fast_forward_to(head_tree, head_tree,1))2082return-1;20832084if(write_cache_as_tree(index,0, NULL))2085return-1;20862087 index_tree =parse_tree_indirect(index);2088if(!index_tree)2089returnerror(_("Could not parse object '%s'."),sha1_to_hex(index));20902091if(fast_forward_to(index_tree, remote_tree,0))2092return-1;20932094if(merge_tree(remote_tree))2095return-1;20962097remove_branch_state();20982099return0;2100}21012102/**2103 * Resets rerere's merge resolution metadata.2104 */2105static voidam_rerere_clear(void)2106{2107struct string_list merge_rr = STRING_LIST_INIT_DUP;2108rerere_clear(&merge_rr);2109string_list_clear(&merge_rr,1);2110}21112112/**2113 * Resume the current am session by skipping the current patch.2114 */2115static voidam_skip(struct am_state *state)2116{2117unsigned char head[GIT_SHA1_RAWSZ];21182119am_rerere_clear();21202121if(get_sha1("HEAD", head))2122hashcpy(head, EMPTY_TREE_SHA1_BIN);21232124if(clean_index(head, head))2125die(_("failed to clean index"));21262127am_next(state);2128am_load(state);2129am_run(state,0);2130}21312132/**2133 * Returns true if it is safe to reset HEAD to the ORIG_HEAD, false otherwise.2134 *2135 * It is not safe to reset HEAD when:2136 * 1. git-am previously failed because the index was dirty.2137 * 2. HEAD has moved since git-am previously failed.2138 */2139static intsafe_to_abort(const struct am_state *state)2140{2141struct strbuf sb = STRBUF_INIT;2142unsigned char abort_safety[GIT_SHA1_RAWSZ], head[GIT_SHA1_RAWSZ];21432144if(file_exists(am_path(state,"dirtyindex")))2145return0;21462147if(read_state_file(&sb, state,"abort-safety",1) >0) {2148if(get_sha1_hex(sb.buf, abort_safety))2149die(_("could not parse%s"),am_path(state,"abort_safety"));2150}else2151hashclr(abort_safety);21522153if(get_sha1("HEAD", head))2154hashclr(head);21552156if(!hashcmp(head, abort_safety))2157return1;21582159error(_("You seem to have moved HEAD since the last 'am' failure.\n"2160"Not rewinding to ORIG_HEAD"));21612162return0;2163}21642165/**2166 * Aborts the current am session if it is safe to do so.2167 */2168static voidam_abort(struct am_state *state)2169{2170unsigned char curr_head[GIT_SHA1_RAWSZ], orig_head[GIT_SHA1_RAWSZ];2171int has_curr_head, has_orig_head;2172char*curr_branch;21732174if(!safe_to_abort(state)) {2175am_destroy(state);2176return;2177}21782179am_rerere_clear();21802181 curr_branch =resolve_refdup("HEAD",0, curr_head, NULL);2182 has_curr_head = !is_null_sha1(curr_head);2183if(!has_curr_head)2184hashcpy(curr_head, EMPTY_TREE_SHA1_BIN);21852186 has_orig_head = !get_sha1("ORIG_HEAD", orig_head);2187if(!has_orig_head)2188hashcpy(orig_head, EMPTY_TREE_SHA1_BIN);21892190clean_index(curr_head, orig_head);21912192if(has_orig_head)2193update_ref("am --abort","HEAD", orig_head,2194 has_curr_head ? curr_head : NULL,0,2195 UPDATE_REFS_DIE_ON_ERR);2196else if(curr_branch)2197delete_ref(curr_branch, NULL, REF_NODEREF);21982199free(curr_branch);2200am_destroy(state);2201}22022203/**2204 * parse_options() callback that validates and sets opt->value to the2205 * PATCH_FORMAT_* enum value corresponding to `arg`.2206 */2207static intparse_opt_patchformat(const struct option *opt,const char*arg,int unset)2208{2209int*opt_value = opt->value;22102211if(!strcmp(arg,"mbox"))2212*opt_value = PATCH_FORMAT_MBOX;2213else if(!strcmp(arg,"stgit"))2214*opt_value = PATCH_FORMAT_STGIT;2215else if(!strcmp(arg,"stgit-series"))2216*opt_value = PATCH_FORMAT_STGIT_SERIES;2217else if(!strcmp(arg,"hg"))2218*opt_value = PATCH_FORMAT_HG;2219else2220returnerror(_("Invalid value for --patch-format:%s"), arg);2221return0;2222}22232224enum resume_mode {2225 RESUME_FALSE =0,2226 RESUME_APPLY,2227 RESUME_RESOLVED,2228 RESUME_SKIP,2229 RESUME_ABORT2230};22312232static intgit_am_config(const char*k,const char*v,void*cb)2233{2234int status;22352236 status =git_gpg_config(k, v, NULL);2237if(status)2238return status;22392240returngit_default_config(k, v, NULL);2241}22422243intcmd_am(int argc,const char**argv,const char*prefix)2244{2245struct am_state state;2246int binary = -1;2247int keep_cr = -1;2248int patch_format = PATCH_FORMAT_UNKNOWN;2249enum resume_mode resume = RESUME_FALSE;2250int in_progress;22512252const char*const usage[] = {2253N_("git am [<options>] [(<mbox>|<Maildir>)...]"),2254N_("git am [<options>] (--continue | --skip | --abort)"),2255 NULL2256};22572258struct option options[] = {2259OPT_BOOL('i',"interactive", &state.interactive,2260N_("run interactively")),2261OPT_HIDDEN_BOOL('b',"binary", &binary,2262N_("historical option -- no-op")),2263OPT_BOOL('3',"3way", &state.threeway,2264N_("allow fall back on 3way merging if needed")),2265OPT__QUIET(&state.quiet,N_("be quiet")),2266OPT_SET_INT('s',"signoff", &state.signoff,2267N_("add a Signed-off-by line to the commit message"),2268 SIGNOFF_EXPLICIT),2269OPT_BOOL('u',"utf8", &state.utf8,2270N_("recode into utf8 (default)")),2271OPT_SET_INT('k',"keep", &state.keep,2272N_("pass -k flag to git-mailinfo"), KEEP_TRUE),2273OPT_SET_INT(0,"keep-non-patch", &state.keep,2274N_("pass -b flag to git-mailinfo"), KEEP_NON_PATCH),2275OPT_BOOL('m',"message-id", &state.message_id,2276N_("pass -m flag to git-mailinfo")),2277{ OPTION_SET_INT,0,"keep-cr", &keep_cr, NULL,2278N_("pass --keep-cr flag to git-mailsplit for mbox format"),2279 PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL,1},2280{ OPTION_SET_INT,0,"no-keep-cr", &keep_cr, NULL,2281N_("do not pass --keep-cr flag to git-mailsplit independent of am.keepcr"),2282 PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL,0},2283OPT_BOOL('c',"scissors", &state.scissors,2284N_("strip everything before a scissors line")),2285OPT_PASSTHRU_ARGV(0,"whitespace", &state.git_apply_opts,N_("action"),2286N_("pass it through git-apply"),22870),2288OPT_PASSTHRU_ARGV(0,"ignore-space-change", &state.git_apply_opts, NULL,2289N_("pass it through git-apply"),2290 PARSE_OPT_NOARG),2291OPT_PASSTHRU_ARGV(0,"ignore-whitespace", &state.git_apply_opts, NULL,2292N_("pass it through git-apply"),2293 PARSE_OPT_NOARG),2294OPT_PASSTHRU_ARGV(0,"directory", &state.git_apply_opts,N_("root"),2295N_("pass it through git-apply"),22960),2297OPT_PASSTHRU_ARGV(0,"exclude", &state.git_apply_opts,N_("path"),2298N_("pass it through git-apply"),22990),2300OPT_PASSTHRU_ARGV(0,"include", &state.git_apply_opts,N_("path"),2301N_("pass it through git-apply"),23020),2303OPT_PASSTHRU_ARGV('C', NULL, &state.git_apply_opts,N_("n"),2304N_("pass it through git-apply"),23050),2306OPT_PASSTHRU_ARGV('p', NULL, &state.git_apply_opts,N_("num"),2307N_("pass it through git-apply"),23080),2309OPT_CALLBACK(0,"patch-format", &patch_format,N_("format"),2310N_("format the patch(es) are in"),2311 parse_opt_patchformat),2312OPT_PASSTHRU_ARGV(0,"reject", &state.git_apply_opts, NULL,2313N_("pass it through git-apply"),2314 PARSE_OPT_NOARG),2315OPT_STRING(0,"resolvemsg", &state.resolvemsg, NULL,2316N_("override error message when patch failure occurs")),2317OPT_CMDMODE(0,"continue", &resume,2318N_("continue applying patches after resolving a conflict"),2319 RESUME_RESOLVED),2320OPT_CMDMODE('r',"resolved", &resume,2321N_("synonyms for --continue"),2322 RESUME_RESOLVED),2323OPT_CMDMODE(0,"skip", &resume,2324N_("skip the current patch"),2325 RESUME_SKIP),2326OPT_CMDMODE(0,"abort", &resume,2327N_("restore the original branch and abort the patching operation."),2328 RESUME_ABORT),2329OPT_BOOL(0,"committer-date-is-author-date",2330&state.committer_date_is_author_date,2331N_("lie about committer date")),2332OPT_BOOL(0,"ignore-date", &state.ignore_date,2333N_("use current timestamp for author date")),2334OPT_RERERE_AUTOUPDATE(&state.allow_rerere_autoupdate),2335{ OPTION_STRING,'S',"gpg-sign", &state.sign_commit,N_("key-id"),2336N_("GPG-sign commits"),2337 PARSE_OPT_OPTARG, NULL, (intptr_t)""},2338OPT_HIDDEN_BOOL(0,"rebasing", &state.rebasing,2339N_("(internal use for git-rebase)")),2340OPT_END()2341};23422343git_config(git_am_config, NULL);23442345am_state_init(&state,git_path("rebase-apply"));23462347 in_progress =am_in_progress(&state);2348if(in_progress)2349am_load(&state);23502351 argc =parse_options(argc, argv, prefix, options, usage,0);23522353if(binary >=0)2354fprintf_ln(stderr,_("The -b/--binary option has been a no-op for long time, and\n"2355"it will be removed. Please do not use it anymore."));23562357/* Ensure a valid committer ident can be constructed */2358git_committer_info(IDENT_STRICT);23592360if(read_index_preload(&the_index, NULL) <0)2361die(_("failed to read the index"));23622363if(in_progress) {2364/*2365 * Catch user error to feed us patches when there is a session2366 * in progress:2367 *2368 * 1. mbox path(s) are provided on the command-line.2369 * 2. stdin is not a tty: the user is trying to feed us a patch2370 * from standard input. This is somewhat unreliable -- stdin2371 * could be /dev/null for example and the caller did not2372 * intend to feed us a patch but wanted to continue2373 * unattended.2374 */2375if(argc || (resume == RESUME_FALSE && !isatty(0)))2376die(_("previous rebase directory%sstill exists but mbox given."),2377 state.dir);23782379if(resume == RESUME_FALSE)2380 resume = RESUME_APPLY;23812382if(state.signoff == SIGNOFF_EXPLICIT)2383am_append_signoff(&state);2384}else{2385struct argv_array paths = ARGV_ARRAY_INIT;2386int i;23872388/*2389 * Handle stray state directory in the independent-run case. In2390 * the --rebasing case, it is up to the caller to take care of2391 * stray directories.2392 */2393if(file_exists(state.dir) && !state.rebasing) {2394if(resume == RESUME_ABORT) {2395am_destroy(&state);2396am_state_release(&state);2397return0;2398}23992400die(_("Stray%sdirectory found.\n"2401"Use\"git am --abort\"to remove it."),2402 state.dir);2403}24042405if(resume)2406die(_("Resolve operation not in progress, we are not resuming."));24072408for(i =0; i < argc; i++) {2409if(is_absolute_path(argv[i]) || !prefix)2410argv_array_push(&paths, argv[i]);2411else2412argv_array_push(&paths,mkpath("%s/%s", prefix, argv[i]));2413}24142415am_setup(&state, patch_format, paths.argv, keep_cr);24162417argv_array_clear(&paths);2418}24192420switch(resume) {2421case RESUME_FALSE:2422am_run(&state,0);2423break;2424case RESUME_APPLY:2425am_run(&state,1);2426break;2427case RESUME_RESOLVED:2428am_resolve(&state);2429break;2430case RESUME_SKIP:2431am_skip(&state);2432break;2433case RESUME_ABORT:2434am_abort(&state);2435break;2436default:2437die("BUG: invalid resume value");2438}24392440am_state_release(&state);24412442return0;2443}