Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add path prefix to ObjectStorage.Iterator #23332

Merged
merged 11 commits into from
Mar 13, 2023
6 changes: 3 additions & 3 deletions cmd/dump.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ func runDump(ctx *cli.Context) error {

if ctx.IsSet("skip-lfs-data") && ctx.Bool("skip-lfs-data") {
log.Info("Skip dumping LFS data")
} else if err := storage.LFS.IterateObjects(func(objPath string, object storage.Object) error {
} else if err := storage.LFS.IterateObjects("", func(objPath string, object storage.Object) error {
info, err := object.Stat()
if err != nil {
return err
Expand Down Expand Up @@ -351,7 +351,7 @@ func runDump(ctx *cli.Context) error {

if ctx.IsSet("skip-attachment-data") && ctx.Bool("skip-attachment-data") {
log.Info("Skip dumping attachment data")
} else if err := storage.Attachments.IterateObjects(func(objPath string, object storage.Object) error {
} else if err := storage.Attachments.IterateObjects("", func(objPath string, object storage.Object) error {
info, err := object.Stat()
if err != nil {
return err
Expand All @@ -364,7 +364,7 @@ func runDump(ctx *cli.Context) error {

if ctx.IsSet("skip-package-data") && ctx.Bool("skip-package-data") {
log.Info("Skip dumping package data")
} else if err := storage.Packages.IterateObjects(func(objPath string, object storage.Object) error {
} else if err := storage.Packages.IterateObjects("", func(objPath string, object storage.Object) error {
info, err := object.Stat()
if err != nil {
return err
Expand Down
2 changes: 1 addition & 1 deletion modules/doctor/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func commonCheckStorage(ctx context.Context, logger log.Logger, autofix bool, op
totalSize, orphanedSize := int64(0), int64(0)

var pathsToDelete []string
if err := opts.storer.IterateObjects(func(p string, obj storage.Object) error {
if err := opts.storer.IterateObjects("", func(p string, obj storage.Object) error {
defer obj.Close()

totalCount++
Expand Down
2 changes: 1 addition & 1 deletion modules/storage/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,6 @@ func (s discardStorage) URL(_, _ string) (*url.URL, error) {
return nil, fmt.Errorf("%s", s)
}

func (s discardStorage) IterateObjects(_ func(string, Object) error) error {
func (s discardStorage) IterateObjects(_ string, _ func(string, Object) error) error {
return fmt.Errorf("%s", s)
}
2 changes: 1 addition & 1 deletion modules/storage/helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func Test_discardStorage(t *testing.T) {
assert.Errorf(t, err, string(tt))
}
{
err := tt.IterateObjects(func(_ string, _ Object) error { return nil })
err := tt.IterateObjects("", func(_ string, _ Object) error { return nil })
assert.Error(t, err, string(tt))
}
})
Expand Down
8 changes: 6 additions & 2 deletions modules/storage/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,12 @@ func (l *LocalStorage) URL(path, name string) (*url.URL, error) {
}

// IterateObjects iterates across the objects in the local storage
func (l *LocalStorage) IterateObjects(fn func(path string, obj Object) error) error {
return filepath.WalkDir(l.dir, func(path string, d os.DirEntry, err error) error {
func (l *LocalStorage) IterateObjects(prefix string, fn func(path string, obj Object) error) error {
dir := l.dir
if prefix != "" {
dir = filepath.Join(l.dir, util.CleanPath(prefix))
}
return filepath.WalkDir(dir, func(path string, d os.DirEntry, err error) error {
if err != nil {
return err
}
Expand Down
42 changes: 42 additions & 0 deletions modules/storage/local_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
package storage

import (
"bytes"
"context"
"os"
"path/filepath"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -50,3 +54,41 @@ func TestBuildLocalPath(t *testing.T) {
})
}
}

func TestLocalStorageIterator(t *testing.T) {
dir := filepath.Join(os.TempDir(), "TestLocalStorageIteratorTestDir")
l, err := NewLocalStorage(context.Background(), LocalStorageConfig{Path: dir})
assert.NoError(t, err)

testFiles := [][]string{
{"a/1.txt", "a1"},
{"/a/1.txt", "aa1"}, // same as above, but with leading slash that will be trim
{"b/1.txt", "b1"},
{"b/2.txt", "b2"},
{"b/3.txt", "b3"},
{"b/x 4.txt", "bx4"},
}
for _, f := range testFiles {
_, err = l.Save(f[0], bytes.NewBufferString(f[1]), -1)
assert.NoError(t, err)
}

expectedList := map[string][]string{
"a": {"a/1.txt"},
"b": {"b/1.txt", "b/2.txt", "b/3.txt", "b/x 4.txt"},
"": {"a/1.txt", "b/1.txt", "b/2.txt", "b/3.txt", "b/x 4.txt"},
"/": {"a/1.txt", "b/1.txt", "b/2.txt", "b/3.txt", "b/x 4.txt"},
"a/b/../../a": {"a/1.txt"},
}
for dir, expected := range expectedList {
count := 0
err = l.IterateObjects(dir, func(path string, f Object) error {
defer f.Close()
assert.Contains(t, expected, path)
count++
return nil
})
assert.NoError(t, err)
assert.Equal(t, count, len(expected))
}
}
12 changes: 9 additions & 3 deletions modules/storage/minio.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,12 +209,18 @@ func (m *MinioStorage) URL(path, name string) (*url.URL, error) {
}

// IterateObjects iterates across the objects in the miniostorage
func (m *MinioStorage) IterateObjects(fn func(path string, obj Object) error) error {
func (m *MinioStorage) IterateObjects(prefix string, fn func(path string, obj Object) error) error {
opts := minio.GetObjectOptions{}
lobjectCtx, cancel := context.WithCancel(m.ctx)
defer cancel()

basePath := m.basePath
if prefix != "" {
basePath = m.buildMinioPath(prefix)
}

for mObjInfo := range m.client.ListObjects(lobjectCtx, m.bucket, minio.ListObjectsOptions{
Prefix: m.basePath,
Prefix: basePath,
Recursive: true,
}) {
object, err := m.client.GetObject(lobjectCtx, m.bucket, mObjInfo.Key, opts)
Expand All @@ -223,7 +229,7 @@ func (m *MinioStorage) IterateObjects(fn func(path string, obj Object) error) er
}
if err := func(object *minio.Object, fn func(path string, obj Object) error) error {
defer object.Close()
return fn(strings.TrimPrefix(mObjInfo.Key, m.basePath), &minioObject{object})
return fn(strings.TrimPrefix(mObjInfo.Key, basePath), &minioObject{object})
}(object, fn); err != nil {
return convertMinioErr(err)
}
Expand Down
4 changes: 2 additions & 2 deletions modules/storage/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ type ObjectStorage interface {
Stat(path string) (os.FileInfo, error)
Delete(path string) error
URL(path, name string) (*url.URL, error)
IterateObjects(func(path string, obj Object) error) error
IterateObjects(path string, iterator func(path string, obj Object) error) error
}

// Copy copies a file from source ObjectStorage to dest ObjectStorage
Expand All @@ -87,7 +87,7 @@ func Copy(dstStorage ObjectStorage, dstPath string, srcStorage ObjectStorage, sr

// Clean delete all the objects in this storage
func Clean(storage ObjectStorage) error {
return storage.IterateObjects(func(path string, obj Object) error {
return storage.IterateObjects("", func(path string, obj Object) error {
_ = obj.Close()
return storage.Delete(path)
})
Expand Down
4 changes: 2 additions & 2 deletions tests/test_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ func PrepareTestEnv(t testing.TB, skip ...int) func() {
lfsFixtures, err := storage.NewStorage("", storage.LocalStorageConfig{Path: path.Join(filepath.Dir(setting.AppPath), "tests/gitea-lfs-meta")})
assert.NoError(t, err)
assert.NoError(t, storage.Clean(storage.LFS))
assert.NoError(t, lfsFixtures.IterateObjects(func(path string, _ storage.Object) error {
assert.NoError(t, lfsFixtures.IterateObjects("", func(path string, _ storage.Object) error {
_, err := storage.Copy(storage.LFS, path, lfsFixtures, path)
return err
}))
Expand Down Expand Up @@ -258,7 +258,7 @@ func ResetFixtures(t *testing.T) {
lfsFixtures, err := storage.NewStorage("", storage.LocalStorageConfig{Path: path.Join(filepath.Dir(setting.AppPath), "tests/gitea-lfs-meta")})
assert.NoError(t, err)
assert.NoError(t, storage.Clean(storage.LFS))
assert.NoError(t, lfsFixtures.IterateObjects(func(path string, _ storage.Object) error {
assert.NoError(t, lfsFixtures.IterateObjects("", func(path string, _ storage.Object) error {
_, err := storage.Copy(storage.LFS, path, lfsFixtures, path)
return err
}))
Expand Down