xxchan commented on code in PR #6140:
URL: https://github.com/apache/opendal/pull/6140#discussion_r2083900794


##########
bin/oli/src/commands/cp.rs:
##########
@@ -84,28 +124,67 @@ impl CopyCmd {
             return Ok(());
         }
 
-        let dst_root = Path::new(&dst_path);
+        // Recursive copy: Ensure the base destination directory exists or 
create it.
+        // Note: final_dst_path here refers to the original dst_path if it was 
a dir or didn't exist.
+        match dst_op.stat(&final_dst_path).await {
+            Ok(meta) if meta.mode().is_dir() => {
+                // Base destination directory exists.
+            }
+            Ok(_) => {
+                bail!(
+                    "Recursive copy destination '{}' exists but is not a 
directory.",
+                    final_dst_path
+                );
+            }
+            Err(e) if e.kind() == ErrorKind::NotFound => {
+                dst_op.create_dir(&final_dst_path).await?;
+            }
+            Err(e) => {
+                // Another error occurred trying to stat the base destination.
+                return Err(e.into());
+            }
+        }
+
+        // Proceed with recursive copy logic. dst_root is the target directory.
+        let dst_root = Path::new(&final_dst_path);
         let mut ds = src_op.lister_with(&src_path).recursive(true).await?;
-        let prefix = src_path.strip_prefix('/').unwrap_or(src_path.as_str());
+        let prefix = src_path.strip_prefix('/').unwrap_or(&src_path); // Using 
original logic for now

Review Comment:
   What does the comment mean here :eyes:



##########
bin/oli/src/commands/cp.rs:
##########
@@ -84,28 +124,67 @@ impl CopyCmd {
             return Ok(());
         }
 
-        let dst_root = Path::new(&dst_path);
+        // Recursive copy: Ensure the base destination directory exists or 
create it.
+        // Note: final_dst_path here refers to the original dst_path if it was 
a dir or didn't exist.
+        match dst_op.stat(&final_dst_path).await {
+            Ok(meta) if meta.mode().is_dir() => {
+                // Base destination directory exists.
+            }
+            Ok(_) => {
+                bail!(
+                    "Recursive copy destination '{}' exists but is not a 
directory.",
+                    final_dst_path
+                );
+            }
+            Err(e) if e.kind() == ErrorKind::NotFound => {
+                dst_op.create_dir(&final_dst_path).await?;
+            }
+            Err(e) => {
+                // Another error occurred trying to stat the base destination.
+                return Err(e.into());
+            }
+        }
+
+        // Proceed with recursive copy logic. dst_root is the target directory.
+        let dst_root = Path::new(&final_dst_path);
         let mut ds = src_op.lister_with(&src_path).recursive(true).await?;
-        let prefix = src_path.strip_prefix('/').unwrap_or(src_path.as_str());
+        let prefix = src_path.strip_prefix('/').unwrap_or(&src_path); // Using 
original logic for now
+
         while let Some(de) = ds.try_next().await? {
             let meta = de.metadata();
+            let depath = de.path();
+
+            // Calculate relative path from the source root
+            let relative_path = depath.strip_prefix(prefix).ok_or_else(|| {
+                anyhow::anyhow!(
+                    "Internal error: Failed to strip prefix '{}' from path 
'{}'",
+                    prefix,
+                    depath
+                )
+            })?;

Review Comment:
   nit: use `.with_context()` instead of `ok_or_else`?



##########
bin/oli/tests/cp.rs:
##########
@@ -61,3 +61,40 @@ async fn test_cp_for_path_in_current_dir() -> Result<()> {
     assert_eq!(expect, actual);
     Ok(())
 }
+
+#[tokio::test]
+async fn test_cp_file_to_existing_dir() -> Result<()> {

Review Comment:
   Also add a test for recursive copy?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscr...@opendal.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to