@@ -7,6 +7,7 @@ mod config;
77mod owned;
88mod stack;
99
10+ use git2:: DiffStats ;
1011use std:: io:: Write ;
1112use std:: path:: Path ;
1213
@@ -337,7 +338,10 @@ fn run_with_repo(logger: &slog::Logger, config: &Config, repo: &git2::Repository
337338 & head_tree,
338339 & [ & head_commit] ,
339340 ) ?) ?;
340- announce ( logger, Announcement :: Committed ( & head_commit, & diff) ) ;
341+ announce (
342+ logger,
343+ Announcement :: Committed ( & head_commit, dest_commit_locator, & diff) ,
344+ ) ;
341345 } else {
342346 announce (
343347 logger,
@@ -572,7 +576,7 @@ fn index_stats(repo: &git2::Repository) -> Result<git2::DiffStats> {
572576
573577// Messages that will be shown to users during normal operations (not debug messages).
574578enum Announcement < ' r > {
575- Committed ( & ' r git2:: Commit < ' r > , & ' r git2:: DiffStats ) ,
579+ Committed ( & ' r git2:: Commit < ' r > , & ' r str , & ' r git2:: DiffStats ) ,
576580 WouldHaveCommitted ( & ' r str , & ' r git2:: DiffStats ) ,
577581 WouldHaveRebased ( & ' r std:: process:: Command ) ,
578582 HowToSquash ( String ) ,
@@ -592,17 +596,26 @@ enum Announcement<'r> {
592596
593597fn announce ( logger : & slog:: Logger , announcement : Announcement ) {
594598 match announcement {
595- Announcement :: Committed ( commit, diff) => info ! (
596- logger,
597- "committed" ;
598- "commit" => & commit. id( ) . to_string( ) ,
599- "header" => format!( "+{},-{}" , & diff. insertions( ) , & diff. deletions( ) )
600- ) ,
599+ Announcement :: Committed ( commit, destination, diff) => {
600+ let commit_short_id = commit. as_object ( ) . short_id ( ) . unwrap ( ) ;
601+ let commit_short_id = commit_short_id
602+ . as_str ( )
603+ . expect ( "the commit short id is always a valid ASCII string" ) ;
604+ let change_header = format_change_header ( diff) ;
605+
606+ info ! (
607+ logger,
608+ "committed" ;
609+ "fixup" => destination,
610+ "commit" => commit_short_id,
611+ "header" => change_header,
612+ ) ;
613+ }
601614 Announcement :: WouldHaveCommitted ( fixup, diff) => info ! (
602615 logger,
603616 "would have committed" ;
604617 "fixup" => fixup,
605- "header" => format! ( "+{},-{}" , & diff. insertions ( ) , & diff . deletions ( ) )
618+ "header" => format_change_header ( diff) ,
606619 ) ,
607620 Announcement :: WouldHaveRebased ( command) => info ! (
608621 logger, "would have run git rebase" ; "command" => format!( "{:?}" , command)
@@ -674,11 +687,45 @@ fn announce(logger: &slog::Logger, announcement: Announcement) {
674687 }
675688}
676689
690+ fn format_change_header ( diff : & DiffStats ) -> String {
691+ let insertions = diff. insertions ( ) ;
692+ let deletions = diff. deletions ( ) ;
693+
694+ let mut header = String :: new ( ) ;
695+ if insertions > 0 {
696+ header. push_str ( & format ! (
697+ "{} {}(+)" ,
698+ insertions,
699+ if insertions == 1 {
700+ "insertion"
701+ } else {
702+ "insertions"
703+ }
704+ ) ) ;
705+ }
706+ if deletions > 0 {
707+ if !header. is_empty ( ) {
708+ header. push_str ( ", " ) ;
709+ }
710+ header. push_str ( & format ! (
711+ "{} {}(-)" ,
712+ deletions,
713+ if deletions == 1 {
714+ "deletion"
715+ } else {
716+ "deletions"
717+ }
718+ ) ) ;
719+ }
720+ header
721+ }
722+
677723#[ cfg( test) ]
678724mod tests {
679725 use git2:: message_trailers_strs;
680726 use serde_json:: json;
681727 use std:: path:: PathBuf ;
728+ use tests:: repo_utils:: add;
682729
683730 use super :: * ;
684731 mod log_utils;
@@ -732,8 +779,113 @@ mod tests {
732779 log_utils:: assert_log_messages_are (
733780 capturing_logger. visible_logs ( ) ,
734781 vec ! [
735- & json!( { "level" : "INFO" , "msg" : "committed" } ) ,
736- & json!( { "level" : "INFO" , "msg" : "committed" } ) ,
782+ & json!( {
783+ "level" : "INFO" ,
784+ "msg" : "committed" ,
785+ "fixup" : "Initial commit." ,
786+ "header" : "1 insertion(+)" ,
787+ } ) ,
788+ & json!( {
789+ "level" : "INFO" ,
790+ "msg" : "committed" ,
791+ "fixup" : "Initial commit." ,
792+ "header" : "2 insertions(+)" ,
793+ } ) ,
794+ & json!( {
795+ "level" : "INFO" ,
796+ "msg" : "To squash the new commits, rebase:" ,
797+ "command" : "git rebase --interactive --autosquash --autostash --root" ,
798+ } ) ,
799+ ] ,
800+ ) ;
801+ }
802+
803+ #[ test]
804+ fn one_deletion ( ) {
805+ let ( ctx, file_path) = repo_utils:: prepare_repo ( ) ;
806+ std:: fs:: write (
807+ ctx. join ( & file_path) ,
808+ br#"
809+ line
810+ line
811+ "# ,
812+ )
813+ . unwrap ( ) ;
814+ add ( & ctx. repo , & file_path) ;
815+
816+ let actual_pre_absorb_commit = ctx. repo . head ( ) . unwrap ( ) . peel_to_commit ( ) . unwrap ( ) . id ( ) ;
817+
818+ // run 'git-absorb'
819+ let mut capturing_logger = log_utils:: CapturingLogger :: new ( ) ;
820+ run_with_repo ( & capturing_logger. logger , & DEFAULT_CONFIG , & ctx. repo ) . unwrap ( ) ;
821+
822+ let mut revwalk = ctx. repo . revwalk ( ) . unwrap ( ) ;
823+ revwalk. push_head ( ) . unwrap ( ) ;
824+ assert_eq ! ( revwalk. count( ) , 2 ) ;
825+
826+ assert ! ( nothing_left_in_index( & ctx. repo) . unwrap( ) ) ;
827+
828+ let pre_absorb_ref_commit = ctx. repo . refname_to_id ( "PRE_ABSORB_HEAD" ) . unwrap ( ) ;
829+ assert_eq ! ( pre_absorb_ref_commit, actual_pre_absorb_commit) ;
830+
831+ log_utils:: assert_log_messages_are (
832+ capturing_logger. visible_logs ( ) ,
833+ vec ! [
834+ & json!( {
835+ "level" : "INFO" ,
836+ "msg" : "committed" ,
837+ "fixup" : "Initial commit." ,
838+ "header" : "3 deletions(-)" ,
839+ } ) ,
840+ & json!( {
841+ "level" : "INFO" ,
842+ "msg" : "To squash the new commits, rebase:" ,
843+ "command" : "git rebase --interactive --autosquash --autostash --root" ,
844+ } ) ,
845+ ] ,
846+ ) ;
847+ }
848+
849+ #[ test]
850+ fn one_insertion_and_one_deletion ( ) {
851+ let ( ctx, file_path) = repo_utils:: prepare_repo ( ) ;
852+ std:: fs:: write (
853+ ctx. join ( & file_path) ,
854+ br#"
855+ line
856+ line
857+
858+ even more
859+ lines
860+ "# ,
861+ )
862+ . unwrap ( ) ;
863+ add ( & ctx. repo , & file_path) ;
864+
865+ let actual_pre_absorb_commit = ctx. repo . head ( ) . unwrap ( ) . peel_to_commit ( ) . unwrap ( ) . id ( ) ;
866+
867+ // run 'git-absorb'
868+ let mut capturing_logger = log_utils:: CapturingLogger :: new ( ) ;
869+ run_with_repo ( & capturing_logger. logger , & DEFAULT_CONFIG , & ctx. repo ) . unwrap ( ) ;
870+
871+ let mut revwalk = ctx. repo . revwalk ( ) . unwrap ( ) ;
872+ revwalk. push_head ( ) . unwrap ( ) ;
873+ assert_eq ! ( revwalk. count( ) , 2 ) ;
874+
875+ assert ! ( nothing_left_in_index( & ctx. repo) . unwrap( ) ) ;
876+
877+ let pre_absorb_ref_commit = ctx. repo . refname_to_id ( "PRE_ABSORB_HEAD" ) . unwrap ( ) ;
878+ assert_eq ! ( pre_absorb_ref_commit, actual_pre_absorb_commit) ;
879+
880+ log_utils:: assert_log_messages_are (
881+ capturing_logger. visible_logs ( ) ,
882+ vec ! [
883+ & json!( {
884+ "level" : "INFO" ,
885+ "msg" : "committed" ,
886+ "fixup" : "Initial commit." ,
887+ "header" : "1 insertion(+), 1 deletion(-)" ,
888+ } ) ,
737889 & json!( {
738890 "level" : "INFO" ,
739891 "msg" : "To squash the new commits, rebase:" ,
@@ -1165,7 +1317,12 @@ mod tests {
11651317 log_utils:: assert_log_messages_are (
11661318 capturing_logger. visible_logs ( ) ,
11671319 vec ! [
1168- & json!( { "level" : "INFO" , "msg" : "committed" } ) ,
1320+ & json!( {
1321+ "level" : "INFO" ,
1322+ "msg" : "committed" ,
1323+ "fixup" : "Initial commit." ,
1324+ "header" : "3 insertions(+)" ,
1325+ } ) ,
11691326 & json!( {
11701327 "level" : "INFO" ,
11711328 "msg" : "To squash the new commits, rebase:" ,
@@ -1600,11 +1757,15 @@ mod tests {
16001757 vec ! [
16011758 & json!( {
16021759 "level" : "INFO" ,
1603- "msg" : "would have committed" , "fixup" : "Initial commit." ,
1760+ "msg" : "would have committed" ,
1761+ "fixup" : "Initial commit." ,
1762+ "header" : "1 insertion(+)" ,
16041763 } ) ,
16051764 & json!( {
16061765 "level" : "INFO" ,
1607- "msg" : "would have committed" , "fixup" : "Initial commit." ,
1766+ "msg" : "would have committed" ,
1767+ "fixup" : "Initial commit." ,
1768+ "header" : "2 insertions(+)" ,
16081769 } ) ,
16091770 ] ,
16101771 ) ;
0 commit comments