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 27/** 28 * Returns 1 if the file is empty or does not exist, 0 otherwise. 29 */ 30static intis_empty_file(const char*filename) 31{ 32struct stat st; 33 34if(stat(filename, &st) <0) { 35if(errno == ENOENT) 36return1; 37die_errno(_("could not stat%s"), filename); 38} 39 40return!st.st_size; 41} 42 43/** 44 * Like strbuf_getline(), but treats both '\n' and "\r\n" as line terminators. 45 */ 46static intstrbuf_getline_crlf(struct strbuf *sb,FILE*fp) 47{ 48if(strbuf_getwholeline(sb, fp,'\n')) 49return EOF; 50if(sb->buf[sb->len -1] =='\n') { 51strbuf_setlen(sb, sb->len -1); 52if(sb->len >0&& sb->buf[sb->len -1] =='\r') 53strbuf_setlen(sb, sb->len -1); 54} 55return0; 56} 57 58/** 59 * Returns the length of the first line of msg. 60 */ 61static intlinelen(const char*msg) 62{ 63returnstrchrnul(msg,'\n') - msg; 64} 65 66enum patch_format { 67 PATCH_FORMAT_UNKNOWN =0, 68 PATCH_FORMAT_MBOX 69}; 70 71enum keep_type { 72 KEEP_FALSE =0, 73 KEEP_TRUE,/* pass -k flag to git-mailinfo */ 74 KEEP_NON_PATCH /* pass -b flag to git-mailinfo */ 75}; 76 77enum scissors_type { 78 SCISSORS_UNSET = -1, 79 SCISSORS_FALSE =0,/* pass --no-scissors to git-mailinfo */ 80 SCISSORS_TRUE /* pass --scissors to git-mailinfo */ 81}; 82 83struct am_state { 84/* state directory path */ 85char*dir; 86 87/* current and last patch numbers, 1-indexed */ 88int cur; 89int last; 90 91/* commit metadata and message */ 92char*author_name; 93char*author_email; 94char*author_date; 95char*msg; 96size_t msg_len; 97 98/* number of digits in patch filename */ 99int prec; 100 101/* various operating modes and command line options */ 102int threeway; 103int quiet; 104int signoff; 105int utf8; 106int keep;/* enum keep_type */ 107int message_id; 108int scissors;/* enum scissors_type */ 109struct argv_array git_apply_opts; 110const char*resolvemsg; 111int committer_date_is_author_date; 112int ignore_date; 113int rebasing; 114}; 115 116/** 117 * Initializes am_state with the default values. The state directory is set to 118 * dir. 119 */ 120static voidam_state_init(struct am_state *state,const char*dir) 121{ 122memset(state,0,sizeof(*state)); 123 124assert(dir); 125 state->dir =xstrdup(dir); 126 127 state->prec =4; 128 129 state->utf8 =1; 130 131git_config_get_bool("am.messageid", &state->message_id); 132 133 state->scissors = SCISSORS_UNSET; 134 135argv_array_init(&state->git_apply_opts); 136} 137 138/** 139 * Releases memory allocated by an am_state. 140 */ 141static voidam_state_release(struct am_state *state) 142{ 143free(state->dir); 144free(state->author_name); 145free(state->author_email); 146free(state->author_date); 147free(state->msg); 148argv_array_clear(&state->git_apply_opts); 149} 150 151/** 152 * Returns path relative to the am_state directory. 153 */ 154staticinlineconst char*am_path(const struct am_state *state,const char*path) 155{ 156returnmkpath("%s/%s", state->dir, path); 157} 158 159/** 160 * If state->quiet is false, calls fprintf(fp, fmt, ...), and appends a newline 161 * at the end. 162 */ 163static voidsay(const struct am_state *state,FILE*fp,const char*fmt, ...) 164{ 165va_list ap; 166 167va_start(ap, fmt); 168if(!state->quiet) { 169vfprintf(fp, fmt, ap); 170putc('\n', fp); 171} 172va_end(ap); 173} 174 175/** 176 * Returns 1 if there is an am session in progress, 0 otherwise. 177 */ 178static intam_in_progress(const struct am_state *state) 179{ 180struct stat st; 181 182if(lstat(state->dir, &st) <0|| !S_ISDIR(st.st_mode)) 183return0; 184if(lstat(am_path(state,"last"), &st) || !S_ISREG(st.st_mode)) 185return0; 186if(lstat(am_path(state,"next"), &st) || !S_ISREG(st.st_mode)) 187return0; 188return1; 189} 190 191/** 192 * Reads the contents of `file` in the `state` directory into `sb`. Returns the 193 * number of bytes read on success, -1 if the file does not exist. If `trim` is 194 * set, trailing whitespace will be removed. 195 */ 196static intread_state_file(struct strbuf *sb,const struct am_state *state, 197const char*file,int trim) 198{ 199strbuf_reset(sb); 200 201if(strbuf_read_file(sb,am_path(state, file),0) >=0) { 202if(trim) 203strbuf_trim(sb); 204 205return sb->len; 206} 207 208if(errno == ENOENT) 209return-1; 210 211die_errno(_("could not read '%s'"),am_path(state, file)); 212} 213 214/** 215 * Reads a KEY=VALUE shell variable assignment from `fp`, returning the VALUE 216 * as a newly-allocated string. VALUE must be a quoted string, and the KEY must 217 * match `key`. Returns NULL on failure. 218 * 219 * This is used by read_author_script() to read the GIT_AUTHOR_* variables from 220 * the author-script. 221 */ 222static char*read_shell_var(FILE*fp,const char*key) 223{ 224struct strbuf sb = STRBUF_INIT; 225const char*str; 226 227if(strbuf_getline(&sb, fp,'\n')) 228goto fail; 229 230if(!skip_prefix(sb.buf, key, &str)) 231goto fail; 232 233if(!skip_prefix(str,"=", &str)) 234goto fail; 235 236strbuf_remove(&sb,0, str - sb.buf); 237 238 str =sq_dequote(sb.buf); 239if(!str) 240goto fail; 241 242returnstrbuf_detach(&sb, NULL); 243 244fail: 245strbuf_release(&sb); 246return NULL; 247} 248 249/** 250 * Reads and parses the state directory's "author-script" file, and sets 251 * state->author_name, state->author_email and state->author_date accordingly. 252 * Returns 0 on success, -1 if the file could not be parsed. 253 * 254 * The author script is of the format: 255 * 256 * GIT_AUTHOR_NAME='$author_name' 257 * GIT_AUTHOR_EMAIL='$author_email' 258 * GIT_AUTHOR_DATE='$author_date' 259 * 260 * where $author_name, $author_email and $author_date are quoted. We are strict 261 * with our parsing, as the file was meant to be eval'd in the old git-am.sh 262 * script, and thus if the file differs from what this function expects, it is 263 * better to bail out than to do something that the user does not expect. 264 */ 265static intread_author_script(struct am_state *state) 266{ 267const char*filename =am_path(state,"author-script"); 268FILE*fp; 269 270assert(!state->author_name); 271assert(!state->author_email); 272assert(!state->author_date); 273 274 fp =fopen(filename,"r"); 275if(!fp) { 276if(errno == ENOENT) 277return0; 278die_errno(_("could not open '%s' for reading"), filename); 279} 280 281 state->author_name =read_shell_var(fp,"GIT_AUTHOR_NAME"); 282if(!state->author_name) { 283fclose(fp); 284return-1; 285} 286 287 state->author_email =read_shell_var(fp,"GIT_AUTHOR_EMAIL"); 288if(!state->author_email) { 289fclose(fp); 290return-1; 291} 292 293 state->author_date =read_shell_var(fp,"GIT_AUTHOR_DATE"); 294if(!state->author_date) { 295fclose(fp); 296return-1; 297} 298 299if(fgetc(fp) != EOF) { 300fclose(fp); 301return-1; 302} 303 304fclose(fp); 305return0; 306} 307 308/** 309 * Saves state->author_name, state->author_email and state->author_date in the 310 * state directory's "author-script" file. 311 */ 312static voidwrite_author_script(const struct am_state *state) 313{ 314struct strbuf sb = STRBUF_INIT; 315 316strbuf_addstr(&sb,"GIT_AUTHOR_NAME="); 317sq_quote_buf(&sb, state->author_name); 318strbuf_addch(&sb,'\n'); 319 320strbuf_addstr(&sb,"GIT_AUTHOR_EMAIL="); 321sq_quote_buf(&sb, state->author_email); 322strbuf_addch(&sb,'\n'); 323 324strbuf_addstr(&sb,"GIT_AUTHOR_DATE="); 325sq_quote_buf(&sb, state->author_date); 326strbuf_addch(&sb,'\n'); 327 328write_file(am_path(state,"author-script"),1,"%s", sb.buf); 329 330strbuf_release(&sb); 331} 332 333/** 334 * Reads the commit message from the state directory's "final-commit" file, 335 * setting state->msg to its contents and state->msg_len to the length of its 336 * contents in bytes. 337 * 338 * Returns 0 on success, -1 if the file does not exist. 339 */ 340static intread_commit_msg(struct am_state *state) 341{ 342struct strbuf sb = STRBUF_INIT; 343 344assert(!state->msg); 345 346if(read_state_file(&sb, state,"final-commit",0) <0) { 347strbuf_release(&sb); 348return-1; 349} 350 351 state->msg =strbuf_detach(&sb, &state->msg_len); 352return0; 353} 354 355/** 356 * Saves state->msg in the state directory's "final-commit" file. 357 */ 358static voidwrite_commit_msg(const struct am_state *state) 359{ 360int fd; 361const char*filename =am_path(state,"final-commit"); 362 363 fd =xopen(filename, O_WRONLY | O_CREAT,0666); 364if(write_in_full(fd, state->msg, state->msg_len) <0) 365die_errno(_("could not write to%s"), filename); 366close(fd); 367} 368 369/** 370 * Loads state from disk. 371 */ 372static voidam_load(struct am_state *state) 373{ 374struct strbuf sb = STRBUF_INIT; 375 376if(read_state_file(&sb, state,"next",1) <0) 377die("BUG: state file 'next' does not exist"); 378 state->cur =strtol(sb.buf, NULL,10); 379 380if(read_state_file(&sb, state,"last",1) <0) 381die("BUG: state file 'last' does not exist"); 382 state->last =strtol(sb.buf, NULL,10); 383 384if(read_author_script(state) <0) 385die(_("could not parse author script")); 386 387read_commit_msg(state); 388 389read_state_file(&sb, state,"threeway",1); 390 state->threeway = !strcmp(sb.buf,"t"); 391 392read_state_file(&sb, state,"quiet",1); 393 state->quiet = !strcmp(sb.buf,"t"); 394 395read_state_file(&sb, state,"sign",1); 396 state->signoff = !strcmp(sb.buf,"t"); 397 398read_state_file(&sb, state,"utf8",1); 399 state->utf8 = !strcmp(sb.buf,"t"); 400 401read_state_file(&sb, state,"keep",1); 402if(!strcmp(sb.buf,"t")) 403 state->keep = KEEP_TRUE; 404else if(!strcmp(sb.buf,"b")) 405 state->keep = KEEP_NON_PATCH; 406else 407 state->keep = KEEP_FALSE; 408 409read_state_file(&sb, state,"messageid",1); 410 state->message_id = !strcmp(sb.buf,"t"); 411 412read_state_file(&sb, state,"scissors",1); 413if(!strcmp(sb.buf,"t")) 414 state->scissors = SCISSORS_TRUE; 415else if(!strcmp(sb.buf,"f")) 416 state->scissors = SCISSORS_FALSE; 417else 418 state->scissors = SCISSORS_UNSET; 419 420read_state_file(&sb, state,"apply-opt",1); 421argv_array_clear(&state->git_apply_opts); 422if(sq_dequote_to_argv_array(sb.buf, &state->git_apply_opts) <0) 423die(_("could not parse%s"),am_path(state,"apply-opt")); 424 425 state->rebasing = !!file_exists(am_path(state,"rebasing")); 426 427strbuf_release(&sb); 428} 429 430/** 431 * Removes the am_state directory, forcefully terminating the current am 432 * session. 433 */ 434static voidam_destroy(const struct am_state *state) 435{ 436struct strbuf sb = STRBUF_INIT; 437 438strbuf_addstr(&sb, state->dir); 439remove_dir_recursively(&sb,0); 440strbuf_release(&sb); 441} 442 443/** 444 * Determines if the file looks like a piece of RFC2822 mail by grabbing all 445 * non-indented lines and checking if they look like they begin with valid 446 * header field names. 447 * 448 * Returns 1 if the file looks like a piece of mail, 0 otherwise. 449 */ 450static intis_mail(FILE*fp) 451{ 452const char*header_regex ="^[!-9;-~]+:"; 453struct strbuf sb = STRBUF_INIT; 454 regex_t regex; 455int ret =1; 456 457if(fseek(fp,0L, SEEK_SET)) 458die_errno(_("fseek failed")); 459 460if(regcomp(®ex, header_regex, REG_NOSUB | REG_EXTENDED)) 461die("invalid pattern:%s", header_regex); 462 463while(!strbuf_getline_crlf(&sb, fp)) { 464if(!sb.len) 465break;/* End of header */ 466 467/* Ignore indented folded lines */ 468if(*sb.buf =='\t'|| *sb.buf ==' ') 469continue; 470 471/* It's a header if it matches header_regex */ 472if(regexec(®ex, sb.buf,0, NULL,0)) { 473 ret =0; 474goto done; 475} 476} 477 478done: 479regfree(®ex); 480strbuf_release(&sb); 481return ret; 482} 483 484/** 485 * Attempts to detect the patch_format of the patches contained in `paths`, 486 * returning the PATCH_FORMAT_* enum value. Returns PATCH_FORMAT_UNKNOWN if 487 * detection fails. 488 */ 489static intdetect_patch_format(const char**paths) 490{ 491enum patch_format ret = PATCH_FORMAT_UNKNOWN; 492struct strbuf l1 = STRBUF_INIT; 493FILE*fp; 494 495/* 496 * We default to mbox format if input is from stdin and for directories 497 */ 498if(!*paths || !strcmp(*paths,"-") ||is_directory(*paths)) 499return PATCH_FORMAT_MBOX; 500 501/* 502 * Otherwise, check the first few lines of the first patch, starting 503 * from the first non-blank line, to try to detect its format. 504 */ 505 506 fp =xfopen(*paths,"r"); 507 508while(!strbuf_getline_crlf(&l1, fp)) { 509if(l1.len) 510break; 511} 512 513if(starts_with(l1.buf,"From ") ||starts_with(l1.buf,"From: ")) { 514 ret = PATCH_FORMAT_MBOX; 515goto done; 516} 517 518if(l1.len &&is_mail(fp)) { 519 ret = PATCH_FORMAT_MBOX; 520goto done; 521} 522 523done: 524fclose(fp); 525strbuf_release(&l1); 526return ret; 527} 528 529/** 530 * Splits out individual email patches from `paths`, where each path is either 531 * a mbox file or a Maildir. Returns 0 on success, -1 on failure. 532 */ 533static intsplit_mail_mbox(struct am_state *state,const char**paths,int keep_cr) 534{ 535struct child_process cp = CHILD_PROCESS_INIT; 536struct strbuf last = STRBUF_INIT; 537 538 cp.git_cmd =1; 539argv_array_push(&cp.args,"mailsplit"); 540argv_array_pushf(&cp.args,"-d%d", state->prec); 541argv_array_pushf(&cp.args,"-o%s", state->dir); 542argv_array_push(&cp.args,"-b"); 543if(keep_cr) 544argv_array_push(&cp.args,"--keep-cr"); 545argv_array_push(&cp.args,"--"); 546argv_array_pushv(&cp.args, paths); 547 548if(capture_command(&cp, &last,8)) 549return-1; 550 551 state->cur =1; 552 state->last =strtol(last.buf, NULL,10); 553 554return0; 555} 556 557/** 558 * Splits a list of files/directories into individual email patches. Each path 559 * in `paths` must be a file/directory that is formatted according to 560 * `patch_format`. 561 * 562 * Once split out, the individual email patches will be stored in the state 563 * directory, with each patch's filename being its index, padded to state->prec 564 * digits. 565 * 566 * state->cur will be set to the index of the first mail, and state->last will 567 * be set to the index of the last mail. 568 * 569 * Set keep_cr to 0 to convert all lines ending with \r\n to end with \n, 1 570 * to disable this behavior, -1 to use the default configured setting. 571 * 572 * Returns 0 on success, -1 on failure. 573 */ 574static intsplit_mail(struct am_state *state,enum patch_format patch_format, 575const char**paths,int keep_cr) 576{ 577if(keep_cr <0) { 578 keep_cr =0; 579git_config_get_bool("am.keepcr", &keep_cr); 580} 581 582switch(patch_format) { 583case PATCH_FORMAT_MBOX: 584returnsplit_mail_mbox(state, paths, keep_cr); 585default: 586die("BUG: invalid patch_format"); 587} 588return-1; 589} 590 591/** 592 * Setup a new am session for applying patches 593 */ 594static voidam_setup(struct am_state *state,enum patch_format patch_format, 595const char**paths,int keep_cr) 596{ 597unsigned char curr_head[GIT_SHA1_RAWSZ]; 598const char*str; 599struct strbuf sb = STRBUF_INIT; 600 601if(!patch_format) 602 patch_format =detect_patch_format(paths); 603 604if(!patch_format) { 605fprintf_ln(stderr,_("Patch format detection failed.")); 606exit(128); 607} 608 609if(mkdir(state->dir,0777) <0&& errno != EEXIST) 610die_errno(_("failed to create directory '%s'"), state->dir); 611 612if(split_mail(state, patch_format, paths, keep_cr) <0) { 613am_destroy(state); 614die(_("Failed to split patches.")); 615} 616 617if(state->rebasing) 618 state->threeway =1; 619 620write_file(am_path(state,"threeway"),1, state->threeway ?"t":"f"); 621 622write_file(am_path(state,"quiet"),1, state->quiet ?"t":"f"); 623 624write_file(am_path(state,"sign"),1, state->signoff ?"t":"f"); 625 626write_file(am_path(state,"utf8"),1, state->utf8 ?"t":"f"); 627 628switch(state->keep) { 629case KEEP_FALSE: 630 str ="f"; 631break; 632case KEEP_TRUE: 633 str ="t"; 634break; 635case KEEP_NON_PATCH: 636 str ="b"; 637break; 638default: 639die("BUG: invalid value for state->keep"); 640} 641 642write_file(am_path(state,"keep"),1,"%s", str); 643 644write_file(am_path(state,"messageid"),1, state->message_id ?"t":"f"); 645 646switch(state->scissors) { 647case SCISSORS_UNSET: 648 str =""; 649break; 650case SCISSORS_FALSE: 651 str ="f"; 652break; 653case SCISSORS_TRUE: 654 str ="t"; 655break; 656default: 657die("BUG: invalid value for state->scissors"); 658} 659 660write_file(am_path(state,"scissors"),1,"%s", str); 661 662sq_quote_argv(&sb, state->git_apply_opts.argv,0); 663write_file(am_path(state,"apply-opt"),1,"%s", sb.buf); 664 665if(state->rebasing) 666write_file(am_path(state,"rebasing"),1,"%s",""); 667else 668write_file(am_path(state,"applying"),1,"%s",""); 669 670if(!get_sha1("HEAD", curr_head)) { 671write_file(am_path(state,"abort-safety"),1,"%s",sha1_to_hex(curr_head)); 672if(!state->rebasing) 673update_ref("am","ORIG_HEAD", curr_head, NULL,0, 674 UPDATE_REFS_DIE_ON_ERR); 675}else{ 676write_file(am_path(state,"abort-safety"),1,"%s",""); 677if(!state->rebasing) 678delete_ref("ORIG_HEAD", NULL,0); 679} 680 681/* 682 * NOTE: Since the "next" and "last" files determine if an am_state 683 * session is in progress, they should be written last. 684 */ 685 686write_file(am_path(state,"next"),1,"%d", state->cur); 687 688write_file(am_path(state,"last"),1,"%d", state->last); 689 690strbuf_release(&sb); 691} 692 693/** 694 * Increments the patch pointer, and cleans am_state for the application of the 695 * next patch. 696 */ 697static voidam_next(struct am_state *state) 698{ 699unsigned char head[GIT_SHA1_RAWSZ]; 700 701free(state->author_name); 702 state->author_name = NULL; 703 704free(state->author_email); 705 state->author_email = NULL; 706 707free(state->author_date); 708 state->author_date = NULL; 709 710free(state->msg); 711 state->msg = NULL; 712 state->msg_len =0; 713 714unlink(am_path(state,"author-script")); 715unlink(am_path(state,"final-commit")); 716 717if(!get_sha1("HEAD", head)) 718write_file(am_path(state,"abort-safety"),1,"%s",sha1_to_hex(head)); 719else 720write_file(am_path(state,"abort-safety"),1,"%s",""); 721 722 state->cur++; 723write_file(am_path(state,"next"),1,"%d", state->cur); 724} 725 726/** 727 * Returns the filename of the current patch email. 728 */ 729static const char*msgnum(const struct am_state *state) 730{ 731static struct strbuf sb = STRBUF_INIT; 732 733strbuf_reset(&sb); 734strbuf_addf(&sb,"%0*d", state->prec, state->cur); 735 736return sb.buf; 737} 738 739/** 740 * Refresh and write index. 741 */ 742static voidrefresh_and_write_cache(void) 743{ 744struct lock_file *lock_file =xcalloc(1,sizeof(struct lock_file)); 745 746hold_locked_index(lock_file,1); 747refresh_cache(REFRESH_QUIET); 748if(write_locked_index(&the_index, lock_file, COMMIT_LOCK)) 749die(_("unable to write index file")); 750} 751 752/** 753 * Returns 1 if the index differs from HEAD, 0 otherwise. When on an unborn 754 * branch, returns 1 if there are entries in the index, 0 otherwise. If an 755 * strbuf is provided, the space-separated list of files that differ will be 756 * appended to it. 757 */ 758static intindex_has_changes(struct strbuf *sb) 759{ 760unsigned char head[GIT_SHA1_RAWSZ]; 761int i; 762 763if(!get_sha1_tree("HEAD", head)) { 764struct diff_options opt; 765 766diff_setup(&opt); 767DIFF_OPT_SET(&opt, EXIT_WITH_STATUS); 768if(!sb) 769DIFF_OPT_SET(&opt, QUICK); 770do_diff_cache(head, &opt); 771diffcore_std(&opt); 772for(i =0; sb && i < diff_queued_diff.nr; i++) { 773if(i) 774strbuf_addch(sb,' '); 775strbuf_addstr(sb, diff_queued_diff.queue[i]->two->path); 776} 777diff_flush(&opt); 778returnDIFF_OPT_TST(&opt, HAS_CHANGES) !=0; 779}else{ 780for(i =0; sb && i < active_nr; i++) { 781if(i) 782strbuf_addch(sb,' '); 783strbuf_addstr(sb, active_cache[i]->name); 784} 785return!!active_nr; 786} 787} 788 789/** 790 * Dies with a user-friendly message on how to proceed after resolving the 791 * problem. This message can be overridden with state->resolvemsg. 792 */ 793static void NORETURN die_user_resolve(const struct am_state *state) 794{ 795if(state->resolvemsg) { 796printf_ln("%s", state->resolvemsg); 797}else{ 798const char*cmdline ="git am"; 799 800printf_ln(_("When you have resolved this problem, run\"%s--continue\"."), cmdline); 801printf_ln(_("If you prefer to skip this patch, run\"%s--skip\"instead."), cmdline); 802printf_ln(_("To restore the original branch and stop patching, run\"%s--abort\"."), cmdline); 803} 804 805exit(128); 806} 807 808/** 809 * Parses `mail` using git-mailinfo, extracting its patch and authorship info. 810 * state->msg will be set to the patch message. state->author_name, 811 * state->author_email and state->author_date will be set to the patch author's 812 * name, email and date respectively. The patch body will be written to the 813 * state directory's "patch" file. 814 * 815 * Returns 1 if the patch should be skipped, 0 otherwise. 816 */ 817static intparse_mail(struct am_state *state,const char*mail) 818{ 819FILE*fp; 820struct child_process cp = CHILD_PROCESS_INIT; 821struct strbuf sb = STRBUF_INIT; 822struct strbuf msg = STRBUF_INIT; 823struct strbuf author_name = STRBUF_INIT; 824struct strbuf author_date = STRBUF_INIT; 825struct strbuf author_email = STRBUF_INIT; 826int ret =0; 827 828 cp.git_cmd =1; 829 cp.in =xopen(mail, O_RDONLY,0); 830 cp.out =xopen(am_path(state,"info"), O_WRONLY | O_CREAT,0777); 831 832argv_array_push(&cp.args,"mailinfo"); 833argv_array_push(&cp.args, state->utf8 ?"-u":"-n"); 834 835switch(state->keep) { 836case KEEP_FALSE: 837break; 838case KEEP_TRUE: 839argv_array_push(&cp.args,"-k"); 840break; 841case KEEP_NON_PATCH: 842argv_array_push(&cp.args,"-b"); 843break; 844default: 845die("BUG: invalid value for state->keep"); 846} 847 848if(state->message_id) 849argv_array_push(&cp.args,"-m"); 850 851switch(state->scissors) { 852case SCISSORS_UNSET: 853break; 854case SCISSORS_FALSE: 855argv_array_push(&cp.args,"--no-scissors"); 856break; 857case SCISSORS_TRUE: 858argv_array_push(&cp.args,"--scissors"); 859break; 860default: 861die("BUG: invalid value for state->scissors"); 862} 863 864argv_array_push(&cp.args,am_path(state,"msg")); 865argv_array_push(&cp.args,am_path(state,"patch")); 866 867if(run_command(&cp) <0) 868die("could not parse patch"); 869 870close(cp.in); 871close(cp.out); 872 873/* Extract message and author information */ 874 fp =xfopen(am_path(state,"info"),"r"); 875while(!strbuf_getline(&sb, fp,'\n')) { 876const char*x; 877 878if(skip_prefix(sb.buf,"Subject: ", &x)) { 879if(msg.len) 880strbuf_addch(&msg,'\n'); 881strbuf_addstr(&msg, x); 882}else if(skip_prefix(sb.buf,"Author: ", &x)) 883strbuf_addstr(&author_name, x); 884else if(skip_prefix(sb.buf,"Email: ", &x)) 885strbuf_addstr(&author_email, x); 886else if(skip_prefix(sb.buf,"Date: ", &x)) 887strbuf_addstr(&author_date, x); 888} 889fclose(fp); 890 891/* Skip pine's internal folder data */ 892if(!strcmp(author_name.buf,"Mail System Internal Data")) { 893 ret =1; 894goto finish; 895} 896 897if(is_empty_file(am_path(state,"patch"))) { 898printf_ln(_("Patch is empty. Was it split wrong?")); 899die_user_resolve(state); 900} 901 902strbuf_addstr(&msg,"\n\n"); 903if(strbuf_read_file(&msg,am_path(state,"msg"),0) <0) 904die_errno(_("could not read '%s'"),am_path(state,"msg")); 905stripspace(&msg,0); 906 907if(state->signoff) 908append_signoff(&msg,0,0); 909 910assert(!state->author_name); 911 state->author_name =strbuf_detach(&author_name, NULL); 912 913assert(!state->author_email); 914 state->author_email =strbuf_detach(&author_email, NULL); 915 916assert(!state->author_date); 917 state->author_date =strbuf_detach(&author_date, NULL); 918 919assert(!state->msg); 920 state->msg =strbuf_detach(&msg, &state->msg_len); 921 922finish: 923strbuf_release(&msg); 924strbuf_release(&author_date); 925strbuf_release(&author_email); 926strbuf_release(&author_name); 927strbuf_release(&sb); 928return ret; 929} 930 931/** 932 * Sets commit_id to the commit hash where the mail was generated from. 933 * Returns 0 on success, -1 on failure. 934 */ 935static intget_mail_commit_sha1(unsigned char*commit_id,const char*mail) 936{ 937struct strbuf sb = STRBUF_INIT; 938FILE*fp =xfopen(mail,"r"); 939const char*x; 940 941if(strbuf_getline(&sb, fp,'\n')) 942return-1; 943 944if(!skip_prefix(sb.buf,"From ", &x)) 945return-1; 946 947if(get_sha1_hex(x, commit_id) <0) 948return-1; 949 950strbuf_release(&sb); 951fclose(fp); 952return0; 953} 954 955/** 956 * Sets state->msg, state->author_name, state->author_email, state->author_date 957 * to the commit's respective info. 958 */ 959static voidget_commit_info(struct am_state *state,struct commit *commit) 960{ 961const char*buffer, *ident_line, *author_date, *msg; 962size_t ident_len; 963struct ident_split ident_split; 964struct strbuf sb = STRBUF_INIT; 965 966 buffer =logmsg_reencode(commit, NULL,get_commit_output_encoding()); 967 968 ident_line =find_commit_header(buffer,"author", &ident_len); 969 970if(split_ident_line(&ident_split, ident_line, ident_len) <0) { 971strbuf_add(&sb, ident_line, ident_len); 972die(_("invalid ident line:%s"), sb.buf); 973} 974 975assert(!state->author_name); 976if(ident_split.name_begin) { 977strbuf_add(&sb, ident_split.name_begin, 978 ident_split.name_end - ident_split.name_begin); 979 state->author_name =strbuf_detach(&sb, NULL); 980}else 981 state->author_name =xstrdup(""); 982 983assert(!state->author_email); 984if(ident_split.mail_begin) { 985strbuf_add(&sb, ident_split.mail_begin, 986 ident_split.mail_end - ident_split.mail_begin); 987 state->author_email =strbuf_detach(&sb, NULL); 988}else 989 state->author_email =xstrdup(""); 990 991 author_date =show_ident_date(&ident_split,DATE_MODE(NORMAL)); 992strbuf_addstr(&sb, author_date); 993assert(!state->author_date); 994 state->author_date =strbuf_detach(&sb, NULL); 995 996assert(!state->msg); 997 msg =strstr(buffer,"\n\n"); 998if(!msg) 999die(_("unable to parse commit%s"),sha1_to_hex(commit->object.sha1));1000 state->msg =xstrdup(msg +2);1001 state->msg_len =strlen(state->msg);1002}10031004/**1005 * Writes `commit` as a patch to the state directory's "patch" file.1006 */1007static voidwrite_commit_patch(const struct am_state *state,struct commit *commit)1008{1009struct rev_info rev_info;1010FILE*fp;10111012 fp =xfopen(am_path(state,"patch"),"w");1013init_revisions(&rev_info, NULL);1014 rev_info.diff =1;1015 rev_info.abbrev =0;1016 rev_info.disable_stdin =1;1017 rev_info.show_root_diff =1;1018 rev_info.diffopt.output_format = DIFF_FORMAT_PATCH;1019 rev_info.no_commit_id =1;1020DIFF_OPT_SET(&rev_info.diffopt, BINARY);1021DIFF_OPT_SET(&rev_info.diffopt, FULL_INDEX);1022 rev_info.diffopt.use_color =0;1023 rev_info.diffopt.file = fp;1024 rev_info.diffopt.close_file =1;1025add_pending_object(&rev_info, &commit->object,"");1026diff_setup_done(&rev_info.diffopt);1027log_tree_commit(&rev_info, commit);1028}10291030/**1031 * Like parse_mail(), but parses the mail by looking up its commit ID1032 * directly. This is used in --rebasing mode to bypass git-mailinfo's munging1033 * of patches.1034 *1035 * Will always return 0 as the patch should never be skipped.1036 */1037static intparse_mail_rebase(struct am_state *state,const char*mail)1038{1039struct commit *commit;1040unsigned char commit_sha1[GIT_SHA1_RAWSZ];10411042if(get_mail_commit_sha1(commit_sha1, mail) <0)1043die(_("could not parse%s"), mail);10441045 commit =lookup_commit_or_die(commit_sha1, mail);10461047get_commit_info(state, commit);10481049write_commit_patch(state, commit);10501051return0;1052}10531054/**1055 * Applies current patch with git-apply. Returns 0 on success, -1 otherwise. If1056 * `index_file` is not NULL, the patch will be applied to that index.1057 */1058static intrun_apply(const struct am_state *state,const char*index_file)1059{1060struct child_process cp = CHILD_PROCESS_INIT;10611062 cp.git_cmd =1;10631064if(index_file)1065argv_array_pushf(&cp.env_array,"GIT_INDEX_FILE=%s", index_file);10661067/*1068 * If we are allowed to fall back on 3-way merge, don't give false1069 * errors during the initial attempt.1070 */1071if(state->threeway && !index_file) {1072 cp.no_stdout =1;1073 cp.no_stderr =1;1074}10751076argv_array_push(&cp.args,"apply");10771078argv_array_pushv(&cp.args, state->git_apply_opts.argv);10791080if(index_file)1081argv_array_push(&cp.args,"--cached");1082else1083argv_array_push(&cp.args,"--index");10841085argv_array_push(&cp.args,am_path(state,"patch"));10861087if(run_command(&cp))1088return-1;10891090/* Reload index as git-apply will have modified it. */1091discard_cache();1092read_cache_from(index_file ? index_file :get_index_file());10931094return0;1095}10961097/**1098 * Builds an index that contains just the blobs needed for a 3way merge.1099 */1100static intbuild_fake_ancestor(const struct am_state *state,const char*index_file)1101{1102struct child_process cp = CHILD_PROCESS_INIT;11031104 cp.git_cmd =1;1105argv_array_push(&cp.args,"apply");1106argv_array_pushv(&cp.args, state->git_apply_opts.argv);1107argv_array_pushf(&cp.args,"--build-fake-ancestor=%s", index_file);1108argv_array_push(&cp.args,am_path(state,"patch"));11091110if(run_command(&cp))1111return-1;11121113return0;1114}11151116/**1117 * Attempt a threeway merge, using index_path as the temporary index.1118 */1119static intfall_back_threeway(const struct am_state *state,const char*index_path)1120{1121unsigned char orig_tree[GIT_SHA1_RAWSZ], his_tree[GIT_SHA1_RAWSZ],1122 our_tree[GIT_SHA1_RAWSZ];1123const unsigned char*bases[1] = {orig_tree};1124struct merge_options o;1125struct commit *result;1126char*his_tree_name;11271128if(get_sha1("HEAD", our_tree) <0)1129hashcpy(our_tree, EMPTY_TREE_SHA1_BIN);11301131if(build_fake_ancestor(state, index_path))1132returnerror("could not build fake ancestor");11331134discard_cache();1135read_cache_from(index_path);11361137if(write_index_as_tree(orig_tree, &the_index, index_path,0, NULL))1138returnerror(_("Repository lacks necessary blobs to fall back on 3-way merge."));11391140say(state, stdout,_("Using index info to reconstruct a base tree..."));11411142if(!state->quiet) {1143/*1144 * List paths that needed 3-way fallback, so that the user can1145 * review them with extra care to spot mismerges.1146 */1147struct rev_info rev_info;1148const char*diff_filter_str ="--diff-filter=AM";11491150init_revisions(&rev_info, NULL);1151 rev_info.diffopt.output_format = DIFF_FORMAT_NAME_STATUS;1152diff_opt_parse(&rev_info.diffopt, &diff_filter_str,1);1153add_pending_sha1(&rev_info,"HEAD", our_tree,0);1154diff_setup_done(&rev_info.diffopt);1155run_diff_index(&rev_info,1);1156}11571158if(run_apply(state, index_path))1159returnerror(_("Did you hand edit your patch?\n"1160"It does not apply to blobs recorded in its index."));11611162if(write_index_as_tree(his_tree, &the_index, index_path,0, NULL))1163returnerror("could not write tree");11641165say(state, stdout,_("Falling back to patching base and 3-way merge..."));11661167discard_cache();1168read_cache();11691170/*1171 * This is not so wrong. Depending on which base we picked, orig_tree1172 * may be wildly different from ours, but his_tree has the same set of1173 * wildly different changes in parts the patch did not touch, so1174 * recursive ends up canceling them, saying that we reverted all those1175 * changes.1176 */11771178init_merge_options(&o);11791180 o.branch1 ="HEAD";1181 his_tree_name =xstrfmt("%.*s",linelen(state->msg), state->msg);1182 o.branch2 = his_tree_name;11831184if(state->quiet)1185 o.verbosity =0;11861187if(merge_recursive_generic(&o, our_tree, his_tree,1, bases, &result)) {1188free(his_tree_name);1189returnerror(_("Failed to merge in the changes."));1190}11911192free(his_tree_name);1193return0;1194}11951196/**1197 * Commits the current index with state->msg as the commit message and1198 * state->author_name, state->author_email and state->author_date as the author1199 * information.1200 */1201static voiddo_commit(const struct am_state *state)1202{1203unsigned char tree[GIT_SHA1_RAWSZ], parent[GIT_SHA1_RAWSZ],1204 commit[GIT_SHA1_RAWSZ];1205unsigned char*ptr;1206struct commit_list *parents = NULL;1207const char*reflog_msg, *author;1208struct strbuf sb = STRBUF_INIT;12091210if(write_cache_as_tree(tree,0, NULL))1211die(_("git write-tree failed to write a tree"));12121213if(!get_sha1_commit("HEAD", parent)) {1214 ptr = parent;1215commit_list_insert(lookup_commit(parent), &parents);1216}else{1217 ptr = NULL;1218say(state, stderr,_("applying to an empty history"));1219}12201221 author =fmt_ident(state->author_name, state->author_email,1222 state->ignore_date ? NULL : state->author_date,1223 IDENT_STRICT);12241225if(state->committer_date_is_author_date)1226setenv("GIT_COMMITTER_DATE",1227 state->ignore_date ?"": state->author_date,1);12281229if(commit_tree(state->msg, state->msg_len, tree, parents, commit,1230 author, NULL))1231die(_("failed to write commit object"));12321233 reflog_msg =getenv("GIT_REFLOG_ACTION");1234if(!reflog_msg)1235 reflog_msg ="am";12361237strbuf_addf(&sb,"%s: %.*s", reflog_msg,linelen(state->msg),1238 state->msg);12391240update_ref(sb.buf,"HEAD", commit, ptr,0, UPDATE_REFS_DIE_ON_ERR);12411242strbuf_release(&sb);1243}12441245/**1246 * Validates the am_state for resuming -- the "msg" and authorship fields must1247 * be filled up.1248 */1249static voidvalidate_resume_state(const struct am_state *state)1250{1251if(!state->msg)1252die(_("cannot resume:%sdoes not exist."),1253am_path(state,"final-commit"));12541255if(!state->author_name || !state->author_email || !state->author_date)1256die(_("cannot resume:%sdoes not exist."),1257am_path(state,"author-script"));1258}12591260/**1261 * Applies all queued mail.1262 *1263 * If `resume` is true, we are "resuming". The "msg" and authorship fields, as1264 * well as the state directory's "patch" file is used as-is for applying the1265 * patch and committing it.1266 */1267static voidam_run(struct am_state *state,int resume)1268{1269const char*argv_gc_auto[] = {"gc","--auto", NULL};1270struct strbuf sb = STRBUF_INIT;12711272unlink(am_path(state,"dirtyindex"));12731274refresh_and_write_cache();12751276if(index_has_changes(&sb)) {1277write_file(am_path(state,"dirtyindex"),1,"t");1278die(_("Dirty index: cannot apply patches (dirty:%s)"), sb.buf);1279}12801281strbuf_release(&sb);12821283while(state->cur <= state->last) {1284const char*mail =am_path(state,msgnum(state));1285int apply_status;12861287if(!file_exists(mail))1288goto next;12891290if(resume) {1291validate_resume_state(state);1292 resume =0;1293}else{1294int skip;12951296if(state->rebasing)1297 skip =parse_mail_rebase(state, mail);1298else1299 skip =parse_mail(state, mail);13001301if(skip)1302goto next;/* mail should be skipped */13031304write_author_script(state);1305write_commit_msg(state);1306}13071308say(state, stdout,_("Applying: %.*s"),linelen(state->msg), state->msg);13091310 apply_status =run_apply(state, NULL);13111312if(apply_status && state->threeway) {1313struct strbuf sb = STRBUF_INIT;13141315strbuf_addstr(&sb,am_path(state,"patch-merge-index"));1316 apply_status =fall_back_threeway(state, sb.buf);1317strbuf_release(&sb);13181319/*1320 * Applying the patch to an earlier tree and merging1321 * the result may have produced the same tree as ours.1322 */1323if(!apply_status && !index_has_changes(NULL)) {1324say(state, stdout,_("No changes -- Patch already applied."));1325goto next;1326}1327}13281329if(apply_status) {1330int advice_amworkdir =1;13311332printf_ln(_("Patch failed at%s%.*s"),msgnum(state),1333linelen(state->msg), state->msg);13341335git_config_get_bool("advice.amworkdir", &advice_amworkdir);13361337if(advice_amworkdir)1338printf_ln(_("The copy of the patch that failed is found in:%s"),1339am_path(state,"patch"));13401341die_user_resolve(state);1342}13431344do_commit(state);13451346next:1347am_next(state);1348}13491350/*1351 * In rebasing mode, it's up to the caller to take care of1352 * housekeeping.1353 */1354if(!state->rebasing) {1355am_destroy(state);1356run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);1357}1358}13591360/**1361 * Resume the current am session after patch application failure. The user did1362 * all the hard work, and we do not have to do any patch application. Just1363 * trust and commit what the user has in the index and working tree.1364 */1365static voidam_resolve(struct am_state *state)1366{1367validate_resume_state(state);13681369say(state, stdout,_("Applying: %.*s"),linelen(state->msg), state->msg);13701371if(!index_has_changes(NULL)) {1372printf_ln(_("No changes - did you forget to use 'git add'?\n"1373"If there is nothing left to stage, chances are that something else\n"1374"already introduced the same changes; you might want to skip this patch."));1375die_user_resolve(state);1376}13771378if(unmerged_cache()) {1379printf_ln(_("You still have unmerged paths in your index.\n"1380"Did you forget to use 'git add'?"));1381die_user_resolve(state);1382}13831384do_commit(state);13851386am_next(state);1387am_run(state,0);1388}13891390/**1391 * Performs a checkout fast-forward from `head` to `remote`. If `reset` is1392 * true, any unmerged entries will be discarded. Returns 0 on success, -1 on1393 * failure.1394 */1395static intfast_forward_to(struct tree *head,struct tree *remote,int reset)1396{1397struct lock_file *lock_file;1398struct unpack_trees_options opts;1399struct tree_desc t[2];14001401if(parse_tree(head) ||parse_tree(remote))1402return-1;14031404 lock_file =xcalloc(1,sizeof(struct lock_file));1405hold_locked_index(lock_file,1);14061407refresh_cache(REFRESH_QUIET);14081409memset(&opts,0,sizeof(opts));1410 opts.head_idx =1;1411 opts.src_index = &the_index;1412 opts.dst_index = &the_index;1413 opts.update =1;1414 opts.merge =1;1415 opts.reset = reset;1416 opts.fn = twoway_merge;1417init_tree_desc(&t[0], head->buffer, head->size);1418init_tree_desc(&t[1], remote->buffer, remote->size);14191420if(unpack_trees(2, t, &opts)) {1421rollback_lock_file(lock_file);1422return-1;1423}14241425if(write_locked_index(&the_index, lock_file, COMMIT_LOCK))1426die(_("unable to write new index file"));14271428return0;1429}14301431/**1432 * Clean the index without touching entries that are not modified between1433 * `head` and `remote`.1434 */1435static intclean_index(const unsigned char*head,const unsigned char*remote)1436{1437struct lock_file *lock_file;1438struct tree *head_tree, *remote_tree, *index_tree;1439unsigned char index[GIT_SHA1_RAWSZ];1440struct pathspec pathspec;14411442 head_tree =parse_tree_indirect(head);1443if(!head_tree)1444returnerror(_("Could not parse object '%s'."),sha1_to_hex(head));14451446 remote_tree =parse_tree_indirect(remote);1447if(!remote_tree)1448returnerror(_("Could not parse object '%s'."),sha1_to_hex(remote));14491450read_cache_unmerged();14511452if(fast_forward_to(head_tree, head_tree,1))1453return-1;14541455if(write_cache_as_tree(index,0, NULL))1456return-1;14571458 index_tree =parse_tree_indirect(index);1459if(!index_tree)1460returnerror(_("Could not parse object '%s'."),sha1_to_hex(index));14611462if(fast_forward_to(index_tree, remote_tree,0))1463return-1;14641465memset(&pathspec,0,sizeof(pathspec));14661467 lock_file =xcalloc(1,sizeof(struct lock_file));1468hold_locked_index(lock_file,1);14691470if(read_tree(remote_tree,0, &pathspec)) {1471rollback_lock_file(lock_file);1472return-1;1473}14741475if(write_locked_index(&the_index, lock_file, COMMIT_LOCK))1476die(_("unable to write new index file"));14771478remove_branch_state();14791480return0;1481}14821483/**1484 * Resume the current am session by skipping the current patch.1485 */1486static voidam_skip(struct am_state *state)1487{1488unsigned char head[GIT_SHA1_RAWSZ];14891490if(get_sha1("HEAD", head))1491hashcpy(head, EMPTY_TREE_SHA1_BIN);14921493if(clean_index(head, head))1494die(_("failed to clean index"));14951496am_next(state);1497am_run(state,0);1498}14991500/**1501 * Returns true if it is safe to reset HEAD to the ORIG_HEAD, false otherwise.1502 *1503 * It is not safe to reset HEAD when:1504 * 1. git-am previously failed because the index was dirty.1505 * 2. HEAD has moved since git-am previously failed.1506 */1507static intsafe_to_abort(const struct am_state *state)1508{1509struct strbuf sb = STRBUF_INIT;1510unsigned char abort_safety[GIT_SHA1_RAWSZ], head[GIT_SHA1_RAWSZ];15111512if(file_exists(am_path(state,"dirtyindex")))1513return0;15141515if(read_state_file(&sb, state,"abort-safety",1) >0) {1516if(get_sha1_hex(sb.buf, abort_safety))1517die(_("could not parse%s"),am_path(state,"abort_safety"));1518}else1519hashclr(abort_safety);15201521if(get_sha1("HEAD", head))1522hashclr(head);15231524if(!hashcmp(head, abort_safety))1525return1;15261527error(_("You seem to have moved HEAD since the last 'am' failure.\n"1528"Not rewinding to ORIG_HEAD"));15291530return0;1531}15321533/**1534 * Aborts the current am session if it is safe to do so.1535 */1536static voidam_abort(struct am_state *state)1537{1538unsigned char curr_head[GIT_SHA1_RAWSZ], orig_head[GIT_SHA1_RAWSZ];1539int has_curr_head, has_orig_head;1540char*curr_branch;15411542if(!safe_to_abort(state)) {1543am_destroy(state);1544return;1545}15461547 curr_branch =resolve_refdup("HEAD",0, curr_head, NULL);1548 has_curr_head = !is_null_sha1(curr_head);1549if(!has_curr_head)1550hashcpy(curr_head, EMPTY_TREE_SHA1_BIN);15511552 has_orig_head = !get_sha1("ORIG_HEAD", orig_head);1553if(!has_orig_head)1554hashcpy(orig_head, EMPTY_TREE_SHA1_BIN);15551556clean_index(curr_head, orig_head);15571558if(has_orig_head)1559update_ref("am --abort","HEAD", orig_head,1560 has_curr_head ? curr_head : NULL,0,1561 UPDATE_REFS_DIE_ON_ERR);1562else if(curr_branch)1563delete_ref(curr_branch, NULL, REF_NODEREF);15641565free(curr_branch);1566am_destroy(state);1567}15681569/**1570 * parse_options() callback that validates and sets opt->value to the1571 * PATCH_FORMAT_* enum value corresponding to `arg`.1572 */1573static intparse_opt_patchformat(const struct option *opt,const char*arg,int unset)1574{1575int*opt_value = opt->value;15761577if(!strcmp(arg,"mbox"))1578*opt_value = PATCH_FORMAT_MBOX;1579else1580returnerror(_("Invalid value for --patch-format:%s"), arg);1581return0;1582}15831584enum resume_mode {1585 RESUME_FALSE =0,1586 RESUME_APPLY,1587 RESUME_RESOLVED,1588 RESUME_SKIP,1589 RESUME_ABORT1590};15911592intcmd_am(int argc,const char**argv,const char*prefix)1593{1594struct am_state state;1595int keep_cr = -1;1596int patch_format = PATCH_FORMAT_UNKNOWN;1597enum resume_mode resume = RESUME_FALSE;15981599const char*const usage[] = {1600N_("git am [options] [(<mbox>|<Maildir>)...]"),1601N_("git am [options] (--continue | --skip | --abort)"),1602 NULL1603};16041605struct option options[] = {1606OPT_BOOL('3',"3way", &state.threeway,1607N_("allow fall back on 3way merging if needed")),1608OPT__QUIET(&state.quiet,N_("be quiet")),1609OPT_BOOL('s',"signoff", &state.signoff,1610N_("add a Signed-off-by line to the commit message")),1611OPT_BOOL('u',"utf8", &state.utf8,1612N_("recode into utf8 (default)")),1613OPT_SET_INT('k',"keep", &state.keep,1614N_("pass -k flag to git-mailinfo"), KEEP_TRUE),1615OPT_SET_INT(0,"keep-non-patch", &state.keep,1616N_("pass -b flag to git-mailinfo"), KEEP_NON_PATCH),1617OPT_BOOL('m',"message-id", &state.message_id,1618N_("pass -m flag to git-mailinfo")),1619{ OPTION_SET_INT,0,"keep-cr", &keep_cr, NULL,1620N_("pass --keep-cr flag to git-mailsplit for mbox format"),1621 PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL,1},1622{ OPTION_SET_INT,0,"no-keep-cr", &keep_cr, NULL,1623N_("do not pass --keep-cr flag to git-mailsplit independent of am.keepcr"),1624 PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL,0},1625OPT_BOOL('c',"scissors", &state.scissors,1626N_("strip everything before a scissors line")),1627OPT_PASSTHRU_ARGV(0,"whitespace", &state.git_apply_opts,N_("action"),1628N_("pass it through git-apply"),16290),1630OPT_PASSTHRU_ARGV(0,"ignore-space-change", &state.git_apply_opts, NULL,1631N_("pass it through git-apply"),1632 PARSE_OPT_NOARG),1633OPT_PASSTHRU_ARGV(0,"ignore-whitespace", &state.git_apply_opts, NULL,1634N_("pass it through git-apply"),1635 PARSE_OPT_NOARG),1636OPT_PASSTHRU_ARGV(0,"directory", &state.git_apply_opts,N_("root"),1637N_("pass it through git-apply"),16380),1639OPT_PASSTHRU_ARGV(0,"exclude", &state.git_apply_opts,N_("path"),1640N_("pass it through git-apply"),16410),1642OPT_PASSTHRU_ARGV(0,"include", &state.git_apply_opts,N_("path"),1643N_("pass it through git-apply"),16440),1645OPT_PASSTHRU_ARGV('C', NULL, &state.git_apply_opts,N_("n"),1646N_("pass it through git-apply"),16470),1648OPT_PASSTHRU_ARGV('p', NULL, &state.git_apply_opts,N_("num"),1649N_("pass it through git-apply"),16500),1651OPT_CALLBACK(0,"patch-format", &patch_format,N_("format"),1652N_("format the patch(es) are in"),1653 parse_opt_patchformat),1654OPT_PASSTHRU_ARGV(0,"reject", &state.git_apply_opts, NULL,1655N_("pass it through git-apply"),1656 PARSE_OPT_NOARG),1657OPT_STRING(0,"resolvemsg", &state.resolvemsg, NULL,1658N_("override error message when patch failure occurs")),1659OPT_CMDMODE(0,"continue", &resume,1660N_("continue applying patches after resolving a conflict"),1661 RESUME_RESOLVED),1662OPT_CMDMODE('r',"resolved", &resume,1663N_("synonyms for --continue"),1664 RESUME_RESOLVED),1665OPT_CMDMODE(0,"skip", &resume,1666N_("skip the current patch"),1667 RESUME_SKIP),1668OPT_CMDMODE(0,"abort", &resume,1669N_("restore the original branch and abort the patching operation."),1670 RESUME_ABORT),1671OPT_BOOL(0,"committer-date-is-author-date",1672&state.committer_date_is_author_date,1673N_("lie about committer date")),1674OPT_BOOL(0,"ignore-date", &state.ignore_date,1675N_("use current timestamp for author date")),1676OPT_HIDDEN_BOOL(0,"rebasing", &state.rebasing,1677N_("(internal use for git-rebase)")),1678OPT_END()1679};16801681/*1682 * NEEDSWORK: Once all the features of git-am.sh have been1683 * re-implemented in builtin/am.c, this preamble can be removed.1684 */1685if(!getenv("_GIT_USE_BUILTIN_AM")) {1686const char*path =mkpath("%s/git-am",git_exec_path());16871688if(sane_execvp(path, (char**)argv) <0)1689die_errno("could not exec%s", path);1690}else{1691 prefix =setup_git_directory();1692trace_repo_setup(prefix);1693setup_work_tree();1694}16951696git_config(git_default_config, NULL);16971698am_state_init(&state,git_path("rebase-apply"));16991700 argc =parse_options(argc, argv, prefix, options, usage,0);17011702if(read_index_preload(&the_index, NULL) <0)1703die(_("failed to read the index"));17041705if(am_in_progress(&state)) {1706/*1707 * Catch user error to feed us patches when there is a session1708 * in progress:1709 *1710 * 1. mbox path(s) are provided on the command-line.1711 * 2. stdin is not a tty: the user is trying to feed us a patch1712 * from standard input. This is somewhat unreliable -- stdin1713 * could be /dev/null for example and the caller did not1714 * intend to feed us a patch but wanted to continue1715 * unattended.1716 */1717if(argc || (resume == RESUME_FALSE && !isatty(0)))1718die(_("previous rebase directory%sstill exists but mbox given."),1719 state.dir);17201721if(resume == RESUME_FALSE)1722 resume = RESUME_APPLY;17231724am_load(&state);1725}else{1726struct argv_array paths = ARGV_ARRAY_INIT;1727int i;17281729/*1730 * Handle stray state directory in the independent-run case. In1731 * the --rebasing case, it is up to the caller to take care of1732 * stray directories.1733 */1734if(file_exists(state.dir) && !state.rebasing) {1735if(resume == RESUME_ABORT) {1736am_destroy(&state);1737am_state_release(&state);1738return0;1739}17401741die(_("Stray%sdirectory found.\n"1742"Use\"git am --abort\"to remove it."),1743 state.dir);1744}17451746if(resume)1747die(_("Resolve operation not in progress, we are not resuming."));17481749for(i =0; i < argc; i++) {1750if(is_absolute_path(argv[i]) || !prefix)1751argv_array_push(&paths, argv[i]);1752else1753argv_array_push(&paths,mkpath("%s/%s", prefix, argv[i]));1754}17551756am_setup(&state, patch_format, paths.argv, keep_cr);17571758argv_array_clear(&paths);1759}17601761switch(resume) {1762case RESUME_FALSE:1763am_run(&state,0);1764break;1765case RESUME_APPLY:1766am_run(&state,1);1767break;1768case RESUME_RESOLVED:1769am_resolve(&state);1770break;1771case RESUME_SKIP:1772am_skip(&state);1773break;1774case RESUME_ABORT:1775am_abort(&state);1776break;1777default:1778die("BUG: invalid resume value");1779}17801781am_state_release(&state);17821783return0;1784}