From 9f0eb2a85f72c802ad5d97785fd0c86e3b84db47 Mon Sep 17 00:00:00 2001 From: Mateusz Wykurz Date: Fri, 11 Oct 2024 14:21:41 -0600 Subject: [PATCH] Provide suggestions for when users are failing to copy because the destination already exists --- rcp/src/main.rs | 23 ++++++++++++++++++----- rlink/src/main.rs | 10 +++++++++- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/rcp/src/main.rs b/rcp/src/main.rs index 76d3971..014a32f 100644 --- a/rcp/src/main.rs +++ b/rcp/src/main.rs @@ -6,7 +6,8 @@ use tracing::{event, instrument, Level}; #[derive(StructOpt, Debug, Clone)] #[structopt( name = "rcp", - about = "`rcp` is a tool for copying files similar to `cp` but generally MUCH faster when dealing with a large number of files. + about = "`rcp` is a tool for copying files similar to `cp` but generally MUCH faster when dealing with a large \ + number of files. Inspired by tools like `dsync`(1) and `pcp`(2). @@ -18,7 +19,8 @@ struct Args { #[structopt(short, long)] overwrite: bool, - /// Comma separated list of file attributes to compare when when deciding if files are "identical", used with --overwrite flag. + /// Comma separated list of file attributes to compare when when deciding if files are "identical", used with + /// --overwrite flag. /// Options are: uid, gid, mode, size, mtime, ctime #[structopt(long, default_value = "size,mtime")] overwrite_compare: String, @@ -96,7 +98,8 @@ struct Args { #[structopt(long, default_value = "0")] max_blocking_threads: usize, - /// Maximum number of open files, 0 means no limit, leaving unspecified means using 80% of max open files system limit + /// Maximum number of open files, 0 means no limit, leaving unspecified means using 80% of max open files system + /// limit #[structopt(long)] max_open_files: Option, @@ -116,7 +119,8 @@ async fn async_main(args: Args) -> Result { for src in src_strings { if src == "." || src.ends_with("/.") { return Err(anyhow!( - "expanding source directory ({:?}) using dot operator ('.') is not supported, please use absolute path or '*' instead", + "expanding source directory ({:?}) using dot operator ('.') is not supported, please use absolute \ + path or '*' instead", std::path::PathBuf::from(src)) ); } @@ -139,7 +143,16 @@ async fn async_main(args: Args) -> Result { } else { if src_strings.len() > 1 { return Err(anyhow!( - "Multiple sources can only be copied to a directory; if this is your intent follow the destination path with a trailing slash" + "Multiple sources can only be copied INTO to a directory; if this is your intent follow the \ + destination path with a trailing slash" + )); + } + let dst_path = std::path::PathBuf::from(dst_string); + if dst_path.exists() && !args.overwrite { + return Err(anyhow!( + "Destination path {dst_path:?} already exists! \n\ + If you want to copy INTO it then follow the destination path with a trailing slash (/) or use \ + --overwrite if you want to overwrite it" )); } assert_eq!(src_strings.len(), 1); diff --git a/rlink/src/main.rs b/rlink/src/main.rs index 25050e2..8846bdd 100644 --- a/rlink/src/main.rs +++ b/rlink/src/main.rs @@ -119,7 +119,15 @@ async fn async_main(args: Args) -> Result { let dst_dir = std::path::PathBuf::from(args.dst); dst_dir.join(src_file) } else { - std::path::PathBuf::from(args.dst) + let dst_path = std::path::PathBuf::from(args.dst); + if dst_path.exists() && !args.overwrite { + return Err(anyhow!( + "Destination path {dst_path:?} already exists! \n\ + If you want to copy INTO it then follow the destination path with a trailing slash (/) or use \ + --overwrite if you want to overwrite it" + )); + } + dst_path }; let result = common::link( &args.src,