Compare commits

..

No commits in common. "knacker_workaround_backport" and "main" have entirely different histories.

381 changed files with 4189 additions and 6640 deletions

View File

@ -1,114 +0,0 @@
# 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

View File

@ -39,6 +39,16 @@ 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
@ -551,7 +561,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.28.0-focal image: mcr.microsoft.com/playwright:v1.27.1-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

View File

@ -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: [0] no-async-promise-executor: [2]
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,7 +229,6 @@ 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]
@ -270,7 +269,6 @@ 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]
@ -445,7 +443,6 @@ 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]
@ -456,7 +453,6 @@ 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]
@ -507,7 +503,6 @@ 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]

View File

@ -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 security-check checks-backend: tidy-check swagger-check fmt-check misspell-check swagger-validate
.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:
go run $(GOVULNCHECK_PACKAGE) -v ./... govulncheck -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 $@

View File

@ -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: "host", Name: "addr",
Value: "", Value: "",
Usage: "SMTP Host", Usage: "SMTP Addr",
}, },
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(ctx, &repo_model.SearchRepoOptions{ repos, count, err := repo_model.SearchRepositoryByName(&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("host") { if c.IsSet("addr") {
conf.Host = c.String("host") conf.Addr = c.String("addr")
} }
if c.IsSet("port") { if c.IsSet("port") {
conf.Port = c.Int("port") conf.Port = c.Int("port")

View File

@ -7,38 +7,6 @@
;; 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
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -58,7 +26,7 @@ RUN_MODE = ; prod
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; ;;
;; The protocol the server listens on. One of 'http', 'https', 'http+unix', 'fcgi' or 'fcgi+unix'. Defaults to 'http' ;; The protocol the server listens on. One of 'http', 'https', 'unix' or 'fcgi'. Defaults to 'http'
;PROTOCOL = http ;PROTOCOL = http
;; ;;
;; Expect PROXY protocol headers on connections ;; Expect PROXY protocol headers on connections
@ -83,8 +51,6 @@ 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.
@ -98,7 +64,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)s ;REDIRECTOR_USE_PROXY_PROTOCOL = %(USE_PROXY_PROTOCOL)
;; 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=
@ -125,7 +91,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)s ;LOCAL_USE_PROXY_PROTOCOL = %(USE_PROXY_PROTOCOL)
;; ;;
;; Disable SSH feature when not available ;; Disable SSH feature when not available
;DISABLE_SSH = false ;DISABLE_SSH = false
@ -179,7 +145,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)s ;; relative paths are made absolute relative to the APP_DATA_PATH
;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,
@ -275,10 +241,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 = ; Will default to the built-in value _`StaticRootPath`_ ;STATIC_ROOT_PATH =
;; ;;
;; Default path for App data ;; Default path for App data
;APP_DATA_PATH = data ; relative paths will be made absolute with _`AppWorkPath`_ ;APP_DATA_PATH = data
;; ;;
;; 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
@ -289,7 +255,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 ; Path is relative to _`AppWorkPath`_ ;PPROF_DATA_PATH = data/tmp/pprof
;; ;;
;; 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.
@ -667,7 +633,7 @@ ROUTER = console
;PATH = ;PATH =
;; ;;
;; The HOME directory for Git ;; The HOME directory for Git
;HOME_PATH = %(APP_DATA_PATH)s/home ;HOME_PATH = %(APP_DATA_PATH)/home
;; ;;
;; Disables highlight of added and removed changes ;; Disables highlight of added and removed changes
;DISABLE_DIFF_HIGHLIGHT = false ;DISABLE_DIFF_HIGHLIGHT = false
@ -872,8 +838,8 @@ ROUTER = console
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;[repository] ;[repository]
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Root path for storing all repository data. By default, it is set to %(APP_DATA_PATH)s/gitea-repositories. ;; Root path for storing all repository data. By default, it is set to %(APP_DATA_PATH)/gitea-repositories.
;; A relative path is interpreted as _`AppWorkPath`_/%(ROOT)s ;; A relative path is interpreted as %(GITEA_WORK_DIR)/%(ROOT)
;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.
@ -1138,9 +1104,6 @@ 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
@ -1333,7 +1296,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 ; Relative paths will be made absolute against _`AppWorkPath`_. ;ISSUE_INDEXER_PATH = indexers/issues.bleve
;; ;;
;; 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
@ -1351,7 +1314,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]`. Relative paths will be made absolute against `%(APP_DATA_PATH)s`. ;ISSUE_INDEXER_QUEUE_DIR = queues/common; **DEPRECATED** use settings in `[queue.issue_indexer]`.
;; ;;
;; 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
@ -1407,7 +1370,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/ ; Relative paths will be made absolute against `%(APP_DATA_PATH)s`. ;DATADIR = queues/
;; ;;
;; Default queue length before a channel queue will block ;; Default queue length before a channel queue will block
;LENGTH = 20 ;LENGTH = 20
@ -1709,7 +1672,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 ; Relative paths will be made absolute against _`AppWorkPath`_. ;PROVIDER_CONFIG = data/sessions
;; ;;
;; Session cookie name ;; Session cookie name
;COOKIE_NAME = i_like_gitea ;COOKIE_NAME = i_like_gitea
@ -2234,9 +2197,7 @@ 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
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -27,56 +27,23 @@ 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`: **_current OS username_/`$USER`/`$USERNAME` e.g. git**: The user Gitea will run as. - `RUN_USER`: **git**: The user Gitea will run as. This should be a dedicated system
This should be a dedicated system (non-user) account. Setting this incorrectly will cause Gitea (non-user) account. Setting this incorrectly will cause Gitea to not start.
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)s/gitea-repositories**: Root path for storing all repository data. - `ROOT`: **%(APP_DATA_PATH)/gitea-repositories**: Root path for storing all repository data.
A relative path is interpreted as **_`AppWorkPath`_/%(ROOT)s**. A relative path is interpreted as **%(GITEA_WORK_DIR)/%(ROOT)**.
- `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.
@ -200,7 +167,6 @@ 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`)
@ -274,7 +240,6 @@ 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.
@ -289,17 +254,12 @@ 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/assets/css/index.css` or `https://cdn.example.com/assets/css/index.css` respectively. Requests are then made as `%(ROOT_URL)s/static/css/index.css` and `https://cdn.example.com/css/index.css` respective.
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.
@ -309,7 +269,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)s**: When making local connections pass the PROXY protocol header. - `LOCAL_USE_PROXY_PROTOCOL`: **%(USE_PROXY_PROTOCOL)**: 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.)
@ -319,7 +279,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)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_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_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.
@ -348,22 +308,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`: **_`StaticRootPath`_**: Upper level of template and static files path. - `STATIC_ROOT_PATH`: **./**: Upper level of template and static files path.
- `APP_DATA_PATH`: **data** (**/data/gitea** on docker): Default path for application data. Relative paths will be made absolute against _`AppWorkPath`_. - `APP_DATA_PATH`: **data** (**/data/gitea** on docker): Default path for application data.
- `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`: **_`AppWorkPath`_/data/tmp/pprof**: `PPROF_DATA_PATH`, use an absolute path when you start Gitea as service - `PPROF_DATA_PATH`: **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)s/lfs**: Default LFS content path. (if it is on local storage.) **DEPRECATED** use settings in `[lfs]`. - `LFS_CONTENT_PATH`: **%(APP_DATA_PATH)/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)s**: expect PROXY protocol header on connections to https redirector. - `REDIRECTOR_USE_PROXY_PROTOCOL`: **%(USE_PROXY_PROTOCOL)**: 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.
@ -453,10 +413,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. Relative paths will be made absolute against _`AppWorkPath`_. - `ISSUE_INDEXER_PATH`: **indexers/issues.bleve**: Index file used for issue search; available when ISSUE_INDEXER_TYPE is bleve and elasticsearch.
- 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]`. Relative paths will be made absolute against `%(APP_DATA_PATH)s`. - `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_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]`.
@ -478,7 +438,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`**.) Relative paths will be made absolute against `%(APP_DATA_PATH)s`. - `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`**.)
- `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`
@ -762,7 +722,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. Relative paths will be made absolute against _`AppWorkPath`_. - `PROVIDER_CONFIG`: **data/sessions**: For file, the root path; for db, empty (database config will be used); for others, the connection string.
- `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.
@ -1020,7 +980,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)s/home**: The HOME directory for Git. - `HOME_PATH`: **%(APP_DATA_PATH)/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.
@ -1288,4 +1248,3 @@ 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.

View File

@ -15,14 +15,6 @@ 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 >}}
@ -31,166 +23,6 @@ As mentioned below, there is a fully functional log output by default, so it is
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
@ -340,6 +172,106 @@ 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

View File

