mirror of
https://github.com/go-gitea/gitea.git
synced 2026-09-19 03:54:55 +02:00
Merge remote-tracking branch 'upstream/main' into limit-repo-size
This commit is contained in:
+44
-15
@@ -31,7 +31,7 @@ func init() {
|
||||
// ActionArtifact is a file that is stored in the artifact storage.
|
||||
type ActionArtifact struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
RunID int64 `xorm:"index UNIQUE(runid_name)"` // The run id of the artifact
|
||||
RunID int64 `xorm:"index unique(runid_name_path)"` // The run id of the artifact
|
||||
RunnerID int64
|
||||
RepoID int64 `xorm:"index"`
|
||||
OwnerID int64
|
||||
@@ -40,27 +40,28 @@ type ActionArtifact struct {
|
||||
FileSize int64 // The size of the artifact in bytes
|
||||
FileCompressedSize int64 // The size of the artifact in bytes after gzip compression
|
||||
ContentEncoding string // The content encoding of the artifact
|
||||
ArtifactPath string // The path to the artifact when runner uploads it
|
||||
ArtifactName string `xorm:"UNIQUE(runid_name)"` // The name of the artifact when runner uploads it
|
||||
Status int64 `xorm:"index"` // The status of the artifact, uploading, expired or need-delete
|
||||
ArtifactPath string `xorm:"index unique(runid_name_path)"` // The path to the artifact when runner uploads it
|
||||
ArtifactName string `xorm:"index unique(runid_name_path)"` // The name of the artifact when runner uploads it
|
||||
Status int64 `xorm:"index"` // The status of the artifact, uploading, expired or need-delete
|
||||
CreatedUnix timeutil.TimeStamp `xorm:"created"`
|
||||
UpdatedUnix timeutil.TimeStamp `xorm:"updated index"`
|
||||
}
|
||||
|
||||
// CreateArtifact create a new artifact with task info or get same named artifact in the same run
|
||||
func CreateArtifact(ctx context.Context, t *ActionTask, artifactName string) (*ActionArtifact, error) {
|
||||
func CreateArtifact(ctx context.Context, t *ActionTask, artifactName, artifactPath string) (*ActionArtifact, error) {
|
||||
if err := t.LoadJob(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
artifact, err := getArtifactByArtifactName(ctx, t.Job.RunID, artifactName)
|
||||
artifact, err := getArtifactByNameAndPath(ctx, t.Job.RunID, artifactName, artifactPath)
|
||||
if errors.Is(err, util.ErrNotExist) {
|
||||
artifact := &ActionArtifact{
|
||||
RunID: t.Job.RunID,
|
||||
RunnerID: t.RunnerID,
|
||||
RepoID: t.RepoID,
|
||||
OwnerID: t.OwnerID,
|
||||
CommitSHA: t.CommitSHA,
|
||||
Status: ArtifactStatusUploadPending,
|
||||
ArtifactName: artifactName,
|
||||
ArtifactPath: artifactPath,
|
||||
RunID: t.Job.RunID,
|
||||
RunnerID: t.RunnerID,
|
||||
RepoID: t.RepoID,
|
||||
OwnerID: t.OwnerID,
|
||||
CommitSHA: t.CommitSHA,
|
||||
Status: ArtifactStatusUploadPending,
|
||||
}
|
||||
if _, err := db.GetEngine(ctx).Insert(artifact); err != nil {
|
||||
return nil, err
|
||||
@@ -72,9 +73,9 @@ func CreateArtifact(ctx context.Context, t *ActionTask, artifactName string) (*A
|
||||
return artifact, nil
|
||||
}
|
||||
|
||||
func getArtifactByArtifactName(ctx context.Context, runID int64, name string) (*ActionArtifact, error) {
|
||||
func getArtifactByNameAndPath(ctx context.Context, runID int64, name, fpath string) (*ActionArtifact, error) {
|
||||
var art ActionArtifact
|
||||
has, err := db.GetEngine(ctx).Where("run_id = ? AND artifact_name = ?", runID, name).Get(&art)
|
||||
has, err := db.GetEngine(ctx).Where("run_id = ? AND artifact_name = ? AND artifact_path = ?", runID, name, fpath).Get(&art)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if !has {
|
||||
@@ -109,14 +110,42 @@ func ListArtifactsByRunID(ctx context.Context, runID int64) ([]*ActionArtifact,
|
||||
return arts, db.GetEngine(ctx).Where("run_id=?", runID).Find(&arts)
|
||||
}
|
||||
|
||||
// ListArtifactsByRunIDAndArtifactName returns an artifacts of a run by artifact name
|
||||
func ListArtifactsByRunIDAndArtifactName(ctx context.Context, runID int64, artifactName string) ([]*ActionArtifact, error) {
|
||||
arts := make([]*ActionArtifact, 0, 10)
|
||||
return arts, db.GetEngine(ctx).Where("run_id=? AND artifact_name=?", runID, artifactName).Find(&arts)
|
||||
}
|
||||
|
||||
// ListUploadedArtifactsByRunID returns all uploaded artifacts of a run
|
||||
func ListUploadedArtifactsByRunID(ctx context.Context, runID int64) ([]*ActionArtifact, error) {
|
||||
arts := make([]*ActionArtifact, 0, 10)
|
||||
return arts, db.GetEngine(ctx).Where("run_id=? AND status=?", runID, ArtifactStatusUploadConfirmed).Find(&arts)
|
||||
}
|
||||
|
||||
// ActionArtifactMeta is the meta data of an artifact
|
||||
type ActionArtifactMeta struct {
|
||||
ArtifactName string
|
||||
FileSize int64
|
||||
}
|
||||
|
||||
// ListUploadedArtifactsMeta returns all uploaded artifacts meta of a run
|
||||
func ListUploadedArtifactsMeta(ctx context.Context, runID int64) ([]*ActionArtifactMeta, error) {
|
||||
arts := make([]*ActionArtifactMeta, 0, 10)
|
||||
return arts, db.GetEngine(ctx).Table("action_artifact").
|
||||
Where("run_id=? AND status=?", runID, ArtifactStatusUploadConfirmed).
|
||||
GroupBy("artifact_name").
|
||||
Select("artifact_name, sum(file_size) as file_size").
|
||||
Find(&arts)
|
||||
}
|
||||
|
||||
// ListArtifactsByRepoID returns all artifacts of a repo
|
||||
func ListArtifactsByRepoID(ctx context.Context, repoID int64) ([]*ActionArtifact, error) {
|
||||
arts := make([]*ActionArtifact, 0, 10)
|
||||
return arts, db.GetEngine(ctx).Where("repo_id=?", repoID).Find(&arts)
|
||||
}
|
||||
|
||||
// ListArtifactsByRunIDAndName returns artifacts by name of a run
|
||||
func ListArtifactsByRunIDAndName(ctx context.Context, runID int64, name string) ([]*ActionArtifact, error) {
|
||||
arts := make([]*ActionArtifact, 0, 10)
|
||||
return arts, db.GetEngine(ctx).Where("run_id=? AND artifact_name=?", runID, name).Find(&arts)
|
||||
}
|
||||
|
||||
@@ -195,6 +195,7 @@ func InsertRun(ctx context.Context, run *ActionRun, jobs []*jobparser.SingleWork
|
||||
}
|
||||
|
||||
runJobs := make([]*ActionRunJob, 0, len(jobs))
|
||||
var hasWaiting bool
|
||||
for _, v := range jobs {
|
||||
id, job := v.Job()
|
||||
needs := job.Needs()
|
||||
@@ -205,6 +206,8 @@ func InsertRun(ctx context.Context, run *ActionRun, jobs []*jobparser.SingleWork
|
||||
status := StatusWaiting
|
||||
if len(needs) > 0 || run.NeedApproval {
|
||||
status = StatusBlocked
|
||||
} else {
|
||||
hasWaiting = true
|
||||
}
|
||||
job.Name, _ = util.SplitStringAtByteN(job.Name, 255)
|
||||
runJobs = append(runJobs, &ActionRunJob{
|
||||
@@ -225,6 +228,13 @@ func InsertRun(ctx context.Context, run *ActionRun, jobs []*jobparser.SingleWork
|
||||
return err
|
||||
}
|
||||
|
||||
// if there is a job in the waiting status, increase tasks version.
|
||||
if hasWaiting {
|
||||
if err := IncreaseTaskVersion(ctx, run.OwnerID, run.RepoID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return commiter.Commit()
|
||||
}
|
||||
|
||||
|
||||
@@ -111,6 +111,13 @@ func UpdateRunJob(ctx context.Context, job *ActionRunJob, cond builder.Cond, col
|
||||
return affected, nil
|
||||
}
|
||||
|
||||
if affected != 0 && util.SliceContains(cols, "status") && job.Status.IsWaiting() {
|
||||
// if the status of job changes to waiting again, increase tasks version.
|
||||
if err := IncreaseTaskVersion(ctx, job.OwnerID, job.RepoID); err != nil {
|
||||
return affected, err
|
||||
}
|
||||
}
|
||||
|
||||
if job.RunID == 0 {
|
||||
var err error
|
||||
if job, err = GetRunJobByID(ctx, job.ID); err != nil {
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
lru "github.com/hashicorp/golang-lru/v2"
|
||||
"github.com/nektos/act/pkg/jobparser"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
"xorm.io/builder"
|
||||
@@ -57,13 +57,13 @@ type ActionTask struct {
|
||||
Updated timeutil.TimeStamp `xorm:"updated index"`
|
||||
}
|
||||
|
||||
var successfulTokenTaskCache *lru.Cache
|
||||
var successfulTokenTaskCache *lru.Cache[string, any]
|
||||
|
||||
func init() {
|
||||
db.RegisterModel(new(ActionTask), func() error {
|
||||
if setting.SuccessfulTokensCacheSize > 0 {
|
||||
var err error
|
||||
successfulTokenTaskCache, err = lru.New(setting.SuccessfulTokensCacheSize)
|
||||
successfulTokenTaskCache, err = lru.New[string, any](setting.SuccessfulTokensCacheSize)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to allocate Task cache: %v", err)
|
||||
}
|
||||
@@ -215,12 +215,11 @@ func GetRunningTaskByToken(ctx context.Context, token string) (*ActionTask, erro
|
||||
}
|
||||
|
||||
func CreateTaskForRunner(ctx context.Context, runner *ActionRunner) (*ActionTask, bool, error) {
|
||||
dbCtx, commiter, err := db.TxContext(ctx)
|
||||
ctx, commiter, err := db.TxContext(ctx)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
defer commiter.Close()
|
||||
ctx = dbCtx.WithContext(ctx)
|
||||
|
||||
e := db.GetEngine(ctx)
|
||||
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package actions
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
)
|
||||
|
||||
// ActionTasksVersion
|
||||
// If both ownerID and repoID is zero, its scope is global.
|
||||
// If ownerID is not zero and repoID is zero, its scope is org (there is no user-level runner currrently).
|
||||
// If ownerID is zero and repoID is not zero, its scope is repo.
|
||||
type ActionTasksVersion struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
OwnerID int64 `xorm:"UNIQUE(owner_repo)"`
|
||||
RepoID int64 `xorm:"INDEX UNIQUE(owner_repo)"`
|
||||
Version int64
|
||||
CreatedUnix timeutil.TimeStamp `xorm:"created"`
|
||||
UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
db.RegisterModel(new(ActionTasksVersion))
|
||||
}
|
||||
|
||||
func GetTasksVersionByScope(ctx context.Context, ownerID, repoID int64) (int64, error) {
|
||||
var tasksVersion ActionTasksVersion
|
||||
has, err := db.GetEngine(ctx).Where("owner_id = ? AND repo_id = ?", ownerID, repoID).Get(&tasksVersion)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
} else if !has {
|
||||
return 0, nil
|
||||
}
|
||||
return tasksVersion.Version, err
|
||||
}
|
||||
|
||||
func insertTasksVersion(ctx context.Context, ownerID, repoID int64) (*ActionTasksVersion, error) {
|
||||
tasksVersion := &ActionTasksVersion{
|
||||
OwnerID: ownerID,
|
||||
RepoID: repoID,
|
||||
Version: 1,
|
||||
}
|
||||
if _, err := db.GetEngine(ctx).Insert(tasksVersion); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return tasksVersion, nil
|
||||
}
|
||||
|
||||
func increaseTasksVersionByScope(ctx context.Context, ownerID, repoID int64) error {
|
||||
result, err := db.GetEngine(ctx).Exec("UPDATE action_tasks_version SET version = version + 1 WHERE owner_id = ? AND repo_id = ?", ownerID, repoID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
affected, err := result.RowsAffected()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if affected == 0 {
|
||||
// if update sql does not affect any rows, the database may be broken,
|
||||
// so re-insert the row of version data here.
|
||||
if _, err := insertTasksVersion(ctx, ownerID, repoID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func IncreaseTaskVersion(ctx context.Context, ownerID, repoID int64) error {
|
||||
ctx, commiter, err := db.TxContext(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer commiter.Close()
|
||||
|
||||
// 1. increase global
|
||||
if err := increaseTasksVersionByScope(ctx, 0, 0); err != nil {
|
||||
log.Error("IncreaseTasksVersionByScope(Global): %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// 2. increase owner
|
||||
if ownerID > 0 {
|
||||
if err := increaseTasksVersionByScope(ctx, ownerID, 0); err != nil {
|
||||
log.Error("IncreaseTasksVersionByScope(Owner): %v", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// 3. increase repo
|
||||
if repoID > 0 {
|
||||
if err := increaseTasksVersionByScope(ctx, 0, repoID); err != nil {
|
||||
log.Error("IncreaseTasksVersionByScope(Repo): %v", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return commiter.Commit()
|
||||
}
|
||||
@@ -391,10 +391,10 @@ func (a *Action) GetIssueInfos() []string {
|
||||
}
|
||||
|
||||
// GetIssueTitle returns the title of first issue associated
|
||||
// with the action.
|
||||
// with the action. This function will be invoked in template so keep db.DefaultContext here
|
||||
func (a *Action) GetIssueTitle() string {
|
||||
index, _ := strconv.ParseInt(a.GetIssueInfos()[0], 10, 64)
|
||||
issue, err := issues_model.GetIssueByIndex(a.RepoID, index)
|
||||
issue, err := issues_model.GetIssueByIndex(db.DefaultContext, a.RepoID, index)
|
||||
if err != nil {
|
||||
log.Error("GetIssueByIndex: %v", err)
|
||||
return "500 when get issue"
|
||||
@@ -404,9 +404,9 @@ func (a *Action) GetIssueTitle() string {
|
||||
|
||||
// GetIssueContent returns the content of first issue associated with
|
||||
// this action.
|
||||
func (a *Action) GetIssueContent() string {
|
||||
func (a *Action) GetIssueContent(ctx context.Context) string {
|
||||
index, _ := strconv.ParseInt(a.GetIssueInfos()[0], 10, 64)
|
||||
issue, err := issues_model.GetIssueByIndex(a.RepoID, index)
|
||||
issue, err := issues_model.GetIssueByIndex(ctx, a.RepoID, index)
|
||||
if err != nil {
|
||||
log.Error("GetIssueByIndex: %v", err)
|
||||
return "500 when get issue"
|
||||
|
||||
@@ -47,21 +47,21 @@ type ActivityStats struct {
|
||||
func GetActivityStats(ctx context.Context, repo *repo_model.Repository, timeFrom time.Time, releases, issues, prs, code bool) (*ActivityStats, error) {
|
||||
stats := &ActivityStats{Code: &git.CodeActivityStats{}}
|
||||
if releases {
|
||||
if err := stats.FillReleases(repo.ID, timeFrom); err != nil {
|
||||
if err := stats.FillReleases(ctx, repo.ID, timeFrom); err != nil {
|
||||
return nil, fmt.Errorf("FillReleases: %w", err)
|
||||
}
|
||||
}
|
||||
if prs {
|
||||
if err := stats.FillPullRequests(repo.ID, timeFrom); err != nil {
|
||||
if err := stats.FillPullRequests(ctx, repo.ID, timeFrom); err != nil {
|
||||
return nil, fmt.Errorf("FillPullRequests: %w", err)
|
||||
}
|
||||
}
|
||||
if issues {
|
||||
if err := stats.FillIssues(repo.ID, timeFrom); err != nil {
|
||||
if err := stats.FillIssues(ctx, repo.ID, timeFrom); err != nil {
|
||||
return nil, fmt.Errorf("FillIssues: %w", err)
|
||||
}
|
||||
}
|
||||
if err := stats.FillUnresolvedIssues(repo.ID, timeFrom, issues, prs); err != nil {
|
||||
if err := stats.FillUnresolvedIssues(ctx, repo.ID, timeFrom, issues, prs); err != nil {
|
||||
return nil, fmt.Errorf("FillUnresolvedIssues: %w", err)
|
||||
}
|
||||
if code {
|
||||
@@ -205,41 +205,41 @@ func (stats *ActivityStats) PublishedReleaseCount() int {
|
||||
}
|
||||
|
||||
// FillPullRequests returns pull request information for activity page
|
||||
func (stats *ActivityStats) FillPullRequests(repoID int64, fromTime time.Time) error {
|
||||
func (stats *ActivityStats) FillPullRequests(ctx context.Context, repoID int64, fromTime time.Time) error {
|
||||
var err error
|
||||
var count int64
|
||||
|
||||
// Merged pull requests
|
||||
sess := pullRequestsForActivityStatement(repoID, fromTime, true)
|
||||
sess := pullRequestsForActivityStatement(ctx, repoID, fromTime, true)
|
||||
sess.OrderBy("pull_request.merged_unix DESC")
|
||||
stats.MergedPRs = make(issues_model.PullRequestList, 0)
|
||||
if err = sess.Find(&stats.MergedPRs); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = stats.MergedPRs.LoadAttributes(); err != nil {
|
||||
if err = stats.MergedPRs.LoadAttributes(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Merged pull request authors
|
||||
sess = pullRequestsForActivityStatement(repoID, fromTime, true)
|
||||
sess = pullRequestsForActivityStatement(ctx, repoID, fromTime, true)
|
||||
if _, err = sess.Select("count(distinct issue.poster_id) as `count`").Table("pull_request").Get(&count); err != nil {
|
||||
return err
|
||||
}
|
||||
stats.MergedPRAuthorCount = count
|
||||
|
||||
// Opened pull requests
|
||||
sess = pullRequestsForActivityStatement(repoID, fromTime, false)
|
||||
sess = pullRequestsForActivityStatement(ctx, repoID, fromTime, false)
|
||||
sess.OrderBy("issue.created_unix ASC")
|
||||
stats.OpenedPRs = make(issues_model.PullRequestList, 0)
|
||||
if err = sess.Find(&stats.OpenedPRs); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = stats.OpenedPRs.LoadAttributes(); err != nil {
|
||||
if err = stats.OpenedPRs.LoadAttributes(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Opened pull request authors
|
||||
sess = pullRequestsForActivityStatement(repoID, fromTime, false)
|
||||
sess = pullRequestsForActivityStatement(ctx, repoID, fromTime, false)
|
||||
if _, err = sess.Select("count(distinct issue.poster_id) as `count`").Table("pull_request").Get(&count); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -248,8 +248,8 @@ func (stats *ActivityStats) FillPullRequests(repoID int64, fromTime time.Time) e
|
||||
return nil
|
||||
}
|
||||
|
||||
func pullRequestsForActivityStatement(repoID int64, fromTime time.Time, merged bool) *xorm.Session {
|
||||
sess := db.GetEngine(db.DefaultContext).Where("pull_request.base_repo_id=?", repoID).
|
||||
func pullRequestsForActivityStatement(ctx context.Context, repoID int64, fromTime time.Time, merged bool) *xorm.Session {
|
||||
sess := db.GetEngine(ctx).Where("pull_request.base_repo_id=?", repoID).
|
||||
Join("INNER", "issue", "pull_request.issue_id = issue.id")
|
||||
|
||||
if merged {
|
||||
@@ -264,12 +264,12 @@ func pullRequestsForActivityStatement(repoID int64, fromTime time.Time, merged b
|
||||
}
|
||||
|
||||
// FillIssues returns issue information for activity page
|
||||
func (stats *ActivityStats) FillIssues(repoID int64, fromTime time.Time) error {
|
||||
func (stats *ActivityStats) FillIssues(ctx context.Context, repoID int64, fromTime time.Time) error {
|
||||
var err error
|
||||
var count int64
|
||||
|
||||
// Closed issues
|
||||
sess := issuesForActivityStatement(repoID, fromTime, true, false)
|
||||
sess := issuesForActivityStatement(ctx, repoID, fromTime, true, false)
|
||||
sess.OrderBy("issue.closed_unix DESC")
|
||||
stats.ClosedIssues = make(issues_model.IssueList, 0)
|
||||
if err = sess.Find(&stats.ClosedIssues); err != nil {
|
||||
@@ -277,14 +277,14 @@ func (stats *ActivityStats) FillIssues(repoID int64, fromTime time.Time) error {
|
||||
}
|
||||
|
||||
// Closed issue authors
|
||||
sess = issuesForActivityStatement(repoID, fromTime, true, false)
|
||||
sess = issuesForActivityStatement(ctx, repoID, fromTime, true, false)
|
||||
if _, err = sess.Select("count(distinct issue.poster_id) as `count`").Table("issue").Get(&count); err != nil {
|
||||
return err
|
||||
}
|
||||
stats.ClosedIssueAuthorCount = count
|
||||
|
||||
// New issues
|
||||
sess = issuesForActivityStatement(repoID, fromTime, false, false)
|
||||
sess = issuesForActivityStatement(ctx, repoID, fromTime, false, false)
|
||||
sess.OrderBy("issue.created_unix ASC")
|
||||
stats.OpenedIssues = make(issues_model.IssueList, 0)
|
||||
if err = sess.Find(&stats.OpenedIssues); err != nil {
|
||||
@@ -292,7 +292,7 @@ func (stats *ActivityStats) FillIssues(repoID int64, fromTime time.Time) error {
|
||||
}
|
||||
|
||||
// Opened issue authors
|
||||
sess = issuesForActivityStatement(repoID, fromTime, false, false)
|
||||
sess = issuesForActivityStatement(ctx, repoID, fromTime, false, false)
|
||||
if _, err = sess.Select("count(distinct issue.poster_id) as `count`").Table("issue").Get(&count); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -302,12 +302,12 @@ func (stats *ActivityStats) FillIssues(repoID int64, fromTime time.Time) error {
|
||||
}
|
||||
|
||||
// FillUnresolvedIssues returns unresolved issue and pull request information for activity page
|
||||
func (stats *ActivityStats) FillUnresolvedIssues(repoID int64, fromTime time.Time, issues, prs bool) error {
|
||||
func (stats *ActivityStats) FillUnresolvedIssues(ctx context.Context, repoID int64, fromTime time.Time, issues, prs bool) error {
|
||||
// Check if we need to select anything
|
||||
if !issues && !prs {
|
||||
return nil
|
||||
}
|
||||
sess := issuesForActivityStatement(repoID, fromTime, false, true)
|
||||
sess := issuesForActivityStatement(ctx, repoID, fromTime, false, true)
|
||||
if !issues || !prs {
|
||||
sess.And("issue.is_pull = ?", prs)
|
||||
}
|
||||
@@ -316,8 +316,8 @@ func (stats *ActivityStats) FillUnresolvedIssues(repoID int64, fromTime time.Tim
|
||||
return sess.Find(&stats.UnresolvedIssues)
|
||||
}
|
||||
|
||||
func issuesForActivityStatement(repoID int64, fromTime time.Time, closed, unresolved bool) *xorm.Session {
|
||||
sess := db.GetEngine(db.DefaultContext).Where("issue.repo_id = ?", repoID).
|
||||
func issuesForActivityStatement(ctx context.Context, repoID int64, fromTime time.Time, closed, unresolved bool) *xorm.Session {
|
||||
sess := db.GetEngine(ctx).Where("issue.repo_id = ?", repoID).
|
||||
And("issue.is_closed = ?", closed)
|
||||
|
||||
if !unresolved {
|
||||
@@ -336,12 +336,12 @@ func issuesForActivityStatement(repoID int64, fromTime time.Time, closed, unreso
|
||||
}
|
||||
|
||||
// FillReleases returns release information for activity page
|
||||
func (stats *ActivityStats) FillReleases(repoID int64, fromTime time.Time) error {
|
||||
func (stats *ActivityStats) FillReleases(ctx context.Context, repoID int64, fromTime time.Time) error {
|
||||
var err error
|
||||
var count int64
|
||||
|
||||
// Published releases list
|
||||
sess := releasesForActivityStatement(repoID, fromTime)
|
||||
sess := releasesForActivityStatement(ctx, repoID, fromTime)
|
||||
sess.OrderBy("release.created_unix DESC")
|
||||
stats.PublishedReleases = make([]*repo_model.Release, 0)
|
||||
if err = sess.Find(&stats.PublishedReleases); err != nil {
|
||||
@@ -349,7 +349,7 @@ func (stats *ActivityStats) FillReleases(repoID int64, fromTime time.Time) error
|
||||
}
|
||||
|
||||
// Published releases authors
|
||||
sess = releasesForActivityStatement(repoID, fromTime)
|
||||
sess = releasesForActivityStatement(ctx, repoID, fromTime)
|
||||
if _, err = sess.Select("count(distinct release.publisher_id) as `count`").Table("release").Get(&count); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -358,8 +358,8 @@ func (stats *ActivityStats) FillReleases(repoID int64, fromTime time.Time) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func releasesForActivityStatement(repoID int64, fromTime time.Time) *xorm.Session {
|
||||
return db.GetEngine(db.DefaultContext).Where("release.repo_id = ?", repoID).
|
||||
func releasesForActivityStatement(ctx context.Context, repoID int64, fromTime time.Time) *xorm.Session {
|
||||
return db.GetEngine(ctx).Where("release.repo_id = ?", repoID).
|
||||
And("release.is_draft = ?", false).
|
||||
And("release.created_unix >= ?", fromTime.Unix())
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
lru "github.com/hashicorp/golang-lru/v2"
|
||||
)
|
||||
|
||||
// ErrAccessTokenNotExist represents a "AccessTokenNotExist" kind of error.
|
||||
@@ -54,7 +54,7 @@ func (err ErrAccessTokenEmpty) Unwrap() error {
|
||||
return util.ErrInvalidArgument
|
||||
}
|
||||
|
||||
var successfulAccessTokenCache *lru.Cache
|
||||
var successfulAccessTokenCache *lru.Cache[string, any]
|
||||
|
||||
// AccessToken represents a personal access token.
|
||||
type AccessToken struct {
|
||||
@@ -83,7 +83,7 @@ func init() {
|
||||
db.RegisterModel(new(AccessToken), func() error {
|
||||
if setting.SuccessfulTokensCacheSize > 0 {
|
||||
var err error
|
||||
successfulAccessTokenCache, err = lru.New(setting.SuccessfulTokensCacheSize)
|
||||
successfulAccessTokenCache, err = lru.New[string, any](setting.SuccessfulTokensCacheSize)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to allocate AccessToken cache: %w", err)
|
||||
}
|
||||
@@ -154,16 +154,16 @@ func GetAccessTokenBySHA(token string) (*AccessToken, error) {
|
||||
lastEight := token[len(token)-8:]
|
||||
|
||||
if id := getAccessTokenIDFromCache(token); id > 0 {
|
||||
token := &AccessToken{
|
||||
accessToken := &AccessToken{
|
||||
TokenLastEight: lastEight,
|
||||
}
|
||||
// Re-get the token from the db in case it has been deleted in the intervening period
|
||||
has, err := db.GetEngine(db.DefaultContext).ID(id).Get(token)
|
||||
has, err := db.GetEngine(db.DefaultContext).ID(id).Get(accessToken)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if has {
|
||||
return token, nil
|
||||
return accessToken, nil
|
||||
}
|
||||
successfulAccessTokenCache.Remove(token)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
creator_id: 2
|
||||
board_type: 1
|
||||
type: 2
|
||||
created_unix: 1688973030
|
||||
updated_unix: 1688973030
|
||||
|
||||
-
|
||||
id: 2
|
||||
@@ -17,6 +19,8 @@
|
||||
creator_id: 3
|
||||
board_type: 1
|
||||
type: 2
|
||||
created_unix: 1688973010
|
||||
updated_unix: 1688973010
|
||||
|
||||
-
|
||||
id: 3
|
||||
@@ -27,6 +31,8 @@
|
||||
creator_id: 5
|
||||
board_type: 1
|
||||
type: 2
|
||||
created_unix: 1688973020
|
||||
updated_unix: 1688973020
|
||||
|
||||
-
|
||||
id: 4
|
||||
@@ -37,3 +43,5 @@
|
||||
creator_id: 2
|
||||
board_type: 1
|
||||
type: 2
|
||||
created_unix: 1688973000
|
||||
updated_unix: 1688973000
|
||||
|
||||
@@ -31,10 +31,6 @@ func TestGetCommitStatuses(t *testing.T) {
|
||||
assert.Equal(t, structs.CommitStatusPending, statuses[0].State)
|
||||
assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[0].APIURL(db.DefaultContext))
|
||||
|
||||
assert.Equal(t, "cov/awesomeness", statuses[1].Context)
|
||||
assert.Equal(t, structs.CommitStatusWarning, statuses[1].State)
|
||||
assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[1].APIURL(db.DefaultContext))
|
||||
|
||||
assert.Equal(t, "cov/awesomeness", statuses[2].Context)
|
||||
assert.Equal(t, structs.CommitStatusSuccess, statuses[2].State)
|
||||
assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[2].APIURL(db.DefaultContext))
|
||||
|
||||
@@ -465,8 +465,9 @@ func (comments CommentList) loadReviews(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// loadAttributes loads all attributes
|
||||
func (comments CommentList) loadAttributes(ctx context.Context) (err error) {
|
||||
// LoadAttributes loads attributes of the comments, except for attachments and
|
||||
// comments
|
||||
func (comments CommentList) LoadAttributes(ctx context.Context) (err error) {
|
||||
if err = comments.LoadPosters(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -501,9 +502,3 @@ func (comments CommentList) loadAttributes(ctx context.Context) (err error) {
|
||||
|
||||
return comments.loadDependentIssues(ctx)
|
||||
}
|
||||
|
||||
// LoadAttributes loads attributes of the comments, except for attachments and
|
||||
// comments
|
||||
func (comments CommentList) LoadAttributes() error {
|
||||
return comments.loadAttributes(db.DefaultContext)
|
||||
}
|
||||
|
||||
@@ -354,7 +354,7 @@ func (issue *Issue) LoadAttributes(ctx context.Context) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
if err = issue.Comments.loadAttributes(ctx); err != nil {
|
||||
if err = issue.Comments.LoadAttributes(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
if issue.IsTimetrackerEnabled(ctx) {
|
||||
@@ -502,7 +502,7 @@ func (issue *Issue) GetLastEventLabelFake() string {
|
||||
}
|
||||
|
||||
// GetIssueByIndex returns raw issue without loading attributes by index in a repository.
|
||||
func GetIssueByIndex(repoID, index int64) (*Issue, error) {
|
||||
func GetIssueByIndex(ctx context.Context, repoID, index int64) (*Issue, error) {
|
||||
if index < 1 {
|
||||
return nil, ErrIssueNotExist{}
|
||||
}
|
||||
@@ -510,7 +510,7 @@ func GetIssueByIndex(repoID, index int64) (*Issue, error) {
|
||||
RepoID: repoID,
|
||||
Index: index,
|
||||
}
|
||||
has, err := db.GetEngine(db.DefaultContext).Get(issue)
|
||||
has, err := db.GetEngine(ctx).Get(issue)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if !has {
|
||||
@@ -520,12 +520,12 @@ func GetIssueByIndex(repoID, index int64) (*Issue, error) {
|
||||
}
|
||||
|
||||
// GetIssueWithAttrsByIndex returns issue by index in a repository.
|
||||
func GetIssueWithAttrsByIndex(repoID, index int64) (*Issue, error) {
|
||||
issue, err := GetIssueByIndex(repoID, index)
|
||||
func GetIssueWithAttrsByIndex(ctx context.Context, repoID, index int64) (*Issue, error) {
|
||||
issue, err := GetIssueByIndex(ctx, repoID, index)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return issue, issue.LoadAttributes(db.DefaultContext)
|
||||
return issue, issue.LoadAttributes(ctx)
|
||||
}
|
||||
|
||||
// GetIssueByID returns an issue by given ID.
|
||||
@@ -551,7 +551,7 @@ func GetIssueWithAttrsByID(id int64) (*Issue, error) {
|
||||
|
||||
// GetIssuesByIDs return issues with the given IDs.
|
||||
func GetIssuesByIDs(ctx context.Context, issueIDs []int64) (IssueList, error) {
|
||||
issues := make([]*Issue, 0, 10)
|
||||
issues := make([]*Issue, 0, len(issueIDs))
|
||||
return issues, db.GetEngine(ctx).In("id", issueIDs).Find(&issues)
|
||||
}
|
||||
|
||||
@@ -846,7 +846,7 @@ func GetPinnedIssues(ctx context.Context, repoID int64, isPull bool) ([]*Issue,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = IssueList(issues).LoadAttributes()
|
||||
err = IssueList(issues).LoadAttributes(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -526,7 +526,7 @@ func (issues IssueList) loadTotalTrackedTimes(ctx context.Context) (err error) {
|
||||
}
|
||||
|
||||
// loadAttributes loads all attributes, expect for attachments and comments
|
||||
func (issues IssueList) loadAttributes(ctx context.Context) error {
|
||||
func (issues IssueList) LoadAttributes(ctx context.Context) error {
|
||||
if _, err := issues.LoadRepositories(ctx); err != nil {
|
||||
return fmt.Errorf("issue.loadAttributes: LoadRepositories: %w", err)
|
||||
}
|
||||
@@ -562,12 +562,6 @@ func (issues IssueList) loadAttributes(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoadAttributes loads attributes of the issues, except for attachments and
|
||||
// comments
|
||||
func (issues IssueList) LoadAttributes() error {
|
||||
return issues.loadAttributes(db.DefaultContext)
|
||||
}
|
||||
|
||||
// LoadComments loads comments
|
||||
func (issues IssueList) LoadComments(ctx context.Context) error {
|
||||
return issues.loadComments(ctx, builder.NewCond())
|
||||
|
||||
@@ -39,7 +39,7 @@ func TestIssueList_LoadAttributes(t *testing.T) {
|
||||
unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 4}),
|
||||
}
|
||||
|
||||
assert.NoError(t, issueList.LoadAttributes())
|
||||
assert.NoError(t, issueList.LoadAttributes(db.DefaultContext))
|
||||
for _, issue := range issueList {
|
||||
assert.EqualValues(t, issue.RepoID, issue.Repo.ID)
|
||||
for _, label := range issue.Labels {
|
||||
@@ -67,9 +67,7 @@ func TestIssueList_LoadAttributes(t *testing.T) {
|
||||
if issue.ID == int64(1) {
|
||||
assert.Equal(t, int64(400), issue.TotalTrackedTime)
|
||||
assert.NotNil(t, issue.Project)
|
||||
} else if issue.ID == int64(2) {
|
||||
assert.Equal(t, int64(3682), issue.TotalTrackedTime)
|
||||
assert.Nil(t, issue.Project)
|
||||
assert.Equal(t, int64(1), issue.Project.ID)
|
||||
} else {
|
||||
assert.Nil(t, issue.Project)
|
||||
}
|
||||
|
||||
@@ -16,13 +16,14 @@ import (
|
||||
func (issue *Issue) LoadProject(ctx context.Context) (err error) {
|
||||
if issue.Project == nil {
|
||||
var p project_model.Project
|
||||
if _, err = db.GetEngine(ctx).Table("project").
|
||||
has, err := db.GetEngine(ctx).Table("project").
|
||||
Join("INNER", "project_issue", "project.id=project_issue.project_id").
|
||||
Where("project_issue.issue_id = ?", issue.ID).
|
||||
Get(&p); err != nil {
|
||||
Where("project_issue.issue_id = ?", issue.ID).Get(&p)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if has {
|
||||
issue.Project = &p
|
||||
}
|
||||
issue.Project = &p
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -440,7 +440,7 @@ func Issues(ctx context.Context, opts *IssuesOptions) ([]*Issue, error) {
|
||||
return nil, fmt.Errorf("unable to query Issues: %w", err)
|
||||
}
|
||||
|
||||
if err := issues.LoadAttributes(); err != nil {
|
||||
if err := issues.LoadAttributes(ctx); err != nil {
|
||||
return nil, fmt.Errorf("unable to LoadAttributes for Issues: %w", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -539,3 +540,47 @@ func TestCountIssues(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, 18, count)
|
||||
}
|
||||
|
||||
func TestIssueLoadAttributes(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
setting.Service.EnableTimetracking = true
|
||||
|
||||
issueList := issues_model.IssueList{
|
||||
unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1}),
|
||||
unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 4}),
|
||||
}
|
||||
|
||||
for _, issue := range issueList {
|
||||
assert.NoError(t, issue.LoadAttributes(db.DefaultContext))
|
||||
assert.EqualValues(t, issue.RepoID, issue.Repo.ID)
|
||||
for _, label := range issue.Labels {
|
||||
assert.EqualValues(t, issue.RepoID, label.RepoID)
|
||||
unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: label.ID})
|
||||
}
|
||||
if issue.PosterID > 0 {
|
||||
assert.EqualValues(t, issue.PosterID, issue.Poster.ID)
|
||||
}
|
||||
if issue.AssigneeID > 0 {
|
||||
assert.EqualValues(t, issue.AssigneeID, issue.Assignee.ID)
|
||||
}
|
||||
if issue.MilestoneID > 0 {
|
||||
assert.EqualValues(t, issue.MilestoneID, issue.Milestone.ID)
|
||||
}
|
||||
if issue.IsPull {
|
||||
assert.EqualValues(t, issue.ID, issue.PullRequest.IssueID)
|
||||
}
|
||||
for _, attachment := range issue.Attachments {
|
||||
assert.EqualValues(t, issue.ID, attachment.IssueID)
|
||||
}
|
||||
for _, comment := range issue.Comments {
|
||||
assert.EqualValues(t, issue.ID, comment.IssueID)
|
||||
}
|
||||
if issue.ID == int64(1) {
|
||||
assert.Equal(t, int64(400), issue.TotalTrackedTime)
|
||||
assert.NotNil(t, issue.Project)
|
||||
assert.Equal(t, int64(1), issue.Project.ID)
|
||||
} else {
|
||||
assert.Nil(t, issue.Project)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -316,15 +316,13 @@ func (pr *PullRequest) LoadRequestedReviewers(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(reviews) > 0 {
|
||||
err = LoadReviewers(ctx, reviews)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, review := range reviews {
|
||||
pr.RequestedReviewers = append(pr.RequestedReviewers, review.Reviewer)
|
||||
}
|
||||
if err = reviews.LoadReviewers(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, review := range reviews {
|
||||
pr.RequestedReviewers = append(pr.RequestedReviewers, review.Reviewer)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -51,16 +51,16 @@ func listPullRequestStatement(baseRepoID int64, opts *PullRequestsOptions) (*xor
|
||||
}
|
||||
|
||||
// GetUnmergedPullRequestsByHeadInfo returns all pull requests that are open and has not been merged
|
||||
func GetUnmergedPullRequestsByHeadInfo(repoID int64, branch string) ([]*PullRequest, error) {
|
||||
func GetUnmergedPullRequestsByHeadInfo(ctx context.Context, repoID int64, branch string) ([]*PullRequest, error) {
|
||||
prs := make([]*PullRequest, 0, 2)
|
||||
sess := db.GetEngine(db.DefaultContext).
|
||||
sess := db.GetEngine(ctx).
|
||||
Join("INNER", "issue", "issue.id = pull_request.issue_id").
|
||||
Where("head_repo_id = ? AND head_branch = ? AND has_merged = ? AND issue.is_closed = ? AND flow = ?", repoID, branch, false, false, PullRequestFlowGithub)
|
||||
return prs, sess.Find(&prs)
|
||||
}
|
||||
|
||||
// CanMaintainerWriteToBranch check whether user is a maintainer and could write to the branch
|
||||
func CanMaintainerWriteToBranch(p access_model.Permission, branch string, user *user_model.User) bool {
|
||||
func CanMaintainerWriteToBranch(ctx context.Context, p access_model.Permission, branch string, user *user_model.User) bool {
|
||||
if p.CanWrite(unit.TypeCode) {
|
||||
return true
|
||||
}
|
||||
@@ -69,18 +69,18 @@ func CanMaintainerWriteToBranch(p access_model.Permission, branch string, user *
|
||||
return false
|
||||
}
|
||||
|
||||
prs, err := GetUnmergedPullRequestsByHeadInfo(p.Units[0].RepoID, branch)
|
||||
prs, err := GetUnmergedPullRequestsByHeadInfo(ctx, p.Units[0].RepoID, branch)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, pr := range prs {
|
||||
if pr.AllowMaintainerEdit {
|
||||
err = pr.LoadBaseRepo(db.DefaultContext)
|
||||
err = pr.LoadBaseRepo(ctx)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
prPerm, err := access_model.GetUserRepoPermission(db.DefaultContext, pr.BaseRepo, user)
|
||||
prPerm, err := access_model.GetUserRepoPermission(ctx, pr.BaseRepo, user)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
@@ -104,9 +104,9 @@ func HasUnmergedPullRequestsByHeadInfo(ctx context.Context, repoID int64, branch
|
||||
|
||||
// GetUnmergedPullRequestsByBaseInfo returns all pull requests that are open and has not been merged
|
||||
// by given base information (repo and branch).
|
||||
func GetUnmergedPullRequestsByBaseInfo(repoID int64, branch string) ([]*PullRequest, error) {
|
||||
func GetUnmergedPullRequestsByBaseInfo(ctx context.Context, repoID int64, branch string) ([]*PullRequest, error) {
|
||||
prs := make([]*PullRequest, 0, 2)
|
||||
return prs, db.GetEngine(db.DefaultContext).
|
||||
return prs, db.GetEngine(ctx).
|
||||
Where("base_repo_id=? AND base_branch=? AND has_merged=? AND issue.is_closed=?",
|
||||
repoID, branch, false, false).
|
||||
OrderBy("issue.updated_unix DESC").
|
||||
@@ -154,7 +154,7 @@ func PullRequests(baseRepoID int64, opts *PullRequestsOptions) ([]*PullRequest,
|
||||
// PullRequestList defines a list of pull requests
|
||||
type PullRequestList []*PullRequest
|
||||
|
||||
func (prs PullRequestList) loadAttributes(ctx context.Context) error {
|
||||
func (prs PullRequestList) LoadAttributes(ctx context.Context) error {
|
||||
if len(prs) == 0 {
|
||||
return nil
|
||||
}
|
||||
@@ -199,8 +199,3 @@ func (prs PullRequestList) GetIssueIDs() []int64 {
|
||||
}
|
||||
return issueIDs
|
||||
}
|
||||
|
||||
// LoadAttributes load all the prs attributes
|
||||
func (prs PullRequestList) LoadAttributes() error {
|
||||
return prs.loadAttributes(db.DefaultContext)
|
||||
}
|
||||
|
||||
@@ -148,7 +148,7 @@ func TestHasUnmergedPullRequestsByHeadInfo(t *testing.T) {
|
||||
|
||||
func TestGetUnmergedPullRequestsByHeadInfo(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(1, "branch2")
|
||||
prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(db.DefaultContext, 1, "branch2")
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, prs, 1)
|
||||
for _, pr := range prs {
|
||||
@@ -159,7 +159,7 @@ func TestGetUnmergedPullRequestsByHeadInfo(t *testing.T) {
|
||||
|
||||
func TestGetUnmergedPullRequestsByBaseInfo(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
prs, err := issues_model.GetUnmergedPullRequestsByBaseInfo(1, "master")
|
||||
prs, err := issues_model.GetUnmergedPullRequestsByBaseInfo(db.DefaultContext, 1, "master")
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, prs, 1)
|
||||
pr := prs[0]
|
||||
@@ -242,13 +242,13 @@ func TestPullRequestList_LoadAttributes(t *testing.T) {
|
||||
unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1}),
|
||||
unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2}),
|
||||
}
|
||||
assert.NoError(t, issues_model.PullRequestList(prs).LoadAttributes())
|
||||
assert.NoError(t, issues_model.PullRequestList(prs).LoadAttributes(db.DefaultContext))
|
||||
for _, pr := range prs {
|
||||
assert.NotNil(t, pr.Issue)
|
||||
assert.Equal(t, pr.IssueID, pr.Issue.ID)
|
||||
}
|
||||
|
||||
assert.NoError(t, issues_model.PullRequestList([]*issues_model.PullRequest{}).LoadAttributes())
|
||||
assert.NoError(t, issues_model.PullRequestList([]*issues_model.PullRequest{}).LoadAttributes(db.DefaultContext))
|
||||
}
|
||||
|
||||
// TODO TestAddTestPullRequestTask
|
||||
|
||||
+2
-158
@@ -162,27 +162,6 @@ func (r *Review) LoadReviewer(ctx context.Context) (err error) {
|
||||
return err
|
||||
}
|
||||
|
||||
// LoadReviewers loads reviewers
|
||||
func LoadReviewers(ctx context.Context, reviews []*Review) (err error) {
|
||||
reviewerIds := make([]int64, len(reviews))
|
||||
for i := 0; i < len(reviews); i++ {
|
||||
reviewerIds[i] = reviews[i].ReviewerID
|
||||
}
|
||||
reviewers, err := user_model.GetPossibleUserByIDs(ctx, reviewerIds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
userMap := make(map[int64]*user_model.User, len(reviewers))
|
||||
for _, reviewer := range reviewers {
|
||||
userMap[reviewer.ID] = reviewer
|
||||
}
|
||||
for _, review := range reviews {
|
||||
review.Reviewer = userMap[review.ReviewerID]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoadReviewerTeam loads reviewer team
|
||||
func (r *Review) LoadReviewerTeam(ctx context.Context) (err error) {
|
||||
if r.ReviewerTeamID == 0 || r.ReviewerTeam != nil {
|
||||
@@ -236,71 +215,6 @@ func GetReviewByID(ctx context.Context, id int64) (*Review, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// FindReviewOptions represent possible filters to find reviews
|
||||
type FindReviewOptions struct {
|
||||
db.ListOptions
|
||||
Type ReviewType
|
||||
IssueID int64
|
||||
ReviewerID int64
|
||||
OfficialOnly bool
|
||||
}
|
||||
|
||||
func (opts *FindReviewOptions) toCond() builder.Cond {
|
||||
cond := builder.NewCond()
|
||||
if opts.IssueID > 0 {
|
||||
cond = cond.And(builder.Eq{"issue_id": opts.IssueID})
|
||||
}
|
||||
if opts.ReviewerID > 0 {
|
||||
cond = cond.And(builder.Eq{"reviewer_id": opts.ReviewerID})
|
||||
}
|
||||
if opts.Type != ReviewTypeUnknown {
|
||||
cond = cond.And(builder.Eq{"type": opts.Type})
|
||||
}
|
||||
if opts.OfficialOnly {
|
||||
cond = cond.And(builder.Eq{"official": true})
|
||||
}
|
||||
return cond
|
||||
}
|
||||
|
||||
// FindReviews returns reviews passing FindReviewOptions
|
||||
func FindReviews(ctx context.Context, opts FindReviewOptions) ([]*Review, error) {
|
||||
reviews := make([]*Review, 0, 10)
|
||||
sess := db.GetEngine(ctx).Where(opts.toCond())
|
||||
if opts.Page > 0 {
|
||||
sess = db.SetSessionPagination(sess, &opts)
|
||||
}
|
||||
return reviews, sess.
|
||||
Asc("created_unix").
|
||||
Asc("id").
|
||||
Find(&reviews)
|
||||
}
|
||||
|
||||
// FindLatestReviews returns only latest reviews per user, passing FindReviewOptions
|
||||
func FindLatestReviews(ctx context.Context, opts FindReviewOptions) ([]*Review, error) {
|
||||
reviews := make([]*Review, 0, 10)
|
||||
cond := opts.toCond()
|
||||
sess := db.GetEngine(ctx).Where(cond)
|
||||
if opts.Page > 0 {
|
||||
sess = db.SetSessionPagination(sess, &opts)
|
||||
}
|
||||
|
||||
sess.In("id", builder.
|
||||
Select("max ( id ) ").
|
||||
From("review").
|
||||
Where(cond).
|
||||
GroupBy("reviewer_id"))
|
||||
|
||||
return reviews, sess.
|
||||
Asc("created_unix").
|
||||
Asc("id").
|
||||
Find(&reviews)
|
||||
}
|
||||
|
||||
// CountReviews returns count of reviews passing FindReviewOptions
|
||||
func CountReviews(opts FindReviewOptions) (int64, error) {
|
||||
return db.GetEngine(db.DefaultContext).Where(opts.toCond()).Count(&Review{})
|
||||
}
|
||||
|
||||
// CreateReviewOptions represent the options to create a review. Type, Issue and Reviewer are required.
|
||||
type CreateReviewOptions struct {
|
||||
Content string
|
||||
@@ -533,76 +447,6 @@ func SubmitReview(doer *user_model.User, issue *Issue, reviewType ReviewType, co
|
||||
return review, comm, committer.Commit()
|
||||
}
|
||||
|
||||
// GetReviewOptions represent filter options for GetReviews
|
||||
type GetReviewOptions struct {
|
||||
IssueID int64
|
||||
ReviewerID int64
|
||||
Dismissed util.OptionalBool
|
||||
}
|
||||
|
||||
// GetReviews return reviews based on GetReviewOptions
|
||||
func GetReviews(ctx context.Context, opts *GetReviewOptions) ([]*Review, error) {
|
||||
if opts == nil {
|
||||
return nil, fmt.Errorf("opts are nil")
|
||||
}
|
||||
|
||||
sess := db.GetEngine(ctx)
|
||||
|
||||
if opts.IssueID != 0 {
|
||||
sess = sess.Where("issue_id=?", opts.IssueID)
|
||||
}
|
||||
if opts.ReviewerID != 0 {
|
||||
sess = sess.Where("reviewer_id=?", opts.ReviewerID)
|
||||
}
|
||||
if !opts.Dismissed.IsNone() {
|
||||
sess = sess.Where("dismissed=?", opts.Dismissed.IsTrue())
|
||||
}
|
||||
|
||||
reviews := make([]*Review, 0, 4)
|
||||
return reviews, sess.Find(&reviews)
|
||||
}
|
||||
|
||||
// GetReviewsByIssueID gets the latest review of each reviewer for a pull request
|
||||
func GetReviewsByIssueID(issueID int64) ([]*Review, error) {
|
||||
reviews := make([]*Review, 0, 10)
|
||||
|
||||
sess := db.GetEngine(db.DefaultContext)
|
||||
|
||||
// Get latest review of each reviewer, sorted in order they were made
|
||||
if err := sess.SQL("SELECT * FROM review WHERE id IN (SELECT max(id) as id FROM review WHERE issue_id = ? AND reviewer_team_id = 0 AND type in (?, ?, ?) AND dismissed = ? AND original_author_id = 0 GROUP BY issue_id, reviewer_id) ORDER BY review.updated_unix ASC",
|
||||
issueID, ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest, false).
|
||||
Find(&reviews); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
teamReviewRequests := make([]*Review, 0, 5)
|
||||
if err := sess.SQL("SELECT * FROM review WHERE id IN (SELECT max(id) as id FROM review WHERE issue_id = ? AND reviewer_team_id <> 0 AND original_author_id = 0 GROUP BY issue_id, reviewer_team_id) ORDER BY review.updated_unix ASC",
|
||||
issueID).
|
||||
Find(&teamReviewRequests); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(teamReviewRequests) > 0 {
|
||||
reviews = append(reviews, teamReviewRequests...)
|
||||
}
|
||||
|
||||
return reviews, nil
|
||||
}
|
||||
|
||||
// GetReviewersFromOriginalAuthorsByIssueID gets the latest review of each original authors for a pull request
|
||||
func GetReviewersFromOriginalAuthorsByIssueID(issueID int64) ([]*Review, error) {
|
||||
reviews := make([]*Review, 0, 10)
|
||||
|
||||
// Get latest review of each reviewer, sorted in order they were made
|
||||
if err := db.GetEngine(db.DefaultContext).SQL("SELECT * FROM review WHERE id IN (SELECT max(id) as id FROM review WHERE issue_id = ? AND reviewer_team_id = 0 AND type in (?, ?, ?) AND original_author_id <> 0 GROUP BY issue_id, original_author_id) ORDER BY review.updated_unix ASC",
|
||||
issueID, ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest).
|
||||
Find(&reviews); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return reviews, nil
|
||||
}
|
||||
|
||||
// GetReviewByIssueIDAndUserID get the latest review of reviewer for a pull request
|
||||
func GetReviewByIssueIDAndUserID(ctx context.Context, issueID, userID int64) (*Review, error) {
|
||||
review := new(Review)
|
||||
@@ -654,7 +498,7 @@ func MarkReviewsAsNotStale(issueID int64, commitID string) (err error) {
|
||||
}
|
||||
|
||||
// DismissReview change the dismiss status of a review
|
||||
func DismissReview(review *Review, isDismiss bool) (err error) {
|
||||
func DismissReview(ctx context.Context, review *Review, isDismiss bool) (err error) {
|
||||
if review.Dismissed == isDismiss || (review.Type != ReviewTypeApprove && review.Type != ReviewTypeReject) {
|
||||
return nil
|
||||
}
|
||||
@@ -665,7 +509,7 @@ func DismissReview(review *Review, isDismiss bool) (err error) {
|
||||
return ErrReviewNotExist{}
|
||||
}
|
||||
|
||||
_, err = db.GetEngine(db.DefaultContext).ID(review.ID).Cols("dismissed").Update(review)
|
||||
_, err = db.GetEngine(ctx).ID(review.ID).Cols("dismissed").Update(review)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package issues
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/container"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"xorm.io/builder"
|
||||
)
|
||||
|
||||
type ReviewList []*Review
|
||||
|
||||
// LoadReviewers loads reviewers
|
||||
func (reviews ReviewList) LoadReviewers(ctx context.Context) error {
|
||||
reviewerIds := make([]int64, len(reviews))
|
||||
for i := 0; i < len(reviews); i++ {
|
||||
reviewerIds[i] = reviews[i].ReviewerID
|
||||
}
|
||||
reviewers, err := user_model.GetPossibleUserByIDs(ctx, reviewerIds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
userMap := make(map[int64]*user_model.User, len(reviewers))
|
||||
for _, reviewer := range reviewers {
|
||||
userMap[reviewer.ID] = reviewer
|
||||
}
|
||||
for _, review := range reviews {
|
||||
review.Reviewer = userMap[review.ReviewerID]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (reviews ReviewList) LoadIssues(ctx context.Context) error {
|
||||
issueIds := container.Set[int64]{}
|
||||
for i := 0; i < len(reviews); i++ {
|
||||
issueIds.Add(reviews[i].IssueID)
|
||||
}
|
||||
|
||||
issues, err := GetIssuesByIDs(ctx, issueIds.Values())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := issues.LoadRepositories(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
issueMap := make(map[int64]*Issue, len(issues))
|
||||
for _, issue := range issues {
|
||||
issueMap[issue.ID] = issue
|
||||
}
|
||||
|
||||
for _, review := range reviews {
|
||||
review.Issue = issueMap[review.IssueID]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindReviewOptions represent possible filters to find reviews
|
||||
type FindReviewOptions struct {
|
||||
db.ListOptions
|
||||
Type ReviewType
|
||||
IssueID int64
|
||||
ReviewerID int64
|
||||
OfficialOnly bool
|
||||
Dismissed util.OptionalBool
|
||||
}
|
||||
|
||||
func (opts *FindReviewOptions) toCond() builder.Cond {
|
||||
cond := builder.NewCond()
|
||||
if opts.IssueID > 0 {
|
||||
cond = cond.And(builder.Eq{"issue_id": opts.IssueID})
|
||||
}
|
||||
if opts.ReviewerID > 0 {
|
||||
cond = cond.And(builder.Eq{"reviewer_id": opts.ReviewerID})
|
||||
}
|
||||
if opts.Type != ReviewTypeUnknown {
|
||||
cond = cond.And(builder.Eq{"type": opts.Type})
|
||||
}
|
||||
if opts.OfficialOnly {
|
||||
cond = cond.And(builder.Eq{"official": true})
|
||||
}
|
||||
if !opts.Dismissed.IsNone() {
|
||||
cond = cond.And(builder.Eq{"dismissed": opts.Dismissed.IsTrue()})
|
||||
}
|
||||
return cond
|
||||
}
|
||||
|
||||
// FindReviews returns reviews passing FindReviewOptions
|
||||
func FindReviews(ctx context.Context, opts FindReviewOptions) (ReviewList, error) {
|
||||
reviews := make([]*Review, 0, 10)
|
||||
sess := db.GetEngine(ctx).Where(opts.toCond())
|
||||
if opts.Page > 0 && !opts.IsListAll() {
|
||||
sess = db.SetSessionPagination(sess, &opts)
|
||||
}
|
||||
return reviews, sess.
|
||||
Asc("created_unix").
|
||||
Asc("id").
|
||||
Find(&reviews)
|
||||
}
|
||||
|
||||
// FindLatestReviews returns only latest reviews per user, passing FindReviewOptions
|
||||
func FindLatestReviews(ctx context.Context, opts FindReviewOptions) (ReviewList, error) {
|
||||
reviews := make([]*Review, 0, 10)
|
||||
cond := opts.toCond()
|
||||
sess := db.GetEngine(ctx).Where(cond)
|
||||
if opts.Page > 0 {
|
||||
sess = db.SetSessionPagination(sess, &opts)
|
||||
}
|
||||
|
||||
sess.In("id", builder.
|
||||
Select("max ( id ) ").
|
||||
From("review").
|
||||
Where(cond).
|
||||
GroupBy("reviewer_id"))
|
||||
|
||||
return reviews, sess.
|
||||
Asc("created_unix").
|
||||
Asc("id").
|
||||
Find(&reviews)
|
||||
}
|
||||
|
||||
// CountReviews returns count of reviews passing FindReviewOptions
|
||||
func CountReviews(opts FindReviewOptions) (int64, error) {
|
||||
return db.GetEngine(db.DefaultContext).Where(opts.toCond()).Count(&Review{})
|
||||
}
|
||||
|
||||
// GetReviewersFromOriginalAuthorsByIssueID gets the latest review of each original authors for a pull request
|
||||
func GetReviewersFromOriginalAuthorsByIssueID(issueID int64) (ReviewList, error) {
|
||||
reviews := make([]*Review, 0, 10)
|
||||
|
||||
// Get latest review of each reviewer, sorted in order they were made
|
||||
if err := db.GetEngine(db.DefaultContext).SQL("SELECT * FROM review WHERE id IN (SELECT max(id) as id FROM review WHERE issue_id = ? AND reviewer_team_id = 0 AND type in (?, ?, ?) AND original_author_id <> 0 GROUP BY issue_id, original_author_id) ORDER BY review.updated_unix ASC",
|
||||
issueID, ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest).
|
||||
Find(&reviews); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return reviews, nil
|
||||
}
|
||||
|
||||
// GetReviewsByIssueID gets the latest review of each reviewer for a pull request
|
||||
func GetReviewsByIssueID(issueID int64) (ReviewList, error) {
|
||||
reviews := make([]*Review, 0, 10)
|
||||
|
||||
sess := db.GetEngine(db.DefaultContext)
|
||||
|
||||
// Get latest review of each reviewer, sorted in order they were made
|
||||
if err := sess.SQL("SELECT * FROM review WHERE id IN (SELECT max(id) as id FROM review WHERE issue_id = ? AND reviewer_team_id = 0 AND type in (?, ?, ?) AND dismissed = ? AND original_author_id = 0 GROUP BY issue_id, reviewer_id) ORDER BY review.updated_unix ASC",
|
||||
issueID, ReviewTypeApprove, ReviewTypeReject, ReviewTypeRequest, false).
|
||||
Find(&reviews); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
teamReviewRequests := make([]*Review, 0, 5)
|
||||
if err := sess.SQL("SELECT * FROM review WHERE id IN (SELECT max(id) as id FROM review WHERE issue_id = ? AND reviewer_team_id <> 0 AND original_author_id = 0 GROUP BY issue_id, reviewer_team_id) ORDER BY review.updated_unix ASC",
|
||||
issueID).
|
||||
Find(&teamReviewRequests); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(teamReviewRequests) > 0 {
|
||||
reviews = append(reviews, teamReviewRequests...)
|
||||
}
|
||||
|
||||
return reviews, nil
|
||||
}
|
||||
@@ -159,7 +159,7 @@ func TestGetReviewersByIssueID(t *testing.T) {
|
||||
|
||||
allReviews, err = issues_model.GetReviewsByIssueID(issue.ID)
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, issues_model.LoadReviewers(db.DefaultContext, allReviews))
|
||||
assert.NoError(t, allReviews.LoadReviewers(db.DefaultContext))
|
||||
if assert.Len(t, allReviews, 3) {
|
||||
for i, review := range allReviews {
|
||||
assert.Equal(t, expectedReviews[i].Reviewer, review.Reviewer)
|
||||
@@ -179,46 +179,46 @@ func TestDismissReview(t *testing.T) {
|
||||
assert.False(t, requestReviewExample.Dismissed)
|
||||
assert.False(t, approveReviewExample.Dismissed)
|
||||
|
||||
assert.NoError(t, issues_model.DismissReview(rejectReviewExample, true))
|
||||
assert.NoError(t, issues_model.DismissReview(db.DefaultContext, rejectReviewExample, true))
|
||||
rejectReviewExample = unittest.AssertExistsAndLoadBean(t, &issues_model.Review{ID: 9})
|
||||
requestReviewExample = unittest.AssertExistsAndLoadBean(t, &issues_model.Review{ID: 11})
|
||||
assert.True(t, rejectReviewExample.Dismissed)
|
||||
assert.False(t, requestReviewExample.Dismissed)
|
||||
|
||||
assert.NoError(t, issues_model.DismissReview(requestReviewExample, true))
|
||||
assert.NoError(t, issues_model.DismissReview(db.DefaultContext, requestReviewExample, true))
|
||||
rejectReviewExample = unittest.AssertExistsAndLoadBean(t, &issues_model.Review{ID: 9})
|
||||
requestReviewExample = unittest.AssertExistsAndLoadBean(t, &issues_model.Review{ID: 11})
|
||||
assert.True(t, rejectReviewExample.Dismissed)
|
||||
assert.False(t, requestReviewExample.Dismissed)
|
||||
assert.False(t, approveReviewExample.Dismissed)
|
||||
|
||||
assert.NoError(t, issues_model.DismissReview(requestReviewExample, true))
|
||||
assert.NoError(t, issues_model.DismissReview(db.DefaultContext, requestReviewExample, true))
|
||||
rejectReviewExample = unittest.AssertExistsAndLoadBean(t, &issues_model.Review{ID: 9})
|
||||
requestReviewExample = unittest.AssertExistsAndLoadBean(t, &issues_model.Review{ID: 11})
|
||||
assert.True(t, rejectReviewExample.Dismissed)
|
||||
assert.False(t, requestReviewExample.Dismissed)
|
||||
assert.False(t, approveReviewExample.Dismissed)
|
||||
|
||||
assert.NoError(t, issues_model.DismissReview(requestReviewExample, false))
|
||||
assert.NoError(t, issues_model.DismissReview(db.DefaultContext, requestReviewExample, false))
|
||||
rejectReviewExample = unittest.AssertExistsAndLoadBean(t, &issues_model.Review{ID: 9})
|
||||
requestReviewExample = unittest.AssertExistsAndLoadBean(t, &issues_model.Review{ID: 11})
|
||||
assert.True(t, rejectReviewExample.Dismissed)
|
||||
assert.False(t, requestReviewExample.Dismissed)
|
||||
assert.False(t, approveReviewExample.Dismissed)
|
||||
|
||||
assert.NoError(t, issues_model.DismissReview(requestReviewExample, false))
|
||||
assert.NoError(t, issues_model.DismissReview(db.DefaultContext, requestReviewExample, false))
|
||||
rejectReviewExample = unittest.AssertExistsAndLoadBean(t, &issues_model.Review{ID: 9})
|
||||
requestReviewExample = unittest.AssertExistsAndLoadBean(t, &issues_model.Review{ID: 11})
|
||||
assert.True(t, rejectReviewExample.Dismissed)
|
||||
assert.False(t, requestReviewExample.Dismissed)
|
||||
assert.False(t, approveReviewExample.Dismissed)
|
||||
|
||||
assert.NoError(t, issues_model.DismissReview(rejectReviewExample, false))
|
||||
assert.NoError(t, issues_model.DismissReview(db.DefaultContext, rejectReviewExample, false))
|
||||
assert.False(t, rejectReviewExample.Dismissed)
|
||||
assert.False(t, requestReviewExample.Dismissed)
|
||||
assert.False(t, approveReviewExample.Dismissed)
|
||||
|
||||
assert.NoError(t, issues_model.DismissReview(approveReviewExample, true))
|
||||
assert.NoError(t, issues_model.DismissReview(db.DefaultContext, approveReviewExample, true))
|
||||
assert.False(t, rejectReviewExample.Dismissed)
|
||||
assert.False(t, requestReviewExample.Dismissed)
|
||||
assert.True(t, approveReviewExample.Dismissed)
|
||||
|
||||
@@ -43,11 +43,7 @@ func (t *TrackedTime) AfterLoad() {
|
||||
}
|
||||
|
||||
// LoadAttributes load Issue, User
|
||||
func (t *TrackedTime) LoadAttributes() (err error) {
|
||||
return t.loadAttributes(db.DefaultContext)
|
||||
}
|
||||
|
||||
func (t *TrackedTime) loadAttributes(ctx context.Context) (err error) {
|
||||
func (t *TrackedTime) LoadAttributes(ctx context.Context) (err error) {
|
||||
// Load the issue
|
||||
if t.Issue == nil {
|
||||
t.Issue, err = GetIssueByID(ctx, t.IssueID)
|
||||
@@ -76,9 +72,9 @@ func (t *TrackedTime) loadAttributes(ctx context.Context) (err error) {
|
||||
}
|
||||
|
||||
// LoadAttributes load Issue, User
|
||||
func (tl TrackedTimeList) LoadAttributes() error {
|
||||
func (tl TrackedTimeList) LoadAttributes(ctx context.Context) error {
|
||||
for _, t := range tl {
|
||||
if err := t.LoadAttributes(); err != nil {
|
||||
if err := t.LoadAttributes(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -143,8 +139,8 @@ func GetTrackedTimes(ctx context.Context, options *FindTrackedTimesOptions) (tra
|
||||
}
|
||||
|
||||
// CountTrackedTimes returns count of tracked times that fit to the given options.
|
||||
func CountTrackedTimes(opts *FindTrackedTimesOptions) (int64, error) {
|
||||
sess := db.GetEngine(db.DefaultContext).Where(opts.toCond())
|
||||
func CountTrackedTimes(ctx context.Context, opts *FindTrackedTimesOptions) (int64, error) {
|
||||
sess := db.GetEngine(ctx).Where(opts.toCond())
|
||||
if opts.RepositoryID > 0 || opts.MilestoneID > 0 {
|
||||
sess = sess.Join("INNER", "issue", "issue.id = tracked_time.issue_id")
|
||||
}
|
||||
@@ -157,8 +153,8 @@ func GetTrackedSeconds(ctx context.Context, opts FindTrackedTimesOptions) (track
|
||||
}
|
||||
|
||||
// AddTime will add the given time (in seconds) to the issue
|
||||
func AddTime(user *user_model.User, issue *Issue, amount int64, created time.Time) (*TrackedTime, error) {
|
||||
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||
func AddTime(ctx context.Context, user *user_model.User, issue *Issue, amount int64, created time.Time) (*TrackedTime, error) {
|
||||
ctx, committer, err := db.TxContext(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -276,7 +272,7 @@ func DeleteTime(t *TrackedTime) error {
|
||||
}
|
||||
defer committer.Close()
|
||||
|
||||
if err := t.loadAttributes(ctx); err != nil {
|
||||
if err := t.LoadAttributes(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ func TestAddTime(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
|
||||
// 3661 = 1h 1min 1s
|
||||
trackedTime, err := issues_model.AddTime(user3, issue1, 3661, time.Now())
|
||||
trackedTime, err := issues_model.AddTime(db.DefaultContext, user3, issue1, 3661, time.Now())
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, int64(3), trackedTime.UserID)
|
||||
assert.Equal(t, int64(1), trackedTime.IssueID)
|
||||
|
||||
+2
-2
@@ -128,8 +128,8 @@ func InsertIssueComments(comments []*issues_model.Comment) error {
|
||||
}
|
||||
|
||||
// InsertPullRequests inserted pull requests
|
||||
func InsertPullRequests(prs ...*issues_model.PullRequest) error {
|
||||
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||
func InsertPullRequests(ctx context.Context, prs ...*issues_model.PullRequest) error {
|
||||
ctx, committer, err := db.TxContext(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ func TestMigrate_InsertPullRequests(t *testing.T) {
|
||||
Issue: i,
|
||||
}
|
||||
|
||||
err := InsertPullRequests(p)
|
||||
err := InsertPullRequests(db.DefaultContext, p)
|
||||
assert.NoError(t, err)
|
||||
|
||||
_ = unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{IssueID: i.ID})
|
||||
|
||||
@@ -511,6 +511,12 @@ var migrations = []Migration{
|
||||
NewMigration("Add git_size and lfs_size columns to repository table", v1_21.AddGitSizeAndLFSSizeToRepositoryTable),
|
||||
// v264 -> v265
|
||||
NewMigration("Add branch table", v1_21.AddBranchTable),
|
||||
// v265 -> v266
|
||||
NewMigration("Alter Actions Artifact table", v1_21.AlterActionArtifactTable),
|
||||
// v266 -> v267
|
||||
NewMigration("Reduce commit status", v1_21.ReduceCommitStatus),
|
||||
// v267 -> v268
|
||||
NewMigration("Add action_tasks_version table", v1_21.CreateActionTasksVersionTable),
|
||||
// to modify later
|
||||
NewMigration("Add size limit on repository", v1_21.AddSizeLimitOnRepo),
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_21 //nolint
|
||||
|
||||
import (
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
func AlterActionArtifactTable(x *xorm.Engine) error {
|
||||
// ActionArtifact is a file that is stored in the artifact storage.
|
||||
type ActionArtifact struct {
|
||||
RunID int64 `xorm:"index unique(runid_name_path)"` // The run id of the artifact
|
||||
ArtifactPath string `xorm:"index unique(runid_name_path)"` // The path to the artifact when runner uploads it
|
||||
ArtifactName string `xorm:"index unique(runid_name_path)"` // The name of the artifact when
|
||||
}
|
||||
|
||||
return x.Sync(new(ActionArtifact))
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_21 //nolint
|
||||
|
||||
import (
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
func ReduceCommitStatus(x *xorm.Engine) error {
|
||||
sess := x.NewSession()
|
||||
defer sess.Close()
|
||||
|
||||
if err := sess.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := sess.Exec(`UPDATE commit_status SET state='pending' WHERE state='running'`); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := sess.Exec(`UPDATE commit_status SET state='failure' WHERE state='warning'`); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return sess.Commit()
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_21 //nolint
|
||||
|
||||
import (
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
func CreateActionTasksVersionTable(x *xorm.Engine) error {
|
||||
type ActionTasksVersion struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
OwnerID int64 `xorm:"UNIQUE(owner_repo)"`
|
||||
RepoID int64 `xorm:"INDEX UNIQUE(owner_repo)"`
|
||||
Version int64
|
||||
CreatedUnix timeutil.TimeStamp `xorm:"created"`
|
||||
UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
|
||||
}
|
||||
|
||||
return x.Sync(new(ActionTasksVersion))
|
||||
}
|
||||
+15
-13
@@ -196,7 +196,7 @@ type SearchOptions struct {
|
||||
RepoID int64
|
||||
Page int
|
||||
IsClosed util.OptionalBool
|
||||
SortType string
|
||||
OrderBy db.SearchOrderBy
|
||||
Type Type
|
||||
}
|
||||
|
||||
@@ -226,26 +226,28 @@ func CountProjects(ctx context.Context, opts SearchOptions) (int64, error) {
|
||||
return db.GetEngine(ctx).Where(opts.toConds()).Count(new(Project))
|
||||
}
|
||||
|
||||
func GetSearchOrderByBySortType(sortType string) db.SearchOrderBy {
|
||||
switch sortType {
|
||||
case "oldest":
|
||||
return db.SearchOrderByOldest
|
||||
case "recentupdate":
|
||||
return db.SearchOrderByRecentUpdated
|
||||
case "leastupdate":
|
||||
return db.SearchOrderByLeastUpdated
|
||||
default:
|
||||
return db.SearchOrderByNewest
|
||||
}
|
||||
}
|
||||
|
||||
// FindProjects returns a list of all projects that have been created in the repository
|
||||
func FindProjects(ctx context.Context, opts SearchOptions) ([]*Project, int64, error) {
|
||||
e := db.GetEngine(ctx).Where(opts.toConds())
|
||||
e := db.GetEngine(ctx).Where(opts.toConds()).OrderBy(opts.OrderBy.String())
|
||||
projects := make([]*Project, 0, setting.UI.IssuePagingNum)
|
||||
|
||||
if opts.Page > 0 {
|
||||
e = e.Limit(setting.UI.IssuePagingNum, (opts.Page-1)*setting.UI.IssuePagingNum)
|
||||
}
|
||||
|
||||
switch opts.SortType {
|
||||
case "oldest":
|
||||
e.Desc("created_unix")
|
||||
case "recentupdate":
|
||||
e.Desc("updated_unix")
|
||||
case "leastupdate":
|
||||
e.Asc("updated_unix")
|
||||
default:
|
||||
e.Asc("created_unix")
|
||||
}
|
||||
|
||||
count, err := e.FindAndCount(&projects)
|
||||
return projects, count, err
|
||||
}
|
||||
|
||||
@@ -82,3 +82,42 @@ func TestProject(t *testing.T) {
|
||||
|
||||
assert.True(t, projectFromDB.IsClosed)
|
||||
}
|
||||
|
||||
func TestProjectsSort(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
tests := []struct {
|
||||
sortType string
|
||||
wants []int64
|
||||
}{
|
||||
{
|
||||
sortType: "default",
|
||||
wants: []int64{1, 3, 2, 4},
|
||||
},
|
||||
{
|
||||
sortType: "oldest",
|
||||
wants: []int64{4, 2, 3, 1},
|
||||
},
|
||||
{
|
||||
sortType: "recentupdate",
|
||||
wants: []int64{1, 3, 2, 4},
|
||||
},
|
||||
{
|
||||
sortType: "leastupdate",
|
||||
wants: []int64{4, 2, 3, 1},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
projects, count, err := FindProjects(db.DefaultContext, SearchOptions{
|
||||
OrderBy: GetSearchOrderByBySortType(tt.sortType),
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, int64(4), count)
|
||||
if assert.Len(t, projects, 4) {
|
||||
for i := range projects {
|
||||
assert.EqualValues(t, tt.wants[i], projects[i].ID)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user