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