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"lockfile.h" 14#include"cache-tree.h" 15#include"refs.h" 16#include"commit.h" 17#include"diff.h" 18#include"diffcore.h" 19#include"unpack-trees.h" 20#include"branch.h" 21#include"sequencer.h" 22#include"revision.h" 23#include"merge-recursive.h" 24#include"revision.h" 25#include"log-tree.h" 26#include"notes-utils.h" 27#include"rerere.h" 28#include"prompt.h" 29 30/** 31 * Returns 1 if the file is empty or does not exist, 0 otherwise. 32 */ 33static intis_empty_file(const char*filename) 34{ 35struct stat st; 36 37if(stat(filename, &st) <0) { 38if(errno == ENOENT) 39return1; 40die_errno(_("could not stat%s"), filename); 41} 42 43return!st.st_size; 44} 45 46/** 47 * Like strbuf_getline(), but treats both '\n' and "\r\n" as line terminators. 48 */ 49static intstrbuf_getline_crlf(struct strbuf *sb,FILE*fp) 50{ 51if(strbuf_getwholeline(sb, fp,'\n')) 52return EOF; 53if(sb->buf[sb->len -1] =='\n') { 54strbuf_setlen(sb, sb->len -1); 55if(sb->len >0&& sb->buf[sb->len -1] =='\r') 56strbuf_setlen(sb, sb->len -1); 57} 58return0; 59} 60 61/** 62 * Returns the length of the first line of msg. 63 */ 64static intlinelen(const char*msg) 65{ 66returnstrchrnul(msg,'\n') - msg; 67} 68 69/** 70 * Returns true if `str` consists of only whitespace, false otherwise. 71 */ 72static intstr_isspace(const char*str) 73{ 74for(; *str; str++) 75if(!isspace(*str)) 76return0; 77 78return1; 79} 80 81enum patch_format { 82 PATCH_FORMAT_UNKNOWN =0, 83 PATCH_FORMAT_MBOX, 84 PATCH_FORMAT_STGIT, 85 PATCH_FORMAT_STGIT_SERIES, 86 PATCH_FORMAT_HG 87}; 88 89enum keep_type { 90 KEEP_FALSE =0, 91 KEEP_TRUE,/* pass -k flag to git-mailinfo */ 92 KEEP_NON_PATCH /* pass -b flag to git-mailinfo */ 93}; 94 95enum scissors_type { 96 SCISSORS_UNSET = -1, 97 SCISSORS_FALSE =0,/* pass --no-scissors to git-mailinfo */ 98 SCISSORS_TRUE /* pass --scissors to git-mailinfo */ 99}; 100 101struct am_state { 102/* state directory path */ 103char*dir; 104 105/* current and last patch numbers, 1-indexed */ 106int cur; 107int last; 108 109/* commit metadata and message */ 110char*author_name; 111char*author_email; 112char*author_date; 113char*msg; 114size_t msg_len; 115 116/* when --rebasing, records the original commit the patch came from */ 117unsigned char orig_commit[GIT_SHA1_RAWSZ]; 118 119/* number of digits in patch filename */ 120int prec; 121 122/* various operating modes and command line options */ 123int interactive; 124int threeway; 125int quiet; 126int signoff; 127int utf8; 128int keep;/* enum keep_type */ 129int message_id; 130int scissors;/* enum scissors_type */ 131struct argv_array git_apply_opts; 132const char*resolvemsg; 133int committer_date_is_author_date; 134int ignore_date; 135int allow_rerere_autoupdate; 136const char*sign_commit; 137int rebasing; 138}; 139 140/** 141 * Initializes am_state with the default values. The state directory is set to 142 * dir. 143 */ 144static voidam_state_init(struct am_state *state,const char*dir) 145{ 146int gpgsign; 147 148memset(state,0,sizeof(*state)); 149 150assert(dir); 151 state->dir =xstrdup(dir); 152 153 state->prec =4; 154 155 state->utf8 =1; 156 157git_config_get_bool("am.messageid", &state->message_id); 158 159 state->scissors = SCISSORS_UNSET; 160 161argv_array_init(&state->git_apply_opts); 162 163if(!git_config_get_bool("commit.gpgsign", &gpgsign)) 164 state->sign_commit = gpgsign ?"": NULL; 165} 166 167/** 168 * Releases memory allocated by an am_state. 169 */ 170static voidam_state_release(struct am_state *state) 171{ 172free(state->dir); 173free(state->author_name); 174free(state->author_email); 175free(state->author_date); 176free(state->msg); 177argv_array_clear(&state->git_apply_opts); 178} 179 180/** 181 * Returns path relative to the am_state directory. 182 */ 183staticinlineconst char*am_path(const struct am_state *state,const char*path) 184{ 185returnmkpath("%s/%s", state->dir, path); 186} 187 188/** 189 * If state->quiet is false, calls fprintf(fp, fmt, ...), and appends a newline 190 * at the end. 191 */ 192static voidsay(const struct am_state *state,FILE*fp,const char*fmt, ...) 193{ 194va_list ap; 195 196va_start(ap, fmt); 197if(!state->quiet) { 198vfprintf(fp, fmt, ap); 199putc('\n', fp); 200} 201va_end(ap); 202} 203 204/** 205 * Returns 1 if there is an am session in progress, 0 otherwise. 206 */ 207static intam_in_progress(const struct am_state *state) 208{ 209struct stat st; 210 211if(lstat(state->dir, &st) <0|| !S_ISDIR(st.st_mode)) 212return0; 213if(lstat(am_path(state,"last"), &st) || !S_ISREG(st.st_mode)) 214return0; 215if(lstat(am_path(state,"next"), &st) || !S_ISREG(st.st_mode)) 216return0; 217return1; 218} 219 220/** 221 * Reads the contents of `file` in the `state` directory into `sb`. Returns the 222 * number of bytes read on success, -1 if the file does not exist. If `trim` is 223 * set, trailing whitespace will be removed. 224 */ 225static intread_state_file(struct strbuf *sb,const struct am_state *state, 226const char*file,int trim) 227{ 228strbuf_reset(sb); 229 230if(strbuf_read_file(sb,am_path(state, file),0) >=0) { 231if(trim) 232strbuf_trim(sb); 233 234return sb->len; 235} 236 237if(errno == ENOENT) 238return-1; 239 240die_errno(_("could not read '%s'"),am_path(state, file)); 241} 242 243/** 244 * Reads a KEY=VALUE shell variable assignment from `fp`, returning the VALUE 245 * as a newly-allocated string. VALUE must be a quoted string, and the KEY must 246 * match `key`. Returns NULL on failure. 247 * 248 * This is used by read_author_script() to read the GIT_AUTHOR_* variables from 249 * the author-script. 250 */ 251static char*read_shell_var(FILE*fp,const char*key) 252{ 253struct strbuf sb = STRBUF_INIT; 254const char*str; 255 256if(strbuf_getline(&sb, fp,'\n')) 257goto fail; 258 259if(!skip_prefix(sb.buf, key, &str)) 260goto fail; 261 262if(!skip_prefix(str,"=", &str)) 263goto fail; 264 265strbuf_remove(&sb,0, str - sb.buf); 266 267 str =sq_dequote(sb.buf); 268if(!str) 269goto fail; 270 271returnstrbuf_detach(&sb, NULL); 272 273fail: 274strbuf_release(&sb); 275return NULL; 276} 277 278/** 279 * Reads and parses the state directory's "author-script" file, and sets 280 * state->author_name, state->author_email and state->author_date accordingly. 281 * Returns 0 on success, -1 if the file could not be parsed. 282 * 283 * The author script is of the format: 284 * 285 * GIT_AUTHOR_NAME='$author_name' 286 * GIT_AUTHOR_EMAIL='$author_email' 287 * GIT_AUTHOR_DATE='$author_date' 288 * 289 * where $author_name, $author_email and $author_date are quoted. We are strict 290 * with our parsing, as the file was meant to be eval'd in the old git-am.sh 291 * script, and thus if the file differs from what this function expects, it is 292 * better to bail out than to do something that the user does not expect. 293 */ 294static intread_author_script(struct am_state *state) 295{ 296const char*filename =am_path(state,"author-script"); 297FILE*fp; 298 299assert(!state->author_name); 300assert(!state->author_email); 301assert(!state->author_date); 302 303 fp =fopen(filename,"r"); 304if(!fp) { 305if(errno == ENOENT) 306return0; 307die_errno(_("could not open '%s' for reading"), filename); 308} 309 310 state->author_name =read_shell_var(fp,"GIT_AUTHOR_NAME"); 311if(!state->author_name) { 312fclose(fp); 313return-1; 314} 315 316 state->author_email =read_shell_var(fp,"GIT_AUTHOR_EMAIL"); 317if(!state->author_email) { 318fclose(fp); 319return-1; 320} 321 322 state->author_date =read_shell_var(fp,"GIT_AUTHOR_DATE"); 323if(!state->author_date) { 324fclose(fp); 325return-1; 326} 327 328if(fgetc(fp) != EOF) { 329fclose(fp); 330return-1; 331} 332 333fclose(fp); 334return0; 335} 336 337/** 338 * Saves state->author_name, state->author_email and state->author_date in the 339 * state directory's "author-script" file. 340 */ 341static voidwrite_author_script(const struct am_state *state) 342{ 343struct strbuf sb = STRBUF_INIT; 344 345strbuf_addstr(&sb,"GIT_AUTHOR_NAME="); 346sq_quote_buf(&sb, state->author_name); 347strbuf_addch(&sb,'\n'); 348 349strbuf_addstr(&sb,"GIT_AUTHOR_EMAIL="); 350sq_quote_buf(&sb, state->author_email); 351strbuf_addch(&sb,'\n'); 352 353strbuf_addstr(&sb,"GIT_AUTHOR_DATE="); 354sq_quote_buf(&sb, state->author_date); 355strbuf_addch(&sb,'\n'); 356 357write_file(am_path(state,"author-script"),1,"%s", sb.buf); 358 359strbuf_release(&sb); 360} 361 362/** 363 * Reads the commit message from the state directory's "final-commit" file, 364 * setting state->msg to its contents and state->msg_len to the length of its 365 * contents in bytes. 366 * 367 * Returns 0 on success, -1 if the file does not exist. 368 */ 369static intread_commit_msg(struct am_state *state) 370{ 371struct strbuf sb = STRBUF_INIT; 372 373assert(!state->msg); 374 375if(read_state_file(&sb, state,"final-commit",0) <0) { 376strbuf_release(&sb); 377return-1; 378} 379 380 state->msg =strbuf_detach(&sb, &state->msg_len); 381return0; 382} 383 384/** 385 * Saves state->msg in the state directory's "final-commit" file. 386 */ 387static voidwrite_commit_msg(const struct am_state *state) 388{ 389int fd; 390const char*filename =am_path(state,"final-commit"); 391 392 fd =xopen(filename, O_WRONLY | O_CREAT,0666); 393if(write_in_full(fd, state->msg, state->msg_len) <0) 394die_errno(_("could not write to%s"), filename); 395close(fd); 396} 397 398/** 399 * Loads state from disk. 400 */ 401static voidam_load(struct am_state *state) 402{ 403struct strbuf sb = STRBUF_INIT; 404 405if(read_state_file(&sb, state,"next",1) <0) 406die("BUG: state file 'next' does not exist"); 407 state->cur =strtol(sb.buf, NULL,10); 408 409if(read_state_file(&sb, state,"last",1) <0) 410die("BUG: state file 'last' does not exist"); 411 state->last =strtol(sb.buf, NULL,10); 412 413if(read_author_script(state) <0) 414die(_("could not parse author script")); 415 416read_commit_msg(state); 417 418if(read_state_file(&sb, state,"original-commit",1) <0) 419hashclr(state->orig_commit); 420else if(get_sha1_hex(sb.buf, state->orig_commit) <0) 421die(_("could not parse%s"),am_path(state,"original-commit")); 422 423read_state_file(&sb, state,"threeway",1); 424 state->threeway = !strcmp(sb.buf,"t"); 425 426read_state_file(&sb, state,"quiet",1); 427 state->quiet = !strcmp(sb.buf,"t"); 428 429read_state_file(&sb, state,"sign",1); 430 state->signoff = !strcmp(sb.buf,"t"); 431 432read_state_file(&sb, state,"utf8",1); 433 state->utf8 = !strcmp(sb.buf,"t"); 434 435read_state_file(&sb, state,"keep",1); 436if(!strcmp(sb.buf,"t")) 437 state->keep = KEEP_TRUE; 438else if(!strcmp(sb.buf,"b")) 439 state->keep = KEEP_NON_PATCH; 440else 441 state->keep = KEEP_FALSE; 442 443read_state_file(&sb, state,"messageid",1); 444 state->message_id = !strcmp(sb.buf,"t"); 445 446read_state_file(&sb, state,"scissors",1); 447if(!strcmp(sb.buf,"t")) 448 state->scissors = SCISSORS_TRUE; 449else if(!strcmp(sb.buf,"f")) 450 state->scissors = SCISSORS_FALSE; 451else 452 state->scissors = SCISSORS_UNSET; 453 454read_state_file(&sb, state,"apply-opt",1); 455argv_array_clear(&state->git_apply_opts); 456if(sq_dequote_to_argv_array(sb.buf, &state->git_apply_opts) <0) 457die(_("could not parse%s"),am_path(state,"apply-opt")); 458 459 state->rebasing = !!file_exists(am_path(state,"rebasing")); 460 461strbuf_release(&sb); 462} 463 464/** 465 * Removes the am_state directory, forcefully terminating the current am 466 * session. 467 */ 468static voidam_destroy(const struct am_state *state) 469{ 470struct strbuf sb = STRBUF_INIT; 471 472strbuf_addstr(&sb, state->dir); 473remove_dir_recursively(&sb,0); 474strbuf_release(&sb); 475} 476 477/** 478 * Runs applypatch-msg hook. Returns its exit code. 479 */ 480static intrun_applypatch_msg_hook(struct am_state *state) 481{ 482int ret; 483 484assert(state->msg); 485 ret =run_hook_le(NULL,"applypatch-msg",am_path(state,"final-commit"), NULL); 486 487if(!ret) { 488free(state->msg); 489 state->msg = NULL; 490if(read_commit_msg(state) <0) 491die(_("'%s' was deleted by the applypatch-msg hook"), 492am_path(state,"final-commit")); 493} 494 495return ret; 496} 497 498/** 499 * Runs post-rewrite hook. Returns it exit code. 500 */ 501static intrun_post_rewrite_hook(const struct am_state *state) 502{ 503struct child_process cp = CHILD_PROCESS_INIT; 504const char*hook =find_hook("post-rewrite"); 505int ret; 506 507if(!hook) 508return0; 509 510argv_array_push(&cp.args, hook); 511argv_array_push(&cp.args,"rebase"); 512 513 cp.in =xopen(am_path(state,"rewritten"), O_RDONLY); 514 cp.stdout_to_stderr =1; 515 516 ret =run_command(&cp); 517 518close(cp.in); 519return ret; 520} 521 522/** 523 * Reads the state directory's "rewritten" file, and copies notes from the old 524 * commits listed in the file to their rewritten commits. 525 * 526 * Returns 0 on success, -1 on failure. 527 */ 528static intcopy_notes_for_rebase(const struct am_state *state) 529{ 530struct notes_rewrite_cfg *c; 531struct strbuf sb = STRBUF_INIT; 532const char*invalid_line =_("Malformed input line: '%s'."); 533const char*msg ="Notes added by 'git rebase'"; 534FILE*fp; 535int ret =0; 536 537assert(state->rebasing); 538 539 c =init_copy_notes_for_rewrite("rebase"); 540if(!c) 541return0; 542 543 fp =xfopen(am_path(state,"rewritten"),"r"); 544 545while(!strbuf_getline(&sb, fp,'\n')) { 546unsigned char from_obj[GIT_SHA1_RAWSZ], to_obj[GIT_SHA1_RAWSZ]; 547 548if(sb.len != GIT_SHA1_HEXSZ *2+1) { 549 ret =error(invalid_line, sb.buf); 550goto finish; 551} 552 553if(get_sha1_hex(sb.buf, from_obj)) { 554 ret =error(invalid_line, sb.buf); 555goto finish; 556} 557 558if(sb.buf[GIT_SHA1_HEXSZ] !=' ') { 559 ret =error(invalid_line, sb.buf); 560goto finish; 561} 562 563if(get_sha1_hex(sb.buf + GIT_SHA1_HEXSZ +1, to_obj)) { 564 ret =error(invalid_line, sb.buf); 565goto finish; 566} 567 568if(copy_note_for_rewrite(c, from_obj, to_obj)) 569 ret =error(_("Failed to copy notes from '%s' to '%s'"), 570sha1_to_hex(from_obj),sha1_to_hex(to_obj)); 571} 572 573finish: 574finish_copy_notes_for_rewrite(c, msg); 575fclose(fp); 576strbuf_release(&sb); 577return ret; 578} 579 580/** 581 * Determines if the file looks like a piece of RFC2822 mail by grabbing all 582 * non-indented lines and checking if they look like they begin with valid 583 * header field names. 584 * 585 * Returns 1 if the file looks like a piece of mail, 0 otherwise. 586 */ 587static intis_mail(FILE*fp) 588{ 589const char*header_regex ="^[!-9;-~]+:"; 590struct strbuf sb = STRBUF_INIT; 591 regex_t regex; 592int ret =1; 593 594if(fseek(fp,0L, SEEK_SET)) 595die_errno(_("fseek failed")); 596 597if(regcomp(®ex, header_regex, REG_NOSUB | REG_EXTENDED)) 598die("invalid pattern:%s", header_regex); 599 600while(!strbuf_getline_crlf(&sb, fp)) { 601if(!sb.len) 602break;/* End of header */ 603 604/* Ignore indented folded lines */ 605if(*sb.buf =='\t'|| *sb.buf ==' ') 606continue; 607 608/* It's a header if it matches header_regex */ 609if(regexec(®ex, sb.buf,0, NULL,0)) { 610 ret =0; 611goto done; 612} 613} 614 615done: 616regfree(®ex); 617strbuf_release(&sb); 618return ret; 619} 620 621/** 622 * Attempts to detect the patch_format of the patches contained in `paths`, 623 * returning the PATCH_FORMAT_* enum value. Returns PATCH_FORMAT_UNKNOWN if 624 * detection fails. 625 */ 626static intdetect_patch_format(const char**paths) 627{ 628enum patch_format ret = PATCH_FORMAT_UNKNOWN; 629struct strbuf l1 = STRBUF_INIT; 630struct strbuf l2 = STRBUF_INIT; 631struct strbuf l3 = STRBUF_INIT; 632FILE*fp; 633 634/* 635 * We default to mbox format if input is from stdin and for directories 636 */ 637if(!*paths || !strcmp(*paths,"-") ||is_directory(*paths)) 638return PATCH_FORMAT_MBOX; 639 640/* 641 * Otherwise, check the first few lines of the first patch, starting 642 * from the first non-blank line, to try to detect its format. 643 */ 644 645 fp =xfopen(*paths,"r"); 646 647while(!strbuf_getline_crlf(&l1, fp)) { 648if(l1.len) 649break; 650} 651 652if(starts_with(l1.buf,"From ") ||starts_with(l1.buf,"From: ")) { 653 ret = PATCH_FORMAT_MBOX; 654goto done; 655} 656 657if(starts_with(l1.buf,"# This series applies on GIT commit")) { 658 ret = PATCH_FORMAT_STGIT_SERIES; 659goto done; 660} 661 662if(!strcmp(l1.buf,"# HG changeset patch")) { 663 ret = PATCH_FORMAT_HG; 664goto done; 665} 666 667strbuf_reset(&l2); 668strbuf_getline_crlf(&l2, fp); 669strbuf_reset(&l3); 670strbuf_getline_crlf(&l3, fp); 671 672/* 673 * If the second line is empty and the third is a From, Author or Date 674 * entry, this is likely an StGit patch. 675 */ 676if(l1.len && !l2.len && 677(starts_with(l3.buf,"From:") || 678starts_with(l3.buf,"Author:") || 679starts_with(l3.buf,"Date:"))) { 680 ret = PATCH_FORMAT_STGIT; 681goto done; 682} 683 684if(l1.len &&is_mail(fp)) { 685 ret = PATCH_FORMAT_MBOX; 686goto done; 687} 688 689done: 690fclose(fp); 691strbuf_release(&l1); 692return ret; 693} 694 695/** 696 * Splits out individual email patches from `paths`, where each path is either 697 * a mbox file or a Maildir. Returns 0 on success, -1 on failure. 698 */ 699static intsplit_mail_mbox(struct am_state *state,const char**paths,int keep_cr) 700{ 701struct child_process cp = CHILD_PROCESS_INIT; 702struct strbuf last = STRBUF_INIT; 703 704 cp.git_cmd =1; 705argv_array_push(&cp.args,"mailsplit"); 706argv_array_pushf(&cp.args,"-d%d", state->prec); 707argv_array_pushf(&cp.args,"-o%s", state->dir); 708argv_array_push(&cp.args,"-b"); 709if(keep_cr) 710argv_array_push(&cp.args,"--keep-cr"); 711argv_array_push(&cp.args,"--"); 712argv_array_pushv(&cp.args, paths); 713 714if(capture_command(&cp, &last,8)) 715return-1; 716 717 state->cur =1; 718 state->last =strtol(last.buf, NULL,10); 719 720return0; 721} 722 723/** 724 * Callback signature for split_mail_conv(). The foreign patch should be 725 * read from `in`, and the converted patch (in RFC2822 mail format) should be 726 * written to `out`. Return 0 on success, or -1 on failure. 727 */ 728typedefint(*mail_conv_fn)(FILE*out,FILE*in,int keep_cr); 729 730/** 731 * Calls `fn` for each file in `paths` to convert the foreign patch to the 732 * RFC2822 mail format suitable for parsing with git-mailinfo. 733 * 734 * Returns 0 on success, -1 on failure. 735 */ 736static intsplit_mail_conv(mail_conv_fn fn,struct am_state *state, 737const char**paths,int keep_cr) 738{ 739static const char*stdin_only[] = {"-", NULL}; 740int i; 741 742if(!*paths) 743 paths = stdin_only; 744 745for(i =0; *paths; paths++, i++) { 746FILE*in, *out; 747const char*mail; 748int ret; 749 750if(!strcmp(*paths,"-")) 751 in = stdin; 752else 753 in =fopen(*paths,"r"); 754 755if(!in) 756returnerror(_("could not open '%s' for reading:%s"), 757*paths,strerror(errno)); 758 759 mail =mkpath("%s/%0*d", state->dir, state->prec, i +1); 760 761 out =fopen(mail,"w"); 762if(!out) 763returnerror(_("could not open '%s' for writing:%s"), 764 mail,strerror(errno)); 765 766 ret =fn(out, in, keep_cr); 767 768fclose(out); 769fclose(in); 770 771if(ret) 772returnerror(_("could not parse patch '%s'"), *paths); 773} 774 775 state->cur =1; 776 state->last = i; 777return0; 778} 779 780/** 781 * A split_mail_conv() callback that converts an StGit patch to an RFC2822 782 * message suitable for parsing with git-mailinfo. 783 */ 784static intstgit_patch_to_mail(FILE*out,FILE*in,int keep_cr) 785{ 786struct strbuf sb = STRBUF_INIT; 787int subject_printed =0; 788 789while(!strbuf_getline(&sb, in,'\n')) { 790const char*str; 791 792if(str_isspace(sb.buf)) 793continue; 794else if(skip_prefix(sb.buf,"Author:", &str)) 795fprintf(out,"From:%s\n", str); 796else if(starts_with(sb.buf,"From") ||starts_with(sb.buf,"Date")) 797fprintf(out,"%s\n", sb.buf); 798else if(!subject_printed) { 799fprintf(out,"Subject:%s\n", sb.buf); 800 subject_printed =1; 801}else{ 802fprintf(out,"\n%s\n", sb.buf); 803break; 804} 805} 806 807strbuf_reset(&sb); 808while(strbuf_fread(&sb,8192, in) >0) { 809fwrite(sb.buf,1, sb.len, out); 810strbuf_reset(&sb); 811} 812 813strbuf_release(&sb); 814return0; 815} 816 817/** 818 * This function only supports a single StGit series file in `paths`. 819 * 820 * Given an StGit series file, converts the StGit patches in the series into 821 * RFC2822 messages suitable for parsing with git-mailinfo, and queues them in 822 * the state directory. 823 * 824 * Returns 0 on success, -1 on failure. 825 */ 826static intsplit_mail_stgit_series(struct am_state *state,const char**paths, 827int keep_cr) 828{ 829const char*series_dir; 830char*series_dir_buf; 831FILE*fp; 832struct argv_array patches = ARGV_ARRAY_INIT; 833struct strbuf sb = STRBUF_INIT; 834int ret; 835 836if(!paths[0] || paths[1]) 837returnerror(_("Only one StGIT patch series can be applied at once")); 838 839 series_dir_buf =xstrdup(*paths); 840 series_dir =dirname(series_dir_buf); 841 842 fp =fopen(*paths,"r"); 843if(!fp) 844returnerror(_("could not open '%s' for reading:%s"), *paths, 845strerror(errno)); 846 847while(!strbuf_getline(&sb, fp,'\n')) { 848if(*sb.buf =='#') 849continue;/* skip comment lines */ 850 851argv_array_push(&patches,mkpath("%s/%s", series_dir, sb.buf)); 852} 853 854fclose(fp); 855strbuf_release(&sb); 856free(series_dir_buf); 857 858 ret =split_mail_conv(stgit_patch_to_mail, state, patches.argv, keep_cr); 859 860argv_array_clear(&patches); 861return ret; 862} 863 864/** 865 * A split_patches_conv() callback that converts a mercurial patch to a RFC2822 866 * message suitable for parsing with git-mailinfo. 867 */ 868static inthg_patch_to_mail(FILE*out,FILE*in,int keep_cr) 869{ 870struct strbuf sb = STRBUF_INIT; 871 872while(!strbuf_getline(&sb, in,'\n')) { 873const char*str; 874 875if(skip_prefix(sb.buf,"# User ", &str)) 876fprintf(out,"From:%s\n", str); 877else if(skip_prefix(sb.buf,"# Date ", &str)) { 878unsigned long timestamp; 879long tz, tz2; 880char*end; 881 882 errno =0; 883 timestamp =strtoul(str, &end,10); 884if(errno) 885returnerror(_("invalid timestamp")); 886 887if(!skip_prefix(end," ", &str)) 888returnerror(_("invalid Date line")); 889 890 errno =0; 891 tz =strtol(str, &end,10); 892if(errno) 893returnerror(_("invalid timezone offset")); 894 895if(*end) 896returnerror(_("invalid Date line")); 897 898/* 899 * mercurial's timezone is in seconds west of UTC, 900 * however git's timezone is in hours + minutes east of 901 * UTC. Convert it. 902 */ 903 tz2 =labs(tz) /3600*100+labs(tz) %3600/60; 904if(tz >0) 905 tz2 = -tz2; 906 907fprintf(out,"Date:%s\n",show_date(timestamp, tz2,DATE_MODE(RFC2822))); 908}else if(starts_with(sb.buf,"# ")) { 909continue; 910}else{ 911fprintf(out,"\n%s\n", sb.buf); 912break; 913} 914} 915 916strbuf_reset(&sb); 917while(strbuf_fread(&sb,8192, in) >0) { 918fwrite(sb.buf,1, sb.len, out); 919strbuf_reset(&sb); 920} 921 922strbuf_release(&sb); 923return0; 924} 925 926/** 927 * Splits a list of files/directories into individual email patches. Each path 928 * in `paths` must be a file/directory that is formatted according to 929 * `patch_format`. 930 * 931 * Once split out, the individual email patches will be stored in the state 932 * directory, with each patch's filename being its index, padded to state->prec 933 * digits. 934 * 935 * state->cur will be set to the index of the first mail, and state->last will 936 * be set to the index of the last mail. 937 * 938 * Set keep_cr to 0 to convert all lines ending with \r\n to end with \n, 1 939 * to disable this behavior, -1 to use the default configured setting. 940 * 941 * Returns 0 on success, -1 on failure. 942 */ 943static intsplit_mail(struct am_state *state,enum patch_format patch_format, 944const char**paths,int keep_cr) 945{ 946if(keep_cr <0) { 947 keep_cr =0; 948git_config_get_bool("am.keepcr", &keep_cr); 949} 950 951switch(patch_format) { 952case PATCH_FORMAT_MBOX: 953returnsplit_mail_mbox(state, paths, keep_cr); 954case PATCH_FORMAT_STGIT: 955returnsplit_mail_conv(stgit_patch_to_mail, state, paths, keep_cr); 956case PATCH_FORMAT_STGIT_SERIES: 957returnsplit_mail_stgit_series(state, paths, keep_cr); 958case PATCH_FORMAT_HG: 959returnsplit_mail_conv(hg_patch_to_mail, state, paths, keep_cr); 960default: 961die("BUG: invalid patch_format"); 962} 963return-1; 964} 965 966/** 967 * Setup a new am session for applying patches 968 */ 969static voidam_setup(struct am_state *state,enum patch_format patch_format, 970const char**paths,int keep_cr) 971{ 972unsigned char curr_head[GIT_SHA1_RAWSZ]; 973const char*str; 974struct strbuf sb = STRBUF_INIT; 975 976if(!patch_format) 977 patch_format =detect_patch_format(paths); 978 979if(!patch_format) { 980fprintf_ln(stderr,_("Patch format detection failed.")); 981exit(128); 982} 983 984if(mkdir(state->dir,0777) <0&& errno != EEXIST) 985die_errno(_("failed to create directory '%s'"), state->dir); 986 987if(split_mail(state, patch_format, paths, keep_cr) <0) { 988am_destroy(state); 989die(_("Failed to split patches.")); 990} 991 992if(state->rebasing) 993 state->threeway =1; 994 995write_file(am_path(state,"threeway"),1, state->threeway ?"t":"f"); 996 997write_file(am_path(state,"quiet"),1, state->quiet ?"t":"f"); 998 999write_file(am_path(state,"sign"),1, state->signoff ?"t":"f");10001001write_file(am_path(state,"utf8"),1, state->utf8 ?"t":"f");10021003switch(state->keep) {1004case KEEP_FALSE:1005 str ="f";1006break;1007case KEEP_TRUE:1008 str ="t";1009break;1010case KEEP_NON_PATCH:1011 str ="b";1012break;1013default:1014die("BUG: invalid value for state->keep");1015}10161017write_file(am_path(state,"keep"),1,"%s", str);10181019write_file(am_path(state,"messageid"),1, state->message_id ?"t":"f");10201021switch(state->scissors) {1022case SCISSORS_UNSET:1023 str ="";1024break;1025case SCISSORS_FALSE:1026 str ="f";1027break;1028case SCISSORS_TRUE:1029 str ="t";1030break;1031default:1032die("BUG: invalid value for state->scissors");1033}10341035write_file(am_path(state,"scissors"),1,"%s", str);10361037sq_quote_argv(&sb, state->git_apply_opts.argv,0);1038write_file(am_path(state,"apply-opt"),1,"%s", sb.buf);10391040if(state->rebasing)1041write_file(am_path(state,"rebasing"),1,"%s","");1042else1043write_file(am_path(state,"applying"),1,"%s","");10441045if(!get_sha1("HEAD", curr_head)) {1046write_file(am_path(state,"abort-safety"),1,"%s",sha1_to_hex(curr_head));1047if(!state->rebasing)1048update_ref("am","ORIG_HEAD", curr_head, NULL,0,1049 UPDATE_REFS_DIE_ON_ERR);1050}else{1051write_file(am_path(state,"abort-safety"),1,"%s","");1052if(!state->rebasing)1053delete_ref("ORIG_HEAD", NULL,0);1054}10551056/*1057 * NOTE: Since the "next" and "last" files determine if an am_state1058 * session is in progress, they should be written last.1059 */10601061write_file(am_path(state,"next"),1,"%d", state->cur);10621063write_file(am_path(state,"last"),1,"%d", state->last);10641065strbuf_release(&sb);1066}10671068/**1069 * Increments the patch pointer, and cleans am_state for the application of the1070 * next patch.1071 */1072static voidam_next(struct am_state *state)1073{1074unsigned char head[GIT_SHA1_RAWSZ];10751076free(state->author_name);1077 state->author_name = NULL;10781079free(state->author_email);1080 state->author_email = NULL;10811082free(state->author_date);1083 state->author_date = NULL;10841085free(state->msg);1086 state->msg = NULL;1087 state->msg_len =0;10881089unlink(am_path(state,"author-script"));1090unlink(am_path(state,"final-commit"));10911092hashclr(state->orig_commit);1093unlink(am_path(state,"original-commit"));10941095if(!get_sha1("HEAD", head))1096write_file(am_path(state,"abort-safety"),1,"%s",sha1_to_hex(head));1097else1098write_file(am_path(state,"abort-safety"),1,"%s","");10991100 state->cur++;1101write_file(am_path(state,"next"),1,"%d", state->cur);1102}11031104/**1105 * Returns the filename of the current patch email.1106 */1107static const char*msgnum(const struct am_state *state)1108{1109static struct strbuf sb = STRBUF_INIT;11101111strbuf_reset(&sb);1112strbuf_addf(&sb,"%0*d", state->prec, state->cur);11131114return sb.buf;1115}11161117/**1118 * Refresh and write index.1119 */1120static voidrefresh_and_write_cache(void)1121{1122struct lock_file *lock_file =xcalloc(1,sizeof(struct lock_file));11231124hold_locked_index(lock_file,1);1125refresh_cache(REFRESH_QUIET);1126if(write_locked_index(&the_index, lock_file, COMMIT_LOCK))1127die(_("unable to write index file"));1128}11291130/**1131 * Returns 1 if the index differs from HEAD, 0 otherwise. When on an unborn1132 * branch, returns 1 if there are entries in the index, 0 otherwise. If an1133 * strbuf is provided, the space-separated list of files that differ will be1134 * appended to it.1135 */1136static intindex_has_changes(struct strbuf *sb)1137{1138unsigned char head[GIT_SHA1_RAWSZ];1139int i;11401141if(!get_sha1_tree("HEAD", head)) {1142struct diff_options opt;11431144diff_setup(&opt);1145DIFF_OPT_SET(&opt, EXIT_WITH_STATUS);1146if(!sb)1147DIFF_OPT_SET(&opt, QUICK);1148do_diff_cache(head, &opt);1149diffcore_std(&opt);1150for(i =0; sb && i < diff_queued_diff.nr; i++) {1151if(i)1152strbuf_addch(sb,' ');1153strbuf_addstr(sb, diff_queued_diff.queue[i]->two->path);1154}1155diff_flush(&opt);1156returnDIFF_OPT_TST(&opt, HAS_CHANGES) !=0;1157}else{1158for(i =0; sb && i < active_nr; i++) {1159if(i)1160strbuf_addch(sb,' ');1161strbuf_addstr(sb, active_cache[i]->name);1162}1163return!!active_nr;1164}1165}11661167/**1168 * Dies with a user-friendly message on how to proceed after resolving the1169 * problem. This message can be overridden with state->resolvemsg.1170 */1171static void NORETURN die_user_resolve(const struct am_state *state)1172{1173if(state->resolvemsg) {1174printf_ln("%s", state->resolvemsg);1175}else{1176const char*cmdline = state->interactive ?"git am -i":"git am";11771178printf_ln(_("When you have resolved this problem, run\"%s--continue\"."), cmdline);1179printf_ln(_("If you prefer to skip this patch, run\"%s--skip\"instead."), cmdline);1180printf_ln(_("To restore the original branch and stop patching, run\"%s--abort\"."), cmdline);1181}11821183exit(128);1184}11851186/**1187 * Parses `mail` using git-mailinfo, extracting its patch and authorship info.1188 * state->msg will be set to the patch message. state->author_name,1189 * state->author_email and state->author_date will be set to the patch author's1190 * name, email and date respectively. The patch body will be written to the1191 * state directory's "patch" file.1192 *1193 * Returns 1 if the patch should be skipped, 0 otherwise.1194 */1195static intparse_mail(struct am_state *state,const char*mail)1196{1197FILE*fp;1198struct child_process cp = CHILD_PROCESS_INIT;1199struct strbuf sb = STRBUF_INIT;1200struct strbuf msg = STRBUF_INIT;1201struct strbuf author_name = STRBUF_INIT;1202struct strbuf author_date = STRBUF_INIT;1203struct strbuf author_email = STRBUF_INIT;1204int ret =0;12051206 cp.git_cmd =1;1207 cp.in =xopen(mail, O_RDONLY,0);1208 cp.out =xopen(am_path(state,"info"), O_WRONLY | O_CREAT,0777);12091210argv_array_push(&cp.args,"mailinfo");1211argv_array_push(&cp.args, state->utf8 ?"-u":"-n");12121213switch(state->keep) {1214case KEEP_FALSE:1215break;1216case KEEP_TRUE:1217argv_array_push(&cp.args,"-k");1218break;1219case KEEP_NON_PATCH:1220argv_array_push(&cp.args,"-b");1221break;1222default:1223die("BUG: invalid value for state->keep");1224}12251226if(state->message_id)1227argv_array_push(&cp.args,"-m");12281229switch(state->scissors) {1230case SCISSORS_UNSET:1231break;1232case SCISSORS_FALSE:1233argv_array_push(&cp.args,"--no-scissors");1234break;1235case SCISSORS_TRUE:1236argv_array_push(&cp.args,"--scissors");1237break;1238default:1239die("BUG: invalid value for state->scissors");1240}12411242argv_array_push(&cp.args,am_path(state,"msg"));1243argv_array_push(&cp.args,am_path(state,"patch"));12441245if(run_command(&cp) <0)1246die("could not parse patch");12471248close(cp.in);1249close(cp.out);12501251/* Extract message and author information */1252 fp =xfopen(am_path(state,"info"),"r");1253while(!strbuf_getline(&sb, fp,'\n')) {1254const char*x;12551256if(skip_prefix(sb.buf,"Subject: ", &x)) {1257if(msg.len)1258strbuf_addch(&msg,'\n');1259strbuf_addstr(&msg, x);1260}else if(skip_prefix(sb.buf,"Author: ", &x))1261strbuf_addstr(&author_name, x);1262else if(skip_prefix(sb.buf,"Email: ", &x))1263strbuf_addstr(&author_email, x);1264else if(skip_prefix(sb.buf,"Date: ", &x))1265strbuf_addstr(&author_date, x);1266}1267fclose(fp);12681269/* Skip pine's internal folder data */1270if(!strcmp(author_name.buf,"Mail System Internal Data")) {1271 ret =1;1272goto finish;1273}12741275if(is_empty_file(am_path(state,"patch"))) {1276printf_ln(_("Patch is empty. Was it split wrong?"));1277die_user_resolve(state);1278}12791280strbuf_addstr(&msg,"\n\n");1281if(strbuf_read_file(&msg,am_path(state,"msg"),0) <0)1282die_errno(_("could not read '%s'"),am_path(state,"msg"));1283stripspace(&msg,0);12841285if(state->signoff)1286append_signoff(&msg,0,0);12871288assert(!state->author_name);1289 state->author_name =strbuf_detach(&author_name, NULL);12901291assert(!state->author_email);1292 state->author_email =strbuf_detach(&author_email, NULL);12931294assert(!state->author_date);1295 state->author_date =strbuf_detach(&author_date, NULL);12961297assert(!state->msg);1298 state->msg =strbuf_detach(&msg, &state->msg_len);12991300finish:1301strbuf_release(&msg);1302strbuf_release(&author_date);1303strbuf_release(&author_email);1304strbuf_release(&author_name);1305strbuf_release(&sb);1306return ret;1307}13081309/**1310 * Sets commit_id to the commit hash where the mail was generated from.1311 * Returns 0 on success, -1 on failure.1312 */1313static intget_mail_commit_sha1(unsigned char*commit_id,const char*mail)1314{1315struct strbuf sb = STRBUF_INIT;1316FILE*fp =xfopen(mail,"r");1317const char*x;13181319if(strbuf_getline(&sb, fp,'\n'))1320return-1;13211322if(!skip_prefix(sb.buf,"From ", &x))1323return-1;13241325if(get_sha1_hex(x, commit_id) <0)1326return-1;13271328strbuf_release(&sb);1329fclose(fp);1330return0;1331}13321333/**1334 * Sets state->msg, state->author_name, state->author_email, state->author_date1335 * to the commit's respective info.1336 */1337static voidget_commit_info(struct am_state *state,struct commit *commit)1338{1339const char*buffer, *ident_line, *author_date, *msg;1340size_t ident_len;1341struct ident_split ident_split;1342struct strbuf sb = STRBUF_INIT;13431344 buffer =logmsg_reencode(commit, NULL,get_commit_output_encoding());13451346 ident_line =find_commit_header(buffer,"author", &ident_len);13471348if(split_ident_line(&ident_split, ident_line, ident_len) <0) {1349strbuf_add(&sb, ident_line, ident_len);1350die(_("invalid ident line:%s"), sb.buf);1351}13521353assert(!state->author_name);1354if(ident_split.name_begin) {1355strbuf_add(&sb, ident_split.name_begin,1356 ident_split.name_end - ident_split.name_begin);1357 state->author_name =strbuf_detach(&sb, NULL);1358}else1359 state->author_name =xstrdup("");13601361assert(!state->author_email);1362if(ident_split.mail_begin) {1363strbuf_add(&sb, ident_split.mail_begin,1364 ident_split.mail_end - ident_split.mail_begin);1365 state->author_email =strbuf_detach(&sb, NULL);1366}else1367 state->author_email =xstrdup("");13681369 author_date =show_ident_date(&ident_split,DATE_MODE(NORMAL));1370strbuf_addstr(&sb, author_date);1371assert(!state->author_date);1372 state->author_date =strbuf_detach(&sb, NULL);13731374assert(!state->msg);1375 msg =strstr(buffer,"\n\n");1376if(!msg)1377die(_("unable to parse commit%s"),sha1_to_hex(commit->object.sha1));1378 state->msg =xstrdup(msg +2);1379 state->msg_len =strlen(state->msg);1380}13811382/**1383 * Writes `commit` as a patch to the state directory's "patch" file.1384 */1385static voidwrite_commit_patch(const struct am_state *state,struct commit *commit)1386{1387struct rev_info rev_info;1388FILE*fp;13891390 fp =xfopen(am_path(state,"patch"),"w");1391init_revisions(&rev_info, NULL);1392 rev_info.diff =1;1393 rev_info.abbrev =0;1394 rev_info.disable_stdin =1;1395 rev_info.show_root_diff =1;1396 rev_info.diffopt.output_format = DIFF_FORMAT_PATCH;1397 rev_info.no_commit_id =1;1398DIFF_OPT_SET(&rev_info.diffopt, BINARY);1399DIFF_OPT_SET(&rev_info.diffopt, FULL_INDEX);1400 rev_info.diffopt.use_color =0;1401 rev_info.diffopt.file = fp;1402 rev_info.diffopt.close_file =1;1403add_pending_object(&rev_info, &commit->object,"");1404diff_setup_done(&rev_info.diffopt);1405log_tree_commit(&rev_info, commit);1406}14071408/**1409 * Writes the diff of the index against HEAD as a patch to the state1410 * directory's "patch" file.1411 */1412static voidwrite_index_patch(const struct am_state *state)1413{1414struct tree *tree;1415unsigned char head[GIT_SHA1_RAWSZ];1416struct rev_info rev_info;1417FILE*fp;14181419if(!get_sha1_tree("HEAD", head))1420 tree =lookup_tree(head);1421else1422 tree =lookup_tree(EMPTY_TREE_SHA1_BIN);14231424 fp =xfopen(am_path(state,"patch"),"w");1425init_revisions(&rev_info, NULL);1426 rev_info.diff =1;1427 rev_info.disable_stdin =1;1428 rev_info.no_commit_id =1;1429 rev_info.diffopt.output_format = DIFF_FORMAT_PATCH;1430 rev_info.diffopt.use_color =0;1431 rev_info.diffopt.file = fp;1432 rev_info.diffopt.close_file =1;1433add_pending_object(&rev_info, &tree->object,"");1434diff_setup_done(&rev_info.diffopt);1435run_diff_index(&rev_info,1);1436}14371438/**1439 * Like parse_mail(), but parses the mail by looking up its commit ID1440 * directly. This is used in --rebasing mode to bypass git-mailinfo's munging1441 * of patches.1442 *1443 * state->orig_commit will be set to the original commit ID.1444 *1445 * Will always return 0 as the patch should never be skipped.1446 */1447static intparse_mail_rebase(struct am_state *state,const char*mail)1448{1449struct commit *commit;1450unsigned char commit_sha1[GIT_SHA1_RAWSZ];14511452if(get_mail_commit_sha1(commit_sha1, mail) <0)1453die(_("could not parse%s"), mail);14541455 commit =lookup_commit_or_die(commit_sha1, mail);14561457get_commit_info(state, commit);14581459write_commit_patch(state, commit);14601461hashcpy(state->orig_commit, commit_sha1);1462write_file(am_path(state,"original-commit"),1,"%s",1463sha1_to_hex(commit_sha1));14641465return0;1466}14671468/**1469 * Applies current patch with git-apply. Returns 0 on success, -1 otherwise. If1470 * `index_file` is not NULL, the patch will be applied to that index.1471 */1472static intrun_apply(const struct am_state *state,const char*index_file)1473{1474struct child_process cp = CHILD_PROCESS_INIT;14751476 cp.git_cmd =1;14771478if(index_file)1479argv_array_pushf(&cp.env_array,"GIT_INDEX_FILE=%s", index_file);14801481/*1482 * If we are allowed to fall back on 3-way merge, don't give false1483 * errors during the initial attempt.1484 */1485if(state->threeway && !index_file) {1486 cp.no_stdout =1;1487 cp.no_stderr =1;1488}14891490argv_array_push(&cp.args,"apply");14911492argv_array_pushv(&cp.args, state->git_apply_opts.argv);14931494if(index_file)1495argv_array_push(&cp.args,"--cached");1496else1497argv_array_push(&cp.args,"--index");14981499argv_array_push(&cp.args,am_path(state,"patch"));15001501if(run_command(&cp))1502return-1;15031504/* Reload index as git-apply will have modified it. */1505discard_cache();1506read_cache_from(index_file ? index_file :get_index_file());15071508return0;1509}15101511/**1512 * Builds an index that contains just the blobs needed for a 3way merge.1513 */1514static intbuild_fake_ancestor(const struct am_state *state,const char*index_file)1515{1516struct child_process cp = CHILD_PROCESS_INIT;15171518 cp.git_cmd =1;1519argv_array_push(&cp.args,"apply");1520argv_array_pushv(&cp.args, state->git_apply_opts.argv);1521argv_array_pushf(&cp.args,"--build-fake-ancestor=%s", index_file);1522argv_array_push(&cp.args,am_path(state,"patch"));15231524if(run_command(&cp))1525return-1;15261527return0;1528}15291530/**1531 * Attempt a threeway merge, using index_path as the temporary index.1532 */1533static intfall_back_threeway(const struct am_state *state,const char*index_path)1534{1535unsigned char orig_tree[GIT_SHA1_RAWSZ], his_tree[GIT_SHA1_RAWSZ],1536 our_tree[GIT_SHA1_RAWSZ];1537const unsigned char*bases[1] = {orig_tree};1538struct merge_options o;1539struct commit *result;1540char*his_tree_name;15411542if(get_sha1("HEAD", our_tree) <0)1543hashcpy(our_tree, EMPTY_TREE_SHA1_BIN);15441545if(build_fake_ancestor(state, index_path))1546returnerror("could not build fake ancestor");15471548discard_cache();1549read_cache_from(index_path);15501551if(write_index_as_tree(orig_tree, &the_index, index_path,0, NULL))1552returnerror(_("Repository lacks necessary blobs to fall back on 3-way merge."));15531554say(state, stdout,_("Using index info to reconstruct a base tree..."));15551556if(!state->quiet) {1557/*1558 * List paths that needed 3-way fallback, so that the user can1559 * review them with extra care to spot mismerges.1560 */1561struct rev_info rev_info;1562const char*diff_filter_str ="--diff-filter=AM";15631564init_revisions(&rev_info, NULL);1565 rev_info.diffopt.output_format = DIFF_FORMAT_NAME_STATUS;1566diff_opt_parse(&rev_info.diffopt, &diff_filter_str,1);1567add_pending_sha1(&rev_info,"HEAD", our_tree,0);1568diff_setup_done(&rev_info.diffopt);1569run_diff_index(&rev_info,1);1570}15711572if(run_apply(state, index_path))1573returnerror(_("Did you hand edit your patch?\n"1574"It does not apply to blobs recorded in its index."));15751576if(write_index_as_tree(his_tree, &the_index, index_path,0, NULL))1577returnerror("could not write tree");15781579say(state, stdout,_("Falling back to patching base and 3-way merge..."));15801581discard_cache();1582read_cache();15831584/*1585 * This is not so wrong. Depending on which base we picked, orig_tree1586 * may be wildly different from ours, but his_tree has the same set of1587 * wildly different changes in parts the patch did not touch, so1588 * recursive ends up canceling them, saying that we reverted all those1589 * changes.1590 */15911592init_merge_options(&o);15931594 o.branch1 ="HEAD";1595 his_tree_name =xstrfmt("%.*s",linelen(state->msg), state->msg);1596 o.branch2 = his_tree_name;15971598if(state->quiet)1599 o.verbosity =0;16001601if(merge_recursive_generic(&o, our_tree, his_tree,1, bases, &result)) {1602rerere(state->allow_rerere_autoupdate);1603free(his_tree_name);1604returnerror(_("Failed to merge in the changes."));1605}16061607free(his_tree_name);1608return0;1609}16101611/**1612 * Commits the current index with state->msg as the commit message and1613 * state->author_name, state->author_email and state->author_date as the author1614 * information.1615 */1616static voiddo_commit(const struct am_state *state)1617{1618unsigned char tree[GIT_SHA1_RAWSZ], parent[GIT_SHA1_RAWSZ],1619 commit[GIT_SHA1_RAWSZ];1620unsigned char*ptr;1621struct commit_list *parents = NULL;1622const char*reflog_msg, *author;1623struct strbuf sb = STRBUF_INIT;16241625if(run_hook_le(NULL,"pre-applypatch", NULL))1626exit(1);16271628if(write_cache_as_tree(tree,0, NULL))1629die(_("git write-tree failed to write a tree"));16301631if(!get_sha1_commit("HEAD", parent)) {1632 ptr = parent;1633commit_list_insert(lookup_commit(parent), &parents);1634}else{1635 ptr = NULL;1636say(state, stderr,_("applying to an empty history"));1637}16381639 author =fmt_ident(state->author_name, state->author_email,1640 state->ignore_date ? NULL : state->author_date,1641 IDENT_STRICT);16421643if(state->committer_date_is_author_date)1644setenv("GIT_COMMITTER_DATE",1645 state->ignore_date ?"": state->author_date,1);16461647if(commit_tree(state->msg, state->msg_len, tree, parents, commit,1648 author, state->sign_commit))1649die(_("failed to write commit object"));16501651 reflog_msg =getenv("GIT_REFLOG_ACTION");1652if(!reflog_msg)1653 reflog_msg ="am";16541655strbuf_addf(&sb,"%s: %.*s", reflog_msg,linelen(state->msg),1656 state->msg);16571658update_ref(sb.buf,"HEAD", commit, ptr,0, UPDATE_REFS_DIE_ON_ERR);16591660if(state->rebasing) {1661FILE*fp =xfopen(am_path(state,"rewritten"),"a");16621663assert(!is_null_sha1(state->orig_commit));1664fprintf(fp,"%s",sha1_to_hex(state->orig_commit));1665fprintf(fp,"%s\n",sha1_to_hex(commit));1666fclose(fp);1667}16681669run_hook_le(NULL,"post-applypatch", NULL);16701671strbuf_release(&sb);1672}16731674/**1675 * Validates the am_state for resuming -- the "msg" and authorship fields must1676 * be filled up.1677 */1678static voidvalidate_resume_state(const struct am_state *state)1679{1680if(!state->msg)1681die(_("cannot resume:%sdoes not exist."),1682am_path(state,"final-commit"));16831684if(!state->author_name || !state->author_email || !state->author_date)1685die(_("cannot resume:%sdoes not exist."),1686am_path(state,"author-script"));1687}16881689/**1690 * Interactively prompt the user on whether the current patch should be1691 * applied.1692 *1693 * Returns 0 if the user chooses to apply the patch, 1 if the user chooses to1694 * skip it.1695 */1696static intdo_interactive(struct am_state *state)1697{1698assert(state->msg);16991700if(!isatty(0))1701die(_("cannot be interactive without stdin connected to a terminal."));17021703for(;;) {1704const char*reply;17051706puts(_("Commit Body is:"));1707puts("--------------------------");1708printf("%s", state->msg);1709puts("--------------------------");17101711/*1712 * TRANSLATORS: Make sure to include [y], [n], [e], [v] and [a]1713 * in your translation. The program will only accept English1714 * input at this point.1715 */1716 reply =git_prompt(_("Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all: "), PROMPT_ECHO);17171718if(!reply) {1719continue;1720}else if(*reply =='y'|| *reply =='Y') {1721return0;1722}else if(*reply =='a'|| *reply =='A') {1723 state->interactive =0;1724return0;1725}else if(*reply =='n'|| *reply =='N') {1726return1;1727}else if(*reply =='e'|| *reply =='E') {1728struct strbuf msg = STRBUF_INIT;17291730if(!launch_editor(am_path(state,"final-commit"), &msg, NULL)) {1731free(state->msg);1732 state->msg =strbuf_detach(&msg, &state->msg_len);1733}1734strbuf_release(&msg);1735}else if(*reply =='v'|| *reply =='V') {1736const char*pager =git_pager(1);1737struct child_process cp = CHILD_PROCESS_INIT;17381739if(!pager)1740 pager ="cat";1741argv_array_push(&cp.args, pager);1742argv_array_push(&cp.args,am_path(state,"patch"));1743run_command(&cp);1744}1745}1746}17471748/**1749 * Applies all queued mail.1750 *1751 * If `resume` is true, we are "resuming". The "msg" and authorship fields, as1752 * well as the state directory's "patch" file is used as-is for applying the1753 * patch and committing it.1754 */1755static voidam_run(struct am_state *state,int resume)1756{1757const char*argv_gc_auto[] = {"gc","--auto", NULL};1758struct strbuf sb = STRBUF_INIT;17591760unlink(am_path(state,"dirtyindex"));17611762refresh_and_write_cache();17631764if(index_has_changes(&sb)) {1765write_file(am_path(state,"dirtyindex"),1,"t");1766die(_("Dirty index: cannot apply patches (dirty:%s)"), sb.buf);1767}17681769strbuf_release(&sb);17701771while(state->cur <= state->last) {1772const char*mail =am_path(state,msgnum(state));1773int apply_status;17741775if(!file_exists(mail))1776goto next;17771778if(resume) {1779validate_resume_state(state);1780 resume =0;1781}else{1782int skip;17831784if(state->rebasing)1785 skip =parse_mail_rebase(state, mail);1786else1787 skip =parse_mail(state, mail);17881789if(skip)1790goto next;/* mail should be skipped */17911792write_author_script(state);1793write_commit_msg(state);1794}17951796if(state->interactive &&do_interactive(state))1797goto next;17981799if(run_applypatch_msg_hook(state))1800exit(1);18011802say(state, stdout,_("Applying: %.*s"),linelen(state->msg), state->msg);18031804 apply_status =run_apply(state, NULL);18051806if(apply_status && state->threeway) {1807struct strbuf sb = STRBUF_INIT;18081809strbuf_addstr(&sb,am_path(state,"patch-merge-index"));1810 apply_status =fall_back_threeway(state, sb.buf);1811strbuf_release(&sb);18121813/*1814 * Applying the patch to an earlier tree and merging1815 * the result may have produced the same tree as ours.1816 */1817if(!apply_status && !index_has_changes(NULL)) {1818say(state, stdout,_("No changes -- Patch already applied."));1819goto next;1820}1821}18221823if(apply_status) {1824int advice_amworkdir =1;18251826printf_ln(_("Patch failed at%s%.*s"),msgnum(state),1827linelen(state->msg), state->msg);18281829git_config_get_bool("advice.amworkdir", &advice_amworkdir);18301831if(advice_amworkdir)1832printf_ln(_("The copy of the patch that failed is found in:%s"),1833am_path(state,"patch"));18341835die_user_resolve(state);1836}18371838do_commit(state);18391840next:1841am_next(state);1842}18431844if(!is_empty_file(am_path(state,"rewritten"))) {1845assert(state->rebasing);1846copy_notes_for_rebase(state);1847run_post_rewrite_hook(state);1848}18491850/*1851 * In rebasing mode, it's up to the caller to take care of1852 * housekeeping.1853 */1854if(!state->rebasing) {1855am_destroy(state);1856run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);1857}1858}18591860/**1861 * Resume the current am session after patch application failure. The user did1862 * all the hard work, and we do not have to do any patch application. Just1863 * trust and commit what the user has in the index and working tree.1864 */1865static voidam_resolve(struct am_state *state)1866{1867validate_resume_state(state);18681869say(state, stdout,_("Applying: %.*s"),linelen(state->msg), state->msg);18701871if(!index_has_changes(NULL)) {1872printf_ln(_("No changes - did you forget to use 'git add'?\n"1873"If there is nothing left to stage, chances are that something else\n"1874"already introduced the same changes; you might want to skip this patch."));1875die_user_resolve(state);1876}18771878if(unmerged_cache()) {1879printf_ln(_("You still have unmerged paths in your index.\n"1880"Did you forget to use 'git add'?"));1881die_user_resolve(state);1882}18831884if(state->interactive) {1885write_index_patch(state);1886if(do_interactive(state))1887goto next;1888}18891890rerere(0);18911892do_commit(state);18931894next:1895am_next(state);1896am_run(state,0);1897}18981899/**1900 * Performs a checkout fast-forward from `head` to `remote`. If `reset` is1901 * true, any unmerged entries will be discarded. Returns 0 on success, -1 on1902 * failure.1903 */1904static intfast_forward_to(struct tree *head,struct tree *remote,int reset)1905{1906struct lock_file *lock_file;1907struct unpack_trees_options opts;1908struct tree_desc t[2];19091910if(parse_tree(head) ||parse_tree(remote))1911return-1;19121913 lock_file =xcalloc(1,sizeof(struct lock_file));1914hold_locked_index(lock_file,1);19151916refresh_cache(REFRESH_QUIET);19171918memset(&opts,0,sizeof(opts));1919 opts.head_idx =1;1920 opts.src_index = &the_index;1921 opts.dst_index = &the_index;1922 opts.update =1;1923 opts.merge =1;1924 opts.reset = reset;1925 opts.fn = twoway_merge;1926init_tree_desc(&t[0], head->buffer, head->size);1927init_tree_desc(&t[1], remote->buffer, remote->size);19281929if(unpack_trees(2, t, &opts)) {1930rollback_lock_file(lock_file);1931return-1;1932}19331934if(write_locked_index(&the_index, lock_file, COMMIT_LOCK))1935die(_("unable to write new index file"));19361937return0;1938}19391940/**1941 * Clean the index without touching entries that are not modified between1942 * `head` and `remote`.1943 */1944static intclean_index(const unsigned char*head,const unsigned char*remote)1945{1946struct lock_file *lock_file;1947struct tree *head_tree, *remote_tree, *index_tree;1948unsigned char index[GIT_SHA1_RAWSZ];1949struct pathspec pathspec;19501951 head_tree =parse_tree_indirect(head);1952if(!head_tree)1953returnerror(_("Could not parse object '%s'."),sha1_to_hex(head));19541955 remote_tree =parse_tree_indirect(remote);1956if(!remote_tree)1957returnerror(_("Could not parse object '%s'."),sha1_to_hex(remote));19581959read_cache_unmerged();19601961if(fast_forward_to(head_tree, head_tree,1))1962return-1;19631964if(write_cache_as_tree(index,0, NULL))1965return-1;19661967 index_tree =parse_tree_indirect(index);1968if(!index_tree)1969returnerror(_("Could not parse object '%s'."),sha1_to_hex(index));19701971if(fast_forward_to(index_tree, remote_tree,0))1972return-1;19731974memset(&pathspec,0,sizeof(pathspec));19751976 lock_file =xcalloc(1,sizeof(struct lock_file));1977hold_locked_index(lock_file,1);19781979if(read_tree(remote_tree,0, &pathspec)) {1980rollback_lock_file(lock_file);1981return-1;1982}19831984if(write_locked_index(&the_index, lock_file, COMMIT_LOCK))1985die(_("unable to write new index file"));19861987remove_branch_state();19881989return0;1990}19911992/**1993 * Resets rerere's merge resolution metadata.1994 */1995static voidam_rerere_clear(void)1996{1997struct string_list merge_rr = STRING_LIST_INIT_DUP;1998int fd =setup_rerere(&merge_rr,0);19992000if(fd <0)2001return;20022003rerere_clear(&merge_rr);2004string_list_clear(&merge_rr,1);2005}20062007/**2008 * Resume the current am session by skipping the current patch.2009 */2010static voidam_skip(struct am_state *state)2011{2012unsigned char head[GIT_SHA1_RAWSZ];20132014am_rerere_clear();20152016if(get_sha1("HEAD", head))2017hashcpy(head, EMPTY_TREE_SHA1_BIN);20182019if(clean_index(head, head))2020die(_("failed to clean index"));20212022am_next(state);2023am_run(state,0);2024}20252026/**2027 * Returns true if it is safe to reset HEAD to the ORIG_HEAD, false otherwise.2028 *2029 * It is not safe to reset HEAD when:2030 * 1. git-am previously failed because the index was dirty.2031 * 2. HEAD has moved since git-am previously failed.2032 */2033static intsafe_to_abort(const struct am_state *state)2034{2035struct strbuf sb = STRBUF_INIT;2036unsigned char abort_safety[GIT_SHA1_RAWSZ], head[GIT_SHA1_RAWSZ];20372038if(file_exists(am_path(state,"dirtyindex")))2039return0;20402041if(read_state_file(&sb, state,"abort-safety",1) >0) {2042if(get_sha1_hex(sb.buf, abort_safety))2043die(_("could not parse%s"),am_path(state,"abort_safety"));2044}else2045hashclr(abort_safety);20462047if(get_sha1("HEAD", head))2048hashclr(head);20492050if(!hashcmp(head, abort_safety))2051return1;20522053error(_("You seem to have moved HEAD since the last 'am' failure.\n"2054"Not rewinding to ORIG_HEAD"));20552056return0;2057}20582059/**2060 * Aborts the current am session if it is safe to do so.2061 */2062static voidam_abort(struct am_state *state)2063{2064unsigned char curr_head[GIT_SHA1_RAWSZ], orig_head[GIT_SHA1_RAWSZ];2065int has_curr_head, has_orig_head;2066char*curr_branch;20672068if(!safe_to_abort(state)) {2069am_destroy(state);2070return;2071}20722073am_rerere_clear();20742075 curr_branch =resolve_refdup("HEAD",0, curr_head, NULL);2076 has_curr_head = !is_null_sha1(curr_head);2077if(!has_curr_head)2078hashcpy(curr_head, EMPTY_TREE_SHA1_BIN);20792080 has_orig_head = !get_sha1("ORIG_HEAD", orig_head);2081if(!has_orig_head)2082hashcpy(orig_head, EMPTY_TREE_SHA1_BIN);20832084clean_index(curr_head, orig_head);20852086if(has_orig_head)2087update_ref("am --abort","HEAD", orig_head,2088 has_curr_head ? curr_head : NULL,0,2089 UPDATE_REFS_DIE_ON_ERR);2090else if(curr_branch)2091delete_ref(curr_branch, NULL, REF_NODEREF);20922093free(curr_branch);2094am_destroy(state);2095}20962097/**2098 * parse_options() callback that validates and sets opt->value to the2099 * PATCH_FORMAT_* enum value corresponding to `arg`.2100 */2101static intparse_opt_patchformat(const struct option *opt,const char*arg,int unset)2102{2103int*opt_value = opt->value;21042105if(!strcmp(arg,"mbox"))2106*opt_value = PATCH_FORMAT_MBOX;2107else if(!strcmp(arg,"stgit"))2108*opt_value = PATCH_FORMAT_STGIT;2109else if(!strcmp(arg,"stgit-series"))2110*opt_value = PATCH_FORMAT_STGIT_SERIES;2111else if(!strcmp(arg,"hg"))2112*opt_value = PATCH_FORMAT_HG;2113else2114returnerror(_("Invalid value for --patch-format:%s"), arg);2115return0;2116}21172118enum resume_mode {2119 RESUME_FALSE =0,2120 RESUME_APPLY,2121 RESUME_RESOLVED,2122 RESUME_SKIP,2123 RESUME_ABORT2124};21252126intcmd_am(int argc,const char**argv,const char*prefix)2127{2128struct am_state state;2129int binary = -1;2130int keep_cr = -1;2131int patch_format = PATCH_FORMAT_UNKNOWN;2132enum resume_mode resume = RESUME_FALSE;21332134const char*const usage[] = {2135N_("git am [options] [(<mbox>|<Maildir>)...]"),2136N_("git am [options] (--continue | --skip | --abort)"),2137 NULL2138};21392140struct option options[] = {2141OPT_BOOL('i',"interactive", &state.interactive,2142N_("run interactively")),2143OPT_HIDDEN_BOOL('b',"binary", &binary,2144N_("(historical option -- no-op")),2145OPT_BOOL('3',"3way", &state.threeway,2146N_("allow fall back on 3way merging if needed")),2147OPT__QUIET(&state.quiet,N_("be quiet")),2148OPT_BOOL('s',"signoff", &state.signoff,2149N_("add a Signed-off-by line to the commit message")),2150OPT_BOOL('u',"utf8", &state.utf8,2151N_("recode into utf8 (default)")),2152OPT_SET_INT('k',"keep", &state.keep,2153N_("pass -k flag to git-mailinfo"), KEEP_TRUE),2154OPT_SET_INT(0,"keep-non-patch", &state.keep,2155N_("pass -b flag to git-mailinfo"), KEEP_NON_PATCH),2156OPT_BOOL('m',"message-id", &state.message_id,2157N_("pass -m flag to git-mailinfo")),2158{ OPTION_SET_INT,0,"keep-cr", &keep_cr, NULL,2159N_("pass --keep-cr flag to git-mailsplit for mbox format"),2160 PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL,1},2161{ OPTION_SET_INT,0,"no-keep-cr", &keep_cr, NULL,2162N_("do not pass --keep-cr flag to git-mailsplit independent of am.keepcr"),2163 PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL,0},2164OPT_BOOL('c',"scissors", &state.scissors,2165N_("strip everything before a scissors line")),2166OPT_PASSTHRU_ARGV(0,"whitespace", &state.git_apply_opts,N_("action"),2167N_("pass it through git-apply"),21680),2169OPT_PASSTHRU_ARGV(0,"ignore-space-change", &state.git_apply_opts, NULL,2170N_("pass it through git-apply"),2171 PARSE_OPT_NOARG),2172OPT_PASSTHRU_ARGV(0,"ignore-whitespace", &state.git_apply_opts, NULL,2173N_("pass it through git-apply"),2174 PARSE_OPT_NOARG),2175OPT_PASSTHRU_ARGV(0,"directory", &state.git_apply_opts,N_("root"),2176N_("pass it through git-apply"),21770),2178OPT_PASSTHRU_ARGV(0,"exclude", &state.git_apply_opts,N_("path"),2179N_("pass it through git-apply"),21800),2181OPT_PASSTHRU_ARGV(0,"include", &state.git_apply_opts,N_("path"),2182N_("pass it through git-apply"),21830),2184OPT_PASSTHRU_ARGV('C', NULL, &state.git_apply_opts,N_("n"),2185N_("pass it through git-apply"),21860),2187OPT_PASSTHRU_ARGV('p', NULL, &state.git_apply_opts,N_("num"),2188N_("pass it through git-apply"),21890),2190OPT_CALLBACK(0,"patch-format", &patch_format,N_("format"),2191N_("format the patch(es) are in"),2192 parse_opt_patchformat),2193OPT_PASSTHRU_ARGV(0,"reject", &state.git_apply_opts, NULL,2194N_("pass it through git-apply"),2195 PARSE_OPT_NOARG),2196OPT_STRING(0,"resolvemsg", &state.resolvemsg, NULL,2197N_("override error message when patch failure occurs")),2198OPT_CMDMODE(0,"continue", &resume,2199N_("continue applying patches after resolving a conflict"),2200 RESUME_RESOLVED),2201OPT_CMDMODE('r',"resolved", &resume,2202N_("synonyms for --continue"),2203 RESUME_RESOLVED),2204OPT_CMDMODE(0,"skip", &resume,2205N_("skip the current patch"),2206 RESUME_SKIP),2207OPT_CMDMODE(0,"abort", &resume,2208N_("restore the original branch and abort the patching operation."),2209 RESUME_ABORT),2210OPT_BOOL(0,"committer-date-is-author-date",2211&state.committer_date_is_author_date,2212N_("lie about committer date")),2213OPT_BOOL(0,"ignore-date", &state.ignore_date,2214N_("use current timestamp for author date")),2215OPT_RERERE_AUTOUPDATE(&state.allow_rerere_autoupdate),2216{ OPTION_STRING,'S',"gpg-sign", &state.sign_commit,N_("key-id"),2217N_("GPG-sign commits"),2218 PARSE_OPT_OPTARG, NULL, (intptr_t)""},2219OPT_HIDDEN_BOOL(0,"rebasing", &state.rebasing,2220N_("(internal use for git-rebase)")),2221OPT_END()2222};22232224/*2225 * NEEDSWORK: Once all the features of git-am.sh have been2226 * re-implemented in builtin/am.c, this preamble can be removed.2227 */2228if(!getenv("_GIT_USE_BUILTIN_AM")) {2229const char*path =mkpath("%s/git-am",git_exec_path());22302231if(sane_execvp(path, (char**)argv) <0)2232die_errno("could not exec%s", path);2233}else{2234 prefix =setup_git_directory();2235trace_repo_setup(prefix);2236setup_work_tree();2237}22382239git_config(git_default_config, NULL);22402241am_state_init(&state,git_path("rebase-apply"));22422243 argc =parse_options(argc, argv, prefix, options, usage,0);22442245if(binary >=0)2246fprintf_ln(stderr,_("The -b/--binary option has been a no-op for long time, and\n"2247"it will be removed. Please do not use it anymore."));22482249/* Ensure a valid committer ident can be constructed */2250git_committer_info(IDENT_STRICT);22512252if(read_index_preload(&the_index, NULL) <0)2253die(_("failed to read the index"));22542255if(am_in_progress(&state)) {2256/*2257 * Catch user error to feed us patches when there is a session2258 * in progress:2259 *2260 * 1. mbox path(s) are provided on the command-line.2261 * 2. stdin is not a tty: the user is trying to feed us a patch2262 * from standard input. This is somewhat unreliable -- stdin2263 * could be /dev/null for example and the caller did not2264 * intend to feed us a patch but wanted to continue2265 * unattended.2266 */2267if(argc || (resume == RESUME_FALSE && !isatty(0)))2268die(_("previous rebase directory%sstill exists but mbox given."),2269 state.dir);22702271if(resume == RESUME_FALSE)2272 resume = RESUME_APPLY;22732274am_load(&state);2275}else{2276struct argv_array paths = ARGV_ARRAY_INIT;2277int i;22782279/*2280 * Handle stray state directory in the independent-run case. In2281 * the --rebasing case, it is up to the caller to take care of2282 * stray directories.2283 */2284if(file_exists(state.dir) && !state.rebasing) {2285if(resume == RESUME_ABORT) {2286am_destroy(&state);2287am_state_release(&state);2288return0;2289}22902291die(_("Stray%sdirectory found.\n"2292"Use\"git am --abort\"to remove it."),2293 state.dir);2294}22952296if(resume)2297die(_("Resolve operation not in progress, we are not resuming."));22982299for(i =0; i < argc; i++) {2300if(is_absolute_path(argv[i]) || !prefix)2301argv_array_push(&paths, argv[i]);2302else2303argv_array_push(&paths,mkpath("%s/%s", prefix, argv[i]));2304}23052306am_setup(&state, patch_format, paths.argv, keep_cr);23072308argv_array_clear(&paths);2309}23102311switch(resume) {2312case RESUME_FALSE:2313am_run(&state,0);2314break;2315case RESUME_APPLY:2316am_run(&state,1);2317break;2318case RESUME_RESOLVED:2319am_resolve(&state);2320break;2321case RESUME_SKIP:2322am_skip(&state);2323break;2324case RESUME_ABORT:2325am_abort(&state);2326break;2327default:2328die("BUG: invalid resume value");2329}23302331am_state_release(&state);23322333return0;2334}