This is an automated email from the ASF dual-hosted git repository.

suyanhanx pushed a commit to branch cp-oss
in repository https://gitbox.apache.org/repos/asf/incubator-opendal.git

commit a7fe7e6211d42fdbbd5a054badf8b90bc7d7ef74
Author: suyanhanx <[email protected]>
AuthorDate: Sat Apr 8 10:07:47 2023 +0800

    feat(oss): support copy
    
    Signed-off-by: suyanhanx <[email protected]>
---
 core/src/services/oss/backend.rs | 36 +++++++++++++++++++++++++++++++++++-
 1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/core/src/services/oss/backend.rs b/core/src/services/oss/backend.rs
index a1bfeacf..91b77ff4 100644
--- a/core/src/services/oss/backend.rs
+++ b/core/src/services/oss/backend.rs
@@ -53,6 +53,7 @@ use crate::*;
 ///
 /// - [x] read
 /// - [x] write
+/// - [x] copy
 /// - [x] list
 /// - [x] scan
 /// - [ ] presign
@@ -417,7 +418,7 @@ impl Accessor for OssBackend {
             .set_root(&self.root)
             .set_name(&self.bucket)
             .set_max_batch_operations(1000)
-            .set_capabilities(Read | Write | List | Scan | Presign | Batch)
+            .set_capabilities(Read | Write | Copy | List | Scan | Presign | 
Batch)
             .set_hints(ReadStreamable);
 
         am
@@ -475,6 +476,19 @@ impl Accessor for OssBackend {
         ))
     }
 
+    async fn copy(&self, from: &str, to: &str, _args: OpCopy) -> 
Result<RpCopy> {
+        let resp = self.oss_copy_object(from, to).await?;
+        let status = resp.status();
+
+        match status {
+            StatusCode::OK => {
+                resp.into_body().consume().await?;
+                Ok(RpCopy::default())
+            }
+            _ => Err(parse_error(resp).await?),
+        }
+    }
+
     async fn stat(&self, path: &str, _: OpStat) -> Result<RpStat> {
         if path == "/" {
             let m = Metadata::new(EntryMode::DIR);
@@ -756,6 +770,26 @@ impl OssBackend {
         self.client.send_async(req).await
     }
 
+    async fn oss_copy_object(&self, from: &str, to: &str) -> 
Result<Response<IncomingAsyncBody>> {
+        let source = build_abs_path(&self.root, from);
+        let target = build_abs_path(&self.root, to);
+
+        let url = format!(
+            "{}/{}",
+            self.get_endpoint(false),
+            percent_encode_path(&target)
+        );
+        let source = format!("{}/{}", self.bucket, 
percent_encode_path(&source));
+
+        let mut req = Request::put(&url)
+            .header("x-oss-copy-source", source)
+            .body(AsyncBody::Empty)
+            .map_err(new_request_build_error)?;
+
+        self.signer.sign(&mut req).map_err(new_request_sign_error)?;
+        self.client.send_async(req).await
+    }
+
     pub(super) async fn oss_list_object(
         &self,
         path: &str,

Reply via email to