Merge branch 'forgejo' into report_abuse

This commit is contained in:
floss4good 2025-03-23 23:09:37 +00:00
commit 36298c7422
84 changed files with 2034 additions and 531 deletions

View file

@ -1,6 +1,6 @@
{
"name": "Gitea DevContainer",
"image": "mcr.microsoft.com/devcontainers/go:1.23-bullseye",
"image": "mcr.microsoft.com/devcontainers/go:1.24-bullseye",
"features": {
// installs nodejs into container
"ghcr.io/devcontainers/features/node:1": {

View file

@ -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

View file

@ -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: ...

File diff suppressed because one or more lines are too long

View file

@ -2407,8 +2407,8 @@ LEVEL = Info
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; The first locale will be used as the default if user browser's language doesn't match any locale in the list.
;LANGS = en-US,zh-CN,zh-HK,zh-TW,de-DE,nds,fr-FR,nl-NL,lv-LV,ru-RU,uk-UA,ja-JP,es-ES,pt-BR,pt-PT,pl-PL,bg,it-IT,fi-FI,fil,eo,tr-TR,cs-CZ,sl,sv-SE,ko-KR,el-GR,fa-IR,hu-HU,id-ID
;NAMES = English,简体中文,繁體中文(香港),繁體中文(台灣),Deutsch,Plattdüütsch,Français,Nederlands,Latviešu,Русский,Українська,日本語,Español,Português do Brasil,Português de Portugal,Polski,Български,Italiano,Suomi,Filipino,Esperanto,Türkçe,Čeština,Slovenščina,Svenska,한국어,Ελληνικά,فارسی,Magyar nyelv,Bahasa Indonesia
;LANGS = en-US,zh-CN,zh-HK,zh-TW,da,de-DE,nds,fr-FR,nl-NL,lv-LV,ru-RU,uk-UA,ja-JP,es-ES,pt-BR,pt-PT,pl-PL,bg,it-IT,fi-FI,fil,eo,tr-TR,cs-CZ,sl,sv-SE,ko-KR,el-GR,fa-IR,hu-HU,id-ID
;NAMES = English,简体中文,繁體中文(香港),繁體中文(台灣),Danish,Deutsch,Plattdüütsch,Français,Nederlands,Latviešu,Русский,Українська,日本語,Español,Português do Brasil,Português de Portugal,Polski,Български,Italiano,Suomi,Filipino,Esperanto,Türkçe,Čeština,Slovenščina,Svenska,한국어,Ελληνικά,فارسی,Magyar nyelv,Bahasa Indonesia
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

18
go.mod
View file

@ -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
@ -47,13 +47,13 @@ require (
github.com/go-git/go-git/v5 v5.13.2
github.com/go-ldap/ldap/v3 v3.4.6
github.com/go-openapi/spec v0.20.14
github.com/go-sql-driver/mysql v1.8.1
github.com/go-sql-driver/mysql v1.9.1
github.com/go-testfixtures/testfixtures/v3 v3.14.0
github.com/go-webauthn/webauthn v0.12.2
github.com/gobwas/glob v0.2.3
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85
github.com/golang-jwt/jwt/v5 v5.2.1
github.com/golang-jwt/jwt/v5 v5.2.2
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
github.com/google/go-github/v64 v64.0.0
github.com/google/pprof v0.0.0-20241017200806-017d972448fc
@ -85,7 +85,7 @@ require (
github.com/opencontainers/image-spec v1.1.1
github.com/pquerna/otp v1.4.0
github.com/prometheus/client_golang v1.21.1
github.com/redis/go-redis/v9 v9.7.0
github.com/redis/go-redis/v9 v9.7.3
github.com/robfig/cron/v3 v3.0.1
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1
github.com/sassoftware/go-rpmutils v0.4.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
)

32
go.sum
View file

@ -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=
@ -960,8 +960,8 @@ github.com/go-openapi/swag v0.22.7 h1:JWrc1uc/P9cSomxfnsFSVWoE1FW6bNbrVPmpQYpCcR
github.com/go-openapi/swag v0.22.7/go.mod h1:Gl91UqO+btAM0plGGxHqJcQZ1ZTy6jbmridBTsDy8A0=
github.com/go-pdf/fpdf v0.5.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M=
github.com/go-pdf/fpdf v0.6.0/go.mod h1:HzcnA+A23uwogo0tp9yU+l3V+KXhiESpt1PMayhOh5M=
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/go-sql-driver/mysql v1.9.1 h1:FrjNGn/BsJQjVRuSa8CBrM5BWA9BWoXXat3KrtSb/iI=
github.com/go-sql-driver/mysql v1.9.1/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U=
github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
@ -985,8 +985,8 @@ github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85 h1:UjoPNDAQ5JP
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85/go.mod h1:fR6z1Ie6rtF7kl/vBYMfgD5/G5B1blui7z426/sj2DU=
github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo=
github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
@ -1347,8 +1347,8 @@ github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ
github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/redis/go-redis/v9 v9.7.0 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa9E=
github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw=
github.com/redis/go-redis/v9 v9.7.3 h1:YpPyAayJV+XErNsatSElgRZZVCwXX9QzkKYNvO7x0wM=
github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRltRTZHSvrA=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rhysd/actionlint v1.6.27 h1:xxwe8YmveBcC8lydW6GoHMGmB6H/MTqUU60F2p10wjw=
@ -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=

View file

@ -0,0 +1,5 @@
-
id: 1001
user_id: 29
repo_id: 3
mode: 1

View 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

View file

@ -0,0 +1,8 @@
-
id: 1001
project_id: 1001
title: Triage
creator_id: 2
default: true
created_unix: 1738000000
updated_unix: 1738000000

View 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

View file

@ -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
}

View file

@ -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)

View file

@ -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)
})
}

View file

@ -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
),
)
}

View file

@ -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

View 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
}

View 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)
}

View file

@ -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)

View file

@ -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()

View file