@ -41,15 +41,13 @@ 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. Note that the requested **password** can also be your access token. 3. If the repository needs authentication expand the **Authorization** section and fill in your authentication information.
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.
@ -61,11 +59,9 @@ 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. 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. 2. Fill in the **Git Remote Repository URL**: `https://github.com/<your_github_group>/<your_github_project>.git`.
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`. 3. Fill in the **Authorization** fields with your GitHub username and the personal access token.
4. Fill in the **Authorization** fields with your GitHub username and the personal access token as **Password**. 4. Select **Add Push Mirror** to save the configuration.
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.

View File

@ -166,47 +166,11 @@ Uses the following fields:
## PAM (Pluggable Authentication Module) ## PAM (Pluggable Authentication Module)
This procedure enables PAM authentication. Users may still be added to the To configure PAM, set the 'PAM Service Name' to a filename in `/etc/pam.d/`. To
system manually using the user administration. PAM provides a mechanism to work with normal Linux passwords, the user running Gitea must have read access
automatically add users to the current database by testing them against PAM to `/etc/shadow`.
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**: If a user has added SSH public keys into Gitea, the use of these **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.
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)

View File

@ -58,33 +58,29 @@ https://github.com/loganinak/MigrateGitlabToGogs
## Where does Gitea store what file ## Where does Gitea store what file
- _`AppWorkPath`_ - WorkPath
- The `--work-path` flag - Environment variable `GITEA_WORK_DIR`
- Else Environment variable `GITEA_WORK_DIR` - Else `--work-path` flag
- 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
- `%(APP_DATA_PATH)` (default for database, indexers, etc.) - AppDataPath (default for database, indexers, etc.)
- `APP_DATA_PATH` from `app.ini` - `APP_DATA_PATH` from `app.ini`
- Else _`AppWorkPath`_`/data` - Else `%(WorkPath)/data`
- _`CustomPath`_ (custom templates) - CustomPath (custom templates)
- The `--custom-path` flag - Environment variable `GITEA_CUSTOM`
- Else Environment variable `GITEA_CUSTOM` - Else `%(WorkPath)/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 `%(APP_DATA_PATH)/gitea-repositories` - Default `%(AppDataPath)/gitea-repositories`
- INI (config file) - INI (config file)
- `--config` flag - `-c` flag
- A possible built-in value set a build time - Else `%(CustomPath)/conf/app.ini`
- Else _`CustomPath`_`/conf/app.ini`
- SQLite Database - SQLite Database
- `PATH` in `database` section of `app.ini` - `PATH` in `database` section of `app.ini`
- Else `%(APP_DATA_PATH)/gitea.db` - Else `%(AppDataPath)/gitea.db`
## Not seeing a clone URL or the clone URL being incorrect ## Not seeing a clone URL or the clone URL being incorrect

View File

@ -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. Required for production build. - `bindata`: Build a single monolithic binary, with all assets included.
- `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,10 +103,11 @@ 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 all assets (JS/CSS/templates, etc) into the binary. Using the `bindata` build tag is required for Bundling assets into the binary using the `bindata` build tag is recommended for
production deployments. You could exclude `bindata` when you are developing/testing Gitea or able to separate the assets correctly. production deployments. It is possible to serve the static assets directly via a reverse proxy,
but in most cases it is not necessary, and assets should still be bundled in the binary.
To include all assets, use the `bindata` tag: You may want to exclude bindata while developing/testing Gitea.
To include assets, add the `bindata` tag:
```bash ```bash
TAGS="bindata" make build TAGS="bindata" make build
@ -143,11 +144,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.
@ -155,10 +156,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`

View File

@ -1,84 +0,0 @@
---
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.

View File

@ -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.), plural: die Branches * _Der_ Branch (m.)
* _Das_ Issue (n.) * _Das_ Issue (n.)
* _Der_ Fork (m.) * _Der_ Fork (m.)
* _Das_ Repository (n.), plural: die Repositories * _Das_ Repository (n.)
* _Der_ Pull-Request (m.) * _Der_ Pull-Request (m.)
* _Der_ Token (m.), plural: die Token * _Der_ Token (m.)
* _Das_ Review (n.) * _Das_ Review (n.)
* _Der_ Key (m.) * _Der_ Key (m.)
* _Der_ Committer (m.), plural: die Committer * _Der_ Committer (m.)
## Weiterführende Links ## Weiterführende Links

10
go.mod
View File

@ -94,14 +94,15 @@ 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.2.1-0.20221112162523-6fad3dfc1891 golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be
golang.org/x/net v0.2.0 golang.org/x/net v0.0.0-20220927171203-f486391704dc
golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1 golang.org/x/oauth2 v0.0.0-20220909003341-f21342109be1
golang.org/x/sys v0.2.0 golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec
golang.org/x/text v0.4.0 golang.org/x/text v0.3.8
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
@ -292,7 +293,6 @@ 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
View File

@ -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.2.1-0.20221112162523-6fad3dfc1891 h1:WhEPFM1Ck5gaKybeSWvzI7Y/cd8K9K5tJGRxXMACOBA= golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be h1:fmw3UbQh+nxngCAHrDCCztao/kbYFnWjoqop8dHx05A=
golang.org/x/crypto v0.2.1-0.20221112162523-6fad3dfc1891/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.0.0-20220926161630-eccd6366d1be/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
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.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU= golang.org/x/net v0.0.0-20220927171203-f486391704dc h1:FxpXZdoBqT8RjqTy6i1E8nXHhW21wK7ptQ/EPIGxzPQ=
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.0.0-20220927171203-f486391704dc/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
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.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A= golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec h1:BkDtF2Ih9xZ7le9ndzTA7KJow28VbQW3odyk/8drmuI=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/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.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=

View File

