mirror of
https://github.com/go-gitea/gitea.git
synced 2026-08-06 16:46:44 +02:00
Merge remote-tracking branch 'upstream/main' into limit-repo-size
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package actions
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
)
|
||||
|
||||
// ActionTaskOutput represents an output of ActionTask.
|
||||
// So the outputs are bound to a task, that means when a completed job has been rerun,
|
||||
// the outputs of the job will be reset because the task is new.
|
||||
// It's by design, to avoid the outputs of the old task to be mixed with the new task.
|
||||
type ActionTaskOutput struct {
|
||||
ID int64
|
||||
TaskID int64 `xorm:"INDEX UNIQUE(task_id_output_key)"`
|
||||
OutputKey string `xorm:"VARCHAR(255) UNIQUE(task_id_output_key)"`
|
||||
OutputValue string `xorm:"MEDIUMTEXT"`
|
||||
}
|
||||
|
||||
// FindTaskOutputByTaskID returns the outputs of the task.
|
||||
func FindTaskOutputByTaskID(ctx context.Context, taskID int64) ([]*ActionTaskOutput, error) {
|
||||
var outputs []*ActionTaskOutput
|
||||
return outputs, db.GetEngine(ctx).Where("task_id=?", taskID).Find(&outputs)
|
||||
}
|
||||
|
||||
// FindTaskOutputKeyByTaskID returns the keys of the outputs of the task.
|
||||
func FindTaskOutputKeyByTaskID(ctx context.Context, taskID int64) ([]string, error) {
|
||||
var keys []string
|
||||
return keys, db.GetEngine(ctx).Table(ActionTaskOutput{}).Where("task_id=?", taskID).Cols("output_key").Find(&keys)
|
||||
}
|
||||
|
||||
// InsertTaskOutputIfNotExist inserts a new task output if it does not exist.
|
||||
func InsertTaskOutputIfNotExist(ctx context.Context, taskID int64, key, value string) error {
|
||||
return db.WithTx(ctx, func(ctx context.Context) error {
|
||||
sess := db.GetEngine(ctx)
|
||||
if exist, err := sess.Exist(&ActionTaskOutput{TaskID: taskID, OutputKey: key}); err != nil {
|
||||
return err
|
||||
} else if exist {
|
||||
return nil
|
||||
}
|
||||
_, err := sess.Insert(&ActionTaskOutput{
|
||||
TaskID: taskID,
|
||||
OutputKey: key,
|
||||
OutputValue: value,
|
||||
})
|
||||
return err
|
||||
})
|
||||
}
|
||||
@@ -19,13 +19,16 @@ func TestIterate(t *testing.T) {
|
||||
xe := unittest.GetXORMEngine()
|
||||
assert.NoError(t, xe.Sync(&repo_model.RepoUnit{}))
|
||||
|
||||
var repoCnt int
|
||||
err := db.Iterate(db.DefaultContext, nil, func(ctx context.Context, repo *repo_model.RepoUnit) error {
|
||||
repoCnt++
|
||||
cnt, err := db.GetEngine(db.DefaultContext).Count(&repo_model.RepoUnit{})
|
||||
assert.NoError(t, err)
|
||||
|
||||
var repoUnitCnt int
|
||||
err = db.Iterate(db.DefaultContext, nil, func(ctx context.Context, repo *repo_model.RepoUnit) error {
|
||||
repoUnitCnt++
|
||||
return nil
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, 84, repoCnt)
|
||||
assert.EqualValues(t, cnt, repoUnitCnt)
|
||||
|
||||
err = db.Iterate(db.DefaultContext, nil, func(ctx context.Context, repoUnit *repo_model.RepoUnit) error {
|
||||
reopUnit2 := repo_model.RepoUnit{ID: repoUnit.ID}
|
||||
|
||||
@@ -31,15 +31,20 @@ func TestFind(t *testing.T) {
|
||||
xe := unittest.GetXORMEngine()
|
||||
assert.NoError(t, xe.Sync(&repo_model.RepoUnit{}))
|
||||
|
||||
var repoUnitCount int
|
||||
_, err := db.GetEngine(db.DefaultContext).SQL("SELECT COUNT(*) FROM repo_unit").Get(&repoUnitCount)
|
||||
assert.NoError(t, err)
|
||||
assert.NotEmpty(t, repoUnitCount)
|
||||
|
||||
opts := mockListOptions{}
|
||||
var repoUnits []repo_model.RepoUnit
|
||||
err := db.Find(db.DefaultContext, &opts, &repoUnits)
|
||||
err = db.Find(db.DefaultContext, &opts, &repoUnits)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, 84, len(repoUnits))
|
||||
assert.Len(t, repoUnits, repoUnitCount)
|
||||
|
||||
cnt, err := db.Count(db.DefaultContext, &opts, new(repo_model.RepoUnit))
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, 84, cnt)
|
||||
assert.EqualValues(t, repoUnitCount, cnt)
|
||||
|
||||
repoUnits = make([]repo_model.RepoUnit, 0, 10)
|
||||
newCnt, err := db.FindAndCount(db.DefaultContext, &opts, &repoUnits)
|
||||
|
||||
@@ -12,8 +12,6 @@ import (
|
||||
"code.gitea.io/gitea/models/db"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
)
|
||||
|
||||
func changeDefaultFileBlockSize(n int64) (restore func()) {
|
||||
|
||||
@@ -66,3 +66,45 @@
|
||||
is_prerelease: true
|
||||
is_tag: false
|
||||
created_unix: 946684800
|
||||
|
||||
- id: 6
|
||||
repo_id: 57
|
||||
publisher_id: 2
|
||||
tag_name: "v1.0"
|
||||
lower_tag_name: "v1.0"
|
||||
target: "main"
|
||||
title: "v1.0"
|
||||
sha1: "a8a700e8c644c783ba2c6e742bb81bf91e244bff"
|
||||
num_commits: 3
|
||||
is_draft: false
|
||||
is_prerelease: false
|
||||
is_tag: false
|
||||
created_unix: 946684801
|
||||
|
||||
- id: 7
|
||||
repo_id: 57
|
||||
publisher_id: 2
|
||||
tag_name: "v1.1"
|
||||
lower_tag_name: "v1.1"
|
||||
target: "main"
|
||||
title: "v1.1"
|
||||
sha1: "cef06e48f2642cd0dc9597b4bea09f4b3f74aad6"
|
||||
num_commits: 5
|
||||
is_draft: false
|
||||
is_prerelease: false
|
||||
is_tag: false
|
||||
created_unix: 946684802
|
||||
|
||||
- id: 8
|
||||
repo_id: 57
|
||||
publisher_id: 2
|
||||
tag_name: "v2.0"
|
||||
lower_tag_name: "v2.0"
|
||||
target: "main"
|
||||
title: "v2.0"
|
||||
sha1: "7197b56fdc75b453f47c9110938cb46a303579fd"
|
||||
num_commits: 6
|
||||
is_draft: false
|
||||
is_prerelease: false
|
||||
is_tag: false
|
||||
created_unix: 946684803
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# See models/unit/unit.go for the meaning of the type
|
||||
-
|
||||
id: 1
|
||||
repo_id: 1
|
||||
@@ -575,3 +576,34 @@
|
||||
repo_id: 56
|
||||
type: 1
|
||||
created_unix: 946684810
|
||||
-
|
||||
id: 85
|
||||
repo_id: 57
|
||||
type: 1
|
||||
created_unix: 946684810
|
||||
-
|
||||
id: 86
|
||||
repo_id: 57
|
||||
type: 2
|
||||
created_unix: 946684810
|
||||
-
|
||||
id: 87
|
||||
repo_id: 57
|
||||
type: 3
|
||||
created_unix: 946684810
|
||||
-
|
||||
id: 88
|
||||
repo_id: 57
|
||||
type: 4
|
||||
created_unix: 946684810
|
||||
-
|
||||
id: 89
|
||||
repo_id: 57
|
||||
type: 5
|
||||
created_unix: 946684810
|
||||
|
||||
-
|
||||
id: 90
|
||||
repo_id: 52
|
||||
type: 1
|
||||
created_unix: 946684810
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# don't forget to add fixtures in repo_unit.yml
|
||||
-
|
||||
id: 1
|
||||
owner_id: 2
|
||||
@@ -1559,6 +1560,7 @@
|
||||
owner_name: user30
|
||||
lower_name: empty
|
||||
name: empty
|
||||
default_branch: master
|
||||
num_watches: 0
|
||||
num_stars: 0
|
||||
num_forks: 0
|
||||
@@ -1647,3 +1649,16 @@
|
||||
is_private: true
|
||||
status: 0
|
||||
num_issues: 0
|
||||
|
||||
-
|
||||
id: 57
|
||||
owner_id: 2
|
||||
owner_name: user2
|
||||
lower_name: repo-release
|
||||
name: repo-release
|
||||
default_branch: main
|
||||
is_empty: false
|
||||
is_archived: false
|
||||
is_private: false
|
||||
status: 0
|
||||
num_issues: 0
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
num_followers: 2
|
||||
num_following: 1
|
||||
num_stars: 2
|
||||
num_repos: 12
|
||||
num_repos: 13
|
||||
num_teams: 0
|
||||
num_members: 0
|
||||
visibility: 0
|
||||
@@ -1091,7 +1091,7 @@
|
||||
max_repo_creation: -1
|
||||
is_active: true
|
||||
is_admin: false
|
||||
is_restricted: true
|
||||
is_restricted: false
|
||||
allow_git_hook: false
|
||||
allow_import_local: false
|
||||
allow_create_organization: true
|
||||
|
||||
@@ -88,12 +88,12 @@ func TestFindRenamedBranch(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
branch, exist, err := git_model.FindRenamedBranch(db.DefaultContext, 1, "dev")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, true, exist)
|
||||
assert.True(t, exist)
|
||||
assert.Equal(t, "master", branch.To)
|
||||
|
||||
_, exist, err = git_model.FindRenamedBranch(db.DefaultContext, 1, "unknow")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, false, exist)
|
||||
assert.False(t, exist)
|
||||
}
|
||||
|
||||
func TestRenameBranch(t *testing.T) {
|
||||
@@ -115,7 +115,7 @@ func TestRenameBranch(t *testing.T) {
|
||||
return nil
|
||||
}))
|
||||
|
||||
assert.Equal(t, true, _isDefault)
|
||||
assert.True(t, _isDefault)
|
||||
repo1 = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||
assert.Equal(t, "main", repo1.DefaultBranch)
|
||||
|
||||
|
||||
+70
-77
@@ -52,84 +52,61 @@ func (err ErrCommentNotExist) Unwrap() error {
|
||||
// CommentType defines whether a comment is just a simple comment, an action (like close) or a reference.
|
||||
type CommentType int
|
||||
|
||||
// define unknown comment type
|
||||
const (
|
||||
CommentTypeUnknown CommentType = -1
|
||||
)
|
||||
// CommentTypeUndefined is used to search for comments of any type
|
||||
const CommentTypeUndefined CommentType = -1
|
||||
|
||||
// Enumerate all the comment types
|
||||
const (
|
||||
// 0 Plain comment, can be associated with a commit (CommitID > 0) and a line (LineNum > 0)
|
||||
CommentTypeComment CommentType = iota
|
||||
CommentTypeReopen // 1
|
||||
CommentTypeClose // 2
|
||||
CommentTypeComment CommentType = iota // 0 Plain comment, can be associated with a commit (CommitID > 0) and a line (LineNum > 0)
|
||||
|
||||
CommentTypeReopen // 1
|
||||
CommentTypeClose // 2
|
||||
|
||||
CommentTypeIssueRef // 3 References.
|
||||
CommentTypeCommitRef // 4 Reference from a commit (not part of a pull request)
|
||||
CommentTypeCommentRef // 5 Reference from a comment
|
||||
CommentTypePullRef // 6 Reference from a pull request
|
||||
|
||||
CommentTypeLabel // 7 Labels changed
|
||||
CommentTypeMilestone // 8 Milestone changed
|
||||
CommentTypeAssignees // 9 Assignees changed
|
||||
CommentTypeChangeTitle // 10 Change Title
|
||||
CommentTypeDeleteBranch // 11 Delete Branch
|
||||
|
||||
CommentTypeStartTracking // 12 Start a stopwatch for time tracking
|
||||
CommentTypeStopTracking // 13 Stop a stopwatch for time tracking
|
||||
CommentTypeAddTimeManual // 14 Add time manual for time tracking
|
||||
CommentTypeCancelTracking // 15 Cancel a stopwatch for time tracking
|
||||
CommentTypeAddedDeadline // 16 Added a due date
|
||||
CommentTypeModifiedDeadline // 17 Modified the due date
|
||||
CommentTypeRemovedDeadline // 18 Removed a due date
|
||||
|
||||
CommentTypeAddDependency // 19 Dependency added
|
||||
CommentTypeRemoveDependency // 20 Dependency removed
|
||||
|
||||
CommentTypeCode // 21 Comment a line of code
|
||||
CommentTypeReview // 22 Reviews a pull request by giving general feedback
|
||||
|
||||
CommentTypeLock // 23 Lock an issue, giving only collaborators access
|
||||
CommentTypeUnlock // 24 Unlocks a previously locked issue
|
||||
|
||||
CommentTypeChangeTargetBranch // 25 Change pull request's target branch
|
||||
|
||||
CommentTypeDeleteTimeManual // 26 Delete time manual for time tracking
|
||||
|
||||
CommentTypeReviewRequest // 27 add or remove Request from one
|
||||
CommentTypeMergePull // 28 merge pull request
|
||||
CommentTypePullRequestPush // 29 push to PR head branch
|
||||
|
||||
CommentTypeProject // 30 Project changed
|
||||
CommentTypeProjectBoard // 31 Project board changed
|
||||
|
||||
CommentTypeDismissReview // 32 Dismiss Review
|
||||
|
||||
CommentTypeChangeIssueRef // 33 Change issue ref
|
||||
|
||||
CommentTypePRScheduledToAutoMerge // 34 pr was scheduled to auto merge when checks succeed
|
||||
CommentTypePRUnScheduledToAutoMerge // 35 pr was un scheduled to auto merge when checks succeed
|
||||
|
||||
// 3 References.
|
||||
CommentTypeIssueRef
|
||||
// 4 Reference from a commit (not part of a pull request)
|
||||
CommentTypeCommitRef
|
||||
// 5 Reference from a comment
|
||||
CommentTypeCommentRef
|
||||
// 6 Reference from a pull request
|
||||
CommentTypePullRef
|
||||
// 7 Labels changed
|
||||
CommentTypeLabel
|
||||
// 8 Milestone changed
|
||||
CommentTypeMilestone
|
||||
// 9 Assignees changed
|
||||
CommentTypeAssignees
|
||||
// 10 Change Title
|
||||
CommentTypeChangeTitle
|
||||
// 11 Delete Branch
|
||||
CommentTypeDeleteBranch
|
||||
// 12 Start a stopwatch for time tracking
|
||||
CommentTypeStartTracking
|
||||
// 13 Stop a stopwatch for time tracking
|
||||
CommentTypeStopTracking
|
||||
// 14 Add time manual for time tracking
|
||||
CommentTypeAddTimeManual
|
||||
// 15 Cancel a stopwatch for time tracking
|
||||
CommentTypeCancelTracking
|
||||
// 16 Added a due date
|
||||
CommentTypeAddedDeadline
|
||||
// 17 Modified the due date
|
||||
CommentTypeModifiedDeadline
|
||||
// 18 Removed a due date
|
||||
CommentTypeRemovedDeadline
|
||||
// 19 Dependency added
|
||||
CommentTypeAddDependency
|
||||
// 20 Dependency removed
|
||||
CommentTypeRemoveDependency
|
||||
// 21 Comment a line of code
|
||||
CommentTypeCode
|
||||
// 22 Reviews a pull request by giving general feedback
|
||||
CommentTypeReview
|
||||
// 23 Lock an issue, giving only collaborators access
|
||||
CommentTypeLock
|
||||
// 24 Unlocks a previously locked issue
|
||||
CommentTypeUnlock
|
||||
// 25 Change pull request's target branch
|
||||
CommentTypeChangeTargetBranch
|
||||
// 26 Delete time manual for time tracking
|
||||
CommentTypeDeleteTimeManual
|
||||
// 27 add or remove Request from one
|
||||
CommentTypeReviewRequest
|
||||
// 28 merge pull request
|
||||
CommentTypeMergePull
|
||||
// 29 push to PR head branch
|
||||
CommentTypePullRequestPush
|
||||
// 30 Project changed
|
||||
CommentTypeProject
|
||||
// 31 Project board changed
|
||||
CommentTypeProjectBoard
|
||||
// 32 Dismiss Review
|
||||
CommentTypeDismissReview
|
||||
// 33 Change issue ref
|
||||
CommentTypeChangeIssueRef
|
||||
// 34 pr was scheduled to auto merge when checks succeed
|
||||
CommentTypePRScheduledToAutoMerge
|
||||
// 35 pr was un scheduled to auto merge when checks succeed
|
||||
CommentTypePRUnScheduledToAutoMerge
|
||||
)
|
||||
|
||||
var commentStrings = []string{
|
||||
@@ -181,7 +158,23 @@ func AsCommentType(typeName string) CommentType {
|
||||
return CommentType(index)
|
||||
}
|
||||
}
|
||||
return CommentTypeUnknown
|
||||
return CommentTypeUndefined
|
||||
}
|
||||
|
||||
func (t CommentType) HasContentSupport() bool {
|
||||
switch t {
|
||||
case CommentTypeComment, CommentTypeCode, CommentTypeReview:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (t CommentType) HasAttachmentSupport() bool {
|
||||
switch t {
|
||||
case CommentTypeComment, CommentTypeCode, CommentTypeReview:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// RoleDescriptor defines comment tag type
|
||||
@@ -1039,7 +1032,7 @@ func (opts *FindCommentsOptions) ToConds() builder.Cond {
|
||||
if opts.Before > 0 {
|
||||
cond = cond.And(builder.Lte{"comment.updated_unix": opts.Before})
|
||||
}
|
||||
if opts.Type != CommentTypeUnknown {
|
||||
if opts.Type != CommentTypeUndefined {
|
||||
cond = cond.And(builder.Eq{"comment.type": opts.Type})
|
||||
}
|
||||
if opts.Line != 0 {
|
||||
|
||||
@@ -56,7 +56,7 @@ func (comments CommentList) getLabelIDs() []int64 {
|
||||
return ids.Values()
|
||||
}
|
||||
|
||||
func (comments CommentList) loadLabels(ctx context.Context) error { //nolint
|
||||
func (comments CommentList) loadLabels(ctx context.Context) error {
|
||||
if len(comments) == 0 {
|
||||
return nil
|
||||
}
|
||||
@@ -415,7 +415,7 @@ func (comments CommentList) getReviewIDs() []int64 {
|
||||
return ids.Values()
|
||||
}
|
||||
|
||||
func (comments CommentList) loadReviews(ctx context.Context) error { //nolint
|
||||
func (comments CommentList) loadReviews(ctx context.Context) error {
|
||||
if len(comments) == 0 {
|
||||
return nil
|
||||
}
|
||||
@@ -453,6 +453,14 @@ func (comments CommentList) loadReviews(ctx context.Context) error { //nolint
|
||||
|
||||
for _, comment := range comments {
|
||||
comment.Review = reviews[comment.ReviewID]
|
||||
|
||||
// If the comment dismisses a review, we need to load the reviewer to show whose review has been dismissed.
|
||||
// Otherwise, the reviewer is the poster of the comment, so we don't need to load it.
|
||||
if comment.Type == CommentTypeDismissReview {
|
||||
if err := comment.Review.LoadReviewer(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -64,8 +64,9 @@ func TestFetchCodeComments(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAsCommentType(t *testing.T) {
|
||||
assert.Equal(t, issues_model.CommentTypeUnknown, issues_model.AsCommentType(""))
|
||||
assert.Equal(t, issues_model.CommentTypeUnknown, issues_model.AsCommentType("nonsense"))
|
||||
assert.Equal(t, issues_model.CommentType(0), issues_model.CommentTypeComment)
|
||||
assert.Equal(t, issues_model.CommentTypeUndefined, issues_model.AsCommentType(""))
|
||||
assert.Equal(t, issues_model.CommentTypeUndefined, issues_model.AsCommentType("nonsense"))
|
||||
assert.Equal(t, issues_model.CommentTypeComment, issues_model.AsCommentType("comment"))
|
||||
assert.Equal(t, issues_model.CommentTypePRUnScheduledToAutoMerge, issues_model.AsCommentType("pull_cancel_scheduled_merge"))
|
||||
}
|
||||
|
||||
@@ -269,7 +269,7 @@ func (issue *Issue) LoadPullRequest(ctx context.Context) (err error) {
|
||||
}
|
||||
|
||||
func (issue *Issue) loadComments(ctx context.Context) (err error) {
|
||||
return issue.loadCommentsByType(ctx, CommentTypeUnknown)
|
||||
return issue.loadCommentsByType(ctx, CommentTypeUndefined)
|
||||
}
|
||||
|
||||
// LoadDiscussComments loads discuss comments
|
||||
|
||||
@@ -109,11 +109,11 @@ func TestHasUnmergedPullRequestsByHeadInfo(t *testing.T) {
|
||||
|
||||
exist, err := issues_model.HasUnmergedPullRequestsByHeadInfo(db.DefaultContext, 1, "branch2")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, true, exist)
|
||||
assert.True(t, exist)
|
||||
|
||||
exist, err = issues_model.HasUnmergedPullRequestsByHeadInfo(db.DefaultContext, 1, "not_exist_branch")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, false, exist)
|
||||
assert.False(t, exist)
|
||||
}
|
||||
|
||||
func TestGetUnmergedPullRequestsByHeadInfo(t *testing.T) {
|
||||
|
||||
@@ -35,7 +35,7 @@ func TestAddTime(t *testing.T) {
|
||||
assert.Equal(t, int64(3661), tt.Time)
|
||||
|
||||
comment := unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{Type: issues_model.CommentTypeAddTimeManual, PosterID: 3, IssueID: 1})
|
||||
assert.Equal(t, comment.Content, "1 hour 1 minute")
|
||||
assert.Equal(t, "1 hour 1 minute", comment.Content)
|
||||
}
|
||||
|
||||
func TestGetTrackedTimes(t *testing.T) {
|
||||
|
||||
@@ -165,11 +165,6 @@ func (log *TestLogger) Init(config string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Content returns the content accumulated in the content provider
|
||||
func (log *TestLogger) Content() (string, error) {
|
||||
return "", fmt.Errorf("not supported")
|
||||
}
|
||||
|
||||
// Flush when log should be flushed
|
||||
func (log *TestLogger) Flush() {
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
//nolint:forbidigo
|
||||
package base
|
||||
|
||||
import (
|
||||
|
||||
@@ -485,6 +485,8 @@ var migrations = []Migration{
|
||||
NewMigration("Fix incorrect admin team unit access mode", v1_20.FixIncorrectAdminTeamUnitAccessMode),
|
||||
// v253 -> v254
|
||||
NewMigration("Fix ExternalTracker and ExternalWiki accessMode in owner and admin team", v1_20.FixExternalTrackerAndExternalWikiAccessModeInOwnerAndAdminTeam),
|
||||
// v254 -> v255
|
||||
NewMigration("Add ActionTaskOutput table", v1_20.AddActionTaskOutputTable),
|
||||
// to modify later
|
||||
NewMigration("Add size limit on repository", v1_20.AddSizeLimitOnRepo),
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ func RemoveAttachmentMissedRepo(x *xorm.Engine) error {
|
||||
for i := 0; i < len(attachments); i++ {
|
||||
uuid := attachments[i].UUID
|
||||
if err = util.RemoveAll(filepath.Join(setting.Attachment.Path, uuid[0:1], uuid[1:2], uuid)); err != nil {
|
||||
fmt.Printf("Error: %v", err)
|
||||
fmt.Printf("Error: %v", err) //nolint:forbidigo
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,10 +22,10 @@ func FixLanguageStatsToSaveSize(x *xorm.Engine) error {
|
||||
type RepoIndexerType int
|
||||
|
||||
const (
|
||||
// RepoIndexerTypeCode code indexer
|
||||
RepoIndexerTypeCode RepoIndexerType = iota // 0
|
||||
// RepoIndexerTypeStats repository stats indexer
|
||||
RepoIndexerTypeStats // 1
|
||||
// RepoIndexerTypeCode code indexer - 0
|
||||
RepoIndexerTypeCode RepoIndexerType = iota //nolint:unused
|
||||
// RepoIndexerTypeStats repository stats indexer - 1
|
||||
RepoIndexerTypeStats
|
||||
)
|
||||
|
||||
// RepoIndexerStatus see models/repo_indexer.go
|
||||
|
||||
@@ -8,13 +8,13 @@ import (
|
||||
)
|
||||
|
||||
func FixRepoTopics(x *xorm.Engine) error {
|
||||
type Topic struct {
|
||||
type Topic struct { //nolint:unused
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
Name string `xorm:"UNIQUE VARCHAR(25)"`
|
||||
RepoCount int
|
||||
}
|
||||
|
||||
type RepoTopic struct {
|
||||
type RepoTopic struct { //nolint:unused
|
||||
RepoID int64 `xorm:"pk"`
|
||||
TopicID int64 `xorm:"pk"`
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ func ConvertHookTaskTypeToVarcharAndTrim(x *xorm.Engine) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type HookTask struct {
|
||||
type HookTask struct { //nolint:unused
|
||||
Typ string `xorm:"VARCHAR(16) index"`
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ func ConvertHookTaskTypeToVarcharAndTrim(x *xorm.Engine) error {
|
||||
return err
|
||||
}
|
||||
|
||||
type Webhook struct {
|
||||
type Webhook struct { //nolint:unused
|
||||
Type string `xorm:"VARCHAR(16) index"`
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_20 //nolint
|
||||
|
||||
import (
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
func AddActionTaskOutputTable(x *xorm.Engine) error {
|
||||
type ActionTaskOutput struct {
|
||||
ID int64
|
||||
TaskID int64 `xorm:"INDEX UNIQUE(task_id_output_key)"`
|
||||
OutputKey string `xorm:"VARCHAR(255) UNIQUE(task_id_output_key)"`
|
||||
OutputValue string `xorm:"MEDIUMTEXT"`
|
||||
}
|
||||
return x.Sync(new(ActionTaskOutput))
|
||||
}
|
||||
+14
-4
@@ -414,10 +414,17 @@ func DeleteTeam(t *organization.Team) error {
|
||||
&organization.TeamUser{OrgID: t.OrgID, TeamID: t.ID},
|
||||
&organization.TeamUnit{TeamID: t.ID},
|
||||
&organization.TeamInvite{TeamID: t.ID},
|
||||
&issues_model.Review{Type: issues_model.ReviewTypeRequest, ReviewerTeamID: t.ID}, // batch delete the binding relationship between team and PR (request review from team)
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, tm := range t.Members {
|
||||
if err := removeInvalidOrgUser(ctx, tm.ID, t.OrgID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Update organization number of teams.
|
||||
if _, err := db.Exec(ctx, "UPDATE `user` SET num_teams=num_teams-1 WHERE id=?", t.OrgID); err != nil {
|
||||
return err
|
||||
@@ -567,16 +574,19 @@ func removeTeamMember(ctx context.Context, team *organization.Team, userID int64
|
||||
}
|
||||
}
|
||||
|
||||
return removeInvalidOrgUser(ctx, userID, team.OrgID)
|
||||
}
|
||||
|
||||
func removeInvalidOrgUser(ctx context.Context, userID, orgID int64) error {
|
||||
// Check if the user is a member of any team in the organization.
|
||||
if count, err := e.Count(&organization.TeamUser{
|
||||
if count, err := db.GetEngine(ctx).Count(&organization.TeamUser{
|
||||
UID: userID,
|
||||
OrgID: team.OrgID,
|
||||
OrgID: orgID,
|
||||
}); err != nil {
|
||||
return err
|
||||
} else if count == 0 {
|
||||
return removeOrgUser(ctx, team.OrgID, userID)
|
||||
return removeOrgUser(ctx, orgID, userID)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -342,11 +342,15 @@ func CreateOrganization(org *Organization, owner *user_model.User) (err error) {
|
||||
// insert units for team
|
||||
units := make([]TeamUnit, 0, len(unit.AllRepoUnitTypes))
|
||||
for _, tp := range unit.AllRepoUnitTypes {
|
||||
up := perm.AccessModeOwner
|
||||
if tp == unit.TypeExternalTracker || tp == unit.TypeExternalWiki {
|
||||
up = perm.AccessModeRead
|
||||
}
|
||||
units = append(units, TeamUnit{
|
||||
OrgID: org.ID,
|
||||
TeamID: t.ID,
|
||||
Type: tp,
|
||||
AccessMode: perm.AccessModeOwner,
|
||||
AccessMode: up,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
+7
-1
@@ -226,6 +226,12 @@ func (repo *Repository) IsBroken() bool {
|
||||
return repo.Status == RepositoryBroken
|
||||
}
|
||||
|
||||
// MarkAsBrokenEmpty marks the repo as broken and empty
|
||||
func (repo *Repository) MarkAsBrokenEmpty() {
|
||||
repo.Status = RepositoryBroken
|
||||
repo.IsEmpty = true
|
||||
}
|
||||
|
||||
// AfterLoad is invoked from XORM after setting the values of all fields of this object.
|
||||
func (repo *Repository) AfterLoad() {
|
||||
repo.NumOpenIssues = repo.NumIssues - repo.NumClosedIssues
|
||||
@@ -769,7 +775,7 @@ func IsRepositoryExist(ctx context.Context, u *user_model.User, repoName string)
|
||||
return false, err
|
||||
}
|
||||
isDir, err := util.IsDir(RepoPath(u.Name, repoName))
|
||||
return has && isDir, err
|
||||
return has || isDir, err
|
||||
}
|
||||
|
||||
// GetTemplateRepo populates repo.TemplateRepo for a generated repository and
|
||||
|
||||
@@ -235,12 +235,12 @@ func TestSearchRepository(t *testing.T) {
|
||||
{
|
||||
name: "AllPublic/PublicRepositoriesOfUserIncludingCollaborative",
|
||||
opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, AllPublic: true, Template: util.OptionalBoolFalse},
|
||||
count: 29,
|
||||
count: 30,
|
||||
},
|
||||
{
|
||||
name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborative",
|
||||
opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 15, Private: true, AllPublic: true, AllLimited: true, Template: util.OptionalBoolFalse},
|
||||
count: 34,
|
||||
count: 35,
|
||||
},
|
||||
{
|
||||
name: "AllPublic/PublicAndPrivateRepositoriesOfUserIncludingCollaborativeByName",
|
||||
@@ -255,7 +255,7 @@ func TestSearchRepository(t *testing.T) {
|
||||
{
|
||||
name: "AllPublic/PublicRepositoriesOfOrganization",
|
||||
opts: &repo_model.SearchRepoOptions{ListOptions: db.ListOptions{Page: 1, PageSize: 10}, OwnerID: 17, AllPublic: true, Collaborate: util.OptionalBoolFalse, Template: util.OptionalBoolFalse},
|
||||
count: 29,
|
||||
count: 30,
|
||||
},
|
||||
{
|
||||
name: "AllTemplates",
|
||||
|
||||
@@ -152,7 +152,7 @@ func init() {
|
||||
Query()
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.EqualValues(t, label.int("NumIssues"), len(issueLabels), "Unexpected number of issue for label id: %d", label.int("ID"))
|
||||
assert.Len(t, issueLabels, label.int("NumIssues"), "Unexpected number of issue for label id: %d", label.int("ID"))
|
||||
|
||||
issueIDs := make([]int, len(issueLabels))
|
||||
for i, issueLabel := range issueLabels {
|
||||
|
||||
+10
-11
@@ -1,6 +1,7 @@
|
||||
// Copyright 2021 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
//nolint:forbidigo
|
||||
package unittest
|
||||
|
||||
import (
|
||||
@@ -17,7 +18,7 @@ import (
|
||||
"xorm.io/xorm/schemas"
|
||||
)
|
||||
|
||||
var fixtures *testfixtures.Loader
|
||||
var fixturesLoader *testfixtures.Loader
|
||||
|
||||
// GetXORMEngine gets the XORM engine
|
||||
func GetXORMEngine(engine ...*xorm.Engine) (x *xorm.Engine) {
|
||||
@@ -30,11 +31,11 @@ func GetXORMEngine(engine ...*xorm.Engine) (x *xorm.Engine) {
|
||||
// InitFixtures initialize test fixtures for a test database
|
||||
func InitFixtures(opts FixturesOptions, engine ...*xorm.Engine) (err error) {
|
||||
e := GetXORMEngine(engine...)
|
||||
var testfiles func(*testfixtures.Loader) error
|
||||
var fixtureOptionFiles func(*testfixtures.Loader) error
|
||||
if opts.Dir != "" {
|
||||
testfiles = testfixtures.Directory(opts.Dir)
|
||||
fixtureOptionFiles = testfixtures.Directory(opts.Dir)
|
||||
} else {
|
||||
testfiles = testfixtures.Files(opts.Files...)
|
||||
fixtureOptionFiles = testfixtures.Files(opts.Files...)
|
||||
}
|
||||
dialect := "unknown"
|
||||
switch e.Dialect().URI().DBType {
|
||||
@@ -54,14 +55,14 @@ func InitFixtures(opts FixturesOptions, engine ...*xorm.Engine) (err error) {
|
||||
testfixtures.Database(e.DB().DB),
|
||||
testfixtures.Dialect(dialect),
|
||||
testfixtures.DangerousSkipTestDatabaseCheck(),
|
||||
testfiles,
|
||||
fixtureOptionFiles,
|
||||
}
|
||||
|
||||
if e.Dialect().URI().DBType == schemas.POSTGRES {
|
||||
loaderOptions = append(loaderOptions, testfixtures.SkipResetSequences())
|
||||
}
|
||||
|
||||
fixtures, err = testfixtures.New(loaderOptions...)
|
||||
fixturesLoader, err = testfixtures.New(loaderOptions...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -78,11 +79,9 @@ func InitFixtures(opts FixturesOptions, engine ...*xorm.Engine) (err error) {
|
||||
func LoadFixtures(engine ...*xorm.Engine) error {
|
||||
e := GetXORMEngine(engine...)
|
||||
var err error
|
||||
// Database transaction conflicts could occur and result in ROLLBACK
|
||||
// As a simple workaround, we just retry 20 times.
|
||||
for i := 0; i < 20; i++ {
|
||||
err = fixtures.Load()
|
||||
if err == nil {
|
||||
// (doubt) database transaction conflicts could occur and result in ROLLBACK? just try for a few times.
|
||||
for i := 0; i < 5; i++ {
|
||||
if err = fixturesLoader.Load(); err == nil {
|
||||
break
|
||||
}
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
|
||||
@@ -17,7 +17,7 @@ type Badge struct {
|
||||
}
|
||||
|
||||
// UserBadge represents a user badge
|
||||
type UserBadge struct {
|
||||
type UserBadge struct { //nolint:revive
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
BadgeID int64
|
||||
UserID int64 `xorm:"INDEX"`
|
||||
|
||||
+1
-1
@@ -62,7 +62,7 @@ const (
|
||||
EmailNotificationsOnMention = "onmention"
|
||||
// EmailNotificationsDisabled indicates that the user would not like to be notified via email.
|
||||
EmailNotificationsDisabled = "disabled"
|
||||
// EmailNotificationsEnabled indicates that the user would like to receive all email notifications and your own
|
||||
// EmailNotificationsAndYourOwn indicates that the user would like to receive all email notifications and your own
|
||||
EmailNotificationsAndYourOwn = "andyourown"
|
||||
)
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ package user_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -35,10 +36,10 @@ func TestGetUserEmailsByNames(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
// ignore none active user email
|
||||
assert.Equal(t, []string{"user8@example.com"}, user_model.GetUserEmailsByNames(db.DefaultContext, []string{"user8", "user9"}))
|
||||
assert.Equal(t, []string{"user8@example.com", "user5@example.com"}, user_model.GetUserEmailsByNames(db.DefaultContext, []string{"user8", "user5"}))
|
||||
assert.ElementsMatch(t, []string{"user8@example.com"}, user_model.GetUserEmailsByNames(db.DefaultContext, []string{"user8", "user9"}))
|
||||
assert.ElementsMatch(t, []string{"user8@example.com", "user5@example.com"}, user_model.GetUserEmailsByNames(db.DefaultContext, []string{"user8", "user5"}))
|
||||
|
||||
assert.Equal(t, []string{"user8@example.com"}, user_model.GetUserEmailsByNames(db.DefaultContext, []string{"user8", "user7"}))
|
||||
assert.ElementsMatch(t, []string{"user8@example.com"}, user_model.GetUserEmailsByNames(db.DefaultContext, []string{"user8", "user7"}))
|
||||
}
|
||||
|
||||
func TestCanCreateOrganization(t *testing.T) {
|
||||
@@ -64,9 +65,10 @@ func TestSearchUsers(t *testing.T) {
|
||||
testSuccess := func(opts *user_model.SearchUserOptions, expectedUserOrOrgIDs []int64) {
|
||||
users, _, err := user_model.SearchUsers(opts)
|
||||
assert.NoError(t, err)
|
||||
if assert.Len(t, users, len(expectedUserOrOrgIDs), opts) {
|
||||
cassText := fmt.Sprintf("ids: %v, opts: %v", expectedUserOrOrgIDs, opts)
|
||||
if assert.Len(t, users, len(expectedUserOrOrgIDs), "case: %s", cassText) {
|
||||
for i, expectedID := range expectedUserOrOrgIDs {
|
||||
assert.EqualValues(t, expectedID, users[i].ID)
|
||||
assert.EqualValues(t, expectedID, users[i].ID, "case: %s", cassText)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -118,7 +120,7 @@ func TestSearchUsers(t *testing.T) {
|
||||
[]int64{1})
|
||||
|
||||
testUserSuccess(&user_model.SearchUserOptions{ListOptions: db.ListOptions{Page: 1}, IsRestricted: util.OptionalBoolTrue},
|
||||
[]int64{29, 30})
|
||||
[]int64{29})
|
||||
|
||||
testUserSuccess(&user_model.SearchUserOptions{ListOptions: db.ListOptions{Page: 1}, IsProhibitLogin: util.OptionalBoolTrue},
|
||||
[]int64{30})
|
||||
|
||||
Reference in New Issue
Block a user