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)
}