@@ -132,10 +132,9 @@ impl CommitList {
132132 commits
133133 }
134134
135- ///
136- pub fn copy_commit_hash ( & self ) -> Result < ( ) > {
137- let marked = self . marked . as_slice ( ) ;
138- let yank: Option < String > = match marked {
135+ /// Build string of marked or selected (if none are marked) commit ids
136+ fn concat_selected_commit_ids ( & self ) -> Option < String > {
137+ match self . marked . as_slice ( ) {
139138 [ ] => self
140139 . items
141140 . iter ( )
@@ -144,24 +143,19 @@ impl CommitList {
144143 . saturating_sub ( self . items . index_offset ( ) ) ,
145144 )
146145 . map ( |e| e. id . to_string ( ) ) ,
147- [ ( _idx, commit) ] => Some ( commit. to_string ( ) ) ,
148- [ first, .., last] => {
149- let marked_consecutive =
150- marked. windows ( 2 ) . all ( |w| w[ 0 ] . 0 + 1 == w[ 1 ] . 0 ) ;
151-
152- let yank = if marked_consecutive {
153- format ! ( "{}^..{}" , first. 1 , last. 1 )
154- } else {
155- marked
156- . iter ( )
157- . map ( |( _idx, commit) | commit. to_string ( ) )
158- . join ( " " )
159- } ;
160- Some ( yank)
161- }
162- } ;
146+ marked => Some (
147+ marked
148+ . iter ( )
149+ . map ( |( _idx, commit) | commit. to_string ( ) )
150+ . join ( " " ) ,
151+ ) ,
152+ }
153+ }
163154
164- if let Some ( yank) = yank {
155+ /// Copy currently marked or selected (if none are marked) commit ids
156+ /// to clipboard
157+ pub fn copy_commit_hash ( & self ) -> Result < ( ) > {
158+ if let Some ( yank) = self . concat_selected_commit_ids ( ) {
165159 crate :: clipboard:: copy_string ( & yank) ?;
166160 self . queue . push ( InternalEvent :: ShowInfoMsg (
167161 strings:: copy_success ( & yank) ,
@@ -893,8 +887,36 @@ impl Component for CommitList {
893887
894888#[ cfg( test) ]
895889mod tests {
890+ use asyncgit:: sync:: CommitInfo ;
891+
896892 use super :: * ;
897893
894+ impl Default for CommitList {
895+ fn default ( ) -> Self {
896+ Self {
897+ title : String :: from ( "" ) . into_boxed_str ( ) ,
898+ selection : 0 ,
899+ highlighted_selection : Option :: None ,
900+ highlights : Option :: None ,
901+ tags : Option :: None ,
902+ items : ItemBatch :: default ( ) ,
903+ commits : IndexSet :: default ( ) ,
904+ marked : Vec :: default ( ) ,
905+ scroll_top : Cell :: default ( ) ,
906+ local_branches : BTreeMap :: default ( ) ,
907+ remote_branches : BTreeMap :: default ( ) ,
908+ theme : SharedTheme :: default ( ) ,
909+ key_config : SharedKeyConfig :: default ( ) ,
910+ scroll_state : ( Instant :: now ( ) , 0.0 ) ,
911+ current_size : Cell :: default ( ) ,
912+ repo : RepoPathRef :: new ( sync:: RepoPath :: Path (
913+ std:: path:: PathBuf :: default ( ) ,
914+ ) ) ,
915+ queue : Queue :: default ( ) ,
916+ }
917+ }
918+ }
919+
898920 #[ test]
899921 fn test_string_width_align ( ) {
900922 assert_eq ! ( string_width_align( "123" , 3 ) , "123" ) ;
@@ -916,4 +938,126 @@ mod tests {
916938 "Jon Grythe Stødle "
917939 ) ;
918940 }
941+
942+ /// Build a commit list with a few commits loaded
943+ fn build_commit_list_with_some_commits ( ) -> CommitList {
944+ let mut items = ItemBatch :: default ( ) ;
945+ let basic_commit_info = CommitInfo {
946+ message : String :: default ( ) ,
947+ time : 0 ,
948+ author : String :: default ( ) ,
949+ id : CommitId :: default ( ) ,
950+ } ;
951+ // This just creates a sequence of fake ordered ids
952+ // 0000000000000000000000000000000000000000
953+ // 0000000000000000000000000000000000000001
954+ // 0000000000000000000000000000000000000002
955+ // ...
956+ items. set_items (
957+ 2 , /* randomly choose an offset */
958+ ( 0 ..20 )
959+ . map ( |idx| CommitInfo {
960+ id : CommitId :: from_str_unchecked ( & format ! (
961+ "{idx:040}" ,
962+ ) )
963+ . unwrap ( ) ,
964+ ..basic_commit_info. clone ( )
965+ } )
966+ . collect ( ) ,
967+ None ,
968+ ) ;
969+ CommitList {
970+ items,
971+ selection : 4 , // Randomly select one commit
972+ ..Default :: default ( )
973+ }
974+ }
975+
976+ /// Build a value for cl.marked based on indices into cl.items
977+ fn build_marked_from_indices (
978+ cl : & CommitList ,
979+ marked_indices : & [ usize ] ,
980+ ) -> Vec < ( usize , CommitId ) > {
981+ let offset = cl. items . index_offset ( ) ;
982+ marked_indices
983+ . iter ( )
984+ . map ( |idx| {
985+ ( * idx, cl. items . iter ( ) . nth ( * idx - offset) . unwrap ( ) . id )
986+ } )
987+ . collect ( )
988+ }
989+
990+ #[ test]
991+ fn test_copy_commit_list_empty ( ) {
992+ assert_eq ! (
993+ CommitList :: default ( ) . concat_selected_commit_ids( ) ,
994+ None
995+ ) ;
996+ }
997+
998+ #[ test]
999+ fn test_copy_commit_none_marked ( ) {
1000+ let cl = CommitList {
1001+ selection : 4 ,
1002+ ..build_commit_list_with_some_commits ( )
1003+ } ;
1004+ // ids from build_commit_list_with_some_commits() are
1005+ // offset by two, so we expect commit id 2 for
1006+ // selection = 4
1007+ assert_eq ! (
1008+ cl. concat_selected_commit_ids( ) ,
1009+ Some ( String :: from(
1010+ "0000000000000000000000000000000000000002"
1011+ ) )
1012+ ) ;
1013+ }
1014+
1015+ #[ test]
1016+ fn test_copy_commit_one_marked ( ) {
1017+ let cl = build_commit_list_with_some_commits ( ) ;
1018+ let cl = CommitList {
1019+ marked : build_marked_from_indices ( & cl, & [ 3 ] ) ,
1020+ ..cl
1021+ } ;
1022+ assert_eq ! (
1023+ cl. concat_selected_commit_ids( ) ,
1024+ Some ( String :: from(
1025+ "0000000000000000000000000000000000000001" ,
1026+ ) )
1027+ ) ;
1028+ }
1029+
1030+ #[ test]
1031+ fn test_copy_commit_range_marked ( ) {
1032+ let cl = build_commit_list_with_some_commits ( ) ;
1033+ let cl = CommitList {
1034+ marked : build_marked_from_indices ( & cl, & [ 4 , 5 , 6 , 7 ] ) ,
1035+ ..cl
1036+ } ;
1037+ assert_eq ! (
1038+ cl. concat_selected_commit_ids( ) ,
1039+ Some ( String :: from( concat!(
1040+ "0000000000000000000000000000000000000002 " ,
1041+ "0000000000000000000000000000000000000003 " ,
1042+ "0000000000000000000000000000000000000004 " ,
1043+ "0000000000000000000000000000000000000005"
1044+ ) ) )
1045+ ) ;
1046+ }
1047+
1048+ #[ test]
1049+ fn test_copy_commit_random_marked ( ) {
1050+ let cl = build_commit_list_with_some_commits ( ) ;
1051+ let cl = CommitList {
1052+ marked : build_marked_from_indices ( & cl, & [ 4 , 7 ] ) ,
1053+ ..cl
1054+ } ;
1055+ assert_eq ! (
1056+ cl. concat_selected_commit_ids( ) ,
1057+ Some ( String :: from( concat!(
1058+ "0000000000000000000000000000000000000002 " ,
1059+ "0000000000000000000000000000000000000005"
1060+ ) ) )
1061+ ) ;
1062+ }
9191063}
0 commit comments