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

View File

@ -45,10 +45,6 @@ linters:
desc: do not use the ini package, use gitea's config system instead
- pkg: gitea.com/go-chi/cache
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:
disabled-checks:
- ifElseChain
@ -87,10 +83,6 @@ linters:
- name: unreachable-code
- name: var-declaration
- 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:
checks:
- all

View File

@ -26,18 +26,18 @@ COMMA := ,
XGO_VERSION := go-1.24.x
AIR_PACKAGE ?= github.com/air-verse/air@v1
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v3/cmd/editorconfig-checker@v3
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.8.0
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.1.6
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v3/cmd/editorconfig-checker@v3.2.1
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.7.0
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
MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.7.0
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.32.3
MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.6.0
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.31.0
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1
GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1
ACTIONLINT_PACKAGE ?= github.com/rhysd/actionlint/cmd/actionlint@v1
GOPLS_PACKAGE ?= golang.org/x/tools/gopls@v0.19.1
GOPLS_MODERNIZE_PACKAGE ?= golang.org/x/tools/gopls/internal/analysis/modernize/cmd/modernize@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.0
DOCKER_IMAGE ?= gitea/gitea
DOCKER_TAG ?= latest
@ -81,6 +81,7 @@ ifeq ($(RACE_ENABLED),true)
endif
STORED_VERSION_FILE := VERSION
HUGO_VERSION ?= 0.111.3
GITHUB_REF_TYPE ?= branch
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 {
args = []string{"**"}
}
pat := make([]glob.Glob, len(args))
for i := range args {
if pat[i], err = glob.Compile(args[i], '/'); err != nil {
return nil, fmt.Errorf("invalid glob patterh %q: %w", args[i], err)
if g, err := glob.Compile(args[i], '/'); err != nil {
return nil, fmt.Errorf("'%s': Invalid glob pattern: %w", args[i], err)
} else { //nolint:revive
pat[i] = g
}
}
return pat, nil

View File

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

View File

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

View File

@ -58,14 +58,14 @@ func TestAggregateJobStatus(t *testing.T) {
{[]Status{StatusCancelled, StatusRunning}, StatusCancelled},
{[]Status{StatusCancelled, StatusBlocked}, StatusCancelled},
// failure with other status, usually fail fast, but "running" wins to match GitHub's behavior
// 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.
// failure with other status, fail fast
// Should "running" win? Maybe no: old code does make "running" win, but GitHub does fail fast.
{[]Status{StatusFailure}, StatusFailure},
{[]Status{StatusFailure, StatusSuccess}, StatusFailure},
{[]Status{StatusFailure, StatusSkipped}, StatusFailure},
{[]Status{StatusFailure, StatusCancelled}, StatusCancelled},
{[]Status{StatusFailure, StatusWaiting}, StatusFailure},
{[]Status{StatusFailure, StatusRunning}, StatusRunning},
{[]Status{StatusFailure, StatusRunning}, StatusFailure},
{[]Status{StatusFailure, StatusBlocked}, StatusFailure},
// skipped with other status

View File

@ -278,13 +278,14 @@ func CreateTaskForRunner(ctx context.Context, runner *ActionRunner) (*ActionTask
return nil, false, err
}
parsedWorkflows, err := jobparser.Parse(job.WorkflowPayload)
if err != nil {
var workflowJob *jobparser.Job
if gots, err := jobparser.Parse(job.WorkflowPayload); err != nil {
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)
} else { //nolint:revive
_, workflowJob = gots[0].Job()
}
_, workflowJob := parsedWorkflows[0].Job()
if _, err := e.Insert(task); err != nil {
return nil, false, err

View File

@ -6,7 +6,6 @@ package activities
import (
"context"
"fmt"
"html/template"
"net/url"
"strconv"
@ -17,7 +16,6 @@ import (
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/svg"
"code.gitea.io/gitea/modules/timeutil"
"xorm.io/builder"
@ -381,22 +379,6 @@ func (n *Notification) Link(ctx context.Context) string {
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
func (n *Notification) APIURL() string {
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)
}
if err != nil {
log.Debug("AddGPGKey CheckArmoredDetachedSignature failed: %v", err)
log.Error("Unable to validate token signature. Error: %v", err)
return nil, ErrGPGInvalidTokenSignature{
ID: ekeys[0].PrimaryKey.KeyIdString(),
Wrapped: err,

View File

@ -85,7 +85,7 @@ func VerifyGPGKey(ctx context.Context, ownerID int64, keyID, token, signature st
}
if signer == nil {
log.Debug("VerifyGPGKey failed: no signer")
log.Error("Unable to validate token signature. Error: %v", err)
return "", ErrGPGInvalidTokenSignature{
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.
switch pkey.Type() {
case ssh.KeyAlgoDSA: //nolint:staticcheck // it's deprecated
case ssh.KeyAlgoDSA: //nolint
rawPub := struct {
Name string
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
// see https://github.com/PowerShell/PowerShell/issues/5974
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{
Fingerprint: key.Fingerprint,
}

View File

@ -15,7 +15,7 @@ import (
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"`
TokenHash string
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)
}
// 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 {
sess := xormEngine.NewSession()
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
// 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(
'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
// 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 {
_ = conn.Close()
return nil, err

View File

@ -518,7 +518,7 @@ func updateTeamWhitelist(ctx context.Context, repo *repo_model.Repository, curre
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 {
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/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/svg"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
@ -443,30 +442,6 @@ func (issue *Issue) PatchURL() string {
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.
func (issue *Issue) State() api.StateType {
if issue.IsClosed {

View File

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

View File

@ -5,6 +5,7 @@ package issues
import (
"context"
"fmt"
"time"
"code.gitea.io/gitea/models/db"
@ -14,6 +15,20 @@ import (
"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.
type Stopwatch struct {
ID int64 `xorm:"pk autoincr"`
@ -40,11 +55,13 @@ func getStopwatch(ctx context.Context, userID, issueID int64) (sw *Stopwatch, ex
return sw, exists, err
}
// UserIDCount is a simple coalition of UserID and Count
type UserStopwatch struct {
UserID int64
StopWatches []*Stopwatch
}
// GetUIDsAndNotificationCounts between the two provided times
func GetUIDsAndStopwatch(ctx context.Context) ([]*UserStopwatch, error) {
sws := []*Stopwatch{}
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
}
// 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) {
sws := make([]*Stopwatch, 0, 8)
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
}
// 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) {
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
}
// FinishIssueStopwatch if stopwatch exists, then finish it.
func FinishIssueStopwatch(ctx context.Context, user *user_model.User, issue *Issue) (ok bool, err error) {
sw, exists, err := getStopwatch(ctx, user.ID, issue.ID)
// FinishIssueStopwatchIfPossible if stopwatch exist then finish it otherwise ignore
func FinishIssueStopwatchIfPossible(ctx context.Context, user *user_model.User, issue *Issue) error {
_, exists, err := getStopwatch(ctx, user.ID, issue.ID)
if err != nil {
return false, err
} else if !exists {
return false, nil
return err
}
if err = finishIssueStopwatch(ctx, user, issue, sw); err != nil {
return false, err
if !exists {
return nil
}
return FinishIssueStopwatch(ctx, user, issue)
}
// 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,
}
return true, nil
}
func finishIssueStopwatch(ctx context.Context, user *user_model.User, issue *Issue, sw *Stopwatch) error {
// Create tracked time out of the time difference between start date and actual date
timediff := time.Now().Unix() - int64(sw.CreatedUnix)
@ -145,12 +184,14 @@ func finishIssueStopwatch(ctx context.Context, user *user_model.User, issue *Iss
Time: timediff,
}
if err := issue.LoadRepo(ctx); err != nil {
return err
}
if err := db.Insert(ctx, tt); err != nil {
return err
}
if err := issue.LoadRepo(ctx); err != nil {
return err
}
if _, err := CreateComment(ctx, &CreateCommentOptions{
Doer: user,
Issue: issue,
@ -161,65 +202,83 @@ func finishIssueStopwatch(ctx context.Context, user *user_model.User, issue *Iss
}); err != nil {
return err
}
_, err := db.DeleteByBean(ctx, sw)
_, err = db.DeleteByBean(ctx, sw)
return err
}
// CreateIssueStopwatch creates a stopwatch if the issue doesn't have the user's stopwatch.
// It also stops any other stopwatch that might be running for the user.
func CreateIssueStopwatch(ctx context.Context, user *user_model.User, issue *Issue) (ok bool, err error) {
{ // if another issue's stopwatch is running: stop it; if this issue has a stopwatch: return an error.
exists, otherStopWatch, otherIssue, err := HasUserStopwatch(ctx, user.ID)
// CreateIssueStopwatch creates a stopwatch if not exist, otherwise return an error
func CreateIssueStopwatch(ctx context.Context, user *user_model.User, issue *Issue) error {
if err := issue.LoadRepo(ctx); err != nil {
return err
}
// if another stopwatch is running: stop it
exists, _, otherIssue, err := HasUserStopwatch(ctx, user.ID)
if err != nil {
return false, err
return err
}
if exists {
if otherStopWatch.IssueID == issue.ID {
// don't allow starting stopwatch for the same issue
return false, nil
}
// stop the other issue's stopwatch
if err = finishIssueStopwatch(ctx, user, otherIssue, otherStopWatch); err != nil {
return false, err
}
if err := FinishIssueStopwatch(ctx, user, otherIssue); err != nil {
return err
}
}
if err = issue.LoadRepo(ctx); err != nil {
return false, err
// Create stopwatch
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,
Issue: issue,
Repo: issue.Repo,
Type: CommentTypeStartTracking,
}); err != nil {
return false, err
return err
}
return true, nil
return nil
}
// 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) {
err = db.WithTx(ctx, func(ctx context.Context) error {
func CancelStopwatch(ctx context.Context, user *user_model.User, issue *Issue) error {
ctx, committer, err := db.TxContext(ctx)
if err != nil {
return err
}
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
} else if !exists {
return nil
}
if err = issue.LoadRepo(ctx); err != nil {
if exists {
if _, err := e.Delete(sw); err != nil {
return err
}
if _, err = e.Delete(sw); err != nil {
if err := issue.LoadRepo(ctx); err != nil {
return err
}
if _, err = CreateComment(ctx, &CreateCommentOptions{
if _, err := CreateComment(ctx, &CreateCommentOptions{
Doer: user,
Issue: issue,
Repo: issue.Repo,
@ -227,8 +286,6 @@ func CancelStopwatch(ctx context.Context, user *user_model.User, issue *Issue) (
}); err != nil {
return err
}
ok = true
return nil
})
return ok, err
}
return nil
}

View File

@ -10,6 +10,7 @@ import (
issues_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/timeutil"
"github.com/stretchr/testify/assert"
)
@ -17,22 +18,26 @@ import (
func TestCancelStopwatch(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
issue1 := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1})
ok, err := issues_model.CancelStopwatch(db.DefaultContext, user1, issue1)
user1, err := user_model.GetUserByID(db.DefaultContext, 1)
assert.NoError(t, err)
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.True(t, ok)
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)
assert.NoError(t, err)
assert.False(t, ok)
_ = unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{Type: issues_model.CommentTypeCancelTracking, PosterID: user1.ID, IssueID: issue1.ID})
assert.NoError(t, issues_model.CancelStopwatch(db.DefaultContext, user1, issue2))
}
func TestStopwatchExists(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
assert.True(t, issues_model.StopwatchExists(db.DefaultContext, 1, 1))
assert.False(t, issues_model.StopwatchExists(db.DefaultContext, 1, 2))
}
@ -53,35 +58,21 @@ func TestHasUserStopwatch(t *testing.T) {
func TestCreateOrStopIssueStopwatch(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase())
user4 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
issue1 := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1})
issue3 := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 3})
user2, err := user_model.GetUserByID(db.DefaultContext, 2)
assert.NoError(t, err)
org3, err := user_model.GetUserByID(db.DefaultContext, 3)
assert.NoError(t, err)
// create a new stopwatch
ok, err := issues_model.CreateIssueStopwatch(db.DefaultContext, user4, issue1)
issue1, err := issues_model.GetIssueByID(db.DefaultContext, 1)
assert.NoError(t, err)
assert.True(t, ok)
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)
issue2, err := issues_model.GetIssueByID(db.DefaultContext, 2)
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
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
issue2 := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2})
ok, err = issues_model.FinishIssueStopwatch(db.DefaultContext, user2, issue2)
assert.NoError(t, err)
assert.True(t, ok)
unittest.AssertNotExistsBean(t, &issues_model.Stopwatch{UserID: user2.ID, IssueID: issue2.ID})
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)
assert.NoError(t, issues_model.CreateOrStopIssueStopwatch(db.DefaultContext, org3, issue1))
sw := unittest.AssertExistsAndLoadBean(t, &issues_model.Stopwatch{UserID: 3, IssueID: 1})
assert.LessOrEqual(t, sw.CreatedUnix, timeutil.TimeStampNow())
assert.NoError(t, issues_model.CreateOrStopIssueStopwatch(db.DefaultContext, user2, issue2))
unittest.AssertNotExistsBean(t, &issues_model.Stopwatch{UserID: 2, IssueID: 2})
unittest.AssertExistsAndLoadBean(t, &issues_model.TrackedTime{UserID: 2, IssueID: 2})
}

View File

@ -1,6 +1,7 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
//nolint:forbidigo
package base
import (
@ -105,7 +106,7 @@ func MainTest(m *testing.M) {
giteaConf := os.Getenv("GITEA_CONF")
if giteaConf == "" {
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) {
@ -133,7 +134,7 @@ func MainTest(m *testing.M) {
exitStatus := m.Run()
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)
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,12 +1,12 @@
// Copyright 2019 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package v1_11
package v1_11 //nolint
import (
"fmt"
"path/filepath"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
@ -31,7 +31,7 @@ func RemoveAttachmentMissedRepo(x *xorm.Engine) error {
for i := 0; i < len(attachments); i++ {
uuid := attachments[i].UUID
if err = util.RemoveAll(filepath.Join(setting.Attachment.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.
// SPDX-License-Identifier: MIT
package v1_11
package v1_11 //nolint
import (
"fmt"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package v1_13
package v1_13 //nolint
import (
"fmt"
@ -21,7 +21,12 @@ func FixLanguageStatsToSaveSize(x *xorm.Engine) error {
// RepoIndexerType specifies the repository indexer type
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
type RepoIndexerStatus struct {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,13 +1,24 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package v1_14
package v1_14 //nolint
import (
"xorm.io/xorm"
)
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 {
ID int64 `xorm:"pk autoincr"`
Topics []string `xorm:"TEXT JSON"`

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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