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();