@ -461,8 +461,7 @@ func DeleteOldActions(olderThan time.Duration) (err error) {
return err return err
} }
// NotifyWatchers creates batch of actions for every watcher. func notifyWatchers(ctx context.Context, actions ...*Action) error {
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
@ -566,15 +565,20 @@ 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(db.DefaultContext) ctx, committer, err := db.TxContext()
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
} }
} }
@ -599,17 +603,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(ctx context.Context) (int64, error) { func CountActionCreatedUnixString() (int64, error) {
if setting.Database.UseSQLite3 { if setting.Database.UseSQLite3 {
return db.GetEngine(ctx).Where(`created_unix = ""`).Count(new(Action)) return db.GetEngine(db.DefaultContext).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(ctx context.Context) (int64, error) { func FixActionCreatedUnixString() (int64, error) {
if setting.Database.UseSQLite3 { if setting.Database.UseSQLite3 {
res, err := db.GetEngine(ctx).Exec(`UPDATE action SET created_unix = 0 WHERE created_unix = ""`) res, err := db.GetEngine(db.DefaultContext).Exec(`UPDATE action SET created_unix = 0 WHERE created_unix = ""`)
if err != nil { if err != nil {
return 0, err return 0, err
} }

View File

@ -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(db.DefaultContext, action)) assert.NoError(t, activities_model.NotifyWatchers(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(db.DefaultContext) count, err := activities_model.CountActionCreatedUnixString()
assert.NoError(t, err) assert.NoError(t, err)
assert.EqualValues(t, 1, count) assert.EqualValues(t, 1, count)
count, err = activities_model.FixActionCreatedUnixString(db.DefaultContext) count, err = activities_model.FixActionCreatedUnixString()
assert.NoError(t, err) assert.NoError(t, err)
assert.EqualValues(t, 1, count) assert.EqualValues(t, 1, count)
count, err = activities_model.CountActionCreatedUnixString(db.DefaultContext) count, err = activities_model.CountActionCreatedUnixString()
assert.NoError(t, err) assert.NoError(t, err)
assert.EqualValues(t, 0, count) assert.EqualValues(t, 0, count)
count, err = activities_model.FixActionCreatedUnixString(db.DefaultContext) count, err = activities_model.FixActionCreatedUnixString()
assert.NoError(t, err) assert.NoError(t, err)
assert.EqualValues(t, 0, count) assert.EqualValues(t, 0, count)

View File

@ -136,48 +136,56 @@ 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(ctx context.Context, opts *FindNotificationOptions) (int64, error) { func CountNotifications(opts *FindNotificationOptions) (int64, error) {
return db.GetEngine(ctx).Where(opts.ToCond()).Count(&Notification{}) return db.GetEngine(db.DefaultContext).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(ctx context.Context, doer, newOwner *user_model.User, repo *repo_model.Repository) error { func CreateRepoTransferNotification(doer, newOwner *user_model.User, repo *repo_model.Repository) error {
return db.AutoTx(ctx, func(ctx context.Context) error { ctx, committer, err := db.TxContext()
var notify []*Notification if err != nil {
return err
}
defer committer.Close()
if newOwner.IsOrganization() { var notify []*Notification
users, err := organization.GetUsersWhoCanCreateOrgRepo(ctx, newOwner.ID)
if err != nil || len(users) == 0 { if newOwner.IsOrganization() {
return err users, err := organization.GetUsersWhoCanCreateOrgRepo(ctx, newOwner.ID)
} if err != nil || len(users) == 0 {
for i := range users { return err
notify = append(notify, &Notification{ }
UserID: users[i].ID, for i := range users {
RepoID: repo.ID, notify = append(notify, &Notification{
Status: NotificationStatusUnread, UserID: users[i].ID,
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,
}}
}
return db.Insert(ctx, notify) if err := db.Insert(ctx, notify); err != nil {
}) 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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }
@ -371,7 +379,11 @@ 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(ctx context.Context) (err error) { func (n *Notification) LoadAttributes() (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
} }
@ -469,10 +481,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(ctx context.Context) error { func (nl NotificationList) LoadAttributes() 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(ctx) err = nl[i].LoadAttributes()
if err != nil && !issues_model.IsErrCommentNotExist(err) { if err != nil && !issues_model.IsErrCommentNotExist(err) {
return err return err
} }
@ -492,7 +504,7 @@ func (nl NotificationList) getPendingRepoIDs() []int64 {
} }
// LoadRepos loads repositories from database // LoadRepos loads repositories from database
func (nl NotificationList) LoadRepos(ctx context.Context) (repo_model.RepositoryList, []int, error) { func (nl NotificationList) LoadRepos() (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
} }
@ -505,7 +517,7 @@ func (nl NotificationList) LoadRepos(ctx context.Context) (repo_model.Repository
if left < limit { if left < limit {
limit = left limit = left
} }
rows, err := db.GetEngine(ctx). rows, err := db.GetEngine(db.DefaultContext).
In("id", repoIDs[:limit]). In("id", repoIDs[:limit]).
Rows(new(repo_model.Repository)) Rows(new(repo_model.Repository))
if err != nil { if err != nil {
@ -566,7 +578,7 @@ func (nl NotificationList) getPendingIssueIDs() []int64 {
} }
// LoadIssues loads issues from database // LoadIssues loads issues from database
func (nl NotificationList) LoadIssues(ctx context.Context) ([]int, error) { func (nl NotificationList) LoadIssues() ([]int, error) {
if len(nl) == 0 { if len(nl) == 0 {
return []int{}, nil return []int{}, nil
} }
@ -579,7 +591,7 @@ func (nl NotificationList) LoadIssues(ctx context.Context) ([]int, error) {
if left < limit { if left < limit {
limit = left limit = left
} }
rows, err := db.GetEngine(ctx). rows, err := db.GetEngine(db.DefaultContext).
In("id", issueIDs[:limit]). In("id", issueIDs[:limit]).
Rows(new(issues_model.Issue)) Rows(new(issues_model.Issue))
if err != nil { if err != nil {
@ -650,7 +662,7 @@ func (nl NotificationList) getPendingCommentIDs() []int64 {
} }
// LoadComments loads comments from database // LoadComments loads comments from database
func (nl NotificationList) LoadComments(ctx context.Context) ([]int, error) { func (nl NotificationList) LoadComments() ([]int, error) {
if len(nl) == 0 { if len(nl) == 0 {
return []int{}, nil return []int{}, nil
} }
@ -663,7 +675,7 @@ func (nl NotificationList) LoadComments(ctx context.Context) ([]int, error) {
if left < limit { if left < limit {
limit = left limit = left
} }
rows, err := db.GetEngine(ctx). rows, err := db.GetEngine(db.DefaultContext).
In("id", commentIDs[:limit]). In("id", commentIDs[:limit]).
Rows(new(issues_model.Comment)) Rows(new(issues_model.Comment))
if err != nil { if err != nil {
@ -763,8 +775,8 @@ func SetRepoReadBy(ctx context.Context, userID, repoID int64) error {
} }
// SetNotificationStatus change the notification status // SetNotificationStatus change the notification status
func SetNotificationStatus(ctx context.Context, notificationID int64, user *user_model.User, status NotificationStatus) (*Notification, error) { func SetNotificationStatus(notificationID int64, user *user_model.User, status NotificationStatus) (*Notification, error) {
notification, err := GetNotificationByID(ctx, notificationID) notification, err := getNotificationByID(db.DefaultContext, notificationID)
if err != nil { if err != nil {
return notification, err return notification, err
} }
@ -775,12 +787,16 @@ func SetNotificationStatus(ctx context.Context, notificationID int64, user *user
notification.Status = status notification.Status = status
_, err = db.GetEngine(ctx).ID(notificationID).Update(notification) _, err = db.GetEngine(db.DefaultContext).ID(notificationID).Update(notification)
return notification, err return notification, err
} }
// GetNotificationByID return notification by ID // GetNotificationByID return notification by ID
func GetNotificationByID(ctx context.Context, notificationID int64) (*Notification, error) { func GetNotificationByID(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).
@ -797,9 +813,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(ctx context.Context, user *user_model.User, currentStatus, desiredStatus NotificationStatus) error { func UpdateNotificationStatuses(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(ctx). _, err := db.GetEngine(db.DefaultContext).
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)

View File

@ -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(db.DefaultContext, notf.ID, user, activities_model.NotificationStatusPinned) _, err := activities_model.SetNotificationStatus(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(db.DefaultContext, 1, user, activities_model.NotificationStatusRead) _, err = activities_model.SetNotificationStatus(1, user, activities_model.NotificationStatusRead)
assert.Error(t, err) assert.Error(t, err)
_, err = activities_model.SetNotificationStatus(db.DefaultContext, unittest.NonexistentID, user, activities_model.NotificationStatusRead) _, err = activities_model.SetNotificationStatus(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(db.DefaultContext, user, activities_model.NotificationStatusUnread, activities_model.NotificationStatusRead)) assert.NoError(t, activities_model.UpdateNotificationStatuses(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,

View File

@ -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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }

View File

@ -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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return "", err return "", err
} }

View File

@ -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(db.DefaultContext) ctx, committer, err := db.TxContext()
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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return false, err return false, err
} }

View File

@ -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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return "", err return "", err
} }

View File

@ -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(db.DefaultContext) ctx, committer, err := db.TxContext()
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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }

View File

@ -37,7 +37,7 @@ func ReadSession(key string) (*Session, error) {
Key: key, Key: key,
} }
ctx, committer, err := db.TxContext(db.DefaultContext) ctx, committer, err := db.TxContext()
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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -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(db.DefaultContext, func(ctx context.Context) error { if err := db.WithTx(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,11 +150,10 @@ func generateEmailAvatarLink(email string, size int, final bool) string {
return DefaultAvatarLink() return DefaultAvatarLink()
} }
enableFederatedAvatarSetting, _ := system_model.GetSetting(system_model.KeyPictureEnableFederatedAvatar) enableFederatedAvatar, _ := system_model.GetSetting(system_model.KeyPictureEnableFederatedAvatar)
enableFederatedAvatar := enableFederatedAvatarSetting.GetValueBool()
var err error var err error
if enableFederatedAvatar && system_model.LibravatarService != nil { if enableFederatedAvatar != nil && enableFederatedAvatar.GetValueBool() && 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
@ -172,10 +171,8 @@ func generateEmailAvatarLink(email string, size int, final bool) string {
return urlStr return urlStr
} }
disableGravatarSetting, _ := system_model.GetSetting(system_model.KeyPictureDisableGravatar) disableGravatar, _ := 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))

View File

@ -4,16 +4,11 @@
package db package db
import ( import "xorm.io/builder"
"context"
"xorm.io/builder"
)
// CountOrphanedObjects count subjects with have no existing refobject anymore // CountOrphanedObjects count subjects with have no existing refobject anymore
func CountOrphanedObjects(ctx context.Context, subject, refobject, joinCond string) (int64, error) { func CountOrphanedObjects(subject, refobject, joinCond string) (int64, error) {
return GetEngine(ctx). return GetEngine(DefaultContext).Table("`"+subject+"`").
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`)").
@ -21,12 +16,12 @@ func CountOrphanedObjects(ctx context.Context, subject, refobject, joinCond stri
} }
// DeleteOrphanedObjects delete subjects with have no existing refobject anymore // DeleteOrphanedObjects delete subjects with have no existing refobject anymore
func DeleteOrphanedObjects(ctx context.Context, subject, refobject, joinCond string) error { func DeleteOrphanedObjects(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(ctx).Exec(b) _, err := GetEngine(DefaultContext).Exec(b)
return err return err
} }

View File

@ -8,7 +8,6 @@ import (
"context" "context"
"database/sql" "database/sql"
"xorm.io/xorm"
"xorm.io/xorm/schemas" "xorm.io/xorm/schemas"
) )
@ -87,11 +86,7 @@ type Committer interface {
} }
// TxContext represents a transaction Context // TxContext represents a transaction Context
func TxContext(parentCtx context.Context) (*Context, Committer, error) { func TxContext() (*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()
@ -102,24 +97,14 @@ func TxContext(parentCtx context.Context) (*Context, Committer, error) {
} }
// WithTx represents executing database operations on a transaction // WithTx represents executing database operations on a transaction
// This function will always open a new transaction, if a transaction exist in parentCtx return an error. // you can optionally change the context to a parent one
func WithTx(parentCtx context.Context, f func(ctx context.Context) error) error { func WithTx(f func(ctx context.Context) error, stdCtx ...context.Context) error {
if InTransaction(parentCtx) { parentCtx := DefaultContext
return ErrAlreadyInTransaction if len(stdCtx) != 0 && stdCtx[0] != nil {
// 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 {
@ -195,28 +180,3 @@ 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
}
}

View File

@ -1,33 +0,0 @@
// 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
}))
}

View File

@ -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(db.DefaultContext, "pull_request", "issue", "pull_request.issue_id=issue.id") orphaned, err := db.CountOrphanedObjects("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(db.DefaultContext, "pull_request", "issue", "pull_request.issue_id=issue.id") err = db.DeleteOrphanedObjects("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{})

View File

@ -5,14 +5,11 @@
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

View File

@ -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(db.DefaultContext, func(ctx context.Context) error { err = db.WithTx(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(db.DefaultContext, func(ctx context.Context) error { err = db.WithTx(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(db.DefaultContext, func(ctx context.Context) error { err = db.WithTx(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(db.DefaultContext, func(ctx context.Context) error { err = db.WithTx(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)

View File

@ -5,7 +5,6 @@
package db package db
import ( import (
"context"
"fmt" "fmt"
"regexp" "regexp"
@ -13,7 +12,7 @@ import (
) )
// CountBadSequences looks for broken sequences from recreate-table mistakes // CountBadSequences looks for broken sequences from recreate-table mistakes
func CountBadSequences(_ context.Context) (int64, error) { func CountBadSequences() (int64, error) {
if !setting.Database.UsePostgreSQL { if !setting.Database.UsePostgreSQL {
return 0, nil return 0, nil
} }
@ -34,7 +33,7 @@ func CountBadSequences(_ context.Context) (int64, error) {
} }
// FixBadSequences fixes for broken sequences from recreate-table mistakes // FixBadSequences fixes for broken sequences from recreate-table mistakes
func FixBadSequences(_ context.Context) error { func FixBadSequences() error {
if !setting.Database.UsePostgreSQL { if !setting.Database.UsePostgreSQL {
return nil return nil
} }

View File

@ -22,7 +22,7 @@ func GetYamlFixturesAccess() (string, error) {
} }
for _, repo := range repos { for _, repo := range repos {
repo.MustOwner(db.DefaultContext) repo.MustOwner()
if err := access_model.RecalculateAccesses(db.DefaultContext, repo); err != nil { if err := access_model.RecalculateAccesses(db.DefaultContext, repo); err != nil {
return "", err return "", err
} }

View File

@ -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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }

View File

@ -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(db.DefaultContext) ctx, committer, err := db.TxContext()
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{

View File

@ -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(db.DefaultContext) ctx, commiter, err := db.TxContext()
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(db.DefaultContext) ctx, committer, err := db.TxContext()
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)
} }

View File

@ -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(db.DefaultContext) ctx, committer, err := db.TxContext()
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(db.DefaultContext) ctx, committer, err := db.TxContext()
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
} }
// ExistsLFSObject checks if a provided Oid exists within the DB // LFSObjectIsAssociated checks if a provided Oid is associated
func ExistsLFSObject(ctx context.Context, oid string) (bool, error) { func LFSObjectIsAssociated(oid string) (bool, error) {
return db.GetEngine(ctx).Exist(&LFSMetaObject{Pointer: lfs.Pointer{Oid: oid}}) return db.GetEngine(db.DefaultContext).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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }

View File

@ -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(db.DefaultContext) dbCtx, committer, err := db.TxContext()
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(db.DefaultContext) dbCtx, committer, err := db.TxContext()
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -5,7 +5,6 @@
package git package git
import ( import (
"context"
"regexp" "regexp"
"strings" "strings"
@ -70,13 +69,13 @@ func UpdateProtectedTag(pt *ProtectedTag) error {
} }
// DeleteProtectedTag deletes a protected tag by ID // DeleteProtectedTag deletes a protected tag by ID
func DeleteProtectedTag(ctx context.Context, pt *ProtectedTag) error { func DeleteProtectedTag(pt *ProtectedTag) error {
_, err := db.GetEngine(ctx).ID(pt.ID).Delete(&ProtectedTag{}) _, err := db.GetEngine(db.DefaultContext).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(ctx context.Context, pt *ProtectedTag, userID int64) (bool, error) { func IsUserAllowedModifyTag(pt *ProtectedTag, userID int64) (bool, error) {
if base.Int64sContains(pt.AllowlistUserIDs, userID) { if base.Int64sContains(pt.AllowlistUserIDs, userID) {
return true, nil return true, nil
} }
@ -85,7 +84,7 @@ func IsUserAllowedModifyTag(ctx context.Context, pt *ProtectedTag, userID int64)
return false, nil return false, nil
} }
in, err := organization.IsUserInTeams(ctx, userID, pt.AllowlistTeamIDs) in, err := organization.IsUserInTeams(db.DefaultContext, userID, pt.AllowlistTeamIDs)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -93,9 +92,9 @@ func IsUserAllowedModifyTag(ctx context.Context, pt *ProtectedTag, userID int64)
} }
// GetProtectedTags gets all protected tags of the repository // GetProtectedTags gets all protected tags of the repository
func GetProtectedTags(ctx context.Context, repoID int64) ([]*ProtectedTag, error) { func GetProtectedTags(repoID int64) ([]*ProtectedTag, error) {
tags := make([]*ProtectedTag, 0) tags := make([]*ProtectedTag, 0)
return tags, db.GetEngine(ctx).Find(&tags, &ProtectedTag{RepoID: repoID}) return tags, db.GetEngine(db.DefaultContext).Find(&tags, &ProtectedTag{RepoID: repoID})
} }
// GetProtectedTagByID gets the protected tag with the specific id // GetProtectedTagByID gets the protected tag with the specific id
@ -113,7 +112,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(ctx context.Context, tags []*ProtectedTag, tagName string, userID int64) (bool, error) { func IsUserAllowedToControlTag(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()
@ -125,7 +124,7 @@ func IsUserAllowedToControlTag(ctx context.Context, tags []*ProtectedTag, tagNam
continue continue
} }
isAllowed, err = IsUserAllowedModifyTag(ctx, tag, userID) isAllowed, err = IsUserAllowedModifyTag(tag, userID)
if err != nil { if err != nil {
return false, err return false, err
} }

View File

@ -7,7 +7,6 @@ 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"
@ -18,29 +17,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(db.DefaultContext, pt, 1) allowed, err := git_model.IsUserAllowedModifyTag(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(db.DefaultContext, pt, 1) allowed, err = git_model.IsUserAllowedModifyTag(pt, 1)
assert.NoError(t, err) assert.NoError(t, err)
assert.True(t, allowed) assert.True(t, allowed)
allowed, err = git_model.IsUserAllowedModifyTag(db.DefaultContext, pt, 2) allowed, err = git_model.IsUserAllowedModifyTag(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(db.DefaultContext, pt, 1) allowed, err = git_model.IsUserAllowedModifyTag(pt, 1)
assert.NoError(t, err) assert.NoError(t, err)
assert.False(t, allowed) assert.False(t, allowed)
allowed, err = git_model.IsUserAllowedModifyTag(db.DefaultContext, pt, 2) allowed, err = git_model.IsUserAllowedModifyTag(pt, 2)
assert.NoError(t, err) assert.NoError(t, err)
assert.True(t, allowed) assert.True(t, allowed)
@ -48,11 +47,11 @@ func TestIsUserAllowed(t *testing.T) {
AllowlistUserIDs: []int64{1}, AllowlistUserIDs: []int64{1},
AllowlistTeamIDs: []int64{1}, AllowlistTeamIDs: []int64{1},
} }
allowed, err = git_model.IsUserAllowedModifyTag(db.DefaultContext, pt, 1) allowed, err = git_model.IsUserAllowedModifyTag(pt, 1)
assert.NoError(t, err) assert.NoError(t, err)
assert.True(t, allowed) assert.True(t, allowed)
allowed, err = git_model.IsUserAllowedModifyTag(db.DefaultContext, pt, 2) allowed, err = git_model.IsUserAllowedModifyTag(pt, 2)
assert.NoError(t, err) assert.NoError(t, err)
assert.True(t, allowed) assert.True(t, allowed)
} }
@ -136,7 +135,7 @@ func TestIsUserAllowedToControlTag(t *testing.T) {
} }
for n, c := range cases { for n, c := range cases {
isAllowed, err := git_model.IsUserAllowedToControlTag(db.DefaultContext, protectedTags, c.name, c.userid) isAllowed, err := git_model.IsUserAllowedToControlTag(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)
} }
@ -158,7 +157,7 @@ func TestIsUserAllowedToControlTag(t *testing.T) {
} }
for n, c := range cases { for n, c := range cases {
isAllowed, err := git_model.IsUserAllowedToControlTag(db.DefaultContext, protectedTags, c.name, c.userid) isAllowed, err := git_model.IsUserAllowedToControlTag(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)
} }

View File

@ -48,10 +48,9 @@ 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(ctx context.Context, issueID int64) ([]int64, error) { func GetAssigneeIDsByIssue(issueID int64) ([]int64, error) {
userIDs := make([]int64, 0, 5) userIDs := make([]int64, 0, 5)
return userIDs, db.GetEngine(ctx). return userIDs, db.GetEngine(db.DefaultContext).Table("issue_assignees").
Table("issue_assignees").
Cols("assignee_id"). Cols("assignee_id").
Where("issue_id = ?", issueID). Where("issue_id = ?", issueID).
Distinct("assignee_id"). Distinct("assignee_id").
@ -65,7 +64,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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return false, nil, err return false, nil, err
} }
@ -152,7 +151,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(ctx context.Context, oneAssignee string, multipleAssignees []string) (assigneeIDs []int64, err error) { func MakeIDsFromAPIAssigneesToAdd(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
@ -166,7 +165,7 @@ func MakeIDsFromAPIAssigneesToAdd(ctx context.Context, oneAssignee string, multi
} }
// Get the IDs of all assignees // Get the IDs of all assignees
assigneeIDs, err = user_model.GetUserIDsByNames(ctx, requestAssignees, false) assigneeIDs, err = user_model.GetUserIDsByNames(requestAssignees, false)
return assigneeIDs, err return assigneeIDs, err
} }

View File

@ -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(db.DefaultContext, "", []string{""}) IDs, err := issues_model.MakeIDsFromAPIAssigneesToAdd("", []string{""})
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, []int64{}, IDs) assert.Equal(t, []int64{}, IDs)
_, err = issues_model.MakeIDsFromAPIAssigneesToAdd(db.DefaultContext, "", []string{"none_existing_user"}) _, err = issues_model.MakeIDsFromAPIAssigneesToAdd("", []string{"none_existing_user"})
assert.Error(t, err) assert.Error(t, err)
IDs, err = issues_model.MakeIDsFromAPIAssigneesToAdd(db.DefaultContext, "user1", []string{"user1"}) IDs, err = issues_model.MakeIDsFromAPIAssigneesToAdd("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(db.DefaultContext, "user2", []string{""}) IDs, err = issues_model.MakeIDsFromAPIAssigneesToAdd("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(db.DefaultContext, "", []string{"user1", "user2"}) IDs, err = issues_model.MakeIDsFromAPIAssigneesToAdd("", []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)
} }

View File

@ -309,8 +309,13 @@ type PushActionContent struct {
CommitIDs []string `json:"commit_ids"` CommitIDs []string `json:"commit_ids"`
} }
// LoadIssue loads the issue reference for the comment // LoadIssue loads issue from database
func (c *Comment) LoadIssue(ctx context.Context) (err error) { func (c *Comment) LoadIssue() (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
} }
@ -345,8 +350,7 @@ func (c *Comment) AfterLoad(session *xorm.Session) {
} }
} }
// LoadPoster loads comment poster func (c *Comment) loadPoster(ctx context.Context) (err error) {
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
} }
@ -377,7 +381,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(db.DefaultContext) err := c.LoadIssue()
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 ""
@ -406,7 +410,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(db.DefaultContext) err := c.LoadIssue()
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 ""
@ -422,7 +426,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(db.DefaultContext) err := c.LoadIssue()
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 ""
@ -442,7 +446,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(db.DefaultContext) err := c.LoadIssue()
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 ""
@ -517,10 +521,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(ctx context.Context) error { func (c *Comment) LoadMilestone() error {
if c.OldMilestoneID > 0 { if c.OldMilestoneID > 0 {
var oldMilestone Milestone var oldMilestone Milestone
has, err := db.GetEngine(ctx).ID(c.OldMilestoneID).Get(&oldMilestone) has, err := db.GetEngine(db.DefaultContext).ID(c.OldMilestoneID).Get(&oldMilestone)
if err != nil { if err != nil {
return err return err
} else if has { } else if has {
@ -530,7 +534,7 @@ func (c *Comment) LoadMilestone(ctx context.Context) error {
if c.MilestoneID > 0 { if c.MilestoneID > 0 {
var milestone Milestone var milestone Milestone
has, err := db.GetEngine(ctx).ID(c.MilestoneID).Get(&milestone) has, err := db.GetEngine(db.DefaultContext).ID(c.MilestoneID).Get(&milestone)
if err != nil { if err != nil {
return err return err
} else if has { } else if has {
@ -540,14 +544,19 @@ func (c *Comment) LoadMilestone(ctx context.Context) 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(ctx context.Context) error { func (c *Comment) LoadAttachments() 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(ctx, c.ID) c.Attachments, err = repo_model.GetAttachmentsByCommentID(db.DefaultContext, c.ID)
if err != nil { if err != nil {
log.Error("getAttachmentsByCommentID[%d]: %v", c.ID, err) log.Error("getAttachmentsByCommentID[%d]: %v", c.ID, err)
} }
@ -556,7 +565,7 @@ func (c *Comment) LoadAttachments(ctx context.Context) 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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }
@ -589,7 +598,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(db.DefaultContext); err != nil { if err = c.LoadIssue(); err != nil {
return err return err
} }
@ -731,7 +740,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(db.DefaultContext) err := c.LoadIssue()
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 ""
@ -994,7 +1003,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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -1126,7 +1135,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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }
@ -1136,7 +1145,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.LoadIssue(ctx); err != nil { if err := c.LoadIssueCtx(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 {
@ -1236,7 +1245,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
} }
@ -1354,11 +1363,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.LoadIssue(ctx); err != nil { if err = pr.LoadIssueCtx(ctx); err != nil {
return return
} }
if err = pr.LoadBaseRepo(ctx); err != nil { if err = pr.LoadBaseRepoCtx(ctx); err != nil {
return return
} }
@ -1503,18 +1512,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(ctx context.Context) (int64, error) { func CountCommentTypeLabelWithEmptyLabel() (int64, error) {
return db.GetEngine(ctx).Where(builder.Eq{"type": CommentTypeLabel, "label_id": 0}).Count(new(Comment)) return db.GetEngine(db.DefaultContext).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(ctx context.Context) (int64, error) { func FixCommentTypeLabelWithEmptyLabel() (int64, error) {
return db.GetEngine(ctx).Where(builder.Eq{"type": CommentTypeLabel, "label_id": 0}).Delete(new(Comment)) return db.GetEngine(db.DefaultContext).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(ctx context.Context) (int64, error) { func CountCommentTypeLabelWithOutsideLabels() (int64, error) {
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). 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).
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 ").
@ -1523,8 +1532,8 @@ func CountCommentTypeLabelWithOutsideLabels(ctx context.Context) (int64, error)
} }
// FixCommentTypeLabelWithOutsideLabels count label comments with outside label // FixCommentTypeLabelWithOutsideLabels count label comments with outside label
func FixCommentTypeLabelWithOutsideLabels(ctx context.Context) (int64, error) { func FixCommentTypeLabelWithOutsideLabels() (int64, error) {
res, err := db.GetEngine(ctx).Exec(`DELETE FROM comment WHERE comment.id IN ( res, err := db.GetEngine(db.DefaultContext).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

View File

@ -24,8 +24,7 @@ func (comments CommentList) getPosterIDs() []int64 {
return posterIDs.Values() return posterIDs.Values()
} }
// LoadPosters loads posters func (comments CommentList) loadPosters(ctx context.Context) error {
func (comments CommentList) LoadPosters(ctx context.Context) error {
if len(comments) == 0 { if len(comments) == 0 {
return nil return nil
} }
@ -278,8 +277,7 @@ func (comments CommentList) Issues() IssueList {
return issueList return issueList
} }
// LoadIssues loads issues of comments func (comments CommentList) loadIssues(ctx context.Context) error {
func (comments CommentList) LoadIssues(ctx context.Context) error {
if len(comments) == 0 { if len(comments) == 0 {
return nil return nil
} }
@ -384,8 +382,7 @@ func (comments CommentList) loadDependentIssues(ctx context.Context) error {
return nil return nil
} }
// LoadAttachments loads attachments func (comments CommentList) loadAttachments(ctx context.Context) (err error) {
func (comments CommentList) LoadAttachments(ctx context.Context) (err error) {
if len(comments) == 0 { if len(comments) == 0 {
return nil return nil
} }
@ -479,7 +476,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
} }
@ -499,7 +496,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
} }
@ -507,7 +504,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
} }
@ -523,3 +520,18 @@ 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)
}

View File

@ -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(db.DefaultContext) ctx, committer, err := db.TxContext()
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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }

View File

@ -241,7 +241,11 @@ func (issue *Issue) LoadLabels(ctx context.Context) (err error) {
} }
// LoadPoster loads poster // LoadPoster loads poster
func (issue *Issue) LoadPoster(ctx context.Context) (err error) { func (issue *Issue) LoadPoster() 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 {
@ -257,8 +261,7 @@ func (issue *Issue) LoadPoster(ctx context.Context) (err error) {
return err return err
} }
// LoadPullRequest loads pull request info func (issue *Issue) loadPullRequest(ctx context.Context) (err error) {
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 {
@ -272,13 +275,18 @@ 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(ctx context.Context) error { func (issue *Issue) LoadDiscussComments() error {
return issue.loadCommentsByType(ctx, CommentTypeComment) return issue.loadCommentsByType(db.DefaultContext, CommentTypeComment)
} }
func (issue *Issue) loadCommentsByType(ctx context.Context, tp CommentType) (err error) { func (issue *Issue) loadCommentsByType(ctx context.Context, tp CommentType) (err error) {
@ -349,8 +357,7 @@ func (issue *Issue) loadForeignReference(ctx context.Context) (err error) {
return nil return nil
} }
// LoadMilestone load milestone of this issue. func (issue *Issue) loadMilestone(ctx context.Context) (err error) {
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) {
@ -366,7 +373,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
} }
@ -374,7 +381,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
} }
@ -386,7 +393,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
} }
@ -418,6 +425,11 @@ 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}
@ -528,7 +540,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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }
@ -536,7 +548,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
} }
@ -576,7 +588,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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }
@ -739,7 +751,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
} }
@ -748,7 +760,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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }
@ -782,7 +794,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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }
@ -832,7 +844,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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }
@ -852,7 +864,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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }
@ -1015,7 +1027,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
} }
@ -1057,7 +1069,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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }
@ -1493,9 +1505,10 @@ 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(ctx context.Context, opts *IssuesOptions) (map[int64]int64, error) { func CountIssuesByRepo(opts *IssuesOptions) (map[int64]int64, error) {
sess := db.GetEngine(ctx). e := db.GetEngine(db.DefaultContext)
Join("INNER", "repository", "`issue`.repo_id = `repository`.id")
sess := e.Join("INNER", "repository", "`issue`.repo_id = `repository`.id")
opts.setupSessionNoLimit(sess) opts.setupSessionNoLimit(sess)
@ -1538,9 +1551,10 @@ 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(ctx context.Context, opts *IssuesOptions) ([]*Issue, error) { func Issues(opts *IssuesOptions) ([]*Issue, error) {
sess := db.GetEngine(ctx). e := db.GetEngine(db.DefaultContext)
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)
@ -1558,11 +1572,11 @@ func Issues(ctx context.Context, opts *IssuesOptions) ([]*Issue, error) {
} }
// CountIssues number return of issues by given conditions. // CountIssues number return of issues by given conditions.
func CountIssues(ctx context.Context, opts *IssuesOptions) (int64, error) { func CountIssues(opts *IssuesOptions) (int64, error) {
sess := db.GetEngine(ctx). e := db.GetEngine(db.DefaultContext)
Select("COUNT(issue.id) AS count").
Table("issue"). sess := e.Select("COUNT(issue.id) AS count").Table("issue")
Join("INNER", "repository", "`issue`.repo_id = `repository`.id") sess.Join("INNER", "repository", "`issue`.repo_id = `repository`.id")
opts.setupSessionNoLimit(sess) opts.setupSessionNoLimit(sess)
return sess.Count() return sess.Count()
@ -1571,10 +1585,9 @@ func CountIssues(ctx context.Context, 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(ctx context.Context, issueID int64) ([]int64, error) { func GetParticipantsIDsByIssueID(issueID int64) ([]int64, error) {
userIDs := make([]int64, 0, 5) userIDs := make([]int64, 0, 5)
return userIDs, db.GetEngine(ctx). return userIDs, db.GetEngine(db.DefaultContext).Table("comment").
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).
@ -1973,7 +1986,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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return nil, false, err return nil, false, err
} }
@ -2031,7 +2044,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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }
@ -2413,9 +2426,8 @@ 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(ctx context.Context) (int64, error) { func CountOrphanedIssues() (int64, error) {
return db.GetEngine(ctx). return db.GetEngine(db.DefaultContext).Table("issue").
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`)").
@ -2423,31 +2435,35 @@ func CountOrphanedIssues(ctx context.Context) (int64, error) {
} }
// DeleteOrphanedIssues delete issues without a repo // DeleteOrphanedIssues delete issues without a repo
func DeleteOrphanedIssues(ctx context.Context) error { func DeleteOrphanedIssues() error {
var attachmentPaths []string ctx, committer, err := db.TxContext()
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 {

View File

@ -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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }

View File

@ -34,8 +34,7 @@ func (issues IssueList) getRepoIDs() []int64 {
return repoIDs.Values() return repoIDs.Values()
} }
// LoadRepositories loads issues' all repositories func (issues IssueList) loadRepositories(ctx context.Context) ([]*repo_model.Repository, error) {
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
} }
@ -74,6 +73,11 @@ 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 {
@ -313,8 +317,7 @@ func (issues IssueList) getPullIssueIDs() []int64 {
return ids return ids
} }
// LoadPullRequests loads pull requests func (issues IssueList) loadPullRequests(ctx context.Context) error {
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
@ -358,8 +361,7 @@ func (issues IssueList) LoadPullRequests(ctx context.Context) error {
return nil return nil
} }
// LoadAttachments loads attachments func (issues IssueList) loadAttachments(ctx context.Context) (err error) {
func (issues IssueList) LoadAttachments(ctx context.Context) (err error) {
if len(issues) == 0 { if len(issues) == 0 {
return nil return nil
} }
@ -511,8 +513,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 {
@ -535,7 +537,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)
} }
@ -552,14 +554,24 @@ 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(ctx context.Context) error { func (issues IssueList) LoadComments() error {
return issues.loadComments(ctx, builder.NewCond()) return issues.loadComments(db.DefaultContext, builder.NewCond())
} }
// LoadDiscussComments loads discuss comments // LoadDiscussComments loads discuss comments
func (issues IssueList) LoadDiscussComments(ctx context.Context) error { func (issues IssueList) LoadDiscussComments() error {
return issues.loadComments(ctx, builder.Eq{"comment.type": CommentTypeComment}) return issues.loadComments(db.DefaultContext, 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

View File

@ -7,7 +7,6 @@ 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"
@ -24,7 +23,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(db.DefaultContext) repos, err := issueList.LoadRepositories()
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 {

View File

@ -40,7 +40,7 @@ func updateIssueLock(opts *IssueLockOptions, lock bool) error {
commentType = CommentTypeUnlock commentType = CommentTypeUnlock
} }
ctx, committer, err := db.TxContext(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }

View File

@ -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(ctx context.Context, b *project_model.Board) (IssueList, error) { func LoadIssuesFromBoard(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(ctx, &IssuesOptions{ issues, err := Issues(&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(ctx context.Context, b *project_model.Board) (IssueList
} }
if b.Default { if b.Default {
issues, err := Issues(ctx, &IssuesOptions{ issues, err := Issues(&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(ctx context.Context, b *project_model.Board) (IssueList
issueList = append(issueList, issues...) issueList = append(issueList, issues...)
} }
if err := IssueList(issueList).LoadComments(ctx); err != nil { if err := IssueList(issueList).LoadComments(); err != nil {
return nil, err return nil, err
} }
@ -96,10 +96,10 @@ func LoadIssuesFromBoard(ctx context.Context, b *project_model.Board) (IssueList
} }
// LoadIssuesFromBoardList load issues assigned to the boards // LoadIssuesFromBoardList load issues assigned to the boards
func LoadIssuesFromBoardList(ctx context.Context, bs project_model.BoardList) (map[int64]IssueList, error) { func LoadIssuesFromBoardList(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(ctx, bs[i]) il, err := LoadIssuesFromBoard(bs[i])
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -110,7 +110,7 @@ func LoadIssuesFromBoardList(ctx context.Context, bs project_model.BoardList) (m
// 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(db.DefaultContext) ctx, committer, err := db.TxContext()
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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }

View File

@ -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(db.DefaultContext, &test.Opts) issues, err := issues_model.Issues(&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(db.DefaultContext, &issues_model.IssuesOptions{}) count, err := issues_model.CountIssues(&issues_model.IssuesOptions{})
assert.NoError(t, err) assert.NoError(t, err)
assert.EqualValues(t, 17, count) assert.EqualValues(t, 17, count)
} }

View File

@ -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.LoadIssue(stdCtx); err != nil { if err := c.LoadIssueCtx(stdCtx); err != nil {
return err return err
} }
ctx := &crossReferencesContext{ ctx := &crossReferencesContext{

View File

@ -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(db.DefaultContext) ctx, committer, err := db.TxContext()
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(db.DefaultContext) ctx, committer, err := db.TxContext()
assert.NoError(t, err) assert.NoError(t, err)
defer committer.Close() defer committer.Close()
err = db.Insert(ctx, c) err = db.Insert(ctx, c)

View File

@ -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(ctx context.Context, repoID, labelID int64) { func (label *Label) CalOpenOrgIssues(repoID, labelID int64) {
counts, _ := CountIssuesByRepo(ctx, &IssuesOptions{ counts, _ := CountIssuesByRepo(&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(db.DefaultContext) ctx, committer, err := db.TxContext()
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(db.DefaultContext) ctx, committer, err := db.TxContext()
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(ctx context.Context, repoID int64, labelIDs []int64) ([]*Label, error) { func GetLabelsInRepoByIDs(repoID int64, labelIDs []int64) ([]*Label, error) {
labels := make([]*Label, 0, len(labelIDs)) labels := make([]*Label, 0, len(labelIDs))
return labels, db.GetEngine(ctx). return labels, db.GetEngine(db.DefaultContext).
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(ctx context.Context, orgID int64, labelIDs []int64) ([]*Label, error) { func GetLabelsInOrgByIDs(orgID int64, labelIDs []int64) ([]*Label, error) {
labels := make([]*Label, 0, len(labelIDs)) labels := make([]*Label, 0, len(labelIDs))
return labels, db.GetEngine(ctx). return labels, db.GetEngine(db.DefaultContext).
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(db.DefaultContext) ctx, committer, err := db.TxContext()
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(db.DefaultContext) ctx, committer, err := db.TxContext()
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(ctx context.Context) (int64, error) { func CountOrphanedLabels() (int64, error) {
noref, err := db.GetEngine(ctx).Table("label").Where("repo_id=? AND org_id=?", 0, 0).Count() noref, err := db.GetEngine(db.DefaultContext).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(ctx).Table("label"). norepo, err := db.GetEngine(db.DefaultContext).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(ctx context.Context) (int64, error) {
return 0, err return 0, err
} }
noorg, err := db.GetEngine(ctx).Table("label"). noorg, err := db.GetEngine(db.DefaultContext).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(ctx context.Context) (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(ctx context.Context) error { func DeleteOrphanedLabels() error {
// delete labels with no reference // delete labels with no reference
if _, err := db.GetEngine(ctx).Table("label").Where("repo_id=? AND org_id=?", 0, 0).Delete(new(Label)); err != nil { if _, err := db.GetEngine(db.DefaultContext).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(ctx). if _, err := db.GetEngine(db.DefaultContext).
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(ctx context.Context) error {
} }
// delete labels with none existing orgs // delete labels with none existing orgs
if _, err := db.GetEngine(ctx). if _, err := db.GetEngine(db.DefaultContext).
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(ctx context.Context) 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(ctx context.Context) (int64, error) { func CountOrphanedIssueLabels() (int64, error) {
return db.GetEngine(ctx).Table("issue_label"). return db.GetEngine(db.DefaultContext).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(ctx context.Context) error { func DeleteOrphanedIssueLabels() error {
_, err := db.GetEngine(ctx). _, err := db.GetEngine(db.DefaultContext).
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(ctx context.Context) (int64, error) { func CountIssueLabelWithOutsideLabels() (int64, error) {
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)")). 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)")).
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(ctx context.Context) (int64, error) {
} }
// FixIssueLabelWithOutsideLabels fix label comments with outside label // FixIssueLabelWithOutsideLabels fix label comments with outside label
func FixIssueLabelWithOutsideLabels(ctx context.Context) (int64, error) { func FixIssueLabelWithOutsideLabels() (int64, error) {
res, err := db.GetEngine(ctx).Exec(`DELETE FROM issue_label WHERE issue_label.id IN ( res, err := db.GetEngine(db.DefaultContext).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

View File

@ -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(db.DefaultContext, 1, []int64{1, 2, unittest.NonexistentID}) labels, err := issues_model.GetLabelsInRepoByIDs(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(db.DefaultContext, 3, []int64{3, 4, unittest.NonexistentID}) labels, err := issues_model.GetLabelsInOrgByIDs(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(db.DefaultContext) ctx, committer, err := db.TxContext()
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))

View File

@ -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(db.DefaultContext) ctx, committer, err := db.TxContext()
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(db.DefaultContext) ctx, committer, err := db.TxContext()
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(db.DefaultContext) ctx, committer, err := db.TxContext()
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(db.DefaultContext) ctx, committer, err := db.TxContext()
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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }

View File

@ -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(ctx context.Context) string { func (pr *PullRequest) MustHeadUserName() string {
if err := pr.LoadHeadRepo(ctx); err != nil { if err := pr.LoadHeadRepo(); 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,9 +220,8 @@ func (pr *PullRequest) MustHeadUserName(ctx context.Context) 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) {
@ -236,8 +235,13 @@ func (pr *PullRequest) LoadAttributes(ctx context.Context) (err error) {
return nil return nil
} }
// LoadHeadRepo loads the head repository // LoadAttributes loads pull request attributes from database
func (pr *PullRequest) LoadHeadRepo(ctx context.Context) (err error) { func (pr *PullRequest) LoadAttributes() 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 {
@ -258,8 +262,18 @@ func (pr *PullRequest) LoadHeadRepo(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(ctx context.Context) (err error) { func (pr *PullRequest) LoadBaseRepo() 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
} }
@ -282,7 +296,12 @@ func (pr *PullRequest) LoadBaseRepo(ctx context.Context) (err error) {
} }
// LoadIssue loads issue information from database // LoadIssue loads issue information from database
func (pr *PullRequest) LoadIssue(ctx context.Context) (err error) { func (pr *PullRequest) LoadIssue() (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
} }
@ -349,7 +368,7 @@ func (pr *PullRequest) getReviewedByLines(writer io.Writer) error {
return nil return nil
} }
ctx, committer, err := db.TxContext(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }
@ -373,7 +392,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 {
@ -439,7 +458,7 @@ func (pr *PullRequest) SetMerged(ctx context.Context) (bool, error) {
} }
pr.Issue = nil pr.Issue = nil
if err := pr.LoadIssue(ctx); err != nil { if err := pr.LoadIssueCtx(ctx); err != nil {
return false, err return false, err
} }
@ -479,7 +498,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(outerCtx) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }
@ -522,9 +541,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(ctx context.Context, headRepoID, baseRepoID int64, headBranch, baseBranch string, flow PullRequestFlow) (*PullRequest, error) { func GetUnmergedPullRequest(headRepoID, baseRepoID int64, headBranch, baseBranch string, flow PullRequestFlow) (*PullRequest, error) {
pr := new(PullRequest) pr := new(PullRequest)
has, err := db.GetEngine(ctx). has, err := db.GetEngine(db.DefaultContext).
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").
@ -569,10 +588,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.LoadIssue(ctx); err != nil { if err = pr.LoadIssueCtx(ctx); err != nil {
return nil, err return nil, err
} }
@ -588,7 +607,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.
@ -615,7 +634,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
@ -645,15 +664,14 @@ 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(ctx context.Context, cols ...string) error { func (pr *PullRequest) UpdateColsIfNotMerged(cols ...string) error {
_, err := db.GetEngine(ctx).Where("id = ? AND has_merged = ?", pr.ID, false).Cols(cols...).Update(pr) _, err := db.GetEngine(db.DefaultContext).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(db.DefaultContext); err != nil { if err := pr.LoadIssue(); err != nil {
log.Error("LoadIssue: %v", err) log.Error("LoadIssue: %v", err)
return false return false
} }
@ -677,8 +695,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(ctx context.Context) string { func (pr *PullRequest) GetWorkInProgressPrefix() string {
if err := pr.LoadIssue(ctx); err != nil { if err := pr.LoadIssue(); err != nil {
log.Error("LoadIssue: %v", err) log.Error("LoadIssue: %v", err)
return "" return ""
} }
@ -721,7 +739,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(db.DefaultContext); err != nil { if err := pr.LoadBaseRepo(); err != nil {
log.Error("LoadBaseRepo: %v", err) log.Error("LoadBaseRepo: %v", err)
return "" return ""
} }
@ -737,7 +755,7 @@ func (pr *PullRequest) GetHeadBranchHTMLURL() string {
return "" return ""
} }
if err := pr.LoadHeadRepo(db.DefaultContext); err != nil { if err := pr.LoadHeadRepo(); err != nil {
log.Error("LoadHeadRepo: %v", err) log.Error("LoadHeadRepo: %v", err)
return "" return ""
} }

View File

@ -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(db.DefaultContext) err = pr.LoadBaseRepo()
if err != nil { if err != nil {
continue continue
} }

View File

@ -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(db.DefaultContext)) assert.NoError(t, pr.LoadAttributes())
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(db.DefaultContext)) assert.NoError(t, pr.LoadIssue())
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(db.DefaultContext)) assert.NoError(t, pr.LoadIssue())
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(db.DefaultContext)) assert.NoError(t, pr.LoadBaseRepo())
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(db.DefaultContext)) assert.NoError(t, pr.LoadBaseRepo())
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(db.DefaultContext)) assert.NoError(t, pr.LoadHeadRepo())
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(db.DefaultContext, 1, 1, "branch2", "master", issues_model.PullRequestFlowGithub) pr, err := issues_model.GetUnmergedPullRequest(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(db.DefaultContext, 1, 9223372036854775807, "branch1", "master", issues_model.PullRequestFlowGithub) _, err = issues_model.GetUnmergedPullRequest(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(db.DefaultContext) pr.LoadIssue()
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(db.DefaultContext) pr.LoadIssue()
assert.Empty(t, pr.GetWorkInProgressPrefix(db.DefaultContext)) assert.Empty(t, pr.GetWorkInProgressPrefix())
original := pr.Issue.Title original := pr.Issue.Title
pr.Issue.Title = "WIP: " + original pr.Issue.Title = "WIP: " + original
assert.Equal(t, "WIP:", pr.GetWorkInProgressPrefix(db.DefaultContext)) assert.Equal(t, "WIP:", pr.GetWorkInProgressPrefix())
pr.Issue.Title = "[wip] " + original pr.Issue.Title = "[wip] " + original
assert.Equal(t, "[wip]", pr.GetWorkInProgressPrefix(db.DefaultContext)) assert.Equal(t, "[wip]", pr.GetWorkInProgressPrefix())
} }
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(db.DefaultContext, "pull_request", "issue", "pull_request.issue_id=issue.id") orphaned, err := db.CountOrphanedObjects("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(db.DefaultContext, "pull_request", "issue", "pull_request.issue_id=issue.id") err = db.DeleteOrphanedObjects("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{})

View File

@ -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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -154,8 +154,7 @@ func (r *Review) loadIssue(ctx context.Context) (err error) {
return err return err
} }
// LoadReviewer loads reviewer func (r *Review) loadReviewer(ctx context.Context) (err error) {
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
} }
@ -163,8 +162,7 @@ func (r *Review) LoadReviewer(ctx context.Context) (err error) {
return err return err
} }
// LoadReviewerTeam loads reviewer team func (r *Review) loadReviewerTeam(ctx context.Context) (err error) {
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
} }
@ -173,6 +171,16 @@ 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 {
@ -181,10 +189,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
@ -366,7 +374,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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -614,7 +622,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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }
@ -656,7 +664,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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -711,7 +719,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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -764,7 +772,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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -823,7 +831,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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -941,7 +949,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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }

