LFS support to be stored on minio (#12518)

* LFS support to be stored on minio

* Fix test

* Fix lint

* Fix lint

* Fix check

* Fix test

* Update documents and add migration for LFS

* Fix some bugs
This commit is contained in:
Lunny Xiao 2020-09-08 23:45:10 +08:00 committed by GitHub
parent e4b3f35b8d
commit 7a5465fc56
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 423 additions and 203 deletions

View file

@ -34,7 +34,7 @@ func NewLocalStorage(bucket string) (*LocalStorage, error) {
}
// Open a file
func (l *LocalStorage) Open(path string) (io.ReadCloser, error) {
func (l *LocalStorage) Open(path string) (Object, error) {
return os.Open(filepath.Join(l.dir, path))
}
@ -58,6 +58,11 @@ func (l *LocalStorage) Save(path string, r io.Reader) (int64, error) {
return io.Copy(f, r)
}
// Stat returns the info of the file
func (l *LocalStorage) Stat(path string) (ObjectInfo, error) {
return os.Stat(filepath.Join(l.dir, path))
}
// Delete delete a file
func (l *LocalStorage) Delete(path string) error {
p := filepath.Join(l.dir, path)

View file

@ -8,6 +8,7 @@ import (
"context"
"io"
"net/url"
"os"
"path"
"strings"
"time"
@ -62,7 +63,7 @@ func (m *MinioStorage) buildMinioPath(p string) string {
}
// Open open a file
func (m *MinioStorage) Open(path string) (io.ReadCloser, error) {
func (m *MinioStorage) Open(path string) (Object, error) {
var opts = minio.GetObjectOptions{}
object, err := m.client.GetObject(m.ctx, m.bucket, m.buildMinioPath(path), opts)
if err != nil {
@ -87,6 +88,41 @@ func (m *MinioStorage) Save(path string, r io.Reader) (int64, error) {
return uploadInfo.Size, nil
}
type minioFileInfo struct {
minio.ObjectInfo
}
func (m minioFileInfo) Name() string {
return m.ObjectInfo.Key
}
func (m minioFileInfo) Size() int64 {
return m.ObjectInfo.Size
}
func (m minioFileInfo) ModTime() time.Time {
return m.LastModified
}
// Stat returns the stat information of the object
func (m *MinioStorage) Stat(path string) (ObjectInfo, error) {
info, err := m.client.StatObject(
m.ctx,
m.bucket,
m.buildMinioPath(path),
minio.StatObjectOptions{},
)
if err != nil {
if errResp, ok := err.(minio.ErrorResponse); ok {
if errResp.Code == "NoSuchKey" {
return nil, os.ErrNotExist
}
}
return nil, err
}
return &minioFileInfo{info}, nil
}
// Delete delete a file
func (m *MinioStorage) Delete(path string) error {
return m.client.RemoveObject(m.ctx, m.bucket, m.buildMinioPath(path), minio.RemoveObjectOptions{})

View file

@ -10,6 +10,7 @@ import (
"fmt"
"io"
"net/url"
"time"
"code.gitea.io/gitea/modules/setting"
)
@ -19,10 +20,24 @@ var (
ErrURLNotSupported = errors.New("url method not supported")
)
// Object represents the object on the storage
type Object interface {
io.ReadCloser
io.Seeker
}
// ObjectInfo represents the object info on the storage
type ObjectInfo interface {
Name() string
Size() int64
ModTime() time.Time
}
// ObjectStorage represents an object storage to handle a bucket and files
type ObjectStorage interface {
Open(path string) (Object, error)
Save(path string, r io.Reader) (int64, error)
Open(path string) (io.ReadCloser, error)
Stat(path string) (ObjectInfo, error)
Delete(path string) error
URL(path, name string) (*url.URL, error)
}
@ -41,10 +56,21 @@ func Copy(dstStorage ObjectStorage, dstPath string, srcStorage ObjectStorage, sr
var (
// Attachments represents attachments storage
Attachments ObjectStorage
// LFS represents lfs storage
LFS ObjectStorage
)
// Init init the stoarge
func Init() error {
if err := initAttachments(); err != nil {
return err
}
return initLFS()
}
func initAttachments() error {
var err error
switch setting.Attachment.StoreType {
case "local":
@ -71,3 +97,31 @@ func Init() error {
return nil
}
func initLFS() error {
var err error
switch setting.LFS.StoreType {
case "local":
LFS, err = NewLocalStorage(setting.LFS.ContentPath)
case "minio":
minio := setting.LFS.Minio
LFS, err = NewMinioStorage(
context.Background(),
minio.Endpoint,
minio.AccessKeyID,
minio.SecretAccessKey,
minio.Bucket,
minio.Location,
minio.BasePath,
minio.UseSSL,
)
default:
return fmt.Errorf("Unsupported LFS store type: %s", setting.LFS.StoreType)
}
if err != nil {
return err
}
return nil
}