Compare commits

..

7 commits

Author SHA1 Message Date
Nulo (he/him)
b699c23a14 Save files in local storage as umask (#21198)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
Go creates temporary files as 600, but sometimes we want the group to be able to read them (for example,
for another user to back up the storage)

This PR applies the umask to the renamed tmp files in local storage.

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
2022-09-24 15:04:53 -03:00
ad123522d5 gitea.nulo.in: Use NPM cache
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
2022-09-16 20:42:21 -03:00
11aacebcf7 gitea.nulo.in: Use APK cache 2022-09-16 20:42:21 -03:00
0f8f77bb59 gitea.nulo.in: Use script to upgrade 2022-09-16 20:42:21 -03:00
4f57897640 gitea.nulo.in: Use Alpine 3.16 2022-09-16 20:42:21 -03:00
43e106a31a Add .woodpecker.yml for gitea.nulo.in 2022-09-16 20:42:21 -03:00
b27dfdcf5d Allow hidden .READMEs 2022-09-06 19:57:33 -03:00
77 changed files with 854 additions and 1188 deletions

View file

@ -4,42 +4,6 @@ This changelog goes through all the changes that have been made in each release
without substantial changes to our git log; to see the highlights of what has without substantial changes to our git log; to see the highlights of what has
been added to each release, please refer to the [blog](https://blog.gitea.io). been added to each release, please refer to the [blog](https://blog.gitea.io).
## [1.17.3](https://github.com/go-gitea/gitea/releases/tag/v1.17.3) - 2022-10-15
* SECURITY
* Sanitize and Escape refs in git backend (#21464) (#21463)
* Bump `golang.org/x/text` (#21412) (#21413)
* Update bluemonday (#21281) (#21287)
* ENHANCEMENTS
* Fix empty container layer history and UI (#21251) (#21278)
* Use en-US as fallback when using other default language (#21200) (#21256)
* Make the vscode clone link respect transport protocol (#20557) (#21128)
* BUGFIXES
* Do DB update after merge in hammer context (#21401) (#21416)
* Add Num{Issues,Pulls} stats checks (#21404) (#21414)
* Stop logging CheckPath returns error: context canceled (#21064) (#21405)
* Parse OAuth Authorization header when request omits client secret (#21351) (#21374)
* Ignore port for loopback redirect URIs (#21293) (#21373)
* Set SemverCompatible to false for Conan packages (#21275) (#21366)
* Tag list should include draft releases with existing tags (#21263) (#21365)
* Fix linked account translation (#21331) (#21334)
* Make NuGet service index publicly accessible (#21242) (#21277)
* Foreign ID conflicts if ID is 0 for each item (#21271) (#21272)
* Use absolute links in feeds (#21229) (#21265)
* Prevent invalid behavior for file reviewing when loading more files (#21230) (#21234)
* Respect `REQUIRE_SIGNIN_VIEW` for packages (#20873) (#21232)
* Treat git object mode 40755 as directory (#21195) (#21218)
* Allow uppercase ASCII alphabet in PyPI package names (#21095) (#21217)
* Fix limited user cannot view himself's profile (#21212)
* Fix template bug of admin monitor (#21209)
* Fix reaction of issues (#21185) (#21196)
* Fix CSV diff for added/deleted files (#21189) (#21193)
* Fix pagination limit parameter problem (#21111)
* TESTING
* Fix missing m.Run() in TestMain (#21341)
* BUILD
* Use Go 1.19 fmt for Gitea 1.17, sync emoji data (#21239)
## [1.17.2](https://github.com/go-gitea/gitea/releases/tag/v1.17.2) - 2022-09-06 ## [1.17.2](https://github.com/go-gitea/gitea/releases/tag/v1.17.2) - 2022-09-06
* SECURITY * SECURITY

View file

@ -33,7 +33,7 @@ GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.3.1
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.46.0 GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.46.0
GXZ_PAGAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.10 GXZ_PAGAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.10
MISSPELL_PACKAGE ?= github.com/client9/misspell/cmd/misspell@v0.3.4 MISSPELL_PACKAGE ?= github.com/client9/misspell/cmd/misspell@v0.3.4
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.30.0 SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.29.0
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
DOCKER_IMAGE ?= gitea/gitea DOCKER_IMAGE ?= gitea/gitea

File diff suppressed because one or more lines are too long

View file

@ -214,7 +214,8 @@ const hdr = `
package emoji package emoji
// Code generated by build/generate-emoji.go. DO NOT EDIT. // Code generated by gen.go. DO NOT EDIT.
// Sourced from %s // Sourced from %s
//
var GemojiData = %#v var GemojiData = %#v
` `

13
go.mod
View file

@ -64,7 +64,7 @@ require (
github.com/mattn/go-isatty v0.0.14 github.com/mattn/go-isatty v0.0.14
github.com/mattn/go-sqlite3 v1.14.12 github.com/mattn/go-sqlite3 v1.14.12
github.com/mholt/archiver/v3 v3.5.1 github.com/mholt/archiver/v3 v3.5.1
github.com/microcosm-cc/bluemonday v1.0.20 github.com/microcosm-cc/bluemonday v1.0.19
github.com/minio/minio-go/v7 v7.0.26 github.com/minio/minio-go/v7 v7.0.26
github.com/msteinert/pam v1.0.0 github.com/msteinert/pam v1.0.0
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
@ -91,11 +91,11 @@ require (
go.jolheiser.com/hcaptcha v0.0.4 go.jolheiser.com/hcaptcha v0.0.4
go.jolheiser.com/pwn v0.0.3 go.jolheiser.com/pwn v0.0.3
golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122 golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122
golang.org/x/net v0.0.0-20220927171203-f486391704dc golang.org/x/net v0.0.0-20220630215102-69896b714898
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a
golang.org/x/text v0.3.8 golang.org/x/text v0.3.7
golang.org/x/tools v0.1.12 golang.org/x/tools v0.1.10
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
gopkg.in/ini.v1 v1.66.4 gopkg.in/ini.v1 v1.66.4
gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v2 v2.4.0
@ -271,8 +271,9 @@ require (
go.uber.org/atomic v1.9.0 // indirect go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.8.0 // indirect go.uber.org/multierr v1.8.0 // indirect
go.uber.org/zap v1.21.0 // indirect go.uber.org/zap v1.21.0 // indirect
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect
golang.org/x/time v0.0.0-20220411224347-583f2d630306 // indirect golang.org/x/time v0.0.0-20220411224347-583f2d630306 // indirect
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f // indirect
google.golang.org/appengine v1.6.7 // indirect google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa // indirect google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa // indirect
google.golang.org/grpc v1.43.0 // indirect google.golang.org/grpc v1.43.0 // indirect

27
go.sum
View file

@ -1146,8 +1146,8 @@ github.com/mholt/acmez v1.0.2 h1:C8wsEBIUVi6e0DYoxqCcFuXtwc4AWXL/jgcDjF7mjVo=
github.com/mholt/acmez v1.0.2/go.mod h1:8qnn8QA/Ewx8E3ZSsmscqsIjhhpxuy9vqdgbX2ceceM= github.com/mholt/acmez v1.0.2/go.mod h1:8qnn8QA/Ewx8E3ZSsmscqsIjhhpxuy9vqdgbX2ceceM=
github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo= github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo=
github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4= github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4=
github.com/microcosm-cc/bluemonday v1.0.20 h1:flpzsq4KU3QIYAYGV/szUat7H+GPOXR0B2JU5A1Wp8Y= github.com/microcosm-cc/bluemonday v1.0.19 h1:OI7hoF5FY4pFz2VA//RN8TfM0YJ2dJcl4P4APrCWy6c=
github.com/microcosm-cc/bluemonday v1.0.20/go.mod h1:yfBmMi8mxvaZut3Yytv+jTXRY8mxyjJ0/kQBTElld50= github.com/microcosm-cc/bluemonday v1.0.19/go.mod h1:QNzV2UbLK2/53oIIwTOyLUSABMkjZ4tqiyC1g/DyqxE=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
@ -1716,8 +1716,8 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -1788,8 +1788,8 @@ golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220927171203-f486391704dc h1:FxpXZdoBqT8RjqTy6i1E8nXHhW21wK7ptQ/EPIGxzPQ= golang.org/x/net v0.0.0-20220630215102-69896b714898 h1:K7wO6V1IrczY9QOQ2WkVpw4JQSwCd52UsxVEirZUfiw=
golang.org/x/net v0.0.0-20220927171203-f486391704dc/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.0.0-20220630215102-69896b714898/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -1824,8 +1824,8 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -1936,8 +1936,8 @@ golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
@ -1950,9 +1950,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@ -2046,14 +2045,16 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f h1:GGU+dLjvlC3qDwqYgL6UgRmHXhOOgns0bZu2Ty5mm6U=
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.5.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.5.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=

View file

@ -266,7 +266,7 @@ func TestPackageConan(t *testing.T) {
pd, err := packages.GetPackageDescriptor(db.DefaultContext, pvs[0]) pd, err := packages.GetPackageDescriptor(db.DefaultContext, pvs[0])
assert.NoError(t, err) assert.NoError(t, err)
assert.Nil(t, pd.SemVer) assert.NotNil(t, pd.SemVer)
assert.Equal(t, name, pd.Package.Name) assert.Equal(t, name, pd.Package.Name)
assert.Equal(t, version1, pd.Version.Version) assert.Equal(t, version1, pd.Version.Version)
assert.IsType(t, &conan_module.Metadata{}, pd.Metadata) assert.IsType(t, &conan_module.Metadata{}, pd.Metadata)

View file

@ -14,7 +14,6 @@ import (
"code.gitea.io/gitea/models/packages" "code.gitea.io/gitea/models/packages"
"code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/setting"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -80,18 +79,6 @@ func TestPackageGeneric(t *testing.T) {
assert.Equal(t, int64(1), pvs[0].DownloadCount) assert.Equal(t, int64(1), pvs[0].DownloadCount)
}) })
t.Run("RequireSignInView", func(t *testing.T) {
defer PrintCurrentTest(t)()
setting.Service.RequireSignInView = true
defer func() {
setting.Service.RequireSignInView = false
}()
req := NewRequest(t, "GET", url)
MakeRequest(t, req, http.StatusUnauthorized)
})
t.Run("Delete", func(t *testing.T) { t.Run("Delete", func(t *testing.T) {
defer PrintCurrentTest(t)() defer PrintCurrentTest(t)()

View file

@ -19,7 +19,6 @@ import (
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
nuget_module "code.gitea.io/gitea/modules/packages/nuget" nuget_module "code.gitea.io/gitea/modules/packages/nuget"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/routers/api/packages/nuget" "code.gitea.io/gitea/routers/api/packages/nuget"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -66,30 +65,12 @@ func TestPackageNuGet(t *testing.T) {
t.Run("ServiceIndex", func(t *testing.T) { t.Run("ServiceIndex", func(t *testing.T) {
defer PrintCurrentTest(t)() defer PrintCurrentTest(t)()
privateUser := unittest.AssertExistsAndLoadBean(t, &user_model.User{Visibility: structs.VisibleTypePrivate}).(*user_model.User)
cases := []struct {
Owner string
UseBasicAuth bool
UseTokenAuth bool
}{
{privateUser.Name, false, false},
{privateUser.Name, true, false},
{privateUser.Name, false, true},
{user.Name, false, false},
{user.Name, true, false},
{user.Name, false, true},
}
for _, c := range cases {
url := fmt.Sprintf("/api/packages/%s/nuget", c.Owner)
req := NewRequest(t, "GET", fmt.Sprintf("%s/index.json", url)) req := NewRequest(t, "GET", fmt.Sprintf("%s/index.json", url))
if c.UseBasicAuth {
req = AddBasicAuthHeader(req, user.Name) req = AddBasicAuthHeader(req, user.Name)
} else if c.UseTokenAuth { MakeRequest(t, req, http.StatusOK)
req = NewRequest(t, "GET", fmt.Sprintf("%s/index.json", url))
req = addNuGetAPIKeyHeader(req, token) req = addNuGetAPIKeyHeader(req, token)
}
resp := MakeRequest(t, req, http.StatusOK) resp := MakeRequest(t, req, http.StatusOK)
var result nuget.ServiceIndexResponse var result nuget.ServiceIndexResponse
@ -119,7 +100,6 @@ func TestPackageNuGet(t *testing.T) {
assert.Equal(t, root, r.ID) assert.Equal(t, root, r.ID)
} }
} }
}
}) })
t.Run("Upload", func(t *testing.T) { t.Run("Upload", func(t *testing.T) {

View file

@ -218,11 +218,6 @@ func (a *Action) GetRepoLink() string {
return path.Join(setting.AppSubURL, "/", url.PathEscape(a.GetRepoUserName()), url.PathEscape(a.GetRepoName())) return path.Join(setting.AppSubURL, "/", url.PathEscape(a.GetRepoUserName()), url.PathEscape(a.GetRepoName()))
} }
// GetRepoAbsoluteLink returns the absolute link to action repository.
func (a *Action) GetRepoAbsoluteLink() string {
return setting.AppURL + url.PathEscape(a.GetRepoUserName()) + "/" + url.PathEscape(a.GetRepoName())
}
// GetRepositoryFromMatch returns a *repo_model.Repository from a username and repo strings // GetRepositoryFromMatch returns a *repo_model.Repository from a username and repo strings
func GetRepositoryFromMatch(ownerName, repoName string) (*repo_model.Repository, error) { func GetRepositoryFromMatch(ownerName, repoName string) (*repo_model.Repository, error) {
var err error var err error

View file

@ -9,7 +9,6 @@ import (
"testing" "testing"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
issue_model "code.gitea.io/gitea/models/issues"
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
@ -20,7 +19,7 @@ import (
func TestAction_GetRepoPath(t *testing.T) { func TestAction_GetRepoPath(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase()) assert.NoError(t, unittest.PrepareTestDatabase())
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}).(*repo_model.Repository) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{}).(*repo_model.Repository)
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}).(*user_model.User) owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}).(*user_model.User)
action := &Action{RepoID: repo.ID} action := &Action{RepoID: repo.ID}
assert.Equal(t, path.Join(owner.Name, repo.Name), action.GetRepoPath()) assert.Equal(t, path.Join(owner.Name, repo.Name), action.GetRepoPath())
@ -28,15 +27,12 @@ func TestAction_GetRepoPath(t *testing.T) {
func TestAction_GetRepoLink(t *testing.T) { func TestAction_GetRepoLink(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase()) assert.NoError(t, unittest.PrepareTestDatabase())
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}).(*repo_model.Repository) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{}).(*repo_model.Repository)
owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}).(*user_model.User) owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}).(*user_model.User)
comment := unittest.AssertExistsAndLoadBean(t, &issue_model.Comment{ID: 2}).(*issue_model.Comment) action := &Action{RepoID: repo.ID}
action := &Action{RepoID: repo.ID, CommentID: comment.ID}
setting.AppSubURL = "/suburl" setting.AppSubURL = "/suburl"
expected := path.Join(setting.AppSubURL, owner.Name, repo.Name) expected := path.Join(setting.AppSubURL, owner.Name, repo.Name)
assert.Equal(t, expected, action.GetRepoLink()) assert.Equal(t, expected, action.GetRepoLink())
assert.Equal(t, repo.HTMLURL(), action.GetRepoAbsoluteLink())
assert.Equal(t, comment.HTMLURL(), action.GetCommentLink())
} }
func TestGetFeeds(t *testing.T) { func TestGetFeeds(t *testing.T) {

View file

@ -10,7 +10,6 @@ import (
"encoding/base32" "encoding/base32"
"encoding/base64" "encoding/base64"
"fmt" "fmt"
"net"
"net/url" "net/url"
"strings" "strings"
@ -57,18 +56,6 @@ func (app *OAuth2Application) PrimaryRedirectURI() string {
// ContainsRedirectURI checks if redirectURI is allowed for app // ContainsRedirectURI checks if redirectURI is allowed for app
func (app *OAuth2Application) ContainsRedirectURI(redirectURI string) bool { func (app *OAuth2Application) ContainsRedirectURI(redirectURI string) bool {
uri, err := url.Parse(redirectURI)
// ignore port for http loopback uris following https://datatracker.ietf.org/doc/html/rfc8252#section-7.3
if err == nil && uri.Scheme == "http" && uri.Port() != "" {
ip := net.ParseIP(uri.Hostname())
if ip != nil && ip.IsLoopback() {
// strip port
uri.Host = uri.Hostname()
if util.IsStringInSlice(uri.String(), app.RedirectURIs, true) {
return true
}
}
}
return util.IsStringInSlice(redirectURI, app.RedirectURIs, true) return util.IsStringInSlice(redirectURI, app.RedirectURIs, true)
} }

View file

@ -42,26 +42,6 @@ func TestOAuth2Application_ContainsRedirectURI(t *testing.T) {
assert.False(t, app.ContainsRedirectURI("d")) assert.False(t, app.ContainsRedirectURI("d"))
} }
func TestOAuth2Application_ContainsRedirectURI_WithPort(t *testing.T) {
app := &OAuth2Application{
RedirectURIs: []string{"http://127.0.0.1/", "http://::1/", "http://192.168.0.1/", "http://intranet/", "https://127.0.0.1/"},
}
// http loopback uris should ignore port
// https://datatracker.ietf.org/doc/html/rfc8252#section-7.3
assert.True(t, app.ContainsRedirectURI("http://127.0.0.1:3456/"))
assert.True(t, app.ContainsRedirectURI("http://127.0.0.1/"))
assert.True(t, app.ContainsRedirectURI("http://[::1]:3456/"))
// not http
assert.False(t, app.ContainsRedirectURI("https://127.0.0.1:3456/"))
// not loopback
assert.False(t, app.ContainsRedirectURI("http://192.168.0.1:9954/"))
assert.False(t, app.ContainsRedirectURI("http://intranet:3456/"))
// unparseable
assert.False(t, app.ContainsRedirectURI(":"))
}
func TestOAuth2Application_ValidateClientSecret(t *testing.T) { func TestOAuth2Application_ValidateClientSecret(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase()) assert.NoError(t, unittest.PrepareTestDatabase())
app := unittest.AssertExistsAndLoadBean(t, &OAuth2Application{ID: 1}).(*OAuth2Application) app := unittest.AssertExistsAndLoadBean(t, &OAuth2Application{ID: 1}).(*OAuth2Application)

View file

@ -181,10 +181,6 @@ func createReaction(ctx context.Context, opts *ReactionOptions) (*Reaction, erro
Reaction: opts.Type, Reaction: opts.Type,
UserID: opts.DoerID, UserID: opts.DoerID,
} }
if findOpts.CommentID == 0 {
// explicit search of Issue Reactions where CommentID = 0
findOpts.CommentID = -1
}
existingR, _, err := FindReactions(ctx, findOpts) existingR, _, err := FindReactions(ctx, findOpts)
if err != nil { if err != nil {
@ -260,13 +256,7 @@ func DeleteReaction(ctx context.Context, opts *ReactionOptions) error {
CommentID: opts.CommentID, CommentID: opts.CommentID,
} }
sess := db.GetEngine(ctx).Where("original_author_id = 0") _, err := db.GetEngine(ctx).Where("original_author_id = 0").Delete(reaction)
if opts.CommentID == -1 {
reaction.CommentID = 0
sess.MustCols("comment_id")
}
_, err := sess.Delete(reaction)
return err return err
} }
@ -276,7 +266,6 @@ func DeleteIssueReaction(doerID, issueID int64, content string) error {
Type: content, Type: content,
DoerID: doerID, DoerID: doerID,
IssueID: issueID, IssueID: issueID,
CommentID: -1,
}) })
} }

View file

@ -170,7 +170,6 @@ type FindReleasesOptions struct {
IsPreRelease util.OptionalBool IsPreRelease util.OptionalBool
IsDraft util.OptionalBool IsDraft util.OptionalBool
TagNames []string TagNames []string
HasSha1 util.OptionalBool // useful to find draft releases which are created with existing tags
} }
func (opts *FindReleasesOptions) toConds(repoID int64) builder.Cond { func (opts *FindReleasesOptions) toConds(repoID int64) builder.Cond {
@ -192,13 +191,6 @@ func (opts *FindReleasesOptions) toConds(repoID int64) builder.Cond {
if !opts.IsDraft.IsNone() { if !opts.IsDraft.IsNone() {
cond = cond.And(builder.Eq{"is_draft": opts.IsDraft.IsTrue()}) cond = cond.And(builder.Eq{"is_draft": opts.IsDraft.IsTrue()})
} }
if !opts.HasSha1.IsNone() {
if opts.HasSha1.IsTrue() {
cond = cond.And(builder.Neq{"sha1": ""})
} else {
cond = cond.And(builder.Eq{"sha1": ""})
}
}
return cond return cond
} }

View file

@ -605,27 +605,15 @@ func CheckRepoStats(ctx context.Context) error {
repoStatsCorrectNumStars, repoStatsCorrectNumStars,
"repository count 'num_stars'", "repository count 'num_stars'",
}, },
// Repository.NumIssues
{
statsQuery("SELECT repo.id FROM `repository` repo WHERE repo.num_issues!=(SELECT COUNT(*) FROM `issue` WHERE repo_id=repo.id AND is_closed=? AND is_pull=?)", false, false),
repoStatsCorrectNumIssues,
"repository count 'num_issues'",
},
// Repository.NumClosedIssues // Repository.NumClosedIssues
{ {
statsQuery("SELECT repo.id FROM `repository` repo WHERE repo.num_closed_issues!=(SELECT COUNT(*) FROM `issue` WHERE repo_id=repo.id AND is_closed=? AND is_pull=?)", true, false), statsQuery("SELECT repo.id FROM `repository` repo WHERE repo.num_closed_issues!=(SELECT COUNT(*) FROM `issue` WHERE repo_id=repo.id AND is_closed=? AND is_pull=?)", true, false),
repoStatsCorrectNumClosedIssues, repoStatsCorrectNumClosedIssues,
"repository count 'num_closed_issues'", "repository count 'num_closed_issues'",
}, },
// Repository.NumPulls
{
statsQuery("SELECT repo.id FROM `repository` repo WHERE repo.num_pulls!=(SELECT COUNT(*) FROM `issue` WHERE repo_id=repo.id AND is_closed=? AND is_pull=?)", false, true),
repoStatsCorrectNumPulls,
"repository count 'num_pulls'",
},
// Repository.NumClosedPulls // Repository.NumClosedPulls
{ {
statsQuery("SELECT repo.id FROM `repository` repo WHERE repo.num_closed_pulls!=(SELECT COUNT(*) FROM `issue` WHERE repo_id=repo.id AND is_closed=? AND is_pull=?)", true, true), statsQuery("SELECT repo.id FROM `repository` repo WHERE repo.num_closed_issues!=(SELECT COUNT(*) FROM `issue` WHERE repo_id=repo.id AND is_closed=? AND is_pull=?)", true, true),
repoStatsCorrectNumClosedPulls, repoStatsCorrectNumClosedPulls,
"repository count 'num_closed_pulls'", "repository count 'num_closed_pulls'",
}, },

View file

@ -1265,7 +1265,7 @@ func isUserVisibleToViewerCond(viewer *User) builder.Cond {
// IsUserVisibleToViewer check if viewer is able to see user profile // IsUserVisibleToViewer check if viewer is able to see user profile
func IsUserVisibleToViewer(ctx context.Context, u, viewer *User) bool { func IsUserVisibleToViewer(ctx context.Context, u, viewer *User) bool {
if viewer != nil && (viewer.IsAdmin || viewer.ID == u.ID) { if viewer != nil && viewer.IsAdmin {
return true return true
} }
@ -1304,7 +1304,7 @@ func IsUserVisibleToViewer(ctx context.Context, u, viewer *User) bool {
return false return false
} }
if count == 0 { if count < 0 {
// No common organization // No common organization
return false return false
} }

View file

@ -59,7 +59,6 @@ func b1(img *image.Paletted, x, y, size, angle int) {
} }
// a small block // a small block
//
// ---------- // ----------
// | | // | |
// | #### | // | #### |

View file

@ -13,7 +13,6 @@ import (
"code.gitea.io/gitea/models/perm" "code.gitea.io/gitea/models/perm"
"code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/models/unit"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/structs"
) )
@ -53,12 +52,48 @@ func packageAssignment(ctx *Context, errCb func(int, string, interface{})) {
Owner: ctx.ContextUser, Owner: ctx.ContextUser,
} }
if ctx.Package.Owner.IsOrganization() {
org := organization.OrgFromUser(ctx.Package.Owner)
// 1. Get user max authorize level for the org (may be none, if user is not member of the org)
if ctx.Doer != nil {
var err error var err error
ctx.Package.AccessMode, err = determineAccessMode(ctx) ctx.Package.AccessMode, err = org.GetOrgUserMaxAuthorizeLevel(ctx.Doer.ID)
if err != nil { if err != nil {
errCb(http.StatusInternalServerError, "determineAccessMode", err) errCb(http.StatusInternalServerError, "GetOrgUserMaxAuthorizeLevel", err)
return return
} }
// If access mode is less than write check every team for more permissions
if ctx.Package.AccessMode < perm.AccessModeWrite {
teams, err := organization.GetUserOrgTeams(ctx, org.ID, ctx.Doer.ID)
if err != nil {
errCb(http.StatusInternalServerError, "GetUserOrgTeams", err)
return
}
for _, t := range teams {
perm := t.UnitAccessModeCtx(ctx, unit.TypePackages)
if ctx.Package.AccessMode < perm {
ctx.Package.AccessMode = perm
}
}
}
}
// 2. If authorize level is none, check if org is visible to user
if ctx.Package.AccessMode == perm.AccessModeNone && organization.HasOrgOrUserVisible(ctx, ctx.Package.Owner, ctx.Doer) {
ctx.Package.AccessMode = perm.AccessModeRead
}
} else {
if ctx.Doer != nil && !ctx.Doer.IsGhost() {
// 1. Check if user is package owner
if ctx.Doer.ID == ctx.Package.Owner.ID {
ctx.Package.AccessMode = perm.AccessModeOwner
} else if ctx.Package.Owner.Visibility == structs.VisibleTypePublic || ctx.Package.Owner.Visibility == structs.VisibleTypeLimited { // 2. Check if package owner is public or limited
ctx.Package.AccessMode = perm.AccessModeRead
}
} else if ctx.Package.Owner.Visibility == structs.VisibleTypePublic { // 3. Check if package owner is public
ctx.Package.AccessMode = perm.AccessModeRead
}
}
packageType := ctx.Params("type") packageType := ctx.Params("type")
name := ctx.Params("name") name := ctx.Params("name")
@ -82,57 +117,6 @@ func packageAssignment(ctx *Context, errCb func(int, string, interface{})) {
} }
} }
func determineAccessMode(ctx *Context) (perm.AccessMode, error) {
accessMode := perm.AccessModeNone
if setting.Service.RequireSignInView && ctx.Doer == nil {
return accessMode, nil
}
if ctx.Package.Owner.IsOrganization() {
org := organization.OrgFromUser(ctx.Package.Owner)
// 1. Get user max authorize level for the org (may be none, if user is not member of the org)
if ctx.Doer != nil {
var err error
accessMode, err = org.GetOrgUserMaxAuthorizeLevel(ctx.Doer.ID)
if err != nil {
return accessMode, err
}
// If access mode is less than write check every team for more permissions
if accessMode < perm.AccessModeWrite {
teams, err := organization.GetUserOrgTeams(ctx, org.ID, ctx.Doer.ID)
if err != nil {
return accessMode, err
}
for _, t := range teams {
perm := t.UnitAccessModeCtx(ctx, unit.TypePackages)
if accessMode < perm {
accessMode = perm
}
}
}
}
// 2. If authorize level is none, check if org is visible to user
if accessMode == perm.AccessModeNone && organization.HasOrgOrUserVisible(ctx, ctx.Package.Owner, ctx.Doer) {
accessMode = perm.AccessModeRead
}
} else {
if ctx.Doer != nil && !ctx.Doer.IsGhost() {
// 1. Check if user is package owner
if ctx.Doer.ID == ctx.Package.Owner.ID {
accessMode = perm.AccessModeOwner
} else if ctx.Package.Owner.Visibility == structs.VisibleTypePublic || ctx.Package.Owner.Visibility == structs.VisibleTypeLimited { // 2. Check if package owner is public or limited
accessMode = perm.AccessModeRead
}
} else if ctx.Package.Owner.Visibility == structs.VisibleTypePublic { // 3. Check if package owner is public
accessMode = perm.AccessModeRead
}
}
return accessMode, nil
}
// PackageContexter initializes a package context for a request. // PackageContexter initializes a package context for a request.
func PackageContexter() func(next http.Handler) http.Handler { func PackageContexter() func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler { return func(next http.Handler) http.Handler {

View file

@ -524,9 +524,7 @@ func RepoAssignment(ctx *Context) (cancel context.CancelFunc) {
} }
ctx.Data["NumTags"], err = models.GetReleaseCountByRepoID(ctx.Repo.Repository.ID, models.FindReleasesOptions{ ctx.Data["NumTags"], err = models.GetReleaseCountByRepoID(ctx.Repo.Repository.ID, models.FindReleasesOptions{
IncludeDrafts: true,
IncludeTags: true, IncludeTags: true,
HasSha1: util.OptionalBoolTrue, // only draft releases which are created with existing tags
}) })
if err != nil { if err != nil {
ctx.ServerError("GetReleaseCountByRepoID", err) ctx.ServerError("GetReleaseCountByRepoID", err)

View file

@ -322,7 +322,7 @@ func TestGuessDelimiter(t *testing.T) {
}, },
// case 3 - tab delimited // case 3 - tab delimited
{ {
csv: "1\t2", csv: "1 2",
expectedDelimiter: '\t', expectedDelimiter: '\t',
}, },
// case 4 - pipe delimited // case 4 - pipe delimited

File diff suppressed because it is too large Load diff

View file

@ -40,7 +40,6 @@ type Command struct {
parentContext context.Context parentContext context.Context
desc string desc string
globalArgsLength int globalArgsLength int
brokenArgs []string
} }
func (c *Command) String() string { func (c *Command) String() string {
@ -51,7 +50,6 @@ func (c *Command) String() string {
} }
// NewCommand creates and returns a new Git Command based on given command and arguments. // NewCommand creates and returns a new Git Command based on given command and arguments.
// Each argument should be safe to be trusted. User-provided arguments should be passed to AddDynamicArguments instead.
func NewCommand(ctx context.Context, args ...string) *Command { func NewCommand(ctx context.Context, args ...string) *Command {
// Make an explicit copy of globalCommandArgs, otherwise append might overwrite it // Make an explicit copy of globalCommandArgs, otherwise append might overwrite it
cargs := make([]string, len(globalCommandArgs)) cargs := make([]string, len(globalCommandArgs))
@ -65,13 +63,11 @@ func NewCommand(ctx context.Context, args ...string) *Command {
} }
// NewCommandNoGlobals creates and returns a new Git Command based on given command and arguments only with the specify args and don't care global command args // NewCommandNoGlobals creates and returns a new Git Command based on given command and arguments only with the specify args and don't care global command args
// Each argument should be safe to be trusted. User-provided arguments should be passed to AddDynamicArguments instead.
func NewCommandNoGlobals(args ...string) *Command { func NewCommandNoGlobals(args ...string) *Command {
return NewCommandContextNoGlobals(DefaultContext, args...) return NewCommandContextNoGlobals(DefaultContext, args...)
} }
// NewCommandContextNoGlobals creates and returns a new Git Command based on given command and arguments only with the specify args and don't care global command args // NewCommandContextNoGlobals creates and returns a new Git Command based on given command and arguments only with the specify args and don't care global command args
// Each argument should be safe to be trusted. User-provided arguments should be passed to AddDynamicArguments instead.
func NewCommandContextNoGlobals(ctx context.Context, args ...string) *Command { func NewCommandContextNoGlobals(ctx context.Context, args ...string) *Command {
return &Command{ return &Command{
name: GitExecutable, name: GitExecutable,
@ -93,28 +89,12 @@ func (c *Command) SetDescription(desc string) *Command {
return c return c
} }
// AddArguments adds new argument(s) to the command. Each argument must be safe to be trusted. // AddArguments adds new argument(s) to the command.
// User-provided arguments should be passed to AddDynamicArguments instead.
func (c *Command) AddArguments(args ...string) *Command { func (c *Command) AddArguments(args ...string) *Command {
c.args = append(c.args, args...) c.args = append(c.args, args...)
return c return c
} }
// AddDynamicArguments adds new dynamic argument(s) to the command.
// The arguments may come from user input and can not be trusted, so no leading '-' is allowed to avoid passing options
func (c *Command) AddDynamicArguments(args ...string) *Command {
for _, arg := range args {
if arg != "" && arg[0] == '-' {
c.brokenArgs = append(c.brokenArgs, arg)
}
}
if len(c.brokenArgs) != 0 {
return c
}
c.args = append(c.args, args...)
return c
}
// RunOpts represents parameters to run the command. If UseContextTimeout is specified, then Timeout is ignored. // RunOpts represents parameters to run the command. If UseContextTimeout is specified, then Timeout is ignored.
type RunOpts struct { type RunOpts struct {
Env []string Env []string
@ -158,14 +138,8 @@ func CommonCmdServEnvs() []string {
return commonBaseEnvs() return commonBaseEnvs()
} }
var ErrBrokenCommand = errors.New("git command is broken")
// Run runs the command with the RunOpts // Run runs the command with the RunOpts
func (c *Command) Run(opts *RunOpts) error { func (c *Command) Run(opts *RunOpts) error {
if len(c.brokenArgs) != 0 {
log.Error("git command is broken: %s, broken args: %s", c.String(), strings.Join(c.brokenArgs, " "))
return ErrBrokenCommand
}
if opts == nil { if opts == nil {
opts = &RunOpts{} opts = &RunOpts{}
} }

View file

@ -26,19 +26,4 @@ func TestRunWithContextStd(t *testing.T) {
assert.Contains(t, err.Error(), "exit status 129 - unknown option:") assert.Contains(t, err.Error(), "exit status 129 - unknown option:")
assert.Empty(t, stdout) assert.Empty(t, stdout)
} }
cmd = NewCommand(context.Background())
cmd.AddDynamicArguments("-test")
assert.ErrorIs(t, cmd.Run(&RunOpts{}), ErrBrokenCommand)
cmd = NewCommand(context.Background())
cmd.AddDynamicArguments("--test")
assert.ErrorIs(t, cmd.Run(&RunOpts{}), ErrBrokenCommand)
subCmd := "version"
cmd = NewCommand(context.Background()).AddDynamicArguments(subCmd) // for test purpose only, the sub-command should never be dynamic for production
stdout, stderr, err = cmd.RunStdString(&RunOpts{})
assert.NoError(t, err)
assert.Empty(t, stderr)
assert.Contains(t, stdout, "git version")
} }

View file

@ -163,7 +163,7 @@ func AllCommitsCount(ctx context.Context, repoPath string, hidePRRefs bool, file
// CommitsCountFiles returns number of total commits of until given revision. // CommitsCountFiles returns number of total commits of until given revision.
func CommitsCountFiles(ctx context.Context, repoPath string, revision, relpath []string) (int64, error) { func CommitsCountFiles(ctx context.Context, repoPath string, revision, relpath []string) (int64, error) {
cmd := NewCommand(ctx, "rev-list", "--count") cmd := NewCommand(ctx, "rev-list", "--count")
cmd.AddDynamicArguments(revision...) cmd.AddArguments(revision...)
if len(relpath) > 0 { if len(relpath) > 0 {
cmd.AddArguments("--") cmd.AddArguments("--")
cmd.AddArguments(relpath...) cmd.AddArguments(relpath...)

View file

@ -69,6 +69,7 @@ func NewParser(r io.Reader, format Format) *Parser {
// It could, for example return something like: // It could, for example return something like:
// //
// { "objecttype": "tag", "refname:short": "v1.16.4", "object": "f460b7543ed500e49c133c2cd85c8c55ee9dbe27" } // { "objecttype": "tag", "refname:short": "v1.16.4", "object": "f460b7543ed500e49c133c2cd85c8c55ee9dbe27" }
//
func (p *Parser) Next() map[string]string { func (p *Parser) Next() map[string]string {
if !p.scanner.Scan() { if !p.scanner.Scan() {
return nil return nil
@ -89,6 +90,7 @@ func (p *Parser) Err() error {
// parseRef parses out all key-value pairs from a single reference block, such as // parseRef parses out all key-value pairs from a single reference block, such as
// //
// "objecttype tag\0refname:short v1.16.4\0object f460b7543ed500e49c133c2cd85c8c55ee9dbe27" // "objecttype tag\0refname:short v1.16.4\0object f460b7543ed500e49c133c2cd85c8c55ee9dbe27"
//
func (p *Parser) parseRef(refBlock string) (map[string]string, error) { func (p *Parser) parseRef(refBlock string) (map[string]string, error) {
if refBlock == "" { if refBlock == "" {
// must be at EOF // must be at EOF

View file

@ -44,7 +44,7 @@ func parseTreeEntries(data []byte, ptree *Tree) ([]*TreeEntry, error) {
case "160000": case "160000":
entry.entryMode = EntryModeCommit entry.entryMode = EntryModeCommit
pos += 14 // skip over "160000 object " pos += 14 // skip over "160000 object "
case "040000", "040755": // git uses 040000 for tree object, but some users may get 040755 for unknown reasons case "040000":
entry.entryMode = EntryModeTree entry.entryMode = EntryModeTree
pos += 12 // skip over "040000 tree " pos += 12 // skip over "040000 tree "
default: default:
@ -119,7 +119,7 @@ loop:
entry.entryMode = EntryModeSymlink entry.entryMode = EntryModeSymlink
case "160000": case "160000":
entry.entryMode = EntryModeCommit entry.entryMode = EntryModeCommit
case "40000", "40755": // git uses 40000 for tree object, but some users may get 40755 for unknown reasons case "40000":
entry.entryMode = EntryModeTree entry.entryMode = EntryModeTree
default: default:
log.Debug("Unknown mode: %v", string(mode)) log.Debug("Unknown mode: %v", string(mode))

View file

@ -191,8 +191,8 @@ func (c *CheckAttributeReader) Run() error {
// CheckPath check attr for given path // CheckPath check attr for given path
func (c *CheckAttributeReader) CheckPath(path string) (rs map[string]string, err error) { func (c *CheckAttributeReader) CheckPath(path string) (rs map[string]string, err error) {
defer func() { defer func() {
if err != nil && err != c.ctx.Err() { if err != nil {
log.Error("Unexpected error when checking path %s in %s. Error: %v", path, c.Repo.Path, err) log.Error("CheckPath returns error: %v", err)
} }
}() }()

View file

@ -158,7 +158,7 @@ func (repo *Repository) searchCommits(id SHA1, opts SearchCommitsOptions) ([]*Co
// add previous arguments except for --grep and --all // add previous arguments except for --grep and --all
hashCmd.AddArguments(args...) hashCmd.AddArguments(args...)
// add keyword as <commit> // add keyword as <commit>
hashCmd.AddDynamicArguments(v) hashCmd.AddArguments(v)
// search with given constraints for commit matching sha hash of v // search with given constraints for commit matching sha hash of v
hashMatching, _, err := hashCmd.RunStdBytes(&RunOpts{Dir: repo.Path}) hashMatching, _, err := hashCmd.RunStdBytes(&RunOpts{Dir: repo.Path})
@ -208,11 +208,10 @@ func (repo *Repository) CommitsByFileAndRange(revision, file string, page int) (
}() }()
go func() { go func() {
stderr := strings.Builder{} stderr := strings.Builder{}
gitCmd := NewCommand(repo.Ctx, "log", prettyLogFormat, "--follow", err := NewCommand(repo.Ctx, "log", revision, "--follow",
"--max-count="+strconv.Itoa(setting.Git.CommitsRangeSize*page)) "--max-count="+strconv.Itoa(setting.Git.CommitsRangeSize*page),
gitCmd.AddDynamicArguments(revision) prettyLogFormat, "--", file).
gitCmd.AddArguments("--", file) Run(&RunOpts{
err := gitCmd.Run(&RunOpts{
Dir: repo.Path, Dir: repo.Path,
Stdout: stdoutWriter, Stdout: stdoutWriter,
Stderr: &stderr, Stderr: &stderr,

View file

@ -59,15 +59,15 @@ func (repo *Repository) GetCodeActivityStats(fromTime time.Time, branch string)
_ = stdoutWriter.Close() _ = stdoutWriter.Close()
}() }()
gitCmd := NewCommand(repo.Ctx, "log", "--numstat", "--no-merges", "--pretty=format:---%n%h%n%aN%n%aE%n", "--date=iso", fmt.Sprintf("--since='%s'", since)) args := []string{"log", "--numstat", "--no-merges", "--pretty=format:---%n%h%n%aN%n%aE%n", "--date=iso", fmt.Sprintf("--since='%s'", since)}
if len(branch) == 0 { if len(branch) == 0 {
gitCmd.AddArguments("--branches=*") args = append(args, "--branches=*")
} else { } else {
gitCmd.AddArguments("--first-parent").AddDynamicArguments(branch) args = append(args, "--first-parent", branch)
} }
stderr := new(strings.Builder) stderr := new(strings.Builder)
err = gitCmd.Run(&RunOpts{ err = NewCommand(repo.Ctx, args...).Run(&RunOpts{
Env: []string{}, Env: []string{},
Dir: repo.Path, Dir: repo.Path,
Stdout: stdoutWriter, Stdout: stdoutWriter,

View file

@ -19,10 +19,8 @@ import (
type Signature = object.Signature type Signature = object.Signature
// Helper to get a signature from the commit line, which looks like these: // Helper to get a signature from the commit line, which looks like these:
//
// author Patrick Gundlach <gundlach@speedata.de> 1378823654 +0200 // author Patrick Gundlach <gundlach@speedata.de> 1378823654 +0200
// author Patrick Gundlach <gundlach@speedata.de> Thu, 07 Apr 2005 22:13:13 +0200 // author Patrick Gundlach <gundlach@speedata.de> Thu, 07 Apr 2005 22:13:13 +0200
//
// but without the "author " at the beginning (this method should) // but without the "author " at the beginning (this method should)
// be used for author and committer. // be used for author and committer.
// //

View file

@ -37,10 +37,8 @@ func (s *Signature) Decode(b []byte) {
} }
// Helper to get a signature from the commit line, which looks like these: // Helper to get a signature from the commit line, which looks like these:
//
// author Patrick Gundlach <gundlach@speedata.de> 1378823654 +0200 // author Patrick Gundlach <gundlach@speedata.de> 1378823654 +0200
// author Patrick Gundlach <gundlach@speedata.de> Thu, 07 Apr 2005 22:13:13 +0200 // author Patrick Gundlach <gundlach@speedata.de> Thu, 07 Apr 2005 22:13:13 +0200
//
// but without the "author " at the beginning (this method should) // but without the "author " at the beginning (this method should)
// be used for author and committer. // be used for author and committer.
func newSignatureFromCommitline(line []byte) (sig *Signature, err error) { func newSignatureFromCommitline(line []byte) (sig *Signature, err error) {

View file

@ -24,17 +24,19 @@ func GetCommitGraph(r *git.Repository, page, maxAllowedColors int, hidePRRefs bo
page = 1 page = 1
} }
graphCmd := git.NewCommand(r.Ctx, "log", "--graph", "--date-order", "--decorate=full") args := make([]string, 0, 12+len(branches)+len(files))
args = append(args, "--graph", "--date-order", "--decorate=full")
if hidePRRefs { if hidePRRefs {
graphCmd.AddArguments("--exclude=" + git.PullPrefix + "*") args = append(args, "--exclude="+git.PullPrefix+"*")
} }
if len(branches) == 0 { if len(branches) == 0 {
graphCmd.AddArguments("--all") args = append(args, "--all")
} }
graphCmd.AddArguments( args = append(args,
"-C", "-C",
"-M", "-M",
fmt.Sprintf("-n %d", setting.UI.GraphMaxCommitNum*page), fmt.Sprintf("-n %d", setting.UI.GraphMaxCommitNum*page),
@ -42,12 +44,15 @@ func GetCommitGraph(r *git.Repository, page, maxAllowedColors int, hidePRRefs bo
fmt.Sprintf("--pretty=format:%s", format)) fmt.Sprintf("--pretty=format:%s", format))
if len(branches) > 0 { if len(branches) > 0 {
graphCmd.AddDynamicArguments(branches...) args = append(args, branches...)
} }
args = append(args, "--")
if len(files) > 0 { if len(files) > 0 {
graphCmd.AddArguments("--") args = append(args, files...)
graphCmd.AddArguments(files...)
} }
graphCmd := git.NewCommand(r.Ctx, "log")
graphCmd.AddArguments(args...)
graph := NewGraph() graph := NewGraph()
stderr := new(strings.Builder) stderr := new(strings.Builder)

View file

@ -93,7 +93,6 @@ func NewFileLogger() LoggerProvider {
// Init file logger with json config. // Init file logger with json config.
// config like: // config like:
//
// { // {
// "filename":"log/gogs.log", // "filename":"log/gogs.log",
// "maxsize":1<<30, // "maxsize":1<<30,

View file

@ -48,7 +48,6 @@ func NewSMTPLogger() LoggerProvider {
// Init smtp writer with json config. // Init smtp writer with json config.
// config like: // config like:
//
// { // {
// "Username":"example@gmail.com", // "Username":"example@gmail.com",
// "password:"password", // "password:"password",

View file

@ -7,7 +7,6 @@ package markup_test
import ( import (
"context" "context"
"io" "io"
"os"
"strings" "strings"
"testing" "testing"
@ -33,7 +32,6 @@ func TestMain(m *testing.M) {
if err := git.InitSimple(context.Background()); err != nil { if err := git.InitSimple(context.Background()); err != nil {
log.Fatal("git init failed, err: %v", err) log.Fatal("git init failed, err: %v", err)
} }
os.Exit(m.Run())
} }
func TestRender_Commits(t *testing.T) { func TestRender_Commits(t *testing.T) {
@ -338,7 +336,7 @@ func TestRender_emoji(t *testing.T) {
`<p>Some text with <span class="emoji" aria-label="grinning face with smiling eyes">😄</span><span class="emoji" aria-label="grinning face with smiling eyes">😄</span> 2 emoji next to each other</p>`) `<p>Some text with <span class="emoji" aria-label="grinning face with smiling eyes">😄</span><span class="emoji" aria-label="grinning face with smiling eyes">😄</span> 2 emoji next to each other</p>`)
test( test(
"😎🤪🔐🤑❓", "😎🤪🔐🤑❓",
`<p><span class="emoji" aria-label="smiling face with sunglasses">😎</span><span class="emoji" aria-label="zany face">🤪</span><span class="emoji" aria-label="locked with key">🔐</span><span class="emoji" aria-label="money-mouth face">🤑</span><span class="emoji" aria-label="red question mark">❓</span></p>`) `<p><span class="emoji" aria-label="smiling face with sunglasses">😎</span><span class="emoji" aria-label="zany face">🤪</span><span class="emoji" aria-label="locked with key">🔐</span><span class="emoji" aria-label="money-mouth face">🤑</span><span class="emoji" aria-label="question mark">❓</span></p>`)
// should match nothing // should match nothing
test( test(

View file

@ -6,7 +6,6 @@ package markdown_test
import ( import (
"context" "context"
"os"
"strings" "strings"
"testing" "testing"
@ -38,7 +37,6 @@ func TestMain(m *testing.M) {
if err := git.InitSimple(context.Background()); err != nil { if err := git.InitSimple(context.Background()); err != nil {
log.Fatal("git init failed, err: %v", err) log.Fatal("git init failed, err: %v", err)
} }
os.Exit(m.Run())
} }
func TestRender_StandardLinks(t *testing.T) { func TestRender_StandardLinks(t *testing.T) {

View file

@ -95,10 +95,8 @@ func parseOCIImageConfig(r io.Reader) (*Metadata, error) {
if i := strings.Index(cmd, "#(nop) "); i != -1 { if i := strings.Index(cmd, "#(nop) "); i != -1 {
cmd = strings.TrimSpace(cmd[i+7:]) cmd = strings.TrimSpace(cmd[i+7:])
} }
if cmd != "" {
imageLayers = append(imageLayers, cmd) imageLayers = append(imageLayers, cmd)
} }
}
metadata := &Metadata{ metadata := &Metadata{
Type: TypeOCI, Type: TypeOCI,

View file

@ -25,7 +25,7 @@ func DumpMemProfileForUsername(pprofDataPath, username string) error {
} }
// DumpCPUProfileForUsername dumps a CPU profile at pprofDataPath as cpuprofile_<username>_<temporary id> // DumpCPUProfileForUsername dumps a CPU profile at pprofDataPath as cpuprofile_<username>_<temporary id>
// the stop function it returns stops, writes and closes the CPU profile file // it returns the stop function which stops, writes and closes the CPU profile file
func DumpCPUProfileForUsername(pprofDataPath, username string) (func(), error) { func DumpCPUProfileForUsername(pprofDataPath, username string) (func(), error) {
f, err := os.CreateTemp(pprofDataPath, fmt.Sprintf("cpuprofile_%s_", username)) f, err := os.CreateTemp(pprofDataPath, fmt.Sprintf("cpuprofile_%s_", username))
if err != nil { if err != nil {

View file

@ -31,8 +31,8 @@ import (
) )
/* /*
GitHub, GitLab, Gogs: *.wiki.git GitHub, GitLab, Gogs: *.wiki.git
BitBucket: *.git/wiki BitBucket: *.git/wiki
*/ */
var commonWikiURLSuffixes = []string{".wiki.git", ".git/wiki"} var commonWikiURLSuffixes = []string{".wiki.git", ".git/wiki"}

View file

@ -154,7 +154,6 @@ func NewFuncMap() []template.FuncMap {
"DiffTypeToStr": DiffTypeToStr, "DiffTypeToStr": DiffTypeToStr,
"DiffLineTypeToStr": DiffLineTypeToStr, "DiffLineTypeToStr": DiffLineTypeToStr,
"ShortSha": base.ShortSha, "ShortSha": base.ShortSha,
"MD5": base.EncodeMD5,
"ActionContent2Commits": ActionContent2Commits, "ActionContent2Commits": ActionContent2Commits,
"PathEscape": url.PathEscape, "PathEscape": url.PathEscape,
"PathEscapeSegments": util.PathEscapeSegments, "PathEscapeSegments": util.PathEscapeSegments,

View file

@ -41,14 +41,14 @@ func NewLocaleStore() *LocaleStore {
} }
// AddLocaleByIni adds locale by ini into the store // AddLocaleByIni adds locale by ini into the store
func (ls *LocaleStore) AddLocaleByIni(langName, langDesc string, source, moreSource []byte) error { func (ls *LocaleStore) AddLocaleByIni(langName, langDesc string, localeFile interface{}, otherLocaleFiles ...interface{}) error {
if _, ok := ls.localeMap[langName]; ok { if _, ok := ls.localeMap[langName]; ok {
return ErrLocaleAlreadyExist return ErrLocaleAlreadyExist
} }
iniFile, err := ini.LoadSources(ini.LoadOptions{ iniFile, err := ini.LoadSources(ini.LoadOptions{
IgnoreInlineComment: true, IgnoreInlineComment: true,
UnescapeValueCommentSymbols: true, UnescapeValueCommentSymbols: true,
}, source, moreSource) }, localeFile, otherLocaleFiles...)
if err == nil { if err == nil {
iniFile.BlockMode = false iniFile.BlockMode = false
lc := &locale{store: ls, langName: langName, langDesc: langDesc, messages: iniFile} lc := &locale{store: ls, langName: langName, langDesc: langDesc, messages: iniFile}

View file

@ -10,7 +10,7 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func TestLocaleStore(t *testing.T) { func Test_Tr(t *testing.T) {
testData1 := []byte(` testData1 := []byte(`
.dot.name = Dot Name .dot.name = Dot Name
fmt = %[1]s %[2]s fmt = %[1]s %[2]s
@ -28,8 +28,8 @@ sub = Changed Sub String
`) `)
ls := NewLocaleStore() ls := NewLocaleStore()
assert.NoError(t, ls.AddLocaleByIni("lang1", "Lang1", testData1, nil)) assert.NoError(t, ls.AddLocaleByIni("lang1", "Lang1", testData1))
assert.NoError(t, ls.AddLocaleByIni("lang2", "Lang2", testData2, nil)) assert.NoError(t, ls.AddLocaleByIni("lang2", "Lang2", testData2))
ls.SetDefaultLang("lang1") ls.SetDefaultLang("lang1")
result := ls.Tr("lang1", "fmt", "a", "b") result := ls.Tr("lang1", "fmt", "a", "b")
@ -54,21 +54,3 @@ sub = Changed Sub String
assert.Equal(t, []string{"lang1", "lang2"}, langs) assert.Equal(t, []string{"lang1", "lang2"}, langs)
assert.Equal(t, []string{"Lang1", "Lang2"}, descs) assert.Equal(t, []string{"Lang1", "Lang2"}, descs)
} }
func TestLocaleStoreMoreSource(t *testing.T) {
testData1 := []byte(`
a=11
b=12
`)
testData2 := []byte(`
b=21
c=22
`)
ls := NewLocaleStore()
assert.NoError(t, ls.AddLocaleByIni("lang1", "Lang1", testData1, testData2))
assert.Equal(t, "11", ls.Tr("lang1", "a"))
assert.Equal(t, "21", ls.Tr("lang1", "b"))
assert.Equal(t, "22", ls.Tr("lang1", "c"))
}

View file

@ -60,9 +60,9 @@ func InitLocales() {
log.Fatal("Failed to list locale files: %v", err) log.Fatal("Failed to list locale files: %v", err)
} }
localeData := make(map[string][]byte, len(localeNames)) localFiles := make(map[string][]byte, len(localeNames))
for _, name := range localeNames { for _, name := range localeNames {
localeData[name], err = options.Locale(name) localFiles[name], err = options.Locale(name)
if err != nil { if err != nil {
log.Fatal("Failed to load %s locale file. %v", name, err) log.Fatal("Failed to load %s locale file. %v", name, err)
} }
@ -75,16 +75,8 @@ func InitLocales() {
matcher = language.NewMatcher(supportedTags) matcher = language.NewMatcher(supportedTags)
for i := range setting.Names { for i := range setting.Names {
var localeDataBase []byte
if i == 0 && setting.Langs[0] != "en-US" {
// Only en-US has complete translations. When use other language as default, the en-US should still be used as fallback.
localeDataBase = localeData["locale_en-US.ini"]
if localeDataBase == nil {
log.Fatal("Failed to load locale_en-US.ini file.")
}
}
key := "locale_" + setting.Langs[i] + ".ini" key := "locale_" + setting.Langs[i] + ".ini"
if err = i18n.DefaultLocales.AddLocaleByIni(setting.Langs[i], setting.Names[i], localeDataBase, localeData[key]); err != nil { if err = i18n.DefaultLocales.AddLocaleByIni(setting.Langs[i], setting.Names[i], localFiles[key]); err != nil {
log.Error("Failed to set messages to %s: %v", setting.Langs[i], err) log.Error("Failed to set messages to %s: %v", setting.Langs[i], err)
} }
} }

View file

@ -17,13 +17,13 @@ func isSnakeCaseLowerOrNumber(c byte) bool {
// ToSnakeCase convert the input string to snake_case format. // ToSnakeCase convert the input string to snake_case format.
// //
// Some samples. // Some samples.
//
// "FirstName" => "first_name" // "FirstName" => "first_name"
// "HTTPServer" => "http_server" // "HTTPServer" => "http_server"
// "NoHTTPS" => "no_https" // "NoHTTPS" => "no_https"
// "GO_PATH" => "go_path" // "GO_PATH" => "go_path"
// "GO PATH" => "go_path" // space is converted to underscore. // "GO PATH" => "go_path" // space is converted to underscore.
// "GO-PATH" => "go_path" // hyphen is converted to underscore. // "GO-PATH" => "go_path" // hyphen is converted to underscore.
//
func ToSnakeCase(input string) string { func ToSnakeCase(input string) string {
if len(input) == 0 { if len(input) == 0 {
return "" return ""

View file

@ -66,7 +66,7 @@ func Routes() *web.Route {
r.Get("/p2/{vendorname}/{projectname}.json", composer.PackageMetadata) r.Get("/p2/{vendorname}/{projectname}.json", composer.PackageMetadata)
r.Get("/files/{package}/{version}/{filename}", composer.DownloadPackageFile) r.Get("/files/{package}/{version}/{filename}", composer.DownloadPackageFile)
r.Put("", reqPackageAccess(perm.AccessModeWrite), composer.UploadPackage) r.Put("", reqPackageAccess(perm.AccessModeWrite), composer.UploadPackage)
}, reqPackageAccess(perm.AccessModeRead)) })
r.Group("/conan", func() { r.Group("/conan", func() {
r.Group("/v1", func() { r.Group("/v1", func() {
r.Get("/ping", conan.Ping) r.Get("/ping", conan.Ping)
@ -154,7 +154,7 @@ func Routes() *web.Route {
}, conan.ExtractPathParameters) }, conan.ExtractPathParameters)
}) })
}) })
}, reqPackageAccess(perm.AccessModeRead)) })
r.Group("/generic", func() { r.Group("/generic", func() {
r.Group("/{packagename}/{packageversion}/{filename}", func() { r.Group("/{packagename}/{packageversion}/{filename}", func() {
r.Get("", generic.DownloadPackageFile) r.Get("", generic.DownloadPackageFile)
@ -163,19 +163,18 @@ func Routes() *web.Route {
r.Delete("", generic.DeletePackage) r.Delete("", generic.DeletePackage)
}, reqPackageAccess(perm.AccessModeWrite)) }, reqPackageAccess(perm.AccessModeWrite))
}) })
}, reqPackageAccess(perm.AccessModeRead)) })
r.Group("/helm", func() { r.Group("/helm", func() {
r.Get("/index.yaml", helm.Index) r.Get("/index.yaml", helm.Index)
r.Get("/{filename}", helm.DownloadPackageFile) r.Get("/{filename}", helm.DownloadPackageFile)
r.Post("/api/charts", reqPackageAccess(perm.AccessModeWrite), helm.UploadPackage) r.Post("/api/charts", reqPackageAccess(perm.AccessModeWrite), helm.UploadPackage)
}, reqPackageAccess(perm.AccessModeRead)) })
r.Group("/maven", func() { r.Group("/maven", func() {
r.Put("/*", reqPackageAccess(perm.AccessModeWrite), maven.UploadPackageFile) r.Put("/*", reqPackageAccess(perm.AccessModeWrite), maven.UploadPackageFile)
r.Get("/*", maven.DownloadPackageFile) r.Get("/*", maven.DownloadPackageFile)
}, reqPackageAccess(perm.AccessModeRead)) })
r.Group("/nuget", func() { r.Group("/nuget", func() {
r.Get("/index.json", nuget.ServiceIndex) // Needs to be unauthenticated for the NuGet client. r.Get("/index.json", nuget.ServiceIndex)
r.Group("", func() {
r.Get("/query", nuget.SearchService) r.Get("/query", nuget.SearchService)
r.Group("/registration/{id}", func() { r.Group("/registration/{id}", func() {
r.Get("/index.json", nuget.RegistrationIndex) r.Get("/index.json", nuget.RegistrationIndex)
@ -191,7 +190,6 @@ func Routes() *web.Route {
r.Delete("/{id}/{version}", nuget.DeletePackage) r.Delete("/{id}/{version}", nuget.DeletePackage)
}, reqPackageAccess(perm.AccessModeWrite)) }, reqPackageAccess(perm.AccessModeWrite))
r.Get("/symbols/{filename}/{guid:[0-9a-f]{32}}FFFFFFFF/{filename2}", nuget.DownloadSymbolFile) r.Get("/symbols/{filename}/{guid:[0-9a-f]{32}}FFFFFFFF/{filename2}", nuget.DownloadSymbolFile)
}, reqPackageAccess(perm.AccessModeRead))
}) })
r.Group("/npm", func() { r.Group("/npm", func() {
r.Group("/@{scope}/{id}", func() { r.Group("/@{scope}/{id}", func() {
@ -218,12 +216,12 @@ func Routes() *web.Route {
r.Delete("", npm.DeletePackageTag) r.Delete("", npm.DeletePackageTag)
}, reqPackageAccess(perm.AccessModeWrite)) }, reqPackageAccess(perm.AccessModeWrite))
}) })
}, reqPackageAccess(perm.AccessModeRead)) })
r.Group("/pypi", func() { r.Group("/pypi", func() {
r.Post("/", reqPackageAccess(perm.AccessModeWrite), pypi.UploadPackageFile) r.Post("/", reqPackageAccess(perm.AccessModeWrite), pypi.UploadPackageFile)
r.Get("/files/{id}/{version}/{filename}", pypi.DownloadPackageFile) r.Get("/files/{id}/{version}/{filename}", pypi.DownloadPackageFile)
r.Get("/simple/{id}", pypi.PackageMetadata) r.Get("/simple/{id}", pypi.PackageMetadata)
}, reqPackageAccess(perm.AccessModeRead)) })
r.Group("/rubygems", func() { r.Group("/rubygems", func() {
r.Get("/specs.4.8.gz", rubygems.EnumeratePackages) r.Get("/specs.4.8.gz", rubygems.EnumeratePackages)
r.Get("/latest_specs.4.8.gz", rubygems.EnumeratePackagesLatest) r.Get("/latest_specs.4.8.gz", rubygems.EnumeratePackagesLatest)
@ -235,7 +233,7 @@ func Routes() *web.Route {
r.Delete("/yank", rubygems.DeletePackage) r.Delete("/yank", rubygems.DeletePackage)
}, reqPackageAccess(perm.AccessModeWrite)) }, reqPackageAccess(perm.AccessModeWrite))
}) })
}, context_service.UserAssignmentWeb(), context.PackageAssignment()) }, context_service.UserAssignmentWeb(), context.PackageAssignment(), reqPackageAccess(perm.AccessModeRead))
return r return r
} }

View file

@ -342,6 +342,7 @@ func uploadFile(ctx *context.Context, fileFilter stringSet, fileKey string) {
Name: rref.Name, Name: rref.Name,
Version: rref.Version, Version: rref.Version,
}, },
SemverCompatible: true,
Creator: ctx.Doer, Creator: ctx.Doer,
} }
pfci := &packages_service.PackageFileCreationInfo{ pfci := &packages_service.PackageFileCreationInfo{

View file

@ -24,7 +24,7 @@ import (
// https://www.python.org/dev/peps/pep-0503/#normalized-names // https://www.python.org/dev/peps/pep-0503/#normalized-names
var normalizer = strings.NewReplacer(".", "-", "_", "-") var normalizer = strings.NewReplacer(".", "-", "_", "-")
var nameMatcher = regexp.MustCompile(`\A[a-zA-Z0-9\.\-_]+\z`) var nameMatcher = regexp.MustCompile(`\A[a-z0-9\.\-_]+\z`)
// https://www.python.org/dev/peps/pep-0440/#appendix-b-parsing-version-strings-with-regular-expressions // https://www.python.org/dev/peps/pep-0440/#appendix-b-parsing-version-strings-with-regular-expressions
var versionMatcher = regexp.MustCompile(`^([1-9][0-9]*!)?(0|[1-9][0-9]*)(\.(0|[1-9][0-9]*))*((a|b|rc)(0|[1-9][0-9]*))?(\.post(0|[1-9][0-9]*))?(\.dev(0|[1-9][0-9]*))?$`) var versionMatcher = regexp.MustCompile(`^([1-9][0-9]*!)?(0|[1-9][0-9]*)(\.(0|[1-9][0-9]*))*((a|b|rc)(0|[1-9][0-9]*))?(\.post(0|[1-9][0-9]*))?(\.dev(0|[1-9][0-9]*))?$`)

View file

@ -34,7 +34,7 @@ func GetGitAllRefs(ctx *context.APIContext) {
// required: true // required: true
// responses: // responses:
// "200": // "200":
// # "$ref": "#/responses/Reference" TODO: swagger doesnt support different output formats by ref // "$ref": "#/responses/Reference"
// "$ref": "#/responses/ReferenceList" // "$ref": "#/responses/ReferenceList"
// "404": // "404":
// "$ref": "#/responses/notFound" // "$ref": "#/responses/notFound"
@ -67,7 +67,7 @@ func GetGitRefs(ctx *context.APIContext) {
// required: true // required: true
// responses: // responses:
// "200": // "200":
// # "$ref": "#/responses/Reference" TODO: swagger doesnt support different output formats by ref // "$ref": "#/responses/Reference"
// "$ref": "#/responses/ReferenceList" // "$ref": "#/responses/ReferenceList"
// "404": // "404":
// "$ref": "#/responses/notFound" // "$ref": "#/responses/notFound"

View file

@ -566,8 +566,6 @@ func ListMyTrackedTimes(ctx *context.APIContext) {
// swagger:operation GET /user/times user userCurrentTrackedTimes // swagger:operation GET /user/times user userCurrentTrackedTimes
// --- // ---
// summary: List the current user's tracked times // summary: List the current user's tracked times
// produces:
// - application/json
// parameters: // parameters:
// - name: page // - name: page
// in: query // in: query
@ -577,6 +575,9 @@ func ListMyTrackedTimes(ctx *context.APIContext) {
// in: query // in: query
// description: page size of results // description: page size of results
// type: integer // type: integer
// produces:
// - application/json
// parameters:
// - name: since // - name: since
// in: query // in: query
// description: Only show times updated after the given time. This is a timestamp in RFC 3339 format // description: Only show times updated after the given time. This is a timestamp in RFC 3339 format

View file

@ -585,6 +585,7 @@ func Edit(ctx *context.APIContext) {
// description: name of the repo to edit // description: name of the repo to edit
// type: string // type: string
// required: true // required: true
// required: true
// - name: body // - name: body
// in: body // in: body
// description: "Properties of a repo that you can edit" // description: "Properties of a repo that you can edit"

View file

@ -48,6 +48,11 @@ func AddEmail(ctx *context.APIContext) {
// produces: // produces:
// - application/json // - application/json
// parameters: // parameters:
// - name: options
// in: body
// schema:
// "$ref": "#/definitions/CreateEmailOption"
// parameters:
// - name: body // - name: body
// in: body // in: body
// schema: // schema:

View file

@ -588,8 +588,7 @@ func OIDCKeys(ctx *context.Context) {
// AccessTokenOAuth manages all access token requests by the client // AccessTokenOAuth manages all access token requests by the client
func AccessTokenOAuth(ctx *context.Context) { func AccessTokenOAuth(ctx *context.Context) {
form := *web.GetForm(ctx).(*forms.AccessTokenForm) form := *web.GetForm(ctx).(*forms.AccessTokenForm)
// if there is no ClientID or ClientSecret in the request body, fill these fields by the Authorization header and ensure the provided field matches the Authorization header if form.ClientID == "" {
if form.ClientID == "" || form.ClientSecret == "" {
authHeader := ctx.Req.Header.Get("Authorization") authHeader := ctx.Req.Header.Get("Authorization")
authContent := strings.SplitN(authHeader, " ", 2) authContent := strings.SplitN(authHeader, " ", 2)
if len(authContent) == 2 && authContent[0] == "Basic" { if len(authContent) == 2 && authContent[0] == "Basic" {
@ -609,21 +608,7 @@ func AccessTokenOAuth(ctx *context.Context) {
}) })
return return
} }
if form.ClientID != "" && form.ClientID != pair[0] {
handleAccessTokenError(ctx, AccessTokenError{
ErrorCode: AccessTokenErrorCodeInvalidRequest,
ErrorDescription: "client_id in request body inconsistent with Authorization header",
})
return
}
form.ClientID = pair[0] form.ClientID = pair[0]
if form.ClientSecret != "" && form.ClientSecret != pair[1] {
handleAccessTokenError(ctx, AccessTokenError{
ErrorCode: AccessTokenErrorCodeInvalidRequest,
ErrorDescription: "client_secret in request body inconsistent with Authorization header",
})
return
}
form.ClientSecret = pair[1] form.ClientSecret = pair[1]
} }
} }
@ -701,13 +686,9 @@ func handleAuthorizationCode(ctx *context.Context, form forms.AccessTokenForm, s
return return
} }
if !app.ValidateClientSecret([]byte(form.ClientSecret)) { if !app.ValidateClientSecret([]byte(form.ClientSecret)) {
errorDescription := "invalid client secret"
if form.ClientSecret == "" {
errorDescription = "invalid empty client secret"
}
handleAccessTokenError(ctx, AccessTokenError{ handleAccessTokenError(ctx, AccessTokenError{
ErrorCode: AccessTokenErrorCodeUnauthorizedClient, ErrorCode: AccessTokenErrorCodeUnauthorizedClient,
ErrorDescription: errorDescription, ErrorDescription: "client is not authorized",
}) })
return return
} }

View file

@ -24,27 +24,27 @@ import (
) )
func toBranchLink(act *models.Action) string { func toBranchLink(act *models.Action) string {
return act.GetRepoAbsoluteLink() + "/src/branch/" + util.PathEscapeSegments(act.GetBranch()) return act.GetRepoLink() + "/src/branch/" + util.PathEscapeSegments(act.GetBranch())
} }
func toTagLink(act *models.Action) string { func toTagLink(act *models.Action) string {
return act.GetRepoAbsoluteLink() + "/src/tag/" + util.PathEscapeSegments(act.GetTag()) return act.GetRepoLink() + "/src/tag/" + util.PathEscapeSegments(act.GetTag())
} }
func toIssueLink(act *models.Action) string { func toIssueLink(act *models.Action) string {
return act.GetRepoAbsoluteLink() + "/issues/" + url.PathEscape(act.GetIssueInfos()[0]) return act.GetRepoLink() + "/issues/" + url.PathEscape(act.GetIssueInfos()[0])
} }
func toPullLink(act *models.Action) string { func toPullLink(act *models.Action) string {
return act.GetRepoAbsoluteLink() + "/pulls/" + url.PathEscape(act.GetIssueInfos()[0]) return act.GetRepoLink() + "/pulls/" + url.PathEscape(act.GetIssueInfos()[0])
} }
func toSrcLink(act *models.Action) string { func toSrcLink(act *models.Action) string {
return act.GetRepoAbsoluteLink() + "/src/" + util.PathEscapeSegments(act.GetBranch()) return act.GetRepoLink() + "/src/" + util.PathEscapeSegments(act.GetBranch())
} }
func toReleaseLink(act *models.Action) string { func toReleaseLink(act *models.Action) string {
return act.GetRepoAbsoluteLink() + "/releases/tag/" + util.PathEscapeSegments(act.GetBranch()) return act.GetRepoLink() + "/releases/tag/" + util.PathEscapeSegments(act.GetBranch())
} }
// renderMarkdown creates a minimal markdown render context from an action. // renderMarkdown creates a minimal markdown render context from an action.
@ -79,17 +79,17 @@ func feedActionsToFeedItems(ctx *context.Context, actions models.ActionList) (it
title = act.ActUser.DisplayName() + " " title = act.ActUser.DisplayName() + " "
switch act.OpType { switch act.OpType {
case models.ActionCreateRepo: case models.ActionCreateRepo:
title += ctx.TrHTMLEscapeArgs("action.create_repo", act.GetRepoAbsoluteLink(), act.ShortRepoPath()) title += ctx.TrHTMLEscapeArgs("action.create_repo", act.GetRepoLink(), act.ShortRepoPath())
link.Href = act.GetRepoAbsoluteLink() link.Href = act.GetRepoLink()
case models.ActionRenameRepo: case models.ActionRenameRepo:
title += ctx.TrHTMLEscapeArgs("action.rename_repo", act.GetContent(), act.GetRepoAbsoluteLink(), act.ShortRepoPath()) title += ctx.TrHTMLEscapeArgs("action.rename_repo", act.GetContent(), act.GetRepoLink(), act.ShortRepoPath())
link.Href = act.GetRepoAbsoluteLink() link.Href = act.GetRepoLink()
case models.ActionCommitRepo: case models.ActionCommitRepo:
link.Href = toBranchLink(act) link.Href = toBranchLink(act)
if len(act.Content) != 0 { if len(act.Content) != 0 {
title += ctx.TrHTMLEscapeArgs("action.commit_repo", act.GetRepoAbsoluteLink(), link.Href, act.GetBranch(), act.ShortRepoPath()) title += ctx.TrHTMLEscapeArgs("action.commit_repo", act.GetRepoLink(), link.Href, act.GetBranch(), act.ShortRepoPath())
} else { } else {
title += ctx.TrHTMLEscapeArgs("action.create_branch", act.GetRepoAbsoluteLink(), link.Href, act.GetBranch(), act.ShortRepoPath()) title += ctx.TrHTMLEscapeArgs("action.create_branch", act.GetRepoLink(), link.Href, act.GetBranch(), act.ShortRepoPath())
} }
case models.ActionCreateIssue: case models.ActionCreateIssue:
link.Href = toIssueLink(act) link.Href = toIssueLink(act)
@ -98,11 +98,11 @@ func feedActionsToFeedItems(ctx *context.Context, actions models.ActionList) (it
link.Href = toPullLink(act) link.Href = toPullLink(act)
title += ctx.TrHTMLEscapeArgs("action.create_pull_request", link.Href, act.GetIssueInfos()[0], act.ShortRepoPath()) title += ctx.TrHTMLEscapeArgs("action.create_pull_request", link.Href, act.GetIssueInfos()[0], act.ShortRepoPath())
case models.ActionTransferRepo: case models.ActionTransferRepo:
link.Href = act.GetRepoAbsoluteLink() link.Href = act.GetRepoLink()
title += ctx.TrHTMLEscapeArgs("action.transfer_repo", act.GetContent(), act.GetRepoAbsoluteLink(), act.ShortRepoPath()) title += ctx.TrHTMLEscapeArgs("action.transfer_repo", act.GetContent(), act.GetRepoLink(), act.ShortRepoPath())
case models.ActionPushTag: case models.ActionPushTag:
link.Href = toTagLink(act) link.Href = toTagLink(act)
title += ctx.TrHTMLEscapeArgs("action.push_tag", act.GetRepoAbsoluteLink(), link.Href, act.GetTag(), act.ShortRepoPath()) title += ctx.TrHTMLEscapeArgs("action.push_tag", act.GetRepoLink(), link.Href, act.GetTag(), act.ShortRepoPath())
case models.ActionCommentIssue: case models.ActionCommentIssue:
issueLink := toIssueLink(act) issueLink := toIssueLink(act)
if link.Href == "#" { if link.Href == "#" {
@ -140,26 +140,26 @@ func feedActionsToFeedItems(ctx *context.Context, actions models.ActionList) (it
} }
title += ctx.TrHTMLEscapeArgs("action.reopen_pull_request", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath()) title += ctx.TrHTMLEscapeArgs("action.reopen_pull_request", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath())
case models.ActionDeleteTag: case models.ActionDeleteTag:
link.Href = act.GetRepoAbsoluteLink() link.Href = act.GetRepoLink()
title += ctx.TrHTMLEscapeArgs("action.delete_tag", act.GetRepoAbsoluteLink(), act.GetTag(), act.ShortRepoPath()) title += ctx.TrHTMLEscapeArgs("action.delete_tag", act.GetRepoLink(), act.GetTag(), act.ShortRepoPath())
case models.ActionDeleteBranch: case models.ActionDeleteBranch:
link.Href = act.GetRepoAbsoluteLink() link.Href = act.GetRepoLink()
title += ctx.TrHTMLEscapeArgs("action.delete_branch", act.GetRepoAbsoluteLink(), html.EscapeString(act.GetBranch()), act.ShortRepoPath()) title += ctx.TrHTMLEscapeArgs("action.delete_branch", act.GetRepoLink(), html.EscapeString(act.GetBranch()), act.ShortRepoPath())
case models.ActionMirrorSyncPush: case models.ActionMirrorSyncPush:
srcLink := toSrcLink(act) srcLink := toSrcLink(act)
if link.Href == "#" { if link.Href == "#" {
link.Href = srcLink link.Href = srcLink
} }
title += ctx.TrHTMLEscapeArgs("action.mirror_sync_push", act.GetRepoAbsoluteLink(), srcLink, act.GetBranch(), act.ShortRepoPath()) title += ctx.TrHTMLEscapeArgs("action.mirror_sync_push", act.GetRepoLink(), srcLink, act.GetBranch(), act.ShortRepoPath())
case models.ActionMirrorSyncCreate: case models.ActionMirrorSyncCreate:
srcLink := toSrcLink(act) srcLink := toSrcLink(act)
if link.Href == "#" { if link.Href == "#" {
link.Href = srcLink link.Href = srcLink
} }
title += ctx.TrHTMLEscapeArgs("action.mirror_sync_create", act.GetRepoAbsoluteLink(), srcLink, act.GetBranch(), act.ShortRepoPath()) title += ctx.TrHTMLEscapeArgs("action.mirror_sync_create", act.GetRepoLink(), srcLink, act.GetBranch(), act.ShortRepoPath())
case models.ActionMirrorSyncDelete: case models.ActionMirrorSyncDelete:
link.Href = act.GetRepoAbsoluteLink() link.Href = act.GetRepoLink()
title += ctx.TrHTMLEscapeArgs("action.mirror_sync_delete", act.GetRepoAbsoluteLink(), act.GetBranch(), act.ShortRepoPath()) title += ctx.TrHTMLEscapeArgs("action.mirror_sync_delete", act.GetRepoLink(), act.GetBranch(), act.ShortRepoPath())
case models.ActionApprovePullRequest: case models.ActionApprovePullRequest:
pullLink := toPullLink(act) pullLink := toPullLink(act)
title += ctx.TrHTMLEscapeArgs("action.approve_pull_request", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath()) title += ctx.TrHTMLEscapeArgs("action.approve_pull_request", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath())
@ -174,16 +174,16 @@ func feedActionsToFeedItems(ctx *context.Context, actions models.ActionList) (it
if link.Href == "#" { if link.Href == "#" {
link.Href = releaseLink link.Href = releaseLink
} }
title += ctx.TrHTMLEscapeArgs("action.publish_release", act.GetRepoAbsoluteLink(), releaseLink, act.ShortRepoPath(), act.Content) title += ctx.TrHTMLEscapeArgs("action.publish_release", act.GetRepoLink(), releaseLink, act.ShortRepoPath(), act.Content)
case models.ActionPullReviewDismissed: case models.ActionPullReviewDismissed:
pullLink := toPullLink(act) pullLink := toPullLink(act)
title += ctx.TrHTMLEscapeArgs("action.review_dismissed", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath(), act.GetIssueInfos()[1]) title += ctx.TrHTMLEscapeArgs("action.review_dismissed", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath(), act.GetIssueInfos()[1])
case models.ActionStarRepo: case models.ActionStarRepo:
link.Href = act.GetRepoAbsoluteLink() link.Href = act.GetRepoLink()
title += ctx.TrHTMLEscapeArgs("action.starred_repo", act.GetRepoAbsoluteLink(), act.GetRepoPath()) title += ctx.TrHTMLEscapeArgs("action.starred_repo", act.GetRepoLink(), act.GetRepoPath())
case models.ActionWatchRepo: case models.ActionWatchRepo:
link.Href = act.GetRepoAbsoluteLink() link.Href = act.GetRepoLink()
title += ctx.TrHTMLEscapeArgs("action.watched_repo", act.GetRepoAbsoluteLink(), act.GetRepoPath()) title += ctx.TrHTMLEscapeArgs("action.watched_repo", act.GetRepoLink(), act.GetRepoPath())
default: default:
return nil, fmt.Errorf("unknown action type: %v", act.OpType) return nil, fmt.Errorf("unknown action type: %v", act.OpType)
} }
@ -193,14 +193,14 @@ func feedActionsToFeedItems(ctx *context.Context, actions models.ActionList) (it
switch act.OpType { switch act.OpType {
case models.ActionCommitRepo, models.ActionMirrorSyncPush: case models.ActionCommitRepo, models.ActionMirrorSyncPush:
push := templates.ActionContent2Commits(act) push := templates.ActionContent2Commits(act)
repoLink := act.GetRepoAbsoluteLink() repoLink := act.GetRepoLink()
for _, commit := range push.Commits { for _, commit := range push.Commits {
if len(desc) != 0 { if len(desc) != 0 {
desc += "\n\n" desc += "\n\n"
} }
desc += fmt.Sprintf("<a href=\"%s\">%s</a>\n%s", desc += fmt.Sprintf("<a href=\"%s\">%s</a>\n%s",
html.EscapeString(fmt.Sprintf("%s/commit/%s", act.GetRepoAbsoluteLink(), commit.Sha1)), html.EscapeString(fmt.Sprintf("%s/commit/%s", act.GetRepoLink(), commit.Sha1)),
commit.Sha1, commit.Sha1,
templates.RenderCommitMessage(ctx, commit.Message, repoLink, nil), templates.RenderCommitMessage(ctx, commit.Message, repoLink, nil),
) )
@ -209,7 +209,7 @@ func feedActionsToFeedItems(ctx *context.Context, actions models.ActionList) (it
if push.Len > 1 { if push.Len > 1 {
link = &feeds.Link{Href: fmt.Sprintf("%s/%s", setting.AppSubURL, push.CompareURL)} link = &feeds.Link{Href: fmt.Sprintf("%s/%s", setting.AppSubURL, push.CompareURL)}
} else if push.Len == 1 { } else if push.Len == 1 {
link = &feeds.Link{Href: fmt.Sprintf("%s/commit/%s", act.GetRepoAbsoluteLink(), push.Commits[0].Sha1)} link = &feeds.Link{Href: fmt.Sprintf("%s/commit/%s", act.GetRepoLink(), push.Commits[0].Sha1)}
} }
case models.ActionCreateIssue, models.ActionCreatePullRequest: case models.ActionCreateIssue, models.ActionCreatePullRequest:

View file

@ -83,7 +83,7 @@ func Commits(ctx *context.Context) {
ctx.Data["CommitCount"] = commitsCount ctx.Data["CommitCount"] = commitsCount
ctx.Data["RefName"] = ctx.Repo.RefName ctx.Data["RefName"] = ctx.Repo.RefName
pager := context.NewPagination(int(commitsCount), pageSize, page, 5) pager := context.NewPagination(int(commitsCount), setting.Git.CommitsRangeSize, page, 5)
pager.SetDefaultParams(ctx) pager.SetDefaultParams(ctx)
ctx.Data["Page"] = pager ctx.Data["Page"] = pager

View file

@ -113,17 +113,17 @@ func setCsvCompareContext(ctx *context.Context) {
Error string Error string
} }
ctx.Data["CreateCsvDiff"] = func(diffFile *gitdiff.DiffFile, baseBlob, headBlob *git.Blob) CsvDiffResult { ctx.Data["CreateCsvDiff"] = func(diffFile *gitdiff.DiffFile, baseCommit, headCommit *git.Commit) CsvDiffResult {
if diffFile == nil { if diffFile == nil || baseCommit == nil || headCommit == nil {
return CsvDiffResult{nil, ""} return CsvDiffResult{nil, ""}
} }
errTooLarge := errors.New(ctx.Locale.Tr("repo.error.csv.too_large")) errTooLarge := errors.New(ctx.Locale.Tr("repo.error.csv.too_large"))
csvReaderFromCommit := func(ctx *markup.RenderContext, blob *git.Blob) (*csv.Reader, io.Closer, error) { csvReaderFromCommit := func(ctx *markup.RenderContext, c *git.Commit) (*csv.Reader, io.Closer, error) {
if blob == nil { blob, err := c.GetBlobByPath(diffFile.Name)
// It's ok for blob to be nil (file added or deleted) if err != nil {
return nil, nil, nil return nil, nil, err
} }
if setting.UI.CSV.MaxFileSize != 0 && setting.UI.CSV.MaxFileSize < blob.Size() { if setting.UI.CSV.MaxFileSize != 0 && setting.UI.CSV.MaxFileSize < blob.Size() {
@ -139,28 +139,28 @@ func setCsvCompareContext(ctx *context.Context) {
return csvReader, reader, err return csvReader, reader, err
} }
baseReader, baseBlobCloser, err := csvReaderFromCommit(&markup.RenderContext{Ctx: ctx, RelativePath: diffFile.OldName}, baseBlob) baseReader, baseBlobCloser, err := csvReaderFromCommit(&markup.RenderContext{Ctx: ctx, RelativePath: diffFile.OldName}, baseCommit)
if baseBlobCloser != nil { if baseBlobCloser != nil {
defer baseBlobCloser.Close() defer baseBlobCloser.Close()
} }
if err != nil {
if err == errTooLarge { if err == errTooLarge {
return CsvDiffResult{nil, err.Error()} return CsvDiffResult{nil, err.Error()}
} }
log.Error("error whilst creating csv.Reader from file %s in base commit %s in %s: %v", diffFile.Name, baseBlob.ID.String(), ctx.Repo.Repository.Name, err) if err != nil {
return CsvDiffResult{nil, "unable to load file"} log.Error("CreateCsvDiff error whilst creating baseReader from file %s in commit %s in %s: %v", diffFile.Name, baseCommit.ID.String(), ctx.Repo.Repository.Name, err)
return CsvDiffResult{nil, "unable to load file from base commit"}
} }
headReader, headBlobCloser, err := csvReaderFromCommit(&markup.RenderContext{Ctx: ctx, RelativePath: diffFile.Name}, headBlob) headReader, headBlobCloser, err := csvReaderFromCommit(&markup.RenderContext{Ctx: ctx, RelativePath: diffFile.Name}, headCommit)
if headBlobCloser != nil { if headBlobCloser != nil {
defer headBlobCloser.Close() defer headBlobCloser.Close()
} }
if err != nil {
if err == errTooLarge { if err == errTooLarge {
return CsvDiffResult{nil, err.Error()} return CsvDiffResult{nil, err.Error()}
} }
log.Error("error whilst creating csv.Reader from file %s in head commit %s in %s: %v", diffFile.Name, headBlob.ID.String(), ctx.Repo.Repository.Name, err) if err != nil {
return CsvDiffResult{nil, "unable to load file"} log.Error("CreateCsvDiff error whilst creating headReader from file %s in commit %s in %s: %v", diffFile.Name, headCommit.ID.String(), ctx.Repo.Repository.Name, err)
return CsvDiffResult{nil, "unable to load file from head commit"}
} }
sections, err := gitdiff.CreateCsvDiff(diffFile, baseReader, headReader) sections, err := gitdiff.CreateCsvDiff(diffFile, baseReader, headReader)

View file

@ -117,16 +117,8 @@ func releasesOrTags(ctx *context.Context, isTagList bool) {
opts := models.FindReleasesOptions{ opts := models.FindReleasesOptions{
ListOptions: listOptions, ListOptions: listOptions,
} IncludeDrafts: writeAccess && !isTagList,
if isTagList { IncludeTags: isTagList,
// for the tags list page, show all releases with real tags (having real commit-id),
// the drafts should also be included because a real tag might be used as a draft.
opts.IncludeDrafts = true
opts.IncludeTags = true
opts.HasSha1 = util.OptionalBoolTrue
} else {
// only show draft releases for users who can write, read-only users shouldn't see draft releases.
opts.IncludeDrafts = writeAccess
} }
releases, err := models.GetReleasesByRepoID(ctx.Repo.Repository.ID, opts) releases, err := models.GetReleasesByRepoID(ctx.Repo.Repository.ID, opts)

View file

@ -1448,6 +1448,8 @@ func GetDiff(gitRepo *git.Repository, opts *DiffOptions, files ...string) (*Diff
} else if language, has := attrs["gitlab-language"]; has && language != "unspecified" && language != "" { } else if language, has := attrs["gitlab-language"]; has && language != "unspecified" && language != "" {
diffFile.Language = language diffFile.Language = language
} }
} else {
log.Error("Unexpected error: %v", err)
} }
} }

View file

@ -26,6 +26,7 @@ import (
"code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/structs"
"github.com/google/uuid" "github.com/google/uuid"
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
) )

View file

@ -78,7 +78,6 @@ type GiteaDownloader struct {
} }
// NewGiteaDownloader creates a gitea Downloader via gitea API // NewGiteaDownloader creates a gitea Downloader via gitea API
//
// Use either a username/password or personal token. token is preferred // Use either a username/password or personal token. token is preferred
// Note: Public access only allows very basic access // Note: Public access only allows very basic access
func NewGiteaDownloader(ctx context.Context, baseURL, repoPath, username, password, token string) (*GiteaDownloader, error) { func NewGiteaDownloader(ctx context.Context, baseURL, repoPath, username, password, token string) (*GiteaDownloader, error) {

View file

@ -412,10 +412,6 @@ func (g *GiteaLocalUploader) CreateIssues(issues ...*base.Issue) error {
}, },
} }
if is.ForeignReference.ForeignIndex == "0" {
is.ForeignReference.ForeignIndex = strconv.FormatInt(is.Index, 10)
}
if err := g.remapUser(issue, &is); err != nil { if err := g.remapUser(issue, &is); err != nil {
return err return err
} }

View file

@ -71,7 +71,6 @@ type GitlabDownloader struct {
} }
// NewGitlabDownloader creates a gitlab Downloader via gitlab API // NewGitlabDownloader creates a gitlab Downloader via gitlab API
//
// Use either a username/password, personal token entered into the username field, or anonymous/public access // Use either a username/password, personal token entered into the username field, or anonymous/public access
// Note: Public access only allows very basic access // Note: Public access only allows very basic access
func NewGitlabDownloader(ctx context.Context, baseURL, repoPath, username, password, token string) (*GitlabDownloader, error) { func NewGitlabDownloader(ctx context.Context, baseURL, repoPath, username, password, token string) (*GitlabDownloader, error) {
@ -375,7 +374,6 @@ type gitlabIssueContext struct {
} }
// GetIssues returns issues according start and limit // GetIssues returns issues according start and limit
//
// Note: issue label description and colors are not supported by the go-gitlab library at this time // Note: issue label description and colors are not supported by the go-gitlab library at this time
func (g *GitlabDownloader) GetIssues(page, perPage int) ([]*base.Issue, bool, error) { func (g *GitlabDownloader) GetIssues(page, perPage int) ([]*base.Issue, bool, error) {
state := "all" state := "all"

View file

@ -28,7 +28,6 @@ import (
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/cache" "code.gitea.io/gitea/modules/cache"
"code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/notification" "code.gitea.io/gitea/modules/notification"
"code.gitea.io/gitea/modules/references" "code.gitea.io/gitea/modules/references"
@ -166,10 +165,9 @@ func Merge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.U
go AddTestPullRequestTask(doer, pr.BaseRepo.ID, pr.BaseBranch, false, "", "") go AddTestPullRequestTask(doer, pr.BaseRepo.ID, pr.BaseBranch, false, "", "")
}() }()
// Run the merge in the hammer context to prevent cancellation // TODO: make it able to do this in a database session
hammerCtx := graceful.GetManager().HammerContext() mergeCtx := context.Background()
pr.MergedCommitID, err = rawMerge(mergeCtx, pr, doer, mergeStyle, expectedHeadCommitID, message)
pr.MergedCommitID, err = rawMerge(hammerCtx, pr, doer, mergeStyle, expectedHeadCommitID, message)
if err != nil { if err != nil {
return err return err
} }
@ -178,18 +176,18 @@ func Merge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.U
pr.Merger = doer pr.Merger = doer
pr.MergerID = doer.ID pr.MergerID = doer.ID
if _, err := pr.SetMerged(hammerCtx); err != nil { if _, err := pr.SetMerged(ctx); err != nil {
log.Error("setMerged [%d]: %v", pr.ID, err) log.Error("setMerged [%d]: %v", pr.ID, err)
} }
if err := pr.LoadIssueCtx(hammerCtx); err != nil { if err := pr.LoadIssueCtx(ctx); err != nil {
log.Error("loadIssue [%d]: %v", pr.ID, err) log.Error("loadIssue [%d]: %v", pr.ID, err)
} }
if err := pr.Issue.LoadRepo(hammerCtx); err != nil { if err := pr.Issue.LoadRepo(ctx); err != nil {
log.Error("loadRepo for issue [%d]: %v", pr.ID, err) log.Error("loadRepo for issue [%d]: %v", pr.ID, err)
} }
if err := pr.Issue.Repo.GetOwner(hammerCtx); err != nil { if err := pr.Issue.Repo.GetOwner(ctx); err != nil {
log.Error("GetOwner for issue repo [%d]: %v", pr.ID, err) log.Error("GetOwner for issue repo [%d]: %v", pr.ID, err)
} }
@ -199,17 +197,17 @@ func Merge(ctx context.Context, pr *issues_model.PullRequest, doer *user_model.U
cache.Remove(pr.Issue.Repo.GetCommitsCountCacheKey(pr.BaseBranch, true)) cache.Remove(pr.Issue.Repo.GetCommitsCountCacheKey(pr.BaseBranch, true))
// Resolve cross references // Resolve cross references
refs, err := pr.ResolveCrossReferences(hammerCtx) refs, err := pr.ResolveCrossReferences(ctx)
if err != nil { if err != nil {
log.Error("ResolveCrossReferences: %v", err) log.Error("ResolveCrossReferences: %v", err)
return nil return nil
} }
for _, ref := range refs { for _, ref := range refs {
if err = ref.LoadIssueCtx(hammerCtx); err != nil { if err = ref.LoadIssueCtx(ctx); err != nil {
return err return err
} }
if err = ref.Issue.LoadRepo(hammerCtx); err != nil { if err = ref.Issue.LoadRepo(ctx); err != nil {
return err return err
} }
close := ref.RefAction == references.XRefActionCloses close := ref.RefAction == references.XRefActionCloses

View file

@ -157,7 +157,7 @@
<tbody> <tbody>
{{range .Queue.Workers}} {{range .Queue.Workers}}
<tr> <tr>
<td>{{.Workers}}{{if .IsFlusher}}<span title="{{$.i18n.Tr "admin.monitor.queue.flush"}}">{{svg "octicon-sync"}}</span>{{end}}</td> <td>{{.Workers}}{{if .IsFlusher}}<span title="{{.i18n.Tr "admin.monitor.queue.flush"}}">{{svg "octicon-sync"}}</span>{{end}}</td>
<td>{{DateFmtLong .Start}}</td> <td>{{DateFmtLong .Start}}</td>
<td>{{if .HasTimeout}}{{DateFmtLong .Timeout}}{{else}}-{{end}}</td> <td>{{if .HasTimeout}}{{DateFmtLong .Timeout}}{{else}}-{{end}}</td>
<td> <td>

View file

@ -43,7 +43,7 @@
{{if .PackageDescriptor.Metadata.ImageLayers}} {{if .PackageDescriptor.Metadata.ImageLayers}}
<h4 class="ui top attached header">{{.i18n.Tr "packages.container.layers"}}</h4> <h4 class="ui top attached header">{{.i18n.Tr "packages.container.layers"}}</h4>
<div class="ui attached segment"> <div class="ui attached segment">
<table class="ui very basic compact table"> <table id="notice-table" class="ui very basic compact table">
<tbody> <tbody>
{{range .PackageDescriptor.Metadata.ImageLayers}} {{range .PackageDescriptor.Metadata.ImageLayers}}
<tr> <tr>
@ -57,7 +57,7 @@
{{if .PackageDescriptor.Metadata.Labels}} {{if .PackageDescriptor.Metadata.Labels}}
<h4 class="ui top attached header">{{.i18n.Tr "packages.container.labels"}}</h4> <h4 class="ui top attached header">{{.i18n.Tr "packages.container.labels"}}</h4>
<div class="ui attached segment"> <div class="ui attached segment">
<table class="ui very basic compact table container-labels"> <table id="notice-table" class="ui very basic compact table">
<thead> <thead>
<tr> <tr>
<th>{{.i18n.Tr "packages.container.labels.key"}}</th> <th>{{.i18n.Tr "packages.container.labels.key"}}</th>

View file

@ -1,11 +1,6 @@
{{/*Golang's template has a bug with string interpolation containing slashes,
the double slash will be treated as a comment there.
But there are also JS lint rules for template that require to use string interpolation in 1.17*/}}
<script> <script>
// synchronously set clone button states and urls here to avoid flickering // synchronously set clone button states and urls here to avoid flickering
// on page load. initRepoCloneLink calls this when proto changes. // on page load. initRepoCloneLink calls this when proto changes.
// this applies the protocol-dependant clone url to all elements with the
// `js-clone-url` and `js-clone-url-vsc` classes.
// TODO: This localStorage setting should be moved to backend user config // TODO: This localStorage setting should be moved to backend user config
// so it's available during rendering, then this inline script can be removed. // so it's available during rendering, then this inline script can be removed.
(window.updateCloneStates = function() { (window.updateCloneStates = function() {
@ -24,9 +19,5 @@ But there are also JS lint rules for template that require to use string interpo
for (const el of document.getElementsByClassName('js-clone-url')) { for (const el of document.getElementsByClassName('js-clone-url')) {
el[el.nodeName === 'INPUT' ? 'value' : 'textContent'] = link; el[el.nodeName === 'INPUT' ? 'value' : 'textContent'] = link;
} }
const sep = '//';
for (const el of document.getElementsByClassName('js-clone-url-vsc')) {
el.href = `vscode:${sep}vscode.git/clone?url=${encodeURIComponent(link)}`;
}
})(); })();
</script> </script>

View file

@ -57,8 +57,7 @@
{{end}} {{end}}
</ol> </ol>
<div id="diff-file-boxes"> <div id="diff-file-boxes">
{{range $file := .Diff.Files}} {{range $i, $file := .Diff.Files}}
{{/*notice: the index of Diff.Files should not be used for element ID, because the index will be restarted from 0 when doing load-more for PRs with a lot of files*/}}
{{$blobBase := call $.GetBlobByPathForCommit $.BaseCommit $file.OldName}} {{$blobBase := call $.GetBlobByPathForCommit $.BaseCommit $file.OldName}}
{{$blobHead := call $.GetBlobByPathForCommit $.HeadCommit $file.Name}} {{$blobHead := call $.GetBlobByPathForCommit $.HeadCommit $file.Name}}
{{$isImage := or (call $.IsBlobAnImage $blobBase) (call $.IsBlobAnImage $blobHead)}} {{$isImage := or (call $.IsBlobAnImage $blobBase) (call $.IsBlobAnImage $blobHead)}}
@ -94,8 +93,8 @@
<div class="diff-file-header-actions df ac"> <div class="diff-file-header-actions df ac">
{{if $showFileViewToggle}} {{if $showFileViewToggle}}
<div class="ui compact icon buttons"> <div class="ui compact icon buttons">
<span class="ui tiny basic button tooltip file-view-toggle" data-toggle-selector="#diff-source-{{$file.NameHash}}" data-content="{{$.i18n.Tr "repo.file_view_source"}}" data-position="bottom center">{{svg "octicon-code"}}</span> <span class="ui tiny basic button tooltip file-view-toggle" data-toggle-selector="#diff-source-{{$i}}" data-content="{{$.i18n.Tr "repo.file_view_source"}}" data-position="bottom center">{{svg "octicon-code"}}</span>
<span class="ui tiny basic button tooltip file-view-toggle active" data-toggle-selector="#diff-rendered-{{$file.NameHash}}" data-content="{{$.i18n.Tr "repo.file_view_rendered"}}" data-position="bottom center">{{svg "octicon-file"}}</span> <span class="ui tiny basic button tooltip file-view-toggle active" data-toggle-selector="#diff-rendered-{{$i}}" data-content="{{$.i18n.Tr "repo.file_view_rendered"}}" data-position="bottom center">{{svg "octicon-file"}}</span>
</div> </div>
{{end}} {{end}}
{{if $file.IsProtected}} {{if $file.IsProtected}}
@ -116,14 +115,15 @@
{{if $file.HasChangedSinceLastReview}} {{if $file.HasChangedSinceLastReview}}
<span class="changed-since-last-review unselectable">{{$.i18n.Tr "repo.pulls.has_changed_since_last_review"}}</span> <span class="changed-since-last-review unselectable">{{$.i18n.Tr "repo.pulls.has_changed_since_last_review"}}</span>
{{end}} {{end}}
<label data-link="{{$.Issue.Link}}/viewed-files" data-headcommit="{{$.PullHeadCommitID}}" class="viewed-file-form unselectable{{if $file.IsViewed}} viewed-file-checked-form{{end}}"> <div data-link="{{$.Issue.Link}}/viewed-files" data-headcommit="{{$.PullHeadCommitID}}" class="viewed-file-form unselectable{{if $file.IsViewed}} viewed-file-checked-form{{end}}">
<input type="checkbox" name="{{$file.GetDiffFileName}}" autocomplete="off"{{if $file.IsViewed}} checked{{end}}> {{$.i18n.Tr "repo.pulls.has_viewed_file"}} <input type="checkbox" name="{{$file.GetDiffFileName}}" id="viewed-file-checkbox-{{$i}}" autocomplete="off" {{if $file.IsViewed}}checked{{end}}></input>
</label> <label for="viewed-file-checkbox-{{$i}}">{{$.i18n.Tr "repo.pulls.has_viewed_file"}}</label>
</div>
{{end}} {{end}}
</div> </div>
</h4> </h4>
<div class="diff-file-body ui attached unstackable table segment" {{if $file.IsViewed}}data-folded="true"{{end}}> <div class="diff-file-body ui attached unstackable table segment" {{if $file.IsViewed}}data-folded="true"{{end}}>
<div id="diff-source-{{$file.NameHash}}" class="file-body file-code unicode-escaped code-diff{{if $.IsSplitStyle}} code-diff-split{{else}} code-diff-unified{{end}}{{if $showFileViewToggle}} hide{{end}}"> <div id="diff-source-{{$i}}" class="file-body file-code unicode-escaped code-diff{{if $.IsSplitStyle}} code-diff-split{{else}} code-diff-unified{{end}}{{if $showFileViewToggle}} hide{{end}}">
{{if or $file.IsIncomplete $file.IsBin}} {{if or $file.IsIncomplete $file.IsBin}}
<div class="diff-file-body binary" style="padding: 5px 10px;"> <div class="diff-file-body binary" style="padding: 5px 10px;">
{{if $file.IsIncomplete}} {{if $file.IsIncomplete}}
@ -148,12 +148,12 @@
{{end}} {{end}}
</div> </div>
{{if $showFileViewToggle}} {{if $showFileViewToggle}}
<div id="diff-rendered-{{$file.NameHash}}" class="file-body file-code {{if $.IsSplitStyle}} code-diff-split{{else}} code-diff-unified{{end}}"> <div id="diff-rendered-{{$i}}" class="file-body file-code {{if $.IsSplitStyle}} code-diff-split{{else}} code-diff-unified{{end}}">
<table class="chroma w-100"> <table class="chroma w-100">
{{if $isImage}} {{if $isImage}}
{{template "repo/diff/image_diff" dict "file" . "root" $ "blobBase" $blobBase "blobHead" $blobHead}} {{template "repo/diff/image_diff" dict "file" . "root" $ "blobBase" $blobBase "blobHead" $blobHead}}
{{else}} {{else}}
{{template "repo/diff/csv_diff" dict "file" . "root" $ "blobBase" $blobBase "blobHead" $blobHead}} {{template "repo/diff/csv_diff" dict "file" . "root" $}}
{{end}} {{end}}
</table> </table>
</div> </div>

View file

@ -1,6 +1,6 @@
<tr> <tr>
<td> <td>
{{$result := call .root.CreateCsvDiff .file .blobBase .blobHead}} {{$result := call .root.CreateCsvDiff .file .root.BaseCommit .root.HeadCommit}}
{{if $result.Error}} {{if $result.Error}}
<div class="ui center">{{$result.Error}}</div> <div class="ui center">{{$result.Error}}</div>
{{else if $result.Sections}} {{else if $result.Sections}}

View file

@ -117,6 +117,7 @@
{{if eq $n 0}} {{if eq $n 0}}
<div class="ui action tiny input" id="clone-panel"> <div class="ui action tiny input" id="clone-panel">
{{template "repo/clone_buttons" .}} {{template "repo/clone_buttons" .}}
{{template "repo/clone_script" .}}
<button id="download-btn" class="ui basic small compact jump dropdown icon button tooltip" data-content="{{.i18n.Tr "repo.download_archive"}}" data-position="top right"> <button id="download-btn" class="ui basic small compact jump dropdown icon button tooltip" data-content="{{.i18n.Tr "repo.download_archive"}}" data-position="top right">
{{svg "octicon-download"}} {{svg "octicon-download"}}
<div class="menu"> <div class="menu">
@ -125,10 +126,9 @@
<a class="item archive-link" href="{{$.RepoLink}}/archive/{{PathEscapeSegments $.RefName}}.tar.gz" rel="nofollow">{{svg "octicon-file-zip" 16 "mr-3"}}{{.i18n.Tr "repo.download_tar"}}</a> <a class="item archive-link" href="{{$.RepoLink}}/archive/{{PathEscapeSegments $.RefName}}.tar.gz" rel="nofollow">{{svg "octicon-file-zip" 16 "mr-3"}}{{.i18n.Tr "repo.download_tar"}}</a>
<a class="item archive-link" href="{{$.RepoLink}}/archive/{{PathEscapeSegments $.RefName}}.bundle" rel="nofollow">{{svg "octicon-package" 16 "mr-3"}}{{.i18n.Tr "repo.download_bundle"}}</a> <a class="item archive-link" href="{{$.RepoLink}}/archive/{{PathEscapeSegments $.RefName}}.bundle" rel="nofollow">{{svg "octicon-package" 16 "mr-3"}}{{.i18n.Tr "repo.download_bundle"}}</a>
{{end}} {{end}}
<a class="item js-clone-url-vsc" href="vscode://vscode.git/clone?url={{.CloneButtonOriginLink.HTTPS}}">{{svg "gitea-vscode" 16 "mr-3"}}{{.i18n.Tr "repo.clone_in_vsc"}}</a> <a class="item" href="vscode://vscode.git/clone?url={{$.RepoCloneLink.HTTPS}}">{{svg "gitea-vscode" 16 "mr-3"}}{{.i18n.Tr "repo.clone_in_vsc"}}</a>
</div> </div>
</button> </button>
{{template "repo/clone_script" .}}{{/* the script will update `.js-clone-url` and related elements */}}
</div> </div>
{{end}} {{end}}
{{if and (ne $n 0) (not .IsViewFile) (not .IsBlame) }} {{if and (ne $n 0) (not .IsViewFile) (not .IsBlame) }}

View file

@ -77,12 +77,14 @@
<span class="ui green label">{{$.i18n.Tr "repo.release.stable"}}</span> <span class="ui green label">{{$.i18n.Tr "repo.release.stable"}}</span>
{{end}} {{end}}
<span class="tag text blue"> <span class="tag text blue">
<a class="df ac je" href="{{if not .Sha1}}#{{else}}{{$.RepoLink}}/src/tag/{{.TagName | PathEscapeSegments}}{{end}}" rel="nofollow">{{svg "octicon-tag" 16 "mr-2"}}{{.TagName}}</a> <a class="df ac je" href="{{if .IsDraft}}#{{else}}{{$.RepoLink}}/src/tag/{{.TagName | PathEscapeSegments}}{{end}}" rel="nofollow">{{svg "octicon-tag" 16 "mr-2"}}{{.TagName}}</a>
</span> </span>
{{if .Sha1}} {{if not .IsDraft}}
<span class="commit"> <span class="commit">
<a class="mono" href="{{$.RepoLink}}/src/commit/{{.Sha1}}" rel="nofollow">{{svg "octicon-git-commit" 16 "mr-2"}}{{ShortSha .Sha1}}</a> <a class="mono" href="{{$.RepoLink}}/src/commit/{{.Sha1}}" rel="nofollow">{{svg "octicon-git-commit" 16 "mr-2"}}{{ShortSha .Sha1}}</a>
</span> </span>
{{end}}
{{if .Sha1 }}
{{template "repo/branch_dropdown" dict "root" $ "release" .}} {{template "repo/branch_dropdown" dict "root" $ "release" .}}
{{end}} {{end}}
{{end}} {{end}}

View file

@ -12420,18 +12420,6 @@
"summary": "List the current user's tracked times", "summary": "List the current user's tracked times",
"operationId": "userCurrentTrackedTimes", "operationId": "userCurrentTrackedTimes",
"parameters": [ "parameters": [
{
"type": "integer",
"description": "page number of results to return (1-based)",
"name": "page",
"in": "query"
},
{
"type": "integer",
"description": "page size of results",
"name": "limit",
"in": "query"
},
{ {
"type": "string", "type": "string",
"format": "date-time", "format": "date-time",
@ -15631,6 +15619,7 @@
"$ref": "#/definitions/FileCommitResponse" "$ref": "#/definitions/FileCommitResponse"
}, },
"content": { "content": {
"type": "object",
"x-go-name": "Content" "x-go-name": "Content"
}, },
"verification": { "verification": {
@ -18672,6 +18661,7 @@
"x-go-name": "Ignored" "x-go-name": "Ignored"
}, },
"reason": { "reason": {
"type": "object",
"x-go-name": "Reason" "x-go-name": "Reason"
}, },
"repository_url": { "repository_url": {

View file

@ -33,7 +33,7 @@
</div> </div>
<div class="content"> <div class="content">
<strong>{{$provider}}</strong> <strong>{{$provider}}</strong>
{{if $loginSource.IsActive}}<span class="text red">{{$.i18n.Tr "repo.settings.active"}}</span>{{end}} {{if $loginSource.IsActive}}<span class="text red">{{$.i18n.Tr "settings.active"}}</span>{{end}}
</div> </div>
</div> </div>
{{end}} {{end}}

View file

@ -1,9 +0,0 @@
.container-labels {
td:nth-child(1) {
vertical-align: top;
}
td:nth-child(2) {
overflow-wrap: anywhere;
}
}

View file

@ -272,22 +272,13 @@ a.blob-excerpt:hover {
} }
.viewed-file-form { .viewed-file-form {
display: flex; margin: 0 3px;
align-items: center; padding: 0 3px;
border: 1px none; border-radius: 3px;
padding: 4px 8px;
margin: -8px 0; // just like other buttons in the diff box header
border-radius: .285rem; // just like .ui.tiny.button
font-size: .857rem; // just like .ui.tiny.button
}
.viewed-file-form input {
margin-right: 4px;
} }
.viewed-file-checked-form { .viewed-file-checked-form {
background-color: var(--color-primary-light-6); background-color: var(--color-primary-light-4);
border: 1px solid var(--color-primary-light-4);
} }
#viewed-files-summary { #viewed-files-summary {

View file

@ -34,6 +34,5 @@
@import "_admin"; @import "_admin";
@import "_explore"; @import "_explore";
@import "_review"; @import "_review";
@import "_package";
@import "./helpers.less"; @import "./helpers.less";