mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-04-20 03:11:35 +02:00
Merge branch 'forgejo' into feat/xorm-EngineGroup
This commit is contained in:
commit
a8a18e67a3
64 changed files with 1287 additions and 417 deletions
|
@ -28,7 +28,7 @@ jobs:
|
|||
|
||||
runs-on: docker
|
||||
container:
|
||||
image: data.forgejo.org/renovate/renovate:39.195.1
|
||||
image: data.forgejo.org/renovate/renovate:39.205.1
|
||||
|
||||
steps:
|
||||
- name: Load renovate repo cache
|
||||
|
|
2
Makefile
2
Makefile
|
@ -49,7 +49,7 @@ GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1 # renovate: datasour
|
|||
DEADCODE_PACKAGE ?= golang.org/x/tools/cmd/deadcode@v0.31.0 # renovate: datasource=go
|
||||
GOMOCK_PACKAGE ?= go.uber.org/mock/mockgen@v0.4.0 # renovate: datasource=go
|
||||
GOPLS_PACKAGE ?= golang.org/x/tools/gopls@v0.18.1 # renovate: datasource=go
|
||||
RENOVATE_NPM_PACKAGE ?= renovate@39.195.1 # renovate: datasource=docker packageName=data.forgejo.org/renovate/renovate
|
||||
RENOVATE_NPM_PACKAGE ?= renovate@39.205.1 # renovate: datasource=docker packageName=data.forgejo.org/renovate/renovate
|
||||
|
||||
# https://github.com/disposable-email-domains/disposable-email-domains/commits/main/
|
||||
DISPOSABLE_EMAILS_SHA ?= 0c27e671231d27cf66370034d7f6818037416989 # renovate: ...
|
||||
|
|
10
assets/go-licenses.json
generated
10
assets/go-licenses.json
generated
File diff suppressed because one or more lines are too long
12
go.mod
12
go.mod
|
@ -5,7 +5,7 @@ go 1.24
|
|||
toolchain go1.24.1
|
||||
|
||||
require (
|
||||
code.forgejo.org/f3/gof3/v3 v3.10.4
|
||||
code.forgejo.org/f3/gof3/v3 v3.10.6
|
||||
code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20191008002943-06d1c002b251
|
||||
code.forgejo.org/forgejo/levelqueue v1.0.0
|
||||
code.forgejo.org/forgejo/reply v1.0.2
|
||||
|
@ -33,7 +33,7 @@ require (
|
|||
github.com/djherbis/nio/v3 v3.0.1
|
||||
github.com/dsnet/compress v0.0.2-0.20230904184137-39efe44ab707
|
||||
github.com/dustin/go-humanize v1.0.1
|
||||
github.com/editorconfig/editorconfig-core-go/v2 v2.6.2
|
||||
github.com/editorconfig/editorconfig-core-go/v2 v2.6.3
|
||||
github.com/emersion/go-imap v1.2.1
|
||||
github.com/felixge/fgprof v0.9.5
|
||||
github.com/fsnotify/fsnotify v1.8.0
|
||||
|
@ -99,8 +99,8 @@ require (
|
|||
github.com/yohcop/openid-go v1.0.1
|
||||
github.com/yuin/goldmark v1.7.8
|
||||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
|
||||
gitlab.com/gitlab-org/api/client-go v0.123.0
|
||||
go.uber.org/mock v0.4.0
|
||||
gitlab.com/gitlab-org/api/client-go v0.126.0
|
||||
go.uber.org/mock v0.5.0
|
||||
golang.org/x/crypto v0.36.0
|
||||
golang.org/x/image v0.25.0
|
||||
golang.org/x/net v0.37.0
|
||||
|
@ -108,7 +108,6 @@ require (
|
|||
golang.org/x/sync v0.12.0
|
||||
golang.org/x/sys v0.31.0
|
||||
golang.org/x/text v0.23.0
|
||||
google.golang.org/grpc v1.71.0
|
||||
google.golang.org/protobuf v1.36.4
|
||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||
gopkg.in/ini.v1 v1.67.0
|
||||
|
@ -270,12 +269,13 @@ require (
|
|||
go.uber.org/zap v1.27.0 // indirect
|
||||
go.uber.org/zap/exp v0.3.0 // indirect
|
||||
golang.org/x/mod v0.24.0 // indirect
|
||||
golang.org/x/time v0.9.0 // indirect
|
||||
golang.org/x/time v0.10.0 // indirect
|
||||
golang.org/x/tools v0.31.0 // indirect
|
||||
google.golang.org/api v0.203.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20241015192408-796eee8c2d53 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect
|
||||
google.golang.org/grpc v1.71.0 // indirect
|
||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
)
|
||||
|
|
20
go.sum
20
go.sum
|
@ -610,8 +610,8 @@ cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoIS
|
|||
cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vfKf5Af+to4M=
|
||||
cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA=
|
||||
cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcPALq2CxzdePw=
|
||||
code.forgejo.org/f3/gof3/v3 v3.10.4 h1:NOkw8lG3PhgYykdR5pJ19KFLdYmRFVII43YBSNKtpvk=
|
||||
code.forgejo.org/f3/gof3/v3 v3.10.4/go.mod h1:aQSlSGpISIf016g1dBrmm16h53WUKjCR7nSCuoO8dq8=
|
||||
code.forgejo.org/f3/gof3/v3 v3.10.6 h1:Ru/Iz+pqM8IPi7atUHE7+q7v3O3DRbYgMFqrFTsO1m8=
|
||||
code.forgejo.org/f3/gof3/v3 v3.10.6/go.mod h1:K6lQCWQIyN/5rjP/OJL9fMA6fd++satndE20w/I6Kss=
|
||||
code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20191008002943-06d1c002b251 h1:HTZl3CBk3ABNYtFI6TPLvJgGKFIhKT5CBk0sbOtkDKU=
|
||||
code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20191008002943-06d1c002b251/go.mod h1:PphB88CPbx601QrWPMZATeorACeVmQlyv3u+uUMbSaM=
|
||||
code.forgejo.org/forgejo/act v1.23.1 h1:4LU7u3FE380DicHz1oZ4ohsWU9I527OHeslVHnr9eP4=
|
||||
|
@ -845,8 +845,8 @@ github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdf
|
|||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/editorconfig/editorconfig-core-go/v2 v2.6.2 h1:dKG8sc7n321deIVRcQtwlMNoBEra7j0qQ8RwxO8RN0w=
|
||||
github.com/editorconfig/editorconfig-core-go/v2 v2.6.2/go.mod h1:7dvD3GCm7eBw53xZ/lsiq72LqobdMg3ITbMBxnmJmqY=
|
||||
github.com/editorconfig/editorconfig-core-go/v2 v2.6.3 h1:XVUp6qW3BIkmM3/1EkrHpa6bL56APOynfXcZEmIgOhs=
|
||||
github.com/editorconfig/editorconfig-core-go/v2 v2.6.3/go.mod h1:ThHVc+hqbUsmE1wmK/MASpQEhCleWu1JDJDNhUOMy0c=
|
||||
github.com/elazarl/goproxy v1.4.0 h1:4GyuSbFa+s26+3rmYNSuUVsx+HgPrV1bk1jXI0l9wjM=
|
||||
github.com/elazarl/goproxy v1.4.0/go.mod h1:X/5W/t+gzDyLfHW4DrMdpjqYjpXsURlBt9lpBDxZZZQ=
|
||||
github.com/emersion/go-imap v1.2.1 h1:+s9ZjMEjOB8NzZMVTM3cCenz2JrQIGGo5j1df19WjTA=
|
||||
|
@ -1452,8 +1452,8 @@ github.com/zeebo/blake3 v0.2.4/go.mod h1:7eeQ6d2iXWRGF6npfaxl2CU+xy2Fjo2gxeyZGCR
|
|||
github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo=
|
||||
github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
|
||||
github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA=
|
||||
gitlab.com/gitlab-org/api/client-go v0.123.0 h1:W3LZ5QNyiSCJA0Zchkwz8nQIUzOuDoSWMZtRDT5DjPI=
|
||||
gitlab.com/gitlab-org/api/client-go v0.123.0/go.mod h1:Jh0qjLILEdbO6z/OY94RD+3NDQRUKiuFSFYozN6cpKM=
|
||||
gitlab.com/gitlab-org/api/client-go v0.126.0 h1:VV5TdkF6pMbEdFGvbR2CwEgJwg6qdg1u3bj5eD2tiWk=
|
||||
gitlab.com/gitlab-org/api/client-go v0.126.0/go.mod h1:bYC6fPORKSmtuPRyD9Z2rtbAjE7UeNatu2VWHRf4/LE=
|
||||
go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI=
|
||||
go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
|
@ -1491,8 +1491,8 @@ go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
|||
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
|
||||
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
|
||||
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
|
||||
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||
|
@ -1839,8 +1839,8 @@ golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxb
|
|||
golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
|
||||
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/time v0.10.0 h1:3usCWA8tQn0L8+hFJQNgzpWbd89begxN66o1Ojdn5L4=
|
||||
golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
|
|
5
models/fixtures/TestPrivateRepoProjects/access.yml
Normal file
5
models/fixtures/TestPrivateRepoProjects/access.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
-
|
||||
id: 1001
|
||||
user_id: 29
|
||||
repo_id: 3
|
||||
mode: 1
|
11
models/fixtures/TestPrivateRepoProjects/project.yml
Normal file
11
models/fixtures/TestPrivateRepoProjects/project.yml
Normal file
|
@ -0,0 +1,11 @@
|
|||
-
|
||||
id: 1001
|
||||
title: Org project that contains private issues
|
||||
owner_id: 3
|
||||
repo_id: 0
|
||||
is_closed: false
|
||||
creator_id: 2
|
||||
board_type: 1
|
||||
type: 3
|
||||
created_unix: 1738000000
|
||||
updated_unix: 1738000000
|
|
@ -0,0 +1,8 @@
|
|||
-
|
||||
id: 1001
|
||||
project_id: 1001
|
||||
title: Triage
|
||||
creator_id: 2
|
||||
default: true
|
||||
created_unix: 1738000000
|
||||
updated_unix: 1738000000
|
11
models/fixtures/TestPrivateRepoProjects/project_issue.yml
Normal file
11
models/fixtures/TestPrivateRepoProjects/project_issue.yml
Normal file
|
@ -0,0 +1,11 @@
|
|||
-
|
||||
id: 1001
|
||||
issue_id: 6
|
||||
project_id: 1001
|
||||
project_board_id: 1001
|
||||
|
||||
-
|
||||
id: 1002
|
||||
issue_id: 15
|
||||
project_id: 1001
|
||||
project_board_id: 1001
|
|
@ -7,9 +7,11 @@ import (
|
|||
"context"
|
||||
"crypto/md5"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
|
||||
"code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/secret"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
|
@ -57,19 +59,38 @@ func MigrateTwoFactorToKeying(x *xorm.Engine) error {
|
|||
|
||||
oldEncryptionKey := md5.Sum([]byte(setting.SecretKey))
|
||||
|
||||
return db.Iterate(context.Background(), nil, func(ctx context.Context, bean *auth.TwoFactor) error {
|
||||
messages := make([]string, 0, 100)
|
||||
ids := make([]int64, 0, 100)
|
||||
|
||||
err = db.Iterate(context.Background(), nil, func(ctx context.Context, bean *auth.TwoFactor) error {
|
||||
decodedStoredSecret, err := base64.StdEncoding.DecodeString(string(bean.Secret))
|
||||
if err != nil {
|
||||
return err
|
||||
messages = append(messages, fmt.Sprintf("two_factor.id=%d, two_factor.uid=%d: base64.StdEncoding.DecodeString: %v", bean.ID, bean.UID, err))
|
||||
ids = append(ids, bean.ID)
|
||||
return nil
|
||||
}
|
||||
|
||||
secretBytes, err := secret.AesDecrypt(oldEncryptionKey[:], decodedStoredSecret)
|
||||
if err != nil {
|
||||
return err
|
||||
messages = append(messages, fmt.Sprintf("two_factor.id=%d, two_factor.uid=%d: secret.AesDecrypt: %v", bean.ID, bean.UID, err))
|
||||
ids = append(ids, bean.ID)
|
||||
return nil
|
||||
}
|
||||
|
||||
bean.SetSecret(string(secretBytes))
|
||||
_, err = db.GetEngine(ctx).Cols("secret").ID(bean.ID).Update(bean)
|
||||
return err
|
||||
})
|
||||
if err == nil {
|
||||
if len(ids) > 0 {
|
||||
log.Error("Forgejo migration[25]: The following TOTP secrets were found to be corrupted and removed from the database. TOTP is no longer required to login with the associated users. They should be informed because they will need to visit their security settings and configure TOTP again. No other action is required. See https://codeberg.org/forgejo/forgejo/issues/6637 for more context on the various causes for such a corruption.")
|
||||
for _, message := range messages {
|
||||
log.Error("Forgejo migration[25]: %s", message)
|
||||
}
|
||||
|
||||
_, err = db.GetEngine(context.Background()).In("id", ids).NoAutoCondition().NoAutoTime().Delete(&auth.TwoFactor{})
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -36,10 +36,14 @@ func Test_MigrateTwoFactorToKeying(t *testing.T) {
|
|||
|
||||
cnt, err := x.Table("two_factor").Count()
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 1, cnt)
|
||||
assert.EqualValues(t, 2, cnt)
|
||||
|
||||
require.NoError(t, MigrateTwoFactorToKeying(x))
|
||||
|
||||
cnt, err = x.Table("two_factor").Count()
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 1, cnt)
|
||||
|
||||
var twofactor auth.TwoFactor
|
||||
_, err = x.Table("two_factor").ID(1).Get(&twofactor)
|
||||
require.NoError(t, err)
|
||||
|
|
|
@ -117,3 +117,57 @@ func TestPrivateIssueProjects(t *testing.T) {
|
|||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestPrivateRepoProjects(t *testing.T) {
|
||||
defer tests.AddFixtures("models/fixtures/TestPrivateRepoProjects/")()
|
||||
require.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3})
|
||||
orgProject := unittest.AssertExistsAndLoadBean(t, &project.Project{ID: 1001, OwnerID: org.ID})
|
||||
column := unittest.AssertExistsAndLoadBean(t, &project.Column{ID: 1001, ProjectID: orgProject.ID})
|
||||
|
||||
t.Run("Partial access", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
user29 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 29})
|
||||
|
||||
issueList, err := issues.LoadIssuesFromColumn(db.DefaultContext, column, user29, org, optional.None[bool]())
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, issueList, 1)
|
||||
assert.EqualValues(t, 6, issueList[0].ID)
|
||||
|
||||
issuesNum, err := issues.NumIssuesInProject(db.DefaultContext, orgProject, user29, org, optional.None[bool]())
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 1, issuesNum)
|
||||
|
||||
issuesNum, err = issues.NumIssuesInProject(db.DefaultContext, orgProject, user29, org, optional.Some(true))
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 0, issuesNum)
|
||||
|
||||
issuesNum, err = issues.NumIssuesInProject(db.DefaultContext, orgProject, user29, org, optional.Some(false))
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 1, issuesNum)
|
||||
})
|
||||
|
||||
t.Run("Full access", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
|
||||
issueList, err := issues.LoadIssuesFromColumn(db.DefaultContext, column, user2, org, optional.None[bool]())
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, issueList, 2)
|
||||
assert.EqualValues(t, 15, issueList[0].ID)
|
||||
assert.EqualValues(t, 6, issueList[1].ID)
|
||||
|
||||
issuesNum, err := issues.NumIssuesInProject(db.DefaultContext, orgProject, user2, org, optional.None[bool]())
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 2, issuesNum)
|
||||
|
||||
issuesNum, err = issues.NumIssuesInProject(db.DefaultContext, orgProject, user2, org, optional.Some(true))
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 0, issuesNum)
|
||||
|
||||
issuesNum, err = issues.NumIssuesInProject(db.DefaultContext, orgProject, user2, org, optional.Some(false))
|
||||
require.NoError(t, err)
|
||||
assert.EqualValues(t, 2, issuesNum)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -341,6 +341,9 @@ func issuePullAccessibleRepoCond(repoIDstr string, userID int64, org *organizati
|
|||
builder.Or(
|
||||
repo_model.UserOrgUnitRepoCond(repoIDstr, userID, org.ID, unitType), // team member repos
|
||||
repo_model.UserOrgPublicUnitRepoCond(userID, org.ID), // user org public non-member repos, TODO: check repo has issues
|
||||
builder.And(
|
||||
builder.In("issue.repo_id", builder.Select("id").From("repository").Where(builder.Eq{"owner_id": org.ID})),
|
||||
repo_model.UserAccessRepoCond(repoIDstr, userID)), // user can access org repo in a unit independent way
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -7,3 +7,12 @@
|
|||
last_used_passcode:
|
||||
created_unix: 1564253724
|
||||
updated_unix: 1564253724
|
||||
-
|
||||
id: 2
|
||||
uid: 23
|
||||
secret: badbad
|
||||
scratch_salt: badbad
|
||||
scratch_hash: badbad
|
||||
last_used_passcode:
|
||||
created_unix: 1564253724
|
||||
updated_unix: 1564253724
|
||||
|
|
45
models/repo/release_list.go
Normal file
45
models/repo/release_list.go
Normal file
|
@ -0,0 +1,45 @@
|
|||
// Copyright 2025 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package repo
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
)
|
||||
|
||||
type ReleaseList []*Release
|
||||
|
||||
// LoadAttributes loads the repository and publisher for the releases.
|
||||
func (r ReleaseList) LoadAttributes(ctx context.Context) error {
|
||||
repoCache := make(map[int64]*Repository)
|
||||
userCache := make(map[int64]*user_model.User)
|
||||
|
||||
for _, release := range r {
|
||||
var err error
|
||||
repo, ok := repoCache[release.RepoID]
|
||||
if !ok {
|
||||
repo, err = GetRepositoryByID(ctx, release.RepoID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
repoCache[release.RepoID] = repo
|
||||
}
|
||||
release.Repo = repo
|
||||
|
||||
publisher, ok := userCache[release.PublisherID]
|
||||
if !ok {
|
||||
publisher, err = user_model.GetUserByID(ctx, release.PublisherID)
|
||||
if err != nil {
|
||||
if !user_model.IsErrUserNotExist(err) {
|
||||
return err
|
||||
}
|
||||
publisher = user_model.NewGhostUser()
|
||||
}
|
||||
userCache[release.PublisherID] = publisher
|
||||
}
|
||||
release.Publisher = publisher
|
||||
}
|
||||
return nil
|
||||
}
|
42
models/repo/release_list_test.go
Normal file
42
models/repo/release_list_test.go
Normal file
|
@ -0,0 +1,42 @@
|
|||
// Copyright 2025 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package repo
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestReleaseListLoadAttributes(t *testing.T) {
|
||||
require.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
releases := ReleaseList{&Release{
|
||||
RepoID: 1,
|
||||
PublisherID: 1,
|
||||
}, &Release{
|
||||
RepoID: 2,
|
||||
PublisherID: 2,
|
||||
}, &Release{
|
||||
RepoID: 1,
|
||||
PublisherID: 2,
|
||||
}, &Release{
|
||||
RepoID: 2,
|
||||
PublisherID: 1,
|
||||
}}
|
||||
|
||||
require.NoError(t, releases.LoadAttributes(t.Context()))
|
||||
|
||||
assert.EqualValues(t, 1, releases[0].Repo.ID)
|
||||
assert.EqualValues(t, 1, releases[0].Publisher.ID)
|
||||
assert.EqualValues(t, 2, releases[1].Repo.ID)
|
||||
assert.EqualValues(t, 2, releases[1].Publisher.ID)
|
||||
assert.EqualValues(t, 1, releases[2].Repo.ID)
|
||||
assert.EqualValues(t, 2, releases[2].Publisher.ID)
|
||||
assert.EqualValues(t, 2, releases[3].Repo.ID)
|
||||
assert.EqualValues(t, 1, releases[3].Publisher.ID)
|
||||
}
|
|
@ -529,7 +529,6 @@ func (repo *Repository) ComposeMetas(ctx context.Context) map[string]string {
|
|||
Join("INNER", "team", "team.id = team_repo.team_id").
|
||||
Where("team_repo.repo_id = ?", repo.ID).
|
||||
Select("team.lower_name").
|
||||
OrderBy("team.lower_name").
|
||||
Find(&teams)
|
||||
metas["teams"] = "," + strings.Join(teams, ",") + ","
|
||||
metas["org"] = strings.ToLower(repo.OwnerName)
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
"runtime/pprof"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
|
@ -280,6 +281,33 @@ const (
|
|||
SortByDeadlineAsc = internal.SortByDeadlineAsc
|
||||
)
|
||||
|
||||
// ParseSortBy parses the `sortBy` string and returns the associated `SortBy`
|
||||
// value, if one exists. Otherwise return `defaultSortBy`.
|
||||
func ParseSortBy(sortBy string, defaultSortBy internal.SortBy) internal.SortBy {
|
||||
switch strings.ToLower(sortBy) {
|
||||
case "relevance":
|
||||
return SortByScore
|
||||
case "latest":
|
||||
return SortByCreatedDesc
|
||||
case "oldest":
|
||||
return SortByCreatedAsc
|
||||
case "recentupdate":
|
||||
return SortByUpdatedDesc
|
||||
case "leastupdate":
|
||||
return SortByUpdatedAsc
|
||||
case "mostcomment":
|
||||
return SortByCommentsDesc
|
||||
case "leastcomment":
|
||||
return SortByCommentsAsc
|
||||
case "nearduedate":
|
||||
return SortByDeadlineAsc
|
||||
case "farduedate":
|
||||
return SortByDeadlineDesc
|
||||
default:
|
||||
return defaultSortBy
|
||||
}
|
||||
}
|
||||
|
||||
// SearchIssues search issues by options.
|
||||
func SearchIssues(ctx context.Context, opts *SearchOptions) ([]int64, int64, error) {
|
||||
indexer := *globalIndexer.Load()
|
||||
|
|
652
package-lock.json
generated
652
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -67,12 +67,12 @@
|
|||
"@stylistic/eslint-plugin-js": "4.2.0",
|
||||
"@stylistic/stylelint-plugin": "3.1.2",
|
||||
"@typescript-eslint/parser": "8.26.1",
|
||||
"@vitejs/plugin-vue": "5.1.5",
|
||||
"@vitejs/plugin-vue": "5.2.3",
|
||||
"@vitest/coverage-v8": "3.0.8",
|
||||
"@vitest/eslint-plugin": "1.1.25",
|
||||
"@vue/test-utils": "2.4.6",
|
||||
"eslint": "9.22.0",
|
||||
"eslint-import-resolver-typescript": "3.8.7",
|
||||
"eslint-import-resolver-typescript": "4.1.1",
|
||||
"eslint-plugin-array-func": "5.0.2",
|
||||
"eslint-plugin-import-x": "4.7.0",
|
||||
"eslint-plugin-no-jquery": "3.1.1",
|
||||
|
|
8
poetry.lock
generated
8
poetry.lock
generated
|
@ -404,13 +404,13 @@ files = [
|
|||
|
||||
[[package]]
|
||||
name = "yamllint"
|
||||
version = "1.36.1"
|
||||
version = "1.36.2"
|
||||
description = "A linter for YAML files."
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
files = [
|
||||
{file = "yamllint-1.36.1-py3-none-any.whl", hash = "sha256:3e2ccd47ea12449837adf6b2c56fd9e31172ce42bc1470380806be461f25df66"},
|
||||
{file = "yamllint-1.36.1.tar.gz", hash = "sha256:a287689daaafc301a80549b2d0170452ebfdcabd826e3fe3b4c66e322d4851fa"},
|
||||
{file = "yamllint-1.36.2-py3-none-any.whl", hash = "sha256:6ba19800513d86c987ed3cf48c0aba4e82b3624596e1dab55723b3733e11f35c"},
|
||||
{file = "yamllint-1.36.2.tar.gz", hash = "sha256:c9ccc818659736e7b13f7e2f9c3c9bb9ac77445be13e789e7d843e92cb8428ef"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
@ -423,4 +423,4 @@ dev = ["doc8", "flake8", "flake8-import-order", "rstcheck[sphinx]", "sphinx"]
|
|||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = "^3.10"
|
||||
content-hash = "15925764be9383752b2d6eaba27c7f65e3a07456123bb69a2837fa54c916d7cb"
|
||||
content-hash = "6e4e2a74db7e165f0aa8cae9bb8932cbe1e84ea9bef64db42371e6d620d77c93"
|
||||
|
|
|
@ -6,7 +6,7 @@ python = "^3.10"
|
|||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
djlint = "1.36.4"
|
||||
yamllint = "1.36.1"
|
||||
yamllint = "1.36.2"
|
||||
codespell = "2.4.1"
|
||||
|
||||
[tool.djlint]
|
||||
|
|
14
release-notes-published/7.0.14.md
Normal file
14
release-notes-published/7.0.14.md
Normal file
|
@ -0,0 +1,14 @@
|
|||
|
||||
|
||||
<!--start release-notes-assistant-->
|
||||
|
||||
## Release notes
|
||||
<!--URL:https://codeberg.org/forgejo/forgejo-->
|
||||
- Bug fixes
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7143) ([backported](https://codeberg.org/forgejo/forgejo/pulls/7145)): <!--number 7145 --><!--line 0 --><!--description Zml4OiBjb25zaWRlciBwdWJsaWMgaXNzdWVzIGZvciBwcm9qZWN0IGJvYXJkcyAoIzcxNDMp-->consider public issues for project boards<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7038) ([backported](https://codeberg.org/forgejo/forgejo/pulls/7049)): <!--number 7049 --><!--line 0 --><!--description Zml4KHJlbGVhc2UpOiB0aGUgcm9vdGxlc3MgaW1hZ2UgdmVyc2lvbiBsYWJlbCBpcyBub3Qgc2V0-->the rootless image version label is not set<!--description-->
|
||||
- Included for completeness but not worth a release note
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/6299) ([backported](https://codeberg.org/forgejo/forgejo/pulls/7233)): <!--number 7233 --><!--line 0 --><!--description Y2hvcmU6IE1ha2UgRm9yZ2VqbyBidWlsZCB3aXRoIGdvMS4yNA==-->chore: Make Forgejo build with go1.24<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7081): <!--number 7081 --><!--line 0 --><!--description VXBkYXRlIGdvbGFuZyBwYWNrYWdlcyB0byB2MS4yMyAodjcuMC9mb3JnZWpvKSAobWlub3Ip-->Update golang packages to v1.23 (v7.0/forgejo) (minor)<!--description-->
|
||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7051): <!--number 7051 --><!--line 0 --><!--description VXBkYXRlIGh0dHBzOi8vY29kZS5mb3JnZWpvLm9yZy9mb3JnZWpvL2Zvcmdlam8tYnVpbGQtcHVibGlzaCBhY3Rpb24gdG8gdjUuMy40ICh2Ny4wL2Zvcmdlam8p-->Update https://code.forgejo.org/forgejo/forgejo-build-publish action to v5.3.4 (v7.0/forgejo)<!--description-->
|
||||
<!--end release-notes-assistant-->
|
1
release-notes/7251.md
Normal file
1
release-notes/7251.md
Normal file
|
@ -0,0 +1 @@
|
|||
When migrating from a Forgejo version lower than v10, the TOTP secrets found to be corrupted are now transparently removed from the database instead of failing the migration. TOTP is no longer required to login with the associated users. They should be informed because they will need to visit their security settings and configure TOTP again. No other action is required.
|
|
@ -137,6 +137,8 @@
|
|||
"@playwright/**",
|
||||
"@stoplight/spectral-cli",
|
||||
"@stylistic/**",
|
||||
"@vitejs/plugin-vue",
|
||||
"@vue/test-utils",
|
||||
"djlint",
|
||||
"github.com/editorconfig-checker/editorconfig-checker/v2/cmd/editorconfig-checker",
|
||||
"github.com/golangci/golangci-lint/cmd/golangci-lint",
|
||||
|
@ -148,7 +150,7 @@
|
|||
"mvdan.cc/gofumpt",
|
||||
"updates",
|
||||
"vite-string-plugin",
|
||||
"@vue/test-utils"
|
||||
"yamllint"
|
||||
],
|
||||
"automerge": true
|
||||
},
|
||||
|
|
|
@ -16,8 +16,6 @@ import (
|
|||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"connectrpc.com/connect"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -37,12 +35,12 @@ var withRunner = connect.WithInterceptors(connect.UnaryInterceptorFunc(func(unar
|
|||
runner, err := actions_model.GetRunnerByUUID(ctx, uuid)
|
||||
if err != nil {
|
||||
if errors.Is(err, util.ErrNotExist) {
|
||||
return nil, status.Error(codes.Unauthenticated, "unregistered runner")
|
||||
return nil, connect.NewError(connect.CodeUnauthenticated, errors.New("unregistered runner"))
|
||||
}
|
||||
return nil, status.Error(codes.Internal, err.Error())
|
||||
return nil, connect.NewError(connect.CodeInternal, err)
|
||||
}
|
||||
if subtle.ConstantTimeCompare([]byte(runner.TokenHash), []byte(auth_model.HashToken(token, runner.TokenSalt))) != 1 {
|
||||
return nil, status.Error(codes.Unauthenticated, "unregistered runner")
|
||||
return nil, connect.NewError(connect.CodeUnauthenticated, errors.New("unregistered runner"))
|
||||
}
|
||||
|
||||
cols := []string{"last_online"}
|
||||
|
|
|
@ -6,6 +6,7 @@ package runner
|
|||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
actions_model "code.gitea.io/gitea/models/actions"
|
||||
|
@ -20,8 +21,6 @@ import (
|
|||
"code.gitea.io/actions-proto-go/runner/v1/runnerv1connect"
|
||||
"connectrpc.com/connect"
|
||||
gouuid "github.com/google/uuid"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
func NewRunnerServiceHandler() (string, http.Handler) {
|
||||
|
@ -44,27 +43,27 @@ func (s *Service) Register(
|
|||
req *connect.Request[runnerv1.RegisterRequest],
|
||||
) (*connect.Response[runnerv1.RegisterResponse], error) {
|
||||
if req.Msg.Token == "" || req.Msg.Name == "" {
|
||||
return nil, errors.New("missing runner token, name")
|
||||
return nil, connect.NewError(connect.CodeInvalidArgument, errors.New("missing runner token, name"))
|
||||
}
|
||||
|
||||
runnerToken, err := actions_model.GetRunnerToken(ctx, req.Msg.Token)
|
||||
if err != nil {
|
||||
return nil, errors.New("runner registration token not found")
|
||||
return nil, connect.NewError(connect.CodeInvalidArgument, errors.New("runner registration token not found"))
|
||||
}
|
||||
|
||||
if !runnerToken.IsActive {
|
||||
return nil, errors.New("runner registration token has been invalidated, please use the latest one")
|
||||
return nil, connect.NewError(connect.CodeInvalidArgument, errors.New("runner registration token has been invalidated, please use the latest one"))
|
||||
}
|
||||
|
||||
if runnerToken.OwnerID > 0 {
|
||||
if _, err := user_model.GetUserByID(ctx, runnerToken.OwnerID); err != nil {
|
||||
return nil, errors.New("owner of the token not found")
|
||||
return nil, connect.NewError(connect.CodeInternal, errors.New("owner of the token not found"))
|
||||
}
|
||||
}
|
||||
|
||||
if runnerToken.RepoID > 0 {
|
||||
if _, err := repo_model.GetRepositoryByID(ctx, runnerToken.RepoID); err != nil {
|
||||
return nil, errors.New("repository of the token not found")
|
||||
return nil, connect.NewError(connect.CodeInternal, errors.New("repository of the token not found"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,18 +80,18 @@ func (s *Service) Register(
|
|||
AgentLabels: labels,
|
||||
}
|
||||
if err := runner.GenerateToken(); err != nil {
|
||||
return nil, errors.New("can't generate token")
|
||||
return nil, connect.NewError(connect.CodeInternal, errors.New("can't generate token"))
|
||||
}
|
||||
|
||||
// create new runner
|
||||
if err := actions_model.CreateRunner(ctx, runner); err != nil {
|
||||
return nil, errors.New("can't create new runner")
|
||||
return nil, connect.NewError(connect.CodeInternal, errors.New("can't create new runner"))
|
||||
}
|
||||
|
||||
// update token status
|
||||
runnerToken.IsActive = true
|
||||
if err := actions_model.UpdateRunnerToken(ctx, runnerToken, "is_active"); err != nil {
|
||||
return nil, errors.New("can't update runner token status")
|
||||
return nil, connect.NewError(connect.CodeInternal, errors.New("can't update runner token status"))
|
||||
}
|
||||
|
||||
res := connect.NewResponse(&runnerv1.RegisterResponse{
|
||||
|
@ -117,7 +116,7 @@ func (s *Service) Declare(
|
|||
runner.AgentLabels = req.Msg.Labels
|
||||
runner.Version = req.Msg.Version
|
||||
if err := actions_model.UpdateRunner(ctx, runner, "agent_labels", "version"); err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "update runner: %v", err)
|
||||
return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("update runner: %w", err))
|
||||
}
|
||||
|
||||
return connect.NewResponse(&runnerv1.DeclareResponse{
|
||||
|
@ -143,10 +142,10 @@ func (s *Service) FetchTask(
|
|||
tasksVersion := req.Msg.TasksVersion // task version from runner
|
||||
latestVersion, err := actions_model.GetTasksVersionByScope(ctx, runner.OwnerID, runner.RepoID)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "query tasks version failed: %v", err)
|
||||
return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("query tasks version failed: %w", err))
|
||||
} else if latestVersion == 0 {
|
||||
if err := actions_model.IncreaseTaskVersion(ctx, runner.OwnerID, runner.RepoID); err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "fail to increase task version: %v", err)
|
||||
return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("fail to increase task version: %w", err))
|
||||
}
|
||||
// if we don't increase the value of `latestVersion` here,
|
||||
// the response of FetchTask will return tasksVersion as zero.
|
||||
|
@ -160,7 +159,7 @@ func (s *Service) FetchTask(
|
|||
// try to pick a task for the runner that send the request.
|
||||
if t, ok, err := actions_service.PickTask(ctx, runner); err != nil {
|
||||
log.Error("pick task failed: %v", err)
|
||||
return nil, status.Errorf(codes.Internal, "pick task: %v", err)
|
||||
return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("pick task: %w", err))
|
||||
} else if ok {
|
||||
task = t
|
||||
}
|
||||
|
@ -181,7 +180,7 @@ func (s *Service) UpdateTask(
|
|||
|
||||
task, err := actions_model.UpdateTaskByState(ctx, runner.ID, req.Msg.State)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "update task: %v", err)
|
||||
return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("update task: %w", err))
|
||||
}
|
||||
|
||||
for k, v := range req.Msg.Outputs {
|
||||
|
@ -210,10 +209,10 @@ func (s *Service) UpdateTask(
|
|||
}
|
||||
|
||||
if err := task.LoadJob(ctx); err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "load job: %v", err)
|
||||
return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("load job: %w", err))
|
||||
}
|
||||
if err := task.Job.LoadRun(ctx); err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "load run: %v", err)
|
||||
return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("load run: %w", err))
|
||||
}
|
||||
|
||||
// don't create commit status for cron job
|
||||
|
@ -247,9 +246,9 @@ func (s *Service) UpdateLog(
|
|||
|
||||
task, err := actions_model.GetTaskByID(ctx, req.Msg.TaskId)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "get task: %v", err)
|
||||
return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("get task: %w", err))
|
||||
} else if runner.ID != task.RunnerID {
|
||||
return nil, status.Errorf(codes.Internal, "invalid runner for task")
|
||||
return nil, connect.NewError(connect.CodeInternal, errors.New("invalid runner for task"))
|
||||
}
|
||||
ack := task.LogLength
|
||||
|
||||
|
@ -259,13 +258,13 @@ func (s *Service) UpdateLog(
|
|||
}
|
||||
|
||||
if task.LogInStorage {
|
||||
return nil, status.Errorf(codes.AlreadyExists, "log file has been archived")
|
||||
return nil, connect.NewError(connect.CodeAlreadyExists, errors.New("log file has been archived"))
|
||||
}
|
||||
|
||||
rows := req.Msg.Rows[ack-req.Msg.Index:]
|
||||
ns, err := actions.WriteLogs(ctx, task.LogFilename, task.LogSize, rows)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "write logs: %v", err)
|
||||
return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("write logs: %w", err))
|
||||
}
|
||||
task.LogLength += int64(len(rows))
|
||||
for _, n := range ns {
|
||||
|
@ -280,12 +279,12 @@ func (s *Service) UpdateLog(
|
|||
task.LogInStorage = true
|
||||
remove, err = actions.TransferLogs(ctx, task.LogFilename)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "transfer logs: %v", err)
|
||||
return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("transfer logs: %w", err))
|
||||
}
|
||||
}
|
||||
|
||||
if err := actions_model.UpdateTask(ctx, task, "log_indexes", "log_length", "log_size", "log_in_storage"); err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "update task: %v", err)
|
||||
return nil, connect.NewError(connect.CodeInternal, fmt.Errorf("update task: %w", err))
|
||||
}
|
||||
if remove != nil {
|
||||
remove()
|
||||
|
|
|
@ -105,9 +105,11 @@ func ServePackageInfo(ctx *context.Context) {
|
|||
ctx, ctx.Package.Owner.ID, packages_model.TypeRubyGems, packageName)
|
||||
if err != nil {
|
||||
apiError(ctx, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
if len(versions) == 0 {
|
||||
apiError(ctx, http.StatusNotFound, fmt.Sprintf("Could not find package %s", packageName))
|
||||
return
|
||||
}
|
||||
|
||||
result, err := buildInfoFileForPackage(ctx, versions)
|
||||
|
@ -135,6 +137,7 @@ func ServeVersionsFile(ctx *context.Context) {
|
|||
ctx, ctx.Package.Owner.ID, packages_model.TypeRubyGems, pack.Name)
|
||||
if err != nil {
|
||||
apiError(ctx, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
if len(versions) == 0 {
|
||||
// No versions left for this package, we should continue.
|
||||
|
@ -144,6 +147,20 @@ func ServeVersionsFile(ctx *context.Context) {
|
|||
fmt.Fprintf(result, "%s ", pack.Name)
|
||||
for i, v := range versions {
|
||||
result.WriteString(v.Version)
|
||||
|
||||
pd, err := packages_model.GetPackageDescriptor(ctx, v)
|
||||
if err != nil {
|
||||
apiError(ctx, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
metadata := pd.Metadata.(*rubygems_module.Metadata)
|
||||
|
||||
if metadata.Platform != "ruby" {
|
||||
result.WriteString("_")
|
||||
result.WriteString(metadata.Platform)
|
||||
}
|
||||
|
||||
if i != len(versions)-1 {
|
||||
result.WriteString(",")
|
||||
}
|
||||
|
@ -152,6 +169,7 @@ func ServeVersionsFile(ctx *context.Context) {
|
|||
info, err := buildInfoFileForPackage(ctx, versions)
|
||||
if err != nil {
|
||||
apiError(ctx, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
checksum := md5.Sum([]byte(*info))
|
||||
|
@ -413,6 +431,11 @@ func buildRequirementStringFromVersion(ctx *context.Context, version *packages_m
|
|||
additionalRequirements.WriteString(",rubygems:")
|
||||
writeRequirements(metadata.RequiredRubygemsVersion, additionalRequirements)
|
||||
}
|
||||
|
||||
if metadata.Platform != "ruby" {
|
||||
return fmt.Sprintf("%s-%s %s|%s", version.Version, metadata.Platform, dependencyRequirements, additionalRequirements), nil
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s %s|%s", version.Version, dependencyRequirements, additionalRequirements), nil
|
||||
}
|
||||
|
||||
|
|
|
@ -397,6 +397,12 @@ func ListIssues(ctx *context.APIContext) {
|
|||
// in: query
|
||||
// description: page size of results
|
||||
// type: integer
|
||||
// - name: sort
|
||||
// in: query
|
||||
// description: Type of sort
|
||||
// type: string
|
||||
// enum: [relevance, latest, oldest, recentupdate, leastupdate, mostcomment, leastcomment, nearduedate, farduedate]
|
||||
// default: latest
|
||||
// responses:
|
||||
// "200":
|
||||
// "$ref": "#/responses/IssueList"
|
||||
|
@ -510,7 +516,7 @@ func ListIssues(ctx *context.APIContext) {
|
|||
RepoIDs: []int64{ctx.Repo.Repository.ID},
|
||||
IsPull: isPull,
|
||||
IsClosed: isClosed,
|
||||
SortBy: issue_indexer.SortByCreatedDesc,
|
||||
SortBy: issue_indexer.ParseSortBy(ctx.FormString("sort"), issue_indexer.SortByCreatedDesc),
|
||||
}
|
||||
if since != 0 {
|
||||
searchOpt.UpdatedAfterUnix = optional.Some(since)
|
||||
|
|
|
@ -101,8 +101,9 @@ func ListMyRepos(ctx *context.APIContext) {
|
|||
// type: integer
|
||||
// - name: order_by
|
||||
// in: query
|
||||
// description: order the repositories by name (default), id, or size
|
||||
// description: order the repositories
|
||||
// type: string
|
||||
// enum: [name, id, newest, oldest, recentupdate, leastupdate, reversealphabetically, alphabetically, reversesize, size, reversegitsize, gitsize, reverselfssize, lfssize, moststars, feweststars, mostforks, fewestforks]
|
||||
// responses:
|
||||
// "200":
|
||||
// "$ref": "#/responses/RepositoryList"
|
||||
|
@ -124,14 +125,15 @@ func ListMyRepos(ctx *context.APIContext) {
|
|||
switch orderBy {
|
||||
case "name":
|
||||
opts.OrderBy = "name ASC"
|
||||
case "size":
|
||||
opts.OrderBy = "size DESC"
|
||||
case "id":
|
||||
opts.OrderBy = "id ASC"
|
||||
case "":
|
||||
default:
|
||||
ctx.Error(http.StatusUnprocessableEntity, "", "invalid order_by")
|
||||
return
|
||||
if orderBy, ok := repo_model.OrderByFlatMap[orderBy]; ok {
|
||||
opts.OrderBy = orderBy
|
||||
} else if orderBy != "" {
|
||||
ctx.Error(http.StatusUnprocessableEntity, "", "invalid order_by")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
repos, count, err := repo_model.SearchRepository(ctx, opts)
|
||||
|
|
|
@ -298,14 +298,14 @@ func GetFeedType(name string, req *http.Request) (bool, string, string) {
|
|||
return false, name, ""
|
||||
}
|
||||
|
||||
// feedActionsToFeedItems convert gitea's Repo's Releases to feeds Item
|
||||
func releasesToFeedItems(ctx *context.Context, releases []*repo_model.Release) (items []*feeds.Item, err error) {
|
||||
for _, rel := range releases {
|
||||
err := rel.LoadAttributes(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// feedActionsToFeedItems convert repository releases into feed items.
|
||||
func releasesToFeedItems(ctx *context.Context, releases repo_model.ReleaseList) (items []*feeds.Item, err error) {
|
||||
if err := releases.LoadAttributes(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
composeCache := make(map[int64]map[string]string)
|
||||
for _, rel := range releases {
|
||||
var title string
|
||||
var content template.HTML
|
||||
|
||||
|
@ -315,13 +315,19 @@ func releasesToFeedItems(ctx *context.Context, releases []*repo_model.Release) (
|
|||
title = rel.Title
|
||||
}
|
||||
|
||||
metas, ok := composeCache[rel.RepoID]
|
||||
if !ok {
|
||||
metas = rel.Repo.ComposeMetas(ctx)
|
||||
composeCache[rel.RepoID] = metas
|
||||
}
|
||||
|
||||
link := &feeds.Link{Href: rel.HTMLURL()}
|
||||
content, err = markdown.RenderString(&markup.RenderContext{
|
||||
Ctx: ctx,
|
||||
Links: markup.Links{
|
||||
Base: rel.Repo.Link(),
|
||||
},
|
||||
Metas: rel.Repo.ComposeMetas(ctx),
|
||||
Metas: metas,
|
||||
}, rel.Note)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -20,6 +20,7 @@ import (
|
|||
"code.gitea.io/gitea/services/attachment"
|
||||
|
||||
"code.forgejo.org/f3/gof3/v3/f3"
|
||||
f3_id "code.forgejo.org/f3/gof3/v3/id"
|
||||
f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
|
||||
"code.forgejo.org/f3/gof3/v3/tree/generic"
|
||||
f3_util "code.forgejo.org/f3/gof3/v3/util"
|
||||
|
@ -131,7 +132,7 @@ func (o *asset) Patch(ctx context.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
func (o *asset) Put(ctx context.Context) generic.NodeID {
|
||||
func (o *asset) Put(ctx context.Context) f3_id.NodeID {
|
||||
node := o.GetNode()
|
||||
o.Trace("%s", node.GetID())
|
||||
|
||||
|
@ -154,7 +155,7 @@ func (o *asset) Put(ctx context.Context) generic.NodeID {
|
|||
}
|
||||
|
||||
o.Trace("asset created %d", o.forgejoAsset.ID)
|
||||
return generic.NewNodeID(o.forgejoAsset.ID)
|
||||
return f3_id.NewNodeID(o.forgejoAsset.ID)
|
||||
}
|
||||
|
||||
func (o *asset) Delete(ctx context.Context) {
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
"code.gitea.io/gitea/modules/timeutil"
|
||||
|
||||
"code.forgejo.org/f3/gof3/v3/f3"
|
||||
f3_id "code.forgejo.org/f3/gof3/v3/id"
|
||||
f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
|
||||
"code.forgejo.org/f3/gof3/v3/tree/generic"
|
||||
f3_util "code.forgejo.org/f3/gof3/v3/util"
|
||||
|
@ -95,7 +96,7 @@ func (o *comment) Patch(ctx context.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
func (o *comment) Put(ctx context.Context) generic.NodeID {
|
||||
func (o *comment) Put(ctx context.Context) f3_id.NodeID {
|
||||
node := o.GetNode()
|
||||
o.Trace("%s", node.GetID())
|
||||
|
||||
|
@ -105,7 +106,7 @@ func (o *comment) Put(ctx context.Context) generic.NodeID {
|
|||
panic(err)
|
||||
}
|
||||
o.Trace("comment created %d", o.forgejoComment.ID)
|
||||
return generic.NewNodeID(o.forgejoComment.ID)
|
||||
return f3_id.NewNodeID(o.forgejoComment.ID)
|
||||
}
|
||||
|
||||
func (o *comment) Delete(ctx context.Context) {
|
||||
|
|
|
@ -7,6 +7,7 @@ package driver
|
|||
import (
|
||||
"context"
|
||||
|
||||
f3_kind "code.forgejo.org/f3/gof3/v3/kind"
|
||||
"code.forgejo.org/f3/gof3/v3/tree/generic"
|
||||
)
|
||||
|
||||
|
@ -37,7 +38,7 @@ func (o *common) getPageSize() int {
|
|||
return o.getTreeDriver().GetPageSize()
|
||||
}
|
||||
|
||||
func (o *common) getKind() generic.Kind {
|
||||
func (o *common) getKind() f3_kind.Kind {
|
||||
return o.GetNode().GetKind()
|
||||
}
|
||||
|
||||
|
|
|
@ -8,8 +8,8 @@ import (
|
|||
"context"
|
||||
|
||||
"code.forgejo.org/f3/gof3/v3/f3"
|
||||
f3_id "code.forgejo.org/f3/gof3/v3/id"
|
||||
f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
|
||||
"code.forgejo.org/f3/gof3/v3/tree/generic"
|
||||
)
|
||||
|
||||
type container struct {
|
||||
|
@ -30,7 +30,7 @@ func (o *container) FromFormat(content f3.Interface) {
|
|||
|
||||
func (o *container) Get(context.Context) bool { return true }
|
||||
|
||||
func (o *container) Put(ctx context.Context) generic.NodeID {
|
||||
func (o *container) Put(ctx context.Context) f3_id.NodeID {
|
||||
return o.upsert(ctx)
|
||||
}
|
||||
|
||||
|
@ -38,6 +38,6 @@ func (o *container) Patch(ctx context.Context) {
|
|||
o.upsert(ctx)
|
||||
}
|
||||
|
||||
func (o *container) upsert(context.Context) generic.NodeID {
|
||||
return generic.NewNodeID(o.getKind())
|
||||
func (o *container) upsert(context.Context) f3_id.NodeID {
|
||||
return f3_id.NewNodeID(o.getKind())
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ import (
|
|||
user_model "code.gitea.io/gitea/models/user"
|
||||
|
||||
"code.forgejo.org/f3/gof3/v3/f3"
|
||||
f3_id "code.forgejo.org/f3/gof3/v3/id"
|
||||
f3_kind "code.forgejo.org/f3/gof3/v3/kind"
|
||||
f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
|
||||
"code.forgejo.org/f3/gof3/v3/tree/generic"
|
||||
"code.forgejo.org/f3/gof3/v3/util"
|
||||
|
@ -19,16 +21,16 @@ import (
|
|||
type forge struct {
|
||||
generic.NullDriver
|
||||
|
||||
ownersKind map[string]generic.Kind
|
||||
ownersKind map[string]f3_kind.Kind
|
||||
}
|
||||
|
||||
func newForge() generic.NodeDriverInterface {
|
||||
return &forge{
|
||||
ownersKind: make(map[string]generic.Kind),
|
||||
ownersKind: make(map[string]f3_kind.Kind),
|
||||
}
|
||||
}
|
||||
|
||||
func (o *forge) getOwnersKind(ctx context.Context, id string) generic.Kind {
|
||||
func (o *forge) getOwnersKind(ctx context.Context, id string) f3_kind.Kind {
|
||||
kind, ok := o.ownersKind[id]
|
||||
if !ok {
|
||||
user, err := user_model.GetUserByID(ctx, util.ParseInt(id))
|
||||
|
@ -50,7 +52,7 @@ func (o *forge) getOwnersPath(ctx context.Context, id string) f3_tree.Path {
|
|||
|
||||
func (o *forge) Equals(context.Context, generic.NodeInterface) bool { return true }
|
||||
func (o *forge) Get(context.Context) bool { return true }
|
||||
func (o *forge) Put(context.Context) generic.NodeID { return generic.NewNodeID("forge") }
|
||||
func (o *forge) Put(context.Context) f3_id.NodeID { return f3_id.NewNodeID("forge") }
|
||||
func (o *forge) Patch(context.Context) {}
|
||||
func (o *forge) Delete(context.Context) {}
|
||||
func (o *forge) NewFormat() f3.Interface { return &f3.Forge{} }
|
||||
|
|
|
@ -17,6 +17,7 @@ import (
|
|||
issue_service "code.gitea.io/gitea/services/issue"
|
||||
|
||||
"code.forgejo.org/f3/gof3/v3/f3"
|
||||
f3_id "code.forgejo.org/f3/gof3/v3/id"
|
||||
f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
|
||||
"code.forgejo.org/f3/gof3/v3/tree/generic"
|
||||
f3_util "code.forgejo.org/f3/gof3/v3/util"
|
||||
|
@ -210,7 +211,7 @@ func updateIssueLabels(ctx context.Context, issueID int64, labels []*issues_mode
|
|||
}
|
||||
}
|
||||
|
||||
func (o *issue) Put(ctx context.Context) generic.NodeID {
|
||||
func (o *issue) Put(ctx context.Context) f3_id.NodeID {
|
||||
node := o.GetNode()
|
||||
o.Trace("%s", node.GetID())
|
||||
|
||||
|
@ -232,7 +233,7 @@ func (o *issue) Put(ctx context.Context) generic.NodeID {
|
|||
updateIssueLabels(ctx, o.forgejoIssue.ID, o.forgejoIssue.Labels)
|
||||
|
||||
o.Trace("issue created %d/%d", o.forgejoIssue.ID, o.forgejoIssue.Index)
|
||||
return generic.NewNodeID(o.forgejoIssue.Index)
|
||||
return f3_id.NewNodeID(o.forgejoIssue.Index)
|
||||
}
|
||||
|
||||
func (o *issue) Delete(ctx context.Context) {
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
|
||||
"code.forgejo.org/f3/gof3/v3/f3"
|
||||
f3_id "code.forgejo.org/f3/gof3/v3/id"
|
||||
f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
|
||||
"code.forgejo.org/f3/gof3/v3/tree/generic"
|
||||
f3_util "code.forgejo.org/f3/gof3/v3/util"
|
||||
|
@ -86,7 +87,7 @@ func (o *label) Patch(ctx context.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
func (o *label) Put(ctx context.Context) generic.NodeID {
|
||||
func (o *label) Put(ctx context.Context) f3_id.NodeID {
|
||||
node := o.GetNode()
|
||||
o.Trace("%s", node.GetID())
|
||||
|
||||
|
@ -95,7 +96,7 @@ func (o *label) Put(ctx context.Context) generic.NodeID {
|
|||
panic(err)
|
||||
}
|
||||
o.Trace("label created %d", o.forgejoLabel.ID)
|
||||
return generic.NewNodeID(o.forgejoLabel.ID)
|
||||
return f3_id.NewNodeID(o.forgejoLabel.ID)
|
||||
}
|
||||
|
||||
func (o *label) Delete(ctx context.Context) {
|
||||
|
|
|
@ -15,6 +15,7 @@ import (
|
|||
"code.gitea.io/gitea/modules/timeutil"
|
||||
|
||||
"code.forgejo.org/f3/gof3/v3/f3"
|
||||
f3_id "code.forgejo.org/f3/gof3/v3/id"
|
||||
f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
|
||||
"code.forgejo.org/f3/gof3/v3/tree/generic"
|
||||
f3_util "code.forgejo.org/f3/gof3/v3/util"
|
||||
|
@ -122,7 +123,7 @@ func (o *milestone) Patch(ctx context.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
func (o *milestone) Put(ctx context.Context) generic.NodeID {
|
||||
func (o *milestone) Put(ctx context.Context) f3_id.NodeID {
|
||||
node := o.GetNode()
|
||||
o.Trace("%s", node.GetID())
|
||||
|
||||
|
@ -131,7 +132,7 @@ func (o *milestone) Put(ctx context.Context) generic.NodeID {
|
|||
panic(err)
|
||||
}
|
||||
o.Trace("milestone created %d", o.forgejoMilestone.ID)
|
||||
return generic.NewNodeID(o.forgejoMilestone.ID)
|
||||
return f3_id.NewNodeID(o.forgejoMilestone.ID)
|
||||
}
|
||||
|
||||
func (o *milestone) Delete(ctx context.Context) {
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
user_model "code.gitea.io/gitea/models/user"
|
||||
|
||||
"code.forgejo.org/f3/gof3/v3/f3"
|
||||
f3_id "code.forgejo.org/f3/gof3/v3/id"
|
||||
f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
|
||||
"code.forgejo.org/f3/gof3/v3/tree/generic"
|
||||
f3_util "code.forgejo.org/f3/gof3/v3/util"
|
||||
|
@ -81,7 +82,7 @@ func (o *organization) Patch(ctx context.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
func (o *organization) Put(ctx context.Context) generic.NodeID {
|
||||
func (o *organization) Put(ctx context.Context) f3_id.NodeID {
|
||||
node := o.GetNode()
|
||||
o.Trace("%s", node.GetID())
|
||||
|
||||
|
@ -94,7 +95,7 @@ func (o *organization) Put(ctx context.Context) generic.NodeID {
|
|||
panic(err)
|
||||
}
|
||||
|
||||
return generic.NewNodeID(o.forgejoOrganization.ID)
|
||||
return f3_id.NewNodeID(o.forgejoOrganization.ID)
|
||||
}
|
||||
|
||||
func (o *organization) Delete(ctx context.Context) {
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
org_model "code.gitea.io/gitea/models/organization"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
|
||||
f3_id "code.forgejo.org/f3/gof3/v3/id"
|
||||
f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
|
||||
"code.forgejo.org/f3/gof3/v3/tree/generic"
|
||||
)
|
||||
|
@ -36,13 +37,13 @@ func (o *organizations) ListPage(ctx context.Context, page int) generic.Children
|
|||
return f3_tree.ConvertListed(ctx, o.GetNode(), f3_tree.ConvertToAny(organizations...)...)
|
||||
}
|
||||
|
||||
func (o *organizations) GetIDFromName(ctx context.Context, name string) generic.NodeID {
|
||||
func (o *organizations) GetIDFromName(ctx context.Context, name string) f3_id.NodeID {
|
||||
organization, err := org_model.GetOrgByName(ctx, name)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("GetOrganizationByName: %v", err))
|
||||
}
|
||||
|
||||
return generic.NewNodeID(organization.ID)
|
||||
return f3_id.NewNodeID(organization.ID)
|
||||
}
|
||||
|
||||
func newOrganizations() generic.NodeDriverInterface {
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
repo_service "code.gitea.io/gitea/services/repository"
|
||||
|
||||
"code.forgejo.org/f3/gof3/v3/f3"
|
||||
f3_id "code.forgejo.org/f3/gof3/v3/id"
|
||||
f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
|
||||
"code.forgejo.org/f3/gof3/v3/tree/generic"
|
||||
f3_util "code.forgejo.org/f3/gof3/v3/util"
|
||||
|
@ -121,7 +122,7 @@ func (o *project) Patch(ctx context.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
func (o *project) Put(ctx context.Context) generic.NodeID {
|
||||
func (o *project) Put(ctx context.Context) f3_id.NodeID {
|
||||
node := o.GetNode()
|
||||
o.Trace("%s", node.GetID())
|
||||
|
||||
|
@ -166,7 +167,7 @@ func (o *project) Put(ctx context.Context) generic.NodeID {
|
|||
o.forgejoProject = repo
|
||||
o.Trace("project created %d", o.forgejoProject.ID)
|
||||
}
|
||||
return generic.NewNodeID(o.forgejoProject.ID)
|
||||
return f3_id.NewNodeID(o.forgejoProject.ID)
|
||||
}
|
||||
|
||||
func (o *project) Delete(ctx context.Context) {
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"code.gitea.io/gitea/models/db"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
|
||||
f3_id "code.forgejo.org/f3/gof3/v3/id"
|
||||
f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
|
||||
"code.forgejo.org/f3/gof3/v3/tree/generic"
|
||||
)
|
||||
|
@ -19,18 +20,18 @@ type projects struct {
|
|||
container
|
||||
}
|
||||
|
||||
func (o *projects) GetIDFromName(ctx context.Context, name string) generic.NodeID {
|
||||
func (o *projects) GetIDFromName(ctx context.Context, name string) f3_id.NodeID {
|
||||
owner := f3_tree.GetOwnerName(o.GetNode())
|
||||
forgejoProject, err := repo_model.GetRepositoryByOwnerAndName(ctx, owner, name)
|
||||
if repo_model.IsErrRepoNotExist(err) {
|
||||
return generic.NilID
|
||||
return f3_id.NilID
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("error GetRepositoryByOwnerAndName(%s, %s): %v", owner, name, err))
|
||||
}
|
||||
|
||||
return generic.NewNodeID(forgejoProject.ID)
|
||||
return f3_id.NewNodeID(forgejoProject.ID)
|
||||
}
|
||||
|
||||
func (o *projects) ListPage(ctx context.Context, page int) generic.ChildrenSlice {
|
||||
|
|
|
@ -18,6 +18,8 @@ import (
|
|||
issue_service "code.gitea.io/gitea/services/issue"
|
||||
|
||||
"code.forgejo.org/f3/gof3/v3/f3"
|
||||
f3_id "code.forgejo.org/f3/gof3/v3/id"
|
||||
f3_path "code.forgejo.org/f3/gof3/v3/path"
|
||||
f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
|
||||
"code.forgejo.org/f3/gof3/v3/tree/generic"
|
||||
f3_util "code.forgejo.org/f3/gof3/v3/util"
|
||||
|
@ -51,7 +53,7 @@ func (o *pullRequest) repositoryToReference(ctx context.Context, repository *rep
|
|||
if repository == nil {
|
||||
panic("unexpected nil repository")
|
||||
}
|
||||
forge := o.getTree().GetRoot().GetChild(generic.NewNodeID(f3_tree.KindForge)).GetDriver().(*forge)
|
||||
forge := o.getTree().GetRoot().GetChild(f3_id.NewNodeID(f3_tree.KindForge)).GetDriver().(*forge)
|
||||
owners := forge.getOwnersPath(ctx, fmt.Sprintf("%d", repository.OwnerID))
|
||||
return f3_tree.NewRepositoryReference(owners.String(), repository.OwnerID, repository.ID)
|
||||
}
|
||||
|
@ -61,7 +63,7 @@ func (o *pullRequest) referenceToRepository(reference *f3.Reference) int64 {
|
|||
if reference.Get() == "../../repository/vcs" {
|
||||
project = f3_tree.GetProjectID(o.GetNode())
|
||||
} else {
|
||||
p := f3_tree.ToPath(generic.PathAbsolute(o.GetNode().GetCurrentPath().String(), reference.Get()))
|
||||
p := f3_tree.ToPath(f3_path.PathAbsolute(generic.NewElementNode, o.GetNode().GetCurrentPath().String(), reference.Get()))
|
||||
o.Trace("%v %v", o.GetNode().GetCurrentPath().String(), p)
|
||||
_, project = p.OwnerAndProjectID()
|
||||
}
|
||||
|
@ -237,7 +239,7 @@ func (o *pullRequest) GetPullRequestRef() string {
|
|||
return fmt.Sprintf("refs/pull/%s/head", o.GetNativeID())
|
||||
}
|
||||
|
||||
func (o *pullRequest) Put(ctx context.Context) generic.NodeID {
|
||||
func (o *pullRequest) Put(ctx context.Context) f3_id.NodeID {
|
||||
node := o.GetNode()
|
||||
o.Trace("%s", node.GetID())
|
||||
|
||||
|
@ -289,7 +291,7 @@ func (o *pullRequest) Put(ctx context.Context) generic.NodeID {
|
|||
}
|
||||
|
||||
o.Trace("pullRequest created %d/%d", o.forgejoPullRequest.ID, o.forgejoPullRequest.Index)
|
||||
return generic.NewNodeID(o.forgejoPullRequest.Index)
|
||||
return f3_id.NewNodeID(o.forgejoPullRequest.Index)
|
||||
}
|
||||
|
||||
func (o *pullRequest) Delete(ctx context.Context) {
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
user_model "code.gitea.io/gitea/models/user"
|
||||
|
||||
"code.forgejo.org/f3/gof3/v3/f3"
|
||||
f3_id "code.forgejo.org/f3/gof3/v3/id"
|
||||
f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
|
||||
"code.forgejo.org/f3/gof3/v3/tree/generic"
|
||||
f3_util "code.forgejo.org/f3/gof3/v3/util"
|
||||
|
@ -87,7 +88,7 @@ func (o *reaction) Patch(ctx context.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
func (o *reaction) Put(ctx context.Context) generic.NodeID {
|
||||
func (o *reaction) Put(ctx context.Context) f3_id.NodeID {
|
||||
o.Error("%v", o.forgejoReaction.User)
|
||||
|
||||
sess := db.GetEngine(ctx)
|
||||
|
@ -115,7 +116,7 @@ func (o *reaction) Put(ctx context.Context) generic.NodeID {
|
|||
panic(err)
|
||||
}
|
||||
o.Trace("reaction created %d", o.forgejoReaction.ID)
|
||||
return generic.NewNodeID(o.forgejoReaction.ID)
|
||||
return f3_id.NewNodeID(o.forgejoReaction.ID)
|
||||
}
|
||||
|
||||
func (o *reaction) Delete(ctx context.Context) {
|
||||
|
|
|
@ -17,6 +17,7 @@ import (
|
|||
release_service "code.gitea.io/gitea/services/release"
|
||||
|
||||
"code.forgejo.org/f3/gof3/v3/f3"
|
||||
f3_id "code.forgejo.org/f3/gof3/v3/id"
|
||||
f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
|
||||
"code.forgejo.org/f3/gof3/v3/tree/generic"
|
||||
f3_util "code.forgejo.org/f3/gof3/v3/util"
|
||||
|
@ -115,7 +116,7 @@ func (o *release) Patch(ctx context.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
func (o *release) Put(ctx context.Context) generic.NodeID {
|
||||
func (o *release) Put(ctx context.Context) f3_id.NodeID {
|
||||
node := o.GetNode()
|
||||
o.Trace("%s", node.GetID())
|
||||
|
||||
|
@ -133,7 +134,7 @@ func (o *release) Put(ctx context.Context) generic.NodeID {
|
|||
panic(err)
|
||||
}
|
||||
o.Trace("release created %d", o.forgejoRelease.ID)
|
||||
return generic.NewNodeID(o.forgejoRelease.ID)
|
||||
return f3_id.NewNodeID(o.forgejoRelease.ID)
|
||||
}
|
||||
|
||||
func (o *release) Delete(ctx context.Context) {
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
|
||||
"code.forgejo.org/f3/gof3/v3/f3"
|
||||
helpers_repository "code.forgejo.org/f3/gof3/v3/forges/helpers/repository"
|
||||
f3_id "code.forgejo.org/f3/gof3/v3/id"
|
||||
f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
|
||||
"code.forgejo.org/f3/gof3/v3/tree/generic"
|
||||
)
|
||||
|
@ -57,7 +58,7 @@ func (o *repository) Get(ctx context.Context) bool {
|
|||
return o.h.Get(ctx)
|
||||
}
|
||||
|
||||
func (o *repository) Put(ctx context.Context) generic.NodeID {
|
||||
func (o *repository) Put(ctx context.Context) f3_id.NodeID {
|
||||
return o.upsert(ctx)
|
||||
}
|
||||
|
||||
|
@ -65,10 +66,10 @@ func (o *repository) Patch(ctx context.Context) {
|
|||
o.upsert(ctx)
|
||||
}
|
||||
|
||||
func (o *repository) upsert(ctx context.Context) generic.NodeID {
|
||||
func (o *repository) upsert(ctx context.Context) f3_id.NodeID {
|
||||
o.Trace("%s", o.GetNativeID())
|
||||
o.h.Upsert(ctx, o.f)
|
||||
return generic.NewNodeID(o.f.Name)
|
||||
return f3_id.NewNodeID(o.f.Name)
|
||||
}
|
||||
|
||||
func (o *repository) SetFetchFunc(fetchFunc func(ctx context.Context, destination string, internalRefs []string)) {
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
"code.gitea.io/gitea/modules/timeutil"
|
||||
|
||||
"code.forgejo.org/f3/gof3/v3/f3"
|
||||
f3_id "code.forgejo.org/f3/gof3/v3/id"
|
||||
f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
|
||||
"code.forgejo.org/f3/gof3/v3/tree/generic"
|
||||
f3_util "code.forgejo.org/f3/gof3/v3/util"
|
||||
|
@ -134,7 +135,7 @@ func (o *review) Patch(ctx context.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
func (o *review) Put(ctx context.Context) generic.NodeID {
|
||||
func (o *review) Put(ctx context.Context) f3_id.NodeID {
|
||||
node := o.GetNode()
|
||||
o.Trace("%s", node.GetID())
|
||||
|
||||
|
@ -153,7 +154,7 @@ func (o *review) Put(ctx context.Context) generic.NodeID {
|
|||
panic(err)
|
||||
}
|
||||
o.Trace("review created %d", o.forgejoReview.ID)
|
||||
return generic.NewNodeID(o.forgejoReview.ID)
|
||||
return f3_id.NewNodeID(o.forgejoReview.ID)
|
||||
}
|
||||
|
||||
func (o *review) Delete(ctx context.Context) {
|
||||
|
|
|
@ -15,6 +15,7 @@ import (
|
|||
"code.gitea.io/gitea/modules/timeutil"
|
||||
|
||||
"code.forgejo.org/f3/gof3/v3/f3"
|
||||
f3_id "code.forgejo.org/f3/gof3/v3/id"
|
||||
f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
|
||||
"code.forgejo.org/f3/gof3/v3/tree/generic"
|
||||
f3_util "code.forgejo.org/f3/gof3/v3/util"
|
||||
|
@ -115,7 +116,7 @@ func (o *reviewComment) Patch(ctx context.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
func (o *reviewComment) Put(ctx context.Context) generic.NodeID {
|
||||
func (o *reviewComment) Put(ctx context.Context) f3_id.NodeID {
|
||||
node := o.GetNode()
|
||||
o.Trace("%s", node.GetID())
|
||||
|
||||
|
@ -125,7 +126,7 @@ func (o *reviewComment) Put(ctx context.Context) generic.NodeID {
|
|||
panic(err)
|
||||
}
|
||||
o.Trace("reviewComment created %d", o.forgejoReviewComment.ID)
|
||||
return generic.NewNodeID(o.forgejoReviewComment.ID)
|
||||
return f3_id.NewNodeID(o.forgejoReviewComment.ID)
|
||||
}
|
||||
|
||||
func (o *reviewComment) Delete(ctx context.Context) {
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"context"
|
||||
|
||||
"code.forgejo.org/f3/gof3/v3/f3"
|
||||
f3_id "code.forgejo.org/f3/gof3/v3/id"
|
||||
"code.forgejo.org/f3/gof3/v3/tree/generic"
|
||||
)
|
||||
|
||||
|
@ -33,8 +34,8 @@ func (o *root) ToFormat() f3.Interface {
|
|||
|
||||
func (o *root) Get(context.Context) bool { return true }
|
||||
|
||||
func (o *root) Put(context.Context) generic.NodeID {
|
||||
return generic.NilID
|
||||
func (o *root) Put(context.Context) f3_id.NodeID {
|
||||
return f3_id.NilID
|
||||
}
|
||||
|
||||
func (o *root) Patch(context.Context) {
|
||||
|
|
|
@ -9,8 +9,8 @@ import (
|
|||
|
||||
driver_options "code.gitea.io/gitea/services/f3/driver/options"
|
||||
|
||||
f3_kind "code.forgejo.org/f3/gof3/v3/kind"
|
||||
"code.forgejo.org/f3/gof3/v3/options"
|
||||
"code.forgejo.org/f3/gof3/v3/tree/generic"
|
||||
forge_test "code.forgejo.org/f3/gof3/v3/tree/tests/f3/forge"
|
||||
)
|
||||
|
||||
|
@ -22,8 +22,8 @@ func (o *forgeTest) NewOptions(t *testing.T) options.Interface {
|
|||
return newTestOptions(t)
|
||||
}
|
||||
|
||||
func (o *forgeTest) GetExceptions() []generic.Kind {
|
||||
return []generic.Kind{}
|
||||
func (o *forgeTest) GetExceptions() []f3_kind.Kind {
|
||||
return []f3_kind.Kind{}
|
||||
}
|
||||
|
||||
func (o *forgeTest) GetNonTestUsers() []string {
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
|
||||
"code.forgejo.org/f3/gof3/v3/f3"
|
||||
f3_id "code.forgejo.org/f3/gof3/v3/id"
|
||||
f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
|
||||
"code.forgejo.org/f3/gof3/v3/tree/generic"
|
||||
f3_util "code.forgejo.org/f3/gof3/v3/util"
|
||||
|
@ -79,14 +80,14 @@ func (o *topic) Patch(ctx context.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
func (o *topic) Put(ctx context.Context) generic.NodeID {
|
||||
func (o *topic) Put(ctx context.Context) f3_id.NodeID {
|
||||
sess := db.GetEngine(ctx)
|
||||
|
||||
if _, err := sess.Insert(o.forgejoTopic); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
o.Trace("topic created %d", o.forgejoTopic.ID)
|
||||
return generic.NewNodeID(o.forgejoTopic.ID)
|
||||
return f3_id.NewNodeID(o.forgejoTopic.ID)
|
||||
}
|
||||
|
||||
func (o *topic) Delete(ctx context.Context) {
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
|
||||
forgejo_options "code.gitea.io/gitea/services/f3/driver/options"
|
||||
|
||||
f3_kind "code.forgejo.org/f3/gof3/v3/kind"
|
||||
f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
|
||||
"code.forgejo.org/f3/gof3/v3/tree/generic"
|
||||
)
|
||||
|
@ -24,7 +25,7 @@ func (o *treeDriver) Init() {
|
|||
o.NullTreeDriver.Init()
|
||||
}
|
||||
|
||||
func (o *treeDriver) Factory(ctx context.Context, kind generic.Kind) generic.NodeDriverInterface {
|
||||
func (o *treeDriver) Factory(ctx context.Context, kind f3_kind.Kind) generic.NodeDriverInterface {
|
||||
switch kind {
|
||||
case f3_tree.KindForge:
|
||||
return newForge()
|
||||
|
@ -88,7 +89,7 @@ func (o *treeDriver) Factory(ctx context.Context, kind generic.Kind) generic.Nod
|
|||
return newRepositories()
|
||||
case f3_tree.KindRepository:
|
||||
return newRepository(ctx)
|
||||
case generic.KindRoot:
|
||||
case f3_kind.KindRoot:
|
||||
return newRoot(o.GetTree().(f3_tree.TreeInterface).NewFormat(kind))
|
||||
default:
|
||||
panic(fmt.Errorf("unexpected kind %s", kind))
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
user_service "code.gitea.io/gitea/services/user"
|
||||
|
||||
"code.forgejo.org/f3/gof3/v3/f3"
|
||||
f3_id "code.forgejo.org/f3/gof3/v3/id"
|
||||
f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
|
||||
"code.forgejo.org/f3/gof3/v3/tree/generic"
|
||||
f3_util "code.forgejo.org/f3/gof3/v3/util"
|
||||
|
@ -96,9 +97,9 @@ func (o *user) Get(ctx context.Context) bool {
|
|||
func (o *user) Patch(context.Context) {
|
||||
}
|
||||
|
||||
func (o *user) Put(ctx context.Context) generic.NodeID {
|
||||
func (o *user) Put(ctx context.Context) f3_id.NodeID {
|
||||
if user := getSystemUserByName(o.forgejoUser.Name); user != nil {
|
||||
return generic.NewNodeID(user.ID)
|
||||
return f3_id.NewNodeID(user.ID)
|
||||
}
|
||||
|
||||
o.forgejoUser.LowerName = strings.ToLower(o.forgejoUser.Name)
|
||||
|
@ -111,7 +112,7 @@ func (o *user) Put(ctx context.Context) generic.NodeID {
|
|||
panic(err)
|
||||
}
|
||||
|
||||
return generic.NewNodeID(o.forgejoUser.ID)
|
||||
return f3_id.NewNodeID(o.forgejoUser.ID)
|
||||
}
|
||||
|
||||
func (o *user) Delete(ctx context.Context) {
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"code.gitea.io/gitea/models/db"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
|
||||
f3_id "code.forgejo.org/f3/gof3/v3/id"
|
||||
f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
|
||||
"code.forgejo.org/f3/gof3/v3/tree/generic"
|
||||
)
|
||||
|
@ -34,13 +35,13 @@ func (o *users) ListPage(ctx context.Context, page int) generic.ChildrenSlice {
|
|||
return f3_tree.ConvertListed(ctx, o.GetNode(), f3_tree.ConvertToAny(users...)...)
|
||||
}
|
||||
|
||||
func (o *users) GetIDFromName(ctx context.Context, name string) generic.NodeID {
|
||||
func (o *users) GetIDFromName(ctx context.Context, name string) f3_id.NodeID {
|
||||
user, err := user_model.GetUserByName(ctx, name)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("GetUserByName: %v", err))
|
||||
}
|
||||
|
||||
return generic.NewNodeID(user.ID)
|
||||
return f3_id.NewNodeID(user.ID)
|
||||
}
|
||||
|
||||
func newUsers() generic.NodeDriverInterface {
|
||||
|
|
|
@ -1381,10 +1381,8 @@ func GetWhitespaceFlag(whitespaceBehavior string) git.TrustedCmdArgs {
|
|||
"ignore-eol": {"--ignore-space-at-eol"},
|
||||
"show-all": nil,
|
||||
}
|
||||
|
||||
if flag, ok := whitespaceFlags[whitespaceBehavior]; ok {
|
||||
return flag
|
||||
}
|
||||
log.Warn("unknown whitespace behavior: %q, default to 'show-all'", whitespaceBehavior)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import (
|
|||
repo_module "code.gitea.io/gitea/modules/repository"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
issue_service "code.gitea.io/gitea/services/issue"
|
||||
notify_service "code.gitea.io/gitea/services/notify"
|
||||
pull_service "code.gitea.io/gitea/services/pull"
|
||||
|
@ -133,23 +134,26 @@ func pushUpdates(optsList []*repo_module.PushUpdateOptions) error {
|
|||
} else { // is new tag
|
||||
newCommit, err := gitRepo.GetCommit(opts.NewCommitID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("gitRepo.GetCommit(%s) in %s/%s[%d]: %w", opts.NewCommitID, repo.OwnerName, repo.Name, repo.ID, err)
|
||||
// in case there is dirty data, for example, the "github.com/git/git" repository has tags pointing to non-existing commits
|
||||
if !errors.Is(err, util.ErrNotExist) {
|
||||
log.Error("Unable to get tag commit: gitRepo.GetCommit(%s) in %s/%s[%d]: %v", opts.NewCommitID, repo.OwnerName, repo.Name, repo.ID, err)
|
||||
}
|
||||
} else {
|
||||
commits := repo_module.NewPushCommits()
|
||||
commits.HeadCommit = repo_module.CommitToPushCommit(newCommit)
|
||||
commits.CompareURL = repo.ComposeCompareURL(objectFormat.EmptyObjectID().String(), opts.NewCommitID)
|
||||
|
||||
notify_service.PushCommits(
|
||||
ctx, pusher, repo,
|
||||
&repo_module.PushUpdateOptions{
|
||||
RefFullName: opts.RefFullName,
|
||||
OldCommitID: objectFormat.EmptyObjectID().String(),
|
||||
NewCommitID: opts.NewCommitID,
|
||||
}, commits)
|
||||
|
||||
addTags = append(addTags, tagName)
|
||||
notify_service.CreateRef(ctx, pusher, repo, opts.RefFullName, opts.NewCommitID)
|
||||
}
|
||||
|
||||
commits := repo_module.NewPushCommits()
|
||||
commits.HeadCommit = repo_module.CommitToPushCommit(newCommit)
|
||||
commits.CompareURL = repo.ComposeCompareURL(objectFormat.EmptyObjectID().String(), opts.NewCommitID)
|
||||
|
||||
notify_service.PushCommits(
|
||||
ctx, pusher, repo,
|
||||
&repo_module.PushUpdateOptions{
|
||||
RefFullName: opts.RefFullName,
|
||||
OldCommitID: objectFormat.EmptyObjectID().String(),
|
||||
NewCommitID: opts.NewCommitID,
|
||||
}, commits)
|
||||
|
||||
addTags = append(addTags, tagName)
|
||||
notify_service.CreateRef(ctx, pusher, repo, opts.RefFullName, opts.NewCommitID)
|
||||
}
|
||||
} else if opts.RefFullName.IsBranch() {
|
||||
if pusher == nil || pusher.ID != opts.PusherID {
|
||||
|
|
|
@ -20,12 +20,6 @@
|
|||
<link rel="icon" href="{{AssetUrlPrefix}}/img/favicon.svg" type="image/svg+xml">
|
||||
<link rel="alternate icon" href="{{AssetUrlPrefix}}/img/favicon.png" type="image/png">
|
||||
{{template "base/head_script" .}}
|
||||
<noscript>
|
||||
<style>
|
||||
.dropdown:hover > .menu { display: block; }
|
||||
.ui.secondary.menu .dropdown.item > .menu { margin-top: 0; }
|
||||
</style>
|
||||
</noscript>
|
||||
{{template "shared/user/mention_highlight" .}}
|
||||
{{template "base/head_opengraph" .}}
|
||||
{{template "base/head_style" .}}
|
||||
|
|
40
templates/swagger/v1_json.tmpl
generated
40
templates/swagger/v1_json.tmpl
generated
|
@ -8628,6 +8628,24 @@
|
|||
"description": "page size of results",
|
||||
"name": "limit",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"enum": [
|
||||
"relevance",
|
||||
"latest",
|
||||
"oldest",
|
||||
"recentupdate",
|
||||
"leastupdate",
|
||||
"mostcomment",
|
||||
"leastcomment",
|
||||
"nearduedate",
|
||||
"farduedate"
|
||||
],
|
||||
"type": "string",
|
||||
"default": "latest",
|
||||
"description": "Type of sort",
|
||||
"name": "sort",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
|
@ -19343,8 +19361,28 @@
|
|||
"in": "query"
|
||||
},
|
||||
{
|
||||
"enum": [
|
||||
"name",
|
||||
"id",
|
||||
"newest",
|
||||
"oldest",
|
||||
"recentupdate",
|
||||
"leastupdate",
|
||||
"reversealphabetically",
|
||||
"alphabetically",
|
||||
"reversesize",
|
||||
"size",
|
||||
"reversegitsize",
|
||||
"gitsize",
|
||||
"reverselfssize",
|
||||
"lfssize",
|
||||
"moststars",
|
||||
"feweststars",
|
||||
"mostforks",
|
||||
"fewestforks"
|
||||
],
|
||||
"type": "string",
|
||||
"description": "order the repositories by name (default), id, or size",
|
||||
"description": "order the repositories",
|
||||
"name": "order_by",
|
||||
"in": "query"
|
||||
}
|
||||
|
|
|
@ -74,6 +74,50 @@ func TestAPIListIssues(t *testing.T) {
|
|||
if assert.Len(t, apiIssues, 1) {
|
||||
assert.EqualValues(t, 1, apiIssues[0].ID)
|
||||
}
|
||||
|
||||
t.Run("Sort", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
link.RawQuery = url.Values{"token": {token}, "sort": {"oldest"}}.Encode()
|
||||
resp = MakeRequest(t, NewRequest(t, "GET", link.String()), http.StatusOK)
|
||||
DecodeJSON(t, resp, &apiIssues)
|
||||
if assert.Len(t, apiIssues, 4) {
|
||||
assert.EqualValues(t, 1, apiIssues[0].ID)
|
||||
assert.EqualValues(t, 2, apiIssues[1].ID)
|
||||
assert.EqualValues(t, 3, apiIssues[2].ID)
|
||||
assert.EqualValues(t, 11, apiIssues[3].ID)
|
||||
}
|
||||
|
||||
link.RawQuery = url.Values{"token": {token}, "sort": {"newest"}}.Encode()
|
||||
resp = MakeRequest(t, NewRequest(t, "GET", link.String()), http.StatusOK)
|
||||
DecodeJSON(t, resp, &apiIssues)
|
||||
if assert.Len(t, apiIssues, 4) {
|
||||
assert.EqualValues(t, 11, apiIssues[0].ID)
|
||||
assert.EqualValues(t, 3, apiIssues[1].ID)
|
||||
assert.EqualValues(t, 2, apiIssues[2].ID)
|
||||
assert.EqualValues(t, 1, apiIssues[3].ID)
|
||||
}
|
||||
|
||||
link.RawQuery = url.Values{"token": {token}, "sort": {"recentupdate"}}.Encode()
|
||||
resp = MakeRequest(t, NewRequest(t, "GET", link.String()), http.StatusOK)
|
||||
DecodeJSON(t, resp, &apiIssues)
|
||||
if assert.Len(t, apiIssues, 4) {
|
||||
assert.EqualValues(t, 11, apiIssues[0].ID)
|
||||
assert.EqualValues(t, 1, apiIssues[1].ID)
|
||||
assert.EqualValues(t, 2, apiIssues[2].ID)
|
||||
assert.EqualValues(t, 3, apiIssues[3].ID)
|
||||
}
|
||||
|
||||
link.RawQuery = url.Values{"token": {token}, "sort": {"leastupdate"}}.Encode()
|
||||
resp = MakeRequest(t, NewRequest(t, "GET", link.String()), http.StatusOK)
|
||||
DecodeJSON(t, resp, &apiIssues)
|
||||
if assert.Len(t, apiIssues, 4) {
|
||||
assert.EqualValues(t, 3, apiIssues[0].ID)
|
||||
assert.EqualValues(t, 2, apiIssues[1].ID)
|
||||
assert.EqualValues(t, 1, apiIssues[2].ID)
|
||||
assert.EqualValues(t, 11, apiIssues[3].ID)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestAPIListIssuesPublicOnly(t *testing.T) {
|
||||
|
|
|
@ -201,6 +201,137 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==`)
|
||||
holaChecksum := fmt.Sprintf("%x", sha256.Sum256(holaGemContent))
|
||||
|
||||
binaryPackageName := "debug_inspector"
|
||||
binaryPackageVersion := "0.0.3"
|
||||
binaryRubyGemsRequirements := "ruby:~> 3.1.0"
|
||||
binaryGemContent, _ := base64.StdEncoding.DecodeString(`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
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==`)
|
||||
binaryChecksum := fmt.Sprintf("%x", sha256.Sum256(binaryGemContent))
|
||||
|
||||
root := fmt.Sprintf("/api/packages/%s/rubygems", user.Name)
|
||||
|
||||
uploadFile := func(t *testing.T, content []byte, expectedStatus int) {
|
||||
|
@ -234,6 +365,8 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==`)
|
|||
pb, err := packages.GetBlobByID(db.DefaultContext, pfs[0].BlobID)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, int64(4608), pb.Size)
|
||||
|
||||
assert.Equal(t, "ruby", pd.Metadata.(*rubygems.Metadata).Platform)
|
||||
})
|
||||
|
||||
t.Run("UploadExists", func(t *testing.T) {
|
||||
|
@ -322,6 +455,33 @@ gAAAAP//MS06Gw==`)
|
|||
sep, holaPackageVersion, holaPackageDependency, holaChecksum, holaRubyGemsRequirements)
|
||||
assert.Equal(t, expected, resp.Body.String())
|
||||
})
|
||||
|
||||
t.Run("UploadBinary", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
uploadFile(t, binaryGemContent, http.StatusCreated)
|
||||
|
||||
pvs, err := packages.GetVersionsByPackageName(db.DefaultContext, user.ID, packages.TypeRubyGems, binaryPackageName)
|
||||
require.NoError(t, err)
|
||||
|
||||
pd, err := packages.GetPackageDescriptor(db.DefaultContext, pvs[0])
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, binaryPackageName, pd.Package.Name)
|
||||
assert.Equal(t, "x86_64-linux-musl", pd.Metadata.(*rubygems.Metadata).Platform)
|
||||
})
|
||||
|
||||
t.Run("BinaryPackageInfo", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
req := NewRequest(t, "GET", fmt.Sprintf("%s/info/%s", root, binaryPackageName)).
|
||||
AddBasicAuth(user.Name)
|
||||
resp := MakeRequest(t, req, http.StatusOK)
|
||||
expected := fmt.Sprintf("%s\n%s-x86_64-linux-musl |checksum:%s,%s\n",
|
||||
sep, binaryPackageVersion, binaryChecksum, binaryRubyGemsRequirements)
|
||||
assert.Equal(t, expected, resp.Body.String())
|
||||
})
|
||||
|
||||
t.Run("Versions", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
|
@ -334,12 +494,16 @@ gAAAAP//MS06Gw==`)
|
|||
holaInfoReq := NewRequest(t, "GET", fmt.Sprintf("%s/info/%s", root, holaPackageName)).
|
||||
AddBasicAuth(user.Name)
|
||||
holaInfoResp := MakeRequest(t, holaInfoReq, http.StatusOK)
|
||||
binaryInfoReq := NewRequest(t, "GET", fmt.Sprintf("%s/info/%s", root, binaryPackageName)).
|
||||
AddBasicAuth(user.Name)
|
||||
binaryInfoResp := MakeRequest(t, binaryInfoReq, http.StatusOK)
|
||||
|
||||
// expected := fmt.Sprintf("%s\n%s %s %x\n",
|
||||
// sep, packageName, packageVersion, md5.Sum(infoResp.Body.Bytes()))
|
||||
lines := versionsResp.Body.String()
|
||||
assert.ElementsMatch(t, strings.Split(lines, "\n"), []string{
|
||||
sep,
|
||||
fmt.Sprintf("%s %s_x86_64-linux-musl %x", binaryPackageName, binaryPackageVersion, md5.Sum(binaryInfoResp.Body.Bytes())),
|
||||
fmt.Sprintf("%s %s %x", packageName, packageVersion, md5.Sum(infoResp.Body.Bytes())),
|
||||
fmt.Sprintf("%s %s %x", holaPackageName, holaPackageVersion, md5.Sum(holaInfoResp.Body.Bytes())),
|
||||
"",
|
||||
|
@ -361,6 +525,21 @@ gAAAAP//MS06Gw==`)
|
|||
MakeRequest(t, req, http.StatusOK)
|
||||
})
|
||||
|
||||
t.Run("DeleteBinary", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
body := bytes.Buffer{}
|
||||
writer := multipart.NewWriter(&body)
|
||||
writer.WriteField("gem_name", binaryPackageName)
|
||||
writer.WriteField("version", binaryPackageVersion)
|
||||
writer.Close()
|
||||
|
||||
req := NewRequestWithBody(t, "DELETE", fmt.Sprintf("%s/api/v1/gems/yank", root), &body).
|
||||
SetHeader("Content-Type", writer.FormDataContentType()).
|
||||
AddBasicAuth(user.Name)
|
||||
MakeRequest(t, req, http.StatusOK)
|
||||
})
|
||||
|
||||
t.Run("Delete", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
|
|
|
@ -764,3 +764,58 @@ func TestAPIRepoCommitPull(t *testing.T) {
|
|||
req = NewRequest(t, "GET", "/api/v1/repos/user2/repo1/commits/not-a-commit/pull")
|
||||
MakeRequest(t, req, http.StatusNotFound)
|
||||
}
|
||||
|
||||
func TestAPIListOwnRepoSorting(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||
session := loginUser(t, user.Name)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeReadRepository, auth_model.AccessTokenScopeReadUser)
|
||||
|
||||
t.Run("No sorting", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
MakeRequest(t, NewRequest(t, "GET", "/api/v1/user/repos").AddTokenAuth(token), http.StatusOK)
|
||||
})
|
||||
|
||||
t.Run("ID sorting", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
var repos []api.Repository
|
||||
resp := MakeRequest(t, NewRequest(t, "GET", "/api/v1/user/repos?limit=2&order_by=id").AddTokenAuth(token), http.StatusOK)
|
||||
DecodeJSON(t, resp, &repos)
|
||||
|
||||
assert.Len(t, repos, 2)
|
||||
assert.EqualValues(t, 1, repos[0].ID)
|
||||
assert.EqualValues(t, 2, repos[1].ID)
|
||||
})
|
||||
|
||||
t.Run("Name sorting", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
var repos []api.Repository
|
||||
resp := MakeRequest(t, NewRequest(t, "GET", "/api/v1/user/repos?limit=2&order_by=name").AddTokenAuth(token), http.StatusOK)
|
||||
DecodeJSON(t, resp, &repos)
|
||||
|
||||
assert.Len(t, repos, 2)
|
||||
assert.EqualValues(t, "big_test_private_4", repos[0].Name)
|
||||
// Postgres doesn't do ascii sorting.
|
||||
if setting.Database.Type.IsPostgreSQL() {
|
||||
assert.EqualValues(t, "commitsonpr", repos[1].Name)
|
||||
} else {
|
||||
assert.EqualValues(t, "commits_search_test", repos[1].Name)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Reverse alphabetic sorting", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
var repos []api.Repository
|
||||
resp := MakeRequest(t, NewRequest(t, "GET", "/api/v1/user/repos?limit=2&order_by=reversealphabetically").AddTokenAuth(token), http.StatusOK)
|
||||
DecodeJSON(t, resp, &repos)
|
||||
|
||||
assert.Len(t, repos, 2)
|
||||
assert.EqualValues(t, "utf8", repos[0].Name)
|
||||
assert.EqualValues(t, "test_workflows", repos[1].Name)
|
||||
})
|
||||
}
|
||||
|
|
91
tests/integration/release_feed_test.go
Normal file
91
tests/integration/release_feed_test.go
Normal file
|
@ -0,0 +1,91 @@
|
|||
// Copyright 2025 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package integration
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"regexp"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/tests"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestReleaseFeed(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
|
||||
normalize := func(body string) string {
|
||||
// Remove port.
|
||||
body = regexp.MustCompile(`localhost:\d+`).ReplaceAllString(body, "localhost")
|
||||
// date is timezone dependent.
|
||||
body = regexp.MustCompile(`<pubDate>.*</pubDate>`).ReplaceAllString(body, "<pubDate></pubDate>")
|
||||
body = regexp.MustCompile(`<updated>.*</updated>`).ReplaceAllString(body, "<updated></updated>")
|
||||
return body
|
||||
}
|
||||
t.Run("RSS feed", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
resp := MakeRequest(t, NewRequest(t, "GET", "/user2/repo1/releases.rss"), http.StatusOK)
|
||||
assert.EqualValues(t, `<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
|
||||
<channel>
|
||||
<title>Releases for user2/repo1</title>
|
||||
<link>http://localhost/user2/repo1/release</link>
|
||||
<description></description>
|
||||
<pubDate></pubDate>
|
||||
<item>
|
||||
<title>pre-release</title>
|
||||
<link>http://localhost/user2/repo1/releases/tag/v1.0</link>
|
||||
<description></description>
|
||||
<content:encoded><![CDATA[<p dir="auto">some text for a pre release</p>
|
||||
]]></content:encoded>
|
||||
<author>user2</author>
|
||||
<guid>5: http://localhost/user2/repo1/releases/tag/v1.0</guid>
|
||||
<pubDate></pubDate>
|
||||
</item>
|
||||
<item>
|
||||
<title>testing-release</title>
|
||||
<link>http://localhost/user2/repo1/releases/tag/v1.1</link>
|
||||
<description></description>
|
||||
<author>user2</author>
|
||||
<guid>1: http://localhost/user2/repo1/releases/tag/v1.1</guid>
|
||||
<pubDate></pubDate>
|
||||
</item>
|
||||
</channel>
|
||||
</rss>`, normalize(resp.Body.String()))
|
||||
})
|
||||
|
||||
t.Run("Atom feed", func(t *testing.T) {
|
||||
defer tests.PrintCurrentTest(t)()
|
||||
|
||||
resp := MakeRequest(t, NewRequest(t, "GET", "/user2/repo1/releases.atom"), http.StatusOK)
|
||||
assert.EqualValues(t, `<?xml version="1.0" encoding="UTF-8"?><feed xmlns="http://www.w3.org/2005/Atom">
|
||||
<title>Releases for user2/repo1</title>
|
||||
<id>http://localhost/user2/repo1/release</id>
|
||||
<updated></updated>
|
||||
<link href="http://localhost/user2/repo1/release"></link>
|
||||
<entry>
|
||||
<title>pre-release</title>
|
||||
<updated></updated>
|
||||
<id>5: http://localhost/user2/repo1/releases/tag/v1.0</id>
|
||||
<content type="html"><p dir="auto">some text for a pre release</p>
</content>
|
||||
<link href="http://localhost/user2/repo1/releases/tag/v1.0" rel="alternate"></link>
|
||||
<author>
|
||||
<name>user2</name>
|
||||
<email>user2@noreply.example.org</email>
|
||||
</author>
|
||||
</entry>
|
||||
<entry>
|
||||
<title>testing-release</title>
|
||||
<updated></updated>
|
||||
<id>1: http://localhost/user2/repo1/releases/tag/v1.1</id>
|
||||
<link href="http://localhost/user2/repo1/releases/tag/v1.1" rel="alternate"></link>
|
||||
<author>
|
||||
<name>user2</name>
|
||||
<email>user2@noreply.example.org</email>
|
||||
</author>
|
||||
</entry>
|
||||
</feed>`, normalize(resp.Body.String()))
|
||||
})
|
||||
}
|
12
web_src/fomantic/package-lock.json
generated
12
web_src/fomantic/package-lock.json
generated
|
@ -1249,9 +1249,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001703",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001703.tgz",
|
||||
"integrity": "sha512-kRlAGTRWgPsOj7oARC9m1okJEXdL/8fekFVcxA8Hl7GH4r/sN4OJn/i6Flde373T50KS7Y37oFbMwlE8+F42kQ==",
|
||||
"version": "1.0.30001705",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001705.tgz",
|
||||
"integrity": "sha512-S0uyMMiYvA7CxNgomYBwwwPUnWzFD83f3B1ce5jHUfHTH//QL6hHsreI8RVC5606R4ssqravelYO5TU6t8sEyg==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
|
@ -2005,9 +2005,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.5.113",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.113.tgz",
|
||||
"integrity": "sha512-wjT2O4hX+wdWPJ76gWSkMhcHAV2PTMX+QetUCPYEdCIe+cxmgzzSSiGRCKW8nuh4mwKZlpv0xvoW7OF2X+wmHg==",
|
||||
"version": "1.5.119",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.119.tgz",
|
||||
"integrity": "sha512-Ku4NMzUjz3e3Vweh7PhApPrZSS4fyiCIbcIrG9eKrriYVLmbMepETR/v6SU7xPm98QTqMSYiCwfO89QNjXLkbQ==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/emoji-regex": {
|
||||
|
|
Loading…
Add table
Reference in a new issue