Compare commits

..

No commits in common. "7aaa2d6de4d780f9b1366978f036ea5e7f00dd63" and "7a1cc340b842a5794b3650e18e02339cf657c33f" have entirely different histories.

668 changed files with 4073 additions and 5063 deletions

View File

@ -91,7 +91,6 @@ module.exports = {
plugins: ['@vitest/eslint-plugin'], plugins: ['@vitest/eslint-plugin'],
globals: vitestPlugin.environments.env.globals, globals: vitestPlugin.environments.env.globals,
rules: { rules: {
'github/unescaped-html-literal': [0],
'@vitest/consistent-test-filename': [0], '@vitest/consistent-test-filename': [0],
'@vitest/consistent-test-it': [0], '@vitest/consistent-test-it': [0],
'@vitest/expect-expect': [0], '@vitest/expect-expect': [0],
@ -424,7 +423,7 @@ module.exports = {
'github/no-useless-passive': [2], 'github/no-useless-passive': [2],
'github/prefer-observers': [2], 'github/prefer-observers': [2],
'github/require-passive-events': [2], 'github/require-passive-events': [2],
'github/unescaped-html-literal': [2], 'github/unescaped-html-literal': [0],
'grouped-accessor-pairs': [2], 'grouped-accessor-pairs': [2],
'guard-for-in': [0], 'guard-for-in': [0],
'id-blacklist': [0], 'id-blacklist': [0],

View File

@ -45,10 +45,6 @@ linters:
desc: do not use the ini package, use gitea's config system instead desc: do not use the ini package, use gitea's config system instead
- pkg: gitea.com/go-chi/cache - pkg: gitea.com/go-chi/cache
desc: do not use the go-chi cache package, use gitea's cache system desc: do not use the go-chi cache package, use gitea's cache system
nolintlint:
allow-unused: false
require-explanation: true
require-specific: true
gocritic: gocritic:
disabled-checks: disabled-checks:
- ifElseChain - ifElseChain
@ -87,10 +83,6 @@ linters:
- name: unreachable-code - name: unreachable-code
- name: var-declaration - name: var-declaration
- name: var-naming - name: var-naming
arguments:
- [] # AllowList - do not remove as args for the rule are positional and won't work without lists first
- [] # DenyList
- - skip-package-name-checks: true # supress errors from underscore in migration packages
staticcheck: staticcheck:
checks: checks:
- all - all

View File

@ -26,18 +26,18 @@ COMMA := ,
XGO_VERSION := go-1.24.x XGO_VERSION := go-1.24.x
AIR_PACKAGE ?= github.com/air-verse/air@v1 AIR_PACKAGE ?= github.com/air-verse/air@v1
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v3/cmd/editorconfig-checker@v3 EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v3/cmd/editorconfig-checker@v3.2.1
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.8.0 GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.7.0
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.1.6 GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.0.2
GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.12 GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.12
MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.7.0 MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.6.0
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.32.3 SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.31.0
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1 GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1
GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1 GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1
ACTIONLINT_PACKAGE ?= github.com/rhysd/actionlint/cmd/actionlint@v1 ACTIONLINT_PACKAGE ?= github.com/rhysd/actionlint/cmd/actionlint@v1
GOPLS_PACKAGE ?= golang.org/x/tools/gopls@v0.19.1 GOPLS_PACKAGE ?= golang.org/x/tools/gopls@v0.19.0
GOPLS_MODERNIZE_PACKAGE ?= golang.org/x/tools/gopls/internal/analysis/modernize/cmd/modernize@v0.19.1 GOPLS_MODERNIZE_PACKAGE ?= golang.org/x/tools/gopls/internal/analysis/modernize/cmd/modernize@v0.19.0
DOCKER_IMAGE ?= gitea/gitea DOCKER_IMAGE ?= gitea/gitea
DOCKER_TAG ?= latest DOCKER_TAG ?= latest
@ -81,6 +81,7 @@ ifeq ($(RACE_ENABLED),true)
endif endif
STORED_VERSION_FILE := VERSION STORED_VERSION_FILE := VERSION
HUGO_VERSION ?= 0.111.3
GITHUB_REF_TYPE ?= branch GITHUB_REF_TYPE ?= branch
GITHUB_REF_NAME ?= $(shell git rev-parse --abbrev-ref HEAD) GITHUB_REF_NAME ?= $(shell git rev-parse --abbrev-ref HEAD)

View File

@ -295,14 +295,16 @@ func collectAssetFilesByPattern(c *cli.Command, globs []glob.Glob, path string,
} }
} }
func compileCollectPatterns(args []string) (_ []glob.Glob, err error) { func compileCollectPatterns(args []string) ([]glob.Glob, error) {
if len(args) == 0 { if len(args) == 0 {
args = []string{"**"} args = []string{"**"}
} }
pat := make([]glob.Glob, len(args)) pat := make([]glob.Glob, len(args))
for i := range args { for i := range args {
if pat[i], err = glob.Compile(args[i], '/'); err != nil { if g, err := glob.Compile(args[i], '/'); err != nil {
return nil, fmt.Errorf("invalid glob patterh %q: %w", args[i], err) return nil, fmt.Errorf("'%s': Invalid glob pattern: %w", args[i], err)
} else { //nolint:revive
pat[i] = g
} }
} }
return pat, nil return pat, nil

View File

@ -1,7 +1,7 @@
// Copyright 2023 The Gitea Authors. All rights reserved. // Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
//nolint:forbidigo // use of print functions is allowed in cli //nolint:forbidigo
package main package main
import ( import (

View File

@ -185,10 +185,10 @@ func AggregateJobStatus(jobs []*ActionRunJob) Status {
return StatusSuccess return StatusSuccess
case hasCancelled: case hasCancelled:
return StatusCancelled return StatusCancelled
case hasRunning:
return StatusRunning
case hasFailure: case hasFailure:
return StatusFailure return StatusFailure
case hasRunning:
return StatusRunning
case hasWaiting: case hasWaiting:
return StatusWaiting return StatusWaiting
case hasBlocked: case hasBlocked:

View File

@ -58,14 +58,14 @@ func TestAggregateJobStatus(t *testing.T) {
{[]Status{StatusCancelled, StatusRunning}, StatusCancelled}, {[]Status{StatusCancelled, StatusRunning}, StatusCancelled},
{[]Status{StatusCancelled, StatusBlocked}, StatusCancelled}, {[]Status{StatusCancelled, StatusBlocked}, StatusCancelled},
// failure with other status, usually fail fast, but "running" wins to match GitHub's behavior // failure with other status, fail fast
// another reason that we can't make "failure" wins over "running": it would cause a weird behavior that user cannot cancel a workflow or get current running workflows correctly by filter after a job fail. // Should "running" win? Maybe no: old code does make "running" win, but GitHub does fail fast.
{[]Status{StatusFailure}, StatusFailure}, {[]Status{StatusFailure}, StatusFailure},
{[]Status{StatusFailure, StatusSuccess}, StatusFailure}, {[]Status{StatusFailure, StatusSuccess}, StatusFailure},
{[]Status{StatusFailure, StatusSkipped}, StatusFailure}, {[]Status{StatusFailure, StatusSkipped}, StatusFailure},
{[]Status{StatusFailure, StatusCancelled}, StatusCancelled}, {[]Status{StatusFailure, StatusCancelled}, StatusCancelled},
{[]Status{StatusFailure, StatusWaiting}, StatusFailure}, {[]Status{StatusFailure, StatusWaiting}, StatusFailure},
{[]Status{StatusFailure, StatusRunning}, StatusRunning}, {[]Status{StatusFailure, StatusRunning}, StatusFailure},
{[]Status{StatusFailure, StatusBlocked}, StatusFailure}, {[]Status{StatusFailure, StatusBlocked}, StatusFailure},
// skipped with other status // skipped with other status

View File

@ -278,13 +278,14 @@ func CreateTaskForRunner(ctx context.Context, runner *ActionRunner) (*ActionTask
return nil, false, err return nil, false, err
} }
parsedWorkflows, err := jobparser.Parse(job.WorkflowPayload) var workflowJob *jobparser.Job
if err != nil { if gots, err := jobparser.Parse(job.WorkflowPayload); err != nil {
return nil, false, fmt.Errorf("parse workflow of job %d: %w", job.ID, err) return nil, false, fmt.Errorf("parse workflow of job %d: %w", job.ID, err)
} else if len(parsedWorkflows) != 1 { } else if len(gots) != 1 {
return nil, false, fmt.Errorf("workflow of job %d: not single workflow", job.ID) return nil, false, fmt.Errorf("workflow of job %d: not single workflow", job.ID)
} else { //nolint:revive
_, workflowJob = gots[0].Job()
} }
_, workflowJob := parsedWorkflows[0].Job()
if _, err := e.Insert(task); err != nil { if _, err := e.Insert(task); err != nil {
return nil, false, err return nil, false, err

View File

@ -6,7 +6,6 @@ package activities
import ( import (
"context" "context"
"fmt" "fmt"
"html/template"
"net/url" "net/url"
"strconv" "strconv"
@ -17,7 +16,6 @@ import (
"code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/svg"
"code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/timeutil"
"xorm.io/builder" "xorm.io/builder"
@ -381,22 +379,6 @@ func (n *Notification) Link(ctx context.Context) string {
return "" return ""
} }
func (n *Notification) IconHTML(ctx context.Context) template.HTML {
switch n.Source {
case NotificationSourceIssue, NotificationSourcePullRequest:
// n.Issue should be loaded before calling this method
return n.Issue.IconHTML(ctx)
case NotificationSourceCommit:
return svg.RenderHTML("octicon-commit", 16, "text grey")
case NotificationSourceRepository:
return svg.RenderHTML("octicon-repo", 16, "text grey")
case NotificationSourceRelease:
return svg.RenderHTML("octicon-tag", 16, "text grey")
default:
return ""
}
}
// APIURL formats a URL-string to the notification // APIURL formats a URL-string to the notification
func (n *Notification) APIURL() string { func (n *Notification) APIURL() string {
return setting.AppURL + "api/v1/notifications/threads/" + strconv.FormatInt(n.ID, 10) return setting.AppURL + "api/v1/notifications/threads/" + strconv.FormatInt(n.ID, 10)

View File

@ -91,7 +91,7 @@ func AddGPGKey(ctx context.Context, ownerID int64, content, token, signature str
signer, err = openpgp.CheckArmoredDetachedSignature(ekeys, strings.NewReader(token+"\r\n"), strings.NewReader(signature), nil) signer, err = openpgp.CheckArmoredDetachedSignature(ekeys, strings.NewReader(token+"\r\n"), strings.NewReader(signature), nil)
} }
if err != nil { if err != nil {
log.Debug("AddGPGKey CheckArmoredDetachedSignature failed: %v", err) log.Error("Unable to validate token signature. Error: %v", err)
return nil, ErrGPGInvalidTokenSignature{ return nil, ErrGPGInvalidTokenSignature{
ID: ekeys[0].PrimaryKey.KeyIdString(), ID: ekeys[0].PrimaryKey.KeyIdString(),
Wrapped: err, Wrapped: err,

View File

@ -85,7 +85,7 @@ func VerifyGPGKey(ctx context.Context, ownerID int64, keyID, token, signature st
} }
if signer == nil { if signer == nil {
log.Debug("VerifyGPGKey failed: no signer") log.Error("Unable to validate token signature. Error: %v", err)
return "", ErrGPGInvalidTokenSignature{ return "", ErrGPGInvalidTokenSignature{
ID: key.KeyID, ID: key.KeyID,
} }

View File

@ -208,7 +208,7 @@ func SSHNativeParsePublicKey(keyLine string) (string, int, error) {
// The ssh library can parse the key, so next we find out what key exactly we have. // The ssh library can parse the key, so next we find out what key exactly we have.
switch pkey.Type() { switch pkey.Type() {
case ssh.KeyAlgoDSA: //nolint:staticcheck // it's deprecated case ssh.KeyAlgoDSA: //nolint
rawPub := struct { rawPub := struct {
Name string Name string
P, Q, G, Y *big.Int P, Q, G, Y *big.Int

View File

@ -35,7 +35,7 @@ func VerifySSHKey(ctx context.Context, ownerID int64, fingerprint, token, signat
// edge case for Windows based shells that will add CR LF if piped to ssh-keygen command // edge case for Windows based shells that will add CR LF if piped to ssh-keygen command
// see https://github.com/PowerShell/PowerShell/issues/5974 // see https://github.com/PowerShell/PowerShell/issues/5974
if sshsig.Verify(strings.NewReader(token+"\r\n"), []byte(signature), []byte(key.Content), "gitea") != nil { if sshsig.Verify(strings.NewReader(token+"\r\n"), []byte(signature), []byte(key.Content), "gitea") != nil {
log.Debug("VerifySSHKey sshsig.Verify failed: %v", err) log.Error("Unable to validate token signature. Error: %v", err)
return "", ErrSSHInvalidTokenSignature{ return "", ErrSSHInvalidTokenSignature{
Fingerprint: key.Fingerprint, Fingerprint: key.Fingerprint,
} }

View File

@ -15,7 +15,7 @@ import (
var ErrAuthTokenNotExist = util.NewNotExistErrorf("auth token does not exist") var ErrAuthTokenNotExist = util.NewNotExistErrorf("auth token does not exist")
type AuthToken struct { //nolint:revive // export stutter type AuthToken struct { //nolint:revive
ID string `xorm:"pk"` ID string `xorm:"pk"`
TokenHash string TokenHash string
UserID int64 `xorm:"INDEX"` UserID int64 `xorm:"INDEX"`

View File

@ -178,15 +178,6 @@ func WithTx(parentCtx context.Context, f func(ctx context.Context) error) error
return txWithNoCheck(parentCtx, f) return txWithNoCheck(parentCtx, f)
} }
// WithTx2 is similar to WithTx, but it has two return values: result and error.
func WithTx2[T any](parentCtx context.Context, f func(ctx context.Context) (T, error)) (ret T, errRet error) {
errRet = WithTx(parentCtx, func(ctx context.Context) (errInner error) {
ret, errInner = f(ctx)
return errInner
})
return ret, errRet
}
func txWithNoCheck(parentCtx context.Context, f func(ctx context.Context) error) error { func txWithNoCheck(parentCtx context.Context, f func(ctx context.Context) error) error {
sess := xormEngine.NewSession() sess := xormEngine.NewSession()
defer sess.Close() defer sess.Close()

View File

@ -39,7 +39,7 @@ func (d *postgresSchemaDriver) Open(name string) (driver.Conn, error) {
// golangci lint is incorrect here - there is no benefit to using driver.ExecerContext here // golangci lint is incorrect here - there is no benefit to using driver.ExecerContext here
// and in any case pq does not implement it // and in any case pq does not implement it
if execer, ok := conn.(driver.Execer); ok { //nolint:staticcheck // see above if execer, ok := conn.(driver.Execer); ok { //nolint:staticcheck
_, err := execer.Exec(`SELECT set_config( _, err := execer.Exec(`SELECT set_config(
'search_path', 'search_path',
$1 || ',' || current_setting('search_path'), $1 || ',' || current_setting('search_path'),
@ -64,7 +64,7 @@ func (d *postgresSchemaDriver) Open(name string) (driver.Conn, error) {
// driver.String.ConvertValue will never return err for string // driver.String.ConvertValue will never return err for string
// golangci lint is incorrect here - there is no benefit to using stmt.ExecWithContext here // golangci lint is incorrect here - there is no benefit to using stmt.ExecWithContext here
_, err = stmt.Exec([]driver.Value{schemaValue}) //nolint:staticcheck // see above _, err = stmt.Exec([]driver.Value{schemaValue}) //nolint:staticcheck
if err != nil { if err != nil {
_ = conn.Close() _ = conn.Close()
return nil, err return nil, err

View File

@ -518,7 +518,7 @@ func updateTeamWhitelist(ctx context.Context, repo *repo_model.Repository, curre
return currentWhitelist, nil return currentWhitelist, nil
} }
teams, err := organization.GetTeamsWithAccessToAnyRepoUnit(ctx, repo.OwnerID, repo.ID, perm.AccessModeRead, unit.TypeCode, unit.TypePullRequests) teams, err := organization.GetTeamsWithAccessToRepo(ctx, repo.OwnerID, repo.ID, perm.AccessModeRead)
if err != nil { if err != nil {
return nil, fmt.Errorf("GetTeamsWithAccessToRepo [org_id: %d, repo_id: %d]: %v", repo.OwnerID, repo.ID, err) return nil, fmt.Errorf("GetTeamsWithAccessToRepo [org_id: %d, repo_id: %d]: %v", repo.OwnerID, repo.ID, err)
} }

View File

@ -21,7 +21,6 @@ import (
"code.gitea.io/gitea/modules/optional" "code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/svg"
"code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/util"
@ -443,30 +442,6 @@ func (issue *Issue) PatchURL() string {
return "" return ""
} }
/* the logic should be kept the same as getIssueIcon/getIssueColor in TS code */
func (issue *Issue) IconHTML(ctx context.Context) template.HTML {
if issue.IsPull {
if issue.PullRequest == nil { // pull request should be loaded before calling this function
return template.HTML("No PullRequest")
}
if issue.IsClosed {
if issue.PullRequest.HasMerged {
return svg.RenderHTML("octicon-git-merge", 16, "text purple")
}
return svg.RenderHTML("octicon-git-pull-request-closed", 16, "text red")
}
if issue.PullRequest.IsWorkInProgress(ctx) {
return svg.RenderHTML("octicon-git-pull-request-draft", 16, "text grey")
}
return svg.RenderHTML("octicon-git-pull-request", 16, "text green")
}
if issue.IsClosed {
return svg.RenderHTML("octicon-issue-closed", 16, "text red")
}
return svg.RenderHTML("octicon-issue-opened", 16, "text green")
}
// State returns string representation of issue status. // State returns string representation of issue status.
func (issue *Issue) State() api.StateType { func (issue *Issue) State() api.StateType {
if issue.IsClosed { if issue.IsClosed {

View File

@ -24,7 +24,7 @@ import (
const ScopeSortPrefix = "scope-" const ScopeSortPrefix = "scope-"
// IssuesOptions represents options of an issue. // IssuesOptions represents options of an issue.
type IssuesOptions struct { //nolint:revive // export stutter type IssuesOptions struct { //nolint
Paginator *db.ListOptions Paginator *db.ListOptions
RepoIDs []int64 // overwrites RepoCond if the length is not 0 RepoIDs []int64 // overwrites RepoCond if the length is not 0
AllPublic bool // include also all public repositories AllPublic bool // include also all public repositories

View File

@ -5,6 +5,7 @@ package issues
import ( import (
"context" "context"
"fmt"
"time" "time"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
@ -14,6 +15,20 @@ import (
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/util"
) )
// ErrIssueStopwatchNotExist represents an error that stopwatch is not exist
type ErrIssueStopwatchNotExist struct {
UserID int64
IssueID int64
}
func (err ErrIssueStopwatchNotExist) Error() string {
return fmt.Sprintf("issue stopwatch doesn't exist[uid: %d, issue_id: %d", err.UserID, err.IssueID)
}
func (err ErrIssueStopwatchNotExist) Unwrap() error {
return util.ErrNotExist
}
// Stopwatch represents a stopwatch for time tracking. // Stopwatch represents a stopwatch for time tracking.
type Stopwatch struct { type Stopwatch struct {
ID int64 `xorm:"pk autoincr"` ID int64 `xorm:"pk autoincr"`
@ -40,11 +55,13 @@ func getStopwatch(ctx context.Context, userID, issueID int64) (sw *Stopwatch, ex
return sw, exists, err return sw, exists, err
} }
// UserIDCount is a simple coalition of UserID and Count
type UserStopwatch struct { type UserStopwatch struct {
UserID int64 UserID int64
StopWatches []*Stopwatch StopWatches []*Stopwatch
} }
// GetUIDsAndNotificationCounts between the two provided times
func GetUIDsAndStopwatch(ctx context.Context) ([]*UserStopwatch, error) { func GetUIDsAndStopwatch(ctx context.Context) ([]*UserStopwatch, error) {
sws := []*Stopwatch{} sws := []*Stopwatch{}
if err := db.GetEngine(ctx).Where("issue_id != 0").Find(&sws); err != nil { if err := db.GetEngine(ctx).Where("issue_id != 0").Find(&sws); err != nil {
@ -70,7 +87,7 @@ func GetUIDsAndStopwatch(ctx context.Context) ([]*UserStopwatch, error) {
return res, nil return res, nil
} }
// GetUserStopwatches return list of the user's all stopwatches // GetUserStopwatches return list of all stopwatches of a user
func GetUserStopwatches(ctx context.Context, userID int64, listOptions db.ListOptions) ([]*Stopwatch, error) { func GetUserStopwatches(ctx context.Context, userID int64, listOptions db.ListOptions) ([]*Stopwatch, error) {
sws := make([]*Stopwatch, 0, 8) sws := make([]*Stopwatch, 0, 8)
sess := db.GetEngine(ctx).Where("stopwatch.user_id = ?", userID) sess := db.GetEngine(ctx).Where("stopwatch.user_id = ?", userID)
@ -85,7 +102,7 @@ func GetUserStopwatches(ctx context.Context, userID int64, listOptions db.ListOp
return sws, nil return sws, nil
} }
// CountUserStopwatches return count of the user's all stopwatches // CountUserStopwatches return count of all stopwatches of a user
func CountUserStopwatches(ctx context.Context, userID int64) (int64, error) { func CountUserStopwatches(ctx context.Context, userID int64) (int64, error) {
return db.GetEngine(ctx).Where("user_id = ?", userID).Count(&Stopwatch{}) return db.GetEngine(ctx).Where("user_id = ?", userID).Count(&Stopwatch{})
} }
@ -119,21 +136,43 @@ func HasUserStopwatch(ctx context.Context, userID int64) (exists bool, sw *Stopw
return exists, sw, issue, err return exists, sw, issue, err
} }
// FinishIssueStopwatch if stopwatch exists, then finish it. // FinishIssueStopwatchIfPossible if stopwatch exist then finish it otherwise ignore
func FinishIssueStopwatch(ctx context.Context, user *user_model.User, issue *Issue) (ok bool, err error) { func FinishIssueStopwatchIfPossible(ctx context.Context, user *user_model.User, issue *Issue) error {
sw, exists, err := getStopwatch(ctx, user.ID, issue.ID) _, exists, err := getStopwatch(ctx, user.ID, issue.ID)
if err != nil { if err != nil {
return false, err return err
} else if !exists {
return false, nil
} }
if err = finishIssueStopwatch(ctx, user, issue, sw); err != nil { if !exists {
return false, err return nil
} }
return true, nil return FinishIssueStopwatch(ctx, user, issue)
} }
func finishIssueStopwatch(ctx context.Context, user *user_model.User, issue *Issue, sw *Stopwatch) error { // CreateOrStopIssueStopwatch create an issue stopwatch if it's not exist, otherwise finish it
func CreateOrStopIssueStopwatch(ctx context.Context, user *user_model.User, issue *Issue) error {
_, exists, err := getStopwatch(ctx, user.ID, issue.ID)
if err != nil {
return err
}
if exists {
return FinishIssueStopwatch(ctx, user, issue)
}
return CreateIssueStopwatch(ctx, user, issue)
}
// FinishIssueStopwatch if stopwatch exist then finish it otherwise return an error
func FinishIssueStopwatch(ctx context.Context, user *user_model.User, issue *Issue) error {
sw, exists, err := getStopwatch(ctx, user.ID, issue.ID)
if err != nil {
return err
}
if !exists {
return ErrIssueStopwatchNotExist{
UserID: user.ID,
IssueID: issue.ID,
}
}
// Create tracked time out of the time difference between start date and actual date // Create tracked time out of the time difference between start date and actual date
timediff := time.Now().Unix() - int64(sw.CreatedUnix) timediff := time.Now().Unix() - int64(sw.CreatedUnix)
@ -145,12 +184,14 @@ func finishIssueStopwatch(ctx context.Context, user *user_model.User, issue *Iss
Time: timediff, Time: timediff,
} }
if err := issue.LoadRepo(ctx); err != nil {
return err
}
if err := db.Insert(ctx, tt); err != nil { if err := db.Insert(ctx, tt); err != nil {
return err return err
} }
if err := issue.LoadRepo(ctx); err != nil {
return err
}
if _, err := CreateComment(ctx, &CreateCommentOptions{ if _, err := CreateComment(ctx, &CreateCommentOptions{
Doer: user, Doer: user,
Issue: issue, Issue: issue,
@ -161,65 +202,83 @@ func finishIssueStopwatch(ctx context.Context, user *user_model.User, issue *Iss
}); err != nil { }); err != nil {
return err return err
} }
_, err := db.DeleteByBean(ctx, sw) _, err = db.DeleteByBean(ctx, sw)
return err return err
} }
// CreateIssueStopwatch creates a stopwatch if the issue doesn't have the user's stopwatch. // CreateIssueStopwatch creates a stopwatch if not exist, otherwise return an error
// It also stops any other stopwatch that might be running for the user. func CreateIssueStopwatch(ctx context.Context, user *user_model.User, issue *Issue) error {
func CreateIssueStopwatch(ctx context.Context, user *user_model.User, issue *Issue) (ok bool, err error) { if err := issue.LoadRepo(ctx); err != nil {
{ // if another issue's stopwatch is running: stop it; if this issue has a stopwatch: return an error. return err
exists, otherStopWatch, otherIssue, err := HasUserStopwatch(ctx, user.ID) }
if err != nil {
return false, err // if another stopwatch is running: stop it
} exists, _, otherIssue, err := HasUserStopwatch(ctx, user.ID)
if exists { if err != nil {
if otherStopWatch.IssueID == issue.ID { return err
// don't allow starting stopwatch for the same issue }
return false, nil if exists {
} if err := FinishIssueStopwatch(ctx, user, otherIssue); err != nil {
// stop the other issue's stopwatch return err
if err = finishIssueStopwatch(ctx, user, otherIssue, otherStopWatch); err != nil {
return false, err
}
} }
} }
if err = issue.LoadRepo(ctx); err != nil { // Create stopwatch
return false, err sw := &Stopwatch{
UserID: user.ID,
IssueID: issue.ID,
} }
if err = db.Insert(ctx, &Stopwatch{UserID: user.ID, IssueID: issue.ID}); err != nil {
return false, err if err := db.Insert(ctx, sw); err != nil {
return err
} }
if _, err = CreateComment(ctx, &CreateCommentOptions{
if err := issue.LoadRepo(ctx); err != nil {
return err
}
if _, err := CreateComment(ctx, &CreateCommentOptions{
Doer: user, Doer: user,
Issue: issue, Issue: issue,
Repo: issue.Repo, Repo: issue.Repo,
Type: CommentTypeStartTracking, Type: CommentTypeStartTracking,
}); err != nil { }); err != nil {
return false, err return err
} }
return true, nil
return nil
} }
// CancelStopwatch removes the given stopwatch and logs it into issue's timeline. // CancelStopwatch removes the given stopwatch and logs it into issue's timeline.
func CancelStopwatch(ctx context.Context, user *user_model.User, issue *Issue) (ok bool, err error) { func CancelStopwatch(ctx context.Context, user *user_model.User, issue *Issue) error {
err = db.WithTx(ctx, func(ctx context.Context) error { ctx, committer, err := db.TxContext(ctx)
e := db.GetEngine(ctx) if err != nil {
sw, exists, err := getStopwatch(ctx, user.ID, issue.ID) return err
if err != nil { }
defer committer.Close()
if err := cancelStopwatch(ctx, user, issue); err != nil {
return err
}
return committer.Commit()
}
func cancelStopwatch(ctx context.Context, user *user_model.User, issue *Issue) error {
e := db.GetEngine(ctx)
sw, exists, err := getStopwatch(ctx, user.ID, issue.ID)
if err != nil {
return err
}
if exists {
if _, err := e.Delete(sw); err != nil {
return err return err
} else if !exists {
return nil
} }
if err = issue.LoadRepo(ctx); err != nil { if err := issue.LoadRepo(ctx); err != nil {
return err return err
} }
if _, err = e.Delete(sw); err != nil {
return err if _, err := CreateComment(ctx, &CreateCommentOptions{
}
if _, err = CreateComment(ctx, &CreateCommentOptions{
Doer: user, Doer: user,
Issue: issue, Issue: issue,
Repo: issue.Repo, Repo: issue.Repo,
@ -227,8 +286,6 @@ func CancelStopwatch(ctx context.Context, user *user_model.User, issue *Issue) (
}); err != nil { }); err != nil {
return err return err
} }
ok = true }
return nil return nil
})
return ok, err
} }

View File

@ -10,6 +10,7 @@ import (
issues_model "code.gitea.io/gitea/models/issues" issues_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/timeutil"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -17,22 +18,26 @@ import (
func TestCancelStopwatch(t *testing.T) { func TestCancelStopwatch(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase()) assert.NoError(t, unittest.PrepareTestDatabase())
user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) user1, err := user_model.GetUserByID(db.DefaultContext, 1)
issue1 := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1}) assert.NoError(t, err)
ok, err := issues_model.CancelStopwatch(db.DefaultContext, user1, issue1) issue1, err := issues_model.GetIssueByID(db.DefaultContext, 1)
assert.NoError(t, err)
issue2, err := issues_model.GetIssueByID(db.DefaultContext, 2)
assert.NoError(t, err)
err = issues_model.CancelStopwatch(db.DefaultContext, user1, issue1)
assert.NoError(t, err) assert.NoError(t, err)
assert.True(t, ok)
unittest.AssertNotExistsBean(t, &issues_model.Stopwatch{UserID: user1.ID, IssueID: issue1.ID}) unittest.AssertNotExistsBean(t, &issues_model.Stopwatch{UserID: user1.ID, IssueID: issue1.ID})
unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{Type: issues_model.CommentTypeCancelTracking, PosterID: user1.ID, IssueID: issue1.ID})
ok, err = issues_model.CancelStopwatch(db.DefaultContext, user1, issue1) _ = unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{Type: issues_model.CommentTypeCancelTracking, PosterID: user1.ID, IssueID: issue1.ID})
assert.NoError(t, err)
assert.False(t, ok) assert.NoError(t, issues_model.CancelStopwatch(db.DefaultContext, user1, issue2))
} }
func TestStopwatchExists(t *testing.T) { func TestStopwatchExists(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase()) assert.NoError(t, unittest.PrepareTestDatabase())
assert.True(t, issues_model.StopwatchExists(db.DefaultContext, 1, 1)) assert.True(t, issues_model.StopwatchExists(db.DefaultContext, 1, 1))
assert.False(t, issues_model.StopwatchExists(db.DefaultContext, 1, 2)) assert.False(t, issues_model.StopwatchExists(db.DefaultContext, 1, 2))
} }
@ -53,35 +58,21 @@ func TestHasUserStopwatch(t *testing.T) {
func TestCreateOrStopIssueStopwatch(t *testing.T) { func TestCreateOrStopIssueStopwatch(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase()) assert.NoError(t, unittest.PrepareTestDatabase())
user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4}) user2, err := user_model.GetUserByID(db.DefaultContext, 2)
issue1 := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1}) assert.NoError(t, err)
issue3 := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 3}) org3, err := user_model.GetUserByID(db.DefaultContext, 3)
assert.NoError(t, err)
// create a new stopwatch issue1, err := issues_model.GetIssueByID(db.DefaultContext, 1)
ok, err := issues_model.CreateIssueStopwatch(db.DefaultContext, user4, issue1)
assert.NoError(t, err) assert.NoError(t, err)
assert.True(t, ok) issue2, err := issues_model.GetIssueByID(db.DefaultContext, 2)
unittest.AssertExistsAndLoadBean(t, &issues_model.Stopwatch{UserID: user4.ID, IssueID: issue1.ID})
// should not create a second stopwatch for the same issue
ok, err = issues_model.CreateIssueStopwatch(db.DefaultContext, user4, issue1)
assert.NoError(t, err) assert.NoError(t, err)
assert.False(t, ok)
// on a different issue, it will finish the existing stopwatch and create a new one
ok, err = issues_model.CreateIssueStopwatch(db.DefaultContext, user4, issue3)
assert.NoError(t, err)
assert.True(t, ok)
unittest.AssertNotExistsBean(t, &issues_model.Stopwatch{UserID: user4.ID, IssueID: issue1.ID})
unittest.AssertExistsAndLoadBean(t, &issues_model.Stopwatch{UserID: user4.ID, IssueID: issue3.ID})
// user2 already has a stopwatch in test fixture assert.NoError(t, issues_model.CreateOrStopIssueStopwatch(db.DefaultContext, org3, issue1))
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) sw := unittest.AssertExistsAndLoadBean(t, &issues_model.Stopwatch{UserID: 3, IssueID: 1})
issue2 := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2}) assert.LessOrEqual(t, sw.CreatedUnix, timeutil.TimeStampNow())
ok, err = issues_model.FinishIssueStopwatch(db.DefaultContext, user2, issue2)
assert.NoError(t, err) assert.NoError(t, issues_model.CreateOrStopIssueStopwatch(db.DefaultContext, user2, issue2))
assert.True(t, ok) unittest.AssertNotExistsBean(t, &issues_model.Stopwatch{UserID: 2, IssueID: 2})
unittest.AssertNotExistsBean(t, &issues_model.Stopwatch{UserID: user2.ID, IssueID: issue2.ID}) unittest.AssertExistsAndLoadBean(t, &issues_model.TrackedTime{UserID: 2, IssueID: 2})
unittest.AssertExistsAndLoadBean(t, &issues_model.TrackedTime{UserID: user2.ID, IssueID: issue2.ID})
ok, err = issues_model.FinishIssueStopwatch(db.DefaultContext, user2, issue2)
assert.NoError(t, err)
assert.False(t, ok)
} }

View File

@ -1,6 +1,7 @@
// Copyright 2022 The Gitea Authors. All rights reserved. // Copyright 2022 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
//nolint:forbidigo
package base package base
import ( import (
@ -105,7 +106,7 @@ func MainTest(m *testing.M) {
giteaConf := os.Getenv("GITEA_CONF") giteaConf := os.Getenv("GITEA_CONF")
if giteaConf == "" { if giteaConf == "" {
giteaConf = filepath.Join(filepath.Dir(setting.AppPath), "tests/sqlite.ini") giteaConf = filepath.Join(filepath.Dir(setting.AppPath), "tests/sqlite.ini")
_, _ = fmt.Fprintf(os.Stderr, "Environment variable $GITEA_CONF not set - defaulting to %s\n", giteaConf) fmt.Printf("Environment variable $GITEA_CONF not set - defaulting to %s\n", giteaConf)
} }
if !filepath.IsAbs(giteaConf) { if !filepath.IsAbs(giteaConf) {
@ -133,7 +134,7 @@ func MainTest(m *testing.M) {
exitStatus := m.Run() exitStatus := m.Run()
if err := removeAllWithRetry(setting.RepoRootPath); err != nil { if err := removeAllWithRetry(setting.RepoRootPath); err != nil {
_, _ = fmt.Fprintf(os.Stderr, "os.RemoveAll: %v\n", err) fmt.Fprintf(os.Stderr, "os.RemoveAll: %v\n", err)
} }
os.Exit(exitStatus) os.Exit(exitStatus)
} }

View File

@ -1,7 +1,7 @@
// Copyright 2019 The Gitea Authors. All rights reserved. // Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_10 package v1_10 //nolint
import ( import (
"net/url" "net/url"

View File

@ -1,7 +1,7 @@
// Copyright 2019 The Gitea Authors. All rights reserved. // Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_10 package v1_10 //nolint
import ( import (
"xorm.io/xorm" "xorm.io/xorm"

View File

@ -1,7 +1,7 @@
// Copyright 2019 The Gitea Authors. All rights reserved. // Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_10 package v1_10 //nolint
import ( import (
"crypto/sha1" "crypto/sha1"

View File

@ -1,7 +1,7 @@
// Copyright 2019 The Gitea Authors. All rights reserved. // Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_10 package v1_10 //nolint
import "xorm.io/xorm" import "xorm.io/xorm"

View File

@ -1,7 +1,7 @@
// Copyright 2019 The Gitea Authors. All rights reserved. // Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_10 package v1_10 //nolint
import "xorm.io/xorm" import "xorm.io/xorm"

View File

@ -1,7 +1,7 @@
// Copyright 2019 The Gitea Authors. All rights reserved. // Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_10 package v1_10 //nolint
import "xorm.io/xorm" import "xorm.io/xorm"

View File

@ -1,7 +1,7 @@
// Copyright 2019 The Gitea Authors. All rights reserved. // Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_10 package v1_10 //nolint
import ( import (
"xorm.io/builder" "xorm.io/builder"

View File

@ -1,7 +1,7 @@
// Copyright 2019 The Gitea Authors. All rights reserved. // Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_10 package v1_10 //nolint
import "xorm.io/xorm" import "xorm.io/xorm"

View File

@ -1,7 +1,7 @@
// Copyright 2019 The Gitea Authors. All rights reserved. // Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_10 package v1_10 //nolint
import "xorm.io/xorm" import "xorm.io/xorm"

View File

@ -1,7 +1,7 @@
// Copyright 2019 The Gitea Authors. All rights reserved. // Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_10 package v1_10 //nolint
import "xorm.io/xorm" import "xorm.io/xorm"

View File

@ -1,7 +1,7 @@
// Copyright 2019 The Gitea Authors. All rights reserved. // Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_10 package v1_10 //nolint
import ( import (
"path/filepath" "path/filepath"

View File

@ -1,7 +1,7 @@
// Copyright 2019 The Gitea Authors. All rights reserved. // Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_10 package v1_10 //nolint
import "xorm.io/xorm" import "xorm.io/xorm"

View File

@ -1,7 +1,7 @@
// Copyright 2019 The Gitea Authors. All rights reserved. // Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_10 package v1_10 //nolint
import "xorm.io/xorm" import "xorm.io/xorm"

View File

@ -1,7 +1,7 @@
// Copyright 2019 The Gitea Authors. All rights reserved. // Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_10 package v1_10 //nolint
import ( import (
"code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/timeutil"

View File

@ -1,7 +1,7 @@
// Copyright 2019 The Gitea Authors. All rights reserved. // Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_11 package v1_11 //nolint
import ( import (
"code.gitea.io/gitea/models/migrations/base" "code.gitea.io/gitea/models/migrations/base"

View File

@ -1,7 +1,7 @@
// Copyright 2019 The Gitea Authors. All rights reserved. // Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_11 package v1_11 //nolint
import ( import (
"xorm.io/xorm" "xorm.io/xorm"

View File

@ -1,7 +1,7 @@
// Copyright 2019 The Gitea Authors. All rights reserved. // Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_11 package v1_11 //nolint
import ( import (
"code.gitea.io/gitea/models/migrations/base" "code.gitea.io/gitea/models/migrations/base"

View File

@ -1,7 +1,7 @@
// Copyright 2019 The Gitea Authors. All rights reserved. // Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_11 package v1_11 //nolint
import ( import (
"xorm.io/xorm" "xorm.io/xorm"

View File

@ -1,7 +1,7 @@
// Copyright 2019 The Gitea Authors. All rights reserved. // Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_11 package v1_11 //nolint
import ( import (
"xorm.io/xorm" "xorm.io/xorm"

View File

@ -1,7 +1,7 @@
// Copyright 2019 The Gitea Authors. All rights reserved. // Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_11 package v1_11 //nolint
import ( import (
"xorm.io/xorm" "xorm.io/xorm"

View File

@ -1,7 +1,7 @@
// Copyright 2019 The Gitea Authors. All rights reserved. // Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_11 package v1_11 //nolint
import ( import (
"xorm.io/xorm" "xorm.io/xorm"

View File

@ -1,7 +1,7 @@
// Copyright 2019 The Gitea Authors. All rights reserved. // Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_11 package v1_11 //nolint
import ( import (
"xorm.io/xorm" "xorm.io/xorm"

View File

@ -1,7 +1,7 @@
// Copyright 2019 The Gitea Authors. All rights reserved. // Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_11 package v1_11 //nolint
import ( import (
"xorm.io/xorm" "xorm.io/xorm"

View File

@ -1,7 +1,7 @@
// Copyright 2019 The Gitea Authors. All rights reserved. // Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_11 package v1_11 //nolint
import ( import (
"fmt" "fmt"

View File

@ -1,12 +1,12 @@
// Copyright 2019 The Gitea Authors. All rights reserved. // Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_11 package v1_11 //nolint
import ( import (
"fmt"
"path/filepath" "path/filepath"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/util"
@ -31,7 +31,7 @@ func RemoveAttachmentMissedRepo(x *xorm.Engine) error {
for i := 0; i < len(attachments); i++ { for i := 0; i < len(attachments); i++ {
uuid := attachments[i].UUID uuid := attachments[i].UUID
if err = util.RemoveAll(filepath.Join(setting.Attachment.Storage.Path, uuid[0:1], uuid[1:2], uuid)); err != nil { if err = util.RemoveAll(filepath.Join(setting.Attachment.Storage.Path, uuid[0:1], uuid[1:2], uuid)); err != nil {
log.Warn("Unable to remove attachment file by UUID %s: %v", uuid, err) fmt.Printf("Error: %v", err) //nolint:forbidigo
} }
} }

View File

@ -1,7 +1,7 @@
// Copyright 2019 The Gitea Authors. All rights reserved. // Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_11 package v1_11 //nolint
import ( import (
"fmt" "fmt"

View File

@ -1,7 +1,7 @@
// Copyright 2019 The Gitea Authors. All rights reserved. // Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_11 package v1_11 //nolint
import ( import (
"net/url" "net/url"

View File

@ -1,7 +1,7 @@
// Copyright 2019 The Gitea Authors. All rights reserved. // Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_11 package v1_11 //nolint
import ( import (
"crypto/md5" "crypto/md5"

View File

@ -1,7 +1,7 @@
// Copyright 2019 The Gitea Authors. All rights reserved. // Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_11 package v1_11 //nolint
import ( import (
"xorm.io/xorm" "xorm.io/xorm"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_12 package v1_12 //nolint
import ( import (
"xorm.io/xorm" "xorm.io/xorm"

View File

@ -1,7 +1,7 @@
// Copyright 2019 The Gitea Authors. All rights reserved. // Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_12 package v1_12 //nolint
import ( import (
"xorm.io/xorm" "xorm.io/xorm"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_12 package v1_12 //nolint
import ( import (
"xorm.io/xorm" "xorm.io/xorm"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_12 package v1_12 //nolint
import ( import (
"xorm.io/xorm" "xorm.io/xorm"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_12 package v1_12 //nolint
import "xorm.io/xorm" import "xorm.io/xorm"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_12 package v1_12 //nolint
import ( import (
"xorm.io/xorm" "xorm.io/xorm"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_12 package v1_12 //nolint
import ( import (
"xorm.io/xorm" "xorm.io/xorm"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_12 package v1_12 //nolint
import ( import (
"xorm.io/xorm" "xorm.io/xorm"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_12 package v1_12 //nolint
import ( import (
"fmt" "fmt"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_12 package v1_12 //nolint
import ( import (
"xorm.io/builder" "xorm.io/builder"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_12 package v1_12 //nolint
import ( import (
"fmt" "fmt"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_12 package v1_12 //nolint
import ( import (
"fmt" "fmt"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_12 package v1_12 //nolint
import ( import (
"xorm.io/xorm" "xorm.io/xorm"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_12 package v1_12 //nolint
import ( import (
"code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/json"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_12 package v1_12 //nolint
import ( import (
"fmt" "fmt"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_12 package v1_12 //nolint
import ( import (
"fmt" "fmt"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_12 package v1_12 //nolint
import "xorm.io/xorm" import "xorm.io/xorm"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_12 package v1_12 //nolint
import ( import (
"fmt" "fmt"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_12 package v1_12 //nolint
import ( import (
"fmt" "fmt"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_12 package v1_12 //nolint
import ( import (
"fmt" "fmt"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_12 package v1_12 //nolint
import ( import (
"xorm.io/xorm" "xorm.io/xorm"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_12 package v1_12 //nolint
import ( import (
"fmt" "fmt"

View File

@ -1,7 +1,7 @@
// Copyright 2019 The Gitea Authors. All rights reserved. // Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_12 package v1_12 //nolint
import ( import (
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_13 package v1_13 //nolint
import ( import (
"fmt" "fmt"
@ -21,7 +21,12 @@ func FixLanguageStatsToSaveSize(x *xorm.Engine) error {
// RepoIndexerType specifies the repository indexer type // RepoIndexerType specifies the repository indexer type
type RepoIndexerType int type RepoIndexerType int
const RepoIndexerTypeStats RepoIndexerType = 1 const (
// RepoIndexerTypeCode code indexer - 0
RepoIndexerTypeCode RepoIndexerType = iota //nolint:unused
// RepoIndexerTypeStats repository stats indexer - 1
RepoIndexerTypeStats
)
// RepoIndexerStatus see models/repo_indexer.go // RepoIndexerStatus see models/repo_indexer.go
type RepoIndexerStatus struct { type RepoIndexerStatus struct {

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_13 package v1_13 //nolint
import ( import (
"fmt" "fmt"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_13 package v1_13 //nolint
import ( import (
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_13 package v1_13 //nolint
import ( import (
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_13 package v1_13 //nolint
import ( import (
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_13 package v1_13 //nolint
import ( import (
"fmt" "fmt"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_13 package v1_13 //nolint
import ( import (
"code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/timeutil"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_13 package v1_13 //nolint
import ( import (
"code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/timeutil"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_13 package v1_13 //nolint
import ( import (
"xorm.io/xorm" "xorm.io/xorm"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_13 package v1_13 //nolint
import ( import (
"fmt" "fmt"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_13 package v1_13 //nolint
import ( import (
"code.gitea.io/gitea/models/migrations/base" "code.gitea.io/gitea/models/migrations/base"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_13 package v1_13 //nolint
import ( import (
"context" "context"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_13 package v1_13 //nolint
import "xorm.io/xorm" import "xorm.io/xorm"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_13 package v1_13 //nolint
import ( import (
"xorm.io/xorm" "xorm.io/xorm"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_13 package v1_13 //nolint
import ( import (
"code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/timeutil"

View File

@ -1,7 +1,7 @@
// Copyright 2021 The Gitea Authors. All rights reserved. // Copyright 2021 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_14 package v1_14 //nolint
import ( import (
"testing" "testing"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_14 package v1_14 //nolint
import ( import (
"fmt" "fmt"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_14 package v1_14 //nolint
import ( import (
"fmt" "fmt"

View File

@ -1,13 +1,24 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_14 package v1_14 //nolint
import ( import (
"xorm.io/xorm" "xorm.io/xorm"
) )
func FixRepoTopics(x *xorm.Engine) error { func FixRepoTopics(x *xorm.Engine) error {
type Topic struct { //nolint:unused
ID int64 `xorm:"pk autoincr"`
Name string `xorm:"UNIQUE VARCHAR(25)"`
RepoCount int
}
type RepoTopic struct { //nolint:unused
RepoID int64 `xorm:"pk"`
TopicID int64 `xorm:"pk"`
}
type Repository struct { type Repository struct {
ID int64 `xorm:"pk autoincr"` ID int64 `xorm:"pk autoincr"`
Topics []string `xorm:"TEXT JSON"` Topics []string `xorm:"TEXT JSON"`

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_14 package v1_14 //nolint
import ( import (
"errors" "errors"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_14 package v1_14 //nolint
import ( import (
"code.gitea.io/gitea/models/migrations/base" "code.gitea.io/gitea/models/migrations/base"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_14 package v1_14 //nolint
import ( import (
"xorm.io/xorm" "xorm.io/xorm"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_14 package v1_14 //nolint
import ( import (
"context" "context"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_14 package v1_14 //nolint
import ( import (
"code.gitea.io/gitea/models/migrations/base" "code.gitea.io/gitea/models/migrations/base"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_14 package v1_14 //nolint
import ( import (
"code.gitea.io/gitea/models/migrations/base" "code.gitea.io/gitea/models/migrations/base"

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved. // Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
package v1_14 package v1_14 //nolint
import ( import (
"fmt" "fmt"

Some files were not shown because too many files have changed in this diff Show More