This is an automated email from the ASF dual-hosted git repository.
xuanwo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-opendal.git
The following commit(s) were added to refs/heads/main by this push:
new 1ae7a401 feat(oli): implement `oli cp -r` (#1787)
1ae7a401 is described below
commit 1ae7a40134f16e4e128bf94d975f2fbc51a05fe4
Author: Jian Zeng <[email protected]>
AuthorDate: Tue Mar 28 17:20:06 2023 +0800
feat(oli): implement `oli cp -r` (#1787)
Signed-off-by: Jian Zeng <[email protected]>
---
bin/oli/src/commands/cp.rs | 53 +++++++++++++++++++++++++++++++++++-----------
1 file changed, 41 insertions(+), 12 deletions(-)
diff --git a/bin/oli/src/commands/cp.rs b/bin/oli/src/commands/cp.rs
index b26c46c9..90aa7403 100644
--- a/bin/oli/src/commands/cp.rs
+++ b/bin/oli/src/commands/cp.rs
@@ -15,13 +15,12 @@
// specific language governing permissions and limitations
// under the License.
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
-use anyhow::anyhow;
-use anyhow::Result;
-use clap::Arg;
-use clap::ArgMatches;
-use clap::Command;
+use anyhow::{anyhow, Result};
+use clap::{Arg, ArgAction, ArgMatches, Command};
+use futures::TryStreamExt;
+use opendal::Metakey;
use crate::config::Config;
@@ -30,6 +29,7 @@ pub async fn main(args: &ArgMatches) -> Result<()> {
.get_one::<PathBuf>("config")
.ok_or_else(|| anyhow!("missing config path"))?;
let cfg = Config::load(config_path)?;
+ let recursive = args.get_flag("recursive");
let src = args
.get_one::<String>("source")
@@ -41,13 +41,34 @@ pub async fn main(args: &ArgMatches) -> Result<()> {
.ok_or_else(|| anyhow!("missing target"))?;
let (dst_op, dst_path) = cfg.parse_location(dst)?;
- let mut dst_w = dst_op.writer(&dst_path).await?;
+ if !recursive {
+ let mut dst_w = dst_op.writer(&dst_path).await?;
+ let reader = src_op.reader(&src_path).await?;
+ let buf_reader = futures::io::BufReader::with_capacity(8 * 1024 *
1024, reader);
+ futures::io::copy_buf(buf_reader, &mut dst_w).await?;
+ // flush data
+ dst_w.close().await?;
+ return Ok(());
+ }
- let reader = src_op.reader(&src_path).await?;
- let buf_reader = futures::io::BufReader::with_capacity(8 * 1024 * 1024,
reader);
- futures::io::copy_buf(buf_reader, &mut dst_w).await?;
- // flush data
- dst_w.close().await?;
+ let dst_root = Path::new(&dst_path);
+ let mut ds = src_op.scan(&src_path).await?;
+ while let Some(de) = ds.try_next().await? {
+ let meta = src_op.metadata(&de, Metakey::Mode).await?;
+ if meta.mode().is_dir() {
+ continue;
+ }
+
+ let fp = de.path().strip_prefix(&src_path).expect("invalid path");
+ let reader = src_op.reader(de.path()).await?;
+ let buf_reader = futures::io::BufReader::with_capacity(8 * 1024 *
1024, reader);
+
+ let mut writer =
dst_op.writer(&dst_root.join(fp).to_string_lossy()).await?;
+
+ println!("Copying {}", de.path());
+ futures::io::copy_buf(buf_reader, &mut writer).await?;
+ writer.close().await?;
+ }
Ok(())
}
@@ -55,4 +76,12 @@ pub fn cli(cmd: Command) -> Command {
cmd.about("copy")
.arg(Arg::new("source").required(true))
.arg(Arg::new("destination").required(true))
+ .arg(
+ Arg::new("recursive")
+ .required(false)
+ .long("recursive")
+ .short('r')
+ .help("Copy files under source recursively to destination")
+ .action(ArgAction::SetTrue),
+ )
}