@@ -13,6 +13,8 @@ import (
13
13
"strings"
14
14
"time"
15
15
16
+ "code.gitea.io/gitea/modules/log"
17
+
16
18
"github.com/minio/minio-go/v7"
17
19
"github.com/minio/minio-go/v7/pkg/credentials"
18
20
)
@@ -58,20 +60,42 @@ type MinioStorage struct {
58
60
basePath string
59
61
}
60
62
63
+ func convertMinioErr (err error ) error {
64
+ if err == nil {
65
+ return nil
66
+ }
67
+ errResp , ok := err .(minio.ErrorResponse )
68
+ if ! ok {
69
+ return err
70
+ }
71
+
72
+ // Convert two responses to standard analogues
73
+ switch errResp .Code {
74
+ case "NoSuchKey" :
75
+ return os .ErrNotExist
76
+ case "AccessDenied" :
77
+ return os .ErrPermission
78
+ }
79
+
80
+ return err
81
+ }
82
+
61
83
// NewMinioStorage returns a minio storage
62
84
func NewMinioStorage (ctx context.Context , cfg interface {}) (ObjectStorage , error ) {
63
85
configInterface , err := toConfig (MinioStorageConfig {}, cfg )
64
86
if err != nil {
65
- return nil , err
87
+ return nil , convertMinioErr ( err )
66
88
}
67
89
config := configInterface .(MinioStorageConfig )
68
90
91
+ log .Info ("Creating Minio storage at %s:%s with base path %s" , config .Endpoint , config .Bucket , config .BasePath )
92
+
69
93
minioClient , err := minio .New (config .Endpoint , & minio.Options {
70
94
Creds : credentials .NewStaticV4 (config .AccessKeyID , config .SecretAccessKey , "" ),
71
95
Secure : config .UseSSL ,
72
96
})
73
97
if err != nil {
74
- return nil , err
98
+ return nil , convertMinioErr ( err )
75
99
}
76
100
77
101
if err := minioClient .MakeBucket (ctx , config .Bucket , minio.MakeBucketOptions {
@@ -80,7 +104,7 @@ func NewMinioStorage(ctx context.Context, cfg interface{}) (ObjectStorage, error
80
104
// Check to see if we already own this bucket (which happens if you run this twice)
81
105
exists , errBucketExists := minioClient .BucketExists (ctx , config .Bucket )
82
106
if ! exists || errBucketExists != nil {
83
- return nil , err
107
+ return nil , convertMinioErr ( err )
84
108
}
85
109
}
86
110
@@ -101,7 +125,7 @@ func (m *MinioStorage) Open(path string) (Object, error) {
101
125
var opts = minio.GetObjectOptions {}
102
126
object , err := m .client .GetObject (m .ctx , m .bucket , m .buildMinioPath (path ), opts )
103
127
if err != nil {
104
- return nil , err
128
+ return nil , convertMinioErr ( err )
105
129
}
106
130
return & minioObject {object }, nil
107
131
}
@@ -117,7 +141,7 @@ func (m *MinioStorage) Save(path string, r io.Reader) (int64, error) {
117
141
minio.PutObjectOptions {ContentType : "application/octet-stream" },
118
142
)
119
143
if err != nil {
120
- return 0 , err
144
+ return 0 , convertMinioErr ( err )
121
145
}
122
146
return uploadInfo .Size , nil
123
147
}
@@ -159,27 +183,25 @@ func (m *MinioStorage) Stat(path string) (os.FileInfo, error) {
159
183
minio.StatObjectOptions {},
160
184
)
161
185
if err != nil {
162
- if errResp , ok := err .(minio.ErrorResponse ); ok {
163
- if errResp .Code == "NoSuchKey" {
164
- return nil , os .ErrNotExist
165
- }
166
- }
167
- return nil , err
186
+ return nil , convertMinioErr (err )
168
187
}
169
188
return & minioFileInfo {info }, nil
170
189
}
171
190
172
191
// Delete delete a file
173
192
func (m * MinioStorage ) Delete (path string ) error {
174
- return m .client .RemoveObject (m .ctx , m .bucket , m .buildMinioPath (path ), minio.RemoveObjectOptions {})
193
+ err := m .client .RemoveObject (m .ctx , m .bucket , m .buildMinioPath (path ), minio.RemoveObjectOptions {})
194
+
195
+ return convertMinioErr (err )
175
196
}
176
197
177
198
// URL gets the redirect URL to a file. The presigned link is valid for 5 minutes.
178
199
func (m * MinioStorage ) URL (path , name string ) (* url.URL , error ) {
179
200
reqParams := make (url.Values )
180
201
// TODO it may be good to embed images with 'inline' like ServeData does, but we don't want to have to read the file, do we?
181
202
reqParams .Set ("response-content-disposition" , "attachment; filename=\" " + quoteEscaper .Replace (name )+ "\" " )
182
- return m .client .PresignedGetObject (m .ctx , m .bucket , m .buildMinioPath (path ), 5 * time .Minute , reqParams )
203
+ u , err := m .client .PresignedGetObject (m .ctx , m .bucket , m .buildMinioPath (path ), 5 * time .Minute , reqParams )
204
+ return u , convertMinioErr (err )
183
205
}
184
206
185
207
// IterateObjects iterates across the objects in the miniostorage
@@ -193,13 +215,13 @@ func (m *MinioStorage) IterateObjects(fn func(path string, obj Object) error) er
193
215
}) {
194
216
object , err := m .client .GetObject (lobjectCtx , m .bucket , mObjInfo .Key , opts )
195
217
if err != nil {
196
- return err
218
+ return convertMinioErr ( err )
197
219
}
198
220
if err := func (object * minio.Object , fn func (path string , obj Object ) error ) error {
199
221
defer object .Close ()
200
222
return fn (strings .TrimPrefix (m .basePath , mObjInfo .Key ), & minioObject {object })
201
223
}(object , fn ); err != nil {
202
- return err
224
+ return convertMinioErr ( err )
203
225
}
204
226
}
205
227
return nil
0 commit comments