View File

@ -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(db.DefaultContext)) assert.NoError(t, reviewer.LoadReviewer())
} }
assert.NoError(t, err) assert.NoError(t, err)
if assert.Len(t, allReviews, 3) { if assert.Len(t, allReviews, 3) {

View File

@ -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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }

View File

@ -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(db.DefaultContext) ctx, committer, err := db.TxContext()
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(db.DefaultContext) ctx, committer, err := db.TxContext()
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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }

View File

@ -20,7 +20,7 @@ func InsertMilestones(ms ...*issues_model.Milestone) (err error) {
return nil return nil
} }
ctx, committer, err := db.TxContext(db.DefaultContext) ctx, committer, err := db.TxContext()
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(db.DefaultContext) ctx, committer, err := db.TxContext()
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(db.DefaultContext) ctx, committer, err := db.TxContext()
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(db.DefaultContext) ctx, committer, err := db.TxContext()
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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }

View File

@ -6,7 +6,6 @@
package migrations package migrations
import ( import (
"context"
"fmt" "fmt"
"os" "os"
@ -24,7 +23,6 @@ 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"
@ -439,8 +437,6 @@ 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
@ -531,13 +527,6 @@ 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())

View File

@ -1,29 +0,0 @@
// 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))
}

View File

@ -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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }

