Skip to content

Commit df68d91

Browse files
committed
cp: split the function from_matches
1 parent f76b53d commit df68d91

File tree

1 file changed

+113
-61
lines changed

1 file changed

+113
-61
lines changed

src/uu/cp/src/cp.rs

Lines changed: 113 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -888,6 +888,7 @@ impl Attributes {
888888

889889
impl 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

Comments
 (0)