1
0
mirror of https://github.com/go-gitea/gitea.git synced 2024-12-04 14:46:57 -05:00

Merge branch 'main' into lunny/maven_deploy

This commit is contained in:
Lunny Xiao 2024-04-11 12:11:02 +08:00
commit 842d734265
75 changed files with 780 additions and 612 deletions

View File

@ -30,10 +30,6 @@ linters:
run: run:
timeout: 10m timeout: 10m
skip-dirs:
- node_modules
- public
- web_src
linters-settings: linters-settings:
stylecheck: stylecheck:
@ -94,6 +90,7 @@ linters-settings:
issues: issues:
max-issues-per-linter: 0 max-issues-per-linter: 0
max-same-issues: 0 max-same-issues: 0
exclude-dirs: [node_modules, public, web_src]
exclude-rules: exclude-rules:
# Exclude some linters from running on tests files. # Exclude some linters from running on tests files.
- path: _test\.go - path: _test\.go

View File

@ -28,7 +28,7 @@ XGO_VERSION := go-1.22.x
AIR_PACKAGE ?= github.com/cosmtrek/air@v1.49.0 AIR_PACKAGE ?= github.com/cosmtrek/air@v1.49.0
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/cmd/editorconfig-checker@2.7.0 EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/cmd/editorconfig-checker@2.7.0
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.6.0 GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.6.0
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.56.1 GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.57.2
GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11 GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11
MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.4.1 MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.4.1
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@db51e79a0e37c572d8b59ae0c58bf2bbbbe53285 SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@db51e79a0e37c572d8b59ae0c58bf2bbbbe53285

View File

@ -304,11 +304,6 @@
"path": "github.com/davecgh/go-spew/spew/LICENSE", "path": "github.com/davecgh/go-spew/spew/LICENSE",
"licenseText": "ISC License\n\nCopyright (c) 2012-2016 Dave Collins \u003cdave@davec.name\u003e\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted, provided that the above\ncopyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\nWITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\nANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\nWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\nACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\nOR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n" "licenseText": "ISC License\n\nCopyright (c) 2012-2016 Dave Collins \u003cdave@davec.name\u003e\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted, provided that the above\ncopyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\nWITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\nANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\nWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\nACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\nOR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n"
}, },
{
"name": "github.com/denisenkom/go-mssqldb",
"path": "github.com/denisenkom/go-mssqldb/LICENSE.txt",
"licenseText": "Copyright (c) 2012 The Go Authors. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n * Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n * Redistributions in binary form must reproduce the above\ncopyright notice, this list of conditions and the following disclaimer\nin the documentation and/or other materials provided with the\ndistribution.\n * Neither the name of Google Inc. nor the names of its\ncontributors may be used to endorse or promote products derived from\nthis software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
},
{ {
"name": "github.com/dgryski/go-rendezvous", "name": "github.com/dgryski/go-rendezvous",
"path": "github.com/dgryski/go-rendezvous/LICENSE", "path": "github.com/dgryski/go-rendezvous/LICENSE",
@ -759,6 +754,16 @@
"path": "github.com/microcosm-cc/bluemonday/LICENSE.md", "path": "github.com/microcosm-cc/bluemonday/LICENSE.md",
"licenseText": "SPDX short identifier: BSD-3-Clause\nhttps://opensource.org/licenses/BSD-3-Clause\n\nCopyright (c) 2014, David Kitchen \u003cdavid@buro9.com\u003e\n\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n this list of conditions and the following disclaimer in the documentation\n and/or other materials provided with the distribution.\n\n* Neither the name of the organisation (Microcosm) nor the names of its\n contributors may be used to endorse or promote products derived from\n this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" "licenseText": "SPDX short identifier: BSD-3-Clause\nhttps://opensource.org/licenses/BSD-3-Clause\n\nCopyright (c) 2014, David Kitchen \u003cdavid@buro9.com\u003e\n\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n this list of conditions and the following disclaimer in the documentation\n and/or other materials provided with the distribution.\n\n* Neither the name of the organisation (Microcosm) nor the names of its\n contributors may be used to endorse or promote products derived from\n this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
}, },
{
"name": "github.com/microsoft/go-mssqldb",
"path": "github.com/microsoft/go-mssqldb/LICENSE.txt",
"licenseText": "Copyright (c) 2012 The Go Authors. All rights reserved.\nCopyright (c) Microsoft Corporation.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n * Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n * Redistributions in binary form must reproduce the above\ncopyright notice, this list of conditions and the following disclaimer\nin the documentation and/or other materials provided with the\ndistribution.\n * Neither the name of Google Inc. nor the names of its\ncontributors may be used to endorse or promote products derived from\nthis software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
},
{
"name": "github.com/microsoft/go-mssqldb/internal/github.com/swisscom/mssql-always-encrypted/pkg",
"path": "github.com/microsoft/go-mssqldb/internal/github.com/swisscom/mssql-always-encrypted/pkg/LICENSE.txt",
"licenseText": "Copyright (c) 2021 Swisscom (Switzerland) Ltd\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n\n"
},
{ {
"name": "github.com/miekg/dns", "name": "github.com/miekg/dns",
"path": "github.com/miekg/dns/LICENSE", "path": "github.com/miekg/dns/LICENSE",

View File

@ -448,23 +448,26 @@ Gitea or set your environment appropriately.`, "")
func hookPrintResults(results []private.HookPostReceiveBranchResult) { func hookPrintResults(results []private.HookPostReceiveBranchResult) {
for _, res := range results { for _, res := range results {
if !res.Message { hookPrintResult(res.Message, res.Create, res.Branch, res.URL)
continue
}
fmt.Fprintln(os.Stderr, "")
if res.Create {
fmt.Fprintf(os.Stderr, "Create a new pull request for '%s':\n", res.Branch)
fmt.Fprintf(os.Stderr, " %s\n", res.URL)
} else {
fmt.Fprint(os.Stderr, "Visit the existing pull request:\n")
fmt.Fprintf(os.Stderr, " %s\n", res.URL)
}
fmt.Fprintln(os.Stderr, "")
os.Stderr.Sync()
} }
} }
func hookPrintResult(output, isCreate bool, branch, url string) {
if !output {
return
}
fmt.Fprintln(os.Stderr, "")
if isCreate {
fmt.Fprintf(os.Stderr, "Create a new pull request for '%s':\n", branch)
fmt.Fprintf(os.Stderr, " %s\n", url)
} else {
fmt.Fprint(os.Stderr, "Visit the existing pull request:\n")
fmt.Fprintf(os.Stderr, " %s\n", url)
}
fmt.Fprintln(os.Stderr, "")
os.Stderr.Sync()
}
func pushOptions() map[string]string { func pushOptions() map[string]string {
opts := make(map[string]string) opts := make(map[string]string)
if pushCount, err := strconv.Atoi(os.Getenv(private.GitPushOptionCount)); err == nil { if pushCount, err := strconv.Atoi(os.Getenv(private.GitPushOptionCount)); err == nil {
@ -691,6 +694,12 @@ Gitea or set your environment appropriately.`, "")
} }
err = writeFlushPktLine(ctx, os.Stdout) err = writeFlushPktLine(ctx, os.Stdout)
if err == nil {
for _, res := range resp.Results {
hookPrintResult(res.ShouldShowMessage, res.IsCreatePR, res.HeadBranch, res.URL)
}
}
return err return err
} }

View File