View File

@ -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(db.DefaultContext) ctx, committer, err := db.TxContext()
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(db.DefaultContext) ctx, committer, err := db.TxContext()
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(db.DefaultContext) ctx, committer, err := db.TxContext()
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(db.DefaultContext) ctx, committer, err := db.TxContext()
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(db.DefaultContext) ctx, committer, err := db.TxContext()
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(db.DefaultContext) ctx, committer, err := db.TxContext()
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(db.DefaultContext) ctx, committer, err := db.TxContext()
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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }

View File

@ -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(db.DefaultContext, user, repo) accessMode, err := access_model.AccessLevel(user, repo)
assert.NoError(t, err) assert.NoError(t, err)
assert.True(t, accessMode < perm.AccessModeWrite) assert.True(t, accessMode < perm.AccessModeWrite)
} }

View File

@ -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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }
@ -458,9 +458,8 @@ 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 {
// If user is nil, it's an anonymous user/request. // Not SignedUser
// The Ghost user is handled like an anonymous user. if user == nil {
if user == nil || user.IsGhost() {
return orgOrUser.Visibility == structs.VisibleTypePublic return orgOrUser.Visibility == structs.VisibleTypePublic
} }
@ -565,7 +564,7 @@ func AddOrgUser(orgID, uid int64) error {
return err return err
} }
ctx, committer, err := db.TxContext(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }

View File

@ -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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }

View File

@ -45,21 +45,6 @@ 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 {

View File

@ -62,13 +62,6 @@ 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)

View File

@ -1,110 +0,0 @@
// 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,
)
}

View File

@ -320,15 +320,6 @@ 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).

View File

@ -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(db.DefaultContext, user2, repo1) level, err := access_model.AccessLevel(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(db.DefaultContext, user2, repo3) level, err = access_model.AccessLevel(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(db.DefaultContext, user5, repo1) level, err = access_model.AccessLevel(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(db.DefaultContext, user5, repo3) level, err = access_model.AccessLevel(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(db.DefaultContext, user29, repo1) level, err = access_model.AccessLevel(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(db.DefaultContext, user29, repo4) level, err = access_model.AccessLevel(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(db.DefaultContext, user29, repo24) level, err = access_model.AccessLevel(user29, repo24)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, perm_model.AccessModeRead, level) assert.Equal(t, perm_model.AccessModeRead, level)
} }

View File

@ -326,13 +326,17 @@ 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(ctx context.Context, user *user_model.User, repo *repo_model.Repository) (perm_model.AccessMode, error) { //nolint func AccessLevel(user *user_model.User, repo *repo_model.Repository) (perm_model.AccessMode, error) { //nolint
return AccessLevelUnit(ctx, user, repo, unit.TypeCode) return AccessLevelUnit(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(ctx context.Context, user *user_model.User, repo *repo_model.Repository, unitType unit.Type) (perm_model.AccessMode, error) { //nolint func AccessLevelUnit(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
@ -342,7 +346,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
} }

View File

@ -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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }

View File

@ -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(db.DefaultContext, func(ctx context.Context) error { return db.WithTx(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))

View File

@ -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(db.DefaultContext) ctx, committer, err := db.TxContext()
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(db.DefaultContext) ctx, committer, err := db.TxContext()
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(db.DefaultContext) ctx, committer, err := db.TxContext()
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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }

View File

@ -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(db.DefaultContext) ctx, committer, err := db.TxContext()
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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }

View File

@ -7,14 +7,11 @@ 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"
) )
@ -47,28 +44,6 @@ 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
@ -90,17 +65,6 @@ 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)

