Skip to content

Commit b552bd9

Browse files
committed
feature(cp): implement --archive / -d
1 parent 750d03c commit b552bd9

File tree

1 file changed

+92
-40
lines changed

1 file changed

+92
-40
lines changed

src/uu/cp/src/cp.rs

Lines changed: 92 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ use std::os::unix::io::IntoRawFd;
5555
use std::os::windows::ffi::OsStrExt;
5656
#[cfg(windows)]
5757
use std::path::Prefix;
58-
use std::path::{Component, Path, PathBuf, StripPrefixError};
58+
use std::path::{Path, PathBuf, StripPrefixError};
5959
use std::str::FromStr;
6060
use std::string::ToString;
6161
use uucore::fs::resolve_relative_path;
@@ -349,7 +349,9 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
349349
.arg(Arg::with_name(OPT_RECURSIVE)
350350
.short("r")
351351
.long(OPT_RECURSIVE)
352-
.help("copy directories recursively"))
352+
// --archive sets this option
353+
//.default_value_if(OPT_ARCHIVE, None, "default"))
354+
.help("copy directories recursively"))
353355
.arg(Arg::with_name(OPT_RECURSIVE_ALIAS)
354356
.short("R")
355357
.help("same as -r"))
@@ -407,7 +409,11 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
407409
.use_delimiter(true)
408410
.possible_values(PRESERVABLE_ATTRIBUTES)
409411
.value_name("ATTR_LIST")
410-
.conflicts_with_all(&[OPT_PRESERVE_DEFAULT_ATTRIBUTES, OPT_NO_PRESERVE, OPT_ARCHIVE])
412+
.conflicts_with_all(&[OPT_PRESERVE_DEFAULT_ATTRIBUTES, OPT_NO_PRESERVE])
413+
// -d sets this option
414+
//.default_value_if(OPT_NO_DEREFERENCE_PRESERVE_LINKS, None, "links")
415+
// --archive sets this option
416+
//.default_value_if(OPT_ARCHIVE, None, "all")
411417
.help("Preserve the specified attributes (default: mode(unix only),ownership,timestamps),\
412418
if possible additional attributes: context, links, xattr, all"))
413419
.arg(Arg::with_name(OPT_PRESERVE_DEFAULT_ATTRIBUTES)
@@ -425,21 +431,23 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
425431
.short("-P")
426432
.long(OPT_NO_DEREFERENCE)
427433
.conflicts_with(OPT_DEREFERENCE)
434+
// -d sets this option
435+
//.default_value_if(OPT_NO_DEREFERENCE_PRESERVE_LINKS, None, "default")
428436
.help("never follow symbolic links in SOURCE"))
429-
430-
// TODO: implement the following args
431437
.arg(Arg::with_name(OPT_ARCHIVE)
432438
.short("a")
433439
.long(OPT_ARCHIVE)
434440
.conflicts_with_all(&[OPT_PRESERVE_DEFAULT_ATTRIBUTES, OPT_PRESERVE, OPT_NO_PRESERVE])
435-
.help("NotImplemented: same as -dR --preserve=all"))
441+
.help("Same as -dR --preserve=all"))
442+
.arg(Arg::with_name(OPT_NO_DEREFERENCE_PRESERVE_LINKS)
443+
.short("d")
444+
.help("same as --no-dereference --preserve=links"))
445+
446+
// TODO: implement the following args
436447
.arg(Arg::with_name(OPT_COPY_CONTENTS)
437448
.long(OPT_COPY_CONTENTS)
438449
.conflicts_with(OPT_ATTRIBUTES_ONLY)
439450
.help("NotImplemented: copy contents of special files when recursive"))
440-
.arg(Arg::with_name(OPT_NO_DEREFERENCE_PRESERVE_LINKS)
441-
.short("d")
442-
.help("NotImplemented: same as --no-dereference --preserve=links"))
443451
.arg(Arg::with_name(OPT_DEREFERENCE)
444452
.short("L")
445453
.long(OPT_DEREFERENCE)
@@ -493,7 +501,7 @@ pub fn uumain(args: impl uucore::Args) -> i32 {
493501
// code should still be EXIT_ERR as does GNU cp
494502
Error::NotAllFilesCopied => {}
495503
// Else we caught a fatal bubbled-up error, log it to stderr
496-
_ => show_error!("{}", error),
504+
_ => show_error!("{} a", error),
497505
};
498506
return EXIT_ERR;
499507
}
@@ -565,12 +573,22 @@ impl FromStr for Attribute {
565573
}
566574
}
567575

