storage.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. package lfsutil
  2. import (
  3. "io"
  4. "os"
  5. "path/filepath"
  6. "github.com/cockroachdb/errors"
  7. "gogs.io/gogs/internal/osutil"
  8. )
  9. var ErrObjectNotExist = errors.New("Object does not exist")
  10. // Storager is an storage backend for uploading and downloading LFS objects.
  11. type Storager interface {
  12. // Storage returns the name of the storage backend.
  13. Storage() Storage
  14. // Upload reads content from the io.ReadCloser and uploads as given oid.
  15. // The reader is closed once upload is finished. ErrInvalidOID is returned
  16. // if the given oid is not valid.
  17. Upload(oid OID, rc io.ReadCloser) (int64, error)
  18. // Download streams content of given oid to the io.Writer. It is caller's
  19. // responsibility the close the writer when needed. ErrObjectNotExist is
  20. // returned if the given oid does not exist.
  21. Download(oid OID, w io.Writer) error
  22. }
  23. // Storage is the storage type of an LFS object.
  24. type Storage string
  25. const (
  26. StorageLocal Storage = "local"
  27. )
  28. var _ Storager = (*LocalStorage)(nil)
  29. // LocalStorage is a LFS storage backend on local file system.
  30. type LocalStorage struct {
  31. // The root path for storing LFS objects.
  32. Root string
  33. }
  34. func (*LocalStorage) Storage() Storage {
  35. return StorageLocal
  36. }
  37. func (s *LocalStorage) storagePath(oid OID) string {
  38. if len(oid) < 2 {
  39. return ""
  40. }
  41. return filepath.Join(s.Root, string(oid[0]), string(oid[1]), string(oid))
  42. }
  43. func (s *LocalStorage) Upload(oid OID, rc io.ReadCloser) (int64, error) {
  44. if !ValidOID(oid) {
  45. return 0, ErrInvalidOID
  46. }
  47. var err error
  48. fpath := s.storagePath(oid)
  49. defer func() {
  50. rc.Close()
  51. if err != nil {
  52. _ = os.Remove(fpath)
  53. }
  54. }()
  55. err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm)
  56. if err != nil {
  57. return 0, errors.Wrap(err, "create directories")
  58. }
  59. w, err := os.Create(fpath)
  60. if err != nil {
  61. return 0, errors.Wrap(err, "create file")
  62. }
  63. defer w.Close()
  64. written, err := io.Copy(w, rc)
  65. if err != nil {
  66. return 0, errors.Wrap(err, "copy file")
  67. }
  68. return written, nil
  69. }
  70. func (s *LocalStorage) Download(oid OID, w io.Writer) error {
  71. fpath := s.storagePath(oid)
  72. if !osutil.IsFile(fpath) {
  73. return ErrObjectNotExist
  74. }
  75. r, err := os.Open(fpath)
  76. if err != nil {
  77. return errors.Wrap(err, "open file")
  78. }
  79. defer r.Close()
  80. _, err = io.Copy(w, r)
  81. if err != nil {
  82. return errors.Wrap(err, "copy file")
  83. }
  84. return nil
  85. }