@@ -27,6 +27,19 @@ static GIT_PATH_FUNC(git_path_todo_file, "sequencer/todo")
27
27
static GIT_PATH_FUNC (git_path_opts_file , "sequencer/opts" )
28
28
static GIT_PATH_FUNC (git_path_head_file , "sequencer/head" )
29
29
30
+ /*
31
+ * A script to set the GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, and
32
+ * GIT_AUTHOR_DATE that will be used for the commit that is currently
33
+ * being rebased.
34
+ */
35
+ static GIT_PATH_FUNC (rebase_path_author_script , "rebase-merge/author-script" )
36
+
37
+ /* We will introduce the 'interactive rebase' mode later */
38
+ static inline int is_rebase_i (const struct replay_opts * opts )
39
+ {
40
+ return 0 ;
41
+ }
42
+
30
43
static const char * get_dir (const struct replay_opts * opts )
31
44
{
32
45
return git_path_seq_dir ();
@@ -369,20 +382,80 @@ static int is_index_unchanged(void)
369
382
return !hashcmp (active_cache_tree -> sha1 , head_commit -> tree -> object .oid .hash );
370
383
}
371
384
385
+ /*
386
+ * Read the author-script file into an environment block, ready for use in
387
+ * run_command(), that can be free()d afterwards.
388
+ */
389
+ static char * * read_author_script (void )
390
+ {
391
+ struct strbuf script = STRBUF_INIT ;
392
+ int i , count = 0 ;
393
+ char * p , * p2 , * * env ;
394
+ size_t env_size ;
395
+
396
+ if (strbuf_read_file (& script , rebase_path_author_script (), 256 ) <= 0 )
397
+ return NULL ;
398
+
399
+ for (p = script .buf ; * p ; p ++ )
400
+ if (skip_prefix (p , "'\\\\''" , (const char * * )& p2 ))
401
+ strbuf_splice (& script , p - script .buf , p2 - p , "'" , 1 );
402
+ else if (* p == '\'' )
403
+ strbuf_splice (& script , p -- - script .buf , 1 , "" , 0 );
404
+ else if (* p == '\n' ) {
405
+ * p = '\0' ;
406
+ count ++ ;
407
+ }
408
+
409
+ env_size = (count + 1 ) * sizeof (* env );
410
+ strbuf_grow (& script , env_size );
411
+ memmove (script .buf + env_size , script .buf , script .len );
412
+ p = script .buf + env_size ;
413
+ env = (char * * )strbuf_detach (& script , NULL );
414
+
415
+ for (i = 0 ; i < count ; i ++ ) {
416
+ env [i ] = p ;
417
+ p += strlen (p ) + 1 ;
418
+ }
419
+ env [count ] = NULL ;
420
+
421
+ return env ;
422
+ }
423
+
372
424
/*
373
425
* If we are cherry-pick, and if the merge did not result in
374
426
* hand-editing, we will hit this commit and inherit the original
375
427
* author date and name.
428
+ *
376
429
* If we are revert, or if our cherry-pick results in a hand merge,
377
430
* we had better say that the current user is responsible for that.
431
+ *
432
+ * An exception is when run_git_commit() is called during an
433
+ * interactive rebase: in that case, we will want to retain the
434
+ * author metadata.
378
435
*/
379
436
static int run_git_commit (const char * defmsg , struct replay_opts * opts ,
380
437
int allow_empty )
381
438
{
439
+ char * * env = NULL ;
382
440
struct argv_array array ;
383
441
int rc ;
384
442
const char * value ;
385
443
444
+ if (is_rebase_i (opts )) {
445
+ env = read_author_script ();
446
+ if (!env )
447
+ return error ("You have staged changes in your working "
448
+ "tree. If these changes are meant to be\n"
449
+ "squashed into the previous commit, run:\n\n"
450
+ " git commit --amend $gpg_sign_opt_quoted\n\n"
451
+ "If they are meant to go into a new commit, "
452
+ "run:\n\n"
453
+ " git commit $gpg_sign_opt_quoted\n\n"
454
+ "In both cases, once you're done, continue "
455
+ "with:\n\n"
456
+ " git rebase --continue\n" );
457
+ }
458
+
386
459
argv_array_init (& array );
387
460
argv_array_push (& array , "commit" );
388
461
argv_array_push (& array , "-n" );
@@ -391,23 +464,25 @@ static int run_git_commit(const char *defmsg, struct replay_opts *opts,
391
464
argv_array_pushf (& array , "-S%s" , opts -> gpg_sign );
392
465
if (opts -> signoff )
393
466
argv_array_push (& array , "-s" );
394
- if (!opts -> edit ) {
395
- argv_array_push (& array , "-F" );
396
- argv_array_push (& array , defmsg );
397
- if (!opts -> signoff &&
398
- !opts -> record_origin &&
399
- git_config_get_value ("commit.cleanup" , & value ))
400
- argv_array_push (& array , "--cleanup=verbatim" );
401
- }
467
+ if (defmsg )
468
+ argv_array_pushl (& array , "-F" , defmsg , NULL );
469
+ if (opts -> edit )
470
+ argv_array_push (& array , "-e" );
471
+ else if (!opts -> signoff && !opts -> record_origin &&
472
+ git_config_get_value ("commit.cleanup" , & value ))
473
+ argv_array_push (& array , "--cleanup=verbatim" );
402
474
403
475
if (allow_empty )
404
476
argv_array_push (& array , "--allow-empty" );
405
477
406
478
if (opts -> allow_empty_message )
407
479
argv_array_push (& array , "--allow-empty-message" );
408
480
409
- rc = run_command_v_opt (array .argv , RUN_GIT_CMD );
481
+ rc = run_command_v_opt_cd_env (array .argv , RUN_GIT_CMD , NULL ,
482
+ (const char * const * )env );
410
483
argv_array_clear (& array );
484
+ free (env );
485
+
411
486
return rc ;
412
487
}
413
488
@@ -657,7 +732,8 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
657
732
goto leave ;
658
733
}
659
734
if (!opts -> no_commit )
660
- res = run_git_commit (git_path_merge_msg (), opts , allow );
735
+ res = run_git_commit (opts -> edit ? NULL : git_path_merge_msg (),
736
+ opts , allow );
661
737
662
738
leave :
663
739
free_message (commit , & msg );
@@ -879,6 +955,9 @@ static int populate_opts_cb(const char *key, const char *value, void *data)
879
955
880
956
static int read_populate_opts (struct replay_opts * opts )
881
957
{
958
+ if (is_rebase_i (opts ))
959
+ return 0 ;
960
+
882
961
if (!file_exists (git_path_opts_file ()))
883
962
return 0 ;
884
963
/*
0 commit comments