@ -9,6 +9,7 @@ var defaultI18nLangNames = []string{
"zh-CN", "简体中文",
"zh-HK", "繁體中文(香港)",
"zh-TW", "繁體中文(台灣)",
"da", "Danish",
"de-DE", "Deutsch",
"nds", "Plattdüütsch",
"fr-FR", "Français",

View file

@ -27,7 +27,7 @@ type User struct {
Email string `json:"email"`
// URL to the user's avatar
AvatarURL string `json:"avatar_url"`
// URL to the user's gitea page
// URL to the user's profile page
HTMLURL string `json:"html_url"`
// User locale
Language string `json:"language"`

View file

@ -58,7 +58,7 @@ your_profile = Profil
your_starred = Stjernemarkeret
your_settings = Indstillinger
passcode = Passcode
repository = Repository
repository = Depot
new_org.title = Ny organisation
new_repo.link = Nyt repository
new_migrate.link = Ny migration
@ -109,7 +109,7 @@ artifacts = Artefakter
archived = Arkiveret
concept_system_global = Global
concept_user_individual = Individuel
concept_code_repository = Repository
concept_code_repository = Depot
concept_user_organization = Organisation
show_timestamps = Vis tidsstempler
show_log_seconds = Vis sekunder
@ -2086,9 +2086,449 @@ activity.period.monthly = 1 måned
activity.period.halfweekly = 3 dage
activity.period.quarterly = 3 måneder
activity.period.semiyearly = 6 måneder
activity.title.prs_1 = %d pull-anmodning
activity.title.prs_merged_by = %s flettet af %s
contributors.contribution_type.commits = Commits
contributors.contribution_type.additions = Tilføjelser
contributors.contribution_type.deletions = Sletninger
settings = Indstillinger
settings.federation_settings = Føderationsindstillinger
settings.hooks = Webhooks
activity.title.issues_created_by = %s oprettet af %s
activity.new_issue_label = Åbnet
activity.active_issues_count_n = <strong>%d</strong> aktive problemer
activity.closed_issue_label = Lukket
activity.commit = Commit aktivitet
settings.collaboration = Samarbejdspartnere
activity.git_stats_commit_n = %d commits
activity.git_stats_files_changed_1 = er ændret
activity.git_stats_files_changed_n = har ændret
activity.git_stats_additions = og der har været
settings.collaboration.admin = Administrator
settings.collaboration.write = Skriv
settings.federation_not_enabled = Føderation er ikke aktiveret på din instans.
settings.mirror_settings.docs.pull_mirror_instructions = For at opsætte et pull-spejl, se venligst:
settings.mirror_settings.docs.more_information_if_disabled = Du kan finde ud af mere om push and pull spejle her:
activity.git_stats_deletion_1 = %d sletning
activity.git_stats_pushed_n = havde pushed
activity.title.unresolved_conv_1 = %d uafsluttet samtale
activity.title.unresolved_conv_n = %d uafsluttede samtaler
activity.git_stats_pushed_1 = har pushed
contributors.contribution_type.filter_label = Bidrags type:
settings.options = Depot
settings.desc = Indstillinger er, hvor du kan administrere indstillingerne for depotet
settings.collaboration.read = Læs
settings.collaboration.owner = Ejer
settings.collaboration.undefined = Udefineret
settings.githooks = Git hooks
settings.basic_settings = Grundlæggende indstillinger
settings.mirror_settings.docs.disabled_push_mirror.instructions = Konfigurer dit projekt til automatisk at trække commits, tags og branches fra et andet depot.
activity.title.prs_opened_by = %s foreslået af %s
activity.merged_prs_label = Flettet
activity.merged_prs_count_n = Flettede pull-anmodninger
activity.title.prs_n = %d pull-anmodninger
activity.opened_prs_label = Foreslået
activity.active_issues_count_1 = <strong>%d</strong> aktivt problem
activity.new_issues_count_1 = Nyt problem
activity.new_issues_count_n = Nye problemer
activity.git_stats_commit_1 = %d commit
settings.federation_apapiurl = Føderations-URL for dette depot. Kopiér og indsæt dette i Federation Settings af et andet lager som en URL for et Følgende Depot.
settings.mirror_settings.docs = Konfigurer dit depot til automatisk at synkronisere commits, tags og branches med et andet depot.
settings.mirror_settings.docs.disabled_pull_mirror.instructions = Indstil dit projekt til automatisk at skubbe commits, tags og branches til et andet depot. Pull-spejle er blevet deaktiveret af din webstedsadministrator.
settings.mirror_settings.docs.doc_link_pull_section = afsnittet "Trækker fra et fjerndepot" i dokumentationen.
settings.mirror_settings.docs.pulling_remote_title = Trækker fra et fjerndepot
settings.mirror_settings.mirrored_repository = Spejlet depot
settings.mirror_settings.pushed_repository = Pushed depot
settings.mirror_settings = Spejl indstillinger
activity.closed_issues_count_n = Lukkede problemer
activity.title.issues_1 = %d problem
activity.title.issues_n = %d problemer
activity.title.issues_closed_from = %s lukket af %s
activity.closed_issues_count_1 = Lukket problem
settings.federation_following_repos = URL'er for følgende depoter. Adskilt af ";", ingen mellemrum.
settings.mirror_settings.docs.disabled_push_mirror.pull_mirror_warning = Lige nu kan dette kun gøres i menuen "Ny migration". For mere information, kontakt venligst:
settings.mirror_settings.docs.disabled_push_mirror.info = Push-spejle er blevet deaktiveret af din webstedsadministrator.
settings.mirror_settings.docs.no_new_mirrors = Dit depot spejler ændringer til eller fra et andet depot. Husk på, at du ikke kan oprette nye spejle på nuværende tidspunkt.
settings.mirror_settings.docs.can_still_use = Selvom du ikke kan ændre eksisterende spejle eller oprette nye, kan du stadig bruge dit eksisterende spejle.
settings.mirror_settings.docs.doc_link_title = Hvordan spejler jeg depoter?
activity.active_prs_count_1 = <strong>%d</strong> aktiv pull-anmodning
activity.active_prs_count_n = <strong>%d</strong> aktive pull-anmodninger
activity.merged_prs_count_1 = Sammenflettet pull-anmodning
activity.opened_prs_count_1 = Foreslået pull anmodning
activity.opened_prs_count_n = Foreslåede pull-anmodninger
activity.title.user_n = %d brugere
activity.title.user_1 = %d bruger
activity.published_prerelease_label = Før-udgivelse
activity.published_tag_label = Tag
activity.no_git_activity = Der har ikke været nogen commit-aktivitet i denne periode.
activity.git_stats_exclude_merges = Med undtagelse af fletninger,
activity.git_stats_author_1 = %d forfatter
activity.git_stats_author_n = %d forfattere
activity.git_stats_addition_1 = %d tilføjelse
activity.git_stats_deletion_n = %d sletninger
activity.git_stats_and_deletions = og
activity.git_stats_addition_n = %d tilføjelser
settings.event_repository = Depot
activity.unresolved_conv_desc = Disse nyligt ændrede problemer og pull-anmodninger er ikke blevet løst endnu.
activity.git_stats_push_to_branch = til %s og
activity.git_stats_push_to_all_branches = til alle grene.
activity.git_stats_on_default_branch = På %s,
activity.git_stats_file_1 = %d fil
activity.git_stats_file_n = %d filer
settings.mirror_settings.push_mirror.remote_url = Git-URL for fjerndepot
settings.external_tracker_url = Eksternt problem tracker URL
settings.admin_enable_health_check = Aktiver depot sundheds checks (git fsck)
settings.external_tracker_url_desc = Besøgende omdirigeres til den eksterne problemsporings-URL, når de klikker på problemer-fanen.
settings.mirror_settings.push_mirror.none = Der er ikke konfigureret push-spejle
settings.mirror_settings.push_mirror.add = Tilføj push spejl
settings.mirror_settings.push_mirror.edit_sync_time = Rediger spejlsynkroniseringsinterval
settings.mirror_settings.last_update = Sidste opdatering
settings.update_settings = Gem indstillinger
settings.admin_settings = Administratorindstillinger
settings.tracker_issue_style.regexp_pattern_desc = Den første fangede gruppe vil blive brugt i stedet for <code>{index}</code>.
settings.actions_desc = Aktiver integrerede CI/CD-pipelines med Forgejo Actions
settings.reindex_requested = Genindeks anmodet
settings.external_wiki_url = Ekstern wiki-URL
settings.tracker_issue_style = Eksternt problem tracker Nummerformat
settings.tracker_issue_style.alphanumeric = Alfanumerisk
settings.tracker_issue_style.regexp = Regulært udtryk
settings.pulls_desc = Aktiver depot pull-anmodninger
settings.pulls.default_allow_edits_from_maintainers = Tillad som standard redigeringer fra vedligeholdere
settings.admin_code_indexer = Kodeindekserer
settings.admin_indexer_unindexed = Uindekseret
settings.admin_enable_close_issues_via_commit_in_any_branch = Luk et problem via en commit lavet i en ikke-standard filial
settings.mirror_settings.direction = Retning
settings.mirror_settings.direction.pull = Pull
settings.mirror_settings.direction.push = Push
settings.event_push = Push
settings.units.units = Enheder
settings.mirror_settings.push_mirror.copy_public_key = Kopier offentlig nøgle
settings.update_mirror_settings = Opdater spejlindstillinger
settings.wiki_desc = Aktiver depot wiki
settings.use_internal_wiki = Brug indbygget wiki
settings.use_external_wiki = Brug ekstern wiki
settings.external_wiki_url_desc = Besøgende omdirigeres til den eksterne wiki-URL, når de klikker på wiki-fanen.
settings.issues_desc = Aktiver depotproblemsporing
settings.use_internal_issue_tracker = Brug indbygget problem tracker
settings.use_external_issue_tracker = Brug ekstern problemsporing
settings.tracker_url_format = Eksternt problem tracker URL-format
settings.tracker_url_format_error = Det eksterne problemsporings-URL-format er ikke en gyldig URL.
settings.external_tracker_url_error = Den eksterne problemsporings-URL er ikke en gyldig URL.
settings.external_wiki_url_error = Den eksterne wiki-URL er ikke en gyldig URL.
settings.reindex_button = Tilføj til genindekskø
settings.mirror_settings.push_mirror.none_ssh = Intet
settings.sync_mirror = Synkroniser nu
settings.pull_mirror_sync_in_progress = Trækker ændringer fra remote %s i øjeblikket.
settings.pull_mirror_sync_quota_exceeded = Kvoten overskredet, ingen ændringer.
settings.push_mirror_sync_in_progress = Pusher ændringer til remote %s i øjeblikket.
settings.branches.switch_default_branch = Skift standardgren
settings.branches.update_default_branch = Opdater standardgren
settings.branches.add_new_rule = Tilføj ny regel
settings.advanced_settings = Avancerede indstillinger
settings.wiki_globally_editable = Tillad enhver at redigere wikien
settings.tracker_issue_style.numeric = Numerisk
settings.tracker_issue_style.regexp_pattern = Regulært udtryksmønster
settings.allow_only_contributors_to_track_time = Lad kun bidragydere spore tid
settings.pulls.enable_autodetect_manual_merge = Aktiver automatisk manuel fletning (Bemærk: I nogle særlige tilfælde kan fejlvurderinger forekomme)
settings.pulls.ignore_whitespace = Ignorer mellemrum for konflikter
settings.projects_desc = Aktiver depot-projekter
settings.admin_stats_indexer = Kode statistik indekserer
settings.tracker_url_format_desc = Brug pladsholderne <code>{user}</code>, <code>{repo}</code> og <code>{index}</code> til brugernavn, depotnavn og problemindeks.
settings.enable_timetracker = Aktiver tidsregistrering
settings.releases_desc = Aktiver depotudgivelser
settings.packages_desc = Aktiver depotpakkeregistrering
settings.danger_zone = Farezone
settings.pulls.default_delete_branch_after_merge = Slet pull request-gren efter fletning som standard
settings.default_update_style_desc = Standard opdateringsstil, der bruges til at opdatere pull-anmodninger, der ligger bag basisgrenen.
settings.event_push_desc = Git push til et depot.
settings.site = Websted
settings.admin_indexer_commit_sha = Sidste indekserede commit
settings.pulls.allow_rebase_update = Aktiver opdatering af pull request-gren ved rebase
settings.trust_model.default = Standard tillidsmodel
settings.transfer_desc = Overfør dette depot til en bruger eller til en organisation, som du har administratorrettigheder til.
settings.enter_repo_name = Indtast ejer- og depotnavnet nøjagtigt som vist:
settings.convert_notices_1 = Denne handling vil konvertere spejlet til et almindeligt depot og kan ikke fortrydes.
settings.transfer.success = Overførsel af depot var vellykket.
settings.convert_fork_confirm = Konverter depot
settings.convert_fork_succeed = Forken er omdannet til et almindeligt depot.
settings.transfer_abort = Annullere overførsel
settings.transfer_abort_invalid = Du kan ikke annullere en ikke-eksisterende depotoverførsel.
settings.transfer_abort_success = Depot overførslen til %s blev annulleret.
settings.transfer_perform = Udfør overførslen
settings.wiki_rename_branch_main_desc = Omdøb grenen, der bruges internt af Wiki, til "%s". Denne ændring er permanent og kan ikke fortrydes.
settings.trust_model.collaboratorcommitter.long = Collaborator+Committer: Stol på underskrifter fra samarbejdspartnere, der matcher forpligteren
settings.wiki_delete = Slet wiki-data
settings.wiki_delete_notices_1 = - Dette vil permanent slette og deaktivere depot-wikien for %s.
settings.wiki_branch_rename_failure = Det lykkedes ikke at normalisere depotwikiens filialnavn.
settings.add_collaborator_duplicate = Samarbejdspartneren er allerede føjet til dette depot.
settings.add_collaborator_owner = Kan ikke tilføje en ejer som samarbejdspartner.
settings.collaborator_deletion = Fjern Samarbejdspartner
settings.collaborator_deletion_desc = Fjernelse af en samarbejdspartner vil tilbagekalde deres adgang til dette depot. Vil du fortsætte?
settings.add_team_duplicate = Teamet har allerede depotet
settings.add_collaborator_blocked_our = Samarbejdspartneren kan ikke tilføjes, fordi depots ejer har blokeret dem.
settings.add_collaborator_blocked_them = Samarbejdspartneren kan ikke tilføjes, fordi de har blokeret depot ejeren.
settings.delete_collaborator = Slet
settings.trust_model.collaboratorcommitter = Samarbejdspartner+Committer
settings.convert_confirm = Konverter depot
settings.trust_model = Signatur tillidsmodel
settings.trust_model.collaborator.desc = Gyldige signaturer fra samarbejdspartnere af dette depot vil blive markeret som "pålidelige" - (uanset om de matcher committeren eller ej). Ellers vil gyldige signaturer blive markeret som "upålidelige", hvis signaturen matcher committeren og "umatchede", hvis ikke.
settings.wiki_rename_branch_main = Normaliser Wiki-grenens navn
settings.wiki_rename_branch_main_notices_1 = Denne handling <strong>KAN IKKE</strong> fortrydes.
settings.wiki_deletion_success = Depot-wiki-dataene er blevet slettet.
settings.delete_notices_1 = - Denne handling <strong>KAN IKKE</strong> fortrydes.
settings.delete = Slet dette depot
settings.deletion_success = Depotet er blevet slettet.
settings.add_collaborator_success = Samarbejdspartneren er tilføjet.
settings.transfer_in_progress = Der er i øjeblikket en igangværende overførsel. Annuller det, hvis du vil overføre dette depot til en anden bruger.
settings.transfer_notices_3 = - Hvis depotet er privat og overføres til en individuel bruger, sikrer denne handling, at brugeren har mindst læsetilladelse (og ændrer tilladelser, hvis det er nødvendigt).
settings.transfer_started = Dette depot er blevet markeret til overførsel og afventer bekræftelse fra "%s"
settings.signing_settings = Indstillinger for signering af bekræftelse
settings.trust_model.committer.long = Committer: Stol på signaturer, der matcher committers (dette matcher GitHub og vil tvinge Forgejo underskrevne commits til at have Forgejo som committer)
settings.trust_model.committer.desc = Gyldige signaturer vil kun blive markeret som "trusted", hvis de matcher committeren, ellers vil de blive markeret "unmatched". Dette tvinger Forgejo til at være committer på underskrevne commits med den faktiske committer markeret som Co-authored-by: og Co-committed-by: trailer i commit. Forgejo-nøglen skal matche en bruger i databasen.
settings.delete_notices_fork_1 = - Forks af dette depot bliver uafhængige efter sletning.
settings.remove_collaborator_success = Samarbejdspartneren er blevet fjernet.
settings.remove_team_success = Teamets adgang til depotet er blevet fjernet.
settings.delete_notices_2 = - Denne handling vil permanent slette <strong>%s</strong>-depotet, inklusive kode, problemer, kommentarer, wiki-data og samarbejdspartnerindstillinger.
settings.convert_succeed = Spejlet er blevet omdannet til et almindeligt depot.
settings.convert_fork_desc = Du kan konvertere denne gaffel til et almindeligt depot. Dette kan ikke fortrydes.
settings.convert_fork_notices_1 = Denne operation vil konvertere forken til et almindeligt depot og kan ikke fortrydes.
settings.transfer.rejected = Depotoverførsel blev afvist.
settings.transfer.title = Overfør ejerskab
settings.transfer.button = Overfør ejerskab
settings.transfer.modal.title = Overfør ejerskab
settings.confirmation_string = Bekræftelsesstreng
settings.transfer_owner = Nye ejer
settings.transfer_notices_2 = - Du beholder adgangen til depotet, hvis du overfører det til en organisation, som du (med)ejer.
settings.transfer_succeed = Depotet er blevet overført.
settings.transfer_quota_exceeded = Den nye ejer (%s) er over kvoten. Depotet er ikke blevet overført.
settings.trust_model.collaborator = Samarbejdspartner
settings.trust_model.collaborator.long = Samarbejdspartner: Tillid til underskrifter fra samarbejdspartnere
settings.trust_model.default.desc = Brug standard depottillidsmodellen til denne installation.
settings.wiki_rename_branch_main_notices_2 = Dette vil permanent omdøbe den interne gren af %s' depot wiki. Eksisterende checkouts skal opdateres.
settings.confirm_wiki_branch_rename = Omdøb wiki-grenen
settings.confirm_wiki_delete = Slet wiki-data
settings.delete_desc = Sletning af et depot er permanent og kan ikke fortrydes.
settings.confirm_delete = Slet depot
settings.add_collaborator = Tilføj samarbejdspartner
settings.update_settings_success = Depotingsindstillingerne er blevet opdateret.
settings.update_settings_no_unit = Depotet bør tillade mindst en form for interaktion.
settings.add_collaborator_inactive_user = Kan ikke tilføje en inaktiv bruger som samarbejdspartner.
settings.add_team_success = Teamet har nu adgang til depotet.
settings.change_team_permission_tip = Teamets tilladelse er angivet på teamindstillingssiden og kan ikke ændres pr. depot
settings.delete_team_tip = Dette team har adgang til alle depoter og kan ikke fjernes
settings.org_not_allowed_to_be_collaborator = Organisationer kan ikke tilføjes som samarbejdspartner.
settings.change_team_access_not_allowed = Ændring af teamadgang til depot er begrænset til organisationsejeren
settings.team_not_in_organization = Teamet er ikke i samme organisation som depotet
settings.add_webhook = Tilføj webhook
settings.new_owner_has_same_repo = Den nye ejer har allerede et depot med samme navn. Vælg venligst et andet navn.
settings.new_owner_blocked_doer = Den nye ejer har blokeret dig.
settings.convert_desc = Du kan konvertere dette spejl til et almindeligt depot. Dette kan ikke fortrydes.
settings.convert = Konverter til et almindeligt depot
settings.transfer_notices_1 = - Du mister adgangen til depotet, hvis du overfører det til en individuel bruger.
settings.wiki_delete_desc = Sletning af depot wiki-data er permanent og kan ikke fortrydes.
settings.trust_model.committer = Committer
settings.trust_model.collaboratorcommitter.desc = Gyldige signaturer fra samarbejdspartnere af dette depot vil blive markeret som "pålidelige", hvis de matcher committeren. Ellers vil gyldige signaturer blive markeret som "upålidelige", hvis signaturen matcher committeren og "umatchede" ellers. Dette vil tvinge Forgejo til at blive markeret som committer på underskrevne commits med den faktiske committer markeret som Co-Authored-By: og Co-Committed-By: trailer i commit. Forgejo-nøglen skal matche en bruger i databasen.
settings.add_team = Tilføj team
settings.convert_fork = Konverter til almindeligt depot
settings.wiki_branch_rename_success = Depot-wikiens filialnavn er blevet normaliseret.
settings.add_webhook.invalid_channel_name = Webhook-kanalnavnet må ikke være tomt og må ikke kun indeholde et #-tegn.
settings.webhook_deletion = Fjern webhook
settings.hooks_desc = Webhooks foretager automatisk HTTP POST-anmodninger til en server, når visse Forgejo-hændelser udløses. Læs mere i <a target="_blank" rel="noopener noreferrer" href="%s">webhooks-guiden</a>.
settings.add_webhook.invalid_path = Sti må ikke indeholde en del, der er "." eller ".." eller den tomme streng. Det kan ikke starte eller slutte med en skråstreg.
settings.webhook_deletion_desc = Fjernelse af en webhook sletter dens indstillinger og leveringshistorik. Vil du fortsætte?
settings.event_pull_request_assign = Tildeling
settings.event_delete = Slet
settings.event_delete_desc = Gren eller tag slettet.
settings.event_fork = Fork
settings.event_release_desc = Udgivelse offentliggjort, opdateret eller slettet i et depot.
settings.event_pull_request_comment_desc = Pull-anmodning om kommentar oprettet, redigeret eller slettet.
settings.event_pull_request_review = Anmeldelser
settings.event_push_only = Push events
settings.event_header_pull_request = Træk anmodnings events
settings.event_pull_request_milestone_desc = Milepæl tilføjet, fjernet eller ændret.
settings.event_pull_request_label_desc = Pull-anmodnings etiketter tilføjet eller fjernet.
settings.slack_icon_url = Icon URL
settings.discord_icon_url.exceeds_max_length = Ikonets URL skal være mindre end eller lig med 2048 tegn
settings.event_desc = Trigger på:
settings.event_send_everything = Alle events
settings.event_choose = Tilpassede begivenheder…
settings.web_hook_name_msteams = Microsoft Teams
settings.web_hook_name_feishu = Feishu / Lark Suite
settings.web_hook_name_feishu_only = Feishu
settings.event_issue_label_desc = Problem etiketter tilføjet eller fjernet.
settings.event_issue_milestone = Milepæle
settings.event_pull_request_comment = Kommentarer
settings.event_pull_request_assign_desc = Pull-anmodning tildelt eller ikke tildelt.
settings.protect_status_check_matched = Matchet
branch.deletion_success = Gren "%s" er blevet slettet.
branch.deletion_failed = Kunne ikke slette grenen "%s".
settings.event_create_desc = Gren eller tag oprettet.
settings.event_header_repository = Depot events
settings.event_create = Opret
settings.event_pull_request = Modifikation
settings.event_pull_request_desc = Pull-anmodning åbnet, lukket, genåbnet eller redigeret.
settings.event_issue_assign = Tildeling
settings.event_issues_desc = Problem åbnet, lukket, genåbnet eller redigeret.
settings.event_issue_comment_desc = Problem kommentar oprettet, redigeret eller slettet.
settings.webhook_deletion_success = Webhook er blevet fjernet.
settings.web_hook_name_telegram = Telegram
settings.webhook.headers = Headers
settings.webhook.response = Svar
settings.webhook.request = Anmod
settings.event_pull_request_sync = Synkroniseret
settings.slack_color = Farve
settings.event_issues = Modifikation
settings.event_issue_assign_desc = Problem tildelt eller ikke tildelt.
settings.event_issue_milestone_desc = Milepæl tilføjet, fjernet eller ændret.
settings.event_issue_comment = Kommentarer
settings.event_repository_desc = Depot oprettet eller slettet.
settings.event_header_issue = Problem events
settings.event_fork_desc = Depot forked.
branch.delete_head = Slet
branch.delete = Slet gren "%s"
branch.delete_html = Slet gren
branch.delete_desc = Sletning af en gren er permanent. Selvom den slettede gren kan fortsætte med at eksistere i kort tid, før den rent faktisk bliver fjernet, KAN den i de fleste tilfælde IKKE fortrydes. Vil du fortsætte?
settings.event_pull_request_milestone = Milepæle
settings.webhook.test_delivery = Test levering
settings.webhook.test_delivery_desc = Test denne webhook med en falsk begivenhed.
settings.webhook.test_delivery_desc_disabled = For at teste denne webhook med en falsk begivenhed skal du aktivere den.
settings.update_webhook = Opdatere webhook
settings.discord_icon_url = Icon URL
settings.web_hook_name_wechatwork = WeCom (Wechat Work)
settings.web_hook_name_packagist = Packagist
settings.packagist_username = Packagist brugernavn
settings.packagist_api_token = API token
settings.web_hook_name_matrix = Matrix
settings.web_hook_name_larksuite_only = Lark Suite
settings.update_hook_success = Webhook er blevet opdateret.
settings.sourcehut_builds.secrets_helper = Giv jobbet adgang til byggehemmelighederne (kræver SECRETS:RO-bevillingen)
settings.sourcehut_builds.access_token_helper = Adgangstoken, der har JOBS:RW-bevilling. Generer et <a target="_blank" rel="noopener noreferrer" href="%s">builds.sr.ht-token</a> eller et <a target="_blank" rel="noopener noreferrer" href="%s">builds.sr.ht-token med hemmelig adgang</a> på meta.sr.ht.
settings.protect_approvals_whitelist_enabled_desc = Kun anmeldelser fra hvidlistede brugere eller teams tæller med til de påkrævede godkendelser. Uden hvidliste for godkendelse tæller anmeldelser fra alle med skriveadgang til de påkrævede godkendelser.
settings.protect_protected_file_patterns_desc = Beskyttede filer må ikke ændres direkte, selvom brugeren har rettigheder til at tilføje, redigere eller slette filer i denne gren. Flere mønstre kan adskilles ved hjælp af semikolon (";"). Se dokumentationen til <a href="%[1]s">%[2]s</a> for mønstersyntaks. Eksempler: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>.
settings.protect_unprotected_file_patterns_desc = Ubeskyttede filer, der må ændres direkte, hvis brugeren har skriveadgang, uden at push-begrænsning. Flere mønstre kan adskilles ved hjælp af semikolon (";"). Se dokumentationen til <a href="%[1]s">%[2]s</a> for mønstersyntaks. Eksempler: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>.
settings.block_rejected_reviews_desc = Fletning vil ikke være mulig, når der anmodes om ændringer af officielle korrekturlæsere, selvom der er tilstrækkelige godkendelser.
settings.event_pull_request_review_desc = Pull-anmodning godkendt, afvist, eller gennemgå kommentarer tilføjet.
settings.event_pull_request_review_request_desc = Pull-anmodning gennemgang anmodet eller gennemgang anmodning fjernet.
settings.event_pull_request_approvals = Pull-anmodningsgodkendelser
settings.event_pull_request_merge = Pull-anmodning flet
settings.event_pull_request_enforcement = Håndhævelse
settings.event_package_desc = Pakke oprettet eller slettet i et depot.
settings.branch_filter = Gren filter
settings.branch_filter_desc = Grenhvidliste til push, grenoprettelse og grensletningshændelser, angivet som globmønster. Hvis den er tom eller <code>*</code>, rapporteres hændelser for alle filialer. Se dokumentationen til <a href="%[1]s">%[2]s</a> for syntaks. Eksempler: <code>master</code>, <code>{master,release*}</code>.
settings.active = Aktiv
settings.active_helper = Oplysninger om udløste hændelser vil blive sendt til denne webhook-URL.
settings.add_hook_success = Webhook er tilføjet.
settings.hook_type = Hook type
settings.slack_token = Token
settings.slack_domain = Domæne
settings.add_web_hook_desc = Integrer <a target="_blank" rel="noreferrer" href="%s">%s</a> i dit depot.
settings.graphql_url = GraphQL URL
settings.dismiss_stale_approvals_desc = Når nye commits, der ændrer indholdet af pull-anmodningen, skubbes til filialen, vil gamle godkendelser blive afvist.
settings.require_signed_commits_desc = Afvis push til denne gren, hvis de er usignerede eller ikke kan verificeres.
settings.protect_branch_name_pattern = Beskyttet gren navn mønster
settings.protect_branch_name_pattern_desc = Beskyttede gren navne mønstre. Se <a href="%s">dokumentationen</a> for mønstersyntaks. Eksempler: main, release/**
settings.block_on_official_review_requests_desc = Sammenlægning vil ikke være mulig, når den har officielle anmodninger om gennemgang, selvom der er tilstrækkelige godkendelser.
settings.block_outdated_branch = Bloker fletning, hvis pull-anmodning er forældet
settings.block_outdated_branch_desc = Fletning vil ikke være mulig, når hovedgrenen er bagved basisgrenen.
settings.tags.protection.pattern = Tag mønster
settings.slack_channel = Kanal
settings.web_hook_name_gitea = Gitea
settings.web_hook_name_forgejo = Forgejo
settings.web_hook_name_gogs = Gogs
settings.protect_merge_whitelist_committers = Aktiver flet hvidliste
settings.protect_merge_whitelist_committers_desc = Tillad kun hvidlistede brugere eller teams at flette pull-anmodninger ind i denne gren.
settings.protect_status_check_patterns_desc = Indtast mønstre for at angive, hvilke statuskontroller der skal bestå, før grene kan flettes til en gren, der matcher denne regel. Hver linje angiver et mønster. Mønstre må ikke være tomme.
settings.protect_no_valid_status_check_patterns = Ingen gyldige statuskontrolmønstre.
settings.protect_required_approvals = Krævede godkendelser
settings.protect_required_approvals_desc = Tillad kun at flette pull-anmodning med nok positive anmeldelser.
settings.protect_approvals_whitelist_enabled = Begræns godkendelser til hvidlistede brugere eller teams
settings.protect_approvals_whitelist_users = Hvidlistede anmeldere
settings.protect_approvals_whitelist_teams = Hvidlistede hold til anmeldelser
settings.dismiss_stale_approvals = Afvis forældede godkendelser
settings.remove_protected_branch_failed = Fjernelse af grenbeskyttelsesreglen "%s" mislykkedes.
settings.protected_branch_deletion = Slet grenbeskyttelse
settings.protected_branch_deletion_desc = Deaktivering af grenbeskyttelse giver brugere med skrivetilladelse mulighed for at push til grenen. Vil du fortsætte?
settings.enforce_on_admins_desc = Depotadministratorer kan ikke omgå denne regel.
settings.block_rejected_reviews = Bloker fletning på afviste anmeldelser
settings.block_on_official_review_requests = Bloker fletning på officielle anmodninger om gennemgang
settings.protected_branch_required_rule_name = Påkrævet regelnavn
settings.protected_branch_duplicate_rule_name = Der er allerede en regel for dette sæt af grene
settings.tags.protection.allowed = Tilladt
settings.tags.protection.allowed.users = Tilladte brugere
settings.event_pull_request_sync_desc = Gren opdateres automatisk med målgren.
settings.event_pull_request_review_request = Gennemse forespørgsler
settings.web_hook_name_discord = Discord
settings.web_hook_name_dingtalk = DingTalk
settings.protect_check_status_contexts_desc = Kræv statustjek for at bestå før fletning. Når det er aktiveret, skal commits først skubbes til en anden gren, derefter flettes eller skubbes direkte til en gren, der matcher denne regel, efter statustjek er bestået. Hvis ingen kontekster matches, skal den sidste commit være vellykket uanset kontekst.
settings.protect_check_status_contexts_list = Statustjek fundet i den sidste uge for dette depot
settings.protect_protected_file_patterns = Beskyttede filmønstre (adskilt med semikolon ";")
settings.protect_unprotected_file_patterns = Ubeskyttede filmønstre (adskilt med semikolon ";")
settings.update_protect_branch_success = Filialbeskyttelse for reglen "%s" er blevet opdateret.
settings.default_branch_desc = Vælg en standardlagergren for pull-anmodninger og kode commits:
settings.default_merge_style_desc = Standard flettestil
settings.no_protected_branch = Der er ingen beskyttede grene.
settings.edit_protected_branch = Redigere
settings.protected_branch_required_approvals_min = Påkrævede godkendelser kan ikke være negative.
settings.tags.protection = Tag beskyttelse
release.edit = Redigere
settings.event_package = Pakke
settings.authorization_header_desc = Vil blive inkluderet som autorisationshoved for anmodninger, når de er til stede. Eksempler: %s.
settings.delete_webhook = Fjern webhook
settings.recent_deliveries = Seneste leverancer
settings.deploy_key_deletion_desc = Fjernelse af en deploy nøgle vil tilbagekalde dens adgang til dette depot. Vil du fortsætte?
settings.merge_style_desc = Flettestil
settings.choose_branch = Vælg en gren…
settings.tags = Tags
settings.protected_branch = Gren beskyttelse
settings.protected_branch.save_rule = Gem regel
settings.protect_whitelist_teams = Hvidlistede hold til at skubbe
settings.protect_patterns = Mønstre
settings.web_hook_name_slack = Slack
settings.packagist_package_url = Packagist-pakke-URL
settings.web_hook_name_sourcehut_builds = SourceHut Builds
settings.sourcehut_builds.manifest_path = Build manifest sti
settings.sourcehut_builds.visibility = Jobsynlighed
settings.sourcehut_builds.secrets = Hemmeligheder
settings.authorization_header = Autorisationshoved
settings.deploy_keys = Deploy nøgler
settings.add_deploy_key = Tilføj deploy nøgle
settings.deploy_key_desc = Deploy nøgler har skrivebeskyttet pull-adgang til depotet.
settings.is_writable = Aktiver skriveadgang
settings.is_writable_info = Tillad denne deploy nøgle at <strong>skubbe</strong> til depotet.
settings.no_deploy_keys = Der er ingen deploy nøgler endnu.
settings.key_been_used = En deploy nøgle med identisk indhold er allerede i brug.
settings.key_name_used = En deploy nøgle med identisk navn er allerede i brug.
settings.add_key_success = Deploy nøglen "%s" er blevet tilføjet.
settings.deploy_key_deletion = Slet deploy nøglen
settings.deploy_key_deletion_success = Deploy nøglen er blevet slettet.
settings.branches = Grene
settings.protected_branch.delete_rule = Slet regel
settings.branch_protection = Beskyttelsesregler for grenen "<b>%s</b>"
settings.protect_new_rule = Opret en ny gren beskyttelsesregel
settings.protect_disable_push = Deaktiver push
settings.protect_disable_push_desc = Ingen push vil være tilladt til denne gren.
settings.protect_enable_push = Aktiver push
settings.protect_enable_push_desc = Enhver med skriveadgang får lov til at pushe til denne gren (men ikke tvinge push).
settings.protect_enable_merge = Aktiver fletning
settings.protect_enable_merge_desc = Enhver med skriveadgang får lov til at flette pull-anmodningerne ind i denne gren.
settings.protect_whitelist_committers = Hvidliste begrænset push
settings.protect_whitelist_committers_desc = Kun hvidlistede brugere eller hold vil få lov til at pushe til denne gren (men ikke tvinge push).
settings.protect_whitelist_deploy_keys = Whitelist deploy nøgler med skriveadgang til push.
settings.protect_whitelist_users = Hvidlistede brugere til at skubbe
settings.protect_merge_whitelist_users = Hvidlistede brugere til fletning
settings.protect_merge_whitelist_teams = Hvidlistede hold til fletning
settings.protect_check_status_contexts = Aktiver statuskontrol
settings.protect_status_check_patterns = Statuskontrolmønstre
settings.protect_invalid_status_check_pattern = Ugyldigt statuskontrolmønster: "%s".
settings.ignore_stale_approvals = Ignorer forældede godkendelser
settings.ignore_stale_approvals_desc = Tæl ikke godkendelser, der er foretaget på ældre commits (gamle anmeldelser) med, hvor mange godkendelser PR'en har. Irrelevant, hvis uaktuelle anmeldelser allerede er afvist.
settings.require_signed_commits = Kræv underskrevne commits
settings.remove_protected_branch_success = Grenbeskyttelse for reglen "%s" er blevet fjernet.
settings.enforce_on_admins = Håndhæv denne regel for depotadministratorer
[notification]
watching = Overvåger
read = Læs
[action]
watched_repo = begyndte at overvåge <a href="%[1]s">%[2]s</a>
@ -2100,6 +2540,27 @@ teams = Teams
members = Medlemmer
org_desc = Beskrivelse
team_desc = Beskrivelse
teams.read_access = Læs
members.owner = Ejer
settings.options = Organisation
settings.full_name = Fulde navn
teams.settings = Indstillinger
teams.no_desc = Dette team har ingen beskrivelse
teams.write_access = Skriv
teams.admin_access = Administrator adgang
teams.admin_access_helper = Medlemmer kan trække og skubbe til teamdepoter og tilføje samarbejdspartnere til dem.
settings = Indstillinger
settings.repoadminchangeteam = Depotsadministrator kan tilføje og fjerne adgang for teams
settings.visibility.public = Offentlig
settings.visibility.private = Privat (kun synlig for organisationsmedlemmer)
settings.visibility.limited_shortname = Begrænset
settings.visibility.limited = Begrænset (kun synlig for brugere, der er logget ind)
settings.visibility.private_shortname = Privat
settings.website = Websted
settings.location = Lokation
settings.permission = Tilladelser
settings.visibility = Synlighed
members.remove = Slet
[admin]
orgs.members = Medlemmer
@ -2110,14 +2571,87 @@ emails.filter_sort.name = Brugernavn
notices.desc = Beskrivelse
config.db_user = Brugernavn
users.name = Brugernavn
emails.activated = Aktiveret
packages.repository = Depot
config.mailer_enabled = Aktiveret
emails.filter_sort.email = Email
auths.name = Navn
config.mailer_name = Navn
auths.enabled = Aktiveret
config_settings = Indstillinger
config.ssh_enabled = Aktiveret
config.lfs_enabled = Aktiveret
monitor.name = Navn
config.oauth_enabled = Aktiveret
orgs.name = Navn
repos.owner = Ejer
packages.name = Navn
packages.owner = Ejer
notices.type_1 = Depot
config.db_name = Navn
users.full_name = Fulde navn
users.activated = Aktiveret
repos.name = Navn
monitor.queue.name = Navn
repos.private = Privat
config.default_enable_timetracking = Aktiver tidsregistrering som standard
config.enable_timetracking = Aktiver tidsregistrering
config.default_allow_only_contributors_to_track_time = Lad kun bidragydere spore tid
config.allow_dots_in_usernames = Tillad brugere at bruge prikker i deres brugernavne. Påvirker ikke eksisterende konti.
auths.oauth2_icon_url = Icon URL
users.edit = Redigere
users.auth_source = Godkendelseskilde
[packages]
arch.version.description = Beskrivelse
container.labels = Etiketter
rubygems.dependencies.development = Udviklingsafhængigheder
conan.details.repository = Depot
conan.registry = Konfigurer dette register fra kommandolinjen:
rubygems.dependencies.runtime = Kørselsafhængigheder
rubygems.install = For at installere pakken ved hjælp af gem skal du køre følgende kommando:
debian.repository = Depot info
npm.details.tag = Tag
chef.install = For at installere pakken skal du køre følgende kommando:
alpine.repository.architectures = Arkitekturer
composer.dependencies.development = Udviklingsafhængigheder
alt.repository.multiple_groups = Denne pakke er tilgængelig i flere grupper.
owner.settings.cleanuprules.enabled = Aktiveret
helm.registry = Konfigurer dette register fra kommandolinjen:
alt.registry.install = For at installere pakken skal du køre følgende kommando:
helm.install = For at installere pakken skal du køre følgende kommando:
alt.repository.architectures = Arkitekturer
swift.registry = Konfigurer dette register fra kommandolinjen:
npm.dependencies.bundle = Samlede afhængigheder
debian.registry = Konfigurer dette register fra kommandolinjen:
cran.install = For at installere pakken skal du køre følgende kommando:
debian.install = For at installere pakken skal du køre følgende kommando:
pub.install = For at installere pakken ved hjælp af Dart skal du køre følgende kommando:
pypi.requires = Kræver Python
nuget.registry = Konfigurer dette register fra kommandolinjen:
debian.repository.distributions = Fordelinger
debian.repository.components = Komponenter
debian.repository.architectures = Arkitekturer
rpm.repository.multiple_groups = Denne pakke er tilgængelig i flere grupper.
rubygems.install2 = eller føj det til Gemfilen:
npm.dependencies.development = Udviklingsafhængigheder
npm.dependencies.peer = Peer-afhængigheder
npm.dependencies.optional = Valgfrie afhængigheder
rpm.registry = Konfigurer dette register fra kommandolinjen:
rpm.install = For at installere pakken skal du køre følgende kommando:
alpine.install = For at installere pakken skal du køre følgende kommando:
alpine.repository = Depot info
pypi.install = For at installere pakken ved hjælp af pip skal du køre følgende kommando:
rpm.repository = Depot info
rpm.repository.architectures = Arkitekturer
alt.registry = Konfigurer dette register fra kommandolinjen:
alt.repository = Depot info
[actions]
runners.description = Beskrivelse
runners.labels = Etiketter
runners.name = Navn
runners.task_list.repository = Depot
[tool]
1d = 1 dag

View file

@ -291,7 +291,7 @@ mailer_password=SMTP-salasana
register_confirm=Vaadi sähköpostinvahvistus rekisteröinnin edellytykseksi
mail_notify=Ota sähköposti-ilmoitukset käyttöön
server_service_title=Palvelimen ja kolmansien osapuolten palveluiden asetukset
offline_mode=Ota käyttöön lokaali tila
offline_mode=Ota käyttöön paikallinen tila
offline_mode.description=Poista kolmannen osapuolen sisällönjakeluverkot ja tarjoa kaikki resurssit paikallisesti.
disable_gravatar=Poista Gravatar käytöstä
disable_gravatar.description=Poista Gravatar- tai muiden kolmansien osapuolien avatar-lähteet käytöstä. Oletuskuvia käytetään käyttäjien avatareissa, elleivät he uloslataa omaa avatariaan ilmentymään.
@ -479,6 +479,7 @@ password_pwned_err = Pyyntöä HaveIBeenPwned-palveluun ei voitu suorittaa
authorization_failed_desc = Valtuus epäonnistui, koska havaitsimme virheellisen pyynnön. Ota yhteys sen sovelluksen ylläpitäjään, jota yritit valtuuttaa.
oauth.signin.error = Valtuuspyynnön käsittelyssä tapahtui virhe. Jos virhe toistuu, ota yhteys sivuston ylläpitoon.
disable_forgot_password_mail_admin = Tilin palautus on käytössä vain, jos sähköposti on määritetty. Aseta sähköposti, jotta tilin palauttaminen on mahdollista ottaa käyttöön.
prohibit_login_desc = Tilinne on estetty kanssakäymästä tämän instanssin kanssa. Ota yhteys instanssin järjestelmävalvojaan pääsyn uudelleenmahdollistamiseksi.
[mail]
view_it_on=Näytä %s
@ -541,6 +542,9 @@ primary_mail_change.text_1 = Tilisi ensisijaiseksi sähköpostiosoitteeksi asete
team_invite.text_1 = %[1]s on kutsunut sinut liittymään tiimiin %[2]s organisaatiossa %[3]s.
issue_assigned.pull = @%[1]s osoitti sinulle vetopyynnön %[2]s repossa %[3]s.
issue_assigned.issue = @%[1]s osoitti sinulle ongelman %[2]s repossa %[3]s.
register_notify.text_1 = tämä on %s:n rekistöröitymisen vahvistussähköposti!
reset_password.text = jos tämä oli sinun toimestasi, ole hyvä ja klikkaa oheista linkkiä palauttaaksesi tilisi <b>%s</b> sisällä:
totp_disabled.no_2fa = Muita kaksivaiheisen tunnistautumisen menetelmiä ei ole konfiguroituna, joten et tarvitse kaksivaiheista tunnistautumista kirjautuaaksesi tilillesi.
@ -2124,6 +2128,7 @@ tree_path_not_found_commit = Polkua %[1]s ei ole olemassa kommitissa %[2]s
archive.pull.noreview = Tämä repo on arkistoitu. Et voi katselmoida vetopyyntöjä.
tree_path_not_found_tag = Polkua %[1]s ei ole olemassa tagissa %[2]s
transfer.no_permission_to_accept = Sinulla ei ole oikeutta hyväksyä tätä siirtoa.
settings.web_hook_name_feishu = Feishu / Lark Suite
@ -2931,30 +2936,30 @@ normal_file = Tavallinen tiedosto
directory = Kansio
[search]
search = Hae...
search = Hae
type_tooltip = Haun tyyppi
fuzzy_tooltip = Sisällytä tulokset, jotka myös melkein vastaavat hakusanaa
regexp = RegExp
regexp_tooltip = Tulkitse hakutermi säännöllisenä lausekkeena
package_kind = Etsi paketteja...
package_kind = Etsi paketteja
exact = Täsmällinen
exact_tooltip = Sisällytä vain täsmälleen hakusanaa vastaavat tulokset
team_kind = Etsi ryhmiä...
code_kind = Etsi koodia...
team_kind = Etsi tiimejä…
code_kind = Etsi koodia
code_search_unavailable = Koodihaku ei tällä hetkellä ole saatavilla. Ota yhteyttä järjestelmänvalvojaan.
union = yhdistelmähaku
union_tooltip = Sisällytä minkä tahansa yksittäisen avainsanan kanssa täsmänneet tulokset
project_kind = Etsi projekteja...
union_tooltip = Sisällytä tulokset, jotka vastaavat minkä tahansa välilyönnillä erotetuista avainsanoista
project_kind = Etsi projekteja
no_results = Hakutuloksia ei löytynyt.
keyword_search_unavailable = Avainsanahaku ei tällä hetkellä ole saatavilla. Ota yhteyttä järjestelmänvalvojaan.
repo_kind = Etsi repositorioita...
user_kind = Etsi käyttäjiä...
org_kind = Etsi organisaatioita...
branch_kind = Etsi haaroja...
issue_kind = Etsi ongelmia...
repo_kind = Etsi repositorioita
user_kind = Etsi käyttäjiä
org_kind = Etsi organisaatioita
branch_kind = Etsi haaroja
issue_kind = Etsi ongelmia
milestone_kind = Etsi merkkipaaluja...
pull_kind = Etsi pull-vetoja...
commit_kind = Etsi kommitteja...
pull_kind = Etsi pull-vetoja
commit_kind = Etsi kommitteja
fuzzy = Sumea
runner_kind = Etsi ajajia...
runner_kind = Etsi ajajia
code_search_by_git_grep = Nykyiset koodin hakutulokset pohjautuvat komentoon "git grep". Parempia tuloksia on mahdollista saada, jos sivuston ylläpitäjä ottaa käyttöön koodin indeksoijan.

View file

@ -166,6 +166,7 @@ new_migrate.title = Nuova migrazione
new_org.title = Nuova organizzazione
new_migrate.link = Nuova migrazione
new_org.link = Nuova organizzazione
copy_path = Copia percorso
[aria]
footer.links = Collegamenti
@ -199,6 +200,15 @@ buttons.enable_monospace_font = Attiva font monospace
buttons.disable_monospace_font = Disattiva font monospace
buttons.indent.tooltip = Annida elementi di un livello
buttons.unindent.tooltip = Disannida elementi di un livello
buttons.new_table.tooltip = Aggiungi tabella
table_modal.header = Aggiungi tabella
table_modal.placeholder.header = Intestazione
table_modal.placeholder.content = Contenuto
table_modal.label.rows = File
table_modal.label.columns = Colonne
link_modal.header = Aggiungi collegamento
link_modal.url = Url
link_modal.description = Descrizione
[filter]
string.asc = A - Z
@ -1400,8 +1410,8 @@ issues.new.open_projects=Apri progetti
issues.new.closed_projects=Progetti chiusi
issues.new.no_items=Nessun elemento
issues.new.milestone=Traguardo
issues.new.no_milestone=Nessuna pietra miliare
issues.new.clear_milestone=Milestone pulita
issues.new.no_milestone=Nessun traguardo
issues.new.clear_milestone=Rimuovi traguardo
issues.new.open_milestone=Traguardi aperti
issues.new.closed_milestone=Traguardi chiusi
issues.new.assignees=Assegnatari
@ -1429,7 +1439,7 @@ issues.remove_labels=rimosso le %s etichette %s
issues.add_remove_labels=aggiunto %s e rimosso %s etichette %s
issues.add_milestone_at=`aggiunta alle pietre miliari <b>%s</b> %s`
issues.add_project_at=`aggiunto questo al progetto <b>%s</b> %s`
issues.change_milestone_at=`pietra miliare modificata da <b> %s</b> a <b>%s</b> %s`
issues.change_milestone_at=`ha modificato il traguardo da <b> %s</b> a <b>%s</b> %s`
issues.change_project_at=`ha modificato il progetto da <b>%s</b> a <b>%s</b> %s`
issues.remove_milestone_at=`rimossa dalle pietre miliari <b>%s</b> %s`
issues.remove_project_at=`rimosso questo dal progetto <b>%s</b> %s`
@ -1477,8 +1487,8 @@ issues.filter_sort.fewestforks=Minor numero di fork
issues.action_open=Apri
issues.action_close=Chiuso
issues.action_label=Etichetta
issues.action_milestone=Pietra Miliare
issues.action_milestone_no_select=Nessuna pietra miliare
issues.action_milestone=Traguardo
issues.action_milestone_no_select=Nessun Traguardo
issues.action_assignee=Assegnatario
issues.action_assignee_no_select=Nessun assegnatario
issues.opened_by=aperta %[1]s da <a href="%[2]s">%[3]s</a>
@ -1626,7 +1636,7 @@ issues.dependency.blocks_short=Blocchi
issues.dependency.blocked_by_short=Dipende da
issues.dependency.remove_header=Rimuovi Dipendenza
issues.dependency.issue_remove_text=Questo rimuoverà la dipendenza da questa issue. Continuare?
issues.dependency.pr_remove_text=Questo rimuoverà la dipendenza da questa pull request. Continuare?
issues.dependency.pr_remove_text=Questo rimuoverà la dipendenza da questa richiesta di modifica. Continuare?
issues.dependency.setting=Abilita le dipendenze per segnalazioni e richieste di modifica
issues.dependency.add_error_same_issue=Non si può fare dipendere una segnalazione da se stessa.
issues.dependency.add_error_dep_issue_not_exist=La segnalazione dalla quale dipende non esiste.
@ -1671,7 +1681,7 @@ issues.reference_link=Riferimento: %s
compare.compare_base=base
compare.compare_head=confronta
pulls.desc=Attiva pull request e revisioni di codice.
pulls.desc=Attiva richieste di modifica e revisioni del codice.
pulls.new=Nuova richiesta di modifica
pulls.view=Visualizza richiesta di modifica
pulls.compare_changes=Nuova richiesta di modifica
@ -1698,17 +1708,17 @@ pulls.change_target_branch_at=`cambiato il ramo di destinazione da <b>%s</b> a <
pulls.tab_conversation=Conversazione
pulls.tab_commits=Commit
pulls.tab_files=File modificati
pulls.reopen_to_merge=Riapri questa pull request per effettuare l'unione.
pulls.cant_reopen_deleted_branch=Questa richiesta di modifica non può essere riaperta perché il ramo è stato eliminato.
pulls.reopen_to_merge=Riapri questa richiesta di modifica per poter fondere.
pulls.cant_reopen_deleted_branch=Questa richiesta di modifica non può essere riaperta in quanto il ramo è stato eliminato.
pulls.merged=Unito
pulls.manually_merged=Unito manualmente
pulls.is_closed=La richiesta di modifica è stata chiusa.
pulls.title_wip_desc=`<a href="#">Inizia il titolo con <strong>%s</strong></a> per evitare che la pull request venga unita accidentalmente.`
pulls.cannot_merge_work_in_progress=Questa pull request è contrassegnata come un lavoro in corso.
pulls.title_wip_desc=`<a href="#">Inizia il titolo con <strong>%s</strong></a> per evitare che la richiesta di modifica venga fusa accidentalmente.`
pulls.cannot_merge_work_in_progress=Questa richiesta di modifica è contrassegnata come lavori in corso.
pulls.still_in_progress=Ancora in corso?
pulls.add_prefix=Aggiungi prefisso <strong>%s</strong>
pulls.remove_prefix=Rimuovi il prefisso <strong>%s</strong>
pulls.data_broken=Questa pull request è rovinata a causa di informazioni mancanti del fork.
pulls.data_broken=Questa richiesta di modifica è rovinata a causa di informazioni mancanti riguardo la derivazione.
pulls.files_conflicted=Questa richiesta di modifica va in conflitto con il ramo di destinazione.
pulls.is_checking=Verifica dei conflitti di fusione in corso. Riprova tra qualche istante.
pulls.is_ancestor=Questo ramo è già incluso nel ramo di destinazione. Non c'è nulla da fondere.
@ -1716,8 +1726,8 @@ pulls.is_empty=Le modifiche di questo ramo sono già nel ramo di destinazione. Q
pulls.required_status_check_failed=Alcuni controlli richiesti non hanno avuto successo.
pulls.required_status_check_missing=Mancano alcuni controlli richiesti.
pulls.required_status_check_administrator=Come amministratore, puoi ancora unire questa pull request.
pulls.can_auto_merge_desc=La pull request può essere unita automaticamente.
pulls.cannot_auto_merge_desc=Questa pull request non può essere unita automaticamente a causa di conflitti.
pulls.can_auto_merge_desc=La richiesta di modifica può essere unita automaticamente.
pulls.cannot_auto_merge_desc=Questa richiesta di modifica non può essere unita automaticamente a causa di conflitti.
pulls.cannot_auto_merge_helper=Unire manualmente per risolvere i conflitti.
pulls.num_conflicting_files_1=%d file in conflitto
pulls.num_conflicting_files_n=%d file in conflitto
@ -1729,20 +1739,20 @@ pulls.waiting_count_1=%d in attesa di revisione
pulls.waiting_count_n=%d in attesa di revisione
pulls.wrong_commit_id=l'ID del commit deve essere un ID del commit nel ramo di destinazione
pulls.no_merge_desc=Questa pull request non può essere unita perché tutte le opzioni di merge del repository sono disattivate.
pulls.no_merge_desc=Questa richiesta di modifica non può essere fusa perché tutte le opzioni di fusione del repositorio sono disattivate.
pulls.no_merge_helper=Attiva le opzioni di merge nelle impostazioni del repository o unisci la pull request manualmente.
pulls.no_merge_wip=Questa pull request non può essere unita perché è contrassegnata come un lavoro in corso.
pulls.no_merge_not_ready=Questa pull request non è pronta per il merge, controlla lo stato della revisione e i controlli di stato.
pulls.no_merge_access=Non sei autorizzato ad effettuare il merge su questa pull request.
pulls.merge_pull_request=Crea commit unito
pulls.rebase_merge_pull_request=Ricostruisci poi manda avanti
pulls.rebase_merge_commit_pull_request=Ricostruisci quindi crea commit unito
pulls.no_merge_access=Non sei autorizzatə a fondere questa richiesta di modifica.
pulls.merge_pull_request=Crea commit di fusione
pulls.rebase_merge_pull_request=Ricostruisci e avanti veloce
pulls.rebase_merge_commit_pull_request=Ricostruisci e crea commit di fusione
pulls.squash_merge_pull_request=Crea commit mescolato
pulls.merge_manually=Unito manualmente
pulls.merge_commit_id=L'ID del commit di merge
pulls.require_signed_wont_sign=Il ramo richiede commit firmati ma questa fusione non verrà firmata
pulls.invalid_merge_option=Non puoi utilizzare questa opzione di merge per questa pull request.
pulls.invalid_merge_option=Non è possibile utilizzare l'opzione di fusione selezionata per questa richiesta di modifica.
pulls.merge_conflict=Unione non riuscita: C'è stato un conflitto durante l'operazione. Suggerimento: Prova una strategia diversa
pulls.merge_conflict_summary=Messaggio d'errore
pulls.rebase_conflict=Merge non riuscito: c'è stato un conflitto durante il rebase dell'commit: %[1]s. Suggerimento: Prova una strategia diversa
@ -1771,7 +1781,7 @@ pulls.reopened_at=`ha riaperto questa richiesta di modifica <a id="%[1]s" href="
pulls.auto_merge_button_when_succeed=(Quando i controlli sono superati)
pulls.auto_merge_when_succeed=Unione automatica quando tutti i controlli sono superati
pulls.auto_merge_newly_scheduled=La pull request era programmata per unire quando tutti i controlli sono superati.
pulls.auto_merge_newly_scheduled=La richiesta di modifica era programmata per essere fusa al passare di tutti i controlli.
pulls.auto_merge_has_pending_schedule=%[1]s ha programmato questa pull request per unire automaticamente quando tutti i controlli hanno successo %[2]s.
pulls.auto_merge_cancel_schedule=Annulla fusione automatica
@ -1781,7 +1791,7 @@ pulls.auto_merge_canceled_schedule=L'unione automatica è stata annullata per qu
pulls.auto_merge_newly_scheduled_comment=`ha programmato questa pull request per unire automaticamente quando tutti i controlli sono superati %[1]s`
pulls.auto_merge_canceled_schedule_comment=`cancella l'auto-merging di questa pull request quando tutti i testi sono superati %[1]s`
pulls.delete.title=Eliminare questa pull request?
pulls.delete.title=Eliminare questa richiesta di modifica?
pulls.delete.text=Vuoi davvero eliminare questa richiesta di modifica? (Ciò rimuoverà permanentemente tutti i contenuti. Considera invece di chiuderla, se vuoi tenerla archiviata)
@ -3883,6 +3893,9 @@ issue_kind = Cerca segnalazioni...
pull_kind = Cerca richieste...
exact = Esatto
milestone_kind = Ricerca tappe...
regexp_tooltip = Interpreta i termini di ricerca come un'espressione regolare
regexp = Espressione Regolare
union_tooltip = Include i risultati che combaciano con una qualsiasi delle parole chiave separata da spazi
[munits.data]
gib = GiB
@ -3897,3 +3910,8 @@ b = B
filepreview.lines = Linee da %[1]d a %[2]d in %[3]s
filepreview.truncated = L'anteprima è stata troncata
filepreview.line = Linea %[1]d in %[2]s
[repo.permissions]
issues.write = <b>Scrittura:</b> Chiudere segnalazioni e gestire metadati come etichette, traguardi, assegnatarɜ, scadenze e dipendenze.
pulls.write = <b>Scrittura:</b> Chiudere richieste di modifica e gestire metadati come etichette, traguardi, assegnatarɜ, scadenze e dipendenze.

View file

@ -112,7 +112,7 @@ preview=Priekšskatījums
loading=Notiek ielāde…
error=Kļūda
error404=Lapa, ko tiek mēģināts atvērt, vai nu <strong>nepastāv</strong>, vai <strong>ir noņemta</strong> vai arī <strong>nav tiesību</strong> to apskatīt.
error404=Šī lapa vai nu <strong>nepastāv</strong>, vai <strong>ir noņemta</strong>, vai arī <strong>nav tiesību</strong> to apskatīt.
go_back=Atgriezties
never=Nekad
@ -437,7 +437,7 @@ invalid_code=Apstiprināšanas kods ir nederīgs, vai ir beidzies tā derīgums.
invalid_code_forgot_password=Apstiprināšanas kods ir nederīgs, vai tā derīgums ir beidzies. Jāklikšķina <a href="%s">šeit</a>, lai uzsāktu jaunu sesiju.
invalid_password=Parole neatbilst tai, kas tika izmantota konta izveidošanas laikā.
reset_password_helper=Atjaunot paroli
reset_password_wrong_user=Tu esi pieteicies kā %s, bet konta atkopes saite ir paredzēta %s
reset_password_wrong_user=Tu pieteicies kā %s, bet konta atkopes saite ir paredzēta %s
password_too_short=Paroles garums nevar būt mazāks par %d rakstzīmēm.
non_local_account=Ārējie konti nevar mainīt paroli, izmantojot, Forgejo saskarni.
verify=Apliecināt
@ -463,8 +463,8 @@ openid_connect_desc=Izvēlētais OpenID URI ir nezināms. Tas ir jāasasaista ar
openid_register_title=Izveidot jaunu kontu
openid_register_desc=Izvēlētais OpenID URI ir nezināms. Tas ir jāasasaista ar jaunu kontu šeit.
openid_signin_desc=Jāievada OpenID URI. Piemēram, anna.openid.example.org vai https://openid.example.org/anna.
disable_forgot_password_mail=Konta atkopšana ir atspējota, jo nav uzstādīta e-pasta izsūtīšana. Lūgums sazināties ar vietnes pārvaldītāju.
disable_forgot_password_mail_admin=Kontu atkope ir pieejama tikai tad, kad ir veikta e-pasta servera iestatīšana. Lūgums iestatīt e-pasta serveri, lai iespējotu kontu atkopi.
disable_forgot_password_mail=Konta atkope ir atspējota, jo nav iestatīta e-pasta izsūtīšana. Lūgums sazināties ar vietnes pārvaldītāju.
disable_forgot_password_mail_admin=Kontu atkope ir pieejama tikai tad, kad ir veikta e-pasta servera iestatīšana. Lūgums iestatīt e-pasta serveri, lai varētu iespējot kontu atkopi.
email_domain_blacklisted=Nav atļauts reģistrēties ar šādu e-pasta adresi.
authorize_application=Pilnvarot lietotni
authorize_redirect_notice=Notiks pārvirzīšana uz %s, ja pilnvaroši šo lietotni.
@ -982,7 +982,7 @@ revoke_oauth2_grant_description=Šīs trešās puses lietotnes piekļuves atsauk
revoke_oauth2_grant_success=Piekļuve sekmīgi atsaukta.
twofa_desc=Lai aizsargātu savu kontu no paroļu zādzības, var izmantot viedtālruni vai citu ierīci, lai saņemtu laikā balstītas vienreiz izmantojamas paroles ("TOTP").
twofa_recovery_tip=Ja ierīce tiks pazaudēta, būs iespējams izmantot vienreizējas izmantošanas atkopšanas atslēgu, lai atgūtu piekļuvi savam kontam.
twofa_recovery_tip=Ja ierīce tiks pazaudēta, būs iespējams izmantot vienreizējas izmantošanas atkopes atslēgu, lai atgūtu piekļuvi savam kontam.
twofa_is_enrolled=Kontam šobrīd ir <strong>ieslēgta</strong> divpakāpju pieteikšanās.
twofa_not_enrolled=Kontam šobrīd nav ieslēgta divpakāpju pieteikšanās.
twofa_disable=Atspējot divpakāpju pieteikšanos
@ -991,13 +991,13 @@ twofa_scratch_token_regenerated=Vienreizējā pilnvara tagad ir %s. Tā ir jāgl
twofa_enroll=Ieslēgt divpakāpju pieteikšanos
twofa_disable_note=Ja nepieciešams, divpakāpju pieteikšanos var atslēgt.
twofa_disable_desc=Divpakāpju pieteikšanās atspējošana padarīs kontu mazāk drošu. Turpināt?
regenerate_scratch_token_desc=Ja atkopšanas atslēga ir pazaudēta vai tā jau ir izmantota, lai pieteiktos, to var atiestatīt šeit.
regenerate_scratch_token_desc=Ja atkopes atslēga ir pazaudēta vai tā jau ir izmantota, lai pieteiktos, to var atiestatīt šeit.
twofa_disabled=Divpakāpju pieteikšanās tika atspējota.
scan_this_image=Šis attēls ir jānolasa ar autentificēšanās lietotni:
or_enter_secret=Vai jāievada noslēpums: %s
then_enter_passcode=Pēc tam jāievada lietotnē attēlotais piekļuves kods:
passcode_invalid=Piekļuves kods ir nepareizs. Jāmēģina vēlreiz.
twofa_enrolled=Kontam tika ieslēgta divpakāpju pieteikšanās. Vienreiz izmantojamā atkopšanas atslēga (%s) ir jāglabā drošā vietā, jo tā vairs netiks rādīta.
twofa_enrolled=Kontam tika ieslēgta divpakāpju pieteikšanās. Vienreiz izmantojamā atkopes atslēga (%s) ir jāglabā drošā vietā, jo tā vairs netiks rādīta.
twofa_failed_get_secret=Neizdevās ielādēt noslēpumu.
webauthn_desc=Drošības atslēgas ir ierīces, kas satur kriptogrāfiskas atslēgas. Tās var tikt izmantotas divpakāpju apliecināšanai. Drošības atslēgām ir jāatbilst <a rel="noreferrer" target="_blank" href="%s">WebAuthn autentificētāja</a> standartam.
@ -2795,7 +2795,7 @@ settings.transfer.modal.title = Nodot īpašumtiesības
settings.mirror_settings.push_mirror.copy_public_key = Ievietot publisko atslēgu starpliktuvē
pulls.agit_explanation = Izveidots ar AGit darbplūsmu. AGit ļauj līdzalībniekiem ieteikt izmaiņas ar "git push" bez atzarojuma vai jauna zara izveidošanas.
settings.wiki_rename_branch_main_notices_1 = Šo darbību <strong>NEVAR</strong> atsaukt.
release.download_count_few = %s lejupielādes
release.download_count_few = %s lejupielādes/žu
settings.rename_branch_failed_protected = Nevar pārdēvēt zaru %s, jo tas ir aizsargāts zars.
release.type_external_asset = Ārējs līdzeklis
release.hide_archive_links = Paslēpt automātiski izveidotos arhīvus
@ -3439,7 +3439,7 @@ config.require_sign_in_view=Pieprasīt pieteikšanos, lai apskatītu saturu
config.mail_notify=Iespējot e-pasta paziņojumus
config.enable_captcha=Iespējot drošības kodu
config.active_code_lives=Aktivēšanas koda derīguma laiks
config.reset_password_code_lives=Atkopšanas koda derīguma laiks
config.reset_password_code_lives=Atkopes koda derīguma laiks
config.default_keep_email_private=Pēc noklusējuma slēpt e-pasta adreses
config.default_allow_create_organization=Pēc noklusējuma ļaut apvienību izveidošanu
config.enable_timetracking=Iespējot laika uzskaiti

View file

@ -1087,6 +1087,10 @@ quota.sizes.assets.attachments.releases = Anexos de release
quota.sizes.assets.artifacts = Artefatos
quota.sizes.assets.packages.all = Pacotes
quota.sizes.wiki = Wiki
regenerate_token = Regenerar
regenerate_token_success = O token foi regenerado. Aplicações que usam este token não terão mais acesso à sua conta e precisam ser atualizadas com o novo token.
access_token_regeneration = Regenerar token de acesso
access_token_regeneration_desc = Regenerar um token de acesso irá revogar o acesso a essa conta para as aplicações que estiverem utilizando este token. Isto não pode ser desfeito. Continuar?
[repo]
owner=Proprietário
@ -1164,7 +1168,7 @@ forks=Forks
reactions_more=e %d mais
unit_disabled=O administrador do site desabilitou esta seção do repositório.
language_other=Outra
adopt_search=Digite o nome de usuário para pesquisar por repositórios órfãos... (deixe em branco para encontrar todos)
adopt_search=Digite o nome de usuário para pesquisar por repositórios órfãos (deixe em branco para encontrar todos)
adopt_preexisting_label=Adotar arquivos
adopt_preexisting=Adotar arquivos pré-existentes
adopt_preexisting_content=Criar repositório a partir de %s
@ -1242,7 +1246,7 @@ migrate.migrate_items_options=Um Token de Acesso é necessário para migrar iten
migrated_from=Migrado de <a href="%[1]s">%[2]s</a>
migrated_from_fake=Migrado de %[1]s
migrate.migrate=Migrar de %s
migrate.migrating=Migrando a partir de <b>%s</b> ...
migrate.migrating=Migrando de <b>%s</b> …
migrate.migrating_failed=Migração a partir de <b>%s</b> falhou.
migrate.migrating_failed.error=Falha ao migrar: %s
migrate.migrating_failed_no_addr=A migração falhou.
@ -2489,7 +2493,7 @@ settings.lfs_invalid_locking_path=Caminho inválido: %s
settings.lfs_invalid_lock_directory=Não é possível bloquear o diretório: %s
settings.lfs_lock_already_exists=O bloqueio já existe: %s
settings.lfs_lock=Bloqueio
settings.lfs_lock_path=Caminho de arquivo para bloquear...
settings.lfs_lock_path=Caminho de arquivo para travar…
settings.lfs_locks_no_locks=Sem bloqueios
settings.lfs_lock_file_no_exist=Arquivo bloqueado não existe no branch padrão
settings.lfs_force_unlock=Forçar desbloqueio
@ -2901,9 +2905,11 @@ pulls.editable = Editável
pulls.editable_explanation = Este pull request permite edições de mantenedores. Voçê pode contribuir diretamenta para ele.
issues.reopen.blocked_by_user = Você não pode reabrir este issue porque você foi bloqueado pelo dono do repositório ou pelo criador deste issue.
pulls.comment.blocked_by_user = Você não pode comentar neste pull request porque você foi bloqueado pelo dono do repositório ou pelo autor do pull request.
issues.filter_no_results = Nenhum resultado
issues.filter_no_results_placeholder = Tente ajustar seus filtros de pesquisa.
[graphs]
component_loading = Carregando %s...
component_loading = Carregando %s
component_loading_failed = Não foi possível carregar o(a) %s
component_loading_info = Pode demorar um pouco…
contributors.what = contribuições
@ -4005,33 +4011,33 @@ executable_file = Arquivo executável
[search]
org_kind = Buscar organizações...
team_kind = Buscar equipes...
code_kind = Buscar código...
user_kind = Buscar usuários...
org_kind = Buscar organizações
team_kind = Buscar equipes
code_kind = Buscar código
user_kind = Buscar usuários
no_results = Nenhum resultado encontrado.
keyword_search_unavailable = A busca por palavras-chave não está disponível. Entre em contato com o administrador.
package_kind = Buscar pacotes...
project_kind = Buscar projetos...
search = Buscar...
package_kind = Buscar pacotes
project_kind = Buscar projetos
search = Buscar
fuzzy = Aproximada
fuzzy_tooltip = Inclui resultados que se aproximam dos termos de busca
match = Correspondente
match_tooltip = Inclui apenas os resultados que correspondem exatamente aos termos de busca
repo_kind = Buscar repositórios...
repo_kind = Buscar repositórios
type_tooltip = Tipo de busca
code_search_by_git_grep = Os resultados atuais da pesquisa de código são fornecidos por "git grep". Pode haver melhores resultados se o administrador do site ativar o indexador de código.
branch_kind = Buscar ramos…
commit_kind = Buscar commits…
runner_kind = Pesquisar runners...
runner_kind = Buscar runners…
code_search_unavailable = A pesquisa de código não está disponível no momento. Entre em contato com o administrador do site.
milestone_kind = Pesquisar marcos...
union_tooltip = Incluir resultados que correspondam a quaisquer palavras-chave separadas por espaços em branco
union = União
exact = Exato
exact_tooltip = Incluir apenas resultados que correspondam exatamente ao termo de pesquisa
issue_kind = Pesquisar problemas...
pull_kind = Pesquisar pulls...
issue_kind = Buscar issues…
pull_kind = Buscar pulls…
regexp_tooltip = Interpretar o termo de busca como uma expressão regular
regexp = RegExp

View file

@ -155,7 +155,7 @@ filter.public = Публичные
filter.private = Частные
filter.is_archived = Архивированные
filter.not_mirror = Не зеркала
more_items = Больше элементов
more_items = Больше разделов
invalid_data = Неверные данные: %v
copy_generic = Копировать в буфер обмена
test = Проверить
@ -4060,7 +4060,7 @@ filepreview.lines = Строки с %[1]d по %[2]d в %[3]s
filepreview.truncated = Предпросмотр был обрезан
[translation_meta]
test = forgejo =)
test = Forgejo!
[repo.permissions]
code.write = <b>Запись:</b> отправка изменений в репозиторий, создание веток и тегов.

View file

@ -56,7 +56,7 @@ organization=Organizasyon
mirror=Yansı
new_repo=Yeni Depo
new_migrate=Yeni Göç
new_mirror=Yeni Yansı
new_mirror=Yeni yansıma
new_fork=Yeni Depo Çatalı
new_org=Yeni Organizasyon
new_project=Yeni proje
@ -76,7 +76,7 @@ collaborative=İşbirlikçi
forks=Çatallar
activities=Etkinlikler
pull_requests=Değişiklik İstekleri
pull_requests=Değişiklik istekleri
issues=Konular
milestones=Kilometre Taşları
@ -112,7 +112,7 @@ preview=Önizleme
loading=Yükleniyor…
error=Hata
error404=Ulaşmaya çalıştığınız sayfa <strong>mevcut değil</strong> veya <strong>görüntüleme yetkiniz yok</strong>.
error404=Ulaşmaya çalıştığınız sayfa <strong>mevcut değil</strong> ,<strong>kaldırılmış</strong> veya <strong>görüntüleme yetkiniz yok</strong>.
go_back=Geri Git
never=Asla
@ -146,7 +146,7 @@ filter = Filtrele
filter.not_archived = Arşivlenmemiş
filter.clear = Filtreleri Temizle
filter.is_archived = Arşivlenmiş
filter.is_mirror = Yansılaştırılmış
filter.is_mirror = Yansılar
filter.is_fork = Çatallar
filter.not_fork = Çatallanmayanlar
filter.not_mirror = Yansılanmamış

View file

@ -1,5 +1,12 @@
{
"repo.pulls.merged_title_desc": "yhdistetty %[1]d committia lähteestä <code>%[2]s</code> kohteeseen <code>%[3]s</code> %[4]s",
"repo.pulls.title_desc": "haluaa yhdistää %[1]d committia lähteestä <code>%[2]s</code> kohteeseen <code id=\"%[4]s\">%[3]s</code>",
"search.milestone_kind": "Etsi merkkipaaluja..."
"search.milestone_kind": "Etsi merkkipaaluja...",
"home.welcome.no_activity": "Ei toimintaa",
"incorrect_root_url": "Tämä Forgejo-instanssi on määritetty toimimaan osoitteessa \"%s\". Tarkastelet tällä hetkellä Forgejoa eri URL-osoitteen kautta, mikä saattaa aiheuttaa sovelluksen osien toimimattomuutta. Virallinen URL-osoite on Forgejo-ylläpitäjien hallinnoima ROOT_URL-asetus app.ini -tiedostossa.",
"themes.names.forgejo-auto": "Forgejo (käyttöjärjestelmän määrittelemä teema)",
"home.welcome.activity_hint": "Syötteelläsi ei ole vielä mitään. Toimintasi ja toiminta repositorioissa joita seuraat ilmaantuu tälle sivulle.",
"home.explore_repos": "Tutki repositorioita",
"home.explore_users": "Tutki käyttäjiä",
"home.explore_orgs": "Tutki organisaatioita"
}

652
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -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
View file

@ -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"

View file

@ -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]

View file

@ -0,0 +1,37 @@
<!--start release-notes-assistant-->
## Release notes
<!--URL:https://codeberg.org/forgejo/forgejo-->
- Localization
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7277): <!--number 7277 --><!--line 0 --><!--description aTE4bjogdXBkYXRlIG9mIHRyYW5zbGF0aW9ucyBmcm9tIENvZGViZXJnIFRyYW5zbGF0ZQ==-->update of translations from Codeberg Translate<!--description-->
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7067): <!--number 7067 --><!--line 0 --><!--description aTE4bjogdXBkYXRlIG9mIHRyYW5zbGF0aW9ucyBmcm9tIG11bHRpcGxlIHNvdXJjZXM=-->update of translations from multiple sources<!--description-->
- Bug fixes
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7251) ([backported](https://codeberg.org/forgejo/forgejo/pulls/7255)): <!--number 7255 --><!--line 0 --><!--description V2hlbiBtaWdyYXRpbmcgZnJvbSBhIEZvcmdlam8gdmVyc2lvbiBsb3dlciB0aGFuIHYxMCwgdGhlIFRPVFAgc2VjcmV0cyBmb3VuZCB0byBiZSBjb3JydXB0ZWQgYXJlIG5vdyB0cmFuc3BhcmVudGx5IHJlbW92ZWQgZnJvbSB0aGUgZGF0YWJhc2UgaW5zdGVhZCBvZiBmYWlsaW5nIHRoZSBtaWdyYXRpb24uIFRPVFAgaXMgbm8gbG9uZ2VyIHJlcXVpcmVkIHRvIGxvZ2luIHdpdGggdGhlIGFzc29jaWF0ZWQgdXNlcnMuIFRoZXkgc2hvdWxkIGJlIGluZm9ybWVkIGJlY2F1c2UgdGhleSB3aWxsIG5lZWQgdG8gdmlzaXQgdGhlaXIgc2VjdXJpdHkgc2V0dGluZ3MgYW5kIGNvbmZpZ3VyZSBUT1RQIGFnYWluLiBObyBvdGhlciBhY3Rpb24gaXMgcmVxdWlyZWQu-->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.<!--description-->
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7167) ([backported](https://codeberg.org/forgejo/forgejo/pulls/7178)): <!--number 7178 --><!--line 0 --><!--description Zml4OiBubyBub3RpZmljYXRpb24gZm9yIHJlcGxpZXMgdG8gcGVuZGluZyBjb21tZW50cw==-->replies to pending review comments no longer generate a notification, this was caused by an incomplete determination if the comment was part of the pending review or not<!--description-->
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7143) ([backported](https://codeberg.org/forgejo/forgejo/pulls/7144)): <!--number 7144 --><!--line 0 --><!--description Zml4OiBjb25zaWRlciBwdWJsaWMgaXNzdWVzIGZvciBwcm9qZWN0IGJvYXJkcw==-->consider public issues for project boards<!--description-->
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7038) ([backported](https://codeberg.org/forgejo/forgejo/pulls/7046)): <!--number 7046 --><!--line 0 --><!--description Zml4KHJlbGVhc2UpOiB0aGUgcm9vdGxlc3MgaW1hZ2UgdmVyc2lvbiBsYWJlbCBpcyBub3Qgc2V0-->the rootless Forgejo image version label is not set<!--description-->
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7004) ([backported](https://codeberg.org/forgejo/forgejo/pulls/7018)): <!--number 7018 --><!--line 0 --><!--description Zml4OiBkbyBub3QgYWxsb3cgU1NIIHVybCBmb3IgbWlncmF0aW9u-->do not allow SSH url for migration<!--description-->
- [PR](https://codeberg.org/forgejo/forgejo/pulls/6680) ([backported](https://codeberg.org/forgejo/forgejo/pulls/6930)): <!--number 6930 --><!--line 0 --><!--description c2V0dGluZy5TZXJ2aWNlLkVuYWJsZUludGVybmFsU2lnbkluID0gZmFsc2UgaXMgZGlzYWJsaW5nIGZvcmdvdHRlbiBwYXNzd29yZA==-->`setting.Service.EnableInternalSignIn = false` is disabling forgotten password<!--description-->
- [PR](https://codeberg.org/forgejo/forgejo/pulls/6920) ([backported](https://codeberg.org/forgejo/forgejo/pulls/6929)): <!--number 6929 --><!--line 0 --><!--description Zml4OiBzaG93IGludGVybmFsIGxvZ2luIHByb21wdCBmb3IgYWNjb3VudCBsaW5raW5n-->show internal login prompt for account linking<!--description-->
- [PR](https://codeberg.org/forgejo/forgejo/pulls/6896) ([backported](https://codeberg.org/forgejo/forgejo/pulls/6915)): <!--number 6915 --><!--line 0 --><!--description ZW5hYmxlIHNzaCBtaXJyb3JzIGluIHJvb3RsZXNzIGltYWdlcw==-->enable ssh mirrors in rootless Forgejo images<!--description-->
- [PR](https://codeberg.org/forgejo/forgejo/pulls/6853) ([backported](https://codeberg.org/forgejo/forgejo/pulls/6859)): <!--number 6859 --><!--line 0 --><!--description Zml4OiByZW5kZXIgbGluayBpbiBoZWFkaW5nIGNvcnJlY3RseSBpbiBUT0M=-->render link in heading correctly in wiki TOC<!--description-->
- Included for completeness but not worth a release note
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7284): <!--number 7284 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL3JlZGlzL2dvLXJlZGlzL3Y5IHRvIHY5LjcuMyAodjEwLjAvZm9yZ2Vqbyk=-->Update module github.com/redis/go-redis/v9 to v9.7.3 (v10.0/forgejo)<!--description-->
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7270) ([backported](https://codeberg.org/forgejo/forgejo/pulls/7272)): <!--number 7272 --><!--line 0 --><!--description Zml4OiBjb25zaWRlciBpc3N1ZXMgaW4gcmVwb3NpdG9yeSBhY2Nlc3NpYmxlIHZpYSBgYWNjZXNzYCB0YWJsZQ==-->fix: consider issues in repository accessible via `access` table<!--description-->
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7199) ([backported](https://codeberg.org/forgejo/forgejo/pulls/7202)): <!--number 7202 --><!--line 0 --><!--description Zml4KGFwaSk6IG1pc3Mtc3BlbGxlZCBkZXNjcmlwdGlvbiwgY29ycmVjdGVkIHRvIGBwdWJsaWNg-->fix(api): miss-spelled description, corrected to `public`<!--description-->
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7171) ([backported](https://codeberg.org/forgejo/forgejo/pulls/7177)): <!--number 7177 --><!--line 0 --><!--description Zml4OiByZXZlcnQgaXNzdWUgcmVuZGVyaW5nIGZvciBgPGE+YCBlbGVtZW50-->fix: revert issue rendering for `<a>` element<!--description-->
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7078) ([backported](https://codeberg.org/forgejo/forgejo/pulls/7079)): <!--number 7079 --><!--line 0 --><!--description Y2hvcmUoY2kpOiBlbnN1cmUgdGhlIG1hbnVhbGx5IGNhY2hlZCBHbyBjYW4gYmUgcnVu-->chore(ci): ensure the manually cached Go can be run<!--description-->
- [PR](https://codeberg.org/forgejo/forgejo/pulls/6590) ([backported](https://codeberg.org/forgejo/forgejo/pulls/7073)): <!--number 7073 --><!--line 0 --><!--description Y2hvcmUoY2kpOiBHZXQgR28gYmluYXJ5IGZyb20gR09ST09UIGluc3RlYWQgb2YgaGFyZGNvZGVkIHBhdGg=-->chore(ci): Get Go binary from GOROOT instead of hardcoded path<!--description-->
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7072): <!--number 7072 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnb2xhbmcub3JnL3gvY3J5cHRvIHRvIHYwLjM1LjAgKHYxMC4wL2Zvcmdlam8p-->Update module golang.org/x/crypto to v0.35.0 (v10.0/forgejo)<!--description-->
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7052): <!--number 7052 --><!--line 0 --><!--description VXBkYXRlIGh0dHBzOi8vZGF0YS5mb3JnZWpvLm9yZy9mb3JnZWpvL2Zvcmdlam8tYnVpbGQtcHVibGlzaCBhY3Rpb24gdG8gdjUuMy40ICh2MTAuMC9mb3JnZWpvKQ==-->Update https://data.forgejo.org/forgejo/forgejo-build-publish action to v5.3.4 (v10.0/forgejo)<!--description-->
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7003) ([backported](https://codeberg.org/forgejo/forgejo/pulls/7014)): <!--number 7014 --><!--line 0 --><!--description Zml4OiByZXR1cm4gNDA0IGZvciBlbXB0eSByZXBvc2l0b3JpZXM=-->fix: return 404 for empty repositories<!--description-->
- [PR](https://codeberg.org/forgejo/forgejo/pulls/6937) ([backported](https://codeberg.org/forgejo/forgejo/pulls/6976)): <!--number 6976 --><!--line 0 --><!--description Zml4OiBkZWxheSBkZWxldGluZyBhdXRob3JpemF0aW9uIHRva2Vu-->fix: delay deleting authorization token<!--description-->
- [PR](https://codeberg.org/forgejo/forgejo/pulls/6953) ([backported](https://codeberg.org/forgejo/forgejo/pulls/6954)): <!--number 6954 --><!--line 0 --><!--description Zml4OiBuYXRpdmUgcGFyc2luZyBvZiBzc2ggY2VydGlmaWNhdGUga2V5-->fix: native parsing of ssh certificate key<!--description-->
- [PR](https://codeberg.org/forgejo/forgejo/pulls/6898) ([backported](https://codeberg.org/forgejo/forgejo/pulls/6905)): <!--number 6905 --><!--line 0 --><!--description Zml4KHVpKTogaGlkZSBleHRyYSBQUiBwcm9wZXJ0eSBsYWJlbHMgb24gdGl0bGUgZWRpdA==-->fix(ui): hide extra PR property labels on title edit<!--description-->
- [PR](https://codeberg.org/forgejo/forgejo/pulls/6866) ([backported](https://codeberg.org/forgejo/forgejo/pulls/6884)): <!--number 6884 --><!--line 0 --><!--description Zml4OiBhbHdheXMgc2V0IHN0cmlwcGVkIHNsYXNoZXMgb24gaHR0cCByZXF1ZXN0-->fix: always set stripped slashes on http request<!--description-->
- [PR](https://codeberg.org/forgejo/forgejo/pulls/6851) ([backported](https://codeberg.org/forgejo/forgejo/pulls/6860)): <!--number 6860 --><!--line 0 --><!--description Zml4KHVpKTogaGlkZSAnTmV3IG1pZ3JhdGlvbicgYnV0dG9uIG9uIG9yZyBwYWdlcyB3aXRoIG1pZ3JhdGlvbnMgZGlzYWJsZWQgKCM2ODUwKQ==-->fix(ui): hide 'New migration' button on org pages with migrations disabled (#6850)<!--description-->
- [PR](https://codeberg.org/forgejo/forgejo/pulls/6700) ([backported](https://codeberg.org/forgejo/forgejo/pulls/6854)): <!--number 6854 --><!--line 0 --><!--description dWk6IHVwZGF0ZSBsYW5ndWFnZSBzdGF0cyBsYXlvdXQgYW5kIGNsaWNrIGJlaGF2aW9y-->ui: update language stats layout and click behavior<!--description-->
- [PR](https://codeberg.org/forgejo/forgejo/pulls/6812): <!--number 6812 --><!--line 0 --><!--description VXBkYXRlIGRlcGVuZGVuY3kgZ28gdG8gdjEuMjMuNiAodjEwLjAvZm9yZ2Vqbyk=-->Update dependency go to v1.23.6 (v10.0/forgejo)<!--description-->
<!--end release-notes-assistant-->

View file

@ -0,0 +1,13 @@
<!--start release-notes-assistant-->
## Release notes
<!--URL:https://codeberg.org/forgejo/forgejo-->
- Bug fixes
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7295) ([backported](https://codeberg.org/forgejo/forgejo/pulls/7306)): <!--number 7306 --><!--line 0 --><!--description Zml4OiB1c2UgY29ycmVjdCBpbnB1dCBmb3Igc3RyaXAgc2xhc2hlcyBtaWRkbGV3YXJl-->fixes a [regression introduced in Forgejo v10.0.2](https://codeberg.org/forgejo/forgejo/pulls/6866/files) which caused unnecessary escaping of URLs. The symptoms were, for instance, a [failure to access theme files when they contain a space](https://codeberg.org/forgejo/forgejo/issues/7294) or [double escaping of links](https://codeberg.org/forgejo/forgejo/issues/7292).<!--description-->
- Included for completeness but not worth a release note
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7304): <!--number 7304 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnb2xhbmcub3JnL3gvb2F1dGgyIHRvIHYwLjI3LjAgW1NFQ1VSSVRZXSAodjEwLjAvZm9yZ2Vqbyk=-->Update module golang.org/x/oauth2 to v0.27.0<!--description-->
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7303): <!--number 7303 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnb2xhbmcub3JnL3gvbmV0IHRvIHYwLjM2LjAgW1NFQ1VSSVRZXSAodjEwLjAvZm9yZ2Vqbyk=-->Update module golang.org/x/net to v0.36.0<!--description-->
- [PR](https://codeberg.org/forgejo/forgejo/pulls/7302): <!--number 7302 --><!--line 0 --><!--description VXBkYXRlIG1vZHVsZSBnaXRodWIuY29tL2dvbGFuZy1qd3Qvand0L3Y1IHRvIHY1LjIuMiBbU0VDVVJJVFldICh2MTAuMC9mb3JnZWpvKQ==-->Update module github.com/golang-jwt/jwt/v5 to v5.2.2<!--description-->
<!--end release-notes-assistant-->

View 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
View 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.

View file

@ -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
},

View file

@ -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"}

View file

@ -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()

View file

@ -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
}

View file

@ -16,11 +16,11 @@ import (
const cacheKeyNodeInfoUsage = "API_NodeInfoUsage"
// NodeInfo returns the NodeInfo for the Gitea instance to allow for federation
// NodeInfo returns the NodeInfo for the Forgejo instance to allow for federation
func NodeInfo(ctx *context.APIContext) {
// swagger:operation GET /nodeinfo miscellaneous getNodeInfo
// ---
// summary: Returns the nodeinfo of the Gitea application
// summary: Returns the nodeinfo of the Forgejo application
// produces:
// - application/json
// responses:

View file

@ -15,7 +15,7 @@ import (
func Version(ctx *context.APIContext) {
// swagger:operation GET /version miscellaneous getVersion
// ---
// summary: Returns the version of the Gitea application
// summary: Returns the version of the running application
// produces:
// - application/json
// responses:

View file

@ -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)

View file

@ -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)

View file

@ -77,27 +77,27 @@ func ProtocolMiddlewares() (handlers []any) {
func stripSlashesMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
// First of all escape the URL RawPath to ensure that all routing is done using a correctly escaped URL
// Ensure that URL.RawPath is always set.
req.URL.RawPath = req.URL.EscapedPath()
urlPath := req.URL.RawPath
rctx := chi.RouteContext(req.Context())
if rctx != nil && rctx.RoutePath != "" {
urlPath = rctx.RoutePath
}
sanitizedPath := &strings.Builder{}
prevWasSlash := false
for _, chr := range strings.TrimRight(urlPath, "/") {
if chr != '/' || !prevWasSlash {
sanitizedPath.WriteRune(chr)
sanitize := func(path string) string {
sanitizedPath := &strings.Builder{}
prevWasSlash := false
for _, chr := range strings.TrimRight(path, "/") {
if chr != '/' || !prevWasSlash {
sanitizedPath.WriteRune(chr)
}
prevWasSlash = chr == '/'
}
prevWasSlash = chr == '/'
return sanitizedPath.String()
}
req.URL.Path = sanitizedPath.String()
// Sanitize the unescaped path for application logic.
req.URL.Path = sanitize(req.URL.Path)
rctx := chi.RouteContext(req.Context())
if rctx != nil {
rctx.RoutePath = req.URL.Path
// Sanitize the escaped path for routing.
rctx.RoutePath = sanitize(req.URL.RawPath)
}
next.ServeHTTP(resp, req)
})

View file

@ -15,9 +15,10 @@ import (
func TestStripSlashesMiddleware(t *testing.T) {
type test struct {
name string
expectedPath string
inputPath string
name string
expectedPath string
expectedNormalPath string
inputPath string
}
tests := []test{
@ -57,9 +58,16 @@ func TestStripSlashesMiddleware(t *testing.T) {
expectedPath: "/repo/migrate",
},
{
name: "path with encoded slash",
inputPath: "/user2/%2F%2Frepo1",
expectedPath: "/user2/%2F%2Frepo1",
name: "path with encoded slash",
inputPath: "/user2/%2F%2Frepo1",
expectedPath: "/user2/%2F%2Frepo1",
expectedNormalPath: "/user2/repo1",
},
{
name: "path with space",
inputPath: "/assets/css/theme%20cappuccino.css",
expectedPath: "/assets/css/theme%20cappuccino.css",
expectedNormalPath: "/assets/css/theme cappuccino.css",
},
}
@ -69,7 +77,11 @@ func TestStripSlashesMiddleware(t *testing.T) {
called := false
r.Get("*", func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, tt.expectedPath, r.URL.Path)
if tt.expectedNormalPath != "" {
assert.Equal(t, tt.expectedNormalPath, r.URL.Path)
} else {
assert.Equal(t, tt.expectedPath, r.URL.Path)
}
rctx := chi.RouteContext(r.Context())
assert.Equal(t, tt.expectedPath, rctx.RoutePath)

View file

@ -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

View file

@ -1059,7 +1059,7 @@ func RepoRefByType(refType RepoRefType, ignoreNotExistErr ...bool) func(*Context
if refType == RepoRefLegacy {
// redirect from old URL scheme to new URL scheme
prefix := strings.TrimPrefix(setting.AppSubURL+strings.ToLower(strings.TrimSuffix(ctx.Req.URL.Path, ctx.PathParamRaw("*"))), strings.ToLower(ctx.Repo.RepoLink))
prefix := strings.TrimPrefix(setting.AppSubURL+strings.ToLower(strings.TrimSuffix(ctx.Req.URL.Path, ctx.Params("*"))), strings.ToLower(ctx.Repo.RepoLink))
ctx.Redirect(path.Join(
ctx.Repo.RepoLink,

View file

@ -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) {

View file

@ -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) {

View file

@ -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()
}

View file

@ -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())
}

View file

@ -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{} }

View file

@ -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) {

View file

@ -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) {

View file

@ -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) {

View file

@ -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) {

View file

@ -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 {

View file

@ -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) {

View file

@ -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 {

View file

@ -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) {

View file

@ -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) {

View file

@ -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) {

View file

@ -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)) {

View file

@ -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) {

View file

@ -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) {

View file

@ -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) {

View file

@ -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 {

View file

@ -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) {

View file

@ -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))

View file

@ -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) {

View file

@ -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 {

View file

@ -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
}

View file

@ -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 {

View file

@ -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" .}}

View file

@ -19,8 +19,8 @@
{{range .BlockingDependencies}}
<div class="item dependency{{if .Issue.IsClosed}} is-closed{{end}} tw-flex tw-items-center tw-justify-between">
<div class="item-left tw-flex tw-justify-center tw-flex-col tw-flex-1 gt-ellipsis">
<a class="title muted" href="{{.Issue.Link}}" data-tooltip-content="#{{.Issue.Index}} {{RenderRefIssueTitle $.Context .Issue.Title}}}">
#{{.Issue.Index}} {{RenderRefIssueTitle $.Context .Issue.Title}}}
<a class="title muted" href="{{.Issue.Link}}" data-tooltip-content="#{{.Issue.Index}} {{RenderRefIssueTitle $.Context .Issue.Title}}">
#{{.Issue.Index}} {{RenderRefIssueTitle $.Context .Issue.Title}}
</a>
<div class="text small gt-ellipsis" data-tooltip-content="{{.Repository.OwnerName}}/{{.Repository.Name}}">
{{.Repository.OwnerName}}/{{.Repository.Name}}

View file

@ -1877,7 +1877,7 @@
"tags": [
"miscellaneous"
],
"summary": "Returns the nodeinfo of the Gitea application",
"summary": "Returns the nodeinfo of the Forgejo application",
"operationId": "getNodeInfo",
"responses": {
"200": {
@ -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"
}
@ -20530,7 +20568,7 @@
"tags": [
"miscellaneous"
],
"summary": "Returns the version of the Gitea application",
"summary": "Returns the version of the running application",
"operationId": "getVersion",
"responses": {
"200": {
@ -27943,7 +27981,7 @@
"x-go-name": "FullName"
},
"html_url": {
"description": "URL to the user's gitea page",
"description": "URL to the user's profile page",
"type": "string",
"x-go-name": "HTMLURL"
},

View file

@ -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) {

View file

@ -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(`bWV0YWRhdGEuZ3oAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAwMDA0NDQAMDAwMDAw
MAAwMDAwMDAwADAwMDAwMDAxMTM0ADE0NDQyNjI3NzcyADAxMzQ1NAAgMAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1c3RhcgAwMHdoZWVsAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAd2hlZWwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMDAwMDAwADAwMDAw
MDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf
iwgA+i+LZAIDxVRbb9MwFH73rzB9KTzksnYrkyUmKm1CRaqECuIBhCInOU28xRdsZ7Sa4LdznN7W
bExcHkgi5ficz+d852JHUUSf2TZfJzq/hsKzNyAZe2+gEEtRcC+0IopLYLSEvK0yoRzavLbkFqxD
K3tk+8eNiVC6B6VxGo+JabhfaisZXZ1Psslp1AjVriLZuobw1tfaOkYi+lbXis65sPR5zpVwHuxS
gCpfBJC28LUVFhjJhSqFZRT/pADrs6LmAmN9/kJK7pHyKD15GaVnUXpO05R1X5zuHvqJlGDQK6hC
QBf3YSaXO8Qak9nUQQolPDiPii0TCco/VobFwYzgIziGC5oI38HFq0G3CMunarl59hUdng1R6dcG
ObESbqHRZhvKWLDQAHdoWvLGwaET2RGJ/0K6BFdYYXynmNIFbqbfLDcGLMXhoL4GOl/M6ChO+0NH
p+9mBCQXTWjXtUXJvq7COi60JLCCovU8b7CdYQpg5UGFwPul5ZktdZEtxQ6zkdAbEg8ySour6eX8
KpZlkPkNbNU9LnEFMohoQcdJz5qgrtBqGdscAY3I+4BfGpJtsQKg1hIMr7CNtffGsSSphK/bPGSb
7I5G3wFpRIFpb7Kazz4QCZ7jgeCM3n0nRjsfsJ43TSbBueCedEXRXU82Zdm2PTPc150jZLpTlllo
ePbEBXA8RP0R6gbox8WA/N747OOM45M4PSYRevCPRHaT/AdEhumQHJ+jULEHdMbxOB5NiBOVEqrK
bmDNiLt/sx6gp8S1UnK7/qsTEa6jeyP9E+HiLnPUBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZGF0
YS50YXIuZ3oAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAwMDA0NDQAMDAwMDAwMAAw
MDAwMDAwADAwMDAwMDA1MzMzADE0NDQyNjI3NzcyADAxMzM3NwAgMAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1c3RhcgAwMHdoZWVsAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAd2hlZWwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMDAwMDAwADAwMDAwMDAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfiwgA
+i+LZAID7Fp7U9tIEs/f+hR94m79KCMTnleuZfcMCNCtsSnbJJsiOSNLY3uCLGn1CMvl8dnv16OH
sQnZvatdbjfFFBU0M/2e7p7uISdiPpGeePZ7jo3nGxu729vPNrKx+hubW8+eb29vb+5u7u3tbQJ+
c3dr4xltPHuEkcaJHUGUm5kQ3hfgfml/Vbk/yYiDNHIE6bMkCeNWsxml49upmMdGEE11TePPUDjq
gyqRfS0q2rOn8fWMvtk+OjONufv/i//tnZ3te/G/ufMU/48xXDFOpyPpc5QnQUSXf7k8SKXn0iCx
kzR+Uy0SQxLZ72S87kjODM2x7cs4EVFzBd+I302/H0e278z25zZD1P5bEjVtf3lo2qhNfeQluons
MBQRTSBoMhPkixs661u0aWyQovL6jibtc2ukaUOAXa1wuKJDEj8nwo9l4JPtuwxLNyISoBLLqS9c
tTqGIRIC38sfAunMJA3s2HbthUJTmczSseEE8+Z18LzWgFAypjAK3oKPhs+38C6yCclTTqRjJ8wv
mBBD3QTRtaFp9Xq3NzQHrXod3zTkHU/CgNEtzZFtY0pjwSiFukoVWtISs8IKxkaD6nU3ID9IFGZy
l2CQJrF0FTlFZir9KcUySZVgcb1uQISe790q4WIKFnSpL35KZcQIMuGN1I/TMAyiBLbC2UhIeiM9
jyIRpzAaRLIhxHoQatpFbE+Fts5D066urviK0SJFT1Bl5WwqmrZGvVD4uaZO4Cc4Kyye23EMZleu
UyHJwkFO20nkO5FxG3uBc62xn7w4a7WOGNsq3TJgiu/pg+t80IjWaGw713BH3HzAytSnaiSSNMKH
DXJRZN+yoYazSNhuq3VQILRanaA4yTGfc1wDRVCJaZ9cxygpj0rKmmJ5G6TkgPRUJNAtTGZMHsnH
uaZJZM8F7Ie1K6ZkxPLfuGgzsmpiJHIOE+NkP0jWQOkgfZcPBGTkOlAd2/M4OBSxhTJ0UMApcQlO
40uvpoiELLFCGOXUqrKm5fRlLH76ReKFvWHqJEod1neAoxU+TPtlhkz+DjfHw/l+lt0qooJkTCLh
u9pH9ilNO4SjwB0yP2NPO4+CsYfyhflDoDg7ZCcDI2hhJ3SZRXAW0csBXaQnCNiRDnKFWJCuclY5
s4aU79SYfXgbyeksoapTo01cYev4Z4uq/wxmCCNbMqFzEc1lrLIOPHiGhIPkMkW2RBQ1oKxQsenM
7GgqkEwCeOItIeHFytkSW/o4Ic2GEuFtlhRAJg4myY2NUOKUBcsEjrQ5Kt3ASecC2ipf5SIfLo40
olUGOUalppi4wvY4hDjFFFvKGZEvOJ6TSKpzbQDI8VL2Eq3Y9uRc5hwYXVkgZqJIPg0lZ4PmgSsn
/FsotcJ07Ml41tBcyaTHaYLFmBeVLRusRxNnFgukE1Dg1JInwEI6BQMuWsgGTXITKb43s2C+rAlM
NIGzgqVwlboBTKY4Ku8EFQafBJ4X3HCYwENcqZyllV0f9jhAjnHKA0ZuhaiZCCrfL04134pncF8a
Cy0zGPhyhrqjTsTsEft+ImF7TqPKOVfUxPUwPDVp0Dsevmz3TbIGdN7vvbCOzCOqtAeYVxr00hqe
9i6GBIh+uzt8Rb1jandf0Q9W96ihmT+e983BgHp9ss7OO5Z51CCre9i5OLK6J3QAPFw/1LHgzCA6
7BEzzElZJvCOtTOzf3iKafvA6ljDVw06toZdpnkMom06b/eH1uFFp92n84v+eW9ggv0RyHat7nEf
XMwzszs0NKuLNTJfYEKD03ano1i1LyB9X8l32Dt/1bdOTod02uscmVg8MCFZ+6BjZqy6r7TDTts6
a9BR+6x9YiqsHqj0FVgu3ctTUy2BXxs/h0Or12WbHPa6wz6mDW3Y6w9L1JfWwGxQu28N2CDH/R7I
szmB0VNEgNc1MypsapZaK08EIKzFxcBcyHJktjugNWDku8dn/CEbpz6KjN/7AYDr/72dnYfq/63t
3b2V+n9rY/Op/3+U8deWgVJuJicJVVAnVhaFGTf7TccTtr9Y1FeqteY7ZF6kLn0FLcGtkdjxNao5
10P5htKoP8YNPZHTVgsRdWydXFaOOuaPw8ob3AORcABxDDc0xM8hEusotJNZVS1g18etXx2Njq2O
ORrVasgCvYMDs2/k2bWq1+vNurH2XrH6qDdILXwqPtbqxZfhBdPyO9CZktnuLugAvXmPVrmYI5fz
QG+o0mQxyr1PdwEz/gu08dv7kq3VjfrD5AxXTJZohO64wBxNvFvuFBSB5aVS1WjsQFmNY73VGuJs
hjgbA+1EtcUnVVN1ZcJ1ZWLACWL69lvSeUdXS/w1ygqI7JQ6uLkvFYASZ8RfYKK/UeC4urhOASwq
QqGW4CbjAO1IvsRlm4ZWyyF9MAtuqPQi9hlq5VNIBeQQTcs9vyswWrT2frnSb7Ve4OpAtv6o32UT
pShQIGVc8IBFbW5U9r+jyxbqvRBqNUiZ442Ww4Tome7I4AW2qqNXZZE+qgrAsrHiGemMth5BMuXY
H5uw6GqPuyTbWPXbfPGjBrcjFAiFkLlcmRDODPRIL8myM6yGo56BZnJwn8V9LgqaCZ9OucG+QSqy
l9cWMyekRRCQYTTxw2roec29kL6i6KShkr9squNKoUG+q8RSQs1hmwl9xiaLoPsflK0sdKpwzeqk
gpuOe+LqaF1qIJFwNYa2vLB0JIpFOESLHztLiXmS+sX26kEuMyvgC+h1b+EGK5jrD3uuoQRTQmfS
3ZWtlHTZfXg79OxkEsDC/GrL7U2ALqzQkMXKnJ2NBFeP5gz2ZlnRjNhDMhv5c/ByaIk518f3BChN
q/gseUBJv65UvWvDe3HBZXaYAhG0EZxLpHldEV86NOU7VcWhVrjIkYwu9YzbG0PYzkylvGn2x48P
ed4tjKDYrb3Pdz9mYcGCLbzpq3n/feCEH/P99/nzvZ2V+m+X/yT0VP89wlij9fo63NoJ+G5rUZpM
1v/Oa2VFd68sq+SXwQO1IHrSslbTtBMxb7UGgCgfQA31jInoiznuYoOrOw6w/Xu3vLpQjaIa2KcH
8qWCstNkFkRcoFzq5ZMLVYtXnIlE1NZUgRIbYm5LT0G+jfAZ/WPKC/zqkwPMgrkI7SnXK/pn3nof
ernO5I3T+ZxfW4H7wLP10pP18ot1RoLzXyTDJFO7JKn2sjqsGPt0BcHIi9fV+pURh55MqvprX68p
8DIl75M6ivN83mr1Lw5eZeYob21lk89dtXeqiMxC+WMNECpn1rCSHYHrjlzxTnhByO9O+A5hdLjW
La5n6UtO33COynf7tFP5urLon3d8+bQfpf/f2MH3cv7f29p4yv+PdP9PaILaeTTPH4IQyirj819M
sg78bSD9B3pxNJhnOZ7Okxu9Ru8/TLKCamKovulvl3nB2nrtv06EMwtI79qubahU8rGo+CY0j+Ro
83usYSJ94X5f5RQ1MrsnVtes0Tff0J057e9nHY6ODcVObeZXAu1/oua/NpsZcSJN3iFfPlXMr+cT
Tl1OJFBblhao3vubVE0TXsyWWbbU15DCPteI/VZx/2v//8/zvdX439l9iv/HGYt3u7Gj3ud+1ZOd
NhZT6d+JJf3hZj5v7jqB7ZpRFERZTD7dvH/Y+C8K+d/0/v/i///b2V29/zf3nuL/UcY8cFNPrLRW
COzyIiV9w9gwtvSngv1pPI2n8TS+qvEfAAAA//8DAME4UCsAMAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABjaGVja3N1bXMu
eWFtbC5negAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDAwMDQ0NAAwMDAwMDAwADAwMDAwMDAA
MDAwMDAwMDA0NTAAMTQ0NDI2Mjc3NzIAMDE0NjIyACAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAHVzdGFyADAwd2hlZWwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAB3aGVlbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAwMDAwMDAAMDAwMDAwMAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB+LCAD6L4tkAgNl
kD2yFEAIhPM9xV5grWH4f5mZuSeAAYxMrBd5escNNaOrmuajX6/X4/u3r5vl4/F8/uzPqPiMLz9+
fzwJjNOXQnXMQG2UxSyqlbBnU0v7VVtpLZeNBsO8dMgBO+ncvHfWZ/x6500p68qBNVRwl5Y5AJep
Z0LobkCdNR5XnVkeiyDF0sM7kf5yMuz/ODmDGF2Sz+6oMt5mMb5zT/PQkcM3NesOZYI5MzsADNzo
PbhIKiAsZCrqa5IcQ7ZAG6Ktw+UXT1dIYIeTph5BaF20//2TSsE1OfAscfPUe1zJLiSagTIZUCLe
5lCp02ap4MA5xT7iRbhh9Tbqi3MpZBBIvGtOlF/vuf8dWJs5tNWlSy6ajvbt1R9/AA8NE1rUAQAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
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)()

View file

@ -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)
})
}

View 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">&lt;p dir=&#34;auto&#34;&gt;some text for a pre release&lt;/p&gt;&#xA;</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()))
})
}

View file

@ -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": {