mirror of
https://github.com/go-gitea/gitea.git
synced 2026-09-20 05:53:12 +02:00
Merge remote-tracking branch 'upstream/main' into limit-repo-size
This commit is contained in:
@@ -137,14 +137,10 @@ func toCommitStatus(status actions_model.Status) api.CommitStatusState {
|
||||
switch status {
|
||||
case actions_model.StatusSuccess, actions_model.StatusSkipped:
|
||||
return api.CommitStatusSuccess
|
||||
case actions_model.StatusFailure:
|
||||
case actions_model.StatusFailure, actions_model.StatusCancelled:
|
||||
return api.CommitStatusFailure
|
||||
case actions_model.StatusCancelled:
|
||||
return api.CommitStatusWarning
|
||||
case actions_model.StatusWaiting, actions_model.StatusBlocked:
|
||||
case actions_model.StatusWaiting, actions_model.StatusBlocked, actions_model.StatusRunning:
|
||||
return api.CommitStatusPending
|
||||
case actions_model.StatusRunning:
|
||||
return api.CommitStatusRunning
|
||||
default:
|
||||
return api.CommitStatusError
|
||||
}
|
||||
|
||||
@@ -197,7 +197,7 @@ func ProcReceive(ctx context.Context, repo *repo_model.Repository, gitRepo *git.
|
||||
return nil, fmt.Errorf("Failed to update pull ref. Error: %w", err)
|
||||
}
|
||||
|
||||
pull_service.AddToTaskQueue(pr)
|
||||
pull_service.AddToTaskQueue(ctx, pr)
|
||||
pusher, err := user_model.GetUserByID(ctx, opts.UserID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to get user. Error: %w", err)
|
||||
|
||||
@@ -22,7 +22,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
)
|
||||
|
||||
// ErrInvalidAlgorithmType represents an invalid algorithm error.
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
)
|
||||
|
||||
// ___________ __
|
||||
@@ -50,6 +50,9 @@ func ParseToken(jwtToken string, signingKey JWTSigningKey) (*Token, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !parsedToken.Valid {
|
||||
return nil, fmt.Errorf("invalid token")
|
||||
}
|
||||
var token *Token
|
||||
var ok bool
|
||||
if token, ok = parsedToken.Claims.(*Token); !ok || !parsedToken.Valid {
|
||||
|
||||
@@ -89,9 +89,9 @@ func (s *SSPI) Verify(req *http.Request, w http.ResponseWriter, store DataStore,
|
||||
}
|
||||
store.GetData()["EnableOpenIDSignIn"] = setting.Service.EnableOpenIDSignIn
|
||||
store.GetData()["EnableSSPI"] = true
|
||||
// in this case, the store is Gitea's web Context
|
||||
// in this case, the Verify function is called in Gitea's web context
|
||||
// FIXME: it doesn't look good to render the page here, why not redirect?
|
||||
store.(*gitea_context.Context).HTML(http.StatusUnauthorized, tplSignIn)
|
||||
gitea_context.GetWebContext(req).HTML(http.StatusUnauthorized, tplSignIn)
|
||||
return nil, err
|
||||
}
|
||||
if outToken != "" {
|
||||
|
||||
@@ -56,16 +56,16 @@ func ToBranch(ctx context.Context, repo *repo_model.Repository, branchName strin
|
||||
var canPush bool
|
||||
var err error
|
||||
if user != nil {
|
||||
hasPerm, err = access_model.HasAccessUnit(db.DefaultContext, user, repo, unit.TypeCode, perm.AccessModeWrite)
|
||||
hasPerm, err = access_model.HasAccessUnit(ctx, user, repo, unit.TypeCode, perm.AccessModeWrite)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
perms, err := access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
|
||||
perms, err := access_model.GetUserRepoPermission(ctx, repo, user)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
canPush = issues_model.CanMaintainerWriteToBranch(perms, branchName, user)
|
||||
canPush = issues_model.CanMaintainerWriteToBranch(ctx, perms, branchName, user)
|
||||
}
|
||||
|
||||
return &api.Branch{
|
||||
@@ -94,13 +94,13 @@ func ToBranch(ctx context.Context, repo *repo_model.Repository, branchName strin
|
||||
}
|
||||
|
||||
if user != nil {
|
||||
permission, err := access_model.GetUserRepoPermission(db.DefaultContext, repo, user)
|
||||
permission, err := access_model.GetUserRepoPermission(ctx, repo, user)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bp.Repo = repo
|
||||
branch.UserCanPush = bp.CanUserPush(db.DefaultContext, user)
|
||||
branch.UserCanMerge = git_model.IsUserMergeWhitelisted(db.DefaultContext, bp, user.ID, permission)
|
||||
branch.UserCanPush = bp.CanUserPush(ctx, user)
|
||||
branch.UserCanMerge = git_model.IsUserMergeWhitelisted(ctx, bp, user.ID, permission)
|
||||
}
|
||||
|
||||
return branch, nil
|
||||
|
||||
@@ -196,10 +196,11 @@ func ToCommit(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Rep
|
||||
}
|
||||
|
||||
affectedFileList := make([]*api.CommitAffectedFiles, 0, len(fileStatus.Added)+len(fileStatus.Removed)+len(fileStatus.Modified))
|
||||
for _, files := range [][]string{fileStatus.Added, fileStatus.Removed, fileStatus.Modified} {
|
||||
for filestatus, files := range map[string][]string{"added": fileStatus.Added, "removed": fileStatus.Removed, "modified": fileStatus.Modified} {
|
||||
for _, filename := range files {
|
||||
affectedFileList = append(affectedFileList, &api.CommitAffectedFiles{
|
||||
Filename: filename,
|
||||
Status: filestatus,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ func ToTimelineComment(ctx context.Context, repo *repo_model.Repository, c *issu
|
||||
}
|
||||
|
||||
if c.Time != nil {
|
||||
err = c.Time.LoadAttributes()
|
||||
err = c.Time.LoadAttributes(ctx)
|
||||
if err != nil {
|
||||
log.Error("Time.LoadAttributes: %v", err)
|
||||
return nil
|
||||
|
||||
@@ -52,6 +52,14 @@ func ToCombinedStatus(ctx context.Context, statuses []*git_model.CommitStatus, r
|
||||
retStatus.State = status.State
|
||||
}
|
||||
}
|
||||
// According to https://docs.github.com/en/rest/commits/statuses?apiVersion=2022-11-28#get-the-combined-status-for-a-specific-reference
|
||||
// > Additionally, a combined state is returned. The state is one of:
|
||||
// > failure if any of the contexts report as error or failure
|
||||
// > pending if there are no statuses or a context is pending
|
||||
// > success if the latest status for all contexts is success
|
||||
if retStatus.State.IsError() {
|
||||
retStatus.State = api.CommitStatusFailure
|
||||
}
|
||||
|
||||
return retStatus
|
||||
}
|
||||
|
||||
+22
-12
@@ -14,10 +14,10 @@ import (
|
||||
"code.gitea.io/gitea/modules/sync"
|
||||
"code.gitea.io/gitea/modules/translation"
|
||||
|
||||
"github.com/gogs/cron"
|
||||
"github.com/go-co-op/gocron"
|
||||
)
|
||||
|
||||
var c = cron.New()
|
||||
var scheduler = gocron.NewScheduler(time.Local)
|
||||
|
||||
// Prevent duplicate running tasks.
|
||||
var taskStatusTable = sync.NewStatusTable()
|
||||
@@ -39,11 +39,11 @@ func NewContext(original context.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
c.Start()
|
||||
scheduler.StartAsync()
|
||||
started = true
|
||||
lock.Unlock()
|
||||
graceful.GetManager().RunAtShutdown(context.Background(), func() {
|
||||
c.Stop()
|
||||
scheduler.Stop()
|
||||
lock.Lock()
|
||||
started = false
|
||||
lock.Unlock()
|
||||
@@ -77,13 +77,20 @@ type TaskTable []*TaskTableRow
|
||||
|
||||
// ListTasks returns all running cron tasks.
|
||||
func ListTasks() TaskTable {
|
||||
entries := c.Entries()
|
||||
eMap := map[string]*cron.Entry{}
|
||||
for _, e := range entries {
|
||||
eMap[e.Description] = e
|
||||
jobs := scheduler.Jobs()
|
||||
jobMap := map[string]*gocron.Job{}
|
||||
for _, job := range jobs {
|
||||
// the first tag is the task name
|
||||
tags := job.Tags()
|
||||
if len(tags) == 0 { // should never happen
|
||||
continue
|
||||
}
|
||||
jobMap[job.Tags()[0]] = job
|
||||
}
|
||||
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
|
||||
tTable := make([]*TaskTableRow, 0, len(tasks))
|
||||
for _, task := range tasks {
|
||||
spec := "-"
|
||||
@@ -91,10 +98,13 @@ func ListTasks() TaskTable {
|
||||
next time.Time
|
||||
prev time.Time
|
||||
)
|
||||
if e, ok := eMap[task.Name]; ok {
|
||||
spec = e.Spec
|
||||
next = e.Next
|
||||
prev = e.Prev
|
||||
if e, ok := jobMap[task.Name]; ok {
|
||||
tags := e.Tags()
|
||||
if len(tags) > 1 {
|
||||
spec = tags[1] // the second tag is the task spec
|
||||
}
|
||||
next = e.NextRun()
|
||||
prev = e.PreviousRun()
|
||||
}
|
||||
task.lock.Lock()
|
||||
tTable = append(tTable, &TaskTableRow{
|
||||
|
||||
+20
-2
@@ -7,6 +7,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
@@ -176,8 +177,7 @@ func RegisterTask(name string, config Config, fun func(context.Context, *user_mo
|
||||
|
||||
if config.IsEnabled() {
|
||||
// We cannot use the entry return as there is no way to lock it
|
||||
if _, err = c.AddJob(name, config.GetSchedule(), task); err != nil {
|
||||
log.Error("Unable to register cron task with name: %s Error: %v", name, err)
|
||||
if err := addTaskToScheduler(task); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -199,3 +199,21 @@ func RegisterTaskFatal(name string, config Config, fun func(context.Context, *us
|
||||
log.Fatal("Unable to register cron task %s Error: %v", name, err)
|
||||
}
|
||||
}
|
||||
|
||||
func addTaskToScheduler(task *Task) error {
|
||||
tags := []string{task.Name, task.config.GetSchedule()} // name and schedule can't be get from job, so we add them as tag
|
||||
if scheduleHasSeconds(task.config.GetSchedule()) {
|
||||
scheduler = scheduler.CronWithSeconds(task.config.GetSchedule())
|
||||
} else {
|
||||
scheduler = scheduler.Cron(task.config.GetSchedule())
|
||||
}
|
||||
if _, err := scheduler.Tag(tags...).Do(task.Run); err != nil {
|
||||
log.Error("Unable to register cron task with name: %s Error: %v", task.Name, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func scheduleHasSeconds(schedule string) bool {
|
||||
return len(strings.Fields(schedule)) >= 6
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package cron
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestAddTaskToScheduler(t *testing.T) {
|
||||
assert.Len(t, scheduler.Jobs(), 0)
|
||||
defer scheduler.Clear()
|
||||
|
||||
// no seconds
|
||||
err := addTaskToScheduler(&Task{
|
||||
Name: "task 1",
|
||||
config: &BaseConfig{
|
||||
Schedule: "5 4 * * *",
|
||||
},
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, scheduler.Jobs(), 1)
|
||||
assert.Equal(t, "task 1", scheduler.Jobs()[0].Tags()[0])
|
||||
assert.Equal(t, "5 4 * * *", scheduler.Jobs()[0].Tags()[1])
|
||||
|
||||
// with seconds
|
||||
err = addTaskToScheduler(&Task{
|
||||
Name: "task 2",
|
||||
config: &BaseConfig{
|
||||
Schedule: "30 5 4 * * *",
|
||||
},
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, scheduler.Jobs(), 2)
|
||||
assert.Equal(t, "task 2", scheduler.Jobs()[1].Tags()[0])
|
||||
assert.Equal(t, "30 5 4 * * *", scheduler.Jobs()[1].Tags()[1])
|
||||
}
|
||||
|
||||
func TestScheduleHasSeconds(t *testing.T) {
|
||||
tests := []struct {
|
||||
schedule string
|
||||
hasSecond bool
|
||||
}{
|
||||
{"* * * * * *", true},
|
||||
{"* * * * *", false},
|
||||
{"5 4 * * *", false},
|
||||
{"5 4 * * *", false},
|
||||
{"5,8 4 * * *", false},
|
||||
{"* * * * * *", true},
|
||||
{"5,8 4 * * *", false},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
t.Run(strconv.Itoa(i), func(t *testing.T) {
|
||||
assert.Equal(t, test.hasSecond, scheduleHasSeconds(test.schedule))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -48,15 +48,16 @@ type CreateRepoForm struct {
|
||||
Readme string
|
||||
Template bool
|
||||
|
||||
RepoTemplate int64
|
||||
GitContent bool
|
||||
Topics bool
|
||||
GitHooks bool
|
||||
Webhooks bool
|
||||
Avatar bool
|
||||
Labels bool
|
||||
TrustModel string
|
||||
SizeLimit int64
|
||||
RepoTemplate int64
|
||||
GitContent bool
|
||||
Topics bool
|
||||
GitHooks bool
|
||||
Webhooks bool
|
||||
Avatar bool
|
||||
Labels bool
|
||||
ProtectedBranch bool
|
||||
TrustModel string
|
||||
SizeLimit int64
|
||||
}
|
||||
|
||||
// Validate validates the fields
|
||||
|
||||
@@ -36,13 +36,13 @@ func CreateComment(ctx context.Context, opts *issues_model.CreateCommentOptions)
|
||||
}
|
||||
|
||||
// CreateRefComment creates a commit reference comment to issue.
|
||||
func CreateRefComment(doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, content, commitSHA string) error {
|
||||
func CreateRefComment(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, issue *issues_model.Issue, content, commitSHA string) error {
|
||||
if len(commitSHA) == 0 {
|
||||
return fmt.Errorf("cannot create reference with empty commit SHA")
|
||||
}
|
||||
|
||||
// Check if same reference from same commit has already existed.
|
||||
has, err := db.GetEngine(db.DefaultContext).Get(&issues_model.Comment{
|
||||
has, err := db.GetEngine(ctx).Get(&issues_model.Comment{
|
||||
Type: issues_model.CommentTypeCommitRef,
|
||||
IssueID: issue.ID,
|
||||
CommitSHA: commitSHA,
|
||||
@@ -53,7 +53,7 @@ func CreateRefComment(doer *user_model.User, repo *repo_model.Repository, issue
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err = CreateComment(db.DefaultContext, &issues_model.CreateCommentOptions{
|
||||
_, err = CreateComment(ctx, &issues_model.CreateCommentOptions{
|
||||
Type: issues_model.CommentTypeCommitRef,
|
||||
Doer: doer,
|
||||
Repo: repo,
|
||||
|
||||
+12
-12
@@ -4,6 +4,7 @@
|
||||
package issue
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"html"
|
||||
"net/url"
|
||||
@@ -12,7 +13,6 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
access_model "code.gitea.io/gitea/models/perm/access"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
@@ -78,20 +78,20 @@ func timeLogToAmount(str string) int64 {
|
||||
return a
|
||||
}
|
||||
|
||||
func issueAddTime(issue *issues_model.Issue, doer *user_model.User, time time.Time, timeLog string) error {
|
||||
func issueAddTime(ctx context.Context, issue *issues_model.Issue, doer *user_model.User, time time.Time, timeLog string) error {
|
||||
amount := timeLogToAmount(timeLog)
|
||||
if amount == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err := issues_model.AddTime(doer, issue, amount, time)
|
||||
_, err := issues_model.AddTime(ctx, doer, issue, amount, time)
|
||||
return err
|
||||
}
|
||||
|
||||
// getIssueFromRef returns the issue referenced by a ref. Returns a nil *Issue
|
||||
// if the provided ref references a non-existent issue.
|
||||
func getIssueFromRef(repo *repo_model.Repository, index int64) (*issues_model.Issue, error) {
|
||||
issue, err := issues_model.GetIssueByIndex(repo.ID, index)
|
||||
func getIssueFromRef(ctx context.Context, repo *repo_model.Repository, index int64) (*issues_model.Issue, error) {
|
||||
issue, err := issues_model.GetIssueByIndex(ctx, repo.ID, index)
|
||||
if err != nil {
|
||||
if issues_model.IsErrIssueNotExist(err) {
|
||||
return nil, nil
|
||||
@@ -102,7 +102,7 @@ func getIssueFromRef(repo *repo_model.Repository, index int64) (*issues_model.Is
|
||||
}
|
||||
|
||||
// UpdateIssuesCommit checks if issues are manipulated by commit message.
|
||||
func UpdateIssuesCommit(doer *user_model.User, repo *repo_model.Repository, commits []*repository.PushCommit, branchName string) error {
|
||||
func UpdateIssuesCommit(ctx context.Context, doer *user_model.User, repo *repo_model.Repository, commits []*repository.PushCommit, branchName string) error {
|
||||
// Commits are appended in the reverse order.
|
||||
for i := len(commits) - 1; i >= 0; i-- {
|
||||
c := commits[i]
|
||||
@@ -120,7 +120,7 @@ func UpdateIssuesCommit(doer *user_model.User, repo *repo_model.Repository, comm
|
||||
|
||||
// issue is from another repo
|
||||
if len(ref.Owner) > 0 && len(ref.Name) > 0 {
|
||||
refRepo, err = repo_model.GetRepositoryByOwnerAndName(db.DefaultContext, ref.Owner, ref.Name)
|
||||
refRepo, err = repo_model.GetRepositoryByOwnerAndName(ctx, ref.Owner, ref.Name)
|
||||
if err != nil {
|
||||
if repo_model.IsErrRepoNotExist(err) {
|
||||
log.Warn("Repository referenced in commit but does not exist: %v", err)
|
||||
@@ -132,14 +132,14 @@ func UpdateIssuesCommit(doer *user_model.User, repo *repo_model.Repository, comm
|
||||
} else {
|
||||
refRepo = repo
|
||||
}
|
||||
if refIssue, err = getIssueFromRef(refRepo, ref.Index); err != nil {
|
||||
if refIssue, err = getIssueFromRef(ctx, refRepo, ref.Index); err != nil {
|
||||
return err
|
||||
}
|
||||
if refIssue == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
perm, err := access_model.GetUserRepoPermission(db.DefaultContext, refRepo, doer)
|
||||
perm, err := access_model.GetUserRepoPermission(ctx, refRepo, doer)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -159,7 +159,7 @@ func UpdateIssuesCommit(doer *user_model.User, repo *repo_model.Repository, comm
|
||||
}
|
||||
|
||||
message := fmt.Sprintf(`<a href="%s/commit/%s">%s</a>`, html.EscapeString(repo.Link()), html.EscapeString(url.PathEscape(c.Sha1)), html.EscapeString(strings.SplitN(c.Message, "\n", 2)[0]))
|
||||
if err = CreateRefComment(doer, refRepo, refIssue, message, c.Sha1); err != nil {
|
||||
if err = CreateRefComment(ctx, doer, refRepo, refIssue, message, c.Sha1); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -187,13 +187,13 @@ func UpdateIssuesCommit(doer *user_model.User, repo *repo_model.Repository, comm
|
||||
}
|
||||
close := ref.Action == references.XRefActionCloses
|
||||
if close && len(ref.TimeLog) > 0 {
|
||||
if err := issueAddTime(refIssue, doer, c.Timestamp, ref.TimeLog); err != nil {
|
||||
if err := issueAddTime(ctx, refIssue, doer, c.Timestamp, ref.TimeLog); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if close != refIssue.IsClosed {
|
||||
refIssue.Repo = refRepo
|
||||
if err := ChangeStatus(refIssue, doer, c.Sha1, close); err != nil {
|
||||
if err := ChangeStatus(ctx, refIssue, doer, c.Sha1, close); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"testing"
|
||||
|
||||
activities_model "code.gitea.io/gitea/models/activities"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
@@ -60,7 +61,7 @@ func TestUpdateIssuesCommit(t *testing.T) {
|
||||
|
||||
unittest.AssertNotExistsBean(t, commentBean)
|
||||
unittest.AssertNotExistsBean(t, &issues_model.Issue{RepoID: repo.ID, Index: 2}, "is_closed=1")
|
||||
assert.NoError(t, UpdateIssuesCommit(user, repo, pushCommits, repo.DefaultBranch))
|
||||
assert.NoError(t, UpdateIssuesCommit(db.DefaultContext, user, repo, pushCommits, repo.DefaultBranch))
|
||||
unittest.AssertExistsAndLoadBean(t, commentBean)
|
||||
unittest.AssertExistsAndLoadBean(t, issueBean, "is_closed=1")
|
||||
unittest.CheckConsistencyFor(t, &activities_model.Action{})
|
||||
@@ -87,7 +88,7 @@ func TestUpdateIssuesCommit(t *testing.T) {
|
||||
|
||||
unittest.AssertNotExistsBean(t, commentBean)
|
||||
unittest.AssertNotExistsBean(t, &issues_model.Issue{RepoID: repo.ID, Index: 1}, "is_closed=1")
|
||||
assert.NoError(t, UpdateIssuesCommit(user, repo, pushCommits, "non-existing-branch"))
|
||||
assert.NoError(t, UpdateIssuesCommit(db.DefaultContext, user, repo, pushCommits, "non-existing-branch"))
|
||||
unittest.AssertExistsAndLoadBean(t, commentBean)
|
||||
unittest.AssertNotExistsBean(t, issueBean, "is_closed=1")
|
||||
unittest.CheckConsistencyFor(t, &activities_model.Action{})
|
||||
@@ -113,7 +114,7 @@ func TestUpdateIssuesCommit(t *testing.T) {
|
||||
|
||||
unittest.AssertNotExistsBean(t, commentBean)
|
||||
unittest.AssertNotExistsBean(t, &issues_model.Issue{RepoID: repo.ID, Index: 1}, "is_closed=1")
|
||||
assert.NoError(t, UpdateIssuesCommit(user, repo, pushCommits, repo.DefaultBranch))
|
||||
assert.NoError(t, UpdateIssuesCommit(db.DefaultContext, user, repo, pushCommits, repo.DefaultBranch))
|
||||
unittest.AssertExistsAndLoadBean(t, commentBean)
|
||||
unittest.AssertExistsAndLoadBean(t, issueBean, "is_closed=1")
|
||||
unittest.CheckConsistencyFor(t, &activities_model.Action{})
|
||||
@@ -139,7 +140,7 @@ func TestUpdateIssuesCommit_Colon(t *testing.T) {
|
||||
issueBean := &issues_model.Issue{RepoID: repo.ID, Index: 4}
|
||||
|
||||
unittest.AssertNotExistsBean(t, &issues_model.Issue{RepoID: repo.ID, Index: 2}, "is_closed=1")
|
||||
assert.NoError(t, UpdateIssuesCommit(user, repo, pushCommits, repo.DefaultBranch))
|
||||
assert.NoError(t, UpdateIssuesCommit(db.DefaultContext, user, repo, pushCommits, repo.DefaultBranch))
|
||||
unittest.AssertExistsAndLoadBean(t, issueBean, "is_closed=1")
|
||||
unittest.CheckConsistencyFor(t, &activities_model.Action{})
|
||||
}
|
||||
@@ -172,7 +173,7 @@ func TestUpdateIssuesCommit_Issue5957(t *testing.T) {
|
||||
|
||||
unittest.AssertNotExistsBean(t, commentBean)
|
||||
unittest.AssertNotExistsBean(t, issueBean, "is_closed=1")
|
||||
assert.NoError(t, UpdateIssuesCommit(user, repo, pushCommits, "non-existing-branch"))
|
||||
assert.NoError(t, UpdateIssuesCommit(db.DefaultContext, user, repo, pushCommits, "non-existing-branch"))
|
||||
unittest.AssertExistsAndLoadBean(t, commentBean)
|
||||
unittest.AssertExistsAndLoadBean(t, issueBean, "is_closed=1")
|
||||
unittest.CheckConsistencyFor(t, &activities_model.Action{})
|
||||
@@ -207,7 +208,7 @@ func TestUpdateIssuesCommit_AnotherRepo(t *testing.T) {
|
||||
|
||||
unittest.AssertNotExistsBean(t, commentBean)
|
||||
unittest.AssertNotExistsBean(t, issueBean, "is_closed=1")
|
||||
assert.NoError(t, UpdateIssuesCommit(user, repo, pushCommits, repo.DefaultBranch))
|
||||
assert.NoError(t, UpdateIssuesCommit(db.DefaultContext, user, repo, pushCommits, repo.DefaultBranch))
|
||||
unittest.AssertExistsAndLoadBean(t, commentBean)
|
||||
unittest.AssertExistsAndLoadBean(t, issueBean, "is_closed=1")
|
||||
unittest.CheckConsistencyFor(t, &activities_model.Action{})
|
||||
@@ -242,7 +243,7 @@ func TestUpdateIssuesCommit_AnotherRepo_FullAddress(t *testing.T) {
|
||||
|
||||
unittest.AssertNotExistsBean(t, commentBean)
|
||||
unittest.AssertNotExistsBean(t, issueBean, "is_closed=1")
|
||||
assert.NoError(t, UpdateIssuesCommit(user, repo, pushCommits, repo.DefaultBranch))
|
||||
assert.NoError(t, UpdateIssuesCommit(db.DefaultContext, user, repo, pushCommits, repo.DefaultBranch))
|
||||
unittest.AssertExistsAndLoadBean(t, commentBean)
|
||||
unittest.AssertExistsAndLoadBean(t, issueBean, "is_closed=1")
|
||||
unittest.CheckConsistencyFor(t, &activities_model.Action{})
|
||||
@@ -292,7 +293,7 @@ func TestUpdateIssuesCommit_AnotherRepoNoPermission(t *testing.T) {
|
||||
unittest.AssertNotExistsBean(t, commentBean)
|
||||
unittest.AssertNotExistsBean(t, commentBean2)
|
||||
unittest.AssertNotExistsBean(t, issueBean, "is_closed=1")
|
||||
assert.NoError(t, UpdateIssuesCommit(user, repo, pushCommits, repo.DefaultBranch))
|
||||
assert.NoError(t, UpdateIssuesCommit(db.DefaultContext, user, repo, pushCommits, repo.DefaultBranch))
|
||||
unittest.AssertNotExistsBean(t, commentBean)
|
||||
unittest.AssertNotExistsBean(t, commentBean2)
|
||||
unittest.AssertNotExistsBean(t, issueBean, "is_closed=1")
|
||||
|
||||
@@ -6,7 +6,6 @@ package issue
|
||||
import (
|
||||
"context"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
@@ -14,13 +13,7 @@ import (
|
||||
)
|
||||
|
||||
// ChangeStatus changes issue status to open or closed.
|
||||
func ChangeStatus(issue *issues_model.Issue, doer *user_model.User, commitID string, closed bool) error {
|
||||
return changeStatusCtx(db.DefaultContext, issue, doer, commitID, closed)
|
||||
}
|
||||
|
||||
// changeStatusCtx changes issue status to open or closed.
|
||||
// TODO: if context is not db.DefaultContext we get a deadlock!!!
|
||||
func changeStatusCtx(ctx context.Context, issue *issues_model.Issue, doer *user_model.User, commitID string, closed bool) error {
|
||||
func ChangeStatus(ctx context.Context, issue *issues_model.Issue, doer *user_model.User, commitID string, closed bool) error {
|
||||
comment, err := issues_model.ChangeIssueStatus(ctx, issue, doer, closed)
|
||||
if err != nil {
|
||||
if issues_model.IsErrDependenciesLeft(err) && closed {
|
||||
|
||||
@@ -32,7 +32,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/storage"
|
||||
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"github.com/minio/sha256-simd"
|
||||
)
|
||||
|
||||
|
||||
@@ -515,6 +515,7 @@ func (g *GiteaLocalUploader) CreateComments(comments ...*base.Comment) error {
|
||||
// CreatePullRequests creates pull requests
|
||||
func (g *GiteaLocalUploader) CreatePullRequests(prs ...*base.PullRequest) error {
|
||||
gprs := make([]*issues_model.PullRequest, 0, len(prs))
|
||||
ctx := db.DefaultContext
|
||||
for _, pr := range prs {
|
||||
gpr, err := g.newPullRequest(pr)
|
||||
if err != nil {
|
||||
@@ -527,12 +528,12 @@ func (g *GiteaLocalUploader) CreatePullRequests(prs ...*base.PullRequest) error
|
||||
|
||||
gprs = append(gprs, gpr)
|
||||
}
|
||||
if err := models.InsertPullRequests(gprs...); err != nil {
|
||||
if err := models.InsertPullRequests(ctx, gprs...); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, pr := range gprs {
|
||||
g.issues[pr.Issue.Index] = pr.Issue
|
||||
pull.AddToTaskQueue(pr)
|
||||
pull.AddToTaskQueue(ctx, pr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
)
|
||||
|
||||
type packageClaims struct {
|
||||
|
||||
@@ -378,7 +378,7 @@ func buildPrimary(pv *packages_model.PackageVersion, pfs []*packages_model.Packa
|
||||
Architecture: pd.FileMetadata.Architecture,
|
||||
Version: Version{
|
||||
Epoch: pd.FileMetadata.Epoch,
|
||||
Version: pd.Version.Version,
|
||||
Version: pd.FileMetadata.Version,
|
||||
Release: pd.FileMetadata.Release,
|
||||
},
|
||||
Checksum: Checksum{
|
||||
@@ -466,7 +466,7 @@ func buildFilelists(pv *packages_model.PackageVersion, pfs []*packages_model.Pac
|
||||
Architecture: pd.FileMetadata.Architecture,
|
||||
Version: Version{
|
||||
Epoch: pd.FileMetadata.Epoch,
|
||||
Version: pd.Version.Version,
|
||||
Version: pd.FileMetadata.Version,
|
||||
Release: pd.FileMetadata.Release,
|
||||
},
|
||||
Files: pd.FileMetadata.Files,
|
||||
@@ -513,7 +513,7 @@ func buildOther(pv *packages_model.PackageVersion, pfs []*packages_model.Package
|
||||
Architecture: pd.FileMetadata.Architecture,
|
||||
Version: Version{
|
||||
Epoch: pd.FileMetadata.Epoch,
|
||||
Version: pd.Version.Version,
|
||||
Version: pd.FileMetadata.Version,
|
||||
Release: pd.FileMetadata.Release,
|
||||
},
|
||||
Changelogs: pd.FileMetadata.Changelogs,
|
||||
|
||||
@@ -43,9 +43,9 @@ var (
|
||||
)
|
||||
|
||||
// AddToTaskQueue adds itself to pull request test task queue.
|
||||
func AddToTaskQueue(pr *issues_model.PullRequest) {
|
||||
func AddToTaskQueue(ctx context.Context, pr *issues_model.PullRequest) {
|
||||
pr.Status = issues_model.PullRequestStatusChecking
|
||||
err := pr.UpdateColsIfNotMerged(db.DefaultContext, "status")
|
||||
err := pr.UpdateColsIfNotMerged(ctx, "status")
|
||||
if err != nil {
|
||||
log.Error("AddToTaskQueue(%-v).UpdateCols.(add to queue): %v", pr, err)
|
||||
return
|
||||
@@ -369,14 +369,14 @@ func testPR(id int64) {
|
||||
}
|
||||
|
||||
// CheckPRsForBaseBranch check all pulls with baseBrannch
|
||||
func CheckPRsForBaseBranch(baseRepo *repo_model.Repository, baseBranchName string) error {
|
||||
prs, err := issues_model.GetUnmergedPullRequestsByBaseInfo(baseRepo.ID, baseBranchName)
|
||||
func CheckPRsForBaseBranch(ctx context.Context, baseRepo *repo_model.Repository, baseBranchName string) error {
|
||||
prs, err := issues_model.GetUnmergedPullRequestsByBaseInfo(ctx, baseRepo.ID, baseBranchName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, pr := range prs {
|
||||
AddToTaskQueue(pr)
|
||||
AddToTaskQueue(ctx, pr)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
"code.gitea.io/gitea/modules/queue"
|
||||
@@ -36,7 +37,7 @@ func TestPullRequest_AddToTaskQueue(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
|
||||
pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2})
|
||||
AddToTaskQueue(pr)
|
||||
AddToTaskQueue(db.DefaultContext, pr)
|
||||
|
||||
assert.Eventually(t, func() bool {
|
||||
pr = unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2})
|
||||
|
||||
+11
-15
@@ -24,7 +24,6 @@ import (
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/cache"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/graceful"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/notification"
|
||||
"code.gitea.io/gitea/modules/references"
|
||||
@@ -182,10 +181,7 @@ func Merge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.U
|
||||
go AddTestPullRequestTask(doer, pr.BaseRepo.ID, pr.BaseBranch, false, "", "")
|
||||
}()
|
||||
|
||||
// Run the merge in the hammer context to prevent cancellation
|
||||
hammerCtx := graceful.GetManager().HammerContext()
|
||||
|
||||
pr.MergedCommitID, err = doMergeAndPush(hammerCtx, pr, doer, mergeStyle, expectedHeadCommitID, message)
|
||||
pr.MergedCommitID, err = doMergeAndPush(ctx, pr, doer, mergeStyle, expectedHeadCommitID, message)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -194,47 +190,47 @@ func Merge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.U
|
||||
pr.Merger = doer
|
||||
pr.MergerID = doer.ID
|
||||
|
||||
if _, err := pr.SetMerged(hammerCtx); err != nil {
|
||||
if _, err := pr.SetMerged(ctx); err != nil {
|
||||
log.Error("SetMerged %-v: %v", pr, err)
|
||||
}
|
||||
|
||||
if err := pr.LoadIssue(hammerCtx); err != nil {
|
||||
if err := pr.LoadIssue(ctx); err != nil {
|
||||
log.Error("LoadIssue %-v: %v", pr, err)
|
||||
}
|
||||
|
||||
if err := pr.Issue.LoadRepo(hammerCtx); err != nil {
|
||||
if err := pr.Issue.LoadRepo(ctx); err != nil {
|
||||
log.Error("pr.Issue.LoadRepo %-v: %v", pr, err)
|
||||
}
|
||||
if err := pr.Issue.Repo.LoadOwner(hammerCtx); err != nil {
|
||||
if err := pr.Issue.Repo.LoadOwner(ctx); err != nil {
|
||||
log.Error("LoadOwner for %-v: %v", pr, err)
|
||||
}
|
||||
|
||||
if wasAutoMerged {
|
||||
notification.NotifyAutoMergePullRequest(hammerCtx, doer, pr)
|
||||
notification.NotifyAutoMergePullRequest(ctx, doer, pr)
|
||||
} else {
|
||||
notification.NotifyMergePullRequest(hammerCtx, doer, pr)
|
||||
notification.NotifyMergePullRequest(ctx, doer, pr)
|
||||
}
|
||||
|
||||
// Reset cached commit count
|
||||
cache.Remove(pr.Issue.Repo.GetCommitsCountCacheKey(pr.BaseBranch, true))
|
||||
|
||||
// Resolve cross references
|
||||
refs, err := pr.ResolveCrossReferences(hammerCtx)
|
||||
refs, err := pr.ResolveCrossReferences(ctx)
|
||||
if err != nil {
|
||||
log.Error("ResolveCrossReferences: %v", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, ref := range refs {
|
||||
if err = ref.LoadIssue(hammerCtx); err != nil {
|
||||
if err = ref.LoadIssue(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = ref.Issue.LoadRepo(hammerCtx); err != nil {
|
||||
if err = ref.Issue.LoadRepo(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
close := ref.RefAction == references.XRefActionCloses
|
||||
if close != ref.Issue.IsClosed {
|
||||
if err = issue_service.ChangeStatus(ref.Issue, doer, pr.MergedCommitID, close); err != nil {
|
||||
if err = issue_service.ChangeStatus(ctx, ref.Issue, doer, pr.MergedCommitID, close); err != nil {
|
||||
// Allow ErrDependenciesLeft
|
||||
if !issues_model.IsErrDependenciesLeft(err) {
|
||||
return err
|
||||
|
||||
+24
-13
@@ -265,7 +265,7 @@ func AddTestPullRequestTask(doer *user_model.User, repoID int64, branch string,
|
||||
// TODO: graceful: AddTestPullRequestTask needs to become a queue!
|
||||
|
||||
// GetUnmergedPullRequestsByHeadInfo() only return open and unmerged PR.
|
||||
prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(repoID, branch)
|
||||
prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(ctx, repoID, branch)
|
||||
if err != nil {
|
||||
log.Error("Find pull requests [head_repo_id: %d, head_branch: %s]: %v", repoID, branch, err)
|
||||
return
|
||||
@@ -282,7 +282,7 @@ func AddTestPullRequestTask(doer *user_model.User, repoID int64, branch string,
|
||||
continue
|
||||
}
|
||||
|
||||
AddToTaskQueue(pr)
|
||||
AddToTaskQueue(ctx, pr)
|
||||
comment, err := CreatePushPullComment(ctx, doer, pr, oldCommitID, newCommitID)
|
||||
if err == nil && comment != nil {
|
||||
notification.NotifyPullRequestPushCommits(ctx, doer, pr, comment)
|
||||
@@ -291,7 +291,7 @@ func AddTestPullRequestTask(doer *user_model.User, repoID int64, branch string,
|
||||
|
||||
if isSync {
|
||||
requests := issues_model.PullRequestList(prs)
|
||||
if err = requests.LoadAttributes(); err != nil {
|
||||
if err = requests.LoadAttributes(ctx); err != nil {
|
||||
log.Error("PullRequestList.LoadAttributes: %v", err)
|
||||
}
|
||||
if invalidationErr := checkForInvalidation(ctx, requests, repoID, doer, branch); invalidationErr != nil {
|
||||
@@ -309,6 +309,17 @@ func AddTestPullRequestTask(doer *user_model.User, repoID int64, branch string,
|
||||
if err := issues_model.MarkReviewsAsStale(pr.IssueID); err != nil {
|
||||
log.Error("MarkReviewsAsStale: %v", err)
|
||||
}
|
||||
|
||||
// dismiss all approval reviews if protected branch rule item enabled.
|
||||
pb, err := git_model.GetFirstMatchProtectedBranchRule(ctx, pr.BaseRepoID, pr.BaseBranch)
|
||||
if err != nil {
|
||||
log.Error("GetFirstMatchProtectedBranchRule: %v", err)
|
||||
}
|
||||
if pb != nil && pb.DismissStaleApprovals {
|
||||
if err := DismissApprovalReviews(ctx, doer, pr); err != nil {
|
||||
log.Error("DismissApprovalReviews: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
if err := issues_model.MarkReviewsAsNotStale(pr.IssueID, newCommitID); err != nil {
|
||||
log.Error("MarkReviewsAsNotStale: %v", err)
|
||||
@@ -330,7 +341,7 @@ func AddTestPullRequestTask(doer *user_model.User, repoID int64, branch string,
|
||||
}
|
||||
|
||||
log.Trace("AddTestPullRequestTask [base_repo_id: %d, base_branch: %s]: finding pull requests", repoID, branch)
|
||||
prs, err = issues_model.GetUnmergedPullRequestsByBaseInfo(repoID, branch)
|
||||
prs, err = issues_model.GetUnmergedPullRequestsByBaseInfo(ctx, repoID, branch)
|
||||
if err != nil {
|
||||
log.Error("Find pull requests [base_repo_id: %d, base_branch: %s]: %v", repoID, branch, err)
|
||||
return
|
||||
@@ -349,7 +360,7 @@ func AddTestPullRequestTask(doer *user_model.User, repoID int64, branch string,
|
||||
log.Error("UpdateCommitDivergence: %v", err)
|
||||
}
|
||||
}
|
||||
AddToTaskQueue(pr)
|
||||
AddToTaskQueue(ctx, pr)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -503,25 +514,25 @@ func (errs errlist) Error() string {
|
||||
}
|
||||
|
||||
// CloseBranchPulls close all the pull requests who's head branch is the branch
|
||||
func CloseBranchPulls(doer *user_model.User, repoID int64, branch string) error {
|
||||
prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(repoID, branch)
|
||||
func CloseBranchPulls(ctx context.Context, doer *user_model.User, repoID int64, branch string) error {
|
||||
prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(ctx, repoID, branch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
prs2, err := issues_model.GetUnmergedPullRequestsByBaseInfo(repoID, branch)
|
||||
prs2, err := issues_model.GetUnmergedPullRequestsByBaseInfo(ctx, repoID, branch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
prs = append(prs, prs2...)
|
||||
if err := issues_model.PullRequestList(prs).LoadAttributes(); err != nil {
|
||||
if err := issues_model.PullRequestList(prs).LoadAttributes(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var errs errlist
|
||||
for _, pr := range prs {
|
||||
if err = issue_service.ChangeStatus(pr.Issue, doer, "", true); err != nil && !issues_model.IsErrPullWasClosed(err) && !issues_model.IsErrDependenciesLeft(err) {
|
||||
if err = issue_service.ChangeStatus(ctx, pr.Issue, doer, "", true); err != nil && !issues_model.IsErrPullWasClosed(err) && !issues_model.IsErrDependenciesLeft(err) {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
@@ -540,12 +551,12 @@ func CloseRepoBranchesPulls(ctx context.Context, doer *user_model.User, repo *re
|
||||
|
||||
var errs errlist
|
||||
for _, branch := range branches {
|
||||
prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(repo.ID, branch.Name)
|
||||
prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(ctx, repo.ID, branch.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = issues_model.PullRequestList(prs).LoadAttributes(); err != nil {
|
||||
if err = issues_model.PullRequestList(prs).LoadAttributes(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -555,7 +566,7 @@ func CloseRepoBranchesPulls(ctx context.Context, doer *user_model.User, repo *re
|
||||
if pr.BaseRepoID == repo.ID {
|
||||
continue
|
||||
}
|
||||
if err = issue_service.ChangeStatus(pr.Issue, doer, "", true); err != nil && !issues_model.IsErrPullWasClosed(err) {
|
||||
if err = issue_service.ChangeStatus(ctx, pr.Issue, doer, "", true); err != nil && !issues_model.IsErrPullWasClosed(err) {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
|
||||
+49
-6
@@ -316,6 +316,52 @@ func SubmitReview(ctx context.Context, doer *user_model.User, gitRepo *git.Repos
|
||||
return review, comm, nil
|
||||
}
|
||||
|
||||
// DismissApprovalReviews dismiss all approval reviews because of new commits
|
||||
func DismissApprovalReviews(ctx context.Context, doer *user_model.User, pull *issues_model.PullRequest) error {
|
||||
reviews, err := issues_model.FindReviews(ctx, issues_model.FindReviewOptions{
|
||||
ListOptions: db.ListOptions{
|
||||
ListAll: true,
|
||||
},
|
||||
IssueID: pull.IssueID,
|
||||
Type: issues_model.ReviewTypeApprove,
|
||||
Dismissed: util.OptionalBoolFalse,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := reviews.LoadIssues(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return db.WithTx(ctx, func(subCtx context.Context) error {
|
||||
for _, review := range reviews {
|
||||
if err := issues_model.DismissReview(subCtx, review, true); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
comment, err := issue_service.CreateComment(ctx, &issues_model.CreateCommentOptions{
|
||||
Doer: doer,
|
||||
Content: "New commits pushed, approval review dismissed automatically according to repository settings",
|
||||
Type: issues_model.CommentTypeDismissReview,
|
||||
ReviewID: review.ID,
|
||||
Issue: review.Issue,
|
||||
Repo: review.Issue.Repo,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
comment.Review = review
|
||||
comment.Poster = doer
|
||||
comment.Issue = review.Issue
|
||||
|
||||
notification.NotifyPullReviewDismiss(ctx, doer, review, comment)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// DismissReview dismissing stale review by repo admin
|
||||
func DismissReview(ctx context.Context, reviewID, repoID int64, message string, doer *user_model.User, isDismiss, dismissPriors bool) (comment *issues_model.Comment, err error) {
|
||||
review, err := issues_model.GetReviewByID(ctx, reviewID)
|
||||
@@ -337,12 +383,12 @@ func DismissReview(ctx context.Context, reviewID, repoID int64, message string,
|
||||
return nil, fmt.Errorf("reviews's repository is not the same as the one we expect")
|
||||
}
|
||||
|
||||
if err := issues_model.DismissReview(review, isDismiss); err != nil {
|
||||
if err := issues_model.DismissReview(ctx, review, isDismiss); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if dismissPriors {
|
||||
reviews, err := issues_model.GetReviews(ctx, &issues_model.GetReviewOptions{
|
||||
reviews, err := issues_model.FindReviews(ctx, issues_model.FindReviewOptions{
|
||||
IssueID: review.IssueID,
|
||||
ReviewerID: review.ReviewerID,
|
||||
Dismissed: util.OptionalBoolFalse,
|
||||
@@ -351,7 +397,7 @@ func DismissReview(ctx context.Context, reviewID, repoID int64, message string,
|
||||
return nil, err
|
||||
}
|
||||
for _, oldReview := range reviews {
|
||||
if err = issues_model.DismissReview(oldReview, true); err != nil {
|
||||
if err = issues_model.DismissReview(ctx, oldReview, true); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@@ -361,9 +407,6 @@ func DismissReview(ctx context.Context, reviewID, repoID int64, message string,
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if err := review.Issue.LoadPullRequest(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := review.Issue.LoadAttributes(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -4,29 +4,23 @@
|
||||
package files
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
git_model "code.gitea.io/gitea/models/git"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/charset"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/lfs"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
asymkey_service "code.gitea.io/gitea/services/asymkey"
|
||||
|
||||
stdcharset "golang.org/x/net/html/charset"
|
||||
"golang.org/x/text/transform"
|
||||
)
|
||||
|
||||
// IdentityOptions for a person's identity like an author or committer
|
||||
@@ -42,12 +36,12 @@ type CommitDateOptions struct {
|
||||
}
|
||||
|
||||
type ChangeRepoFile struct {
|
||||
Operation string
|
||||
TreePath string
|
||||
FromTreePath string
|
||||
Content string
|
||||
SHA string
|
||||
Options *RepoFileOptions
|
||||
Operation string
|
||||
TreePath string
|
||||
FromTreePath string
|
||||
ContentReader io.Reader
|
||||
SHA string
|
||||
Options *RepoFileOptions
|
||||
}
|
||||
|
||||
// ChangeRepoFilesOptions holds the repository files update options
|
||||
@@ -66,78 +60,9 @@ type ChangeRepoFilesOptions struct {
|
||||
type RepoFileOptions struct {
|
||||
treePath string
|
||||
fromTreePath string
|
||||
encoding string
|
||||
bom bool
|
||||
executable bool
|
||||
}
|
||||
|
||||
func detectEncodingAndBOM(entry *git.TreeEntry, repo *repo_model.Repository) (string, bool) {
|
||||
reader, err := entry.Blob().DataAsync()
|
||||
if err != nil {
|
||||
// return default
|
||||
return "UTF-8", false
|
||||
}
|
||||
defer reader.Close()
|
||||
buf := make([]byte, 1024)
|
||||
n, err := util.ReadAtMost(reader, buf)
|
||||
if err != nil {
|
||||
// return default
|
||||
return "UTF-8", false
|
||||
}
|
||||
buf = buf[:n]
|
||||
|
||||
if setting.LFS.StartServer {
|
||||
pointer, _ := lfs.ReadPointerFromBuffer(buf)
|
||||
if pointer.IsValid() {
|
||||
meta, err := git_model.GetLFSMetaObjectByOid(db.DefaultContext, repo.ID, pointer.Oid)
|
||||
if err != nil && err != git_model.ErrLFSObjectNotExist {
|
||||
// return default
|
||||
return "UTF-8", false
|
||||
}
|
||||
if meta != nil {
|
||||
dataRc, err := lfs.ReadMetaObject(pointer)
|
||||
if err != nil {
|
||||
// return default
|
||||
return "UTF-8", false
|
||||
}
|
||||
defer dataRc.Close()
|
||||
buf = make([]byte, 1024)
|
||||
n, err = util.ReadAtMost(dataRc, buf)
|
||||
if err != nil {
|
||||
// return default
|
||||
return "UTF-8", false
|
||||
}
|
||||
buf = buf[:n]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
encoding, err := charset.DetectEncoding(buf)
|
||||
if err != nil {
|
||||
// just default to utf-8 and no bom
|
||||
return "UTF-8", false
|
||||
}
|
||||
if encoding == "UTF-8" {
|
||||
return encoding, bytes.Equal(buf[0:3], charset.UTF8BOM)
|
||||
}
|
||||
charsetEncoding, _ := stdcharset.Lookup(encoding)
|
||||
if charsetEncoding == nil {
|
||||
return "UTF-8", false
|
||||
}
|
||||
|
||||
result, n, err := transform.String(charsetEncoding.NewDecoder(), string(buf))
|
||||
if err != nil {
|
||||
// return default
|
||||
return "UTF-8", false
|
||||
}
|
||||
|
||||
if n > 2 {
|
||||
return encoding, bytes.Equal([]byte(result)[0:3], charset.UTF8BOM)
|
||||
}
|
||||
|
||||
return encoding, false
|
||||
}
|
||||
|
||||
// ChangeRepoFiles adds, updates or removes multiple files in the given repository
|
||||
func ChangeRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *user_model.User, opts *ChangeRepoFilesOptions) (*structs.FilesResponse, error) {
|
||||
// If no branch name is set, assume default branch
|
||||
@@ -184,8 +109,6 @@ func ChangeRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *use
|
||||
file.Options = &RepoFileOptions{
|
||||
treePath: treePath,
|
||||
fromTreePath: fromTreePath,
|
||||
encoding: "UTF-8",
|
||||
bom: false,
|
||||
executable: false,
|
||||
}
|
||||
treePaths = append(treePaths, treePath)
|
||||
@@ -381,7 +304,6 @@ func handleCheckErrors(file *ChangeRepoFile, commit *git.Commit, opts *ChangeRep
|
||||
// haven't been made. We throw an error if one wasn't provided.
|
||||
return models.ErrSHAOrCommitIDNotProvided{}
|
||||
}
|
||||
file.Options.encoding, file.Options.bom = detectEncodingAndBOM(fromEntry, repo)
|
||||
file.Options.executable = fromEntry.IsExecutable()
|
||||
}
|
||||
if file.Operation == "create" || file.Operation == "update" {
|
||||
@@ -466,28 +388,8 @@ func CreateOrUpdateFile(ctx context.Context, t *TemporaryUploadRepository, file
|
||||
}
|
||||
}
|
||||
|
||||
content := file.Content
|
||||
if file.Options.bom {
|
||||
content = string(charset.UTF8BOM) + content
|
||||
}
|
||||
if file.Options.encoding != "UTF-8" {
|
||||
charsetEncoding, _ := stdcharset.Lookup(file.Options.encoding)
|
||||
if charsetEncoding != nil {
|
||||
result, _, err := transform.String(charsetEncoding.NewEncoder(), content)
|
||||
if err != nil {
|
||||
// Look if we can't encode back in to the original we should just stick with utf-8
|
||||
log.Error("Error re-encoding %s (%s) as %s - will stay as UTF-8: %v", file.TreePath, file.FromTreePath, file.Options.encoding, err)
|
||||
result = content
|
||||
}
|
||||
content = result
|
||||
} else {
|
||||
log.Error("Unknown encoding: %s", file.Options.encoding)
|
||||
}
|
||||
}
|
||||
// Reset the opts.Content to our adjusted content to ensure that LFS gets the correct content
|
||||
file.Content = content
|
||||
treeObjectContentReader := file.ContentReader
|
||||
var lfsMetaObject *git_model.LFSMetaObject
|
||||
|
||||
if setting.LFS.StartServer && hasOldBranch {
|
||||
// Check there is no way this can return multiple infos
|
||||
filename2attribute2info, err := t.gitRepo.CheckAttribute(git.CheckAttributeOpts{
|
||||
@@ -501,17 +403,17 @@ func CreateOrUpdateFile(ctx context.Context, t *TemporaryUploadRepository, file
|
||||
|
||||
if filename2attribute2info[file.Options.treePath] != nil && filename2attribute2info[file.Options.treePath]["filter"] == "lfs" {
|
||||
// OK so we are supposed to LFS this data!
|
||||
pointer, err := lfs.GeneratePointer(strings.NewReader(file.Content))
|
||||
pointer, err := lfs.GeneratePointer(treeObjectContentReader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
lfsMetaObject = &git_model.LFSMetaObject{Pointer: pointer, RepositoryID: repoID}
|
||||
content = pointer.StringContent()
|
||||
treeObjectContentReader = strings.NewReader(pointer.StringContent())
|
||||
}
|
||||
}
|
||||
|
||||
// Add the object to the database
|
||||
objectHash, err := t.HashObject(strings.NewReader(content))
|
||||
objectHash, err := t.HashObject(treeObjectContentReader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -538,7 +440,7 @@ func CreateOrUpdateFile(ctx context.Context, t *TemporaryUploadRepository, file
|
||||
return err
|
||||
}
|
||||
if !exist {
|
||||
if err := contentStore.Put(lfsMetaObject.Pointer, strings.NewReader(file.Content)); err != nil {
|
||||
if err := contentStore.Put(lfsMetaObject.Pointer, file.ContentReader); err != nil {
|
||||
if _, err2 := git_model.RemoveLFSMetaObjectByOid(ctx, repoID, lfsMetaObject.Oid); err2 != nil {
|
||||
return fmt.Errorf("unable to remove failed inserted LFS object %s: %v (Prev Error: %w)", lfsMetaObject.Oid, err2, err)
|
||||
}
|
||||
|
||||
@@ -222,7 +222,7 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
|
||||
commits := repo_module.GitToPushCommits(l)
|
||||
commits.HeadCommit = repo_module.CommitToPushCommit(newCommit)
|
||||
|
||||
if err := issue_service.UpdateIssuesCommit(pusher, repo, commits.Commits, refName); err != nil {
|
||||
if err := issue_service.UpdateIssuesCommit(ctx, pusher, repo, commits.Commits, refName); err != nil {
|
||||
log.Error("updateIssuesCommit: %v", err)
|
||||
}
|
||||
|
||||
@@ -257,24 +257,24 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
|
||||
commits.Commits = commits.Commits[:setting.UI.FeedMaxCommitNum]
|
||||
}
|
||||
|
||||
notification.NotifyPushCommits(ctx, pusher, repo, opts, commits)
|
||||
|
||||
if err = git_model.UpdateBranch(ctx, repo.ID, opts.PusherID, branch, newCommit); err != nil {
|
||||
return fmt.Errorf("git_model.UpdateBranch %s:%s failed: %v", repo.FullName(), branch, err)
|
||||
}
|
||||
|
||||
notification.NotifyPushCommits(ctx, pusher, repo, opts, commits)
|
||||
|
||||
// Cache for big repository
|
||||
if err := CacheRef(graceful.GetManager().HammerContext(), repo, gitRepo, opts.RefFullName); err != nil {
|
||||
log.Error("repo_module.CacheRef %s/%s failed: %v", repo.ID, branch, err)
|
||||
}
|
||||
} else {
|
||||
notification.NotifyDeleteRef(ctx, pusher, repo, opts.RefFullName)
|
||||
if err = pull_service.CloseBranchPulls(pusher, repo.ID, branch); err != nil {
|
||||
if err = pull_service.CloseBranchPulls(ctx, pusher, repo.ID, branch); err != nil {
|
||||
// close all related pulls
|
||||
log.Error("close related pull request failed: %v", err)
|
||||
}
|
||||
|
||||
if err := git_model.AddDeletedBranch(db.DefaultContext, repo.ID, branch, pusher.ID); err != nil {
|
||||
if err := git_model.AddDeletedBranch(ctx, repo.ID, branch, pusher.ID); err != nil {
|
||||
return fmt.Errorf("AddDeletedBranch %s:%s failed: %v", repo.FullName(), branch, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"context"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
git_model "code.gitea.io/gitea/models/git"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
@@ -39,6 +40,28 @@ func GenerateIssueLabels(ctx context.Context, templateRepo, generateRepo *repo_m
|
||||
return db.Insert(ctx, newLabels)
|
||||
}
|
||||
|
||||
func GenerateProtectedBranch(ctx context.Context, templateRepo, generateRepo *repo_model.Repository) error {
|
||||
templateBranches, err := git_model.FindRepoProtectedBranchRules(ctx, templateRepo.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Prevent insert being called with an empty slice which would result in
|
||||
// err "no element on slice when insert".
|
||||
if len(templateBranches) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
newBranches := make([]*git_model.ProtectedBranch, 0, len(templateBranches))
|
||||
for _, templateBranch := range templateBranches {
|
||||
templateBranch.ID = 0
|
||||
templateBranch.RepoID = generateRepo.ID
|
||||
templateBranch.UpdatedUnix = 0
|
||||
templateBranch.CreatedUnix = 0
|
||||
newBranches = append(newBranches, templateBranch)
|
||||
}
|
||||
return db.Insert(ctx, newBranches)
|
||||
}
|
||||
|
||||
// GenerateRepository generates a repository from a template
|
||||
func GenerateRepository(ctx context.Context, doer, owner *user_model.User, templateRepo *repo_model.Repository, opts repo_module.GenerateRepoOptions) (_ *repo_model.Repository, err error) {
|
||||
if !doer.IsAdmin && !owner.CanCreateRepo() {
|
||||
@@ -96,6 +119,12 @@ func GenerateRepository(ctx context.Context, doer, owner *user_model.User, templ
|
||||
}
|
||||
}
|
||||
|
||||
if opts.ProtectedBranch {
|
||||
if err = GenerateProtectedBranch(ctx, templateRepo, generateRepo); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -58,7 +58,7 @@ func RenameUser(ctx context.Context, u *user_model.User, newUserName string) err
|
||||
u.Name = oldUserName
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return repo_model.UpdateRepositoryOwnerNames(u.ID, newUserName)
|
||||
}
|
||||
|
||||
ctx, committer, err := db.TxContext(ctx)
|
||||
|
||||
Reference in New Issue
Block a user