@@ -132,10 +132,9 @@ impl CommitList {
132
132
commits
133
133
}
134
134
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 ( ) {
139
138
[ ] => self
140
139
. items
141
140
. iter ( )
@@ -144,24 +143,19 @@ impl CommitList {
144
143
. saturating_sub ( self . items . index_offset ( ) ) ,
145
144
)
146
145
. 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
+ }
163
154
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 ( ) {
165
159
crate :: clipboard:: copy_string ( & yank) ?;
166
160
self . queue . push ( InternalEvent :: ShowInfoMsg (
167
161
strings:: copy_success ( & yank) ,
@@ -893,8 +887,36 @@ impl Component for CommitList {
893
887
894
888
#[ cfg( test) ]
895
889
mod tests {
890
+ use asyncgit:: sync:: CommitInfo ;
891
+
896
892
use super :: * ;
897
893
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
+
898
920
#[ test]
899
921
fn test_string_width_align ( ) {
900
922
assert_eq ! ( string_width_align( "123" , 3 ) , "123" ) ;
@@ -916,4 +938,126 @@ mod tests {
916
938
"Jon Grythe Stødle "
917
939
) ;
918
940
}
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
+ }
919
1063
}
0 commit comments