You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@opendal.apache.org by xu...@apache.org on 2026/08/27 07:55:38 UTC

(opendal) 01/03: fix(core): respect stat condition capabilities

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

Xuanwo pushed a commit to branch xuanwo/fix-behavior-main-ci
in repository https://gitbox.apache.org/repos/asf/opendal.git

commit c8973b3c04dd46f9e890ac912d92698b1addb3e2
Author: Xuanwo <gi...@xuanwo.io>
AuthorDate: Thu Aug 27 15:54:58 2026 +0800

    fix(core): respect stat condition capabilities
---
 core/core/src/types/context/read.rs | 46 +++++++++++++++++++++++++++++++++----
 1 file changed, 42 insertions(+), 4 deletions(-)

diff --git a/core/core/src/types/context/read.rs b/core/core/src/types/context/read.rs
index 3f0a017887..cbbfb90df0 100644
--- a/core/core/src/types/context/read.rs
+++ b/core/core/src/types/context/read.rs
@@ -123,20 +123,29 @@ impl ReadContext {
         }
 
         let mut op_stat = OpStat::new();
+        let capability = self.srv.capability();
 
         if let Some(v) = self.args().version() {
             op_stat = op_stat.with_version(v);
         }
-        if let Some(v) = self.args().if_match() {
+        if capability.stat_with_if_match
+            && let Some(v) = self.args().if_match()
+        {
             op_stat = op_stat.with_if_match(v);
         }
-        if let Some(v) = self.args().if_none_match() {
+        if capability.stat_with_if_none_match
+            && let Some(v) = self.args().if_none_match()
+        {
             op_stat = op_stat.with_if_none_match(v);
         }
-        if let Some(v) = self.args().if_modified_since() {
+        if capability.stat_with_if_modified_since
+            && let Some(v) = self.args().if_modified_since()
+        {
             op_stat = op_stat.with_if_modified_since(v);
         }
-        if let Some(v) = self.args().if_unmodified_since() {
+        if capability.stat_with_if_unmodified_since
+            && let Some(v) = self.args().if_unmodified_since()
+        {
             op_stat = op_stat.with_if_unmodified_since(v);
         }
 
@@ -271,6 +280,8 @@ mod tests {
     use bytes::Bytes;
 
     use super::*;
+    use crate::layers::CapabilityOverrideLayer;
+    use crate::layers::CorrectnessCheckLayer;
 
     fn new_read_context(
         ctx: OperationContext,
@@ -410,4 +421,31 @@ mod tests {
         pretty_assertions::assert_eq!(range, 32..42);
         Ok(())
     }
+
+    #[tokio::test]
+    async fn test_parse_into_range_skips_unsupported_stat_conditions() -> Result<()> {
+        let op = Operator::new(services::Memory::default())?;
+        op.write("test", Buffer::from("HelloWorld")).await?;
+
+        let srv = CapabilityOverrideLayer::new(|mut capability| {
+            capability.read_with_if_match = true;
+            capability.stat_with_if_match = false;
+            capability
+        })
+        .apply_service(op.base_service().clone());
+        let srv = CorrectnessCheckLayer.apply_service(srv);
+
+        let (_, args, options) = options::ReadOptions {
+            if_match: Some("invalid-etag".to_string()),
+            ..Default::default()
+        }
+        .into();
+        let ctx =
+            new_read_context_with_args(op.base_context().clone(), srv, "test", args, options)?;
+
+        let range = ctx.parse_into_range(..).await?;
+
+        pretty_assertions::assert_eq!(range, 0..10);
+        Ok(())
+    }
 }