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

xuanwo pushed a commit to branch fix-list-root
in repository https://gitbox.apache.org/repos/asf/incubator-opendal.git

commit 87f2370f1a684930d27133884344620da9ac264a
Author: Xuanwo <[email protected]>
AuthorDate: Tue Dec 26 11:40:24 2023 +0800

    fix: List root should not return itself
    
    Signed-off-by: Xuanwo <[email protected]>
---
 core/src/services/azblob/lister.rs |  2 +-
 core/src/services/cos/lister.rs    |  2 +-
 core/src/services/gcs/lister.rs    |  2 +-
 core/src/services/obs/lister.rs    |  2 +-
 core/src/services/oss/lister.rs    |  2 +-
 core/src/services/s3/lister.rs     |  2 +-
 core/tests/behavior/list.rs        | 38 +++++++++++++++++++++++++++++++++++++-
 7 files changed, 43 insertions(+), 7 deletions(-)

diff --git a/core/src/services/azblob/lister.rs 
b/core/src/services/azblob/lister.rs
index 6760cecb2..eeded0499 100644
--- a/core/src/services/azblob/lister.rs
+++ b/core/src/services/azblob/lister.rs
@@ -89,7 +89,7 @@ impl oio::PageList for AzblobLister {
             let path = build_rel_path(&self.core.root, &object.name);
 
             // azblob could return the dir itself in contents.
-            if path == self.path {
+            if path == self.path || path.is_empty() {
                 continue;
             }
 
diff --git a/core/src/services/cos/lister.rs b/core/src/services/cos/lister.rs
index 6a8f62907..f289b3383 100644
--- a/core/src/services/cos/lister.rs
+++ b/core/src/services/cos/lister.rs
@@ -85,7 +85,7 @@ impl oio::PageList for CosLister {
         for object in output.contents {
             let path = build_rel_path(&self.core.root, &object.key);
 
-            if path == self.path {
+            if path == self.path || path.is_empty() {
                 continue;
             }
 
diff --git a/core/src/services/gcs/lister.rs b/core/src/services/gcs/lister.rs
index c7da1a86e..0a0180198 100644
--- a/core/src/services/gcs/lister.rs
+++ b/core/src/services/gcs/lister.rs
@@ -105,7 +105,7 @@ impl oio::PageList for GcsLister {
         for object in output.items {
             // exclude the inclusive start_after itself
             let path = build_rel_path(&self.core.root, &object.name);
-            if path == self.path {
+            if path == self.path || path.is_empty() {
                 continue;
             }
             if self.start_after.as_ref() == Some(&path) {
diff --git a/core/src/services/obs/lister.rs b/core/src/services/obs/lister.rs
index 3a9a5b4e7..ead6bbbea 100644
--- a/core/src/services/obs/lister.rs
+++ b/core/src/services/obs/lister.rs
@@ -87,7 +87,7 @@ impl oio::PageList for ObsLister {
 
         for object in output.contents {
             let path = build_rel_path(&self.core.root, &object.key);
-            if path == self.path {
+            if path == self.path || path.is_empty() {
                 continue;
             }
 
diff --git a/core/src/services/oss/lister.rs b/core/src/services/oss/lister.rs
index 0e8864068..926946a61 100644
--- a/core/src/services/oss/lister.rs
+++ b/core/src/services/oss/lister.rs
@@ -96,7 +96,7 @@ impl oio::PageList for OssLister {
 
         for object in output.contents {
             let path = build_rel_path(&self.core.root, &object.key);
-            if path == self.path {
+            if path == self.path || path.is_empty() {
                 continue;
             }
             if self.start_after.as_ref() == Some(&path) {
diff --git a/core/src/services/s3/lister.rs b/core/src/services/s3/lister.rs
index f0712e650..569d83ebe 100644
--- a/core/src/services/s3/lister.rs
+++ b/core/src/services/s3/lister.rs
@@ -116,7 +116,7 @@ impl oio::PageList for S3Lister {
             let path = build_rel_path(&self.core.root, &object.key);
 
             // s3 could return the dir itself in contents.
-            if path == self.path {
+            if path == self.path || path.is_empty() {
                 continue;
             }
 
diff --git a/core/tests/behavior/list.rs b/core/tests/behavior/list.rs
index c29f0e2dc..1123dfa83 100644
--- a/core/tests/behavior/list.rs
+++ b/core/tests/behavior/list.rs
@@ -243,15 +243,51 @@ pub async fn test_list_empty_dir(op: Operator) -> 
Result<()> {
 
     op.create_dir(&dir).await.expect("write must succeed");
 
+    // List "dir/" should return empty object.
     let mut obs = op.lister(&dir).await?;
     let mut objects = HashMap::new();
     while let Some(de) = obs.try_next().await? {
         objects.insert(de.path().to_string(), de);
     }
-    debug!("got objects: {:?}", objects);
+    assert_eq!(objects.len(), 0, "dir should only return empty");
 
+    // List "dir" should return "dir/".
+    let mut obs = op.lister(&dir.trim_end_matches('/')).await?;
+    let mut objects = HashMap::new();
+    while let Some(de) = obs.try_next().await? {
+        objects.insert(de.path().to_string(), de);
+    }
+    assert_eq!(objects.len(), 1, "dir should only return empty");
+    assert_eq!(
+        objects[&dir].metadata().mode(),
+        EntryMode::DIR,
+        "given dir should exist and must be dir"
+    );
+
+    // List "dir/" should return empty object.
+    let mut obs = op.lister_with(&dir).recursive(true).await?;
+    let mut objects = HashMap::new();
+    while let Some(de) = obs.try_next().await? {
+        objects.insert(de.path().to_string(), de);
+    }
     assert_eq!(objects.len(), 0, "dir should only return empty");
 
+    // List "dir" should return "dir/".
+    let mut obs = op
+        .lister_with(&dir.trim_end_matches('/'))
+        .recursive(true)
+        .await?;
+    let mut objects = HashMap::new();
+    while let Some(de) = obs.try_next().await? {
+        objects.insert(de.path().to_string(), de);
+    }
+    assert_eq!(objects.len(), 1, "dir should only return empty");
+    assert_eq!(
+        objects[&dir].metadata().mode(),
+        EntryMode::DIR,
+        "given dir should exist and must be dir"
+    );
+
     op.delete(&dir).await.expect("delete must succeed");
     Ok(())
 }

Reply via email to