gitea源码

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. // Copyright 2021 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package repo
  4. import (
  5. "context"
  6. "time"
  7. "code.gitea.io/gitea/models/db"
  8. "code.gitea.io/gitea/modules/log"
  9. "code.gitea.io/gitea/modules/optional"
  10. "code.gitea.io/gitea/modules/timeutil"
  11. "code.gitea.io/gitea/modules/util"
  12. "xorm.io/builder"
  13. )
  14. // PushMirror represents mirror information of a repository.
  15. type PushMirror struct {
  16. ID int64 `xorm:"pk autoincr"`
  17. RepoID int64 `xorm:"INDEX"`
  18. Repo *Repository `xorm:"-"`
  19. RemoteName string
  20. RemoteAddress string `xorm:"VARCHAR(2048)"`
  21. SyncOnCommit bool `xorm:"NOT NULL DEFAULT true"`
  22. Interval time.Duration
  23. CreatedUnix timeutil.TimeStamp `xorm:"created"`
  24. LastUpdateUnix timeutil.TimeStamp `xorm:"INDEX last_update"`
  25. LastError string `xorm:"text"`
  26. }
  27. type PushMirrorOptions struct {
  28. db.ListOptions
  29. ID int64
  30. RepoID int64
  31. RemoteName string
  32. }
  33. func (opts PushMirrorOptions) ToConds() builder.Cond {
  34. cond := builder.NewCond()
  35. if opts.RepoID > 0 {
  36. cond = cond.And(builder.Eq{"repo_id": opts.RepoID})
  37. }
  38. if opts.RemoteName != "" {
  39. cond = cond.And(builder.Eq{"remote_name": opts.RemoteName})
  40. }
  41. if opts.ID > 0 {
  42. cond = cond.And(builder.Eq{"id": opts.ID})
  43. }
  44. return cond
  45. }
  46. func init() {
  47. db.RegisterModel(new(PushMirror))
  48. }
  49. // GetRepository returns the path of the repository.
  50. func (m *PushMirror) GetRepository(ctx context.Context) *Repository {
  51. if m.Repo != nil {
  52. return m.Repo
  53. }
  54. var err error
  55. m.Repo, err = GetRepositoryByID(ctx, m.RepoID)
  56. if err != nil {
  57. log.Error("getRepositoryByID[%d]: %v", m.ID, err)
  58. }
  59. return m.Repo
  60. }
  61. // GetRemoteName returns the name of the remote.
  62. func (m *PushMirror) GetRemoteName() string {
  63. return m.RemoteName
  64. }
  65. // UpdatePushMirror updates the push-mirror
  66. func UpdatePushMirror(ctx context.Context, m *PushMirror) error {
  67. _, err := db.GetEngine(ctx).ID(m.ID).AllCols().Update(m)
  68. return err
  69. }
  70. // UpdatePushMirrorInterval updates the push-mirror
  71. func UpdatePushMirrorInterval(ctx context.Context, m *PushMirror) error {
  72. _, err := db.GetEngine(ctx).ID(m.ID).Cols("interval").Update(m)
  73. return err
  74. }
  75. func DeletePushMirrors(ctx context.Context, opts PushMirrorOptions) error {
  76. if opts.RepoID > 0 {
  77. _, err := db.Delete[PushMirror](ctx, opts)
  78. return err
  79. }
  80. return util.NewInvalidArgumentErrorf("repoID required and must be set")
  81. }
  82. type findPushMirrorOptions struct {
  83. db.ListOptions
  84. RepoID int64
  85. SyncOnCommit optional.Option[bool]
  86. }
  87. func (opts findPushMirrorOptions) ToConds() builder.Cond {
  88. cond := builder.NewCond()
  89. if opts.RepoID > 0 {
  90. cond = cond.And(builder.Eq{"repo_id": opts.RepoID})
  91. }
  92. if opts.SyncOnCommit.Has() {
  93. cond = cond.And(builder.Eq{"sync_on_commit": opts.SyncOnCommit.Value()})
  94. }
  95. return cond
  96. }
  97. // GetPushMirrorsByRepoID returns push-mirror information of a repository.
  98. func GetPushMirrorsByRepoID(ctx context.Context, repoID int64, listOptions db.ListOptions) ([]*PushMirror, int64, error) {
  99. return db.FindAndCount[PushMirror](ctx, findPushMirrorOptions{
  100. ListOptions: listOptions,
  101. RepoID: repoID,
  102. })
  103. }
  104. func GetPushMirrorByIDAndRepoID(ctx context.Context, id, repoID int64) (*PushMirror, bool, error) {
  105. var pushMirror PushMirror
  106. has, err := db.GetEngine(ctx).Where("id = ?", id).And("repo_id = ?", repoID).Get(&pushMirror)
  107. if !has || err != nil {
  108. return nil, has, err
  109. }
  110. return &pushMirror, true, nil
  111. }
  112. // GetPushMirrorsSyncedOnCommit returns push-mirrors for this repo that should be updated by new commits
  113. func GetPushMirrorsSyncedOnCommit(ctx context.Context, repoID int64) ([]*PushMirror, error) {
  114. return db.Find[PushMirror](ctx, findPushMirrorOptions{
  115. RepoID: repoID,
  116. SyncOnCommit: optional.Some(true),
  117. })
  118. }
  119. // PushMirrorsIterate iterates all push-mirror repositories.
  120. func PushMirrorsIterate(ctx context.Context, limit int, f func(idx int, bean any) error) error {
  121. sess := db.GetEngine(ctx).
  122. Table("push_mirror").
  123. Join("INNER", "`repository`", "`repository`.id = `push_mirror`.repo_id").
  124. Where("`push_mirror`.last_update + (`push_mirror`.`interval` / ?) <= ?", time.Second, time.Now().Unix()).
  125. And("`push_mirror`.`interval` != 0").
  126. And("`repository`.is_archived = ?", false).
  127. OrderBy("last_update ASC")
  128. if limit > 0 {
  129. sess = sess.Limit(limit)
  130. }
  131. return sess.Iterate(new(PushMirror), f)
  132. }