You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iceberg.apache.org by ze...@apache.org on 2026/06/24 20:16:30 UTC
(iceberg-go) branch main updated: fix(io): keep MemFS WalkDir within root (#1302)
This is an automated email from the ASF dual-hosted git repository.
zeroshade pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iceberg-go.git
The following commit(s) were added to refs/heads/main by this push:
new 59265455 fix(io): keep MemFS WalkDir within root (#1302)
59265455 is described below
commit 59265455ab65917d653821524091fee763d712e9
Author: Minh Vu <vu...@gmail.com>
AuthorDate: Wed Jun 24 22:16:24 2026 +0200
fix(io): keep MemFS WalkDir within root (#1302)
MemFS.WalkDir matched roots by raw string prefix, so walking a path like .../table also included sibling keys such as table2 and table_backup. Match on path boundaries instead and normalize trailing slashes on the walk root, with regression coverage for sibling prefixes.
---
io/mem.go | 7 ++++++-
io/mem_test.go | 33 +++++++++++++++++++++++++++++++++
2 files changed, 39 insertions(+), 1 deletion(-)
diff --git a/io/mem.go b/io/mem.go
index 217da242..f0965eb4 100644
--- a/io/mem.go
+++ b/io/mem.go
@@ -104,8 +104,9 @@ func (m *MemFS) WalkDir(root string, fn fs.WalkDirFunc) error {
m.mu.RLock()
defer m.mu.RUnlock()
+ root = strings.TrimRight(root, "/")
for key, data := range m.files {
- if !strings.HasPrefix(key, root) {
+ if !memPathInRoot(key, root) {
continue
}
info := &memFileInfo{name: filepath.Base(key), size: int64(len(data))}
@@ -117,6 +118,10 @@ func (m *MemFS) WalkDir(root string, fn fs.WalkDirFunc) error {
return nil
}
+func memPathInRoot(path, root string) bool {
+ return root == "" || path == root || strings.HasPrefix(path, root+"/")
+}
+
type memFile struct {
data []byte
name string
diff --git a/io/mem_test.go b/io/mem_test.go
index c064c49c..97d3b536 100644
--- a/io/mem_test.go
+++ b/io/mem_test.go
@@ -159,3 +159,36 @@ func TestMemIO_WalkDir(t *testing.T) {
"mem://walkdir-bucket/a/2.txt",
}, walked)
}
+
+func TestMemIO_WalkDirDoesNotIncludeSiblingPrefixes(t *testing.T) {
+ ctx := context.Background()
+
+ memIO, err := icebergio.LoadFS(ctx, map[string]string{}, "mem://walkdir-boundary-bucket/")
+ require.NoError(t, err)
+
+ listable := memIO.(icebergio.ListableIO)
+ writeIO := memIO.(icebergio.WriteFileIO)
+
+ require.NoError(t, writeIO.WriteFile("mem://walkdir-boundary-bucket/table/data.parquet", []byte("table")))
+ require.NoError(t, writeIO.WriteFile("mem://walkdir-boundary-bucket/table2/data.parquet", []byte("table2")))
+ require.NoError(t, writeIO.WriteFile("mem://walkdir-boundary-bucket/table_backup/data.parquet", []byte("backup")))
+
+ for _, root := range []string{
+ "mem://walkdir-boundary-bucket/table",
+ "mem://walkdir-boundary-bucket/table/",
+ } {
+ t.Run(root, func(t *testing.T) {
+ var walked []string
+ err := listable.WalkDir(root, func(path string, _ fs.DirEntry, err error) error {
+ require.NoError(t, err)
+ walked = append(walked, path)
+
+ return nil
+ })
+ require.NoError(t, err)
+ assert.ElementsMatch(t, []string{
+ "mem://walkdir-boundary-bucket/table/data.parquet",
+ }, walked)
+ })
+ }
+}