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

mneumann pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-rs-object-store.git


The following commit(s) were added to refs/heads/main by this push:
     new e89f62b  fix[prefix]: strip_meta from get_opts result in PrefixStore 
(#686)
e89f62b is described below

commit e89f62b6508f6f65873ce6a5017cd0d5d7395184
Author: Alfonso Subiotto Marqués <[email protected]>
AuthorDate: Wed Apr 8 14:52:59 2026 +0200

    fix[prefix]: strip_meta from get_opts result in PrefixStore (#686)
---
 src/integration.rs |  1 +
 src/prefix.rs      | 24 +++++++++++++++++++++++-
 2 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/src/integration.rs b/src/integration.rs
index 6b55bb2..e68837c 100644
--- a/src/integration.rs
+++ b/src/integration.rs
@@ -177,6 +177,7 @@ pub async fn put_get_delete_list(storage: &DynObjectStore) {
 
     let head = storage.head(&location).await.unwrap();
     assert_eq!(head.size, data.len() as u64);
+    assert_eq!(head.location, location);
 
     storage.delete(&location).await.unwrap();
 
diff --git a/src/prefix.rs b/src/prefix.rs
index 0ffb09a..9cdf3b0 100644
--- a/src/prefix.rs
+++ b/src/prefix.rs
@@ -117,7 +117,9 @@ impl<T: ObjectStore> ObjectStore for PrefixStore<T> {
 
     async fn get_opts(&self, location: &Path, options: GetOptions) -> 
Result<GetResult> {
         let full_path = self.full_path(location);
-        self.inner.get_opts(&full_path, options).await
+        let mut result = self.inner.get_opts(&full_path, options).await?;
+        result.meta = self.strip_meta(result.meta);
+        Ok(result)
     }
 
     async fn get_ranges(&self, location: &Path, ranges: &[Range<u64>]) -> 
Result<Vec<Bytes>> {
@@ -299,6 +301,26 @@ mod tests {
         assert_eq!(&*read_data, data)
     }
 
+    // Regression test for
+    // https://github.com/apache/arrow-rs-object-store/issues/664:
+    // head/get returned an ObjectMeta whose location still contained the
+    // prefix, so round-tripping the returned location back into the store 
would
+    // double-prefix it.
+    #[tokio::test]
+    async fn prefix_head_get_strip_prefix() {
+        let store = PrefixStore::new(InMemory::new(), "prefix");
+        let path = Path::from("test_file");
+        store.put(&path, "data".into()).await.unwrap();
+
+        let head = store.head(&path).await.unwrap();
+        assert_eq!(head.location, path);
+        let get = store.get(&path).await.unwrap();
+        assert_eq!(get.meta.location, path);
+
+        // The returned location must round-trip back into the same store.
+        store.get(&head.location).await.unwrap();
+    }
+
     #[tokio::test]
     async fn prefix_multipart() {
         let store = PrefixStore::new(InMemory::new(), "prefix");

Reply via email to