]> source.dussan.org Git - gitea.git/commitdiff
Fix object storage path handling (#27024)
authorwxiaoguang <wxiaoguang@gmail.com>
Wed, 13 Sep 2023 01:18:52 +0000 (09:18 +0800)
committerGitHub <noreply@github.com>
Wed, 13 Sep 2023 01:18:52 +0000 (01:18 +0000)
Object storage path rules:

* No single `/` or `.`, use empty string for root path
* Need to use trailing `/` for a list prefix to distinguish a "dir/"

modules/storage/minio.go
modules/storage/minio_test.go

index 714530ab50a7c2b8b59880e8cbbb1772d7a86c33..b58ab67dc747a1f0bcd10a9c5634e8b0ccf90c63 100644 (file)
@@ -136,9 +136,18 @@ func NewMinioStorage(ctx context.Context, cfg *setting.Storage) (ObjectStorage,
 }
 
 func (m *MinioStorage) buildMinioPath(p string) string {
-       p = util.PathJoinRelX(m.basePath, p)
+       p = strings.TrimPrefix(util.PathJoinRelX(m.basePath, p), "/") // object store doesn't use slash for root path
        if p == "." {
-               p = "" // minio doesn't use dot as relative path
+               p = "" // object store doesn't use dot as relative path
+       }
+       return p
+}
+
+func (m *MinioStorage) buildMinioDirPrefix(p string) string {
+       // ending slash is required for avoiding matching like "foo/" and "foobar/" with prefix "foo"
+       p = m.buildMinioPath(p) + "/"
+       if p == "/" {
+               p = "" // object store doesn't use slash for root path
        }
        return p
 }
@@ -237,20 +246,11 @@ func (m *MinioStorage) URL(path, name string) (*url.URL, error) {
 // IterateObjects iterates across the objects in the miniostorage
 func (m *MinioStorage) IterateObjects(dirName string, fn func(path string, obj Object) error) error {
        opts := minio.GetObjectOptions{}
-       lobjectCtx, cancel := context.WithCancel(m.ctx)
-       defer cancel()
-
-       basePath := m.basePath
-       if dirName != "" {
-               // ending slash is required for avoiding matching like "foo/" and "foobar/" with prefix "foo"
-               basePath = m.buildMinioPath(dirName) + "/"
-       }
-
-       for mObjInfo := range m.client.ListObjects(lobjectCtx, m.bucket, minio.ListObjectsOptions{
-               Prefix:    basePath,
+       for mObjInfo := range m.client.ListObjects(m.ctx, m.bucket, minio.ListObjectsOptions{
+               Prefix:    m.buildMinioDirPrefix(dirName),
                Recursive: true,
        }) {
-               object, err := m.client.GetObject(lobjectCtx, m.bucket, mObjInfo.Key, opts)
+               object, err := m.client.GetObject(m.ctx, m.bucket, mObjInfo.Key, opts)
                if err != nil {
                        return convertMinioErr(err)
                }
index 56dfd9100a406c210e37a357744b0436c3818d2b..c6fbb91ab472364e4d1854e34bb57f7f0ad29183 100644 (file)
@@ -31,6 +31,40 @@ func TestMinioStorageIterator(t *testing.T) {
        })
 }
 
+func TestMinioStoragePath(t *testing.T) {
+       m := &MinioStorage{basePath: ""}
+       assert.Equal(t, "", m.buildMinioPath("/"))
+       assert.Equal(t, "", m.buildMinioPath("."))
+       assert.Equal(t, "a", m.buildMinioPath("/a"))
+       assert.Equal(t, "a/b", m.buildMinioPath("/a/b/"))
+       assert.Equal(t, "", m.buildMinioDirPrefix(""))
+       assert.Equal(t, "a/", m.buildMinioDirPrefix("/a/"))
+
+       m = &MinioStorage{basePath: "/"}
+       assert.Equal(t, "", m.buildMinioPath("/"))
+       assert.Equal(t, "", m.buildMinioPath("."))
+       assert.Equal(t, "a", m.buildMinioPath("/a"))
+       assert.Equal(t, "a/b", m.buildMinioPath("/a/b/"))
+       assert.Equal(t, "", m.buildMinioDirPrefix(""))
+       assert.Equal(t, "a/", m.buildMinioDirPrefix("/a/"))
+
+       m = &MinioStorage{basePath: "/base"}
+       assert.Equal(t, "base", m.buildMinioPath("/"))
+       assert.Equal(t, "base", m.buildMinioPath("."))
+       assert.Equal(t, "base/a", m.buildMinioPath("/a"))
+       assert.Equal(t, "base/a/b", m.buildMinioPath("/a/b/"))
+       assert.Equal(t, "base/", m.buildMinioDirPrefix(""))
+       assert.Equal(t, "base/a/", m.buildMinioDirPrefix("/a/"))
+
+       m = &MinioStorage{basePath: "/base/"}
+       assert.Equal(t, "base", m.buildMinioPath("/"))
+       assert.Equal(t, "base", m.buildMinioPath("."))
+       assert.Equal(t, "base/a", m.buildMinioPath("/a"))
+       assert.Equal(t, "base/a/b", m.buildMinioPath("/a/b/"))
+       assert.Equal(t, "base/", m.buildMinioDirPrefix(""))
+       assert.Equal(t, "base/a/", m.buildMinioDirPrefix("/a/"))
+}
+
 func TestS3StorageBadRequest(t *testing.T) {
        if os.Getenv("CI") == "" {
                t.Skip("S3Storage not present outside of CI")