aboutsummaryrefslogtreecommitdiffstats
path: root/models/repo
diff options
context:
space:
mode:
Diffstat (limited to 'models/repo')
-rw-r--r--models/repo/language_stats.go148
-rw-r--r--models/repo/org_repo.go31
-rw-r--r--models/repo/pushmirror_test.go2
-rw-r--r--models/repo/release.go97
-rw-r--r--models/repo/repo.go35
-rw-r--r--models/repo/repo_list.go40
-rw-r--r--models/repo/repo_list_test.go86
-rw-r--r--models/repo/repo_test.go15
-rw-r--r--models/repo/repo_unit.go6
-rw-r--r--models/repo/star.go77
-rw-r--r--models/repo/topic.go150
-rw-r--r--models/repo/transfer.go4
-rw-r--r--models/repo/update.go21
-rw-r--r--models/repo/upload.go12
14 files changed, 316 insertions, 408 deletions
diff --git a/models/repo/language_stats.go b/models/repo/language_stats.go
index 0bc0f1fb40..1cddd25f1d 100644
--- a/models/repo/language_stats.go
+++ b/models/repo/language_stats.go
@@ -141,102 +141,90 @@ func GetTopLanguageStats(ctx context.Context, repo *Repository, limit int) (Lang
// UpdateLanguageStats updates the language statistics for repository
func UpdateLanguageStats(ctx context.Context, repo *Repository, commitID string, stats map[string]int64) error {
- ctx, committer, err := db.TxContext(ctx)
- if err != nil {
- return err
- }
- defer committer.Close()
- sess := db.GetEngine(ctx)
+ return db.WithTx(ctx, func(ctx context.Context) error {
+ sess := db.GetEngine(ctx)
- oldstats, err := GetLanguageStats(ctx, repo)
- if err != nil {
- return err
- }
- var topLang string
- var s int64
- for lang, size := range stats {
- if size > s {
- s = size
- topLang = strings.ToLower(lang)
+ oldstats, err := GetLanguageStats(ctx, repo)
+ if err != nil {
+ return err
+ }
+ var topLang string
+ var s int64
+ for lang, size := range stats {
+ if size > s {
+ s = size
+ topLang = lang
+ }
}
- }
- for lang, size := range stats {
- upd := false
- llang := strings.ToLower(lang)
- for _, s := range oldstats {
- // Update already existing language
- if strings.ToLower(s.Language) == llang {
- s.CommitID = commitID
- s.IsPrimary = llang == topLang
- s.Size = size
- if _, err := sess.ID(s.ID).Cols("`commit_id`", "`size`", "`is_primary`").Update(s); err != nil {
+ for lang, size := range stats {
+ upd := false
+ for _, s := range oldstats {
+ // Update already existing language
+ if strings.EqualFold(s.Language, lang) {
+ s.CommitID = commitID
+ s.IsPrimary = lang == topLang
+ s.Size = size
+ if _, err := sess.ID(s.ID).Cols("`commit_id`", "`size`", "`is_primary`").Update(s); err != nil {
+ return err
+ }
+ upd = true
+ break
+ }
+ }
+ // Insert new language
+ if !upd {
+ if err := db.Insert(ctx, &LanguageStat{
+ RepoID: repo.ID,
+ CommitID: commitID,
+ IsPrimary: lang == topLang,
+ Language: lang,
+ Size: size,
+ }); err != nil {
return err
}
- upd = true
- break
}
}
- // Insert new language
- if !upd {
- if err := db.Insert(ctx, &LanguageStat{
- RepoID: repo.ID,
- CommitID: commitID,
- IsPrimary: llang == topLang,
- Language: lang,
- Size: size,
- }); err != nil {
- return err
+ // Delete old languages
+ statsToDelete := make([]int64, 0, len(oldstats))
+ for _, s := range oldstats {
+ if s.CommitID != commitID {
+ statsToDelete = append(statsToDelete, s.ID)
}
}
- }
- // Delete old languages
- statsToDelete := make([]int64, 0, len(oldstats))
- for _, s := range oldstats {
- if s.CommitID != commitID {
- statsToDelete = append(statsToDelete, s.ID)
- }
- }
- if len(statsToDelete) > 0 {
- if _, err := sess.In("`id`", statsToDelete).Delete(&LanguageStat{}); err != nil {
- return err
+ if len(statsToDelete) > 0 {
+ if _, err := sess.In("`id`", statsToDelete).Delete(&LanguageStat{}); err != nil {
+ return err
+ }
}
- }
- // Update indexer status
- if err = UpdateIndexerStatus(ctx, repo, RepoIndexerTypeStats, commitID); err != nil {
- return err
- }
-
- return committer.Commit()
+ // Update indexer status
+ return UpdateIndexerStatus(ctx, repo, RepoIndexerTypeStats, commitID)
+ })
}
// CopyLanguageStat Copy originalRepo language stat information to destRepo (use for forked repo)
func CopyLanguageStat(ctx context.Context, originalRepo, destRepo *Repository) error {
- ctx, committer, err := db.TxContext(ctx)
- if err != nil {
- return err
- }
- defer committer.Close()
-
- RepoLang := make(LanguageStatList, 0, 6)
- if err := db.GetEngine(ctx).Where("`repo_id` = ?", originalRepo.ID).Desc("`size`").Find(&RepoLang); err != nil {
- return err
- }
- if len(RepoLang) > 0 {
- for i := range RepoLang {
- RepoLang[i].ID = 0
- RepoLang[i].RepoID = destRepo.ID
- RepoLang[i].CreatedUnix = timeutil.TimeStampNow()
- }
- // update destRepo's indexer status
- tmpCommitID := RepoLang[0].CommitID
- if err := UpdateIndexerStatus(ctx, destRepo, RepoIndexerTypeStats, tmpCommitID); err != nil {
+ return db.WithTx(ctx, func(ctx context.Context) error {
+ RepoLang := make(LanguageStatList, 0, 6)
+ if err := db.GetEngine(ctx).Where("`repo_id` = ?", originalRepo.ID).Desc("`size`").Find(&RepoLang); err != nil {
return err
}
- if err := db.Insert(ctx, &RepoLang); err != nil {
- return err
+ if len(RepoLang) > 0 {
+ for i := range RepoLang {
+ RepoLang[i].ID = 0
+ RepoLang[i].RepoID = destRepo.ID
+ RepoLang[i].CreatedUnix = timeutil.TimeStampNow()
+ }
+ // update destRepo's indexer status
+ tmpCommitID := RepoLang[0].CommitID
+ if err := UpdateIndexerStatus(ctx, destRepo, RepoIndexerTypeStats, tmpCommitID); err != nil {
+ return err
+ }
+ if err := db.Insert(ctx, &RepoLang); err != nil {
+ return err
+ }
}
- }
- return committer.Commit()
+ return nil
+ })
}
diff --git a/models/repo/org_repo.go b/models/repo/org_repo.go
index fa519d25b1..96f21ba2ac 100644
--- a/models/repo/org_repo.go
+++ b/models/repo/org_repo.go
@@ -48,8 +48,7 @@ func GetTeamRepositories(ctx context.Context, opts *SearchTeamRepoOptions) (Repo
// accessible to a particular user
type AccessibleReposEnvironment interface {
CountRepos(ctx context.Context) (int64, error)
- RepoIDs(ctx context.Context, page, pageSize int) ([]int64, error)
- Repos(ctx context.Context, page, pageSize int) (RepositoryList, error)
+ RepoIDs(ctx context.Context) ([]int64, error)
MirrorRepos(ctx context.Context) (RepositoryList, error)
AddKeyword(keyword string)
SetSort(db.SearchOrderBy)
@@ -132,40 +131,18 @@ func (env *accessibleReposEnv) CountRepos(ctx context.Context) (int64, error) {
return repoCount, nil
}
-func (env *accessibleReposEnv) RepoIDs(ctx context.Context, page, pageSize int) ([]int64, error) {
- if page <= 0 {
- page = 1
- }
-
- repoIDs := make([]int64, 0, pageSize)
+func (env *accessibleReposEnv) RepoIDs(ctx context.Context) ([]int64, error) {
+ var repoIDs []int64
return repoIDs, db.GetEngine(ctx).
Table("repository").
Join("INNER", "team_repo", "`team_repo`.repo_id=`repository`.id").
Where(env.cond()).
- GroupBy("`repository`.id,`repository`."+strings.Fields(string(env.orderBy))[0]).
+ GroupBy("`repository`.id,`repository`." + strings.Fields(string(env.orderBy))[0]).
OrderBy(string(env.orderBy)).
- Limit(pageSize, (page-1)*pageSize).
Cols("`repository`.id").
Find(&repoIDs)
}
-func (env *accessibleReposEnv) Repos(ctx context.Context, page, pageSize int) (RepositoryList, error) {
- repoIDs, err := env.RepoIDs(ctx, page, pageSize)
- if err != nil {
- return nil, fmt.Errorf("GetUserRepositoryIDs: %w", err)
- }
-
- repos := make([]*Repository, 0, len(repoIDs))
- if len(repoIDs) == 0 {
- return repos, nil
- }
-
- return repos, db.GetEngine(ctx).
- In("`repository`.id", repoIDs).
- OrderBy(string(env.orderBy)).
- Find(&repos)
-}
-
func (env *accessibleReposEnv) MirrorRepoIDs(ctx context.Context) ([]int64, error) {
repoIDs := make([]int64, 0, 10)
return repoIDs, db.GetEngine(ctx).
diff --git a/models/repo/pushmirror_test.go b/models/repo/pushmirror_test.go
index e19749d93a..9fb7471147 100644
--- a/models/repo/pushmirror_test.go
+++ b/models/repo/pushmirror_test.go
@@ -39,8 +39,6 @@ func TestPushMirrorsIterate(t *testing.T) {
Interval: 0,
})
- time.Sleep(1 * time.Millisecond)
-
repo_model.PushMirrorsIterate(db.DefaultContext, 1, func(idx int, bean any) error {
m, ok := bean.(*repo_model.PushMirror)
assert.True(t, ok)
diff --git a/models/repo/release.go b/models/repo/release.go
index 663d310bc0..0db57503ce 100644
--- a/models/repo/release.go
+++ b/models/repo/release.go
@@ -161,6 +161,11 @@ func UpdateRelease(ctx context.Context, rel *Release) error {
return err
}
+func UpdateReleaseNumCommits(ctx context.Context, rel *Release) error {
+ _, err := db.GetEngine(ctx).ID(rel.ID).Cols("num_commits").Update(rel)
+ return err
+}
+
// AddReleaseAttachments adds a release attachments
func AddReleaseAttachments(ctx context.Context, releaseID int64, attachmentUUIDs []string) (err error) {
// Check attachments
@@ -175,7 +180,7 @@ func AddReleaseAttachments(ctx context.Context, releaseID int64, attachmentUUIDs
}
attachments[i].ReleaseID = releaseID
// No assign value could be 0, so ignore AllCols().
- if _, err = db.GetEngine(ctx).ID(attachments[i].ID).Update(attachments[i]); err != nil {
+ if _, err = db.GetEngine(ctx).ID(attachments[i].ID).Cols("release_id").Update(attachments[i]); err != nil {
return fmt.Errorf("update attachment [%d]: %w", attachments[i].ID, err)
}
}
@@ -418,8 +423,8 @@ func UpdateReleasesMigrationsByType(ctx context.Context, gitServiceType structs.
return err
}
-// PushUpdateDeleteTagsContext updates a number of delete tags with context
-func PushUpdateDeleteTagsContext(ctx context.Context, repo *Repository, tags []string) error {
+// PushUpdateDeleteTags updates a number of delete tags with context
+func PushUpdateDeleteTags(ctx context.Context, repo *Repository, tags []string) error {
if len(tags) == 0 {
return nil
}
@@ -448,58 +453,6 @@ func PushUpdateDeleteTagsContext(ctx context.Context, repo *Repository, tags []s
return nil
}
-// PushUpdateDeleteTag must be called for any push actions to delete tag
-func PushUpdateDeleteTag(ctx context.Context, repo *Repository, tagName string) error {
- rel, err := GetRelease(ctx, repo.ID, tagName)
- if err != nil {
- if IsErrReleaseNotExist(err) {
- return nil
- }
- return fmt.Errorf("GetRelease: %w", err)
- }
- if rel.IsTag {
- if _, err = db.DeleteByID[Release](ctx, rel.ID); err != nil {
- return fmt.Errorf("Delete: %w", err)
- }
- } else {
- rel.IsDraft = true
- rel.NumCommits = 0
- rel.Sha1 = ""
- if _, err = db.GetEngine(ctx).ID(rel.ID).AllCols().Update(rel); err != nil {
- return fmt.Errorf("Update: %w", err)
- }
- }
-
- return nil
-}
-
-// SaveOrUpdateTag must be called for any push actions to add tag
-func SaveOrUpdateTag(ctx context.Context, repo *Repository, newRel *Release) error {
- rel, err := GetRelease(ctx, repo.ID, newRel.TagName)
- if err != nil && !IsErrReleaseNotExist(err) {
- return fmt.Errorf("GetRelease: %w", err)
- }
-
- if rel == nil {
- rel = newRel
- if _, err = db.GetEngine(ctx).Insert(rel); err != nil {
- return fmt.Errorf("InsertOne: %w", err)
- }
- } else {
- rel.Sha1 = newRel.Sha1
- rel.CreatedUnix = newRel.CreatedUnix
- rel.NumCommits = newRel.NumCommits
- rel.IsDraft = false
- if rel.IsTag && newRel.PublisherID > 0 {
- rel.PublisherID = newRel.PublisherID
- }
- if _, err = db.GetEngine(ctx).ID(rel.ID).AllCols().Update(rel); err != nil {
- return fmt.Errorf("Update: %w", err)
- }
- }
- return nil
-}
-
// RemapExternalUser ExternalUserRemappable interface
func (r *Release) RemapExternalUser(externalName string, externalID, userID int64) error {
r.OriginalAuthor = externalName
@@ -519,30 +472,24 @@ func (r *Release) GetExternalID() int64 { return r.OriginalAuthorID }
// InsertReleases migrates release
func InsertReleases(ctx context.Context, rels ...*Release) error {
- ctx, committer, err := db.TxContext(ctx)
- if err != nil {
- return err
- }
- defer committer.Close()
- sess := db.GetEngine(ctx)
-
- for _, rel := range rels {
- if _, err := sess.NoAutoTime().Insert(rel); err != nil {
- return err
- }
-
- if len(rel.Attachments) > 0 {
- for i := range rel.Attachments {
- rel.Attachments[i].ReleaseID = rel.ID
+ return db.WithTx(ctx, func(ctx context.Context) error {
+ for _, rel := range rels {
+ if _, err := db.GetEngine(ctx).NoAutoTime().Insert(rel); err != nil {
+ return err
}
- if _, err := sess.NoAutoTime().Insert(rel.Attachments); err != nil {
- return err
+ if len(rel.Attachments) > 0 {
+ for i := range rel.Attachments {
+ rel.Attachments[i].ReleaseID = rel.ID
+ }
+
+ if _, err := db.GetEngine(ctx).NoAutoTime().Insert(rel.Attachments); err != nil {
+ return err
+ }
}
}
- }
-
- return committer.Commit()
+ return nil
+ })
}
func FindTagsByCommitIDs(ctx context.Context, repoID int64, commitIDs ...string) (map[string][]*Release, error) {
diff --git a/models/repo/repo.go b/models/repo/repo.go
index 2977dfb9f1..2403b3b40b 100644
--- a/models/repo/repo.go
+++ b/models/repo/repo.go
@@ -64,18 +64,18 @@ func (err ErrRepoIsArchived) Error() string {
}
type globalVarsStruct struct {
- validRepoNamePattern *regexp.Regexp
- invalidRepoNamePattern *regexp.Regexp
- reservedRepoNames []string
- reservedRepoPatterns []string
+ validRepoNamePattern *regexp.Regexp
+ invalidRepoNamePattern *regexp.Regexp
+ reservedRepoNames []string
+ reservedRepoNamePatterns []string
}
var globalVars = sync.OnceValue(func() *globalVarsStruct {
return &globalVarsStruct{
- validRepoNamePattern: regexp.MustCompile(`[-.\w]+`),
- invalidRepoNamePattern: regexp.MustCompile(`[.]{2,}`),
- reservedRepoNames: []string{".", "..", "-"},
- reservedRepoPatterns: []string{"*.git", "*.wiki", "*.rss", "*.atom"},
+ validRepoNamePattern: regexp.MustCompile(`^[-.\w]+$`),
+ invalidRepoNamePattern: regexp.MustCompile(`[.]{2,}`),
+ reservedRepoNames: []string{".", "..", "-"},
+ reservedRepoNamePatterns: []string{"*.wiki", "*.git", "*.rss", "*.atom"},
}
})
@@ -86,7 +86,16 @@ func IsUsableRepoName(name string) error {
// Note: usually this error is normally caught up earlier in the UI
return db.ErrNameCharsNotAllowed{Name: name}
}
- return db.IsUsableName(vars.reservedRepoNames, vars.reservedRepoPatterns, name)
+ return db.IsUsableName(vars.reservedRepoNames, vars.reservedRepoNamePatterns, name)
+}
+
+// IsValidSSHAccessRepoName is like IsUsableRepoName, but it allows "*.wiki" because wiki repo needs to be accessed in SSH code
+func IsValidSSHAccessRepoName(name string) bool {
+ vars := globalVars()
+ if !vars.validRepoNamePattern.MatchString(name) || vars.invalidRepoNamePattern.MatchString(name) {
+ return false
+ }
+ return db.IsUsableName(vars.reservedRepoNames, vars.reservedRepoNamePatterns[1:], name) == nil
}
// TrustModelType defines the types of trust model for this repository
@@ -643,8 +652,14 @@ func (repo *Repository) AllowsPulls(ctx context.Context) bool {
}
// CanEnableEditor returns true if repository meets the requirements of web editor.
+// FIXME: most CanEnableEditor calls should be replaced with CanContentChange
+// And all other like CanCreateBranch / CanEnablePulls should also be updated
func (repo *Repository) CanEnableEditor() bool {
- return !repo.IsMirror
+ return repo.CanContentChange()
+}
+
+func (repo *Repository) CanContentChange() bool {
+ return !repo.IsMirror && !repo.IsArchived
}
// DescriptionHTML does special handles to description and return HTML string.
diff --git a/models/repo/repo_list.go b/models/repo/repo_list.go
index 02c228e8a0..f2cdd2f284 100644
--- a/models/repo/repo_list.go
+++ b/models/repo/repo_list.go
@@ -359,7 +359,7 @@ func UserOrgPublicUnitRepoCond(userID, orgID int64) builder.Cond {
}
// SearchRepositoryCondition creates a query condition according search repository options
-func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond {
+func SearchRepositoryCondition(opts SearchRepoOptions) builder.Cond {
cond := builder.NewCond()
if opts.Private {
@@ -449,7 +449,7 @@ func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond {
if opts.Keyword != "" {
// separate keyword
subQueryCond := builder.NewCond()
- for _, v := range strings.Split(opts.Keyword, ",") {
+ for v := range strings.SplitSeq(opts.Keyword, ",") {
if opts.TopicOnly {
subQueryCond = subQueryCond.Or(builder.Eq{"topic.name": strings.ToLower(v)})
} else {
@@ -464,7 +464,7 @@ func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond {
keywordCond := builder.In("id", subQuery)
if !opts.TopicOnly {
likes := builder.NewCond()
- for _, v := range strings.Split(opts.Keyword, ",") {
+ for v := range strings.SplitSeq(opts.Keyword, ",") {
likes = likes.Or(builder.Like{"lower_name", strings.ToLower(v)})
// If the string looks like "org/repo", match against that pattern too
@@ -551,18 +551,18 @@ func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond {
// SearchRepository returns repositories based on search options,
// it returns results in given range and number of total results.
-func SearchRepository(ctx context.Context, opts *SearchRepoOptions) (RepositoryList, int64, error) {
+func SearchRepository(ctx context.Context, opts SearchRepoOptions) (RepositoryList, int64, error) {
cond := SearchRepositoryCondition(opts)
return SearchRepositoryByCondition(ctx, opts, cond, true)
}
// CountRepository counts repositories based on search options,
-func CountRepository(ctx context.Context, opts *SearchRepoOptions) (int64, error) {
+func CountRepository(ctx context.Context, opts SearchRepoOptions) (int64, error) {
return db.GetEngine(ctx).Where(SearchRepositoryCondition(opts)).Count(new(Repository))
}
// SearchRepositoryByCondition search repositories by condition
-func SearchRepositoryByCondition(ctx context.Context, opts *SearchRepoOptions, cond builder.Cond, loadAttributes bool) (RepositoryList, int64, error) {
+func SearchRepositoryByCondition(ctx context.Context, opts SearchRepoOptions, cond builder.Cond, loadAttributes bool) (RepositoryList, int64, error) {
sess, count, err := searchRepositoryByCondition(ctx, opts, cond)
if err != nil {
return nil, 0, err
@@ -590,23 +590,25 @@ func SearchRepositoryByCondition(ctx context.Context, opts *SearchRepoOptions, c
return repos, count, nil
}
-func searchRepositoryByCondition(ctx context.Context, opts *SearchRepoOptions, cond builder.Cond) (db.Engine, int64, error) {
- if opts.Page <= 0 {
- opts.Page = 1
+func searchRepositoryByCondition(ctx context.Context, opts SearchRepoOptions, cond builder.Cond) (db.Engine, int64, error) {
+ page := opts.Page
+ if page <= 0 {
+ page = 1
}
- if len(opts.OrderBy) == 0 {
- opts.OrderBy = db.SearchOrderByAlphabetically
+ orderBy := opts.OrderBy
+ if len(orderBy) == 0 {
+ orderBy = db.SearchOrderByAlphabetically
}
args := make([]any, 0)
if opts.PriorityOwnerID > 0 {
- opts.OrderBy = db.SearchOrderBy(fmt.Sprintf("CASE WHEN owner_id = ? THEN 0 ELSE owner_id END, %s", opts.OrderBy))
+ orderBy = db.SearchOrderBy(fmt.Sprintf("CASE WHEN owner_id = ? THEN 0 ELSE owner_id END, %s", orderBy))
args = append(args, opts.PriorityOwnerID)
} else if strings.Count(opts.Keyword, "/") == 1 {
// With "owner/repo" search times, prioritise results which match the owner field
orgName := strings.Split(opts.Keyword, "/")[0]
- opts.OrderBy = db.SearchOrderBy(fmt.Sprintf("CASE WHEN owner_name LIKE ? THEN 0 ELSE 1 END, %s", opts.OrderBy))
+ orderBy = db.SearchOrderBy(fmt.Sprintf("CASE WHEN owner_name LIKE ? THEN 0 ELSE 1 END, %s", orderBy))
args = append(args, orgName)
}
@@ -623,9 +625,9 @@ func searchRepositoryByCondition(ctx context.Context, opts *SearchRepoOptions, c
}
}
- sess = sess.Where(cond).OrderBy(opts.OrderBy.String(), args...)
+ sess = sess.Where(cond).OrderBy(orderBy.String(), args...)
if opts.PageSize > 0 {
- sess = sess.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize)
+ sess = sess.Limit(opts.PageSize, (page-1)*opts.PageSize)
}
return sess, count, nil
}
@@ -689,14 +691,14 @@ func AccessibleRepositoryCondition(user *user_model.User, unitType unit.Type) bu
// SearchRepositoryByName takes keyword and part of repository name to search,
// it returns results in given range and number of total results.
-func SearchRepositoryByName(ctx context.Context, opts *SearchRepoOptions) (RepositoryList, int64, error) {
+func SearchRepositoryByName(ctx context.Context, opts SearchRepoOptions) (RepositoryList, int64, error) {
opts.IncludeDescription = false
return SearchRepository(ctx, opts)
}
// SearchRepositoryIDs takes keyword and part of repository name to search,
// it returns results in given range and number of total results.
-func SearchRepositoryIDs(ctx context.Context, opts *SearchRepoOptions) ([]int64, int64, error) {
+func SearchRepositoryIDs(ctx context.Context, opts SearchRepoOptions) ([]int64, int64, error) {
opts.IncludeDescription = false
cond := SearchRepositoryCondition(opts)
@@ -740,7 +742,7 @@ func FindUserCodeAccessibleOwnerRepoIDs(ctx context.Context, ownerID int64, user
}
// GetUserRepositories returns a list of repositories of given user.
-func GetUserRepositories(ctx context.Context, opts *SearchRepoOptions) (RepositoryList, int64, error) {
+func GetUserRepositories(ctx context.Context, opts SearchRepoOptions) (RepositoryList, int64, error) {
if len(opts.OrderBy) == 0 {
opts.OrderBy = "updated_unix DESC"
}
@@ -767,5 +769,5 @@ func GetUserRepositories(ctx context.Context, opts *SearchRepoOptions) (Reposito
sess = sess.Where(cond).OrderBy(opts.OrderBy.String())
repos := make(RepositoryList, 0, opts.PageSize)
- return repos, count, db.SetSessionPagination(sess, opts).Find(&repos)
+ return repos, count, db.SetSessionPagination(sess, &opts).Find(&repos)
}
diff --git a/models/repo/repo_list_test.go b/models/repo/repo_list_test.go
index ca6007f6c7..7eb76416c2 100644
--- a/models/repo/repo_list_test.go
+++ b/models/repo/repo_list_test.go
@@ -17,162 +17,162 @@ import (
func getTestCases() []struct {
name string
- opts *repo_model.SearchRepoOptions
+ opts repo_model.SearchRepoOptions
count int
} {
testCases := []struct {
name string
- opts *repo_model.SearchRepoOptions
+ opts repo_model.SearchRepoOptions
count int
}{
{
name: "PublicRepositoriesByName",
- opts: &repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{PageSize: 10}, Collaborate: optional.Some(false)},
+ opts: repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{PageSize: 10}, Collaborate: optional.Some(false)},
count: 7,
},
{
name: "PublicAndPrivateRepositoriesByName",
- opts: &repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 1, PageSize: 10}, Private: true, Collaborate: optional.Some(false)},
+ opts: repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 1, PageSize: 10}, Private: true, Collaborate: optional.Some(false)},
count: 14,
},
{
name: "PublicAndPrivateRepositoriesByNameWithPagesizeLimitFirstPage",
- opts: &repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 1, PageSize: 5}, Private: true, Collaborate: optional.Some(false)},
+ opts: repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 1, PageSize: 5}, Private: true, Collaborate: optional.Some(false)},
count: 14,
},
{
name: "PublicAndPrivateRepositoriesByNameWithPagesizeLimitSecondPage",
- opts: &repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 2, PageSize: 5}, Private: true, Collaborate: optional.Some(false)},
+ opts: repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 2, PageSize: 5}, Private: true, Collaborate: optional.Some(false)},
count: 14,
},
{
name: "PublicAndPrivateRepositoriesByNameWithPagesizeLimitThirdPage",
- opts: &repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 3, PageSize: 5}, Private: true, Collaborate: optional.Some(false)},
+ opts: repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 3, PageSize: 5}, Private: true, Collaborate: optional.Some(false)},
count: 14,
},
{
name: "PublicAndPrivateRepositoriesByNameWithPagesizeLimitFourthPage",
- opts: &repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 3, PageSize: 5}, Private: true, Collaborate: optional.Some(false)},
+ opts: repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 3, PageSize: 5}, Private: true, Collaborate: optional.Some(false)},
count: 14,
},
{
name: "PublicRepositoriesOfUser",
- opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Collaborate: optional.Some(false)},
+ opts: repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Collaborate: optional.Some(false)},
count: 2,
},
{
name: "PublicRepositoriesOfUser2",
- opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 18, Collaborate: optional.Some(false)},
+ opts: repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 18, Collaborate: optional.Some(false)},
count: 0,
},
{
name: "PublicRepositoriesOfOrg3",
- opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 20, Collaborate: optional.Some(false)},
+ opts: repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 20, Collaborate: optional.Some(false)},
count: 2,
},
{
name: "PublicAndPrivateRepositoriesOfUser",
- opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Private: true, Collaborate: optional.Some(false)},
+ opts: repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Private: true, Collaborate: optional.Some(false)},
count: 4,
},
{
name: "PublicAndPrivateRepositoriesOfUser2",
- opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 18, Private: true, Collaborate: optional.Some(false)},
+ opts: repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 18, Private: true, Collaborate: optional.Some(false)},
count: 0,
},
{
name: "PublicAndPrivateRepositoriesOfOrg3",
- opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 20, Private: true, Collaborate: optional.Some(false)},
+ opts: repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 20, Private: true, Collaborate: optional.Some(false)},
count: 4,
},
{
name: "PublicRepositoriesOfUserIncludingCollaborative",
- opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15},
+ opts: repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15},
count: 5,
},
{
name: "PublicRepositoriesOfUser2IncludingCollaborative",
- opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 18},
+ opts: repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 18},
count: 1,
},
{
name: "PublicRepositoriesOfOrg3IncludingCollaborative",
- opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 20},
+ opts: repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 20},
count: 3,
},
{
name: "PublicAndPrivateRepositoriesOfUserIncludingCollaborative",
- opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Private: true},
+ opts: repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Private: true},
count: 9,
},
{
name: "PublicAndPrivateRepositoriesOfUser2IncludingCollaborative",
- opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 18, Private: true},
+ opts: repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 18, Private: true},
count: 4,
},
{
name: "PublicAndPrivateRepositoriesOfOrg3IncludingCollaborative",
- opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 20, Private: true},
+ opts: repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 20, Private: true},
count: 7,
},
{
name: "PublicRepositoriesOfOrganization",
- opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 17, Collaborate: optional.Some(false)},
+ opts: repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 17, Collaborate: optional.Some(false)},
count: 1,
},
{
name: "PublicAndPrivateRepositoriesOfOrganization",
- opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 17, Private: true, Collaborate: optional.Some(false)},
+ opts: repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 17, Private: true, Collaborate: optional.Some(false)},
count: 2,
},
{
name: "AllPublic/PublicRepositoriesByName",
- opts: &repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{PageSize: 10}, AllPublic: true, Collaborate: optional.Some(false)},
+ opts: repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{PageSize: 10}, AllPublic: true, Collaborate: optional.Some(false)},
count: 7,
},
{
name: "AllPublic/PublicAndPrivateRepositoriesByName",
- opts: &repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 1, PageSize: 10}, Private: true, AllPublic: true, Collaborate: optional.Some(false)},
+ opts: repo_model.SearchRepoOptions{Keyword: "big_test_", ListOptions: db.ListOptions{Page: 1, PageSize: 10}, Private: true, AllPublic: true, Collaborate: optional.Some(false)},
count: 14,
},
{
name: "AllPublic/PublicRepositoriesOfUserIncludingCollaborative",
- opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, AllPublic: true, Template: optional.Some(false)},
+ opts: repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, AllPublic: true, Template: optional.Some(false)},
count: 34,
},
{
name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborative",
- opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Private: true, AllPublic: true, AllLimited: true, Template: optional.Some(false)},
+ opts: repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Private: true, AllPublic: true, AllLimited: true, Template: optional.Some(false)},
count: 39,
},
{
name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborativeByName",
- opts: &repo_model.SearchRepoOptions{Keyword: "test", ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Private: true, AllPublic: true},
+ opts: repo_model.SearchRepoOptions{Keyword: "test", ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Private: true, AllPublic: true},
count: 15,
},
{
name: "AllPublic/PublicAndPrivateRepositoriesOfUser2IncludingCollaborativeByName",
- opts: &repo_model.SearchRepoOptions{Keyword: "test", ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 18, Private: true, AllPublic: true},
+ opts: repo_model.SearchRepoOptions{Keyword: "test", ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 18, Private: true, AllPublic: true},
count: 13,
},
{
name: "AllPublic/PublicRepositoriesOfOrganization",
- opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 17, AllPublic: true, Collaborate: optional.Some(false), Template: optional.Some(false)},
+ opts: repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 17, AllPublic: true, Collaborate: optional.Some(false), Template: optional.Some(false)},
count: 34,
},
{
name: "AllTemplates",
- opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, Template: optional.Some(true)},
+ opts: repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, Template: optional.Some(true)},
count: 2,
},
{
name: "OwnerSlashRepoSearch",
- opts: &repo_model.SearchRepoOptions{Keyword: "user/repo2", ListOptions: db.ListOptions{Page: 1, PageSize: 10}, Private: true, OwnerID: 0},
+ opts: repo_model.SearchRepoOptions{Keyword: "user/repo2", ListOptions: db.ListOptions{Page: 1, PageSize: 10}, Private: true, OwnerID: 0},
count: 2,
},
{
name: "OwnerSlashSearch",
- opts: &repo_model.SearchRepoOptions{Keyword: "user20/", ListOptions: db.ListOptions{Page: 1, PageSize: 10}, Private: true, OwnerID: 0},
+ opts: repo_model.SearchRepoOptions{Keyword: "user20/", ListOptions: db.ListOptions{Page: 1, PageSize: 10}, Private: true, OwnerID: 0},
count: 4,
},
}
@@ -184,7 +184,7 @@ func TestSearchRepository(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
// test search public repository on explore page
- repos, count, err := repo_model.SearchRepositoryByName(db.DefaultContext, &repo_model.SearchRepoOptions{
+ repos, count, err := repo_model.SearchRepositoryByName(db.DefaultContext, repo_model.SearchRepoOptions{
ListOptions: db.ListOptions{
Page: 1,
PageSize: 10,
@@ -199,7 +199,7 @@ func TestSearchRepository(t *testing.T) {
}
assert.Equal(t, int64(1), count)
- repos, count, err = repo_model.SearchRepositoryByName(db.DefaultContext, &repo_model.SearchRepoOptions{
+ repos, count, err = repo_model.SearchRepositoryByName(db.DefaultContext, repo_model.SearchRepoOptions{
ListOptions: db.ListOptions{
Page: 1,
PageSize: 10,
@@ -213,7 +213,7 @@ func TestSearchRepository(t *testing.T) {
assert.Len(t, repos, 2)
// test search private repository on explore page
- repos, count, err = repo_model.SearchRepositoryByName(db.DefaultContext, &repo_model.SearchRepoOptions{
+ repos, count, err = repo_model.SearchRepositoryByName(db.DefaultContext, repo_model.SearchRepoOptions{
ListOptions: db.ListOptions{
Page: 1,
PageSize: 10,
@@ -229,7 +229,7 @@ func TestSearchRepository(t *testing.T) {
}
assert.Equal(t, int64(1), count)
- repos, count, err = repo_model.SearchRepositoryByName(db.DefaultContext, &repo_model.SearchRepoOptions{
+ repos, count, err = repo_model.SearchRepositoryByName(db.DefaultContext, repo_model.SearchRepoOptions{
ListOptions: db.ListOptions{
Page: 1,
PageSize: 10,
@@ -244,14 +244,14 @@ func TestSearchRepository(t *testing.T) {
assert.Len(t, repos, 3)
// Test non existing owner
- repos, count, err = repo_model.SearchRepositoryByName(db.DefaultContext, &repo_model.SearchRepoOptions{OwnerID: unittest.NonexistentID})
+ repos, count, err = repo_model.SearchRepositoryByName(db.DefaultContext, repo_model.SearchRepoOptions{OwnerID: unittest.NonexistentID})
assert.NoError(t, err)
assert.Empty(t, repos)
assert.Equal(t, int64(0), count)
// Test search within description
- repos, count, err = repo_model.SearchRepository(db.DefaultContext, &repo_model.SearchRepoOptions{
+ repos, count, err = repo_model.SearchRepository(db.DefaultContext, repo_model.SearchRepoOptions{
ListOptions: db.ListOptions{
Page: 1,
PageSize: 10,
@@ -268,7 +268,7 @@ func TestSearchRepository(t *testing.T) {
assert.Equal(t, int64(1), count)
// Test NOT search within description
- repos, count, err = repo_model.SearchRepository(db.DefaultContext, &repo_model.SearchRepoOptions{
+ repos, count, err = repo_model.SearchRepository(db.DefaultContext, repo_model.SearchRepoOptions{
ListOptions: db.ListOptions{
Page: 1,
PageSize: 10,
@@ -374,22 +374,22 @@ func TestSearchRepositoryByTopicName(t *testing.T) {
testCases := []struct {
name string
- opts *repo_model.SearchRepoOptions
+ opts repo_model.SearchRepoOptions
count int
}{
{
name: "AllPublic/SearchPublicRepositoriesFromTopicAndName",
- opts: &repo_model.SearchRepoOptions{OwnerID: 21, AllPublic: true, Keyword: "graphql"},
+ opts: repo_model.SearchRepoOptions{OwnerID: 21, AllPublic: true, Keyword: "graphql"},
count: 2,
},
{
name: "AllPublic/OnlySearchPublicRepositoriesFromTopic",
- opts: &repo_model.SearchRepoOptions{OwnerID: 21, AllPublic: true, Keyword: "graphql", TopicOnly: true},
+ opts: repo_model.SearchRepoOptions{OwnerID: 21, AllPublic: true, Keyword: "graphql", TopicOnly: true},
count: 1,
},
{
name: "AllPublic/OnlySearchMultipleKeywordPublicRepositoriesFromTopic",
- opts: &repo_model.SearchRepoOptions{OwnerID: 21, AllPublic: true, Keyword: "graphql,golang", TopicOnly: true},
+ opts: repo_model.SearchRepoOptions{OwnerID: 21, AllPublic: true, Keyword: "graphql,golang", TopicOnly: true},
count: 2,
},
}
diff --git a/models/repo/repo_test.go b/models/repo/repo_test.go
index b2604ab575..66abe864fc 100644
--- a/models/repo/repo_test.go
+++ b/models/repo/repo_test.go
@@ -216,8 +216,23 @@ func TestIsUsableRepoName(t *testing.T) {
assert.Error(t, IsUsableRepoName("-"))
assert.Error(t, IsUsableRepoName("🌞"))
+ assert.Error(t, IsUsableRepoName("the/repo"))
assert.Error(t, IsUsableRepoName("the..repo"))
assert.Error(t, IsUsableRepoName("foo.wiki"))
assert.Error(t, IsUsableRepoName("foo.git"))
assert.Error(t, IsUsableRepoName("foo.RSS"))
}
+
+func TestIsValidSSHAccessRepoName(t *testing.T) {
+ assert.True(t, IsValidSSHAccessRepoName("a"))
+ assert.True(t, IsValidSSHAccessRepoName("-1_."))
+ assert.True(t, IsValidSSHAccessRepoName(".profile"))
+ assert.True(t, IsValidSSHAccessRepoName("foo.wiki"))
+
+ assert.False(t, IsValidSSHAccessRepoName("-"))
+ assert.False(t, IsValidSSHAccessRepoName("🌞"))
+ assert.False(t, IsValidSSHAccessRepoName("the/repo"))
+ assert.False(t, IsValidSSHAccessRepoName("the..repo"))
+ assert.False(t, IsValidSSHAccessRepoName("foo.git"))
+ assert.False(t, IsValidSSHAccessRepoName("foo.RSS"))
+}
diff --git a/models/repo/repo_unit.go b/models/repo/repo_unit.go
index 8a7dbfe340..a5207bc22a 100644
--- a/models/repo/repo_unit.go
+++ b/models/repo/repo_unit.go
@@ -185,10 +185,8 @@ func (cfg *ActionsConfig) IsWorkflowDisabled(file string) bool {
}
func (cfg *ActionsConfig) DisableWorkflow(file string) {
- for _, workflow := range cfg.DisabledWorkflows {
- if file == workflow {
- return
- }
+ if slices.Contains(cfg.DisabledWorkflows, file) {
+ return
}
cfg.DisabledWorkflows = append(cfg.DisabledWorkflows, file)
diff --git a/models/repo/star.go b/models/repo/star.go
index 4c66855525..bc865f8373 100644
--- a/models/repo/star.go
+++ b/models/repo/star.go
@@ -25,48 +25,45 @@ func init() {
// StarRepo or unstar repository.
func StarRepo(ctx context.Context, doer *user_model.User, repo *Repository, star bool) error {
- ctx, committer, err := db.TxContext(ctx)
- if err != nil {
- return err
- }
- defer committer.Close()
- staring := IsStaring(ctx, doer.ID, repo.ID)
-
- if star {
- if user_model.IsUserBlockedBy(ctx, doer, repo.OwnerID) {
- return user_model.ErrBlockedUser
- }
-
- if staring {
- return nil
- }
-
- if err := db.Insert(ctx, &Star{UID: doer.ID, RepoID: repo.ID}); err != nil {
- return err
- }
- if _, err := db.Exec(ctx, "UPDATE `repository` SET num_stars = num_stars + 1 WHERE id = ?", repo.ID); err != nil {
- return err
+ return db.WithTx(ctx, func(ctx context.Context) error {
+ staring := IsStaring(ctx, doer.ID, repo.ID)
+
+ if star {
+ if user_model.IsUserBlockedBy(ctx, doer, repo.OwnerID) {
+ return user_model.ErrBlockedUser
+ }
+
+ if staring {
+ return nil
+ }
+
+ if err := db.Insert(ctx, &Star{UID: doer.ID, RepoID: repo.ID}); err != nil {
+ return err
+ }
+ if _, err := db.Exec(ctx, "UPDATE `repository` SET num_stars = num_stars + 1 WHERE id = ?", repo.ID); err != nil {
+ return err
+ }
+ if _, err := db.Exec(ctx, "UPDATE `user` SET num_stars = num_stars + 1 WHERE id = ?", doer.ID); err != nil {
+ return err
+ }
+ } else {
+ if !staring {
+ return nil
+ }
+
+ if _, err := db.DeleteByBean(ctx, &Star{UID: doer.ID, RepoID: repo.ID}); err != nil {
+ return err
+ }
+ if _, err := db.Exec(ctx, "UPDATE `repository` SET num_stars = num_stars - 1 WHERE id = ?", repo.ID); err != nil {
+ return err
+ }
+ if _, err := db.Exec(ctx, "UPDATE `user` SET num_stars = num_stars - 1 WHERE id = ?", doer.ID); err != nil {
+ return err
+ }
}
- if _, err := db.Exec(ctx, "UPDATE `user` SET num_stars = num_stars + 1 WHERE id = ?", doer.ID); err != nil {
- return err
- }
- } else {
- if !staring {
- return nil
- }
-
- if _, err := db.DeleteByBean(ctx, &Star{UID: doer.ID, RepoID: repo.ID}); err != nil {
- return err
- }
- if _, err := db.Exec(ctx, "UPDATE `repository` SET num_stars = num_stars - 1 WHERE id = ?", repo.ID); err != nil {
- return err
- }
- if _, err := db.Exec(ctx, "UPDATE `user` SET num_stars = num_stars - 1 WHERE id = ?", doer.ID); err != nil {
- return err
- }
- }
- return committer.Commit()
+ return nil
+ })
}
// IsStaring checks if user has starred given repository.
diff --git a/models/repo/topic.go b/models/repo/topic.go
index 430a60f603..baeae01efa 100644
--- a/models/repo/topic.go
+++ b/models/repo/topic.go
@@ -227,32 +227,26 @@ func GetRepoTopicByName(ctx context.Context, repoID int64, topicName string) (*T
// AddTopic adds a topic name to a repository (if it does not already have it)
func AddTopic(ctx context.Context, repoID int64, topicName string) (*Topic, error) {
- ctx, committer, err := db.TxContext(ctx)
- if err != nil {
- return nil, err
- }
- defer committer.Close()
- sess := db.GetEngine(ctx)
-
- topic, err := GetRepoTopicByName(ctx, repoID, topicName)
- if err != nil {
- return nil, err
- }
- if topic != nil {
- // Repo already have topic
- return topic, nil
- }
-
- topic, err = addTopicByNameToRepo(ctx, repoID, topicName)
- if err != nil {
- return nil, err
- }
+ return db.WithTx2(ctx, func(ctx context.Context) (*Topic, error) {
+ topic, err := GetRepoTopicByName(ctx, repoID, topicName)
+ if err != nil {
+ return nil, err
+ }
+ if topic != nil {
+ // Repo already have topic
+ return topic, nil
+ }
- if err = syncTopicsInRepository(sess, repoID); err != nil {
- return nil, err
- }
+ topic, err = addTopicByNameToRepo(ctx, repoID, topicName)
+ if err != nil {
+ return nil, err
+ }
- return topic, committer.Commit()
+ if err = syncTopicsInRepository(ctx, repoID); err != nil {
+ return nil, err
+ }
+ return topic, nil
+ })
}
// DeleteTopic removes a topic name from a repository (if it has it)
@@ -266,14 +260,15 @@ func DeleteTopic(ctx context.Context, repoID int64, topicName string) (*Topic, e
return nil, nil
}
- err = removeTopicFromRepo(ctx, repoID, topic)
- if err != nil {
- return nil, err
- }
-
- err = syncTopicsInRepository(db.GetEngine(ctx), repoID)
-
- return topic, err
+ return db.WithTx2(ctx, func(ctx context.Context) (*Topic, error) {
+ if err = removeTopicFromRepo(ctx, repoID, topic); err != nil {
+ return nil, err
+ }
+ if err = syncTopicsInRepository(ctx, repoID); err != nil {
+ return nil, err
+ }
+ return topic, nil
+ })
}
// SaveTopics save topics to a repository
@@ -285,64 +280,55 @@ func SaveTopics(ctx context.Context, repoID int64, topicNames ...string) error {
return err
}
- ctx, committer, err := db.TxContext(ctx)
- if err != nil {
- return err
- }
- defer committer.Close()
- sess := db.GetEngine(ctx)
+ return db.WithTx(ctx, func(ctx context.Context) error {
+ var addedTopicNames []string
+ for _, topicName := range topicNames {
+ if strings.TrimSpace(topicName) == "" {
+ continue
+ }
- var addedTopicNames []string
- for _, topicName := range topicNames {
- if strings.TrimSpace(topicName) == "" {
- continue
+ var found bool
+ for _, t := range topics {
+ if strings.EqualFold(topicName, t.Name) {
+ found = true
+ break
+ }
+ }
+ if !found {
+ addedTopicNames = append(addedTopicNames, topicName)
+ }
}
- var found bool
+ var removeTopics []*Topic
for _, t := range topics {
- if strings.EqualFold(topicName, t.Name) {
- found = true
- break
+ var found bool
+ for _, topicName := range topicNames {
+ if strings.EqualFold(topicName, t.Name) {
+ found = true
+ break
+ }
}
- }
- if !found {
- addedTopicNames = append(addedTopicNames, topicName)
- }
- }
-
- var removeTopics []*Topic
- for _, t := range topics {
- var found bool
- for _, topicName := range topicNames {
- if strings.EqualFold(topicName, t.Name) {
- found = true
- break
+ if !found {
+ removeTopics = append(removeTopics, t)
}
}
- if !found {
- removeTopics = append(removeTopics, t)
- }
- }
- for _, topicName := range addedTopicNames {
- _, err := addTopicByNameToRepo(ctx, repoID, topicName)
- if err != nil {
- return err
+ for _, topicName := range addedTopicNames {
+ _, err := addTopicByNameToRepo(ctx, repoID, topicName)
+ if err != nil {
+ return err
+ }
}
- }
- for _, topic := range removeTopics {
- err := removeTopicFromRepo(ctx, repoID, topic)
- if err != nil {
- return err
+ for _, topic := range removeTopics {
+ err := removeTopicFromRepo(ctx, repoID, topic)
+ if err != nil {
+ return err
+ }
}
- }
- if err := syncTopicsInRepository(sess, repoID); err != nil {
- return err
- }
-
- return committer.Commit()
+ return syncTopicsInRepository(ctx, repoID)
+ })
}
// GenerateTopics generates topics from a template repository
@@ -353,19 +339,19 @@ func GenerateTopics(ctx context.Context, templateRepo, generateRepo *Repository)
}
}
- return syncTopicsInRepository(db.GetEngine(ctx), generateRepo.ID)
+ return syncTopicsInRepository(ctx, generateRepo.ID)
}
// syncTopicsInRepository makes sure topics in the topics table are copied into the topics field of the repository
-func syncTopicsInRepository(sess db.Engine, repoID int64) error {
+func syncTopicsInRepository(ctx context.Context, repoID int64) error {
topicNames := make([]string, 0, 25)
- if err := sess.Table("topic").Cols("name").
+ if err := db.GetEngine(ctx).Table("topic").Cols("name").
Join("INNER", "repo_topic", "repo_topic.topic_id = topic.id").
Where("repo_topic.repo_id = ?", repoID).Asc("topic.name").Find(&topicNames); err != nil {
return err
}
- if _, err := sess.ID(repoID).Cols("topics").Update(&Repository{
+ if _, err := db.GetEngine(ctx).ID(repoID).Cols("topics").Update(&Repository{
Topics: topicNames,
}); err != nil {
return err
diff --git a/models/repo/transfer.go b/models/repo/transfer.go
index b669145d68..3fb8cb69ab 100644
--- a/models/repo/transfer.go
+++ b/models/repo/transfer.go
@@ -61,7 +61,7 @@ func (err ErrRepoTransferInProgress) Unwrap() error {
}
// RepoTransfer is used to manage repository transfers
-type RepoTransfer struct { //nolint
+type RepoTransfer struct { //nolint:revive // export stutter
ID int64 `xorm:"pk autoincr"`
DoerID int64
Doer *user_model.User `xorm:"-"`
@@ -249,7 +249,7 @@ func CreatePendingRepositoryTransfer(ctx context.Context, doer, newOwner *user_m
}
repo.Status = RepositoryPendingTransfer
- if err := UpdateRepositoryCols(ctx, repo, "status"); err != nil {
+ if err := UpdateRepositoryColsNoAutoTime(ctx, repo, "status"); err != nil {
return err
}
diff --git a/models/repo/update.go b/models/repo/update.go
index 15c8c48d5b..3228ae11a4 100644
--- a/models/repo/update.go
+++ b/models/repo/update.go
@@ -19,19 +19,14 @@ func UpdateRepositoryOwnerNames(ctx context.Context, ownerID int64, ownerName st
if ownerID == 0 {
return nil
}
- ctx, committer, err := db.TxContext(ctx)
- if err != nil {
- return err
- }
- defer committer.Close()
- if _, err := db.GetEngine(ctx).Where("owner_id = ?", ownerID).Cols("owner_name").Update(&Repository{
+ if _, err := db.GetEngine(ctx).Where("owner_id = ?", ownerID).Cols("owner_name").NoAutoTime().Update(&Repository{
OwnerName: ownerName,
}); err != nil {
return err
}
- return committer.Commit()
+ return nil
}
// UpdateRepositoryUpdatedTime updates a repository's updated time
@@ -40,15 +35,15 @@ func UpdateRepositoryUpdatedTime(ctx context.Context, repoID int64, updateTime t
return err
}
-// UpdateRepositoryCols updates repository's columns
-func UpdateRepositoryCols(ctx context.Context, repo *Repository, cols ...string) error {
- _, err := db.GetEngine(ctx).ID(repo.ID).Cols(cols...).Update(repo)
+// UpdateRepositoryColsWithAutoTime updates repository's columns and the timestamp fields automatically
+func UpdateRepositoryColsWithAutoTime(ctx context.Context, repo *Repository, colName string, moreColNames ...string) error {
+ _, err := db.GetEngine(ctx).ID(repo.ID).Cols(append([]string{colName}, moreColNames...)...).Update(repo)
return err
}
-// UpdateRepositoryColsNoAutoTime updates repository's columns and but applies time change automatically
-func UpdateRepositoryColsNoAutoTime(ctx context.Context, repo *Repository, cols ...string) error {
- _, err := db.GetEngine(ctx).ID(repo.ID).Cols(cols...).NoAutoTime().Update(repo)
+// UpdateRepositoryColsNoAutoTime updates repository's columns, doesn't change timestamp field automatically
+func UpdateRepositoryColsNoAutoTime(ctx context.Context, repo *Repository, colName string, moreColNames ...string) error {
+ _, err := db.GetEngine(ctx).ID(repo.ID).Cols(append([]string{colName}, moreColNames...)...).NoAutoTime().Update(repo)
return err
}
diff --git a/models/repo/upload.go b/models/repo/upload.go
index fb57fb6c51..f7d4749842 100644
--- a/models/repo/upload.go
+++ b/models/repo/upload.go
@@ -117,24 +117,14 @@ func DeleteUploads(ctx context.Context, uploads ...*Upload) (err error) {
return nil
}
- ctx, committer, err := db.TxContext(ctx)
- if err != nil {
- return err
- }
- defer committer.Close()
-
ids := make([]int64, len(uploads))
- for i := 0; i < len(uploads); i++ {
+ for i := range uploads {
ids[i] = uploads[i].ID
}
if err = db.DeleteByIDs[Upload](ctx, ids...); err != nil {
return fmt.Errorf("delete uploads: %w", err)
}
- if err = committer.Commit(); err != nil {
- return err
- }
-
for _, upload := range uploads {
localPath := upload.LocalPath()
isFile, err := util.IsFile(localPath)