@@ -888,6 +888,7 @@ impl Attributes {
888888
889889impl Options {
890890 #[ allow( clippy:: cognitive_complexity) ]
891+ /// Constructs an Options instance from command line matches.
891892 fn from_matches ( matches : & ArgMatches ) -> CopyResult < Self > {
892893 let not_implemented_opts = vec ! [
893894 #[ cfg( not( any( windows, unix) ) ) ]
@@ -931,23 +932,7 @@ impl Options {
931932 } ;
932933
933934 // Parse attributes to preserve
934- let mut attributes =
935- if let Some ( attribute_strs) = matches. get_many :: < String > ( options:: PRESERVE ) {
936- if attribute_strs. len ( ) == 0 {
937- Attributes :: DEFAULT
938- } else {
939- Attributes :: parse_iter ( attribute_strs) ?
940- }
941- } else if matches. get_flag ( options:: ARCHIVE ) {
942- // --archive is used. Same as --preserve=all
943- Attributes :: ALL
944- } else if matches. get_flag ( options:: NO_DEREFERENCE_PRESERVE_LINKS ) {
945- Attributes :: LINKS
946- } else if matches. get_flag ( options:: PRESERVE_DEFAULT_ATTRIBUTES ) {
947- Attributes :: DEFAULT
948- } else {
949- Attributes :: NONE
950- } ;
935+ let mut attributes = Self :: determine_attributes ( matches) ?;
951936
952937 // handling no-preserve options and adjusting the attributes
953938 if let Some ( attribute_strs) = matches. get_many :: < String > ( options:: NO_PRESERVE ) {
@@ -987,50 +972,8 @@ impl Options {
987972 debug : matches. get_flag ( options:: DEBUG ) ,
988973 verbose : matches. get_flag ( options:: VERBOSE ) || matches. get_flag ( options:: DEBUG ) ,
989974 strip_trailing_slashes : matches. get_flag ( options:: STRIP_TRAILING_SLASHES ) ,
990- reflink_mode : {
991- if let Some ( reflink) = matches. get_one :: < String > ( options:: REFLINK ) {
992- match reflink. as_str ( ) {
993- "always" => ReflinkMode :: Always ,
994- "auto" => ReflinkMode :: Auto ,
995- "never" => ReflinkMode :: Never ,
996- value => {
997- return Err ( Error :: InvalidArgument ( format ! (
998- "invalid argument {} for \' reflink\' " ,
999- value. quote( )
1000- ) ) ) ;
1001- }
1002- }
1003- } else {
1004- #[ cfg( any( target_os = "linux" , target_os = "android" , target_os = "macos" ) ) ]
1005- {
1006- ReflinkMode :: Auto
1007- }
1008- #[ cfg( not( any(
1009- target_os = "linux" ,
1010- target_os = "android" ,
1011- target_os = "macos"
1012- ) ) ) ]
1013- {
1014- ReflinkMode :: Never
1015- }
1016- }
1017- } ,
1018- sparse_mode : {
1019- if let Some ( val) = matches. get_one :: < String > ( options:: SPARSE ) {
1020- match val. as_str ( ) {
1021- "always" => SparseMode :: Always ,
1022- "auto" => SparseMode :: Auto ,
1023- "never" => SparseMode :: Never ,
1024- _ => {
1025- return Err ( Error :: InvalidArgument ( format ! (
1026- "invalid argument {val} for \' sparse\' "
1027- ) ) ) ;
1028- }
1029- }
1030- } else {
1031- SparseMode :: Auto
1032- }
1033- } ,
975+ reflink_mode : Self :: determine_reflink_mode ( matches) ?,
976+ sparse_mode : Self :: determine_sparse_mode ( matches) ?,
1034977 backup : backup_mode,
1035978 backup_suffix,
1036979 overwrite,
@@ -1044,17 +987,126 @@ impl Options {
1044987 Ok ( options)
1045988 }
1046989
990+ /// Determines if symbolic links should be dereferenced.
991+ /// dereference means follow
1047992 fn dereference ( & self , in_command_line : bool ) -> bool {
1048993 self . dereference || ( in_command_line && self . cli_dereference )
1049994 }
1050995
996+ /// Checks if hard links should be preserved.
1051997 fn preserve_hard_links ( & self ) -> bool {
1052998 match self . attributes . links {
1053999 Preserve :: No => false ,
10541000 Preserve :: Yes { .. } => true ,
10551001 }
10561002 }
10571003
1004+ /// Gets the attributes to be preserved based on the command line matches.
1005+ fn get_attributes ( matches : & ArgMatches ) -> CopyResult < Attributes > {
1006+ if let Some ( attribute_strs) = matches. get_many :: < String > ( options:: PRESERVE ) {
1007+ if attribute_strs. len ( ) == 0 {
1008+ return Ok ( Attributes :: DEFAULT ) ;
1009+ } else {
1010+ return Attributes :: parse_iter ( attribute_strs) ;
1011+ }
1012+ } else if matches. get_flag ( options:: ARCHIVE ) {
1013+ // --archive is used. Same as --preserve=all
1014+ return Ok ( Attributes :: ALL ) ;
1015+ } else if matches. get_flag ( options:: NO_DEREFERENCE_PRESERVE_LINKS ) {
1016+ return Ok ( Attributes :: LINKS ) ;
1017+ } else if matches. get_flag ( options:: PRESERVE_DEFAULT_ATTRIBUTES ) {
1018+ return Ok ( Attributes :: DEFAULT ) ;
1019+ } else {
1020+ return Ok ( Attributes :: NONE ) ;
1021+ }
1022+ }
1023+
1024+ /// Determines the attributes to be preserved based on the command line matches.
1025+ fn determine_attributes ( matches : & ArgMatches ) -> CopyResult < Attributes > {
1026+ let mut attributes = Self :: get_attributes ( matches) ?;
1027+
1028+ // handling no-preserve options and adjusting the attributes
1029+ if let Some ( attribute_strs) = matches. get_many :: < String > ( options:: NO_PRESERVE ) {
1030+ if attribute_strs. len ( ) > 0 {
1031+ let no_preserve_attributes = Attributes :: parse_iter ( attribute_strs) ?;
1032+ if matches ! ( no_preserve_attributes. links, Preserve :: Yes { .. } ) {
1033+ attributes. links = Preserve :: No ;
1034+ }
1035+ }
1036+ }
1037+
1038+ attributes = Self :: handle_no_preserve_option ( attributes, matches) ?;
1039+
1040+ #[ cfg( not( feature = "feat_selinux" ) ) ]
1041+ if let Preserve :: Yes { required } = attributes. context {
1042+ let selinux_disabled_error =
1043+ Error :: Error ( "SELinux was not enabled during the compile time!" . to_string ( ) ) ;
1044+ if required {
1045+ return Err ( selinux_disabled_error) ;
1046+ } else {
1047+ show_error_if_needed ( & selinux_disabled_error) ;
1048+ }
1049+ }
1050+
1051+ Ok ( attributes)
1052+ }
1053+
1054+ /// Handles the no-preserve option and adjusts the attributes accordingly.
1055+ fn handle_no_preserve_option (
1056+ mut attributes : Attributes ,
1057+ matches : & ArgMatches ,
1058+ ) -> CopyResult < Attributes > {
1059+ if let Some ( attribute_strs) = matches. get_many :: < String > ( options:: NO_PRESERVE ) {
1060+ if attribute_strs. len ( ) > 0 {
1061+ let no_preserve_attributes = Attributes :: parse_iter ( attribute_strs) ?;
1062+ if matches ! ( no_preserve_attributes. links, Preserve :: Yes { .. } ) {
1063+ attributes. links = Preserve :: No ;
1064+ }
1065+ }
1066+ }
1067+ Ok ( attributes)
1068+ }
1069+
1070+ /// Determines the reflink mode based on the command line matches.
1071+ fn determine_reflink_mode ( matches : & ArgMatches ) -> CopyResult < ReflinkMode > {
1072+ if let Some ( reflink) = matches. get_one :: < String > ( options:: REFLINK ) {
1073+ match reflink. as_str ( ) {
1074+ "always" => Ok ( ReflinkMode :: Always ) ,
1075+ "auto" => Ok ( ReflinkMode :: Auto ) ,
1076+ "never" => Ok ( ReflinkMode :: Never ) ,
1077+ value => Err ( Error :: InvalidArgument ( format ! (
1078+ "invalid argument {} for 'reflink'" ,
1079+ value
1080+ ) ) ) ,
1081+ }
1082+ } else {
1083+ #[ cfg( any( target_os = "linux" , target_os = "android" , target_os = "macos" ) ) ]
1084+ {
1085+ Ok ( ReflinkMode :: Auto )
1086+ }
1087+ #[ cfg( not( any( target_os = "linux" , target_os = "android" , target_os = "macos" ) ) ) ]
1088+ {
1089+ Ok ( ReflinkMode :: Never )
1090+ }
1091+ }
1092+ }
1093+
1094+ /// Determines the sparse mode based on the command line matches.
1095+ fn determine_sparse_mode ( matches : & ArgMatches ) -> CopyResult < SparseMode > {
1096+ if let Some ( val) = matches. get_one :: < String > ( options:: SPARSE ) {
1097+ match val. as_str ( ) {
1098+ "always" => Ok ( SparseMode :: Always ) ,
1099+ "auto" => Ok ( SparseMode :: Auto ) ,
1100+ "never" => Ok ( SparseMode :: Never ) ,
1101+ _ => Err ( Error :: InvalidArgument ( format ! (
1102+ "invalid argument {} for 'sparse'" ,
1103+ val
1104+ ) ) ) ,
1105+ }
1106+ } else {
1107+ Ok ( SparseMode :: Auto )
1108+ }
1109+ }
10581110 /// Whether to force overwriting the destination file.
10591111 fn force ( & self ) -> bool {
10601112 matches ! ( self . overwrite, OverwriteMode :: Clobber ( ClobberMode :: Force ) )
0 commit comments