View File

@ -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 exists with the given UUID // ExistAttachmentsByUUID returns true if attachment is exist by given UUID
func ExistAttachmentsByUUID(ctx context.Context, uuid string) (bool, error) { func ExistAttachmentsByUUID(uuid string) (bool, error) {
return db.GetEngine(ctx).Where("`uuid`=?", uuid).Exist(new(Attachment)) return db.GetEngine(db.DefaultContext).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(ctx context.Context, releaseID int64) error { func DeleteAttachmentsByRelease(releaseID int64) error {
_, err := db.GetEngine(ctx).Where("release_id = ?", releaseID).Delete(&Attachment{}) _, err := db.GetEngine(db.DefaultContext).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(ctx context.Context) (int64, error) { func CountOrphanedAttachments() (int64, error) {
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`))"). 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`))").
Count(new(Attachment)) Count(new(Attachment))
} }
// DeleteOrphanedAttachments delete all bad attachments // DeleteOrphanedAttachments delete all bad attachments
func DeleteOrphanedAttachments(ctx context.Context) error { func DeleteOrphanedAttachments() error {
_, 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`))"). _, 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`))").
Delete(new(Attachment)) Delete(new(Attachment))
return err return err
} }

View File

@ -24,13 +24,6 @@ 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)

View File

@ -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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }

