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 f15ce89c1 feat(services/onedrive): List dir shows metadata (#5632)
f15ce89c1 is described below

commit f15ce89c1e39b6ff4d15e2bf6b2064304edb94b5
Author: Erick Guan <[email protected]>
AuthorDate: Mon Mar 3 06:34:30 2025 +0100

    feat(services/onedrive): List dir shows metadata (#5632)
    
    Most my test folders have 0 in size, but one has 3. I didn't dig into
    it.
---
 core/src/raw/chrono_util.rs               | 26 +++++++++++++++++++++++++-
 core/src/services/onedrive/backend.rs     |  3 +++
 core/src/services/onedrive/graph_model.rs | 15 +++++++++++++--
 core/src/services/onedrive/lister.rs      | 28 +++++++++++++++++++---------
 4 files changed, 60 insertions(+), 12 deletions(-)

diff --git a/core/src/raw/chrono_util.rs b/core/src/raw/chrono_util.rs
index a5cc6a9a1..2899be619 100644
--- a/core/src/raw/chrono_util.rs
+++ b/core/src/raw/chrono_util.rs
@@ -36,7 +36,31 @@ pub fn parse_datetime_from_rfc2822(s: &str) -> 
Result<DateTime<Utc>> {
 
 /// Parse datetime from rfc3339.
 ///
-/// For example: `2014-11-28T21:00:09+09:00`
+/// # Examples
+///
+/// With a time zone:
+///
+/// ```
+/// use chrono::Datelike;
+/// use opendal::Error;
+/// use opendal::raw::parse_datetime_from_rfc3339;
+///
+/// let date_time = parse_datetime_from_rfc3339("2014-11-28T21:00:09+09:00")?;
+/// assert_eq!(date_time.date_naive().day(), 28);
+/// # Ok::<(), Error>(())
+/// ```
+///
+/// With the UTC offset of 00:00:
+///
+/// ```
+/// use chrono::Timelike;
+/// # use opendal::Error;
+/// # use opendal::raw::parse_datetime_from_rfc3339;
+///
+/// let date_time = parse_datetime_from_rfc3339("2014-11-28T21:00:09Z")?;
+/// assert_eq!(date_time.hour(), 21);
+/// # Ok::<(), Error>(())
+/// ```
 pub fn parse_datetime_from_rfc3339(s: &str) -> Result<DateTime<Utc>> {
     DateTime::parse_from_rfc3339(s)
         .map(|v| v.into())
diff --git a/core/src/services/onedrive/backend.rs 
b/core/src/services/onedrive/backend.rs
index 60318a265..a252055ed 100644
--- a/core/src/services/onedrive/backend.rs
+++ b/core/src/services/onedrive/backend.rs
@@ -61,6 +61,9 @@ impl OnedriveBackend {
                         delete: true,
                         create_dir: true,
                         list: true,
+                        list_has_content_length: true,
+                        list_has_etag: true,
+                        list_has_last_modified: true,
                         shared: true,
                         ..Default::default()
                     });
diff --git a/core/src/services/onedrive/graph_model.rs 
b/core/src/services/onedrive/graph_model.rs
index 7821281fe..e3e3f8691 100644
--- a/core/src/services/onedrive/graph_model.rs
+++ b/core/src/services/onedrive/graph_model.rs
@@ -27,12 +27,20 @@ pub struct GraphApiOnedriveListResponse {
     pub value: Vec<OneDriveItem>,
 }
 
-/// DriveItem representation
-/// 
https://learn.microsoft.com/en-us/onedrive/developer/rest-api/resources/list?view=odsp-graph-online#json-representation
+/// mapping for a DriveItem representation
+/// read more at 
https://learn.microsoft.com/en-us/onedrive/developer/rest-api/resources/driveitem
 #[derive(Debug, Serialize, Deserialize)]
 pub struct OneDriveItem {
     pub name: String,
 
+    #[serde(rename = "lastModifiedDateTime")]
+    pub last_modified_date_time: String,
+
+    #[serde(rename = "eTag")]
+    pub e_tag: String,
+
+    pub size: i64,
+
     #[serde(rename = "parentReference")]
     pub parent_reference: ParentReference,
 
@@ -45,6 +53,9 @@ pub struct ParentReference {
     pub path: String,
 }
 
+/// Additional properties when represents a facet of a "DriveItem":
+/// - "file", read more at 
https://learn.microsoft.com/en-us/onedrive/developer/rest-api/resources/file
+/// - "folder", read more at 
https://learn.microsoft.com/en-us/onedrive/developer/rest-api/resources/folder
 #[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
 #[serde(untagged)]
 pub enum ItemType {
diff --git a/core/src/services/onedrive/lister.rs 
b/core/src/services/onedrive/lister.rs
index ef7b1887f..8d030a311 100644
--- a/core/src/services/onedrive/lister.rs
+++ b/core/src/services/onedrive/lister.rs
@@ -101,19 +101,29 @@ impl oio::PageList for OnedriveLister {
                 .unwrap_or("");
 
             let path = format!("{}/{}", parent_path, name);
+            let mut normalized_path = build_rel_path(&self.root, &path);
+            let entry_mode = match drive_item.item_type {
+                ItemType::Folder { .. } => EntryMode::DIR,
+                ItemType::File { .. } => EntryMode::FILE,
+            };
 
-            let normalized_path = build_rel_path(&self.root, &path);
+            // OneDrive returns the folder without the trailing `/`
+            if entry_mode == EntryMode::DIR {
+                normalized_path.push('/');
+            }
 
-            let entry: oio::Entry = match drive_item.item_type {
-                ItemType::Folder { .. } => {
-                    let normalized_path = format!("{}/", normalized_path);
-                    oio::Entry::new(&normalized_path, 
Metadata::new(EntryMode::DIR))
-                }
-                ItemType::File { .. } => {
-                    oio::Entry::new(&normalized_path, 
Metadata::new(EntryMode::FILE))
-                }
+            let mut meta = 
Metadata::new(entry_mode).with_etag(drive_item.e_tag);
+            let last_modified =
+                
parse_datetime_from_rfc3339(drive_item.last_modified_date_time.as_str())?;
+            meta.set_last_modified(last_modified);
+            let content_length = if drive_item.size < 0 {
+                0
+            } else {
+                drive_item.size as u64
             };
+            meta.set_content_length(content_length);
 
+            let entry = oio::Entry::new(&normalized_path, meta);
             ctx.entries.push_back(entry)
         }
 

Reply via email to