gitea源码

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. // Copyright 2019 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package files
  4. import (
  5. "context"
  6. "fmt"
  7. "os"
  8. "path"
  9. "sync"
  10. repo_model "code.gitea.io/gitea/models/repo"
  11. user_model "code.gitea.io/gitea/models/user"
  12. "code.gitea.io/gitea/modules/log"
  13. )
  14. // UploadRepoFileOptions contains the uploaded repository file options
  15. type UploadRepoFileOptions struct {
  16. LastCommitID string
  17. OldBranch string
  18. NewBranch string
  19. TreePath string
  20. Message string
  21. Files []string // In UUID format.
  22. Signoff bool
  23. Author *IdentityOptions
  24. Committer *IdentityOptions
  25. }
  26. type lazyLocalFileReader struct {
  27. *os.File
  28. localFilename string
  29. counter int
  30. mu sync.Mutex
  31. }
  32. var _ LazyReadSeeker = (*lazyLocalFileReader)(nil)
  33. func (l *lazyLocalFileReader) Close() error {
  34. l.mu.Lock()
  35. defer l.mu.Unlock()
  36. if l.counter > 0 {
  37. l.counter--
  38. if l.counter == 0 {
  39. if err := l.File.Close(); err != nil {
  40. return fmt.Errorf("close file %s: %w", l.localFilename, err)
  41. }
  42. l.File = nil
  43. }
  44. return nil
  45. }
  46. return fmt.Errorf("file %s already closed", l.localFilename)
  47. }
  48. func (l *lazyLocalFileReader) OpenLazyReader() error {
  49. l.mu.Lock()
  50. defer l.mu.Unlock()
  51. if l.File != nil {
  52. l.counter++
  53. return nil
  54. }
  55. file, err := os.Open(l.localFilename)
  56. if err != nil {
  57. return err
  58. }
  59. l.File = file
  60. l.counter = 1
  61. return nil
  62. }
  63. // UploadRepoFiles uploads files to the given repository
  64. func UploadRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *user_model.User, opts *UploadRepoFileOptions) error {
  65. if len(opts.Files) == 0 {
  66. return nil
  67. }
  68. uploads, err := repo_model.GetUploadsByUUIDs(ctx, opts.Files)
  69. if err != nil {
  70. return fmt.Errorf("GetUploadsByUUIDs [uuids: %v]: %w", opts.Files, err)
  71. }
  72. changeOpts := &ChangeRepoFilesOptions{
  73. LastCommitID: opts.LastCommitID,
  74. OldBranch: opts.OldBranch,
  75. NewBranch: opts.NewBranch,
  76. Message: opts.Message,
  77. Signoff: opts.Signoff,
  78. Author: opts.Author,
  79. Committer: opts.Committer,
  80. }
  81. for _, upload := range uploads {
  82. changeOpts.Files = append(changeOpts.Files, &ChangeRepoFile{
  83. Operation: "upload",
  84. TreePath: path.Join(opts.TreePath, upload.Name),
  85. ContentReader: &lazyLocalFileReader{localFilename: upload.LocalPath()},
  86. })
  87. }
  88. _, err = ChangeRepoFiles(ctx, repo, doer, changeOpts)
  89. if err != nil {
  90. return err
  91. }
  92. if err := repo_model.DeleteUploads(ctx, uploads...); err != nil {
  93. log.Error("DeleteUploads: %v", err)
  94. }
  95. return nil
  96. }