mirror of https://github.com/gogs/gogs.git
110 lines
2.4 KiB
Go
110 lines
2.4 KiB
Go
// Copyright 2020 The Gogs Authors. All rights reserved.
|
|
// Use of this source code is governed by a MIT-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package lfsutil
|
|
|
|
import (
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
"gogs.io/gogs/internal/osutil"
|
|
)
|
|
|
|
var ErrObjectNotExist = errors.New("Object does not exist")
|
|
|
|
// Storager is an storage backend for uploading and downloading LFS objects.
|
|
type Storager interface {
|
|
// Storage returns the name of the storage backend.
|
|
Storage() Storage
|
|
// Upload reads content from the io.ReadCloser and uploads as given oid.
|
|
// The reader is closed once upload is finished. ErrInvalidOID is returned
|
|
// if the given oid is not valid.
|
|
Upload(oid OID, rc io.ReadCloser) (int64, error)
|
|
// Download streams content of given oid to the io.Writer. It is caller's
|
|
// responsibility the close the writer when needed. ErrObjectNotExist is
|
|
// returned if the given oid does not exist.
|
|
Download(oid OID, w io.Writer) error
|
|
}
|
|
|
|
// Storage is the storage type of an LFS object.
|
|
type Storage string
|
|
|
|
const (
|
|
StorageLocal Storage = "local"
|
|
)
|
|
|
|
var _ Storager = (*LocalStorage)(nil)
|
|
|
|
// LocalStorage is a LFS storage backend on local file system.
|
|
type LocalStorage struct {
|
|
// The root path for storing LFS objects.
|
|
Root string
|
|
}
|
|
|
|
func (s *LocalStorage) Storage() Storage {
|
|
return StorageLocal
|
|
}
|
|
|
|
func (s *LocalStorage) storagePath(oid OID) string {
|
|
if len(oid) < 2 {
|
|
return ""
|
|
}
|
|
|
|
return filepath.Join(s.Root, string(oid[0]), string(oid[1]), string(oid))
|
|
}
|
|
|
|
func (s *LocalStorage) Upload(oid OID, rc io.ReadCloser) (int64, error) {
|
|
if !ValidOID(oid) {
|
|
return 0, ErrInvalidOID
|
|
}
|
|
|
|
var err error
|
|
fpath := s.storagePath(oid)
|
|
defer func() {
|
|
rc.Close()
|
|
|
|
if err != nil {
|
|
_ = os.Remove(fpath)
|
|
}
|
|
}()
|
|
|
|
err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm)
|
|
if err != nil {
|
|
return 0, errors.Wrap(err, "create directories")
|
|
}
|
|
w, err := os.Create(fpath)
|
|
if err != nil {
|
|
return 0, errors.Wrap(err, "create file")
|
|
}
|
|
defer w.Close()
|
|
|
|
written, err := io.Copy(w, rc)
|
|
if err != nil {
|
|
return 0, errors.Wrap(err, "copy file")
|
|
}
|
|
return written, nil
|
|
}
|
|
|
|
func (s *LocalStorage) Download(oid OID, w io.Writer) error {
|
|
fpath := s.storagePath(oid)
|
|
if !osutil.IsFile(fpath) {
|
|
return ErrObjectNotExist
|
|
}
|
|
|
|
r, err := os.Open(fpath)
|
|
if err != nil {
|
|
return errors.Wrap(err, "open file")
|
|
}
|
|
defer r.Close()
|
|
|
|
_, err = io.Copy(w, r)
|
|
if err != nil {
|
|
return errors.Wrap(err, "copy file")
|
|
}
|
|
return nil
|
|
}
|