Merge remote-tracking branch 'upstream/v11.0/forgejo' into v11.0/forgejo
Some checks failed
/ release (push) Has been cancelled
testing / backend-checks (push) Has been cancelled
testing / frontend-checks (push) Has been cancelled
testing / test-unit (push) Has been cancelled
testing / test-e2e (push) Has been cancelled
testing / test-remote-cacher (redis) (push) Has been cancelled
testing / test-remote-cacher (valkey) (push) Has been cancelled
testing / test-remote-cacher (garnet) (push) Has been cancelled
testing / test-remote-cacher (redict) (push) Has been cancelled
testing / test-mysql (push) Has been cancelled
testing / test-pgsql (push) Has been cancelled
testing / test-sqlite (push) Has been cancelled
testing / security-check (push) Has been cancelled

This commit is contained in:
Minecon724 2025-06-18 20:22:50 +02:00
commit e875f8c105
Signed by: Minecon724
GPG key ID: A02E6E67AB961189
27 changed files with 187 additions and 43 deletions

8
go.mod
View file

@ -2,7 +2,7 @@ module forgejo.org
go 1.24
toolchain go1.24.1
toolchain go1.24.3
require (
code.forgejo.org/f3/gof3/v3 v3.10.6
@ -25,7 +25,7 @@ require (
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.7.2
github.com/alecthomas/chroma/v2 v2.15.0
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
github.com/blevesearch/bleve/v2 v2.5.1
github.com/blevesearch/bleve/v2 v2.5.2
github.com/buildkite/terminal-to-html/v3 v3.16.8
github.com/caddyserver/certmagic v0.22.2
github.com/chi-middleware/proxy v1.1.1
@ -146,13 +146,13 @@ require (
github.com/blevesearch/zapx/v13 v13.4.2 // indirect
github.com/blevesearch/zapx/v14 v14.4.2 // indirect
github.com/blevesearch/zapx/v15 v15.4.2 // indirect
github.com/blevesearch/zapx/v16 v16.2.3 // indirect
github.com/blevesearch/zapx/v16 v16.2.4 // indirect
github.com/boombuler/barcode v1.0.1 // indirect
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 // indirect
github.com/caddyserver/zerossl v0.1.3 // indirect
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cloudflare/circl v1.3.8 // indirect
github.com/cloudflare/circl v1.6.1 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
github.com/cyphar/filepath-securejoin v0.3.6 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect

12
go.sum
View file

@ -87,8 +87,8 @@ github.com/bits-and-blooms/bitset v1.22.0 h1:Tquv9S8+SGaS3EhyA+up3FXzmkhxPGjQQCk
github.com/bits-and-blooms/bitset v1.22.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb h1:m935MPodAbYS46DG4pJSv7WO+VECIWUQ7OJYSoTrMh4=
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI=
github.com/blevesearch/bleve/v2 v2.5.1 h1:cc/O++W2Hcjp1SU5ETHeE+QYWv2oV88ldYEPowdmg8M=
github.com/blevesearch/bleve/v2 v2.5.1/go.mod h1:9g/wnbWKm9AgXrU8Ecqi+IDdqjUHWymwkQRDg+5tafU=
github.com/blevesearch/bleve/v2 v2.5.2 h1:Ab0r0MODV2C5A6BEL87GqLBySqp/s9xFgceCju6BQk8=
github.com/blevesearch/bleve/v2 v2.5.2/go.mod h1:5Dj6dUQxZM6aqYT3eutTD/GpWKGFSsV8f7LDidFbwXo=
github.com/blevesearch/bleve_index_api v1.2.8 h1:Y98Pu5/MdlkRyLM0qDHostYo7i+Vv1cDNhqTeR4Sy6Y=
github.com/blevesearch/bleve_index_api v1.2.8/go.mod h1:rKQDl4u51uwafZxFrPD1R7xFOwKnzZW7s/LSeK4lgo0=
github.com/blevesearch/geo v0.2.3 h1:K9/vbGI9ehlXdxjxDRJtoAMt7zGAsMIzc6n8zWcwnhg=
@ -121,8 +121,8 @@ github.com/blevesearch/zapx/v14 v14.4.2 h1:2SGHakVKd+TrtEqpfeq8X+So5PShQ5nW6GNxT
github.com/blevesearch/zapx/v14 v14.4.2/go.mod h1:rz0XNb/OZSMjNorufDGSpFpjoFKhXmppH9Hi7a877D8=
github.com/blevesearch/zapx/v15 v15.4.2 h1:sWxpDE0QQOTjyxYbAVjt3+0ieu8NCE0fDRaFxEsp31k=
github.com/blevesearch/zapx/v15 v15.4.2/go.mod h1:1pssev/59FsuWcgSnTa0OeEpOzmhtmr/0/11H0Z8+Nw=
github.com/blevesearch/zapx/v16 v16.2.3 h1:7Y0r+a3diEvlazsncexq1qoFOcBd64xwMS7aDm4lo1s=
github.com/blevesearch/zapx/v16 v16.2.3/go.mod h1:wVJ+GtURAaRG9KQAMNYyklq0egV+XJlGcXNCE0OFjjA=
github.com/blevesearch/zapx/v16 v16.2.4 h1:tGgfvleXTAkwsD5mEzgM3zCS/7pgocTCnO1oyAUjlww=
github.com/blevesearch/zapx/v16 v16.2.4/go.mod h1:Rti/REtuuMmzwsI8/C/qIzRaEoSK/wiFYw5e5ctUKKs=
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/boombuler/barcode v1.0.1 h1:NDBbPmhS+EqABEs5Kg3n/5ZNjy73Pz7SIV+KCeqyXcs=
github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
@ -150,8 +150,8 @@ github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moA
github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ=
github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk=
github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
github.com/cloudflare/circl v1.3.8 h1:j+V8jJt09PoeMFIu2uh5JUyEaIHTXVOHslFoLNAKqwI=
github.com/cloudflare/circl v1.3.8/go.mod h1:PDRU+oXvdD7KCtgKxW95M5Z8BpSCJXQORiZFnBQS5QU=
github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=

View file

@ -69,6 +69,9 @@ func (l *XORMLogBridge) Warn(v ...any) {
// Warnf show warning log
func (l *XORMLogBridge) Warnf(format string, v ...any) {
if format == "Table %s Column %s db default is %s, struct default is %s" || format == "Table %s Column %s db nullable is %v, struct nullable is %v" {
return
}
l.Log(stackLevel, log.WARN, format, v...)
}

View file

@ -0,0 +1,17 @@
-
id: 1001
run_id: 792
runner_id: 1
repo_id: 4
owner_id: 1
commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0
storage_path: "27/5/1730330775594233150.chunk"
file_size: 693147180559
file_compressed_size: 693147180559
content_encoding: "application/zip"
artifact_path: "big-file.zip"
artifact_name: "big-file"
status: 4
created_unix: 1730330775
updated_unix: 1730330775
expired_unix: 1738106775

View file

@ -649,8 +649,11 @@ func (c *Comment) LoadAssigneeUserAndTeam(ctx context.Context) error {
if c.Issue.Repo.Owner.IsOrganization() {
c.AssigneeTeam, err = organization.GetTeamByID(ctx, c.AssigneeTeamID)
if err != nil && !organization.IsErrTeamNotExist(err) {
return err
if err != nil {
if !organization.IsErrTeamNotExist(err) {
return err
}
c.AssigneeTeam = organization.NewGhostTeam()
}
}
}

View file

@ -0,0 +1,5 @@
-
id: 1000
uid: 4
org_id: 22
is_public: true

View file

@ -26,6 +26,7 @@ type SearchOrganizationsOptions struct {
type FindOrgOptions struct {
db.ListOptions
UserID int64
IncludeLimited bool
IncludePrivate bool
}
@ -43,7 +44,11 @@ func (opts FindOrgOptions) ToConds() builder.Cond {
cond = cond.And(builder.In("`user`.`id`", queryUserOrgIDs(opts.UserID, opts.IncludePrivate)))
}
if !opts.IncludePrivate {
cond = cond.And(builder.Eq{"`user`.visibility": structs.VisibleTypePublic})
if !opts.IncludeLimited {
cond = cond.And(builder.Eq{"`user`.visibility": structs.VisibleTypePublic})
} else {
cond = cond.And(builder.In("`user`.visibility", structs.VisibleTypePublic, structs.VisibleTypeLimited))
}
}
return cond
}

View file

@ -27,6 +27,7 @@ func TestCountOrganizations(t *testing.T) {
}
func TestFindOrgs(t *testing.T) {
defer unittest.OverrideFixtures("models/organization/TestFindOrgs")()
require.NoError(t, unittest.PrepareTestDatabase())
orgs, err := db.Find[organization.Organization](db.DefaultContext, organization.FindOrgOptions{
@ -34,8 +35,14 @@ func TestFindOrgs(t *testing.T) {
IncludePrivate: true,
})
require.NoError(t, err)
if assert.Len(t, orgs, 1) {
assert.EqualValues(t, 3, orgs[0].ID)
if assert.Len(t, orgs, 2) {
if orgs[0].ID == 22 {
assert.EqualValues(t, 22, orgs[0].ID)
assert.EqualValues(t, 3, orgs[1].ID)
} else {
assert.EqualValues(t, 3, orgs[0].ID)
assert.EqualValues(t, 22, orgs[1].ID)
}
}
orgs, err = db.Find[organization.Organization](db.DefaultContext, organization.FindOrgOptions{
@ -50,6 +57,14 @@ func TestFindOrgs(t *testing.T) {
IncludePrivate: true,
})
require.NoError(t, err)
assert.EqualValues(t, 2, total)
total, err = db.Count[organization.Organization](db.DefaultContext, organization.FindOrgOptions{
UserID: 4,
IncludePrivate: false,
IncludeLimited: true,
})
require.NoError(t, err)
assert.EqualValues(t, 1, total)
}

View file

@ -292,3 +292,11 @@ func FixInconsistentOwnerTeams(ctx context.Context) (int64, error) {
return int64(len(teamIDs)), nil
}
func NewGhostTeam() *Team {
return &Team{
ID: -1,
Name: "Ghost team",
LowerName: "ghost team",
}
}

19
models/quota/main_test.go Normal file
View file

@ -0,0 +1,19 @@
// Copyright 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: GPL-3.0-or-later
package quota
import (
"testing"
"forgejo.org/models/unittest"
_ "forgejo.org/models"
_ "forgejo.org/models/actions"
_ "forgejo.org/models/activities"
_ "forgejo.org/models/forgefed"
)
func TestMain(m *testing.M) {
unittest.MainTest(m)
}

View file

@ -131,7 +131,8 @@ func createQueryFor(ctx context.Context, userID int64, q string) db.Engine {
case "artifacts":
session = session.
Table("action_artifact").
Join("INNER", "`repository`", "`action_artifact`.repo_id = `repository`.id")
Join("INNER", "`repository`", "`action_artifact`.repo_id = `repository`.id").
Where("`action_artifact`.status != ?", action_model.ArtifactStatusExpired)
case "packages":
session = session.
Table("package_version").

23
models/quota/used_test.go Normal file
View file

@ -0,0 +1,23 @@
// Copyright 2025 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: GPL-3.0-or-later
package quota
import (
"testing"
"forgejo.org/models/unittest"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestGetUsedForUser(t *testing.T) {
defer unittest.OverrideFixtures("models/fixtures/TestGetUsedForUser/")()
require.NoError(t, unittest.PrepareTestDatabase())
used, err := GetUsedForUser(t.Context(), 5)
require.NoError(t, err)
assert.EqualValues(t, 4096, used.Size.Assets.Artifacts)
}

View file

@ -259,11 +259,11 @@ func (b *Indexer) Search(ctx context.Context, opts *internal.SearchOptions) (int
if opts.Mode == internal.CodeSearchModeUnion {
query := bleve.NewDisjunctionQuery()
for _, field := range strings.Fields(opts.Keyword) {
query.AddQuery(inner_bleve.MatchPhraseQuery(field, "Content", repoIndexerAnalyzer, 0))
query.AddQuery(inner_bleve.MatchPhraseQuery(field, "Content", repoIndexerAnalyzer, false))
}
keywordQuery = query
} else {
keywordQuery = inner_bleve.MatchPhraseQuery(opts.Keyword, "Content", repoIndexerAnalyzer, 0)
keywordQuery = inner_bleve.MatchPhraseQuery(opts.Keyword, "Content", repoIndexerAnalyzer, false)
}
if len(opts.RepoIDs) > 0 {

View file

@ -29,11 +29,11 @@ func MatchQuery(matchTerm, field, analyzer string, fuzziness int) *query.MatchQu
}
// MatchPhraseQuery generates a match phrase query for the given phrase, field and analyzer
func MatchPhraseQuery(matchPhrase, field, analyzer string, fuzziness int) *query.MatchPhraseQuery {
func MatchPhraseQuery(matchPhrase, field, analyzer string, autoFuzzy bool) *query.MatchPhraseQuery {
q := bleve.NewMatchPhraseQuery(matchPhrase)
q.FieldVal = field
q.Analyzer = analyzer
q.Fuzziness = fuzziness
q.SetAutoFuzziness(autoFuzzy)
return q
}

View file

@ -162,15 +162,10 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
}
q := bleve.NewBooleanQuery()
for _, token := range tokens {
fuzziness := 0
if token.Fuzzy {
// TODO: replace with "auto" after bleve update
fuzziness = min(len(token.Term)/4, 2)
}
innerQ := bleve.NewDisjunctionQuery(
inner_bleve.MatchPhraseQuery(token.Term, "title", issueIndexerAnalyzer, fuzziness),
inner_bleve.MatchPhraseQuery(token.Term, "content", issueIndexerAnalyzer, fuzziness),
inner_bleve.MatchPhraseQuery(token.Term, "comments", issueIndexerAnalyzer, fuzziness))
inner_bleve.MatchPhraseQuery(token.Term, "title", issueIndexerAnalyzer, token.Fuzzy),
inner_bleve.MatchPhraseQuery(token.Term, "content", issueIndexerAnalyzer, token.Fuzzy),
inner_bleve.MatchPhraseQuery(token.Term, "comments", issueIndexerAnalyzer, token.Fuzzy))
switch token.Kind {
case internal.BoolOptMust:

View file

@ -460,7 +460,8 @@ func findAllIssueReferencesBytes(content []byte, links []string) []*rawReference
}
parts := strings.Split(u.EscapedPath(), "/")
// /user/repo/issues/3
if len(parts) != 5 || parts[0] != "" {
// /user/repo/pulls/7/files/...
if len(parts) < 5 || parts[0] != "" {
continue
}
var sep string

View file

@ -132,6 +132,30 @@ func TestFindAllIssueReferences(t *testing.T) {
{203, "user4", "repo5", "203", true, XRefActionNone, nil, nil, ""},
},
},
{
"This http://gitea.com:3000/user4/repo5/pulls/202#x yes.",
[]testResult{
{202, "user4", "repo5", "202", true, XRefActionNone, nil, nil, ""},
},
},
{
"This http://gitea.com:3000/user4/repo5/pulls/202/commits yes.",
[]testResult{
{202, "user4", "repo5", "202", true, XRefActionNone, nil, nil, ""},
},
},
{
"This http://gitea.com:3000/user4/repo5/pulls/202/files yes.",
[]testResult{
{202, "user4", "repo5", "202", true, XRefActionNone, nil, nil, ""},
},
},
{
"This http://gitea.com:3000/user4/repo5/pulls/202/files#diff- yes.",
[]testResult{
{202, "user4", "repo5", "202", true, XRefActionNone, nil, nil, ""},
},
},
{
"This http://GiTeA.COM:3000/user4/repo6/pulls/205 yes.",
[]testResult{

View file

@ -90,7 +90,7 @@ func logPrinter(logger log.Logger) func(trigger Event, record *requestRecord) {
status = v.WrittenStatus()
}
logf := logger.Info
if strings.HasPrefix(req.RequestURI, "/assets/") {
if strings.HasPrefix(req.RequestURI, "/assets/") || req.RequestURI == "/api/actions/runner.v1.RunnerService/FetchTask" || req.RequestURI == "/api/actions/runner.v1.RunnerService/UpdateLog" {
logf = logger.Trace
}
message := completedMessage

1
package-lock.json generated
View file

@ -67,7 +67,6 @@
"@stoplight/spectral-cli": "6.14.3",
"@stylistic/eslint-plugin-js": "4.2.0",
"@stylistic/stylelint-plugin": "3.1.2",
"@typescript-eslint/parser": "8.26.1",
"@vitejs/plugin-vue": "5.2.3",
"@vitest/coverage-v8": "3.0.8",
"@vitest/eslint-plugin": "1.1.25",

View file

@ -66,7 +66,6 @@
"@stoplight/spectral-cli": "6.14.3",
"@stylistic/eslint-plugin-js": "4.2.0",
"@stylistic/stylelint-plugin": "3.1.2",
"@typescript-eslint/parser": "8.26.1",
"@vitejs/plugin-vue": "5.2.3",
"@vitest/coverage-v8": "3.0.8",
"@vitest/eslint-plugin": "1.1.25",

View file

@ -224,9 +224,8 @@ func Migrate(ctx *context.APIContext) {
HasWiki: &opts.Wiki,
}
// only enabling wiki could return an error
if err = updateRepoUnits(ctx, repoOpt); err != nil {
log.Error("Failed to enable wiki on %s/%s repo. %w", repoOwner.Name, form.RepoName, err)
if err = updateRepoUnits(ctx, repoOwner.Name, repo, repoOpt); err != nil {
log.Error("Failed to update units on %s/%s repo. %w", repoOwner.Name, form.RepoName, err)
}
}

View file

@ -647,7 +647,7 @@ func Edit(ctx *context.APIContext) {
return
}
if err := updateRepoUnits(ctx, opts); err != nil {
if err := updateRepoUnits(ctx, ctx.Repo.Owner.Name, ctx.Repo.Repository, opts); err != nil {
return
}
@ -779,10 +779,7 @@ func updateBasicProperties(ctx *context.APIContext, opts api.EditRepoOption) err
}
// updateRepoUnits updates repo units: Issue settings, Wiki settings, PR settings
func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error {
owner := ctx.Repo.Owner
repo := ctx.Repo.Repository
func updateRepoUnits(ctx *context.APIContext, owner string, repo *repo_model.Repository, opts api.EditRepoOption) error {
var units []repo_model.RepoUnit
var deleteUnitTypes []unit_model.Type
@ -1045,7 +1042,7 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error {
}
}
log.Trace("Repository advanced settings updated: %s/%s", owner.Name, repo.Name)
log.Trace("Repository advanced settings updated: %s/%s", owner, repo.Name)
return nil
}

View file

@ -94,6 +94,14 @@ func reqReview(t int64, name string, delReq bool) *issue_model.Comment {
return c
}
func ghostReqReview(t, id int64) *issue_model.Comment {
c := testComment(t)
c.Type = issue_model.CommentTypeReviewRequest
c.AssigneeTeam = organization.NewGhostTeam()
c.AssigneeTeamID = id
return c
}
func reqReviewList(t int64, del bool, names ...string) *issue_model.Comment {
req := []issue_model.RequestReviewTarget{}
for _, name := range names {
@ -588,6 +596,27 @@ func TestCombineReviewRequests(t *testing.T) {
reqReviewList(121, true, "titi", "toto-team"),
},
},
// Ghost.
{
name: "ghost reviews",
beforeCombined: []*issue_model.Comment{
reqReview(1, "titi", false),
ghostReqReview(2, 50),
ghostReqReview(3, 51),
ghostReqReview(4, 50),
},
afterCombined: []*issue_model.Comment{
{
PosterID: 1,
Type: issue_model.CommentTypeReviewRequest,
CreatedUnix: timeutil.TimeStamp(1),
AddedRequestReview: []issue_model.RequestReviewTarget{
createReqReviewTarget("titi"), {Team: organization.NewGhostTeam()},
},
},
},
},
}
for _, kase := range kases {

View file

@ -66,6 +66,7 @@ func PrepareContextForProfileBigAvatar(ctx *context.Context) {
showPrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || ctx.Doer.ID == ctx.ContextUser.ID)
orgs, err := db.Find[organization.Organization](ctx, organization.FindOrgOptions{
UserID: ctx.ContextUser.ID,
IncludeLimited: ctx.IsSigned,
IncludePrivate: showPrivate,
})
if err != nil {

View file

@ -98,7 +98,7 @@
{{range $release.Attachments}}
{{if .ExternalURL}}
<li>
<a class="tw-flex-1 flex-text-inline tw-font-bold" target="_blank" rel="nofollow" href="{{.DownloadURL}}" download>
<a class="tw-flex-1 flex-text-inline tw-font-bold" target="_blank" rel="nofollow" href="{{.DownloadURL}}">
{{svg "octicon-link-external" 16 "tw-mr-1"}}{{.Name}}
</a>
</li>

View file

@ -396,6 +396,7 @@ func TestAPIRepoMigrate(t *testing.T) {
CloneAddr: testCase.cloneURL,
RepoOwnerID: testCase.userID,
RepoName: testCase.repoName,
Wiki: true,
}).AddTokenAuth(token)
resp := MakeRequest(t, req, NoExpectedStatus)
if resp.Code == http.StatusUnprocessableEntity {

View file

@ -907,7 +907,7 @@ td .commit-summary {
@media (min-width: 768px) {
.repository.view.issue .comment-list .timeline-item .forced-push {
display: grid;
grid-auto-flow: column;
grid-template-columns: 1fr auto;
column-gap: 1rem;
}
}