mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 21:28:11 +09:00 
			
		
		
		
	Move more functions to db.Find (#28419)
Following #28220 This PR move more functions to use `db.Find`. --------- Co-authored-by: delvh <dev.lh@web.de>
This commit is contained in:
		| @@ -157,10 +157,10 @@ func runRepoSyncReleases(_ *cli.Context) error { | ||||
| } | ||||
|  | ||||
| func getReleaseCount(ctx context.Context, id int64) (int64, error) { | ||||
| 	return repo_model.GetReleaseCountByRepoID( | ||||
| 	return db.Count[repo_model.Release]( | ||||
| 		ctx, | ||||
| 		id, | ||||
| 		repo_model.FindReleasesOptions{ | ||||
| 			RepoID:      id, | ||||
| 			IncludeTags: true, | ||||
| 		}, | ||||
| 	) | ||||
|   | ||||
| @@ -11,21 +11,13 @@ import ( | ||||
|  | ||||
| 	"code.gitea.io/gitea/models/db" | ||||
| 	user_model "code.gitea.io/gitea/models/user" | ||||
| 	"code.gitea.io/gitea/modules/log" | ||||
| 	"code.gitea.io/gitea/modules/timeutil" | ||||
|  | ||||
| 	"github.com/keybase/go-crypto/openpgp" | ||||
| 	"github.com/keybase/go-crypto/openpgp/packet" | ||||
| 	"xorm.io/xorm" | ||||
| 	"xorm.io/builder" | ||||
| ) | ||||
|  | ||||
| //   __________________  ________   ____  __. | ||||
| //  /  _____/\______   \/  _____/  |    |/ _|____ ___.__. | ||||
| // /   \  ___ |     ___/   \  ___  |      <_/ __ <   |  | | ||||
| // \    \_\  \|    |   \    \_\  \ |    |  \  ___/\___  | | ||||
| //	\______  /|____|    \______  / |____|__ \___  > ____| | ||||
| //				 \/                  \/          \/   \/\/ | ||||
|  | ||||
| // GPGKey represents a GPG key. | ||||
| type GPGKey struct { | ||||
| 	ID                int64              `xorm:"pk autoincr"` | ||||
| @@ -54,12 +46,11 @@ func (key *GPGKey) BeforeInsert() { | ||||
| 	key.AddedUnix = timeutil.TimeStampNow() | ||||
| } | ||||
|  | ||||
| // AfterLoad is invoked from XORM after setting the values of all fields of this object. | ||||
| func (key *GPGKey) AfterLoad(session *xorm.Session) { | ||||
| 	err := session.Where("primary_key_id=?", key.KeyID).Find(&key.SubsKey) | ||||
| 	if err != nil { | ||||
| 		log.Error("Find Sub GPGkeys[%s]: %v", key.KeyID, err) | ||||
| func (key *GPGKey) LoadSubKeys(ctx context.Context) error { | ||||
| 	if err := db.GetEngine(ctx).Where("primary_key_id=?", key.KeyID).Find(&key.SubsKey); err != nil { | ||||
| 		return fmt.Errorf("find Sub GPGkeys[%s]: %v", key.KeyID, err) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // PaddedKeyID show KeyID padded to 16 characters | ||||
| @@ -76,20 +67,26 @@ func PaddedKeyID(keyID string) string { | ||||
| 	return zeros[0:16-len(keyID)] + keyID | ||||
| } | ||||
|  | ||||
| // ListGPGKeys returns a list of public keys belongs to given user. | ||||
| func ListGPGKeys(ctx context.Context, uid int64, listOptions db.ListOptions) ([]*GPGKey, error) { | ||||
| 	sess := db.GetEngine(ctx).Table(&GPGKey{}).Where("owner_id=? AND primary_key_id=''", uid) | ||||
| 	if listOptions.Page != 0 { | ||||
| 		sess = db.SetSessionPagination(sess, &listOptions) | ||||
| type FindGPGKeyOptions struct { | ||||
| 	db.ListOptions | ||||
| 	OwnerID        int64 | ||||
| 	KeyID          string | ||||
| 	IncludeSubKeys bool | ||||
| } | ||||
|  | ||||
| 	keys := make([]*GPGKey, 0, 2) | ||||
| 	return keys, sess.Find(&keys) | ||||
| func (opts FindGPGKeyOptions) ToConds() builder.Cond { | ||||
| 	cond := builder.NewCond() | ||||
| 	if !opts.IncludeSubKeys { | ||||
| 		cond = cond.And(builder.Eq{"primary_key_id": ""}) | ||||
| 	} | ||||
|  | ||||
| // CountUserGPGKeys return number of gpg keys a user own | ||||
| func CountUserGPGKeys(ctx context.Context, userID int64) (int64, error) { | ||||
| 	return db.GetEngine(ctx).Where("owner_id=? AND primary_key_id=''", userID).Count(&GPGKey{}) | ||||
| 	if opts.OwnerID > 0 { | ||||
| 		cond = cond.And(builder.Eq{"owner_id": opts.OwnerID}) | ||||
| 	} | ||||
| 	if opts.KeyID != "" { | ||||
| 		cond = cond.And(builder.Eq{"key_id": opts.KeyID}) | ||||
| 	} | ||||
| 	return cond | ||||
| } | ||||
|  | ||||
| func GetGPGKeyForUserByID(ctx context.Context, ownerID, keyID int64) (*GPGKey, error) { | ||||
| @@ -103,12 +100,6 @@ func GetGPGKeyForUserByID(ctx context.Context, ownerID, keyID int64) (*GPGKey, e | ||||
| 	return key, nil | ||||
| } | ||||
|  | ||||
| // GetGPGKeysByKeyID returns public key by given ID. | ||||
| func GetGPGKeysByKeyID(ctx context.Context, keyID string) ([]*GPGKey, error) { | ||||
| 	keys := make([]*GPGKey, 0, 1) | ||||
| 	return keys, db.GetEngine(ctx).Where("key_id=?", keyID).Find(&keys) | ||||
| } | ||||
|  | ||||
| // GPGKeyToEntity retrieve the imported key and the traducted entity | ||||
| func GPGKeyToEntity(ctx context.Context, k *GPGKey) (*openpgp.Entity, error) { | ||||
| 	impKey, err := GetGPGImportByKeyID(ctx, k.KeyID) | ||||
|   | ||||
| @@ -166,7 +166,9 @@ func ParseCommitWithSignature(ctx context.Context, c *git.Commit) *CommitVerific | ||||
|  | ||||
| 	// Now try to associate the signature with the committer, if present | ||||
| 	if committer.ID != 0 { | ||||
| 		keys, err := ListGPGKeys(ctx, committer.ID, db.ListOptions{}) | ||||
| 		keys, err := db.Find[GPGKey](ctx, FindGPGKeyOptions{ | ||||
| 			OwnerID: committer.ID, | ||||
| 		}) | ||||
| 		if err != nil { // Skipping failed to get gpg keys of user | ||||
| 			log.Error("ListGPGKeys: %v", err) | ||||
| 			return &CommitVerification{ | ||||
| @@ -176,6 +178,15 @@ func ParseCommitWithSignature(ctx context.Context, c *git.Commit) *CommitVerific | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		if err := GPGKeyList(keys).LoadSubKeys(ctx); err != nil { | ||||
| 			log.Error("LoadSubKeys: %v", err) | ||||
| 			return &CommitVerification{ | ||||
| 				CommittingUser: committer, | ||||
| 				Verified:       false, | ||||
| 				Reason:         "gpg.error.failed_retrieval_gpg_keys", | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		committerEmailAddresses, _ := user_model.GetEmailAddresses(ctx, committer.ID) | ||||
| 		activated := false | ||||
| 		for _, e := range committerEmailAddresses { | ||||
| @@ -392,7 +403,10 @@ func hashAndVerifyForKeyID(ctx context.Context, sig *packet.Signature, payload s | ||||
| 	if keyID == "" { | ||||
| 		return nil | ||||
| 	} | ||||
| 	keys, err := GetGPGKeysByKeyID(ctx, keyID) | ||||
| 	keys, err := db.Find[GPGKey](ctx, FindGPGKeyOptions{ | ||||
| 		KeyID:          keyID, | ||||
| 		IncludeSubKeys: true, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		log.Error("GetGPGKeysByKeyID: %v", err) | ||||
| 		return &CommitVerification{ | ||||
| @@ -407,7 +421,10 @@ func hashAndVerifyForKeyID(ctx context.Context, sig *packet.Signature, payload s | ||||
| 	for _, key := range keys { | ||||
| 		var primaryKeys []*GPGKey | ||||
| 		if key.PrimaryKeyID != "" { | ||||
| 			primaryKeys, err = GetGPGKeysByKeyID(ctx, key.PrimaryKeyID) | ||||
| 			primaryKeys, err = db.Find[GPGKey](ctx, FindGPGKeyOptions{ | ||||
| 				KeyID:          key.PrimaryKeyID, | ||||
| 				IncludeSubKeys: true, | ||||
| 			}) | ||||
| 			if err != nil { | ||||
| 				log.Error("GetGPGKeysByKeyID: %v", err) | ||||
| 				return &CommitVerification{ | ||||
|   | ||||
							
								
								
									
										38
									
								
								models/asymkey/gpg_key_list.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								models/asymkey/gpg_key_list.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| // Copyright 2023 The Gitea Authors. All rights reserved. | ||||
| // SPDX-License-Identifier: MIT | ||||
|  | ||||
| package asymkey | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
|  | ||||
| 	"code.gitea.io/gitea/models/db" | ||||
| ) | ||||
|  | ||||
| type GPGKeyList []*GPGKey | ||||
|  | ||||
| func (keys GPGKeyList) keyIDs() []string { | ||||
| 	ids := make([]string, len(keys)) | ||||
| 	for i, key := range keys { | ||||
| 		ids[i] = key.KeyID | ||||
| 	} | ||||
| 	return ids | ||||
| } | ||||
|  | ||||
| func (keys GPGKeyList) LoadSubKeys(ctx context.Context) error { | ||||
| 	subKeys := make([]*GPGKey, 0, len(keys)) | ||||
| 	if err := db.GetEngine(ctx).In("primary_key_id", keys.keyIDs()).Find(&subKeys); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	subKeysMap := make(map[string][]*GPGKey, len(subKeys)) | ||||
| 	for _, key := range subKeys { | ||||
| 		subKeysMap[key.PrimaryKeyID] = append(subKeysMap[key.PrimaryKeyID], key) | ||||
| 	} | ||||
|  | ||||
| 	for _, key := range keys { | ||||
| 		if subKeys, ok := subKeysMap[key.KeyID]; ok { | ||||
| 			key.SubsKey = subKeys | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| @@ -197,10 +197,10 @@ func (opts FindPublicKeyOptions) ToConds() builder.Cond { | ||||
| 		cond = cond.And(builder.Eq{"fingerprint": opts.Fingerprint}) | ||||
| 	} | ||||
| 	if len(opts.KeyTypes) > 0 { | ||||
| 		cond = cond.And(builder.In("type", opts.KeyTypes)) | ||||
| 		cond = cond.And(builder.In("`type`", opts.KeyTypes)) | ||||
| 	} | ||||
| 	if opts.NotKeytype > 0 { | ||||
| 		cond = cond.And(builder.Neq{"type": opts.NotKeytype}) | ||||
| 		cond = cond.And(builder.Neq{"`type`": opts.NotKeytype}) | ||||
| 	} | ||||
| 	if opts.LoginSourceID > 0 { | ||||
| 		cond = cond.And(builder.Eq{"login_source_id": opts.LoginSourceID}) | ||||
|   | ||||
| @@ -15,15 +15,6 @@ import ( | ||||
| 	"code.gitea.io/gitea/modules/util" | ||||
| ) | ||||
|  | ||||
| // __________       .__              .__             .__ | ||||
| // \______   _______|__| ____   ____ |_____________  |  |   ______ | ||||
| //  |     ___\_  __ |  |/    \_/ ___\|  \____ \__  \ |  |  /  ___/ | ||||
| //  |    |    |  | \|  |   |  \  \___|  |  |_> / __ \|  |__\___ \ | ||||
| //  |____|    |__|  |__|___|  /\___  |__|   __(____  |____/____  > | ||||
| //                          \/     \/   |__|       \/          \/ | ||||
| // | ||||
| // This file contains functions related to principals | ||||
|  | ||||
| // AddPrincipalKey adds new principal to database and authorized_principals file. | ||||
| func AddPrincipalKey(ctx context.Context, ownerID int64, content string, authSourceID int64) (*PublicKey, error) { | ||||
| 	dbCtx, committer, err := db.TxContext(ctx) | ||||
| @@ -103,17 +94,3 @@ func CheckPrincipalKeyString(ctx context.Context, user *user_model.User, content | ||||
|  | ||||
| 	return "", fmt.Errorf("didn't match allowed principals: %s", setting.SSH.AuthorizedPrincipalsAllow) | ||||
| } | ||||
|  | ||||
| // ListPrincipalKeys returns a list of principals belongs to given user. | ||||
| func ListPrincipalKeys(ctx context.Context, uid int64, listOptions db.ListOptions) ([]*PublicKey, error) { | ||||
| 	sess := db.GetEngine(ctx).Where("owner_id = ? AND type = ?", uid, KeyTypePrincipal) | ||||
| 	if listOptions.Page != 0 { | ||||
| 		sess = db.SetSessionPagination(sess, &listOptions) | ||||
|  | ||||
| 		keys := make([]*PublicKey, 0, listOptions.PageSize) | ||||
| 		return keys, sess.Find(&keys) | ||||
| 	} | ||||
|  | ||||
| 	keys := make([]*PublicKey, 0, 5) | ||||
| 	return keys, sess.Find(&keys) | ||||
| } | ||||
|   | ||||
| @@ -13,7 +13,6 @@ import ( | ||||
| 	"code.gitea.io/gitea/modules/util" | ||||
|  | ||||
| 	"github.com/go-webauthn/webauthn/webauthn" | ||||
| 	"xorm.io/xorm" | ||||
| ) | ||||
|  | ||||
| // ErrWebAuthnCredentialNotExist represents a "ErrWebAuthnCRedentialNotExist" kind of error. | ||||
| @@ -83,7 +82,7 @@ func (cred *WebAuthnCredential) BeforeUpdate() { | ||||
| } | ||||
|  | ||||
| // AfterLoad is invoked from XORM after setting the values of all fields of this object. | ||||
| func (cred *WebAuthnCredential) AfterLoad(session *xorm.Session) { | ||||
| func (cred *WebAuthnCredential) AfterLoad() { | ||||
| 	cred.LowerName = strings.ToLower(cred.Name) | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -21,17 +21,9 @@ const ( | ||||
| // Paginator is the base for different ListOptions types | ||||
| type Paginator interface { | ||||
| 	GetSkipTake() (skip, take int) | ||||
| 	GetStartEnd() (start, end int) | ||||
| 	IsListAll() bool | ||||
| } | ||||
|  | ||||
| // GetPaginatedSession creates a paginated database session | ||||
| func GetPaginatedSession(p Paginator) *xorm.Session { | ||||
| 	skip, take := p.GetSkipTake() | ||||
|  | ||||
| 	return x.Limit(take, skip) | ||||
| } | ||||
|  | ||||
| // SetSessionPagination sets pagination for a database session | ||||
| func SetSessionPagination(sess Engine, p Paginator) *xorm.Session { | ||||
| 	skip, take := p.GetSkipTake() | ||||
| @@ -39,13 +31,6 @@ func SetSessionPagination(sess Engine, p Paginator) *xorm.Session { | ||||
| 	return sess.Limit(take, skip) | ||||
| } | ||||
|  | ||||
| // SetEnginePagination sets pagination for a database engine | ||||
| func SetEnginePagination(e Engine, p Paginator) Engine { | ||||
| 	skip, take := p.GetSkipTake() | ||||
|  | ||||
| 	return e.Limit(take, skip) | ||||
| } | ||||
|  | ||||
| // ListOptions options to paginate results | ||||
| type ListOptions struct { | ||||
| 	PageSize int | ||||
| @@ -66,13 +51,6 @@ func (opts *ListOptions) GetSkipTake() (skip, take int) { | ||||
| 	return (opts.Page - 1) * opts.PageSize, opts.PageSize | ||||
| } | ||||
|  | ||||
| // GetStartEnd returns the start and end of the ListOptions | ||||
| func (opts *ListOptions) GetStartEnd() (start, end int) { | ||||
| 	start, take := opts.GetSkipTake() | ||||
| 	end = start + take | ||||
| 	return start, end | ||||
| } | ||||
|  | ||||
| func (opts ListOptions) GetPage() int { | ||||
| 	return opts.Page | ||||
| } | ||||
| @@ -135,11 +113,6 @@ func (opts *AbsoluteListOptions) GetSkipTake() (skip, take int) { | ||||
| 	return opts.skip, opts.take | ||||
| } | ||||
|  | ||||
| // GetStartEnd returns the start and end values | ||||
| func (opts *AbsoluteListOptions) GetStartEnd() (start, end int) { | ||||
| 	return opts.skip, opts.skip + opts.take | ||||
| } | ||||
|  | ||||
| // FindOptions represents a find options | ||||
| type FindOptions interface { | ||||
| 	GetPage() int | ||||
| @@ -148,15 +121,34 @@ type FindOptions interface { | ||||
| 	ToConds() builder.Cond | ||||
| } | ||||
|  | ||||
| type JoinFunc func(sess Engine) error | ||||
|  | ||||
| type FindOptionsJoin interface { | ||||
| 	ToJoins() []JoinFunc | ||||
| } | ||||
|  | ||||
| type FindOptionsOrder interface { | ||||
| 	ToOrders() string | ||||
| } | ||||
|  | ||||
| // Find represents a common find function which accept an options interface | ||||
| func Find[T any](ctx context.Context, opts FindOptions) ([]*T, error) { | ||||
| 	sess := GetEngine(ctx).Where(opts.ToConds()) | ||||
| 	sess := GetEngine(ctx) | ||||
|  | ||||
| 	if joinOpt, ok := opts.(FindOptionsJoin); ok && len(joinOpt.ToJoins()) > 0 { | ||||
| 		for _, joinFunc := range joinOpt.ToJoins() { | ||||
| 			if err := joinFunc(sess); err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	sess = sess.Where(opts.ToConds()) | ||||
| 	page, pageSize := opts.GetPage(), opts.GetPageSize() | ||||
| 	if !opts.IsListAll() && pageSize > 0 && page >= 1 { | ||||
| 	if !opts.IsListAll() && pageSize > 0 { | ||||
| 		if page == 0 { | ||||
| 			page = 1 | ||||
| 		} | ||||
| 		sess.Limit(pageSize, (page-1)*pageSize) | ||||
| 	} | ||||
| 	if newOpt, ok := opts.(FindOptionsOrder); ok && newOpt.ToOrders() != "" { | ||||
| @@ -176,8 +168,17 @@ func Find[T any](ctx context.Context, opts FindOptions) ([]*T, error) { | ||||
|  | ||||
| // Count represents a common count function which accept an options interface | ||||
| func Count[T any](ctx context.Context, opts FindOptions) (int64, error) { | ||||
| 	sess := GetEngine(ctx) | ||||
| 	if joinOpt, ok := opts.(FindOptionsJoin); ok && len(joinOpt.ToJoins()) > 0 { | ||||
| 		for _, joinFunc := range joinOpt.ToJoins() { | ||||
| 			if err := joinFunc(sess); err != nil { | ||||
| 				return 0, err | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	var object T | ||||
| 	return GetEngine(ctx).Where(opts.ToConds()).Count(&object) | ||||
| 	return sess.Where(opts.ToConds()).Count(&object) | ||||
| } | ||||
|  | ||||
| // FindAndCount represents a common findandcount function which accept an options interface | ||||
|   | ||||
| @@ -52,11 +52,8 @@ func TestPaginator(t *testing.T) { | ||||
|  | ||||
| 	for _, c := range cases { | ||||
| 		skip, take := c.Paginator.GetSkipTake() | ||||
| 		start, end := c.Paginator.GetStartEnd() | ||||
|  | ||||
| 		assert.Equal(t, c.Skip, skip) | ||||
| 		assert.Equal(t, c.Take, take) | ||||
| 		assert.Equal(t, c.Start, start) | ||||
| 		assert.Equal(t, c.End, end) | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -28,7 +28,6 @@ import ( | ||||
| 	"code.gitea.io/gitea/modules/util" | ||||
|  | ||||
| 	"xorm.io/builder" | ||||
| 	"xorm.io/xorm" | ||||
| ) | ||||
|  | ||||
| // ErrCommentNotExist represents a "CommentNotExist" kind of error. | ||||
| @@ -338,7 +337,7 @@ func (c *Comment) BeforeUpdate() { | ||||
| } | ||||
|  | ||||
| // AfterLoad is invoked from XORM after setting the values of all fields of this object. | ||||
| func (c *Comment) AfterLoad(session *xorm.Session) { | ||||
| func (c *Comment) AfterLoad() { | ||||
| 	c.Patch = c.PatchQuoted | ||||
| 	if len(c.PatchQuoted) > 0 && c.PatchQuoted[0] == '"' { | ||||
| 		unquoted, err := strconv.Unquote(c.PatchQuoted) | ||||
|   | ||||
| @@ -94,7 +94,7 @@ type FindTrackedTimesOptions struct { | ||||
| } | ||||
|  | ||||
| // toCond will convert each condition into a xorm-Cond | ||||
| func (opts *FindTrackedTimesOptions) toCond() builder.Cond { | ||||
| func (opts *FindTrackedTimesOptions) ToConds() builder.Cond { | ||||
| 	cond := builder.NewCond().And(builder.Eq{"tracked_time.deleted": false}) | ||||
| 	if opts.IssueID != 0 { | ||||
| 		cond = cond.And(builder.Eq{"issue_id": opts.IssueID}) | ||||
| @@ -117,6 +117,18 @@ func (opts *FindTrackedTimesOptions) toCond() builder.Cond { | ||||
| 	return cond | ||||
| } | ||||
|  | ||||
| func (opts *FindTrackedTimesOptions) ToJoins() []db.JoinFunc { | ||||
| 	if opts.RepositoryID > 0 || opts.MilestoneID > 0 { | ||||
| 		return []db.JoinFunc{ | ||||
| 			func(e db.Engine) error { | ||||
| 				e.Join("INNER", "issue", "issue.id = tracked_time.issue_id") | ||||
| 				return nil | ||||
| 			}, | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // toSession will convert the given options to a xorm Session by using the conditions from toCond and joining with issue table if required | ||||
| func (opts *FindTrackedTimesOptions) toSession(e db.Engine) db.Engine { | ||||
| 	sess := e | ||||
| @@ -124,10 +136,10 @@ func (opts *FindTrackedTimesOptions) toSession(e db.Engine) db.Engine { | ||||
| 		sess = e.Join("INNER", "issue", "issue.id = tracked_time.issue_id") | ||||
| 	} | ||||
|  | ||||
| 	sess = sess.Where(opts.toCond()) | ||||
| 	sess = sess.Where(opts.ToConds()) | ||||
|  | ||||
| 	if opts.Page != 0 { | ||||
| 		sess = db.SetEnginePagination(sess, opts) | ||||
| 		sess = db.SetSessionPagination(sess, opts) | ||||
| 	} | ||||
|  | ||||
| 	return sess | ||||
| @@ -141,7 +153,7 @@ func GetTrackedTimes(ctx context.Context, options *FindTrackedTimesOptions) (tra | ||||
|  | ||||
| // CountTrackedTimes returns count of tracked times that fit to the given options. | ||||
| func CountTrackedTimes(ctx context.Context, opts *FindTrackedTimesOptions) (int64, error) { | ||||
| 	sess := db.GetEngine(ctx).Where(opts.toCond()) | ||||
| 	sess := db.GetEngine(ctx).Where(opts.ToConds()) | ||||
| 	if opts.RepositoryID > 0 || opts.MilestoneID > 0 { | ||||
| 		sess = sess.Join("INNER", "issue", "issue.id = tracked_time.issue_id") | ||||
| 	} | ||||
|   | ||||
| @@ -111,7 +111,7 @@ type FindRepoArchiversOption struct { | ||||
| 	OlderThan time.Duration | ||||
| } | ||||
|  | ||||
| func (opts FindRepoArchiversOption) toConds() builder.Cond { | ||||
| func (opts FindRepoArchiversOption) ToConds() builder.Cond { | ||||
| 	cond := builder.NewCond() | ||||
| 	if opts.OlderThan > 0 { | ||||
| 		cond = cond.And(builder.Lt{"created_unix": time.Now().Add(-opts.OlderThan).Unix()}) | ||||
| @@ -119,15 +119,8 @@ func (opts FindRepoArchiversOption) toConds() builder.Cond { | ||||
| 	return cond | ||||
| } | ||||
|  | ||||
| // FindRepoArchives find repo archivers | ||||
| func FindRepoArchives(ctx context.Context, opts FindRepoArchiversOption) ([]*RepoArchiver, error) { | ||||
| 	archivers := make([]*RepoArchiver, 0, opts.PageSize) | ||||
| 	start, limit := opts.GetSkipTake() | ||||
| 	err := db.GetEngine(ctx).Where(opts.toConds()). | ||||
| 		Asc("created_unix"). | ||||
| 		Limit(limit, start). | ||||
| 		Find(&archivers) | ||||
| 	return archivers, err | ||||
| func (opts FindRepoArchiversOption) ToOrders() string { | ||||
| 	return "created_unix ASC" | ||||
| } | ||||
|  | ||||
| // SetArchiveRepoState sets if a repo is archived | ||||
|   | ||||
| @@ -11,8 +11,9 @@ import ( | ||||
| 	"code.gitea.io/gitea/models/perm" | ||||
| 	"code.gitea.io/gitea/models/unit" | ||||
| 	user_model "code.gitea.io/gitea/models/user" | ||||
| 	"code.gitea.io/gitea/modules/log" | ||||
| 	"code.gitea.io/gitea/modules/timeutil" | ||||
|  | ||||
| 	"xorm.io/builder" | ||||
| ) | ||||
|  | ||||
| // Collaboration represent the relation between an individual and a repository. | ||||
| @@ -37,35 +38,38 @@ type Collaborator struct { | ||||
|  | ||||
| // GetCollaborators returns the collaborators for a repository | ||||
| func GetCollaborators(ctx context.Context, repoID int64, listOptions db.ListOptions) ([]*Collaborator, error) { | ||||
| 	collaborations, err := getCollaborations(ctx, repoID, listOptions) | ||||
| 	collaborations, err := db.Find[Collaboration](ctx, FindCollaborationOptions{ | ||||
| 		ListOptions: listOptions, | ||||
| 		RepoID:      repoID, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("getCollaborations: %w", err) | ||||
| 		return nil, fmt.Errorf("db.Find[Collaboration]: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	collaborators := make([]*Collaborator, 0, len(collaborations)) | ||||
| 	userIDs := make([]int64, 0, len(collaborations)) | ||||
| 	for _, c := range collaborations { | ||||
| 		user, err := user_model.GetUserByID(ctx, c.UserID) | ||||
| 		if err != nil { | ||||
| 			if user_model.IsErrUserNotExist(err) { | ||||
| 				log.Warn("Inconsistent DB: User: %d is listed as collaborator of %-v but does not exist", c.UserID, repoID) | ||||
| 				user = user_model.NewGhostUser() | ||||
| 			} else { | ||||
| 				return nil, err | ||||
| 		userIDs = append(userIDs, c.UserID) | ||||
| 	} | ||||
|  | ||||
| 	usersMap := make(map[int64]*user_model.User) | ||||
| 	if err := db.GetEngine(ctx).In("id", userIDs).Find(&usersMap); err != nil { | ||||
| 		return nil, fmt.Errorf("Find users map by user ids: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	for _, c := range collaborations { | ||||
| 		u := usersMap[c.UserID] | ||||
| 		if u == nil { | ||||
| 			u = user_model.NewGhostUser() | ||||
| 		} | ||||
| 		collaborators = append(collaborators, &Collaborator{ | ||||
| 			User:          user, | ||||
| 			User:          u, | ||||
| 			Collaboration: c, | ||||
| 		}) | ||||
| 	} | ||||
| 	return collaborators, nil | ||||
| } | ||||
|  | ||||
| // CountCollaborators returns total number of collaborators for a repository | ||||
| func CountCollaborators(ctx context.Context, repoID int64) (int64, error) { | ||||
| 	return db.GetEngine(ctx).Where("repo_id = ? ", repoID).Count(&Collaboration{}) | ||||
| } | ||||
|  | ||||
| // GetCollaboration get collaboration for a repository id with a user id | ||||
| func GetCollaboration(ctx context.Context, repoID, uid int64) (*Collaboration, error) { | ||||
| 	collaboration := &Collaboration{ | ||||
| @@ -84,18 +88,13 @@ func IsCollaborator(ctx context.Context, repoID, userID int64) (bool, error) { | ||||
| 	return db.GetEngine(ctx).Get(&Collaboration{RepoID: repoID, UserID: userID}) | ||||
| } | ||||
|  | ||||
| func getCollaborations(ctx context.Context, repoID int64, listOptions db.ListOptions) ([]*Collaboration, error) { | ||||
| 	if listOptions.Page == 0 { | ||||
| 		collaborations := make([]*Collaboration, 0, 8) | ||||
| 		return collaborations, db.GetEngine(ctx).Find(&collaborations, &Collaboration{RepoID: repoID}) | ||||
| type FindCollaborationOptions struct { | ||||
| 	db.ListOptions | ||||
| 	RepoID int64 | ||||
| } | ||||
|  | ||||
| 	e := db.GetEngine(ctx) | ||||
|  | ||||
| 	e = db.SetEnginePagination(e, &listOptions) | ||||
|  | ||||
| 	collaborations := make([]*Collaboration, 0, listOptions.PageSize) | ||||
| 	return collaborations, e.Find(&collaborations, &Collaboration{RepoID: repoID}) | ||||
| func (opts FindCollaborationOptions) ToConds() builder.Cond { | ||||
| 	return builder.And(builder.Eq{"repo_id": opts.RepoID}) | ||||
| } | ||||
|  | ||||
| // ChangeCollaborationAccessMode sets new access mode for the collaboration. | ||||
|   | ||||
| @@ -89,17 +89,23 @@ func TestRepository_CountCollaborators(t *testing.T) { | ||||
| 	assert.NoError(t, unittest.PrepareTestDatabase()) | ||||
|  | ||||
| 	repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4}) | ||||
| 	count, err := repo_model.CountCollaborators(db.DefaultContext, repo1.ID) | ||||
| 	count, err := db.Count[repo_model.Collaboration](db.DefaultContext, repo_model.FindCollaborationOptions{ | ||||
| 		RepoID: repo1.ID, | ||||
| 	}) | ||||
| 	assert.NoError(t, err) | ||||
| 	assert.EqualValues(t, 2, count) | ||||
|  | ||||
| 	repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 22}) | ||||
| 	count, err = repo_model.CountCollaborators(db.DefaultContext, repo2.ID) | ||||
| 	count, err = db.Count[repo_model.Collaboration](db.DefaultContext, repo_model.FindCollaborationOptions{ | ||||
| 		RepoID: repo2.ID, | ||||
| 	}) | ||||
| 	assert.NoError(t, err) | ||||
| 	assert.EqualValues(t, 2, count) | ||||
|  | ||||
| 	// Non-existent repository. | ||||
| 	count, err = repo_model.CountCollaborators(db.DefaultContext, unittest.NonexistentID) | ||||
| 	count, err = db.Count[repo_model.Collaboration](db.DefaultContext, repo_model.FindCollaborationOptions{ | ||||
| 		RepoID: unittest.NonexistentID, | ||||
| 	}) | ||||
| 	assert.NoError(t, err) | ||||
| 	assert.EqualValues(t, 0, count) | ||||
| } | ||||
|   | ||||
| @@ -56,13 +56,16 @@ func GetUserFork(ctx context.Context, repoID, userID int64) (*Repository, error) | ||||
|  | ||||
| // GetForks returns all the forks of the repository | ||||
| func GetForks(ctx context.Context, repo *Repository, listOptions db.ListOptions) ([]*Repository, error) { | ||||
| 	sess := db.GetEngine(ctx) | ||||
|  | ||||
| 	var forks []*Repository | ||||
| 	if listOptions.Page == 0 { | ||||
| 		forks := make([]*Repository, 0, repo.NumForks) | ||||
| 		return forks, db.GetEngine(ctx).Find(&forks, &Repository{ForkID: repo.ID}) | ||||
| 		forks = make([]*Repository, 0, repo.NumForks) | ||||
| 	} else { | ||||
| 		forks = make([]*Repository, 0, listOptions.PageSize) | ||||
| 		sess = db.SetSessionPagination(sess, &listOptions) | ||||
| 	} | ||||
|  | ||||
| 	sess := db.GetPaginatedSession(&listOptions) | ||||
| 	forks := make([]*Repository, 0, listOptions.PageSize) | ||||
| 	return forks, sess.Find(&forks, &Repository{ForkID: repo.ID}) | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -225,6 +225,7 @@ func GetReleaseForRepoByID(ctx context.Context, repoID, id int64) (*Release, err | ||||
| // FindReleasesOptions describes the conditions to Find releases | ||||
| type FindReleasesOptions struct { | ||||
| 	db.ListOptions | ||||
| 	RepoID        int64 | ||||
| 	IncludeDrafts bool | ||||
| 	IncludeTags   bool | ||||
| 	IsPreRelease  util.OptionalBool | ||||
| @@ -233,9 +234,8 @@ type FindReleasesOptions struct { | ||||
| 	HasSha1       util.OptionalBool // useful to find draft releases which are created with existing tags | ||||
| } | ||||
|  | ||||
| func (opts *FindReleasesOptions) toConds(repoID int64) builder.Cond { | ||||
| 	cond := builder.NewCond() | ||||
| 	cond = cond.And(builder.Eq{"repo_id": repoID}) | ||||
| func (opts FindReleasesOptions) ToConds() builder.Cond { | ||||
| 	var cond builder.Cond = builder.Eq{"repo_id": opts.RepoID} | ||||
|  | ||||
| 	if !opts.IncludeDrafts { | ||||
| 		cond = cond.And(builder.Eq{"is_draft": false}) | ||||
| @@ -262,18 +262,8 @@ func (opts *FindReleasesOptions) toConds(repoID int64) builder.Cond { | ||||
| 	return cond | ||||
| } | ||||
|  | ||||
| // GetReleasesByRepoID returns a list of releases of repository. | ||||
| func GetReleasesByRepoID(ctx context.Context, repoID int64, opts FindReleasesOptions) ([]*Release, error) { | ||||
| 	sess := db.GetEngine(ctx). | ||||
| 		Desc("created_unix", "id"). | ||||
| 		Where(opts.toConds(repoID)) | ||||
|  | ||||
| 	if opts.PageSize != 0 { | ||||
| 		sess = db.SetSessionPagination(sess, &opts.ListOptions) | ||||
| 	} | ||||
|  | ||||
| 	rels := make([]*Release, 0, opts.PageSize) | ||||
| 	return rels, sess.Find(&rels) | ||||
| func (opts FindReleasesOptions) ToOrders() string { | ||||
| 	return "created_unix DESC, id DESC" | ||||
| } | ||||
|  | ||||
| // GetTagNamesByRepoID returns a list of release tag names of repository. | ||||
| @@ -286,23 +276,19 @@ func GetTagNamesByRepoID(ctx context.Context, repoID int64) ([]string, error) { | ||||
| 		IncludeDrafts: true, | ||||
| 		IncludeTags:   true, | ||||
| 		HasSha1:       util.OptionalBoolTrue, | ||||
| 		RepoID:        repoID, | ||||
| 	} | ||||
|  | ||||
| 	tags := make([]string, 0) | ||||
| 	sess := db.GetEngine(ctx). | ||||
| 		Table("release"). | ||||
| 		Desc("created_unix", "id"). | ||||
| 		Where(opts.toConds(repoID)). | ||||
| 		Where(opts.ToConds()). | ||||
| 		Cols("tag_name") | ||||
|  | ||||
| 	return tags, sess.Find(&tags) | ||||
| } | ||||
|  | ||||
| // CountReleasesByRepoID returns a number of releases matching FindReleaseOptions and RepoID. | ||||
| func CountReleasesByRepoID(ctx context.Context, repoID int64, opts FindReleasesOptions) (int64, error) { | ||||
| 	return db.GetEngine(ctx).Where(opts.toConds(repoID)).Count(new(Release)) | ||||
| } | ||||
|  | ||||
| // GetLatestReleaseByRepoID returns the latest release for a repository | ||||
| func GetLatestReleaseByRepoID(ctx context.Context, repoID int64) (*Release, error) { | ||||
| 	cond := builder.NewCond(). | ||||
| @@ -325,20 +311,6 @@ func GetLatestReleaseByRepoID(ctx context.Context, repoID int64) (*Release, erro | ||||
| 	return rel, nil | ||||
| } | ||||
|  | ||||
| // GetReleasesByRepoIDAndNames returns a list of releases of repository according repoID and tagNames. | ||||
| func GetReleasesByRepoIDAndNames(ctx context.Context, repoID int64, tagNames []string) (rels []*Release, err error) { | ||||
| 	err = db.GetEngine(ctx). | ||||
| 		In("tag_name", tagNames). | ||||
| 		Desc("created_unix"). | ||||
| 		Find(&rels, Release{RepoID: repoID}) | ||||
| 	return rels, err | ||||
| } | ||||
|  | ||||
| // GetReleaseCountByRepoID returns the count of releases of repository | ||||
| func GetReleaseCountByRepoID(ctx context.Context, repoID int64, opts FindReleasesOptions) (int64, error) { | ||||
| 	return db.GetEngine(ctx).Where(opts.toConds(repoID)).Count(&Release{}) | ||||
| } | ||||
|  | ||||
| type releaseMetaSearch struct { | ||||
| 	ID  []int64 | ||||
| 	Rel []*Release | ||||
|   | ||||
| @@ -536,18 +536,20 @@ func RepoAssignment(ctx *Context) context.CancelFunc { | ||||
| 		ctx.Data["RepoExternalIssuesLink"] = unit.ExternalTrackerConfig().ExternalTrackerURL | ||||
| 	} | ||||
|  | ||||
| 	ctx.Data["NumTags"], err = repo_model.GetReleaseCountByRepoID(ctx, ctx.Repo.Repository.ID, repo_model.FindReleasesOptions{ | ||||
| 	ctx.Data["NumTags"], err = db.Count[repo_model.Release](ctx, repo_model.FindReleasesOptions{ | ||||
| 		IncludeDrafts: true, | ||||
| 		IncludeTags:   true, | ||||
| 		HasSha1:       util.OptionalBoolTrue, // only draft releases which are created with existing tags | ||||
| 		RepoID:        ctx.Repo.Repository.ID, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		ctx.ServerError("GetReleaseCountByRepoID", err) | ||||
| 		return nil | ||||
| 	} | ||||
| 	ctx.Data["NumReleases"], err = repo_model.GetReleaseCountByRepoID(ctx, ctx.Repo.Repository.ID, repo_model.FindReleasesOptions{ | ||||
| 	ctx.Data["NumReleases"], err = db.Count[repo_model.Release](ctx, repo_model.FindReleasesOptions{ | ||||
| 		// only show draft releases for users who can write, read-only users shouldn't see draft releases. | ||||
| 		IncludeDrafts: ctx.Repo.CanWrite(unit_model.TypeReleases), | ||||
| 		RepoID:        ctx.Repo.Repository.ID, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		ctx.ServerError("GetReleaseCountByRepoID", err) | ||||
|   | ||||
| @@ -299,10 +299,11 @@ func SyncReleasesWithTags(ctx context.Context, repo *repo_model.Repository, gitR | ||||
| 		IncludeDrafts: true, | ||||
| 		IncludeTags:   true, | ||||
| 		ListOptions:   db.ListOptions{PageSize: 50}, | ||||
| 		RepoID:        repo.ID, | ||||
| 	} | ||||
| 	for page := 1; ; page++ { | ||||
| 		opts.Page = page | ||||
| 		rels, err := repo_model.GetReleasesByRepoID(gitRepo.Ctx, repo.ID, opts) | ||||
| 		rels, err := db.Find[repo_model.Release](gitRepo.Ctx, opts) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("unable to GetReleasesByRepoID in Repo[%d:%s/%s]: %w", repo.ID, repo.OwnerName, repo.Name, err) | ||||
| 		} | ||||
|   | ||||
| @@ -8,6 +8,7 @@ import ( | ||||
| 	"errors" | ||||
| 	"net/http" | ||||
|  | ||||
| 	"code.gitea.io/gitea/models/db" | ||||
| 	"code.gitea.io/gitea/models/perm" | ||||
| 	access_model "code.gitea.io/gitea/models/perm/access" | ||||
| 	repo_model "code.gitea.io/gitea/models/repo" | ||||
| @@ -53,7 +54,9 @@ func ListCollaborators(ctx *context.APIContext) { | ||||
| 	//   "404": | ||||
| 	//     "$ref": "#/responses/notFound" | ||||
|  | ||||
| 	count, err := repo_model.CountCollaborators(ctx, ctx.Repo.Repository.ID) | ||||
| 	count, err := db.Count[repo_model.Collaboration](ctx, repo_model.FindCollaborationOptions{ | ||||
| 		RepoID: ctx.Repo.Repository.ID, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		ctx.InternalServerError(err) | ||||
| 		return | ||||
|   | ||||
| @@ -1329,17 +1329,16 @@ func GetPullRequestCommits(ctx *context.APIContext) { | ||||
|  | ||||
| 	userCache := make(map[string]*user_model.User) | ||||
|  | ||||
| 	start, end := listOptions.GetStartEnd() | ||||
| 	start, limit := listOptions.GetSkipTake() | ||||
|  | ||||
| 	if end > totalNumberOfCommits { | ||||
| 		end = totalNumberOfCommits | ||||
| 	} | ||||
| 	limit = min(limit, totalNumberOfCommits-start) | ||||
| 	limit = max(limit, 0) | ||||
|  | ||||
| 	verification := ctx.FormString("verification") == "" || ctx.FormBool("verification") | ||||
| 	files := ctx.FormString("files") == "" || ctx.FormBool("files") | ||||
|  | ||||
| 	apiCommits := make([]*api.Commit, 0, end-start) | ||||
| 	for i := start; i < end; i++ { | ||||
| 	apiCommits := make([]*api.Commit, 0, limit) | ||||
| 	for i := start; i < start+limit; i++ { | ||||
| 		apiCommit, err := convert.ToCommit(ctx, ctx.Repo.Repository, baseGitRepo, commits[i], userCache, | ||||
| 			convert.ToCommitOptions{ | ||||
| 				Stat:         true, | ||||
| @@ -1477,19 +1476,14 @@ func GetPullRequestFiles(ctx *context.APIContext) { | ||||
| 	totalNumberOfFiles := diff.NumFiles | ||||
| 	totalNumberOfPages := int(math.Ceil(float64(totalNumberOfFiles) / float64(listOptions.PageSize))) | ||||
|  | ||||
| 	start, end := listOptions.GetStartEnd() | ||||
| 	start, limit := listOptions.GetSkipTake() | ||||
|  | ||||
| 	if end > totalNumberOfFiles { | ||||
| 		end = totalNumberOfFiles | ||||
| 	} | ||||
| 	limit = min(limit, totalNumberOfFiles-start) | ||||
|  | ||||
| 	lenFiles := end - start | ||||
| 	if lenFiles < 0 { | ||||
| 		lenFiles = 0 | ||||
| 	} | ||||
| 	limit = max(limit, 0) | ||||
|  | ||||
| 	apiFiles := make([]*api.ChangedFile, 0, lenFiles) | ||||
| 	for i := start; i < end; i++ { | ||||
| 	apiFiles := make([]*api.ChangedFile, 0, limit) | ||||
| 	for i := start; i < start+limit; i++ { | ||||
| 		apiFiles = append(apiFiles, convert.ToChangedFile(diff.Files[i], pr.HeadRepo, endCommitID)) | ||||
| 	} | ||||
|  | ||||
|   | ||||
| @@ -7,6 +7,7 @@ import ( | ||||
| 	"net/http" | ||||
|  | ||||
| 	"code.gitea.io/gitea/models" | ||||
| 	"code.gitea.io/gitea/models/db" | ||||
| 	"code.gitea.io/gitea/models/perm" | ||||
| 	repo_model "code.gitea.io/gitea/models/repo" | ||||
| 	"code.gitea.io/gitea/models/unit" | ||||
| @@ -154,9 +155,10 @@ func ListReleases(ctx *context.APIContext) { | ||||
| 		IncludeTags:   false, | ||||
| 		IsDraft:       ctx.FormOptionalBool("draft"), | ||||
| 		IsPreRelease:  ctx.FormOptionalBool("pre-release"), | ||||
| 		RepoID:        ctx.Repo.Repository.ID, | ||||
| 	} | ||||
|  | ||||
| 	releases, err := repo_model.GetReleasesByRepoID(ctx, ctx.Repo.Repository.ID, opts) | ||||
| 	releases, err := db.Find[repo_model.Release](ctx, opts) | ||||
| 	if err != nil { | ||||
| 		ctx.Error(http.StatusInternalServerError, "GetReleasesByRepoID", err) | ||||
| 		return | ||||
| @@ -170,7 +172,7 @@ func ListReleases(ctx *context.APIContext) { | ||||
| 		rels[i] = convert.ToAPIRelease(ctx, ctx.Repo.Repository, release) | ||||
| 	} | ||||
|  | ||||
| 	filteredCount, err := repo_model.CountReleasesByRepoID(ctx, ctx.Repo.Repository.ID, opts) | ||||
| 	filteredCount, err := db.Count[repo_model.Release](ctx, opts) | ||||
| 	if err != nil { | ||||
| 		ctx.InternalServerError(err) | ||||
| 		return | ||||
|   | ||||
| @@ -18,23 +18,25 @@ import ( | ||||
| ) | ||||
|  | ||||
| func listGPGKeys(ctx *context.APIContext, uid int64, listOptions db.ListOptions) { | ||||
| 	keys, err := asymkey_model.ListGPGKeys(ctx, uid, listOptions) | ||||
| 	keys, total, err := db.FindAndCount[asymkey_model.GPGKey](ctx, asymkey_model.FindGPGKeyOptions{ | ||||
| 		ListOptions: listOptions, | ||||
| 		OwnerID:     uid, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		ctx.Error(http.StatusInternalServerError, "ListGPGKeys", err) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	if err := asymkey_model.GPGKeyList(keys).LoadSubKeys(ctx); err != nil { | ||||
| 		ctx.Error(http.StatusInternalServerError, "ListGPGKeys", err) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	apiKeys := make([]*api.GPGKey, len(keys)) | ||||
| 	for i := range keys { | ||||
| 		apiKeys[i] = convert.ToGPGKey(keys[i]) | ||||
| 	} | ||||
|  | ||||
| 	total, err := asymkey_model.CountUserGPGKeys(ctx, uid) | ||||
| 	if err != nil { | ||||
| 		ctx.InternalServerError(err) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	ctx.SetTotalCountHeader(total) | ||||
| 	ctx.JSON(http.StatusOK, &apiKeys) | ||||
| } | ||||
| @@ -121,6 +123,10 @@ func GetGPGKey(ctx *context.APIContext) { | ||||
| 		} | ||||
| 		return | ||||
| 	} | ||||
| 	if err := key.LoadSubKeys(ctx); err != nil { | ||||
| 		ctx.Error(http.StatusInternalServerError, "LoadSubKeys", err) | ||||
| 		return | ||||
| 	} | ||||
| 	ctx.JSON(http.StatusOK, convert.ToGPGKey(key)) | ||||
| } | ||||
|  | ||||
| @@ -198,7 +204,10 @@ func VerifyUserGPGKey(ctx *context.APIContext) { | ||||
| 		ctx.Error(http.StatusInternalServerError, "VerifyUserGPGKey", err) | ||||
| 	} | ||||
|  | ||||
| 	key, err := asymkey_model.GetGPGKeysByKeyID(ctx, form.KeyID) | ||||
| 	keys, err := db.Find[asymkey_model.GPGKey](ctx, asymkey_model.FindGPGKeyOptions{ | ||||
| 		KeyID:          form.KeyID, | ||||
| 		IncludeSubKeys: true, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		if asymkey_model.IsErrGPGKeyNotExist(err) { | ||||
| 			ctx.NotFound() | ||||
| @@ -207,7 +216,7 @@ func VerifyUserGPGKey(ctx *context.APIContext) { | ||||
| 		} | ||||
| 		return | ||||
| 	} | ||||
| 	ctx.JSON(http.StatusOK, convert.ToGPGKey(key[0])) | ||||
| 	ctx.JSON(http.StatusOK, convert.ToGPGKey(keys[0])) | ||||
| } | ||||
|  | ||||
| // swagger:parameters userCurrentPostGPGKey | ||||
|   | ||||
| @@ -6,6 +6,7 @@ package feed | ||||
| import ( | ||||
| 	"time" | ||||
|  | ||||
| 	"code.gitea.io/gitea/models/db" | ||||
| 	repo_model "code.gitea.io/gitea/models/repo" | ||||
| 	"code.gitea.io/gitea/modules/context" | ||||
|  | ||||
| @@ -14,8 +15,9 @@ import ( | ||||
|  | ||||
| // shows tags and/or releases on the repo as RSS / Atom feed | ||||
| func ShowReleaseFeed(ctx *context.Context, repo *repo_model.Repository, isReleasesOnly bool, formatType string) { | ||||
| 	releases, err := repo_model.GetReleasesByRepoID(ctx, ctx.Repo.Repository.ID, repo_model.FindReleasesOptions{ | ||||
| 	releases, err := db.Find[repo_model.Release](ctx, repo_model.FindReleasesOptions{ | ||||
| 		IncludeTags: !isReleasesOnly, | ||||
| 		RepoID:      ctx.Repo.Repository.ID, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		ctx.ServerError("GetReleasesByRepoID", err) | ||||
|   | ||||
| @@ -95,9 +95,10 @@ func Releases(ctx *context.Context) { | ||||
| 		ListOptions: listOptions, | ||||
| 		// only show draft releases for users who can write, read-only users shouldn't see draft releases. | ||||
| 		IncludeDrafts: writeAccess, | ||||
| 		RepoID:        ctx.Repo.Repository.ID, | ||||
| 	} | ||||
|  | ||||
| 	releases, err := repo_model.GetReleasesByRepoID(ctx, ctx.Repo.Repository.ID, opts) | ||||
| 	releases, err := db.Find[repo_model.Release](ctx, opts) | ||||
| 	if err != nil { | ||||
| 		ctx.ServerError("GetReleasesByRepoID", err) | ||||
| 		return | ||||
| @@ -194,9 +195,10 @@ func TagsList(ctx *context.Context) { | ||||
| 		IncludeDrafts: true, | ||||
| 		IncludeTags:   true, | ||||
| 		HasSha1:       util.OptionalBoolTrue, | ||||
| 		RepoID:        ctx.Repo.Repository.ID, | ||||
| 	} | ||||
|  | ||||
| 	releases, err := repo_model.GetReleasesByRepoID(ctx, ctx.Repo.Repository.ID, opts) | ||||
| 	releases, err := db.Find[repo_model.Release](ctx, opts) | ||||
| 	if err != nil { | ||||
| 		ctx.ServerError("GetReleasesByRepoID", err) | ||||
| 		return | ||||
|   | ||||
| @@ -6,6 +6,7 @@ package repo | ||||
| import ( | ||||
| 	"testing" | ||||
|  | ||||
| 	"code.gitea.io/gitea/models/db" | ||||
| 	repo_model "code.gitea.io/gitea/models/repo" | ||||
| 	"code.gitea.io/gitea/models/unit" | ||||
| 	"code.gitea.io/gitea/models/unittest" | ||||
| @@ -74,8 +75,9 @@ func TestCalReleaseNumCommitsBehind(t *testing.T) { | ||||
| 	contexttest.LoadGitRepo(t, ctx) | ||||
| 	t.Cleanup(func() { ctx.Repo.GitRepo.Close() }) | ||||
|  | ||||
| 	releases, err := repo_model.GetReleasesByRepoID(ctx, ctx.Repo.Repository.ID, repo_model.FindReleasesOptions{ | ||||
| 	releases, err := db.Find[repo_model.Release](ctx, repo_model.FindReleasesOptions{ | ||||
| 		IncludeDrafts: ctx.Repo.CanWrite(unit.TypeReleases), | ||||
| 		RepoID:        ctx.Repo.Repository.ID, | ||||
| 	}) | ||||
| 	assert.NoError(t, err) | ||||
|  | ||||
|   | ||||
| @@ -379,7 +379,10 @@ func RedirectDownload(ctx *context.Context) { | ||||
| 	) | ||||
| 	tagNames := []string{vTag} | ||||
| 	curRepo := ctx.Repo.Repository | ||||
| 	releases, err := repo_model.GetReleasesByRepoIDAndNames(ctx, curRepo.ID, tagNames) | ||||
| 	releases, err := db.Find[repo_model.Release](ctx, repo_model.FindReleasesOptions{ | ||||
| 		RepoID:   curRepo.ID, | ||||
| 		TagNames: tagNames, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		ctx.ServerError("RedirectDownload", err) | ||||
| 		return | ||||
|   | ||||
| @@ -663,7 +663,10 @@ func ShowSSHKeys(ctx *context.Context) { | ||||
|  | ||||
| // ShowGPGKeys output all the public GPG keys of user by uid | ||||
| func ShowGPGKeys(ctx *context.Context) { | ||||
| 	keys, err := asymkey_model.ListGPGKeys(ctx, ctx.ContextUser.ID, db.ListOptions{}) | ||||
| 	keys, err := db.Find[asymkey_model.GPGKey](ctx, asymkey_model.FindGPGKeyOptions{ | ||||
| 		ListOptions: db.ListOptionsAll, | ||||
| 		OwnerID:     ctx.ContextUser.ID, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		ctx.ServerError("ListGPGKeys", err) | ||||
| 		return | ||||
|   | ||||
| @@ -277,18 +277,29 @@ func loadKeysData(ctx *context.Context) { | ||||
| 	} | ||||
| 	ctx.Data["ExternalKeys"] = externalKeys | ||||
|  | ||||
| 	gpgkeys, err := asymkey_model.ListGPGKeys(ctx, ctx.Doer.ID, db.ListOptions{}) | ||||
| 	gpgkeys, err := db.Find[asymkey_model.GPGKey](ctx, asymkey_model.FindGPGKeyOptions{ | ||||
| 		ListOptions: db.ListOptionsAll, | ||||
| 		OwnerID:     ctx.Doer.ID, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		ctx.ServerError("ListGPGKeys", err) | ||||
| 		return | ||||
| 	} | ||||
| 	if err := asymkey_model.GPGKeyList(gpgkeys).LoadSubKeys(ctx); err != nil { | ||||
| 		ctx.ServerError("LoadSubKeys", err) | ||||
| 		return | ||||
| 	} | ||||
| 	ctx.Data["GPGKeys"] = gpgkeys | ||||
| 	tokenToSign := asymkey_model.VerificationToken(ctx.Doer, 1) | ||||
|  | ||||
| 	// generate a new aes cipher using the csrfToken | ||||
| 	ctx.Data["TokenToSign"] = tokenToSign | ||||
|  | ||||
| 	principals, err := asymkey_model.ListPrincipalKeys(ctx, ctx.Doer.ID, db.ListOptions{}) | ||||
| 	principals, err := db.Find[asymkey_model.PublicKey](ctx, asymkey_model.FindPublicKeyOptions{ | ||||
| 		ListOptions: db.ListOptionsAll, | ||||
| 		OwnerID:     ctx.Doer.ID, | ||||
| 		KeyTypes:    []asymkey_model.KeyType{asymkey_model.KeyTypePrincipal}, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		ctx.ServerError("ListPrincipalKeys", err) | ||||
| 		return | ||||
|   | ||||
| @@ -143,7 +143,10 @@ Loop: | ||||
| 		case always: | ||||
| 			break Loop | ||||
| 		case pubkey: | ||||
| 			keys, err := asymkey_model.ListGPGKeys(ctx, u.ID, db.ListOptions{}) | ||||
| 			keys, err := db.Find[asymkey_model.GPGKey](ctx, asymkey_model.FindGPGKeyOptions{ | ||||
| 				OwnerID:        u.ID, | ||||
| 				IncludeSubKeys: true, | ||||
| 			}) | ||||
| 			if err != nil { | ||||
| 				return false, "", nil, err | ||||
| 			} | ||||
| @@ -179,7 +182,10 @@ Loop: | ||||
| 		case always: | ||||
| 			break Loop | ||||
| 		case pubkey: | ||||
| 			keys, err := asymkey_model.ListGPGKeys(ctx, u.ID, db.ListOptions{}) | ||||
| 			keys, err := db.Find[asymkey_model.GPGKey](ctx, asymkey_model.FindGPGKeyOptions{ | ||||
| 				OwnerID:        u.ID, | ||||
| 				IncludeSubKeys: true, | ||||
| 			}) | ||||
| 			if err != nil { | ||||
| 				return false, "", nil, err | ||||
| 			} | ||||
| @@ -232,7 +238,10 @@ Loop: | ||||
| 		case always: | ||||
| 			break Loop | ||||
| 		case pubkey: | ||||
| 			keys, err := asymkey_model.ListGPGKeys(ctx, u.ID, db.ListOptions{}) | ||||
| 			keys, err := db.Find[asymkey_model.GPGKey](ctx, asymkey_model.FindGPGKeyOptions{ | ||||
| 				OwnerID:        u.ID, | ||||
| 				IncludeSubKeys: true, | ||||
| 			}) | ||||
| 			if err != nil { | ||||
| 				return false, "", nil, err | ||||
| 			} | ||||
| @@ -294,7 +303,10 @@ Loop: | ||||
| 		case always: | ||||
| 			break Loop | ||||
| 		case pubkey: | ||||
| 			keys, err := asymkey_model.ListGPGKeys(ctx, u.ID, db.ListOptions{}) | ||||
| 			keys, err := db.Find[asymkey_model.GPGKey](ctx, asymkey_model.FindGPGKeyOptions{ | ||||
| 				OwnerID:        u.ID, | ||||
| 				IncludeSubKeys: true, | ||||
| 			}) | ||||
| 			if err != nil { | ||||
| 				return false, "", nil, err | ||||
| 			} | ||||
|   | ||||
| @@ -8,6 +8,7 @@ import ( | ||||
| 	"time" | ||||
|  | ||||
| 	"code.gitea.io/gitea/models" | ||||
| 	"code.gitea.io/gitea/models/db" | ||||
| 	"code.gitea.io/gitea/models/perm" | ||||
| 	access_model "code.gitea.io/gitea/models/perm/access" | ||||
| 	repo_model "code.gitea.io/gitea/models/repo" | ||||
| @@ -133,7 +134,11 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, permissionInR | ||||
| 		return nil | ||||
| 	} | ||||
|  | ||||
| 	numReleases, _ := repo_model.GetReleaseCountByRepoID(ctx, repo.ID, repo_model.FindReleasesOptions{IncludeDrafts: false, IncludeTags: false}) | ||||
| 	numReleases, _ := db.Count[repo_model.Release](ctx, repo_model.FindReleasesOptions{ | ||||
| 		IncludeDrafts: false, | ||||
| 		IncludeTags:   false, | ||||
| 		RepoID:        repo.ID, | ||||
| 	}) | ||||
|  | ||||
| 	mirrorInterval := "" | ||||
| 	var mirrorUpdated time.Time | ||||
|   | ||||
| @@ -83,22 +83,24 @@ func TestGiteaUploadRepo(t *testing.T) { | ||||
| 	assert.NoError(t, err) | ||||
| 	assert.Len(t, labels, 12) | ||||
|  | ||||
| 	releases, err := repo_model.GetReleasesByRepoID(db.DefaultContext, repo.ID, repo_model.FindReleasesOptions{ | ||||
| 	releases, err := db.Find[repo_model.Release](db.DefaultContext, repo_model.FindReleasesOptions{ | ||||
| 		ListOptions: db.ListOptions{ | ||||
| 			PageSize: 10, | ||||
| 			Page:     0, | ||||
| 		}, | ||||
| 		IncludeTags: true, | ||||
| 		RepoID:      repo.ID, | ||||
| 	}) | ||||
| 	assert.NoError(t, err) | ||||
| 	assert.Len(t, releases, 8) | ||||
|  | ||||
| 	releases, err = repo_model.GetReleasesByRepoID(db.DefaultContext, repo.ID, repo_model.FindReleasesOptions{ | ||||
| 	releases, err = db.Find[repo_model.Release](db.DefaultContext, repo_model.FindReleasesOptions{ | ||||
| 		ListOptions: db.ListOptions{ | ||||
| 			PageSize: 10, | ||||
| 			Page:     0, | ||||
| 		}, | ||||
| 		IncludeTags: false, | ||||
| 		RepoID:      repo.ID, | ||||
| 	}) | ||||
| 	assert.NoError(t, err) | ||||
| 	assert.Len(t, releases, 1) | ||||
|   | ||||
| @@ -324,7 +324,7 @@ func DeleteOldRepositoryArchives(ctx context.Context, olderThan time.Duration) e | ||||
| 	log.Trace("Doing: ArchiveCleanup") | ||||
|  | ||||
| 	for { | ||||
| 		archivers, err := repo_model.FindRepoArchives(ctx, repo_model.FindRepoArchiversOption{ | ||||
| 		archivers, err := db.Find[repo_model.RepoArchiver](ctx, repo_model.FindRepoArchiversOption{ | ||||
| 			ListOptions: db.ListOptions{ | ||||
| 				PageSize: 100, | ||||
| 				Page:     1, | ||||
|   | ||||
| @@ -327,9 +327,12 @@ func pushUpdateAddTags(ctx context.Context, repo *repo_model.Repository, gitRepo | ||||
| 		lowerTags = append(lowerTags, strings.ToLower(tag)) | ||||
| 	} | ||||
|  | ||||
| 	releases, err := repo_model.GetReleasesByRepoIDAndNames(ctx, repo.ID, lowerTags) | ||||
| 	releases, err := db.Find[repo_model.Release](ctx, repo_model.FindReleasesOptions{ | ||||
| 		RepoID:   repo.ID, | ||||
| 		TagNames: lowerTags, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("GetReleasesByRepoIDAndNames: %w", err) | ||||
| 		return fmt.Errorf("db.Find[repo_model.Release]: %w", err) | ||||
| 	} | ||||
| 	relMap := make(map[string]*repo_model.Release) | ||||
| 	for _, rel := range releases { | ||||
|   | ||||
| @@ -159,7 +159,9 @@ func deleteUser(ctx context.Context, u *user_model.User, purge bool) (err error) | ||||
| 	// ***** END: PublicKey ***** | ||||
|  | ||||
| 	// ***** START: GPGPublicKey ***** | ||||
| 	keys, err := asymkey_model.ListGPGKeys(ctx, u.ID, db.ListOptions{}) | ||||
| 	keys, err := db.Find[asymkey_model.GPGKey](ctx, asymkey_model.FindGPGKeyOptions{ | ||||
| 		OwnerID: u.ID, | ||||
| 	}) | ||||
| 	if err != nil { | ||||
| 		return fmt.Errorf("ListGPGKeys: %w", err) | ||||
| 	} | ||||
|   | ||||
| @@ -58,8 +58,12 @@ func TestMirrorPull(t *testing.T) { | ||||
| 	assert.NoError(t, err) | ||||
| 	defer gitRepo.Close() | ||||
|  | ||||
| 	findOptions := repo_model.FindReleasesOptions{IncludeDrafts: true, IncludeTags: true} | ||||
| 	initCount, err := repo_model.GetReleaseCountByRepoID(db.DefaultContext, mirror.ID, findOptions) | ||||
| 	findOptions := repo_model.FindReleasesOptions{ | ||||
| 		IncludeDrafts: true, | ||||
| 		IncludeTags:   true, | ||||
| 		RepoID:        mirror.ID, | ||||
| 	} | ||||
| 	initCount, err := db.Count[repo_model.Release](db.DefaultContext, findOptions) | ||||
| 	assert.NoError(t, err) | ||||
|  | ||||
| 	assert.NoError(t, release_service.CreateRelease(gitRepo, &repo_model.Release{ | ||||
| @@ -82,7 +86,7 @@ func TestMirrorPull(t *testing.T) { | ||||
| 	ok := mirror_service.SyncPullMirror(ctx, mirror.ID) | ||||
| 	assert.True(t, ok) | ||||
|  | ||||
| 	count, err := repo_model.GetReleaseCountByRepoID(db.DefaultContext, mirror.ID, findOptions) | ||||
| 	count, err := db.Count[repo_model.Release](db.DefaultContext, findOptions) | ||||
| 	assert.NoError(t, err) | ||||
| 	assert.EqualValues(t, initCount+1, count) | ||||
|  | ||||
| @@ -93,7 +97,7 @@ func TestMirrorPull(t *testing.T) { | ||||
| 	ok = mirror_service.SyncPullMirror(ctx, mirror.ID) | ||||
| 	assert.True(t, ok) | ||||
|  | ||||
| 	count, err = repo_model.GetReleaseCountByRepoID(db.DefaultContext, mirror.ID, findOptions) | ||||
| 	count, err = db.Count[repo_model.Release](db.DefaultContext, findOptions) | ||||
| 	assert.NoError(t, err) | ||||
| 	assert.EqualValues(t, initCount, count) | ||||
| } | ||||
|   | ||||
| @@ -74,9 +74,10 @@ func TestCreateNewTagProtected(t *testing.T) { | ||||
| 	}) | ||||
|  | ||||
| 	// Cleanup | ||||
| 	releases, err := repo_model.GetReleasesByRepoID(db.DefaultContext, repo.ID, repo_model.FindReleasesOptions{ | ||||
| 	releases, err := db.Find[repo_model.Release](db.DefaultContext, repo_model.FindReleasesOptions{ | ||||
| 		IncludeTags: true, | ||||
| 		TagNames:    []string{"v-1", "v-1.1"}, | ||||
| 		RepoID:      repo.ID, | ||||
| 	}) | ||||
| 	assert.NoError(t, err) | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user