Compare commits
55 Commits
main
...
knacker_wo
Author | SHA1 | Date | |
---|---|---|---|
|
8c5c2a2ce9 | ||
|
e77b76425e | ||
|
1d52228ee7 | ||
|
371dd96e3e | ||
|
c8b217110b | ||
|
1c7496c7a7 | ||
|
2e5ac53bdc | ||
|
2836382f34 | ||
|
c2fb27beb4 | ||
|
e4eaa68a2b | ||
|
b4802b9b2e | ||
|
9380bb6d0c | ||
|
43aafc5ba1 | ||
|
32db62515f | ||
|
d3f850cc0e | ||
|
c8f3eb6acb | ||
|
eec1c71880 | ||
|
044c754ea5 | ||
|
fefdb7ffd1 | ||
|
595d940daa | ||
|
6da8bc6be9 | ||
|
20385b52a3 | ||
|
0b993a0d04 | ||
|
6dbcf724ac | ||
|
88d5275614 | ||
|
43ab9324c5 | ||
|
c144942b23 | ||
|
92dd24716d | ||
|
f311d15a0b | ||
|
40229a7dd8 | ||
|
6c8ff32511 | ||
|
c772934ff6 | ||
|
de6dfb7141 | ||
|
55115dbb73 | ||
|
d9ba7f7442 | ||
|
3e3975e0fa | ||
|
8ce2dd588a | ||
|
0ace4cee33 | ||
|
6f3efdfe11 | ||
|
bea25d77ce | ||
|
34283a74e8 | ||
|
a0a425a13b | ||
|
158b088ec3 | ||
|
aed1622766 | ||
|
bf2078640f | ||
|
9f8e778918 | ||
|
9db221780f | ||
|
50dd32ede4 | ||
|
2cbea23d70 | ||
|
fb704f6c72 | ||
|
92525ddffd | ||
|
1d22911cfe | ||
|
385462d36c | ||
|
ce5aafbc69 | ||
|
99688ef994 |
114
.dockerignore
Normal file
114
.dockerignore
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||||
|
*.o
|
||||||
|
*.a
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Folders
|
||||||
|
_obj
|
||||||
|
_test
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
.idea
|
||||||
|
# Goland's output filename can not be set manually
|
||||||
|
/go_build_*
|
||||||
|
|
||||||
|
# MS VSCode
|
||||||
|
.vscode
|
||||||
|
__debug_bin
|
||||||
|
|
||||||
|
# Architecture specific extensions/prefixes
|
||||||
|
*.[568vq]
|
||||||
|
[568vq].out
|
||||||
|
|
||||||
|
*.cgo1.go
|
||||||
|
*.cgo2.c
|
||||||
|
_cgo_defun.c
|
||||||
|
_cgo_gotypes.go
|
||||||
|
_cgo_export.*
|
||||||
|
|
||||||
|
_testmain.go
|
||||||
|
|
||||||
|
*.exe
|
||||||
|
*.test
|
||||||
|
*.prof
|
||||||
|
|
||||||
|
*coverage.out
|
||||||
|
coverage.all
|
||||||
|
cpu.out
|
||||||
|
|
||||||
|
/modules/migration/bindata.go
|
||||||
|
/modules/migration/bindata.go.hash
|
||||||
|
/modules/options/bindata.go
|
||||||
|
/modules/options/bindata.go.hash
|
||||||
|
/modules/public/bindata.go
|
||||||
|
/modules/public/bindata.go.hash
|
||||||
|
/modules/templates/bindata.go
|
||||||
|
/modules/templates/bindata.go.hash
|
||||||
|
|
||||||
|
*.db
|
||||||
|
*.log
|
||||||
|
|
||||||
|
/gitea
|
||||||
|
/gitea-vet
|
||||||
|
/debug
|
||||||
|
/integrations.test
|
||||||
|
|
||||||
|
/bin
|
||||||
|
/dist
|
||||||
|
/custom/*
|
||||||
|
!/custom/conf
|
||||||
|
/custom/conf/*
|
||||||
|
!/custom/conf/app.example.ini
|
||||||
|
/data
|
||||||
|
/indexers
|
||||||
|
/log
|
||||||
|
/public/img/avatar
|
||||||
|
/tests/integration/gitea-integration-*
|
||||||
|
/tests/integration/indexers-*
|
||||||
|
/tests/e2e/gitea-e2e-*
|
||||||
|
/tests/e2e/indexers-*
|
||||||
|
/tests/e2e/reports
|
||||||
|
/tests/e2e/test-artifacts
|
||||||
|
/tests/e2e/test-snapshots
|
||||||
|
/tests/*.ini
|
||||||
|
/node_modules
|
||||||
|
/yarn.lock
|
||||||
|
/yarn-error.log
|
||||||
|
/npm-debug.log*
|
||||||
|
/public/js
|
||||||
|
/public/serviceworker.js
|
||||||
|
/public/css
|
||||||
|
/public/fonts
|
||||||
|
/public/img/webpack
|
||||||
|
/vendor
|
||||||
|
/web_src/fomantic/node_modules
|
||||||
|
/web_src/fomantic/build/*
|
||||||
|
!/web_src/fomantic/build/semantic.js
|
||||||
|
!/web_src/fomantic/build/semantic.css
|
||||||
|
!/web_src/fomantic/build/themes
|
||||||
|
/web_src/fomantic/build/themes/*
|
||||||
|
!/web_src/fomantic/build/themes/default
|
||||||
|
/web_src/fomantic/build/themes/default/assets/*
|
||||||
|
!/web_src/fomantic/build/themes/default/assets/fonts
|
||||||
|
/web_src/fomantic/build/themes/default/assets/fonts/*
|
||||||
|
!/web_src/fomantic/build/themes/default/assets/fonts/icons.woff2
|
||||||
|
!/web_src/fomantic/build/themes/default/assets/fonts/outline-icons.woff2
|
||||||
|
/VERSION
|
||||||
|
/.air
|
||||||
|
/.go-licenses
|
||||||
|
|
||||||
|
# Snapcraft
|
||||||
|
snap/.snapcraft/
|
||||||
|
parts/
|
||||||
|
stage/
|
||||||
|
prime/
|
||||||
|
*.snap
|
||||||
|
*.snap-build
|
||||||
|
*_source.tar.bz2
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Make evidence files
|
||||||
|
/.make_evidence
|
||||||
|
|
||||||
|
# Manpage
|
||||||
|
/man
|
12
.drone.yml
12
.drone.yml
@ -39,16 +39,6 @@ steps:
|
|||||||
- make lint-frontend
|
- make lint-frontend
|
||||||
depends_on: [deps-frontend]
|
depends_on: [deps-frontend]
|
||||||
|
|
||||||
- name: security-check
|
|
||||||
image: golang:1.19
|
|
||||||
pull: always
|
|
||||||
commands:
|
|
||||||
- make security-check
|
|
||||||
depends_on: [deps-backend]
|
|
||||||
volumes:
|
|
||||||
- name: deps
|
|
||||||
path: /go
|
|
||||||
|
|
||||||
- name: lint-backend
|
- name: lint-backend
|
||||||
image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
|
image: gitea/test_env:linux-amd64 # https://gitea.com/gitea/test-env
|
||||||
pull: always
|
pull: always
|
||||||
@ -561,7 +551,7 @@ steps:
|
|||||||
|
|
||||||
# TODO: We should probably build all dependencies into a test image
|
# TODO: We should probably build all dependencies into a test image
|
||||||
- name: test-e2e
|
- name: test-e2e
|
||||||
image: mcr.microsoft.com/playwright:v1.27.1-focal
|
image: mcr.microsoft.com/playwright:v1.28.0-focal
|
||||||
commands:
|
commands:
|
||||||
- curl -sLO https://go.dev/dl/go1.19.linux-amd64.tar.gz && tar -C /usr/local -xzf go1.19.linux-amd64.tar.gz
|
- curl -sLO https://go.dev/dl/go1.19.linux-amd64.tar.gz && tar -C /usr/local -xzf go1.19.linux-amd64.tar.gz
|
||||||
- groupadd --gid 1001 gitea && useradd -m --gid 1001 --uid 1001 gitea
|
- groupadd --gid 1001 gitea && useradd -m --gid 1001 --uid 1001 gitea
|
||||||
|
@ -199,7 +199,7 @@ rules:
|
|||||||
newline-per-chained-call: [0]
|
newline-per-chained-call: [0]
|
||||||
no-alert: [0]
|
no-alert: [0]
|
||||||
no-array-constructor: [2]
|
no-array-constructor: [2]
|
||||||
no-async-promise-executor: [2]
|
no-async-promise-executor: [0]
|
||||||
no-await-in-loop: [0]
|
no-await-in-loop: [0]
|
||||||
no-bitwise: [0]
|
no-bitwise: [0]
|
||||||
no-buffer-constructor: [0]
|
no-buffer-constructor: [0]
|
||||||
@ -229,6 +229,7 @@ rules:
|
|||||||
no-empty-character-class: [2]
|
no-empty-character-class: [2]
|
||||||
no-empty-function: [0]
|
no-empty-function: [0]
|
||||||
no-empty-pattern: [2]
|
no-empty-pattern: [2]
|
||||||
|
no-empty-static-block: [2]
|
||||||
no-empty: [2, {allowEmptyCatch: true}]
|
no-empty: [2, {allowEmptyCatch: true}]
|
||||||
no-eq-null: [2]
|
no-eq-null: [2]
|
||||||
no-eval: [2]
|
no-eval: [2]
|
||||||
@ -269,6 +270,7 @@ rules:
|
|||||||
no-negated-condition: [0]
|
no-negated-condition: [0]
|
||||||
no-nested-ternary: [0]
|
no-nested-ternary: [0]
|
||||||
no-new-func: [2]
|
no-new-func: [2]
|
||||||
|
no-new-native-nonconstructor: [2]
|
||||||
no-new-object: [2]
|
no-new-object: [2]
|
||||||
no-new-symbol: [2]
|
no-new-symbol: [2]
|
||||||
no-new-wrappers: [2]
|
no-new-wrappers: [2]
|
||||||
@ -443,6 +445,7 @@ rules:
|
|||||||
unicorn/no-invalid-remove-event-listener: [2]
|
unicorn/no-invalid-remove-event-listener: [2]
|
||||||
unicorn/no-keyword-prefix: [0]
|
unicorn/no-keyword-prefix: [0]
|
||||||
unicorn/no-lonely-if: [2]
|
unicorn/no-lonely-if: [2]
|
||||||
|
unicorn/no-negated-condition: [0]
|
||||||
unicorn/no-nested-ternary: [0]
|
unicorn/no-nested-ternary: [0]
|
||||||
unicorn/no-new-array: [0]
|
unicorn/no-new-array: [0]
|
||||||
unicorn/no-new-buffer: [0]
|
unicorn/no-new-buffer: [0]
|
||||||
@ -453,6 +456,7 @@ rules:
|
|||||||
unicorn/no-static-only-class: [2]
|
unicorn/no-static-only-class: [2]
|
||||||
unicorn/no-thenable: [2]
|
unicorn/no-thenable: [2]
|
||||||
unicorn/no-this-assignment: [2]
|
unicorn/no-this-assignment: [2]
|
||||||
|
unicorn/no-typeof-undefined: [2]
|
||||||
unicorn/no-unnecessary-await: [2]
|
unicorn/no-unnecessary-await: [2]
|
||||||
unicorn/no-unreadable-array-destructuring: [0]
|
unicorn/no-unreadable-array-destructuring: [0]
|
||||||
unicorn/no-unreadable-iife: [2]
|
unicorn/no-unreadable-iife: [2]
|
||||||
@ -503,6 +507,7 @@ rules:
|
|||||||
unicorn/prefer-regexp-test: [2]
|
unicorn/prefer-regexp-test: [2]
|
||||||
unicorn/prefer-replace-all: [0]
|
unicorn/prefer-replace-all: [0]
|
||||||
unicorn/prefer-set-has: [0]
|
unicorn/prefer-set-has: [0]
|
||||||
|
unicorn/prefer-set-size: [2]
|
||||||
unicorn/prefer-spread: [0]
|
unicorn/prefer-spread: [0]
|
||||||
unicorn/prefer-starts-ends-with: [2]
|
unicorn/prefer-starts-ends-with: [2]
|
||||||
unicorn/prefer-string-slice: [0]
|
unicorn/prefer-string-slice: [0]
|
||||||
|
4
Makefile
4
Makefile
@ -333,7 +333,7 @@ checks: checks-frontend checks-backend
|
|||||||
checks-frontend: lockfile-check svg-check
|
checks-frontend: lockfile-check svg-check
|
||||||
|
|
||||||
.PHONY: checks-backend
|
.PHONY: checks-backend
|
||||||
checks-backend: tidy-check swagger-check fmt-check misspell-check swagger-validate
|
checks-backend: tidy-check swagger-check fmt-check misspell-check swagger-validate security-check
|
||||||
|
|
||||||
.PHONY: lint
|
.PHONY: lint
|
||||||
lint: lint-frontend lint-backend
|
lint: lint-frontend lint-backend
|
||||||
@ -745,7 +745,7 @@ generate-go: $(TAGS_PREREQ)
|
|||||||
|
|
||||||
.PHONY: security-check
|
.PHONY: security-check
|
||||||
security-check:
|
security-check:
|
||||||
govulncheck -v ./...
|
go run $(GOVULNCHECK_PACKAGE) -v ./...
|
||||||
|
|
||||||
$(EXECUTABLE): $(GO_SOURCES) $(TAGS_PREREQ)
|
$(EXECUTABLE): $(GO_SOURCES) $(TAGS_PREREQ)
|
||||||
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) build $(GOFLAGS) $(EXTRA_GOFLAGS) -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -o $@
|
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) build $(GOFLAGS) $(EXTRA_GOFLAGS) -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -o $@
|
||||||
|
10
cmd/admin.go
10
cmd/admin.go
@ -413,9 +413,9 @@ var (
|
|||||||
Usage: "SMTP Authentication Type (PLAIN/LOGIN/CRAM-MD5) default PLAIN",
|
Usage: "SMTP Authentication Type (PLAIN/LOGIN/CRAM-MD5) default PLAIN",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "addr",
|
Name: "host",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "SMTP Addr",
|
Usage: "SMTP Host",
|
||||||
},
|
},
|
||||||
cli.IntFlag{
|
cli.IntFlag{
|
||||||
Name: "port",
|
Name: "port",
|
||||||
@ -727,7 +727,7 @@ func runRepoSyncReleases(_ *cli.Context) error {
|
|||||||
|
|
||||||
log.Trace("Synchronizing repository releases (this may take a while)")
|
log.Trace("Synchronizing repository releases (this may take a while)")
|
||||||
for page := 1; ; page++ {
|
for page := 1; ; page++ {
|
||||||
repos, count, err := repo_model.SearchRepositoryByName(&repo_model.SearchRepoOptions{
|
repos, count, err := repo_model.SearchRepositoryByName(ctx, &repo_model.SearchRepoOptions{
|
||||||
ListOptions: db.ListOptions{
|
ListOptions: db.ListOptions{
|
||||||
PageSize: repo_model.RepositoryListDefaultPageSize,
|
PageSize: repo_model.RepositoryListDefaultPageSize,
|
||||||
Page: page,
|
Page: page,
|
||||||
@ -955,8 +955,8 @@ func parseSMTPConfig(c *cli.Context, conf *smtp.Source) error {
|
|||||||
}
|
}
|
||||||
conf.Auth = c.String("auth-type")
|
conf.Auth = c.String("auth-type")
|
||||||
}
|
}
|
||||||
if c.IsSet("addr") {
|
if c.IsSet("host") {
|
||||||
conf.Addr = c.String("addr")
|
conf.Host = c.String("host")
|
||||||
}
|
}
|
||||||
if c.IsSet("port") {
|
if c.IsSet("port") {
|
||||||
conf.Port = c.Int("port")
|
conf.Port = c.Int("port")
|
||||||
|
@ -7,6 +7,38 @@
|
|||||||
;; see https://docs.gitea.io/en-us/config-cheat-sheet/ for additional documentation.
|
;; see https://docs.gitea.io/en-us/config-cheat-sheet/ for additional documentation.
|
||||||
|
|
||||||
|
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;; Default Configuration (non-`app.ini` configuration)
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;;
|
||||||
|
;; These values are environment-dependent but form the basis of a lot of values. They will be
|
||||||
|
;; reported as part of the default configuration when running `gitea --help` or on start-up. The order they are emitted there is slightly different but we will list them here in the order they are set-up.
|
||||||
|
;;
|
||||||
|
;; - _`AppPath`_: This is the absolute path of the running gitea binary.
|
||||||
|
;; - _`AppWorkPath`_: This refers to "working path" of the `gitea` binary. It is determined by using the first set thing in the following hierarchy:
|
||||||
|
;; - The `--work-path` flag passed to the binary
|
||||||
|
;; - The environment variable `$GITEA_WORK_DIR`
|
||||||
|
;; - A built-in value set at build time (see building from source)
|
||||||
|
;; - Otherwise it defaults to the directory of the _`AppPath`_
|
||||||
|
;; - If any of the above are relative paths then they are made absolute against the
|
||||||
|
;; the directory of the _`AppPath`_
|
||||||
|
;; - _`CustomPath`_: This is the base directory for custom templates and other options.
|
||||||
|
;; It is determined by using the first set thing in the following hierarchy:
|
||||||
|
;; - The `--custom-path` flag passed to the binary
|
||||||
|
;; - The environment variable `$GITEA_CUSTOM`
|
||||||
|
;; - A built-in value set at build time (see building from source)
|
||||||
|
;; - Otherwise it defaults to _`AppWorkPath`_`/custom`
|
||||||
|
;; - If any of the above are relative paths then they are made absolute against the
|
||||||
|
;; the directory of the _`AppWorkPath`_
|
||||||
|
;; - _`CustomConf`_: This is the path to the `app.ini` file.
|
||||||
|
;; - The `--config` flag passed to the binary
|
||||||
|
;; - A built-in value set at build time (see building from source)
|
||||||
|
;; - Otherwise it defaults to _`CustomPath`_`/conf/app.ini`
|
||||||
|
;; - If any of the above are relative paths then they are made absolute against the
|
||||||
|
;; the directory of the _`CustomPath`_
|
||||||
|
;;
|
||||||
|
;; In addition there is _`StaticRootPath`_ which can be set as a built-in at build time, but will otherwise default to _`AppWorkPath`_
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; General Settings
|
;; General Settings
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
@ -26,7 +58,7 @@ RUN_MODE = ; prod
|
|||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;
|
;;
|
||||||
;; The protocol the server listens on. One of 'http', 'https', 'unix' or 'fcgi'. Defaults to 'http'
|
;; The protocol the server listens on. One of 'http', 'https', 'http+unix', 'fcgi' or 'fcgi+unix'. Defaults to 'http'
|
||||||
;PROTOCOL = http
|
;PROTOCOL = http
|
||||||
;;
|
;;
|
||||||
;; Expect PROXY protocol headers on connections
|
;; Expect PROXY protocol headers on connections
|
||||||
@ -51,6 +83,8 @@ RUN_MODE = ; prod
|
|||||||
;STATIC_URL_PREFIX =
|
;STATIC_URL_PREFIX =
|
||||||
;;
|
;;
|
||||||
;; The address to listen on. Either a IPv4/IPv6 address or the path to a unix socket.
|
;; The address to listen on. Either a IPv4/IPv6 address or the path to a unix socket.
|
||||||
|
;; If PROTOCOL is set to `http+unix` or `fcgi+unix`, this should be the name of the Unix socket file to use.
|
||||||
|
;; Relative paths will be made absolute against the _`AppWorkPath`_.
|
||||||
;HTTP_ADDR = 0.0.0.0
|
;HTTP_ADDR = 0.0.0.0
|
||||||
;;
|
;;
|
||||||
;; The port to listen on. Leave empty when using a unix socket.
|
;; The port to listen on. Leave empty when using a unix socket.
|
||||||
@ -64,7 +98,7 @@ RUN_MODE = ; prod
|
|||||||
;PORT_TO_REDIRECT = 80
|
;PORT_TO_REDIRECT = 80
|
||||||
;;
|
;;
|
||||||
;; expect PROXY protocol header on connections to https redirector.
|
;; expect PROXY protocol header on connections to https redirector.
|
||||||
;REDIRECTOR_USE_PROXY_PROTOCOL = %(USE_PROXY_PROTOCOL)
|
;REDIRECTOR_USE_PROXY_PROTOCOL = %(USE_PROXY_PROTOCOL)s
|
||||||
;; Minimum and maximum supported TLS versions
|
;; Minimum and maximum supported TLS versions
|
||||||
;SSL_MIN_VERSION=TLSv1.2
|
;SSL_MIN_VERSION=TLSv1.2
|
||||||
;SSL_MAX_VERSION=
|
;SSL_MAX_VERSION=
|
||||||
@ -91,7 +125,7 @@ RUN_MODE = ; prod
|
|||||||
;LOCAL_ROOT_URL = %(PROTOCOL)s://%(HTTP_ADDR)s:%(HTTP_PORT)s/
|
;LOCAL_ROOT_URL = %(PROTOCOL)s://%(HTTP_ADDR)s:%(HTTP_PORT)s/
|
||||||
;;
|
;;
|
||||||
;; When making local connections pass the PROXY protocol header.
|
;; When making local connections pass the PROXY protocol header.
|
||||||
;LOCAL_USE_PROXY_PROTOCOL = %(USE_PROXY_PROTOCOL)
|
;LOCAL_USE_PROXY_PROTOCOL = %(USE_PROXY_PROTOCOL)s
|
||||||
;;
|
;;
|
||||||
;; Disable SSH feature when not available
|
;; Disable SSH feature when not available
|
||||||
;DISABLE_SSH = false
|
;DISABLE_SSH = false
|
||||||
@ -145,7 +179,7 @@ RUN_MODE = ; prod
|
|||||||
;;
|
;;
|
||||||
;; For the built-in SSH server, choose the keypair to offer as the host key
|
;; For the built-in SSH server, choose the keypair to offer as the host key
|
||||||
;; The private key should be at SSH_SERVER_HOST_KEY and the public SSH_SERVER_HOST_KEY.pub
|
;; The private key should be at SSH_SERVER_HOST_KEY and the public SSH_SERVER_HOST_KEY.pub
|
||||||
;; relative paths are made absolute relative to the APP_DATA_PATH
|
;; relative paths are made absolute relative to the %(APP_DATA_PATH)s
|
||||||
;SSH_SERVER_HOST_KEYS=ssh/gitea.rsa, ssh/gogs.rsa
|
;SSH_SERVER_HOST_KEYS=ssh/gitea.rsa, ssh/gogs.rsa
|
||||||
;;
|
;;
|
||||||
;; Directory to create temporary files in when testing public keys using ssh-keygen,
|
;; Directory to create temporary files in when testing public keys using ssh-keygen,
|
||||||
@ -241,10 +275,10 @@ RUN_MODE = ; prod
|
|||||||
;;
|
;;
|
||||||
;; Root directory containing templates and static files.
|
;; Root directory containing templates and static files.
|
||||||
;; default is the path where Gitea is executed
|
;; default is the path where Gitea is executed
|
||||||
;STATIC_ROOT_PATH =
|
;STATIC_ROOT_PATH = ; Will default to the built-in value _`StaticRootPath`_
|
||||||
;;
|
;;
|
||||||
;; Default path for App data
|
;; Default path for App data
|
||||||
;APP_DATA_PATH = data
|
;APP_DATA_PATH = data ; relative paths will be made absolute with _`AppWorkPath`_
|
||||||
;;
|
;;
|
||||||
;; Enable gzip compression for runtime-generated content, static resources excluded
|
;; Enable gzip compression for runtime-generated content, static resources excluded
|
||||||
;ENABLE_GZIP = false
|
;ENABLE_GZIP = false
|
||||||
@ -255,7 +289,7 @@ RUN_MODE = ; prod
|
|||||||
;ENABLE_PPROF = false
|
;ENABLE_PPROF = false
|
||||||
;;
|
;;
|
||||||
;; PPROF_DATA_PATH, use an absolute path when you start gitea as service
|
;; PPROF_DATA_PATH, use an absolute path when you start gitea as service
|
||||||
;PPROF_DATA_PATH = data/tmp/pprof
|
;PPROF_DATA_PATH = data/tmp/pprof ; Path is relative to _`AppWorkPath`_
|
||||||
;;
|
;;
|
||||||
;; Landing page, can be "home", "explore", "organizations", "login", or any URL such as "/org/repo" or even "https://anotherwebsite.com"
|
;; Landing page, can be "home", "explore", "organizations", "login", or any URL such as "/org/repo" or even "https://anotherwebsite.com"
|
||||||
;; The "login" choice is not a security measure but just a UI flow change, use REQUIRE_SIGNIN_VIEW to force users to log in.
|
;; The "login" choice is not a security measure but just a UI flow change, use REQUIRE_SIGNIN_VIEW to force users to log in.
|
||||||
@ -633,7 +667,7 @@ ROUTER = console
|
|||||||
;PATH =
|
;PATH =
|
||||||
;;
|
;;
|
||||||
;; The HOME directory for Git
|
;; The HOME directory for Git
|
||||||
;HOME_PATH = %(APP_DATA_PATH)/home
|
;HOME_PATH = %(APP_DATA_PATH)s/home
|
||||||
;;
|
;;
|
||||||
;; Disables highlight of added and removed changes
|
;; Disables highlight of added and removed changes
|
||||||
;DISABLE_DIFF_HIGHLIGHT = false
|
;DISABLE_DIFF_HIGHLIGHT = false
|
||||||
@ -838,8 +872,8 @@ ROUTER = console
|
|||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;[repository]
|
;[repository]
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Root path for storing all repository data. By default, it is set to %(APP_DATA_PATH)/gitea-repositories.
|
;; Root path for storing all repository data. By default, it is set to %(APP_DATA_PATH)s/gitea-repositories.
|
||||||
;; A relative path is interpreted as %(GITEA_WORK_DIR)/%(ROOT)
|
;; A relative path is interpreted as _`AppWorkPath`_/%(ROOT)s
|
||||||
;ROOT =
|
;ROOT =
|
||||||
;;
|
;;
|
||||||
;; The script type this server supports. Usually this is `bash`, but some users report that only `sh` is available.
|
;; The script type this server supports. Usually this is `bash`, but some users report that only `sh` is available.
|
||||||
@ -1104,6 +1138,9 @@ ROUTER = console
|
|||||||
;; allow request with credentials
|
;; allow request with credentials
|
||||||
;ALLOW_CREDENTIALS = false
|
;ALLOW_CREDENTIALS = false
|
||||||
;;
|
;;
|
||||||
|
;; headers to permit
|
||||||
|
;HEADERS = Content-Type,User-Agent
|
||||||
|
;;
|
||||||
;; set X-FRAME-OPTIONS header
|
;; set X-FRAME-OPTIONS header
|
||||||
;X_FRAME_OPTIONS = SAMEORIGIN
|
;X_FRAME_OPTIONS = SAMEORIGIN
|
||||||
|
|
||||||
@ -1296,7 +1333,7 @@ ROUTER = console
|
|||||||
;ISSUE_INDEXER_TYPE = bleve
|
;ISSUE_INDEXER_TYPE = bleve
|
||||||
;;
|
;;
|
||||||
;; Issue indexer storage path, available when ISSUE_INDEXER_TYPE is bleve
|
;; Issue indexer storage path, available when ISSUE_INDEXER_TYPE is bleve
|
||||||
;ISSUE_INDEXER_PATH = indexers/issues.bleve
|
;ISSUE_INDEXER_PATH = indexers/issues.bleve ; Relative paths will be made absolute against _`AppWorkPath`_.
|
||||||
;;
|
;;
|
||||||
;; Issue indexer connection string, available when ISSUE_INDEXER_TYPE is elasticsearch
|
;; Issue indexer connection string, available when ISSUE_INDEXER_TYPE is elasticsearch
|
||||||
;ISSUE_INDEXER_CONN_STR = http://elastic:changeme@localhost:9200
|
;ISSUE_INDEXER_CONN_STR = http://elastic:changeme@localhost:9200
|
||||||
@ -1314,7 +1351,7 @@ ROUTER = console
|
|||||||
;; When ISSUE_INDEXER_QUEUE_TYPE is levelqueue, this will be the path where the queue will be saved.
|
;; When ISSUE_INDEXER_QUEUE_TYPE is levelqueue, this will be the path where the queue will be saved.
|
||||||
;; This can be overridden by `ISSUE_INDEXER_QUEUE_CONN_STR`.
|
;; This can be overridden by `ISSUE_INDEXER_QUEUE_CONN_STR`.
|
||||||
;; default is queues/common
|
;; default is queues/common
|
||||||
;ISSUE_INDEXER_QUEUE_DIR = queues/common; **DEPRECATED** use settings in `[queue.issue_indexer]`.
|
;ISSUE_INDEXER_QUEUE_DIR = queues/common; **DEPRECATED** use settings in `[queue.issue_indexer]`. Relative paths will be made absolute against `%(APP_DATA_PATH)s`.
|
||||||
;;
|
;;
|
||||||
;; When `ISSUE_INDEXER_QUEUE_TYPE` is `redis`, this will store the redis connection string.
|
;; When `ISSUE_INDEXER_QUEUE_TYPE` is `redis`, this will store the redis connection string.
|
||||||
;; When `ISSUE_INDEXER_QUEUE_TYPE` is `levelqueue`, this is a directory or additional options of
|
;; When `ISSUE_INDEXER_QUEUE_TYPE` is `levelqueue`, this is a directory or additional options of
|
||||||
@ -1370,7 +1407,7 @@ ROUTER = console
|
|||||||
;TYPE = persistable-channel
|
;TYPE = persistable-channel
|
||||||
;;
|
;;
|
||||||
;; data-dir for storing persistable queues and level queues, individual queues will default to `queues/common` meaning the queue is shared.
|
;; data-dir for storing persistable queues and level queues, individual queues will default to `queues/common` meaning the queue is shared.
|
||||||
;DATADIR = queues/
|
;DATADIR = queues/ ; Relative paths will be made absolute against `%(APP_DATA_PATH)s`.
|
||||||
;;
|
;;
|
||||||
;; Default queue length before a channel queue will block
|
;; Default queue length before a channel queue will block
|
||||||
;LENGTH = 20
|
;LENGTH = 20
|
||||||
@ -1672,7 +1709,7 @@ ROUTER = console
|
|||||||
;; file: session file path, e.g. `data/sessions`
|
;; file: session file path, e.g. `data/sessions`
|
||||||
;; redis: network=tcp,addr=:6379,password=macaron,db=0,pool_size=100,idle_timeout=180
|
;; redis: network=tcp,addr=:6379,password=macaron,db=0,pool_size=100,idle_timeout=180
|
||||||
;; mysql: go-sql-driver/mysql dsn config string, e.g. `root:password@/session_table`
|
;; mysql: go-sql-driver/mysql dsn config string, e.g. `root:password@/session_table`
|
||||||
;PROVIDER_CONFIG = data/sessions
|
;PROVIDER_CONFIG = data/sessions ; Relative paths will be made absolute against _`AppWorkPath`_.
|
||||||
;;
|
;;
|
||||||
;; Session cookie name
|
;; Session cookie name
|
||||||
;COOKIE_NAME = i_like_gitea
|
;COOKIE_NAME = i_like_gitea
|
||||||
@ -2197,7 +2234,9 @@ ROUTER = console
|
|||||||
;; Show template execution time in the footer
|
;; Show template execution time in the footer
|
||||||
;SHOW_FOOTER_TEMPLATE_LOAD_TIME = true
|
;SHOW_FOOTER_TEMPLATE_LOAD_TIME = true
|
||||||
;; Generate sitemap. Defaults to `true`.
|
;; Generate sitemap. Defaults to `true`.
|
||||||
; ENABLE_SITEMAP = true
|
;ENABLE_SITEMAP = true
|
||||||
|
;; Enable/Disable RSS/Atom feed
|
||||||
|
;ENABLE_FEED = true
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -27,23 +27,56 @@ accurately recorded in [app.example.ini](https://github.com/go-gitea/gitea/blob/
|
|||||||
(s/main/\<tag|release\>). Any string in the format `%(X)s` is a feature powered
|
(s/main/\<tag|release\>). Any string in the format `%(X)s` is a feature powered
|
||||||
by [ini](https://github.com/go-ini/ini/#recursive-values), for reading values recursively.
|
by [ini](https://github.com/go-ini/ini/#recursive-values), for reading values recursively.
|
||||||
|
|
||||||
|
In the default values below, a value in the form `$XYZ` refers to an environment variable. (However, see `environment-to-ini`.) Values in the form _`XxYyZz`_ refer to values listed as part of the default configuration. These notation forms will not work in your own `app.ini` file and are only listed here as documentation.
|
||||||
|
|
||||||
Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
|
Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
|
||||||
|
|
||||||
**Note:** A full restart is required for Gitea configuration changes to take effect.
|
**Note:** A full restart is required for Gitea configuration changes to take effect.
|
||||||
|
|
||||||
{{< toc >}}
|
{{< toc >}}
|
||||||
|
|
||||||
|
## Default Configuration (non-`app.ini` configuration)
|
||||||
|
|
||||||
|
These values are environment-dependent but form the basis of a lot of values. They will be
|
||||||
|
reported as part of the default configuration when running `gitea --help` or on start-up. The order they are emitted there is slightly different but we will list them here in the order they are set-up.
|
||||||
|
|
||||||
|
- _`AppPath`_: This is the absolute path of the running gitea binary.
|
||||||
|
- _`AppWorkPath`_: This refers to "working path" of the `gitea` binary. It is determined by using the first set thing in the following hierarchy:
|
||||||
|
- The `--work-path` flag passed to the binary
|
||||||
|
- The environment variable `$GITEA_WORK_DIR`
|
||||||
|
- A built-in value set at build time (see building from source)
|
||||||
|
- Otherwise it defaults to the directory of the _`AppPath`_
|
||||||
|
- If any of the above are relative paths then they are made absolute against the
|
||||||
|
the directory of the _`AppPath`_
|
||||||
|
- _`CustomPath`_: This is the base directory for custom templates and other options.
|
||||||
|
It is determined by using the first set thing in the following hierarchy:
|
||||||
|
- The `--custom-path` flag passed to the binary
|
||||||
|
- The environment variable `$GITEA_CUSTOM`
|
||||||
|
- A built-in value set at build time (see building from source)
|
||||||
|
- Otherwise it defaults to _`AppWorkPath`_`/custom`
|
||||||
|
- If any of the above are relative paths then they are made absolute against the
|
||||||
|
the directory of the _`AppWorkPath`_
|
||||||
|
- _`CustomConf`_: This is the path to the `app.ini` file.
|
||||||
|
- The `--config` flag passed to the binary
|
||||||
|
- A built-in value set at build time (see building from source)
|
||||||
|
- Otherwise it defaults to _`CustomPath`_`/conf/app.ini`
|
||||||
|
- If any of the above are relative paths then they are made absolute against the
|
||||||
|
the directory of the _`CustomPath`_
|
||||||
|
|
||||||
|
In addition there is _`StaticRootPath`_ which can be set as a built-in at build time, but will otherwise default to _`AppWorkPath`_
|
||||||
|
|
||||||
## Overall (`DEFAULT`)
|
## Overall (`DEFAULT`)
|
||||||
|
|
||||||
- `APP_NAME`: **Gitea: Git with a cup of tea**: Application name, used in the page title.
|
- `APP_NAME`: **Gitea: Git with a cup of tea**: Application name, used in the page title.
|
||||||
- `RUN_USER`: **git**: The user Gitea will run as. This should be a dedicated system
|
- `RUN_USER`: **_current OS username_/`$USER`/`$USERNAME` e.g. git**: The user Gitea will run as.
|
||||||
(non-user) account. Setting this incorrectly will cause Gitea to not start.
|
This should be a dedicated system (non-user) account. Setting this incorrectly will cause Gitea
|
||||||
|
to not start.
|
||||||
- `RUN_MODE`: **prod**: Application run mode, affects performance and debugging. Either "dev", "prod" or "test".
|
- `RUN_MODE`: **prod**: Application run mode, affects performance and debugging. Either "dev", "prod" or "test".
|
||||||
|
|
||||||
## Repository (`repository`)
|
## Repository (`repository`)
|
||||||
|
|
||||||
- `ROOT`: **%(APP_DATA_PATH)/gitea-repositories**: Root path for storing all repository data.
|
- `ROOT`: **%(APP_DATA_PATH)s/gitea-repositories**: Root path for storing all repository data.
|
||||||
A relative path is interpreted as **%(GITEA_WORK_DIR)/%(ROOT)**.
|
A relative path is interpreted as **_`AppWorkPath`_/%(ROOT)s**.
|
||||||
- `SCRIPT_TYPE`: **bash**: The script type this server supports. Usually this is `bash`,
|
- `SCRIPT_TYPE`: **bash**: The script type this server supports. Usually this is `bash`,
|
||||||
but some users report that only `sh` is available.
|
but some users report that only `sh` is available.
|
||||||
- `DETECTED_CHARSETS_ORDER`: **UTF-8, UTF-16BE, UTF-16LE, UTF-32BE, UTF-32LE, ISO-8859, windows-1252, ISO-8859, windows-1250, ISO-8859, ISO-8859, ISO-8859, windows-1253, ISO-8859, windows-1255, ISO-8859, windows-1251, windows-1256, KOI8-R, ISO-8859, windows-1254, Shift_JIS, GB18030, EUC-JP, EUC-KR, Big5, ISO-2022, ISO-2022, ISO-2022, IBM424_rtl, IBM424_ltr, IBM420_rtl, IBM420_ltr**: Tie-break order of detected charsets - if the detected charsets have equal confidence, charsets earlier in the list will be chosen in preference to those later. Adding `defaults` will place the unnamed charsets at that point.
|
- `DETECTED_CHARSETS_ORDER`: **UTF-8, UTF-16BE, UTF-16LE, UTF-32BE, UTF-32LE, ISO-8859, windows-1252, ISO-8859, windows-1250, ISO-8859, ISO-8859, ISO-8859, windows-1253, ISO-8859, windows-1255, ISO-8859, windows-1251, windows-1256, KOI8-R, ISO-8859, windows-1254, Shift_JIS, GB18030, EUC-JP, EUC-KR, Big5, ISO-2022, ISO-2022, ISO-2022, IBM424_rtl, IBM424_ltr, IBM420_rtl, IBM420_ltr**: Tie-break order of detected charsets - if the detected charsets have equal confidence, charsets earlier in the list will be chosen in preference to those later. Adding `defaults` will place the unnamed charsets at that point.
|
||||||
@ -167,6 +200,7 @@ The following configuration set `Content-Type: application/vnd.android.package-a
|
|||||||
- `METHODS`: **GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS**: list of methods allowed to request
|
- `METHODS`: **GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS**: list of methods allowed to request
|
||||||
- `MAX_AGE`: **10m**: max time to cache response
|
- `MAX_AGE`: **10m**: max time to cache response
|
||||||
- `ALLOW_CREDENTIALS`: **false**: allow request with credentials
|
- `ALLOW_CREDENTIALS`: **false**: allow request with credentials
|
||||||
|
- `HEADERS`: **Content-Type,User-Agent**: additional headers that are permitted in requests
|
||||||
- `X_FRAME_OPTIONS`: **SAMEORIGIN**: Set the `X-Frame-Options` header value.
|
- `X_FRAME_OPTIONS`: **SAMEORIGIN**: Set the `X-Frame-Options` header value.
|
||||||
|
|
||||||
## UI (`ui`)
|
## UI (`ui`)
|
||||||
@ -240,6 +274,7 @@ The following configuration set `Content-Type: application/vnd.android.package-a
|
|||||||
|
|
||||||
## Server (`server`)
|
## Server (`server`)
|
||||||
|
|
||||||
|
- `APP_DATA_PATH`: **_`AppWorkPath`_/data**: This is the default root path for storing data.
|
||||||
- `PROTOCOL`: **http**: \[http, https, fcgi, http+unix, fcgi+unix\]
|
- `PROTOCOL`: **http**: \[http, https, fcgi, http+unix, fcgi+unix\]
|
||||||
- `USE_PROXY_PROTOCOL`: **false**: Expect PROXY protocol headers on connections
|
- `USE_PROXY_PROTOCOL`: **false**: Expect PROXY protocol headers on connections
|
||||||
- `PROXY_PROTOCOL_TLS_BRIDGING`: **false**: When protocol is https, expect PROXY protocol headers after TLS negotiation.
|
- `PROXY_PROTOCOL_TLS_BRIDGING`: **false**: When protocol is https, expect PROXY protocol headers after TLS negotiation.
|
||||||
@ -254,12 +289,17 @@ The following configuration set `Content-Type: application/vnd.android.package-a
|
|||||||
This includes CSS files, images, JS files and web fonts.
|
This includes CSS files, images, JS files and web fonts.
|
||||||
Avatar images are dynamic resources and still served by Gitea.
|
Avatar images are dynamic resources and still served by Gitea.
|
||||||
The option can be just a different path, as in `/static`, or another domain, as in `https://cdn.example.com`.
|
The option can be just a different path, as in `/static`, or another domain, as in `https://cdn.example.com`.
|
||||||
Requests are then made as `%(ROOT_URL)s/static/css/index.css` and `https://cdn.example.com/css/index.css` respective.
|
Requests are then made as `%(ROOT_URL)s/static/assets/css/index.css` or `https://cdn.example.com/assets/css/index.css` respectively.
|
||||||
The static files are located in the `public/` directory of the Gitea source repository.
|
The static files are located in the `public/` directory of the Gitea source repository.
|
||||||
|
You can proxy the STATIC_URL_PREFIX requests to Gitea server to serve the static
|
||||||
|
assets, or copy the manually built Gitea assets from `$GITEA_BUILD/public` to
|
||||||
|
the assets location, eg: `/var/www/assets`, make sure `$STATIC_URL_PREFIX/assets/css/index.css`
|
||||||
|
points to `/var/www/assets/css/index.css`.
|
||||||
|
|
||||||
- `HTTP_ADDR`: **0.0.0.0**: HTTP listen address.
|
- `HTTP_ADDR`: **0.0.0.0**: HTTP listen address.
|
||||||
- If `PROTOCOL` is set to `fcgi`, Gitea will listen for FastCGI requests on TCP socket
|
- If `PROTOCOL` is set to `fcgi`, Gitea will listen for FastCGI requests on TCP socket
|
||||||
defined by `HTTP_ADDR` and `HTTP_PORT` configuration settings.
|
defined by `HTTP_ADDR` and `HTTP_PORT` configuration settings.
|
||||||
- If `PROTOCOL` is set to `http+unix` or `fcgi+unix`, this should be the name of the Unix socket file to use. Relative paths will be made absolute against the AppWorkPath.
|
- If `PROTOCOL` is set to `http+unix` or `fcgi+unix`, this should be the name of the Unix socket file to use. Relative paths will be made absolute against the _`AppWorkPath`_.
|
||||||
- `HTTP_PORT`: **3000**: HTTP listen port.
|
- `HTTP_PORT`: **3000**: HTTP listen port.
|
||||||
- If `PROTOCOL` is set to `fcgi`, Gitea will listen for FastCGI requests on TCP socket
|
- If `PROTOCOL` is set to `fcgi`, Gitea will listen for FastCGI requests on TCP socket
|
||||||
defined by `HTTP_ADDR` and `HTTP_PORT` configuration settings.
|
defined by `HTTP_ADDR` and `HTTP_PORT` configuration settings.
|
||||||
@ -269,7 +309,7 @@ The following configuration set `Content-Type: application/vnd.android.package-a
|
|||||||
most cases you do not need to change the default value. Alter it only if
|
most cases you do not need to change the default value. Alter it only if
|
||||||
your SSH server node is not the same as HTTP node. Do not set this variable
|
your SSH server node is not the same as HTTP node. Do not set this variable
|
||||||
if `PROTOCOL` is set to `http+unix`.
|
if `PROTOCOL` is set to `http+unix`.
|
||||||
- `LOCAL_USE_PROXY_PROTOCOL`: **%(USE_PROXY_PROTOCOL)**: When making local connections pass the PROXY protocol header.
|
- `LOCAL_USE_PROXY_PROTOCOL`: **%(USE_PROXY_PROTOCOL)s**: When making local connections pass the PROXY protocol header.
|
||||||
This should be set to false if the local connection will go through the proxy.
|
This should be set to false if the local connection will go through the proxy.
|
||||||
- `PER_WRITE_TIMEOUT`: **30s**: Timeout for any write to the connection. (Set to -1 to
|
- `PER_WRITE_TIMEOUT`: **30s**: Timeout for any write to the connection. (Set to -1 to
|
||||||
disable all timeouts.)
|
disable all timeouts.)
|
||||||
@ -279,7 +319,7 @@ The following configuration set `Content-Type: application/vnd.android.package-a
|
|||||||
- `START_SSH_SERVER`: **false**: When enabled, use the built-in SSH server.
|
- `START_SSH_SERVER`: **false**: When enabled, use the built-in SSH server.
|
||||||
- `SSH_SERVER_USE_PROXY_PROTOCOL`: **false**: Expect PROXY protocol header on connections to the built-in SSH Server.
|
- `SSH_SERVER_USE_PROXY_PROTOCOL`: **false**: Expect PROXY protocol header on connections to the built-in SSH Server.
|
||||||
- `BUILTIN_SSH_SERVER_USER`: **%(RUN_USER)s**: Username to use for the built-in SSH Server.
|
- `BUILTIN_SSH_SERVER_USER`: **%(RUN_USER)s**: Username to use for the built-in SSH Server.
|
||||||
- `SSH_USER`: **%(BUILTIN_SSH_SERVER_USER)**: SSH username displayed in clone URLs. This is only for people who configure the SSH server themselves; in most cases, you want to leave this blank and modify the `BUILTIN_SSH_SERVER_USER`.
|
- `SSH_USER`: **%(BUILTIN_SSH_SERVER_USER)s**: SSH username displayed in clone URLs. This is only for people who configure the SSH server themselves; in most cases, you want to leave this blank and modify the `BUILTIN_SSH_SERVER_USER`.
|
||||||
- `SSH_DOMAIN`: **%(DOMAIN)s**: Domain name of this server, used for displayed clone URL.
|
- `SSH_DOMAIN`: **%(DOMAIN)s**: Domain name of this server, used for displayed clone URL.
|
||||||
- `SSH_PORT`: **22**: SSH port displayed in clone URL.
|
- `SSH_PORT`: **22**: SSH port displayed in clone URL.
|
||||||
- `SSH_LISTEN_HOST`: **0.0.0.0**: Listen address for the built-in SSH server.
|
- `SSH_LISTEN_HOST`: **0.0.0.0**: Listen address for the built-in SSH server.
|
||||||
@ -308,22 +348,22 @@ The following configuration set `Content-Type: application/vnd.android.package-a
|
|||||||
- `OFFLINE_MODE`: **false**: Disables use of CDN for static files and Gravatar for profile pictures.
|
- `OFFLINE_MODE`: **false**: Disables use of CDN for static files and Gravatar for profile pictures.
|
||||||
- `CERT_FILE`: **https/cert.pem**: Cert file path used for HTTPS. When chaining, the server certificate must come first, then intermediate CA certificates (if any). This is ignored if `ENABLE_ACME=true`. Paths are relative to `CUSTOM_PATH`.
|
- `CERT_FILE`: **https/cert.pem**: Cert file path used for HTTPS. When chaining, the server certificate must come first, then intermediate CA certificates (if any). This is ignored if `ENABLE_ACME=true`. Paths are relative to `CUSTOM_PATH`.
|
||||||
- `KEY_FILE`: **https/key.pem**: Key file path used for HTTPS. This is ignored if `ENABLE_ACME=true`. Paths are relative to `CUSTOM_PATH`.
|
- `KEY_FILE`: **https/key.pem**: Key file path used for HTTPS. This is ignored if `ENABLE_ACME=true`. Paths are relative to `CUSTOM_PATH`.
|
||||||
- `STATIC_ROOT_PATH`: **./**: Upper level of template and static files path.
|
- `STATIC_ROOT_PATH`: **_`StaticRootPath`_**: Upper level of template and static files path.
|
||||||
- `APP_DATA_PATH`: **data** (**/data/gitea** on docker): Default path for application data.
|
- `APP_DATA_PATH`: **data** (**/data/gitea** on docker): Default path for application data. Relative paths will be made absolute against _`AppWorkPath`_.
|
||||||
- `STATIC_CACHE_TIME`: **6h**: Web browser cache time for static resources on `custom/`, `public/` and all uploaded avatars. Note that this cache is disabled when `RUN_MODE` is "dev".
|
- `STATIC_CACHE_TIME`: **6h**: Web browser cache time for static resources on `custom/`, `public/` and all uploaded avatars. Note that this cache is disabled when `RUN_MODE` is "dev".
|
||||||
- `ENABLE_GZIP`: **false**: Enable gzip compression for runtime-generated content, static resources excluded.
|
- `ENABLE_GZIP`: **false**: Enable gzip compression for runtime-generated content, static resources excluded.
|
||||||
- `ENABLE_PPROF`: **false**: Application profiling (memory and cpu). For "web" command it listens on `localhost:6060`. For "serv" command it dumps to disk at `PPROF_DATA_PATH` as `(cpuprofile|memprofile)_<username>_<temporary id>`
|
- `ENABLE_PPROF`: **false**: Application profiling (memory and cpu). For "web" command it listens on `localhost:6060`. For "serv" command it dumps to disk at `PPROF_DATA_PATH` as `(cpuprofile|memprofile)_<username>_<temporary id>`
|
||||||
- `PPROF_DATA_PATH`: **data/tmp/pprof**: `PPROF_DATA_PATH`, use an absolute path when you start Gitea as service
|
- `PPROF_DATA_PATH`: **_`AppWorkPath`_/data/tmp/pprof**: `PPROF_DATA_PATH`, use an absolute path when you start Gitea as service
|
||||||
- `LANDING_PAGE`: **home**: Landing page for unauthenticated users \[home, explore, organizations, login, **custom**\]. Where custom would instead be any URL such as "/org/repo" or even `https://anotherwebsite.com`
|
- `LANDING_PAGE`: **home**: Landing page for unauthenticated users \[home, explore, organizations, login, **custom**\]. Where custom would instead be any URL such as "/org/repo" or even `https://anotherwebsite.com`
|
||||||
- `LFS_START_SERVER`: **false**: Enables Git LFS support.
|
- `LFS_START_SERVER`: **false**: Enables Git LFS support.
|
||||||
- `LFS_CONTENT_PATH`: **%(APP_DATA_PATH)/lfs**: Default LFS content path. (if it is on local storage.) **DEPRECATED** use settings in `[lfs]`.
|
- `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`: **\<empty\>**: LFS authentication secret, change this a unique string.
|
||||||
- `LFS_HTTP_AUTH_EXPIRY`: **20m**: LFS authentication validity period in time.Duration, pushes taking longer than this may fail.
|
- `LFS_HTTP_AUTH_EXPIRY`: **20m**: 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_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.
|
- `LFS_LOCKS_PAGING_NUM`: **50**: Maximum number of LFS Locks returned per page.
|
||||||
|
|
||||||
- `REDIRECT_OTHER_PORT`: **false**: If true and `PROTOCOL` is https, allows redirecting http requests on `PORT_TO_REDIRECT` to the https port Gitea listens on.
|
- `REDIRECT_OTHER_PORT`: **false**: If true and `PROTOCOL` is https, allows redirecting http requests on `PORT_TO_REDIRECT` to the https port Gitea listens on.
|
||||||
- `REDIRECTOR_USE_PROXY_PROTOCOL`: **%(USE_PROXY_PROTOCOL)**: expect PROXY protocol header on connections to https redirector.
|
- `REDIRECTOR_USE_PROXY_PROTOCOL`: **%(USE_PROXY_PROTOCOL)s**: expect PROXY protocol header on connections to https redirector.
|
||||||
- `PORT_TO_REDIRECT`: **80**: Port for the http redirection service to listen on. Used when `REDIRECT_OTHER_PORT` is true.
|
- `PORT_TO_REDIRECT`: **80**: Port for the http redirection service to listen on. Used when `REDIRECT_OTHER_PORT` is true.
|
||||||
- `SSL_MIN_VERSION`: **TLSv1.2**: Set the minimum version of ssl support.
|
- `SSL_MIN_VERSION`: **TLSv1.2**: Set the minimum version of ssl support.
|
||||||
- `SSL_MAX_VERSION`: **\<empty\>**: Set the maximum version of ssl support.
|
- `SSL_MAX_VERSION`: **\<empty\>**: Set the maximum version of ssl support.
|
||||||
@ -413,10 +453,10 @@ relation to port exhaustion.
|
|||||||
- `ISSUE_INDEXER_TYPE`: **bleve**: Issue indexer type, currently supported: `bleve`, `db` or `elasticsearch`.
|
- `ISSUE_INDEXER_TYPE`: **bleve**: Issue indexer type, currently supported: `bleve`, `db` or `elasticsearch`.
|
||||||
- `ISSUE_INDEXER_CONN_STR`: ****: Issue indexer connection string, available when ISSUE_INDEXER_TYPE is elasticsearch. i.e. http://elastic:changeme@localhost:9200
|
- `ISSUE_INDEXER_CONN_STR`: ****: Issue indexer connection string, available when ISSUE_INDEXER_TYPE is elasticsearch. i.e. http://elastic:changeme@localhost:9200
|
||||||
- `ISSUE_INDEXER_NAME`: **gitea_issues**: Issue indexer name, available when ISSUE_INDEXER_TYPE is elasticsearch
|
- `ISSUE_INDEXER_NAME`: **gitea_issues**: Issue indexer name, available when ISSUE_INDEXER_TYPE is elasticsearch
|
||||||
- `ISSUE_INDEXER_PATH`: **indexers/issues.bleve**: Index file used for issue search; available when ISSUE_INDEXER_TYPE is bleve and elasticsearch.
|
- `ISSUE_INDEXER_PATH`: **indexers/issues.bleve**: Index file used for issue search; available when ISSUE_INDEXER_TYPE is bleve and elasticsearch. Relative paths will be made absolute against _`AppWorkPath`_.
|
||||||
- The next 4 configuration values are deprecated and should be set in `queue.issue_indexer` however are kept for backwards compatibility:
|
- The next 4 configuration values are deprecated and should be set in `queue.issue_indexer` however are kept for backwards compatibility:
|
||||||
- `ISSUE_INDEXER_QUEUE_TYPE`: **levelqueue**: Issue indexer queue, currently supports:`channel`, `levelqueue`, `redis`. **DEPRECATED** use settings in `[queue.issue_indexer]`.
|
- `ISSUE_INDEXER_QUEUE_TYPE`: **levelqueue**: Issue indexer queue, currently supports:`channel`, `levelqueue`, `redis`. **DEPRECATED** use settings in `[queue.issue_indexer]`.
|
||||||
- `ISSUE_INDEXER_QUEUE_DIR`: **queues/common**: When `ISSUE_INDEXER_QUEUE_TYPE` is `levelqueue`, this will be the path where the queue will be saved. **DEPRECATED** use settings in `[queue.issue_indexer]`.
|
- `ISSUE_INDEXER_QUEUE_DIR`: **queues/common**: When `ISSUE_INDEXER_QUEUE_TYPE` is `levelqueue`, this will be the path where the queue will be saved. **DEPRECATED** use settings in `[queue.issue_indexer]`. Relative paths will be made absolute against `%(APP_DATA_PATH)s`.
|
||||||
- `ISSUE_INDEXER_QUEUE_CONN_STR`: **addrs=127.0.0.1:6379 db=0**: When `ISSUE_INDEXER_QUEUE_TYPE` is `redis`, this will store the redis connection string. When `ISSUE_INDEXER_QUEUE_TYPE` is `levelqueue`, this is a directory or additional options of the form `leveldb://path/to/db?option=value&....`, and overrides `ISSUE_INDEXER_QUEUE_DIR`. **DEPRECATED** use settings in `[queue.issue_indexer]`.
|
- `ISSUE_INDEXER_QUEUE_CONN_STR`: **addrs=127.0.0.1:6379 db=0**: When `ISSUE_INDEXER_QUEUE_TYPE` is `redis`, this will store the redis connection string. When `ISSUE_INDEXER_QUEUE_TYPE` is `levelqueue`, this is a directory or additional options of the form `leveldb://path/to/db?option=value&....`, and overrides `ISSUE_INDEXER_QUEUE_DIR`. **DEPRECATED** use settings in `[queue.issue_indexer]`.
|
||||||
- `ISSUE_INDEXER_QUEUE_BATCH_NUMBER`: **20**: Batch queue number. **DEPRECATED** use settings in `[queue.issue_indexer]`.
|
- `ISSUE_INDEXER_QUEUE_BATCH_NUMBER`: **20**: Batch queue number. **DEPRECATED** use settings in `[queue.issue_indexer]`.
|
||||||
|
|
||||||
@ -438,7 +478,7 @@ relation to port exhaustion.
|
|||||||
Configuration at `[queue]` will set defaults for queues with overrides for individual queues at `[queue.*]`. (However see below.)
|
Configuration at `[queue]` will set defaults for queues with overrides for individual queues at `[queue.*]`. (However see below.)
|
||||||
|
|
||||||
- `TYPE`: **persistable-channel**: General queue type, currently support: `persistable-channel` (uses a LevelDB internally), `channel`, `level`, `redis`, `dummy`
|
- `TYPE`: **persistable-channel**: General queue type, currently support: `persistable-channel` (uses a LevelDB internally), `channel`, `level`, `redis`, `dummy`
|
||||||
- `DATADIR`: **queues/**: Base DataDir for storing persistent and level queues. `DATADIR` for individual queues can be set in `queue.name` sections but will default to `DATADIR/`**`common`**. (Previously each queue would default to `DATADIR/`**`name`**.)
|
- `DATADIR`: **queues/**: Base DataDir for storing persistent and level queues. `DATADIR` for individual queues can be set in `queue.name` sections but will default to `DATADIR/`**`common`**. (Previously each queue would default to `DATADIR/`**`name`**.) Relative paths will be made absolute against `%(APP_DATA_PATH)s`.
|
||||||
- `LENGTH`: **20**: Maximal queue size before channel queues block
|
- `LENGTH`: **20**: Maximal queue size before channel queues block
|
||||||
- `BATCH_LENGTH`: **20**: Batch data before passing to the handler
|
- `BATCH_LENGTH`: **20**: Batch data before passing to the handler
|
||||||
- `CONN_STR`: **redis://127.0.0.1:6379/0**: Connection string for the redis queue type. Options can be set using query params. Similarly LevelDB options can also be set using: **leveldb://relative/path?option=value** or **leveldb:///absolute/path?option=value**, and will override `DATADIR`
|
- `CONN_STR`: **redis://127.0.0.1:6379/0**: Connection string for the redis queue type. Options can be set using query params. Similarly LevelDB options can also be set using: **leveldb://relative/path?option=value** or **leveldb:///absolute/path?option=value**, and will override `DATADIR`
|
||||||
@ -722,7 +762,7 @@ and
|
|||||||
## Session (`session`)
|
## Session (`session`)
|
||||||
|
|
||||||
- `PROVIDER`: **memory**: Session engine provider \[memory, file, redis, db, mysql, couchbase, memcache, postgres\]. Setting `db` will reuse the configuration in `[database]`
|
- `PROVIDER`: **memory**: Session engine provider \[memory, file, redis, db, mysql, couchbase, memcache, postgres\]. Setting `db` will reuse the configuration in `[database]`
|
||||||
- `PROVIDER_CONFIG`: **data/sessions**: For file, the root path; for db, empty (database config will be used); for others, the connection string.
|
- `PROVIDER_CONFIG`: **data/sessions**: For file, the root path; for db, empty (database config will be used); for others, the connection string. Relative paths will be made absolute against _`AppWorkPath`_.
|
||||||
- `COOKIE_SECURE`: **false**: Enable this to force using HTTPS for all session access.
|
- `COOKIE_SECURE`: **false**: Enable this to force using HTTPS for all session access.
|
||||||
- `COOKIE_NAME`: **i\_like\_gitea**: The name of the cookie used for the session ID.
|
- `COOKIE_NAME`: **i\_like\_gitea**: The name of the cookie used for the session ID.
|
||||||
- `GC_INTERVAL_TIME`: **86400**: GC interval in seconds.
|
- `GC_INTERVAL_TIME`: **86400**: GC interval in seconds.
|
||||||
@ -980,7 +1020,7 @@ Default templates for project boards:
|
|||||||
## Git (`git`)
|
## Git (`git`)
|
||||||
|
|
||||||
- `PATH`: **""**: The path of Git executable. If empty, Gitea searches through the PATH environment.
|
- `PATH`: **""**: The path of Git executable. If empty, Gitea searches through the PATH environment.
|
||||||
- `HOME_PATH`: **%(APP_DATA_PATH)/home**: The HOME directory for Git.
|
- `HOME_PATH`: **%(APP_DATA_PATH)s/home**: The HOME directory for Git.
|
||||||
This directory will be used to contain the `.gitconfig` and possible `.gnupg` directories that Gitea's git calls will use. If you can confirm Gitea is the only application running in this environment, you can set it to the normal home directory for Gitea user.
|
This directory will be used to contain the `.gitconfig` and possible `.gnupg` directories that Gitea's git calls will use. If you can confirm Gitea is the only application running in this environment, you can set it to the normal home directory for Gitea user.
|
||||||
- `DISABLE_DIFF_HIGHLIGHT`: **false**: Disables highlight of added and removed changes.
|
- `DISABLE_DIFF_HIGHLIGHT`: **false**: Disables highlight of added and removed changes.
|
||||||
- `MAX_GIT_DIFF_LINES`: **1000**: Max number of lines allowed of a single file in diff view.
|
- `MAX_GIT_DIFF_LINES`: **1000**: Max number of lines allowed of a single file in diff view.
|
||||||
@ -1248,3 +1288,4 @@ PROXY_HOSTS = *.github.com
|
|||||||
- `SHOW_FOOTER_VERSION`: **true**: Show Gitea and Go version information in the footer.
|
- `SHOW_FOOTER_VERSION`: **true**: Show Gitea and Go version information in the footer.
|
||||||
- `SHOW_FOOTER_TEMPLATE_LOAD_TIME`: **true**: Show time of template execution in the footer.
|
- `SHOW_FOOTER_TEMPLATE_LOAD_TIME`: **true**: Show time of template execution in the footer.
|
||||||
- `ENABLE_SITEMAP`: **true**: Generate sitemap.
|
- `ENABLE_SITEMAP`: **true**: Generate sitemap.
|
||||||
|
- `ENABLE_FEED`: **true**: Enable/Disable RSS/Atom feed.
|
||||||
|
@ -15,6 +15,14 @@ menu:
|
|||||||
|
|
||||||
# Logging Configuration
|
# Logging Configuration
|
||||||
|
|
||||||
|
The logging configuration of Gitea mainly consists of 3 types of components:
|
||||||
|
|
||||||
|
- The `[log]` section for general configuration
|
||||||
|
- `[log.<sublogger>]` sections for the configuration of different log outputs
|
||||||
|
- `[log.<sublogger>.<group>]` sections for output specific configuration of a log group
|
||||||
|
|
||||||
|
As mentioned below, there is a fully functional log output by default, so it is not necessary to define one.
|
||||||
|
|
||||||
**Table of Contents**
|
**Table of Contents**
|
||||||
|
|
||||||
{{< toc >}}
|
{{< toc >}}
|
||||||
@ -23,6 +31,166 @@ menu:
|
|||||||
|
|
||||||
To collect logs for help and issue report, see [Support Options]({{< relref "doc/help/seek-help.en-us.md" >}}).
|
To collect logs for help and issue report, see [Support Options]({{< relref "doc/help/seek-help.en-us.md" >}}).
|
||||||
|
|
||||||
|
## The `[log]` section
|
||||||
|
|
||||||
|
Configuration of logging facilities in Gitea happen in the `[log]` section and it's subsections.
|
||||||
|
|
||||||
|
In the top level `[log]` section the following configurations can be placed:
|
||||||
|
|
||||||
|
- `ROOT_PATH`: (Default: **%(GITEA_WORK_DIR)/log**): Base path for log files
|
||||||
|
- `MODE`: (Default: **console**) List of log outputs to use for the Default logger.
|
||||||
|
- `ROUTER`: (Default: **console**): List of log outputs to use for the Router logger.
|
||||||
|
- `ACCESS`: List of log outputs to use for the Access logger.
|
||||||
|
- `XORM`: (Default: **,**) List of log outputs to use for the XORM logger.
|
||||||
|
- `ENABLE_ACCESS_LOG`: (Default: **false**): whether the Access logger is allowed to emit logs
|
||||||
|
- `ENABLE_XORM_LOG`: (Default: **true**): whether the XORM logger is allowed to emit logs
|
||||||
|
|
||||||
|
For details on the loggers check the "Log Groups" section.
|
||||||
|
Important: log outputs won't be used if you don't enable them for the desired loggers in the corresponding list value.
|
||||||
|
|
||||||
|
Lists are specified as comma separated values. This format also works in subsection.
|
||||||
|
|
||||||
|
This section may be used for defining default values for subsections.
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
- `LEVEL`: (Default: **Info**) Least severe log events to persist. Case insensitive. The full list of levels as of v1.17.3 can be read [here](https://github.com/go-gitea/gitea/blob/v1.17.3/custom/conf/app.example.ini#L507).
|
||||||
|
- `STACKTRACE_LEVEL`: (Default: **None**) For this and more severe events the stacktrace will be printed upon getting logged.
|
||||||
|
|
||||||
|
Some values are not inherited by subsections. For details see the "Non-inherited default values" section.
|
||||||
|
|
||||||
|
## Log outputs
|
||||||
|
|
||||||
|
Log outputs are the targets to which log messages will be sent.
|
||||||
|
The content and the format of the log messages to be saved can be configured in these.
|
||||||
|
|
||||||
|
Log outputs are also called subloggers.
|
||||||
|
|
||||||
|
Gitea provides 4 possible log outputs:
|
||||||
|
|
||||||
|
- `console` - Log to `os.Stdout` or `os.Stderr`
|
||||||
|
- `file` - Log to a file
|
||||||
|
- `conn` - Log to a socket (network or unix)
|
||||||
|
- `smtp` - Log via email
|
||||||
|
|
||||||
|
By default, Gitea has a `console` output configured, which is used by the loggers as seen in the section "The log section" above.
|
||||||
|
|
||||||
|
### Common configuration
|
||||||
|
|
||||||
|
Certain configuration is common to all modes of log output:
|
||||||
|
|
||||||
|
- `MODE` is the mode of the log output. It will default to the sublogger
|
||||||
|
name, thus `[log.console.router]` will default to `MODE = console`.
|
||||||
|
For mode specific confgurations read further.
|
||||||
|
- `LEVEL` is the lowest level that this output will log. This value
|
||||||
|
is inherited from `[log]` and in the case of the non-default loggers
|
||||||
|
from `[log.sublogger]`.
|
||||||
|
- `STACKTRACE_LEVEL` is the lowest level that this output will print
|
||||||
|
a stacktrace. This value is inherited.
|
||||||
|
- `COLORIZE` will default to `true` for `console` as
|
||||||
|
described, otherwise it will default to `false`.
|
||||||
|
|
||||||
|
### Non-inherited default values
|
||||||
|
|
||||||
|
There are several values which are not inherited as described above but
|
||||||
|
rather default to those specific to type of logger, these are:
|
||||||
|
`EXPRESSION`, `FLAGS`, `PREFIX` and `FILE_NAME`.
|
||||||
|
|
||||||
|
#### `EXPRESSION`
|
||||||
|
|
||||||
|
`EXPRESSION` represents a regular expression that log events must match to be logged by the sublogger. Either the log message, (with colors removed), must match or the `longfilename:linenumber:functionname` must match. NB: the whole message or string doesn't need to completely match.
|
||||||
|
|
||||||
|
Please note this expression will be run in the sublogger's goroutine
|
||||||
|
not the logging event subroutine. Therefore it can be complicated.
|
||||||
|
|
||||||
|
#### `FLAGS`
|
||||||
|
|
||||||
|
`FLAGS` represents the preceding logging context information that is
|
||||||
|
printed before each message. It is a comma-separated string set. The order of values does not matter.
|
||||||
|
|
||||||
|
Possible values are:
|
||||||
|
|
||||||
|
- `none` or `,` - No flags.
|
||||||
|
- `date` - the date in the local time zone: `2009/01/23`.
|
||||||
|
- `time` - the time in the local time zone: `01:23:23`.
|
||||||
|
- `microseconds` - microsecond resolution: `01:23:23.123123`. Assumes
|
||||||
|
time.
|
||||||
|
- `longfile` - full file name and line number: `/a/b/c/d.go:23`.
|
||||||
|
- `shortfile` - final file name element and line number: `d.go:23`.
|
||||||
|
- `funcname` - function name of the caller: `runtime.Caller()`.
|
||||||
|
- `shortfuncname` - last part of the function name. Overrides
|
||||||
|
`funcname`.
|
||||||
|
- `utc` - if date or time is set, use UTC rather than the local time
|
||||||
|
zone.
|
||||||
|
- `levelinitial` - Initial character of the provided level in brackets eg. `[I]` for info.
|
||||||
|
- `level` - Provided level in brackets `[INFO]`
|
||||||
|
- `medfile` - Last 20 characters of the filename - equivalent to
|
||||||
|
`shortfile,longfile`.
|
||||||
|
- `stdflags` - Equivalent to `date,time,medfile,shortfuncname,levelinitial`
|
||||||
|
|
||||||
|
### Console mode
|
||||||
|
|
||||||
|
In this mode the logger will forward log messages to the stdout and
|
||||||
|
stderr streams attached to the Gitea process.
|
||||||
|
|
||||||
|
For loggers in console mode, `COLORIZE` will default to `true` if not
|
||||||
|
on windows, or the windows terminal can be set into ANSI mode or is a
|
||||||
|
cygwin or Msys pipe.
|
||||||
|
|
||||||
|
Settings:
|
||||||
|
|
||||||
|
- `STDERR`: **false**: Whether the logger should print to `stderr` instead of `stdout`.
|
||||||
|
|
||||||
|
### File mode
|
||||||
|
|
||||||
|
In this mode the logger will save log messages to a file.
|
||||||
|
|
||||||
|
Settings:
|
||||||
|
|
||||||
|
- `FILE_NAME`: The file to write the log events to. For details see below.
|
||||||
|
- `MAX_SIZE_SHIFT`: **28**: Maximum size shift of a single file. 28 represents 256Mb. For details see below.
|
||||||
|
- `LOG_ROTATE` **true**: Whether to rotate the log files. TODO: if false, will it delete instead on daily rotate, or do nothing?.
|
||||||
|
- `DAILY_ROTATE`: **true**: Whether to rotate logs daily.
|
||||||
|
- `MAX_DAYS`: **7**: Delete rotated log files after this number of days.
|
||||||
|
- `COMPRESS`: **true**: Whether to compress old log files by default with gzip.
|
||||||
|
- `COMPRESSION_LEVEL`: **-1**: Compression level. For details see below.
|
||||||
|
|
||||||
|
The default value of `FILE_NAME` depends on the respective logger facility.
|
||||||
|
If unset, their own default will be used.
|
||||||
|
If set it will be relative to the provided `ROOT_PATH` in the master `[log]` section.
|
||||||
|
|
||||||
|
`MAX_SIZE_SHIFT` defines the maximum size of a file by left shifting 1 the given number of times (`1 << x`).
|
||||||
|
The exact behavior at the time of v1.17.3 can be seen [here](https://github.com/go-gitea/gitea/blob/v1.17.3/modules/setting/log.go#L185).
|
||||||
|
|
||||||
|
The useful values of `COMPRESSION_LEVEL` are from 1 to (and including) 9, where higher numbers mean better compression.
|
||||||
|
Beware that better compression might come with higher resource usage.
|
||||||
|
Must be preceded with a `-` sign.
|
||||||
|
|
||||||
|
### Conn mode
|
||||||
|
|
||||||
|
In this mode the logger will send log messages over a network socket.
|
||||||
|
|
||||||
|
Settings:
|
||||||
|
|
||||||
|
- `ADDR`: **:7020**: Sets the address to connect to.
|
||||||
|
- `PROTOCOL`: **tcp**: Set the protocol, either "tcp", "unix" or "udp".
|
||||||
|
- `RECONNECT`: **false**: Try to reconnect when connection is lost.
|
||||||
|
- `RECONNECT_ON_MSG`: **false**: Reconnect host for every single message.
|
||||||
|
|
||||||
|
### SMTP mode
|
||||||
|
|
||||||
|
In this mode the logger will send log messages in email.
|
||||||
|
|
||||||
|
It is not recommended to use this logger to send general logging
|
||||||
|
messages. However, you could perhaps set this logger to work on `FATAL` messages only.
|
||||||
|
|
||||||
|
Settings:
|
||||||
|
|
||||||
|
- `HOST`: **127.0.0.1:25**: The SMTP host to connect to.
|
||||||
|
- `USER`: User email address to send from.
|
||||||
|
- `PASSWD`: Password for the smtp server.
|
||||||
|
- `RECEIVERS`: Email addresses to send to.
|
||||||
|
- `SUBJECT`: **Diagnostic message from Gitea**. The content of the email's subject field.
|
||||||
|
|
||||||
## Log Groups
|
## Log Groups
|
||||||
|
|
||||||
The fundamental thing to be aware of in Gitea is that there are several
|
The fundamental thing to be aware of in Gitea is that there are several
|
||||||
@ -172,106 +340,6 @@ which will not be inherited from the `[log]` or relevant
|
|||||||
- `EXPRESSION` will default to `""`
|
- `EXPRESSION` will default to `""`
|
||||||
- `PREFIX` will default to `""`
|
- `PREFIX` will default to `""`
|
||||||
|
|
||||||
## Log outputs
|
|
||||||
|
|
||||||
Gitea provides 4 possible log outputs:
|
|
||||||
|
|
||||||
- `console` - Log to `os.Stdout` or `os.Stderr`
|
|
||||||
- `file` - Log to a file
|
|
||||||
- `conn` - Log to a keep-alive TCP connection
|
|
||||||
- `smtp` - Log via email
|
|
||||||
|
|
||||||
Certain configuration is common to all modes of log output:
|
|
||||||
|
|
||||||
- `LEVEL` is the lowest level that this output will log. This value
|
|
||||||
is inherited from `[log]` and in the case of the non-default loggers
|
|
||||||
from `[log.sublogger]`.
|
|
||||||
- `STACKTRACE_LEVEL` is the lowest level that this output will print
|
|
||||||
a stacktrace. This value is inherited.
|
|
||||||
- `MODE` is the mode of the log output. It will default to the sublogger
|
|
||||||
name. Thus `[log.console.router]` will default to `MODE = console`.
|
|
||||||
- `COLORIZE` will default to `true` for `console` as
|
|
||||||
described, otherwise it will default to `false`.
|
|
||||||
|
|
||||||
### Non-inherited default values
|
|
||||||
|
|
||||||
There are several values which are not inherited as described above but
|
|
||||||
rather default to those specific to type of logger, these are:
|
|
||||||
`EXPRESSION`, `FLAGS`, `PREFIX` and `FILE_NAME`.
|
|
||||||
|
|
||||||
#### `EXPRESSION`
|
|
||||||
|
|
||||||
`EXPRESSION` represents a regular expression that log events must match to be logged by the sublogger. Either the log message, (with colors removed), must match or the `longfilename:linenumber:functionname` must match. NB: the whole message or string doesn't need to completely match.
|
|
||||||
|
|
||||||
Please note this expression will be run in the sublogger's goroutine
|
|
||||||
not the logging event subroutine. Therefore it can be complicated.
|
|
||||||
|
|
||||||
#### `FLAGS`
|
|
||||||
|
|
||||||
`FLAGS` represents the preceding logging context information that is
|
|
||||||
printed before each message. It is a comma-separated string set. The order of values does not matter.
|
|
||||||
|
|
||||||
Possible values are:
|
|
||||||
|
|
||||||
- `none` or `,` - No flags.
|
|
||||||
- `date` - the date in the local time zone: `2009/01/23`.
|
|
||||||
- `time` - the time in the local time zone: `01:23:23`.
|
|
||||||
- `microseconds` - microsecond resolution: `01:23:23.123123`. Assumes
|
|
||||||
time.
|
|
||||||
- `longfile` - full file name and line number: `/a/b/c/d.go:23`.
|
|
||||||
- `shortfile` - final file name element and line number: `d.go:23`.
|
|
||||||
- `funcname` - function name of the caller: `runtime.Caller()`.
|
|
||||||
- `shortfuncname` - last part of the function name. Overrides
|
|
||||||
`funcname`.
|
|
||||||
- `utc` - if date or time is set, use UTC rather than the local time
|
|
||||||
zone.
|
|
||||||
- `levelinitial` - Initial character of the provided level in brackets eg. `[I]` for info.
|
|
||||||
- `level` - Provided level in brackets `[INFO]`
|
|
||||||
- `medfile` - Last 20 characters of the filename - equivalent to
|
|
||||||
`shortfile,longfile`.
|
|
||||||
- `stdflags` - Equivalent to `date,time,medfile,shortfuncname,levelinitial`
|
|
||||||
|
|
||||||
### Console mode
|
|
||||||
|
|
||||||
For loggers in console mode, `COLORIZE` will default to `true` if not
|
|
||||||
on windows, or the windows terminal can be set into ANSI mode or is a
|
|
||||||
cygwin or Msys pipe.
|
|
||||||
|
|
||||||
If `STDERR` is set to `true` the logger will use `os.Stderr` instead of
|
|
||||||
`os.Stdout`.
|
|
||||||
|
|
||||||
### File mode
|
|
||||||
|
|
||||||
The `FILE_NAME` defaults as described above. If set it will be relative
|
|
||||||
to the provided `ROOT_PATH` in the master `[log]` section.
|
|
||||||
|
|
||||||
Other values:
|
|
||||||
|
|
||||||
- `LOG_ROTATE`: **true**: Rotate the log files.
|
|
||||||
- `MAX_SIZE_SHIFT`: **28**: Maximum size shift of a single file, 28 represents 256Mb.
|
|
||||||
- `DAILY_ROTATE`: **true**: Rotate logs daily.
|
|
||||||
- `MAX_DAYS`: **7**: Delete the log file after n days
|
|
||||||
- `COMPRESS`: **true**: Compress old log files by default with gzip
|
|
||||||
- `COMPRESSION_LEVEL`: **-1**: Compression level
|
|
||||||
|
|
||||||
### Conn mode
|
|
||||||
|
|
||||||
- `RECONNECT_ON_MSG`: **false**: Reconnect host for every single message.
|
|
||||||
- `RECONNECT`: **false**: Try to reconnect when connection is lost.
|
|
||||||
- `PROTOCOL`: **tcp**: Set the protocol, either "tcp", "unix" or "udp".
|
|
||||||
- `ADDR`: **:7020**: Sets the address to connect to.
|
|
||||||
|
|
||||||
### SMTP mode
|
|
||||||
|
|
||||||
It is not recommended to use this logger to send general logging
|
|
||||||
messages. However, you could perhaps set this logger to work on `FATAL`.
|
|
||||||
|
|
||||||
- `USER`: User email address to send from.
|
|
||||||
- `PASSWD`: Password for the smtp server.
|
|
||||||
- `HOST`: **127.0.0.1:25**: The SMTP host to connect to.
|
|
||||||
- `RECEIVERS`: Email addresses to send to.
|
|
||||||
- `SUBJECT`: **Diagnostic message from Gitea**
|
|
||||||
|
|
||||||
## Debugging problems
|
## Debugging problems
|
||||||
|
|
||||||
When submitting logs in Gitea issues it is often helpful to submit
|
When submitting logs in Gitea issues it is often helpful to submit
|
||||||
|
@ -41,13 +41,15 @@ For an existing remote repository, you can set up pull mirroring as follows:
|
|||||||
|
|
||||||
The repository now gets mirrored periodically from the remote repository. You can force a sync by selecting **Synchronize Now** in the repository settings.
|
The repository now gets mirrored periodically from the remote repository. You can force a sync by selecting **Synchronize Now** in the repository settings.
|
||||||
|
|
||||||
|
:exclamation::exclamation: **NOTE:** You can only set up pull mirroring for repos that don't exist yet on your instance. Once the repo is created, you can't convert it into a pull mirror anymore. :exclamation::exclamation:
|
||||||
|
|
||||||
## Pushing to a remote repository
|
## Pushing to a remote repository
|
||||||
|
|
||||||
For an existing repository, you can set up push mirroring as follows:
|
For an existing repository, you can set up push mirroring as follows:
|
||||||
|
|
||||||
1. In your repository, go to **Settings** > **Repository**, and then the **Mirror Settings** section.
|
1. In your repository, go to **Settings** > **Repository**, and then the **Mirror Settings** section.
|
||||||
2. Enter a repository URL.
|
2. Enter a repository URL.
|
||||||
3. If the repository needs authentication expand the **Authorization** section and fill in your authentication information.
|
3. If the repository needs authentication expand the **Authorization** section and fill in your authentication information. Note that the requested **password** can also be your access token.
|
||||||
4. Select **Add Push Mirror** to save the configuration.
|
4. Select **Add Push Mirror** to save the configuration.
|
||||||
|
|
||||||
The repository now gets mirrored periodically to the remote repository. You can force a sync by selecting **Synchronize Now**. In case of an error a message displayed to help you resolve it.
|
The repository now gets mirrored periodically to the remote repository. You can force a sync by selecting **Synchronize Now**. In case of an error a message displayed to help you resolve it.
|
||||||
@ -59,9 +61,11 @@ The repository now gets mirrored periodically to the remote repository. You can
|
|||||||
To set up a mirror from Gitea to GitHub, you need to follow these steps:
|
To set up a mirror from Gitea to GitHub, you need to follow these steps:
|
||||||
|
|
||||||
1. Create a [GitHub personal access token](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token) with the *public_repo* box checked.
|
1. Create a [GitHub personal access token](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token) with the *public_repo* box checked.
|
||||||
2. Fill in the **Git Remote Repository URL**: `https://github.com/<your_github_group>/<your_github_project>.git`.
|
2. Create a repository with that name on GitHub. Unlike Gitea, GitHub does not support creating repositories by pushing to the remote. You can also use an existing remote repo if it has the same commit history as your Gitea repo.
|
||||||
3. Fill in the **Authorization** fields with your GitHub username and the personal access token.
|
3. In the settings of your Gitea repo, fill in the **Git Remote Repository URL**: `https://github.com/<your_github_group>/<your_github_project>.git`.
|
||||||
4. Select **Add Push Mirror** to save the configuration.
|
4. Fill in the **Authorization** fields with your GitHub username and the personal access token as **Password**.
|
||||||
|
5. (Optional, available on Gitea 1.18+) Select `Sync when new commits are pushed` so that the mirror will be updated as well as soon as there are changes. You can also disable the periodic sync if you like.
|
||||||
|
6. Select **Add Push Mirror** to save the configuration.
|
||||||
|
|
||||||
The repository pushes shortly thereafter. To force a push, select the **Synchronize Now** button.
|
The repository pushes shortly thereafter. To force a push, select the **Synchronize Now** button.
|
||||||
|
|
||||||
|
@ -166,11 +166,47 @@ Uses the following fields:
|
|||||||
|
|
||||||
## PAM (Pluggable Authentication Module)
|
## PAM (Pluggable Authentication Module)
|
||||||
|
|
||||||
To configure PAM, set the 'PAM Service Name' to a filename in `/etc/pam.d/`. To
|
This procedure enables PAM authentication. Users may still be added to the
|
||||||
work with normal Linux passwords, the user running Gitea must have read access
|
system manually using the user administration. PAM provides a mechanism to
|
||||||
to `/etc/shadow`.
|
automatically add users to the current database by testing them against PAM
|
||||||
|
authentication. To work with normal Linux passwords, the user running Gitea
|
||||||
|
must also have read access to `/etc/shadow` in order to check the validity of
|
||||||
|
the account when logging in using a public key.
|
||||||
|
|
||||||
**Note**: PAM support is added via [build-time flags](https://docs.gitea.io/en-us/install-from-source/#build), and the official binaries provided do not have this enabled.
|
**Note**: If a user has added SSH public keys into Gitea, the use of these
|
||||||
|
keys _may_ bypass the login check system. Therefore, if you wish to disable a user who
|
||||||
|
authenticates with PAM, you _should_ also manually disable the account in Gitea using the
|
||||||
|
built-in user manager.
|
||||||
|
|
||||||
|
1. Configure and prepare the installation.
|
||||||
|
- It is recommended that you create an administrative user.
|
||||||
|
- Deselecting automatic sign-up may also be desired.
|
||||||
|
1. Once the database has been initialized, log in as the newly created
|
||||||
|
administrative user.
|
||||||
|
1. Navigate to the user setting (icon in top-right corner), and select
|
||||||
|
`Site Administration` -> `Authentication Sources`, and select
|
||||||
|
`Add Authentication Source`.
|
||||||
|
1. Fill out the field as follows:
|
||||||
|
- `Authentication Type` : `PAM`
|
||||||
|
- `Name` : Any value should be valid here, use "System Authentication" if
|
||||||
|
you'd like.
|
||||||
|
- `PAM Service Name` : Select the appropriate file listed under `/etc/pam.d/`
|
||||||
|
that performs the authentication desired.[^1]
|
||||||
|
- `PAM Email Domain` : The e-mail suffix to append to user authentication.
|
||||||
|
For example, if the login system expects a user called `gituser`, and this
|
||||||
|
field is set to `mail.com`, then Gitea will expect the `user email` field
|
||||||
|
for an authenticated GIT instance to be `gituser@mail.com`.[^2]
|
||||||
|
|
||||||
|
**Note**: PAM support is added via [build-time flags](https://docs.gitea.io/en-us/install-from-source/#build),
|
||||||
|
and the official binaries provided do not have this enabled. PAM requires that
|
||||||
|
the necessary libpam dynamic library be available and the necessary PAM
|
||||||
|
development headers be accessible to the compiler.
|
||||||
|
|
||||||
|
[^1]: For example, using standard Linux log-in on Debian "Bullseye" use
|
||||||
|
`common-session-noninteractive` - this value may be valid for other flavors of
|
||||||
|
Debian including Ubuntu and Mint, consult your distribution's documentation.
|
||||||
|
[^2]: **This is a required field for PAM**. Be aware: In the above example, the
|
||||||
|
user will log into the Gitea web interface as `gituser` and not `gituser@mail.com`
|
||||||
|
|
||||||
## SMTP (Simple Mail Transfer Protocol)
|
## SMTP (Simple Mail Transfer Protocol)
|
||||||
|
|
||||||
|
@ -58,29 +58,33 @@ https://github.com/loganinak/MigrateGitlabToGogs
|
|||||||
|
|
||||||
## Where does Gitea store what file
|
## Where does Gitea store what file
|
||||||
|
|
||||||
- WorkPath
|
- _`AppWorkPath`_
|
||||||
- Environment variable `GITEA_WORK_DIR`
|
- The `--work-path` flag
|
||||||
- Else `--work-path` flag
|
- Else Environment variable `GITEA_WORK_DIR`
|
||||||
|
- Else a built-in value set at build time
|
||||||
- Else the directory that contains the Gitea binary
|
- Else the directory that contains the Gitea binary
|
||||||
- AppDataPath (default for database, indexers, etc.)
|
- `%(APP_DATA_PATH)` (default for database, indexers, etc.)
|
||||||
- `APP_DATA_PATH` from `app.ini`
|
- `APP_DATA_PATH` from `app.ini`
|
||||||
- Else `%(WorkPath)/data`
|
- Else _`AppWorkPath`_`/data`
|
||||||
- CustomPath (custom templates)
|
- _`CustomPath`_ (custom templates)
|
||||||
- Environment variable `GITEA_CUSTOM`
|
- The `--custom-path` flag
|
||||||
- Else `%(WorkPath)/custom`
|
- Else Environment variable `GITEA_CUSTOM`
|
||||||
|
- Else a built-in value set at build time
|
||||||
|
- Else _`AppWorkPath`_`/custom`
|
||||||
- HomeDir
|
- HomeDir
|
||||||
- Unix: Environment variable `HOME`
|
- Unix: Environment variable `HOME`
|
||||||
- Windows: Environment variable `USERPROFILE`, else environment variables `HOMEDRIVE`+`HOMEPATH`
|
- Windows: Environment variable `USERPROFILE`, else environment variables `HOMEDRIVE`+`HOMEPATH`
|
||||||
- RepoRootPath
|
- RepoRootPath
|
||||||
- `ROOT` in the \[repository] section of `app.ini` if absolute
|
- `ROOT` in the \[repository] section of `app.ini` if absolute
|
||||||
- Else `%(AppWorkPath)/ROOT` if `ROOT` in the \[repository] section of `app.ini` if relative
|
- Else _`AppWorkPath`_`/ROOT` if `ROOT` in the \[repository] section of `app.ini` if relative
|
||||||
- Default `%(AppDataPath)/gitea-repositories`
|
- Default `%(APP_DATA_PATH)/gitea-repositories`
|
||||||
- INI (config file)
|
- INI (config file)
|
||||||
- `-c` flag
|
- `--config` flag
|
||||||
- Else `%(CustomPath)/conf/app.ini`
|
- A possible built-in value set a build time
|
||||||
|
- Else _`CustomPath`_`/conf/app.ini`
|
||||||
- SQLite Database
|
- SQLite Database
|
||||||
- `PATH` in `database` section of `app.ini`
|
- `PATH` in `database` section of `app.ini`
|
||||||
- Else `%(AppDataPath)/gitea.db`
|
- Else `%(APP_DATA_PATH)/gitea.db`
|
||||||
|
|
||||||
## Not seeing a clone URL or the clone URL being incorrect
|
## Not seeing a clone URL or the clone URL being incorrect
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ are provided to keep the build process as simple as possible.
|
|||||||
|
|
||||||
Depending on requirements, the following build tags can be included.
|
Depending on requirements, the following build tags can be included.
|
||||||
|
|
||||||
- `bindata`: Build a single monolithic binary, with all assets included.
|
- `bindata`: Build a single monolithic binary, with all assets included. Required for production build.
|
||||||
- `sqlite sqlite_unlock_notify`: Enable support for a
|
- `sqlite sqlite_unlock_notify`: Enable support for a
|
||||||
[SQLite3](https://sqlite.org/) database. Suggested only for tiny
|
[SQLite3](https://sqlite.org/) database. Suggested only for tiny
|
||||||
installations.
|
installations.
|
||||||
@ -103,11 +103,10 @@ Depending on requirements, the following build tags can be included.
|
|||||||
available to PAM.
|
available to PAM.
|
||||||
- `gogit`: (EXPERIMENTAL) Use go-git variants of Git commands.
|
- `gogit`: (EXPERIMENTAL) Use go-git variants of Git commands.
|
||||||
|
|
||||||
Bundling assets into the binary using the `bindata` build tag is recommended for
|
Bundling all assets (JS/CSS/templates, etc) into the binary. Using the `bindata` build tag is required for
|
||||||
production deployments. It is possible to serve the static assets directly via a reverse proxy,
|
production deployments. You could exclude `bindata` when you are developing/testing Gitea or able to separate the assets correctly.
|
||||||
but in most cases it is not necessary, and assets should still be bundled in the binary.
|
|
||||||
You may want to exclude bindata while developing/testing Gitea.
|
To include all assets, use the `bindata` tag:
|
||||||
To include assets, add the `bindata` tag:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
TAGS="bindata" make build
|
TAGS="bindata" make build
|
||||||
@ -144,11 +143,11 @@ launched manually from command line, it can be killed by pressing `Ctrl + C`.
|
|||||||
|
|
||||||
## Changing default paths
|
## Changing default paths
|
||||||
|
|
||||||
Gitea will search for a number of things from the `CustomPath`. By default this is
|
Gitea will search for a number of things from the _`CustomPath`_. By default this is
|
||||||
the `custom/` directory in the current working directory when running Gitea. It will also
|
the `custom/` directory in the current working directory when running Gitea. It will also
|
||||||
look for its configuration file `CustomConf` in `$CustomPath/conf/app.ini`, and will use the
|
look for its configuration file _`CustomConf`_ in _`CustomPath`_/conf/app.ini`, and will use the
|
||||||
current working directory as the relative base path `AppWorkPath` for a number configurable
|
current working directory as the relative base path _`AppWorkPath`_ for a number configurable
|
||||||
values. Finally the static files will be served from `StaticRootPath` which defaults to the `AppWorkPath`.
|
values. Finally the static files will be served from _`StaticRootPath`_ which defaults to the _`AppWorkPath`_.
|
||||||
|
|
||||||
These values, although useful when developing, may conflict with downstream users preferences.
|
These values, although useful when developing, may conflict with downstream users preferences.
|
||||||
|
|
||||||
@ -156,10 +155,10 @@ One option is to use a script file to shadow the `gitea` binary and create an ap
|
|||||||
environment before running Gitea. However, when building you can change these defaults
|
environment before running Gitea. However, when building you can change these defaults
|
||||||
using the `LDFLAGS` environment variable for `make`. The appropriate settings are as follows
|
using the `LDFLAGS` environment variable for `make`. The appropriate settings are as follows
|
||||||
|
|
||||||
- To set the `CustomPath` use `LDFLAGS="-X \"code.gitea.io/gitea/modules/setting.CustomPath=custom-path\""`
|
- To set the _`CustomPath`_ use `LDFLAGS="-X \"code.gitea.io/gitea/modules/setting.CustomPath=custom-path\""`
|
||||||
- For `CustomConf` you should use `-X \"code.gitea.io/gitea/modules/setting.CustomConf=conf.ini\"`
|
- For _`CustomConf`_ you should use `-X \"code.gitea.io/gitea/modules/setting.CustomConf=conf.ini\"`
|
||||||
- For `AppWorkPath` you should use `-X \"code.gitea.io/gitea/modules/setting.AppWorkPath=working-path\"`
|
- For _`AppWorkPath`_ you should use `-X \"code.gitea.io/gitea/modules/setting.AppWorkPath=working-path\"`
|
||||||
- For `StaticRootPath` you should use `-X \"code.gitea.io/gitea/modules/setting.StaticRootPath=static-root-path\"`
|
- For _`StaticRootPath`_ you should use `-X \"code.gitea.io/gitea/modules/setting.StaticRootPath=static-root-path\"`
|
||||||
- To change the default PID file location use `-X \"code.gitea.io/gitea/modules/setting.PIDFile=/run/gitea.pid\"`
|
- To change the default PID file location use `-X \"code.gitea.io/gitea/modules/setting.PIDFile=/run/gitea.pid\"`
|
||||||
|
|
||||||
Add as many of the strings with their preceding `-X` to the `LDFLAGS` variable and run `make build`
|
Add as many of the strings with their preceding `-X` to the `LDFLAGS` variable and run `make build`
|
||||||
|
84
docs/content/doc/packages/storage.en-us.md
Normal file
84
docs/content/doc/packages/storage.en-us.md
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
---
|
||||||
|
date: "2022-11-01T00:00:00+00:00"
|
||||||
|
title: "Storage"
|
||||||
|
slug: "packages/storage"
|
||||||
|
draft: false
|
||||||
|
toc: false
|
||||||
|
menu:
|
||||||
|
sidebar:
|
||||||
|
parent: "packages"
|
||||||
|
name: "storage"
|
||||||
|
weight: 5
|
||||||
|
identifier: "storage"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Storage
|
||||||
|
|
||||||
|
This document describes the storage of the package registry and how it can be managed.
|
||||||
|
|
||||||
|
**Table of Contents**
|
||||||
|
|
||||||
|
{{< toc >}}
|
||||||
|
|
||||||
|
## Deduplication
|
||||||
|
|
||||||
|
The package registry has a build-in deduplication of uploaded blobs.
|
||||||
|
If two identical files are uploaded only one blob is saved on the filesystem.
|
||||||
|
This ensures no space is wasted for duplicated files.
|
||||||
|
|
||||||
|
If two packages are uploaded with identical files, both packages will display the same size but on the filesystem they require only half of the size.
|
||||||
|
Whenever a package gets deleted only the references to the underlaying blobs are removed.
|
||||||
|
The blobs get not removed at this moment, so they still require space on the filesystem.
|
||||||
|
When a new package gets uploaded the existing blobs may get referenced again.
|
||||||
|
|
||||||
|
These unreferenced blobs get deleted by a [clean up job]({{< relref "doc/advanced/config-cheat-sheet.en-us.md#cron---cleanup-expired-packages-croncleanup_packages" >}}).
|
||||||
|
The config setting `OLDER_THAN` configures how long unreferenced blobs are kept before they get deleted.
|
||||||
|
|
||||||
|
## Cleanup Rules
|
||||||
|
|
||||||
|
Package registries can become large over time without cleanup.
|
||||||
|
It's recommended to delete unnecessary packages and set up cleanup rules to automatically manage the package registry usage.
|
||||||
|
Every package owner (user or organization) manages the cleanup rules which are applied to their packages.
|
||||||
|
|
||||||
|
|Setting|Description|
|
||||||
|
|-|-|
|
||||||
|
|Enabled|Turn the cleanup rule on or off.|
|
||||||
|
|Type|Every rule manages a specific package type.|
|
||||||
|
|Apply pattern to full package name|If enabled, the patterns below are applied to the full package name (`package/version`). Otherwise only the version (`version`) is used.|
|
||||||
|
|Keep the most recent|How many versions to *always* keep for each package.|
|
||||||
|
|Keep versions matching|The regex pattern that determines which versions to keep. An empty pattern keeps no version while `.+` keeps all versions. The container registry will always keep the `latest` version even if not configured.|
|
||||||
|
|Remove versions older than|Remove only versions older than the selected days.|
|
||||||
|
|Remove versions matching|The regex pattern that determines which versions to remove. An empty pattern or `.+` leads to the removal of every package if no other setting tells otherwise.|
|
||||||
|
|
||||||
|
Every cleanup rule can show a preview of the affected packages.
|
||||||
|
This can be used to check if the cleanup rules is proper configured.
|
||||||
|
|
||||||
|
### Regex examples
|
||||||
|
|
||||||
|
Regex patterns are automatically surrounded with `\A` and `\z` anchors.
|
||||||
|
Do not include any `\A`, `\z`, `^` or `$` token in the regex patterns as they are not necessary.
|
||||||
|
The patterns are case-insensitive which matches the behaviour of the package registry in Gitea.
|
||||||
|
|
||||||
|
|Pattern|Description|
|
||||||
|
|-|-|
|
||||||
|
|`.*`|Match every possible version.|
|
||||||
|
|`v.+`|Match versions that start with `v`.|
|
||||||
|
|`release`|Match only the version `release`.|
|
||||||
|
|`release.*`|Match versions that are either named or start with `release`.|
|
||||||
|
|`.+-temp-.+`|Match versions that contain `-temp-`.|
|
||||||
|
|`v.+\|release`|Match versions that either start with `v` or are named `release`.|
|
||||||
|
|`package/v.+\|other/release`|Match versions of the package `package` that start with `v` or the version `release` of the package `other`. This needs the setting *Apply pattern to full package name* enabled.|
|
||||||
|
|
||||||
|
### How the cleanup rules work
|
||||||
|
|
||||||
|
The cleanup rules are part of the [clean up job]({{< relref "doc/advanced/config-cheat-sheet.en-us.md#cron---cleanup-expired-packages-croncleanup_packages" >}}) and run periodicly.
|
||||||
|
|
||||||
|
The cleanup rule:
|
||||||
|
|
||||||
|
1. Collects all packages of the package type for the owners registry.
|
||||||
|
1. For every package it collects all versions.
|
||||||
|
1. Excludes from the list the # versions based on the *Keep the most recent* value.
|
||||||
|
1. Excludes from the list any versions matching the *Keep versions matching* value.
|
||||||
|
1. Excludes from the list the versions more recent than the *Remove versions older than* value.
|
||||||
|
1. Excludes from the list any versions not matching the *Remove versions matching* value.
|
||||||
|
1. Deletes the remaining versions.
|
@ -45,15 +45,15 @@ Beispiel: Wenn der Button mit `löschen` beschriftet ist, sollte im Modal die Fr
|
|||||||
## Artikeldefinitionen für Anglizismen
|
## Artikeldefinitionen für Anglizismen
|
||||||
|
|
||||||
* _Der_ Commit (m.)
|
* _Der_ Commit (m.)
|
||||||
* _Der_ Branch (m.)
|
* _Der_ Branch (m.), plural: die Branches
|
||||||
* _Das_ Issue (n.)
|
* _Das_ Issue (n.)
|
||||||
* _Der_ Fork (m.)
|
* _Der_ Fork (m.)
|
||||||
* _Das_ Repository (n.)
|
* _Das_ Repository (n.), plural: die Repositories
|
||||||
* _Der_ Pull-Request (m.)
|
* _Der_ Pull-Request (m.)
|
||||||
* _Der_ Token (m.)
|
* _Der_ Token (m.), plural: die Token
|
||||||
* _Das_ Review (n.)
|
* _Das_ Review (n.)
|
||||||
* _Der_ Key (m.)
|
* _Der_ Key (m.)
|
||||||
* _Der_ Committer (m.)
|
* _Der_ Committer (m.), plural: die Committer
|
||||||
|
|
||||||
## Weiterführende Links
|
## Weiterführende Links
|
||||||
|
|
||||||
|
10
go.mod
10
go.mod
@ -94,15 +94,14 @@ require (
|
|||||||
github.com/yuin/goldmark-meta v1.1.0
|
github.com/yuin/goldmark-meta v1.1.0
|
||||||
go.jolheiser.com/hcaptcha v0.0.4
|
go.jolheiser.com/hcaptcha v0.0.4
|
||||||
go.jolheiser.com/pwn v0.0.3
|
go.jolheiser.com/pwn v0.0.3
|
||||||
golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be
|
golang.org/x/crypto v0.2.1-0.20221112162523-6fad3dfc1891
|
||||||
golang.org/x/net v0.0.0-20220927171203-f486391704dc
|
golang.org/x/net v0.2.0
|
||||||
golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1
|
golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1
|
||||||
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec
|
golang.org/x/sys v0.2.0
|
||||||
golang.org/x/text v0.3.8
|
golang.org/x/text v0.4.0
|
||||||
golang.org/x/tools v0.1.12
|
golang.org/x/tools v0.1.12
|
||||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||||
gopkg.in/ini.v1 v1.67.0
|
gopkg.in/ini.v1 v1.67.0
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
mvdan.cc/xurls/v2 v2.4.0
|
mvdan.cc/xurls/v2 v2.4.0
|
||||||
strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251
|
strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251
|
||||||
@ -293,6 +292,7 @@ require (
|
|||||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||||
gopkg.in/cheggaaa/pb.v1 v1.0.28 // indirect
|
gopkg.in/cheggaaa/pb.v1 v1.0.28 // indirect
|
||||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
sigs.k8s.io/yaml v1.2.0 // indirect
|
sigs.k8s.io/yaml v1.2.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
|
18
go.sum
18
go.sum
@ -1608,8 +1608,8 @@ golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0
|
|||||||
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be h1:fmw3UbQh+nxngCAHrDCCztao/kbYFnWjoqop8dHx05A=
|
golang.org/x/crypto v0.2.1-0.20221112162523-6fad3dfc1891 h1:WhEPFM1Ck5gaKybeSWvzI7Y/cd8K9K5tJGRxXMACOBA=
|
||||||
golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.2.1-0.20221112162523-6fad3dfc1891/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
@ -1721,8 +1721,8 @@ golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su
|
|||||||
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.0.0-20220630215102-69896b714898/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220630215102-69896b714898/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||||
golang.org/x/net v0.0.0-20220927171203-f486391704dc h1:FxpXZdoBqT8RjqTy6i1E8nXHhW21wK7ptQ/EPIGxzPQ=
|
golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU=
|
||||||
golang.org/x/net v0.0.0-20220927171203-f486391704dc/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
@ -1876,13 +1876,13 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec h1:BkDtF2Ih9xZ7le9ndzTA7KJow28VbQW3odyk/8drmuI=
|
golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
|
||||||
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 h1:Q5284mrmYTpACcm+eAKjKJH48BBwSyfJqmmGDTtT8Vc=
|
|
||||||
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
|
golang.org/x/term v0.2.0 h1:z85xZCsEl7bi/KwbNADeBYoOP0++7W1ipu+aGnpwzRM=
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
@ -1892,8 +1892,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|||||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY=
|
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
|
||||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
@ -461,7 +461,8 @@ func DeleteOldActions(olderThan time.Duration) (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func notifyWatchers(ctx context.Context, actions ...*Action) error {
|
// NotifyWatchers creates batch of actions for every watcher.
|
||||||
|
func NotifyWatchers(ctx context.Context, actions ...*Action) error {
|
||||||
var watchers []*repo_model.Watch
|
var watchers []*repo_model.Watch
|
||||||
var repo *repo_model.Repository
|
var repo *repo_model.Repository
|
||||||
var err error
|
var err error
|
||||||
@ -565,20 +566,15 @@ func notifyWatchers(ctx context.Context, actions ...*Action) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotifyWatchers creates batch of actions for every watcher.
|
|
||||||
func NotifyWatchers(actions ...*Action) error {
|
|
||||||
return notifyWatchers(db.DefaultContext, actions...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotifyWatchersActions creates batch of actions for every watcher.
|
// NotifyWatchersActions creates batch of actions for every watcher.
|
||||||
func NotifyWatchersActions(acts []*Action) error {
|
func NotifyWatchersActions(acts []*Action) error {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer committer.Close()
|
defer committer.Close()
|
||||||
for _, act := range acts {
|
for _, act := range acts {
|
||||||
if err := notifyWatchers(ctx, act); err != nil {
|
if err := NotifyWatchers(ctx, act); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -603,17 +599,17 @@ func DeleteIssueActions(ctx context.Context, repoID, issueID int64) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CountActionCreatedUnixString count actions where created_unix is an empty string
|
// CountActionCreatedUnixString count actions where created_unix is an empty string
|
||||||
func CountActionCreatedUnixString() (int64, error) {
|
func CountActionCreatedUnixString(ctx context.Context) (int64, error) {
|
||||||
if setting.Database.UseSQLite3 {
|
if setting.Database.UseSQLite3 {
|
||||||
return db.GetEngine(db.DefaultContext).Where(`created_unix = ""`).Count(new(Action))
|
return db.GetEngine(ctx).Where(`created_unix = ""`).Count(new(Action))
|
||||||
}
|
}
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// FixActionCreatedUnixString set created_unix to zero if it is an empty string
|
// FixActionCreatedUnixString set created_unix to zero if it is an empty string
|
||||||
func FixActionCreatedUnixString() (int64, error) {
|
func FixActionCreatedUnixString(ctx context.Context) (int64, error) {
|
||||||
if setting.Database.UseSQLite3 {
|
if setting.Database.UseSQLite3 {
|
||||||
res, err := db.GetEngine(db.DefaultContext).Exec(`UPDATE action SET created_unix = 0 WHERE created_unix = ""`)
|
res, err := db.GetEngine(ctx).Exec(`UPDATE action SET created_unix = 0 WHERE created_unix = ""`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
@ -188,7 +188,7 @@ func TestNotifyWatchers(t *testing.T) {
|
|||||||
RepoID: 1,
|
RepoID: 1,
|
||||||
OpType: activities_model.ActionStarRepo,
|
OpType: activities_model.ActionStarRepo,
|
||||||
}
|
}
|
||||||
assert.NoError(t, activities_model.NotifyWatchers(action))
|
assert.NoError(t, activities_model.NotifyWatchers(db.DefaultContext, action))
|
||||||
|
|
||||||
// One watchers are inactive, thus action is only created for user 8, 1, 4, 11
|
// One watchers are inactive, thus action is only created for user 8, 1, 4, 11
|
||||||
unittest.AssertExistsAndLoadBean(t, &activities_model.Action{
|
unittest.AssertExistsAndLoadBean(t, &activities_model.Action{
|
||||||
@ -256,17 +256,17 @@ func TestConsistencyUpdateAction(t *testing.T) {
|
|||||||
//
|
//
|
||||||
// Get rid of incorrectly set created_unix
|
// Get rid of incorrectly set created_unix
|
||||||
//
|
//
|
||||||
count, err := activities_model.CountActionCreatedUnixString()
|
count, err := activities_model.CountActionCreatedUnixString(db.DefaultContext)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.EqualValues(t, 1, count)
|
assert.EqualValues(t, 1, count)
|
||||||
count, err = activities_model.FixActionCreatedUnixString()
|
count, err = activities_model.FixActionCreatedUnixString(db.DefaultContext)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.EqualValues(t, 1, count)
|
assert.EqualValues(t, 1, count)
|
||||||
|
|
||||||
count, err = activities_model.CountActionCreatedUnixString()
|
count, err = activities_model.CountActionCreatedUnixString(db.DefaultContext)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.EqualValues(t, 0, count)
|
assert.EqualValues(t, 0, count)
|
||||||
count, err = activities_model.FixActionCreatedUnixString()
|
count, err = activities_model.FixActionCreatedUnixString(db.DefaultContext)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.EqualValues(t, 0, count)
|
assert.EqualValues(t, 0, count)
|
||||||
|
|
||||||
|
@ -136,56 +136,48 @@ func GetNotifications(ctx context.Context, options *FindNotificationOptions) (nl
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CountNotifications count all notifications that fit to the given options and ignore pagination.
|
// CountNotifications count all notifications that fit to the given options and ignore pagination.
|
||||||
func CountNotifications(opts *FindNotificationOptions) (int64, error) {
|
func CountNotifications(ctx context.Context, opts *FindNotificationOptions) (int64, error) {
|
||||||
return db.GetEngine(db.DefaultContext).Where(opts.ToCond()).Count(&Notification{})
|
return db.GetEngine(ctx).Where(opts.ToCond()).Count(&Notification{})
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateRepoTransferNotification creates notification for the user a repository was transferred to
|
// CreateRepoTransferNotification creates notification for the user a repository was transferred to
|
||||||
func CreateRepoTransferNotification(doer, newOwner *user_model.User, repo *repo_model.Repository) error {
|
func CreateRepoTransferNotification(ctx context.Context, doer, newOwner *user_model.User, repo *repo_model.Repository) error {
|
||||||
ctx, committer, err := db.TxContext()
|
return db.AutoTx(ctx, func(ctx context.Context) error {
|
||||||
if err != nil {
|
var notify []*Notification
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer committer.Close()
|
|
||||||
|
|
||||||
var notify []*Notification
|
if newOwner.IsOrganization() {
|
||||||
|
users, err := organization.GetUsersWhoCanCreateOrgRepo(ctx, newOwner.ID)
|
||||||
if newOwner.IsOrganization() {
|
if err != nil || len(users) == 0 {
|
||||||
users, err := organization.GetUsersWhoCanCreateOrgRepo(ctx, newOwner.ID)
|
return err
|
||||||
if err != nil || len(users) == 0 {
|
}
|
||||||
return err
|
for i := range users {
|
||||||
}
|
notify = append(notify, &Notification{
|
||||||
for i := range users {
|
UserID: users[i].ID,
|
||||||
notify = append(notify, &Notification{
|
RepoID: repo.ID,
|
||||||
UserID: users[i].ID,
|
Status: NotificationStatusUnread,
|
||||||
|
UpdatedBy: doer.ID,
|
||||||
|
Source: NotificationSourceRepository,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
notify = []*Notification{{
|
||||||
|
UserID: newOwner.ID,
|
||||||
RepoID: repo.ID,
|
RepoID: repo.ID,
|
||||||
Status: NotificationStatusUnread,
|
Status: NotificationStatusUnread,
|
||||||
UpdatedBy: doer.ID,
|
UpdatedBy: doer.ID,
|
||||||
Source: NotificationSourceRepository,
|
Source: NotificationSourceRepository,
|
||||||
})
|
}}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
notify = []*Notification{{
|
|
||||||
UserID: newOwner.ID,
|
|
||||||
RepoID: repo.ID,
|
|
||||||
Status: NotificationStatusUnread,
|
|
||||||
UpdatedBy: doer.ID,
|
|
||||||
Source: NotificationSourceRepository,
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := db.Insert(ctx, notify); err != nil {
|
return db.Insert(ctx, notify)
|
||||||
return err
|
})
|
||||||
}
|
|
||||||
|
|
||||||
return committer.Commit()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateOrUpdateIssueNotifications creates an issue notification
|
// CreateOrUpdateIssueNotifications creates an issue notification
|
||||||
// for each watcher, or updates it if already exists
|
// for each watcher, or updates it if already exists
|
||||||
// receiverID > 0 just send to receiver, else send to all watcher
|
// receiverID > 0 just send to receiver, else send to all watcher
|
||||||
func CreateOrUpdateIssueNotifications(issueID, commentID, notificationAuthorID, receiverID int64) error {
|
func CreateOrUpdateIssueNotifications(issueID, commentID, notificationAuthorID, receiverID int64) error {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -379,11 +371,7 @@ func CountUnread(ctx context.Context, userID int64) int64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// LoadAttributes load Repo Issue User and Comment if not loaded
|
// LoadAttributes load Repo Issue User and Comment if not loaded
|
||||||
func (n *Notification) LoadAttributes() (err error) {
|
func (n *Notification) LoadAttributes(ctx context.Context) (err error) {
|
||||||
return n.loadAttributes(db.DefaultContext)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n *Notification) loadAttributes(ctx context.Context) (err error) {
|
|
||||||
if err = n.loadRepo(ctx); err != nil {
|
if err = n.loadRepo(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -481,10 +469,10 @@ func (n *Notification) APIURL() string {
|
|||||||
type NotificationList []*Notification
|
type NotificationList []*Notification
|
||||||
|
|
||||||
// LoadAttributes load Repo Issue User and Comment if not loaded
|
// LoadAttributes load Repo Issue User and Comment if not loaded
|
||||||
func (nl NotificationList) LoadAttributes() error {
|
func (nl NotificationList) LoadAttributes(ctx context.Context) error {
|
||||||
var err error
|
var err error
|
||||||
for i := 0; i < len(nl); i++ {
|
for i := 0; i < len(nl); i++ {
|
||||||
err = nl[i].LoadAttributes()
|
err = nl[i].LoadAttributes(ctx)
|
||||||
if err != nil && !issues_model.IsErrCommentNotExist(err) {
|
if err != nil && !issues_model.IsErrCommentNotExist(err) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -504,7 +492,7 @@ func (nl NotificationList) getPendingRepoIDs() []int64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// LoadRepos loads repositories from database
|
// LoadRepos loads repositories from database
|
||||||
func (nl NotificationList) LoadRepos() (repo_model.RepositoryList, []int, error) {
|
func (nl NotificationList) LoadRepos(ctx context.Context) (repo_model.RepositoryList, []int, error) {
|
||||||
if len(nl) == 0 {
|
if len(nl) == 0 {
|
||||||
return repo_model.RepositoryList{}, []int{}, nil
|
return repo_model.RepositoryList{}, []int{}, nil
|
||||||
}
|
}
|
||||||
@ -517,7 +505,7 @@ func (nl NotificationList) LoadRepos() (repo_model.RepositoryList, []int, error)
|
|||||||
if left < limit {
|
if left < limit {
|
||||||
limit = left
|
limit = left
|
||||||
}
|
}
|
||||||
rows, err := db.GetEngine(db.DefaultContext).
|
rows, err := db.GetEngine(ctx).
|
||||||
In("id", repoIDs[:limit]).
|
In("id", repoIDs[:limit]).
|
||||||
Rows(new(repo_model.Repository))
|
Rows(new(repo_model.Repository))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -578,7 +566,7 @@ func (nl NotificationList) getPendingIssueIDs() []int64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// LoadIssues loads issues from database
|
// LoadIssues loads issues from database
|
||||||
func (nl NotificationList) LoadIssues() ([]int, error) {
|
func (nl NotificationList) LoadIssues(ctx context.Context) ([]int, error) {
|
||||||
if len(nl) == 0 {
|
if len(nl) == 0 {
|
||||||
return []int{}, nil
|
return []int{}, nil
|
||||||
}
|
}
|
||||||
@ -591,7 +579,7 @@ func (nl NotificationList) LoadIssues() ([]int, error) {
|
|||||||
if left < limit {
|
if left < limit {
|
||||||
limit = left
|
limit = left
|
||||||
}
|
}
|
||||||
rows, err := db.GetEngine(db.DefaultContext).
|
rows, err := db.GetEngine(ctx).
|
||||||
In("id", issueIDs[:limit]).
|
In("id", issueIDs[:limit]).
|
||||||
Rows(new(issues_model.Issue))
|
Rows(new(issues_model.Issue))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -662,7 +650,7 @@ func (nl NotificationList) getPendingCommentIDs() []int64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// LoadComments loads comments from database
|
// LoadComments loads comments from database
|
||||||
func (nl NotificationList) LoadComments() ([]int, error) {
|
func (nl NotificationList) LoadComments(ctx context.Context) ([]int, error) {
|
||||||
if len(nl) == 0 {
|
if len(nl) == 0 {
|
||||||
return []int{}, nil
|
return []int{}, nil
|
||||||
}
|
}
|
||||||
@ -675,7 +663,7 @@ func (nl NotificationList) LoadComments() ([]int, error) {
|
|||||||
if left < limit {
|
if left < limit {
|
||||||
limit = left
|
limit = left
|
||||||
}
|
}
|
||||||
rows, err := db.GetEngine(db.DefaultContext).
|
rows, err := db.GetEngine(ctx).
|
||||||
In("id", commentIDs[:limit]).
|
In("id", commentIDs[:limit]).
|
||||||
Rows(new(issues_model.Comment))
|
Rows(new(issues_model.Comment))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -775,8 +763,8 @@ func SetRepoReadBy(ctx context.Context, userID, repoID int64) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetNotificationStatus change the notification status
|
// SetNotificationStatus change the notification status
|
||||||
func SetNotificationStatus(notificationID int64, user *user_model.User, status NotificationStatus) (*Notification, error) {
|
func SetNotificationStatus(ctx context.Context, notificationID int64, user *user_model.User, status NotificationStatus) (*Notification, error) {
|
||||||
notification, err := getNotificationByID(db.DefaultContext, notificationID)
|
notification, err := GetNotificationByID(ctx, notificationID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return notification, err
|
return notification, err
|
||||||
}
|
}
|
||||||
@ -787,16 +775,12 @@ func SetNotificationStatus(notificationID int64, user *user_model.User, status N
|
|||||||
|
|
||||||
notification.Status = status
|
notification.Status = status
|
||||||
|
|
||||||
_, err = db.GetEngine(db.DefaultContext).ID(notificationID).Update(notification)
|
_, err = db.GetEngine(ctx).ID(notificationID).Update(notification)
|
||||||
return notification, err
|
return notification, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetNotificationByID return notification by ID
|
// GetNotificationByID return notification by ID
|
||||||
func GetNotificationByID(notificationID int64) (*Notification, error) {
|
func GetNotificationByID(ctx context.Context, notificationID int64) (*Notification, error) {
|
||||||
return getNotificationByID(db.DefaultContext, notificationID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getNotificationByID(ctx context.Context, notificationID int64) (*Notification, error) {
|
|
||||||
notification := new(Notification)
|
notification := new(Notification)
|
||||||
ok, err := db.GetEngine(ctx).
|
ok, err := db.GetEngine(ctx).
|
||||||
Where("id = ?", notificationID).
|
Where("id = ?", notificationID).
|
||||||
@ -813,9 +797,9 @@ func getNotificationByID(ctx context.Context, notificationID int64) (*Notificati
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateNotificationStatuses updates the statuses of all of a user's notifications that are of the currentStatus type to the desiredStatus
|
// UpdateNotificationStatuses updates the statuses of all of a user's notifications that are of the currentStatus type to the desiredStatus
|
||||||
func UpdateNotificationStatuses(user *user_model.User, currentStatus, desiredStatus NotificationStatus) error {
|
func UpdateNotificationStatuses(ctx context.Context, user *user_model.User, currentStatus, desiredStatus NotificationStatus) error {
|
||||||
n := &Notification{Status: desiredStatus, UpdatedBy: user.ID}
|
n := &Notification{Status: desiredStatus, UpdatedBy: user.ID}
|
||||||
_, err := db.GetEngine(db.DefaultContext).
|
_, err := db.GetEngine(ctx).
|
||||||
Where("user_id = ? AND status = ?", user.ID, currentStatus).
|
Where("user_id = ? AND status = ?", user.ID, currentStatus).
|
||||||
Cols("status", "updated_by", "updated_unix").
|
Cols("status", "updated_by", "updated_unix").
|
||||||
Update(n)
|
Update(n)
|
||||||
|
@ -82,14 +82,14 @@ func TestSetNotificationStatus(t *testing.T) {
|
|||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
notf := unittest.AssertExistsAndLoadBean(t,
|
notf := unittest.AssertExistsAndLoadBean(t,
|
||||||
&activities_model.Notification{UserID: user.ID, Status: activities_model.NotificationStatusRead})
|
&activities_model.Notification{UserID: user.ID, Status: activities_model.NotificationStatusRead})
|
||||||
_, err := activities_model.SetNotificationStatus(notf.ID, user, activities_model.NotificationStatusPinned)
|
_, err := activities_model.SetNotificationStatus(db.DefaultContext, notf.ID, user, activities_model.NotificationStatusPinned)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
unittest.AssertExistsAndLoadBean(t,
|
unittest.AssertExistsAndLoadBean(t,
|
||||||
&activities_model.Notification{ID: notf.ID, Status: activities_model.NotificationStatusPinned})
|
&activities_model.Notification{ID: notf.ID, Status: activities_model.NotificationStatusPinned})
|
||||||
|
|
||||||
_, err = activities_model.SetNotificationStatus(1, user, activities_model.NotificationStatusRead)
|
_, err = activities_model.SetNotificationStatus(db.DefaultContext, 1, user, activities_model.NotificationStatusRead)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
_, err = activities_model.SetNotificationStatus(unittest.NonexistentID, user, activities_model.NotificationStatusRead)
|
_, err = activities_model.SetNotificationStatus(db.DefaultContext, unittest.NonexistentID, user, activities_model.NotificationStatusRead)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,7 +102,7 @@ func TestUpdateNotificationStatuses(t *testing.T) {
|
|||||||
&activities_model.Notification{UserID: user.ID, Status: activities_model.NotificationStatusRead})
|
&activities_model.Notification{UserID: user.ID, Status: activities_model.NotificationStatusRead})
|
||||||
notfPinned := unittest.AssertExistsAndLoadBean(t,
|
notfPinned := unittest.AssertExistsAndLoadBean(t,
|
||||||
&activities_model.Notification{UserID: user.ID, Status: activities_model.NotificationStatusPinned})
|
&activities_model.Notification{UserID: user.ID, Status: activities_model.NotificationStatusPinned})
|
||||||
assert.NoError(t, activities_model.UpdateNotificationStatuses(user, activities_model.NotificationStatusUnread, activities_model.NotificationStatusRead))
|
assert.NoError(t, activities_model.UpdateNotificationStatuses(db.DefaultContext, user, activities_model.NotificationStatusUnread, activities_model.NotificationStatusRead))
|
||||||
unittest.AssertExistsAndLoadBean(t,
|
unittest.AssertExistsAndLoadBean(t,
|
||||||
&activities_model.Notification{ID: notfUnread.ID, Status: activities_model.NotificationStatusRead})
|
&activities_model.Notification{ID: notfUnread.ID, Status: activities_model.NotificationStatusRead})
|
||||||
unittest.AssertExistsAndLoadBean(t,
|
unittest.AssertExistsAndLoadBean(t,
|
||||||
|
@ -234,7 +234,7 @@ func DeleteGPGKey(doer *user_model.User, id int64) (err error) {
|
|||||||
return ErrGPGKeyAccessDenied{doer.ID, key.ID}
|
return ErrGPGKeyAccessDenied{doer.ID, key.ID}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ func AddGPGKey(ownerID int64, content, token, signature string) ([]*GPGKey, erro
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ import (
|
|||||||
|
|
||||||
// VerifyGPGKey marks a GPG key as verified
|
// VerifyGPGKey marks a GPG key as verified
|
||||||
func VerifyGPGKey(ownerID int64, keyID, token, signature string) (string, error) {
|
func VerifyGPGKey(ownerID int64, keyID, token, signature string) (string, error) {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ func AddPublicKey(ownerID int64, name, content string, authSourceID int64) (*Pub
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -321,7 +321,7 @@ func PublicKeyIsExternallyManaged(id int64) (bool, error) {
|
|||||||
// deleteKeysMarkedForDeletion returns true if ssh keys needs update
|
// deleteKeysMarkedForDeletion returns true if ssh keys needs update
|
||||||
func deleteKeysMarkedForDeletion(keys []string) (bool, error) {
|
func deleteKeysMarkedForDeletion(keys []string) (bool, error) {
|
||||||
// Start session
|
// Start session
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
@ -126,7 +126,7 @@ func AddDeployKey(repoID int64, name, content string, readOnly bool) (*DeployKey
|
|||||||
accessMode = perm.AccessModeWrite
|
accessMode = perm.AccessModeWrite
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ import (
|
|||||||
|
|
||||||
// AddPrincipalKey adds new principal to database and authorized_principals file.
|
// AddPrincipalKey adds new principal to database and authorized_principals file.
|
||||||
func AddPrincipalKey(ownerID int64, content string, authSourceID int64) (*PublicKey, error) {
|
func AddPrincipalKey(ownerID int64, content string, authSourceID int64) (*PublicKey, error) {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ import (
|
|||||||
|
|
||||||
// VerifySSHKey marks a SSH key as verified
|
// VerifySSHKey marks a SSH key as verified
|
||||||
func VerifySSHKey(ownerID int64, fingerprint, token, signature string) (string, error) {
|
func VerifySSHKey(ownerID int64, fingerprint, token, signature string) (string, error) {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -201,7 +201,7 @@ type UpdateOAuth2ApplicationOptions struct {
|
|||||||
|
|
||||||
// UpdateOAuth2Application updates an oauth2 application
|
// UpdateOAuth2Application updates an oauth2 application
|
||||||
func UpdateOAuth2Application(opts UpdateOAuth2ApplicationOptions) (*OAuth2Application, error) {
|
func UpdateOAuth2Application(opts UpdateOAuth2ApplicationOptions) (*OAuth2Application, error) {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -265,7 +265,7 @@ func deleteOAuth2Application(ctx context.Context, id, userid int64) error {
|
|||||||
|
|
||||||
// DeleteOAuth2Application deletes the application with the given id and the grants and auth codes related to it. It checks if the userid was the creator of the app.
|
// DeleteOAuth2Application deletes the application with the given id and the grants and auth codes related to it. It checks if the userid was the creator of the app.
|
||||||
func DeleteOAuth2Application(id, userid int64) error {
|
func DeleteOAuth2Application(id, userid int64) error {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ func ReadSession(key string) (*Session, error) {
|
|||||||
Key: key,
|
Key: key,
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -73,7 +73,7 @@ func DestroySession(key string) error {
|
|||||||
|
|
||||||
// RegenerateSession regenerates a session from the old id
|
// RegenerateSession regenerates a session from the old id
|
||||||
func RegenerateSession(oldKey, newKey string) (*Session, error) {
|
func RegenerateSession(oldKey, newKey string) (*Session, error) {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,7 @@ func saveEmailHash(email string) string {
|
|||||||
Hash: emailHash,
|
Hash: emailHash,
|
||||||
}
|
}
|
||||||
// OK we're going to open a session just because I think that that might hide away any problems with postgres reporting errors
|
// OK we're going to open a session just because I think that that might hide away any problems with postgres reporting errors
|
||||||
if err := db.WithTx(func(ctx context.Context) error {
|
if err := db.WithTx(db.DefaultContext, func(ctx context.Context) error {
|
||||||
has, err := db.GetEngine(ctx).Where("email = ? AND hash = ?", emailHash.Email, emailHash.Hash).Get(new(EmailHash))
|
has, err := db.GetEngine(ctx).Where("email = ? AND hash = ?", emailHash.Email, emailHash.Hash).Get(new(EmailHash))
|
||||||
if has || err != nil {
|
if has || err != nil {
|
||||||
// Seriously we don't care about any DB problems just return the lowerEmail - we expect the transaction to fail most of the time
|
// Seriously we don't care about any DB problems just return the lowerEmail - we expect the transaction to fail most of the time
|
||||||
@ -150,10 +150,11 @@ func generateEmailAvatarLink(email string, size int, final bool) string {
|
|||||||
return DefaultAvatarLink()
|
return DefaultAvatarLink()
|
||||||
}
|
}
|
||||||
|
|
||||||
enableFederatedAvatar, _ := system_model.GetSetting(system_model.KeyPictureEnableFederatedAvatar)
|
enableFederatedAvatarSetting, _ := system_model.GetSetting(system_model.KeyPictureEnableFederatedAvatar)
|
||||||
|
enableFederatedAvatar := enableFederatedAvatarSetting.GetValueBool()
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
if enableFederatedAvatar != nil && enableFederatedAvatar.GetValueBool() && system_model.LibravatarService != nil {
|
if enableFederatedAvatar && system_model.LibravatarService != nil {
|
||||||
emailHash := saveEmailHash(email)
|
emailHash := saveEmailHash(email)
|
||||||
if final {
|
if final {
|
||||||
// for final link, we can spend more time on slow external query
|
// for final link, we can spend more time on slow external query
|
||||||
@ -171,8 +172,10 @@ func generateEmailAvatarLink(email string, size int, final bool) string {
|
|||||||
return urlStr
|
return urlStr
|
||||||
}
|
}
|
||||||
|
|
||||||
disableGravatar, _ := system_model.GetSetting(system_model.KeyPictureDisableGravatar)
|
disableGravatarSetting, _ := system_model.GetSetting(system_model.KeyPictureDisableGravatar)
|
||||||
if disableGravatar != nil && !disableGravatar.GetValueBool() {
|
|
||||||
|
disableGravatar := disableGravatarSetting.GetValueBool()
|
||||||
|
if !disableGravatar {
|
||||||
// copy GravatarSourceURL, because we will modify its Path.
|
// copy GravatarSourceURL, because we will modify its Path.
|
||||||
avatarURLCopy := *system_model.GravatarSourceURL
|
avatarURLCopy := *system_model.GravatarSourceURL
|
||||||
avatarURLCopy.Path = path.Join(avatarURLCopy.Path, HashEmail(email))
|
avatarURLCopy.Path = path.Join(avatarURLCopy.Path, HashEmail(email))
|
||||||
|
@ -4,11 +4,16 @@
|
|||||||
|
|
||||||
package db
|
package db
|
||||||
|
|
||||||
import "xorm.io/builder"
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"xorm.io/builder"
|
||||||
|
)
|
||||||
|
|
||||||
// CountOrphanedObjects count subjects with have no existing refobject anymore
|
// CountOrphanedObjects count subjects with have no existing refobject anymore
|
||||||
func CountOrphanedObjects(subject, refobject, joinCond string) (int64, error) {
|
func CountOrphanedObjects(ctx context.Context, subject, refobject, joinCond string) (int64, error) {
|
||||||
return GetEngine(DefaultContext).Table("`"+subject+"`").
|
return GetEngine(ctx).
|
||||||
|
Table("`"+subject+"`").
|
||||||
Join("LEFT", "`"+refobject+"`", joinCond).
|
Join("LEFT", "`"+refobject+"`", joinCond).
|
||||||
Where(builder.IsNull{"`" + refobject + "`.id"}).
|
Where(builder.IsNull{"`" + refobject + "`.id"}).
|
||||||
Select("COUNT(`" + subject + "`.`id`)").
|
Select("COUNT(`" + subject + "`.`id`)").
|
||||||
@ -16,12 +21,12 @@ func CountOrphanedObjects(subject, refobject, joinCond string) (int64, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DeleteOrphanedObjects delete subjects with have no existing refobject anymore
|
// DeleteOrphanedObjects delete subjects with have no existing refobject anymore
|
||||||
func DeleteOrphanedObjects(subject, refobject, joinCond string) error {
|
func DeleteOrphanedObjects(ctx context.Context, subject, refobject, joinCond string) error {
|
||||||
subQuery := builder.Select("`"+subject+"`.id").
|
subQuery := builder.Select("`"+subject+"`.id").
|
||||||
From("`"+subject+"`").
|
From("`"+subject+"`").
|
||||||
Join("LEFT", "`"+refobject+"`", joinCond).
|
Join("LEFT", "`"+refobject+"`", joinCond).
|
||||||
Where(builder.IsNull{"`" + refobject + "`.id"})
|
Where(builder.IsNull{"`" + refobject + "`.id"})
|
||||||
b := builder.Delete(builder.In("id", subQuery)).From("`" + subject + "`")
|
b := builder.Delete(builder.In("id", subQuery)).From("`" + subject + "`")
|
||||||
_, err := GetEngine(DefaultContext).Exec(b)
|
_, err := GetEngine(ctx).Exec(b)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
|
||||||
|
"xorm.io/xorm"
|
||||||
"xorm.io/xorm/schemas"
|
"xorm.io/xorm/schemas"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -86,7 +87,11 @@ type Committer interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TxContext represents a transaction Context
|
// TxContext represents a transaction Context
|
||||||
func TxContext() (*Context, Committer, error) {
|
func TxContext(parentCtx context.Context) (*Context, Committer, error) {
|
||||||
|
if InTransaction(parentCtx) {
|
||||||
|
return nil, nil, ErrAlreadyInTransaction
|
||||||
|
}
|
||||||
|
|
||||||
sess := x.NewSession()
|
sess := x.NewSession()
|
||||||
if err := sess.Begin(); err != nil {
|
if err := sess.Begin(); err != nil {
|
||||||
sess.Close()
|
sess.Close()
|
||||||
@ -97,14 +102,24 @@ func TxContext() (*Context, Committer, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WithTx represents executing database operations on a transaction
|
// WithTx represents executing database operations on a transaction
|
||||||
// you can optionally change the context to a parent one
|
// This function will always open a new transaction, if a transaction exist in parentCtx return an error.
|
||||||
func WithTx(f func(ctx context.Context) error, stdCtx ...context.Context) error {
|
func WithTx(parentCtx context.Context, f func(ctx context.Context) error) error {
|
||||||
parentCtx := DefaultContext
|
if InTransaction(parentCtx) {
|
||||||
if len(stdCtx) != 0 && stdCtx[0] != nil {
|
return ErrAlreadyInTransaction
|
||||||
// TODO: make sure parent context has no open session
|
|
||||||
parentCtx = stdCtx[0]
|
|
||||||
}
|
}
|
||||||
|
return txWithNoCheck(parentCtx, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AutoTx represents executing database operations on a transaction, if the transaction exist,
|
||||||
|
// this function will reuse it otherwise will create a new one and close it when finished.
|
||||||
|
func AutoTx(parentCtx context.Context, f func(ctx context.Context) error) error {
|
||||||
|
if InTransaction(parentCtx) {
|
||||||
|
return f(newContext(parentCtx, GetEngine(parentCtx), true))
|
||||||
|
}
|
||||||
|
return txWithNoCheck(parentCtx, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
func txWithNoCheck(parentCtx context.Context, f func(ctx context.Context) error) error {
|
||||||
sess := x.NewSession()
|
sess := x.NewSession()
|
||||||
defer sess.Close()
|
defer sess.Close()
|
||||||
if err := sess.Begin(); err != nil {
|
if err := sess.Begin(); err != nil {
|
||||||
@ -180,3 +195,28 @@ func EstimateCount(ctx context.Context, bean interface{}) (int64, error) {
|
|||||||
}
|
}
|
||||||
return rows, err
|
return rows, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// InTransaction returns true if the engine is in a transaction otherwise return false
|
||||||
|
func InTransaction(ctx context.Context) bool {
|
||||||
|
var e Engine
|
||||||
|
if engined, ok := ctx.(Engined); ok {
|
||||||
|
e = engined.Engine()
|
||||||
|
} else {
|
||||||
|
enginedInterface := ctx.Value(enginedContextKey)
|
||||||
|
if enginedInterface != nil {
|
||||||
|
e = enginedInterface.(Engined).Engine()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if e == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
switch t := e.(type) {
|
||||||
|
case *xorm.Engine:
|
||||||
|
return false
|
||||||
|
case *xorm.Session:
|
||||||
|
return t.IsInTx()
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
33
models/db/context_test.go
Normal file
33
models/db/context_test.go
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package db_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestInTransaction(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
assert.False(t, db.InTransaction(db.DefaultContext))
|
||||||
|
assert.NoError(t, db.WithTx(db.DefaultContext, func(ctx context.Context) error {
|
||||||
|
assert.True(t, db.InTransaction(ctx))
|
||||||
|
return nil
|
||||||
|
}))
|
||||||
|
|
||||||
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
defer committer.Close()
|
||||||
|
assert.True(t, db.InTransaction(ctx))
|
||||||
|
assert.Error(t, db.WithTx(ctx, func(ctx context.Context) error {
|
||||||
|
assert.True(t, db.InTransaction(ctx))
|
||||||
|
return nil
|
||||||
|
}))
|
||||||
|
}
|
@ -41,11 +41,11 @@ func TestDeleteOrphanedObjects(t *testing.T) {
|
|||||||
_, err = db.GetEngine(db.DefaultContext).Insert(&issues_model.PullRequest{IssueID: 1000}, &issues_model.PullRequest{IssueID: 1001}, &issues_model.PullRequest{IssueID: 1003})
|
_, err = db.GetEngine(db.DefaultContext).Insert(&issues_model.PullRequest{IssueID: 1000}, &issues_model.PullRequest{IssueID: 1001}, &issues_model.PullRequest{IssueID: 1003})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
orphaned, err := db.CountOrphanedObjects("pull_request", "issue", "pull_request.issue_id=issue.id")
|
orphaned, err := db.CountOrphanedObjects(db.DefaultContext, "pull_request", "issue", "pull_request.issue_id=issue.id")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.EqualValues(t, 3, orphaned)
|
assert.EqualValues(t, 3, orphaned)
|
||||||
|
|
||||||
err = db.DeleteOrphanedObjects("pull_request", "issue", "pull_request.issue_id=issue.id")
|
err = db.DeleteOrphanedObjects(db.DefaultContext, "pull_request", "issue", "pull_request.issue_id=issue.id")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
countAfter, err := db.GetEngine(db.DefaultContext).Count(&issues_model.PullRequest{})
|
countAfter, err := db.GetEngine(db.DefaultContext).Count(&issues_model.PullRequest{})
|
||||||
|
@ -5,11 +5,14 @@
|
|||||||
package db
|
package db
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var ErrAlreadyInTransaction = errors.New("database connection has already been in a transaction")
|
||||||
|
|
||||||
// ErrCancelled represents an error due to context cancellation
|
// ErrCancelled represents an error due to context cancellation
|
||||||
type ErrCancelled struct {
|
type ErrCancelled struct {
|
||||||
Message string
|
Message string
|
||||||
|
@ -59,7 +59,7 @@ func TestSyncMaxResourceIndex(t *testing.T) {
|
|||||||
assert.EqualValues(t, 62, maxIndex)
|
assert.EqualValues(t, 62, maxIndex)
|
||||||
|
|
||||||
// commit transaction
|
// commit transaction
|
||||||
err = db.WithTx(func(ctx context.Context) error {
|
err = db.WithTx(db.DefaultContext, func(ctx context.Context) error {
|
||||||
err = db.SyncMaxResourceIndex(ctx, "test_index", 10, 73)
|
err = db.SyncMaxResourceIndex(ctx, "test_index", 10, 73)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
maxIndex, err = getCurrentResourceIndex(ctx, "test_index", 10)
|
maxIndex, err = getCurrentResourceIndex(ctx, "test_index", 10)
|
||||||
@ -73,7 +73,7 @@ func TestSyncMaxResourceIndex(t *testing.T) {
|
|||||||
assert.EqualValues(t, 73, maxIndex)
|
assert.EqualValues(t, 73, maxIndex)
|
||||||
|
|
||||||
// rollback transaction
|
// rollback transaction
|
||||||
err = db.WithTx(func(ctx context.Context) error {
|
err = db.WithTx(db.DefaultContext, func(ctx context.Context) error {
|
||||||
err = db.SyncMaxResourceIndex(ctx, "test_index", 10, 84)
|
err = db.SyncMaxResourceIndex(ctx, "test_index", 10, 84)
|
||||||
maxIndex, err = getCurrentResourceIndex(ctx, "test_index", 10)
|
maxIndex, err = getCurrentResourceIndex(ctx, "test_index", 10)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
@ -102,7 +102,7 @@ func TestGetNextResourceIndex(t *testing.T) {
|
|||||||
assert.EqualValues(t, 2, maxIndex)
|
assert.EqualValues(t, 2, maxIndex)
|
||||||
|
|
||||||
// commit transaction
|
// commit transaction
|
||||||
err = db.WithTx(func(ctx context.Context) error {
|
err = db.WithTx(db.DefaultContext, func(ctx context.Context) error {
|
||||||
maxIndex, err = db.GetNextResourceIndex(ctx, "test_index", 20)
|
maxIndex, err = db.GetNextResourceIndex(ctx, "test_index", 20)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.EqualValues(t, 3, maxIndex)
|
assert.EqualValues(t, 3, maxIndex)
|
||||||
@ -114,7 +114,7 @@ func TestGetNextResourceIndex(t *testing.T) {
|
|||||||
assert.EqualValues(t, 3, maxIndex)
|
assert.EqualValues(t, 3, maxIndex)
|
||||||
|
|
||||||
// rollback transaction
|
// rollback transaction
|
||||||
err = db.WithTx(func(ctx context.Context) error {
|
err = db.WithTx(db.DefaultContext, func(ctx context.Context) error {
|
||||||
maxIndex, err = db.GetNextResourceIndex(ctx, "test_index", 20)
|
maxIndex, err = db.GetNextResourceIndex(ctx, "test_index", 20)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.EqualValues(t, 4, maxIndex)
|
assert.EqualValues(t, 4, maxIndex)
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
package db
|
package db
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
@ -12,7 +13,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// CountBadSequences looks for broken sequences from recreate-table mistakes
|
// CountBadSequences looks for broken sequences from recreate-table mistakes
|
||||||
func CountBadSequences() (int64, error) {
|
func CountBadSequences(_ context.Context) (int64, error) {
|
||||||
if !setting.Database.UsePostgreSQL {
|
if !setting.Database.UsePostgreSQL {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
@ -33,7 +34,7 @@ func CountBadSequences() (int64, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FixBadSequences fixes for broken sequences from recreate-table mistakes
|
// FixBadSequences fixes for broken sequences from recreate-table mistakes
|
||||||
func FixBadSequences() error {
|
func FixBadSequences(_ context.Context) error {
|
||||||
if !setting.Database.UsePostgreSQL {
|
if !setting.Database.UsePostgreSQL {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ func GetYamlFixturesAccess() (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, repo := range repos {
|
for _, repo := range repos {
|
||||||
repo.MustOwner()
|
repo.MustOwner(db.DefaultContext)
|
||||||
if err := access_model.RecalculateAccesses(db.DefaultContext, repo); err != nil {
|
if err := access_model.RecalculateAccesses(db.DefaultContext, repo); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -544,7 +544,7 @@ func FindRenamedBranch(repoID int64, from string) (branch *RenamedBranch, exist
|
|||||||
|
|
||||||
// RenameBranch rename a branch
|
// RenameBranch rename a branch
|
||||||
func RenameBranch(repo *repo_model.Repository, from, to string, gitAction func(isDefault bool) error) (err error) {
|
func RenameBranch(repo *repo_model.Repository, from, to string, gitAction func(isDefault bool) error) (err error) {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -102,7 +102,7 @@ func TestRenameBranch(t *testing.T) {
|
|||||||
repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||||
_isDefault := false
|
_isDefault := false
|
||||||
|
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
defer committer.Close()
|
defer committer.Close()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NoError(t, git_model.UpdateProtectBranch(ctx, repo1, &git_model.ProtectedBranch{
|
assert.NoError(t, git_model.UpdateProtectBranch(ctx, repo1, &git_model.ProtectedBranch{
|
||||||
|
@ -94,7 +94,7 @@ func GetNextCommitStatusIndex(repoID int64, sha string) (int64, error) {
|
|||||||
|
|
||||||
// getNextCommitStatusIndex return the next index
|
// getNextCommitStatusIndex return the next index
|
||||||
func getNextCommitStatusIndex(repoID int64, sha string) (int64, error) {
|
func getNextCommitStatusIndex(repoID int64, sha string) (int64, error) {
|
||||||
ctx, commiter, err := db.TxContext()
|
ctx, commiter, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@ -297,7 +297,7 @@ func NewCommitStatus(opts NewCommitStatusOptions) error {
|
|||||||
return fmt.Errorf("generate commit status index failed: %w", err)
|
return fmt.Errorf("generate commit status index failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("NewCommitStatus[repo_id: %d, user_id: %d, sha: %s]: %w", opts.Repo.ID, opts.Creator.ID, opts.SHA, err)
|
return fmt.Errorf("NewCommitStatus[repo_id: %d, user_id: %d, sha: %s]: %w", opts.Repo.ID, opts.Creator.ID, opts.SHA, err)
|
||||||
}
|
}
|
||||||
|
@ -137,7 +137,7 @@ var ErrLFSObjectNotExist = db.ErrNotExist{Resource: "LFS Meta object"}
|
|||||||
func NewLFSMetaObject(m *LFSMetaObject) (*LFSMetaObject, error) {
|
func NewLFSMetaObject(m *LFSMetaObject) (*LFSMetaObject, error) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -185,7 +185,7 @@ func RemoveLFSMetaObjectByOid(repoID int64, oid string) (int64, error) {
|
|||||||
return 0, ErrLFSObjectNotExist
|
return 0, ErrLFSObjectNotExist
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@ -235,14 +235,14 @@ func LFSObjectAccessible(user *user_model.User, oid string) (bool, error) {
|
|||||||
return count > 0, err
|
return count > 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// LFSObjectIsAssociated checks if a provided Oid is associated
|
// ExistsLFSObject checks if a provided Oid exists within the DB
|
||||||
func LFSObjectIsAssociated(oid string) (bool, error) {
|
func ExistsLFSObject(ctx context.Context, oid string) (bool, error) {
|
||||||
return db.GetEngine(db.DefaultContext).Exist(&LFSMetaObject{Pointer: lfs.Pointer{Oid: oid}})
|
return db.GetEngine(ctx).Exist(&LFSMetaObject{Pointer: lfs.Pointer{Oid: oid}})
|
||||||
}
|
}
|
||||||
|
|
||||||
// LFSAutoAssociate auto associates accessible LFSMetaObjects
|
// LFSAutoAssociate auto associates accessible LFSMetaObjects
|
||||||
func LFSAutoAssociate(metas []*LFSMetaObject, user *user_model.User, repoID int64) error {
|
func LFSAutoAssociate(metas []*LFSMetaObject, user *user_model.User, repoID int64) error {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ func cleanPath(p string) string {
|
|||||||
|
|
||||||
// CreateLFSLock creates a new lock.
|
// CreateLFSLock creates a new lock.
|
||||||
func CreateLFSLock(repo *repo_model.Repository, lock *LFSLock) (*LFSLock, error) {
|
func CreateLFSLock(repo *repo_model.Repository, lock *LFSLock) (*LFSLock, error) {
|
||||||
dbCtx, committer, err := db.TxContext()
|
dbCtx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -137,7 +137,7 @@ func CountLFSLockByRepoID(repoID int64) (int64, error) {
|
|||||||
|
|
||||||
// DeleteLFSLockByID deletes a lock by given ID.
|
// DeleteLFSLockByID deletes a lock by given ID.
|
||||||
func DeleteLFSLockByID(id int64, repo *repo_model.Repository, u *user_model.User, force bool) (*LFSLock, error) {
|
func DeleteLFSLockByID(id int64, repo *repo_model.Repository, u *user_model.User, force bool) (*LFSLock, error) {
|
||||||
dbCtx, committer, err := db.TxContext()
|
dbCtx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
package git
|
package git
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -69,13 +70,13 @@ func UpdateProtectedTag(pt *ProtectedTag) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DeleteProtectedTag deletes a protected tag by ID
|
// DeleteProtectedTag deletes a protected tag by ID
|
||||||
func DeleteProtectedTag(pt *ProtectedTag) error {
|
func DeleteProtectedTag(ctx context.Context, pt *ProtectedTag) error {
|
||||||
_, err := db.GetEngine(db.DefaultContext).ID(pt.ID).Delete(&ProtectedTag{})
|
_, err := db.GetEngine(ctx).ID(pt.ID).Delete(&ProtectedTag{})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsUserAllowedModifyTag returns true if the user is allowed to modify the tag
|
// IsUserAllowedModifyTag returns true if the user is allowed to modify the tag
|
||||||
func IsUserAllowedModifyTag(pt *ProtectedTag, userID int64) (bool, error) {
|
func IsUserAllowedModifyTag(ctx context.Context, pt *ProtectedTag, userID int64) (bool, error) {
|
||||||
if base.Int64sContains(pt.AllowlistUserIDs, userID) {
|
if base.Int64sContains(pt.AllowlistUserIDs, userID) {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
@ -84,7 +85,7 @@ func IsUserAllowedModifyTag(pt *ProtectedTag, userID int64) (bool, error) {
|
|||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
in, err := organization.IsUserInTeams(db.DefaultContext, userID, pt.AllowlistTeamIDs)
|
in, err := organization.IsUserInTeams(ctx, userID, pt.AllowlistTeamIDs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
@ -92,9 +93,9 @@ func IsUserAllowedModifyTag(pt *ProtectedTag, userID int64) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetProtectedTags gets all protected tags of the repository
|
// GetProtectedTags gets all protected tags of the repository
|
||||||
func GetProtectedTags(repoID int64) ([]*ProtectedTag, error) {
|
func GetProtectedTags(ctx context.Context, repoID int64) ([]*ProtectedTag, error) {
|
||||||
tags := make([]*ProtectedTag, 0)
|
tags := make([]*ProtectedTag, 0)
|
||||||
return tags, db.GetEngine(db.DefaultContext).Find(&tags, &ProtectedTag{RepoID: repoID})
|
return tags, db.GetEngine(ctx).Find(&tags, &ProtectedTag{RepoID: repoID})
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetProtectedTagByID gets the protected tag with the specific id
|
// GetProtectedTagByID gets the protected tag with the specific id
|
||||||
@ -112,7 +113,7 @@ func GetProtectedTagByID(id int64) (*ProtectedTag, error) {
|
|||||||
|
|
||||||
// IsUserAllowedToControlTag checks if a user can control the specific tag.
|
// IsUserAllowedToControlTag checks if a user can control the specific tag.
|
||||||
// It returns true if the tag name is not protected or the user is allowed to control it.
|
// It returns true if the tag name is not protected or the user is allowed to control it.
|
||||||
func IsUserAllowedToControlTag(tags []*ProtectedTag, tagName string, userID int64) (bool, error) {
|
func IsUserAllowedToControlTag(ctx context.Context, tags []*ProtectedTag, tagName string, userID int64) (bool, error) {
|
||||||
isAllowed := true
|
isAllowed := true
|
||||||
for _, tag := range tags {
|
for _, tag := range tags {
|
||||||
err := tag.EnsureCompiledPattern()
|
err := tag.EnsureCompiledPattern()
|
||||||
@ -124,7 +125,7 @@ func IsUserAllowedToControlTag(tags []*ProtectedTag, tagName string, userID int6
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
isAllowed, err = IsUserAllowedModifyTag(tag, userID)
|
isAllowed, err = IsUserAllowedModifyTag(ctx, tag, userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ package git_test
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
git_model "code.gitea.io/gitea/models/git"
|
git_model "code.gitea.io/gitea/models/git"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
|
||||||
@ -17,29 +18,29 @@ func TestIsUserAllowed(t *testing.T) {
|
|||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
pt := &git_model.ProtectedTag{}
|
pt := &git_model.ProtectedTag{}
|
||||||
allowed, err := git_model.IsUserAllowedModifyTag(pt, 1)
|
allowed, err := git_model.IsUserAllowedModifyTag(db.DefaultContext, pt, 1)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.False(t, allowed)
|
assert.False(t, allowed)
|
||||||
|
|
||||||
pt = &git_model.ProtectedTag{
|
pt = &git_model.ProtectedTag{
|
||||||
AllowlistUserIDs: []int64{1},
|
AllowlistUserIDs: []int64{1},
|
||||||
}
|
}
|
||||||
allowed, err = git_model.IsUserAllowedModifyTag(pt, 1)
|
allowed, err = git_model.IsUserAllowedModifyTag(db.DefaultContext, pt, 1)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.True(t, allowed)
|
assert.True(t, allowed)
|
||||||
|
|
||||||
allowed, err = git_model.IsUserAllowedModifyTag(pt, 2)
|
allowed, err = git_model.IsUserAllowedModifyTag(db.DefaultContext, pt, 2)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.False(t, allowed)
|
assert.False(t, allowed)
|
||||||
|
|
||||||
pt = &git_model.ProtectedTag{
|
pt = &git_model.ProtectedTag{
|
||||||
AllowlistTeamIDs: []int64{1},
|
AllowlistTeamIDs: []int64{1},
|
||||||
}
|
}
|
||||||
allowed, err = git_model.IsUserAllowedModifyTag(pt, 1)
|
allowed, err = git_model.IsUserAllowedModifyTag(db.DefaultContext, pt, 1)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.False(t, allowed)
|
assert.False(t, allowed)
|
||||||
|
|
||||||
allowed, err = git_model.IsUserAllowedModifyTag(pt, 2)
|
allowed, err = git_model.IsUserAllowedModifyTag(db.DefaultContext, pt, 2)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.True(t, allowed)
|
assert.True(t, allowed)
|
||||||
|
|
||||||
@ -47,11 +48,11 @@ func TestIsUserAllowed(t *testing.T) {
|
|||||||
AllowlistUserIDs: []int64{1},
|
AllowlistUserIDs: []int64{1},
|
||||||
AllowlistTeamIDs: []int64{1},
|
AllowlistTeamIDs: []int64{1},
|
||||||
}
|
}
|
||||||
allowed, err = git_model.IsUserAllowedModifyTag(pt, 1)
|
allowed, err = git_model.IsUserAllowedModifyTag(db.DefaultContext, pt, 1)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.True(t, allowed)
|
assert.True(t, allowed)
|
||||||
|
|
||||||
allowed, err = git_model.IsUserAllowedModifyTag(pt, 2)
|
allowed, err = git_model.IsUserAllowedModifyTag(db.DefaultContext, pt, 2)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.True(t, allowed)
|
assert.True(t, allowed)
|
||||||
}
|
}
|
||||||
@ -135,7 +136,7 @@ func TestIsUserAllowedToControlTag(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for n, c := range cases {
|
for n, c := range cases {
|
||||||
isAllowed, err := git_model.IsUserAllowedToControlTag(protectedTags, c.name, c.userid)
|
isAllowed, err := git_model.IsUserAllowedToControlTag(db.DefaultContext, protectedTags, c.name, c.userid)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, c.allowed, isAllowed, "case %d: error should match", n)
|
assert.Equal(t, c.allowed, isAllowed, "case %d: error should match", n)
|
||||||
}
|
}
|
||||||
@ -157,7 +158,7 @@ func TestIsUserAllowedToControlTag(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for n, c := range cases {
|
for n, c := range cases {
|
||||||
isAllowed, err := git_model.IsUserAllowedToControlTag(protectedTags, c.name, c.userid)
|
isAllowed, err := git_model.IsUserAllowedToControlTag(db.DefaultContext, protectedTags, c.name, c.userid)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, c.allowed, isAllowed, "case %d: error should match", n)
|
assert.Equal(t, c.allowed, isAllowed, "case %d: error should match", n)
|
||||||
}
|
}
|
||||||
|
@ -48,9 +48,10 @@ func (issue *Issue) LoadAssignees(ctx context.Context) (err error) {
|
|||||||
// GetAssigneeIDsByIssue returns the IDs of users assigned to an issue
|
// GetAssigneeIDsByIssue returns the IDs of users assigned to an issue
|
||||||
// but skips joining with `user` for performance reasons.
|
// but skips joining with `user` for performance reasons.
|
||||||
// User permissions must be verified elsewhere if required.
|
// User permissions must be verified elsewhere if required.
|
||||||
func GetAssigneeIDsByIssue(issueID int64) ([]int64, error) {
|
func GetAssigneeIDsByIssue(ctx context.Context, issueID int64) ([]int64, error) {
|
||||||
userIDs := make([]int64, 0, 5)
|
userIDs := make([]int64, 0, 5)
|
||||||
return userIDs, db.GetEngine(db.DefaultContext).Table("issue_assignees").
|
return userIDs, db.GetEngine(ctx).
|
||||||
|
Table("issue_assignees").
|
||||||
Cols("assignee_id").
|
Cols("assignee_id").
|
||||||
Where("issue_id = ?", issueID).
|
Where("issue_id = ?", issueID).
|
||||||
Distinct("assignee_id").
|
Distinct("assignee_id").
|
||||||
@ -64,7 +65,7 @@ func IsUserAssignedToIssue(ctx context.Context, issue *Issue, user *user_model.U
|
|||||||
|
|
||||||
// ToggleIssueAssignee changes a user between assigned and not assigned for this issue, and make issue comment for it.
|
// ToggleIssueAssignee changes a user between assigned and not assigned for this issue, and make issue comment for it.
|
||||||
func ToggleIssueAssignee(issue *Issue, doer *user_model.User, assigneeID int64) (removed bool, comment *Comment, err error) {
|
func ToggleIssueAssignee(issue *Issue, doer *user_model.User, assigneeID int64) (removed bool, comment *Comment, err error) {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, nil, err
|
return false, nil, err
|
||||||
}
|
}
|
||||||
@ -151,7 +152,7 @@ func toggleUserAssignee(ctx context.Context, issue *Issue, assigneeID int64) (re
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MakeIDsFromAPIAssigneesToAdd returns an array with all assignee IDs
|
// MakeIDsFromAPIAssigneesToAdd returns an array with all assignee IDs
|
||||||
func MakeIDsFromAPIAssigneesToAdd(oneAssignee string, multipleAssignees []string) (assigneeIDs []int64, err error) {
|
func MakeIDsFromAPIAssigneesToAdd(ctx context.Context, oneAssignee string, multipleAssignees []string) (assigneeIDs []int64, err error) {
|
||||||
var requestAssignees []string
|
var requestAssignees []string
|
||||||
|
|
||||||
// Keeping the old assigning method for compatibility reasons
|
// Keeping the old assigning method for compatibility reasons
|
||||||
@ -165,7 +166,7 @@ func MakeIDsFromAPIAssigneesToAdd(oneAssignee string, multipleAssignees []string
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the IDs of all assignees
|
// Get the IDs of all assignees
|
||||||
assigneeIDs, err = user_model.GetUserIDsByNames(requestAssignees, false)
|
assigneeIDs, err = user_model.GetUserIDsByNames(ctx, requestAssignees, false)
|
||||||
|
|
||||||
return assigneeIDs, err
|
return assigneeIDs, err
|
||||||
}
|
}
|
||||||
|
@ -71,22 +71,22 @@ func TestMakeIDsFromAPIAssigneesToAdd(t *testing.T) {
|
|||||||
_ = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
_ = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||||
_ = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
_ = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
|
|
||||||
IDs, err := issues_model.MakeIDsFromAPIAssigneesToAdd("", []string{""})
|
IDs, err := issues_model.MakeIDsFromAPIAssigneesToAdd(db.DefaultContext, "", []string{""})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, []int64{}, IDs)
|
assert.Equal(t, []int64{}, IDs)
|
||||||
|
|
||||||
_, err = issues_model.MakeIDsFromAPIAssigneesToAdd("", []string{"none_existing_user"})
|
_, err = issues_model.MakeIDsFromAPIAssigneesToAdd(db.DefaultContext, "", []string{"none_existing_user"})
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
IDs, err = issues_model.MakeIDsFromAPIAssigneesToAdd("user1", []string{"user1"})
|
IDs, err = issues_model.MakeIDsFromAPIAssigneesToAdd(db.DefaultContext, "user1", []string{"user1"})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, []int64{1}, IDs)
|
assert.Equal(t, []int64{1}, IDs)
|
||||||
|
|
||||||
IDs, err = issues_model.MakeIDsFromAPIAssigneesToAdd("user2", []string{""})
|
IDs, err = issues_model.MakeIDsFromAPIAssigneesToAdd(db.DefaultContext, "user2", []string{""})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, []int64{2}, IDs)
|
assert.Equal(t, []int64{2}, IDs)
|
||||||
|
|
||||||
IDs, err = issues_model.MakeIDsFromAPIAssigneesToAdd("", []string{"user1", "user2"})
|
IDs, err = issues_model.MakeIDsFromAPIAssigneesToAdd(db.DefaultContext, "", []string{"user1", "user2"})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, []int64{1, 2}, IDs)
|
assert.Equal(t, []int64{1, 2}, IDs)
|
||||||
}
|
}
|
||||||
|
@ -309,13 +309,8 @@ type PushActionContent struct {
|
|||||||
CommitIDs []string `json:"commit_ids"`
|
CommitIDs []string `json:"commit_ids"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadIssue loads issue from database
|
// LoadIssue loads the issue reference for the comment
|
||||||
func (c *Comment) LoadIssue() (err error) {
|
func (c *Comment) LoadIssue(ctx context.Context) (err error) {
|
||||||
return c.LoadIssueCtx(db.DefaultContext)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadIssueCtx loads issue from database
|
|
||||||
func (c *Comment) LoadIssueCtx(ctx context.Context) (err error) {
|
|
||||||
if c.Issue != nil {
|
if c.Issue != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -350,7 +345,8 @@ func (c *Comment) AfterLoad(session *xorm.Session) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Comment) loadPoster(ctx context.Context) (err error) {
|
// LoadPoster loads comment poster
|
||||||
|
func (c *Comment) LoadPoster(ctx context.Context) (err error) {
|
||||||
if c.PosterID <= 0 || c.Poster != nil {
|
if c.PosterID <= 0 || c.Poster != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -381,7 +377,7 @@ func (c *Comment) AfterDelete() {
|
|||||||
|
|
||||||
// HTMLURL formats a URL-string to the issue-comment
|
// HTMLURL formats a URL-string to the issue-comment
|
||||||
func (c *Comment) HTMLURL() string {
|
func (c *Comment) HTMLURL() string {
|
||||||
err := c.LoadIssue()
|
err := c.LoadIssue(db.DefaultContext)
|
||||||
if err != nil { // Silently dropping errors :unamused:
|
if err != nil { // Silently dropping errors :unamused:
|
||||||
log.Error("LoadIssue(%d): %v", c.IssueID, err)
|
log.Error("LoadIssue(%d): %v", c.IssueID, err)
|
||||||
return ""
|
return ""
|
||||||
@ -410,7 +406,7 @@ func (c *Comment) HTMLURL() string {
|
|||||||
|
|
||||||
// APIURL formats a API-string to the issue-comment
|
// APIURL formats a API-string to the issue-comment
|
||||||
func (c *Comment) APIURL() string {
|
func (c *Comment) APIURL() string {
|
||||||
err := c.LoadIssue()
|
err := c.LoadIssue(db.DefaultContext)
|
||||||
if err != nil { // Silently dropping errors :unamused:
|
if err != nil { // Silently dropping errors :unamused:
|
||||||
log.Error("LoadIssue(%d): %v", c.IssueID, err)
|
log.Error("LoadIssue(%d): %v", c.IssueID, err)
|
||||||
return ""
|
return ""
|
||||||
@ -426,7 +422,7 @@ func (c *Comment) APIURL() string {
|
|||||||
|
|
||||||
// IssueURL formats a URL-string to the issue
|
// IssueURL formats a URL-string to the issue
|
||||||
func (c *Comment) IssueURL() string {
|
func (c *Comment) IssueURL() string {
|
||||||
err := c.LoadIssue()
|
err := c.LoadIssue(db.DefaultContext)
|
||||||
if err != nil { // Silently dropping errors :unamused:
|
if err != nil { // Silently dropping errors :unamused:
|
||||||
log.Error("LoadIssue(%d): %v", c.IssueID, err)
|
log.Error("LoadIssue(%d): %v", c.IssueID, err)
|
||||||
return ""
|
return ""
|
||||||
@ -446,7 +442,7 @@ func (c *Comment) IssueURL() string {
|
|||||||
|
|
||||||
// PRURL formats a URL-string to the pull-request
|
// PRURL formats a URL-string to the pull-request
|
||||||
func (c *Comment) PRURL() string {
|
func (c *Comment) PRURL() string {
|
||||||
err := c.LoadIssue()
|
err := c.LoadIssue(db.DefaultContext)
|
||||||
if err != nil { // Silently dropping errors :unamused:
|
if err != nil { // Silently dropping errors :unamused:
|
||||||
log.Error("LoadIssue(%d): %v", c.IssueID, err)
|
log.Error("LoadIssue(%d): %v", c.IssueID, err)
|
||||||
return ""
|
return ""
|
||||||
@ -521,10 +517,10 @@ func (c *Comment) LoadProject() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// LoadMilestone if comment.Type is CommentTypeMilestone, then load milestone
|
// LoadMilestone if comment.Type is CommentTypeMilestone, then load milestone
|
||||||
func (c *Comment) LoadMilestone() error {
|
func (c *Comment) LoadMilestone(ctx context.Context) error {
|
||||||
if c.OldMilestoneID > 0 {
|
if c.OldMilestoneID > 0 {
|
||||||
var oldMilestone Milestone
|
var oldMilestone Milestone
|
||||||
has, err := db.GetEngine(db.DefaultContext).ID(c.OldMilestoneID).Get(&oldMilestone)
|
has, err := db.GetEngine(ctx).ID(c.OldMilestoneID).Get(&oldMilestone)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
} else if has {
|
} else if has {
|
||||||
@ -534,7 +530,7 @@ func (c *Comment) LoadMilestone() error {
|
|||||||
|
|
||||||
if c.MilestoneID > 0 {
|
if c.MilestoneID > 0 {
|
||||||
var milestone Milestone
|
var milestone Milestone
|
||||||
has, err := db.GetEngine(db.DefaultContext).ID(c.MilestoneID).Get(&milestone)
|
has, err := db.GetEngine(ctx).ID(c.MilestoneID).Get(&milestone)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
} else if has {
|
} else if has {
|
||||||
@ -544,19 +540,14 @@ func (c *Comment) LoadMilestone() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadPoster loads comment poster
|
|
||||||
func (c *Comment) LoadPoster() error {
|
|
||||||
return c.loadPoster(db.DefaultContext)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadAttachments loads attachments (it never returns error, the error during `GetAttachmentsByCommentIDCtx` is ignored)
|
// LoadAttachments loads attachments (it never returns error, the error during `GetAttachmentsByCommentIDCtx` is ignored)
|
||||||
func (c *Comment) LoadAttachments() error {
|
func (c *Comment) LoadAttachments(ctx context.Context) error {
|
||||||
if len(c.Attachments) > 0 {
|
if len(c.Attachments) > 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
c.Attachments, err = repo_model.GetAttachmentsByCommentID(db.DefaultContext, c.ID)
|
c.Attachments, err = repo_model.GetAttachmentsByCommentID(ctx, c.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("getAttachmentsByCommentID[%d]: %v", c.ID, err)
|
log.Error("getAttachmentsByCommentID[%d]: %v", c.ID, err)
|
||||||
}
|
}
|
||||||
@ -565,7 +556,7 @@ func (c *Comment) LoadAttachments() error {
|
|||||||
|
|
||||||
// UpdateAttachments update attachments by UUIDs for the comment
|
// UpdateAttachments update attachments by UUIDs for the comment
|
||||||
func (c *Comment) UpdateAttachments(uuids []string) error {
|
func (c *Comment) UpdateAttachments(uuids []string) error {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -598,7 +589,7 @@ func (c *Comment) LoadAssigneeUserAndTeam() error {
|
|||||||
c.Assignee = user_model.NewGhostUser()
|
c.Assignee = user_model.NewGhostUser()
|
||||||
}
|
}
|
||||||
} else if c.AssigneeTeamID > 0 && c.AssigneeTeam == nil {
|
} else if c.AssigneeTeamID > 0 && c.AssigneeTeam == nil {
|
||||||
if err = c.LoadIssue(); err != nil {
|
if err = c.LoadIssue(db.DefaultContext); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -740,7 +731,7 @@ func (c *Comment) UnsignedLine() uint64 {
|
|||||||
|
|
||||||
// CodeCommentURL returns the url to a comment in code
|
// CodeCommentURL returns the url to a comment in code
|
||||||
func (c *Comment) CodeCommentURL() string {
|
func (c *Comment) CodeCommentURL() string {
|
||||||
err := c.LoadIssue()
|
err := c.LoadIssue(db.DefaultContext)
|
||||||
if err != nil { // Silently dropping errors :unamused:
|
if err != nil { // Silently dropping errors :unamused:
|
||||||
log.Error("LoadIssue(%d): %v", c.IssueID, err)
|
log.Error("LoadIssue(%d): %v", c.IssueID, err)
|
||||||
return ""
|
return ""
|
||||||
@ -1003,7 +994,7 @@ type CreateCommentOptions struct {
|
|||||||
|
|
||||||
// CreateComment creates comment of issue or commit.
|
// CreateComment creates comment of issue or commit.
|
||||||
func CreateComment(opts *CreateCommentOptions) (comment *Comment, err error) {
|
func CreateComment(opts *CreateCommentOptions) (comment *Comment, err error) {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -1135,7 +1126,7 @@ func CountComments(opts *FindCommentsOptions) (int64, error) {
|
|||||||
|
|
||||||
// UpdateComment updates information of comment.
|
// UpdateComment updates information of comment.
|
||||||
func UpdateComment(c *Comment, doer *user_model.User) error {
|
func UpdateComment(c *Comment, doer *user_model.User) error {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -1145,7 +1136,7 @@ func UpdateComment(c *Comment, doer *user_model.User) error {
|
|||||||
if _, err := sess.ID(c.ID).AllCols().Update(c); err != nil {
|
if _, err := sess.ID(c.ID).AllCols().Update(c); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := c.LoadIssueCtx(ctx); err != nil {
|
if err := c.LoadIssue(ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := c.AddCrossReferences(ctx, doer, true); err != nil {
|
if err := c.AddCrossReferences(ctx, doer, true); err != nil {
|
||||||
@ -1245,7 +1236,7 @@ func findCodeComments(ctx context.Context, opts FindCommentsOptions, issue *Issu
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := CommentList(comments).loadPosters(ctx); err != nil {
|
if err := CommentList(comments).LoadPosters(ctx); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1363,11 +1354,11 @@ func CreateAutoMergeComment(ctx context.Context, typ CommentType, pr *PullReques
|
|||||||
if typ != CommentTypePRScheduledToAutoMerge && typ != CommentTypePRUnScheduledToAutoMerge {
|
if typ != CommentTypePRScheduledToAutoMerge && typ != CommentTypePRUnScheduledToAutoMerge {
|
||||||
return nil, fmt.Errorf("comment type %d cannot be used to create an auto merge comment", typ)
|
return nil, fmt.Errorf("comment type %d cannot be used to create an auto merge comment", typ)
|
||||||
}
|
}
|
||||||
if err = pr.LoadIssueCtx(ctx); err != nil {
|
if err = pr.LoadIssue(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = pr.LoadBaseRepoCtx(ctx); err != nil {
|
if err = pr.LoadBaseRepo(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1512,18 +1503,18 @@ func (c *Comment) GetExternalName() string { return c.OriginalAuthor }
|
|||||||
func (c *Comment) GetExternalID() int64 { return c.OriginalAuthorID }
|
func (c *Comment) GetExternalID() int64 { return c.OriginalAuthorID }
|
||||||
|
|
||||||
// CountCommentTypeLabelWithEmptyLabel count label comments with empty label
|
// CountCommentTypeLabelWithEmptyLabel count label comments with empty label
|
||||||
func CountCommentTypeLabelWithEmptyLabel() (int64, error) {
|
func CountCommentTypeLabelWithEmptyLabel(ctx context.Context) (int64, error) {
|
||||||
return db.GetEngine(db.DefaultContext).Where(builder.Eq{"type": CommentTypeLabel, "label_id": 0}).Count(new(Comment))
|
return db.GetEngine(ctx).Where(builder.Eq{"type": CommentTypeLabel, "label_id": 0}).Count(new(Comment))
|
||||||
}
|
}
|
||||||
|
|
||||||
// FixCommentTypeLabelWithEmptyLabel count label comments with empty label
|
// FixCommentTypeLabelWithEmptyLabel count label comments with empty label
|
||||||
func FixCommentTypeLabelWithEmptyLabel() (int64, error) {
|
func FixCommentTypeLabelWithEmptyLabel(ctx context.Context) (int64, error) {
|
||||||
return db.GetEngine(db.DefaultContext).Where(builder.Eq{"type": CommentTypeLabel, "label_id": 0}).Delete(new(Comment))
|
return db.GetEngine(ctx).Where(builder.Eq{"type": CommentTypeLabel, "label_id": 0}).Delete(new(Comment))
|
||||||
}
|
}
|
||||||
|
|
||||||
// CountCommentTypeLabelWithOutsideLabels count label comments with outside label
|
// CountCommentTypeLabelWithOutsideLabels count label comments with outside label
|
||||||
func CountCommentTypeLabelWithOutsideLabels() (int64, error) {
|
func CountCommentTypeLabelWithOutsideLabels(ctx context.Context) (int64, error) {
|
||||||
return db.GetEngine(db.DefaultContext).Where("comment.type = ? AND ((label.org_id = 0 AND issue.repo_id != label.repo_id) OR (label.repo_id = 0 AND label.org_id != repository.owner_id))", CommentTypeLabel).
|
return db.GetEngine(ctx).Where("comment.type = ? AND ((label.org_id = 0 AND issue.repo_id != label.repo_id) OR (label.repo_id = 0 AND label.org_id != repository.owner_id))", CommentTypeLabel).
|
||||||
Table("comment").
|
Table("comment").
|
||||||
Join("inner", "label", "label.id = comment.label_id").
|
Join("inner", "label", "label.id = comment.label_id").
|
||||||
Join("inner", "issue", "issue.id = comment.issue_id ").
|
Join("inner", "issue", "issue.id = comment.issue_id ").
|
||||||
@ -1532,8 +1523,8 @@ func CountCommentTypeLabelWithOutsideLabels() (int64, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FixCommentTypeLabelWithOutsideLabels count label comments with outside label
|
// FixCommentTypeLabelWithOutsideLabels count label comments with outside label
|
||||||
func FixCommentTypeLabelWithOutsideLabels() (int64, error) {
|
func FixCommentTypeLabelWithOutsideLabels(ctx context.Context) (int64, error) {
|
||||||
res, err := db.GetEngine(db.DefaultContext).Exec(`DELETE FROM comment WHERE comment.id IN (
|
res, err := db.GetEngine(ctx).Exec(`DELETE FROM comment WHERE comment.id IN (
|
||||||
SELECT il_too.id FROM (
|
SELECT il_too.id FROM (
|
||||||
SELECT com.id
|
SELECT com.id
|
||||||
FROM comment AS com
|
FROM comment AS com
|
||||||
|
@ -24,7 +24,8 @@ func (comments CommentList) getPosterIDs() []int64 {
|
|||||||
return posterIDs.Values()
|
return posterIDs.Values()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (comments CommentList) loadPosters(ctx context.Context) error {
|
// LoadPosters loads posters
|
||||||
|
func (comments CommentList) LoadPosters(ctx context.Context) error {
|
||||||
if len(comments) == 0 {
|
if len(comments) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -277,7 +278,8 @@ func (comments CommentList) Issues() IssueList {
|
|||||||
return issueList
|
return issueList
|
||||||
}
|
}
|
||||||
|
|
||||||
func (comments CommentList) loadIssues(ctx context.Context) error {
|
// LoadIssues loads issues of comments
|
||||||
|
func (comments CommentList) LoadIssues(ctx context.Context) error {
|
||||||
if len(comments) == 0 {
|
if len(comments) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -382,7 +384,8 @@ func (comments CommentList) loadDependentIssues(ctx context.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (comments CommentList) loadAttachments(ctx context.Context) (err error) {
|
// LoadAttachments loads attachments
|
||||||
|
func (comments CommentList) LoadAttachments(ctx context.Context) (err error) {
|
||||||
if len(comments) == 0 {
|
if len(comments) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -476,7 +479,7 @@ func (comments CommentList) loadReviews(ctx context.Context) error { //nolint
|
|||||||
|
|
||||||
// loadAttributes loads all attributes
|
// loadAttributes loads all attributes
|
||||||
func (comments CommentList) loadAttributes(ctx context.Context) (err error) {
|
func (comments CommentList) loadAttributes(ctx context.Context) (err error) {
|
||||||
if err = comments.loadPosters(ctx); err != nil {
|
if err = comments.LoadPosters(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -496,7 +499,7 @@ func (comments CommentList) loadAttributes(ctx context.Context) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = comments.loadAttachments(ctx); err != nil {
|
if err = comments.LoadAttachments(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -504,7 +507,7 @@ func (comments CommentList) loadAttributes(ctx context.Context) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = comments.loadIssues(ctx); err != nil {
|
if err = comments.LoadIssues(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -520,18 +523,3 @@ func (comments CommentList) loadAttributes(ctx context.Context) (err error) {
|
|||||||
func (comments CommentList) LoadAttributes() error {
|
func (comments CommentList) LoadAttributes() error {
|
||||||
return comments.loadAttributes(db.DefaultContext)
|
return comments.loadAttributes(db.DefaultContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadAttachments loads attachments
|
|
||||||
func (comments CommentList) LoadAttachments() error {
|
|
||||||
return comments.loadAttachments(db.DefaultContext)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadPosters loads posters
|
|
||||||
func (comments CommentList) LoadPosters() error {
|
|
||||||
return comments.loadPosters(db.DefaultContext)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadIssues loads issues of comments
|
|
||||||
func (comments CommentList) LoadIssues() error {
|
|
||||||
return comments.loadIssues(db.DefaultContext)
|
|
||||||
}
|
|
||||||
|
@ -129,7 +129,7 @@ const (
|
|||||||
|
|
||||||
// CreateIssueDependency creates a new dependency for an issue
|
// CreateIssueDependency creates a new dependency for an issue
|
||||||
func CreateIssueDependency(user *user_model.User, issue, dep *Issue) error {
|
func CreateIssueDependency(user *user_model.User, issue, dep *Issue) error {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -170,7 +170,7 @@ func CreateIssueDependency(user *user_model.User, issue, dep *Issue) error {
|
|||||||
|
|
||||||
// RemoveIssueDependency removes a dependency from an issue
|
// RemoveIssueDependency removes a dependency from an issue
|
||||||
func RemoveIssueDependency(user *user_model.User, issue, dep *Issue, depType DependencyType) (err error) {
|
func RemoveIssueDependency(user *user_model.User, issue, dep *Issue, depType DependencyType) (err error) {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -241,11 +241,7 @@ func (issue *Issue) LoadLabels(ctx context.Context) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// LoadPoster loads poster
|
// LoadPoster loads poster
|
||||||
func (issue *Issue) LoadPoster() error {
|
func (issue *Issue) LoadPoster(ctx context.Context) (err error) {
|
||||||
return issue.loadPoster(db.DefaultContext)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (issue *Issue) loadPoster(ctx context.Context) (err error) {
|
|
||||||
if issue.Poster == nil {
|
if issue.Poster == nil {
|
||||||
issue.Poster, err = user_model.GetUserByIDCtx(ctx, issue.PosterID)
|
issue.Poster, err = user_model.GetUserByIDCtx(ctx, issue.PosterID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -261,7 +257,8 @@ func (issue *Issue) loadPoster(ctx context.Context) (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (issue *Issue) loadPullRequest(ctx context.Context) (err error) {
|
// LoadPullRequest loads pull request info
|
||||||
|
func (issue *Issue) LoadPullRequest(ctx context.Context) (err error) {
|
||||||
if issue.IsPull && issue.PullRequest == nil {
|
if issue.IsPull && issue.PullRequest == nil {
|
||||||
issue.PullRequest, err = GetPullRequestByIssueID(ctx, issue.ID)
|
issue.PullRequest, err = GetPullRequestByIssueID(ctx, issue.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -275,18 +272,13 @@ func (issue *Issue) loadPullRequest(ctx context.Context) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadPullRequest loads pull request info
|
|
||||||
func (issue *Issue) LoadPullRequest() error {
|
|
||||||
return issue.loadPullRequest(db.DefaultContext)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (issue *Issue) loadComments(ctx context.Context) (err error) {
|
func (issue *Issue) loadComments(ctx context.Context) (err error) {
|
||||||
return issue.loadCommentsByType(ctx, CommentTypeUnknown)
|
return issue.loadCommentsByType(ctx, CommentTypeUnknown)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadDiscussComments loads discuss comments
|
// LoadDiscussComments loads discuss comments
|
||||||
func (issue *Issue) LoadDiscussComments() error {
|
func (issue *Issue) LoadDiscussComments(ctx context.Context) error {
|
||||||
return issue.loadCommentsByType(db.DefaultContext, CommentTypeComment)
|
return issue.loadCommentsByType(ctx, CommentTypeComment)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (issue *Issue) loadCommentsByType(ctx context.Context, tp CommentType) (err error) {
|
func (issue *Issue) loadCommentsByType(ctx context.Context, tp CommentType) (err error) {
|
||||||
@ -357,7 +349,8 @@ func (issue *Issue) loadForeignReference(ctx context.Context) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (issue *Issue) loadMilestone(ctx context.Context) (err error) {
|
// LoadMilestone load milestone of this issue.
|
||||||
|
func (issue *Issue) LoadMilestone(ctx context.Context) (err error) {
|
||||||
if (issue.Milestone == nil || issue.Milestone.ID != issue.MilestoneID) && issue.MilestoneID > 0 {
|
if (issue.Milestone == nil || issue.Milestone.ID != issue.MilestoneID) && issue.MilestoneID > 0 {
|
||||||
issue.Milestone, err = GetMilestoneByRepoID(ctx, issue.RepoID, issue.MilestoneID)
|
issue.Milestone, err = GetMilestoneByRepoID(ctx, issue.RepoID, issue.MilestoneID)
|
||||||
if err != nil && !IsErrMilestoneNotExist(err) {
|
if err != nil && !IsErrMilestoneNotExist(err) {
|
||||||
@ -373,7 +366,7 @@ func (issue *Issue) LoadAttributes(ctx context.Context) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = issue.loadPoster(ctx); err != nil {
|
if err = issue.LoadPoster(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -381,7 +374,7 @@ func (issue *Issue) LoadAttributes(ctx context.Context) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = issue.loadMilestone(ctx); err != nil {
|
if err = issue.LoadMilestone(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -393,7 +386,7 @@ func (issue *Issue) LoadAttributes(ctx context.Context) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = issue.loadPullRequest(ctx); err != nil && !IsErrPullRequestNotExist(err) {
|
if err = issue.LoadPullRequest(ctx); err != nil && !IsErrPullRequestNotExist(err) {
|
||||||
// It is possible pull request is not yet created.
|
// It is possible pull request is not yet created.
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -425,11 +418,6 @@ func (issue *Issue) LoadAttributes(ctx context.Context) (err error) {
|
|||||||
return issue.loadReactions(ctx)
|
return issue.loadReactions(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadMilestone load milestone of this issue.
|
|
||||||
func (issue *Issue) LoadMilestone() error {
|
|
||||||
return issue.loadMilestone(db.DefaultContext)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetIsRead load the `IsRead` field of the issue
|
// GetIsRead load the `IsRead` field of the issue
|
||||||
func (issue *Issue) GetIsRead(userID int64) error {
|
func (issue *Issue) GetIsRead(userID int64) error {
|
||||||
issueUser := &IssueUser{IssueID: issue.ID, UID: userID}
|
issueUser := &IssueUser{IssueID: issue.ID, UID: userID}
|
||||||
@ -540,7 +528,7 @@ func clearIssueLabels(ctx context.Context, issue *Issue, doer *user_model.User)
|
|||||||
// ClearIssueLabels removes all issue labels as the given user.
|
// ClearIssueLabels removes all issue labels as the given user.
|
||||||
// Triggers appropriate WebHooks, if any.
|
// Triggers appropriate WebHooks, if any.
|
||||||
func ClearIssueLabels(issue *Issue, doer *user_model.User) (err error) {
|
func ClearIssueLabels(issue *Issue, doer *user_model.User) (err error) {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -548,7 +536,7 @@ func ClearIssueLabels(issue *Issue, doer *user_model.User) (err error) {
|
|||||||
|
|
||||||
if err := issue.LoadRepo(ctx); err != nil {
|
if err := issue.LoadRepo(ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if err = issue.loadPullRequest(ctx); err != nil {
|
} else if err = issue.LoadPullRequest(ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -588,7 +576,7 @@ func (ts labelSorter) Swap(i, j int) {
|
|||||||
// ReplaceIssueLabels removes all current labels and add new labels to the issue.
|
// ReplaceIssueLabels removes all current labels and add new labels to the issue.
|
||||||
// Triggers appropriate WebHooks, if any.
|
// Triggers appropriate WebHooks, if any.
|
||||||
func ReplaceIssueLabels(issue *Issue, labels []*Label, doer *user_model.User) (err error) {
|
func ReplaceIssueLabels(issue *Issue, labels []*Label, doer *user_model.User) (err error) {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -751,7 +739,7 @@ func ChangeIssueStatus(ctx context.Context, issue *Issue, doer *user_model.User,
|
|||||||
if err := issue.LoadRepo(ctx); err != nil {
|
if err := issue.LoadRepo(ctx); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := issue.loadPoster(ctx); err != nil {
|
if err := issue.LoadPoster(ctx); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -760,7 +748,7 @@ func ChangeIssueStatus(ctx context.Context, issue *Issue, doer *user_model.User,
|
|||||||
|
|
||||||
// ChangeIssueTitle changes the title of this issue, as the given user.
|
// ChangeIssueTitle changes the title of this issue, as the given user.
|
||||||
func ChangeIssueTitle(issue *Issue, doer *user_model.User, oldTitle string) (err error) {
|
func ChangeIssueTitle(issue *Issue, doer *user_model.User, oldTitle string) (err error) {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -794,7 +782,7 @@ func ChangeIssueTitle(issue *Issue, doer *user_model.User, oldTitle string) (err
|
|||||||
|
|
||||||
// ChangeIssueRef changes the branch of this issue, as the given user.
|
// ChangeIssueRef changes the branch of this issue, as the given user.
|
||||||
func ChangeIssueRef(issue *Issue, doer *user_model.User, oldRef string) (err error) {
|
func ChangeIssueRef(issue *Issue, doer *user_model.User, oldRef string) (err error) {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -844,7 +832,7 @@ func AddDeletePRBranchComment(ctx context.Context, doer *user_model.User, repo *
|
|||||||
|
|
||||||
// UpdateIssueAttachments update attachments by UUIDs for the issue
|
// UpdateIssueAttachments update attachments by UUIDs for the issue
|
||||||
func UpdateIssueAttachments(issueID int64, uuids []string) (err error) {
|
func UpdateIssueAttachments(issueID int64, uuids []string) (err error) {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -864,7 +852,7 @@ func UpdateIssueAttachments(issueID int64, uuids []string) (err error) {
|
|||||||
|
|
||||||
// ChangeIssueContent changes issue content, as the given user.
|
// ChangeIssueContent changes issue content, as the given user.
|
||||||
func ChangeIssueContent(issue *Issue, doer *user_model.User, content string) (err error) {
|
func ChangeIssueContent(issue *Issue, doer *user_model.User, content string) (err error) {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -1027,7 +1015,7 @@ func NewIssueWithIndex(ctx context.Context, doer *user_model.User, opts NewIssue
|
|||||||
return fmt.Errorf("find all labels [label_ids: %v]: %w", opts.LabelIDs, err)
|
return fmt.Errorf("find all labels [label_ids: %v]: %w", opts.LabelIDs, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = opts.Issue.loadPoster(ctx); err != nil {
|
if err = opts.Issue.LoadPoster(ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1069,7 +1057,7 @@ func NewIssueWithIndex(ctx context.Context, doer *user_model.User, opts NewIssue
|
|||||||
|
|
||||||
// NewIssue creates new issue with labels for repository.
|
// NewIssue creates new issue with labels for repository.
|
||||||
func NewIssue(repo *repo_model.Repository, issue *Issue, labelIDs []int64, uuids []string) (err error) {
|
func NewIssue(repo *repo_model.Repository, issue *Issue, labelIDs []int64, uuids []string) (err error) {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -1505,10 +1493,9 @@ func applySubscribedCondition(sess *xorm.Session, subscriberID int64) *xorm.Sess
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CountIssuesByRepo map from repoID to number of issues matching the options
|
// CountIssuesByRepo map from repoID to number of issues matching the options
|
||||||
func CountIssuesByRepo(opts *IssuesOptions) (map[int64]int64, error) {
|
func CountIssuesByRepo(ctx context.Context, opts *IssuesOptions) (map[int64]int64, error) {
|
||||||
e := db.GetEngine(db.DefaultContext)
|
sess := db.GetEngine(ctx).
|
||||||
|
Join("INNER", "repository", "`issue`.repo_id = `repository`.id")
|
||||||
sess := e.Join("INNER", "repository", "`issue`.repo_id = `repository`.id")
|
|
||||||
|
|
||||||
opts.setupSessionNoLimit(sess)
|
opts.setupSessionNoLimit(sess)
|
||||||
|
|
||||||
@ -1551,10 +1538,9 @@ func GetRepoIDsForIssuesOptions(opts *IssuesOptions, user *user_model.User) ([]i
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Issues returns a list of issues by given conditions.
|
// Issues returns a list of issues by given conditions.
|
||||||
func Issues(opts *IssuesOptions) ([]*Issue, error) {
|
func Issues(ctx context.Context, opts *IssuesOptions) ([]*Issue, error) {
|
||||||
e := db.GetEngine(db.DefaultContext)
|
sess := db.GetEngine(ctx).
|
||||||
|
Join("INNER", "repository", "`issue`.repo_id = `repository`.id")
|
||||||
sess := e.Join("INNER", "repository", "`issue`.repo_id = `repository`.id")
|
|
||||||
opts.setupSessionWithLimit(sess)
|
opts.setupSessionWithLimit(sess)
|
||||||
|
|
||||||
sortIssuesSession(sess, opts.SortType, opts.PriorityRepoID)
|
sortIssuesSession(sess, opts.SortType, opts.PriorityRepoID)
|
||||||
@ -1572,11 +1558,11 @@ func Issues(opts *IssuesOptions) ([]*Issue, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CountIssues number return of issues by given conditions.
|
// CountIssues number return of issues by given conditions.
|
||||||
func CountIssues(opts *IssuesOptions) (int64, error) {
|
func CountIssues(ctx context.Context, opts *IssuesOptions) (int64, error) {
|
||||||
e := db.GetEngine(db.DefaultContext)
|
sess := db.GetEngine(ctx).
|
||||||
|
Select("COUNT(issue.id) AS count").
|
||||||
sess := e.Select("COUNT(issue.id) AS count").Table("issue")
|
Table("issue").
|
||||||
sess.Join("INNER", "repository", "`issue`.repo_id = `repository`.id")
|
Join("INNER", "repository", "`issue`.repo_id = `repository`.id")
|
||||||
opts.setupSessionNoLimit(sess)
|
opts.setupSessionNoLimit(sess)
|
||||||
|
|
||||||
return sess.Count()
|
return sess.Count()
|
||||||
@ -1585,9 +1571,10 @@ func CountIssues(opts *IssuesOptions) (int64, error) {
|
|||||||
// GetParticipantsIDsByIssueID returns the IDs of all users who participated in comments of an issue,
|
// GetParticipantsIDsByIssueID returns the IDs of all users who participated in comments of an issue,
|
||||||
// but skips joining with `user` for performance reasons.
|
// but skips joining with `user` for performance reasons.
|
||||||
// User permissions must be verified elsewhere if required.
|
// User permissions must be verified elsewhere if required.
|
||||||
func GetParticipantsIDsByIssueID(issueID int64) ([]int64, error) {
|
func GetParticipantsIDsByIssueID(ctx context.Context, issueID int64) ([]int64, error) {
|
||||||
userIDs := make([]int64, 0, 5)
|
userIDs := make([]int64, 0, 5)
|
||||||
return userIDs, db.GetEngine(db.DefaultContext).Table("comment").
|
return userIDs, db.GetEngine(ctx).
|
||||||
|
Table("comment").
|
||||||
Cols("poster_id").
|
Cols("poster_id").
|
||||||
Where("issue_id = ?", issueID).
|
Where("issue_id = ?", issueID).
|
||||||
And("type in (?,?,?)", CommentTypeComment, CommentTypeCode, CommentTypeReview).
|
And("type in (?,?,?)", CommentTypeComment, CommentTypeCode, CommentTypeReview).
|
||||||
@ -1986,7 +1973,7 @@ func SearchIssueIDsByKeyword(ctx context.Context, kw string, repoIDs []int64, li
|
|||||||
// If the issue status is changed a statusChangeComment is returned
|
// If the issue status is changed a statusChangeComment is returned
|
||||||
// similarly if the title is changed the titleChanged bool is set to true
|
// similarly if the title is changed the titleChanged bool is set to true
|
||||||
func UpdateIssueByAPI(issue *Issue, doer *user_model.User) (statusChangeComment *Comment, titleChanged bool, err error) {
|
func UpdateIssueByAPI(issue *Issue, doer *user_model.User) (statusChangeComment *Comment, titleChanged bool, err error) {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
@ -2044,7 +2031,7 @@ func UpdateIssueDeadline(issue *Issue, deadlineUnix timeutil.TimeStamp, doer *us
|
|||||||
if issue.DeadlineUnix == deadlineUnix {
|
if issue.DeadlineUnix == deadlineUnix {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -2426,8 +2413,9 @@ func (issue *Issue) GetExternalName() string { return issue.OriginalAuthor }
|
|||||||
func (issue *Issue) GetExternalID() int64 { return issue.OriginalAuthorID }
|
func (issue *Issue) GetExternalID() int64 { return issue.OriginalAuthorID }
|
||||||
|
|
||||||
// CountOrphanedIssues count issues without a repo
|
// CountOrphanedIssues count issues without a repo
|
||||||
func CountOrphanedIssues() (int64, error) {
|
func CountOrphanedIssues(ctx context.Context) (int64, error) {
|
||||||
return db.GetEngine(db.DefaultContext).Table("issue").
|
return db.GetEngine(ctx).
|
||||||
|
Table("issue").
|
||||||
Join("LEFT", "repository", "issue.repo_id=repository.id").
|
Join("LEFT", "repository", "issue.repo_id=repository.id").
|
||||||
Where(builder.IsNull{"repository.id"}).
|
Where(builder.IsNull{"repository.id"}).
|
||||||
Select("COUNT(`issue`.`id`)").
|
Select("COUNT(`issue`.`id`)").
|
||||||
@ -2435,35 +2423,31 @@ func CountOrphanedIssues() (int64, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DeleteOrphanedIssues delete issues without a repo
|
// DeleteOrphanedIssues delete issues without a repo
|
||||||
func DeleteOrphanedIssues() error {
|
func DeleteOrphanedIssues(ctx context.Context) error {
|
||||||
ctx, committer, err := db.TxContext()
|
var attachmentPaths []string
|
||||||
|
err := db.AutoTx(ctx, func(ctx context.Context) error {
|
||||||
|
var ids []int64
|
||||||
|
|
||||||
|
if err := db.GetEngine(ctx).Table("issue").Distinct("issue.repo_id").
|
||||||
|
Join("LEFT", "repository", "issue.repo_id=repository.id").
|
||||||
|
Where(builder.IsNull{"repository.id"}).GroupBy("issue.repo_id").
|
||||||
|
Find(&ids); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range ids {
|
||||||
|
paths, err := DeleteIssuesByRepoID(ctx, ids[i])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
attachmentPaths = append(attachmentPaths, paths...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer committer.Close()
|
|
||||||
|
|
||||||
var ids []int64
|
|
||||||
|
|
||||||
if err := db.GetEngine(ctx).Table("issue").Distinct("issue.repo_id").
|
|
||||||
Join("LEFT", "repository", "issue.repo_id=repository.id").
|
|
||||||
Where(builder.IsNull{"repository.id"}).GroupBy("issue.repo_id").
|
|
||||||
Find(&ids); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var attachmentPaths []string
|
|
||||||
for i := range ids {
|
|
||||||
paths, err := DeleteIssuesByRepoID(ctx, ids[i])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
attachmentPaths = append(attachmentPaths, paths...)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := committer.Commit(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
committer.Close()
|
|
||||||
|
|
||||||
// Remove issue attachment files.
|
// Remove issue attachment files.
|
||||||
for i := range attachmentPaths {
|
for i := range attachmentPaths {
|
||||||
|
@ -9,7 +9,7 @@ import "code.gitea.io/gitea/models/db"
|
|||||||
// RecalculateIssueIndexForRepo create issue_index for repo if not exist and
|
// RecalculateIssueIndexForRepo create issue_index for repo if not exist and
|
||||||
// update it based on highest index of existing issues assigned to a repo
|
// update it based on highest index of existing issues assigned to a repo
|
||||||
func RecalculateIssueIndexForRepo(repoID int64) error {
|
func RecalculateIssueIndexForRepo(repoID int64) error {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,8 @@ func (issues IssueList) getRepoIDs() []int64 {
|
|||||||
return repoIDs.Values()
|
return repoIDs.Values()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (issues IssueList) loadRepositories(ctx context.Context) ([]*repo_model.Repository, error) {
|
// LoadRepositories loads issues' all repositories
|
||||||
|
func (issues IssueList) LoadRepositories(ctx context.Context) ([]*repo_model.Repository, error) {
|
||||||
if len(issues) == 0 {
|
if len(issues) == 0 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
@ -73,11 +74,6 @@ func (issues IssueList) loadRepositories(ctx context.Context) ([]*repo_model.Rep
|
|||||||
return repo_model.ValuesRepository(repoMaps), nil
|
return repo_model.ValuesRepository(repoMaps), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadRepositories loads issues' all repositories
|
|
||||||
func (issues IssueList) LoadRepositories() ([]*repo_model.Repository, error) {
|
|
||||||
return issues.loadRepositories(db.DefaultContext)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (issues IssueList) getPosterIDs() []int64 {
|
func (issues IssueList) getPosterIDs() []int64 {
|
||||||
posterIDs := make(container.Set[int64], len(issues))
|
posterIDs := make(container.Set[int64], len(issues))
|
||||||
for _, issue := range issues {
|
for _, issue := range issues {
|
||||||
@ -317,7 +313,8 @@ func (issues IssueList) getPullIssueIDs() []int64 {
|
|||||||
return ids
|
return ids
|
||||||
}
|
}
|
||||||
|
|
||||||
func (issues IssueList) loadPullRequests(ctx context.Context) error {
|
// LoadPullRequests loads pull requests
|
||||||
|
func (issues IssueList) LoadPullRequests(ctx context.Context) error {
|
||||||
issuesIDs := issues.getPullIssueIDs()
|
issuesIDs := issues.getPullIssueIDs()
|
||||||
if len(issuesIDs) == 0 {
|
if len(issuesIDs) == 0 {
|
||||||
return nil
|
return nil
|
||||||
@ -361,7 +358,8 @@ func (issues IssueList) loadPullRequests(ctx context.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (issues IssueList) loadAttachments(ctx context.Context) (err error) {
|
// LoadAttachments loads attachments
|
||||||
|
func (issues IssueList) LoadAttachments(ctx context.Context) (err error) {
|
||||||
if len(issues) == 0 {
|
if len(issues) == 0 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -513,8 +511,8 @@ func (issues IssueList) loadTotalTrackedTimes(ctx context.Context) (err error) {
|
|||||||
|
|
||||||
// loadAttributes loads all attributes, expect for attachments and comments
|
// loadAttributes loads all attributes, expect for attachments and comments
|
||||||
func (issues IssueList) loadAttributes(ctx context.Context) error {
|
func (issues IssueList) loadAttributes(ctx context.Context) error {
|
||||||
if _, err := issues.loadRepositories(ctx); err != nil {
|
if _, err := issues.LoadRepositories(ctx); err != nil {
|
||||||
return fmt.Errorf("issue.loadAttributes: loadRepositories: %w", err)
|
return fmt.Errorf("issue.loadAttributes: LoadRepositories: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := issues.loadPosters(ctx); err != nil {
|
if err := issues.loadPosters(ctx); err != nil {
|
||||||
@ -537,7 +535,7 @@ func (issues IssueList) loadAttributes(ctx context.Context) error {
|
|||||||
return fmt.Errorf("issue.loadAttributes: loadAssignees: %w", err)
|
return fmt.Errorf("issue.loadAttributes: loadAssignees: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := issues.loadPullRequests(ctx); err != nil {
|
if err := issues.LoadPullRequests(ctx); err != nil {
|
||||||
return fmt.Errorf("issue.loadAttributes: loadPullRequests: %w", err)
|
return fmt.Errorf("issue.loadAttributes: loadPullRequests: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -554,24 +552,14 @@ func (issues IssueList) LoadAttributes() error {
|
|||||||
return issues.loadAttributes(db.DefaultContext)
|
return issues.loadAttributes(db.DefaultContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadAttachments loads attachments
|
|
||||||
func (issues IssueList) LoadAttachments() error {
|
|
||||||
return issues.loadAttachments(db.DefaultContext)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadComments loads comments
|
// LoadComments loads comments
|
||||||
func (issues IssueList) LoadComments() error {
|
func (issues IssueList) LoadComments(ctx context.Context) error {
|
||||||
return issues.loadComments(db.DefaultContext, builder.NewCond())
|
return issues.loadComments(ctx, builder.NewCond())
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadDiscussComments loads discuss comments
|
// LoadDiscussComments loads discuss comments
|
||||||
func (issues IssueList) LoadDiscussComments() error {
|
func (issues IssueList) LoadDiscussComments(ctx context.Context) error {
|
||||||
return issues.loadComments(db.DefaultContext, builder.Eq{"comment.type": CommentTypeComment})
|
return issues.loadComments(ctx, builder.Eq{"comment.type": CommentTypeComment})
|
||||||
}
|
|
||||||
|
|
||||||
// LoadPullRequests loads pull requests
|
|
||||||
func (issues IssueList) LoadPullRequests() error {
|
|
||||||
return issues.loadPullRequests(db.DefaultContext)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetApprovalCounts returns a map of issue ID to slice of approval counts
|
// GetApprovalCounts returns a map of issue ID to slice of approval counts
|
||||||
|
@ -7,6 +7,7 @@ package issues_test
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
issues_model "code.gitea.io/gitea/models/issues"
|
issues_model "code.gitea.io/gitea/models/issues"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
@ -23,7 +24,7 @@ func TestIssueList_LoadRepositories(t *testing.T) {
|
|||||||
unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 4}),
|
unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 4}),
|
||||||
}
|
}
|
||||||
|
|
||||||
repos, err := issueList.LoadRepositories()
|
repos, err := issueList.LoadRepositories(db.DefaultContext)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Len(t, repos, 2)
|
assert.Len(t, repos, 2)
|
||||||
for _, issue := range issueList {
|
for _, issue := range issueList {
|
||||||
|
@ -40,7 +40,7 @@ func updateIssueLock(opts *IssueLockOptions, lock bool) error {
|
|||||||
commentType = CommentTypeUnlock
|
commentType = CommentTypeUnlock
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -61,11 +61,11 @@ func (issue *Issue) projectBoardID(ctx context.Context) int64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// LoadIssuesFromBoard load issues assigned to this board
|
// LoadIssuesFromBoard load issues assigned to this board
|
||||||
func LoadIssuesFromBoard(b *project_model.Board) (IssueList, error) {
|
func LoadIssuesFromBoard(ctx context.Context, b *project_model.Board) (IssueList, error) {
|
||||||
issueList := make([]*Issue, 0, 10)
|
issueList := make([]*Issue, 0, 10)
|
||||||
|
|
||||||
if b.ID != 0 {
|
if b.ID != 0 {
|
||||||
issues, err := Issues(&IssuesOptions{
|
issues, err := Issues(ctx, &IssuesOptions{
|
||||||
ProjectBoardID: b.ID,
|
ProjectBoardID: b.ID,
|
||||||
ProjectID: b.ProjectID,
|
ProjectID: b.ProjectID,
|
||||||
SortType: "project-column-sorting",
|
SortType: "project-column-sorting",
|
||||||
@ -77,7 +77,7 @@ func LoadIssuesFromBoard(b *project_model.Board) (IssueList, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if b.Default {
|
if b.Default {
|
||||||
issues, err := Issues(&IssuesOptions{
|
issues, err := Issues(ctx, &IssuesOptions{
|
||||||
ProjectBoardID: -1, // Issues without ProjectBoardID
|
ProjectBoardID: -1, // Issues without ProjectBoardID
|
||||||
ProjectID: b.ProjectID,
|
ProjectID: b.ProjectID,
|
||||||
SortType: "project-column-sorting",
|
SortType: "project-column-sorting",
|
||||||
@ -88,7 +88,7 @@ func LoadIssuesFromBoard(b *project_model.Board) (IssueList, error) {
|
|||||||
issueList = append(issueList, issues...)
|
issueList = append(issueList, issues...)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := IssueList(issueList).LoadComments(); err != nil {
|
if err := IssueList(issueList).LoadComments(ctx); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,10 +96,10 @@ func LoadIssuesFromBoard(b *project_model.Board) (IssueList, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// LoadIssuesFromBoardList load issues assigned to the boards
|
// LoadIssuesFromBoardList load issues assigned to the boards
|
||||||
func LoadIssuesFromBoardList(bs project_model.BoardList) (map[int64]IssueList, error) {
|
func LoadIssuesFromBoardList(ctx context.Context, bs project_model.BoardList) (map[int64]IssueList, error) {
|
||||||
issuesMap := make(map[int64]IssueList, len(bs))
|
issuesMap := make(map[int64]IssueList, len(bs))
|
||||||
for i := range bs {
|
for i := range bs {
|
||||||
il, err := LoadIssuesFromBoard(bs[i])
|
il, err := LoadIssuesFromBoard(ctx, bs[i])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -110,7 +110,7 @@ func LoadIssuesFromBoardList(bs project_model.BoardList) (map[int64]IssueList, e
|
|||||||
|
|
||||||
// ChangeProjectAssign changes the project associated with an issue
|
// ChangeProjectAssign changes the project associated with an issue
|
||||||
func ChangeProjectAssign(issue *Issue, doer *user_model.User, newProjectID int64) error {
|
func ChangeProjectAssign(issue *Issue, doer *user_model.User, newProjectID int64) error {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -166,7 +166,7 @@ func addUpdateIssueProject(ctx context.Context, issue *Issue, doer *user_model.U
|
|||||||
|
|
||||||
// MoveIssueAcrossProjectBoards move a card from one board to another
|
// MoveIssueAcrossProjectBoards move a card from one board to another
|
||||||
func MoveIssueAcrossProjectBoards(issue *Issue, board *project_model.Board) error {
|
func MoveIssueAcrossProjectBoards(issue *Issue, board *project_model.Board) error {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -189,7 +189,7 @@ func TestIssues(t *testing.T) {
|
|||||||
[]int64{}, // issues with **both** label 1 and 2, none of these issues matches, TODO: add more tests
|
[]int64{}, // issues with **both** label 1 and 2, none of these issues matches, TODO: add more tests
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
issues, err := issues_model.Issues(&test.Opts)
|
issues, err := issues_model.Issues(db.DefaultContext, &test.Opts)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
if assert.Len(t, issues, len(test.ExpectedIssueIDs)) {
|
if assert.Len(t, issues, len(test.ExpectedIssueIDs)) {
|
||||||
for i, issue := range issues {
|
for i, issue := range issues {
|
||||||
@ -556,7 +556,7 @@ func TestLoadTotalTrackedTime(t *testing.T) {
|
|||||||
|
|
||||||
func TestCountIssues(t *testing.T) {
|
func TestCountIssues(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
count, err := issues_model.CountIssues(&issues_model.IssuesOptions{})
|
count, err := issues_model.CountIssues(db.DefaultContext, &issues_model.IssuesOptions{})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.EqualValues(t, 17, count)
|
assert.EqualValues(t, 17, count)
|
||||||
}
|
}
|
||||||
|
@ -235,7 +235,7 @@ func (c *Comment) AddCrossReferences(stdCtx context.Context, doer *user_model.Us
|
|||||||
if c.Type != CommentTypeCode && c.Type != CommentTypeComment {
|
if c.Type != CommentTypeCode && c.Type != CommentTypeComment {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if err := c.LoadIssueCtx(stdCtx); err != nil {
|
if err := c.LoadIssue(stdCtx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
ctx := &crossReferencesContext{
|
ctx := &crossReferencesContext{
|
||||||
|
@ -131,7 +131,7 @@ func testCreateIssue(t *testing.T, repo, doer int64, title, content string, ispu
|
|||||||
r := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repo})
|
r := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repo})
|
||||||
d := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: doer})
|
d := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: doer})
|
||||||
|
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer committer.Close()
|
defer committer.Close()
|
||||||
|
|
||||||
@ -174,7 +174,7 @@ func testCreateComment(t *testing.T, repo, doer, issue int64, content string) *i
|
|||||||
i := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: issue})
|
i := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: issue})
|
||||||
c := &issues_model.Comment{Type: issues_model.CommentTypeComment, PosterID: doer, Poster: d, IssueID: issue, Issue: i, Content: content}
|
c := &issues_model.Comment{Type: issues_model.CommentTypeComment, PosterID: doer, Poster: d, IssueID: issue, Issue: i, Content: content}
|
||||||
|
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer committer.Close()
|
defer committer.Close()
|
||||||
err = db.Insert(ctx, c)
|
err = db.Insert(ctx, c)
|
||||||
|
@ -116,8 +116,8 @@ func (label *Label) CalOpenIssues() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CalOpenOrgIssues calculates the open issues of a label for a specific repo
|
// CalOpenOrgIssues calculates the open issues of a label for a specific repo
|
||||||
func (label *Label) CalOpenOrgIssues(repoID, labelID int64) {
|
func (label *Label) CalOpenOrgIssues(ctx context.Context, repoID, labelID int64) {
|
||||||
counts, _ := CountIssuesByRepo(&IssuesOptions{
|
counts, _ := CountIssuesByRepo(ctx, &IssuesOptions{
|
||||||
RepoID: repoID,
|
RepoID: repoID,
|
||||||
LabelIDs: []int64{labelID},
|
LabelIDs: []int64{labelID},
|
||||||
IsClosed: util.OptionalBoolFalse,
|
IsClosed: util.OptionalBoolFalse,
|
||||||
@ -232,7 +232,7 @@ func NewLabel(ctx context.Context, label *Label) error {
|
|||||||
|
|
||||||
// NewLabels creates new labels
|
// NewLabels creates new labels
|
||||||
func NewLabels(labels ...*Label) error {
|
func NewLabels(labels ...*Label) error {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -267,7 +267,7 @@ func DeleteLabel(id, labelID int64) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -395,9 +395,9 @@ func BuildLabelNamesIssueIDsCondition(labelNames []string) *builder.Builder {
|
|||||||
|
|
||||||
// GetLabelsInRepoByIDs returns a list of labels by IDs in given repository,
|
// GetLabelsInRepoByIDs returns a list of labels by IDs in given repository,
|
||||||
// it silently ignores label IDs that do not belong to the repository.
|
// it silently ignores label IDs that do not belong to the repository.
|
||||||
func GetLabelsInRepoByIDs(repoID int64, labelIDs []int64) ([]*Label, error) {
|
func GetLabelsInRepoByIDs(ctx context.Context, repoID int64, labelIDs []int64) ([]*Label, error) {
|
||||||
labels := make([]*Label, 0, len(labelIDs))
|
labels := make([]*Label, 0, len(labelIDs))
|
||||||
return labels, db.GetEngine(db.DefaultContext).
|
return labels, db.GetEngine(ctx).
|
||||||
Where("repo_id = ?", repoID).
|
Where("repo_id = ?", repoID).
|
||||||
In("id", labelIDs).
|
In("id", labelIDs).
|
||||||
Asc("name").
|
Asc("name").
|
||||||
@ -498,9 +498,9 @@ func GetLabelIDsInOrgByNames(orgID int64, labelNames []string) ([]int64, error)
|
|||||||
|
|
||||||
// GetLabelsInOrgByIDs returns a list of labels by IDs in given organization,
|
// GetLabelsInOrgByIDs returns a list of labels by IDs in given organization,
|
||||||
// it silently ignores label IDs that do not belong to the organization.
|
// it silently ignores label IDs that do not belong to the organization.
|
||||||
func GetLabelsInOrgByIDs(orgID int64, labelIDs []int64) ([]*Label, error) {
|
func GetLabelsInOrgByIDs(ctx context.Context, orgID int64, labelIDs []int64) ([]*Label, error) {
|
||||||
labels := make([]*Label, 0, len(labelIDs))
|
labels := make([]*Label, 0, len(labelIDs))
|
||||||
return labels, db.GetEngine(db.DefaultContext).
|
return labels, db.GetEngine(ctx).
|
||||||
Where("org_id = ?", orgID).
|
Where("org_id = ?", orgID).
|
||||||
In("id", labelIDs).
|
In("id", labelIDs).
|
||||||
Asc("name").
|
Asc("name").
|
||||||
@ -627,7 +627,7 @@ func NewIssueLabel(issue *Issue, label *Label, doer *user_model.User) (err error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -676,7 +676,7 @@ func newIssueLabels(ctx context.Context, issue *Issue, labels []*Label, doer *us
|
|||||||
|
|
||||||
// NewIssueLabels creates a list of issue-label relations.
|
// NewIssueLabels creates a list of issue-label relations.
|
||||||
func NewIssueLabels(issue *Issue, labels []*Label, doer *user_model.User) (err error) {
|
func NewIssueLabels(issue *Issue, labels []*Label, doer *user_model.User) (err error) {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -746,13 +746,13 @@ func DeleteLabelsByRepoID(ctx context.Context, repoID int64) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CountOrphanedLabels return count of labels witch are broken and not accessible via ui anymore
|
// CountOrphanedLabels return count of labels witch are broken and not accessible via ui anymore
|
||||||
func CountOrphanedLabels() (int64, error) {
|
func CountOrphanedLabels(ctx context.Context) (int64, error) {
|
||||||
noref, err := db.GetEngine(db.DefaultContext).Table("label").Where("repo_id=? AND org_id=?", 0, 0).Count()
|
noref, err := db.GetEngine(ctx).Table("label").Where("repo_id=? AND org_id=?", 0, 0).Count()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
norepo, err := db.GetEngine(db.DefaultContext).Table("label").
|
norepo, err := db.GetEngine(ctx).Table("label").
|
||||||
Where(builder.And(
|
Where(builder.And(
|
||||||
builder.Gt{"repo_id": 0},
|
builder.Gt{"repo_id": 0},
|
||||||
builder.NotIn("repo_id", builder.Select("id").From("repository")),
|
builder.NotIn("repo_id", builder.Select("id").From("repository")),
|
||||||
@ -762,7 +762,7 @@ func CountOrphanedLabels() (int64, error) {
|
|||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
noorg, err := db.GetEngine(db.DefaultContext).Table("label").
|
noorg, err := db.GetEngine(ctx).Table("label").
|
||||||
Where(builder.And(
|
Where(builder.And(
|
||||||
builder.Gt{"org_id": 0},
|
builder.Gt{"org_id": 0},
|
||||||
builder.NotIn("org_id", builder.Select("id").From("user")),
|
builder.NotIn("org_id", builder.Select("id").From("user")),
|
||||||
@ -776,14 +776,14 @@ func CountOrphanedLabels() (int64, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DeleteOrphanedLabels delete labels witch are broken and not accessible via ui anymore
|
// DeleteOrphanedLabels delete labels witch are broken and not accessible via ui anymore
|
||||||
func DeleteOrphanedLabels() error {
|
func DeleteOrphanedLabels(ctx context.Context) error {
|
||||||
// delete labels with no reference
|
// delete labels with no reference
|
||||||
if _, err := db.GetEngine(db.DefaultContext).Table("label").Where("repo_id=? AND org_id=?", 0, 0).Delete(new(Label)); err != nil {
|
if _, err := db.GetEngine(ctx).Table("label").Where("repo_id=? AND org_id=?", 0, 0).Delete(new(Label)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete labels with none existing repos
|
// delete labels with none existing repos
|
||||||
if _, err := db.GetEngine(db.DefaultContext).
|
if _, err := db.GetEngine(ctx).
|
||||||
Where(builder.And(
|
Where(builder.And(
|
||||||
builder.Gt{"repo_id": 0},
|
builder.Gt{"repo_id": 0},
|
||||||
builder.NotIn("repo_id", builder.Select("id").From("repository")),
|
builder.NotIn("repo_id", builder.Select("id").From("repository")),
|
||||||
@ -793,7 +793,7 @@ func DeleteOrphanedLabels() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// delete labels with none existing orgs
|
// delete labels with none existing orgs
|
||||||
if _, err := db.GetEngine(db.DefaultContext).
|
if _, err := db.GetEngine(ctx).
|
||||||
Where(builder.And(
|
Where(builder.And(
|
||||||
builder.Gt{"org_id": 0},
|
builder.Gt{"org_id": 0},
|
||||||
builder.NotIn("org_id", builder.Select("id").From("user")),
|
builder.NotIn("org_id", builder.Select("id").From("user")),
|
||||||
@ -806,23 +806,23 @@ func DeleteOrphanedLabels() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CountOrphanedIssueLabels return count of IssueLabels witch have no label behind anymore
|
// CountOrphanedIssueLabels return count of IssueLabels witch have no label behind anymore
|
||||||
func CountOrphanedIssueLabels() (int64, error) {
|
func CountOrphanedIssueLabels(ctx context.Context) (int64, error) {
|
||||||
return db.GetEngine(db.DefaultContext).Table("issue_label").
|
return db.GetEngine(ctx).Table("issue_label").
|
||||||
NotIn("label_id", builder.Select("id").From("label")).
|
NotIn("label_id", builder.Select("id").From("label")).
|
||||||
Count()
|
Count()
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteOrphanedIssueLabels delete IssueLabels witch have no label behind anymore
|
// DeleteOrphanedIssueLabels delete IssueLabels witch have no label behind anymore
|
||||||
func DeleteOrphanedIssueLabels() error {
|
func DeleteOrphanedIssueLabels(ctx context.Context) error {
|
||||||
_, err := db.GetEngine(db.DefaultContext).
|
_, err := db.GetEngine(ctx).
|
||||||
NotIn("label_id", builder.Select("id").From("label")).
|
NotIn("label_id", builder.Select("id").From("label")).
|
||||||
Delete(IssueLabel{})
|
Delete(IssueLabel{})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// CountIssueLabelWithOutsideLabels count label comments with outside label
|
// CountIssueLabelWithOutsideLabels count label comments with outside label
|
||||||
func CountIssueLabelWithOutsideLabels() (int64, error) {
|
func CountIssueLabelWithOutsideLabels(ctx context.Context) (int64, error) {
|
||||||
return db.GetEngine(db.DefaultContext).Where(builder.Expr("(label.org_id = 0 AND issue.repo_id != label.repo_id) OR (label.repo_id = 0 AND label.org_id != repository.owner_id)")).
|
return db.GetEngine(ctx).Where(builder.Expr("(label.org_id = 0 AND issue.repo_id != label.repo_id) OR (label.repo_id = 0 AND label.org_id != repository.owner_id)")).
|
||||||
Table("issue_label").
|
Table("issue_label").
|
||||||
Join("inner", "label", "issue_label.label_id = label.id ").
|
Join("inner", "label", "issue_label.label_id = label.id ").
|
||||||
Join("inner", "issue", "issue.id = issue_label.issue_id ").
|
Join("inner", "issue", "issue.id = issue_label.issue_id ").
|
||||||
@ -831,8 +831,8 @@ func CountIssueLabelWithOutsideLabels() (int64, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FixIssueLabelWithOutsideLabels fix label comments with outside label
|
// FixIssueLabelWithOutsideLabels fix label comments with outside label
|
||||||
func FixIssueLabelWithOutsideLabels() (int64, error) {
|
func FixIssueLabelWithOutsideLabels(ctx context.Context) (int64, error) {
|
||||||
res, err := db.GetEngine(db.DefaultContext).Exec(`DELETE FROM issue_label WHERE issue_label.id IN (
|
res, err := db.GetEngine(ctx).Exec(`DELETE FROM issue_label WHERE issue_label.id IN (
|
||||||
SELECT il_too.id FROM (
|
SELECT il_too.id FROM (
|
||||||
SELECT il_too_too.id
|
SELECT il_too_too.id
|
||||||
FROM issue_label AS il_too_too
|
FROM issue_label AS il_too_too
|
||||||
|
@ -121,7 +121,7 @@ func TestGetLabelInRepoByID(t *testing.T) {
|
|||||||
|
|
||||||
func TestGetLabelsInRepoByIDs(t *testing.T) {
|
func TestGetLabelsInRepoByIDs(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
labels, err := issues_model.GetLabelsInRepoByIDs(1, []int64{1, 2, unittest.NonexistentID})
|
labels, err := issues_model.GetLabelsInRepoByIDs(db.DefaultContext, 1, []int64{1, 2, unittest.NonexistentID})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
if assert.Len(t, labels, 2) {
|
if assert.Len(t, labels, 2) {
|
||||||
assert.EqualValues(t, 1, labels[0].ID)
|
assert.EqualValues(t, 1, labels[0].ID)
|
||||||
@ -212,7 +212,7 @@ func TestGetLabelInOrgByID(t *testing.T) {
|
|||||||
|
|
||||||
func TestGetLabelsInOrgByIDs(t *testing.T) {
|
func TestGetLabelsInOrgByIDs(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
labels, err := issues_model.GetLabelsInOrgByIDs(3, []int64{3, 4, unittest.NonexistentID})
|
labels, err := issues_model.GetLabelsInOrgByIDs(db.DefaultContext, 3, []int64{3, 4, unittest.NonexistentID})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
if assert.Len(t, labels, 2) {
|
if assert.Len(t, labels, 2) {
|
||||||
assert.EqualValues(t, 3, labels[0].ID)
|
assert.EqualValues(t, 3, labels[0].ID)
|
||||||
@ -370,7 +370,7 @@ func TestDeleteIssueLabel(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
defer committer.Close()
|
defer committer.Close()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NoError(t, issues_model.DeleteIssueLabel(ctx, issue, label, doer))
|
assert.NoError(t, issues_model.DeleteIssueLabel(ctx, issue, label, doer))
|
||||||
|
@ -111,7 +111,7 @@ func (m *Milestone) State() api.StateType {
|
|||||||
|
|
||||||
// NewMilestone creates new milestone of repository.
|
// NewMilestone creates new milestone of repository.
|
||||||
func NewMilestone(m *Milestone) (err error) {
|
func NewMilestone(m *Milestone) (err error) {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -161,7 +161,7 @@ func GetMilestoneByRepoIDANDName(repoID int64, name string) (*Milestone, error)
|
|||||||
|
|
||||||
// UpdateMilestone updates information of given milestone.
|
// UpdateMilestone updates information of given milestone.
|
||||||
func UpdateMilestone(m *Milestone, oldIsClosed bool) error {
|
func UpdateMilestone(m *Milestone, oldIsClosed bool) error {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -219,7 +219,7 @@ func UpdateMilestoneCounters(ctx context.Context, id int64) error {
|
|||||||
|
|
||||||
// ChangeMilestoneStatusByRepoIDAndID changes a milestone open/closed status if the milestone ID is in the repo.
|
// ChangeMilestoneStatusByRepoIDAndID changes a milestone open/closed status if the milestone ID is in the repo.
|
||||||
func ChangeMilestoneStatusByRepoIDAndID(repoID, milestoneID int64, isClosed bool) error {
|
func ChangeMilestoneStatusByRepoIDAndID(repoID, milestoneID int64, isClosed bool) error {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -246,7 +246,7 @@ func ChangeMilestoneStatusByRepoIDAndID(repoID, milestoneID int64, isClosed bool
|
|||||||
|
|
||||||
// ChangeMilestoneStatus changes the milestone open/closed status.
|
// ChangeMilestoneStatus changes the milestone open/closed status.
|
||||||
func ChangeMilestoneStatus(m *Milestone, isClosed bool) (err error) {
|
func ChangeMilestoneStatus(m *Milestone, isClosed bool) (err error) {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -290,7 +290,7 @@ func DeleteMilestoneByRepoID(repoID, id int64) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -205,8 +205,8 @@ func DeletePullsByBaseRepoID(ctx context.Context, repoID int64) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MustHeadUserName returns the HeadRepo's username if failed return blank
|
// MustHeadUserName returns the HeadRepo's username if failed return blank
|
||||||
func (pr *PullRequest) MustHeadUserName() string {
|
func (pr *PullRequest) MustHeadUserName(ctx context.Context) string {
|
||||||
if err := pr.LoadHeadRepo(); err != nil {
|
if err := pr.LoadHeadRepo(ctx); err != nil {
|
||||||
if !repo_model.IsErrRepoNotExist(err) {
|
if !repo_model.IsErrRepoNotExist(err) {
|
||||||
log.Error("LoadHeadRepo: %v", err)
|
log.Error("LoadHeadRepo: %v", err)
|
||||||
} else {
|
} else {
|
||||||
@ -220,8 +220,9 @@ func (pr *PullRequest) MustHeadUserName() string {
|
|||||||
return pr.HeadRepo.OwnerName
|
return pr.HeadRepo.OwnerName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LoadAttributes loads pull request attributes from database
|
||||||
// Note: don't try to get Issue because will end up recursive querying.
|
// Note: don't try to get Issue because will end up recursive querying.
|
||||||
func (pr *PullRequest) loadAttributes(ctx context.Context) (err error) {
|
func (pr *PullRequest) LoadAttributes(ctx context.Context) (err error) {
|
||||||
if pr.HasMerged && pr.Merger == nil {
|
if pr.HasMerged && pr.Merger == nil {
|
||||||
pr.Merger, err = user_model.GetUserByIDCtx(ctx, pr.MergerID)
|
pr.Merger, err = user_model.GetUserByIDCtx(ctx, pr.MergerID)
|
||||||
if user_model.IsErrUserNotExist(err) {
|
if user_model.IsErrUserNotExist(err) {
|
||||||
@ -235,13 +236,8 @@ func (pr *PullRequest) loadAttributes(ctx context.Context) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadAttributes loads pull request attributes from database
|
// LoadHeadRepo loads the head repository
|
||||||
func (pr *PullRequest) LoadAttributes() error {
|
func (pr *PullRequest) LoadHeadRepo(ctx context.Context) (err error) {
|
||||||
return pr.loadAttributes(db.DefaultContext)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadHeadRepoCtx loads the head repository
|
|
||||||
func (pr *PullRequest) LoadHeadRepoCtx(ctx context.Context) (err error) {
|
|
||||||
if !pr.isHeadRepoLoaded && pr.HeadRepo == nil && pr.HeadRepoID > 0 {
|
if !pr.isHeadRepoLoaded && pr.HeadRepo == nil && pr.HeadRepoID > 0 {
|
||||||
if pr.HeadRepoID == pr.BaseRepoID {
|
if pr.HeadRepoID == pr.BaseRepoID {
|
||||||
if pr.BaseRepo != nil {
|
if pr.BaseRepo != nil {
|
||||||
@ -262,18 +258,8 @@ func (pr *PullRequest) LoadHeadRepoCtx(ctx context.Context) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadHeadRepo loads the head repository
|
|
||||||
func (pr *PullRequest) LoadHeadRepo() error {
|
|
||||||
return pr.LoadHeadRepoCtx(db.DefaultContext)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadBaseRepo loads the target repository
|
// LoadBaseRepo loads the target repository
|
||||||
func (pr *PullRequest) LoadBaseRepo() error {
|
func (pr *PullRequest) LoadBaseRepo(ctx context.Context) (err error) {
|
||||||
return pr.LoadBaseRepoCtx(db.DefaultContext)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadBaseRepoCtx loads the target repository
|
|
||||||
func (pr *PullRequest) LoadBaseRepoCtx(ctx context.Context) (err error) {
|
|
||||||
if pr.BaseRepo != nil {
|
if pr.BaseRepo != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -296,12 +282,7 @@ func (pr *PullRequest) LoadBaseRepoCtx(ctx context.Context) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// LoadIssue loads issue information from database
|
// LoadIssue loads issue information from database
|
||||||
func (pr *PullRequest) LoadIssue() (err error) {
|
func (pr *PullRequest) LoadIssue(ctx context.Context) (err error) {
|
||||||
return pr.LoadIssueCtx(db.DefaultContext)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadIssueCtx loads issue information from database
|
|
||||||
func (pr *PullRequest) LoadIssueCtx(ctx context.Context) (err error) {
|
|
||||||
if pr.Issue != nil {
|
if pr.Issue != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -368,7 +349,7 @@ func (pr *PullRequest) getReviewedByLines(writer io.Writer) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -392,7 +373,7 @@ func (pr *PullRequest) getReviewedByLines(writer io.Writer) error {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := review.loadReviewer(ctx); err != nil && !user_model.IsErrUserNotExist(err) {
|
if err := review.LoadReviewer(ctx); err != nil && !user_model.IsErrUserNotExist(err) {
|
||||||
log.Error("Unable to LoadReviewer[%d] for PR ID %d : %v", review.ReviewerID, pr.ID, err)
|
log.Error("Unable to LoadReviewer[%d] for PR ID %d : %v", review.ReviewerID, pr.ID, err)
|
||||||
return err
|
return err
|
||||||
} else if review.Reviewer == nil {
|
} else if review.Reviewer == nil {
|
||||||
@ -458,7 +439,7 @@ func (pr *PullRequest) SetMerged(ctx context.Context) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pr.Issue = nil
|
pr.Issue = nil
|
||||||
if err := pr.LoadIssueCtx(ctx); err != nil {
|
if err := pr.LoadIssue(ctx); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -498,7 +479,7 @@ func (pr *PullRequest) SetMerged(ctx context.Context) (bool, error) {
|
|||||||
|
|
||||||
// NewPullRequest creates new pull request with labels for repository.
|
// NewPullRequest creates new pull request with labels for repository.
|
||||||
func NewPullRequest(outerCtx context.Context, repo *repo_model.Repository, issue *Issue, labelIDs []int64, uuids []string, pr *PullRequest) (err error) {
|
func NewPullRequest(outerCtx context.Context, repo *repo_model.Repository, issue *Issue, labelIDs []int64, uuids []string, pr *PullRequest) (err error) {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(outerCtx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -541,9 +522,9 @@ func NewPullRequest(outerCtx context.Context, repo *repo_model.Repository, issue
|
|||||||
|
|
||||||
// GetUnmergedPullRequest returns a pull request that is open and has not been merged
|
// GetUnmergedPullRequest returns a pull request that is open and has not been merged
|
||||||
// by given head/base and repo/branch.
|
// by given head/base and repo/branch.
|
||||||
func GetUnmergedPullRequest(headRepoID, baseRepoID int64, headBranch, baseBranch string, flow PullRequestFlow) (*PullRequest, error) {
|
func GetUnmergedPullRequest(ctx context.Context, headRepoID, baseRepoID int64, headBranch, baseBranch string, flow PullRequestFlow) (*PullRequest, error) {
|
||||||
pr := new(PullRequest)
|
pr := new(PullRequest)
|
||||||
has, err := db.GetEngine(db.DefaultContext).
|
has, err := db.GetEngine(ctx).
|
||||||
Where("head_repo_id=? AND head_branch=? AND base_repo_id=? AND base_branch=? AND has_merged=? AND flow = ? AND issue.is_closed=?",
|
Where("head_repo_id=? AND head_branch=? AND base_repo_id=? AND base_branch=? AND has_merged=? AND flow = ? AND issue.is_closed=?",
|
||||||
headRepoID, headBranch, baseRepoID, baseBranch, false, flow, false).
|
headRepoID, headBranch, baseRepoID, baseBranch, false, flow, false).
|
||||||
Join("INNER", "issue", "issue.id=pull_request.issue_id").
|
Join("INNER", "issue", "issue.id=pull_request.issue_id").
|
||||||
@ -588,10 +569,10 @@ func GetPullRequestByIndex(ctx context.Context, repoID, index int64) (*PullReque
|
|||||||
return nil, ErrPullRequestNotExist{0, 0, 0, repoID, "", ""}
|
return nil, ErrPullRequestNotExist{0, 0, 0, repoID, "", ""}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = pr.loadAttributes(ctx); err != nil {
|
if err = pr.LoadAttributes(ctx); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err = pr.LoadIssueCtx(ctx); err != nil {
|
if err = pr.LoadIssue(ctx); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -607,7 +588,7 @@ func GetPullRequestByID(ctx context.Context, id int64) (*PullRequest, error) {
|
|||||||
} else if !has {
|
} else if !has {
|
||||||
return nil, ErrPullRequestNotExist{id, 0, 0, 0, "", ""}
|
return nil, ErrPullRequestNotExist{id, 0, 0, 0, "", ""}
|
||||||
}
|
}
|
||||||
return pr, pr.loadAttributes(ctx)
|
return pr, pr.LoadAttributes(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPullRequestByIssueIDWithNoAttributes returns pull request with no attributes loaded by given issue ID.
|
// GetPullRequestByIssueIDWithNoAttributes returns pull request with no attributes loaded by given issue ID.
|
||||||
@ -634,7 +615,7 @@ func GetPullRequestByIssueID(ctx context.Context, issueID int64) (*PullRequest,
|
|||||||
} else if !has {
|
} else if !has {
|
||||||
return nil, ErrPullRequestNotExist{0, issueID, 0, 0, "", ""}
|
return nil, ErrPullRequestNotExist{0, issueID, 0, 0, "", ""}
|
||||||
}
|
}
|
||||||
return pr, pr.loadAttributes(ctx)
|
return pr, pr.LoadAttributes(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAllUnmergedAgitPullRequestByPoster get all unmerged agit flow pull request
|
// GetAllUnmergedAgitPullRequestByPoster get all unmerged agit flow pull request
|
||||||
@ -664,14 +645,15 @@ func (pr *PullRequest) UpdateCols(cols ...string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateColsIfNotMerged updates specific fields of a pull request if it has not been merged
|
// UpdateColsIfNotMerged updates specific fields of a pull request if it has not been merged
|
||||||
func (pr *PullRequest) UpdateColsIfNotMerged(cols ...string) error {
|
func (pr *PullRequest) UpdateColsIfNotMerged(ctx context.Context, cols ...string) error {
|
||||||
_, err := db.GetEngine(db.DefaultContext).Where("id = ? AND has_merged = ?", pr.ID, false).Cols(cols...).Update(pr)
|
_, err := db.GetEngine(ctx).Where("id = ? AND has_merged = ?", pr.ID, false).Cols(cols...).Update(pr)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsWorkInProgress determine if the Pull Request is a Work In Progress by its title
|
// IsWorkInProgress determine if the Pull Request is a Work In Progress by its title
|
||||||
|
// Issue must be set before this method can be called.
|
||||||
func (pr *PullRequest) IsWorkInProgress() bool {
|
func (pr *PullRequest) IsWorkInProgress() bool {
|
||||||
if err := pr.LoadIssue(); err != nil {
|
if err := pr.LoadIssue(db.DefaultContext); err != nil {
|
||||||
log.Error("LoadIssue: %v", err)
|
log.Error("LoadIssue: %v", err)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -695,8 +677,8 @@ func (pr *PullRequest) IsFilesConflicted() bool {
|
|||||||
|
|
||||||
// GetWorkInProgressPrefix returns the prefix used to mark the pull request as a work in progress.
|
// GetWorkInProgressPrefix returns the prefix used to mark the pull request as a work in progress.
|
||||||
// It returns an empty string when none were found
|
// It returns an empty string when none were found
|
||||||
func (pr *PullRequest) GetWorkInProgressPrefix() string {
|
func (pr *PullRequest) GetWorkInProgressPrefix(ctx context.Context) string {
|
||||||
if err := pr.LoadIssue(); err != nil {
|
if err := pr.LoadIssue(ctx); err != nil {
|
||||||
log.Error("LoadIssue: %v", err)
|
log.Error("LoadIssue: %v", err)
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@ -739,7 +721,7 @@ func GetPullRequestsByHeadBranch(ctx context.Context, headBranch string, headRep
|
|||||||
|
|
||||||
// GetBaseBranchHTMLURL returns the HTML URL of the base branch
|
// GetBaseBranchHTMLURL returns the HTML URL of the base branch
|
||||||
func (pr *PullRequest) GetBaseBranchHTMLURL() string {
|
func (pr *PullRequest) GetBaseBranchHTMLURL() string {
|
||||||
if err := pr.LoadBaseRepo(); err != nil {
|
if err := pr.LoadBaseRepo(db.DefaultContext); err != nil {
|
||||||
log.Error("LoadBaseRepo: %v", err)
|
log.Error("LoadBaseRepo: %v", err)
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@ -755,7 +737,7 @@ func (pr *PullRequest) GetHeadBranchHTMLURL() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := pr.LoadHeadRepo(); err != nil {
|
if err := pr.LoadHeadRepo(db.DefaultContext); err != nil {
|
||||||
log.Error("LoadHeadRepo: %v", err)
|
log.Error("LoadHeadRepo: %v", err)
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,7 @@ func CanMaintainerWriteToBranch(p access_model.Permission, branch string, user *
|
|||||||
|
|
||||||
for _, pr := range prs {
|
for _, pr := range prs {
|
||||||
if pr.AllowMaintainerEdit {
|
if pr.AllowMaintainerEdit {
|
||||||
err = pr.LoadBaseRepo()
|
err = pr.LoadBaseRepo(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ import (
|
|||||||
func TestPullRequest_LoadAttributes(t *testing.T) {
|
func TestPullRequest_LoadAttributes(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1})
|
pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1})
|
||||||
assert.NoError(t, pr.LoadAttributes())
|
assert.NoError(t, pr.LoadAttributes(db.DefaultContext))
|
||||||
assert.NotNil(t, pr.Merger)
|
assert.NotNil(t, pr.Merger)
|
||||||
assert.Equal(t, pr.MergerID, pr.Merger.ID)
|
assert.Equal(t, pr.MergerID, pr.Merger.ID)
|
||||||
}
|
}
|
||||||
@ -25,10 +25,10 @@ func TestPullRequest_LoadAttributes(t *testing.T) {
|
|||||||
func TestPullRequest_LoadIssue(t *testing.T) {
|
func TestPullRequest_LoadIssue(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1})
|
pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1})
|
||||||
assert.NoError(t, pr.LoadIssue())
|
assert.NoError(t, pr.LoadIssue(db.DefaultContext))
|
||||||
assert.NotNil(t, pr.Issue)
|
assert.NotNil(t, pr.Issue)
|
||||||
assert.Equal(t, int64(2), pr.Issue.ID)
|
assert.Equal(t, int64(2), pr.Issue.ID)
|
||||||
assert.NoError(t, pr.LoadIssue())
|
assert.NoError(t, pr.LoadIssue(db.DefaultContext))
|
||||||
assert.NotNil(t, pr.Issue)
|
assert.NotNil(t, pr.Issue)
|
||||||
assert.Equal(t, int64(2), pr.Issue.ID)
|
assert.Equal(t, int64(2), pr.Issue.ID)
|
||||||
}
|
}
|
||||||
@ -36,10 +36,10 @@ func TestPullRequest_LoadIssue(t *testing.T) {
|
|||||||
func TestPullRequest_LoadBaseRepo(t *testing.T) {
|
func TestPullRequest_LoadBaseRepo(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1})
|
pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1})
|
||||||
assert.NoError(t, pr.LoadBaseRepo())
|
assert.NoError(t, pr.LoadBaseRepo(db.DefaultContext))
|
||||||
assert.NotNil(t, pr.BaseRepo)
|
assert.NotNil(t, pr.BaseRepo)
|
||||||
assert.Equal(t, pr.BaseRepoID, pr.BaseRepo.ID)
|
assert.Equal(t, pr.BaseRepoID, pr.BaseRepo.ID)
|
||||||
assert.NoError(t, pr.LoadBaseRepo())
|
assert.NoError(t, pr.LoadBaseRepo(db.DefaultContext))
|
||||||
assert.NotNil(t, pr.BaseRepo)
|
assert.NotNil(t, pr.BaseRepo)
|
||||||
assert.Equal(t, pr.BaseRepoID, pr.BaseRepo.ID)
|
assert.Equal(t, pr.BaseRepoID, pr.BaseRepo.ID)
|
||||||
}
|
}
|
||||||
@ -47,7 +47,7 @@ func TestPullRequest_LoadBaseRepo(t *testing.T) {
|
|||||||
func TestPullRequest_LoadHeadRepo(t *testing.T) {
|
func TestPullRequest_LoadHeadRepo(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1})
|
pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1})
|
||||||
assert.NoError(t, pr.LoadHeadRepo())
|
assert.NoError(t, pr.LoadHeadRepo(db.DefaultContext))
|
||||||
assert.NotNil(t, pr.HeadRepo)
|
assert.NotNil(t, pr.HeadRepo)
|
||||||
assert.Equal(t, pr.HeadRepoID, pr.HeadRepo.ID)
|
assert.Equal(t, pr.HeadRepoID, pr.HeadRepo.ID)
|
||||||
}
|
}
|
||||||
@ -96,11 +96,11 @@ func TestPullRequestsOldest(t *testing.T) {
|
|||||||
|
|
||||||
func TestGetUnmergedPullRequest(t *testing.T) {
|
func TestGetUnmergedPullRequest(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
pr, err := issues_model.GetUnmergedPullRequest(1, 1, "branch2", "master", issues_model.PullRequestFlowGithub)
|
pr, err := issues_model.GetUnmergedPullRequest(db.DefaultContext, 1, 1, "branch2", "master", issues_model.PullRequestFlowGithub)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, int64(2), pr.ID)
|
assert.Equal(t, int64(2), pr.ID)
|
||||||
|
|
||||||
_, err = issues_model.GetUnmergedPullRequest(1, 9223372036854775807, "branch1", "master", issues_model.PullRequestFlowGithub)
|
_, err = issues_model.GetUnmergedPullRequest(db.DefaultContext, 1, 9223372036854775807, "branch1", "master", issues_model.PullRequestFlowGithub)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.True(t, issues_model.IsErrPullRequestNotExist(err))
|
assert.True(t, issues_model.IsErrPullRequestNotExist(err))
|
||||||
}
|
}
|
||||||
@ -228,7 +228,7 @@ func TestPullRequest_IsWorkInProgress(t *testing.T) {
|
|||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2})
|
pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2})
|
||||||
pr.LoadIssue()
|
pr.LoadIssue(db.DefaultContext)
|
||||||
|
|
||||||
assert.False(t, pr.IsWorkInProgress())
|
assert.False(t, pr.IsWorkInProgress())
|
||||||
|
|
||||||
@ -243,16 +243,16 @@ func TestPullRequest_GetWorkInProgressPrefixWorkInProgress(t *testing.T) {
|
|||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2})
|
pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2})
|
||||||
pr.LoadIssue()
|
pr.LoadIssue(db.DefaultContext)
|
||||||
|
|
||||||
assert.Empty(t, pr.GetWorkInProgressPrefix())
|
assert.Empty(t, pr.GetWorkInProgressPrefix(db.DefaultContext))
|
||||||
|
|
||||||
original := pr.Issue.Title
|
original := pr.Issue.Title
|
||||||
pr.Issue.Title = "WIP: " + original
|
pr.Issue.Title = "WIP: " + original
|
||||||
assert.Equal(t, "WIP:", pr.GetWorkInProgressPrefix())
|
assert.Equal(t, "WIP:", pr.GetWorkInProgressPrefix(db.DefaultContext))
|
||||||
|
|
||||||
pr.Issue.Title = "[wip] " + original
|
pr.Issue.Title = "[wip] " + original
|
||||||
assert.Equal(t, "[wip]", pr.GetWorkInProgressPrefix())
|
assert.Equal(t, "[wip]", pr.GetWorkInProgressPrefix(db.DefaultContext))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDeleteOrphanedObjects(t *testing.T) {
|
func TestDeleteOrphanedObjects(t *testing.T) {
|
||||||
@ -264,11 +264,11 @@ func TestDeleteOrphanedObjects(t *testing.T) {
|
|||||||
_, err = db.GetEngine(db.DefaultContext).Insert(&issues_model.PullRequest{IssueID: 1000}, &issues_model.PullRequest{IssueID: 1001}, &issues_model.PullRequest{IssueID: 1003})
|
_, err = db.GetEngine(db.DefaultContext).Insert(&issues_model.PullRequest{IssueID: 1000}, &issues_model.PullRequest{IssueID: 1001}, &issues_model.PullRequest{IssueID: 1003})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
orphaned, err := db.CountOrphanedObjects("pull_request", "issue", "pull_request.issue_id=issue.id")
|
orphaned, err := db.CountOrphanedObjects(db.DefaultContext, "pull_request", "issue", "pull_request.issue_id=issue.id")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.EqualValues(t, 3, orphaned)
|
assert.EqualValues(t, 3, orphaned)
|
||||||
|
|
||||||
err = db.DeleteOrphanedObjects("pull_request", "issue", "pull_request.issue_id=issue.id")
|
err = db.DeleteOrphanedObjects(db.DefaultContext, "pull_request", "issue", "pull_request.issue_id=issue.id")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
countAfter, err := db.GetEngine(db.DefaultContext).Count(&issues_model.PullRequest{})
|
countAfter, err := db.GetEngine(db.DefaultContext).Count(&issues_model.PullRequest{})
|
||||||
|
@ -224,7 +224,7 @@ func CreateReaction(opts *ReactionOptions) (*Reaction, error) {
|
|||||||
return nil, ErrForbiddenIssueReaction{opts.Type}
|
return nil, ErrForbiddenIssueReaction{opts.Type}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -154,7 +154,8 @@ func (r *Review) loadIssue(ctx context.Context) (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Review) loadReviewer(ctx context.Context) (err error) {
|
// LoadReviewer loads reviewer
|
||||||
|
func (r *Review) LoadReviewer(ctx context.Context) (err error) {
|
||||||
if r.ReviewerID == 0 || r.Reviewer != nil {
|
if r.ReviewerID == 0 || r.Reviewer != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -162,7 +163,8 @@ func (r *Review) loadReviewer(ctx context.Context) (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Review) loadReviewerTeam(ctx context.Context) (err error) {
|
// LoadReviewerTeam loads reviewer team
|
||||||
|
func (r *Review) LoadReviewerTeam(ctx context.Context) (err error) {
|
||||||
if r.ReviewerTeamID == 0 || r.ReviewerTeam != nil {
|
if r.ReviewerTeamID == 0 || r.ReviewerTeam != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -171,16 +173,6 @@ func (r *Review) loadReviewerTeam(ctx context.Context) (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadReviewer loads reviewer
|
|
||||||
func (r *Review) LoadReviewer() error {
|
|
||||||
return r.loadReviewer(db.DefaultContext)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadReviewerTeam loads reviewer team
|
|
||||||
func (r *Review) LoadReviewerTeam() error {
|
|
||||||
return r.loadReviewerTeam(db.DefaultContext)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadAttributes loads all attributes except CodeComments
|
// LoadAttributes loads all attributes except CodeComments
|
||||||
func (r *Review) LoadAttributes(ctx context.Context) (err error) {
|
func (r *Review) LoadAttributes(ctx context.Context) (err error) {
|
||||||
if err = r.loadIssue(ctx); err != nil {
|
if err = r.loadIssue(ctx); err != nil {
|
||||||
@ -189,10 +181,10 @@ func (r *Review) LoadAttributes(ctx context.Context) (err error) {
|
|||||||
if err = r.LoadCodeComments(ctx); err != nil {
|
if err = r.LoadCodeComments(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err = r.loadReviewer(ctx); err != nil {
|
if err = r.LoadReviewer(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err = r.loadReviewerTeam(ctx); err != nil {
|
if err = r.LoadReviewerTeam(ctx); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
@ -374,7 +366,7 @@ func IsContentEmptyErr(err error) bool {
|
|||||||
|
|
||||||
// SubmitReview creates a review out of the existing pending review or creates a new one if no pending review exist
|
// SubmitReview creates a review out of the existing pending review or creates a new one if no pending review exist
|
||||||
func SubmitReview(doer *user_model.User, issue *Issue, reviewType ReviewType, content, commitID string, stale bool, attachmentUUIDs []string) (*Review, *Comment, error) {
|
func SubmitReview(doer *user_model.User, issue *Issue, reviewType ReviewType, content, commitID string, stale bool, attachmentUUIDs []string) (*Review, *Comment, error) {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@ -622,7 +614,7 @@ func DismissReview(review *Review, isDismiss bool) (err error) {
|
|||||||
|
|
||||||
// InsertReviews inserts review and review comments
|
// InsertReviews inserts review and review comments
|
||||||
func InsertReviews(reviews []*Review) error {
|
func InsertReviews(reviews []*Review) error {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -664,7 +656,7 @@ func InsertReviews(reviews []*Review) error {
|
|||||||
|
|
||||||
// AddReviewRequest add a review request from one reviewer
|
// AddReviewRequest add a review request from one reviewer
|
||||||
func AddReviewRequest(issue *Issue, reviewer, doer *user_model.User) (*Comment, error) {
|
func AddReviewRequest(issue *Issue, reviewer, doer *user_model.User) (*Comment, error) {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -719,7 +711,7 @@ func AddReviewRequest(issue *Issue, reviewer, doer *user_model.User) (*Comment,
|
|||||||
|
|
||||||
// RemoveReviewRequest remove a review request from one reviewer
|
// RemoveReviewRequest remove a review request from one reviewer
|
||||||
func RemoveReviewRequest(issue *Issue, reviewer, doer *user_model.User) (*Comment, error) {
|
func RemoveReviewRequest(issue *Issue, reviewer, doer *user_model.User) (*Comment, error) {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -772,7 +764,7 @@ func RemoveReviewRequest(issue *Issue, reviewer, doer *user_model.User) (*Commen
|
|||||||
|
|
||||||
// AddTeamReviewRequest add a review request from one team
|
// AddTeamReviewRequest add a review request from one team
|
||||||
func AddTeamReviewRequest(issue *Issue, reviewer *organization.Team, doer *user_model.User) (*Comment, error) {
|
func AddTeamReviewRequest(issue *Issue, reviewer *organization.Team, doer *user_model.User) (*Comment, error) {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -831,7 +823,7 @@ func AddTeamReviewRequest(issue *Issue, reviewer *organization.Team, doer *user_
|
|||||||
|
|
||||||
// RemoveTeamReviewRequest remove a review request from one team
|
// RemoveTeamReviewRequest remove a review request from one team
|
||||||
func RemoveTeamReviewRequest(issue *Issue, reviewer *organization.Team, doer *user_model.User) (*Comment, error) {
|
func RemoveTeamReviewRequest(issue *Issue, reviewer *organization.Team, doer *user_model.User) (*Comment, error) {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -949,7 +941,7 @@ func CanMarkConversation(issue *Issue, doer *user_model.User) (permResult bool,
|
|||||||
|
|
||||||
// DeleteReview delete a review and it's code comments
|
// DeleteReview delete a review and it's code comments
|
||||||
func DeleteReview(r *Review) error {
|
func DeleteReview(r *Review) error {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -135,7 +135,7 @@ func TestGetReviewersByIssueID(t *testing.T) {
|
|||||||
|
|
||||||
allReviews, err := issues_model.GetReviewersByIssueID(issue.ID)
|
allReviews, err := issues_model.GetReviewersByIssueID(issue.ID)
|
||||||
for _, reviewer := range allReviews {
|
for _, reviewer := range allReviews {
|
||||||
assert.NoError(t, reviewer.LoadReviewer())
|
assert.NoError(t, reviewer.LoadReviewer(db.DefaultContext))
|
||||||
}
|
}
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
if assert.Len(t, allReviews, 3) {
|
if assert.Len(t, allReviews, 3) {
|
||||||
|
@ -261,7 +261,7 @@ func CreateIssueStopwatch(ctx context.Context, user *user_model.User, issue *Iss
|
|||||||
|
|
||||||
// CancelStopwatch removes the given stopwatch and logs it into issue's timeline.
|
// CancelStopwatch removes the given stopwatch and logs it into issue's timeline.
|
||||||
func CancelStopwatch(user *user_model.User, issue *Issue) error {
|
func CancelStopwatch(user *user_model.User, issue *Issue) error {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -149,7 +149,7 @@ func GetTrackedSeconds(ctx context.Context, opts FindTrackedTimesOptions) (track
|
|||||||
|
|
||||||
// AddTime will add the given time (in seconds) to the issue
|
// AddTime will add the given time (in seconds) to the issue
|
||||||
func AddTime(user *user_model.User, issue *Issue, amount int64, created time.Time) (*TrackedTime, error) {
|
func AddTime(user *user_model.User, issue *Issue, amount int64, created time.Time) (*TrackedTime, error) {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -220,7 +220,7 @@ func TotalTimes(options *FindTrackedTimesOptions) (map[*user_model.User]string,
|
|||||||
|
|
||||||
// DeleteIssueUserTimes deletes times for issue
|
// DeleteIssueUserTimes deletes times for issue
|
||||||
func DeleteIssueUserTimes(issue *Issue, user *user_model.User) error {
|
func DeleteIssueUserTimes(issue *Issue, user *user_model.User) error {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -257,7 +257,7 @@ func DeleteIssueUserTimes(issue *Issue, user *user_model.User) error {
|
|||||||
|
|
||||||
// DeleteTime delete a specific Time
|
// DeleteTime delete a specific Time
|
||||||
func DeleteTime(t *TrackedTime) error {
|
func DeleteTime(t *TrackedTime) error {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ func InsertMilestones(ms ...*issues_model.Milestone) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -42,7 +42,7 @@ func InsertMilestones(ms ...*issues_model.Milestone) (err error) {
|
|||||||
|
|
||||||
// InsertIssues insert issues to database
|
// InsertIssues insert issues to database
|
||||||
func InsertIssues(issues ...*issues_model.Issue) error {
|
func InsertIssues(issues ...*issues_model.Issue) error {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -105,7 +105,7 @@ func InsertIssueComments(comments []*issues_model.Comment) error {
|
|||||||
issueIDs.Add(comment.IssueID)
|
issueIDs.Add(comment.IssueID)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -137,7 +137,7 @@ func InsertIssueComments(comments []*issues_model.Comment) error {
|
|||||||
|
|
||||||
// InsertPullRequests inserted pull requests
|
// InsertPullRequests inserted pull requests
|
||||||
func InsertPullRequests(prs ...*issues_model.PullRequest) error {
|
func InsertPullRequests(prs ...*issues_model.PullRequest) error {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -157,7 +157,7 @@ func InsertPullRequests(prs ...*issues_model.PullRequest) error {
|
|||||||
|
|
||||||
// InsertReleases migrates release
|
// InsertReleases migrates release
|
||||||
func InsertReleases(rels ...*repo_model.Release) error {
|
func InsertReleases(rels ...*repo_model.Release) error {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
package migrations
|
package migrations
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
@ -23,6 +24,7 @@ import (
|
|||||||
"code.gitea.io/gitea/models/migrations/v1_7"
|
"code.gitea.io/gitea/models/migrations/v1_7"
|
||||||
"code.gitea.io/gitea/models/migrations/v1_8"
|
"code.gitea.io/gitea/models/migrations/v1_8"
|
||||||
"code.gitea.io/gitea/models/migrations/v1_9"
|
"code.gitea.io/gitea/models/migrations/v1_9"
|
||||||
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
@ -437,6 +439,8 @@ var migrations = []Migration{
|
|||||||
NewMigration("Alter package_version.metadata_json to LONGTEXT", v1_19.AlterPackageVersionMetadataToLongText),
|
NewMigration("Alter package_version.metadata_json to LONGTEXT", v1_19.AlterPackageVersionMetadataToLongText),
|
||||||
// v233 -> v234
|
// v233 -> v234
|
||||||
NewMigration("Add header_authorization_encrypted column to webhook table", v1_19.AddHeaderAuthorizationEncryptedColWebhook),
|
NewMigration("Add header_authorization_encrypted column to webhook table", v1_19.AddHeaderAuthorizationEncryptedColWebhook),
|
||||||
|
// v234 -> v235
|
||||||
|
NewMigration("Add package cleanup rule table", v1_19.CreatePackageCleanupRuleTable),
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCurrentDBVersion returns the current db version
|
// GetCurrentDBVersion returns the current db version
|
||||||
@ -527,6 +531,13 @@ Please try upgrading to a lower version first (suggested v1.6.4), then upgrade t
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Some migration tasks depend on the git command
|
||||||
|
if git.DefaultContext == nil {
|
||||||
|
if err = git.InitSimple(context.Background()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Migrate
|
// Migrate
|
||||||
for i, m := range migrations[v-minDBVersion:] {
|
for i, m := range migrations[v-minDBVersion:] {
|
||||||
log.Info("Migration[%d]: %s", v+int64(i), m.Description())
|
log.Info("Migration[%d]: %s", v+int64(i), m.Description())
|
||||||
|
29
models/migrations/v1_19/v234.go
Normal file
29
models/migrations/v1_19/v234.go
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package v1_19 //nolint
|
||||||
|
|
||||||
|
import (
|
||||||
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
|
|
||||||
|
"xorm.io/xorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
func CreatePackageCleanupRuleTable(x *xorm.Engine) error {
|
||||||
|
type PackageCleanupRule struct {
|
||||||
|
ID int64 `xorm:"pk autoincr"`
|
||||||
|
Enabled bool `xorm:"INDEX NOT NULL DEFAULT false"`
|
||||||
|
OwnerID int64 `xorm:"UNIQUE(s) INDEX NOT NULL DEFAULT 0"`
|
||||||
|
Type string `xorm:"UNIQUE(s) INDEX NOT NULL"`
|
||||||
|
KeepCount int `xorm:"NOT NULL DEFAULT 0"`
|
||||||
|
KeepPattern string `xorm:"NOT NULL DEFAULT ''"`
|
||||||
|
RemoveDays int `xorm:"NOT NULL DEFAULT 0"`
|
||||||
|
RemovePattern string `xorm:"NOT NULL DEFAULT ''"`
|
||||||
|
MatchFullName bool `xorm:"NOT NULL DEFAULT false"`
|
||||||
|
CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL DEFAULT 0"`
|
||||||
|
UpdatedUnix timeutil.TimeStamp `xorm:"updated NOT NULL DEFAULT 0"`
|
||||||
|
}
|
||||||
|
|
||||||
|
return x.Sync2(new(PackageCleanupRule))
|
||||||
|
}
|
@ -99,7 +99,7 @@ func removeOrgUser(ctx context.Context, orgID, userID int64) error {
|
|||||||
|
|
||||||
// RemoveOrgUser removes user from given organization.
|
// RemoveOrgUser removes user from given organization.
|
||||||
func RemoveOrgUser(orgID, userID int64) error {
|
func RemoveOrgUser(orgID, userID int64) error {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ func addAllRepositories(ctx context.Context, t *organization.Team) error {
|
|||||||
|
|
||||||
// AddAllRepositories adds all repositories to the team
|
// AddAllRepositories adds all repositories to the team
|
||||||
func AddAllRepositories(t *organization.Team) (err error) {
|
func AddAllRepositories(t *organization.Team) (err error) {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -95,7 +95,7 @@ func RemoveAllRepositories(t *organization.Team) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -219,7 +219,7 @@ func RemoveRepository(t *organization.Team, repoID int64) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -263,7 +263,7 @@ func NewTeam(t *organization.Team) (err error) {
|
|||||||
return organization.ErrTeamAlreadyExist{OrgID: t.OrgID, Name: t.LowerName}
|
return organization.ErrTeamAlreadyExist{OrgID: t.OrgID, Name: t.LowerName}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -308,7 +308,7 @@ func UpdateTeam(t *organization.Team, authChanged, includeAllChanged bool) (err
|
|||||||
t.Description = t.Description[:255]
|
t.Description = t.Description[:255]
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -375,7 +375,7 @@ func UpdateTeam(t *organization.Team, authChanged, includeAllChanged bool) (err
|
|||||||
// DeleteTeam deletes given team.
|
// DeleteTeam deletes given team.
|
||||||
// It's caller's responsibility to assign organization ID.
|
// It's caller's responsibility to assign organization ID.
|
||||||
func DeleteTeam(t *organization.Team) error {
|
func DeleteTeam(t *organization.Team) error {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -460,7 +460,7 @@ func AddTeamMember(team *organization.Team, userID int64) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -598,7 +598,7 @@ func removeTeamMember(ctx context.Context, team *organization.Team, userID int64
|
|||||||
|
|
||||||
// RemoveTeamMember removes member from given team of given organization.
|
// RemoveTeamMember removes member from given team of given organization.
|
||||||
func RemoveTeamMember(team *organization.Team, userID int64) error {
|
func RemoveTeamMember(team *organization.Team, userID int64) error {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -143,7 +143,7 @@ func TestDeleteTeam(t *testing.T) {
|
|||||||
// check that team members don't have "leftover" access to repos
|
// check that team members don't have "leftover" access to repos
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 4})
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3})
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3})
|
||||||
accessMode, err := access_model.AccessLevel(user, repo)
|
accessMode, err := access_model.AccessLevel(db.DefaultContext, user, repo)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.True(t, accessMode < perm.AccessModeWrite)
|
assert.True(t, accessMode < perm.AccessModeWrite)
|
||||||
}
|
}
|
||||||
|
@ -277,7 +277,7 @@ func CreateOrganization(org *Organization, owner *user_model.User) (err error) {
|
|||||||
org.NumMembers = 1
|
org.NumMembers = 1
|
||||||
org.Type = user_model.UserTypeOrganization
|
org.Type = user_model.UserTypeOrganization
|
||||||
|
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -458,8 +458,9 @@ func CountOrgs(opts FindOrgOptions) (int64, error) {
|
|||||||
|
|
||||||
// HasOrgOrUserVisible tells if the given user can see the given org or user
|
// HasOrgOrUserVisible tells if the given user can see the given org or user
|
||||||
func HasOrgOrUserVisible(ctx context.Context, orgOrUser, user *user_model.User) bool {
|
func HasOrgOrUserVisible(ctx context.Context, orgOrUser, user *user_model.User) bool {
|
||||||
// Not SignedUser
|
// If user is nil, it's an anonymous user/request.
|
||||||
if user == nil {
|
// The Ghost user is handled like an anonymous user.
|
||||||
|
if user == nil || user.IsGhost() {
|
||||||
return orgOrUser.Visibility == structs.VisibleTypePublic
|
return orgOrUser.Visibility == structs.VisibleTypePublic
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -564,7 +565,7 @@ func AddOrgUser(orgID, uid int64) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ func getUnitsByTeamID(ctx context.Context, teamID int64) (units []*TeamUnit, err
|
|||||||
|
|
||||||
// UpdateTeamUnits updates a teams's units
|
// UpdateTeamUnits updates a teams's units
|
||||||
func UpdateTeamUnits(team *Team, units []TeamUnit) (err error) {
|
func UpdateTeamUnits(team *Team, units []TeamUnit) (err error) {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,21 @@ const (
|
|||||||
TypeVagrant Type = "vagrant"
|
TypeVagrant Type = "vagrant"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var TypeList = []Type{
|
||||||
|
TypeComposer,
|
||||||
|
TypeConan,
|
||||||
|
TypeContainer,
|
||||||
|
TypeGeneric,
|
||||||
|
TypeHelm,
|
||||||
|
TypeMaven,
|
||||||
|
TypeNpm,
|
||||||
|
TypeNuGet,
|
||||||
|
TypePub,
|
||||||
|
TypePyPI,
|
||||||
|
TypeRubyGems,
|
||||||
|
TypeVagrant,
|
||||||
|
}
|
||||||
|
|
||||||
// Name gets the name of the package type
|
// Name gets the name of the package type
|
||||||
func (pt Type) Name() string {
|
func (pt Type) Name() string {
|
||||||
switch pt {
|
switch pt {
|
||||||
|
@ -62,6 +62,13 @@ func GetBlobByID(ctx context.Context, blobID int64) (*PackageBlob, error) {
|
|||||||
return pb, nil
|
return pb, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExistPackageBlobWithSHA returns if a package blob exists with the provided sha
|
||||||
|
func ExistPackageBlobWithSHA(ctx context.Context, blobSha256 string) (bool, error) {
|
||||||
|
return db.GetEngine(ctx).Exist(&PackageBlob{
|
||||||
|
HashSHA256: blobSha256,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// FindExpiredUnreferencedBlobs gets all blobs without associated files older than the specific duration
|
// FindExpiredUnreferencedBlobs gets all blobs without associated files older than the specific duration
|
||||||
func FindExpiredUnreferencedBlobs(ctx context.Context, olderThan time.Duration) ([]*PackageBlob, error) {
|
func FindExpiredUnreferencedBlobs(ctx context.Context, olderThan time.Duration) ([]*PackageBlob, error) {
|
||||||
pbs := make([]*PackageBlob, 0, 10)
|
pbs := make([]*PackageBlob, 0, 10)
|
||||||
|
110
models/packages/package_cleanup_rule.go
Normal file
110
models/packages/package_cleanup_rule.go
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
// Copyright 2022 The Gitea Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package packages
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
|
|
||||||
|
"xorm.io/builder"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ErrPackageCleanupRuleNotExist = errors.New("Package blob does not exist")
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
db.RegisterModel(new(PackageCleanupRule))
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackageCleanupRule represents a rule which describes when to clean up package versions
|
||||||
|
type PackageCleanupRule struct {
|
||||||
|
ID int64 `xorm:"pk autoincr"`
|
||||||
|
Enabled bool `xorm:"INDEX NOT NULL DEFAULT false"`
|
||||||
|
OwnerID int64 `xorm:"UNIQUE(s) INDEX NOT NULL DEFAULT 0"`
|
||||||
|
Type Type `xorm:"UNIQUE(s) INDEX NOT NULL"`
|
||||||
|
KeepCount int `xorm:"NOT NULL DEFAULT 0"`
|
||||||
|
KeepPattern string `xorm:"NOT NULL DEFAULT ''"`
|
||||||
|
KeepPatternMatcher *regexp.Regexp `xorm:"-"`
|
||||||
|
RemoveDays int `xorm:"NOT NULL DEFAULT 0"`
|
||||||
|
RemovePattern string `xorm:"NOT NULL DEFAULT ''"`
|
||||||
|
RemovePatternMatcher *regexp.Regexp `xorm:"-"`
|
||||||
|
MatchFullName bool `xorm:"NOT NULL DEFAULT false"`
|
||||||
|
CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL DEFAULT 0"`
|
||||||
|
UpdatedUnix timeutil.TimeStamp `xorm:"updated NOT NULL DEFAULT 0"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pcr *PackageCleanupRule) CompiledPattern() error {
|
||||||
|
if pcr.KeepPatternMatcher != nil || pcr.RemovePatternMatcher != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if pcr.KeepPattern != "" {
|
||||||
|
var err error
|
||||||
|
pcr.KeepPatternMatcher, err = regexp.Compile(fmt.Sprintf(`(?i)\A%s\z`, pcr.KeepPattern))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if pcr.RemovePattern != "" {
|
||||||
|
var err error
|
||||||
|
pcr.RemovePatternMatcher, err = regexp.Compile(fmt.Sprintf(`(?i)\A%s\z`, pcr.RemovePattern))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func InsertCleanupRule(ctx context.Context, pcr *PackageCleanupRule) (*PackageCleanupRule, error) {
|
||||||
|
return pcr, db.Insert(ctx, pcr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetCleanupRuleByID(ctx context.Context, id int64) (*PackageCleanupRule, error) {
|
||||||
|
pcr := &PackageCleanupRule{}
|
||||||
|
|
||||||
|
has, err := db.GetEngine(ctx).ID(id).Get(pcr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !has {
|
||||||
|
return nil, ErrPackageCleanupRuleNotExist
|
||||||
|
}
|
||||||
|
return pcr, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func UpdateCleanupRule(ctx context.Context, pcr *PackageCleanupRule) error {
|
||||||
|
_, err := db.GetEngine(ctx).ID(pcr.ID).AllCols().Update(pcr)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetCleanupRulesByOwner(ctx context.Context, ownerID int64) ([]*PackageCleanupRule, error) {
|
||||||
|
pcrs := make([]*PackageCleanupRule, 0, 10)
|
||||||
|
return pcrs, db.GetEngine(ctx).Where("owner_id = ?", ownerID).Find(&pcrs)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeleteCleanupRuleByID(ctx context.Context, ruleID int64) error {
|
||||||
|
_, err := db.GetEngine(ctx).ID(ruleID).Delete(&PackageCleanupRule{})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func HasOwnerCleanupRuleForPackageType(ctx context.Context, ownerID int64, packageType Type) (bool, error) {
|
||||||
|
return db.GetEngine(ctx).
|
||||||
|
Where("owner_id = ? AND type = ?", ownerID, packageType).
|
||||||
|
Exist(&PackageCleanupRule{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func IterateEnabledCleanupRules(ctx context.Context, callback func(context.Context, *PackageCleanupRule) error) error {
|
||||||
|
return db.Iterate(
|
||||||
|
ctx,
|
||||||
|
builder.Eq{"enabled": true},
|
||||||
|
callback,
|
||||||
|
)
|
||||||
|
}
|
@ -320,6 +320,15 @@ func SearchLatestVersions(ctx context.Context, opts *PackageSearchOptions) ([]*P
|
|||||||
return pvs, count, err
|
return pvs, count, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExistVersion checks if a version matching the search options exist
|
||||||
|
func ExistVersion(ctx context.Context, opts *PackageSearchOptions) (bool, error) {
|
||||||
|
return db.GetEngine(ctx).
|
||||||
|
Where(opts.toConds()).
|
||||||
|
Table("package_version").
|
||||||
|
Join("INNER", "package", "package.id = package_version.package_id").
|
||||||
|
Exist(new(PackageVersion))
|
||||||
|
}
|
||||||
|
|
||||||
// CountVersions counts all versions of packages matching the search options
|
// CountVersions counts all versions of packages matching the search options
|
||||||
func CountVersions(ctx context.Context, opts *PackageSearchOptions) (int64, error) {
|
func CountVersions(ctx context.Context, opts *PackageSearchOptions) (int64, error) {
|
||||||
return db.GetEngine(ctx).
|
return db.GetEngine(ctx).
|
||||||
|
@ -36,34 +36,34 @@ func TestAccessLevel(t *testing.T) {
|
|||||||
// org. owned private repo
|
// org. owned private repo
|
||||||
repo24 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 24})
|
repo24 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 24})
|
||||||
|
|
||||||
level, err := access_model.AccessLevel(user2, repo1)
|
level, err := access_model.AccessLevel(db.DefaultContext, user2, repo1)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, perm_model.AccessModeOwner, level)
|
assert.Equal(t, perm_model.AccessModeOwner, level)
|
||||||
|
|
||||||
level, err = access_model.AccessLevel(user2, repo3)
|
level, err = access_model.AccessLevel(db.DefaultContext, user2, repo3)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, perm_model.AccessModeOwner, level)
|
assert.Equal(t, perm_model.AccessModeOwner, level)
|
||||||
|
|
||||||
level, err = access_model.AccessLevel(user5, repo1)
|
level, err = access_model.AccessLevel(db.DefaultContext, user5, repo1)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, perm_model.AccessModeRead, level)
|
assert.Equal(t, perm_model.AccessModeRead, level)
|
||||||
|
|
||||||
level, err = access_model.AccessLevel(user5, repo3)
|
level, err = access_model.AccessLevel(db.DefaultContext, user5, repo3)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, perm_model.AccessModeNone, level)
|
assert.Equal(t, perm_model.AccessModeNone, level)
|
||||||
|
|
||||||
// restricted user has no access to a public repo
|
// restricted user has no access to a public repo
|
||||||
level, err = access_model.AccessLevel(user29, repo1)
|
level, err = access_model.AccessLevel(db.DefaultContext, user29, repo1)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, perm_model.AccessModeNone, level)
|
assert.Equal(t, perm_model.AccessModeNone, level)
|
||||||
|
|
||||||
// ... unless he's a collaborator
|
// ... unless he's a collaborator
|
||||||
level, err = access_model.AccessLevel(user29, repo4)
|
level, err = access_model.AccessLevel(db.DefaultContext, user29, repo4)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, perm_model.AccessModeWrite, level)
|
assert.Equal(t, perm_model.AccessModeWrite, level)
|
||||||
|
|
||||||
// ... or a team member
|
// ... or a team member
|
||||||
level, err = access_model.AccessLevel(user29, repo24)
|
level, err = access_model.AccessLevel(db.DefaultContext, user29, repo24)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, perm_model.AccessModeRead, level)
|
assert.Equal(t, perm_model.AccessModeRead, level)
|
||||||
}
|
}
|
||||||
|
@ -326,17 +326,13 @@ func IsUserRepoAdmin(ctx context.Context, repo *repo_model.Repository, user *use
|
|||||||
|
|
||||||
// AccessLevel returns the Access a user has to a repository. Will return NoneAccess if the
|
// AccessLevel returns the Access a user has to a repository. Will return NoneAccess if the
|
||||||
// user does not have access.
|
// user does not have access.
|
||||||
func AccessLevel(user *user_model.User, repo *repo_model.Repository) (perm_model.AccessMode, error) { //nolint
|
func AccessLevel(ctx context.Context, user *user_model.User, repo *repo_model.Repository) (perm_model.AccessMode, error) { //nolint
|
||||||
return AccessLevelUnit(user, repo, unit.TypeCode)
|
return AccessLevelUnit(ctx, user, repo, unit.TypeCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AccessLevelUnit returns the Access a user has to a repository's. Will return NoneAccess if the
|
// AccessLevelUnit returns the Access a user has to a repository's. Will return NoneAccess if the
|
||||||
// user does not have access.
|
// user does not have access.
|
||||||
func AccessLevelUnit(user *user_model.User, repo *repo_model.Repository, unitType unit.Type) (perm_model.AccessMode, error) { //nolint
|
func AccessLevelUnit(ctx context.Context, user *user_model.User, repo *repo_model.Repository, unitType unit.Type) (perm_model.AccessMode, error) { //nolint
|
||||||
return accessLevelUnit(db.DefaultContext, user, repo, unitType)
|
|
||||||
}
|
|
||||||
|
|
||||||
func accessLevelUnit(ctx context.Context, user *user_model.User, repo *repo_model.Repository, unitType unit.Type) (perm_model.AccessMode, error) {
|
|
||||||
perm, err := GetUserRepoPermission(ctx, repo, user)
|
perm, err := GetUserRepoPermission(ctx, repo, user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return perm_model.AccessModeNone, err
|
return perm_model.AccessModeNone, err
|
||||||
@ -346,7 +342,7 @@ func accessLevelUnit(ctx context.Context, user *user_model.User, repo *repo_mode
|
|||||||
|
|
||||||
// HasAccessUnit returns true if user has testMode to the unit of the repository
|
// HasAccessUnit returns true if user has testMode to the unit of the repository
|
||||||
func HasAccessUnit(ctx context.Context, user *user_model.User, repo *repo_model.Repository, unitType unit.Type, testMode perm_model.AccessMode) (bool, error) {
|
func HasAccessUnit(ctx context.Context, user *user_model.User, repo *repo_model.Repository, unitType unit.Type, testMode perm_model.AccessMode) (bool, error) {
|
||||||
mode, err := accessLevelUnit(ctx, user, repo, unitType)
|
mode, err := AccessLevelUnit(ctx, user, repo, unitType)
|
||||||
return testMode <= mode, err
|
return testMode <= mode, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ func NewBoard(board *Board) error {
|
|||||||
|
|
||||||
// DeleteBoardByID removes all issues references to the project board.
|
// DeleteBoardByID removes all issues references to the project board.
|
||||||
func DeleteBoardByID(boardID int64) error {
|
func DeleteBoardByID(boardID int64) error {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@ func (p *Project) NumOpenIssues() int {
|
|||||||
|
|
||||||
// MoveIssuesOnProjectBoard moves or keeps issues in a column and sorts them inside that column
|
// MoveIssuesOnProjectBoard moves or keeps issues in a column and sorts them inside that column
|
||||||
func MoveIssuesOnProjectBoard(board *Board, sortedIssueIDs map[int64]int64) error {
|
func MoveIssuesOnProjectBoard(board *Board, sortedIssueIDs map[int64]int64) error {
|
||||||
return db.WithTx(func(ctx context.Context) error {
|
return db.WithTx(db.DefaultContext, func(ctx context.Context) error {
|
||||||
sess := db.GetEngine(ctx)
|
sess := db.GetEngine(ctx)
|
||||||
|
|
||||||
issueIDs := make([]int64, 0, len(sortedIssueIDs))
|
issueIDs := make([]int64, 0, len(sortedIssueIDs))
|
||||||
|
@ -180,7 +180,7 @@ func NewProject(p *Project) error {
|
|||||||
return errors.New("project type is not valid")
|
return errors.New("project type is not valid")
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -248,7 +248,7 @@ func updateRepositoryProjectCount(ctx context.Context, repoID int64) error {
|
|||||||
|
|
||||||
// ChangeProjectStatusByRepoIDAndID toggles a project between opened and closed
|
// ChangeProjectStatusByRepoIDAndID toggles a project between opened and closed
|
||||||
func ChangeProjectStatusByRepoIDAndID(repoID, projectID int64, isClosed bool) error {
|
func ChangeProjectStatusByRepoIDAndID(repoID, projectID int64, isClosed bool) error {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -272,7 +272,7 @@ func ChangeProjectStatusByRepoIDAndID(repoID, projectID int64, isClosed bool) er
|
|||||||
|
|
||||||
// ChangeProjectStatus toggle a project between opened and closed
|
// ChangeProjectStatus toggle a project between opened and closed
|
||||||
func ChangeProjectStatus(p *Project, isClosed bool) error {
|
func ChangeProjectStatus(p *Project, isClosed bool) error {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -301,7 +301,7 @@ func changeProjectStatus(ctx context.Context, p *Project, isClosed bool) error {
|
|||||||
|
|
||||||
// DeleteProjectByID deletes a project from a repository.
|
// DeleteProjectByID deletes a project from a repository.
|
||||||
func DeleteProjectByID(id int64) error {
|
func DeleteProjectByID(id int64) error {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ func Init() error {
|
|||||||
// DeleteRepository deletes a repository for a user or organization.
|
// DeleteRepository deletes a repository for a user or organization.
|
||||||
// make sure if you call this func to close open sessions (sqlite will otherwise get a deadlock)
|
// make sure if you call this func to close open sessions (sqlite will otherwise get a deadlock)
|
||||||
func DeleteRepository(doer *user_model.User, uid, repoID int64) error {
|
func DeleteRepository(doer *user_model.User, uid, repoID int64) error {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -569,7 +569,7 @@ func UpdateRepoStats(ctx context.Context, id int64) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func updateUserStarNumbers(users []user_model.User) error {
|
func updateUserStarNumbers(users []user_model.User) error {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -7,11 +7,14 @@ package repo
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
)
|
)
|
||||||
@ -44,6 +47,28 @@ func (archiver *RepoArchiver) RelativePath() string {
|
|||||||
return fmt.Sprintf("%d/%s/%s.%s", archiver.RepoID, archiver.CommitID[:2], archiver.CommitID, archiver.Type.String())
|
return fmt.Sprintf("%d/%s/%s.%s", archiver.RepoID, archiver.CommitID[:2], archiver.CommitID, archiver.Type.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// repoArchiverForRelativePath takes a relativePath created from (archiver *RepoArchiver) RelativePath() and creates a shell repoArchiver struct representing it
|
||||||
|
func repoArchiverForRelativePath(relativePath string) (*RepoArchiver, error) {
|
||||||
|
parts := strings.SplitN(relativePath, "/", 3)
|
||||||
|
if len(parts) != 3 {
|
||||||
|
return nil, util.SilentWrap{Message: fmt.Sprintf("invalid storage path: %s", relativePath), Err: util.ErrInvalidArgument}
|
||||||
|
}
|
||||||
|
repoID, err := strconv.ParseInt(parts[0], 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, util.SilentWrap{Message: fmt.Sprintf("invalid storage path: %s", relativePath), Err: util.ErrInvalidArgument}
|
||||||
|
}
|
||||||
|
nameExts := strings.SplitN(parts[2], ".", 2)
|
||||||
|
if len(nameExts) != 2 {
|
||||||
|
return nil, util.SilentWrap{Message: fmt.Sprintf("invalid storage path: %s", relativePath), Err: util.ErrInvalidArgument}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &RepoArchiver{
|
||||||
|
RepoID: repoID,
|
||||||
|
CommitID: parts[1] + nameExts[0],
|
||||||
|
Type: git.ToArchiveType(nameExts[1]),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
var delRepoArchiver = new(RepoArchiver)
|
var delRepoArchiver = new(RepoArchiver)
|
||||||
|
|
||||||
// DeleteRepoArchiver delete archiver
|
// DeleteRepoArchiver delete archiver
|
||||||
@ -65,6 +90,17 @@ func GetRepoArchiver(ctx context.Context, repoID int64, tp git.ArchiveType, comm
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExistsRepoArchiverWithStoragePath checks if there is a RepoArchiver for a given storage path
|
||||||
|
func ExistsRepoArchiverWithStoragePath(ctx context.Context, storagePath string) (bool, error) {
|
||||||
|
// We need to invert the path provided func (archiver *RepoArchiver) RelativePath() above
|
||||||
|
archiver, err := repoArchiverForRelativePath(storagePath)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return db.GetEngine(ctx).Exist(archiver)
|
||||||
|
}
|
||||||
|
|
||||||
// AddRepoArchiver adds an archiver
|
// AddRepoArchiver adds an archiver
|
||||||
func AddRepoArchiver(ctx context.Context, archiver *RepoArchiver) error {
|
func AddRepoArchiver(ctx context.Context, archiver *RepoArchiver) error {
|
||||||
_, err := db.GetEngine(ctx).Insert(archiver)
|
_, err := db.GetEngine(ctx).Insert(archiver)
|
||||||
|
@ -122,9 +122,9 @@ func GetAttachmentsByUUIDs(ctx context.Context, uuids []string) ([]*Attachment,
|
|||||||
return attachments, db.GetEngine(ctx).In("uuid", uuids).Find(&attachments)
|
return attachments, db.GetEngine(ctx).In("uuid", uuids).Find(&attachments)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExistAttachmentsByUUID returns true if attachment is exist by given UUID
|
// ExistAttachmentsByUUID returns true if attachment exists with the given UUID
|
||||||
func ExistAttachmentsByUUID(uuid string) (bool, error) {
|
func ExistAttachmentsByUUID(ctx context.Context, uuid string) (bool, error) {
|
||||||
return db.GetEngine(db.DefaultContext).Where("`uuid`=?", uuid).Exist(new(Attachment))
|
return db.GetEngine(ctx).Where("`uuid`=?", uuid).Exist(new(Attachment))
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAttachmentsByIssueID returns all attachments of an issue.
|
// GetAttachmentsByIssueID returns all attachments of an issue.
|
||||||
@ -226,20 +226,20 @@ func UpdateAttachment(ctx context.Context, atta *Attachment) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DeleteAttachmentsByRelease deletes all attachments associated with the given release.
|
// DeleteAttachmentsByRelease deletes all attachments associated with the given release.
|
||||||
func DeleteAttachmentsByRelease(releaseID int64) error {
|
func DeleteAttachmentsByRelease(ctx context.Context, releaseID int64) error {
|
||||||
_, err := db.GetEngine(db.DefaultContext).Where("release_id = ?", releaseID).Delete(&Attachment{})
|
_, err := db.GetEngine(ctx).Where("release_id = ?", releaseID).Delete(&Attachment{})
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// CountOrphanedAttachments returns the number of bad attachments
|
// CountOrphanedAttachments returns the number of bad attachments
|
||||||
func CountOrphanedAttachments() (int64, error) {
|
func CountOrphanedAttachments(ctx context.Context) (int64, error) {
|
||||||
return db.GetEngine(db.DefaultContext).Where("(issue_id > 0 and issue_id not in (select id from issue)) or (release_id > 0 and release_id not in (select id from `release`))").
|
return db.GetEngine(ctx).Where("(issue_id > 0 and issue_id not in (select id from issue)) or (release_id > 0 and release_id not in (select id from `release`))").
|
||||||
Count(new(Attachment))
|
Count(new(Attachment))
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteOrphanedAttachments delete all bad attachments
|
// DeleteOrphanedAttachments delete all bad attachments
|
||||||
func DeleteOrphanedAttachments() error {
|
func DeleteOrphanedAttachments(ctx context.Context) error {
|
||||||
_, err := db.GetEngine(db.DefaultContext).Where("(issue_id > 0 and issue_id not in (select id from issue)) or (release_id > 0 and release_id not in (select id from `release`))").
|
_, err := db.GetEngine(ctx).Where("(issue_id > 0 and issue_id not in (select id from issue)) or (release_id > 0 and release_id not in (select id from `release`))").
|
||||||
Delete(new(Attachment))
|
Delete(new(Attachment))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,13 @@ func (repo *Repository) CustomAvatarRelativePath() string {
|
|||||||
return repo.Avatar
|
return repo.Avatar
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExistsWithAvatarAtStoragePath returns true if there is a user with this Avatar
|
||||||
|
func ExistsWithAvatarAtStoragePath(ctx context.Context, storagePath string) (bool, error) {
|
||||||
|
// See func (repo *Repository) CustomAvatarRelativePath()
|
||||||
|
// repo.Avatar is used directly as the storage path - therefore we can check for existence directly using the path
|
||||||
|
return db.GetEngine(ctx).Where("`avatar`=?", storagePath).Exist(new(Repository))
|
||||||
|
}
|
||||||
|
|
||||||
// RelAvatarLink returns a relative link to the repository's avatar.
|
// RelAvatarLink returns a relative link to the repository's avatar.
|
||||||
func (repo *Repository) RelAvatarLink() string {
|
func (repo *Repository) RelAvatarLink() string {
|
||||||
return repo.relAvatarLink(db.DefaultContext)
|
return repo.relAvatarLink(db.DefaultContext)
|
||||||
|
@ -138,7 +138,7 @@ func ChangeCollaborationAccessModeCtx(ctx context.Context, repo *Repository, uid
|
|||||||
|
|
||||||
// ChangeCollaborationAccessMode sets new access mode for the collaboration.
|
// ChangeCollaborationAccessMode sets new access mode for the collaboration.
|
||||||
func ChangeCollaborationAccessMode(repo *Repository, uid int64, mode perm.AccessMode) error {
|
func ChangeCollaborationAccessMode(repo *Repository, uid int64, mode perm.AccessMode) error {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -110,7 +110,7 @@ func GetTopLanguageStats(repo *Repository, limit int) (LanguageStatList, error)
|
|||||||
|
|
||||||
// UpdateLanguageStats updates the language statistics for repository
|
// UpdateLanguageStats updates the language statistics for repository
|
||||||
func UpdateLanguageStats(repo *Repository, commitID string, stats map[string]int64) error {
|
func UpdateLanguageStats(repo *Repository, commitID string, stats map[string]int64) error {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -182,7 +182,7 @@ func UpdateLanguageStats(repo *Repository, commitID string, stats map[string]int
|
|||||||
|
|
||||||
// CopyLanguageStat Copy originalRepo language stat information to destRepo (use for forked repo)
|
// CopyLanguageStat Copy originalRepo language stat information to destRepo (use for forked repo)
|
||||||
func CopyLanguageStat(originalRepo, destRepo *Repository) error {
|
func CopyLanguageStat(originalRepo, destRepo *Repository) error {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -120,9 +120,9 @@ func GetPushMirrorsByRepoID(ctx context.Context, repoID int64, listOptions db.Li
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetPushMirrorsSyncedOnCommit returns push-mirrors for this repo that should be updated by new commits
|
// GetPushMirrorsSyncedOnCommit returns push-mirrors for this repo that should be updated by new commits
|
||||||
func GetPushMirrorsSyncedOnCommit(repoID int64) ([]*PushMirror, error) {
|
func GetPushMirrorsSyncedOnCommit(ctx context.Context, repoID int64) ([]*PushMirror, error) {
|
||||||
mirrors := make([]*PushMirror, 0, 10)
|
mirrors := make([]*PushMirror, 0, 10)
|
||||||
return mirrors, db.GetEngine(db.DefaultContext).
|
return mirrors, db.GetEngine(ctx).
|
||||||
Where("repo_id=? AND sync_on_commit=?", repoID, true).
|
Where("repo_id=? AND sync_on_commit=?", repoID, true).
|
||||||
Find(&mirrors)
|
Find(&mirrors)
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,8 @@ func init() {
|
|||||||
db.RegisterModel(new(Release))
|
db.RegisterModel(new(Release))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Release) loadAttributes(ctx context.Context) error {
|
// LoadAttributes load repo and publisher attributes for a release
|
||||||
|
func (r *Release) LoadAttributes(ctx context.Context) error {
|
||||||
var err error
|
var err error
|
||||||
if r.Repo == nil {
|
if r.Repo == nil {
|
||||||
r.Repo, err = GetRepositoryByIDCtx(ctx, r.RepoID)
|
r.Repo, err = GetRepositoryByIDCtx(ctx, r.RepoID)
|
||||||
@ -111,11 +112,6 @@ func (r *Release) loadAttributes(ctx context.Context) error {
|
|||||||
return GetReleaseAttachments(ctx, r)
|
return GetReleaseAttachments(ctx, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadAttributes load repo and publisher attributes for a release
|
|
||||||
func (r *Release) LoadAttributes() error {
|
|
||||||
return r.loadAttributes(db.DefaultContext)
|
|
||||||
}
|
|
||||||
|
|
||||||
// APIURL the api url for a release. release must have attributes loaded
|
// APIURL the api url for a release. release must have attributes loaded
|
||||||
func (r *Release) APIURL() string {
|
func (r *Release) APIURL() string {
|
||||||
return r.Repo.APIURL() + "/releases/" + strconv.FormatInt(r.ID, 10)
|
return r.Repo.APIURL() + "/releases/" + strconv.FormatInt(r.ID, 10)
|
||||||
@ -241,8 +237,8 @@ func (opts *FindReleasesOptions) toConds(repoID int64) builder.Cond {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetReleasesByRepoID returns a list of releases of repository.
|
// GetReleasesByRepoID returns a list of releases of repository.
|
||||||
func GetReleasesByRepoID(repoID int64, opts FindReleasesOptions) ([]*Release, error) {
|
func GetReleasesByRepoID(ctx context.Context, repoID int64, opts FindReleasesOptions) ([]*Release, error) {
|
||||||
sess := db.GetEngine(db.DefaultContext).
|
sess := db.GetEngine(ctx).
|
||||||
Desc("created_unix", "id").
|
Desc("created_unix", "id").
|
||||||
Where(opts.toConds(repoID))
|
Where(opts.toConds(repoID))
|
||||||
|
|
||||||
@ -381,8 +377,8 @@ func SortReleases(rels []*Release) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DeleteReleaseByID deletes a release from database by given ID.
|
// DeleteReleaseByID deletes a release from database by given ID.
|
||||||
func DeleteReleaseByID(id int64) error {
|
func DeleteReleaseByID(ctx context.Context, id int64) error {
|
||||||
_, err := db.GetEngine(db.DefaultContext).ID(id).Delete(new(Release))
|
_, err := db.GetEngine(ctx).ID(id).Delete(new(Release))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,14 +236,6 @@ func (repo *Repository) AfterLoad() {
|
|||||||
repo.NumOpenProjects = repo.NumProjects - repo.NumClosedProjects
|
repo.NumOpenProjects = repo.NumProjects - repo.NumClosedProjects
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustOwner always returns a valid *user_model.User object to avoid
|
|
||||||
// conceptually impossible error handling.
|
|
||||||
// It creates a fake object that contains error details
|
|
||||||
// when error occurs.
|
|
||||||
func (repo *Repository) MustOwner() *user_model.User {
|
|
||||||
return repo.mustOwner(db.DefaultContext)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadAttributes loads attributes of the repository.
|
// LoadAttributes loads attributes of the repository.
|
||||||
func (repo *Repository) LoadAttributes(ctx context.Context) error {
|
func (repo *Repository) LoadAttributes(ctx context.Context) error {
|
||||||
// Load owner
|
// Load owner
|
||||||
@ -403,7 +395,11 @@ func (repo *Repository) GetOwner(ctx context.Context) (err error) {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (repo *Repository) mustOwner(ctx context.Context) *user_model.User {
|
// MustOwner always returns a valid *user_model.User object to avoid
|
||||||
|
// conceptually impossible error handling.
|
||||||
|
// It creates a fake object that contains error details
|
||||||
|
// when error occurs.
|
||||||
|
func (repo *Repository) MustOwner(ctx context.Context) *user_model.User {
|
||||||
if err := repo.GetOwner(ctx); err != nil {
|
if err := repo.GetOwner(ctx); err != nil {
|
||||||
return &user_model.User{
|
return &user_model.User{
|
||||||
Name: "error",
|
Name: "error",
|
||||||
@ -438,7 +434,7 @@ func (repo *Repository) ComposeMetas() map[string]string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
repo.MustOwner()
|
repo.MustOwner(db.DefaultContext)
|
||||||
if repo.Owner.IsOrganization() {
|
if repo.Owner.IsOrganization() {
|
||||||
teams := make([]string, 0, 5)
|
teams := make([]string, 0, 5)
|
||||||
_ = db.GetEngine(db.DefaultContext).Table("team_repo").
|
_ = db.GetEngine(db.DefaultContext).Table("team_repo").
|
||||||
@ -792,13 +788,13 @@ func UpdateRepoIssueNumbers(ctx context.Context, repoID int64, isPull, isClosed
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CountNullArchivedRepository counts the number of repositories with is_archived is null
|
// CountNullArchivedRepository counts the number of repositories with is_archived is null
|
||||||
func CountNullArchivedRepository() (int64, error) {
|
func CountNullArchivedRepository(ctx context.Context) (int64, error) {
|
||||||
return db.GetEngine(db.DefaultContext).Where(builder.IsNull{"is_archived"}).Count(new(Repository))
|
return db.GetEngine(ctx).Where(builder.IsNull{"is_archived"}).Count(new(Repository))
|
||||||
}
|
}
|
||||||
|
|
||||||
// FixNullArchivedRepository sets is_archived to false where it is null
|
// FixNullArchivedRepository sets is_archived to false where it is null
|
||||||
func FixNullArchivedRepository() (int64, error) {
|
func FixNullArchivedRepository(ctx context.Context) (int64, error) {
|
||||||
return db.GetEngine(db.DefaultContext).Where(builder.IsNull{"is_archived"}).Cols("is_archived").NoAutoTime().Update(&Repository{
|
return db.GetEngine(ctx).Where(builder.IsNull{"is_archived"}).Cols("is_archived").NoAutoTime().Update(&Repository{
|
||||||
IsArchived: false,
|
IsArchived: false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -518,14 +518,13 @@ func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond {
|
|||||||
|
|
||||||
// SearchRepository returns repositories based on search options,
|
// SearchRepository returns repositories based on search options,
|
||||||
// it returns results in given range and number of total results.
|
// it returns results in given range and number of total results.
|
||||||
func SearchRepository(opts *SearchRepoOptions) (RepositoryList, int64, error) {
|
func SearchRepository(ctx context.Context, opts *SearchRepoOptions) (RepositoryList, int64, error) {
|
||||||
cond := SearchRepositoryCondition(opts)
|
cond := SearchRepositoryCondition(opts)
|
||||||
return SearchRepositoryByCondition(opts, cond, true)
|
return SearchRepositoryByCondition(ctx, opts, cond, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SearchRepositoryByCondition search repositories by condition
|
// SearchRepositoryByCondition search repositories by condition
|
||||||
func SearchRepositoryByCondition(opts *SearchRepoOptions, cond builder.Cond, loadAttributes bool) (RepositoryList, int64, error) {
|
func SearchRepositoryByCondition(ctx context.Context, opts *SearchRepoOptions, cond builder.Cond, loadAttributes bool) (RepositoryList, int64, error) {
|
||||||
ctx := db.DefaultContext
|
|
||||||
sess, count, err := searchRepositoryByCondition(ctx, opts, cond)
|
sess, count, err := searchRepositoryByCondition(ctx, opts, cond)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
@ -652,9 +651,9 @@ func AccessibleRepositoryCondition(user *user_model.User, unitType unit.Type) bu
|
|||||||
|
|
||||||
// SearchRepositoryByName takes keyword and part of repository name to search,
|
// SearchRepositoryByName takes keyword and part of repository name to search,
|
||||||
// it returns results in given range and number of total results.
|
// it returns results in given range and number of total results.
|
||||||
func SearchRepositoryByName(opts *SearchRepoOptions) (RepositoryList, int64, error) {
|
func SearchRepositoryByName(ctx context.Context, opts *SearchRepoOptions) (RepositoryList, int64, error) {
|
||||||
opts.IncludeDescription = false
|
opts.IncludeDescription = false
|
||||||
return SearchRepository(opts)
|
return SearchRepository(ctx, opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SearchRepositoryIDs takes keyword and part of repository name to search,
|
// SearchRepositoryIDs takes keyword and part of repository name to search,
|
||||||
|
@ -20,7 +20,7 @@ func TestSearchRepository(t *testing.T) {
|
|||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
// test search public repository on explore page
|
// test search public repository on explore page
|
||||||
repos, count, err := repo_model.SearchRepositoryByName(&repo_model.SearchRepoOptions{
|
repos, count, err := repo_model.SearchRepositoryByName(db.DefaultContext, &repo_model.SearchRepoOptions{
|
||||||
ListOptions: db.ListOptions{
|
ListOptions: db.ListOptions{
|
||||||
Page: 1,
|
Page: 1,
|
||||||
PageSize: 10,
|
PageSize: 10,
|
||||||
@ -35,7 +35,7 @@ func TestSearchRepository(t *testing.T) {
|
|||||||
}
|
}
|
||||||
assert.Equal(t, int64(1), count)
|
assert.Equal(t, int64(1), count)
|
||||||
|
|
||||||
repos, count, err = repo_model.SearchRepositoryByName(&repo_model.SearchRepoOptions{
|
repos, count, err = repo_model.SearchRepositoryByName(db.DefaultContext, &repo_model.SearchRepoOptions{
|
||||||
ListOptions: db.ListOptions{
|
ListOptions: db.ListOptions{
|
||||||
Page: 1,
|
Page: 1,
|
||||||
PageSize: 10,
|
PageSize: 10,
|
||||||
@ -49,7 +49,7 @@ func TestSearchRepository(t *testing.T) {
|
|||||||
assert.Len(t, repos, 2)
|
assert.Len(t, repos, 2)
|
||||||
|
|
||||||
// test search private repository on explore page
|
// test search private repository on explore page
|
||||||
repos, count, err = repo_model.SearchRepositoryByName(&repo_model.SearchRepoOptions{
|
repos, count, err = repo_model.SearchRepositoryByName(db.DefaultContext, &repo_model.SearchRepoOptions{
|
||||||
ListOptions: db.ListOptions{
|
ListOptions: db.ListOptions{
|
||||||
Page: 1,
|
Page: 1,
|
||||||
PageSize: 10,
|
PageSize: 10,
|
||||||
@ -65,7 +65,7 @@ func TestSearchRepository(t *testing.T) {
|
|||||||
}
|
}
|
||||||
assert.Equal(t, int64(1), count)
|
assert.Equal(t, int64(1), count)
|
||||||
|
|
||||||
repos, count, err = repo_model.SearchRepositoryByName(&repo_model.SearchRepoOptions{
|
repos, count, err = repo_model.SearchRepositoryByName(db.DefaultContext, &repo_model.SearchRepoOptions{
|
||||||
ListOptions: db.ListOptions{
|
ListOptions: db.ListOptions{
|
||||||
Page: 1,
|
Page: 1,
|
||||||
PageSize: 10,
|
PageSize: 10,
|
||||||
@ -80,14 +80,14 @@ func TestSearchRepository(t *testing.T) {
|
|||||||
assert.Len(t, repos, 3)
|
assert.Len(t, repos, 3)
|
||||||
|
|
||||||
// Test non existing owner
|
// Test non existing owner
|
||||||
repos, count, err = repo_model.SearchRepositoryByName(&repo_model.SearchRepoOptions{OwnerID: unittest.NonexistentID})
|
repos, count, err = repo_model.SearchRepositoryByName(db.DefaultContext, &repo_model.SearchRepoOptions{OwnerID: unittest.NonexistentID})
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Empty(t, repos)
|
assert.Empty(t, repos)
|
||||||
assert.Equal(t, int64(0), count)
|
assert.Equal(t, int64(0), count)
|
||||||
|
|
||||||
// Test search within description
|
// Test search within description
|
||||||
repos, count, err = repo_model.SearchRepository(&repo_model.SearchRepoOptions{
|
repos, count, err = repo_model.SearchRepository(db.DefaultContext, &repo_model.SearchRepoOptions{
|
||||||
ListOptions: db.ListOptions{
|
ListOptions: db.ListOptions{
|
||||||
Page: 1,
|
Page: 1,
|
||||||
PageSize: 10,
|
PageSize: 10,
|
||||||
@ -104,7 +104,7 @@ func TestSearchRepository(t *testing.T) {
|
|||||||
assert.Equal(t, int64(1), count)
|
assert.Equal(t, int64(1), count)
|
||||||
|
|
||||||
// Test NOT search within description
|
// Test NOT search within description
|
||||||
repos, count, err = repo_model.SearchRepository(&repo_model.SearchRepoOptions{
|
repos, count, err = repo_model.SearchRepository(db.DefaultContext, &repo_model.SearchRepoOptions{
|
||||||
ListOptions: db.ListOptions{
|
ListOptions: db.ListOptions{
|
||||||
Page: 1,
|
Page: 1,
|
||||||
PageSize: 10,
|
PageSize: 10,
|
||||||
@ -277,7 +277,7 @@ func TestSearchRepository(t *testing.T) {
|
|||||||
|
|
||||||
for _, testCase := range testCases {
|
for _, testCase := range testCases {
|
||||||
t.Run(testCase.name, func(t *testing.T) {
|
t.Run(testCase.name, func(t *testing.T) {
|
||||||
repos, count, err := repo_model.SearchRepositoryByName(testCase.opts)
|
repos, count, err := repo_model.SearchRepositoryByName(db.DefaultContext, testCase.opts)
|
||||||
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, int64(testCase.count), count)
|
assert.Equal(t, int64(testCase.count), count)
|
||||||
@ -377,7 +377,7 @@ func TestSearchRepositoryByTopicName(t *testing.T) {
|
|||||||
|
|
||||||
for _, testCase := range testCases {
|
for _, testCase := range testCases {
|
||||||
t.Run(testCase.name, func(t *testing.T) {
|
t.Run(testCase.name, func(t *testing.T) {
|
||||||
_, count, err := repo_model.SearchRepositoryByName(testCase.opts)
|
_, count, err := repo_model.SearchRepositoryByName(db.DefaultContext, testCase.opts)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, int64(testCase.count), count)
|
assert.Equal(t, int64(testCase.count), count)
|
||||||
})
|
})
|
||||||
|
@ -241,7 +241,7 @@ func UpdateRepoUnit(unit *RepoUnit) error {
|
|||||||
|
|
||||||
// UpdateRepositoryUnits updates a repository's units
|
// UpdateRepositoryUnits updates a repository's units
|
||||||
func UpdateRepositoryUnits(repo *Repository, units []RepoUnit, deleteUnitTypes []unit.Type) (err error) {
|
func UpdateRepositoryUnits(repo *Repository, units []RepoUnit, deleteUnitTypes []unit.Type) (err error) {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ func init() {
|
|||||||
|
|
||||||
// StarRepo or unstar repository.
|
// StarRepo or unstar repository.
|
||||||
func StarRepo(userID, repoID int64, star bool) error {
|
func StarRepo(userID, repoID int64, star bool) error {
|
||||||
ctx, committer, err := db.TxContext()
|
ctx, committer, err := db.TxContext(db.DefaultContext)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user