Skip to content

Commit b49fac3

Browse files
committed
cp: gnu test case preserve-mode fix
1 parent 6adf07e commit b49fac3

File tree

1 file changed

+97
-41
lines changed

1 file changed

+97
-41
lines changed

src/uu/cp/src/cp.rs

Lines changed: 97 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -556,11 +556,6 @@ pub fn uu_app() -> Command {
556556
.num_args(0..)
557557
.require_equals(true)
558558
.value_name("ATTR_LIST")
559-
.overrides_with_all([
560-
options::ARCHIVE,
561-
options::PRESERVE_DEFAULT_ATTRIBUTES,
562-
options::NO_PRESERVE,
563-
])
564559
// -d sets this option
565560
// --archive sets this option
566561
.help(
@@ -572,19 +567,18 @@ pub fn uu_app() -> Command {
572567
Arg::new(options::PRESERVE_DEFAULT_ATTRIBUTES)
573568
.short('p')
574569
.long(options::PRESERVE_DEFAULT_ATTRIBUTES)
575-
.overrides_with_all([options::PRESERVE, options::NO_PRESERVE, options::ARCHIVE])
576570
.help("same as --preserve=mode,ownership(unix only),timestamps")
577571
.action(ArgAction::SetTrue),
578572
)
579573
.arg(
580574
Arg::new(options::NO_PRESERVE)
581575
.long(options::NO_PRESERVE)
576+
.action(ArgAction::Append)
577+
.use_value_delimiter(true)
578+
.value_parser(ShortcutValueParser::new(PRESERVABLE_ATTRIBUTES))
579+
.num_args(0..)
580+
.require_equals(true)
582581
.value_name("ATTR_LIST")
583-
.overrides_with_all([
584-
options::PRESERVE_DEFAULT_ATTRIBUTES,
585-
options::PRESERVE,
586-
options::ARCHIVE,
587-
])
588582
.help("don't preserve the specified attributes"),
589583
)
590584
.arg(
@@ -621,11 +615,6 @@ pub fn uu_app() -> Command {
621615
Arg::new(options::ARCHIVE)
622616
.short('a')
623617
.long(options::ARCHIVE)
624-
.overrides_with_all([
625-
options::PRESERVE_DEFAULT_ATTRIBUTES,
626-
options::PRESERVE,
627-
options::NO_PRESERVE,
628-
])
629618
.help("Same as -dR --preserve=all")
630619
.action(ArgAction::SetTrue),
631620
)
@@ -839,6 +828,42 @@ impl Attributes {
839828
}
840829
}
841830

831+
pub fn diff(self, other: &Self) -> Self {
832+
Self {
833+
#[cfg(unix)]
834+
ownership: if matches!(other.ownership, Preserve::Yes { .. }) {
835+
Preserve::No { explicit: true }
836+
} else {
837+
self.ownership
838+
},
839+
mode: if matches!(other.mode, Preserve::Yes { .. }) {
840+
Preserve::No { explicit: true }
841+
} else {
842+
self.mode
843+
},
844+
timestamps: if matches!(other.timestamps, Preserve::Yes { .. }) {
845+
Preserve::No { explicit: true }
846+
} else {
847+
self.timestamps
848+
},
849+
context: if matches!(other.context, Preserve::Yes { .. }) {
850+
Preserve::No { explicit: true }
851+
} else {
852+
self.context
853+
},
854+
links: if matches!(other.links, Preserve::Yes { .. }) {
855+
Preserve::No { explicit: true }
856+
} else {
857+
self.links
858+
},
859+
xattr: if matches!(other.xattr, Preserve::Yes { .. }) {
860+
Preserve::No { explicit: true }
861+
} else {
862+
self.xattr
863+
},
864+
}
865+
}
866+
842867
pub fn parse_iter<T>(values: impl Iterator<Item = T>) -> Result<Self, Error>
843868
where
844869
T: AsRef<str>,
@@ -926,34 +951,65 @@ impl Options {
926951
}
927952
};
928953

929-
// Parse attributes to preserve
930-
let mut attributes =
931-
if let Some(attribute_strs) = matches.get_many::<String>(options::PRESERVE) {
932-
if attribute_strs.len() == 0 {
933-
Attributes::DEFAULT
934-
} else {
935-
Attributes::parse_iter(attribute_strs)?
954+
let mut overiding_priority = [
955+
options::ARCHIVE,
956+
options::PRESERVE,
957+
options::NO_PRESERVE,
958+
options::PRESERVE_DEFAULT_ATTRIBUTES,
959+
options::NO_DEREFERENCE_PRESERVE_LINKS,
960+
];
961+
overiding_priority.sort_by(|a, b| {
962+
let a_index = matches.indices_of(a).and_then(|v| v.last());
963+
let b_index = matches.indices_of(b).and_then(|v| v.last());
964+
match (a_index, b_index) {
965+
(None, None) => Ordering::Equal,
966+
(None, Some(_)) => Ordering::Greater,
967+
(Some(_), None) => Ordering::Less,
968+
(Some(a), Some(b)) => {
969+
if a < b {
970+
Ordering::Less
971+
} else {
972+
Ordering::Greater
973+
}
936974
}
937-
} else if matches.get_flag(options::ARCHIVE) {
938-
// --archive is used. Same as --preserve=all
939-
Attributes::ALL
940-
} else if matches.get_flag(options::NO_DEREFERENCE_PRESERVE_LINKS) {
941-
Attributes::LINKS
942-
} else if matches.get_flag(options::PRESERVE_DEFAULT_ATTRIBUTES) {
943-
Attributes::DEFAULT
944-
} else {
945-
Attributes::NONE
946-
};
975+
}
976+
});
947977

948-
// handling no-preserve options and adjusting the attributes
949-
if let Some(attribute_strs) = matches.get_many::<String>(options::NO_PRESERVE) {
950-
if attribute_strs.len() > 0 {
951-
let no_preserve_attributes = Attributes::parse_iter(attribute_strs)?;
952-
if matches!(no_preserve_attributes.links, Preserve::Yes { .. }) {
953-
attributes.links = Preserve::No { explicit: true };
954-
} else if matches!(no_preserve_attributes.mode, Preserve::Yes { .. }) {
955-
attributes.mode = Preserve::No { explicit: true };
978+
let mut attributes = Attributes::NONE;
979+
980+
for option in overiding_priority {
981+
match option {
982+
options::ARCHIVE => {
983+
if matches.get_flag(options::ARCHIVE) {
984+
attributes = Attributes::ALL;
985+
}
986+
}
987+
options::PRESERVE_DEFAULT_ATTRIBUTES => {
988+
if matches.get_flag(options::PRESERVE_DEFAULT_ATTRIBUTES) {
989+
attributes = attributes.union(&Attributes::DEFAULT);
990+
}
991+
}
992+
options::NO_DEREFERENCE_PRESERVE_LINKS => {
993+
if matches.get_flag(options::NO_DEREFERENCE_PRESERVE_LINKS) {
994+
attributes = attributes.union(&Attributes::LINKS);
995+
}
996+
}
997+
options::PRESERVE => {
998+
if let Some(attribute_strs) = matches.get_many::<String>(options::PRESERVE) {
999+
if attribute_strs.len() == 0 {
1000+
attributes = attributes.union(&Attributes::DEFAULT);
1001+
}
1002+
attributes = attributes.union(&Attributes::parse_iter(attribute_strs)?);
1003+
}
1004+
}
1005+
options::NO_PRESERVE => {
1006+
if let Some(attribute_strs) = matches.get_many::<String>(options::NO_PRESERVE) {
1007+
if attribute_strs.len() > 0 {
1008+
attributes = attributes.diff(&Attributes::parse_iter(attribute_strs)?);
1009+
}
1010+
}
9561011
}
1012+
_ => (),
9571013
}
9581014
}
9591015

0 commit comments

Comments
 (0)