gitea源码

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. // Copyright 2020 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package storage
  4. import (
  5. "context"
  6. "errors"
  7. "fmt"
  8. "io"
  9. "net/url"
  10. "os"
  11. "code.gitea.io/gitea/modules/log"
  12. "code.gitea.io/gitea/modules/setting"
  13. )
  14. // ErrURLNotSupported represents url is not supported
  15. var ErrURLNotSupported = errors.New("url method not supported")
  16. // ErrInvalidConfiguration is called when there is invalid configuration for a storage
  17. type ErrInvalidConfiguration struct {
  18. cfg any
  19. err error
  20. }
  21. func (err ErrInvalidConfiguration) Error() string {
  22. if err.err != nil {
  23. return fmt.Sprintf("Invalid Configuration Argument: %v: Error: %v", err.cfg, err.err)
  24. }
  25. return fmt.Sprintf("Invalid Configuration Argument: %v", err.cfg)
  26. }
  27. // IsErrInvalidConfiguration checks if an error is an ErrInvalidConfiguration
  28. func IsErrInvalidConfiguration(err error) bool {
  29. _, ok := err.(ErrInvalidConfiguration)
  30. return ok
  31. }
  32. type Type = setting.StorageType
  33. // NewStorageFunc is a function that creates a storage
  34. type NewStorageFunc func(ctx context.Context, cfg *setting.Storage) (ObjectStorage, error)
  35. var storageMap = map[Type]NewStorageFunc{}
  36. // RegisterStorageType registers a provided storage type with a function to create it
  37. func RegisterStorageType(typ Type, fn func(ctx context.Context, cfg *setting.Storage) (ObjectStorage, error)) {
  38. storageMap[typ] = fn
  39. }
  40. // Object represents the object on the storage
  41. type Object interface {
  42. io.ReadCloser
  43. io.Seeker
  44. Stat() (os.FileInfo, error)
  45. }
  46. // ObjectStorage represents an object storage to handle a bucket and files
  47. type ObjectStorage interface {
  48. Open(path string) (Object, error)
  49. // Save store an object, if size is unknown set -1
  50. // NOTICE: Some storage SDK will close the Reader after saving if it is also a Closer,
  51. // DO NOT use the reader anymore after Save, or wrap it to a non-Closer reader.
  52. Save(path string, r io.Reader, size int64) (int64, error)
  53. Stat(path string) (os.FileInfo, error)
  54. Delete(path string) error
  55. URL(path, name, method string, reqParams url.Values) (*url.URL, error)
  56. IterateObjects(path string, iterator func(path string, obj Object) error) error
  57. }
  58. // Copy copies a file from source ObjectStorage to dest ObjectStorage
  59. func Copy(dstStorage ObjectStorage, dstPath string, srcStorage ObjectStorage, srcPath string) (int64, error) {
  60. f, err := srcStorage.Open(srcPath)
  61. if err != nil {
  62. return 0, err
  63. }
  64. defer f.Close()
  65. size := int64(-1)
  66. fsinfo, err := f.Stat()
  67. if err == nil {
  68. size = fsinfo.Size()
  69. }
  70. return dstStorage.Save(dstPath, f, size)
  71. }
  72. // Clean delete all the objects in this storage
  73. func Clean(storage ObjectStorage) error {
  74. return storage.IterateObjects("", func(path string, obj Object) error {
  75. _ = obj.Close()
  76. return storage.Delete(path)
  77. })
  78. }
  79. // SaveFrom saves data to the ObjectStorage with path p from the callback
  80. func SaveFrom(objStorage ObjectStorage, path string, callback func(w io.Writer) error) error {
  81. pr, pw := io.Pipe()
  82. defer pr.Close()
  83. go func() {
  84. defer pw.Close()
  85. if err := callback(pw); err != nil {
  86. _ = pw.CloseWithError(err)
  87. }
  88. }()
  89. _, err := objStorage.Save(path, pr, -1)
  90. return err
  91. }
  92. var (
  93. // Attachments represents attachments storage
  94. Attachments ObjectStorage = uninitializedStorage
  95. // LFS represents lfs storage
  96. LFS ObjectStorage = uninitializedStorage
  97. // Avatars represents user avatars storage
  98. Avatars ObjectStorage = uninitializedStorage
  99. // RepoAvatars represents repository avatars storage
  100. RepoAvatars ObjectStorage = uninitializedStorage
  101. // RepoArchives represents repository archives storage
  102. RepoArchives ObjectStorage = uninitializedStorage
  103. // Packages represents packages storage
  104. Packages ObjectStorage = uninitializedStorage
  105. // Actions represents actions storage
  106. Actions ObjectStorage = uninitializedStorage
  107. // Actions Artifacts represents actions artifacts storage
  108. ActionsArtifacts ObjectStorage = uninitializedStorage
  109. )
  110. // Init init the storage
  111. func Init() error {
  112. for _, f := range []func() error{
  113. initAttachments,
  114. initAvatars,
  115. initRepoAvatars,
  116. initLFS,
  117. initRepoArchives,
  118. initPackages,
  119. initActions,
  120. } {
  121. if err := f(); err != nil {
  122. return err
  123. }
  124. }
  125. return nil
  126. }
  127. // NewStorage takes a storage type and some config and returns an ObjectStorage or an error
  128. func NewStorage(typStr Type, cfg *setting.Storage) (ObjectStorage, error) {
  129. if len(typStr) == 0 {
  130. typStr = setting.LocalStorageType
  131. }
  132. fn, ok := storageMap[typStr]
  133. if !ok {
  134. return nil, fmt.Errorf("Unsupported storage type: %s", typStr)
  135. }
  136. return fn(context.Background(), cfg)
  137. }
  138. func initAvatars() (err error) {
  139. log.Info("Initialising Avatar storage with type: %s", setting.Avatar.Storage.Type)
  140. Avatars, err = NewStorage(setting.Avatar.Storage.Type, setting.Avatar.Storage)
  141. return err
  142. }
  143. func initAttachments() (err error) {
  144. if !setting.Attachment.Enabled {
  145. Attachments = discardStorage("Attachment isn't enabled")
  146. return nil
  147. }
  148. log.Info("Initialising Attachment storage with type: %s", setting.Attachment.Storage.Type)
  149. Attachments, err = NewStorage(setting.Attachment.Storage.Type, setting.Attachment.Storage)
  150. return err
  151. }
  152. func initLFS() (err error) {
  153. if !setting.LFS.StartServer {
  154. LFS = discardStorage("LFS isn't enabled")
  155. return nil
  156. }
  157. log.Info("Initialising LFS storage with type: %s", setting.LFS.Storage.Type)
  158. LFS, err = NewStorage(setting.LFS.Storage.Type, setting.LFS.Storage)
  159. return err
  160. }
  161. func initRepoAvatars() (err error) {
  162. log.Info("Initialising Repository Avatar storage with type: %s", setting.RepoAvatar.Storage.Type)
  163. RepoAvatars, err = NewStorage(setting.RepoAvatar.Storage.Type, setting.RepoAvatar.Storage)
  164. return err
  165. }
  166. func initRepoArchives() (err error) {
  167. log.Info("Initialising Repository Archive storage with type: %s", setting.RepoArchive.Storage.Type)
  168. RepoArchives, err = NewStorage(setting.RepoArchive.Storage.Type, setting.RepoArchive.Storage)
  169. return err
  170. }
  171. func initPackages() (err error) {
  172. if !setting.Packages.Enabled {
  173. Packages = discardStorage("Packages isn't enabled")
  174. return nil
  175. }
  176. log.Info("Initialising Packages storage with type: %s", setting.Packages.Storage.Type)
  177. Packages, err = NewStorage(setting.Packages.Storage.Type, setting.Packages.Storage)
  178. return err
  179. }
  180. func initActions() (err error) {
  181. if !setting.Actions.Enabled {
  182. Actions = discardStorage("Actions isn't enabled")
  183. ActionsArtifacts = discardStorage("ActionsArtifacts isn't enabled")
  184. return nil
  185. }
  186. log.Info("Initialising Actions storage with type: %s", setting.Actions.LogStorage.Type)
  187. if Actions, err = NewStorage(setting.Actions.LogStorage.Type, setting.Actions.LogStorage); err != nil {
  188. return err
  189. }
  190. log.Info("Initialising ActionsArtifacts storage with type: %s", setting.Actions.ArtifactStorage.Type)
  191. ActionsArtifacts, err = NewStorage(setting.Actions.ArtifactStorage.Type, setting.Actions.ArtifactStorage)
  192. return err
  193. }