@ -303,34 +303,3 @@ sudo systemctl enable act_runner --now
``` ```
If using Docker, the `act_runner` user should also be added to the `docker` group before starting the service. Keep in mind that this effectively gives `act_runner` root access to the system [[1]](https://docs.docker.com/engine/security/#docker-daemon-attack-surface). If using Docker, the `act_runner` user should also be added to the `docker` group before starting the service. Keep in mind that this effectively gives `act_runner` root access to the system [[1]](https://docs.docker.com/engine/security/#docker-daemon-attack-surface).
## Configuration variable
You can create configuration variables on the user, organization and repository level.
The level of the variable depends on where you created it.
### Naming conventions
The following rules apply to variable names:
- Variable names can only contain alphanumeric characters (`[a-z]`, `[A-Z]`, `[0-9]`) or underscores (`_`). Spaces are not allowed.
- Variable names must not start with the `GITHUB_` and `GITEA_` prefix.
- Variable names must not start with a number.
- Variable names are case-insensitive.
- Variable names must be unique at the level they are created at.
- Variable names must not be `CI`.
### Using variable
After creating configuration variables, they will be automatically filled in the `vars` context.
They can be accessed through expressions like `{{ vars.VARIABLE_NAME }}` in the workflow.
### Precedence
If a variable with the same name exists at multiple levels, the variable at the lowest level takes precedence:
A repository variable will always be chosen over an organization/user variable.

View File

@ -258,32 +258,3 @@ Runner的标签用于确定Runner可以运行哪些Job以及如何运行它们
Runner将从Gitea实例获取Job并自动运行它们。 Runner将从Gitea实例获取Job并自动运行它们。
由于Act Runner仍处于开发中建议定期检查最新版本并进行升级。 由于Act Runner仍处于开发中建议定期检查最新版本并进行升级。
## 变量
您可以创建用户、组织和仓库级别的变量。变量的级别取决于创建它的位置。
### 命名规则
以下规则适用于变量名:
- 变量名称只能包含字母数字字符 (`[a-z]`, `[A-Z]`, `[0-9]`) 或下划线 (`_`)。不允许使用空格。
- 变量名称不能以 `GITHUB_``GITEA_` 前缀开头。
- 变量名称不能以数字开头。
- 变量名称不区分大小写。
- 变量名称在创建它们的级别上必须是唯一的。
- 变量名称不能为 “CI”。
### 使用
创建配置变量后,它们将自动填充到 `vars` 上下文中。您可以在工作流中使用类似 `{{ vars.VARIABLE_NAME }}` 这样的表达式来使用它们。
### 优先级
如果同名变量存在于多个级别,则级别最低的变量优先。
仓库级别的变量总是比组织或者用户级别的变量优先被选中。

View File

@ -104,7 +104,7 @@ However, if a job container tries to fetch code from localhost, it will fail bec
### Connection 3, act runner to internet ### Connection 3, act runner to internet
When you use some actions like `actions/checkout@v4`, the act runner downloads the scripts, not the job containers. When you use some actions like `actions/checkout@v4`, the act runner downloads the scripts, not the job containers.
By default, it downloads from [gitea.com](http://gitea.com/), so it requires access to the internet. By default, it downloads from [github.com](http://github.com/), so it requires access to the internet. If you configure the `DEFAULT_ACTIONS_URL` to `self`, then it will download from your Gitea instance by default. Then it will not connect to internet when downloading the action itself.
It also downloads some docker images from Docker Hub by default, which also requires internet access. It also downloads some docker images from Docker Hub by default, which also requires internet access.
However, internet access is not strictly necessary. However, internet access is not strictly necessary.

View File

@ -105,7 +105,8 @@ act runner 必须能够连接到Gitea以接收任务并发送执行结果回来
### 连接 3act runner到互联网 ### 连接 3act runner到互联网
当您使用诸如 `actions/checkout@v4` 的一些Actions时act runner下载的是脚本而不是Job容器。 当您使用诸如 `actions/checkout@v4` 的一些Actions时act runner下载的是脚本而不是Job容器。
默认情况下,它从[gitea.com](http://gitea.com/)下载,因此需要访问互联网。 默认情况下,它从[github.com](http://github.com/)下载,因此需要访问互联网。如果您设置的是 self
那么默认将从您的当前Gitea实例下载那么此步骤不需要连接到互联网。
它还默认从Docker Hub下载一些Docker镜像这也需要互联网访问。 它还默认从Docker Hub下载一些Docker镜像这也需要互联网访问。
然而,互联网访问并不是绝对必需的。 然而,互联网访问并不是绝对必需的。

View File

@ -0,0 +1,41 @@
---
date: "2024-04-10T22:21:00+08:00"
title: "Variables"
slug: "actions-variables"
sidebar_position: 25
draft: false
toc: false
menu:
sidebar:
parent: "actions"
name: "Variables"
sidebar_position: 25
identifier: "actions-variables"
---
## Variables
You can create configuration variables on the user, organization and repository level.
The level of the variable depends on where you created it. When creating a variable, the
key will be converted to uppercase. You need use uppercase on the yaml file.
### Naming conventions
The following rules apply to variable names:
- Variable names can only contain alphanumeric characters (`[a-z]`, `[A-Z]`, `[0-9]`) or underscores (`_`). Spaces are not allowed.
- Variable names must not start with the `GITHUB_` and `GITEA_` prefix.
- Variable names must not start with a number.
- Variable names are case-insensitive.
- Variable names must be unique at the level they are created at.
- Variable names must not be `CI`.
### Using variable
After creating configuration variables, they will be automatically filled in the `vars` context.
They can be accessed through expressions like `${{ vars.VARIABLE_NAME }}` in the workflow.
### Precedence
If a variable with the same name exists at multiple levels, the variable at the lowest level takes precedence:
A repository variable will always be chosen over an organization/user variable.

View File

@ -0,0 +1,39 @@
---
date: "2024-04-10T22:21:00+08:00"
title: "变量"
slug: "actions-variables"
sidebar_position: 25
draft: false
toc: false
menu:
sidebar:
parent: "actions"
name: "变量"
sidebar_position: 25
identifier: "actions-variables"
---
## 变量
您可以创建用户、组织和仓库级别的变量。变量的级别取决于创建它的位置。当创建变量时,变量的名称会被
转换为大写在yaml文件中引用时需要使用大写。
### 命名规则
以下规则适用于变量名:
- 变量名称只能包含字母数字字符 (`[a-z]`, `[A-Z]`, `[0-9]`) 或下划线 (`_`)。不允许使用空格。
- 变量名称不能以 `GITHUB_``GITEA_` 前缀开头。
- 变量名称不能以数字开头。
- 变量名称不区分大小写。
- 变量名称在创建它们的级别上必须是唯一的。
- 变量名称不能为 `CI`
### 使用
创建配置变量后,它们将自动填充到 `vars` 上下文中。您可以在工作流中使用类似 `${{ vars.VARIABLE_NAME }}` 这样的表达式来使用它们。
### 优先级
如果同名变量存在于多个级别,则级别最低的变量优先。
仓库级别的变量总是比组织或者用户级别的变量优先被选中。

2
go.mod
View File

@ -24,7 +24,6 @@ require (
github.com/buildkite/terminal-to-html/v3 v3.11.0 github.com/buildkite/terminal-to-html/v3 v3.11.0
github.com/caddyserver/certmagic v0.20.0 github.com/caddyserver/certmagic v0.20.0
github.com/chi-middleware/proxy v1.1.1 github.com/chi-middleware/proxy v1.1.1
github.com/denisenkom/go-mssqldb v0.12.3
github.com/dimiro1/reply v0.0.0-20200315094148-d0136a4c9e21 github.com/dimiro1/reply v0.0.0-20200315094148-d0136a4c9e21
github.com/djherbis/buffer v1.2.0 github.com/djherbis/buffer v1.2.0
github.com/djherbis/nio/v3 v3.0.1 github.com/djherbis/nio/v3 v3.0.1
@ -77,6 +76,7 @@ require (
github.com/meilisearch/meilisearch-go v0.26.2 github.com/meilisearch/meilisearch-go v0.26.2
github.com/mholt/archiver/v3 v3.5.1 github.com/mholt/archiver/v3 v3.5.1
github.com/microcosm-cc/bluemonday v1.0.26 github.com/microcosm-cc/bluemonday v1.0.26
github.com/microsoft/go-mssqldb v1.7.0
github.com/minio/minio-go/v7 v7.0.69 github.com/minio/minio-go/v7 v7.0.69
github.com/msteinert/pam v1.2.0 github.com/msteinert/pam v1.2.0
github.com/nektos/act v0.2.52 github.com/nektos/act v0.2.52

28
go.sum
View File

@ -38,11 +38,20 @@ github.com/42wim/sshsig v0.0.0-20211121163825-841cf5bbc121 h1:r3qt8PCHnfjOv9PN3H
github.com/42wim/sshsig v0.0.0-20211121163825-841cf5bbc121/go.mod h1:Ock8XgA7pvULhIaHGAk/cDnRfNrF9Jey81nPcc403iU= github.com/42wim/sshsig v0.0.0-20211121163825-841cf5bbc121/go.mod h1:Ock8XgA7pvULhIaHGAk/cDnRfNrF9Jey81nPcc403iU=
github.com/6543/go-version v1.3.1 h1:HvOp+Telns7HWJ2Xo/05YXQSB2bE0WmVgbHqwMPZT4U= github.com/6543/go-version v1.3.1 h1:HvOp+Telns7HWJ2Xo/05YXQSB2bE0WmVgbHqwMPZT4U=
github.com/6543/go-version v1.3.1/go.mod h1:oqFAHCwtLVUTLdhQmVZWYvaHXTdsbB4SY85at64SQEo= github.com/6543/go-version v1.3.1/go.mod h1:oqFAHCwtLVUTLdhQmVZWYvaHXTdsbB4SY85at64SQEo=
github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1 h1:lGlwhPtrX6EVml1hO0ivjkUxsSyl4dsiw9qcA1k/3IQ=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1/go.mod h1:RKUqNu35KJYcVG/fqTRqmuXJZYNhYkBrnC/hX7yGbTA=
github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1 h1:sO0/P7g68FrryJzljemN+6GTssUXdANk6aJ7T1ZxnsQ=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1/go.mod h1:h8hyGFDsU5HMivxiS2iYFZsgDbU9OnnJ163x5UGVKYo=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1 h1:6oNBlSdi1QqM1PNW7FPA6xOGA5UNsXnkaYZz9vdPGhA=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1/go.mod h1:s4kgfzA0covAXNicZHDMN58jExvcng2mC/DepXiF1EI=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.1 h1:MyVTgWR8qd/Jw1Le0NZebGBUCLbtak3bJ3z1OlqZBpw=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.1/go.mod h1:GpPjLhVR9dnUoJMyHWSPy71xY9/lcmpzIPZXmF0FCVY=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0 h1:D3occbWoio4EBLkbkevetNMAVX197GkzbUMtqjGWn80=
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0/go.mod h1:bTSOgj05NGRuHHhQwAdPnYr9TOdNmKlZTgGLL6nyAdI=
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8= github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8=
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1 h1:DzHpqpoJVaCgOUdVHxE8QB52S6NiVdDQvGlny1qvPqA=
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/ClickHouse/ch-go v0.61.5 h1:zwR8QbYI0tsMiEcze/uIMK+Tz1D3XZXLdNrlaOpeEI4= github.com/ClickHouse/ch-go v0.61.5 h1:zwR8QbYI0tsMiEcze/uIMK+Tz1D3XZXLdNrlaOpeEI4=
github.com/ClickHouse/ch-go v0.61.5/go.mod h1:s1LJW/F/LcFs5HJnuogFMta50kKDO0lf9zzfrbl0RQg= github.com/ClickHouse/ch-go v0.61.5/go.mod h1:s1LJW/F/LcFs5HJnuogFMta50kKDO0lf9zzfrbl0RQg=
@ -220,7 +229,6 @@ github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55k
github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY= github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY=
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s= github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s=
github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
@ -355,7 +363,6 @@ github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOW
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA= github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
@ -513,6 +520,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs= github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
@ -551,6 +560,8 @@ github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Cl
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.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58=
github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs=
github.com/microsoft/go-mssqldb v1.7.0 h1:sgMPW0HA6Ihd37Yx0MzHyKD726C2kY/8KJsQtXHNaAs=
github.com/microsoft/go-mssqldb v1.7.0/go.mod h1:kOvZKUdrhhFQmxLZqbwUV0rHkNkZpthMITIb2Ko1IoA=
github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4= github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4=
github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY= github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY=
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
@ -574,7 +585,6 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
github.com/mrjones/oauth v0.0.0-20190623134757-126b35219450 h1:j2kD3MT1z4PXCiUllUJF9mWUESr9TWKS7iEKsQ/IipM= github.com/mrjones/oauth v0.0.0-20190623134757-126b35219450 h1:j2kD3MT1z4PXCiUllUJF9mWUESr9TWKS7iEKsQ/IipM=
github.com/mrjones/oauth v0.0.0-20190623134757-126b35219450/go.mod h1:skjdDftzkFALcuGzYSklqYd8gvat6F1gZJ4YPVbkZpM= github.com/mrjones/oauth v0.0.0-20190623134757-126b35219450/go.mod h1:skjdDftzkFALcuGzYSklqYd8gvat6F1gZJ4YPVbkZpM=
@ -627,7 +637,8 @@ github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ
github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4=
github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI=
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@ -836,7 +847,6 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
@ -871,7 +881,6 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/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-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
@ -1022,7 +1031,6 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI= lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI=

View File

@ -16,14 +16,9 @@ import (
type ActionJobList []*ActionRunJob type ActionJobList []*ActionRunJob
func (jobs ActionJobList) GetRunIDs() []int64 { func (jobs ActionJobList) GetRunIDs() []int64 {
ids := make(container.Set[int64], len(jobs)) return container.FilterSlice(jobs, func(j *ActionRunJob) (int64, bool) {
for _, j := range jobs { return j.RunID, j.RunID != 0
if j.RunID == 0 { })
continue
}
ids.Add(j.RunID)
}
return ids.Values()
} }
func (jobs ActionJobList) LoadRuns(ctx context.Context, withRepo bool) error { func (jobs ActionJobList) LoadRuns(ctx context.Context, withRepo bool) error {

View File

@ -19,19 +19,15 @@ type RunList []*ActionRun
// GetUserIDs returns a slice of user's id // GetUserIDs returns a slice of user's id
func (runs RunList) GetUserIDs() []int64 { func (runs RunList) GetUserIDs() []int64 {
ids := make(container.Set[int64], len(runs)) return container.FilterSlice(runs, func(run *ActionRun) (int64, bool) {
for _, run := range runs { return run.TriggerUserID, true
ids.Add(run.TriggerUserID) })
}
return ids.Values()
} }
func (runs RunList) GetRepoIDs() []int64 { func (runs RunList) GetRepoIDs() []int64 {
ids := make(container.Set[int64], len(runs)) return container.FilterSlice(runs, func(run *ActionRun) (int64, bool) {
for _, run := range runs { return run.RepoID, true
ids.Add(run.RepoID) })
}
return ids.Values()
} }
func (runs RunList) LoadTriggerUser(ctx context.Context) error { func (runs RunList) LoadTriggerUser(ctx context.Context) error {

View File

@ -16,14 +16,9 @@ type RunnerList []*ActionRunner
// GetUserIDs returns a slice of user's id // GetUserIDs returns a slice of user's id
func (runners RunnerList) GetUserIDs() []int64 { func (runners RunnerList) GetUserIDs() []int64 {
ids := make(container.Set[int64], len(runners)) return container.FilterSlice(runners, func(runner *ActionRunner) (int64, bool) {
for _, runner := range runners { return runner.OwnerID, runner.OwnerID != 0
if runner.OwnerID == 0 { })
continue
}
ids.Add(runner.OwnerID)
}
return ids.Values()
} }
func (runners RunnerList) LoadOwners(ctx context.Context) error { func (runners RunnerList) LoadOwners(ctx context.Context) error {
@ -41,16 +36,9 @@ func (runners RunnerList) LoadOwners(ctx context.Context) error {
} }
func (runners RunnerList) getRepoIDs() []int64 { func (runners RunnerList) getRepoIDs() []int64 {
repoIDs := make(container.Set[int64], len(runners)) return container.FilterSlice(runners, func(runner *ActionRunner) (int64, bool) {
for _, runner := range runners { return runner.RepoID, runner.RepoID > 0
if runner.RepoID == 0 { })
continue
}
if _, ok := repoIDs[runner.RepoID]; !ok {
repoIDs[runner.RepoID] = struct{}{}
}
}
return repoIDs.Values()
} }
func (runners RunnerList) LoadRepos(ctx context.Context) error { func (runners RunnerList) LoadRepos(ctx context.Context) error {

View File

@ -18,19 +18,15 @@ type ScheduleList []*ActionSchedule
// GetUserIDs returns a slice of user's id // GetUserIDs returns a slice of user's id
func (schedules ScheduleList) GetUserIDs() []int64 { func (schedules ScheduleList) GetUserIDs() []int64 {
ids := make(container.Set[int64], len(schedules)) return container.FilterSlice(schedules, func(schedule *ActionSchedule) (int64, bool) {
for _, schedule := range schedules { return schedule.TriggerUserID, true
ids.Add(schedule.TriggerUserID) })
}
return ids.Values()
} }
func (schedules ScheduleList) GetRepoIDs() []int64 { func (schedules ScheduleList) GetRepoIDs() []int64 {
ids := make(container.Set[int64], len(schedules)) return container.FilterSlice(schedules, func(schedule *ActionSchedule) (int64, bool) {
for _, schedule := range schedules { return schedule.RepoID, true
ids.Add(schedule.RepoID) })
}
return ids.Values()
} }
func (schedules ScheduleList) LoadTriggerUser(ctx context.Context) error { func (schedules ScheduleList) LoadTriggerUser(ctx context.Context) error {

View File

@ -16,11 +16,9 @@ import (
type SpecList []*ActionScheduleSpec type SpecList []*ActionScheduleSpec
func (specs SpecList) GetScheduleIDs() []int64 { func (specs SpecList) GetScheduleIDs() []int64 {
ids := make(container.Set[int64], len(specs)) return container.FilterSlice(specs, func(spec *ActionScheduleSpec) (int64, bool) {
for _, spec := range specs { return spec.ScheduleID, true
ids.Add(spec.ScheduleID) })
}
return ids.Values()
} }
func (specs SpecList) LoadSchedules(ctx context.Context) error { func (specs SpecList) LoadSchedules(ctx context.Context) error {
@ -46,11 +44,9 @@ func (specs SpecList) LoadSchedules(ctx context.Context) error {
} }
func (specs SpecList) GetRepoIDs() []int64 { func (specs SpecList) GetRepoIDs() []int64 {
ids := make(container.Set[int64], len(specs)) return container.FilterSlice(specs, func(spec *ActionScheduleSpec) (int64, bool) {
for _, spec := range specs { return spec.RepoID, true
ids.Add(spec.RepoID) })
}
return ids.Values()
} }
func (specs SpecList) LoadRepos(ctx context.Context) error { func (specs SpecList) LoadRepos(ctx context.Context) error {

View File

@ -11,6 +11,7 @@ import (
auth_model "code.gitea.io/gitea/models/auth" auth_model "code.gitea.io/gitea/models/auth"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/models/unit"
"code.gitea.io/gitea/modules/container" "code.gitea.io/gitea/modules/container"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
@ -227,7 +228,9 @@ func CreateTaskForRunner(ctx context.Context, runner *ActionRunner) (*ActionTask
if runner.RepoID != 0 { if runner.RepoID != 0 {
jobCond = builder.Eq{"repo_id": runner.RepoID} jobCond = builder.Eq{"repo_id": runner.RepoID}
} else if runner.OwnerID != 0 { } else if runner.OwnerID != 0 {
jobCond = builder.In("repo_id", builder.Select("id").From("repository").Where(builder.Eq{"owner_id": runner.OwnerID})) jobCond = builder.In("repo_id", builder.Select("`repository`.id").From("repository").
Join("INNER", "repo_unit", "`repository`.id = `repo_unit`.repo_id").
Where(builder.Eq{"`repository`.owner_id": runner.OwnerID, "`repo_unit`.type": unit.TypeActions}))
} }
if jobCond.IsValid() { if jobCond.IsValid() {
jobCond = builder.In("run_id", builder.Select("id").From("action_run").Where(jobCond)) jobCond = builder.In("run_id", builder.Select("id").From("action_run").Where(jobCond))

View File

@ -16,14 +16,9 @@ import (
type TaskList []*ActionTask type TaskList []*ActionTask
func (tasks TaskList) GetJobIDs() []int64 { func (tasks TaskList) GetJobIDs() []int64 {
ids := make(container.Set[int64], len(tasks)) return container.FilterSlice(tasks, func(t *ActionTask) (int64, bool) {
for _, t := range tasks { return t.JobID, t.JobID != 0
if t.JobID == 0 { })
continue
}
ids.Add(t.JobID)
}
return ids.Values()
} }
func (tasks TaskList) LoadJobs(ctx context.Context) error { func (tasks TaskList) LoadJobs(ctx context.Context) error {

View File

@ -22,11 +22,9 @@ import (
type ActionList []*Action type ActionList []*Action
func (actions ActionList) getUserIDs() []int64 { func (actions ActionList) getUserIDs() []int64 {
userIDs := make(container.Set[int64], len(actions)) return container.FilterSlice(actions, func(action *Action) (int64, bool) {
for _, action := range actions { return action.ActUserID, true
userIDs.Add(action.ActUserID) })
}
return userIDs.Values()
} }
func (actions ActionList) LoadActUsers(ctx context.Context) (map[int64]*user_model.User, error) { func (actions ActionList) LoadActUsers(ctx context.Context) (map[int64]*user_model.User, error) {
@ -50,11 +48,9 @@ func (actions ActionList) LoadActUsers(ctx context.Context) (map[int64]*user_mod
} }
func (actions ActionList) getRepoIDs() []int64 { func (actions ActionList) getRepoIDs() []int64 {
repoIDs := make(container.Set[int64], len(actions)) return container.FilterSlice(actions, func(action *Action) (int64, bool) {
for _, action := range actions { return action.RepoID, true
repoIDs.Add(action.RepoID) })
}
return repoIDs.Values()
} }
func (actions ActionList) LoadRepositories(ctx context.Context) error { func (actions ActionList) LoadRepositories(ctx context.Context) error {
@ -80,18 +76,16 @@ func (actions ActionList) loadRepoOwner(ctx context.Context, userMap map[int64]*
userMap = make(map[int64]*user_model.User) userMap = make(map[int64]*user_model.User)
} }
userSet := make(container.Set[int64], len(actions)) missingUserIDs := container.FilterSlice(actions, func(action *Action) (int64, bool) {
for _, action := range actions {
if action.Repo == nil { if action.Repo == nil {
continue return 0, false
} }
if _, ok := userMap[action.Repo.OwnerID]; !ok { _, alreadyLoaded := userMap[action.Repo.OwnerID]
userSet.Add(action.Repo.OwnerID) return action.Repo.OwnerID, !alreadyLoaded
} })
}
if err := db.GetEngine(ctx). if err := db.GetEngine(ctx).
In("id", userSet.Values()). In("id", missingUserIDs).
Find(&userMap); err != nil { Find(&userMap); err != nil {
return fmt.Errorf("find user: %w", err) return fmt.Errorf("find user: %w", err)
} }

View File

@ -190,14 +190,12 @@ func (nl NotificationList) LoadAttributes(ctx context.Context) error {
} }
func (nl NotificationList) getPendingRepoIDs() []int64 { func (nl NotificationList) getPendingRepoIDs() []int64 {
ids := make(container.Set[int64], len(nl)) return container.FilterSlice(nl, func(n *Notification) (int64, bool) {
for _, notification := range nl { if n.Repository != nil {
if notification.Repository != nil { return 0, false
continue
} }
ids.Add(notification.RepoID) return n.RepoID, true
} })
return ids.Values()
} }
// LoadRepos loads repositories from database // LoadRepos loads repositories from database

View File

@ -21,9 +21,9 @@ import (
"xorm.io/xorm/names" "xorm.io/xorm/names"
"xorm.io/xorm/schemas" "xorm.io/xorm/schemas"
_ "github.com/denisenkom/go-mssqldb" // Needed for the MSSQL driver _ "github.com/go-sql-driver/mysql" // Needed for the MySQL driver
_ "github.com/go-sql-driver/mysql" // Needed for the MySQL driver _ "github.com/lib/pq" // Needed for the Postgresql driver
_ "github.com/lib/pq" // Needed for the Postgresql driver _ "github.com/microsoft/go-mssqldb" // Needed for the MSSQL driver
) )
var ( var (

View File

@ -17,15 +17,12 @@ import (
type BranchList []*Branch type BranchList []*Branch
func (branches BranchList) LoadDeletedBy(ctx context.Context) error { func (branches BranchList) LoadDeletedBy(ctx context.Context) error {
ids := container.Set[int64]{} ids := container.FilterSlice(branches, func(branch *Branch) (int64, bool) {
for _, branch := range branches { return branch.DeletedByID, branch.IsDeleted
if !branch.IsDeleted { })
continue
}
ids.Add(branch.DeletedByID)
}
usersMap := make(map[int64]*user_model.User, len(ids)) usersMap := make(map[int64]*user_model.User, len(ids))
if err := db.GetEngine(ctx).In("id", ids.Values()).Find(&usersMap); err != nil { if err := db.GetEngine(ctx).In("id", ids).Find(&usersMap); err != nil {
return err return err
} }
for _, branch := range branches { for _, branch := range branches {
@ -41,14 +38,13 @@ func (branches BranchList) LoadDeletedBy(ctx context.Context) error {
} }
func (branches BranchList) LoadPusher(ctx context.Context) error { func (branches BranchList) LoadPusher(ctx context.Context) error {
ids := container.Set[int64]{} ids := container.FilterSlice(branches, func(branch *Branch) (int64, bool) {
for _, branch := range branches { // pusher_id maybe zero because some branches are sync by backend with no pusher
if branch.PusherID > 0 { // pusher_id maybe zero because some branches are sync by backend with no pusher return branch.PusherID, branch.PusherID > 0
ids.Add(branch.PusherID) })
}
}
usersMap := make(map[int64]*user_model.User, len(ids)) usersMap := make(map[int64]*user_model.User, len(ids))
if err := db.GetEngine(ctx).In("id", ids.Values()).Find(&usersMap); err != nil { if err := db.GetEngine(ctx).In("id", ids).Find(&usersMap); err != nil {
return err return err
} }
for _, branch := range branches { for _, branch := range branches {

View File

@ -1272,10 +1272,9 @@ func InsertIssueComments(ctx context.Context, comments []*Comment) error {
return nil return nil
} }
issueIDs := make(container.Set[int64]) issueIDs := container.FilterSlice(comments, func(comment *Comment) (int64, bool) {
for _, comment := range comments { return comment.IssueID, true
issueIDs.Add(comment.IssueID) })
}
ctx, committer, err := db.TxContext(ctx) ctx, committer, err := db.TxContext(ctx)
if err != nil { if err != nil {
@ -1298,7 +1297,7 @@ func InsertIssueComments(ctx context.Context, comments []*Comment) error {
} }
} }
for issueID := range issueIDs { for _, issueID := range issueIDs {
if _, err := db.Exec(ctx, "UPDATE issue set num_comments = (SELECT count(*) FROM comment WHERE issue_id = ? AND `type`=?) WHERE id = ?", if _, err := db.Exec(ctx, "UPDATE issue set num_comments = (SELECT count(*) FROM comment WHERE issue_id = ? AND `type`=?) WHERE id = ?",
issueID, CommentTypeComment, issueID); err != nil { issueID, CommentTypeComment, issueID); err != nil {
return err return err

View File

@ -17,13 +17,9 @@ import (
type CommentList []*Comment type CommentList []*Comment
func (comments CommentList) getPosterIDs() []int64 { func (comments CommentList) getPosterIDs() []int64 {
posterIDs := make(container.Set[int64], len(comments)) return container.FilterSlice(comments, func(c *Comment) (int64, bool) {
for _, comment := range comments { return c.PosterID, c.PosterID > 0
if comment.PosterID > 0 { })
posterIDs.Add(comment.PosterID)
}
}
return posterIDs.Values()
} }
// LoadPosters loads posters // LoadPosters loads posters
@ -44,13 +40,9 @@ func (comments CommentList) LoadPosters(ctx context.Context) error {
} }
func (comments CommentList) getLabelIDs() []int64 { func (comments CommentList) getLabelIDs() []int64 {
ids := make(container.Set[int64], len(comments)) return container.FilterSlice(comments, func(comment *Comment) (int64, bool) {
for _, comment := range comments { return comment.LabelID, comment.LabelID > 0
if comment.LabelID > 0 { })
ids.Add(comment.LabelID)
}
}
return ids.Values()
} }
func (comments CommentList) loadLabels(ctx context.Context) error { func (comments CommentList) loadLabels(ctx context.Context) error {
@ -94,13 +86,9 @@ func (comments CommentList) loadLabels(ctx context.Context) error {
} }
func (comments CommentList) getMilestoneIDs() []int64 { func (comments CommentList) getMilestoneIDs() []int64 {
ids := make(container.Set[int64], len(comments)) return container.FilterSlice(comments, func(comment *Comment) (int64, bool) {
for _, comment := range comments { return comment.MilestoneID, comment.MilestoneID > 0
if comment.MilestoneID > 0 { })
ids.Add(comment.MilestoneID)
}
}
return ids.Values()
} }
func (comments CommentList) loadMilestones(ctx context.Context) error { func (comments CommentList) loadMilestones(ctx context.Context) error {
@ -137,13 +125,9 @@ func (comments CommentList) loadMilestones(ctx context.Context) error {
} }
func (comments CommentList) getOldMilestoneIDs() []int64 { func (comments CommentList) getOldMilestoneIDs() []int64 {
ids := make(container.Set[int64], len(comments)) return container.FilterSlice(comments, func(comment *Comment) (int64, bool) {
for _, comment := range comments { return comment.OldMilestoneID, comment.OldMilestoneID > 0
if comment.OldMilestoneID > 0 { })
ids.Add(comment.OldMilestoneID)
}
}
return ids.Values()
} }
func (comments CommentList) loadOldMilestones(ctx context.Context) error { func (comments CommentList) loadOldMilestones(ctx context.Context) error {
@ -180,13 +164,9 @@ func (comments CommentList) loadOldMilestones(ctx context.Context) error {
} }
func (comments CommentList) getAssigneeIDs() []int64 { func (comments CommentList) getAssigneeIDs() []int64 {
ids := make(container.Set[int64], len(comments)) return container.FilterSlice(comments, func(comment *Comment) (int64, bool) {
for _, comment := range comments { return comment.AssigneeID, comment.AssigneeID > 0
if comment.AssigneeID > 0 { })
ids.Add(comment.AssigneeID)
}
}
return ids.Values()
} }
func (comments CommentList) loadAssignees(ctx context.Context) error { func (comments CommentList) loadAssignees(ctx context.Context) error {
@ -237,14 +217,9 @@ func (comments CommentList) loadAssignees(ctx context.Context) error {
// getIssueIDs returns all the issue ids on this comment list which issue hasn't been loaded // getIssueIDs returns all the issue ids on this comment list which issue hasn't been loaded
func (comments CommentList) getIssueIDs() []int64 { func (comments CommentList) getIssueIDs() []int64 {
ids := make(container.Set[int64], len(comments)) return container.FilterSlice(comments, func(comment *Comment) (int64, bool) {
for _, comment := range comments { return comment.IssueID, comment.Issue == nil
if comment.Issue != nil { })
continue
}
ids.Add(comment.IssueID)
}
return ids.Values()
} }
// Issues returns all the issues of comments // Issues returns all the issues of comments
@ -311,16 +286,12 @@ func (comments CommentList) LoadIssues(ctx context.Context) error {
} }
func (comments CommentList) getDependentIssueIDs() []int64 { func (comments CommentList) getDependentIssueIDs() []int64 {
ids := make(container.Set[int64], len(comments)) return container.FilterSlice(comments, func(comment *Comment) (int64, bool) {
for _, comment := range comments {
if comment.DependentIssue != nil { if comment.DependentIssue != nil {
continue return 0, false
} }
if comment.DependentIssueID > 0 { return comment.DependentIssueID, comment.DependentIssueID > 0
ids.Add(comment.DependentIssueID) })
}
}
return ids.Values()
} }
func (comments CommentList) loadDependentIssues(ctx context.Context) error { func (comments CommentList) loadDependentIssues(ctx context.Context) error {
@ -375,15 +346,9 @@ func (comments CommentList) loadDependentIssues(ctx context.Context) error {
// getAttachmentCommentIDs only return the comment ids which possibly has attachments // getAttachmentCommentIDs only return the comment ids which possibly has attachments
func (comments CommentList) getAttachmentCommentIDs() []int64 { func (comments CommentList) getAttachmentCommentIDs() []int64 {
ids := make(container.Set[int64], len(comments)) return container.FilterSlice(comments, func(comment *Comment) (int64, bool) {
for _, comment := range comments { return comment.ID, comment.Type.HasAttachmentSupport()
if comment.Type == CommentTypeComment || })
comment.Type == CommentTypeReview ||
comment.Type == CommentTypeCode {
ids.Add(comment.ID)
}
}
return ids.Values()
} }
// LoadAttachmentsByIssue loads attachments by issue id // LoadAttachmentsByIssue loads attachments by issue id
@ -451,13 +416,9 @@ func (comments CommentList) LoadAttachments(ctx context.Context) (err error) {
} }
func (comments CommentList) getReviewIDs() []int64 { func (comments CommentList) getReviewIDs() []int64 {
ids := make(container.Set[int64], len(comments)) return container.FilterSlice(comments, func(comment *Comment) (int64, bool) {
for _, comment := range comments { return comment.ReviewID, comment.ReviewID > 0
if comment.ReviewID > 0 { })
ids.Add(comment.ReviewID)
}
}
return ids.Values()
} }
func (comments CommentList) loadReviews(ctx context.Context) error { func (comments CommentList) loadReviews(ctx context.Context) error {

View File

@ -21,16 +21,15 @@ type IssueList []*Issue
// get the repo IDs to be loaded later, these IDs are for issue.Repo and issue.PullRequest.HeadRepo // get the repo IDs to be loaded later, these IDs are for issue.Repo and issue.PullRequest.HeadRepo
func (issues IssueList) getRepoIDs() []int64 { func (issues IssueList) getRepoIDs() []int64 {
repoIDs := make(container.Set[int64], len(issues)) return container.FilterSlice(issues, func(issue *Issue) (int64, bool) {
for _, issue := range issues {
if issue.Repo == nil { if issue.Repo == nil {
repoIDs.Add(issue.RepoID) return issue.RepoID, true
} }
if issue.PullRequest != nil && issue.PullRequest.HeadRepo == nil { if issue.PullRequest != nil && issue.PullRequest.HeadRepo == nil {
repoIDs.Add(issue.PullRequest.HeadRepoID) return issue.PullRequest.HeadRepoID, true
} }
} return 0, false
return repoIDs.Values() })
} }
// LoadRepositories loads issues' all repositories // LoadRepositories loads issues' all repositories
@ -74,11 +73,9 @@ func (issues IssueList) LoadRepositories(ctx context.Context) (repo_model.Reposi
} }
func (issues IssueList) getPosterIDs() []int64 { func (issues IssueList) getPosterIDs() []int64 {
posterIDs := make(container.Set[int64], len(issues)) return container.FilterSlice(issues, func(issue *Issue) (int64, bool) {
for _, issue := range issues { return issue.PosterID, true
posterIDs.Add(issue.PosterID) })
}
return posterIDs.Values()
} }
func (issues IssueList) loadPosters(ctx context.Context) error { func (issues IssueList) loadPosters(ctx context.Context) error {
@ -193,11 +190,9 @@ func (issues IssueList) loadLabels(ctx context.Context) error {
} }
func (issues IssueList) getMilestoneIDs() []int64 { func (issues IssueList) getMilestoneIDs() []int64 {
ids := make(container.Set[int64], len(issues)) return container.FilterSlice(issues, func(issue *Issue) (int64, bool) {
for _, issue := range issues { return issue.MilestoneID, true
ids.Add(issue.MilestoneID) })
}
return ids.Values()
} }
func (issues IssueList) loadMilestones(ctx context.Context) error { func (issues IssueList) loadMilestones(ctx context.Context) error {

View File

@ -305,14 +305,12 @@ func (list ReactionList) GroupByType() map[string]ReactionList {
} }
func (list ReactionList) getUserIDs() []int64 { func (list ReactionList) getUserIDs() []int64 {
userIDs := make(container.Set[int64], len(list)) return container.FilterSlice(list, func(reaction *Reaction) (int64, bool) {
for _, reaction := range list {
if reaction.OriginalAuthor != "" { if reaction.OriginalAuthor != "" {
continue return 0, false
} }
userIDs.Add(reaction.UserID) return reaction.UserID, true
} })
return userIDs.Values()
} }
func valuesUser(m map[int64]*user_model.User) []*user_model.User { func valuesUser(m map[int64]*user_model.User) []*user_model.User {

View File

@ -38,12 +38,11 @@ func (reviews ReviewList) LoadReviewers(ctx context.Context) error {
} }
func (reviews ReviewList) LoadIssues(ctx context.Context) error { func (reviews ReviewList) LoadIssues(ctx context.Context) error {
issueIDs := container.Set[int64]{} issueIDs := container.FilterSlice(reviews, func(review *Review) (int64, bool) {
for i := 0; i < len(reviews); i++ { return review.IssueID, true
issueIDs.Add(reviews[i].IssueID) })
}
issues, err := GetIssuesByIDs(ctx, issueIDs.Values()) issues, err := GetIssuesByIDs(ctx, issueIDs)
if err != nil { if err != nil {
return err return err
} }

View File

@ -104,18 +104,19 @@ func (repos RepositoryList) LoadAttributes(ctx context.Context) error {
return nil return nil
} }
set := make(container.Set[int64]) userIDs := container.FilterSlice(repos, func(repo *Repository) (int64, bool) {
return repo.OwnerID, true
})
repoIDs := make([]int64, len(repos)) repoIDs := make([]int64, len(repos))
for i := range repos { for i := range repos {
set.Add(repos[i].OwnerID)
repoIDs[i] = repos[i].ID repoIDs[i] = repos[i].ID
} }
// Load owners. // Load owners.
users := make(map[int64]*user_model.User, len(set)) users := make(map[int64]*user_model.User, len(userIDs))
if err := db.GetEngine(ctx). if err := db.GetEngine(ctx).
Where("id > 0"). Where("id > 0").
In("id", set.Values()). In("id", userIDs).
Find(&users); err != nil { Find(&users); err != nil {
return fmt.Errorf("find users: %w", err) return fmt.Errorf("find users: %w", err)
} }

View File

@ -0,0 +1,21 @@
// Copyright 2024 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package container
import "slices"
// FilterSlice ranges over the slice and calls include() for each element.
// If the second returned value is true, the first returned value will be included in the resulting
// slice (after deduplication).
func FilterSlice[E any, T comparable](s []E, include func(E) (T, bool)) []T {
filtered := make([]T, 0, len(s)) // slice will be clipped before returning
seen := make(map[T]bool, len(s))
for i := range s {
if v, ok := include(s[i]); ok && !seen[v] {
filtered = append(filtered, v)
seen[v] = true
}
}
return slices.Clip(filtered)
}

View File

@ -0,0 +1,28 @@
// Copyright 2024 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package container
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestFilterMapUnique(t *testing.T) {
result := FilterSlice([]int{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
}, func(i int) (int, bool) {
switch i {
case 0:
return 0, true // included later
case 1:
return 0, true // duplicate of previous (should be ignored)
case 2:
return 2, false // not included
default:
return i, true
}
})
assert.Equal(t, []int{0, 3, 4, 5, 6, 7, 8, 9}, result)
}

View File

@ -709,7 +709,8 @@ func shortLinkProcessor(ctx *RenderContext, node *html.Node) {
name += tail name += tail
image := false image := false
switch ext := filepath.Ext(link); ext { ext := filepath.Ext(link)
switch ext {
// fast path: empty string, ignore // fast path: empty string, ignore
case "": case "":
// leave image as false // leave image as false
@ -767,11 +768,26 @@ func shortLinkProcessor(ctx *RenderContext, node *html.Node) {
} }
} else { } else {
if !absoluteLink { if !absoluteLink {
var base string
if ctx.IsWiki { if ctx.IsWiki {
link = util.URLJoin(ctx.Links.WikiLink(), link) switch ext {
case "":
// no file extension, create a regular wiki link
base = ctx.Links.WikiLink()
default:
// we have a file extension:
// return a regular wiki link if it's a renderable file (extension),
// raw link otherwise
if Type(link) != "" {
base = ctx.Links.WikiLink()
} else {
base = ctx.Links.WikiRawLink()
}
}
} else { } else {
link = util.URLJoin(ctx.Links.SrcLink(), link) base = ctx.Links.SrcLink()
} }
link = util.URLJoin(base, link)
} }
childNode.Type = html.TextNode childNode.Type = html.TextNode
childNode.Data = name childNode.Data = name

View File

@ -427,6 +427,10 @@ func TestRender_ShortLinks(t *testing.T) {
otherImgurlWiki := util.URLJoin(markup.TestRepoURL, "wiki", "raw", "Link+Other.jpg") otherImgurlWiki := util.URLJoin(markup.TestRepoURL, "wiki", "raw", "Link+Other.jpg")
encodedImgurlWiki := util.URLJoin(markup.TestRepoURL, "wiki", "raw", "Link+%23.jpg") encodedImgurlWiki := util.URLJoin(markup.TestRepoURL, "wiki", "raw", "Link+%23.jpg")
notencodedImgurlWiki := util.URLJoin(markup.TestRepoURL, "wiki", "raw", "some", "path", "Link+#.jpg") notencodedImgurlWiki := util.URLJoin(markup.TestRepoURL, "wiki", "raw", "some", "path", "Link+#.jpg")
renderableFileURL := util.URLJoin(tree, "markdown_file.md")
renderableFileURLWiki := util.URLJoin(markup.TestRepoURL, "wiki", "markdown_file.md")
unrenderableFileURL := util.URLJoin(tree, "file.zip")
unrenderableFileURLWiki := util.URLJoin(markup.TestRepoURL, "wiki", "raw", "file.zip")
favicon := "http://google.com/favicon.ico" favicon := "http://google.com/favicon.ico"
test( test(
@ -481,6 +485,14 @@ func TestRender_ShortLinks(t *testing.T) {
"[[Link]] [[Other Link]] [[Link?]]", "[[Link]] [[Other Link]] [[Link?]]",
`<p><a href="`+url+`" rel="nofollow">Link</a> <a href="`+otherURL+`" rel="nofollow">Other Link</a> <a href="`+encodedURL+`" rel="nofollow">Link?</a></p>`, `<p><a href="`+url+`" rel="nofollow">Link</a> <a href="`+otherURL+`" rel="nofollow">Other Link</a> <a href="`+encodedURL+`" rel="nofollow">Link?</a></p>`,
`<p><a href="`+urlWiki+`" rel="nofollow">Link</a> <a href="`+otherURLWiki+`" rel="nofollow">Other Link</a> <a href="`+encodedURLWiki+`" rel="nofollow">Link?</a></p>`) `<p><a href="`+urlWiki+`" rel="nofollow">Link</a> <a href="`+otherURLWiki+`" rel="nofollow">Other Link</a> <a href="`+encodedURLWiki+`" rel="nofollow">Link?</a></p>`)
test(
"[[markdown_file.md]]",
`<p><a href="`+renderableFileURL+`" rel="nofollow">markdown_file.md</a></p>`,
`<p><a href="`+renderableFileURLWiki+`" rel="nofollow">markdown_file.md</a></p>`)
test(
"[[file.zip]]",
`<p><a href="`+unrenderableFileURL+`" rel="nofollow">file.zip</a></p>`,
`<p><a href="`+unrenderableFileURLWiki+`" rel="nofollow">file.zip</a></p>`)
test( test(
"[[Link #.jpg]]", "[[Link #.jpg]]",
`<p><a href="`+encodedImgurl+`" rel="nofollow"><img src="`+encodedImgurl+`" title="Link #.jpg" alt="Link #.jpg"/></a></p>`, `<p><a href="`+encodedImgurl+`" rel="nofollow"><img src="`+encodedImgurl+`" title="Link #.jpg" alt="Link #.jpg"/></a></p>`,

View File

@ -653,9 +653,9 @@ space</p>
Expected: `<p>space @mention-user<br/> Expected: `<p>space @mention-user<br/>
/just/a/path.bin<br/> /just/a/path.bin<br/>
<a href="https://example.com/file.bin" rel="nofollow">https://example.com/file.bin</a><br/> <a href="https://example.com/file.bin" rel="nofollow">https://example.com/file.bin</a><br/>
<a href="/wiki/file.bin" rel="nofollow">local link</a><br/> <a href="/wiki/raw/file.bin" rel="nofollow">local link</a><br/>
<a href="https://example.com" rel="nofollow">remote link</a><br/> <a href="https://example.com" rel="nofollow">remote link</a><br/>
<a href="/wiki/file.bin" rel="nofollow">local link</a><br/> <a href="/wiki/raw/file.bin" rel="nofollow">local link</a><br/>
<a href="https://example.com" rel="nofollow">remote link</a><br/> <a href="https://example.com" rel="nofollow">remote link</a><br/>
<a href="/wiki/raw/image.jpg" target="_blank" rel="nofollow noopener"><img src="/wiki/raw/image.jpg" alt="local image"/></a><br/> <a href="/wiki/raw/image.jpg" target="_blank" rel="nofollow noopener"><img src="/wiki/raw/image.jpg" alt="local image"/></a><br/>
<a href="/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/wiki/raw/path/file" alt="local image"/></a><br/> <a href="/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/wiki/raw/path/file" alt="local image"/></a><br/>
@ -711,9 +711,9 @@ space</p>
Expected: `<p>space @mention-user<br/> Expected: `<p>space @mention-user<br/>
/just/a/path.bin<br/> /just/a/path.bin<br/>
<a href="https://example.com/file.bin" rel="nofollow">https://example.com/file.bin</a><br/> <a href="https://example.com/file.bin" rel="nofollow">https://example.com/file.bin</a><br/>
<a href="https://gitea.io/wiki/file.bin" rel="nofollow">local link</a><br/> <a href="https://gitea.io/wiki/raw/file.bin" rel="nofollow">local link</a><br/>
<a href="https://example.com" rel="nofollow">remote link</a><br/> <a href="https://example.com" rel="nofollow">remote link</a><br/>
<a href="https://gitea.io/wiki/file.bin" rel="nofollow">local link</a><br/> <a href="https://gitea.io/wiki/raw/file.bin" rel="nofollow">local link</a><br/>
<a href="https://example.com" rel="nofollow">remote link</a><br/> <a href="https://example.com" rel="nofollow">remote link</a><br/>
<a href="https://gitea.io/wiki/raw/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://gitea.io/wiki/raw/image.jpg" alt="local image"/></a><br/> <a href="https://gitea.io/wiki/raw/image.jpg" target="_blank" rel="nofollow noopener"><img src="https://gitea.io/wiki/raw/image.jpg" alt="local image"/></a><br/>
<a href="https://gitea.io/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="https://gitea.io/wiki/raw/path/file" alt="local image"/></a><br/> <a href="https://gitea.io/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="https://gitea.io/wiki/raw/path/file" alt="local image"/></a><br/>
@ -769,9 +769,9 @@ space</p>
Expected: `<p>space @mention-user<br/> Expected: `<p>space @mention-user<br/>
/just/a/path.bin<br/> /just/a/path.bin<br/>
<a href="https://example.com/file.bin" rel="nofollow">https://example.com/file.bin</a><br/> <a href="https://example.com/file.bin" rel="nofollow">https://example.com/file.bin</a><br/>
<a href="/relative/path/wiki/file.bin" rel="nofollow">local link</a><br/> <a href="/relative/path/wiki/raw/file.bin" rel="nofollow">local link</a><br/>
<a href="https://example.com" rel="nofollow">remote link</a><br/> <a href="https://example.com" rel="nofollow">remote link</a><br/>
<a href="/relative/path/wiki/file.bin" rel="nofollow">local link</a><br/> <a href="/relative/path/wiki/raw/file.bin" rel="nofollow">local link</a><br/>
<a href="https://example.com" rel="nofollow">remote link</a><br/> <a href="https://example.com" rel="nofollow">remote link</a><br/>
<a href="/relative/path/wiki/raw/image.jpg" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/image.jpg" alt="local image"/></a><br/> <a href="/relative/path/wiki/raw/image.jpg" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/image.jpg" alt="local image"/></a><br/>
<a href="/relative/path/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/path/file" alt="local image"/></a><br/> <a href="/relative/path/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/path/file" alt="local image"/></a><br/>
@ -829,9 +829,9 @@ space</p>
Expected: `<p>space @mention-user<br/> Expected: `<p>space @mention-user<br/>
/just/a/path.bin<br/> /just/a/path.bin<br/>
<a href="https://example.com/file.bin" rel="nofollow">https://example.com/file.bin</a><br/> <a href="https://example.com/file.bin" rel="nofollow">https://example.com/file.bin</a><br/>
<a href="/relative/path/wiki/file.bin" rel="nofollow">local link</a><br/> <a href="/relative/path/wiki/raw/file.bin" rel="nofollow">local link</a><br/>
<a href="https://example.com" rel="nofollow">remote link</a><br/> <a href="https://example.com" rel="nofollow">remote link</a><br/>
<a href="/relative/path/wiki/file.bin" rel="nofollow">local link</a><br/> <a href="/relative/path/wiki/raw/file.bin" rel="nofollow">local link</a><br/>
<a href="https://example.com" rel="nofollow">remote link</a><br/> <a href="https://example.com" rel="nofollow">remote link</a><br/>
<a href="/relative/path/wiki/raw/image.jpg" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/image.jpg" alt="local image"/></a><br/> <a href="/relative/path/wiki/raw/image.jpg" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/image.jpg" alt="local image"/></a><br/>
<a href="/relative/path/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/path/file" alt="local image"/></a><br/> <a href="/relative/path/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/path/file" alt="local image"/></a><br/>
@ -889,9 +889,9 @@ space</p>
Expected: `<p>space @mention-user<br/> Expected: `<p>space @mention-user<br/>
/just/a/path.bin<br/> /just/a/path.bin<br/>
<a href="https://example.com/file.bin" rel="nofollow">https://example.com/file.bin</a><br/> <a href="https://example.com/file.bin" rel="nofollow">https://example.com/file.bin</a><br/>
<a href="/relative/path/wiki/file.bin" rel="nofollow">local link</a><br/> <a href="/relative/path/wiki/raw/file.bin" rel="nofollow">local link</a><br/>
<a href="https://example.com" rel="nofollow">remote link</a><br/> <a href="https://example.com" rel="nofollow">remote link</a><br/>
<a href="/relative/path/wiki/file.bin" rel="nofollow">local link</a><br/> <a href="/relative/path/wiki/raw/file.bin" rel="nofollow">local link</a><br/>
<a href="https://example.com" rel="nofollow">remote link</a><br/> <a href="https://example.com" rel="nofollow">remote link</a><br/>
<a href="/relative/path/wiki/raw/image.jpg" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/image.jpg" alt="local image"/></a><br/> <a href="/relative/path/wiki/raw/image.jpg" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/image.jpg" alt="local image"/></a><br/>
<a href="/relative/path/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/path/file" alt="local image"/></a><br/> <a href="/relative/path/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/path/file" alt="local image"/></a><br/>
@ -951,9 +951,9 @@ space</p>
Expected: `<p>space @mention-user<br/> Expected: `<p>space @mention-user<br/>
/just/a/path.bin<br/> /just/a/path.bin<br/>
<a href="https://example.com/file.bin" rel="nofollow">https://example.com/file.bin</a><br/> <a href="https://example.com/file.bin" rel="nofollow">https://example.com/file.bin</a><br/>
<a href="/relative/path/wiki/file.bin" rel="nofollow">local link</a><br/> <a href="/relative/path/wiki/raw/file.bin" rel="nofollow">local link</a><br/>
<a href="https://example.com" rel="nofollow">remote link</a><br/> <a href="https://example.com" rel="nofollow">remote link</a><br/>
<a href="/relative/path/wiki/file.bin" rel="nofollow">local link</a><br/> <a href="/relative/path/wiki/raw/file.bin" rel="nofollow">local link</a><br/>
<a href="https://example.com" rel="nofollow">remote link</a><br/> <a href="https://example.com" rel="nofollow">remote link</a><br/>
<a href="/relative/path/wiki/raw/image.jpg" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/image.jpg" alt="local image"/></a><br/> <a href="/relative/path/wiki/raw/image.jpg" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/image.jpg" alt="local image"/></a><br/>
<a href="/relative/path/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/path/file" alt="local image"/></a><br/> <a href="/relative/path/wiki/raw/path/file" target="_blank" rel="nofollow noopener"><img src="/relative/path/wiki/raw/path/file" alt="local image"/></a><br/>

View File

@ -4,6 +4,8 @@
package markdown package markdown
import ( import (
"path/filepath"
"code.gitea.io/gitea/modules/markup" "code.gitea.io/gitea/modules/markup"
giteautil "code.gitea.io/gitea/modules/util" giteautil "code.gitea.io/gitea/modules/util"
@ -18,7 +20,16 @@ func (g *ASTTransformer) transformLink(ctx *markup.RenderContext, v *ast.Link, r
if !isAnchorFragment && !markup.IsFullURLBytes(link) { if !isAnchorFragment && !markup.IsFullURLBytes(link) {
base := ctx.Links.Base base := ctx.Links.Base
if ctx.IsWiki { if ctx.IsWiki {
base = ctx.Links.WikiLink() if filepath.Ext(string(link)) == "" {
// This link doesn't have a file extension - assume a regular wiki link
base = ctx.Links.WikiLink()
} else if markup.Type(string(link)) != "" {
// If it's a file type we can render, use a regular wiki link
base = ctx.Links.WikiLink()
} else {
// Otherwise, use a raw link instead
base = ctx.Links.WikiRawLink()
}
} else if ctx.Links.HasBranchInfo() { } else if ctx.Links.HasBranchInfo() {
base = ctx.Links.SrcLink() base = ctx.Links.SrcLink()
} }

View File

@ -11,6 +11,7 @@ import (
"time" "time"
"code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
) )
@ -32,13 +33,13 @@ const (
) )
// Bool checks for a key in the map and parses as a boolean // Bool checks for a key in the map and parses as a boolean
func (g GitPushOptions) Bool(key string, def bool) bool { func (g GitPushOptions) Bool(key string) optional.Option[bool] {
if val, ok := g[key]; ok { if val, ok := g[key]; ok {
if b, err := strconv.ParseBool(val); err == nil { if b, err := strconv.ParseBool(val); err == nil {
return b return optional.Some(b)
} }
} }
return def return optional.None[bool]()
} }
// HookOptions represents the options for the Hook calls // HookOptions represents the options for the Hook calls
@ -87,13 +88,17 @@ type HookProcReceiveResult struct {
// HookProcReceiveRefResult represents an individual result from ProcReceive // HookProcReceiveRefResult represents an individual result from ProcReceive
type HookProcReceiveRefResult struct { type HookProcReceiveRefResult struct {
OldOID string OldOID string
NewOID string NewOID string
Ref string Ref string
OriginalRef git.RefName OriginalRef git.RefName
IsForcePush bool IsForcePush bool
IsNotMatched bool IsNotMatched bool
Err string Err string
IsCreatePR bool
URL string
ShouldShowMessage bool
HeadBranch string
} }
// HookPreReceive check whether the provided commits are allowed // HookPreReceive check whether the provided commits are allowed

View File

@ -1331,12 +1331,53 @@ runners.task_list.repository=Repositori
runners.task_list.commit=Memperbuat runners.task_list.commit=Memperbuat
runs.commit=Memperbuat runs.commit=Memperbuat
runs.no_matching_online_runner_helper=Tidak ada runner online yang cocok dengan label: %s
runs.actor=Aktor
runs.status=Status
runs.actors_no_select=Semua aktor
runs.status_no_select=Semua status
runs.no_results=Tidak ada hasil yang cocok.
runs.no_workflows=Belum ada alur kerja.
runs.no_workflows.quick_start=Tidak tahu cara memulai dengan Gitea Actions? Lihat <a target="_blank" rel="noopener noreferrer" href="%s">panduan cepat</a>.
runs.no_workflows.documentation=Untuk informasi lebih lanjut tentang Gitea Actions, lihat <a target="_blank" rel="noopener noreferrer" href="%s">dokumentasi</a>.
runs.no_runs=Alur kerja belum berjalan.
runs.empty_commit_message=(pesan commit kosong)
workflow.disable=Nonaktifkan Alur Kerja
workflow.disable_success=Alur kerja '%s' berhasil dinonaktifkan.
workflow.enable=Aktifkan Alur Kerja
workflow.enable_success=Alur kerja '%s' berhasil diaktifkan.
workflow.disabled=Alur kerja dinonaktifkan.
need_approval_desc=Butuh persetujuan untuk menjalankan alur kerja untuk pull request fork.
variables=Variabel
variables.management=Managemen Variabel
variables.creation=Tambah Variabel
variables.none=Belum ada variabel.
variables.deletion=Hapus variabel
variables.deletion.description=Menghapus variabel bersifat permanen dan tidak dapat dibatalkan. Lanjutkan?
variables.description=Variabel akan diteruskan ke beberapa tindakan dan tidak dapat dibaca sebaliknya.
variables.id_not_exist=Variabel dengan ID %d tidak ada.
variables.edit=Edit Variabel
variables.deletion.failed=Gagal menghapus variabel.
variables.deletion.success=Variabel telah dihapus.
variables.creation.failed=Gagal menambahkan variabel.
variables.creation.success=Variabel "%s" telah ditambahkan.
variables.update.failed=Gagal mengedit variabel.
variables.update.success=Variabel telah diedit.
[projects] [projects]
type-1.display_name=Proyek Individu
type-2.display_name=Proyek Repositori
type-3.display_name=Proyek Organisasi
[git.filemode] [git.filemode]
changed_filemode=%[1]s → %[2]s
; Ordered by git filemode value, ascending. E.g. directory has "040000", normal file has "100644", … ; Ordered by git filemode value, ascending. E.g. directory has "040000", normal file has "100644", …
directory=Directory
normal_file=Normal file
executable_file=Executable file
symbolic_link=Symbolic link
submodule=Submodule

View File

@ -2109,7 +2109,7 @@ settings.pulls.default_delete_branch_after_merge=デフォルトでプルリク
settings.pulls.default_allow_edits_from_maintainers=デフォルトでメンテナからの編集を許可する settings.pulls.default_allow_edits_from_maintainers=デフォルトでメンテナからの編集を許可する
settings.releases_desc=リリースを有効にする settings.releases_desc=リリースを有効にする
settings.packages_desc=リポジトリパッケージレジストリを有効にする settings.packages_desc=リポジトリパッケージレジストリを有効にする
settings.projects_desc=リポジトリプロジェクトを有効にする settings.projects_desc=プロジェクトを有効にする
settings.projects_mode_all=すべてのプロジェクト settings.projects_mode_all=すべてのプロジェクト
settings.actions_desc=Actionsを有効にする settings.actions_desc=Actionsを有効にする
settings.admin_settings=管理者用設定 settings.admin_settings=管理者用設定

View File

@ -311,7 +311,7 @@ func SearchIssues(ctx *context.APIContext) {
ctx.SetLinkHeader(int(total), limit) ctx.SetLinkHeader(int(total), limit)
ctx.SetTotalCountHeader(total) ctx.SetTotalCountHeader(total)
ctx.JSON(http.StatusOK, convert.ToAPIIssueList(ctx, issues)) ctx.JSON(http.StatusOK, convert.ToAPIIssueList(ctx, ctx.Doer, issues))
} }
// ListIssues list the issues of a repository // ListIssues list the issues of a repository
@ -548,7 +548,7 @@ func ListIssues(ctx *context.APIContext) {
ctx.SetLinkHeader(int(total), listOptions.PageSize) ctx.SetLinkHeader(int(total), listOptions.PageSize)
ctx.SetTotalCountHeader(total) ctx.SetTotalCountHeader(total)
ctx.JSON(http.StatusOK, convert.ToAPIIssueList(ctx, issues)) ctx.JSON(http.StatusOK, convert.ToAPIIssueList(ctx, ctx.Doer, issues))
} }
func getUserIDForFilter(ctx *context.APIContext, queryName string) int64 { func getUserIDForFilter(ctx *context.APIContext, queryName string) int64 {
@ -614,7 +614,7 @@ func GetIssue(ctx *context.APIContext) {
ctx.NotFound() ctx.NotFound()
return return
} }
ctx.JSON(http.StatusOK, convert.ToAPIIssue(ctx, issue)) ctx.JSON(http.StatusOK, convert.ToAPIIssue(ctx, ctx.Doer, issue))
} }
// CreateIssue create an issue of a repository // CreateIssue create an issue of a repository
@ -737,7 +737,7 @@ func CreateIssue(ctx *context.APIContext) {
ctx.Error(http.StatusInternalServerError, "GetIssueByID", err) ctx.Error(http.StatusInternalServerError, "GetIssueByID", err)
return return
} }
ctx.JSON(http.StatusCreated, convert.ToAPIIssue(ctx, issue)) ctx.JSON(http.StatusCreated, convert.ToAPIIssue(ctx, ctx.Doer, issue))
} }
// EditIssue modify an issue of a repository // EditIssue modify an issue of a repository
@ -911,7 +911,7 @@ func EditIssue(ctx *context.APIContext) {
ctx.InternalServerError(err) ctx.InternalServerError(err)
return return
} }
ctx.JSON(http.StatusCreated, convert.ToAPIIssue(ctx, issue)) ctx.JSON(http.StatusCreated, convert.ToAPIIssue(ctx, ctx.Doer, issue))
} }
func DeleteIssue(ctx *context.APIContext) { func DeleteIssue(ctx *context.APIContext) {

View File

@ -107,7 +107,7 @@ func ListIssueAttachments(ctx *context.APIContext) {
return return
} }
ctx.JSON(http.StatusOK, convert.ToAPIIssue(ctx, issue).Attachments) ctx.JSON(http.StatusOK, convert.ToAPIIssue(ctx, ctx.Doer, issue).Attachments)
} }
// CreateIssueAttachment creates an attachment and saves the given file // CreateIssueAttachment creates an attachment and saves the given file

View File

@ -153,7 +153,7 @@ func GetIssueDependencies(ctx *context.APIContext) {
blockerIssues = append(blockerIssues, &blocker.Issue) blockerIssues = append(blockerIssues, &blocker.Issue)
} }
ctx.JSON(http.StatusOK, convert.ToAPIIssueList(ctx, blockerIssues)) ctx.JSON(http.StatusOK, convert.ToAPIIssueList(ctx, ctx.Doer, blockerIssues))
} }
// CreateIssueDependency create a new issue dependencies // CreateIssueDependency create a new issue dependencies
@ -214,7 +214,7 @@ func CreateIssueDependency(ctx *context.APIContext) {
return return
} }
ctx.JSON(http.StatusCreated, convert.ToAPIIssue(ctx, target)) ctx.JSON(http.StatusCreated, convert.ToAPIIssue(ctx, ctx.Doer, target))
} }
// RemoveIssueDependency remove an issue dependency // RemoveIssueDependency remove an issue dependency
@ -275,7 +275,7 @@ func RemoveIssueDependency(ctx *context.APIContext) {
return return
} }
ctx.JSON(http.StatusCreated, convert.ToAPIIssue(ctx, target)) ctx.JSON(http.StatusCreated, convert.ToAPIIssue(ctx, ctx.Doer, target))
} }
// GetIssueBlocks list issues that are blocked by this issue // GetIssueBlocks list issues that are blocked by this issue
@ -381,7 +381,7 @@ func GetIssueBlocks(ctx *context.APIContext) {
issues = append(issues, &depMeta.Issue) issues = append(issues, &depMeta.Issue)
} }
ctx.JSON(http.StatusOK, convert.ToAPIIssueList(ctx, issues)) ctx.JSON(http.StatusOK, convert.ToAPIIssueList(ctx, ctx.Doer, issues))
} }
// CreateIssueBlocking block the issue given in the body by the issue in path // CreateIssueBlocking block the issue given in the body by the issue in path
@ -438,7 +438,7 @@ func CreateIssueBlocking(ctx *context.APIContext) {
return return
} }
ctx.JSON(http.StatusCreated, convert.ToAPIIssue(ctx, dependency)) ctx.JSON(http.StatusCreated, convert.ToAPIIssue(ctx, ctx.Doer, dependency))
} }
// RemoveIssueBlocking unblock the issue given in the body by the issue in path // RemoveIssueBlocking unblock the issue given in the body by the issue in path
@ -495,7 +495,7 @@ func RemoveIssueBlocking(ctx *context.APIContext) {
return return
} }
ctx.JSON(http.StatusCreated, convert.ToAPIIssue(ctx, dependency)) ctx.JSON(http.StatusCreated, convert.ToAPIIssue(ctx, ctx.Doer, dependency))
} }
func getParamsIssue(ctx *context.APIContext) *issues_model.Issue { func getParamsIssue(ctx *context.APIContext) *issues_model.Issue {

View File

@ -207,7 +207,7 @@ func ListPinnedIssues(ctx *context.APIContext) {
return return
} }
ctx.JSON(http.StatusOK, convert.ToAPIIssueList(ctx, issues)) ctx.JSON(http.StatusOK, convert.ToAPIIssueList(ctx, ctx.Doer, issues))
} }
// ListPinnedPullRequests returns a list of all pinned PRs // ListPinnedPullRequests returns a list of all pinned PRs

View File

@ -138,7 +138,7 @@ func ListTrackedTimes(ctx *context.APIContext) {
} }
ctx.SetTotalCountHeader(count) ctx.SetTotalCountHeader(count)
ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(ctx, trackedTimes)) ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(ctx, ctx.Doer, trackedTimes))
} }
// AddTime add time manual to the given issue // AddTime add time manual to the given issue
@ -225,7 +225,7 @@ func AddTime(ctx *context.APIContext) {
ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) ctx.Error(http.StatusInternalServerError, "LoadAttributes", err)
return return
} }
ctx.JSON(http.StatusOK, convert.ToTrackedTime(ctx, trackedTime)) ctx.JSON(http.StatusOK, convert.ToTrackedTime(ctx, user, trackedTime))
} }
// ResetIssueTime reset time manual to the given issue // ResetIssueTime reset time manual to the given issue
@ -455,7 +455,7 @@ func ListTrackedTimesByUser(ctx *context.APIContext) {
ctx.Error(http.StatusInternalServerError, "LoadAttributes", err) ctx.Error(http.StatusInternalServerError, "LoadAttributes", err)
return return
} }
ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(ctx, trackedTimes)) ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(ctx, ctx.Doer, trackedTimes))
} }
// ListTrackedTimesByRepository lists all tracked times of the repository // ListTrackedTimesByRepository lists all tracked times of the repository
@ -567,7 +567,7 @@ func ListTrackedTimesByRepository(ctx *context.APIContext) {
} }
ctx.SetTotalCountHeader(count) ctx.SetTotalCountHeader(count)
ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(ctx, trackedTimes)) ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(ctx, ctx.Doer, trackedTimes))
} }
// ListMyTrackedTimes lists all tracked times of the current user // ListMyTrackedTimes lists all tracked times of the current user
@ -629,5 +629,5 @@ func ListMyTrackedTimes(ctx *context.APIContext) {
} }
ctx.SetTotalCountHeader(count) ctx.SetTotalCountHeader(count)
ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(ctx, trackedTimes)) ctx.JSON(http.StatusOK, convert.ToTrackedTimeList(ctx, ctx.Doer, trackedTimes))
} }

View File

@ -6,11 +6,12 @@ package private
import ( import (
"fmt" "fmt"
"net/http" "net/http"
"strconv"
git_model "code.gitea.io/gitea/models/git" git_model "code.gitea.io/gitea/models/git"
issues_model "code.gitea.io/gitea/models/issues" issues_model "code.gitea.io/gitea/models/issues"
access_model "code.gitea.io/gitea/models/perm/access"
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/gitrepo"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
@ -159,8 +160,10 @@ func HookPostReceive(ctx *gitea_context.PrivateContext) {
} }
} }
isPrivate := opts.GitPushOptions.Bool(private.GitPushOptionRepoPrivate)
isTemplate := opts.GitPushOptions.Bool(private.GitPushOptionRepoTemplate)
// Handle Push Options // Handle Push Options
if len(opts.GitPushOptions) > 0 { if isPrivate.Has() || isTemplate.Has() {
// load the repository // load the repository
if repo == nil { if repo == nil {
repo = loadRepository(ctx, ownerName, repoName) repo = loadRepository(ctx, ownerName, repoName)
@ -171,13 +174,49 @@ func HookPostReceive(ctx *gitea_context.PrivateContext) {
wasEmpty = repo.IsEmpty wasEmpty = repo.IsEmpty
} }
repo.IsPrivate = opts.GitPushOptions.Bool(private.GitPushOptionRepoPrivate, repo.IsPrivate) pusher, err := user_model.GetUserByID(ctx, opts.UserID)
repo.IsTemplate = opts.GitPushOptions.Bool(private.GitPushOptionRepoTemplate, repo.IsTemplate) if err != nil {
if err := repo_model.UpdateRepositoryCols(ctx, repo, "is_private", "is_template"); err != nil {
log.Error("Failed to Update: %s/%s Error: %v", ownerName, repoName, err) log.Error("Failed to Update: %s/%s Error: %v", ownerName, repoName, err)
ctx.JSON(http.StatusInternalServerError, private.HookPostReceiveResult{ ctx.JSON(http.StatusInternalServerError, private.HookPostReceiveResult{
Err: fmt.Sprintf("Failed to Update: %s/%s Error: %v", ownerName, repoName, err), Err: fmt.Sprintf("Failed to Update: %s/%s Error: %v", ownerName, repoName, err),
}) })
return
}
perm, err := access_model.GetUserRepoPermission(ctx, repo, pusher)
if err != nil {
log.Error("Failed to Update: %s/%s Error: %v", ownerName, repoName, err)
ctx.JSON(http.StatusInternalServerError, private.HookPostReceiveResult{
Err: fmt.Sprintf("Failed to Update: %s/%s Error: %v", ownerName, repoName, err),
})
return
}
if !perm.IsOwner() && !perm.IsAdmin() {
ctx.JSON(http.StatusNotFound, private.HookPostReceiveResult{
Err: "Permissions denied",
})
return
}
cols := make([]string, 0, len(opts.GitPushOptions))
if isPrivate.Has() {
repo.IsPrivate = isPrivate.Value()
cols = append(cols, "is_private")
}
if isTemplate.Has() {
repo.IsTemplate = isTemplate.Value()
cols = append(cols, "is_template")
}
if len(cols) > 0 {
if err := repo_model.UpdateRepositoryCols(ctx, repo, cols...); err != nil {
log.Error("Failed to Update: %s/%s Error: %v", ownerName, repoName, err)
ctx.JSON(http.StatusInternalServerError, private.HookPostReceiveResult{
Err: fmt.Sprintf("Failed to Update: %s/%s Error: %v", ownerName, repoName, err),
})
return
}
} }
} }
@ -192,42 +231,6 @@ func HookPostReceive(ctx *gitea_context.PrivateContext) {
refFullName := opts.RefFullNames[i] refFullName := opts.RefFullNames[i]
newCommitID := opts.NewCommitIDs[i] newCommitID := opts.NewCommitIDs[i]
// post update for agit pull request
// FIXME: use pr.Flow to test whether it's an Agit PR or a GH PR
if git.DefaultFeatures.SupportProcReceive && refFullName.IsPull() {
if repo == nil {
repo = loadRepository(ctx, ownerName, repoName)
if ctx.Written() {
return
}
}
pullIndex, _ := strconv.ParseInt(refFullName.PullName(), 10, 64)
if pullIndex <= 0 {
continue
}
pr, err := issues_model.GetPullRequestByIndex(ctx, repo.ID, pullIndex)
if err != nil && !issues_model.IsErrPullRequestNotExist(err) {
log.Error("Failed to get PR by index %v Error: %v", pullIndex, err)
ctx.JSON(http.StatusInternalServerError, private.Response{
Err: fmt.Sprintf("Failed to get PR by index %v Error: %v", pullIndex, err),
})
return
}
if pr == nil {
continue
}
results = append(results, private.HookPostReceiveBranchResult{
Message: setting.Git.PullRequestPushMessage && repo.AllowsPulls(ctx),
Create: false,
Branch: "",
URL: fmt.Sprintf("%s/pulls/%d", repo.HTMLURL(), pr.Index),
})
continue
}
// If we've pushed a branch (and not deleted it) // If we've pushed a branch (and not deleted it)
if !git.IsEmptyCommitID(newCommitID) && refFullName.IsBranch() { if !git.IsEmptyCommitID(newCommitID) && refFullName.IsBranch() {
// First ensure we have the repository loaded, we're allowed pulls requests and we can get the base repo // First ensure we have the repository loaded, we're allowed pulls requests and we can get the base repo

View File

@ -2179,7 +2179,7 @@ func GetIssueInfo(ctx *context.Context) {
} }
} }
ctx.JSON(http.StatusOK, convert.ToIssue(ctx, issue)) ctx.JSON(http.StatusOK, convert.ToIssue(ctx, ctx.Doer, issue))
} }
// UpdateIssueTitle change issue's title // UpdateIssueTitle change issue's title
@ -2709,7 +2709,7 @@ func SearchIssues(ctx *context.Context) {
} }
ctx.SetTotalCountHeader(total) ctx.SetTotalCountHeader(total)
ctx.JSON(http.StatusOK, convert.ToIssueList(ctx, issues)) ctx.JSON(http.StatusOK, convert.ToIssueList(ctx, ctx.Doer, issues))
} }
func getUserIDForFilter(ctx *context.Context, queryName string) int64 { func getUserIDForFilter(ctx *context.Context, queryName string) int64 {
@ -2879,7 +2879,7 @@ func ListIssues(ctx *context.Context) {
} }
ctx.SetTotalCountHeader(total) ctx.SetTotalCountHeader(total)
ctx.JSON(http.StatusOK, convert.ToIssueList(ctx, issues)) ctx.JSON(http.StatusOK, convert.ToIssueList(ctx, ctx.Doer, issues))
} }
func BatchDeleteIssues(ctx *context.Context) { func BatchDeleteIssues(ctx *context.Context) {

View File

@ -200,12 +200,13 @@ func TestDeleteWikiPagePost(t *testing.T) {
func TestWikiRaw(t *testing.T) { func TestWikiRaw(t *testing.T) {
for filepath, filetype := range map[string]string{ for filepath, filetype := range map[string]string{
"jpeg.jpg": "image/jpeg", "jpeg.jpg": "image/jpeg",
"images/jpeg.jpg": "image/jpeg", "images/jpeg.jpg": "image/jpeg",
"Page With Spaced Name": "text/plain; charset=utf-8", "files/Non-Renderable-File.zip": "application/octet-stream",
"Page-With-Spaced-Name": "text/plain; charset=utf-8", "Page With Spaced Name": "text/plain; charset=utf-8",
"Page With Spaced Name.md": "", // there is no "Page With Spaced Name.md" in repo "Page-With-Spaced-Name": "text/plain; charset=utf-8",
"Page-With-Spaced-Name.md": "text/plain; charset=utf-8", "Page With Spaced Name.md": "", // there is no "Page With Spaced Name.md" in repo
"Page-With-Spaced-Name.md": "text/plain; charset=utf-8",
} { } {
unittest.PrepareTestEnv(t) unittest.PrepareTestEnv(t)
@ -226,6 +227,12 @@ func TestWikiRaw(t *testing.T) {
func TestDefaultWikiBranch(t *testing.T) { func TestDefaultWikiBranch(t *testing.T) {
unittest.PrepareTestEnv(t) unittest.PrepareTestEnv(t)
// repo with no wiki
repoWithNoWiki := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
assert.False(t, repoWithNoWiki.HasWiki())
assert.NoError(t, wiki_service.ChangeDefaultWikiBranch(db.DefaultContext, repoWithNoWiki, "main"))
// repo with wiki
assert.NoError(t, repo_model.UpdateRepositoryCols(db.DefaultContext, &repo_model.Repository{ID: 1, DefaultWikiBranch: "wrong-branch"})) assert.NoError(t, repo_model.UpdateRepositoryCols(db.DefaultContext, &repo_model.Repository{ID: 1, DefaultWikiBranch: "wrong-branch"}))
ctx, _ := contexttest.MockContext(t, "user2/repo1/wiki") ctx, _ := contexttest.MockContext(t, "user2/repo1/wiki")

View File

@ -49,7 +49,7 @@ func (n *actionsNotifier) NewIssue(ctx context.Context, issue *issues_model.Issu
newNotifyInputFromIssue(issue, webhook_module.HookEventIssues).WithPayload(&api.IssuePayload{ newNotifyInputFromIssue(issue, webhook_module.HookEventIssues).WithPayload(&api.IssuePayload{
Action: api.HookIssueOpened, Action: api.HookIssueOpened,
Index: issue.Index, Index: issue.Index,
Issue: convert.ToAPIIssue(ctx, issue), Issue: convert.ToAPIIssue(ctx, issue.Poster, issue),
Repository: convert.ToRepo(ctx, issue.Repo, permission), Repository: convert.ToRepo(ctx, issue.Repo, permission),
Sender: convert.ToUser(ctx, issue.Poster, nil), Sender: convert.ToUser(ctx, issue.Poster, nil),
}).Notify(withMethod(ctx, "NewIssue")) }).Notify(withMethod(ctx, "NewIssue"))
@ -89,7 +89,7 @@ func (n *actionsNotifier) IssueChangeContent(ctx context.Context, doer *user_mod
WithPayload(&api.IssuePayload{ WithPayload(&api.IssuePayload{
Action: api.HookIssueEdited, Action: api.HookIssueEdited,
Index: issue.Index, Index: issue.Index,
Issue: convert.ToAPIIssue(ctx, issue), Issue: convert.ToAPIIssue(ctx, doer, issue),
Repository: convert.ToRepo(ctx, issue.Repo, permission), Repository: convert.ToRepo(ctx, issue.Repo, permission),
Sender: convert.ToUser(ctx, doer, nil), Sender: convert.ToUser(ctx, doer, nil),
}). }).
@ -127,7 +127,7 @@ func (n *actionsNotifier) IssueChangeStatus(ctx context.Context, doer *user_mode
} }
apiIssue := &api.IssuePayload{ apiIssue := &api.IssuePayload{
Index: issue.Index, Index: issue.Index,
Issue: convert.ToAPIIssue(ctx, issue), Issue: convert.ToAPIIssue(ctx, doer, issue),
Repository: convert.ToRepo(ctx, issue.Repo, permission), Repository: convert.ToRepo(ctx, issue.Repo, permission),
Sender: convert.ToUser(ctx, doer, nil), Sender: convert.ToUser(ctx, doer, nil),
} }
@ -229,7 +229,7 @@ func notifyIssueChange(ctx context.Context, doer *user_model.User, issue *issues
WithPayload(&api.IssuePayload{ WithPayload(&api.IssuePayload{
Action: action, Action: action,
Index: issue.Index, Index: issue.Index,
Issue: convert.ToAPIIssue(ctx, issue), Issue: convert.ToAPIIssue(ctx, doer, issue),
Repository: convert.ToRepo(ctx, issue.Repo, permission), Repository: convert.ToRepo(ctx, issue.Repo, permission),
Sender: convert.ToUser(ctx, doer, nil), Sender: convert.ToUser(ctx, doer, nil),
}). }).
@ -293,7 +293,7 @@ func notifyIssueCommentChange(ctx context.Context, doer *user_model.User, commen
payload := &api.IssueCommentPayload{ payload := &api.IssueCommentPayload{
Action: action, Action: action,
Issue: convert.ToAPIIssue(ctx, comment.Issue), Issue: convert.ToAPIIssue(ctx, doer, comment.Issue),
Comment: convert.ToAPIComment(ctx, comment.Issue.Repo, comment), Comment: convert.ToAPIComment(ctx, comment.Issue.Repo, comment),
Repository: convert.ToRepo(ctx, comment.Issue.Repo, permission), Repository: convert.ToRepo(ctx, comment.Issue.Repo, permission),
Sender: convert.ToUser(ctx, doer, nil), Sender: convert.ToUser(ctx, doer, nil),

View File

@ -16,6 +16,7 @@ import (
"code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/private" "code.gitea.io/gitea/modules/private"
"code.gitea.io/gitea/modules/setting"
notify_service "code.gitea.io/gitea/services/notify" notify_service "code.gitea.io/gitea/services/notify"
pull_service "code.gitea.io/gitea/services/pull" pull_service "code.gitea.io/gitea/services/pull"
) )
@ -145,10 +146,14 @@ func ProcReceive(ctx context.Context, repo *repo_model.Repository, gitRepo *git.
log.Trace("Pull request created: %d/%d", repo.ID, prIssue.ID) log.Trace("Pull request created: %d/%d", repo.ID, prIssue.ID)
results = append(results, private.HookProcReceiveRefResult{ results = append(results, private.HookProcReceiveRefResult{
Ref: pr.GetGitRefName(), Ref: pr.GetGitRefName(),
OriginalRef: opts.RefFullNames[i], OriginalRef: opts.RefFullNames[i],
OldOID: objectFormat.EmptyObjectID().String(), OldOID: objectFormat.EmptyObjectID().String(),
NewOID: opts.NewCommitIDs[i], NewOID: opts.NewCommitIDs[i],
IsCreatePR: true,
URL: fmt.Sprintf("%s/pulls/%d", repo.HTMLURL(), pr.Index),
ShouldShowMessage: setting.Git.PullRequestPushMessage && repo.AllowsPulls(ctx),
HeadBranch: headBranch,
}) })
continue continue
} }
@ -208,11 +213,14 @@ func ProcReceive(ctx context.Context, repo *repo_model.Repository, gitRepo *git.
isForcePush := comment != nil && comment.IsForcePush isForcePush := comment != nil && comment.IsForcePush
results = append(results, private.HookProcReceiveRefResult{ results = append(results, private.HookProcReceiveRefResult{
OldOID: oldCommitID, OldOID: oldCommitID,
NewOID: opts.NewCommitIDs[i], NewOID: opts.NewCommitIDs[i],
Ref: pr.GetGitRefName(), Ref: pr.GetGitRefName(),
OriginalRef: opts.RefFullNames[i], OriginalRef: opts.RefFullNames[i],
IsForcePush: isForcePush, IsForcePush: isForcePush,
IsCreatePR: false,
URL: fmt.Sprintf("%s/pulls/%d", repo.HTMLURL(), pr.Index),
ShouldShowMessage: setting.Git.PullRequestPushMessage && repo.AllowsPulls(ctx),
}) })
} }

View File

@ -18,19 +18,19 @@ import (
api "code.gitea.io/gitea/modules/structs" api "code.gitea.io/gitea/modules/structs"
) )
func ToIssue(ctx context.Context, issue *issues_model.Issue) *api.Issue { func ToIssue(ctx context.Context, doer *user_model.User, issue *issues_model.Issue) *api.Issue {
return toIssue(ctx, issue, WebAssetDownloadURL) return toIssue(ctx, doer, issue, WebAssetDownloadURL)
} }
// ToAPIIssue converts an Issue to API format // ToAPIIssue converts an Issue to API format
// it assumes some fields assigned with values: // it assumes some fields assigned with values:
// Required - Poster, Labels, // Required - Poster, Labels,
// Optional - Milestone, Assignee, PullRequest // Optional - Milestone, Assignee, PullRequest
func ToAPIIssue(ctx context.Context, issue *issues_model.Issue) *api.Issue { func ToAPIIssue(ctx context.Context, doer *user_model.User, issue *issues_model.Issue) *api.Issue {
return toIssue(ctx, issue, APIAssetDownloadURL) return toIssue(ctx, doer, issue, APIAssetDownloadURL)
} }
func toIssue(ctx context.Context, issue *issues_model.Issue, getDownloadURL func(repo *repo_model.Repository, attach *repo_model.Attachment) string) *api.Issue { func toIssue(ctx context.Context, doer *user_model.User, issue *issues_model.Issue, getDownloadURL func(repo *repo_model.Repository, attach *repo_model.Attachment) string) *api.Issue {
if err := issue.LoadLabels(ctx); err != nil { if err := issue.LoadLabels(ctx); err != nil {
return &api.Issue{} return &api.Issue{}
} }
@ -44,7 +44,7 @@ func toIssue(ctx context.Context, issue *issues_model.Issue, getDownloadURL func
apiIssue := &api.Issue{ apiIssue := &api.Issue{
ID: issue.ID, ID: issue.ID,
Index: issue.Index, Index: issue.Index,
Poster: ToUser(ctx, issue.Poster, nil), Poster: ToUser(ctx, issue.Poster, doer),
Title: issue.Title, Title: issue.Title,
Body: issue.Content, Body: issue.Content,
Attachments: toAttachments(issue.Repo, issue.Attachments, getDownloadURL), Attachments: toAttachments(issue.Repo, issue.Attachments, getDownloadURL),
@ -114,25 +114,25 @@ func toIssue(ctx context.Context, issue *issues_model.Issue, getDownloadURL func
} }
// ToIssueList converts an IssueList to API format // ToIssueList converts an IssueList to API format
func ToIssueList(ctx context.Context, il issues_model.IssueList) []*api.Issue { func ToIssueList(ctx context.Context, doer *user_model.User, il issues_model.IssueList) []*api.Issue {
result := make([]*api.Issue, len(il)) result := make([]*api.Issue, len(il))
for i := range il { for i := range il {
result[i] = ToIssue(ctx, il[i]) result[i] = ToIssue(ctx, doer, il[i])
} }
return result return result
} }
// ToAPIIssueList converts an IssueList to API format // ToAPIIssueList converts an IssueList to API format
func ToAPIIssueList(ctx context.Context, il issues_model.IssueList) []*api.Issue { func ToAPIIssueList(ctx context.Context, doer *user_model.User, il issues_model.IssueList) []*api.Issue {
result := make([]*api.Issue, len(il)) result := make([]*api.Issue, len(il))
for i := range il { for i := range il {
result[i] = ToAPIIssue(ctx, il[i]) result[i] = ToAPIIssue(ctx, doer, il[i])
} }
return result return result
} }
// ToTrackedTime converts TrackedTime to API format // ToTrackedTime converts TrackedTime to API format
func ToTrackedTime(ctx context.Context, t *issues_model.TrackedTime) (apiT *api.TrackedTime) { func ToTrackedTime(ctx context.Context, doer *user_model.User, t *issues_model.TrackedTime) (apiT *api.TrackedTime) {
apiT = &api.TrackedTime{ apiT = &api.TrackedTime{
ID: t.ID, ID: t.ID,
IssueID: t.IssueID, IssueID: t.IssueID,
@ -141,7 +141,7 @@ func ToTrackedTime(ctx context.Context, t *issues_model.TrackedTime) (apiT *api.
Created: t.Created, Created: t.Created,
} }
if t.Issue != nil { if t.Issue != nil {
apiT.Issue = ToAPIIssue(ctx, t.Issue) apiT.Issue = ToAPIIssue(ctx, doer, t.Issue)
} }
if t.User != nil { if t.User != nil {
apiT.UserName = t.User.Name apiT.UserName = t.User.Name
@ -192,10 +192,10 @@ func ToStopWatches(ctx context.Context, sws []*issues_model.Stopwatch) (api.Stop
} }
// ToTrackedTimeList converts TrackedTimeList to API format // ToTrackedTimeList converts TrackedTimeList to API format
func ToTrackedTimeList(ctx context.Context, tl issues_model.TrackedTimeList) api.TrackedTimeList { func ToTrackedTimeList(ctx context.Context, doer *user_model.User, tl issues_model.TrackedTimeList) api.TrackedTimeList {
result := make([]*api.TrackedTime, 0, len(tl)) result := make([]*api.TrackedTime, 0, len(tl))
for _, t := range tl { for _, t := range tl {
result = append(result, ToTrackedTime(ctx, t)) result = append(result, ToTrackedTime(ctx, doer, t))
} }
return result return result
} }

View File

@ -120,7 +120,7 @@ func ToTimelineComment(ctx context.Context, repo *repo_model.Repository, c *issu
return nil return nil
} }
comment.TrackedTime = ToTrackedTime(ctx, c.Time) comment.TrackedTime = ToTrackedTime(ctx, doer, c.Time)
} }
if c.RefIssueID != 0 { if c.RefIssueID != 0 {
@ -129,7 +129,7 @@ func ToTimelineComment(ctx context.Context, repo *repo_model.Repository, c *issu
log.Error("GetIssueByID(%d): %v", c.RefIssueID, err) log.Error("GetIssueByID(%d): %v", c.RefIssueID, err)
return nil return nil
} }
comment.RefIssue = ToAPIIssue(ctx, issue) comment.RefIssue = ToAPIIssue(ctx, doer, issue)
} }
if c.RefCommentID != 0 { if c.RefCommentID != 0 {
@ -180,7 +180,7 @@ func ToTimelineComment(ctx context.Context, repo *repo_model.Repository, c *issu
} }
if c.DependentIssue != nil { if c.DependentIssue != nil {
comment.DependentIssue = ToAPIIssue(ctx, c.DependentIssue) comment.DependentIssue = ToAPIIssue(ctx, doer, c.DependentIssue)
} }
return comment return comment

View File

@ -33,7 +33,7 @@ func ToAPIPullRequest(ctx context.Context, pr *issues_model.PullRequest, doer *u
return nil return nil
} }
apiIssue := ToAPIIssue(ctx, pr.Issue) apiIssue := ToAPIIssue(ctx, doer, pr.Issue)
if err := pr.LoadBaseRepo(ctx); err != nil { if err := pr.LoadBaseRepo(ctx); err != nil {
log.Error("GetRepositoryById[%d]: %v", pr.ID, err) log.Error("GetRepositoryById[%d]: %v", pr.ID, err)
return nil return nil

View File

@ -14,6 +14,7 @@ import (
"code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/storage"
) )
// Check represents a Doctor check // Check represents a Doctor check
@ -25,6 +26,7 @@ type Check struct {
AbortIfFailed bool AbortIfFailed bool
SkipDatabaseInitialization bool SkipDatabaseInitialization bool
Priority int Priority int
InitStorage bool
} }
func initDBSkipLogger(ctx context.Context) error { func initDBSkipLogger(ctx context.Context) error {
@ -84,6 +86,7 @@ func RunChecks(ctx context.Context, colorize, autofix bool, checks []*Check) err
logger := log.BaseLoggerToGeneralLogger(&doctorCheckLogger{colorize: colorize}) logger := log.BaseLoggerToGeneralLogger(&doctorCheckLogger{colorize: colorize})
loggerStep := log.BaseLoggerToGeneralLogger(&doctorCheckStepLogger{colorize: colorize}) loggerStep := log.BaseLoggerToGeneralLogger(&doctorCheckStepLogger{colorize: colorize})
dbIsInit := false dbIsInit := false
storageIsInit := false
for i, check := range checks { for i, check := range checks {
if !dbIsInit && !check.SkipDatabaseInitialization { if !dbIsInit && !check.SkipDatabaseInitialization {
// Only open database after the most basic configuration check // Only open database after the most basic configuration check
@ -94,6 +97,14 @@ func RunChecks(ctx context.Context, colorize, autofix bool, checks []*Check) err
} }
dbIsInit = true dbIsInit = true
} }
if !storageIsInit && check.InitStorage {
if err := storage.Init(); err != nil {
logger.Error("Error whilst initializing the storage: %v", err)
logger.Error("Check if you are using the right config file. You can use a --config directive to specify one.")
return nil
}
storageIsInit = true
}
logger.Info("\n[%d] %s", i+1, check.Title) logger.Info("\n[%d] %s", i+1, check.Title)
if err := check.Run(ctx, loggerStep, autofix); err != nil { if err := check.Run(ctx, loggerStep, autofix); err != nil {
if check.AbortIfFailed { if check.AbortIfFailed {

View File

@ -67,7 +67,7 @@ func (m *webhookNotifier) IssueClearLabels(ctx context.Context, doer *user_model
err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventIssueLabel, &api.IssuePayload{ err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventIssueLabel, &api.IssuePayload{
Action: api.HookIssueLabelCleared, Action: api.HookIssueLabelCleared,
Index: issue.Index, Index: issue.Index,
Issue: convert.ToAPIIssue(ctx, issue), Issue: convert.ToAPIIssue(ctx, doer, issue),
Repository: convert.ToRepo(ctx, issue.Repo, permission), Repository: convert.ToRepo(ctx, issue.Repo, permission),
Sender: convert.ToUser(ctx, doer, nil), Sender: convert.ToUser(ctx, doer, nil),
}) })
@ -168,7 +168,7 @@ func (m *webhookNotifier) IssueChangeAssignee(ctx context.Context, doer *user_mo
permission, _ := access_model.GetUserRepoPermission(ctx, issue.Repo, doer) permission, _ := access_model.GetUserRepoPermission(ctx, issue.Repo, doer)
apiIssue := &api.IssuePayload{ apiIssue := &api.IssuePayload{
Index: issue.Index, Index: issue.Index,
Issue: convert.ToAPIIssue(ctx, issue), Issue: convert.ToAPIIssue(ctx, doer, issue),
Repository: convert.ToRepo(ctx, issue.Repo, permission), Repository: convert.ToRepo(ctx, issue.Repo, permission),
Sender: convert.ToUser(ctx, doer, nil), Sender: convert.ToUser(ctx, doer, nil),
} }
@ -214,7 +214,7 @@ func (m *webhookNotifier) IssueChangeTitle(ctx context.Context, doer *user_model
From: oldTitle, From: oldTitle,
}, },
}, },
Issue: convert.ToAPIIssue(ctx, issue), Issue: convert.ToAPIIssue(ctx, doer, issue),
Repository: convert.ToRepo(ctx, issue.Repo, permission), Repository: convert.ToRepo(ctx, issue.Repo, permission),
Sender: convert.ToUser(ctx, doer, nil), Sender: convert.ToUser(ctx, doer, nil),
}) })
@ -250,7 +250,7 @@ func (m *webhookNotifier) IssueChangeStatus(ctx context.Context, doer *user_mode
} else { } else {
apiIssue := &api.IssuePayload{ apiIssue := &api.IssuePayload{
Index: issue.Index, Index: issue.Index,
Issue: convert.ToAPIIssue(ctx, issue), Issue: convert.ToAPIIssue(ctx, doer, issue),
Repository: convert.ToRepo(ctx, issue.Repo, permission), Repository: convert.ToRepo(ctx, issue.Repo, permission),
Sender: convert.ToUser(ctx, doer, nil), Sender: convert.ToUser(ctx, doer, nil),
CommitID: commitID, CommitID: commitID,
@ -281,7 +281,7 @@ func (m *webhookNotifier) NewIssue(ctx context.Context, issue *issues_model.Issu
if err := PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventIssues, &api.IssuePayload{ if err := PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventIssues, &api.IssuePayload{
Action: api.HookIssueOpened, Action: api.HookIssueOpened,
Index: issue.Index, Index: issue.Index,
Issue: convert.ToAPIIssue(ctx, issue), Issue: convert.ToAPIIssue(ctx, issue.Poster, issue),
Repository: convert.ToRepo(ctx, issue.Repo, permission), Repository: convert.ToRepo(ctx, issue.Repo, permission),
Sender: convert.ToUser(ctx, issue.Poster, nil), Sender: convert.ToUser(ctx, issue.Poster, nil),
}); err != nil { }); err != nil {
@ -349,7 +349,7 @@ func (m *webhookNotifier) IssueChangeContent(ctx context.Context, doer *user_mod
From: oldContent, From: oldContent,
}, },
}, },
Issue: convert.ToAPIIssue(ctx, issue), Issue: convert.ToAPIIssue(ctx, doer, issue),
Repository: convert.ToRepo(ctx, issue.Repo, permission), Repository: convert.ToRepo(ctx, issue.Repo, permission),
Sender: convert.ToUser(ctx, doer, nil), Sender: convert.ToUser(ctx, doer, nil),
}) })
@ -384,7 +384,7 @@ func (m *webhookNotifier) UpdateComment(ctx context.Context, doer *user_model.Us
permission, _ := access_model.GetUserRepoPermission(ctx, c.Issue.Repo, doer) permission, _ := access_model.GetUserRepoPermission(ctx, c.Issue.Repo, doer)
if err := PrepareWebhooks(ctx, EventSource{Repository: c.Issue.Repo}, eventType, &api.IssueCommentPayload{ if err := PrepareWebhooks(ctx, EventSource{Repository: c.Issue.Repo}, eventType, &api.IssueCommentPayload{
Action: api.HookIssueCommentEdited, Action: api.HookIssueCommentEdited,
Issue: convert.ToAPIIssue(ctx, c.Issue), Issue: convert.ToAPIIssue(ctx, doer, c.Issue),
Comment: convert.ToAPIComment(ctx, c.Issue.Repo, c), Comment: convert.ToAPIComment(ctx, c.Issue.Repo, c),
Changes: &api.ChangesPayload{ Changes: &api.ChangesPayload{
Body: &api.ChangesFromPayload{ Body: &api.ChangesFromPayload{
@ -412,7 +412,7 @@ func (m *webhookNotifier) CreateIssueComment(ctx context.Context, doer *user_mod
permission, _ := access_model.GetUserRepoPermission(ctx, repo, doer) permission, _ := access_model.GetUserRepoPermission(ctx, repo, doer)
if err := PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, eventType, &api.IssueCommentPayload{ if err := PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, eventType, &api.IssueCommentPayload{
Action: api.HookIssueCommentCreated, Action: api.HookIssueCommentCreated,
Issue: convert.ToAPIIssue(ctx, issue), Issue: convert.ToAPIIssue(ctx, doer, issue),
Comment: convert.ToAPIComment(ctx, repo, comment), Comment: convert.ToAPIComment(ctx, repo, comment),
Repository: convert.ToRepo(ctx, repo, permission), Repository: convert.ToRepo(ctx, repo, permission),
Sender: convert.ToUser(ctx, doer, nil), Sender: convert.ToUser(ctx, doer, nil),
@ -449,7 +449,7 @@ func (m *webhookNotifier) DeleteComment(ctx context.Context, doer *user_model.Us
permission, _ := access_model.GetUserRepoPermission(ctx, comment.Issue.Repo, doer) permission, _ := access_model.GetUserRepoPermission(ctx, comment.Issue.Repo, doer)
if err := PrepareWebhooks(ctx, EventSource{Repository: comment.Issue.Repo}, eventType, &api.IssueCommentPayload{ if err := PrepareWebhooks(ctx, EventSource{Repository: comment.Issue.Repo}, eventType, &api.IssueCommentPayload{
Action: api.HookIssueCommentDeleted, Action: api.HookIssueCommentDeleted,
Issue: convert.ToAPIIssue(ctx, comment.Issue), Issue: convert.ToAPIIssue(ctx, doer, comment.Issue),
Comment: convert.ToAPIComment(ctx, comment.Issue.Repo, comment), Comment: convert.ToAPIComment(ctx, comment.Issue.Repo, comment),
Repository: convert.ToRepo(ctx, comment.Issue.Repo, permission), Repository: convert.ToRepo(ctx, comment.Issue.Repo, permission),
Sender: convert.ToUser(ctx, doer, nil), Sender: convert.ToUser(ctx, doer, nil),
@ -533,7 +533,7 @@ func (m *webhookNotifier) IssueChangeLabels(ctx context.Context, doer *user_mode
err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventIssueLabel, &api.IssuePayload{ err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventIssueLabel, &api.IssuePayload{
Action: api.HookIssueLabelUpdated, Action: api.HookIssueLabelUpdated,
Index: issue.Index, Index: issue.Index,
Issue: convert.ToAPIIssue(ctx, issue), Issue: convert.ToAPIIssue(ctx, doer, issue),
Repository: convert.ToRepo(ctx, issue.Repo, permission), Repository: convert.ToRepo(ctx, issue.Repo, permission),
Sender: convert.ToUser(ctx, doer, nil), Sender: convert.ToUser(ctx, doer, nil),
}) })
@ -575,7 +575,7 @@ func (m *webhookNotifier) IssueChangeMilestone(ctx context.Context, doer *user_m
err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventIssueMilestone, &api.IssuePayload{ err = PrepareWebhooks(ctx, EventSource{Repository: issue.Repo}, webhook_module.HookEventIssueMilestone, &api.IssuePayload{
Action: hookAction, Action: hookAction,
Index: issue.Index, Index: issue.Index,
Issue: convert.ToAPIIssue(ctx, issue), Issue: convert.ToAPIIssue(ctx, doer, issue),
Repository: convert.ToRepo(ctx, issue.Repo, permission), Repository: convert.ToRepo(ctx, issue.Repo, permission),
Sender: convert.ToUser(ctx, doer, nil), Sender: convert.ToUser(ctx, doer, nil),
}) })

View File

@ -370,6 +370,10 @@ func ChangeDefaultWikiBranch(ctx context.Context, repo *repo_model.Repository, n
return fmt.Errorf("unable to update database: %w", err) return fmt.Errorf("unable to update database: %w", err)
} }
if !repo.HasWiki() {
return nil
}
oldDefBranch, err := gitrepo.GetWikiDefaultBranch(ctx, repo) oldDefBranch, err := gitrepo.GetWikiDefaultBranch(ctx, repo)
if err != nil { if err != nil {
return fmt.Errorf("unable to get default branch: %w", err) return fmt.Errorf("unable to get default branch: %w", err)

View File

@ -18,10 +18,10 @@
{{end}} {{end}}
{{end}} {{end}}
<div class="ui top attached header clearing segment tw-relative commit-header {{$class}}"> <div class="ui top attached header clearing segment tw-relative commit-header {{$class}}">
<div class="tw-flex tw-mb-4 tw-flex-wrap"> <div class="tw-flex tw-mb-4 tw-gap-1">
<h3 class="tw-mb-0 tw-flex-1"><span class="commit-summary" title="{{.Commit.Summary}}">{{RenderCommitMessage $.Context .Commit.Message ($.Repository.ComposeMetas ctx)}}</span>{{template "repo/commit_statuses" dict "Status" .CommitStatus "Statuses" .CommitStatuses}}</h3> <h3 class="tw-mb-0 tw-flex-1"><span class="commit-summary" title="{{.Commit.Summary}}">{{RenderCommitMessage $.Context .Commit.Message ($.Repository.ComposeMetas ctx)}}</span>{{template "repo/commit_statuses" dict "Status" .CommitStatus "Statuses" .CommitStatuses}}</h3>
{{if not $.PageIsWiki}} {{if not $.PageIsWiki}}
<div> <div class="commit-header-buttons">
<a class="ui primary tiny button" href="{{.SourcePath}}"> <a class="ui primary tiny button" href="{{.SourcePath}}">
{{ctx.Locale.Tr "repo.diff.browse_source"}} {{ctx.Locale.Tr "repo.diff.browse_source"}}
</a> </a>

View File

@ -13,17 +13,19 @@
{{$commitRepoLink := $.RepoLink}}{{if $.CommitRepoLink}}{{$commitRepoLink = $.CommitRepoLink}}{{end}} {{$commitRepoLink := $.RepoLink}}{{if $.CommitRepoLink}}{{$commitRepoLink = $.CommitRepoLink}}{{end}}
{{range .Commits}} {{range .Commits}}
<tr> <tr>
<td class="author tw-flex"> <td class="author">
{{$userName := .Author.Name}} <div class="tw-flex">
{{if .User}} {{$userName := .Author.Name}}
{{if and .User.FullName DefaultShowFullName}} {{if .User}}
{{$userName = .User.FullName}} {{if and .User.FullName DefaultShowFullName}}
{{$userName = .User.FullName}}
{{end}}
{{ctx.AvatarUtils.Avatar .User 28 "tw-mr-2"}}<a class="muted author-wrapper" href="{{.User.HomeLink}}">{{$userName}}</a>
{{else}}
{{ctx.AvatarUtils.AvatarByEmail .Author.Email .Author.Name 28 "tw-mr-2"}}
<span class="author-wrapper">{{$userName}}</span>
{{end}} {{end}}
{{ctx.AvatarUtils.Avatar .User 28 "tw-mr-2"}}<a class="muted author-wrapper" href="{{.User.HomeLink}}">{{$userName}}</a> </div>
{{else}}
{{ctx.AvatarUtils.AvatarByEmail .Author.Email .Author.Name 28 "tw-mr-2"}}
<span class="author-wrapper">{{$userName}}</span>
{{end}}
</td> </td>
<td class="sha"> <td class="sha">
{{$class := "ui sha label"}} {{$class := "ui sha label"}}

View File

@ -111,7 +111,7 @@
{{$isReviewFile := and $.IsSigned $.PageIsPullFiles (not $.IsArchived) $.IsShowingAllCommits}} {{$isReviewFile := and $.IsSigned $.PageIsPullFiles (not $.IsArchived) $.IsShowingAllCommits}}
<div class="diff-file-box diff-box file-content {{TabSizeClass $.Editorconfig $file.Name}} tw-mt-0" id="diff-{{$file.NameHash}}" data-old-filename="{{$file.OldName}}" data-new-filename="{{$file.Name}}" {{if or ($file.ShouldBeHidden) (not $isExpandable)}}data-folded="true"{{end}}> <div class="diff-file-box diff-box file-content {{TabSizeClass $.Editorconfig $file.Name}} tw-mt-0" id="diff-{{$file.NameHash}}" data-old-filename="{{$file.OldName}}" data-new-filename="{{$file.Name}}" {{if or ($file.ShouldBeHidden) (not $isExpandable)}}data-folded="true"{{end}}>
<h4 class="diff-file-header sticky-2nd-row ui top attached header tw-font-normal tw-flex tw-items-center tw-justify-between tw-flex-wrap"> <h4 class="diff-file-header sticky-2nd-row ui top attached header tw-font-normal tw-flex tw-items-center tw-justify-between tw-flex-wrap">
<div class="diff-file-name tw-flex tw-items-center tw-gap-1 tw-flex-wrap"> <div class="diff-file-name tw-flex tw-flex-1 tw-items-center tw-gap-1 tw-flex-wrap">
<button class="fold-file btn interact-bg tw-p-1{{if not $isExpandable}} tw-invisible{{end}}"> <button class="fold-file btn interact-bg tw-p-1{{if not $isExpandable}} tw-invisible{{end}}">
{{if $file.ShouldBeHidden}} {{if $file.ShouldBeHidden}}
{{svg "octicon-chevron-right" 18}} {{svg "octicon-chevron-right" 18}}
@ -128,21 +128,23 @@
{{template "repo/diff/stats" dict "file" . "root" $}} {{template "repo/diff/stats" dict "file" . "root" $}}
{{end}} {{end}}
</div> </div>
<span class="file tw-font-mono"><a class="muted file-link" title="{{if $file.IsRenamed}}{{$file.OldName}}{{end}}{{$file.Name}}" href="#diff-{{$file.NameHash}}">{{if $file.IsRenamed}}{{$file.OldName}}{{end}}{{$file.Name}}</a>{{if .IsLFSFile}} ({{ctx.Locale.Tr "repo.stored_lfs"}}){{end}}</span> <span class="file tw-flex tw-items-center tw-font-mono tw-flex-1"><a class="muted file-link" title="{{if $file.IsRenamed}}{{$file.OldName}}{{end}}{{$file.Name}}" href="#diff-{{$file.NameHash}}">{{if $file.IsRenamed}}{{$file.OldName}}{{end}}{{$file.Name}}</a>
<button class="btn interact-fg tw-p-2" data-clipboard-text="{{$file.Name}}">{{svg "octicon-copy" 14}}</button> {{if .IsLFSFile}} ({{ctx.Locale.Tr "repo.stored_lfs"}}){{end}}
{{if $file.IsGenerated}} <button class="btn interact-fg tw-p-2" data-clipboard-text="{{$file.Name}}">{{svg "octicon-copy" 14}}</button>
<span class="ui label">{{ctx.Locale.Tr "repo.diff.generated"}}</span> {{if $file.IsGenerated}}
{{end}} <span class="ui label">{{ctx.Locale.Tr "repo.diff.generated"}}</span>
{{if $file.IsVendored}} {{end}}
<span class="ui label">{{ctx.Locale.Tr "repo.diff.vendored"}}</span> {{if $file.IsVendored}}
{{end}} <span class="ui label">{{ctx.Locale.Tr "repo.diff.vendored"}}</span>
{{if and $file.Mode $file.OldMode}} {{end}}
{{$old := ctx.Locale.Tr ($file.ModeTranslationKey $file.OldMode)}} {{if and $file.Mode $file.OldMode}}
{{$new := ctx.Locale.Tr ($file.ModeTranslationKey $file.Mode)}} {{$old := ctx.Locale.Tr ($file.ModeTranslationKey $file.OldMode)}}
<span class="tw-ml-4 tw-font-mono">{{ctx.Locale.Tr "git.filemode.changed_filemode" $old $new}}</span> {{$new := ctx.Locale.Tr ($file.ModeTranslationKey $file.Mode)}}
{{else if $file.Mode}} <span class="tw-mx-2 tw-font-mono tw-whitespace-nowrap">{{ctx.Locale.Tr "git.filemode.changed_filemode" $old $new}}</span>
<span class="tw-ml-4 tw-font-mono">{{ctx.Locale.Tr ($file.ModeTranslationKey $file.Mode)}}</span> {{else if $file.Mode}}
{{end}} <span class="tw-mx-2 tw-font-mono tw-whitespace-nowrap">{{ctx.Locale.Tr ($file.ModeTranslationKey $file.Mode)}}</span>
{{end}}
</span>
</div> </div>
<div class="diff-file-header-actions tw-flex tw-items-center tw-gap-1 tw-flex-wrap"> <div class="diff-file-header-actions tw-flex tw-items-center tw-gap-1 tw-flex-wrap">
{{if $showFileViewToggle}} {{if $showFileViewToggle}}

View File

@ -50,8 +50,11 @@
</div> </div>
{{end}} {{end}}
{{template "repo/sub_menu" .}} {{template "repo/sub_menu" .}}
{{$n := len .TreeNames}}
{{$l := Eval $n "-" 1}}
{{$isHomepage := (eq $n 0)}}
<div class="repo-button-row"> <div class="repo-button-row">
<div class="tw-flex tw-items-center tw-flex-wrap tw-gap-y-2"> <div class="tw-flex tw-items-center tw-gap-y-2">
{{template "repo/branch_dropdown" dict "root" . "ContainerClasses" "tw-mr-1"}} {{template "repo/branch_dropdown" dict "root" . "ContainerClasses" "tw-mr-1"}}
{{if and .CanCompareOrPull .IsViewBranch (not .Repository.IsArchived)}} {{if and .CanCompareOrPull .IsViewBranch (not .Repository.IsArchived)}}
{{$cmpBranch := ""}} {{$cmpBranch := ""}}
@ -66,9 +69,7 @@
</a> </a>
{{end}} {{end}}
<!-- Show go to file and breadcrumbs if not on home page --> <!-- Show go to file and breadcrumbs if not on home page -->
{{$n := len .TreeNames}} {{if $isHomepage}}
{{$l := Eval $n "-" 1}}
{{if eq $n 0}}
<a href="{{.Repository.Link}}/find/{{.BranchNameSubURL}}" class="ui compact basic button">{{ctx.Locale.Tr "repo.find_file.go_to_file"}}</a> <a href="{{.Repository.Link}}/find/{{.BranchNameSubURL}}" class="ui compact basic button">{{ctx.Locale.Tr "repo.find_file.go_to_file"}}</a>
{{end}} {{end}}
@ -92,20 +93,20 @@
</button> </button>
{{end}} {{end}}
{{if and (eq $n 0) (.Repository.IsTemplate)}} {{if and $isHomepage (.Repository.IsTemplate)}}
<a role="button" class="ui primary compact button" href="{{AppSubUrl}}/repo/create?template_id={{.Repository.ID}}"> <a role="button" class="ui primary compact button" href="{{AppSubUrl}}/repo/create?template_id={{.Repository.ID}}">
{{ctx.Locale.Tr "repo.use_template"}} {{ctx.Locale.Tr "repo.use_template"}}
</a> </a>
{{end}} {{end}}
{{if ne $n 0}} {{if (not $isHomepage)}}
<span class="breadcrumb repo-path tw-ml-1"> <span class="breadcrumb repo-path tw-ml-1">
<a class="section" href="{{.RepoLink}}/src/{{.BranchNameSubURL}}" title="{{.Repository.Name}}">{{StringUtils.EllipsisString .Repository.Name 30}}</a> <a class="section" href="{{.RepoLink}}/src/{{.BranchNameSubURL}}" title="{{.Repository.Name}}">{{StringUtils.EllipsisString .Repository.Name 30}}</a>
{{- range $i, $v := .TreeNames -}} {{- range $i, $v := .TreeNames -}}
<span class="breadcrumb-divider">/</span> <span class="breadcrumb-divider">/</span>
{{- if eq $i $l -}} {{- if eq $i $l -}}
<span class="active section" title="{{$v}}">{{StringUtils.EllipsisString $v 30}}</span> <span class="active section" title="{{$v}}">{{$v}}</span>
{{- else -}} {{- else -}}
{{$p := index $.Paths $i}}<span class="section"><a href="{{$.BranchLink}}/{{PathEscapeSegments $p}}" title="{{$v}}">{{StringUtils.EllipsisString $v 30}}</a></span> {{$p := index $.Paths $i}}<span class="section"><a href="{{$.BranchLink}}/{{PathEscapeSegments $p}}" title="{{$v}}">{{$v}}</a></span>
{{- end -}} {{- end -}}
{{- end -}} {{- end -}}
</span> </span>
@ -113,7 +114,7 @@
</div> </div>
<div class="tw-flex tw-items-center"> <div class="tw-flex tw-items-center">
<!-- Only show clone panel in repository home page --> <!-- Only show clone panel in repository home page -->
{{if eq $n 0}} {{if $isHomepage}}
<div class="clone-panel ui action tiny input"> <div class="clone-panel ui action tiny input">
{{template "repo/clone_buttons" .}} {{template "repo/clone_buttons" .}}
<button class="ui small jump dropdown icon button" data-tooltip-content="{{ctx.Locale.Tr "repo.more_operations"}}"> <button class="ui small jump dropdown icon button" data-tooltip-content="{{ctx.Locale.Tr "repo.more_operations"}}">
@ -136,7 +137,7 @@
</div> </div>
{{template "repo/cite/cite_modal" .}} {{template "repo/cite/cite_modal" .}}
{{end}} {{end}}
{{if and (ne $n 0) (not .IsViewFile) (not .IsBlame)}} {{if and (not $isHomepage) (not .IsViewFile) (not .IsBlame)}}
<a class="ui button" href="{{.RepoLink}}/commits/{{.BranchNameSubURL}}/{{.TreePath | PathEscapeSegments}}"> <a class="ui button" href="{{.RepoLink}}/commits/{{.BranchNameSubURL}}/{{.TreePath | PathEscapeSegments}}">
{{svg "octicon-history" 16 "tw-mr-2"}}{{ctx.Locale.Tr "repo.file_history"}} {{svg "octicon-history" 16 "tw-mr-2"}}{{ctx.Locale.Tr "repo.file_history"}}
</a> </a>

View File

@ -11,13 +11,13 @@
{{end}} {{end}}
{{if not .ReadmeInList}} {{if not .ReadmeInList}}
<div id="repo-file-commit-box" class="ui top attached header list-header tw-mb-4"> <div id="repo-file-commit-box" class="ui top attached header list-header tw-mb-4 tw-flex tw-justify-between">
<div> <div class="latest-commit">
{{template "repo/latest_commit" .}} {{template "repo/latest_commit" .}}
</div> </div>
{{if .LatestCommit}} {{if .LatestCommit}}
{{if .LatestCommit.Committer}} {{if .LatestCommit.Committer}}
<div class="ui text grey right age"> <div class="text grey age">
{{TimeSince .LatestCommit.Committer.When ctx.Locale}} {{TimeSince .LatestCommit.Committer.When ctx.Locale}}
</div> </div>
{{end}} {{end}}

View File

@ -1,8 +1,12 @@
<table id="repo-files-table" class="ui single line table tw-mt-0" {{if .HasFilesWithoutLatestCommit}}hx-indicator="tr.notready td.message span" hx-trigger="load" hx-swap="morph" hx-post="{{.LastCommitLoaderURL}}"{{end}}> <table id="repo-files-table" class="ui single line table tw-mt-0" {{if .HasFilesWithoutLatestCommit}}hx-indicator="tr.notready td.message span" hx-trigger="load" hx-swap="morph" hx-post="{{.LastCommitLoaderURL}}"{{end}}>
<thead> <thead>
<tr class="commit-list"> <tr class="commit-list">
<th colspan="2"> <th class="tw-overflow-hidden" colspan="2">
{{template "repo/latest_commit" .}} <div class="tw-flex">
<div class="latest-commit">
{{template "repo/latest_commit" .}}
</div>
</div>
</th> </th>
<th class="text grey right age">{{if .LatestCommit}}{{if .LatestCommit.Committer}}{{TimeSince .LatestCommit.Committer.When ctx.Locale}}{{end}}{{end}}</th> <th class="text grey right age">{{if .LatestCommit}}{{if .LatestCommit.Committer}}{{TimeSince .LatestCommit.Committer.When ctx.Locale}}{{end}}{{end}}</th>
</tr> </tr>

View File

@ -0,0 +1 @@
xťŹKnÄ Dłć죱ÁvóEQ˛Ę~nĐ@3Fň đ‰r”\,dŽ<64>^”TĄŇSµĎŹGj|žĹK+DÜĘࢠ$2`ĺ4ÇÉY«”Y”u{‡Xho\Źŕu4E;k- P4<>Q^Hł84Ŕđlk.ü†iă_©ü|gţVžv¨Ă=ĚŤüž|Î-U—q8Ú;—ZJµč,ý<>Nnô_<C3B4>Ő”ę0Ůaě3ľçýŇż TĐmÄ·ěqă1mÄŘŤb˝ňµµŁ^ÇńžÚzşˇ/ďůŇá_Ö5ŐzR'-'É~étl˝

View File

@ -1 +1 @@
0dca5bd9b5d7ef937710e056f575e86c0184ba85 a5bbc0fd39a696feabed2d4cccaf05abbcaf3b02

View File

@ -45,6 +45,7 @@ func TestRepoCloneWiki(t *testing.T) {
assertFileExist(t, filepath.Join(dstPath, "Page-With-Image.md")) assertFileExist(t, filepath.Join(dstPath, "Page-With-Image.md"))
assertFileExist(t, filepath.Join(dstPath, "Page-With-Spaced-Name.md")) assertFileExist(t, filepath.Join(dstPath, "Page-With-Spaced-Name.md"))
assertFileExist(t, filepath.Join(dstPath, "images")) assertFileExist(t, filepath.Join(dstPath, "images"))
assertFileExist(t, filepath.Join(dstPath, "files/Non-Renderable-File.zip"))
assertFileExist(t, filepath.Join(dstPath, "jpeg.jpg")) assertFileExist(t, filepath.Join(dstPath, "jpeg.jpg"))
}) })
}) })

View File

@ -49,6 +49,17 @@ func testGitPush(t *testing.T, u *url.URL) {
}) })
}) })
t.Run("Push branch with options", func(t *testing.T) {
runTestGitPush(t, u, func(t *testing.T, gitPath string) (pushed, deleted []string) {
branchName := "branch-with-options"
doGitCreateBranch(gitPath, branchName)(t)
doGitPushTestRepository(gitPath, "origin", branchName, "-o", "repo.private=true", "-o", "repo.template=true")(t)
pushed = append(pushed, branchName)
return pushed, deleted
})
})
t.Run("Delete branches", func(t *testing.T) { t.Run("Delete branches", func(t *testing.T) {
runTestGitPush(t, u, func(t *testing.T, gitPath string) (pushed, deleted []string) { runTestGitPush(t, u, func(t *testing.T, gitPath string) (pushed, deleted []string) {
doGitPushTestRepository(gitPath, "origin", "master")(t) // make sure master is the default branch instead of a branch we are going to delete doGitPushTestRepository(gitPath, "origin", "master")(t) // make sure master is the default branch instead of a branch we are going to delete

View File

@ -23,8 +23,21 @@
--height-loading: 16rem; --height-loading: 16rem;
--min-height-textarea: 132px; /* padding + 6 lines + border = calc(1.57142em + 6lh + 2px), but lh is not fully supported */ --min-height-textarea: 132px; /* padding + 6 lines + border = calc(1.57142em + 6lh + 2px), but lh is not fully supported */
--tab-size: 4; --tab-size: 4;
--checkbox-size: 16px; /* height and width of checkbox and radio inputs */ --checkbox-size: 15px; /* height and width of checkbox and radio inputs */
--page-spacing: 16px; /* space between page elements */ --page-spacing: 16px; /* space between page elements */
--page-margin-x: 32px; /* minimum space on left and right side of page */
}
@media (min-width: 768px) and (max-width: 1200px) {
:root {
--page-margin-x: 16px;
}
}
@media (max-width: 767.98px) {
:root {
--page-margin-x: 8px;
}
} }
:root * { :root * {
@ -1242,6 +1255,7 @@ overflow-menu .ui.label {
white-space: pre-wrap; white-space: pre-wrap;
word-break: break-all; word-break: break-all;
overflow-wrap: anywhere; overflow-wrap: anywhere;
line-height: inherit; /* needed for inline code preview in markup */
} }
.blame .code-inner { .blame .code-inner {

View File

@ -20,7 +20,7 @@ input[type="radio"] {
.ui.checkbox input[type="checkbox"], .ui.checkbox input[type="checkbox"],
.ui.checkbox input[type="radio"] { .ui.checkbox input[type="radio"] {
position: absolute; position: absolute;
top: 0; top: 1px;
left: 0; left: 0;
width: var(--checkbox-size); width: var(--checkbox-size);
height: var(--checkbox-size); height: var(--checkbox-size);

View File

@ -49,30 +49,11 @@
/* overwrite width of containers inside the main page content div (div with class "page-content") */ /* overwrite width of containers inside the main page content div (div with class "page-content") */
.page-content .ui.ui.ui.container:not(.fluid) { .page-content .ui.ui.ui.container:not(.fluid) {
width: 1280px; width: 1280px;
max-width: calc(100% - 64px); max-width: calc(100% - calc(2 * var(--page-margin-x)));
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
} }
.ui.container.fluid.padded { .ui.container.fluid.padded {
padding: 0 32px; padding: 0 var(--page-margin-x);
}
/* enable fluid page widths for medium size viewports */
@media (min-width: 768px) and (max-width: 1200px) {
.page-content .ui.ui.ui.container:not(.fluid) {
max-width: calc(100% - 32px);
}
.ui.container.fluid.padded {
padding: 0 16px;
}
}
@media (max-width: 767.98px) {
.page-content .ui.ui.ui.container:not(.fluid) {
max-width: calc(100% - 16px);
}
.ui.container.fluid.padded {
padding: 0 8px;
}
} }

View File

@ -126,6 +126,12 @@
cursor: pointer; cursor: pointer;
} }
.ui.list .list > .item [class*="right floated"],
.ui.list > .item [class*="right floated"] {
float: right;
margin: 0 0 0 1em;
}
.ui.menu .ui.list > .item, .ui.menu .ui.list > .item,
.ui.menu .ui.list .list > .item { .ui.menu .ui.list .list > .item {
display: list-item; display: list-item;

View File

@ -177,12 +177,44 @@
} }
} }
.repository.file.list .repo-path { .commit-summary {
word-break: break-word; flex: 1;
overflow-wrap: anywhere;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
} }
.repository.file.list #repo-files-table { .commit-header .commit-summary,
table-layout: fixed; td .commit-summary {
white-space: normal;
}
.latest-commit {
display: flex;
flex: 1;
align-items: center;
overflow: hidden;
text-overflow: ellipsis;
}
@media (max-width: 767.98px) {
.latest-commit .sha {
display: none;
}
.latest-commit .commit-summary {
margin-left: 8px;
}
}
.repo-path {
display: flex;
overflow-wrap: anywhere;
}
/* this is what limits the commit table width to a value that works on all viewport sizes */
#repo-files-table th:first-of-type {
max-width: calc(calc(min(100vw, 1280px)) - 145px - calc(2 * var(--page-margin-x)));
} }
.repository.file.list #repo-files-table thead th { .repository.file.list #repo-files-table thead th {
@ -262,7 +294,6 @@
} }
.repository.file.list #repo-files-table td.age { .repository.file.list #repo-files-table td.age {
width: 120px;
color: var(--color-text-light-1); color: var(--color-text-light-1);
} }
@ -1219,10 +1250,6 @@
margin: 0; margin: 0;
} }
.repository #commits-table td.message {
text-overflow: unset;
}
.repository #commits-table.ui.basic.striped.table tbody tr:nth-child(2n) { .repository #commits-table.ui.basic.striped.table tbody tr:nth-child(2n) {
background-color: var(--color-light) !important; background-color: var(--color-light) !important;
} }
@ -2114,6 +2141,20 @@
padding-bottom: 0 !important; padding-bottom: 0 !important;
} }
.commit-header-buttons {
display: flex;
gap: 4px;
align-items: flex-start;
white-space: nowrap;
}
@media (max-width: 767.98px) {
.commit-header-buttons {
flex-direction: column;
align-items: stretch;
}
}
.settings.webhooks .list > .item:not(:first-child), .settings.webhooks .list > .item:not(:first-child),
.settings.githooks .list > .item:not(:first-child), .settings.githooks .list > .item:not(:first-child),
.settings.actions .list > .item:not(:first-child) { .settings.actions .list > .item:not(:first-child) {
@ -2274,9 +2315,9 @@
} }
.labels-list { .labels-list {
display: flex; display: inline-flex;
flex-wrap: wrap; flex-wrap: wrap;
gap: 0.25em; gap: 2.5px;
} }
.labels-list a { .labels-list a {
@ -2346,7 +2387,7 @@ tbody.commit-list {
.author-wrapper { .author-wrapper {
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
max-width: calc(100% - 50px); max-width: 100%;
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
} }
@ -2371,10 +2412,6 @@ tbody.commit-list {
tr.commit-list { tr.commit-list {
width: 100%; width: 100%;
} }
th .message-wrapper {
display: block;
max-width: calc(100vw - 70px);
}
.author-wrapper { .author-wrapper {
max-width: 80px; max-width: 80px;
} }
@ -2384,27 +2421,18 @@ tbody.commit-list {
tr.commit-list { tr.commit-list {
width: 723px; width: 723px;
} }
th .message-wrapper {
max-width: 120px;
}
} }
@media (min-width: 992px) and (max-width: 1200px) { @media (min-width: 992px) and (max-width: 1200px) {
tr.commit-list { tr.commit-list {
width: 933px; width: 933px;
} }
th .message-wrapper {
max-width: 350px;
}
} }
@media (min-width: 1201px) { @media (min-width: 1201px) {
tr.commit-list { tr.commit-list {
width: 1127px; width: 1127px;
} }
th .message-wrapper {
max-width: 525px;
}
} }
.commit-list .commit-status-link { .commit-list .commit-status-link {
@ -2732,7 +2760,7 @@ tbody.commit-list {
.repository.file.list #repo-files-table .entry td.message, .repository.file.list #repo-files-table .entry td.message,
.repository.file.list #repo-files-table .commit-list td.message, .repository.file.list #repo-files-table .commit-list td.message,
.repository.file.list #repo-files-table .entry span.commit-summary, .repository.file.list #repo-files-table .entry span.commit-summary,
.repository.file.list #repo-files-table .commit-list span.commit-summary { .repository.file.list #repo-files-table .commit-list tr span.commit-summary {
display: none !important; display: none !important;
} }
.repository.view.issue .comment-list .timeline, .repository.view.issue .comment-list .timeline,

View File

@ -30,45 +30,45 @@
--color-primary-alpha-90: #4183c4e1; --color-primary-alpha-90: #4183c4e1;
--color-primary-hover: var(--color-primary-light-1); --color-primary-hover: var(--color-primary-light-1);
--color-primary-active: var(--color-primary-light-2); --color-primary-active: var(--color-primary-light-2);
--color-secondary: #3b444a; --color-secondary: #3b444c;
--color-secondary-dark-1: #424b51; --color-secondary-dark-1: #414b54;
--color-secondary-dark-2: #4a545b; --color-secondary-dark-2: #49545f;
--color-secondary-dark-3: #59646c; --color-secondary-dark-3: #576471;
--color-secondary-dark-4: #6b7681; --color-secondary-dark-4: #677685;
--color-secondary-dark-5: #78858f; --color-secondary-dark-5: #758594;
--color-secondary-dark-6: #87929d; --color-secondary-dark-6: #8392a0;
--color-secondary-dark-7: #939ea9; --color-secondary-dark-7: #929eab;
--color-secondary-dark-8: #a1acb4; --color-secondary-dark-8: #a2acb7;
--color-secondary-dark-9: #aab3bc; --color-secondary-dark-9: #a9b3bd;
--color-secondary-dark-10: #b6bfc8; --color-secondary-dark-10: #b7bfc7;
--color-secondary-dark-11: #c2cbd3; --color-secondary-dark-11: #c5cbd2;
--color-secondary-dark-12: #ccd4dc; --color-secondary-dark-12: #cfd4da;
--color-secondary-dark-13: #cfd7df; --color-secondary-dark-13: #d2d7dc;
--color-secondary-light-1: #2e353b; --color-secondary-light-1: #313940;
--color-secondary-light-2: #2b353e; --color-secondary-light-2: #292f35;
--color-secondary-light-3: #1c2227; --color-secondary-light-3: #1d2226;
--color-secondary-light-4: #161b1f; --color-secondary-light-4: #171b1e;
--color-secondary-alpha-10: #3b444a19; --color-secondary-alpha-10: #3b444c19;
--color-secondary-alpha-20: #3b444a33; --color-secondary-alpha-20: #3b444c33;
--color-secondary-alpha-30: #3b444a4b; --color-secondary-alpha-30: #3b444c4b;
--color-secondary-alpha-40: #3b444a66; --color-secondary-alpha-40: #3b444c66;
--color-secondary-alpha-50: #3b444a80; --color-secondary-alpha-50: #3b444c80;
--color-secondary-alpha-60: #3b444a99; --color-secondary-alpha-60: #3b444c99;
--color-secondary-alpha-70: #3b444ab3; --color-secondary-alpha-70: #3b444cb3;
--color-secondary-alpha-80: #3b444acc; --color-secondary-alpha-80: #3b444ccc;
--color-secondary-alpha-90: #3b444ae1; --color-secondary-alpha-90: #3b444ce1;
--color-secondary-button: var(--color-secondary-dark-4); --color-secondary-button: var(--color-secondary-dark-4);
--color-secondary-hover: var(--color-secondary-dark-3); --color-secondary-hover: var(--color-secondary-dark-3);
--color-secondary-active: var(--color-secondary-dark-2); --color-secondary-active: var(--color-secondary-dark-2);
/* console colors - used for actions console and console files */ /* console colors - used for actions console and console files */
--color-console-fg: #f8f8f9; --color-console-fg: #f7f8f9;
--color-console-fg-subtle: #bec4c8; --color-console-fg-subtle: #bdc4cc;
--color-console-bg: #171b1e; --color-console-bg: #171b1e;
--color-console-border: #2e353b; --color-console-border: #2e353b;
--color-console-hover-bg: #292d31; --color-console-hover-bg: #272d33;
--color-console-active-bg: #2e353b; --color-console-active-bg: #2e353b;
--color-console-menu-bg: #252b30; --color-console-menu-bg: #262b31;
--color-console-menu-border: #424b51; --color-console-menu-border: #414b55;
/* named colors */ /* named colors */
--color-red: #cc4848; --color-red: #cc4848;
--color-orange: #cc580c; --color-orange: #cc580c;
@ -122,7 +122,7 @@
--color-brown-dark-2: #835b42; --color-brown-dark-2: #835b42;
--color-black-dark-2: #272930; --color-black-dark-2: #272930;
/* ansi colors used for actions console and console files */ /* ansi colors used for actions console and console files */
--color-ansi-black: #1d2328; --color-ansi-black: #1e2327;
--color-ansi-red: #cc4848; --color-ansi-red: #cc4848;
--color-ansi-green: #87ab63; --color-ansi-green: #87ab63;
--color-ansi-yellow: #cc9903; --color-ansi-yellow: #cc9903;
@ -139,8 +139,8 @@
--color-ansi-bright-cyan: #00b6ad; --color-ansi-bright-cyan: #00b6ad;
--color-ansi-bright-white: var(--color-console-fg); --color-ansi-bright-white: var(--color-console-fg);
/* other colors */ /* other colors */
--color-grey: #384147; --color-grey: #384149;
--color-grey-light: #828f99; --color-grey-light: #818f9e;
--color-gold: #b1983b; --color-gold: #b1983b;
--color-white: #ffffff; --color-white: #ffffff;
--color-diff-removed-word-bg: #6f3333; --color-diff-removed-word-bg: #6f3333;
@ -180,55 +180,55 @@
--color-orange-badge-hover-bg: #f2711c4d; --color-orange-badge-hover-bg: #f2711c4d;
--color-git: #f05133; --color-git: #f05133;
/* target-based colors */ /* target-based colors */
--color-body: #1c1f25; --color-body: #1b1f23;
--color-box-header: #1a1d1f; --color-box-header: #1a1d1f;
--color-box-body: #14171a; --color-box-body: #14171a;
--color-box-body-highlight: #1c2227; --color-box-body-highlight: #1e2226;
--color-text-dark: #f8f8f9; --color-text-dark: #f7f8f9;
--color-text: #d1d5d8; --color-text: #d0d5da;
--color-text-light: #bdc3c7; --color-text-light: #bcc3cb;
--color-text-light-1: #a8afb5; --color-text-light-1: #a5afb9;
--color-text-light-2: #929ba2; --color-text-light-2: #8f9ba8;
--color-text-light-3: #7c8790; --color-text-light-3: #788797;
--color-footer: var(--color-nav-bg); --color-footer: var(--color-nav-bg);
--color-timeline: #353c42; --color-timeline: #343c44;
--color-input-text: var(--color-text-dark); --color-input-text: var(--color-text-dark);
--color-input-background: #151a1e; --color-input-background: #171a1e;
--color-input-toggle-background: #2e353b; --color-input-toggle-background: #2e353c;
--color-input-border: var(--color-secondary); --color-input-border: var(--color-secondary);
--color-input-border-hover: var(--color-secondary-dark-1); --color-input-border-hover: var(--color-secondary-dark-1);
--color-light: #00001728; --color-light: #00001728;
--color-light-mimic-enabled: rgba(0, 0, 0, calc(40 / 255 * 222 / 255 / var(--opacity-disabled))); --color-light-mimic-enabled: rgba(0, 0, 0, calc(40 / 255 * 222 / 255 / var(--opacity-disabled)));
--color-light-border: #e8e8ff28; --color-light-border: #e8f3ff28;
--color-hover: #e8e8ff19; --color-hover: #e8f3ff19;
--color-active: #e8e8ff24; --color-active: #e8f3ff24;
--color-menu: #151a1e; --color-menu: #171a1e;
--color-card: #151a1e; --color-card: #171a1e;
--color-markup-table-row: #e8e8ff0f; --color-markup-table-row: #e8f3ff0f;
--color-markup-code-block: #e8e8ff12; --color-markup-code-block: #e8f3ff12;
--color-markup-code-inline: #e8e8ff28; --color-markup-code-inline: #e8f3ff28;
--color-button: #151a1e; --color-button: #171a1e;
--color-code-bg: #14171a; --color-code-bg: #14171a;
--color-shadow: #00001758; --color-shadow: #00001758;
--color-secondary-bg: #2f3138; --color-secondary-bg: #2a3137;
--color-expand-button: #2b353e; --color-expand-button: #2f363d;
--color-placeholder-text: var(--color-text-light-3); --color-placeholder-text: var(--color-text-light-3);
--color-editor-line-highlight: var(--color-primary-light-5); --color-editor-line-highlight: var(--color-primary-light-5);
--color-project-board-bg: var(--color-secondary-light-2); --color-project-board-bg: var(--color-secondary-light-2);
--color-caret: var(--color-text); /* should ideally be --color-text-dark, see #15651 */ --color-caret: var(--color-text); /* should ideally be --color-text-dark, see #15651 */
--color-reaction-bg: #e8e8ff12; --color-reaction-bg: #e8f3ff12;
--color-reaction-hover-bg: var(--color-primary-light-4); --color-reaction-hover-bg: var(--color-primary-light-4);
--color-reaction-active-bg: var(--color-primary-light-5); --color-reaction-active-bg: var(--color-primary-light-5);
--color-tooltip-text: #fafafb; --color-tooltip-text: #f9fafb;
--color-tooltip-bg: #000017f0; --color-tooltip-bg: #000b17f0;
--color-nav-bg: #16191c; --color-nav-bg: #16191d;
--color-nav-hover-bg: var(--color-secondary-light-1); --color-nav-hover-bg: var(--color-secondary-light-1);
--color-nav-text: var(--color-text); --color-nav-text: var(--color-text);
--color-secondary-nav-bg: #181c20; --color-secondary-nav-bg: #181c20;
--color-label-text: var(--color-text); --color-label-text: var(--color-text);
--color-label-bg: #73828e4b; --color-label-bg: #7282924b;
--color-label-hover-bg: #73828ea0; --color-label-hover-bg: #728292a0;
--color-label-active-bg: #73828eff; --color-label-active-bg: #728292ff;
--color-accent: var(--color-primary-light-1); --color-accent: var(--color-primary-light-1);
--color-small-accent: var(--color-primary-light-5); --color-small-accent: var(--color-primary-light-5);
--color-highlight-fg: #87651e; --color-highlight-fg: #87651e;

View File

@ -61,14 +61,14 @@
--color-secondary-hover: var(--color-secondary-dark-5); --color-secondary-hover: var(--color-secondary-dark-5);
--color-secondary-active: var(--color-secondary-dark-6); --color-secondary-active: var(--color-secondary-dark-6);
/* console colors - used for actions console and console files */ /* console colors - used for actions console and console files */
--color-console-fg: #f8f8f9; --color-console-fg: #f7f8f9;
--color-console-fg-subtle: #bec4c8; --color-console-fg-subtle: #bdc4cc;
--color-console-bg: #171b1e; --color-console-bg: #171b1e;
--color-console-border: #2e353b; --color-console-border: #2e353b;
--color-console-hover-bg: #292d31; --color-console-hover-bg: #272d33;
--color-console-active-bg: #2e353b; --color-console-active-bg: #2e353b;
--color-console-menu-bg: #252b30; --color-console-menu-bg: #262b31;
--color-console-menu-border: #424b51; --color-console-menu-border: #414b55;
/* named colors */ /* named colors */
--color-red: #db2828; --color-red: #db2828;
--color-orange: #f2711c; --color-orange: #f2711c;
@ -81,7 +81,7 @@
--color-purple: #a333c8; --color-purple: #a333c8;
--color-pink: #e03997; --color-pink: #e03997;
--color-brown: #a5673f; --color-brown: #a5673f;
--color-black: #191c1d; --color-black: #1d2328;
/* light variants - produced via Sass scale-color(color, $lightness: +25%) */ /* light variants - produced via Sass scale-color(color, $lightness: +25%) */
--color-red-light: #e45e5e; --color-red-light: #e45e5e;
--color-orange-light: #f59555; --color-orange-light: #f59555;
@ -94,7 +94,7 @@
--color-purple-light: #bb64d8; --color-purple-light: #bb64d8;
--color-pink-light: #e86bb1; --color-pink-light: #e86bb1;
--color-brown-light: #c58b66; --color-brown-light: #c58b66;
--color-black-light: #525558; --color-black-light: #4b5b68;
/* dark 1 variants - produced via Sass scale-color(color, $lightness: -10%) */ /* dark 1 variants - produced via Sass scale-color(color, $lightness: -10%) */
--color-red-dark-1: #c82121; --color-red-dark-1: #c82121;
--color-orange-dark-1: #e6630d; --color-orange-dark-1: #e6630d;
@ -107,7 +107,7 @@
--color-purple-dark-1: #932eb4; --color-purple-dark-1: #932eb4;
--color-pink-dark-1: #db228a; --color-pink-dark-1: #db228a;
--color-brown-dark-1: #955d39; --color-brown-dark-1: #955d39;
--color-black-dark-1: #16191c; --color-black-dark-1: #2c3339;
/* dark 2 variants - produced via Sass scale-color(color, $lightness: -20%) */ /* dark 2 variants - produced via Sass scale-color(color, $lightness: -20%) */
--color-red-dark-2: #b11e1e; --color-red-dark-2: #b11e1e;
--color-orange-dark-2: #cc580c; --color-orange-dark-2: #cc580c;
@ -122,7 +122,7 @@
--color-brown-dark-2: #845232; --color-brown-dark-2: #845232;
--color-black-dark-2: #131619; --color-black-dark-2: #131619;
/* ansi colors used for actions console and console files */ /* ansi colors used for actions console and console files */
--color-ansi-black: #1f2326; --color-ansi-black: #1e2327;
--color-ansi-red: #cc4848; --color-ansi-red: #cc4848;
--color-ansi-green: #87ab63; --color-ansi-green: #87ab63;
--color-ansi-yellow: #cc9903; --color-ansi-yellow: #cc9903;