@@ -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,127 @@ 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
+ "{:040}" ,
962
+ idx
963
+ ) )
964
+ . unwrap ( ) ,
965
+ ..basic_commit_info. clone ( )
966
+ } )
967
+ . collect ( ) ,
968
+ None ,
969
+ ) ;
970
+ CommitList {
971
+ items : items,
972
+ selection : 4 , // Randomly select one commit
973
+ ..Default :: default ( )
974
+ }
975
+ }
976
+
977
+ /// Build a value for cl.marked based on indices into cl.items
978
+ fn build_marked_from_indices (
979
+ cl : & CommitList ,
980
+ marked_indices : & [ usize ] ,
981
+ ) -> Vec < ( usize , CommitId ) > {
982
+ let offset = cl. items . index_offset ( ) ;
983
+ marked_indices
984
+ . iter ( )
985
+ . map ( |idx| {
986
+ ( * idx, cl. items . iter ( ) . nth ( * idx - offset) . unwrap ( ) . id )
987
+ } )
988
+ . collect ( )
989
+ }
990
+
991
+ #[ test]
992
+ fn test_copy_commit_list_empty ( ) {
993
+ assert_eq ! (
994
+ CommitList :: default ( ) . concat_selected_commit_ids( ) ,
995
+ None
996
+ ) ;
997
+ }
998
+
999
+ #[ test]
1000
+ fn test_copy_commit_none_marked ( ) {
1001
+ let cl = CommitList {
1002
+ selection : 4 ,
1003
+ ..build_commit_list_with_some_commits ( )
1004
+ } ;
1005
+ // ids from build_commit_list_with_some_commits() are
1006
+ // offset by two, so we expect commit id 2 for
1007
+ // selection = 4
1008
+ assert_eq ! (
1009
+ cl. concat_selected_commit_ids( ) ,
1010
+ Some ( String :: from(
1011
+ "0000000000000000000000000000000000000002"
1012
+ ) )
1013
+ ) ;
1014
+ }
1015
+
1016
+ #[ test]
1017
+ fn test_copy_commit_one_marked ( ) {
1018
+ let cl = build_commit_list_with_some_commits ( ) ;
1019
+ let cl = CommitList {
1020
+ marked : build_marked_from_indices ( & cl, & vec ! [ 3 ] ) ,
1021
+ ..cl
1022
+ } ;
1023
+ assert_eq ! (
1024
+ cl. concat_selected_commit_ids( ) ,
1025
+ Some ( String :: from(
1026
+ "0000000000000000000000000000000000000001" ,
1027
+ ) )
1028
+ ) ;
1029
+ }
1030
+
1031
+ #[ test]
1032
+ fn test_copy_commit_range_marked ( ) {
1033
+ let cl = build_commit_list_with_some_commits ( ) ;
1034
+ let cl = CommitList {
1035
+ marked : build_marked_from_indices ( & cl, & vec ! [ 4 , 5 , 6 , 7 ] ) ,
1036
+ ..cl
1037
+ } ;
1038
+ assert_eq ! (
1039
+ cl. concat_selected_commit_ids( ) ,
1040
+ Some ( String :: from( concat!(
1041
+ "0000000000000000000000000000000000000002 " ,
1042
+ "0000000000000000000000000000000000000003 " ,
1043
+ "0000000000000000000000000000000000000004 " ,
1044
+ "0000000000000000000000000000000000000005"
1045
+ ) ) )
1046
+ ) ;
1047
+ }
1048
+
1049
+ #[ test]
1050
+ fn test_copy_commit_random_marked ( ) {
1051
+ let cl = build_commit_list_with_some_commits ( ) ;
1052
+ let cl = CommitList {
1053
+ marked : build_marked_from_indices ( & cl, & vec ! [ 4 , 7 ] ) ,
1054
+ ..cl
1055
+ } ;
1056
+ assert_eq ! (
1057
+ cl. concat_selected_commit_ids( ) ,
1058
+ Some ( String :: from( concat!(
1059
+ "0000000000000000000000000000000000000002 " ,
1060
+ "0000000000000000000000000000000000000005"
1061
+ ) ) )
1062
+ ) ;
1063
+ }
919
1064
}
0 commit comments