View File

@ -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(db.DefaultContext) ctx, committer, err := db.TxContext()
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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }

View File

@ -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(ctx context.Context, repoID int64) ([]*PushMirror, error) { func GetPushMirrorsSyncedOnCommit(repoID int64) ([]*PushMirror, error) {
mirrors := make([]*PushMirror, 0, 10) mirrors := make([]*PushMirror, 0, 10)
return mirrors, db.GetEngine(ctx). return mirrors, db.GetEngine(db.DefaultContext).
Where("repo_id=? AND sync_on_commit=?", repoID, true). Where("repo_id=? AND sync_on_commit=?", repoID, true).
Find(&mirrors) Find(&mirrors)
} }

View File

@ -90,8 +90,7 @@ func init() {
db.RegisterModel(new(Release)) db.RegisterModel(new(Release))
} }
// LoadAttributes load repo and publisher attributes for a release func (r *Release) loadAttributes(ctx context.Context) error {
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)
@ -112,6 +111,11 @@ 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)
@ -237,8 +241,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(ctx context.Context, repoID int64, opts FindReleasesOptions) ([]*Release, error) { func GetReleasesByRepoID(repoID int64, opts FindReleasesOptions) ([]*Release, error) {
sess := db.GetEngine(ctx). sess := db.GetEngine(db.DefaultContext).
Desc("created_unix", "id"). Desc("created_unix", "id").
Where(opts.toConds(repoID)) Where(opts.toConds(repoID))
@ -377,8 +381,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(ctx context.Context, id int64) error { func DeleteReleaseByID(id int64) error {
_, err := db.GetEngine(ctx).ID(id).Delete(new(Release)) _, err := db.GetEngine(db.DefaultContext).ID(id).Delete(new(Release))
return err return err
} }

View File

@ -236,6 +236,14 @@ 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
@ -395,11 +403,7 @@ func (repo *Repository) GetOwner(ctx context.Context) (err error) {
return err return err
} }
// MustOwner always returns a valid *user_model.User object to avoid func (repo *Repository) mustOwner(ctx context.Context) *user_model.User {
// 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",
@ -434,7 +438,7 @@ func (repo *Repository) ComposeMetas() map[string]string {
} }
} }
repo.MustOwner(db.DefaultContext) repo.MustOwner()
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").
@ -788,13 +792,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(ctx context.Context) (int64, error) { func CountNullArchivedRepository() (int64, error) {
return db.GetEngine(ctx).Where(builder.IsNull{"is_archived"}).Count(new(Repository)) return db.GetEngine(db.DefaultContext).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(ctx context.Context) (int64, error) { func FixNullArchivedRepository() (int64, error) {
return db.GetEngine(ctx).Where(builder.IsNull{"is_archived"}).Cols("is_archived").NoAutoTime().Update(&Repository{ return db.GetEngine(db.DefaultContext).Where(builder.IsNull{"is_archived"}).Cols("is_archived").NoAutoTime().Update(&Repository{
IsArchived: false, IsArchived: false,
}) })
} }

View File

@ -518,13 +518,14 @@ 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(ctx context.Context, opts *SearchRepoOptions) (RepositoryList, int64, error) { func SearchRepository(opts *SearchRepoOptions) (RepositoryList, int64, error) {
cond := SearchRepositoryCondition(opts) cond := SearchRepositoryCondition(opts)
return SearchRepositoryByCondition(ctx, opts, cond, true) return SearchRepositoryByCondition(opts, cond, true)
} }
// SearchRepositoryByCondition search repositories by condition // SearchRepositoryByCondition search repositories by condition
func SearchRepositoryByCondition(ctx context.Context, opts *SearchRepoOptions, cond builder.Cond, loadAttributes bool) (RepositoryList, int64, error) { func SearchRepositoryByCondition(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
@ -651,9 +652,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(ctx context.Context, opts *SearchRepoOptions) (RepositoryList, int64, error) { func SearchRepositoryByName(opts *SearchRepoOptions) (RepositoryList, int64, error) {
opts.IncludeDescription = false opts.IncludeDescription = false
return SearchRepository(ctx, opts) return SearchRepository(opts)
} }
// SearchRepositoryIDs takes keyword and part of repository name to search, // SearchRepositoryIDs takes keyword and part of repository name to search,

View File

@ -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(db.DefaultContext, &repo_model.SearchRepoOptions{ repos, count, err := repo_model.SearchRepositoryByName(&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(db.DefaultContext, &repo_model.SearchRepoOptions{ repos, count, err = repo_model.SearchRepositoryByName(&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(db.DefaultContext, &repo_model.SearchRepoOptions{ repos, count, err = repo_model.SearchRepositoryByName(&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(db.DefaultContext, &repo_model.SearchRepoOptions{ repos, count, err = repo_model.SearchRepositoryByName(&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(db.DefaultContext, &repo_model.SearchRepoOptions{OwnerID: unittest.NonexistentID}) repos, count, err = repo_model.SearchRepositoryByName(&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(db.DefaultContext, &repo_model.SearchRepoOptions{ repos, count, err = repo_model.SearchRepository(&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(db.DefaultContext, &repo_model.SearchRepoOptions{ repos, count, err = repo_model.SearchRepository(&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(db.DefaultContext, testCase.opts) repos, count, err := repo_model.SearchRepositoryByName(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(db.DefaultContext, testCase.opts) _, count, err := repo_model.SearchRepositoryByName(testCase.opts)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, int64(testCase.count), count) assert.Equal(t, int64(testCase.count), count)
}) })

View File

@ -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(db.DefaultContext) ctx, committer, err := db.TxContext()
if err != nil { if err != nil {
return err return err
} }

View File

@ -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(db.DefaultContext) ctx, committer, err := db.TxContext()
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