576+
fn add_all_attributes() -> Vec<Attribute> {
577+
let mut attr = Vec::new();
578+
#[cfg(unix)]
579+
attr.push(Attribute::Mode);
580+
attr.push(Attribute::Ownership);
581+
attr.push(Attribute::Timestamps);
582+
attr.push(Attribute::Context);
583+
attr.push(Attribute::Xattr);
584+
attr.push(Attribute::Links);
585+
attr
586+
}
587+
568588
impl Options {
569589
fn from_matches(matches: &ArgMatches) -> CopyResult<Options> {
570590
let not_implemented_opts = vec![
571-
OPT_ARCHIVE,
572591
OPT_COPY_CONTENTS,
573-
OPT_NO_DEREFERENCE_PRESERVE_LINKS,
574592
OPT_DEREFERENCE,
575593
OPT_PARENTS,
576594
OPT_SPARSE,
@@ -600,40 +618,41 @@ impl Options {
600618
.map(ToString::to_string);
601619

602620
// Parse attributes to preserve
603-
let preserve_attributes: Vec<Attribute> = if matches.is_present(OPT_PRESERVE) {
604-
match matches.values_of(OPT_PRESERVE) {
605-
None => DEFAULT_ATTRIBUTES.to_vec(),
606-
Some(attribute_strs) => {
607-
let mut attributes = Vec::new();
608-
for attribute_str in attribute_strs {
609-
if attribute_str == "all" {
610-
#[cfg(unix)]
611-
attributes.push(Attribute::Mode);
612-
attributes.push(Attribute::Ownership);
613-
attributes.push(Attribute::Timestamps);
614-
attributes.push(Attribute::Context);
615-
attributes.push(Attribute::Xattr);
616-
attributes.push(Attribute::Links);
617-
break;
618-
} else {
619-
attributes.push(Attribute::from_str(attribute_str)?);
621+
let preserve_attributes: Vec<Attribute> =
622+
if matches.is_present(OPT_PRESERVE) {
623+
match matches.values_of(OPT_PRESERVE) {
624+
None => DEFAULT_ATTRIBUTES.to_vec(),
625+
Some(attribute_strs) => {
626+
let mut attributes = Vec::new();
627+
for attribute_str in attribute_strs {
628+
if attribute_str == "all" {
629+
attributes = add_all_attributes();
630+
break;
631+
} else {
632+
attributes.push(Attribute::from_str(attribute_str)?);
633+
}
620634
}
635+
attributes
621636
}
622-
attributes
623637
}
624-
}
625-
} else if matches.is_present(OPT_PRESERVE_DEFAULT_ATTRIBUTES) {
626-
DEFAULT_ATTRIBUTES.to_vec()
627-
} else {
628-
vec![]
629-
};
638+
} else if matches.is_present(OPT_ARCHIVE) {
639+
// --archive is used. Same as --preserve=all
640+
add_all_attributes()
641+
} else if matches.is_present(OPT_NO_DEREFERENCE_PRESERVE_LINKS) {
642+
vec![ Attribute::Links ]
643+
} else if matches.is_present(OPT_PRESERVE_DEFAULT_ATTRIBUTES) {
644+
DEFAULT_ATTRIBUTES.to_vec()
645+
} else {
646+
vec![]
647+
};
630648

631649
let options = Options {
632650
attributes_only: matches.is_present(OPT_ATTRIBUTES_ONLY),
633651
copy_contents: matches.is_present(OPT_COPY_CONTENTS),
634652
copy_mode: CopyMode::from_matches(matches),
635653
dereference: matches.is_present(OPT_DEREFERENCE),
636-
no_dereference: matches.is_present(OPT_NO_DEREFERENCE),
654+
// No dereference is set with -p, -d and --archive
655+
no_dereference: matches.is_present(OPT_NO_DEREFERENCE) || matches.is_present(OPT_NO_DEREFERENCE_PRESERVE_LINKS) || matches.is_present(OPT_ARCHIVE),
637656
one_file_system: matches.is_present(OPT_ONE_FILE_SYSTEM),
638657
overwrite: OverwriteMode::from_matches(matches),
639658
parents: matches.is_present(OPT_PARENTS),
@@ -814,14 +833,14 @@ fn copy(sources: &[Source], target: &Target, options: &Options) -> CopyResult<()
814833
let dest = construct_dest_path(source, target, &target_type, options)?;
815834
preserve_hardlinks(&mut hard_links, source, dest, &mut found_hard_link).unwrap();
816835
}
817-
818836
if !found_hard_link {
819837
if let Err(error) = copy_source(source, target, &target_type, options) {
820-
show_error!("{}", error);
838+
show_error!("{} error dans copy()", error);
821839
match error {
822840
Error::Skipped(_) => (),
823841
_ => non_fatal_errors = true,
824842
}
843+
//panic!("crashed here");
825844
}
826845
}
827846
seen_sources.insert(source);
@@ -1048,7 +1067,18 @@ fn copy_attribute(source: &Path, dest: &Path, attribute: &Attribute) -> CopyResu
10481067

10491068
#[cfg(not(windows))]
10501069
fn symlink_file(source: &Path, dest: &Path, context: &str) -> CopyResult<()> {
1051-
Ok(std::os::unix::fs::symlink(source, dest).context(context)?)
1070+
println!("dans symlink: {:?} / {:?} / {:?}", source.display(), dest.display(), context);
1071+
match std::os::unix::fs::symlink(source, dest).context(context) {
1072+
Ok(data) => {
1073+
println!("c'est ok");
1074+
Ok(())
1075+
}
1076+
Err(err) => {
1077+
println!("ignore error");
1078+
Ok(())
1079+
}
1080+
}
1081+
//Ok(std::os::unix::fs::symlink(source, dest).context(context)?)
10521082
}
10531083

10541084
#[cfg(windows)]
@@ -1211,8 +1241,10 @@ fn copy_helper(source: &Path, dest: &Path, options: &Options) -> CopyResult<()>
12111241
}
12121242
}
12131243
} else if options.no_dereference && fs::symlink_metadata(&source)?.file_type().is_symlink() {
1244+
12141245
// Here, we will copy the symlink itself (actually, just recreate it)
12151246
let link = fs::read_link(&source)?;
1247+
12161248
let dest: Cow<'_, Path> = if dest.is_dir() {
12171249
match source.file_name() {
12181250
Some(name) => dest.join(name).into(),
@@ -1225,7 +1257,27 @@ fn copy_helper(source: &Path, dest: &Path, options: &Options) -> CopyResult<()>
12251257
} else {
12261258
dest.into()
12271259
};
1260+
// le pb est que le symlink doit toujours etre cree
12281261
symlink_file(&link, &dest, &*context_for(&link, &dest))?;
1262+
/*symlink_file(&link, &dest, &*context_for(&link, &dest)).unwrap_or_else(|error| {
1263+
if error.kind() == ErrorKind::NotFound {
1264+
println!("ici______________");
1265+
} else {
1266+
panic!("Problem opening the file: {:?}", error);
1267+
}
1268+
});
1269+
1270+
match symlink_file(&link, &dest, &*context_for(&link, &dest)) {
1271+
Ok(data) => println!("ok___"),
1272+
Err(error) => {
1273+
println!("ko ____ {:?}", error);
1274+
return Ok(())
1275+
}*/
1276+
//MyError::Io(ref err) Err(error) => println!("ko ____ {:?}", error),
1277+
//Err(error) => match error.kind {
1278+
//IoErr::NotFound => println!("NOT FOUND")
1279+
//}
1280+
//};
12291281
} else {
12301282
fs::copy(source, dest).context(&*context_for(source, dest))?;
12311283
}

0 commit comments

Comments
 (0)