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/opendal.git


The following commit(s) were added to refs/heads/main by this push:
     new 87e98ef7ca feat(fs): expose the metadata for fs services (#5005)
87e98ef7ca is described below

commit 87e98ef7ca163ffde83c14b3b1f072dcafa56274
Author: WenjunMin <[email protected]>
AuthorDate: Wed Aug 14 13:18:53 2024 +0800

    feat(fs): expose the metadata for fs services (#5005)
    
    * fix(fs): expose the metadata for fs services
    
    * fix
    
    * fix comments
    
    * clippy
    
    * fix
    
    * fix comments
    
    * fix comments
---
 core/src/services/fs/backend.rs |  8 ++--
 core/src/services/fs/lister.rs  | 88 ++++++++++++++++++++++++++++++-----------
 2 files changed, 68 insertions(+), 28 deletions(-)

diff --git a/core/src/services/fs/backend.rs b/core/src/services/fs/backend.rs
index 93bdd445ad..151e35aef6 100644
--- a/core/src/services/fs/backend.rs
+++ b/core/src/services/fs/backend.rs
@@ -353,7 +353,7 @@ impl Access for FsBackend {
         }
     }
 
-    async fn list(&self, path: &str, _: OpList) -> Result<(RpList, 
Self::Lister)> {
+    async fn list(&self, path: &str, arg: OpList) -> Result<(RpList, 
Self::Lister)> {
         let p = self.core.root.join(path.trim_end_matches('/'));
 
         let f = match tokio::fs::read_dir(&p).await {
@@ -367,7 +367,7 @@ impl Access for FsBackend {
             }
         };
 
-        let rd = FsLister::new(&self.core.root, f);
+        let rd = FsLister::new(&self.core.root, f, arg);
 
         Ok((RpList::default(), Some(rd)))
     }
@@ -523,7 +523,7 @@ impl Access for FsBackend {
         }
     }
 
-    fn blocking_list(&self, path: &str, _: OpList) -> Result<(RpList, 
Self::BlockingLister)> {
+    fn blocking_list(&self, path: &str, arg: OpList) -> Result<(RpList, 
Self::BlockingLister)> {
         let p = self.core.root.join(path.trim_end_matches('/'));
 
         let f = match std::fs::read_dir(p) {
@@ -537,7 +537,7 @@ impl Access for FsBackend {
             }
         };
 
-        let rd = FsLister::new(&self.core.root, f);
+        let rd = FsLister::new(&self.core.root, f, arg);
 
         Ok((RpList::default(), Some(rd)))
     }
diff --git a/core/src/services/fs/lister.rs b/core/src/services/fs/lister.rs
index eec0a4b8aa..229e7f7896 100644
--- a/core/src/services/fs/lister.rs
+++ b/core/src/services/fs/lister.rs
@@ -15,25 +15,27 @@
 // specific language governing permissions and limitations
 // under the License.
 
-use std::path::Path;
-use std::path::PathBuf;
-
 use crate::raw::*;
-use crate::EntryMode;
 use crate::Metadata;
 use crate::Result;
+use crate::{EntryMode, Metakey};
+use std::path::Path;
+use std::path::PathBuf;
 
 pub struct FsLister<P> {
     root: PathBuf,
 
     rd: P,
+
+    op: OpList,
 }
 
 impl<P> FsLister<P> {
-    pub fn new(root: &Path, rd: P) -> Self {
+    pub fn new(root: &Path, rd: P, arg: OpList) -> Self {
         Self {
             root: root.to_owned(),
             rd,
+            op: arg,
         }
     }
 }
@@ -49,8 +51,6 @@ impl oio::List for FsLister<tokio::fs::ReadDir> {
             return Ok(None);
         };
 
-        let ft = de.file_type().await.map_err(new_std_io_error)?;
-
         let entry_path = de.path();
         let rel_path = normalize_path(
             &entry_path
@@ -60,16 +60,39 @@ impl oio::List for FsLister<tokio::fs::ReadDir> {
                 .replace('\\', "/"),
         );
 
-        let d = if ft.is_file() {
-            oio::Entry::new(&rel_path, Metadata::new(EntryMode::FILE))
-        } else if ft.is_dir() {
+        let default_meta = self.op.metakey() == Metakey::Mode;
+
+        let metadata = if default_meta {
+            let ft = de.file_type().await.map_err(new_std_io_error)?;
+            if ft.is_file() {
+                Metadata::new(EntryMode::FILE)
+            } else if ft.is_dir() {
+                Metadata::new(EntryMode::DIR)
+            } else {
+                Metadata::new(EntryMode::Unknown)
+            }
+        } else {
+            let fs_meta = de.metadata().await.map_err(new_std_io_error)?;
+            let mut meta = if fs_meta.file_type().is_file() {
+                Metadata::new(EntryMode::FILE)
+            } else if fs_meta.file_type().is_dir() {
+                Metadata::new(EntryMode::DIR)
+            } else {
+                Metadata::new(EntryMode::Unknown)
+            };
+            meta.set_content_length(fs_meta.len());
+            
meta.set_last_modified(fs_meta.modified().map_err(new_std_io_error)?.into());
+            meta
+        };
+
+        let p = if metadata.is_dir() {
             // Make sure we are returning the correct path.
-            oio::Entry::new(&format!("{rel_path}/"), 
Metadata::new(EntryMode::DIR))
+            &format!("{rel_path}/")
         } else {
-            oio::Entry::new(&rel_path, Metadata::new(EntryMode::Unknown))
+            &rel_path
         };
 
-        Ok(Some(d))
+        Ok(Some(oio::Entry::new(p, metadata)))
     }
 }
 
@@ -89,21 +112,38 @@ impl oio::BlockingList for FsLister<std::fs::ReadDir> {
                 .replace('\\', "/"),
         );
 
-        // On Windows and most Unix platforms this function is free
-        // (no extra system calls needed), but some Unix platforms may
-        // require the equivalent call to symlink_metadata to learn about
-        // the target file type.
-        let file_type = de.file_type().map_err(new_std_io_error)?;
+        let default_meta = self.op.metakey() == Metakey::Mode;
+
+        let metadata = if default_meta {
+            let ft = de.file_type().map_err(new_std_io_error)?;
+            if ft.is_file() {
+                Metadata::new(EntryMode::FILE)
+            } else if ft.is_dir() {
+                Metadata::new(EntryMode::DIR)
+            } else {
+                Metadata::new(EntryMode::Unknown)
+            }
+        } else {
+            let fs_meta = de.metadata().map_err(new_std_io_error)?;
+            let mut meta = if fs_meta.file_type().is_file() {
+                Metadata::new(EntryMode::FILE)
+            } else if fs_meta.file_type().is_dir() {
+                Metadata::new(EntryMode::DIR)
+            } else {
+                Metadata::new(EntryMode::Unknown)
+            };
+            meta.set_content_length(fs_meta.len());
+            
meta.set_last_modified(fs_meta.modified().map_err(new_std_io_error)?.into());
+            meta
+        };
 
-        let entry = if file_type.is_file() {
-            oio::Entry::new(&rel_path, Metadata::new(EntryMode::FILE))
-        } else if file_type.is_dir() {
+        let p = if metadata.is_dir() {
             // Make sure we are returning the correct path.
-            oio::Entry::new(&format!("{rel_path}/"), 
Metadata::new(EntryMode::DIR))
+            &format!("{rel_path}/")
         } else {
-            oio::Entry::new(&rel_path, Metadata::new(EntryMode::Unknown))
+            &rel_path
         };
 
-        Ok(Some(entry))
+        Ok(Some(oio::Entry::new(p, metadata)))
     }
 }

Reply via email to