@@ -354,7 +354,8 @@ mod in_memory {
354354 use crate :: core:: rewrite:: move_branches;
355355 use crate :: core:: rewrite:: plan:: { OidOrLabel , RebaseCommand , RebasePlan } ;
356356 use crate :: git:: {
357- CherryPickFastError , CherryPickFastOptions , GitRunInfo , MaybeZeroOid , NonZeroOid , Repo ,
357+ AmendFastOptions , CherryPickFastError , CherryPickFastOptions , GitRunInfo , MaybeZeroOid ,
358+ NonZeroOid , Repo ,
358359 } ;
359360 use crate :: util:: ExitCode ;
360361
@@ -404,6 +405,7 @@ mod in_memory {
404405 | RebaseCommand :: CreateLabel { .. }
405406 | RebaseCommand :: Reset { .. }
406407 | RebaseCommand :: Pick { .. }
408+ | RebaseCommand :: FixUp { .. }
407409 | RebaseCommand :: RegisterExtraPostRewriteHook
408410 | RebaseCommand :: DetectEmptyCommit { .. }
409411 | RebaseCommand :: SkipUpstreamAppliedCommit { .. } => None ,
@@ -453,6 +455,7 @@ mod in_memory {
453455 | RebaseCommand :: RegisterExtraPostRewriteHook
454456 | RebaseCommand :: DetectEmptyCommit { .. } => false ,
455457 RebaseCommand :: Pick { .. }
458+ | RebaseCommand :: FixUp { .. }
456459 | RebaseCommand :: Merge { .. }
457460 | RebaseCommand :: SkipUpstreamAppliedCommit { .. } => true ,
458461 } )
@@ -572,9 +575,8 @@ mod in_memory {
572575
573576 writeln ! (
574577 effects. get_output_stream( ) ,
575- "[{}/{}] Skipped now-empty commit: {}" ,
576- i,
577- num_picks,
578+ "{} Skipped now-empty commit: {}" ,
579+ commit_num,
578580 commit_description
579581 ) ?;
580582 } else {
@@ -593,6 +595,131 @@ mod in_memory {
593595 }
594596 }
595597
598+ RebaseCommand :: FixUp {
599+ commit_to_fixup_oid,
600+ fixup_commit_oid,
601+ } => {
602+ // FIXME this was mostly copied from RebaseCommand::Pick;
603+ // review before push to make sure it really makes sense or
604+ // can be simplified
605+ let current_commit = repo
606+ . find_commit_or_fail ( current_oid)
607+ . wrap_err ( "Finding current commit" ) ?;
608+ let commit_to_fixup = match rewritten_oids. get ( commit_to_fixup_oid) {
609+ Some ( MaybeZeroOid :: NonZero ( rewritten_oid) ) => repo
610+ . find_commit_or_fail ( * rewritten_oid)
611+ . wrap_err ( "Finding commit to apply" ) ?,
612+ Some ( MaybeZeroOid :: Zero ) => todo ! ( "FIXME fixing up deleted commit" ) ,
613+ None => repo
614+ . find_commit_or_fail ( * commit_to_fixup_oid)
615+ . wrap_err ( "Finding commit to apply" ) ?,
616+ } ;
617+ let fixup_commit = repo
618+ . find_commit_or_fail ( * fixup_commit_oid)
619+ . wrap_err ( "Finding commit to apply" ) ?;
620+ i += 1 ;
621+
622+ let commit_description = printable_styled_string (
623+ effects. get_glyphs ( ) ,
624+ commit_to_fixup. friendly_describe ( effects. get_glyphs ( ) ) ?,
625+ ) ?;
626+ let commit_num = format ! ( "[{}/{}]" , i, num_picks) ;
627+ progress. notify_progress ( i, num_picks) ;
628+
629+ if fixup_commit. get_parent_count ( ) > 1 {
630+ warn ! (
631+ ?fixup_commit_oid,
632+ "BUG: Merge commit should have been detected during planning phase"
633+ ) ;
634+ return Ok ( RebaseInMemoryResult :: CannotRebaseMergeCommit {
635+ commit_oid : * fixup_commit_oid,
636+ } ) ;
637+ } ;
638+
639+ progress. notify_status ( format ! (
640+ "Applying patch for commit: {}" ,
641+ commit_description
642+ ) ) ;
643+
644+ let commit_tree = repo. amend_fast (
645+ & commit_to_fixup,
646+ & AmendFastOptions :: FromCommit {
647+ commit : fixup_commit,
648+ } ,
649+ ) ?;
650+
651+ let commit_message = commit_to_fixup. get_message_raw ( ) ?;
652+ let commit_message = commit_message. to_str ( ) . with_context ( || {
653+ eyre:: eyre!(
654+ "Could not decode commit message for commit: {:?}" ,
655+ fixup_commit_oid
656+ )
657+ } ) ?;
658+
659+ progress
660+ . notify_status ( format ! ( "Committing to repository: {}" , commit_description) ) ;
661+ let committer_signature = if * preserve_timestamps {
662+ commit_to_fixup. get_committer ( )
663+ } else {
664+ commit_to_fixup. get_committer ( ) . update_timestamp ( * now) ?
665+ } ;
666+ let parent_commit = current_commit. get_parents ( ) [ 0 ] . clone ( ) ;
667+ let rebased_commit_oid = repo
668+ . create_commit (
669+ None ,
670+ & commit_to_fixup. get_author ( ) ,
671+ & committer_signature,
672+ commit_message,
673+ & commit_tree,
674+ vec ! [ & parent_commit] ,
675+ )
676+ . wrap_err ( "Applying rebased commit" ) ?;
677+
678+ let rebased_commit = repo
679+ . find_commit_or_fail ( rebased_commit_oid)
680+ . wrap_err ( "Looking up just-rebased commit" ) ?;
681+ let commit_description = printable_styled_string (
682+ effects. get_glyphs ( ) ,
683+ repo. friendly_describe_commit_from_oid (
684+ effects. get_glyphs ( ) ,
685+ rebased_commit_oid,
686+ ) ?,
687+ ) ?;
688+ if rebased_commit. is_empty ( ) {
689+ rewritten_oids. insert ( * commit_to_fixup_oid, MaybeZeroOid :: Zero ) ;
690+ maybe_set_skipped_head_new_oid ( * commit_to_fixup_oid, current_oid) ;
691+
692+ writeln ! (
693+ effects. get_output_stream( ) ,
694+ "{} Skipped now-empty commit: {}" ,
695+ commit_num,
696+ commit_description
697+ ) ?;
698+ } else {
699+ rewritten_oids. insert (
700+ * commit_to_fixup_oid,
701+ MaybeZeroOid :: NonZero ( rebased_commit_oid) ,
702+ ) ;
703+ rewritten_oids. insert (
704+ * fixup_commit_oid,
705+ match head_oid {
706+ Some ( head_oid) if head_oid == * fixup_commit_oid => {
707+ MaybeZeroOid :: NonZero ( rebased_commit_oid)
708+ }
709+ None | Some ( _) => MaybeZeroOid :: Zero ,
710+ } ,
711+ ) ;
712+ current_oid = rebased_commit_oid;
713+
714+ writeln ! (
715+ effects. get_output_stream( ) ,
716+ "{} Amended as: {}" ,
717+ commit_num,
718+ commit_description
719+ ) ?;
720+ }
721+ }
722+
596723 RebaseCommand :: Merge {
597724 replacement_commit_oid : None ,
598725 commit_oid,
0 commit comments