mirror of
https://github.com/go-gitea/gitea.git
synced 2026-08-10 07:15:42 +02:00
Merge remote-tracking branch 'upstream/main' into limit-repo-size
This commit is contained in:
+3
-3
@@ -22,7 +22,7 @@ plugins:
|
||||
- eslint-plugin-wc
|
||||
|
||||
env:
|
||||
es2022: true
|
||||
es2024: true
|
||||
node: true
|
||||
|
||||
overrides:
|
||||
@@ -156,7 +156,7 @@ rules:
|
||||
import/no-restricted-paths: [0]
|
||||
import/no-self-import: [2]
|
||||
import/no-unassigned-import: [0]
|
||||
import/no-unresolved: [2, {commonjs: true, ignore: ["\\?.+$"]}]
|
||||
import/no-unresolved: [2, {commonjs: true, ignore: [\?.+$, ^vitest/]}]
|
||||
import/no-unused-modules: [2, {unusedExports: true}]
|
||||
import/no-useless-path-segments: [2, {commonjs: true}]
|
||||
import/no-webpack-loader-syntax: [2]
|
||||
@@ -693,7 +693,7 @@ rules:
|
||||
unicorn/prefer-dom-node-remove: [2]
|
||||
unicorn/prefer-dom-node-text-content: [2]
|
||||
unicorn/prefer-event-target: [2]
|
||||
unicorn/prefer-export-from: [2, {ignoreUsedVariables: true}]
|
||||
unicorn/prefer-export-from: [0]
|
||||
unicorn/prefer-includes: [2]
|
||||
unicorn/prefer-json-parse-buffer: [0]
|
||||
unicorn/prefer-keyboard-event-key: [2]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: Feature Request
|
||||
description: Got an idea for a feature that Gitea doesn't have currently? Submit your idea here!
|
||||
labels: ["kind/feature", "kind/proposal"]
|
||||
labels: ["kind/proposal"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
|
||||
+15
-10
@@ -77,16 +77,21 @@ linters-settings:
|
||||
extra-rules: true
|
||||
lang-version: "1.20"
|
||||
depguard:
|
||||
list-type: denylist
|
||||
# Check the list against standard lib.
|
||||
include-go-root: true
|
||||
packages-with-error-message:
|
||||
- encoding/json: "use gitea's modules/json instead of encoding/json"
|
||||
- github.com/unknwon/com: "use gitea's util and replacements"
|
||||
- io/ioutil: "use os or io instead"
|
||||
- golang.org/x/exp: "it's experimental and unreliable."
|
||||
- code.gitea.io/gitea/modules/git/internal: "do not use the internal package, use AddXxx function instead"
|
||||
- gopkg.in/ini.v1: "do not use the ini package, use gitea's config system instead"
|
||||
rules:
|
||||
main:
|
||||
deny:
|
||||
- pkg: encoding/json
|
||||
desc: use gitea's modules/json instead of encoding/json
|
||||
- pkg: github.com/unknwon/com
|
||||
desc: use gitea's util and replacements
|
||||
- pkg: io/ioutil
|
||||
desc: use os or io instead
|
||||
- pkg: golang.org/x/exp
|
||||
desc: it's experimental and unreliable
|
||||
- pkg: code.gitea.io/gitea/modules/git/internal
|
||||
desc: do not use the internal package, use AddXxx function instead
|
||||
- pkg: gopkg.in/ini.v1
|
||||
desc: do not use the ini package, use gitea's config system instead
|
||||
|
||||
issues:
|
||||
max-issues-per-linter: 0
|
||||
|
||||
@@ -4,6 +4,54 @@ This changelog goes through all the changes that have been made in each release
|
||||
without substantial changes to our git log; to see the highlights of what has
|
||||
been added to each release, please refer to the [blog](https://blog.gitea.io).
|
||||
|
||||
## [1.19.4](https://github.com/go-gitea/gitea/releases/tag/v1.19.4) - 2023-07-04
|
||||
|
||||
* SECURITY
|
||||
* Fix open redirect check for more cases (#25143) (#25155)
|
||||
* API
|
||||
* Return `404` in the API if the requested webhooks were not found (#24823) (#24830)
|
||||
* Fix `organization` field being `null` in `GET /api/v1/teams/{id}` (#24694) (#24696)
|
||||
* ENHANCEMENTS
|
||||
* Set `--font-weight-bold` to 600 (#24840)
|
||||
* Make mailer SMTP check have timed context (#24751) (#24759)
|
||||
* Do not select line numbers when selecting text from the action run logs (#24594) (#24596)
|
||||
* BUGFIXES
|
||||
* Fix bug when change user name (#25637) (#25645)
|
||||
* Fix task list checkbox toggle to work with YAML front matter (#25184) (#25236)
|
||||
* Hide limited users if viewed by anonymous ghost (#25214) (#25224)
|
||||
* Add `WithPullRequest` for `actionsNotifier` (#25144) (#25196)
|
||||
* Fix parallelly generating index failure with Mysql (#24567) (#25081)
|
||||
* GitLab migration: Sanitize response for reaction list (#25054) (#25059)
|
||||
* Fix users cannot visit issue attachment bug (#25019) (#25027)
|
||||
* Fix missing reference prefix of commits when sync mirror repository (#24994)
|
||||
* Only validate changed columns when update user (#24867) (#24903)
|
||||
* Make DeleteIssue use correct context (#24885)
|
||||
* Fix topics deleted via API not being deleted in org page (#24825) (#24829)
|
||||
* Fix Actions being enabled accidentally (#24802) (#24810)
|
||||
* Fix missed table name on iterate lfs meta objects (#24768) (#24774)
|
||||
* Fix safari cookie session bug (#24772)
|
||||
* Respect original content when creating secrets (#24745) (#24746)
|
||||
* Fix Pull Mirror out-of-sync bugs (#24732) (#24733)
|
||||
* Fix run list broken when trigger user deleted (#24706) (#24709)
|
||||
* Fix issues list page multiple selection update milestones (#24660) (#24663)
|
||||
* Fix: release page for empty or non-existing target (#24659)
|
||||
* Fix close org projects (#24588) (#24591)
|
||||
* Refresh the refernce of the closed PR when reopening (#24231) (#24587)
|
||||
* Fix the permission of team's `Actions` unit issue (#24536) (#24545)
|
||||
* Bump go.etcd.io/bbolt and blevesearch deps (#23062) (#24519)
|
||||
* Fix new wiki page mirror (#24518)
|
||||
* Match unqualified references when syncing pulls as well (#23070)
|
||||
* DOCS
|
||||
* Change branch name from master to main in some documents' links (#25126) (#25139)
|
||||
* Remove unnecessary content on docs (#24976) (#25001)
|
||||
* Unify doc links to use paths relative to doc folder (#24979) (#25000)
|
||||
* Fix docs documenting invalid `@every` for `OLDER_THAN` cron settings (#24695) (#24698)
|
||||
* MISC
|
||||
* Merge different languages for language stats (#24900) (#24921)
|
||||
* Hiding Secrets options when Actions feature is disabled (#24792)
|
||||
* Improve decryption failure message (#24573) (#24575)
|
||||
* Makefile: Use portable !, not GNUish -not, with find(1). (#24565) (#24572)
|
||||
|
||||
## [1.19.3](https://github.com/go-gitea/gitea/releases/tag/1.19.3) - 2023-05-03
|
||||
|
||||
* SECURITY
|
||||
|
||||
@@ -52,3 +52,5 @@ Xinyi Gong <hestergong@gmail.com> (@HesterG)
|
||||
wxiaoguang <wxiaoguang@gmail.com> (@wxiaoguang)
|
||||
Gary Moon <gary@garymoon.net> (@garymoon)
|
||||
Philip Peterson <philip.c.peterson@gmail.com> (@philip-peterson)
|
||||
Denys Konovalov <kontakt@denyskon.de> (@denyskon)
|
||||
Punit Inani <punitinani1@gmail.com> (@puni9869)
|
||||
|
||||
@@ -25,17 +25,17 @@ COMMA := ,
|
||||
|
||||
XGO_VERSION := go-1.20.x
|
||||
|
||||
AIR_PACKAGE ?= github.com/cosmtrek/air@v1.43.0
|
||||
AIR_PACKAGE ?= github.com/cosmtrek/air@v1.44.0
|
||||
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/cmd/editorconfig-checker@2.7.0
|
||||
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.5.0
|
||||
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.52.2
|
||||
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.53.3
|
||||
GXZ_PAGAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11
|
||||
MISSPELL_PACKAGE ?= github.com/client9/misspell/cmd/misspell@v0.3.4
|
||||
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.30.4
|
||||
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.30.5
|
||||
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
|
||||
GO_LICENSES_PACKAGE ?= github.com/google/go-licenses@v1.6.0
|
||||
GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@latest
|
||||
ACTIONLINT_PACKAGE ?= github.com/rhysd/actionlint/cmd/actionlint@latest
|
||||
GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v0.2.0
|
||||
ACTIONLINT_PACKAGE ?= github.com/rhysd/actionlint/cmd/actionlint@v1.6.25
|
||||
|
||||
DOCKER_IMAGE ?= gitea/gitea
|
||||
DOCKER_TAG ?= latest
|
||||
|
||||
@@ -25,7 +25,7 @@ import (
|
||||
|
||||
var optionLogVerbose bool
|
||||
|
||||
func logVerbose(msg string, args ...interface{}) {
|
||||
func logVerbose(msg string, args ...any) {
|
||||
if optionLogVerbose {
|
||||
log.Printf(msg, args...)
|
||||
}
|
||||
|
||||
+3
-3
@@ -63,7 +63,7 @@ Outputs to 'cert.pem' and 'key.pem' and will overwrite existing files.`,
|
||||
},
|
||||
}
|
||||
|
||||
func publicKey(priv interface{}) interface{} {
|
||||
func publicKey(priv any) any {
|
||||
switch k := priv.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
return &k.PublicKey
|
||||
@@ -74,7 +74,7 @@ func publicKey(priv interface{}) interface{} {
|
||||
}
|
||||
}
|
||||
|
||||
func pemBlockForKey(priv interface{}) *pem.Block {
|
||||
func pemBlockForKey(priv any) *pem.Block {
|
||||
switch k := priv.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(k)}
|
||||
@@ -94,7 +94,7 @@ func runCert(c *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
var priv interface{}
|
||||
var priv any
|
||||
var err error
|
||||
switch c.String("ecdsa-curve") {
|
||||
case "":
|
||||
|
||||
+2
-2
@@ -161,7 +161,7 @@ It can be used for backup and capture Gitea server image to send to maintainer`,
|
||||
},
|
||||
}
|
||||
|
||||
func fatal(format string, args ...interface{}) {
|
||||
func fatal(format string, args ...any) {
|
||||
fmt.Fprintf(os.Stderr, format+"\n", args...)
|
||||
log.Fatal(format, args...)
|
||||
}
|
||||
@@ -236,7 +236,7 @@ func runDump(ctx *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
var iface interface{}
|
||||
var iface any
|
||||
if fileName == "-" {
|
||||
iface, err = archiver.ByExtension(fmt.Sprintf(".%s", outType))
|
||||
} else {
|
||||
|
||||
@@ -178,7 +178,7 @@ func runAddConnLogger(c *cli.Context) error {
|
||||
defer cancel()
|
||||
|
||||
setup(ctx, c.Bool("debug"))
|
||||
vals := map[string]interface{}{}
|
||||
vals := map[string]any{}
|
||||
mode := "conn"
|
||||
vals["net"] = "tcp"
|
||||
if c.IsSet("protocol") {
|
||||
@@ -208,7 +208,7 @@ func runAddFileLogger(c *cli.Context) error {
|
||||
defer cancel()
|
||||
|
||||
setup(ctx, c.Bool("debug"))
|
||||
vals := map[string]interface{}{}
|
||||
vals := map[string]any{}
|
||||
mode := "file"
|
||||
if c.IsSet("filename") {
|
||||
vals["filename"] = c.String("filename")
|
||||
@@ -236,7 +236,7 @@ func runAddFileLogger(c *cli.Context) error {
|
||||
return commonAddLogger(c, mode, vals)
|
||||
}
|
||||
|
||||
func commonAddLogger(c *cli.Context, mode string, vals map[string]interface{}) error {
|
||||
func commonAddLogger(c *cli.Context, mode string, vals map[string]any) error {
|
||||
if len(c.String("level")) > 0 {
|
||||
vals["level"] = log.LevelFromString(c.String("level")).String()
|
||||
}
|
||||
|
||||
+1
-1
@@ -95,7 +95,7 @@ var (
|
||||
|
||||
// fail prints message to stdout, it's mainly used for git serv and git hook commands.
|
||||
// The output will be passed to git client and shown to user.
|
||||
func fail(ctx context.Context, userMessage, logMsgFmt string, args ...interface{}) error {
|
||||
func fail(ctx context.Context, userMessage, logMsgFmt string, args ...any) error {
|
||||
if userMessage == "" {
|
||||
userMessage = "Internal Server Error (no specific error)"
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
@@ -13,9 +12,6 @@ import (
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
// EnvironmentPrefix environment variables prefixed with this represent ini values to write
|
||||
const EnvironmentPrefix = "GITEA"
|
||||
|
||||
func main() {
|
||||
app := cli.NewApp()
|
||||
app.Name = "environment-to-ini"
|
||||
@@ -70,15 +66,6 @@ func main() {
|
||||
Value: "",
|
||||
Usage: "Destination file to write to",
|
||||
},
|
||||
cli.BoolFlag{
|
||||
Name: "clear",
|
||||
Usage: "Clears the matched variables from the environment",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "prefix, p",
|
||||
Value: EnvironmentPrefix,
|
||||
Usage: "Environment prefix to look for - will be suffixed by __ (2 underscores)",
|
||||
},
|
||||
}
|
||||
app.Action = runEnvironmentToIni
|
||||
err := app.Run(os.Args)
|
||||
@@ -99,9 +86,7 @@ func runEnvironmentToIni(c *cli.Context) error {
|
||||
log.Fatal("Failed to load custom conf '%s': %v", setting.CustomConf, err)
|
||||
}
|
||||
|
||||
prefixGitea := c.String("prefix") + "__"
|
||||
suffixFile := "__FILE"
|
||||
changed := setting.EnvironmentToConfig(cfg, prefixGitea, suffixFile, os.Environ())
|
||||
changed := setting.EnvironmentToConfig(cfg, os.Environ())
|
||||
|
||||
// try to save the config file
|
||||
destination := c.String("out")
|
||||
@@ -116,19 +101,5 @@ func runEnvironmentToIni(c *cli.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
// clear Gitea's specific environment variables if requested
|
||||
if c.Bool("clear") {
|
||||
for _, kv := range os.Environ() {
|
||||
idx := strings.IndexByte(kv, '=')
|
||||
if idx < 0 {
|
||||
continue
|
||||
}
|
||||
eKey := kv[:idx]
|
||||
if strings.HasPrefix(eKey, prefixGitea) {
|
||||
_ = os.Unsetenv(eKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -193,8 +193,8 @@ RUN_USER = ; git
|
||||
;; Use `ssh-keygen` to parse public SSH keys. The value is passed to the shell. By default, Gitea does the parsing itself.
|
||||
;SSH_KEYGEN_PATH =
|
||||
;;
|
||||
;; Enable SSH Authorized Key Backup when rewriting all keys, default is true
|
||||
;SSH_AUTHORIZED_KEYS_BACKUP = true
|
||||
;; Enable SSH Authorized Key Backup when rewriting all keys, default is false
|
||||
;SSH_AUTHORIZED_KEYS_BACKUP = false
|
||||
;;
|
||||
;; Determines which principals to allow
|
||||
;; - empty: if SSH_TRUSTED_USER_CA_KEYS is empty this will default to off, otherwise will default to email, username.
|
||||
@@ -303,7 +303,10 @@ RUN_USER = ; git
|
||||
;;
|
||||
;;
|
||||
;; LFS authentication secret, change this yourself
|
||||
LFS_JWT_SECRET =
|
||||
;LFS_JWT_SECRET =
|
||||
;;
|
||||
;; Alternative location to specify LFS authentication secret. You cannot specify both this and LFS_JWT_SECRET, and must pick one
|
||||
;LFS_JWT_SECRET_URI = file:/etc/gitea/lfs_jwt_secret
|
||||
;;
|
||||
;; LFS authentication validity period (in time.Duration), pushes taking longer than this may fail.
|
||||
;LFS_HTTP_AUTH_EXPIRY = 24h
|
||||
@@ -527,6 +530,9 @@ ENABLE = true
|
||||
;; This setting is only needed if JWT_SIGNING_ALGORITHM is set to HS256, HS384 or HS512.
|
||||
;JWT_SECRET =
|
||||
;;
|
||||
;; Alternative location to specify OAuth2 authentication secret. You cannot specify both this and JWT_SECRET, and must pick one
|
||||
;JWT_SECRET_URI = file:/etc/gitea/oauth2_jwt_secret
|
||||
;;
|
||||
;; Lifetime of an OAuth2 access token in seconds
|
||||
;ACCESS_TOKEN_EXPIRATION_TIME = 3600
|
||||
;;
|
||||
@@ -2550,8 +2556,8 @@ LEVEL = Info
|
||||
;; Enable/Disable actions capabilities
|
||||
;ENABLED = false
|
||||
;;
|
||||
;; Default address to get action plugins, e.g. the default value means downloading from "https://gitea.com/actions/checkout" for "uses: actions/checkout@v3"
|
||||
;DEFAULT_ACTIONS_URL = https://gitea.com
|
||||
;; Default platform to get action plugins, `github` for `https://github.com`, `self` for the current Gitea instance.
|
||||
;DEFAULT_ACTIONS_URL = github
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
@@ -2,7 +2,15 @@
|
||||
|
||||
if [ ! -d /data/git/.ssh ]; then
|
||||
mkdir -p /data/git/.ssh
|
||||
chmod 700 /data/git/.ssh
|
||||
fi
|
||||
|
||||
# Set the correct permissions on the .ssh directory and authorized_keys file,
|
||||
# or sshd will refuse to use them and lead to clone/push/pull failures.
|
||||
# It could happen when users have copied their data to a new volume and changed the file permission by accident,
|
||||
# and it would be very hard to troubleshoot unless users know how to check the logs of sshd which is started by s6.
|
||||
chmod 700 /data/git/.ssh
|
||||
if [ -f /data/git/.ssh/authorized_keys ]; then
|
||||
chmod 600 /data/git/.ssh/authorized_keys
|
||||
fi
|
||||
|
||||
if [ ! -f /data/git/.ssh/environment ]; then
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#
|
||||
# And place the original in /usr/lib/gitea with working files in /data/gitea
|
||||
GITEA="/app/gitea/gitea"
|
||||
WORK_DIR="/app/gitea"
|
||||
WORK_DIR="/data/gitea"
|
||||
CUSTOM_PATH="/data/gitea"
|
||||
|
||||
# Provide docker defaults
|
||||
|
||||
@@ -339,7 +339,7 @@ The following configuration set `Content-Type: application/vnd.android.package-a
|
||||
- `SSH_LISTEN_PORT`: **%(SSH\_PORT)s**: Port for the built-in SSH server.
|
||||
- `SSH_ROOT_PATH`: **~/.ssh**: Root path of SSH directory.
|
||||
- `SSH_CREATE_AUTHORIZED_KEYS_FILE`: **true**: Gitea will create a authorized_keys file by default when it is not using the internal ssh server. If you intend to use the AuthorizedKeysCommand functionality then you should turn this off.
|
||||
- `SSH_AUTHORIZED_KEYS_BACKUP`: **true**: Enable SSH Authorized Key Backup when rewriting all keys, default is true.
|
||||
- `SSH_AUTHORIZED_KEYS_BACKUP`: **false**: Enable SSH Authorized Key Backup when rewriting all keys, default is false.
|
||||
- `SSH_TRUSTED_USER_CA_KEYS`: **\<empty\>**: Specifies the public keys of certificate authorities that are trusted to sign user certificates for authentication. Multiple keys should be comma separated. E.g.`ssh-<algorithm> <key>` or `ssh-<algorithm> <key1>, ssh-<algorithm> <key2>`. For more information see `TrustedUserCAKeys` in the sshd config man pages. When empty no file will be created and `SSH_AUTHORIZED_PRINCIPALS_ALLOW` will default to `off`.
|
||||
- `SSH_TRUSTED_USER_CA_KEYS_FILENAME`: **`RUN_USER`/.ssh/gitea-trusted-user-ca-keys.pem**: Absolute path of the `TrustedUserCaKeys` file Gitea will manage. If you're running your own ssh server and you want to use the Gitea managed file you'll also need to modify your sshd_config to point to this file. The official docker image will automatically work without further configuration.
|
||||
- `SSH_AUTHORIZED_PRINCIPALS_ALLOW`: **off** or **username, email**: \[off, username, email, anything\]: Specify the principals values that users are allowed to use as principal. When set to `anything` no checks are done on the principal string. When set to `off` authorized principal are not allowed to be set.
|
||||
@@ -371,6 +371,7 @@ The following configuration set `Content-Type: application/vnd.android.package-a
|
||||
- `LFS_START_SERVER`: **false**: Enables Git LFS support.
|
||||
- `LFS_CONTENT_PATH`: **%(APP_DATA_PATH)s/lfs**: Default LFS content path. (if it is on local storage.) **DEPRECATED** use settings in `[lfs]`.
|
||||
- `LFS_JWT_SECRET`: **\<empty\>**: LFS authentication secret, change this a unique string.
|
||||
- `LFS_JWT_SECRET_URI`: **\<empty\>**: Instead of defining LFS_JWT_SECRET in the configuration, this configuration option can be used to give Gitea a path to a file that contains the secret (example value: `file:/etc/gitea/lfs_jwt_secret`)
|
||||
- `LFS_HTTP_AUTH_EXPIRY`: **24h**: LFS authentication validity period in time.Duration, pushes taking longer than this may fail.
|
||||
- `LFS_MAX_FILE_SIZE`: **0**: Maximum allowed LFS file size in bytes (Set to 0 for no limit).
|
||||
- `LFS_LOCKS_PAGING_NUM`: **50**: Maximum number of LFS Locks returned per page.
|
||||
@@ -1100,6 +1101,7 @@ This section only does "set" config, a removed config key from this section won'
|
||||
- `INVALIDATE_REFRESH_TOKENS`: **false**: Check if refresh token has already been used
|
||||
- `JWT_SIGNING_ALGORITHM`: **RS256**: Algorithm used to sign OAuth2 tokens. Valid values: \[`HS256`, `HS384`, `HS512`, `RS256`, `RS384`, `RS512`, `ES256`, `ES384`, `ES512`\]
|
||||
- `JWT_SECRET`: **\<empty\>**: OAuth2 authentication secret for access and refresh tokens, change this to a unique string. This setting is only needed if `JWT_SIGNING_ALGORITHM` is set to `HS256`, `HS384` or `HS512`.
|
||||
- `JWT_SECRET_URI`: **\<empty\>**: Instead of defining JWT_SECRET in the configuration, this configuration option can be used to give Gitea a path to a file that contains the secret (example value: `file:/etc/gitea/oauth2_jwt_secret`)
|
||||
- `JWT_SIGNING_PRIVATE_KEY_FILE`: **jwt/private.pem**: Private key file path used to sign OAuth2 tokens. The path is relative to `APP_DATA_PATH`. This setting is only needed if `JWT_SIGNING_ALGORITHM` is set to `RS256`, `RS384`, `RS512`, `ES256`, `ES384` or `ES512`. The file must contain a RSA or ECDSA private key in the PKCS8 format. If no key exists a 4096 bit key will be created for you.
|
||||
- `MAX_TOKEN_LENGTH`: **32767**: Maximum length of token/cookie to accept from OAuth2 provider
|
||||
|
||||
@@ -1379,39 +1381,22 @@ PROXY_HOSTS = *.github.com
|
||||
## Actions (`actions`)
|
||||
|
||||
- `ENABLED`: **false**: Enable/Disable actions capabilities
|
||||
- `DEFAULT_ACTIONS_URL`: **https://gitea.com**: Default address to get action plugins, e.g. the default value means downloading from "<https://gitea.com/actions/checkout>" for "uses: actions/checkout@v3"
|
||||
- `DEFAULT_ACTIONS_URL`: **github**: Default platform to get action plugins, `github` for `https://github.com`, `self` for the current Gitea instance.
|
||||
- `STORAGE_TYPE`: **local**: Storage type for actions logs, `local` for local disk or `minio` for s3 compatible object storage service, default is `local` or other name defined with `[storage.xxx]`
|
||||
- `MINIO_BASE_PATH`: **actions_log/**: Minio base path on the bucket only available when STORAGE_TYPE is `minio`
|
||||
|
||||
`DEFAULT_ACTIONS_URL` indicates where should we find the relative path action plugin. i.e. when use an action in a workflow file like
|
||||
`DEFAULT_ACTIONS_URL` indicates where the Gitea Actions runners should find the actions with relative path.
|
||||
For example, `uses: actions/checkout@v3` means `https://github.com/actions/checkout@v3` since the value of `DEFAULT_ACTIONS_URL` is `github`.
|
||||
And it can be changed to `self` to make it `root_url_of_your_gitea/actions/checkout@v3`.
|
||||
|
||||
```yaml
|
||||
name: versions
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- releases/*
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
```
|
||||
Please note that using `self` is not recommended for most cases, as it could make names globally ambiguous.
|
||||
Additionally, it requires you to mirror all the actions you need to your Gitea instance, which may not be worth it.
|
||||
Therefore, please use `self` only if you understand what you are doing.
|
||||
|
||||
Now we need to know how to get actions/checkout, this configuration is the default git server to get it. That means we will get the repository via git clone ${DEFAULT_ACTIONS_URL}/actions/checkout and fetch tag v3.
|
||||
|
||||
To help people who don't want to mirror these actions in their git instances, the default value is https://gitea.com
|
||||
To help people run actions totally in their network, they can change the value and copy all necessary action repositories into their git server.
|
||||
|
||||
Of course we should support the form in future PRs like
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- uses: gitea.com/actions/checkout@v3
|
||||
```
|
||||
|
||||
although Github don't support this form.
|
||||
In earlier versions (<= 1.19), `DEFAULT_ACTIONS_URL` cound be set to any custom URLs like `https://gitea.com` or `http://your-git-server,https://gitea.com`, and the default value was `https://gitea.com`.
|
||||
However, later updates removed those options, and now the only options are `github` and `self`, with the default value being `github`.
|
||||
However, if you want to use actions from other git server, you can use a complete URL in `uses` field, it's supported by Gitea (but not GitHub).
|
||||
Like `uses: https://gitea.com/actions/checkout@v3` or `uses: http://your-git-server/actions/checkout@v3`.
|
||||
|
||||
## Other (`other`)
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ services:
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
ports:
|
||||
- "3000:3000"
|
||||
- "222:22"
|
||||
- "2222:2222"
|
||||
+ depends_on:
|
||||
+ - db
|
||||
+
|
||||
@@ -288,7 +288,7 @@ docker-compose up -d
|
||||
|
||||
In addition to the environment variables above, any settings in `app.ini` can be set
|
||||
or overridden with an environment variable of the form: `GITEA__SECTION_NAME__KEY_NAME`.
|
||||
These settings are applied each time the docker container starts.
|
||||
These settings are applied each time the docker container starts, and won't be passed into Gitea's sub-processes.
|
||||
Full information [here](https://github.com/go-gitea/gitea/tree/main/contrib/environment-to-ini).
|
||||
|
||||
These environment variables can be passed to the docker container in `docker-compose.yml`.
|
||||
|
||||
@@ -289,7 +289,7 @@ docker-compose up -d
|
||||
|
||||
In addition to the environment variables above, any settings in `app.ini` can be set
|
||||
or overridden with an environment variable of the form: `GITEA__SECTION_NAME__KEY_NAME`.
|
||||
These settings are applied each time the docker container starts.
|
||||
These settings are applied each time the docker container starts, and won't be passed into Gitea's sub-processes.
|
||||
Full information [here](https://github.com/go-gitea/gitea/tree/master/contrib/environment-to-ini).
|
||||
|
||||
These environment variables can be passed to the docker container in `docker-compose.yml`.
|
||||
|
||||
@@ -343,7 +343,7 @@ func getIssueNotification(ctx context.Context, userID, issueID int64) (*Notifica
|
||||
// NotificationsForUser returns notifications for a given user and status
|
||||
func NotificationsForUser(ctx context.Context, user *user_model.User, statuses []NotificationStatus, page, perPage int) (notifications NotificationList, err error) {
|
||||
if len(statuses) == 0 {
|
||||
return
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
sess := db.GetEngine(ctx).
|
||||
@@ -372,16 +372,16 @@ func CountUnread(ctx context.Context, userID int64) int64 {
|
||||
// LoadAttributes load Repo Issue User and Comment if not loaded
|
||||
func (n *Notification) LoadAttributes(ctx context.Context) (err error) {
|
||||
if err = n.loadRepo(ctx); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
if err = n.loadIssue(ctx); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
if err = n.loadUser(ctx); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
if err = n.loadComment(ctx); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ func init() {
|
||||
// TranslatableMessage represents JSON struct that can be translated with a Locale
|
||||
type TranslatableMessage struct {
|
||||
Format string
|
||||
Args []interface{} `json:"omitempty"`
|
||||
Args []any `json:"omitempty"`
|
||||
}
|
||||
|
||||
// LoadRepo loads repository of the task
|
||||
|
||||
@@ -455,9 +455,9 @@ func hashAndVerifyForKeyID(sig *packet.Signature, payload string, committer *use
|
||||
|
||||
// CalculateTrustStatus will calculate the TrustStatus for a commit verification within a repository
|
||||
// There are several trust models in Gitea
|
||||
func CalculateTrustStatus(verification *CommitVerification, repoTrustModel repo_model.TrustModelType, isOwnerMemberCollaborator func(*user_model.User) (bool, error), keyMap *map[string]bool) (err error) {
|
||||
func CalculateTrustStatus(verification *CommitVerification, repoTrustModel repo_model.TrustModelType, isOwnerMemberCollaborator func(*user_model.User) (bool, error), keyMap *map[string]bool) error {
|
||||
if !verification.Verified {
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
// In the Committer trust model a signature is trusted if it matches the committer
|
||||
@@ -475,7 +475,7 @@ func CalculateTrustStatus(verification *CommitVerification, repoTrustModel repo_
|
||||
verification.SigningUser.Email == verification.CommittingUser.Email) {
|
||||
verification.TrustStatus = "trusted"
|
||||
}
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
// Now we drop to the more nuanced trust models...
|
||||
@@ -490,10 +490,11 @@ func CalculateTrustStatus(verification *CommitVerification, repoTrustModel repo_
|
||||
verification.SigningUser.Email != verification.CommittingUser.Email) {
|
||||
verification.TrustStatus = "untrusted"
|
||||
}
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check we actually have a GPG SigningKey
|
||||
var err error
|
||||
if verification.SigningKey != nil {
|
||||
var isMember bool
|
||||
if keyMap != nil {
|
||||
|
||||
@@ -111,7 +111,7 @@ func populateHash(hashFunc crypto.Hash, msg []byte) (hash.Hash, error) {
|
||||
func readArmoredSign(r io.Reader) (body io.Reader, err error) {
|
||||
block, err := armor.Decode(r)
|
||||
if err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
if block.Type != openpgp.SignatureType {
|
||||
return nil, fmt.Errorf("expected '" + openpgp.SignatureType + "', got: " + block.Type)
|
||||
|
||||
@@ -47,7 +47,7 @@ var sshOpLocker sync.Mutex
|
||||
// AuthorizedStringForKey creates the authorized keys string appropriate for the provided key
|
||||
func AuthorizedStringForKey(key *PublicKey) string {
|
||||
sb := &strings.Builder{}
|
||||
_ = setting.SSH.AuthorizedKeysCommandTemplateTemplate.Execute(sb, map[string]interface{}{
|
||||
_ = setting.SSH.AuthorizedKeysCommandTemplateTemplate.Execute(sb, map[string]any{
|
||||
"AppPath": util.ShellEscape(setting.AppPath),
|
||||
"AppWorkPath": util.ShellEscape(setting.AppWorkPath),
|
||||
"CustomConf": util.ShellEscape(setting.CustomConf),
|
||||
@@ -175,7 +175,7 @@ func RewriteAllPublicKeys() error {
|
||||
|
||||
// RegeneratePublicKeys regenerates the authorized_keys file
|
||||
func RegeneratePublicKeys(ctx context.Context, t io.StringWriter) error {
|
||||
if err := db.GetEngine(ctx).Where("type != ?", KeyTypePrincipal).Iterate(new(PublicKey), func(idx int, bean interface{}) (err error) {
|
||||
if err := db.GetEngine(ctx).Where("type != ?", KeyTypePrincipal).Iterate(new(PublicKey), func(idx int, bean any) (err error) {
|
||||
_, err = t.WriteString((bean.(*PublicKey)).AuthorizedString())
|
||||
return err
|
||||
}); err != nil {
|
||||
|
||||
@@ -97,7 +97,7 @@ func RewriteAllPrincipalKeys(ctx context.Context) error {
|
||||
}
|
||||
|
||||
func regeneratePrincipalKeys(ctx context.Context, t io.StringWriter) error {
|
||||
if err := db.GetEngine(ctx).Where("type = ?", KeyTypePrincipal).Iterate(new(PublicKey), func(idx int, bean interface{}) (err error) {
|
||||
if err := db.GetEngine(ctx).Where("type = ?", KeyTypePrincipal).Iterate(new(PublicKey), func(idx int, bean any) (err error) {
|
||||
_, err = t.WriteString((bean.(*PublicKey)).AuthorizedString())
|
||||
return err
|
||||
}); err != nil {
|
||||
|
||||
@@ -306,9 +306,10 @@ func (code *OAuth2AuthorizationCode) TableName() string {
|
||||
}
|
||||
|
||||
// GenerateRedirectURI generates a redirect URI for a successful authorization request. State will be used if not empty.
|
||||
func (code *OAuth2AuthorizationCode) GenerateRedirectURI(state string) (redirect *url.URL, err error) {
|
||||
if redirect, err = url.Parse(code.RedirectURI); err != nil {
|
||||
return
|
||||
func (code *OAuth2AuthorizationCode) GenerateRedirectURI(state string) (*url.URL, error) {
|
||||
redirect, err := url.Parse(code.RedirectURI)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
q := redirect.Query()
|
||||
if state != "" {
|
||||
|
||||
+11
-11
@@ -52,7 +52,7 @@ func (ctx *Context) Engine() Engine {
|
||||
}
|
||||
|
||||
// Value shadows Value for context.Context but allows us to get ourselves and an Engined object
|
||||
func (ctx *Context) Value(key interface{}) interface{} {
|
||||
func (ctx *Context) Value(key any) any {
|
||||
if key == enginedContextKey {
|
||||
return ctx
|
||||
}
|
||||
@@ -163,28 +163,28 @@ func txWithNoCheck(parentCtx context.Context, f func(ctx context.Context) error)
|
||||
}
|
||||
|
||||
// Insert inserts records into database
|
||||
func Insert(ctx context.Context, beans ...interface{}) error {
|
||||
func Insert(ctx context.Context, beans ...any) error {
|
||||
_, err := GetEngine(ctx).Insert(beans...)
|
||||
return err
|
||||
}
|
||||
|
||||
// Exec executes a sql with args
|
||||
func Exec(ctx context.Context, sqlAndArgs ...interface{}) (sql.Result, error) {
|
||||
func Exec(ctx context.Context, sqlAndArgs ...any) (sql.Result, error) {
|
||||
return GetEngine(ctx).Exec(sqlAndArgs...)
|
||||
}
|
||||
|
||||
// GetByBean filled empty fields of the bean according non-empty fields to query in database.
|
||||
func GetByBean(ctx context.Context, bean interface{}) (bool, error) {
|
||||
func GetByBean(ctx context.Context, bean any) (bool, error) {
|
||||
return GetEngine(ctx).Get(bean)
|
||||
}
|
||||
|
||||
// DeleteByBean deletes all records according non-empty fields of the bean as conditions.
|
||||
func DeleteByBean(ctx context.Context, bean interface{}) (int64, error) {
|
||||
func DeleteByBean(ctx context.Context, bean any) (int64, error) {
|
||||
return GetEngine(ctx).Delete(bean)
|
||||
}
|
||||
|
||||
// DeleteByID deletes the given bean with the given ID
|
||||
func DeleteByID(ctx context.Context, id int64, bean interface{}) (int64, error) {
|
||||
func DeleteByID(ctx context.Context, id int64, bean any) (int64, error) {
|
||||
return GetEngine(ctx).ID(id).NoAutoTime().Delete(bean)
|
||||
}
|
||||
|
||||
@@ -203,13 +203,13 @@ func FindIDs(ctx context.Context, tableName, idCol string, cond builder.Cond) ([
|
||||
|
||||
// DecrByIDs decreases the given column for entities of the "bean" type with one of the given ids by one
|
||||
// Timestamps of the entities won't be updated
|
||||
func DecrByIDs(ctx context.Context, ids []int64, decrCol string, bean interface{}) error {
|
||||
func DecrByIDs(ctx context.Context, ids []int64, decrCol string, bean any) error {
|
||||
_, err := GetEngine(ctx).Decr(decrCol).In("id", ids).NoAutoCondition().NoAutoTime().Update(bean)
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteBeans deletes all given beans, beans must contain delete conditions.
|
||||
func DeleteBeans(ctx context.Context, beans ...interface{}) (err error) {
|
||||
func DeleteBeans(ctx context.Context, beans ...any) (err error) {
|
||||
e := GetEngine(ctx)
|
||||
for i := range beans {
|
||||
if _, err = e.Delete(beans[i]); err != nil {
|
||||
@@ -220,7 +220,7 @@ func DeleteBeans(ctx context.Context, beans ...interface{}) (err error) {
|
||||
}
|
||||
|
||||
// TruncateBeans deletes all given beans, beans may contain delete conditions.
|
||||
func TruncateBeans(ctx context.Context, beans ...interface{}) (err error) {
|
||||
func TruncateBeans(ctx context.Context, beans ...any) (err error) {
|
||||
e := GetEngine(ctx)
|
||||
for i := range beans {
|
||||
if _, err = e.Truncate(beans[i]); err != nil {
|
||||
@@ -231,12 +231,12 @@ func TruncateBeans(ctx context.Context, beans ...interface{}) (err error) {
|
||||
}
|
||||
|
||||
// CountByBean counts the number of database records according non-empty fields of the bean as conditions.
|
||||
func CountByBean(ctx context.Context, bean interface{}) (int64, error) {
|
||||
func CountByBean(ctx context.Context, bean any) (int64, error) {
|
||||
return GetEngine(ctx).Count(bean)
|
||||
}
|
||||
|
||||
// TableName returns the table name according a bean object
|
||||
func TableName(bean interface{}) string {
|
||||
func TableName(bean any) string {
|
||||
return x.TableName(bean)
|
||||
}
|
||||
|
||||
|
||||
+31
-31
@@ -25,7 +25,7 @@ import (
|
||||
|
||||
var (
|
||||
x *xorm.Engine
|
||||
tables []interface{}
|
||||
tables []any
|
||||
initFuncs []func() error
|
||||
|
||||
// HasEngine specifies if we have a xorm.Engine
|
||||
@@ -34,41 +34,41 @@ var (
|
||||
|
||||
// Engine represents a xorm engine or session.
|
||||
type Engine interface {
|
||||
Table(tableNameOrBean interface{}) *xorm.Session
|
||||
Count(...interface{}) (int64, error)
|
||||
Decr(column string, arg ...interface{}) *xorm.Session
|
||||
Delete(...interface{}) (int64, error)
|
||||
Truncate(...interface{}) (int64, error)
|
||||
Exec(...interface{}) (sql.Result, error)
|
||||
Find(interface{}, ...interface{}) error
|
||||
Get(beans ...interface{}) (bool, error)
|
||||
ID(interface{}) *xorm.Session
|
||||
In(string, ...interface{}) *xorm.Session
|
||||
Incr(column string, arg ...interface{}) *xorm.Session
|
||||
Insert(...interface{}) (int64, error)
|
||||
Iterate(interface{}, xorm.IterFunc) error
|
||||
Join(joinOperator string, tablename, condition interface{}, args ...interface{}) *xorm.Session
|
||||
SQL(interface{}, ...interface{}) *xorm.Session
|
||||
Where(interface{}, ...interface{}) *xorm.Session
|
||||
Table(tableNameOrBean any) *xorm.Session
|
||||
Count(...any) (int64, error)
|
||||
Decr(column string, arg ...any) *xorm.Session
|
||||
Delete(...any) (int64, error)
|
||||
Truncate(...any) (int64, error)
|
||||
Exec(...any) (sql.Result, error)
|
||||
Find(any, ...any) error
|
||||
Get(beans ...any) (bool, error)
|
||||
ID(any) *xorm.Session
|
||||
In(string, ...any) *xorm.Session
|
||||
Incr(column string, arg ...any) *xorm.Session
|
||||
Insert(...any) (int64, error)
|
||||
Iterate(any, xorm.IterFunc) error
|
||||
Join(joinOperator string, tablename, condition any, args ...any) *xorm.Session
|
||||
SQL(any, ...any) *xorm.Session
|
||||
Where(any, ...any) *xorm.Session
|
||||
Asc(colNames ...string) *xorm.Session
|
||||
Desc(colNames ...string) *xorm.Session
|
||||
Limit(limit int, start ...int) *xorm.Session
|
||||
NoAutoTime() *xorm.Session
|
||||
SumInt(bean interface{}, columnName string) (res int64, err error)
|
||||
Sync2(...interface{}) error
|
||||
SumInt(bean any, columnName string) (res int64, err error)
|
||||
Sync2(...any) error
|
||||
Select(string) *xorm.Session
|
||||
NotIn(string, ...interface{}) *xorm.Session
|
||||
OrderBy(interface{}, ...interface{}) *xorm.Session
|
||||
Exist(...interface{}) (bool, error)
|
||||
NotIn(string, ...any) *xorm.Session
|
||||
OrderBy(any, ...any) *xorm.Session
|
||||
Exist(...any) (bool, error)
|
||||
Distinct(...string) *xorm.Session
|
||||
Query(...interface{}) ([]map[string][]byte, error)
|
||||
Query(...any) ([]map[string][]byte, error)
|
||||
Cols(...string) *xorm.Session
|
||||
Context(ctx context.Context) *xorm.Session
|
||||
Ping() error
|
||||
}
|
||||
|
||||
// TableInfo returns table's information via an object
|
||||
func TableInfo(v interface{}) (*schemas.Table, error) {
|
||||
func TableInfo(v any) (*schemas.Table, error) {
|
||||
return x.TableInfo(v)
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ func DumpTables(tables []*schemas.Table, w io.Writer, tp ...schemas.DBType) erro
|
||||
}
|
||||
|
||||
// RegisterModel registers model, if initfunc provided, it will be invoked after data model sync
|
||||
func RegisterModel(bean interface{}, initFunc ...func() error) {
|
||||
func RegisterModel(bean any, initFunc ...func() error) {
|
||||
tables = append(tables, bean)
|
||||
if len(initFuncs) > 0 && initFunc[0] != nil {
|
||||
initFuncs = append(initFuncs, initFunc[0])
|
||||
@@ -209,14 +209,14 @@ func InitEngineWithMigration(ctx context.Context, migrateFunc func(*xorm.Engine)
|
||||
}
|
||||
|
||||
// NamesToBean return a list of beans or an error
|
||||
func NamesToBean(names ...string) ([]interface{}, error) {
|
||||
beans := []interface{}{}
|
||||
func NamesToBean(names ...string) ([]any, error) {
|
||||
beans := []any{}
|
||||
if len(names) == 0 {
|
||||
beans = append(beans, tables...)
|
||||
return beans, nil
|
||||
}
|
||||
// Need to map provided names to beans...
|
||||
beanMap := make(map[string]interface{})
|
||||
beanMap := make(map[string]any)
|
||||
for _, bean := range tables {
|
||||
|
||||
beanMap[strings.ToLower(reflect.Indirect(reflect.ValueOf(bean)).Type().Name())] = bean
|
||||
@@ -224,7 +224,7 @@ func NamesToBean(names ...string) ([]interface{}, error) {
|
||||
beanMap[strings.ToLower(x.TableName(bean, true))] = bean
|
||||
}
|
||||
|
||||
gotBean := make(map[interface{}]bool)
|
||||
gotBean := make(map[any]bool)
|
||||
for _, name := range names {
|
||||
bean, ok := beanMap[strings.ToLower(strings.TrimSpace(name))]
|
||||
if !ok {
|
||||
@@ -266,7 +266,7 @@ func DumpDatabase(filePath, dbType string) error {
|
||||
}
|
||||
|
||||
// MaxBatchInsertSize returns the table's max batch insert size
|
||||
func MaxBatchInsertSize(bean interface{}) int {
|
||||
func MaxBatchInsertSize(bean any) int {
|
||||
t, err := x.TableInfo(bean)
|
||||
if err != nil {
|
||||
return 50
|
||||
@@ -286,7 +286,7 @@ func DeleteAllRecords(tableName string) error {
|
||||
}
|
||||
|
||||
// GetMaxID will return max id of the table
|
||||
func GetMaxID(beanOrTableName interface{}) (maxID int64, err error) {
|
||||
func GetMaxID(beanOrTableName any) (maxID int64, err error) {
|
||||
_, err = x.Select("MAX(id)").Table(beanOrTableName).Get(&maxID)
|
||||
return maxID, err
|
||||
}
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ func (err ErrCancelled) Error() string {
|
||||
}
|
||||
|
||||
// ErrCancelledf returns an ErrCancelled for the provided format and args
|
||||
func ErrCancelledf(format string, args ...interface{}) error {
|
||||
func ErrCancelledf(format string, args ...any) error {
|
||||
return ErrCancelled{
|
||||
fmt.Sprintf(format, args...),
|
||||
}
|
||||
|
||||
+9
-9
@@ -28,47 +28,47 @@ func NewXORMLogger(showSQL bool) xormlog.Logger {
|
||||
const stackLevel = 8
|
||||
|
||||
// Log a message with defined skip and at logging level
|
||||
func (l *XORMLogBridge) Log(skip int, level log.Level, format string, v ...interface{}) {
|
||||
func (l *XORMLogBridge) Log(skip int, level log.Level, format string, v ...any) {
|
||||
l.logger.Log(skip+1, level, format, v...)
|
||||
}
|
||||
|
||||
// Debug show debug log
|
||||
func (l *XORMLogBridge) Debug(v ...interface{}) {
|
||||
func (l *XORMLogBridge) Debug(v ...any) {
|
||||
l.Log(stackLevel, log.DEBUG, "%s", fmt.Sprint(v...))
|
||||
}
|
||||
|
||||
// Debugf show debug log
|
||||
func (l *XORMLogBridge) Debugf(format string, v ...interface{}) {
|
||||
func (l *XORMLogBridge) Debugf(format string, v ...any) {
|
||||
l.Log(stackLevel, log.DEBUG, format, v...)
|
||||
}
|
||||
|
||||
// Error show error log
|
||||
func (l *XORMLogBridge) Error(v ...interface{}) {
|
||||
func (l *XORMLogBridge) Error(v ...any) {
|
||||
l.Log(stackLevel, log.ERROR, "%s", fmt.Sprint(v...))
|
||||
}
|
||||
|
||||
// Errorf show error log
|
||||
func (l *XORMLogBridge) Errorf(format string, v ...interface{}) {
|
||||
func (l *XORMLogBridge) Errorf(format string, v ...any) {
|
||||
l.Log(stackLevel, log.ERROR, format, v...)
|
||||
}
|
||||
|
||||
// Info show information level log
|
||||
func (l *XORMLogBridge) Info(v ...interface{}) {
|
||||
func (l *XORMLogBridge) Info(v ...any) {
|
||||
l.Log(stackLevel, log.INFO, "%s", fmt.Sprint(v...))
|
||||
}
|
||||
|
||||
// Infof show information level log
|
||||
func (l *XORMLogBridge) Infof(format string, v ...interface{}) {
|
||||
func (l *XORMLogBridge) Infof(format string, v ...any) {
|
||||
l.Log(stackLevel, log.INFO, format, v...)
|
||||
}
|
||||
|
||||
// Warn show warning log
|
||||
func (l *XORMLogBridge) Warn(v ...interface{}) {
|
||||
func (l *XORMLogBridge) Warn(v ...any) {
|
||||
l.Log(stackLevel, log.WARN, "%s", fmt.Sprint(v...))
|
||||
}
|
||||
|
||||
// Warnf show warnning log
|
||||
func (l *XORMLogBridge) Warnf(format string, v ...interface{}) {
|
||||
func (l *XORMLogBridge) Warnf(format string, v ...any) {
|
||||
l.Log(stackLevel, log.WARN, format, v...)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
-
|
||||
id: 1
|
||||
repo_id: 5
|
||||
interval: 3600
|
||||
enable_prune: false
|
||||
updated_unix: 0
|
||||
next_update_unix: 0
|
||||
lfs_enabled: false
|
||||
lfs_endpoint: ""
|
||||
|
||||
-
|
||||
id: 2
|
||||
repo_id: 25
|
||||
interval: 3600
|
||||
enable_prune: false
|
||||
updated_unix: 0
|
||||
next_update_unix: 0
|
||||
lfs_enabled: false
|
||||
lfs_endpoint: ""
|
||||
|
||||
-
|
||||
id: 3
|
||||
repo_id: 26
|
||||
interval: 3600
|
||||
enable_prune: false
|
||||
updated_unix: 0
|
||||
next_update_unix: 0
|
||||
lfs_enabled: false
|
||||
lfs_endpoint: ""
|
||||
|
||||
-
|
||||
id: 4
|
||||
repo_id: 27
|
||||
interval: 3600
|
||||
enable_prune: false
|
||||
updated_unix: 0
|
||||
next_update_unix: 0
|
||||
lfs_enabled: false
|
||||
lfs_endpoint: ""
|
||||
|
||||
-
|
||||
id: 5
|
||||
repo_id: 28
|
||||
interval: 3600
|
||||
enable_prune: false
|
||||
updated_unix: 0
|
||||
next_update_unix: 0
|
||||
lfs_enabled: false
|
||||
lfs_endpoint: ""
|
||||
@@ -81,3 +81,21 @@
|
||||
uid: 5
|
||||
org_id: 23
|
||||
is_public: false
|
||||
|
||||
-
|
||||
id: 15
|
||||
uid: 1
|
||||
org_id: 35
|
||||
is_public: true
|
||||
|
||||
-
|
||||
id: 16
|
||||
uid: 1
|
||||
org_id: 36
|
||||
is_public: true
|
||||
|
||||
-
|
||||
id: 17
|
||||
uid: 5
|
||||
org_id: 36
|
||||
is_public: true
|
||||
|
||||
@@ -141,7 +141,7 @@
|
||||
num_projects: 0
|
||||
num_closed_projects: 0
|
||||
is_private: true
|
||||
is_empty: true
|
||||
is_empty: false
|
||||
is_archived: false
|
||||
is_mirror: true
|
||||
status: 0
|
||||
|
||||
@@ -184,3 +184,36 @@
|
||||
num_members: 1
|
||||
includes_all_repositories: false
|
||||
can_create_org_repo: true
|
||||
|
||||
-
|
||||
id: 18
|
||||
org_id: 35
|
||||
lower_name: owners
|
||||
name: Owners
|
||||
authorize: 4 # owner
|
||||
num_repos: 0
|
||||
num_members: 1
|
||||
includes_all_repositories: false
|
||||
can_create_org_repo: true
|
||||
|
||||
-
|
||||
id: 19
|
||||
org_id: 36
|
||||
lower_name: owners
|
||||
name: Owners
|
||||
authorize: 4 # owner
|
||||
num_repos: 0
|
||||
num_members: 1
|
||||
includes_all_repositories: false
|
||||
can_create_org_repo: true
|
||||
|
||||
-
|
||||
id: 20
|
||||
org_id: 36
|
||||
lower_name: team20writepackage
|
||||
name: team20writepackage
|
||||
authorize: 1
|
||||
num_repos: 0
|
||||
num_members: 1
|
||||
includes_all_repositories: false
|
||||
can_create_org_repo: true
|
||||
|
||||
@@ -273,4 +273,10 @@
|
||||
id: 46
|
||||
team_id: 17
|
||||
type: 9 # package
|
||||
access_mode: 0
|
||||
access_mode: 2
|
||||
|
||||
-
|
||||
id: 47
|
||||
team_id: 20
|
||||
type: 9 # package
|
||||
access_mode: 2
|
||||
|
||||
@@ -105,3 +105,21 @@
|
||||
org_id: 23
|
||||
team_id: 17
|
||||
uid: 5
|
||||
|
||||
-
|
||||
id: 19
|
||||
org_id: 35
|
||||
team_id: 18
|
||||
uid: 1
|
||||
|
||||
-
|
||||
id: 20
|
||||
org_id: 36
|
||||
team_id: 19
|
||||
uid: 1
|
||||
|
||||
-
|
||||
id: 21
|
||||
org_id: 36
|
||||
team_id: 20
|
||||
uid: 5
|
||||
|
||||
@@ -1258,3 +1258,77 @@
|
||||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
|
||||
-
|
||||
id: 35
|
||||
lower_name: private_org35
|
||||
name: private_org35
|
||||
full_name: Private Org 35
|
||||
email: private_org35@example.com
|
||||
keep_email_private: false
|
||||
email_notifications_preference: enabled
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
must_change_password: false
|
||||
login_source: 0
|
||||
login_name: private_org35
|
||||
type: 1
|
||||
salt: ZogKvWdyEx
|
||||
max_repo_creation: -1
|
||||
is_active: true
|
||||
is_admin: false
|
||||
is_restricted: false
|
||||
allow_git_hook: false
|
||||
allow_import_local: false
|
||||
allow_create_organization: true
|
||||
prohibit_login: false
|
||||
avatar: avatar35
|
||||
avatar_email: private_org35@example.com
|
||||
use_custom_avatar: false
|
||||
num_followers: 0
|
||||
num_following: 0
|
||||
num_stars: 0
|
||||
num_repos: 0
|
||||
num_teams: 1
|
||||
num_members: 1
|
||||
visibility: 2
|
||||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
|
||||
-
|
||||
id: 36
|
||||
lower_name: limited_org36
|
||||
name: limited_org36
|
||||
full_name: Limited Org 36
|
||||
email: limited_org36@example.com
|
||||
keep_email_private: false
|
||||
email_notifications_preference: enabled
|
||||
passwd: ZogKvWdyEx:password
|
||||
passwd_hash_algo: dummy
|
||||
must_change_password: false
|
||||
login_source: 0
|
||||
login_name: limited_org36
|
||||
type: 1
|
||||
salt: ZogKvWdyEx
|
||||
max_repo_creation: -1
|
||||
is_active: true
|
||||
is_admin: false
|
||||
is_restricted: false
|
||||
allow_git_hook: false
|
||||
allow_import_local: false
|
||||
allow_create_organization: true
|
||||
prohibit_login: false
|
||||
avatar: avatar22
|
||||
avatar_email: limited_org36@example.com
|
||||
use_custom_avatar: false
|
||||
num_followers: 0
|
||||
num_following: 0
|
||||
num_stars: 0
|
||||
num_repos: 0
|
||||
num_teams: 2
|
||||
num_members: 2
|
||||
visibility: 1
|
||||
repo_admin_change_team_access: false
|
||||
theme: ""
|
||||
keep_activity_private: false
|
||||
|
||||
+34
-10
@@ -11,9 +11,12 @@ import (
|
||||
"code.gitea.io/gitea/models/db"
|
||||
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/log"
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"xorm.io/builder"
|
||||
)
|
||||
|
||||
// ErrBranchNotExist represents an error that branch with such name does not exist.
|
||||
@@ -100,9 +103,9 @@ func (err ErrBranchesEqual) Unwrap() error {
|
||||
type Branch struct {
|
||||
ID int64
|
||||
RepoID int64 `xorm:"UNIQUE(s)"`
|
||||
Name string `xorm:"UNIQUE(s) NOT NULL"`
|
||||
Name string `xorm:"UNIQUE(s) NOT NULL"` // git's ref-name is case-sensitive internally, however, in some databases (mssql, mysql, by default), it's case-insensitive at the moment
|
||||
CommitID string
|
||||
CommitMessage string `xorm:"TEXT"`
|
||||
CommitMessage string `xorm:"TEXT"` // it only stores the message summary (the first line)
|
||||
PusherID int64
|
||||
Pusher *user_model.User `xorm:"-"`
|
||||
IsDeleted bool `xorm:"index"`
|
||||
@@ -204,14 +207,14 @@ func DeleteBranches(ctx context.Context, repoID, doerID int64, branchIDs []int64
|
||||
|
||||
// UpdateBranch updates the branch information in the database. If the branch exist, it will update latest commit of this branch information
|
||||
// If it doest not exist, insert a new record into database
|
||||
func UpdateBranch(ctx context.Context, repoID int64, branchName, commitID, commitMessage string, pusherID int64, commitTime time.Time) error {
|
||||
func UpdateBranch(ctx context.Context, repoID, pusherID int64, branchName string, commit *git.Commit) error {
|
||||
cnt, err := db.GetEngine(ctx).Where("repo_id=? AND name=?", repoID, branchName).
|
||||
Cols("commit_id, commit_message, pusher_id, commit_time, is_deleted, updated_unix").
|
||||
Update(&Branch{
|
||||
CommitID: commitID,
|
||||
CommitMessage: commitMessage,
|
||||
CommitID: commit.ID.String(),
|
||||
CommitMessage: commit.Summary(),
|
||||
PusherID: pusherID,
|
||||
CommitTime: timeutil.TimeStamp(commitTime.Unix()),
|
||||
CommitTime: timeutil.TimeStamp(commit.Committer.When.Unix()),
|
||||
IsDeleted: false,
|
||||
})
|
||||
if err != nil {
|
||||
@@ -224,10 +227,10 @@ func UpdateBranch(ctx context.Context, repoID int64, branchName, commitID, commi
|
||||
return db.Insert(ctx, &Branch{
|
||||
RepoID: repoID,
|
||||
Name: branchName,
|
||||
CommitID: commitID,
|
||||
CommitMessage: commitMessage,
|
||||
CommitID: commit.ID.String(),
|
||||
CommitMessage: commit.Summary(),
|
||||
PusherID: pusherID,
|
||||
CommitTime: timeutil.TimeStamp(commitTime.Unix()),
|
||||
CommitTime: timeutil.TimeStamp(commit.Committer.When.Unix()),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -354,7 +357,7 @@ func RenameBranch(ctx context.Context, repo *repo_model.Repository, from, to str
|
||||
// 4. Update all not merged pull request base branch name
|
||||
_, err = sess.Table("pull_request").Where("base_repo_id=? AND base_branch=? AND has_merged=?",
|
||||
repo.ID, from, false).
|
||||
Update(map[string]interface{}{"base_branch": to})
|
||||
Update(map[string]any{"base_branch": to})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -377,3 +380,24 @@ func RenameBranch(ctx context.Context, repo *repo_model.Repository, from, to str
|
||||
|
||||
return committer.Commit()
|
||||
}
|
||||
|
||||
// FindRecentlyPushedNewBranches return at most 2 new branches pushed by the user in 6 hours which has no opened PRs created
|
||||
// except the indicate branch
|
||||
func FindRecentlyPushedNewBranches(ctx context.Context, repoID, userID int64, excludeBranchName string) (BranchList, error) {
|
||||
branches := make(BranchList, 0, 2)
|
||||
subQuery := builder.Select("head_branch").From("pull_request").
|
||||
InnerJoin("issue", "issue.id = pull_request.issue_id").
|
||||
Where(builder.Eq{
|
||||
"pull_request.head_repo_id": repoID,
|
||||
"issue.is_closed": false,
|
||||
})
|
||||
err := db.GetEngine(ctx).
|
||||
Where("pusher_id=? AND is_deleted=?", userID, false).
|
||||
And("name <> ?", excludeBranchName).
|
||||
And("updated_unix >= ?", time.Now().Add(-time.Hour*6).Unix()).
|
||||
NotIn("name", subQuery).
|
||||
OrderBy("branch.updated_unix DESC").
|
||||
Limit(2).
|
||||
Find(&branches)
|
||||
return branches, err
|
||||
}
|
||||
|
||||
@@ -64,11 +64,6 @@ func (branches BranchList) LoadPusher(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
const (
|
||||
BranchOrderByNameAsc = "name ASC"
|
||||
BranchOrderByCommitTimeDesc = "commit_time DESC"
|
||||
)
|
||||
|
||||
type FindBranchOptions struct {
|
||||
db.ListOptions
|
||||
RepoID int64
|
||||
@@ -102,7 +97,8 @@ func orderByBranches(sess *xorm.Session, opts FindBranchOptions) *xorm.Session {
|
||||
}
|
||||
|
||||
if opts.OrderBy == "" {
|
||||
opts.OrderBy = BranchOrderByCommitTimeDesc
|
||||
// the commit_time might be the same, so add the "name" to make sure the order is stable
|
||||
opts.OrderBy = "commit_time DESC, name ASC"
|
||||
}
|
||||
return sess.OrderBy(opts.OrderBy)
|
||||
}
|
||||
@@ -130,3 +126,20 @@ func FindBranchNames(ctx context.Context, opts FindBranchOptions) ([]string, err
|
||||
}
|
||||
return branches, nil
|
||||
}
|
||||
|
||||
func FindBranchesByRepoAndBranchName(ctx context.Context, repoBranches map[int64]string) (map[int64]string, error) {
|
||||
cond := builder.NewCond()
|
||||
for repoID, branchName := range repoBranches {
|
||||
cond = cond.Or(builder.And(builder.Eq{"repo_id": repoID}, builder.Eq{"name": branchName}))
|
||||
}
|
||||
var branches []*Branch
|
||||
if err := db.GetEngine(ctx).
|
||||
Where(cond).Find(&branches); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
branchMap := make(map[int64]string, len(branches))
|
||||
for _, branch := range branches {
|
||||
branchMap[branch.RepoID] = branch.CommitID
|
||||
}
|
||||
return branchMap, nil
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
"code.gitea.io/gitea/modules/git"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -28,7 +29,15 @@ func TestAddDeletedBranch(t *testing.T) {
|
||||
secondBranch := unittest.AssertExistsAndLoadBean(t, &git_model.Branch{RepoID: repo.ID, Name: "branch2"})
|
||||
assert.True(t, secondBranch.IsDeleted)
|
||||
|
||||
err := git_model.UpdateBranch(db.DefaultContext, repo.ID, secondBranch.Name, secondBranch.CommitID, secondBranch.CommitMessage, secondBranch.PusherID, secondBranch.CommitTime.AsLocalTime())
|
||||
commit := &git.Commit{
|
||||
ID: git.MustIDFromString(secondBranch.CommitID),
|
||||
CommitMessage: secondBranch.CommitMessage,
|
||||
Committer: &git.Signature{
|
||||
When: secondBranch.CommitTime.AsLocalTime(),
|
||||
},
|
||||
}
|
||||
|
||||
err := git_model.UpdateBranch(db.DefaultContext, repo.ID, secondBranch.PusherID, secondBranch.Name, commit)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
|
||||
@@ -346,6 +346,53 @@ func GetLatestCommitStatusForPairs(ctx context.Context, repoIDsToLatestCommitSHA
|
||||
return repoStatuses, nil
|
||||
}
|
||||
|
||||
// GetLatestCommitStatusForRepoCommitIDs returns all statuses with a unique context for a given list of repo-sha pairs
|
||||
func GetLatestCommitStatusForRepoCommitIDs(ctx context.Context, repoID int64, commitIDs []string) (map[string][]*CommitStatus, error) {
|
||||
type result struct {
|
||||
ID int64
|
||||
Sha string
|
||||
}
|
||||
|
||||
results := make([]result, 0, len(commitIDs))
|
||||
|
||||
sess := db.GetEngine(ctx).Table(&CommitStatus{})
|
||||
|
||||
// Create a disjunction of conditions for each repoID and SHA pair
|
||||
conds := make([]builder.Cond, 0, len(commitIDs))
|
||||
for _, sha := range commitIDs {
|
||||
conds = append(conds, builder.Eq{"sha": sha})
|
||||
}
|
||||
sess = sess.Where(builder.Eq{"repo_id": repoID}.And(builder.Or(conds...))).
|
||||
Select("max( id ) as id, sha").
|
||||
GroupBy("context_hash, sha").OrderBy("max( id ) desc")
|
||||
|
||||
err := sess.Find(&results)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ids := make([]int64, 0, len(results))
|
||||
repoStatuses := make(map[string][]*CommitStatus)
|
||||
for _, result := range results {
|
||||
ids = append(ids, result.ID)
|
||||
}
|
||||
|
||||
statuses := make([]*CommitStatus, 0, len(ids))
|
||||
if len(ids) > 0 {
|
||||
err = db.GetEngine(ctx).In("id", ids).Find(&statuses)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Group the statuses by repo ID
|
||||
for _, status := range statuses {
|
||||
repoStatuses[status.SHA] = append(repoStatuses[status.SHA], status)
|
||||
}
|
||||
}
|
||||
|
||||
return repoStatuses, nil
|
||||
}
|
||||
|
||||
// FindRepoRecentCommitStatusContexts returns repository's recent commit status contexts
|
||||
func FindRepoRecentCommitStatusContexts(ctx context.Context, repoID int64, before time.Duration) ([]string, error) {
|
||||
start := timeutil.TimeStampNow().AddDuration(-before)
|
||||
|
||||
+1
-1
@@ -264,7 +264,7 @@ func LFSAutoAssociate(ctx context.Context, metas []*LFSMetaObject, user *user_mo
|
||||
|
||||
sess := db.GetEngine(ctx)
|
||||
|
||||
oids := make([]interface{}, len(metas))
|
||||
oids := make([]any, len(metas))
|
||||
oidMap := make(map[string]*LFSMetaObject, len(metas))
|
||||
for i, meta := range metas {
|
||||
oids[i] = meta.Oid
|
||||
|
||||
@@ -749,7 +749,7 @@ func (c *Comment) LoadPushCommits(ctx context.Context) (err error) {
|
||||
|
||||
err = json.Unmarshal([]byte(c.Content), &data)
|
||||
if err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
c.IsForcePush = data.IsForcePush
|
||||
@@ -925,7 +925,7 @@ func createIssueDependencyComment(ctx context.Context, doer *user_model.User, is
|
||||
cType = CommentTypeRemoveDependency
|
||||
}
|
||||
if err = issue.LoadRepo(ctx); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
// Make two comments, one in each issue
|
||||
@@ -937,7 +937,7 @@ func createIssueDependencyComment(ctx context.Context, doer *user_model.User, is
|
||||
DependentIssueID: dependentIssue.ID,
|
||||
}
|
||||
if _, err = CreateComment(ctx, opts); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
opts = &CreateCommentOptions{
|
||||
@@ -1131,7 +1131,7 @@ func DeleteComment(ctx context.Context, comment *Comment) error {
|
||||
}
|
||||
if _, err := e.Table("action").
|
||||
Where("comment_id = ?", comment.ID).
|
||||
Update(map[string]interface{}{
|
||||
Update(map[string]any{
|
||||
"is_deleted": true,
|
||||
}); err != nil {
|
||||
return err
|
||||
@@ -1156,7 +1156,7 @@ func UpdateCommentsMigrationsByType(tp structs.GitServiceType, originalAuthorID
|
||||
}),
|
||||
)).
|
||||
And("comment.original_author_id = ?", originalAuthorID).
|
||||
Update(map[string]interface{}{
|
||||
Update(map[string]any{
|
||||
"poster_id": posterID,
|
||||
"original_author": "",
|
||||
"original_author_id": 0,
|
||||
@@ -1170,11 +1170,11 @@ func CreateAutoMergeComment(ctx context.Context, typ CommentType, pr *PullReques
|
||||
return nil, fmt.Errorf("comment type %d cannot be used to create an auto merge comment", typ)
|
||||
}
|
||||
if err = pr.LoadIssue(ctx); err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = pr.LoadBaseRepo(ctx); err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
|
||||
comment, err = CreateComment(ctx, &CreateCommentOptions{
|
||||
|
||||
@@ -468,42 +468,38 @@ func (comments CommentList) loadReviews(ctx context.Context) error {
|
||||
// loadAttributes loads all attributes
|
||||
func (comments CommentList) loadAttributes(ctx context.Context) (err error) {
|
||||
if err = comments.LoadPosters(ctx); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
if err = comments.loadLabels(ctx); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
if err = comments.loadMilestones(ctx); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
if err = comments.loadOldMilestones(ctx); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
if err = comments.loadAssignees(ctx); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
if err = comments.LoadAttachments(ctx); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
if err = comments.loadReviews(ctx); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
if err = comments.LoadIssues(ctx); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
if err = comments.loadDependentIssues(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return nil
|
||||
return comments.loadDependentIssues(ctx)
|
||||
}
|
||||
|
||||
// LoadAttributes loads attributes of the comments, except for attachments and
|
||||
|
||||
+10
-11
@@ -222,8 +222,7 @@ func (issue *Issue) LoadPoster(ctx context.Context) (err error) {
|
||||
if !user_model.IsErrUserNotExist(err) {
|
||||
return fmt.Errorf("getUserByID.(poster) [%d]: %w", issue.PosterID, err)
|
||||
}
|
||||
err = nil
|
||||
return
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return err
|
||||
@@ -316,27 +315,27 @@ func (issue *Issue) LoadMilestone(ctx context.Context) (err error) {
|
||||
// LoadAttributes loads the attribute of this issue.
|
||||
func (issue *Issue) LoadAttributes(ctx context.Context) (err error) {
|
||||
if err = issue.LoadRepo(ctx); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
if err = issue.LoadPoster(ctx); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
if err = issue.LoadLabels(ctx); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
if err = issue.LoadMilestone(ctx); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
if err = issue.LoadProject(ctx); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
if err = issue.LoadAssignees(ctx); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
if err = issue.LoadPullRequest(ctx); err != nil && !IsErrPullRequestNotExist(err) {
|
||||
@@ -714,7 +713,7 @@ func (issue *Issue) Pin(ctx context.Context, user *user_model.User) error {
|
||||
|
||||
_, err = db.GetEngine(ctx).Table("issue").
|
||||
Where("id = ?", issue.ID).
|
||||
Update(map[string]interface{}{
|
||||
Update(map[string]any{
|
||||
"pin_order": maxPin + 1,
|
||||
})
|
||||
if err != nil {
|
||||
@@ -750,7 +749,7 @@ func (issue *Issue) Unpin(ctx context.Context, user *user_model.User) error {
|
||||
|
||||
_, err = db.GetEngine(ctx).Table("issue").
|
||||
Where("id = ?", issue.ID).
|
||||
Update(map[string]interface{}{
|
||||
Update(map[string]any{
|
||||
"pin_order": 0,
|
||||
})
|
||||
if err != nil {
|
||||
@@ -822,7 +821,7 @@ func (issue *Issue) MovePin(ctx context.Context, newPosition int) error {
|
||||
|
||||
_, err = db.GetEngine(dbctx).Table("issue").
|
||||
Where("id = ?", issue.ID).
|
||||
Update(map[string]interface{}{
|
||||
Update(map[string]any{
|
||||
"pin_order": newPosition,
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
@@ -39,7 +39,7 @@ func newIssueLabel(ctx context.Context, issue *Issue, label *Label, doer *user_m
|
||||
}
|
||||
|
||||
if err = issue.LoadRepo(ctx); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
opts := &CreateCommentOptions{
|
||||
@@ -168,7 +168,7 @@ func deleteIssueLabel(ctx context.Context, issue *Issue, label *Label, doer *use
|
||||
}
|
||||
|
||||
if err = issue.LoadRepo(ctx); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
opts := &CreateCommentOptions{
|
||||
|
||||
@@ -511,7 +511,7 @@ func UpdateIssueDeadline(issue *Issue, deadlineUnix timeutil.TimeStamp, doer *us
|
||||
}
|
||||
|
||||
// DeleteInIssue delete records in beans with external key issue_id = ?
|
||||
func DeleteInIssue(ctx context.Context, issueID int64, beans ...interface{}) error {
|
||||
func DeleteInIssue(ctx context.Context, issueID int64, beans ...any) error {
|
||||
e := db.GetEngine(ctx)
|
||||
for _, bean := range beans {
|
||||
if _, err := e.In("issue_id", issueID).Delete(bean); err != nil {
|
||||
@@ -538,10 +538,10 @@ func FindAndUpdateIssueMentions(ctx context.Context, issue *Issue, doer *user_mo
|
||||
// don't have access to reading it. Teams are expanded into their users, but organizations are ignored.
|
||||
func ResolveIssueMentionsByVisibility(ctx context.Context, issue *Issue, doer *user_model.User, mentions []string) (users []*user_model.User, err error) {
|
||||
if len(mentions) == 0 {
|
||||
return
|
||||
return nil, nil
|
||||
}
|
||||
if err = issue.LoadRepo(ctx); err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resolved := make(map[string]bool, 10)
|
||||
@@ -635,7 +635,7 @@ func ResolveIssueMentionsByVisibility(ctx context.Context, issue *Issue, doer *u
|
||||
}
|
||||
}
|
||||
if len(mentionUsers) == 0 {
|
||||
return
|
||||
return users, err
|
||||
}
|
||||
|
||||
if users == nil {
|
||||
@@ -673,7 +673,7 @@ func UpdateIssuesMigrationsByType(gitServiceType api.GitServiceType, originalAut
|
||||
_, err := db.GetEngine(db.DefaultContext).Table("issue").
|
||||
Where("repo_id IN (SELECT id FROM repository WHERE original_service_type = ?)", gitServiceType).
|
||||
And("original_author_id = ?", originalAuthorID).
|
||||
Update(map[string]interface{}{
|
||||
Update(map[string]any{
|
||||
"poster_id": posterID,
|
||||
"original_author": "",
|
||||
"original_author_id": 0,
|
||||
@@ -686,7 +686,7 @@ func UpdateReactionsMigrationsByType(gitServiceType api.GitServiceType, original
|
||||
_, err := db.GetEngine(db.DefaultContext).Table("reaction").
|
||||
Where("original_author_id = ?", originalAuthorID).
|
||||
And(migratedIssueCond(gitServiceType)).
|
||||
Update(map[string]interface{}{
|
||||
Update(map[string]any{
|
||||
"user_id": userID,
|
||||
"original_author": "",
|
||||
"original_author_id": 0,
|
||||
@@ -702,66 +702,66 @@ func DeleteIssuesByRepoID(ctx context.Context, repoID int64) (attachmentPaths []
|
||||
// Delete content histories
|
||||
if _, err = sess.In("issue_id", deleteCond).
|
||||
Delete(&ContentHistory{}); err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Delete comments and attachments
|
||||
if _, err = sess.In("issue_id", deleteCond).
|
||||
Delete(&Comment{}); err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Dependencies for issues in this repository
|
||||
if _, err = sess.In("issue_id", deleteCond).
|
||||
Delete(&IssueDependency{}); err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Delete dependencies for issues in other repositories
|
||||
if _, err = sess.In("dependency_id", deleteCond).
|
||||
Delete(&IssueDependency{}); err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, err = sess.In("issue_id", deleteCond).
|
||||
Delete(&IssueUser{}); err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, err = sess.In("issue_id", deleteCond).
|
||||
Delete(&Reaction{}); err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, err = sess.In("issue_id", deleteCond).
|
||||
Delete(&IssueWatch{}); err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, err = sess.In("issue_id", deleteCond).
|
||||
Delete(&Stopwatch{}); err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, err = sess.In("issue_id", deleteCond).
|
||||
Delete(&TrackedTime{}); err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, err = sess.In("issue_id", deleteCond).
|
||||
Delete(&project_model.ProjectIssue{}); err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, err = sess.In("dependent_issue_id", deleteCond).
|
||||
Delete(&Comment{}); err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var attachments []*repo_model.Attachment
|
||||
if err = sess.In("issue_id", deleteCond).
|
||||
Find(&attachments); err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for j := range attachments {
|
||||
@@ -770,11 +770,11 @@ func DeleteIssuesByRepoID(ctx context.Context, repoID int64) (attachmentPaths []
|
||||
|
||||
if _, err = sess.In("issue_id", deleteCond).
|
||||
Delete(&repo_model.Attachment{}); err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, err = db.DeleteByBean(ctx, &Issue{RepoID: repoID}); err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return attachmentPaths, err
|
||||
|
||||
+10
-10
@@ -136,10 +136,10 @@ func init() {
|
||||
// LoadCodeComments loads CodeComments
|
||||
func (r *Review) LoadCodeComments(ctx context.Context) (err error) {
|
||||
if r.CodeComments != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
if err = r.loadIssue(ctx); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
r.CodeComments, err = fetchCodeCommentsByReview(ctx, r.Issue, nil, r, false)
|
||||
return err
|
||||
@@ -147,7 +147,7 @@ func (r *Review) LoadCodeComments(ctx context.Context) (err error) {
|
||||
|
||||
func (r *Review) loadIssue(ctx context.Context) (err error) {
|
||||
if r.Issue != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
r.Issue, err = GetIssueByID(ctx, r.IssueID)
|
||||
return err
|
||||
@@ -156,7 +156,7 @@ func (r *Review) loadIssue(ctx context.Context) (err error) {
|
||||
// LoadReviewer loads reviewer
|
||||
func (r *Review) LoadReviewer(ctx context.Context) (err error) {
|
||||
if r.ReviewerID == 0 || r.Reviewer != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
r.Reviewer, err = user_model.GetPossibleUserByID(ctx, r.ReviewerID)
|
||||
return err
|
||||
@@ -186,7 +186,7 @@ func LoadReviewers(ctx context.Context, reviews []*Review) (err error) {
|
||||
// LoadReviewerTeam loads reviewer team
|
||||
func (r *Review) LoadReviewerTeam(ctx context.Context) (err error) {
|
||||
if r.ReviewerTeamID == 0 || r.ReviewerTeam != nil {
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
r.ReviewerTeam, err = organization.GetTeamByID(ctx, r.ReviewerTeamID)
|
||||
@@ -196,16 +196,16 @@ func (r *Review) LoadReviewerTeam(ctx context.Context) (err error) {
|
||||
// LoadAttributes loads all attributes except CodeComments
|
||||
func (r *Review) LoadAttributes(ctx context.Context) (err error) {
|
||||
if err = r.loadIssue(ctx); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
if err = r.LoadCodeComments(ctx); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
if err = r.LoadReviewer(ctx); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
if err = r.LoadReviewerTeam(ctx); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -1111,7 +1111,7 @@ func UpdateReviewsMigrationsByType(tp structs.GitServiceType, originalAuthorID s
|
||||
_, err := db.GetEngine(db.DefaultContext).Table("review").
|
||||
Where("original_author_id = ?", originalAuthorID).
|
||||
And(migratedIssueCond(tp)).
|
||||
Update(map[string]interface{}{
|
||||
Update(map[string]any{
|
||||
"reviewer_id": posterID,
|
||||
"original_author": "",
|
||||
"original_author_id": 0,
|
||||
|
||||
@@ -302,7 +302,7 @@ func DeleteTime(t *TrackedTime) error {
|
||||
func deleteTimes(ctx context.Context, opts FindTrackedTimesOptions) (removedTime int64, err error) {
|
||||
removedTime, err = GetTrackedSeconds(ctx, opts)
|
||||
if err != nil || removedTime == 0 {
|
||||
return
|
||||
return removedTime, err
|
||||
}
|
||||
|
||||
_, err = opts.toSession(db.GetEngine(ctx)).Table("tracked_time").Cols("deleted").Update(&TrackedTime{Deleted: true})
|
||||
|
||||
@@ -27,7 +27,7 @@ import (
|
||||
|
||||
// RecreateTables will recreate the tables for the provided beans using the newly provided bean definition and move all data to that new table
|
||||
// WARNING: YOU MUST PROVIDE THE FULL BEAN DEFINITION
|
||||
func RecreateTables(beans ...interface{}) func(*xorm.Engine) error {
|
||||
func RecreateTables(beans ...any) func(*xorm.Engine) error {
|
||||
return func(x *xorm.Engine) error {
|
||||
sess := x.NewSession()
|
||||
defer sess.Close()
|
||||
@@ -48,7 +48,7 @@ func RecreateTables(beans ...interface{}) func(*xorm.Engine) error {
|
||||
// RecreateTable will recreate the table using the newly provided bean definition and move all data to that new table
|
||||
// WARNING: YOU MUST PROVIDE THE FULL BEAN DEFINITION
|
||||
// WARNING: YOU MUST COMMIT THE SESSION AT THE END
|
||||
func RecreateTable(sess *xorm.Session, bean interface{}) error {
|
||||
func RecreateTable(sess *xorm.Session, bean any) error {
|
||||
// TODO: This will not work if there are foreign keys
|
||||
|
||||
tableName := sess.Engine().TableName(bean)
|
||||
|
||||
@@ -30,7 +30,7 @@ import (
|
||||
// Provide models to be sync'd with the database - in particular any models you expect fixtures to be loaded from.
|
||||
//
|
||||
// fixtures in `models/migrations/fixtures/<TestName>` will be loaded automatically
|
||||
func PrepareTestEnv(t *testing.T, skip int, syncModels ...interface{}) (*xorm.Engine, func()) {
|
||||
func PrepareTestEnv(t *testing.T, skip int, syncModels ...any) (*xorm.Engine, func()) {
|
||||
t.Helper()
|
||||
ourSkip := 2
|
||||
ourSkip += skip
|
||||
|
||||
@@ -59,11 +59,11 @@ func UpdateMigrationServiceTypes(x *xorm.Engine) error {
|
||||
}
|
||||
|
||||
type ExternalLoginUser struct {
|
||||
ExternalID string `xorm:"pk NOT NULL"`
|
||||
UserID int64 `xorm:"INDEX NOT NULL"`
|
||||
LoginSourceID int64 `xorm:"pk NOT NULL"`
|
||||
RawData map[string]interface{} `xorm:"TEXT JSON"`
|
||||
Provider string `xorm:"index VARCHAR(25)"`
|
||||
ExternalID string `xorm:"pk NOT NULL"`
|
||||
UserID int64 `xorm:"INDEX NOT NULL"`
|
||||
LoginSourceID int64 `xorm:"pk NOT NULL"`
|
||||
RawData map[string]any `xorm:"TEXT JSON"`
|
||||
Provider string `xorm:"index VARCHAR(25)"`
|
||||
Email string
|
||||
Name string
|
||||
FirstName string
|
||||
|
||||
@@ -16,10 +16,10 @@ type Watch struct {
|
||||
Mode RepoWatchMode `xorm:"SMALLINT NOT NULL DEFAULT 1"`
|
||||
}
|
||||
|
||||
func AddModeColumnToWatch(x *xorm.Engine) (err error) {
|
||||
if err = x.Sync2(new(Watch)); err != nil {
|
||||
return
|
||||
func AddModeColumnToWatch(x *xorm.Engine) error {
|
||||
if err := x.Sync2(new(Watch)); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = x.Exec("UPDATE `watch` SET `mode` = 1")
|
||||
_, err := x.Exec("UPDATE `watch` SET `mode` = 1")
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -23,25 +23,25 @@ func RecalculateStars(x *xorm.Engine) (err error) {
|
||||
|
||||
for start := 0; ; start += batchSize {
|
||||
users := make([]User, 0, batchSize)
|
||||
if err = sess.Limit(batchSize, start).Where("type = ?", 0).Cols("id").Find(&users); err != nil {
|
||||
return
|
||||
if err := sess.Limit(batchSize, start).Where("type = ?", 0).Cols("id").Find(&users); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(users) == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
if err = sess.Begin(); err != nil {
|
||||
return
|
||||
if err := sess.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, user := range users {
|
||||
if _, err = sess.Exec("UPDATE `user` SET num_stars=(SELECT COUNT(*) FROM `star` WHERE uid=?) WHERE id=?", user.ID, user.ID); err != nil {
|
||||
return
|
||||
if _, err := sess.Exec("UPDATE `user` SET num_stars=(SELECT COUNT(*) FROM `star` WHERE uid=?) WHERE id=?", user.ID, user.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err = sess.Commit(); err != nil {
|
||||
return
|
||||
if err := sess.Commit(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -78,14 +78,14 @@ func RecalculateUserEmptyPWD(x *xorm.Engine) (err error) {
|
||||
for start := 0; ; start += batchSize {
|
||||
users := make([]*User, 0, batchSize)
|
||||
if err = sess.Limit(batchSize, start).Where(builder.Neq{"passwd": ""}, 0).Find(&users); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
if len(users) == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
if err = sess.Begin(); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
|
||||
for _, user := range users {
|
||||
@@ -100,7 +100,7 @@ func RecalculateUserEmptyPWD(x *xorm.Engine) (err error) {
|
||||
}
|
||||
|
||||
if err = sess.Commit(); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,25 +44,25 @@ func DeleteMigrationCredentials(x *xorm.Engine) (err error) {
|
||||
|
||||
for start := 0; ; start += batchSize {
|
||||
tasks := make([]*Task, 0, batchSize)
|
||||
if err = sess.Limit(batchSize, start).Where(cond, 0).Find(&tasks); err != nil {
|
||||
return
|
||||
if err := sess.Limit(batchSize, start).Where(cond, 0).Find(&tasks); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(tasks) == 0 {
|
||||
break
|
||||
}
|
||||
if err = sess.Begin(); err != nil {
|
||||
return
|
||||
if err := sess.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, t := range tasks {
|
||||
if t.PayloadContent, err = removeCredentials(t.PayloadContent); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
if _, err = sess.ID(t.ID).Cols("payload_content").Update(t); err != nil {
|
||||
return
|
||||
if _, err := sess.ID(t.ID).Cols("payload_content").Update(t); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err = sess.Commit(); err != nil {
|
||||
return
|
||||
if err := sess.Commit(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return err
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
func AddPrimaryEmail2EmailAddress(x *xorm.Engine) (err error) {
|
||||
func AddPrimaryEmail2EmailAddress(x *xorm.Engine) error {
|
||||
type User struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
Email string `xorm:"NOT NULL"`
|
||||
@@ -26,12 +26,12 @@ func AddPrimaryEmail2EmailAddress(x *xorm.Engine) (err error) {
|
||||
}
|
||||
|
||||
// Add lower_email and is_primary columns
|
||||
if err = x.Table("email_address").Sync2(new(EmailAddress1)); err != nil {
|
||||
return
|
||||
if err := x.Table("email_address").Sync2(new(EmailAddress1)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = x.Exec("UPDATE email_address SET lower_email=LOWER(email), is_primary=?", false); err != nil {
|
||||
return
|
||||
if _, err := x.Exec("UPDATE email_address SET lower_email=LOWER(email), is_primary=?", false); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
type EmailAddress struct {
|
||||
@@ -44,8 +44,8 @@ func AddPrimaryEmail2EmailAddress(x *xorm.Engine) (err error) {
|
||||
}
|
||||
|
||||
// change lower_email as unique
|
||||
if err = x.Sync2(new(EmailAddress)); err != nil {
|
||||
return
|
||||
if err := x.Sync2(new(EmailAddress)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sess := x.NewSession()
|
||||
@@ -55,34 +55,33 @@ func AddPrimaryEmail2EmailAddress(x *xorm.Engine) (err error) {
|
||||
|
||||
for start := 0; ; start += batchSize {
|
||||
users := make([]*User, 0, batchSize)
|
||||
if err = sess.Limit(batchSize, start).Find(&users); err != nil {
|
||||
return
|
||||
if err := sess.Limit(batchSize, start).Find(&users); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(users) == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
for _, user := range users {
|
||||
var exist bool
|
||||
exist, err = sess.Where("email=?", user.Email).Table("email_address").Exist()
|
||||
exist, err := sess.Where("email=?", user.Email).Table("email_address").Exist()
|
||||
if err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
if !exist {
|
||||
if _, err = sess.Insert(&EmailAddress{
|
||||
if _, err := sess.Insert(&EmailAddress{
|
||||
UID: user.ID,
|
||||
Email: user.Email,
|
||||
LowerEmail: strings.ToLower(user.Email),
|
||||
IsActivated: user.IsActive,
|
||||
IsPrimary: true,
|
||||
}); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if _, err = sess.Where("email=?", user.Email).Cols("is_primary").Update(&EmailAddress{
|
||||
if _, err := sess.Where("email=?", user.Email).Cols("is_primary").Update(&EmailAddress{
|
||||
IsPrimary: true,
|
||||
}); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
)
|
||||
|
||||
func UnwrapLDAPSourceCfg(x *xorm.Engine) error {
|
||||
jsonUnmarshalHandleDoubleEncode := func(bs []byte, v interface{}) error {
|
||||
jsonUnmarshalHandleDoubleEncode := func(bs []byte, v any) error {
|
||||
err := json.Unmarshal(bs, v)
|
||||
if err != nil {
|
||||
ok := true
|
||||
@@ -54,7 +54,7 @@ func UnwrapLDAPSourceCfg(x *xorm.Engine) error {
|
||||
const dldapType = 5
|
||||
|
||||
type WrappedSource struct {
|
||||
Source map[string]interface{}
|
||||
Source map[string]any
|
||||
}
|
||||
|
||||
// change lower_email as unique
|
||||
@@ -77,7 +77,7 @@ func UnwrapLDAPSourceCfg(x *xorm.Engine) error {
|
||||
|
||||
for _, source := range sources {
|
||||
wrapped := &WrappedSource{
|
||||
Source: map[string]interface{}{},
|
||||
Source: map[string]any{},
|
||||
}
|
||||
err := jsonUnmarshalHandleDoubleEncode([]byte(source.Cfg), &wrapped)
|
||||
if err != nil {
|
||||
|
||||
@@ -62,8 +62,8 @@ func Test_UnwrapLDAPSourceCfg(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, source := range sources {
|
||||
converted := map[string]interface{}{}
|
||||
expected := map[string]interface{}{}
|
||||
converted := map[string]any{}
|
||||
expected := map[string]any{}
|
||||
|
||||
if err := json.Unmarshal([]byte(source.Cfg), &converted); err != nil {
|
||||
assert.NoError(t, err)
|
||||
|
||||
@@ -79,7 +79,7 @@ func Test_AddHeaderAuthorizationEncryptedColWebhook(t *testing.T) {
|
||||
return
|
||||
}
|
||||
for _, h := range hookTasks {
|
||||
var m map[string]interface{}
|
||||
var m map[string]any
|
||||
err := json.Unmarshal([]byte(h.PayloadContent), &m)
|
||||
assert.NoError(t, err)
|
||||
assert.Nil(t, m["access_token"])
|
||||
|
||||
@@ -81,11 +81,11 @@ func AddIssueDependencies(x *xorm.Engine) (err error) {
|
||||
// RepoUnit describes all units of a repository
|
||||
type RepoUnit struct {
|
||||
ID int64
|
||||
RepoID int64 `xorm:"INDEX(s)"`
|
||||
Type int `xorm:"INDEX(s)"`
|
||||
Config map[string]interface{} `xorm:"JSON"`
|
||||
CreatedUnix int64 `xorm:"INDEX CREATED"`
|
||||
Created time.Time `xorm:"-"`
|
||||
RepoID int64 `xorm:"INDEX(s)"`
|
||||
Type int `xorm:"INDEX(s)"`
|
||||
Config map[string]any `xorm:"JSON"`
|
||||
CreatedUnix int64 `xorm:"INDEX CREATED"`
|
||||
Created time.Time `xorm:"-"`
|
||||
}
|
||||
|
||||
// Updating existing issue units
|
||||
@@ -96,7 +96,7 @@ func AddIssueDependencies(x *xorm.Engine) (err error) {
|
||||
}
|
||||
for _, unit := range units {
|
||||
if unit.Config == nil {
|
||||
unit.Config = make(map[string]interface{})
|
||||
unit.Config = make(map[string]any)
|
||||
}
|
||||
if _, ok := unit.Config["EnableDependencies"]; !ok {
|
||||
unit.Config["EnableDependencies"] = setting.Service.DefaultEnableDependencies
|
||||
|
||||
@@ -15,10 +15,10 @@ func AddPullRequestRebaseWithMerge(x *xorm.Engine) error {
|
||||
// RepoUnit describes all units of a repository
|
||||
type RepoUnit struct {
|
||||
ID int64
|
||||
RepoID int64 `xorm:"INDEX(s)"`
|
||||
Type int `xorm:"INDEX(s)"`
|
||||
Config map[string]interface{} `xorm:"JSON"`
|
||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX CREATED"`
|
||||
RepoID int64 `xorm:"INDEX(s)"`
|
||||
Type int `xorm:"INDEX(s)"`
|
||||
Config map[string]any `xorm:"JSON"`
|
||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX CREATED"`
|
||||
}
|
||||
|
||||
const (
|
||||
@@ -46,7 +46,7 @@ func AddPullRequestRebaseWithMerge(x *xorm.Engine) error {
|
||||
}
|
||||
for _, unit := range units {
|
||||
if unit.Config == nil {
|
||||
unit.Config = make(map[string]interface{})
|
||||
unit.Config = make(map[string]any)
|
||||
}
|
||||
// Allow the new merge style if all other merge styles are allowed
|
||||
allowMergeRebase := true
|
||||
|
||||
@@ -532,27 +532,6 @@ func GetOrgsCanCreateRepoByUserID(userID int64) ([]*Organization, error) {
|
||||
Find(&orgs)
|
||||
}
|
||||
|
||||
// GetOrgUsersByUserID returns all organization-user relations by user ID.
|
||||
func GetOrgUsersByUserID(uid int64, opts *SearchOrganizationsOptions) ([]*OrgUser, error) {
|
||||
ous := make([]*OrgUser, 0, 10)
|
||||
sess := db.GetEngine(db.DefaultContext).
|
||||
Join("LEFT", "`user`", "`org_user`.org_id=`user`.id").
|
||||
Where("`org_user`.uid=?", uid)
|
||||
if !opts.All {
|
||||
// Only show public organizations
|
||||
sess.And("is_public=?", true)
|
||||
}
|
||||
|
||||
if opts.PageSize != 0 {
|
||||
sess = db.SetSessionPagination(sess, opts)
|
||||
}
|
||||
|
||||
err := sess.
|
||||
Asc("`user`.name").
|
||||
Find(&ous)
|
||||
return ous, err
|
||||
}
|
||||
|
||||
// GetOrgUsersByOrgID returns all organization-user relations by organization ID.
|
||||
func GetOrgUsersByOrgID(ctx context.Context, opts *FindOrgMembersOpts) ([]*OrgUser, error) {
|
||||
sess := db.GetEngine(ctx).Where("org_id=?", opts.OrgID)
|
||||
|
||||
@@ -207,42 +207,6 @@ func TestFindOrgs(t *testing.T) {
|
||||
assert.EqualValues(t, 1, total)
|
||||
}
|
||||
|
||||
func TestGetOrgUsersByUserID(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
orgUsers, err := organization.GetOrgUsersByUserID(5, &organization.SearchOrganizationsOptions{All: true})
|
||||
assert.NoError(t, err)
|
||||
if assert.Len(t, orgUsers, 3) {
|
||||
assert.Equal(t, organization.OrgUser{
|
||||
ID: orgUsers[0].ID,
|
||||
OrgID: 23,
|
||||
UID: 5,
|
||||
IsPublic: false,
|
||||
}, *orgUsers[0])
|
||||
assert.Equal(t, organization.OrgUser{
|
||||
ID: orgUsers[1].ID,
|
||||
OrgID: 6,
|
||||
UID: 5,
|
||||
IsPublic: true,
|
||||
}, *orgUsers[1])
|
||||
assert.Equal(t, organization.OrgUser{
|
||||
ID: orgUsers[2].ID,
|
||||
OrgID: 7,
|
||||
UID: 5,
|
||||
IsPublic: false,
|
||||
}, *orgUsers[2])
|
||||
}
|
||||
|
||||
publicOrgUsers, err := organization.GetOrgUsersByUserID(5, &organization.SearchOrganizationsOptions{All: false})
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, publicOrgUsers, 1)
|
||||
assert.Equal(t, *orgUsers[1], *publicOrgUsers[0])
|
||||
|
||||
orgUsers, err = organization.GetOrgUsersByUserID(1, &organization.SearchOrganizationsOptions{All: true})
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, orgUsers, 0)
|
||||
}
|
||||
|
||||
func TestGetOrgUsersByOrgID(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ type PackageDescriptor struct {
|
||||
Creator *user_model.User
|
||||
PackageProperties PackagePropertyList
|
||||
VersionProperties PackagePropertyList
|
||||
Metadata interface{}
|
||||
Metadata any
|
||||
Files []*PackageFileDescriptor
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ func GetPackageDescriptor(ctx context.Context, pv *PackageVersion) (*PackageDesc
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var metadata interface{}
|
||||
var metadata any
|
||||
switch p.Type {
|
||||
case TypeAlpine:
|
||||
metadata = &alpine.VersionMetadata{}
|
||||
|
||||
@@ -5,11 +5,18 @@ package packages
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/models/perm"
|
||||
"code.gitea.io/gitea/models/unit"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"xorm.io/builder"
|
||||
)
|
||||
|
||||
// ErrPackageBlobNotExist indicates a package blob not exist error
|
||||
@@ -98,3 +105,42 @@ func GetTotalUnreferencedBlobSize(ctx context.Context) (int64, error) {
|
||||
Where("package_file.id IS NULL").
|
||||
SumInt(&PackageBlob{}, "size")
|
||||
}
|
||||
|
||||
// IsBlobAccessibleForUser tests if the user has access to the blob
|
||||
func IsBlobAccessibleForUser(ctx context.Context, blobID int64, user *user_model.User) (bool, error) {
|
||||
if user.IsAdmin {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
maxTeamAuthorize := builder.
|
||||
Select("max(team.authorize)").
|
||||
From("team").
|
||||
InnerJoin("team_user", "team_user.team_id = team.id").
|
||||
Where(builder.Eq{"team_user.uid": user.ID}.And(builder.Expr("team_user.org_id = `user`.id")))
|
||||
|
||||
maxTeamUnitAccessMode := builder.
|
||||
Select("max(team_unit.access_mode)").
|
||||
From("team").
|
||||
InnerJoin("team_user", "team_user.team_id = team.id").
|
||||
InnerJoin("team_unit", "team_unit.team_id = team.id").
|
||||
Where(builder.Eq{"team_user.uid": user.ID, "team_unit.type": unit.TypePackages}.And(builder.Expr("team_user.org_id = `user`.id")))
|
||||
|
||||
cond := builder.Eq{"package_blob.id": blobID}.And(
|
||||
// owner = user
|
||||
builder.Eq{"`user`.id": user.ID}.
|
||||
// user can see owner
|
||||
Or(builder.Eq{"`user`.visibility": structs.VisibleTypePublic}.Or(builder.Eq{"`user`.visibility": structs.VisibleTypeLimited})).
|
||||
// owner is an organization and user has access to it
|
||||
Or(builder.Eq{"`user`.type": user_model.UserTypeOrganization}.
|
||||
And(builder.Lte{strconv.Itoa(int(perm.AccessModeRead)): maxTeamAuthorize}.Or(builder.Lte{strconv.Itoa(int(perm.AccessModeRead)): maxTeamUnitAccessMode}))),
|
||||
)
|
||||
|
||||
return db.GetEngine(ctx).
|
||||
Table("package_blob").
|
||||
Join("INNER", "package_file", "package_file.blob_id = package_blob.id").
|
||||
Join("INNER", "package_version", "package_version.id = package_file.version_id").
|
||||
Join("INNER", "package", "package.id = package_version.package_id").
|
||||
Join("INNER", "user", "`user`.id = package.owner_id").
|
||||
Where(cond).
|
||||
Exist(&PackageBlob{})
|
||||
}
|
||||
|
||||
@@ -127,7 +127,8 @@ func (p *Permission) LogString() string {
|
||||
}
|
||||
|
||||
// GetUserRepoPermission returns the user permissions to the repository
|
||||
func GetUserRepoPermission(ctx context.Context, repo *repo_model.Repository, user *user_model.User) (perm Permission, err error) {
|
||||
func GetUserRepoPermission(ctx context.Context, repo *repo_model.Repository, user *user_model.User) (Permission, error) {
|
||||
var perm Permission
|
||||
if log.IsTrace() {
|
||||
defer func() {
|
||||
if user == nil {
|
||||
@@ -147,30 +148,31 @@ func GetUserRepoPermission(ctx context.Context, repo *repo_model.Repository, use
|
||||
// TODO: anonymous user visit public unit of private repo???
|
||||
if user == nil && repo.IsPrivate {
|
||||
perm.AccessMode = perm_model.AccessModeNone
|
||||
return
|
||||
return perm, nil
|
||||
}
|
||||
|
||||
var is bool
|
||||
var isCollaborator bool
|
||||
var err error
|
||||
if user != nil {
|
||||
is, err = repo_model.IsCollaborator(ctx, repo.ID, user.ID)
|
||||
isCollaborator, err = repo_model.IsCollaborator(ctx, repo.ID, user.ID)
|
||||
if err != nil {
|
||||
return perm, err
|
||||
}
|
||||
}
|
||||
|
||||
if err = repo.LoadOwner(ctx); err != nil {
|
||||
return
|
||||
if err := repo.LoadOwner(ctx); err != nil {
|
||||
return perm, err
|
||||
}
|
||||
|
||||
// Prevent strangers from checking out public repo of private organization/users
|
||||
// Allow user if they are collaborator of a repo within a private user or a private organization but not a member of the organization itself
|
||||
if !organization.HasOrgOrUserVisible(ctx, repo.Owner, user) && !is {
|
||||
if !organization.HasOrgOrUserVisible(ctx, repo.Owner, user) && !isCollaborator {
|
||||
perm.AccessMode = perm_model.AccessModeNone
|
||||
return
|
||||
return perm, nil
|
||||
}
|
||||
|
||||
if err = repo.LoadUnits(ctx); err != nil {
|
||||
return
|
||||
if err := repo.LoadUnits(ctx); err != nil {
|
||||
return perm, err
|
||||
}
|
||||
|
||||
perm.Units = repo.Units
|
||||
@@ -178,32 +180,32 @@ func GetUserRepoPermission(ctx context.Context, repo *repo_model.Repository, use
|
||||
// anonymous visit public repo
|
||||
if user == nil {
|
||||
perm.AccessMode = perm_model.AccessModeRead
|
||||
return
|
||||
return perm, nil
|
||||
}
|
||||
|
||||
// Admin or the owner has super access to the repository
|
||||
if user.IsAdmin || user.ID == repo.OwnerID {
|
||||
perm.AccessMode = perm_model.AccessModeOwner
|
||||
return
|
||||
return perm, nil
|
||||
}
|
||||
|
||||
// plain user
|
||||
perm.AccessMode, err = accessLevel(ctx, user, repo)
|
||||
if err != nil {
|
||||
return
|
||||
return perm, err
|
||||
}
|
||||
|
||||
if err = repo.LoadOwner(ctx); err != nil {
|
||||
return
|
||||
if err := repo.LoadOwner(ctx); err != nil {
|
||||
return perm, err
|
||||
}
|
||||
if !repo.Owner.IsOrganization() {
|
||||
return
|
||||
return perm, nil
|
||||
}
|
||||
|
||||
perm.UnitsMode = make(map[unit.Type]perm_model.AccessMode)
|
||||
|
||||
// Collaborators on organization
|
||||
if is {
|
||||
if isCollaborator {
|
||||
for _, u := range repo.Units {
|
||||
perm.UnitsMode[u.Type] = perm.AccessMode
|
||||
}
|
||||
@@ -212,7 +214,7 @@ func GetUserRepoPermission(ctx context.Context, repo *repo_model.Repository, use
|
||||
// get units mode from teams
|
||||
teams, err := organization.GetUserRepoTeams(ctx, repo.OwnerID, user.ID, repo.ID)
|
||||
if err != nil {
|
||||
return
|
||||
return perm, err
|
||||
}
|
||||
|
||||
// if user in an owner team
|
||||
@@ -220,7 +222,7 @@ func GetUserRepoPermission(ctx context.Context, repo *repo_model.Repository, use
|
||||
if team.AccessMode >= perm_model.AccessModeAdmin {
|
||||
perm.AccessMode = perm_model.AccessModeOwner
|
||||
perm.UnitsMode = nil
|
||||
return
|
||||
return perm, nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -456,7 +456,7 @@ func repoStatsCorrectNumClosedPulls(ctx context.Context, id int64) error {
|
||||
return repo_model.UpdateRepoIssueNumbers(ctx, id, true, true)
|
||||
}
|
||||
|
||||
func statsQuery(args ...interface{}) func(context.Context) ([]map[string][]byte, error) {
|
||||
func statsQuery(args ...any) func(context.Context) ([]map[string][]byte, error) {
|
||||
return func(ctx context.Context) ([]map[string][]byte, error) {
|
||||
return db.GetEngine(ctx).Query(args...)
|
||||
}
|
||||
@@ -628,14 +628,14 @@ func DoctorUserStarNum() (err error) {
|
||||
for start := 0; ; start += batchSize {
|
||||
users := make([]user_model.User, 0, batchSize)
|
||||
if err = db.GetEngine(db.DefaultContext).Limit(batchSize, start).Where("type = ?", 0).Cols("id").Find(&users); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
if len(users) == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
if err = updateUserStarNumbers(users); err != nil {
|
||||
return
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -65,13 +65,6 @@ func (a *Attachment) DownloadURL() string {
|
||||
return setting.AppURL + "attachments/" + url.PathEscape(a.UUID)
|
||||
}
|
||||
|
||||
// _____ __ __ .__ __
|
||||
// / _ \_/ |__/ |______ ____ | |__ _____ ____ _____/ |_
|
||||
// / /_\ \ __\ __\__ \ _/ ___\| | \ / \_/ __ \ / \ __\
|
||||
// / | \ | | | / __ \\ \___| Y \ Y Y \ ___/| | \ |
|
||||
// \____|__ /__| |__| (____ /\___ >___| /__|_| /\___ >___| /__|
|
||||
// \/ \/ \/ \/ \/ \/ \/
|
||||
|
||||
// ErrAttachmentNotExist represents a "AttachmentNotExist" kind of error.
|
||||
type ErrAttachmentNotExist struct {
|
||||
ID int64
|
||||
|
||||
@@ -33,6 +33,19 @@ func TestRepository_GetCollaborators(t *testing.T) {
|
||||
test(2)
|
||||
test(3)
|
||||
test(4)
|
||||
|
||||
// Test db.ListOptions
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 22})
|
||||
|
||||
collaborators1, err := repo_model.GetCollaborators(db.DefaultContext, repo.ID, db.ListOptions{PageSize: 1, Page: 1})
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, collaborators1, 1)
|
||||
|
||||
collaborators2, err := repo_model.GetCollaborators(db.DefaultContext, repo.ID, db.ListOptions{PageSize: 1, Page: 2})
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, collaborators2, 1)
|
||||
|
||||
assert.NotEqualValues(t, collaborators1[0].ID, collaborators2[0].ID)
|
||||
}
|
||||
|
||||
func TestRepository_IsCollaborator(t *testing.T) {
|
||||
@@ -66,5 +79,80 @@ func TestRepository_ChangeCollaborationAccessMode(t *testing.T) {
|
||||
|
||||
assert.NoError(t, repo_model.ChangeCollaborationAccessMode(db.DefaultContext, repo, unittest.NonexistentID, perm.AccessModeAdmin))
|
||||
|
||||
// Disvard invalid input.
|
||||
assert.NoError(t, repo_model.ChangeCollaborationAccessMode(db.DefaultContext, repo, 4, perm.AccessMode(unittest.NonexistentID)))
|
||||
|
||||
unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: repo.ID})
|
||||
}
|
||||
|
||||
func TestRepository_CountCollaborators(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
|
||||
count, err := repo_model.CountCollaborators(repo1.ID)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, 2, count)
|
||||
|
||||
repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 22})
|
||||
count, err = repo_model.CountCollaborators(repo2.ID)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, 2, count)
|
||||
|
||||
// Non-existent repository.
|
||||
count, err = repo_model.CountCollaborators(unittest.NonexistentID)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, 0, count)
|
||||
}
|
||||
|
||||
func TestRepository_IsOwnerMemberCollaborator(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3})
|
||||
|
||||
// Organisation owner.
|
||||
actual, err := repo_model.IsOwnerMemberCollaborator(repo1, 2)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, actual)
|
||||
|
||||
// Team member.
|
||||
actual, err = repo_model.IsOwnerMemberCollaborator(repo1, 4)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, actual)
|
||||
|
||||
// Normal user.
|
||||
actual, err = repo_model.IsOwnerMemberCollaborator(repo1, 1)
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, actual)
|
||||
|
||||
repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
|
||||
|
||||
// Collaborator.
|
||||
actual, err = repo_model.IsOwnerMemberCollaborator(repo2, 4)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, actual)
|
||||
|
||||
repo3 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 15})
|
||||
|
||||
// Repository owner.
|
||||
actual, err = repo_model.IsOwnerMemberCollaborator(repo3, 2)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, actual)
|
||||
}
|
||||
|
||||
func TestRepo_GetCollaboration(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
|
||||
|
||||
// Existing collaboration.
|
||||
collab, err := repo_model.GetCollaboration(db.DefaultContext, repo.ID, 4)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, collab)
|
||||
assert.EqualValues(t, 4, collab.UserID)
|
||||
assert.EqualValues(t, 4, collab.RepoID)
|
||||
|
||||
// Non-existing collaboration.
|
||||
collab, err = repo_model.GetCollaboration(db.DefaultContext, repo.ID, 1)
|
||||
assert.NoError(t, err)
|
||||
assert.Nil(t, collab)
|
||||
}
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ type MergeStyle string
|
||||
const (
|
||||
// MergeStyleMerge create merge commit
|
||||
MergeStyleMerge MergeStyle = "merge"
|
||||
// MergeStyleRebase rebase before merging
|
||||
// MergeStyleRebase rebase before merging, and fast-forward
|
||||
MergeStyleRebase MergeStyle = "rebase"
|
||||
// MergeStyleRebaseMerge rebase before merging with merge commit (--no-ff)
|
||||
MergeStyleRebaseMerge MergeStyle = "rebase-merge"
|
||||
|
||||
@@ -105,7 +105,7 @@ func DeleteMirrorByRepoID(repoID int64) error {
|
||||
}
|
||||
|
||||
// MirrorsIterate iterates all mirror repositories.
|
||||
func MirrorsIterate(limit int, f func(idx int, bean interface{}) error) error {
|
||||
func MirrorsIterate(limit int, f func(idx int, bean any) error) error {
|
||||
sess := db.GetEngine(db.DefaultContext).
|
||||
Where("next_update_unix<=?", time.Now().Unix()).
|
||||
And("next_update_unix!=0").
|
||||
|
||||
@@ -127,7 +127,7 @@ func GetPushMirrorsSyncedOnCommit(ctx context.Context, repoID int64) ([]*PushMir
|
||||
}
|
||||
|
||||
// PushMirrorsIterate iterates all push-mirror repositories.
|
||||
func PushMirrorsIterate(ctx context.Context, limit int, f func(idx int, bean interface{}) error) error {
|
||||
func PushMirrorsIterate(ctx context.Context, limit int, f func(idx int, bean any) error) error {
|
||||
sess := db.GetEngine(ctx).
|
||||
Where("last_update + (`interval` / ?) <= ?", time.Second, time.Now().Unix()).
|
||||
And("`interval` != 0").
|
||||
|
||||
@@ -41,7 +41,7 @@ func TestPushMirrorsIterate(t *testing.T) {
|
||||
|
||||
time.Sleep(1 * time.Millisecond)
|
||||
|
||||
repo_model.PushMirrorsIterate(db.DefaultContext, 1, func(idx int, bean interface{}) error {
|
||||
repo_model.PushMirrorsIterate(db.DefaultContext, 1, func(idx int, bean any) error {
|
||||
m, ok := bean.(*repo_model.PushMirror)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, "test-1", m.RemoteName)
|
||||
|
||||
@@ -339,7 +339,7 @@ func (s releaseMetaSearch) Less(i, j int) bool {
|
||||
// GetReleaseAttachments retrieves the attachments for releases
|
||||
func GetReleaseAttachments(ctx context.Context, rels ...*Release) (err error) {
|
||||
if len(rels) == 0 {
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
// To keep this efficient as possible sort all releases by id,
|
||||
@@ -442,7 +442,7 @@ func UpdateReleasesMigrationsByType(gitServiceType structs.GitServiceType, origi
|
||||
_, err := db.GetEngine(db.DefaultContext).Table("release").
|
||||
Where("repo_id IN (SELECT id FROM repository WHERE original_service_type = ?)", gitServiceType).
|
||||
And("original_author_id = ?", originalAuthorID).
|
||||
Update(map[string]interface{}{
|
||||
Update(map[string]any{
|
||||
"publisher_id": posterID,
|
||||
"original_author": "",
|
||||
"original_author_id": 0,
|
||||
|
||||
@@ -530,6 +530,18 @@ func (repo *Repository) ComposeCompareURL(oldCommitID, newCommitID string) strin
|
||||
return fmt.Sprintf("%s/%s/compare/%s...%s", url.PathEscape(repo.OwnerName), url.PathEscape(repo.Name), util.PathEscapeSegments(oldCommitID), util.PathEscapeSegments(newCommitID))
|
||||
}
|
||||
|
||||
func (repo *Repository) ComposeBranchCompareURL(baseRepo *Repository, branchName string) string {
|
||||
if baseRepo == nil {
|
||||
baseRepo = repo
|
||||
}
|
||||
var cmpBranchEscaped string
|
||||
if repo.ID != baseRepo.ID {
|
||||
cmpBranchEscaped = fmt.Sprintf("%s/%s:", url.PathEscape(repo.OwnerName), url.PathEscape(repo.Name))
|
||||
}
|
||||
cmpBranchEscaped = fmt.Sprintf("%s%s", cmpBranchEscaped, util.PathEscapeSegments(branchName))
|
||||
return fmt.Sprintf("%s/compare/%s...%s", baseRepo.Link(), util.PathEscapeSegments(baseRepo.DefaultBranch), cmpBranchEscaped)
|
||||
}
|
||||
|
||||
// IsOwnedBy returns true when user owns this repository
|
||||
func (repo *Repository) IsOwnedBy(userID int64) bool {
|
||||
return repo.OwnerID == userID
|
||||
|
||||
@@ -560,7 +560,7 @@ func searchRepositoryByCondition(ctx context.Context, opts *SearchRepoOptions, c
|
||||
opts.OrderBy = db.SearchOrderByAlphabetically
|
||||
}
|
||||
|
||||
args := make([]interface{}, 0)
|
||||
args := make([]any, 0)
|
||||
if opts.PriorityOwnerID > 0 {
|
||||
opts.OrderBy = db.SearchOrderBy(fmt.Sprintf("CASE WHEN owner_id = ? THEN 0 ELSE owner_id END, %s", opts.OrderBy))
|
||||
args = append(args, opts.PriorityOwnerID)
|
||||
|
||||
@@ -43,7 +43,7 @@ func (n *Notice) TrStr() string {
|
||||
}
|
||||
|
||||
// CreateNotice creates new system notice.
|
||||
func CreateNotice(ctx context.Context, tp NoticeType, desc string, args ...interface{}) error {
|
||||
func CreateNotice(ctx context.Context, tp NoticeType, desc string, args ...any) error {
|
||||
if len(args) > 0 {
|
||||
desc = fmt.Sprintf(desc, args...)
|
||||
}
|
||||
@@ -55,7 +55,7 @@ func CreateNotice(ctx context.Context, tp NoticeType, desc string, args ...inter
|
||||
}
|
||||
|
||||
// CreateRepositoryNotice creates new system notice with type NoticeRepository.
|
||||
func CreateRepositoryNotice(desc string, args ...interface{}) error {
|
||||
func CreateRepositoryNotice(desc string, args ...any) error {
|
||||
// Note we use the db.DefaultContext here rather than passing in a context as the context may be cancelled
|
||||
return CreateNotice(db.DefaultContext, NoticeRepository, desc, args...)
|
||||
}
|
||||
|
||||
@@ -21,10 +21,10 @@ const (
|
||||
modelsCommentTypeComment = 0
|
||||
)
|
||||
|
||||
var consistencyCheckMap = make(map[string]func(t assert.TestingT, bean interface{}))
|
||||
var consistencyCheckMap = make(map[string]func(t assert.TestingT, bean any))
|
||||
|
||||
// CheckConsistencyFor test that all matching database entries are consistent
|
||||
func CheckConsistencyFor(t assert.TestingT, beansToCheck ...interface{}) {
|
||||
func CheckConsistencyFor(t assert.TestingT, beansToCheck ...any) {
|
||||
for _, bean := range beansToCheck {
|
||||
sliceType := reflect.SliceOf(reflect.TypeOf(bean))
|
||||
sliceValue := reflect.MakeSlice(sliceType, 0, 10)
|
||||
@@ -42,7 +42,7 @@ func CheckConsistencyFor(t assert.TestingT, beansToCheck ...interface{}) {
|
||||
}
|
||||
}
|
||||
|
||||
func checkForConsistency(t assert.TestingT, bean interface{}) {
|
||||
func checkForConsistency(t assert.TestingT, bean any) {
|
||||
tb, err := db.TableInfo(bean)
|
||||
assert.NoError(t, err)
|
||||
f := consistencyCheckMap[tb.Name]
|
||||
@@ -63,7 +63,7 @@ func init() {
|
||||
return i
|
||||
}
|
||||
|
||||
checkForUserConsistency := func(t assert.TestingT, bean interface{}) {
|
||||
checkForUserConsistency := func(t assert.TestingT, bean any) {
|
||||
user := reflectionWrap(bean)
|
||||
AssertCountByCond(t, "repository", builder.Eq{"owner_id": user.int("ID")}, user.int("NumRepos"))
|
||||
AssertCountByCond(t, "star", builder.Eq{"uid": user.int("ID")}, user.int("NumStars"))
|
||||
@@ -77,7 +77,7 @@ func init() {
|
||||
}
|
||||
}
|
||||
|
||||
checkForRepoConsistency := func(t assert.TestingT, bean interface{}) {
|
||||
checkForRepoConsistency := func(t assert.TestingT, bean any) {
|
||||
repo := reflectionWrap(bean)
|
||||
assert.Equal(t, repo.str("LowerName"), strings.ToLower(repo.str("Name")), "repo: %+v", repo)
|
||||
AssertCountByCond(t, "star", builder.Eq{"repo_id": repo.int("ID")}, repo.int("NumStars"))
|
||||
@@ -113,7 +113,7 @@ func init() {
|
||||
"Unexpected number of closed milestones for repo id: %d", repo.int("ID"))
|
||||
}
|
||||
|
||||
checkForIssueConsistency := func(t assert.TestingT, bean interface{}) {
|
||||
checkForIssueConsistency := func(t assert.TestingT, bean any) {
|
||||
issue := reflectionWrap(bean)
|
||||
typeComment := modelsCommentTypeComment
|
||||
actual := GetCountByCond(t, "comment", builder.Eq{"`type`": typeComment, "issue_id": issue.int("ID")})
|
||||
@@ -124,14 +124,14 @@ func init() {
|
||||
}
|
||||
}
|
||||
|
||||
checkForPullRequestConsistency := func(t assert.TestingT, bean interface{}) {
|
||||
checkForPullRequestConsistency := func(t assert.TestingT, bean any) {
|
||||
pr := reflectionWrap(bean)
|
||||
issueRow := AssertExistsAndLoadMap(t, "issue", builder.Eq{"id": pr.int("IssueID")})
|
||||
assert.True(t, parseBool(issueRow["is_pull"]))
|
||||
assert.EqualValues(t, parseInt(issueRow["index"]), pr.int("Index"), "Unexpected index for pull request id: %d", pr.int("ID"))
|
||||
}
|
||||
|
||||
checkForMilestoneConsistency := func(t assert.TestingT, bean interface{}) {
|
||||
checkForMilestoneConsistency := func(t assert.TestingT, bean any) {
|
||||
milestone := reflectionWrap(bean)
|
||||
AssertCountByCond(t, "issue", builder.Eq{"milestone_id": milestone.int("ID")}, milestone.int("NumIssues"))
|
||||
|
||||
@@ -145,7 +145,7 @@ func init() {
|
||||
assert.Equal(t, completeness, milestone.int("Completeness"))
|
||||
}
|
||||
|
||||
checkForLabelConsistency := func(t assert.TestingT, bean interface{}) {
|
||||
checkForLabelConsistency := func(t assert.TestingT, bean any) {
|
||||
label := reflectionWrap(bean)
|
||||
issueLabels, err := db.GetEngine(db.DefaultContext).Table("issue_label").
|
||||
Where(builder.Eq{"label_id": label.int("ID")}).
|
||||
@@ -166,13 +166,13 @@ func init() {
|
||||
assert.EqualValues(t, expected, label.int("NumClosedIssues"), "Unexpected number of closed issues for label id: %d", label.int("ID"))
|
||||
}
|
||||
|
||||
checkForTeamConsistency := func(t assert.TestingT, bean interface{}) {
|
||||
checkForTeamConsistency := func(t assert.TestingT, bean any) {
|
||||
team := reflectionWrap(bean)
|
||||
AssertCountByCond(t, "team_user", builder.Eq{"team_id": team.int("ID")}, team.int("NumMembers"))
|
||||
AssertCountByCond(t, "team_repo", builder.Eq{"team_id": team.int("ID")}, team.int("NumRepos"))
|
||||
}
|
||||
|
||||
checkForActionConsistency := func(t assert.TestingT, bean interface{}) {
|
||||
checkForActionConsistency := func(t assert.TestingT, bean any) {
|
||||
action := reflectionWrap(bean)
|
||||
if action.int("RepoID") != 1700 { // dangling intentional
|
||||
repoRow := AssertExistsAndLoadMap(t, "repository", builder.Eq{"id": action.int("RepoID")})
|
||||
|
||||
@@ -23,7 +23,7 @@ type reflectionValue struct {
|
||||
v reflect.Value
|
||||
}
|
||||
|
||||
func reflectionWrap(v interface{}) *reflectionValue {
|
||||
func reflectionWrap(v any) *reflectionValue {
|
||||
return &reflectionValue{v: reflect.ValueOf(v)}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ func FixturesDir() string {
|
||||
return fixturesDir
|
||||
}
|
||||
|
||||
func fatalTestError(fmtStr string, args ...interface{}) {
|
||||
func fatalTestError(fmtStr string, args ...any) {
|
||||
_, _ = fmt.Fprintf(os.Stderr, fmtStr, args...)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
@@ -57,11 +57,11 @@ func (err ErrExternalLoginUserNotExist) Unwrap() error {
|
||||
|
||||
// ExternalLoginUser makes the connecting between some existing user and additional external login sources
|
||||
type ExternalLoginUser struct {
|
||||
ExternalID string `xorm:"pk NOT NULL"`
|
||||
UserID int64 `xorm:"INDEX NOT NULL"`
|
||||
LoginSourceID int64 `xorm:"pk NOT NULL"`
|
||||
RawData map[string]interface{} `xorm:"TEXT JSON"`
|
||||
Provider string `xorm:"index VARCHAR(25)"`
|
||||
ExternalID string `xorm:"pk NOT NULL"`
|
||||
UserID int64 `xorm:"INDEX NOT NULL"`
|
||||
LoginSourceID int64 `xorm:"pk NOT NULL"`
|
||||
RawData map[string]any `xorm:"TEXT JSON"`
|
||||
Provider string `xorm:"index VARCHAR(25)"`
|
||||
Email string
|
||||
Name string
|
||||
FirstName string
|
||||
|
||||
@@ -64,6 +64,10 @@ func NewUserRedirect(ctx context.Context, ID int64, oldUserName, newUserName str
|
||||
oldUserName = strings.ToLower(oldUserName)
|
||||
newUserName = strings.ToLower(newUserName)
|
||||
|
||||
if err := DeleteUserRedirect(ctx, oldUserName); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := DeleteUserRedirect(ctx, newUserName); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
+1
-1
@@ -336,7 +336,7 @@ func GetUserFollowers(ctx context.Context, u, viewer *User, listOptions db.ListO
|
||||
|
||||
// GetUserFollowing returns range of user's following.
|
||||
func GetUserFollowing(ctx context.Context, u, viewer *User, listOptions db.ListOptions) ([]*User, int64, error) {
|
||||
sess := db.GetEngine(db.DefaultContext).
|
||||
sess := db.GetEngine(ctx).
|
||||
Select("`user`.*").
|
||||
Join("LEFT", "follow", "`user`.id=follow.follow_id").
|
||||
Where("follow.user_id=?", u.ID).
|
||||
|
||||
@@ -92,7 +92,7 @@ func (t *HookTask) AfterLoad() {
|
||||
}
|
||||
}
|
||||
|
||||
func (t *HookTask) simpleMarshalJSON(v interface{}) string {
|
||||
func (t *HookTask) simpleMarshalJSON(v any) string {
|
||||
p, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
log.Error("Marshal [%d]: %v", t.ID, err)
|
||||
|
||||
@@ -23,13 +23,11 @@ import (
|
||||
type DetectedWorkflow struct {
|
||||
EntryName string
|
||||
TriggerEvent string
|
||||
Commit *git.Commit
|
||||
Ref string
|
||||
Content []byte
|
||||
}
|
||||
|
||||
func init() {
|
||||
model.OnDecodeNodeError = func(node yaml.Node, out interface{}, err error) {
|
||||
model.OnDecodeNodeError = func(node yaml.Node, out any, err error) {
|
||||
// Log the error instead of panic or fatal.
|
||||
// It will be a big job to refactor act/pkg/model to return decode error,
|
||||
// so we just log the error and return empty value, and improve it later.
|
||||
@@ -120,7 +118,6 @@ func DetectWorkflows(commit *git.Commit, triggedEvent webhook_module.HookEventTy
|
||||
dwf := &DetectedWorkflow{
|
||||
EntryName: entry.Name(),
|
||||
TriggerEvent: evt.Name,
|
||||
Commit: commit,
|
||||
Content: content,
|
||||
}
|
||||
workflows = append(workflows, dwf)
|
||||
@@ -335,44 +332,47 @@ func matchIssuesEvent(commit *git.Commit, issuePayload *api.IssuePayload, evt *j
|
||||
}
|
||||
|
||||
func matchPullRequestEvent(commit *git.Commit, prPayload *api.PullRequestPayload, evt *jobparser.Event) bool {
|
||||
// with no special filter parameters
|
||||
if len(evt.Acts()) == 0 {
|
||||
acts := evt.Acts()
|
||||
activityTypeMatched := false
|
||||
matchTimes := 0
|
||||
|
||||
if vals, ok := acts["types"]; !ok {
|
||||
// defaultly, only pull request `opened`, `reopened` and `synchronized` will trigger workflow
|
||||
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request
|
||||
return prPayload.Action == api.HookIssueSynchronized || prPayload.Action == api.HookIssueOpened || prPayload.Action == api.HookIssueReOpened
|
||||
activityTypeMatched = prPayload.Action == api.HookIssueSynchronized || prPayload.Action == api.HookIssueOpened || prPayload.Action == api.HookIssueReOpened
|
||||
} else {
|
||||
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request
|
||||
// Actions with the same name:
|
||||
// opened, edited, closed, reopened, assigned, unassigned
|
||||
// Actions need to be converted:
|
||||
// synchronized -> synchronize
|
||||
// label_updated -> labeled
|
||||
// label_cleared -> unlabeled
|
||||
// Unsupported activity types:
|
||||
// converted_to_draft, ready_for_review, locked, unlocked, review_requested, review_request_removed, auto_merge_enabled, auto_merge_disabled
|
||||
|
||||
action := prPayload.Action
|
||||
switch action {
|
||||
case api.HookIssueSynchronized:
|
||||
action = "synchronize"
|
||||
case api.HookIssueLabelUpdated:
|
||||
action = "labeled"
|
||||
case api.HookIssueLabelCleared:
|
||||
action = "unlabeled"
|
||||
}
|
||||
log.Trace("matching pull_request %s with %v", action, vals)
|
||||
for _, val := range vals {
|
||||
if glob.MustCompile(val, '/').Match(string(action)) {
|
||||
activityTypeMatched = true
|
||||
matchTimes++
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
matchTimes := 0
|
||||
// all acts conditions should be satisfied
|
||||
for cond, vals := range evt.Acts() {
|
||||
for cond, vals := range acts {
|
||||
switch cond {
|
||||
case "types":
|
||||
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request
|
||||
// Actions with the same name:
|
||||
// opened, edited, closed, reopened, assigned, unassigned
|
||||
// Actions need to be converted:
|
||||
// synchronized -> synchronize
|
||||
// label_updated -> labeled
|
||||
// label_cleared -> unlabeled
|
||||
// Unsupported activity types:
|
||||
// converted_to_draft, ready_for_review, locked, unlocked, review_requested, review_request_removed, auto_merge_enabled, auto_merge_disabled
|
||||
|
||||
action := prPayload.Action
|
||||
switch action {
|
||||
case api.HookIssueSynchronized:
|
||||
action = "synchronize"
|
||||
case api.HookIssueLabelUpdated:
|
||||
action = "labeled"
|
||||
case api.HookIssueLabelCleared:
|
||||
action = "unlabeled"
|
||||
}
|
||||
log.Trace("matching pull_request %s with %v", action, vals)
|
||||
for _, val := range vals {
|
||||
if glob.MustCompile(val, '/').Match(string(action)) {
|
||||
matchTimes++
|
||||
break
|
||||
}
|
||||
}
|
||||
case "branches":
|
||||
refName := git.RefName(prPayload.PullRequest.Base.Ref)
|
||||
patterns, err := workflowpattern.CompilePatterns(vals...)
|
||||
@@ -421,7 +421,7 @@ func matchPullRequestEvent(commit *git.Commit, prPayload *api.PullRequestPayload
|
||||
log.Warn("pull request event unsupported condition %q", cond)
|
||||
}
|
||||
}
|
||||
return matchTimes == len(evt.Acts())
|
||||
return activityTypeMatched && matchTimes == len(evt.Acts())
|
||||
}
|
||||
|
||||
func matchIssueCommentEvent(commit *git.Commit, issueCommentPayload *api.IssueCommentPayload, evt *jobparser.Event) bool {
|
||||
|
||||
@@ -57,6 +57,25 @@ func TestDetectMatched(t *testing.T) {
|
||||
yamlOn: "on: pull_request",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
desc: "HookEventPullRequest(pull_request) `closed` action doesn't match GithubEventPullRequest(pull_request) with no activity type",
|
||||
triggedEvent: webhook_module.HookEventPullRequest,
|
||||
payload: &api.PullRequestPayload{Action: api.HookIssueClosed},
|
||||
yamlOn: "on: pull_request",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
desc: "HookEventPullRequest(pull_request) `closed` action doesn't match GithubEventPullRequest(pull_request) with branches",
|
||||
triggedEvent: webhook_module.HookEventPullRequest,
|
||||
payload: &api.PullRequestPayload{
|
||||
Action: api.HookIssueClosed,
|
||||
PullRequest: &api.PullRequest{
|
||||
Base: &api.PRBranchInfo{},
|
||||
},
|
||||
},
|
||||
yamlOn: "on:\n pull_request:\n branches: [main]",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
desc: "HookEventPullRequest(pull_request) `label_updated` action matches GithubEventPullRequest(pull_request) with `label` activity type",
|
||||
triggedEvent: webhook_module.HookEventPullRequest,
|
||||
|
||||
@@ -63,19 +63,19 @@ type Client struct {
|
||||
// NewClient function
|
||||
func NewClient(user *user_model.User, pubID string) (c *Client, err error) {
|
||||
if err = containsRequiredHTTPHeaders(http.MethodGet, setting.Federation.GetHeaders); err != nil {
|
||||
return
|
||||
return nil, err
|
||||
} else if err = containsRequiredHTTPHeaders(http.MethodPost, setting.Federation.PostHeaders); err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
|
||||
priv, err := GetPrivateKey(user)
|
||||
if err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
privPem, _ := pem.Decode([]byte(priv))
|
||||
privParsed, err := x509.ParsePKCS1PrivateKey(privPem.Bytes)
|
||||
if err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c = &Client{
|
||||
@@ -99,14 +99,14 @@ func (c *Client) NewRequest(b []byte, to string) (req *http.Request, err error)
|
||||
buf := bytes.NewBuffer(b)
|
||||
req, err = http.NewRequest(http.MethodPost, to, buf)
|
||||
if err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Add("Content-Type", ActivityStreamsContentType)
|
||||
req.Header.Add("Date", CurrentTime())
|
||||
req.Header.Add("User-Agent", "Gitea/"+setting.AppVer)
|
||||
signer, _, err := httpsig.NewSigner(c.algs, c.digestAlg, c.postHeaders, httpsig.Signature, httpsigExpirationTime)
|
||||
if err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
err = signer.SignRequest(c.priv, c.pubID, req, b)
|
||||
return req, err
|
||||
@@ -116,7 +116,7 @@ func (c *Client) NewRequest(b []byte, to string) (req *http.Request, err error)
|
||||
func (c *Client) Post(b []byte, to string) (resp *http.Response, err error) {
|
||||
var req *http.Request
|
||||
if req, err = c.NewRequest(b, to); err != nil {
|
||||
return
|
||||
return nil, err
|
||||
}
|
||||
resp, err = c.client.Do(req)
|
||||
return resp, err
|
||||
|
||||
@@ -15,22 +15,22 @@ func GetKeyPair(user *user_model.User) (pub, priv string, err error) {
|
||||
var settings map[string]*user_model.Setting
|
||||
settings, err = user_model.GetSettings(user.ID, []string{user_model.UserActivityPubPrivPem, user_model.UserActivityPubPubPem})
|
||||
if err != nil {
|
||||
return
|
||||
return pub, priv, err
|
||||
} else if len(settings) == 0 {
|
||||
if priv, pub, err = util.GenerateKeyPair(rsaBits); err != nil {
|
||||
return
|
||||
return pub, priv, err
|
||||
}
|
||||
if err = user_model.SetUserSetting(user.ID, user_model.UserActivityPubPrivPem, priv); err != nil {
|
||||
return
|
||||
return pub, priv, err
|
||||
}
|
||||
if err = user_model.SetUserSetting(user.ID, user_model.UserActivityPubPubPem, pub); err != nil {
|
||||
return
|
||||
return pub, priv, err
|
||||
}
|
||||
return
|
||||
return pub, priv, err
|
||||
} else {
|
||||
priv = settings[user_model.UserActivityPubPrivPem].SettingValue
|
||||
pub = settings[user_model.UserActivityPubPubPem].SettingValue
|
||||
return
|
||||
return pub, priv, err
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -215,6 +215,7 @@ func (l *LayeredFS) WatchLocalChanges(ctx context.Context, callback func()) {
|
||||
log.Error("Unable to list directories for asset local file-system %q: %v", layer.localPath, err)
|
||||
continue
|
||||
}
|
||||
layerDirs = append(layerDirs, ".")
|
||||
for _, dir := range layerDirs {
|
||||
if err = watcher.Add(util.FilePathJoinAbs(layer.localPath, dir)); err != nil {
|
||||
log.Error("Unable to watch directory %s: %v", dir, err)
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package avatar_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"image"
|
||||
"image/png"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/modules/avatar"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_HashAvatar(t *testing.T) {
|
||||
myImage := image.NewRGBA(image.Rect(0, 0, 32, 32))
|
||||
var buff bytes.Buffer
|
||||
png.Encode(&buff, myImage)
|
||||
|
||||
assert.EqualValues(t, "9ddb5bac41d57e72aa876321d0c09d71090c05f94bc625303801be2f3240d2cb", avatar.HashAvatar(1, buff.Bytes()))
|
||||
assert.EqualValues(t, "9a5d44e5d637b9582a976676e8f3de1dccd877c2fe3e66ca3fab1629f2f47609", avatar.HashAvatar(8, buff.Bytes()))
|
||||
assert.EqualValues(t, "ed7399158672088770de6f5211ce15528ebd675e92fc4fc060c025f4b2794ccb", avatar.HashAvatar(1024, buff.Bytes()))
|
||||
assert.EqualValues(t, "161178642c7d59eb25a61dddced5e6b66eae1c70880d5f148b1b497b767e72d9", avatar.HashAvatar(1024, []byte{}))
|
||||
}
|
||||
@@ -107,7 +107,7 @@ const TimeLimitCodeLength = 12 + 6 + 40
|
||||
|
||||
// CreateTimeLimitCode create a time limit code
|
||||
// code format: 12 length date time string + 6 minutes string + 40 sha1 encoded string
|
||||
func CreateTimeLimitCode(data string, minutes int, startInf interface{}) string {
|
||||
func CreateTimeLimitCode(data string, minutes int, startInf any) string {
|
||||
format := "200601021504"
|
||||
|
||||
var start, end time.Time
|
||||
@@ -252,7 +252,7 @@ func SetupGiteaRoot() string {
|
||||
}
|
||||
|
||||
// FormatNumberSI format a number
|
||||
func FormatNumberSI(data interface{}) string {
|
||||
func FormatNumberSI(data any) string {
|
||||
var num int64
|
||||
if num1, ok := data.(int64); ok {
|
||||
num = num1
|
||||
|
||||
Vendored
+3
-3
@@ -24,7 +24,7 @@ type RedisCacher struct {
|
||||
}
|
||||
|
||||
// toStr convert string/int/int64 interface to string. it's only used by the RedisCacher.Put internally
|
||||
func toStr(v interface{}) string {
|
||||
func toStr(v any) string {
|
||||
if v == nil {
|
||||
return ""
|
||||
}
|
||||
@@ -44,7 +44,7 @@ func toStr(v interface{}) string {
|
||||
|
||||
// Put puts value (string type) into cache with key and expire time.
|
||||
// If expired is 0, it lives forever.
|
||||
func (c *RedisCacher) Put(key string, val interface{}, expire int64) error {
|
||||
func (c *RedisCacher) Put(key string, val any, expire int64) error {
|
||||
// this function is not well-designed, it only puts string values into cache
|
||||
key = c.prefix + key
|
||||
if expire == 0 {
|
||||
@@ -65,7 +65,7 @@ func (c *RedisCacher) Put(key string, val interface{}, expire int64) error {
|
||||
}
|
||||
|
||||
// Get gets cached value by given key.
|
||||
func (c *RedisCacher) Get(key string) interface{} {
|
||||
func (c *RedisCacher) Get(key string) any {
|
||||
val, err := c.c.Get(graceful.GetManager().HammerContext(), c.prefix+key).Result()
|
||||
if err != nil {
|
||||
return nil
|
||||
|
||||
Vendored
+4
-4
@@ -30,7 +30,7 @@ type TwoQueueCacheConfig struct {
|
||||
|
||||
// MemoryItem represents a memory cache item.
|
||||
type MemoryItem struct {
|
||||
Val interface{}
|
||||
Val any
|
||||
Created int64
|
||||
Timeout int64
|
||||
}
|
||||
@@ -43,7 +43,7 @@ func (item *MemoryItem) hasExpired() bool {
|
||||
var _ mc.Cache = &TwoQueueCache{}
|
||||
|
||||
// Put puts value into cache with key and expire time.
|
||||
func (c *TwoQueueCache) Put(key string, val interface{}, timeout int64) error {
|
||||
func (c *TwoQueueCache) Put(key string, val any, timeout int64) error {
|
||||
item := &MemoryItem{
|
||||
Val: val,
|
||||
Created: time.Now().Unix(),
|
||||
@@ -56,7 +56,7 @@ func (c *TwoQueueCache) Put(key string, val interface{}, timeout int64) error {
|
||||
}
|
||||
|
||||
// Get gets cached value by given key.
|
||||
func (c *TwoQueueCache) Get(key string) interface{} {
|
||||
func (c *TwoQueueCache) Get(key string) any {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
cached, ok := c.cache.Get(key)
|
||||
@@ -146,7 +146,7 @@ func (c *TwoQueueCache) Flush() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *TwoQueueCache) checkAndInvalidate(key interface{}) {
|
||||
func (c *TwoQueueCache) checkAndInvalidate(key any) {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
cached, ok := c.cache.Peek(key)
|
||||
|
||||
@@ -90,7 +90,7 @@ Usage: %[1]s [-v] [-o output.go] ambiguous.json
|
||||
sort.Slice(tables, func(i, j int) bool {
|
||||
return tables[i].Locale < tables[j].Locale
|
||||
})
|
||||
data := map[string]interface{}{
|
||||
data := map[string]any{
|
||||
"Tables": tables,
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ Usage: %[1]s [-v] [-o output.go] ambiguous.json
|
||||
}
|
||||
}
|
||||
|
||||
func runTemplate(t *template.Template, filename string, data interface{}) error {
|
||||
func runTemplate(t *template.Template, filename string, data any) error {
|
||||
buf := bytes.NewBuffer(nil)
|
||||
if err := t.Execute(buf, data); err != nil {
|
||||
return fmt.Errorf("unable to execute template: %w", err)
|
||||
@@ -172,17 +172,17 @@ var AmbiguousCharacters = map[string]*AmbiguousTable{
|
||||
|
||||
`))
|
||||
|
||||
func logf(format string, args ...interface{}) {
|
||||
func logf(format string, args ...any) {
|
||||
fmt.Fprintf(os.Stderr, format+"\n", args...)
|
||||
}
|
||||
|
||||
func verbosef(format string, args ...interface{}) {
|
||||
func verbosef(format string, args ...any) {
|
||||
if verbose {
|
||||
logf(format, args...)
|
||||
}
|
||||
}
|
||||
|
||||
func fatalf(format string, args ...interface{}) {
|
||||
func fatalf(format string, args ...any) {
|
||||
logf("fatal: "+format+"\n", args...)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ Usage: %[1]s [-v] [-o output.go]
|
||||
}
|
||||
}
|
||||
|
||||
func runTemplate(t *template.Template, filename string, data interface{}) error {
|
||||
func runTemplate(t *template.Template, filename string, data any) error {
|
||||
buf := bytes.NewBuffer(nil)
|
||||
if err := t.Execute(buf, data); err != nil {
|
||||
return fmt.Errorf("unable to execute template: %w", err)
|
||||
@@ -105,17 +105,17 @@ var InvisibleRanges = &unicode.RangeTable{
|
||||
}
|
||||
`))
|
||||
|
||||
func logf(format string, args ...interface{}) {
|
||||
func logf(format string, args ...any) {
|
||||
fmt.Fprintf(os.Stderr, format+"\n", args...)
|
||||
}
|
||||
|
||||
func verbosef(format string, args ...interface{}) {
|
||||
func verbosef(format string, args ...any) {
|
||||
if verbose {
|
||||
logf(format, args...)
|
||||
}
|
||||
}
|
||||
|
||||
func fatalf(format string, args ...interface{}) {
|
||||
func fatalf(format string, args ...any) {
|
||||
logf("fatal: "+format+"\n", args...)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ type routerLoggerOptions struct {
|
||||
Identity *string
|
||||
Start *time.Time
|
||||
ResponseWriter http.ResponseWriter
|
||||
Ctx map[string]interface{}
|
||||
Ctx map[string]any
|
||||
RequestID *string
|
||||
}
|
||||
|
||||
@@ -84,7 +84,7 @@ func AccessLogger() func(http.Handler) http.Handler {
|
||||
Identity: &identity,
|
||||
Start: &start,
|
||||
ResponseWriter: rw,
|
||||
Ctx: map[string]interface{}{
|
||||
Ctx: map[string]any{
|
||||
"RemoteAddr": req.RemoteAddr,
|
||||
"RemoteHost": reqHost,
|
||||
"Req": req,
|
||||
|
||||
@@ -108,7 +108,7 @@ func (ctx *APIContext) ServerError(title string, err error) {
|
||||
|
||||
// Error responds with an error message to client with given obj as the message.
|
||||
// If status is 500, also it prints error to log.
|
||||
func (ctx *APIContext) Error(status int, title string, obj interface{}) {
|
||||
func (ctx *APIContext) Error(status int, title string, obj any) {
|
||||
var message string
|
||||
if err, ok := obj.(error); ok {
|
||||
message = err.Error()
|
||||
@@ -265,7 +265,7 @@ func APIContexter() func(http.Handler) http.Handler {
|
||||
|
||||
// NotFound handles 404s for APIContext
|
||||
// String will replace message, errors will be added to a slice
|
||||
func (ctx *APIContext) NotFound(objs ...interface{}) {
|
||||
func (ctx *APIContext) NotFound(objs ...any) {
|
||||
message := ctx.Tr("error.not_found")
|
||||
var errors []string
|
||||
for _, obj := range objs {
|
||||
@@ -281,7 +281,7 @@ func (ctx *APIContext) NotFound(objs ...interface{}) {
|
||||
}
|
||||
}
|
||||
|
||||
ctx.JSON(http.StatusNotFound, map[string]interface{}{
|
||||
ctx.JSON(http.StatusNotFound, map[string]any{
|
||||
"message": message,
|
||||
"url": setting.API.SwaggerURL,
|
||||
"errors": errors,
|
||||
@@ -294,7 +294,7 @@ func ReferencesGitRepo(allowEmpty ...bool) func(ctx *APIContext) (cancel context
|
||||
return func(ctx *APIContext) (cancel context.CancelFunc) {
|
||||
// Empty repository does not have reference information.
|
||||
if ctx.Repo.Repository.IsEmpty && !(len(allowEmpty) != 0 && allowEmpty[0]) {
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
// For API calls.
|
||||
@@ -303,7 +303,7 @@ func ReferencesGitRepo(allowEmpty ...bool) func(ctx *APIContext) (cancel context
|
||||
gitRepo, err := git.OpenRepository(ctx, repoPath)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "RepoRef Invalid repo "+repoPath, err)
|
||||
return
|
||||
return cancel
|
||||
}
|
||||
ctx.Repo.GitRepo = gitRepo
|
||||
// We opened it, we should close it
|
||||
|
||||
@@ -128,7 +128,7 @@ func (b *Base) Error(status int, contents ...string) {
|
||||
}
|
||||
|
||||
// JSON render content as JSON
|
||||
func (b *Base) JSON(status int, content interface{}) {
|
||||
func (b *Base) JSON(status int, content any) {
|
||||
b.Resp.Header().Set("Content-Type", "application/json;charset=utf-8")
|
||||
b.Resp.WriteHeader(status)
|
||||
if err := json.NewEncoder(b.Resp).Encode(content); err != nil {
|
||||
|
||||
@@ -60,7 +60,7 @@ const (
|
||||
|
||||
// VerifyCaptcha verifies Captcha data
|
||||
// No-op if captchas are not enabled
|
||||
func VerifyCaptcha(ctx *Context, tpl base.TplName, form interface{}) {
|
||||
func VerifyCaptcha(ctx *Context, tpl base.TplName, form any) {
|
||||
if !setting.Service.EnableCaptcha {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ import (
|
||||
// Render represents a template render
|
||||
type Render interface {
|
||||
TemplateLookup(tmpl string) (templates.TemplateExecutor, error)
|
||||
HTML(w io.Writer, status int, name string, data interface{}) error
|
||||
HTML(w io.Writer, status int, name string, data any) error
|
||||
}
|
||||
|
||||
// Context represents context of a request.
|
||||
@@ -69,7 +69,7 @@ func init() {
|
||||
// TrHTMLEscapeArgs runs ".Locale.Tr()" but pre-escapes all arguments with html.EscapeString.
|
||||
// This is useful if the locale message is intended to only produce HTML content.
|
||||
func (ctx *Context) TrHTMLEscapeArgs(msg string, args ...string) string {
|
||||
trArgs := make([]interface{}, len(args))
|
||||
trArgs := make([]any, len(args))
|
||||
for i, arg := range args {
|
||||
trArgs[i] = html.EscapeString(arg)
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user