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

meteorgan pushed a commit to branch azdls-recursive-deletion
in repository https://gitbox.apache.org/repos/asf/opendal.git

commit d09adefeea6b77f1f28524109f7fddd8f106b506
Author: meteorgan <[email protected]>
AuthorDate: Sat Jan 10 23:34:18 2026 +0800

    feat(services/azdls): add recursive deletion for azdls
---
 core/services/azdls/src/backend.rs |  3 +++
 core/services/azdls/src/core.rs    | 54 ++++++++++++++++++++++++++++++++++++++
 core/services/azdls/src/deleter.rs |  8 ++++--
 3 files changed, 63 insertions(+), 2 deletions(-)

diff --git a/core/services/azdls/src/backend.rs 
b/core/services/azdls/src/backend.rs
index 19ef30188..2892cd69d 100644
--- a/core/services/azdls/src/backend.rs
+++ b/core/services/azdls/src/backend.rs
@@ -282,7 +282,10 @@ impl Builder for AzdlsBuilder {
                             write_with_if_not_exists: true,
 
                             create_dir: true,
+
                             delete: true,
+                            delete_with_recursive: true,
+
                             rename: true,
 
                             list: true,
diff --git a/core/services/azdls/src/core.rs b/core/services/azdls/src/core.rs
index f40cfc636..bd286653c 100644
--- a/core/services/azdls/src/core.rs
+++ b/core/services/azdls/src/core.rs
@@ -366,6 +366,60 @@ impl AzdlsCore {
         self.send(req).await
     }
 
+    pub async fn azdls_recursive_delete(&self, path: &str) -> 
Result<Response<Buffer>> {
+        const X_MS_CONTINUATION: &str = "x-ms-continuation";
+
+        let p = build_abs_path(&self.root, path)
+            .trim_end_matches('/')
+            .to_string();
+
+        let base = format!(
+            "{}/{}/{}",
+            self.endpoint,
+            self.filesystem,
+            percent_encode_path(&p)
+        );
+
+        let mut continuation = String::new();
+
+        loop {
+            let mut url = QueryPairsWriter::new(&base)
+                .push("recursive", "true")
+                .push("paginated", "true");
+
+            if !continuation.is_empty() {
+                url = url.push("continuation", 
&percent_encode_path(&continuation));
+            }
+
+            let mut req = Request::delete(url.finish())
+                .extension(Operation::Delete)
+                .body(Buffer::new())
+                .map_err(new_request_build_error)?;
+
+            self.sign(&mut req).await?;
+            let resp = self.send(req).await?;
+
+            let status = resp.status();
+            match status {
+                StatusCode::OK | StatusCode::ACCEPTED | StatusCode::NOT_FOUND 
=> {}
+                _ => return Err(parse_error(resp)),
+            }
+
+            let next = resp
+                .headers()
+                .get(X_MS_CONTINUATION)
+                .and_then(|v| v.to_str().ok())
+                .unwrap_or_default()
+                .trim();
+
+            if next.is_empty() {
+                return Ok(resp);
+            }
+
+            continuation = next.to_string();
+        }
+    }
+
     pub async fn azdls_list(
         &self,
         path: &str,
diff --git a/core/services/azdls/src/deleter.rs 
b/core/services/azdls/src/deleter.rs
index f90c87c8a..56dc359be 100644
--- a/core/services/azdls/src/deleter.rs
+++ b/core/services/azdls/src/deleter.rs
@@ -35,8 +35,12 @@ impl AzdlsDeleter {
 }
 
 impl oio::OneShotDelete for AzdlsDeleter {
-    async fn delete_once(&self, path: String, _: OpDelete) -> Result<()> {
-        let resp = self.core.azdls_delete(&path).await?;
+    async fn delete_once(&self, path: String, args: OpDelete) -> Result<()> {
+        let resp = if args.recursive() {
+            self.core.azdls_recursive_delete(&path).await?
+        } else {
+            self.core.azdls_delete(&path).await?
+        };
 
         let status = resp.status();
 

Reply via email to