Merge branch 'main' into pacman-packages

This commit is contained in:
Danila Fominykh 2023-10-11 23:38:46 -03:00 committed by GitHub
commit 99f856a4db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
262 changed files with 1998 additions and 1613 deletions

View File

@ -1,428 +0,0 @@
---
kind: pipeline
name: release-version
platform:
os: linux
arch: amd64
workspace:
base: /source
path: /
trigger:
event:
- tag
volumes:
- name: deps
temp: {}
steps:
- name: fetch-tags
image: docker:git
pull: always
commands:
- git fetch --tags --force
- name: deps-frontend
image: node:20
pull: always
commands:
- make deps-frontend
- name: deps-backend
image: gitea/test_env:linux-1.20-amd64
pull: always
commands:
- make deps-backend
volumes:
- name: deps
path: /go
- name: static
image: techknowlogick/xgo:go-1.21.x
pull: always
commands:
- apt-get update && apt-get -qqy install ca-certificates curl gnupg
- mkdir -p /etc/apt/keyrings && curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
- echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main" > /etc/apt/sources.list.d/nodesource.list
- apt-get update && apt-get -qqy install nodejs
- export PATH=$PATH:$GOPATH/bin
- make release
environment:
GOPROXY: https://goproxy.io # proxy.golang.org is blocked in China, this proxy is not
TAGS: bindata sqlite sqlite_unlock_notify
DEBIAN_FRONTEND: noninteractive
depends_on: [fetch-tags]
volumes:
- name: deps
path: /go
- name: gpg-sign
image: plugins/gpgsign:1
pull: always
settings:
detach_sign: true
excludes:
- "dist/release/*.sha256"
files:
- "dist/release/*"
environment:
GPGSIGN_KEY:
from_secret: gpgsign_key
GPGSIGN_PASSPHRASE:
from_secret: gpgsign_passphrase
depends_on: [static]
- name: release-tag
image: woodpeckerci/plugin-s3:latest
pull: always
settings:
acl:
from_secret: aws_s3_acl
region:
from_secret: aws_s3_region
bucket:
from_secret: aws_s3_bucket
endpoint:
from_secret: aws_s3_endpoint
path_style:
from_secret: aws_s3_path_style
source: "dist/release/*"
strip_prefix: dist/release/
target: "/gitea/${DRONE_TAG##v}"
environment:
AWS_ACCESS_KEY_ID:
from_secret: aws_access_key_id
AWS_SECRET_ACCESS_KEY:
from_secret: aws_secret_access_key
depends_on: [gpg-sign]
- name: github
image: plugins/github-release:latest
pull: always
settings:
files:
- "dist/release/*"
file_exists: overwrite
environment:
GITHUB_TOKEN:
from_secret: github_token
depends_on: [gpg-sign]
---
kind: pipeline
type: docker
name: docker-linux-amd64-release-version
platform:
os: linux
arch: amd64
trigger:
ref:
include:
- "refs/tags/**"
exclude:
- "refs/tags/**-rc*"
paths:
exclude:
- "docs/**"
steps:
- name: fetch-tags
image: docker:git
pull: always
commands:
- git fetch --tags --force
- name: publish
image: plugins/docker:latest
pull: always
settings:
auto_tag: true
auto_tag_suffix: linux-amd64
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.io
password:
from_secret: docker_password
username:
from_secret: docker_username
environment:
PLUGIN_MIRROR:
from_secret: plugin_mirror
DOCKER_BUILDKIT: 1
when:
event:
exclude:
- pull_request
- name: publish-rootless
image: plugins/docker:latest
settings:
dockerfile: Dockerfile.rootless
auto_tag: true
auto_tag_suffix: linux-amd64-rootless
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.io
password:
from_secret: docker_password
username:
from_secret: docker_username
environment:
PLUGIN_MIRROR:
from_secret: plugin_mirror
DOCKER_BUILDKIT: 1
when:
event:
exclude:
- pull_request
---
kind: pipeline
type: docker
name: docker-linux-amd64-release-candidate-version
platform:
os: linux
arch: amd64
trigger:
ref:
- "refs/tags/**-rc*"
paths:
exclude:
- "docs/**"
steps:
- name: fetch-tags
image: docker:git
pull: always
commands:
- git fetch --tags --force
- name: publish
image: plugins/docker:latest
pull: always
settings:
tags: ${DRONE_TAG##v}-linux-amd64
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.io
password:
from_secret: docker_password
username:
from_secret: docker_username
environment:
PLUGIN_MIRROR:
from_secret: plugin_mirror
DOCKER_BUILDKIT: 1
when:
event:
exclude:
- pull_request
- name: publish-rootless
image: plugins/docker:latest
settings:
dockerfile: Dockerfile.rootless
tags: ${DRONE_TAG##v}-linux-amd64-rootless
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.io
password:
from_secret: docker_password
username:
from_secret: docker_username
environment:
PLUGIN_MIRROR:
from_secret: plugin_mirror
DOCKER_BUILDKIT: 1
when:
event:
exclude:
- pull_request
---
kind: pipeline
type: docker
name: docker-linux-arm64-release-version
platform:
os: linux
arch: arm64
trigger:
ref:
include:
- "refs/tags/**"
exclude:
- "refs/tags/**-rc*"
paths:
exclude:
- "docs/**"
steps:
- name: fetch-tags
image: docker:git
pull: always
commands:
- git fetch --tags --force
- name: publish
image: plugins/docker:latest
pull: always
settings:
auto_tag: true
auto_tag_suffix: linux-arm64
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.io
password:
from_secret: docker_password
username:
from_secret: docker_username
environment:
PLUGIN_MIRROR:
from_secret: plugin_mirror
DOCKER_BUILDKIT: 1
when:
event:
exclude:
- pull_request
- name: publish-rootless
image: plugins/docker:latest
settings:
dockerfile: Dockerfile.rootless
auto_tag: true
auto_tag_suffix: linux-arm64-rootless
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.io
password:
from_secret: docker_password
username:
from_secret: docker_username
environment:
PLUGIN_MIRROR:
from_secret: plugin_mirror
DOCKER_BUILDKIT: 1
when:
event:
exclude:
- pull_request
---
kind: pipeline
type: docker
name: docker-linux-arm64-release-candidate-version
platform:
os: linux
arch: arm64
trigger:
ref:
- "refs/tags/**-rc*"
paths:
exclude:
- "docs/**"
steps:
- name: fetch-tags
image: docker:git
pull: always
commands:
- git fetch --tags --force
- name: publish
image: plugins/docker:latest
pull: always
settings:
tags: ${DRONE_TAG##v}-linux-arm64
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.io
password:
from_secret: docker_password
username:
from_secret: docker_username
environment:
PLUGIN_MIRROR:
from_secret: plugin_mirror
DOCKER_BUILDKIT: 1
when:
event:
exclude:
- pull_request
- name: publish-rootless
image: plugins/docker:latest
settings:
dockerfile: Dockerfile.rootless
tags: ${DRONE_TAG##v}-linux-arm64-rootless
repo: gitea/gitea
build_args:
- GOPROXY=https://goproxy.io
password:
from_secret: docker_password
username:
from_secret: docker_username
environment:
PLUGIN_MIRROR:
from_secret: plugin_mirror
DOCKER_BUILDKIT: 1
when:
event:
exclude:
- pull_request
---
kind: pipeline
type: docker
name: docker-manifest-version
platform:
os: linux
arch: amd64
steps:
- name: manifest-rootless
image: plugins/manifest
pull: always
settings:
auto_tag: true
ignore_missing: true
spec: docker/manifest.rootless.tmpl
password:
from_secret: docker_password
username:
from_secret: docker_username
- name: manifest
image: plugins/manifest
settings:
auto_tag: true
ignore_missing: true
spec: docker/manifest.tmpl
password:
from_secret: docker_password
username:
from_secret: docker_username
trigger:
ref:
- "refs/tags/**"
paths:
exclude:
- "docs/**"
depends_on:
- docker-linux-amd64-release-version
- docker-linux-amd64-release-candidate-version
- docker-linux-arm64-release-version
- docker-linux-arm64-release-candidate-version

View File

@ -476,7 +476,7 @@ rules:
prefer-exponentiation-operator: [2] prefer-exponentiation-operator: [2]
prefer-named-capture-group: [0] prefer-named-capture-group: [0]
prefer-numeric-literals: [2] prefer-numeric-literals: [2]
prefer-object-has-own: [0] prefer-object-has-own: [2]
prefer-object-spread: [2] prefer-object-spread: [2]
prefer-promise-reject-errors: [2, {allowEmptyReject: false}] prefer-promise-reject-errors: [2, {allowEmptyReject: false}]
prefer-regex-literals: [2] prefer-regex-literals: [2]

View File

@ -1,6 +1,6 @@
name: Bug Report name: Bug Report
description: Found something you weren't expecting? Report it here! description: Found something you weren't expecting? Report it here!
labels: ["kind/bug"] labels: ["type/bug"]
body: body:
- type: markdown - type: markdown
attributes: attributes:

View File

@ -1,6 +1,6 @@
name: Feature Request name: Feature Request
description: Got an idea for a feature that Gitea doesn't have currently? Submit your idea here! description: Got an idea for a feature that Gitea doesn't have currently? Submit your idea here!
labels: ["kind/proposal"] labels: ["type/proposal"]
body: body:
- type: markdown - type: markdown
attributes: attributes:

View File

@ -1,6 +1,6 @@
name: Web Interface Bug Report name: Web Interface Bug Report
description: Something doesn't look quite as it should? Report it here! description: Something doesn't look quite as it should? Report it here!
labels: ["kind/bug", "kind/ui"] labels: ["type/bug", "topic/ui"]
body: body:
- type: markdown - type: markdown
attributes: attributes:

View File

@ -2,3 +2,4 @@ self-hosted-runner:
labels: labels:
- actuated-4cpu-8gb - actuated-4cpu-8gb
- actuated-4cpu-16gb - actuated-4cpu-16gb
- nscloud

33
.github/labeler.yml vendored
View File

@ -1,35 +1,36 @@
kind/docs: modifies/docs:
- "**/*.md" - "**/*.md"
- "docs/**" - "docs/**"
kind/ui: modifies/frontend:
- "web_src/**/*" - "web_src/**/*"
modifies/templates:
- all: ["templates/**", "!templates/swagger/v1_json.tmpl"] - all: ["templates/**", "!templates/swagger/v1_json.tmpl"]
kind/api: modifies/api:
- "templates/swagger/v1_json.tmpl"
- "routers/api/**" - "routers/api/**"
- "templates/swagger/v1_json.tmpl"
kind/build: modifies/cli:
- "cmd/**"
modifies/translation:
- "options/locale/*.ini"
modifies/migrations:
- "models/migrations/**/*"
modifies/internal:
- "Makefile" - "Makefile"
- "Dockerfile" - "Dockerfile"
- "Dockerfile.rootless" - "Dockerfile.rootless"
- "docker/**" - "docker/**"
- "webpack.config.js" - "webpack.config.js"
theme/package-registry:
- "modules/packages/**"
- "services/packages/**"
- "routers/api/packages/**"
- "routers/web/shared/packages/**"
kind/cli:
- "cmd/**"
kind/lint:
- ".eslintrc.yaml" - ".eslintrc.yaml"
- ".golangci.yml" - ".golangci.yml"
- ".markdownlint.yaml" - ".markdownlint.yaml"
- ".spectral.yaml" - ".spectral.yaml"
- ".stylelintrc.yaml" - ".stylelintrc.yaml"
- ".yamllint.yaml" - ".yamllint.yaml"
- ".github/**"

View File

@ -18,4 +18,3 @@ jobs:
- uses: actions/labeler@v4 - uses: actions/labeler@v4
with: with:
dot: true dot: true
sync-labels: true

View File

@ -1,4 +1,4 @@
name: release-nightly-assets name: release-nightly
on: on:
push: push:
@ -48,15 +48,15 @@ jobs:
REF_NAME=$(echo "${{ github.ref }}" | sed -e 's/refs\/heads\///' -e 's/refs\/tags\///' -e 's/release\/v//') REF_NAME=$(echo "${{ github.ref }}" | sed -e 's/refs\/heads\///' -e 's/refs\/tags\///' -e 's/release\/v//')
echo "Cleaned name is ${REF_NAME}" echo "Cleaned name is ${REF_NAME}"
echo "branch=${REF_NAME}" >> "$GITHUB_OUTPUT" echo "branch=${REF_NAME}" >> "$GITHUB_OUTPUT"
- name: configure aws
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: ${{ secrets.AWS_REGION }}
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- name: upload binaries to s3 - name: upload binaries to s3
uses: jakejarvis/s3-sync-action@master run: |
env: aws s3 sync dist/release s3://${{ secrets.AWS_S3_BUCKET }}/gitea/${{ steps.clean_name.outputs.branch }} --no-progress
AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_REGION: ${{ secrets.AWS_REGION }}
SOURCE_DIR: dist/release
DEST_DIR: gitea/${{ steps.clean_name.outputs.branch }}
nightly-docker-rootful: nightly-docker-rootful:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:

125
.github/workflows/release-tag-rc.yml vendored Normal file
View File

@ -0,0 +1,125 @@
name: release-tag-rc
on:
push:
tags:
- 'v1*-rc*'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false
jobs:
binary:
runs-on: nscloud
steps:
- uses: actions/checkout@v4
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
- run: git fetch --unshallow --quiet --tags --force
- uses: actions/setup-go@v4
with:
go-version: "~1.21"
check-latest: true
- uses: actions/setup-node@v3
with:
node-version: 20
- run: make deps-frontend deps-backend
# xgo build
- run: make release
env:
TAGS: bindata sqlite sqlite_unlock_notify
- name: import gpg key
id: import_gpg
uses: crazy-max/ghaction-import-gpg@v5
with:
gpg_private_key: ${{ secrets.GPGSIGN_KEY }}
passphrase: ${{ secrets.GPGSIGN_PASSPHRASE }}
- name: sign binaries
run: |
for f in dist/release/*; do
echo '${{ secrets.GPGSIGN_PASSPHRASE }}' | gpg --pinentry-mode loopback --passphrase-fd 0 --batch --yes --detach-sign -u ${{ steps.import_gpg.outputs.fingerprint }} --output "$f.asc" "$f"
done
# clean branch name to get the folder name in S3
- name: Get cleaned branch name
id: clean_name
run: |
REF_NAME=$(echo "${{ github.ref }}" | sed -e 's/refs\/heads\///' -e 's/refs\/tags\///' -e 's/release\/v//')
echo "Cleaned name is ${REF_NAME}"
echo "branch=${REF_NAME}" >> "$GITHUB_OUTPUT"
- name: configure aws
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: ${{ secrets.AWS_REGION }}
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- name: upload binaries to s3
run: |
aws s3 sync dist/release s3://${{ secrets.AWS_S3_BUCKET }}/gitea/${{ steps.clean_name.outputs.branch }} --no-progress
- name: create github release
run: |
gh release create ${{ github.ref_name }} --title ${{ github.ref_name }} --draft --notes-from-tag dist/release/*
env:
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
docker-rootful:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
- run: git fetch --unshallow --quiet --tags --force
- uses: docker/setup-qemu-action@v2
- uses: docker/setup-buildx-action@v2
- uses: docker/metadata-action@v5
id: meta
with:
images: gitea/gitea
# 1.2.3-rc0
tags: |
type=semver,pattern={{version}}
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: build rootful docker image
uses: docker/build-push-action@v4
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
docker-rootless:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
- run: git fetch --unshallow --quiet --tags --force
- uses: docker/setup-qemu-action@v2
- uses: docker/setup-buildx-action@v2
- uses: docker/metadata-action@v5
id: meta
with:
images: gitea/gitea
# each tag below will have the suffix of -rootless
flavor: |
suffix=-rootless
# 1.2.3-rc0
tags: |
type=semver,pattern={{version}}
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: build rootless docker image
uses: docker/build-push-action@v4
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
file: Dockerfile.rootless
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

View File

@ -0,0 +1,141 @@
name: release-tag-version
on:
push:
tags:
- 'v1.*'
- '!v1*-rc*'
- '!v1*-dev'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false
jobs:
binary:
runs-on: nscloud
steps:
- uses: actions/checkout@v4
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
- run: git fetch --unshallow --quiet --tags --force
- uses: actions/setup-go@v4
with:
go-version: "~1.21"
check-latest: true
- uses: actions/setup-node@v3
with:
node-version: 20
- run: make deps-frontend deps-backend
# xgo build
- run: make release
env:
TAGS: bindata sqlite sqlite_unlock_notify
- name: import gpg key
id: import_gpg
uses: crazy-max/ghaction-import-gpg@v5
with:
gpg_private_key: ${{ secrets.GPGSIGN_KEY }}
passphrase: ${{ secrets.GPGSIGN_PASSPHRASE }}
- name: sign binaries
run: |
for f in dist/release/*; do
echo '${{ secrets.GPGSIGN_PASSPHRASE }}' | gpg --pinentry-mode loopback --passphrase-fd 0 --batch --yes --detach-sign -u ${{ steps.import_gpg.outputs.fingerprint }} --output "$f.asc" "$f"
done
# clean branch name to get the folder name in S3
- name: Get cleaned branch name
id: clean_name
run: |
REF_NAME=$(echo "${{ github.ref }}" | sed -e 's/refs\/heads\///' -e 's/refs\/tags\///' -e 's/release\/v//')
echo "Cleaned name is ${REF_NAME}"
echo "branch=${REF_NAME}" >> "$GITHUB_OUTPUT"
- name: configure aws
uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: ${{ secrets.AWS_REGION }}
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- name: upload binaries to s3
run: |
aws s3 sync dist/release s3://${{ secrets.AWS_S3_BUCKET }}/gitea/${{ steps.clean_name.outputs.branch }} --no-progress
- name: create github release
run: |
gh release create ${{ github.ref_name }} --title ${{ github.ref_name }} --draft --notes-from-tag dist/release/*
env:
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
docker-rootful:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
- run: git fetch --unshallow --quiet --tags --force
- uses: docker/setup-qemu-action@v2
- uses: docker/setup-buildx-action@v2
- uses: docker/metadata-action@v5
id: meta
with:
images: gitea/gitea
# this will generate tags in the following format:
# latest
# 1
# 1.2
# 1.2.3
tags: |
type=raw,value=latest
type=semver,pattern={{major}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{version}}
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: build rootful docker image
uses: docker/build-push-action@v4
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
docker-rootless:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
- run: git fetch --unshallow --quiet --tags --force
- uses: docker/setup-qemu-action@v2
- uses: docker/setup-buildx-action@v2
- uses: docker/metadata-action@v5
id: meta
with:
images: gitea/gitea
# each tag below will have the suffix of -rootless
flavor: |
suffix=-rootless
# this will generate tags in the following format (with -rootless suffix added):
# latest
# 1
# 1.2
# 1.2.3
tags: |
type=raw,value=latest
type=semver,pattern={{major}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{version}}
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: build rootless docker image
uses: docker/build-push-action@v4
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
file: Dockerfile.rootless
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

View File

@ -24,8 +24,6 @@ rules:
document-start: document-start:
level: error level: error
present: false present: false
ignore: |
/.drone.yml
document-end: document-end:
present: false present: false

View File

@ -225,17 +225,20 @@ PRs without a milestone may not be merged.
### Labels ### Labels
Every PR should be labeled correctly with every label that applies. \ Almost all labels used inside Gitea can be classified as one of the following:
This includes especially the distinction between `bug` (fixing existing functionality), `feature` (new functionality), `enhancement` (upgrades for existing functionality), and `refactoring` (improving the internal code structure without changing the output (much)). \
Furthermore, - `modifies/…`: Determines which parts of the codebase are affected. These labels will be set through the CI.
- `topic/…`: Determines the conceptual component of Gitea that is affected, i.e. issues, projects, or authentication. At best, PRs should only target one component but there might be overlap. Must be set manually.
- `type/…`: Determines the type of an issue or PR (feature, refactoring, docs, bug, …). If GitHub supported scoped labels, these labels would be exclusive, so you should set **exactly** one, not more or less (every PR should fall into one of the provided categories, and only one).
- `issue/…` / `pr/…`: Labels that are specific to issues or PRs respectively and that are only necessary in a given context, i.e. `issue/not-a-bug` or `pr/need-2-approvals`
Every PR should be labeled correctly with every label that applies.
There are also some labels that will be managed automatically.\
In particular, these are
- the amount of pending required approvals - the amount of pending required approvals
- whether this PR is `blocked`, a `backport` or `breaking` - has all `backport`s or needs a manual backport
- if it targets the `ui` or `api`
- if it increases the application `speed`
- reduces `memory usage`
are oftentimes notable labels.
### Breaking PRs ### Breaking PRs

View File

@ -58,3 +58,4 @@ CaiCandong <1290147055@qq.com> (@caicandong)
Rui Chen <rui@chenrui.dev> (@chenrui333) Rui Chen <rui@chenrui.dev> (@chenrui333)
Nanguan Lin <nanguanlin6@gmail.com> (@lng2020) Nanguan Lin <nanguanlin6@gmail.com> (@lng2020)
kerwin612 <kerwin612@qq.com> (@kerwin612) kerwin612 <kerwin612@qq.com> (@kerwin612)
Gary Wang <git@blumia.net> (@BLumia)

View File

@ -62,7 +62,7 @@ func runListAuth(c *cli.Context) error {
return err return err
} }
authSources, err := auth_model.Sources() authSources, err := auth_model.Sources(ctx)
if err != nil { if err != nil {
return err return err
} }
@ -100,7 +100,7 @@ func runDeleteAuth(c *cli.Context) error {
return err return err
} }
source, err := auth_model.GetSourceByID(c.Int64("id")) source, err := auth_model.GetSourceByID(ctx, c.Int64("id"))
if err != nil { if err != nil {
return err return err
} }

View File

@ -17,9 +17,9 @@ import (
type ( type (
authService struct { authService struct {
initDB func(ctx context.Context) error initDB func(ctx context.Context) error
createAuthSource func(*auth.Source) error createAuthSource func(context.Context, *auth.Source) error
updateAuthSource func(*auth.Source) error updateAuthSource func(context.Context, *auth.Source) error
getAuthSourceByID func(id int64) (*auth.Source, error) getAuthSourceByID func(ctx context.Context, id int64) (*auth.Source, error)
} }
) )
@ -289,12 +289,12 @@ func findLdapSecurityProtocolByName(name string) (ldap.SecurityProtocol, bool) {
// getAuthSource gets the login source by its id defined in the command line flags. // getAuthSource gets the login source by its id defined in the command line flags.
// It returns an error if the id is not set, does not match any source or if the source is not of expected type. // It returns an error if the id is not set, does not match any source or if the source is not of expected type.
func (a *authService) getAuthSource(c *cli.Context, authType auth.Type) (*auth.Source, error) { func (a *authService) getAuthSource(ctx context.Context, c *cli.Context, authType auth.Type) (*auth.Source, error) {
if err := argsSet(c, "id"); err != nil { if err := argsSet(c, "id"); err != nil {
return nil, err return nil, err
} }
authSource, err := a.getAuthSourceByID(c.Int64("id")) authSource, err := a.getAuthSourceByID(ctx, c.Int64("id"))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -332,7 +332,7 @@ func (a *authService) addLdapBindDn(c *cli.Context) error {
return err return err
} }
return a.createAuthSource(authSource) return a.createAuthSource(ctx, authSource)
} }
// updateLdapBindDn updates a new LDAP via Bind DN authentication source. // updateLdapBindDn updates a new LDAP via Bind DN authentication source.
@ -344,7 +344,7 @@ func (a *authService) updateLdapBindDn(c *cli.Context) error {
return err return err
} }
authSource, err := a.getAuthSource(c, auth.LDAP) authSource, err := a.getAuthSource(ctx, c, auth.LDAP)
if err != nil { if err != nil {
return err return err
} }
@ -354,7 +354,7 @@ func (a *authService) updateLdapBindDn(c *cli.Context) error {
return err return err
} }
return a.updateAuthSource(authSource) return a.updateAuthSource(ctx, authSource)
} }
// addLdapSimpleAuth adds a new LDAP (simple auth) authentication source. // addLdapSimpleAuth adds a new LDAP (simple auth) authentication source.
@ -383,7 +383,7 @@ func (a *authService) addLdapSimpleAuth(c *cli.Context) error {
return err return err
} }
return a.createAuthSource(authSource) return a.createAuthSource(ctx, authSource)
} }
// updateLdapBindDn updates a new LDAP (simple auth) authentication source. // updateLdapBindDn updates a new LDAP (simple auth) authentication source.
@ -395,7 +395,7 @@ func (a *authService) updateLdapSimpleAuth(c *cli.Context) error {
return err return err
} }
authSource, err := a.getAuthSource(c, auth.DLDAP) authSource, err := a.getAuthSource(ctx, c, auth.DLDAP)
if err != nil { if err != nil {
return err return err
} }
@ -405,5 +405,5 @@ func (a *authService) updateLdapSimpleAuth(c *cli.Context) error {
return err return err
} }
return a.updateAuthSource(authSource) return a.updateAuthSource(ctx, authSource)
} }

View File

@ -210,15 +210,15 @@ func TestAddLdapBindDn(t *testing.T) {
initDB: func(context.Context) error { initDB: func(context.Context) error {
return nil return nil
}, },
createAuthSource: func(authSource *auth.Source) error { createAuthSource: func(ctx context.Context, authSource *auth.Source) error {
createdAuthSource = authSource createdAuthSource = authSource
return nil return nil
}, },
updateAuthSource: func(authSource *auth.Source) error { updateAuthSource: func(ctx context.Context, authSource *auth.Source) error {
assert.FailNow(t, "case %d: should not call updateAuthSource", n) assert.FailNow(t, "case %d: should not call updateAuthSource", n)
return nil return nil
}, },
getAuthSourceByID: func(id int64) (*auth.Source, error) { getAuthSourceByID: func(ctx context.Context, id int64) (*auth.Source, error) {
assert.FailNow(t, "case %d: should not call getAuthSourceByID", n) assert.FailNow(t, "case %d: should not call getAuthSourceByID", n)
return nil, nil return nil, nil
}, },
@ -441,15 +441,15 @@ func TestAddLdapSimpleAuth(t *testing.T) {
initDB: func(context.Context) error { initDB: func(context.Context) error {
return nil return nil
}, },
createAuthSource: func(authSource *auth.Source) error { createAuthSource: func(ctx context.Context, authSource *auth.Source) error {
createdAuthSource = authSource createdAuthSource = authSource
return nil return nil
}, },
updateAuthSource: func(authSource *auth.Source) error { updateAuthSource: func(ctx context.Context, authSource *auth.Source) error {
assert.FailNow(t, "case %d: should not call updateAuthSource", n) assert.FailNow(t, "case %d: should not call updateAuthSource", n)
return nil return nil
}, },
getAuthSourceByID: func(id int64) (*auth.Source, error) { getAuthSourceByID: func(ctx context.Context, id int64) (*auth.Source, error) {
assert.FailNow(t, "case %d: should not call getAuthSourceByID", n) assert.FailNow(t, "case %d: should not call getAuthSourceByID", n)
return nil, nil return nil, nil
}, },
@ -896,15 +896,15 @@ func TestUpdateLdapBindDn(t *testing.T) {
initDB: func(context.Context) error { initDB: func(context.Context) error {
return nil return nil
}, },
createAuthSource: func(authSource *auth.Source) error { createAuthSource: func(ctx context.Context, authSource *auth.Source) error {
assert.FailNow(t, "case %d: should not call createAuthSource", n) assert.FailNow(t, "case %d: should not call createAuthSource", n)
return nil return nil
}, },
updateAuthSource: func(authSource *auth.Source) error { updateAuthSource: func(ctx context.Context, authSource *auth.Source) error {
updatedAuthSource = authSource updatedAuthSource = authSource
return nil return nil
}, },
getAuthSourceByID: func(id int64) (*auth.Source, error) { getAuthSourceByID: func(ctx context.Context, id int64) (*auth.Source, error) {
if c.id != 0 { if c.id != 0 {
assert.Equal(t, c.id, id, "case %d: wrong id", n) assert.Equal(t, c.id, id, "case %d: wrong id", n)
} }
@ -1286,15 +1286,15 @@ func TestUpdateLdapSimpleAuth(t *testing.T) {
initDB: func(context.Context) error { initDB: func(context.Context) error {
return nil return nil
}, },
createAuthSource: func(authSource *auth.Source) error { createAuthSource: func(ctx context.Context, authSource *auth.Source) error {
assert.FailNow(t, "case %d: should not call createAuthSource", n) assert.FailNow(t, "case %d: should not call createAuthSource", n)
return nil return nil
}, },
updateAuthSource: func(authSource *auth.Source) error { updateAuthSource: func(ctx context.Context, authSource *auth.Source) error {
updatedAuthSource = authSource updatedAuthSource = authSource
return nil return nil
}, },
getAuthSourceByID: func(id int64) (*auth.Source, error) { getAuthSourceByID: func(ctx context.Context, id int64) (*auth.Source, error) {
if c.id != 0 { if c.id != 0 {
assert.Equal(t, c.id, id, "case %d: wrong id", n) assert.Equal(t, c.id, id, "case %d: wrong id", n)
} }

View File

@ -183,7 +183,7 @@ func runAddOauth(c *cli.Context) error {
} }
} }
return auth_model.CreateSource(&auth_model.Source{ return auth_model.CreateSource(ctx, &auth_model.Source{
Type: auth_model.OAuth2, Type: auth_model.OAuth2,
Name: c.String("name"), Name: c.String("name"),
IsActive: true, IsActive: true,
@ -203,7 +203,7 @@ func runUpdateOauth(c *cli.Context) error {
return err return err
} }
source, err := auth_model.GetSourceByID(c.Int64("id")) source, err := auth_model.GetSourceByID(ctx, c.Int64("id"))
if err != nil { if err != nil {
return err return err
} }
@ -294,5 +294,5 @@ func runUpdateOauth(c *cli.Context) error {
oAuth2Config.CustomURLMapping = customURLMapping oAuth2Config.CustomURLMapping = customURLMapping
source.Cfg = oAuth2Config source.Cfg = oAuth2Config
return auth_model.UpdateSource(source) return auth_model.UpdateSource(ctx, source)
} }

View File

@ -156,7 +156,7 @@ func runAddSMTP(c *cli.Context) error {
smtpConfig.Auth = "PLAIN" smtpConfig.Auth = "PLAIN"
} }
return auth_model.CreateSource(&auth_model.Source{ return auth_model.CreateSource(ctx, &auth_model.Source{
Type: auth_model.SMTP, Type: auth_model.SMTP,
Name: c.String("name"), Name: c.String("name"),
IsActive: active, IsActive: active,
@ -176,7 +176,7 @@ func runUpdateSMTP(c *cli.Context) error {
return err return err
} }
source, err := auth_model.GetSourceByID(c.Int64("id")) source, err := auth_model.GetSourceByID(ctx, c.Int64("id"))
if err != nil { if err != nil {
return err return err
} }
@ -197,5 +197,5 @@ func runUpdateSMTP(c *cli.Context) error {
source.Cfg = smtpConfig source.Cfg = smtpConfig
return auth_model.UpdateSource(source) return auth_model.UpdateSource(ctx, source)
} }

View File

@ -548,7 +548,8 @@ ENABLE = true
;; Pre-register OAuth2 applications for some universally useful services ;; Pre-register OAuth2 applications for some universally useful services
;; * https://github.com/hickford/git-credential-oauth ;; * https://github.com/hickford/git-credential-oauth
;; * https://github.com/git-ecosystem/git-credential-manager ;; * https://github.com/git-ecosystem/git-credential-manager
;DEFAULT_APPLICATIONS = git-credential-oauth, git-credential-manager ;; * https://gitea.com/gitea/tea
;DEFAULT_APPLICATIONS = git-credential-oauth, git-credential-manager, tea
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -950,7 +951,7 @@ LEVEL = Info
;; Note: Code and Releases can currently not be deactivated. If you specify default repo units you should still list them for future compatibility. ;; Note: Code and Releases can currently not be deactivated. If you specify default repo units you should still list them for future compatibility.
;; External wiki and issue tracker can't be enabled by default as it requires additional settings. ;; External wiki and issue tracker can't be enabled by default as it requires additional settings.
;; Disabled repo units will not be added to new repositories regardless if it is in the default list. ;; Disabled repo units will not be added to new repositories regardless if it is in the default list.
;DEFAULT_REPO_UNITS = repo.code,repo.releases,repo.issues,repo.pulls,repo.wiki,repo.projects,repo.packages ;DEFAULT_REPO_UNITS = repo.code,repo.releases,repo.issues,repo.pulls,repo.wiki,repo.projects,repo.packages,repo.actions
;; ;;
;; Comma separated list of default forked repo units. ;; Comma separated list of default forked repo units.
;; The set of allowed values and rules are the same as DEFAULT_REPO_UNITS. ;; The set of allowed values and rules are the same as DEFAULT_REPO_UNITS.
@ -1420,7 +1421,7 @@ LEVEL = Info
;DATADIR = queues/ ; Relative paths will be made absolute against `%(APP_DATA_PATH)s`. ;DATADIR = queues/ ; Relative paths will be made absolute against `%(APP_DATA_PATH)s`.
;; ;;
;; Default queue length before a channel queue will block ;; Default queue length before a channel queue will block
;LENGTH = 100 ;LENGTH = 100000
;; ;;
;; Batch size to send for batched queues ;; Batch size to send for batched queues
;BATCH_LENGTH = 20 ;BATCH_LENGTH = 20

View File

@ -102,7 +102,7 @@ In addition, there is _`StaticRootPath`_ which can be set as a built-in at build
- `ENABLE_PUSH_CREATE_USER`: **false**: Allow users to push local repositories to Gitea and have them automatically created for a user. - `ENABLE_PUSH_CREATE_USER`: **false**: Allow users to push local repositories to Gitea and have them automatically created for a user.
- `ENABLE_PUSH_CREATE_ORG`: **false**: Allow users to push local repositories to Gitea and have them automatically created for an org. - `ENABLE_PUSH_CREATE_ORG`: **false**: Allow users to push local repositories to Gitea and have them automatically created for an org.
- `DISABLED_REPO_UNITS`: **_empty_**: Comma separated list of globally disabled repo units. Allowed values: \[repo.issues, repo.ext_issues, repo.pulls, repo.wiki, repo.ext_wiki, repo.projects, repo.packages, repo.actions\] - `DISABLED_REPO_UNITS`: **_empty_**: Comma separated list of globally disabled repo units. Allowed values: \[repo.issues, repo.ext_issues, repo.pulls, repo.wiki, repo.ext_wiki, repo.projects, repo.packages, repo.actions\]
- `DEFAULT_REPO_UNITS`: **repo.code,repo.releases,repo.issues,repo.pulls,repo.wiki,repo.projects,repo.packages**: Comma separated list of default new repo units. Allowed values: \[repo.code, repo.releases, repo.issues, repo.pulls, repo.wiki, repo.projects, repo.packages, repo.actions\]. Note: Code and Releases can currently not be deactivated. If you specify default repo units you should still list them for future compatibility. External wiki and issue tracker can't be enabled by default as it requires additional settings. Disabled repo units will not be added to new repositories regardless if it is in the default list. - `DEFAULT_REPO_UNITS`: **repo.code,repo.releases,repo.issues,repo.pulls,repo.wiki,repo.projects,repo.packages,repo.actions**: Comma separated list of default new repo units. Allowed values: \[repo.code, repo.releases, repo.issues, repo.pulls, repo.wiki, repo.projects, repo.packages, repo.actions\]. Note: Code and Releases can currently not be deactivated. If you specify default repo units you should still list them for future compatibility. External wiki and issue tracker can't be enabled by default as it requires additional settings. Disabled repo units will not be added to new repositories regardless if it is in the default list.
- `DEFAULT_FORK_REPO_UNITS`: **repo.code,repo.pulls**: Comma separated list of default forked repo units. The set of allowed values and rules is the same as `DEFAULT_REPO_UNITS`. - `DEFAULT_FORK_REPO_UNITS`: **repo.code,repo.pulls**: Comma separated list of default forked repo units. The set of allowed values and rules is the same as `DEFAULT_REPO_UNITS`.
- `PREFIX_ARCHIVE_FILES`: **true**: Prefix archive files by placing them in a directory named after the repository. - `PREFIX_ARCHIVE_FILES`: **true**: Prefix archive files by placing them in a directory named after the repository.
- `DISABLE_MIGRATIONS`: **false**: Disable migrating feature. - `DISABLE_MIGRATIONS`: **false**: Disable migrating feature.
@ -483,7 +483,7 @@ Configuration at `[queue]` will set defaults for queues with overrides for indiv
- `TYPE`: **level**: General queue type, currently support: `level` (uses a LevelDB internally), `channel`, `redis`, `dummy`. Invalid types are treated as `level`. - `TYPE`: **level**: General queue type, currently support: `level` (uses a LevelDB internally), `channel`, `redis`, `dummy`. Invalid types are treated as `level`.
- `DATADIR`: **queues/common**: Base DataDir for storing level queues. `DATADIR` for individual queues can be set in `queue.name` sections. Relative paths will be made absolute against `%(APP_DATA_PATH)s`. - `DATADIR`: **queues/common**: Base DataDir for storing level queues. `DATADIR` for individual queues can be set in `queue.name` sections. Relative paths will be made absolute against `%(APP_DATA_PATH)s`.
- `LENGTH`: **100**: Maximal queue size before channel queues block - `LENGTH`: **100000**: 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. For `redis-cluster` use `redis+cluster://127.0.0.1:6379/0`. 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. For `redis-cluster` use `redis+cluster://127.0.0.1:6379/0`. 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`
- `QUEUE_NAME`: **_queue**: The suffix for default redis and disk queue name. Individual queues will default to **`name`**`QUEUE_NAME` but can be overridden in the specific `queue.name` section. - `QUEUE_NAME`: **_queue**: The suffix for default redis and disk queue name. Individual queues will default to **`name`**`QUEUE_NAME` but can be overridden in the specific `queue.name` section.
@ -1107,7 +1107,7 @@ This section only does "set" config, a removed config key from this section won'
- `JWT_SECRET_URI`: **_empty_**: Instead of defining JWT_SECRET in the configuration, this configuration option can be used to give Gitea a path to a file that contains the secret (example value: `file:/etc/gitea/oauth2_jwt_secret`) - `JWT_SECRET_URI`: **_empty_**: Instead of defining JWT_SECRET in the configuration, this configuration option can be used to give Gitea a path to a file that contains the secret (example value: `file:/etc/gitea/oauth2_jwt_secret`)
- `JWT_SIGNING_PRIVATE_KEY_FILE`: **jwt/private.pem**: Private key file path used to sign OAuth2 tokens. The path is relative to `APP_DATA_PATH`. This setting is only needed if `JWT_SIGNING_ALGORITHM` is set to `RS256`, `RS384`, `RS512`, `ES256`, `ES384` or `ES512`. The file must contain a RSA or ECDSA private key in the PKCS8 format. If no key exists a 4096 bit key will be created for you. - `JWT_SIGNING_PRIVATE_KEY_FILE`: **jwt/private.pem**: Private key file path used to sign OAuth2 tokens. The path is relative to `APP_DATA_PATH`. This setting is only needed if `JWT_SIGNING_ALGORITHM` is set to `RS256`, `RS384`, `RS512`, `ES256`, `ES384` or `ES512`. The file must contain a RSA or ECDSA private key in the PKCS8 format. If no key exists a 4096 bit key will be created for you.
- `MAX_TOKEN_LENGTH`: **32767**: Maximum length of token/cookie to accept from OAuth2 provider - `MAX_TOKEN_LENGTH`: **32767**: Maximum length of token/cookie to accept from OAuth2 provider
- `DEFAULT_APPLICATIONS`: **git-credential-oauth, git-credential-manager**: Pre-register OAuth applications for some services on startup. See the [OAuth2 documentation](/development/oauth2-provider.md) for the list of available options. - `DEFAULT_APPLICATIONS`: **git-credential-oauth, git-credential-manager, tea**: Pre-register OAuth applications for some services on startup. See the [OAuth2 documentation](/development/oauth2-provider.md) for the list of available options.
## i18n (`i18n`) ## i18n (`i18n`)

View File

@ -102,7 +102,7 @@ menu:
- `ENABLE_PUSH_CREATE_USER`: **false**: 允许用户将本地存储库推送到Gitea并为用户自动创建它们。 - `ENABLE_PUSH_CREATE_USER`: **false**: 允许用户将本地存储库推送到Gitea并为用户自动创建它们。
- `ENABLE_PUSH_CREATE_ORG`: **false**: 允许用户将本地存储库推送到Gitea并为组织自动创建它们。 - `ENABLE_PUSH_CREATE_ORG`: **false**: 允许用户将本地存储库推送到Gitea并为组织自动创建它们。
- `DISABLED_REPO_UNITS`: **_empty_**: 逗号分隔的全局禁用的仓库单元列表。允许的值是:: \[repo.issues, repo.ext_issues, repo.pulls, repo.wiki, repo.ext_wiki, repo.projects, repo.packages, repo.actions\] - `DISABLED_REPO_UNITS`: **_empty_**: 逗号分隔的全局禁用的仓库单元列表。允许的值是:: \[repo.issues, repo.ext_issues, repo.pulls, repo.wiki, repo.ext_wiki, repo.projects, repo.packages, repo.actions\]
- `DEFAULT_REPO_UNITS`: **repo.code,repo.releases,repo.issues,repo.pulls,repo.wiki,repo.projects,repo.packages**: 逗号分隔的默认新仓库单元列表。允许的值是:: \[repo.code, repo.releases, repo.issues, repo.pulls, repo.wiki, repo.projects, repo.packages, repo.actions\]. 注意目前无法停用代码和发布。如果您指定了默认的仓库单元您仍应将它们列出以保持未来的兼容性。外部wiki和问题跟踪器不能默认启用因为它需要额外的设置。禁用的仓库单元将不会添加到新的仓库中无论它是否在默认列表中。 - `DEFAULT_REPO_UNITS`: **repo.code,repo.releases,repo.issues,repo.pulls,repo.wiki,repo.projects,repo.packages,repo.actions**: 逗号分隔的默认新仓库单元列表。允许的值是:: \[repo.code, repo.releases, repo.issues, repo.pulls, repo.wiki, repo.projects, repo.packages, repo.actions\]. 注意目前无法停用代码和发布。如果您指定了默认的仓库单元您仍应将它们列出以保持未来的兼容性。外部wiki和问题跟踪器不能默认启用因为它需要额外的设置。禁用的仓库单元将不会添加到新的仓库中无论它是否在默认列表中。
- `DEFAULT_FORK_REPO_UNITS`: **repo.code,repo.pulls**: 逗号分隔的默认分叉仓库单元列表。允许的值和规则与`DEFAULT_REPO_UNITS`相同。 - `DEFAULT_FORK_REPO_UNITS`: **repo.code,repo.pulls**: 逗号分隔的默认分叉仓库单元列表。允许的值和规则与`DEFAULT_REPO_UNITS`相同。
- `PREFIX_ARCHIVE_FILES`: **true**: 通过将存档文件放置在以仓库命名的目录中来添加前缀。 - `PREFIX_ARCHIVE_FILES`: **true**: 通过将存档文件放置在以仓库命名的目录中来添加前缀。
- `DISABLE_MIGRATIONS`: **false**: 禁用迁移功能。 - `DISABLE_MIGRATIONS`: **false**: 禁用迁移功能。
@ -472,7 +472,7 @@ menu:
- `TYPE`**level**:通用队列类型,当前支持:`level`(在内部使用 LevelDB、`channel`、`redis`、`dummy`。无效的类型将视为 `level` - `TYPE`**level**:通用队列类型,当前支持:`level`(在内部使用 LevelDB、`channel`、`redis`、`dummy`。无效的类型将视为 `level`
- `DATADIR`**queues/common**:用于存储 level 队列的基本 DataDir。单独的队列的 `DATADIR` 可以在 `queue.name` 部分进行设置。相对路径将根据 `%(APP_DATA_PATH)s` 变为绝对路径。 - `DATADIR`**queues/common**:用于存储 level 队列的基本 DataDir。单独的队列的 `DATADIR` 可以在 `queue.name` 部分进行设置。相对路径将根据 `%(APP_DATA_PATH)s` 变为绝对路径。
- `LENGTH`**100**:通道队列阻塞之前的最大队列大小 - `LENGTH`**100000**:通道队列阻塞之前的最大队列大小
- `BATCH_LENGTH`**20**:在传递给处理程序之前批处理数据 - `BATCH_LENGTH`**20**:在传递给处理程序之前批处理数据
- `CONN_STR`**redis://127.0.0.1:6379/0**redis 队列类型的连接字符串。对于 `redis-cluster`,使用 `redis+cluster://127.0.0.1:6379/0`。可以使用查询参数来设置选项。类似地LevelDB 选项也可以使用:**leveldb://relative/path?option=value** 或 **leveldb:///absolute/path?option=value** 进行设置,并将覆盖 `DATADIR` - `CONN_STR`**redis://127.0.0.1:6379/0**redis 队列类型的连接字符串。对于 `redis-cluster`,使用 `redis+cluster://127.0.0.1:6379/0`。可以使用查询参数来设置选项。类似地LevelDB 选项也可以使用:**leveldb://relative/path?option=value** 或 **leveldb:///absolute/path?option=value** 进行设置,并将覆盖 `DATADIR`
- `QUEUE_NAME`**_queue**:默认的 redis 和磁盘队列名称的后缀。单独的队列将默认为 **`name`**`QUEUE_NAME`,但可以在特定的 `queue.name` 部分中进行覆盖。 - `QUEUE_NAME`**_queue**:默认的 redis 和磁盘队列名称的后缀。单独的队列将默认为 **`name`**`QUEUE_NAME`,但可以在特定的 `queue.name` 部分中进行覆盖。
@ -1056,7 +1056,7 @@ Gitea 创建以下非唯一队列:
- `JWT_SECRET_URI`**_empty_**:可以使用此配置选项,而不是在配置中定义`JWT_SECRET`以向Gitea提供包含密钥的文件的路径示例值`file:/etc/gitea/oauth2_jwt_secret`)。 - `JWT_SECRET_URI`**_empty_**:可以使用此配置选项,而不是在配置中定义`JWT_SECRET`以向Gitea提供包含密钥的文件的路径示例值`file:/etc/gitea/oauth2_jwt_secret`)。
- `JWT_SIGNING_PRIVATE_KEY_FILE`**jwt/private.pem**用于签署OAuth2令牌的私钥文件路径。路径相对于`APP_DATA_PATH`。仅当`JWT_SIGNING_ALGORITHM`设置为`RS256``RS384``RS512``ES256``ES384`或`ES512`时才需要此设置。文件必须包含PKCS8格式的RSA或ECDSA私钥。如果不存在密钥则将为您创建一个4096位密钥。 - `JWT_SIGNING_PRIVATE_KEY_FILE`**jwt/private.pem**用于签署OAuth2令牌的私钥文件路径。路径相对于`APP_DATA_PATH`。仅当`JWT_SIGNING_ALGORITHM`设置为`RS256``RS384``RS512``ES256``ES384`或`ES512`时才需要此设置。文件必须包含PKCS8格式的RSA或ECDSA私钥。如果不存在密钥则将为您创建一个4096位密钥。
- `MAX_TOKEN_LENGTH`**32767**从OAuth2提供者接受的令牌/cookie的最大长度。 - `MAX_TOKEN_LENGTH`**32767**从OAuth2提供者接受的令牌/cookie的最大长度。
- `DEFAULT_APPLICATIONS`**git-credential-oauthgit-credential-manager**在启动时预注册用于某些服务的OAuth应用程序。有关可用选项列表请参阅[OAuth2文档](/development/oauth2-provider.md)。 - `DEFAULT_APPLICATIONS`**git-credential-oauthgit-credential-manager, tea**在启动时预注册用于某些服务的OAuth应用程序。有关可用选项列表请参阅[OAuth2文档](/development/oauth2-provider.md)。
## i18n (`i18n`) ## i18n (`i18n`)

View File

@ -381,3 +381,9 @@ If you really need to do so, to make Gitea works with sub-path (eg: `http://exam
1. Set `[server] ROOT_URL = http://example.com/gitea/` in your `app.ini` file. 1. Set `[server] ROOT_URL = http://example.com/gitea/` in your `app.ini` file.
2. Make the reverse-proxy pass `http://example.com/gitea/foo` to `http://gitea-server:3000/foo`. 2. Make the reverse-proxy pass `http://example.com/gitea/foo` to `http://gitea-server:3000/foo`.
3. Make sure the reverse-proxy not decode the URI, the request `http://example.com/gitea/a%2Fb` should be passed as `http://gitea-server:3000/a%2Fb`. 3. Make sure the reverse-proxy not decode the URI, the request `http://example.com/gitea/a%2Fb` should be passed as `http://gitea-server:3000/a%2Fb`.
## Docker / Container Registry
The container registry uses a fixed sub-path `/v2` which can't be changed.
Even if you deploy Gitea with a different sub-path, `/v2` will be used by the `docker` client.
Therefore you may need to add an additional route to your reverse proxy configuration.

View File

@ -23,7 +23,7 @@ If you don't want your repository to be visible for search engines read further.
## Block search engines indexation using robots.txt ## Block search engines indexation using robots.txt
To make Gitea serve a custom `robots.txt` (default: empty 404) for top level installations, To make Gitea serve a custom `robots.txt` (default: empty 404) for top level installations,
create a file called `robots.txt` in the [`custom` folder or `CustomPath`](administration/customizing-gitea.md) create a file with path `public/robots.txt` in the [`custom` folder or `CustomPath`](administration/customizing-gitea.md)
Examples on how to configure the `robots.txt` can be found at [https://moz.com/learn/seo/robotstxt](https://moz.com/learn/seo/robotstxt). Examples on how to configure the `robots.txt` can be found at [https://moz.com/learn/seo/robotstxt](https://moz.com/learn/seo/robotstxt).

View File

@ -22,7 +22,7 @@ menu:
## 使用 robots.txt 阻止搜索引擎索引 ## 使用 robots.txt 阻止搜索引擎索引
为了使 Gitea 为顶级安装提供自定义的`robots.txt`(默认为空的 404请在[`custom`文件夹或`CustomPath`]administration/customizing-gitea.md中创建一个名为 `robots.txt` 的文件。 为了使 Gitea 为顶级安装提供自定义的`robots.txt`(默认为空的 404请在 [`custom`文件夹或`CustomPath`]administration/customizing-gitea.md中创建一个名为 `public/robots.txt` 的文件。
有关如何配置 `robots.txt` 的示例,请参考 [https://moz.com/learn/seo/robotstxt](https://moz.com/learn/seo/robotstxt)。 有关如何配置 `robots.txt` 的示例,请参考 [https://moz.com/learn/seo/robotstxt](https://moz.com/learn/seo/robotstxt)。

View File

@ -86,6 +86,7 @@ Gitea creates OAuth applications for the following services by default on startu
|-----------|-----------|---------| |-----------|-----------|---------|
|[git-credential-oauth](https://github.com/hickford/git-credential-oauth)|Git credential helper|`a4792ccc-144e-407e-86c9-5e7d8d9c3269`| |[git-credential-oauth](https://github.com/hickford/git-credential-oauth)|Git credential helper|`a4792ccc-144e-407e-86c9-5e7d8d9c3269`|
|[Git Credential Manager](https://github.com/git-ecosystem/git-credential-manager)|Git credential helper|`e90ee53c-94e2-48ac-9358-a874fb9e0662`| |[Git Credential Manager](https://github.com/git-ecosystem/git-credential-manager)|Git credential helper|`e90ee53c-94e2-48ac-9358-a874fb9e0662`|
|[tea](https://gitea.com/gitea/tea)|tea|`d57cb8c4-630c-4168-8324-ec79935e18d4`|
To prevent unexpected behavior, they are being displayed as locked in the UI and their creation can instead be controlled by the `DEFAULT_APPLICATIONS` parameter in `app.ini`. To prevent unexpected behavior, they are being displayed as locked in the UI and their creation can instead be controlled by the `DEFAULT_APPLICATIONS` parameter in `app.ini`.

View File

@ -1,6 +1,6 @@
--- ---
date: "2017-07-21T12:00:00+02:00" date: "2017-07-21T12:00:00+02:00"
title: "Run as service in Linux" title: "Run as a Linux service"
slug: "linux-service" slug: "linux-service"
sidebar_position: 40 sidebar_position: 40
toc: false toc: false
@ -15,11 +15,11 @@ menu:
identifier: "linux-service" identifier: "linux-service"
--- ---
### Run Gitea as Linux service # Run as a Linux service
You can run Gitea as service, using either systemd or supervisor. The steps below tested on Ubuntu 16.04, but those should work on any Linux distributions (with little modification). You can run Gitea as a Linux service, using either systemd or supervisor. The steps below tested on Ubuntu 16.04, but those should work on any Linux distributions (with little modification).
#### Using systemd ## Using systemd
Copy the sample [gitea.service](https://github.com/go-gitea/gitea/blob/main/contrib/systemd/gitea.service) to `/etc/systemd/system/gitea.service`, then edit the file with your favorite editor. Copy the sample [gitea.service](https://github.com/go-gitea/gitea/blob/main/contrib/systemd/gitea.service) to `/etc/systemd/system/gitea.service`, then edit the file with your favorite editor.
@ -41,7 +41,7 @@ If you have systemd version 220 or later, you can enable and immediately start G
sudo systemctl enable gitea --now sudo systemctl enable gitea --now
``` ```
#### Using supervisor ## Using supervisor
Install supervisor by running below command in terminal: Install supervisor by running below command in terminal:

View File

@ -1,6 +1,6 @@
--- ---
date: "2016-12-21T15:00:00-02:00" date: "2016-12-21T15:00:00-02:00"
title: "Register as a Windows Service" title: "Register as a Windows service"
slug: "windows-service" slug: "windows-service"
sidebar_position: 50 sidebar_position: 50
toc: false toc: false
@ -14,8 +14,9 @@ menu:
sidebar_position: 50 sidebar_position: 50
identifier: "windows-service" identifier: "windows-service"
--- ---
# Register as a Windows service
# Prerequisites ## Prerequisites
The following changes are made in C:\gitea\custom\conf\app.ini: The following changes are made in C:\gitea\custom\conf\app.ini:
@ -27,7 +28,7 @@ Sets Gitea to run as the local system user.
COMPUTERNAME is whatever the response is from `echo %COMPUTERNAME%` on the command line. If the response is `USER-PC` then `RUN_USER = USER-PC$` COMPUTERNAME is whatever the response is from `echo %COMPUTERNAME%` on the command line. If the response is `USER-PC` then `RUN_USER = USER-PC$`
## Use absolute paths ### Use absolute paths
If you use SQLite3, change the `PATH` to include the full path: If you use SQLite3, change the `PATH` to include the full path:
@ -36,7 +37,7 @@ If you use SQLite3, change the `PATH` to include the full path:
PATH = c:/gitea/data/gitea.db PATH = c:/gitea/data/gitea.db
``` ```
# Register as a Windows Service ## Register Gitea
To register Gitea as a Windows service, open a command prompt (cmd) as an Administrator, To register Gitea as a Windows service, open a command prompt (cmd) as an Administrator,
then run the following command: then run the following command:
@ -51,7 +52,7 @@ Open "Windows Services", search for the service named "gitea", right-click it an
"Run". If everything is OK, Gitea will be reachable on `http://localhost:3000` (or the port "Run". If everything is OK, Gitea will be reachable on `http://localhost:3000` (or the port
that was configured). that was configured).
## Service startup type ### Service startup type
It was observed that on loaded systems during boot Gitea service may fail to start with timeout records in Windows Event Log. It was observed that on loaded systems during boot Gitea service may fail to start with timeout records in Windows Event Log.
In that case change startup type to `Automatic-Delayed`. This can be done during service creation, or by running config command In that case change startup type to `Automatic-Delayed`. This can be done during service creation, or by running config command
@ -60,7 +61,7 @@ In that case change startup type to `Automatic-Delayed`. This can be done during
sc.exe config gitea start= delayed-auto sc.exe config gitea start= delayed-auto
``` ```
## Adding startup dependencies ### Adding startup dependencies
To add a startup dependency to the Gitea Windows service (eg Mysql, Mariadb), as an Administrator, then run the following command: To add a startup dependency to the Gitea Windows service (eg Mysql, Mariadb), as an Administrator, then run the following command:
@ -70,9 +71,9 @@ sc.exe config gitea depend= mariadb
This will ensure that when the Windows machine restarts, the automatic starting of Gitea is postponed until the database is ready and thus mitigate failed startups. This will ensure that when the Windows machine restarts, the automatic starting of Gitea is postponed until the database is ready and thus mitigate failed startups.
## Unregister as a service ## Unregister Gitea
To unregister Gitea as a service, open a command prompt (cmd) as an Administrator and run: To unregister Gitea as a Windows service, open a command prompt (cmd) as an Administrator and run:
``` ```
sc.exe delete gitea sc.exe delete gitea

View File

@ -77,6 +77,7 @@ curl --user your_username:your_password_or_token \
``` ```
If you are using 2FA or OAuth use a [personal access token](development/api-usage.md#authentication) instead of the password. If you are using 2FA or OAuth use a [personal access token](development/api-usage.md#authentication) instead of the password.
You cannot publish a file with the same name twice to a package. You must delete the existing package file first. You cannot publish a file with the same name twice to a package. You must delete the existing package file first.
The server responds with the following HTTP Status codes. The server responds with the following HTTP Status codes.

View File

@ -25,6 +25,7 @@ To work with the Composer package registry, you can use [Composer](https://getco
To publish a Composer package perform a HTTP PUT operation with the package content in the request body. To publish a Composer package perform a HTTP PUT operation with the package content in the request body.
The package content must be the zipped PHP project with the `composer.json` file. The package content must be the zipped PHP project with the `composer.json` file.
You cannot publish a package if a package of the same name and version already exists. You must delete the existing package first. You cannot publish a package if a package of the same name and version already exists. You must delete the existing package first.
``` ```
@ -64,7 +65,8 @@ The server responds with the following HTTP Status codes.
| HTTP Status Code | Meaning | | HTTP Status Code | Meaning |
| ----------------- | ------- | | ----------------- | ------- |
| `201 Created` | The package has been published. | | `201 Created` | The package has been published. |
| `400 Bad Request` | The package name and/or version are invalid or a package with the same name and version already exist. | | `400 Bad Request` | The package is invalid. |
| `409 Conflict` | A package file with the same combination of parameters exists already. |
## Configuring the package registry ## Configuring the package registry

View File

@ -63,6 +63,8 @@ For example:
conan upload --remote=gitea ConanPackage/1.2@gitea/final conan upload --remote=gitea ConanPackage/1.2@gitea/final
``` ```
You cannot publish a file with the same name twice to a package. You must delete the existing package or file first.
The Gitea Conan package registry has full [revision](https://docs.conan.io/en/latest/versioning/revisions.html) support. The Gitea Conan package registry has full [revision](https://docs.conan.io/en/latest/versioning/revisions.html) support.
## Install a package ## Install a package

View File

@ -63,8 +63,18 @@ curl --user your_username:your_password_or_token \
https://gitea.example.com/api/packages/testuser/conda/package-1.0.conda https://gitea.example.com/api/packages/testuser/conda/package-1.0.conda
``` ```
If you are using 2FA or OAuth use a [personal access token](development/api-usage.md#authentication) instead of the password.
You cannot publish a package if a package of the same name and version already exists. You must delete the existing package first. You cannot publish a package if a package of the same name and version already exists. You must delete the existing package first.
The server responds with the following HTTP Status codes.
| HTTP Status Code | Meaning |
| ----------------- | ------- |
| `201 Created` | The package has been published. |
| `400 Bad Request` | The package is invalid. |
| `409 Conflict` | A package file with the same combination of parameters exists already. |
## Install a package ## Install a package
To install a package from the package registry, execute one of the following commands: To install a package from the package registry, execute one of the following commands:

View File

@ -68,8 +68,18 @@ curl --user your_username:your_password_or_token \
https://gitea.example.com/api/packages/testuser/cran/bin?platform=windows&rversion=4.2 https://gitea.example.com/api/packages/testuser/cran/bin?platform=windows&rversion=4.2
``` ```
If you are using 2FA or OAuth use a [personal access token](development/api-usage.md#authentication) instead of the password.
You cannot publish a package if a package of the same name and version already exists. You must delete the existing package first. You cannot publish a package if a package of the same name and version already exists. You must delete the existing package first.
The server responds with the following HTTP Status codes.
| HTTP Status Code | Meaning |
| ----------------- | ------- |
| `201 Created` | The package has been published. |
| `400 Bad Request` | The package is invalid. |
| `409 Conflict` | A package file with the same combination of parameters exists already. |
## Install a package ## Install a package
To install a R package from the package registry, execute the following command: To install a R package from the package registry, execute the following command:

View File

@ -77,14 +77,15 @@ curl --user your_username:your_password_or_token \
``` ```
If you are using 2FA or OAuth use a [personal access token](development/api-usage.md#authentication) instead of the password. If you are using 2FA or OAuth use a [personal access token](development/api-usage.md#authentication) instead of the password.
You cannot publish a file with the same name twice to a package. You must delete the existing package version first.
You cannot publish a package if a package of the same name, version, distribution, component and architecture already exists. You must delete the existing package first.
The server responds with the following HTTP Status codes. The server responds with the following HTTP Status codes.
| HTTP Status Code | Meaning | | HTTP Status Code | Meaning |
| ----------------- | ------- | | ----------------- | ------- |
| `201 Created` | The package has been published. | | `201 Created` | The package has been published. |
| `400 Bad Request` | The package name, version, distribution, component or architecture are invalid. | | `400 Bad Request` | The package is invalid. |
| `409 Conflict` | A package file with the same combination of parameters exists already. | | `409 Conflict` | A package file with the same combination of parameters exists already. |
## Delete a package ## Delete a package

View File

@ -41,6 +41,8 @@ curl --user your_username:your_password_or_token \
If you are using 2FA or OAuth use a [personal access token](development/api-usage.md#authentication) instead of the password. If you are using 2FA or OAuth use a [personal access token](development/api-usage.md#authentication) instead of the password.
You cannot publish a package if a package of the same name and version already exists. You must delete the existing package first.
The server responds with the following HTTP Status codes. The server responds with the following HTTP Status codes.
| HTTP Status Code | Meaning | | HTTP Status Code | Meaning |

View File

@ -67,6 +67,14 @@ curl -X PUT --user {username}:{password} \
You cannot publish a package if a package of the same name and version already exists. You must delete the existing package first. You cannot publish a package if a package of the same name and version already exists. You must delete the existing package first.
The server responds with the following HTTP Status codes.
| HTTP Status Code | Meaning |
| ----------------- | ------- |
| `201 Created` | The package has been published. |
| `400 Bad Request` | The package is invalid. |
| `409 Conflict` | A package file with the same combination of parameters exists already. |
## Install a package ## Install a package
To install a Swift package from the package registry, add it in the `Package.swift` file dependencies list: To install a Swift package from the package registry, add it in the `Package.swift` file dependencies list:

View File

@ -44,8 +44,18 @@ curl --user your_username:your_password_or_token \
https://gitea.example.com/api/packages/testuser/vagrant/test_system/1.0.0/hyperv.box https://gitea.example.com/api/packages/testuser/vagrant/test_system/1.0.0/hyperv.box
``` ```
If you are using 2FA or OAuth use a [personal access token](development/api-usage.md#authentication) instead of the password.
You cannot publish a box if a box of the same name, version and provider already exists. You must delete the existing package first. You cannot publish a box if a box of the same name, version and provider already exists. You must delete the existing package first.
The server responds with the following HTTP Status codes.
| HTTP Status Code | Meaning |
| ----------------- | ------- |
| `201 Created` | The package has been published. |
| `400 Bad Request` | The package is invalid. |
| `409 Conflict` | A package with the same combination of parameters exists already. |
## Install a package ## Install a package
To install a box from the package registry, execute the following command: To install a box from the package registry, execute the following command:

2
go.mod
View File

@ -41,7 +41,7 @@ require (
github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73 github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73
github.com/go-chi/chi/v5 v5.0.10 github.com/go-chi/chi/v5 v5.0.10
github.com/go-chi/cors v1.2.1 github.com/go-chi/cors v1.2.1
github.com/go-co-op/gocron v1.35.0 github.com/go-co-op/gocron v1.31.1
github.com/go-enry/go-enry/v2 v2.8.6 github.com/go-enry/go-enry/v2 v2.8.6
github.com/go-fed/httpsig v1.1.1-0.20201223112313-55836744818e github.com/go-fed/httpsig v1.1.1-0.20201223112313-55836744818e
github.com/go-git/go-billy/v5 v5.5.0 github.com/go-git/go-billy/v5 v5.5.0

4
go.sum
View File

@ -345,8 +345,8 @@ github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk=
github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4= github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58= github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
github.com/go-co-op/gocron v1.35.0 h1:niC91OHiSEimXgPPay02AI1gLGL4JGBgDzmWtgZ8n5A= github.com/go-co-op/gocron v1.31.1 h1:LZAuBlU0t3SPGUMJGhrJ6VuCc3CsrYzkzicygvVWlfA=
github.com/go-co-op/gocron v1.35.0/go.mod h1:NLi+bkm4rRSy1F8U7iacZOz0xPseMoIOnvabGoSe/no= github.com/go-co-op/gocron v1.31.1/go.mod h1:39f6KNSGVOU1LO/ZOoZfcSxwlsJDQOKSu8erN0SH48Y=
github.com/go-enry/go-enry/v2 v2.8.6 h1:T6ljs5+qNiUTDqpfK5GUD5EvLNdDbf804u8iC30vw7U= github.com/go-enry/go-enry/v2 v2.8.6 h1:T6ljs5+qNiUTDqpfK5GUD5EvLNdDbf804u8iC30vw7U=
github.com/go-enry/go-enry/v2 v2.8.6/go.mod h1:9yrj4ES1YrbNb1Wb7/PWYr2bpaCXUGRt0uafN0ISyG8= github.com/go-enry/go-enry/v2 v2.8.6/go.mod h1:9yrj4ES1YrbNb1Wb7/PWYr2bpaCXUGRt0uafN0ISyG8=
github.com/go-enry/go-oniguruma v1.2.1 h1:k8aAMuJfMrqm/56SG2lV9Cfti6tC4x8673aHCcBk+eo= github.com/go-enry/go-oniguruma v1.2.1 h1:k8aAMuJfMrqm/56SG2lV9Cfti6tC4x8673aHCcBk+eo=

View File

@ -42,7 +42,7 @@ func (jobs ActionJobList) LoadRuns(ctx context.Context, withRepo bool) error {
for _, r := range runs { for _, r := range runs {
runsList = append(runsList, r) runsList = append(runsList, r)
} }
return runsList.LoadRepos() return runsList.LoadRepos(ctx)
} }
return nil return nil
} }

View File

@ -52,9 +52,9 @@ func (runs RunList) LoadTriggerUser(ctx context.Context) error {
return nil return nil
} }
func (runs RunList) LoadRepos() error { func (runs RunList) LoadRepos(ctx context.Context) error {
repoIDs := runs.GetRepoIDs() repoIDs := runs.GetRepoIDs()
repos, err := repo_model.GetRepositoriesMapByIDs(repoIDs) repos, err := repo_model.GetRepositoriesMapByIDs(ctx, repoIDs)
if err != nil { if err != nil {
return err return err
} }

View File

@ -49,9 +49,9 @@ func (schedules ScheduleList) LoadTriggerUser(ctx context.Context) error {
return nil return nil
} }
func (schedules ScheduleList) LoadRepos() error { func (schedules ScheduleList) LoadRepos(ctx context.Context) error {
repoIDs := schedules.GetRepoIDs() repoIDs := schedules.GetRepoIDs()
repos, err := repo_model.GetRepositoriesMapByIDs(repoIDs) repos, err := repo_model.GetRepositoriesMapByIDs(ctx, repoIDs)
if err != nil { if err != nil {
return err return err
} }

View File

@ -53,9 +53,9 @@ func (specs SpecList) GetRepoIDs() []int64 {
return ids.Values() return ids.Values()
} }
func (specs SpecList) LoadRepos() error { func (specs SpecList) LoadRepos(ctx context.Context) error {
repoIDs := specs.GetRepoIDs() repoIDs := specs.GetRepoIDs()
repos, err := repo_model.GetRepositoriesMapByIDs(repoIDs) repos, err := repo_model.GetRepositoriesMapByIDs(ctx, repoIDs)
if err != nil { if err != nil {
return err return err
} }

View File

@ -102,7 +102,7 @@ func GetStatistic(ctx context.Context) (stats Statistic) {
stats.Counter.Follow, _ = e.Count(new(user_model.Follow)) stats.Counter.Follow, _ = e.Count(new(user_model.Follow))
stats.Counter.Mirror, _ = e.Count(new(repo_model.Mirror)) stats.Counter.Mirror, _ = e.Count(new(repo_model.Mirror))
stats.Counter.Release, _ = e.Count(new(repo_model.Release)) stats.Counter.Release, _ = e.Count(new(repo_model.Release))
stats.Counter.AuthSource = auth.CountSources() stats.Counter.AuthSource = auth.CountSources(ctx)
stats.Counter.Webhook, _ = e.Count(new(webhook.Webhook)) stats.Counter.Webhook, _ = e.Count(new(webhook.Webhook))
stats.Counter.Milestone, _ = e.Count(new(issues_model.Milestone)) stats.Counter.Milestone, _ = e.Count(new(issues_model.Milestone))
stats.Counter.Label, _ = e.Count(new(issues_model.Label)) stats.Counter.Label, _ = e.Count(new(issues_model.Label))

View File

@ -91,7 +91,7 @@ func addKey(ctx context.Context, key *PublicKey) (err error) {
} }
// AddPublicKey adds new public key to database and authorized_keys file. // AddPublicKey adds new public key to database and authorized_keys file.
func AddPublicKey(ownerID int64, name, content string, authSourceID int64) (*PublicKey, error) { func AddPublicKey(ctx context.Context, ownerID int64, name, content string, authSourceID int64) (*PublicKey, error) {
log.Trace(content) log.Trace(content)
fingerprint, err := CalcFingerprint(content) fingerprint, err := CalcFingerprint(content)
@ -99,7 +99,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(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -136,9 +136,9 @@ func AddPublicKey(ownerID int64, name, content string, authSourceID int64) (*Pub
} }
// GetPublicKeyByID returns public key by given ID. // GetPublicKeyByID returns public key by given ID.
func GetPublicKeyByID(keyID int64) (*PublicKey, error) { func GetPublicKeyByID(ctx context.Context, keyID int64) (*PublicKey, error) {
key := new(PublicKey) key := new(PublicKey)
has, err := db.GetEngine(db.DefaultContext). has, err := db.GetEngine(ctx).
ID(keyID). ID(keyID).
Get(key) Get(key)
if err != nil { if err != nil {
@ -180,7 +180,7 @@ func SearchPublicKeyByContentExact(ctx context.Context, content string) (*Public
} }
// SearchPublicKey returns a list of public keys matching the provided arguments. // SearchPublicKey returns a list of public keys matching the provided arguments.
func SearchPublicKey(uid int64, fingerprint string) ([]*PublicKey, error) { func SearchPublicKey(ctx context.Context, uid int64, fingerprint string) ([]*PublicKey, error) {
keys := make([]*PublicKey, 0, 5) keys := make([]*PublicKey, 0, 5)
cond := builder.NewCond() cond := builder.NewCond()
if uid != 0 { if uid != 0 {
@ -189,12 +189,12 @@ func SearchPublicKey(uid int64, fingerprint string) ([]*PublicKey, error) {
if fingerprint != "" { if fingerprint != "" {
cond = cond.And(builder.Eq{"fingerprint": fingerprint}) cond = cond.And(builder.Eq{"fingerprint": fingerprint})
} }
return keys, db.GetEngine(db.DefaultContext).Where(cond).Find(&keys) return keys, db.GetEngine(ctx).Where(cond).Find(&keys)
} }
// ListPublicKeys returns a list of public keys belongs to given user. // ListPublicKeys returns a list of public keys belongs to given user.
func ListPublicKeys(uid int64, listOptions db.ListOptions) ([]*PublicKey, error) { func ListPublicKeys(ctx context.Context, uid int64, listOptions db.ListOptions) ([]*PublicKey, error) {
sess := db.GetEngine(db.DefaultContext).Where("owner_id = ? AND type != ?", uid, KeyTypePrincipal) sess := db.GetEngine(ctx).Where("owner_id = ? AND type != ?", uid, KeyTypePrincipal)
if listOptions.Page != 0 { if listOptions.Page != 0 {
sess = db.SetSessionPagination(sess, &listOptions) sess = db.SetSessionPagination(sess, &listOptions)
@ -207,30 +207,30 @@ func ListPublicKeys(uid int64, listOptions db.ListOptions) ([]*PublicKey, error)
} }
// CountPublicKeys count public keys a user has // CountPublicKeys count public keys a user has
func CountPublicKeys(userID int64) (int64, error) { func CountPublicKeys(ctx context.Context, userID int64) (int64, error) {
sess := db.GetEngine(db.DefaultContext).Where("owner_id = ? AND type != ?", userID, KeyTypePrincipal) sess := db.GetEngine(ctx).Where("owner_id = ? AND type != ?", userID, KeyTypePrincipal)
return sess.Count(&PublicKey{}) return sess.Count(&PublicKey{})
} }
// ListPublicKeysBySource returns a list of synchronized public keys for a given user and login source. // ListPublicKeysBySource returns a list of synchronized public keys for a given user and login source.
func ListPublicKeysBySource(uid, authSourceID int64) ([]*PublicKey, error) { func ListPublicKeysBySource(ctx context.Context, uid, authSourceID int64) ([]*PublicKey, error) {
keys := make([]*PublicKey, 0, 5) keys := make([]*PublicKey, 0, 5)
return keys, db.GetEngine(db.DefaultContext). return keys, db.GetEngine(ctx).
Where("owner_id = ? AND login_source_id = ?", uid, authSourceID). Where("owner_id = ? AND login_source_id = ?", uid, authSourceID).
Find(&keys) Find(&keys)
} }
// UpdatePublicKeyUpdated updates public key use time. // UpdatePublicKeyUpdated updates public key use time.
func UpdatePublicKeyUpdated(id int64) error { func UpdatePublicKeyUpdated(ctx context.Context, id int64) error {
// Check if key exists before update as affected rows count is unreliable // Check if key exists before update as affected rows count is unreliable
// and will return 0 affected rows if two updates are made at the same time // and will return 0 affected rows if two updates are made at the same time
if cnt, err := db.GetEngine(db.DefaultContext).ID(id).Count(&PublicKey{}); err != nil { if cnt, err := db.GetEngine(ctx).ID(id).Count(&PublicKey{}); err != nil {
return err return err
} else if cnt != 1 { } else if cnt != 1 {
return ErrKeyNotExist{id} return ErrKeyNotExist{id}
} }
_, err := db.GetEngine(db.DefaultContext).ID(id).Cols("updated_unix").Update(&PublicKey{ _, err := db.GetEngine(ctx).ID(id).Cols("updated_unix").Update(&PublicKey{
UpdatedUnix: timeutil.TimeStampNow(), UpdatedUnix: timeutil.TimeStampNow(),
}) })
if err != nil { if err != nil {
@ -250,7 +250,7 @@ func DeletePublicKeys(ctx context.Context, keyIDs ...int64) error {
} }
// PublicKeysAreExternallyManaged returns whether the provided KeyID represents an externally managed Key // PublicKeysAreExternallyManaged returns whether the provided KeyID represents an externally managed Key
func PublicKeysAreExternallyManaged(keys []*PublicKey) ([]bool, error) { func PublicKeysAreExternallyManaged(ctx context.Context, keys []*PublicKey) ([]bool, error) {
sources := make([]*auth.Source, 0, 5) sources := make([]*auth.Source, 0, 5)
externals := make([]bool, len(keys)) externals := make([]bool, len(keys))
keyloop: keyloop:
@ -272,7 +272,7 @@ keyloop:
if source == nil { if source == nil {
var err error var err error
source, err = auth.GetSourceByID(key.LoginSourceID) source, err = auth.GetSourceByID(ctx, key.LoginSourceID)
if err != nil { if err != nil {
if auth.IsErrSourceNotExist(err) { if auth.IsErrSourceNotExist(err) {
externals[i] = false externals[i] = false
@ -295,15 +295,15 @@ keyloop:
} }
// PublicKeyIsExternallyManaged returns whether the provided KeyID represents an externally managed Key // PublicKeyIsExternallyManaged returns whether the provided KeyID represents an externally managed Key
func PublicKeyIsExternallyManaged(id int64) (bool, error) { func PublicKeyIsExternallyManaged(ctx context.Context, id int64) (bool, error) {
key, err := GetPublicKeyByID(id) key, err := GetPublicKeyByID(ctx, id)
if err != nil { if err != nil {
return false, err return false, err
} }
if key.LoginSourceID == 0 { if key.LoginSourceID == 0 {
return false, nil return false, nil
} }
source, err := auth.GetSourceByID(key.LoginSourceID) source, err := auth.GetSourceByID(ctx, key.LoginSourceID)
if err != nil { if err != nil {
if auth.IsErrSourceNotExist(err) { if auth.IsErrSourceNotExist(err) {
return false, nil return false, nil
@ -318,9 +318,9 @@ 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(ctx context.Context, keys []string) (bool, error) {
// Start session // Start session
ctx, committer, err := db.TxContext(db.DefaultContext) ctx, committer, err := db.TxContext(ctx)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -349,7 +349,7 @@ func deleteKeysMarkedForDeletion(keys []string) (bool, error) {
} }
// AddPublicKeysBySource add a users public keys. Returns true if there are changes. // AddPublicKeysBySource add a users public keys. Returns true if there are changes.
func AddPublicKeysBySource(usr *user_model.User, s *auth.Source, sshPublicKeys []string) bool { func AddPublicKeysBySource(ctx context.Context, usr *user_model.User, s *auth.Source, sshPublicKeys []string) bool {
var sshKeysNeedUpdate bool var sshKeysNeedUpdate bool
for _, sshKey := range sshPublicKeys { for _, sshKey := range sshPublicKeys {
var err error var err error
@ -368,7 +368,7 @@ func AddPublicKeysBySource(usr *user_model.User, s *auth.Source, sshPublicKeys [
marshalled = marshalled[:len(marshalled)-1] marshalled = marshalled[:len(marshalled)-1]
sshKeyName := fmt.Sprintf("%s-%s", s.Name, ssh.FingerprintSHA256(out)) sshKeyName := fmt.Sprintf("%s-%s", s.Name, ssh.FingerprintSHA256(out))
if _, err := AddPublicKey(usr.ID, sshKeyName, marshalled, s.ID); err != nil { if _, err := AddPublicKey(ctx, usr.ID, sshKeyName, marshalled, s.ID); err != nil {
if IsErrKeyAlreadyExist(err) { if IsErrKeyAlreadyExist(err) {
log.Trace("AddPublicKeysBySource[%s]: Public SSH Key %s already exists for user", sshKeyName, usr.Name) log.Trace("AddPublicKeysBySource[%s]: Public SSH Key %s already exists for user", sshKeyName, usr.Name)
} else { } else {
@ -387,14 +387,14 @@ func AddPublicKeysBySource(usr *user_model.User, s *auth.Source, sshPublicKeys [
} }
// SynchronizePublicKeys updates a users public keys. Returns true if there are changes. // SynchronizePublicKeys updates a users public keys. Returns true if there are changes.
func SynchronizePublicKeys(usr *user_model.User, s *auth.Source, sshPublicKeys []string) bool { func SynchronizePublicKeys(ctx context.Context, usr *user_model.User, s *auth.Source, sshPublicKeys []string) bool {
var sshKeysNeedUpdate bool var sshKeysNeedUpdate bool
log.Trace("synchronizePublicKeys[%s]: Handling Public SSH Key synchronization for user %s", s.Name, usr.Name) log.Trace("synchronizePublicKeys[%s]: Handling Public SSH Key synchronization for user %s", s.Name, usr.Name)
// Get Public Keys from DB with current LDAP source // Get Public Keys from DB with current LDAP source
var giteaKeys []string var giteaKeys []string
keys, err := ListPublicKeysBySource(usr.ID, s.ID) keys, err := ListPublicKeysBySource(ctx, usr.ID, s.ID)
if err != nil { if err != nil {
log.Error("synchronizePublicKeys[%s]: Error listing Public SSH Keys for user %s: %v", s.Name, usr.Name, err) log.Error("synchronizePublicKeys[%s]: Error listing Public SSH Keys for user %s: %v", s.Name, usr.Name, err)
} }
@ -429,7 +429,7 @@ func SynchronizePublicKeys(usr *user_model.User, s *auth.Source, sshPublicKeys [
newKeys = append(newKeys, key) newKeys = append(newKeys, key)
} }
} }
if AddPublicKeysBySource(usr, s, newKeys) { if AddPublicKeysBySource(ctx, usr, s, newKeys) {
sshKeysNeedUpdate = true sshKeysNeedUpdate = true
} }
@ -443,7 +443,7 @@ func SynchronizePublicKeys(usr *user_model.User, s *auth.Source, sshPublicKeys [
} }
// Delete keys from DB that no longer exist in the source // Delete keys from DB that no longer exist in the source
needUpd, err := deleteKeysMarkedForDeletion(giteaKeysToDelete) needUpd, err := deleteKeysMarkedForDeletion(ctx, giteaKeysToDelete)
if err != nil { if err != nil {
log.Error("synchronizePublicKeys[%s]: Error deleting Public Keys marked for deletion for user %s: %v", s.Name, usr.Name, err) log.Error("synchronizePublicKeys[%s]: Error deleting Public Keys marked for deletion for user %s: %v", s.Name, usr.Name, err)
} }

View File

@ -21,7 +21,7 @@ import (
func ParseCommitWithSSHSignature(ctx context.Context, c *git.Commit, committer *user_model.User) *CommitVerification { func ParseCommitWithSSHSignature(ctx context.Context, c *git.Commit, committer *user_model.User) *CommitVerification {
// Now try to associate the signature with the committer, if present // Now try to associate the signature with the committer, if present
if committer.ID != 0 { if committer.ID != 0 {
keys, err := ListPublicKeys(committer.ID, db.ListOptions{}) keys, err := ListPublicKeys(ctx, committer.ID, db.ListOptions{})
if err != nil { // Skipping failed to get ssh keys of user if err != nil { // Skipping failed to get ssh keys of user
log.Error("ListPublicKeys: %v", err) log.Error("ListPublicKeys: %v", err)
return &CommitVerification{ return &CommitVerification{

View File

@ -48,8 +48,8 @@ func (key *DeployKey) AfterLoad() {
} }
// GetContent gets associated public key content. // GetContent gets associated public key content.
func (key *DeployKey) GetContent() error { func (key *DeployKey) GetContent(ctx context.Context) error {
pkey, err := GetPublicKeyByID(key.KeyID) pkey, err := GetPublicKeyByID(ctx, key.KeyID)
if err != nil { if err != nil {
return err return err
} }

View File

@ -81,7 +81,7 @@ func CalcFingerprint(publicKeyContent string) (string, error) {
fnName, fp string fnName, fp string
err error err error
) )
if setting.SSH.StartBuiltinServer { if len(setting.SSH.KeygenPath) == 0 {
fnName = "calcFingerprintNative" fnName = "calcFingerprintNative"
fp, err = calcFingerprintNative(publicKeyContent) fp, err = calcFingerprintNative(publicKeyContent)
} else { } else {

View File

@ -51,7 +51,7 @@ func Test_SSHParsePublicKey(t *testing.T) {
if err != nil { if err != nil {
// Some servers do not support ecdsa format. // Some servers do not support ecdsa format.
if !strings.Contains(err.Error(), "line 1 too long:") { if !strings.Contains(err.Error(), "line 1 too long:") {
assert.Fail(t, "%v", err) assert.FailNow(t, "%v", err)
} }
} }
assert.Equal(t, tc.keyType, keyTypeK) assert.Equal(t, tc.keyType, keyTypeK)
@ -60,7 +60,7 @@ func Test_SSHParsePublicKey(t *testing.T) {
t.Run("SSHParseKeyNative", func(t *testing.T) { t.Run("SSHParseKeyNative", func(t *testing.T) {
keyTypeK, lengthK, err := SSHNativeParsePublicKey(tc.content) keyTypeK, lengthK, err := SSHNativeParsePublicKey(tc.content)
if err != nil { if err != nil {
assert.Fail(t, "%v", err) assert.FailNow(t, "%v", err)
} }
assert.Equal(t, tc.keyType, keyTypeK) assert.Equal(t, tc.keyType, keyTypeK)
assert.EqualValues(t, tc.length, lengthK) assert.EqualValues(t, tc.length, lengthK)

View File

@ -66,6 +66,11 @@ func BuiltinApplications() map[string]*BuiltinOAuth2Application {
DisplayName: "Git Credential Manager", DisplayName: "Git Credential Manager",
RedirectURIs: []string{"http://127.0.0.1", "https://127.0.0.1"}, RedirectURIs: []string{"http://127.0.0.1", "https://127.0.0.1"},
} }
m["d57cb8c4-630c-4168-8324-ec79935e18d4"] = &BuiltinOAuth2Application{
ConfigName: "tea",
DisplayName: "tea",
RedirectURIs: []string{"http://127.0.0.1", "https://127.0.0.1"},
}
return m return m
} }

View File

@ -5,6 +5,7 @@
package auth package auth
import ( import (
"context"
"fmt" "fmt"
"reflect" "reflect"
@ -199,8 +200,8 @@ func (source *Source) SkipVerify() bool {
// CreateSource inserts a AuthSource in the DB if not already // CreateSource inserts a AuthSource in the DB if not already
// existing with the given name. // existing with the given name.
func CreateSource(source *Source) error { func CreateSource(ctx context.Context, source *Source) error {
has, err := db.GetEngine(db.DefaultContext).Where("name=?", source.Name).Exist(new(Source)) has, err := db.GetEngine(ctx).Where("name=?", source.Name).Exist(new(Source))
if err != nil { if err != nil {
return err return err
} else if has { } else if has {
@ -211,7 +212,7 @@ func CreateSource(source *Source) error {
source.IsSyncEnabled = false source.IsSyncEnabled = false
} }
_, err = db.GetEngine(db.DefaultContext).Insert(source) _, err = db.GetEngine(ctx).Insert(source)
if err != nil { if err != nil {
return err return err
} }
@ -232,7 +233,7 @@ func CreateSource(source *Source) error {
err = registerableSource.RegisterSource() err = registerableSource.RegisterSource()
if err != nil { if err != nil {
// remove the AuthSource in case of errors while registering configuration // remove the AuthSource in case of errors while registering configuration
if _, err := db.GetEngine(db.DefaultContext).Delete(source); err != nil { if _, err := db.GetEngine(ctx).Delete(source); err != nil {
log.Error("CreateSource: Error while wrapOpenIDConnectInitializeError: %v", err) log.Error("CreateSource: Error while wrapOpenIDConnectInitializeError: %v", err)
} }
} }
@ -240,33 +241,33 @@ func CreateSource(source *Source) error {
} }
// Sources returns a slice of all login sources found in DB. // Sources returns a slice of all login sources found in DB.
func Sources() ([]*Source, error) { func Sources(ctx context.Context) ([]*Source, error) {
auths := make([]*Source, 0, 6) auths := make([]*Source, 0, 6)
return auths, db.GetEngine(db.DefaultContext).Find(&auths) return auths, db.GetEngine(ctx).Find(&auths)
} }
// SourcesByType returns all sources of the specified type // SourcesByType returns all sources of the specified type
func SourcesByType(loginType Type) ([]*Source, error) { func SourcesByType(ctx context.Context, loginType Type) ([]*Source, error) {
sources := make([]*Source, 0, 1) sources := make([]*Source, 0, 1)
if err := db.GetEngine(db.DefaultContext).Where("type = ?", loginType).Find(&sources); err != nil { if err := db.GetEngine(ctx).Where("type = ?", loginType).Find(&sources); err != nil {
return nil, err return nil, err
} }
return sources, nil return sources, nil
} }
// AllActiveSources returns all active sources // AllActiveSources returns all active sources
func AllActiveSources() ([]*Source, error) { func AllActiveSources(ctx context.Context) ([]*Source, error) {
sources := make([]*Source, 0, 5) sources := make([]*Source, 0, 5)
if err := db.GetEngine(db.DefaultContext).Where("is_active = ?", true).Find(&sources); err != nil { if err := db.GetEngine(ctx).Where("is_active = ?", true).Find(&sources); err != nil {
return nil, err return nil, err
} }
return sources, nil return sources, nil
} }
// ActiveSources returns all active sources of the specified type // ActiveSources returns all active sources of the specified type
func ActiveSources(tp Type) ([]*Source, error) { func ActiveSources(ctx context.Context, tp Type) ([]*Source, error) {
sources := make([]*Source, 0, 1) sources := make([]*Source, 0, 1)
if err := db.GetEngine(db.DefaultContext).Where("is_active = ? and type = ?", true, tp).Find(&sources); err != nil { if err := db.GetEngine(ctx).Where("is_active = ? and type = ?", true, tp).Find(&sources); err != nil {
return nil, err return nil, err
} }
return sources, nil return sources, nil
@ -274,11 +275,11 @@ func ActiveSources(tp Type) ([]*Source, error) {
// IsSSPIEnabled returns true if there is at least one activated login // IsSSPIEnabled returns true if there is at least one activated login
// source of type LoginSSPI // source of type LoginSSPI
func IsSSPIEnabled() bool { func IsSSPIEnabled(ctx context.Context) bool {
if !db.HasEngine { if !db.HasEngine {
return false return false
} }
sources, err := ActiveSources(SSPI) sources, err := ActiveSources(ctx, SSPI)
if err != nil { if err != nil {
log.Error("ActiveSources: %v", err) log.Error("ActiveSources: %v", err)
return false return false
@ -287,7 +288,7 @@ func IsSSPIEnabled() bool {
} }
// GetSourceByID returns login source by given ID. // GetSourceByID returns login source by given ID.
func GetSourceByID(id int64) (*Source, error) { func GetSourceByID(ctx context.Context, id int64) (*Source, error) {
source := new(Source) source := new(Source)
if id == 0 { if id == 0 {
source.Cfg = registeredConfigs[NoType]() source.Cfg = registeredConfigs[NoType]()
@ -297,7 +298,7 @@ func GetSourceByID(id int64) (*Source, error) {
return source, nil return source, nil
} }
has, err := db.GetEngine(db.DefaultContext).ID(id).Get(source) has, err := db.GetEngine(ctx).ID(id).Get(source)
if err != nil { if err != nil {
return nil, err return nil, err
} else if !has { } else if !has {
@ -307,24 +308,24 @@ func GetSourceByID(id int64) (*Source, error) {
} }
// UpdateSource updates a Source record in DB. // UpdateSource updates a Source record in DB.
func UpdateSource(source *Source) error { func UpdateSource(ctx context.Context, source *Source) error {
var originalSource *Source var originalSource *Source
if source.IsOAuth2() { if source.IsOAuth2() {
// keep track of the original values so we can restore in case of errors while registering OAuth2 providers // keep track of the original values so we can restore in case of errors while registering OAuth2 providers
var err error var err error
if originalSource, err = GetSourceByID(source.ID); err != nil { if originalSource, err = GetSourceByID(ctx, source.ID); err != nil {
return err return err
} }
} }
has, err := db.GetEngine(db.DefaultContext).Where("name=? AND id!=?", source.Name, source.ID).Exist(new(Source)) has, err := db.GetEngine(ctx).Where("name=? AND id!=?", source.Name, source.ID).Exist(new(Source))
if err != nil { if err != nil {
return err return err
} else if has { } else if has {
return ErrSourceAlreadyExist{source.Name} return ErrSourceAlreadyExist{source.Name}
} }
_, err = db.GetEngine(db.DefaultContext).ID(source.ID).AllCols().Update(source) _, err = db.GetEngine(ctx).ID(source.ID).AllCols().Update(source)
if err != nil { if err != nil {
return err return err
} }
@ -345,7 +346,7 @@ func UpdateSource(source *Source) error {
err = registerableSource.RegisterSource() err = registerableSource.RegisterSource()
if err != nil { if err != nil {
// restore original values since we cannot update the provider it self // restore original values since we cannot update the provider it self
if _, err := db.GetEngine(db.DefaultContext).ID(source.ID).AllCols().Update(originalSource); err != nil { if _, err := db.GetEngine(ctx).ID(source.ID).AllCols().Update(originalSource); err != nil {
log.Error("UpdateSource: Error while wrapOpenIDConnectInitializeError: %v", err) log.Error("UpdateSource: Error while wrapOpenIDConnectInitializeError: %v", err)
} }
} }
@ -353,8 +354,8 @@ func UpdateSource(source *Source) error {
} }
// CountSources returns number of login sources. // CountSources returns number of login sources.
func CountSources() int64 { func CountSources(ctx context.Context) int64 {
count, _ := db.GetEngine(db.DefaultContext).Count(new(Source)) count, _ := db.GetEngine(ctx).Count(new(Source))
return count return count
} }

View File

@ -42,7 +42,7 @@ func TestDumpAuthSource(t *testing.T) {
auth_model.RegisterTypeConfig(auth_model.OAuth2, new(TestSource)) auth_model.RegisterTypeConfig(auth_model.OAuth2, new(TestSource))
auth_model.CreateSource(&auth_model.Source{ auth_model.CreateSource(db.DefaultContext, &auth_model.Source{
Type: auth_model.OAuth2, Type: auth_model.OAuth2,
Name: "TestSource", Name: "TestSource",
IsActive: false, IsActive: false,

View File

@ -31,6 +31,10 @@ func TestGetCommitStatuses(t *testing.T) {
assert.Equal(t, structs.CommitStatusPending, statuses[0].State) assert.Equal(t, structs.CommitStatusPending, statuses[0].State)
assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[0].APIURL(db.DefaultContext)) assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[0].APIURL(db.DefaultContext))
assert.Equal(t, "cov/awesomeness", statuses[1].Context)
assert.Equal(t, structs.CommitStatusWarning, statuses[1].State)
assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[1].APIURL(db.DefaultContext))
assert.Equal(t, "cov/awesomeness", statuses[2].Context) assert.Equal(t, "cov/awesomeness", statuses[2].Context)
assert.Equal(t, structs.CommitStatusSuccess, statuses[2].State) assert.Equal(t, structs.CommitStatusSuccess, statuses[2].State)
assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[2].APIURL(db.DefaultContext)) assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[2].APIURL(db.DefaultContext))

View File

@ -111,7 +111,7 @@ func findCodeComments(ctx context.Context, opts FindCommentsOptions, issue *Issu
if comment.RenderedContent, err = markdown.RenderString(&markup.RenderContext{ if comment.RenderedContent, err = markdown.RenderString(&markup.RenderContext{
Ctx: ctx, Ctx: ctx,
URLPrefix: issue.Repo.Link(), URLPrefix: issue.Repo.Link(),
Metas: issue.Repo.ComposeMetas(), Metas: issue.Repo.ComposeMetas(ctx),
}, comment.Content); err != nil { }, comment.Content); err != nil {
return nil, err return nil, err
} }

View File

@ -127,8 +127,8 @@ 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(ctx context.Context, user *user_model.User, issue, dep *Issue) error {
ctx, committer, err := db.TxContext(db.DefaultContext) ctx, committer, err := db.TxContext(ctx)
if err != nil { if err != nil {
return err return err
} }
@ -168,8 +168,8 @@ 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(ctx context.Context, user *user_model.User, issue, dep *Issue, depType DependencyType) (err error) {
ctx, committer, err := db.TxContext(db.DefaultContext) ctx, committer, err := db.TxContext(ctx)
if err != nil { if err != nil {
return err return err
} }

View File

@ -28,16 +28,16 @@ func TestCreateIssueDependency(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
// Create a dependency and check if it was successful // Create a dependency and check if it was successful
err = issues_model.CreateIssueDependency(user1, issue1, issue2) err = issues_model.CreateIssueDependency(db.DefaultContext, user1, issue1, issue2)
assert.NoError(t, err) assert.NoError(t, err)
// Do it again to see if it will check if the dependency already exists // Do it again to see if it will check if the dependency already exists
err = issues_model.CreateIssueDependency(user1, issue1, issue2) err = issues_model.CreateIssueDependency(db.DefaultContext, user1, issue1, issue2)
assert.Error(t, err) assert.Error(t, err)
assert.True(t, issues_model.IsErrDependencyExists(err)) assert.True(t, issues_model.IsErrDependencyExists(err))
// Check for circular dependencies // Check for circular dependencies
err = issues_model.CreateIssueDependency(user1, issue2, issue1) err = issues_model.CreateIssueDependency(db.DefaultContext, user1, issue2, issue1)
assert.Error(t, err) assert.Error(t, err)
assert.True(t, issues_model.IsErrCircularDependency(err)) assert.True(t, issues_model.IsErrCircularDependency(err))
@ -57,6 +57,6 @@ func TestCreateIssueDependency(t *testing.T) {
assert.True(t, left) assert.True(t, left)
// Test removing the dependency // Test removing the dependency
err = issues_model.RemoveIssueDependency(user1, issue1, issue2, issues_model.DependencyTypeBlockedBy) err = issues_model.RemoveIssueDependency(db.DefaultContext, user1, issue1, issue2, issues_model.DependencyTypeBlockedBy)
assert.NoError(t, err) assert.NoError(t, err)
} }

View File

@ -83,12 +83,12 @@ func RemoveDuplicateExclusiveIssueLabels(ctx context.Context, issue *Issue, labe
} }
// NewIssueLabel creates a new issue-label relation. // NewIssueLabel creates a new issue-label relation.
func NewIssueLabel(issue *Issue, label *Label, doer *user_model.User) (err error) { func NewIssueLabel(ctx context.Context, issue *Issue, label *Label, doer *user_model.User) (err error) {
if HasIssueLabel(db.DefaultContext, issue.ID, label.ID) { if HasIssueLabel(ctx, issue.ID, label.ID) {
return nil return nil
} }
ctx, committer, err := db.TxContext(db.DefaultContext) ctx, committer, err := db.TxContext(ctx)
if err != nil { if err != nil {
return err return err
} }
@ -149,8 +149,8 @@ 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(ctx context.Context, issue *Issue, labels []*Label, doer *user_model.User) (err error) {
ctx, committer, err := db.TxContext(db.DefaultContext) ctx, committer, err := db.TxContext(ctx)
if err != nil { if err != nil {
return err return err
} }
@ -359,8 +359,8 @@ 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(ctx context.Context, issue *Issue, doer *user_model.User) (err error) {
ctx, committer, err := db.TxContext(db.DefaultContext) ctx, committer, err := db.TxContext(ctx)
if err != nil { if err != nil {
return err return err
} }
@ -432,8 +432,8 @@ func RemoveDuplicateExclusiveLabels(labels []*Label) []*Label {
// 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(ctx context.Context, issue *Issue, labels []*Label, doer *user_model.User) (err error) {
ctx, committer, err := db.TxContext(db.DefaultContext) ctx, committer, err := db.TxContext(ctx)
if err != nil { if err != nil {
return err return err
} }

View File

@ -6,6 +6,7 @@ package issues_test
import ( import (
"testing" "testing"
"code.gitea.io/gitea/models/db"
issues_model "code.gitea.io/gitea/models/issues" issues_model "code.gitea.io/gitea/models/issues"
"code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/models/unittest"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
@ -21,7 +22,7 @@ func TestNewIssueLabelsScope(t *testing.T) {
label2 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 8}) label2 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 8})
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
assert.NoError(t, issues_model.NewIssueLabels(issue, []*issues_model.Label{label1, label2}, doer)) assert.NoError(t, issues_model.NewIssueLabels(db.DefaultContext, issue, []*issues_model.Label{label1, label2}, doer))
assert.Len(t, issue.Labels, 1) assert.Len(t, issue.Labels, 1)
assert.Equal(t, label2.ID, issue.Labels[0].ID) assert.Equal(t, label2.ID, issue.Labels[0].ID)

View File

@ -4,6 +4,8 @@
package issues package issues
import ( import (
"context"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user" user_model "code.gitea.io/gitea/models/user"
) )
@ -17,16 +19,16 @@ type IssueLockOptions struct {
// LockIssue locks an issue. This would limit commenting abilities to // LockIssue locks an issue. This would limit commenting abilities to
// users with write access to the repo // users with write access to the repo
func LockIssue(opts *IssueLockOptions) error { func LockIssue(ctx context.Context, opts *IssueLockOptions) error {
return updateIssueLock(opts, true) return updateIssueLock(ctx, opts, true)
} }
// UnlockIssue unlocks a previously locked issue. // UnlockIssue unlocks a previously locked issue.
func UnlockIssue(opts *IssueLockOptions) error { func UnlockIssue(ctx context.Context, opts *IssueLockOptions) error {
return updateIssueLock(opts, false) return updateIssueLock(ctx, opts, false)
} }
func updateIssueLock(opts *IssueLockOptions, lock bool) error { func updateIssueLock(ctx context.Context, opts *IssueLockOptions, lock bool) error {
if opts.Issue.IsLocked == lock { if opts.Issue.IsLocked == lock {
return nil return nil
} }
@ -39,7 +41,7 @@ func updateIssueLock(opts *IssueLockOptions, lock bool) error {
commentType = CommentTypeUnlock commentType = CommentTypeUnlock
} }
ctx, committer, err := db.TxContext(db.DefaultContext) ctx, committer, err := db.TxContext(ctx)
if err != nil { if err != nil {
return err return err
} }

View File

@ -38,11 +38,7 @@ func (issue *Issue) projectID(ctx context.Context) int64 {
} }
// ProjectBoardID return project board id if issue was assigned to one // ProjectBoardID return project board id if issue was assigned to one
func (issue *Issue) ProjectBoardID() int64 { func (issue *Issue) ProjectBoardID(ctx context.Context) int64 {
return issue.projectBoardID(db.DefaultContext)
}
func (issue *Issue) projectBoardID(ctx context.Context) int64 {
var ip project_model.ProjectIssue var ip project_model.ProjectIssue
has, err := db.GetEngine(ctx).Where("issue_id=?", issue.ID).Get(&ip) has, err := db.GetEngine(ctx).Where("issue_id=?", issue.ID).Get(&ip)
if err != nil || !has { if err != nil || !has {
@ -100,8 +96,8 @@ 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(ctx context.Context, issue *Issue, doer *user_model.User, newProjectID int64) error {
ctx, committer, err := db.TxContext(db.DefaultContext) ctx, committer, err := db.TxContext(ctx)
if err != nil { if err != nil {
return err return err
} }
@ -156,8 +152,8 @@ 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(ctx context.Context, issue *Issue, board *project_model.Board) error {
ctx, committer, err := db.TxContext(db.DefaultContext) ctx, committer, err := db.TxContext(ctx)
if err != nil { if err != nil {
return err return err
} }

View File

@ -444,9 +444,9 @@ func applySubscribedCondition(sess *xorm.Session, subscriberID int64) *xorm.Sess
} }
// GetRepoIDsForIssuesOptions find all repo ids for the given options // GetRepoIDsForIssuesOptions find all repo ids for the given options
func GetRepoIDsForIssuesOptions(opts *IssuesOptions, user *user_model.User) ([]int64, error) { func GetRepoIDsForIssuesOptions(ctx context.Context, opts *IssuesOptions, user *user_model.User) ([]int64, error) {
repoIDs := make([]int64, 0, 5) repoIDs := make([]int64, 0, 5)
e := db.GetEngine(db.DefaultContext) e := db.GetEngine(ctx)
sess := e.Join("INNER", "repository", "`issue`.repo_id = `repository`.id") sess := e.Join("INNER", "repository", "`issue`.repo_id = `repository`.id")

View File

@ -34,7 +34,7 @@ func TestIssue_ReplaceLabels(t *testing.T) {
for i, labelID := range labelIDs { for i, labelID := range labelIDs {
labels[i] = unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: labelID, RepoID: repo.ID}) labels[i] = unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: labelID, RepoID: repo.ID})
} }
assert.NoError(t, issues_model.ReplaceIssueLabels(issue, labels, doer)) assert.NoError(t, issues_model.ReplaceIssueLabels(db.DefaultContext, issue, labels, doer))
unittest.AssertCount(t, &issues_model.IssueLabel{IssueID: issueID}, len(expectedLabelIDs)) unittest.AssertCount(t, &issues_model.IssueLabel{IssueID: issueID}, len(expectedLabelIDs))
for _, labelID := range expectedLabelIDs { for _, labelID := range expectedLabelIDs {
unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issueID, LabelID: labelID}) unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issueID, LabelID: labelID})
@ -122,7 +122,7 @@ func TestIssue_ClearLabels(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase()) assert.NoError(t, unittest.PrepareTestDatabase())
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: test.issueID}) issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: test.issueID})
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: test.doerID}) doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: test.doerID})
assert.NoError(t, issues_model.ClearIssueLabels(issue, doer)) assert.NoError(t, issues_model.ClearIssueLabels(db.DefaultContext, issue, doer))
unittest.AssertNotExistsBean(t, &issues_model.IssueLabel{IssueID: test.issueID}) unittest.AssertNotExistsBean(t, &issues_model.IssueLabel{IssueID: test.issueID})
} }
} }
@ -230,7 +230,7 @@ func TestGetRepoIDsForIssuesOptions(t *testing.T) {
[]int64{1, 2}, []int64{1, 2},
}, },
} { } {
repoIDs, err := issues_model.GetRepoIDsForIssuesOptions(&test.Opts, user) repoIDs, err := issues_model.GetRepoIDsForIssuesOptions(db.DefaultContext, &test.Opts, user)
assert.NoError(t, err) assert.NoError(t, err)
if assert.Len(t, repoIDs, len(test.ExpectedRepoIDs)) { if assert.Len(t, repoIDs, len(test.ExpectedRepoIDs)) {
for i, repoID := range repoIDs { for i, repoID := range repoIDs {

View File

@ -307,7 +307,7 @@ func TestNewIssueLabel(t *testing.T) {
// add new IssueLabel // add new IssueLabel
prevNumIssues := label.NumIssues prevNumIssues := label.NumIssues
assert.NoError(t, issues_model.NewIssueLabel(issue, label, doer)) assert.NoError(t, issues_model.NewIssueLabel(db.DefaultContext, issue, label, doer))
unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: label.ID}) unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: label.ID})
unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{
Type: issues_model.CommentTypeLabel, Type: issues_model.CommentTypeLabel,
@ -320,7 +320,7 @@ func TestNewIssueLabel(t *testing.T) {
assert.EqualValues(t, prevNumIssues+1, label.NumIssues) assert.EqualValues(t, prevNumIssues+1, label.NumIssues)
// re-add existing IssueLabel // re-add existing IssueLabel
assert.NoError(t, issues_model.NewIssueLabel(issue, label, doer)) assert.NoError(t, issues_model.NewIssueLabel(db.DefaultContext, issue, label, doer))
unittest.CheckConsistencyFor(t, &issues_model.Issue{}, &issues_model.Label{}) unittest.CheckConsistencyFor(t, &issues_model.Issue{}, &issues_model.Label{})
} }
@ -334,19 +334,19 @@ func TestNewIssueExclusiveLabel(t *testing.T) {
exclusiveLabelB := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 8}) exclusiveLabelB := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 8})
// coexisting regular and exclusive label // coexisting regular and exclusive label
assert.NoError(t, issues_model.NewIssueLabel(issue, otherLabel, doer)) assert.NoError(t, issues_model.NewIssueLabel(db.DefaultContext, issue, otherLabel, doer))
assert.NoError(t, issues_model.NewIssueLabel(issue, exclusiveLabelA, doer)) assert.NoError(t, issues_model.NewIssueLabel(db.DefaultContext, issue, exclusiveLabelA, doer))
unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: otherLabel.ID}) unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: otherLabel.ID})
unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: exclusiveLabelA.ID}) unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: exclusiveLabelA.ID})
// exclusive label replaces existing one // exclusive label replaces existing one
assert.NoError(t, issues_model.NewIssueLabel(issue, exclusiveLabelB, doer)) assert.NoError(t, issues_model.NewIssueLabel(db.DefaultContext, issue, exclusiveLabelB, doer))
unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: otherLabel.ID}) unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: otherLabel.ID})
unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: exclusiveLabelB.ID}) unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: exclusiveLabelB.ID})
unittest.AssertNotExistsBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: exclusiveLabelA.ID}) unittest.AssertNotExistsBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: exclusiveLabelA.ID})
// exclusive label replaces existing one again // exclusive label replaces existing one again
assert.NoError(t, issues_model.NewIssueLabel(issue, exclusiveLabelA, doer)) assert.NoError(t, issues_model.NewIssueLabel(db.DefaultContext, issue, exclusiveLabelA, doer))
unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: otherLabel.ID}) unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: otherLabel.ID})
unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: exclusiveLabelA.ID}) unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: exclusiveLabelA.ID})
unittest.AssertNotExistsBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: exclusiveLabelB.ID}) unittest.AssertNotExistsBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: exclusiveLabelB.ID})
@ -359,7 +359,7 @@ func TestNewIssueLabels(t *testing.T) {
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 5}) issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 5})
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
assert.NoError(t, issues_model.NewIssueLabels(issue, []*issues_model.Label{label1, label2}, doer)) assert.NoError(t, issues_model.NewIssueLabels(db.DefaultContext, issue, []*issues_model.Label{label1, label2}, doer))
unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: label1.ID}) unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: label1.ID})
unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{
Type: issues_model.CommentTypeLabel, Type: issues_model.CommentTypeLabel,
@ -377,7 +377,7 @@ func TestNewIssueLabels(t *testing.T) {
assert.EqualValues(t, 1, label2.NumClosedIssues) assert.EqualValues(t, 1, label2.NumClosedIssues)
// corner case: test empty slice // corner case: test empty slice
assert.NoError(t, issues_model.NewIssueLabels(issue, []*issues_model.Label{}, doer)) assert.NoError(t, issues_model.NewIssueLabels(db.DefaultContext, issue, []*issues_model.Label{}, doer))
unittest.CheckConsistencyFor(t, &issues_model.Issue{}, &issues_model.Label{}) unittest.CheckConsistencyFor(t, &issues_model.Issue{}, &issues_model.Label{})
} }

View File

@ -58,8 +58,8 @@ func (opts GetMilestonesOption) toCond() builder.Cond {
} }
// GetMilestones returns milestones filtered by GetMilestonesOption's // GetMilestones returns milestones filtered by GetMilestonesOption's
func GetMilestones(opts GetMilestonesOption) (MilestoneList, int64, error) { func GetMilestones(ctx context.Context, opts GetMilestonesOption) (MilestoneList, int64, error) {
sess := db.GetEngine(db.DefaultContext).Where(opts.toCond()) sess := db.GetEngine(ctx).Where(opts.toCond())
if opts.Page != 0 { if opts.Page != 0 {
sess = db.SetSessionPagination(sess, &opts) sess = db.SetSessionPagination(sess, &opts)

View File

@ -40,7 +40,7 @@ func TestGetMilestonesByRepoID(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase()) assert.NoError(t, unittest.PrepareTestDatabase())
test := func(repoID int64, state api.StateType) { test := func(repoID int64, state api.StateType) {
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repoID}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repoID})
milestones, _, err := issues_model.GetMilestones(issues_model.GetMilestonesOption{ milestones, _, err := issues_model.GetMilestones(db.DefaultContext, issues_model.GetMilestonesOption{
RepoID: repo.ID, RepoID: repo.ID,
State: state, State: state,
}) })
@ -77,7 +77,7 @@ func TestGetMilestonesByRepoID(t *testing.T) {
test(3, api.StateClosed) test(3, api.StateClosed)
test(3, api.StateAll) test(3, api.StateAll)
milestones, _, err := issues_model.GetMilestones(issues_model.GetMilestonesOption{ milestones, _, err := issues_model.GetMilestones(db.DefaultContext, issues_model.GetMilestonesOption{
RepoID: unittest.NonexistentID, RepoID: unittest.NonexistentID,
State: api.StateOpen, State: api.StateOpen,
}) })
@ -90,7 +90,7 @@ func TestGetMilestones(t *testing.T) {
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
test := func(sortType string, sortCond func(*issues_model.Milestone) int) { test := func(sortType string, sortCond func(*issues_model.Milestone) int) {
for _, page := range []int{0, 1} { for _, page := range []int{0, 1} {
milestones, _, err := issues_model.GetMilestones(issues_model.GetMilestonesOption{ milestones, _, err := issues_model.GetMilestones(db.DefaultContext, issues_model.GetMilestonesOption{
ListOptions: db.ListOptions{ ListOptions: db.ListOptions{
Page: page, Page: page,
PageSize: setting.UI.IssuePagingNum, PageSize: setting.UI.IssuePagingNum,
@ -107,7 +107,7 @@ func TestGetMilestones(t *testing.T) {
} }
assert.True(t, sort.IntsAreSorted(values)) assert.True(t, sort.IntsAreSorted(values))
milestones, _, err = issues_model.GetMilestones(issues_model.GetMilestonesOption{ milestones, _, err = issues_model.GetMilestones(db.DefaultContext, issues_model.GetMilestonesOption{
ListOptions: db.ListOptions{ ListOptions: db.ListOptions{
Page: page, Page: page,
PageSize: setting.UI.IssuePagingNum, PageSize: setting.UI.IssuePagingNum,

View File

@ -378,9 +378,9 @@ func (pr *PullRequest) GetApprovalCounts(ctx context.Context) ([]*ReviewCount, e
} }
// GetApprovers returns the approvers of the pull request // GetApprovers returns the approvers of the pull request
func (pr *PullRequest) GetApprovers() string { func (pr *PullRequest) GetApprovers(ctx context.Context) string {
stringBuilder := strings.Builder{} stringBuilder := strings.Builder{}
if err := pr.getReviewedByLines(&stringBuilder); err != nil { if err := pr.getReviewedByLines(ctx, &stringBuilder); err != nil {
log.Error("Unable to getReviewedByLines: Error: %v", err) log.Error("Unable to getReviewedByLines: Error: %v", err)
return "" return ""
} }
@ -388,14 +388,14 @@ func (pr *PullRequest) GetApprovers() string {
return stringBuilder.String() return stringBuilder.String()
} }
func (pr *PullRequest) getReviewedByLines(writer io.Writer) error { func (pr *PullRequest) getReviewedByLines(ctx context.Context, writer io.Writer) error {
maxReviewers := setting.Repository.PullRequest.DefaultMergeMessageMaxApprovers maxReviewers := setting.Repository.PullRequest.DefaultMergeMessageMaxApprovers
if maxReviewers == 0 { if maxReviewers == 0 {
return nil return nil
} }
ctx, committer, err := db.TxContext(db.DefaultContext) ctx, committer, err := db.TxContext(ctx)
if err != nil { if err != nil {
return err return err
} }
@ -594,9 +594,9 @@ func GetUnmergedPullRequest(ctx context.Context, headRepoID, baseRepoID int64, h
// GetLatestPullRequestByHeadInfo returns the latest pull request (regardless of its status) // GetLatestPullRequestByHeadInfo returns the latest pull request (regardless of its status)
// by given head information (repo and branch). // by given head information (repo and branch).
func GetLatestPullRequestByHeadInfo(repoID int64, branch string) (*PullRequest, error) { func GetLatestPullRequestByHeadInfo(ctx context.Context, repoID int64, branch string) (*PullRequest, error) {
pr := new(PullRequest) pr := new(PullRequest)
has, err := db.GetEngine(db.DefaultContext). has, err := db.GetEngine(ctx).
Where("head_repo_id = ? AND head_branch = ? AND flow = ?", repoID, branch, PullRequestFlowGithub). Where("head_repo_id = ? AND head_branch = ? AND flow = ?", repoID, branch, PullRequestFlowGithub).
OrderBy("id DESC"). OrderBy("id DESC").
Get(pr) Get(pr)
@ -646,9 +646,9 @@ func GetPullRequestByID(ctx context.Context, id int64) (*PullRequest, error) {
} }
// GetPullRequestByIssueIDWithNoAttributes returns pull request with no attributes loaded by given issue ID. // GetPullRequestByIssueIDWithNoAttributes returns pull request with no attributes loaded by given issue ID.
func GetPullRequestByIssueIDWithNoAttributes(issueID int64) (*PullRequest, error) { func GetPullRequestByIssueIDWithNoAttributes(ctx context.Context, issueID int64) (*PullRequest, error) {
var pr PullRequest var pr PullRequest
has, err := db.GetEngine(db.DefaultContext).Where("issue_id = ?", issueID).Get(&pr) has, err := db.GetEngine(ctx).Where("issue_id = ?", issueID).Get(&pr)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -687,14 +687,14 @@ func GetAllUnmergedAgitPullRequestByPoster(ctx context.Context, uid int64) ([]*P
} }
// Update updates all fields of pull request. // Update updates all fields of pull request.
func (pr *PullRequest) Update() error { func (pr *PullRequest) Update(ctx context.Context) error {
_, err := db.GetEngine(db.DefaultContext).ID(pr.ID).AllCols().Update(pr) _, err := db.GetEngine(ctx).ID(pr.ID).AllCols().Update(pr)
return err return err
} }
// UpdateCols updates specific fields of pull request. // UpdateCols updates specific fields of pull request.
func (pr *PullRequest) UpdateCols(cols ...string) error { func (pr *PullRequest) UpdateCols(ctx context.Context, cols ...string) error {
_, err := db.GetEngine(db.DefaultContext).ID(pr.ID).Cols(cols...).Update(pr) _, err := db.GetEngine(ctx).ID(pr.ID).Cols(cols...).Update(pr)
return err return err
} }
@ -706,8 +706,8 @@ func (pr *PullRequest) UpdateColsIfNotMerged(ctx context.Context, cols ...string
// 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. // Issue must be set before this method can be called.
func (pr *PullRequest) IsWorkInProgress() bool { func (pr *PullRequest) IsWorkInProgress(ctx context.Context) bool {
if err := pr.LoadIssue(db.DefaultContext); err != nil { if err := pr.LoadIssue(ctx); err != nil {
log.Error("LoadIssue: %v", err) log.Error("LoadIssue: %v", err)
return false return false
} }
@ -774,8 +774,8 @@ func GetPullRequestsByHeadBranch(ctx context.Context, headBranch string, headRep
} }
// GetBaseBranchLink returns the relative URL of the base branch // GetBaseBranchLink returns the relative URL of the base branch
func (pr *PullRequest) GetBaseBranchLink() string { func (pr *PullRequest) GetBaseBranchLink(ctx context.Context) string {
if err := pr.LoadBaseRepo(db.DefaultContext); err != nil { if err := pr.LoadBaseRepo(ctx); err != nil {
log.Error("LoadBaseRepo: %v", err) log.Error("LoadBaseRepo: %v", err)
return "" return ""
} }
@ -786,12 +786,12 @@ func (pr *PullRequest) GetBaseBranchLink() string {
} }
// GetHeadBranchLink returns the relative URL of the head branch // GetHeadBranchLink returns the relative URL of the head branch
func (pr *PullRequest) GetHeadBranchLink() string { func (pr *PullRequest) GetHeadBranchLink(ctx context.Context) string {
if pr.Flow == PullRequestFlowAGit { if pr.Flow == PullRequestFlowAGit {
return "" return ""
} }
if err := pr.LoadHeadRepo(db.DefaultContext); err != nil { if err := pr.LoadHeadRepo(ctx); err != nil {
log.Error("LoadHeadRepo: %v", err) log.Error("LoadHeadRepo: %v", err)
return "" return ""
} }
@ -810,14 +810,14 @@ func UpdateAllowEdits(ctx context.Context, pr *PullRequest) error {
} }
// Mergeable returns if the pullrequest is mergeable. // Mergeable returns if the pullrequest is mergeable.
func (pr *PullRequest) Mergeable() bool { func (pr *PullRequest) Mergeable(ctx context.Context) bool {
// If a pull request isn't mergable if it's: // If a pull request isn't mergable if it's:
// - Being conflict checked. // - Being conflict checked.
// - Has a conflict. // - Has a conflict.
// - Received a error while being conflict checked. // - Received a error while being conflict checked.
// - Is a work-in-progress pull request. // - Is a work-in-progress pull request.
return pr.Status != PullRequestStatusChecking && pr.Status != PullRequestStatusConflict && return pr.Status != PullRequestStatusChecking && pr.Status != PullRequestStatusConflict &&
pr.Status != PullRequestStatusError && !pr.IsWorkInProgress() pr.Status != PullRequestStatusError && !pr.IsWorkInProgress(ctx)
} }
// HasEnoughApprovals returns true if pr has enough granted approvals. // HasEnoughApprovals returns true if pr has enough granted approvals.
@ -890,7 +890,7 @@ func MergeBlockedByOutdatedBranch(protectBranch *git_model.ProtectedBranch, pr *
func PullRequestCodeOwnersReview(ctx context.Context, pull *Issue, pr *PullRequest) error { func PullRequestCodeOwnersReview(ctx context.Context, pull *Issue, pr *PullRequest) error {
files := []string{"CODEOWNERS", "docs/CODEOWNERS", ".gitea/CODEOWNERS"} files := []string{"CODEOWNERS", "docs/CODEOWNERS", ".gitea/CODEOWNERS"}
if pr.IsWorkInProgress() { if pr.IsWorkInProgress(ctx) {
return nil return nil
} }

View File

@ -213,7 +213,7 @@ func TestPullRequest_Update(t *testing.T) {
pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1}) pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1})
pr.BaseBranch = "baseBranch" pr.BaseBranch = "baseBranch"
pr.HeadBranch = "headBranch" pr.HeadBranch = "headBranch"
pr.Update() pr.Update(db.DefaultContext)
pr = unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: pr.ID}) pr = unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: pr.ID})
assert.Equal(t, "baseBranch", pr.BaseBranch) assert.Equal(t, "baseBranch", pr.BaseBranch)
@ -228,7 +228,7 @@ func TestPullRequest_UpdateCols(t *testing.T) {
BaseBranch: "baseBranch", BaseBranch: "baseBranch",
HeadBranch: "headBranch", HeadBranch: "headBranch",
} }
assert.NoError(t, pr.UpdateCols("head_branch")) assert.NoError(t, pr.UpdateCols(db.DefaultContext, "head_branch"))
pr = unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1}) pr = unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 1})
assert.Equal(t, "master", pr.BaseBranch) assert.Equal(t, "master", pr.BaseBranch)
@ -260,13 +260,13 @@ func TestPullRequest_IsWorkInProgress(t *testing.T) {
pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2}) pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: 2})
pr.LoadIssue(db.DefaultContext) pr.LoadIssue(db.DefaultContext)
assert.False(t, pr.IsWorkInProgress()) assert.False(t, pr.IsWorkInProgress(db.DefaultContext))
pr.Issue.Title = "WIP: " + pr.Issue.Title pr.Issue.Title = "WIP: " + pr.Issue.Title
assert.True(t, pr.IsWorkInProgress()) assert.True(t, pr.IsWorkInProgress(db.DefaultContext))
pr.Issue.Title = "[wip]: " + pr.Issue.Title pr.Issue.Title = "[wip]: " + pr.Issue.Title
assert.True(t, pr.IsWorkInProgress()) assert.True(t, pr.IsWorkInProgress(db.DefaultContext))
} }
func TestPullRequest_GetWorkInProgressPrefixWorkInProgress(t *testing.T) { func TestPullRequest_GetWorkInProgressPrefixWorkInProgress(t *testing.T) {
@ -334,7 +334,7 @@ func TestGetApprovers(t *testing.T) {
// Official reviews are already deduplicated. Allow unofficial reviews // Official reviews are already deduplicated. Allow unofficial reviews
// to assert that there are no duplicated approvers. // to assert that there are no duplicated approvers.
setting.Repository.PullRequest.DefaultMergeMessageOfficialApproversOnly = false setting.Repository.PullRequest.DefaultMergeMessageOfficialApproversOnly = false
approvers := pr.GetApprovers() approvers := pr.GetApprovers(db.DefaultContext)
expected := "Reviewed-by: User Five <user5@example.com>\nReviewed-by: Org Six <org6@example.com>\n" expected := "Reviewed-by: User Five <user5@example.com>\nReviewed-by: Org Six <org6@example.com>\n"
assert.EqualValues(t, expected, approvers) assert.EqualValues(t, expected, approvers)
} }

View File

@ -18,9 +18,6 @@ func ReduceCommitStatus(x *xorm.Engine) error {
if _, err := sess.Exec(`UPDATE commit_status SET state='pending' WHERE state='running'`); err != nil { if _, err := sess.Exec(`UPDATE commit_status SET state='pending' WHERE state='running'`); err != nil {
return err return err
} }
if _, err := sess.Exec(`UPDATE commit_status SET state='failure' WHERE state='warning'`); err != nil {
return err
}
return sess.Commit() return sess.Commit()
} }

View File

@ -277,8 +277,8 @@ func UpdateRepoStats(ctx context.Context, id int64) error {
return nil return nil
} }
func updateUserStarNumbers(users []user_model.User) error { func updateUserStarNumbers(ctx context.Context, users []user_model.User) error {
ctx, committer, err := db.TxContext(db.DefaultContext) ctx, committer, err := db.TxContext(ctx)
if err != nil { if err != nil {
return err return err
} }
@ -294,19 +294,19 @@ func updateUserStarNumbers(users []user_model.User) error {
} }
// DoctorUserStarNum recalculate Stars number for all user // DoctorUserStarNum recalculate Stars number for all user
func DoctorUserStarNum() (err error) { func DoctorUserStarNum(ctx context.Context) (err error) {
const batchSize = 100 const batchSize = 100
for start := 0; ; start += batchSize { for start := 0; ; start += batchSize {
users := make([]user_model.User, 0, batchSize) users := make([]user_model.User, 0, batchSize)
if err = db.GetEngine(db.DefaultContext).Limit(batchSize, start).Where("type = ?", 0).Cols("id").Find(&users); err != nil { if err = db.GetEngine(ctx).Limit(batchSize, start).Where("type = ?", 0).Cols("id").Find(&users); err != nil {
return err return err
} }
if len(users) == 0 { if len(users) == 0 {
break break
} }
if err = updateUserStarNumbers(users); err != nil { if err = updateUserStarNumbers(ctx, users); err != nil {
return err return err
} }
} }

View File

@ -31,8 +31,8 @@ func ExistsWithAvatarAtStoragePath(ctx context.Context, storagePath string) (boo
} }
// 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(ctx context.Context) string {
return repo.relAvatarLink(db.DefaultContext) return repo.relAvatarLink(ctx)
} }
// generateRandomAvatar generates a random avatar for repository. // generateRandomAvatar generates a random avatar for repository.

View File

@ -108,8 +108,8 @@ func GetLanguageStats(ctx context.Context, repo *Repository) (LanguageStatList,
} }
// GetTopLanguageStats returns the top language statistics for a repository // GetTopLanguageStats returns the top language statistics for a repository
func GetTopLanguageStats(repo *Repository, limit int) (LanguageStatList, error) { func GetTopLanguageStats(ctx context.Context, repo *Repository, limit int) (LanguageStatList, error) {
stats, err := GetLanguageStats(db.DefaultContext, repo) stats, err := GetLanguageStats(ctx, repo)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -140,8 +140,8 @@ 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(ctx context.Context, repo *Repository, commitID string, stats map[string]int64) error {
ctx, committer, err := db.TxContext(db.DefaultContext) ctx, committer, err := db.TxContext(ctx)
if err != nil { if err != nil {
return err return err
} }
@ -212,8 +212,8 @@ 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(ctx context.Context, originalRepo, destRepo *Repository) error {
ctx, committer, err := db.TxContext(db.DefaultContext) ctx, committer, err := db.TxContext(ctx)
if err != nil { if err != nil {
return err return err
} }

View File

@ -447,7 +447,7 @@ func (repo *Repository) MustOwner(ctx context.Context) *user_model.User {
} }
// ComposeMetas composes a map of metas for properly rendering issue links and external issue trackers. // ComposeMetas composes a map of metas for properly rendering issue links and external issue trackers.
func (repo *Repository) ComposeMetas() map[string]string { func (repo *Repository) ComposeMetas(ctx context.Context) map[string]string {
if len(repo.RenderingMetas) == 0 { if len(repo.RenderingMetas) == 0 {
metas := map[string]string{ metas := map[string]string{
"user": repo.OwnerName, "user": repo.OwnerName,
@ -456,7 +456,7 @@ func (repo *Repository) ComposeMetas() map[string]string {
"mode": "comment", "mode": "comment",
} }
unit, err := repo.GetUnit(db.DefaultContext, unit.TypeExternalTracker) unit, err := repo.GetUnit(ctx, unit.TypeExternalTracker)
if err == nil { if err == nil {
metas["format"] = unit.ExternalTrackerConfig().ExternalTrackerFormat metas["format"] = unit.ExternalTrackerConfig().ExternalTrackerFormat
switch unit.ExternalTrackerConfig().ExternalTrackerStyle { switch unit.ExternalTrackerConfig().ExternalTrackerStyle {
@ -470,10 +470,10 @@ func (repo *Repository) ComposeMetas() map[string]string {
} }
} }
repo.MustOwner(db.DefaultContext) repo.MustOwner(ctx)
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(ctx).Table("team_repo").
Join("INNER", "team", "team.id = team_repo.team_id"). Join("INNER", "team", "team.id = team_repo.team_id").
Where("team_repo.repo_id = ?", repo.ID). Where("team_repo.repo_id = ?", repo.ID).
Select("team.lower_name"). Select("team.lower_name").
@ -489,10 +489,10 @@ func (repo *Repository) ComposeMetas() map[string]string {
} }
// ComposeDocumentMetas composes a map of metas for properly rendering documents // ComposeDocumentMetas composes a map of metas for properly rendering documents
func (repo *Repository) ComposeDocumentMetas() map[string]string { func (repo *Repository) ComposeDocumentMetas(ctx context.Context) map[string]string {
if len(repo.DocumentRenderingMetas) == 0 { if len(repo.DocumentRenderingMetas) == 0 {
metas := map[string]string{} metas := map[string]string{}
for k, v := range repo.ComposeMetas() { for k, v := range repo.ComposeMetas(ctx) {
metas[k] = v metas[k] = v
} }
metas["mode"] = "document" metas["mode"] = "document"
@ -566,8 +566,8 @@ func (repo *Repository) CanEnablePulls() bool {
} }
// AllowsPulls returns true if repository meets the requirements of accepting pulls and has them enabled. // AllowsPulls returns true if repository meets the requirements of accepting pulls and has them enabled.
func (repo *Repository) AllowsPulls() bool { func (repo *Repository) AllowsPulls(ctx context.Context) bool {
return repo.CanEnablePulls() && repo.UnitEnabled(db.DefaultContext, unit.TypePullRequests) return repo.CanEnablePulls() && repo.UnitEnabled(ctx, unit.TypePullRequests)
} }
// CanEnableEditor returns true if repository meets the requirements of web editor. // CanEnableEditor returns true if repository meets the requirements of web editor.
@ -718,12 +718,12 @@ func GetRepositoryByOwnerAndName(ctx context.Context, ownerName, repoName string
} }
// GetRepositoryByName returns the repository by given name under user if exists. // GetRepositoryByName returns the repository by given name under user if exists.
func GetRepositoryByName(ownerID int64, name string) (*Repository, error) { func GetRepositoryByName(ctx context.Context, ownerID int64, name string) (*Repository, error) {
repo := &Repository{ repo := &Repository{
OwnerID: ownerID, OwnerID: ownerID,
LowerName: strings.ToLower(name), LowerName: strings.ToLower(name),
} }
has, err := db.GetEngine(db.DefaultContext).Get(repo) has, err := db.GetEngine(ctx).Get(repo)
if err != nil { if err != nil {
return nil, err return nil, err
} else if !has { } else if !has {
@ -788,9 +788,9 @@ func GetRepositoryByID(ctx context.Context, id int64) (*Repository, error) {
} }
// GetRepositoriesMapByIDs returns the repositories by given id slice. // GetRepositoriesMapByIDs returns the repositories by given id slice.
func GetRepositoriesMapByIDs(ids []int64) (map[int64]*Repository, error) { func GetRepositoriesMapByIDs(ctx context.Context, ids []int64) (map[int64]*Repository, error) {
repos := make(map[int64]*Repository, len(ids)) repos := make(map[int64]*Repository, len(ids))
return repos, db.GetEngine(db.DefaultContext).In("id", ids).Find(&repos) return repos, db.GetEngine(ctx).In("id", ids).Find(&repos)
} }
// IsRepositoryModelOrDirExist returns true if the repository with given name under user has already existed. // IsRepositoryModelOrDirExist returns true if the repository with given name under user has already existed.
@ -822,8 +822,8 @@ func GetTemplateRepo(ctx context.Context, repo *Repository) (*Repository, error)
} }
// TemplateRepo returns the repository, which is template of this repository // TemplateRepo returns the repository, which is template of this repository
func (repo *Repository) TemplateRepo() *Repository { func (repo *Repository) TemplateRepo(ctx context.Context) *Repository {
repo, err := GetTemplateRepo(db.DefaultContext, repo) repo, err := GetTemplateRepo(ctx, repo)
if err != nil { if err != nil {
log.Error("TemplateRepo: %v", err) log.Error("TemplateRepo: %v", err)
return nil return nil

View File

@ -36,14 +36,14 @@ func init() {
} }
// GetUnindexedRepos returns repos which do not have an indexer status // GetUnindexedRepos returns repos which do not have an indexer status
func GetUnindexedRepos(indexerType RepoIndexerType, maxRepoID int64, page, pageSize int) ([]int64, error) { func GetUnindexedRepos(ctx context.Context, indexerType RepoIndexerType, maxRepoID int64, page, pageSize int) ([]int64, error) {
ids := make([]int64, 0, 50) ids := make([]int64, 0, 50)
cond := builder.Cond(builder.IsNull{ cond := builder.Cond(builder.IsNull{
"repo_indexer_status.id", "repo_indexer_status.id",
}).And(builder.Eq{ }).And(builder.Eq{
"repository.is_empty": false, "repository.is_empty": false,
}) })
sess := db.GetEngine(db.DefaultContext).Table("repository").Join("LEFT OUTER", "repo_indexer_status", "repository.id = repo_indexer_status.repo_id AND repo_indexer_status.indexer_type = ?", indexerType) sess := db.GetEngine(ctx).Table("repository").Join("LEFT OUTER", "repo_indexer_status", "repository.id = repo_indexer_status.repo_id AND repo_indexer_status.indexer_type = ?", indexerType)
if maxRepoID > 0 { if maxRepoID > 0 {
cond = builder.And(cond, builder.Lte{ cond = builder.And(cond, builder.Lte{
"repository.id": maxRepoID, "repository.id": maxRepoID,

View File

@ -21,8 +21,8 @@ import (
) )
// FindReposMapByIDs find repos as map // FindReposMapByIDs find repos as map
func FindReposMapByIDs(repoIDs []int64, res map[int64]*Repository) error { func FindReposMapByIDs(ctx context.Context, repoIDs []int64, res map[int64]*Repository) error {
return db.GetEngine(db.DefaultContext).In("id", repoIDs).Find(&res) return db.GetEngine(ctx).In("id", repoIDs).Find(&res)
} }
// RepositoryListDefaultPageSize is the default number of repositories // RepositoryListDefaultPageSize is the default number of repositories
@ -672,12 +672,12 @@ func SearchRepositoryByName(ctx context.Context, opts *SearchRepoOptions) (Repos
// SearchRepositoryIDs takes keyword and part of repository name to search, // SearchRepositoryIDs 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 SearchRepositoryIDs(opts *SearchRepoOptions) ([]int64, int64, error) { func SearchRepositoryIDs(ctx context.Context, opts *SearchRepoOptions) ([]int64, int64, error) {
opts.IncludeDescription = false opts.IncludeDescription = false
cond := SearchRepositoryCondition(opts) cond := SearchRepositoryCondition(opts)
sess, count, err := searchRepositoryByCondition(db.DefaultContext, opts, cond) sess, count, err := searchRepositoryByCondition(ctx, opts, cond)
if err != nil { if err != nil {
return nil, 0, err return nil, 0, err
} }

View File

@ -83,7 +83,7 @@ func TestMetas(t *testing.T) {
repo.Units = nil repo.Units = nil
metas := repo.ComposeMetas() metas := repo.ComposeMetas(db.DefaultContext)
assert.Equal(t, "testRepo", metas["repo"]) assert.Equal(t, "testRepo", metas["repo"])
assert.Equal(t, "testOwner", metas["user"]) assert.Equal(t, "testOwner", metas["user"])
@ -97,7 +97,7 @@ func TestMetas(t *testing.T) {
testSuccess := func(expectedStyle string) { testSuccess := func(expectedStyle string) {
repo.Units = []*repo_model.RepoUnit{&externalTracker} repo.Units = []*repo_model.RepoUnit{&externalTracker}
repo.RenderingMetas = nil repo.RenderingMetas = nil
metas := repo.ComposeMetas() metas := repo.ComposeMetas(db.DefaultContext)
assert.Equal(t, expectedStyle, metas["style"]) assert.Equal(t, expectedStyle, metas["style"])
assert.Equal(t, "testRepo", metas["repo"]) assert.Equal(t, "testRepo", metas["repo"])
assert.Equal(t, "testOwner", metas["user"]) assert.Equal(t, "testOwner", metas["user"])
@ -118,7 +118,7 @@ func TestMetas(t *testing.T) {
repo, err := repo_model.GetRepositoryByID(db.DefaultContext, 3) repo, err := repo_model.GetRepositoryByID(db.DefaultContext, 3)
assert.NoError(t, err) assert.NoError(t, err)
metas = repo.ComposeMetas() metas = repo.ComposeMetas(db.DefaultContext)
assert.Contains(t, metas, "org") assert.Contains(t, metas, "org")
assert.Contains(t, metas, "teams") assert.Contains(t, metas, "teams")
assert.Equal(t, "org3", metas["org"]) assert.Equal(t, "org3", metas["org"])

View File

@ -20,5 +20,5 @@ func TestCheckRepoStats(t *testing.T) {
func TestDoctorUserStarNum(t *testing.T) { func TestDoctorUserStarNum(t *testing.T) {
assert.NoError(t, unittest.PrepareTestDatabase()) assert.NoError(t, unittest.PrepareTestDatabase())
assert.NoError(t, DoctorUserStarNum()) assert.NoError(t, DoctorUserStarNum(db.DefaultContext))
} }

View File

@ -91,6 +91,7 @@ var (
TypeWiki, TypeWiki,
TypeProjects, TypeProjects,
TypePackages, TypePackages,
TypeActions,
} }
// ForkRepoUnits contains the default unit types for forks // ForkRepoUnits contains the default unit types for forks

View File

@ -89,7 +89,7 @@ func TestLoadUnitConfig(t *testing.T) {
setting.Repository.DefaultForkRepoUnits = []string{"repo.releases", "repo.releases"} setting.Repository.DefaultForkRepoUnits = []string{"repo.releases", "repo.releases"}
assert.NoError(t, LoadUnitConfig()) assert.NoError(t, LoadUnitConfig())
assert.Equal(t, []Type{TypeIssues}, DisabledRepoUnits) assert.Equal(t, []Type{TypeIssues}, DisabledRepoUnits)
assert.ElementsMatch(t, []Type{TypeCode, TypePullRequests, TypeReleases, TypeWiki, TypePackages, TypeProjects}, DefaultRepoUnits) assert.ElementsMatch(t, []Type{TypeCode, TypePullRequests, TypeReleases, TypeWiki, TypePackages, TypeProjects, TypeActions}, DefaultRepoUnits)
assert.Equal(t, []Type{TypeReleases}, DefaultForkRepoUnits) assert.Equal(t, []Type{TypeReleases}, DefaultForkRepoUnits)
}) })
} }

View File

@ -47,8 +47,7 @@ func checkForConsistency(t assert.TestingT, bean any) {
assert.NoError(t, err) assert.NoError(t, err)
f := consistencyCheckMap[tb.Name] f := consistencyCheckMap[tb.Name]
if f == nil { if f == nil {
assert.Fail(t, "unknown bean type: %#v", bean) assert.FailNow(t, "unknown bean type: %#v", bean)
return
} }
f(t, bean) f(t, bean)
} }

View File

@ -495,7 +495,7 @@ func RepoAssignment(ctx *Context) context.CancelFunc {
} }
// Get repository. // Get repository.
repo, err := repo_model.GetRepositoryByName(owner.ID, repoName) repo, err := repo_model.GetRepositoryByName(ctx, owner.ID, repoName)
if err != nil { if err != nil {
if repo_model.IsErrRepoNotExist(err) { if repo_model.IsErrRepoNotExist(err) {
redirectRepoID, err := repo_model.LookupRedirect(owner.ID, repoName) redirectRepoID, err := repo_model.LookupRedirect(owner.ID, repoName)
@ -711,13 +711,13 @@ func RepoAssignment(ctx *Context) context.CancelFunc {
// Pull request is allowed if this is a fork repository // Pull request is allowed if this is a fork repository
// and base repository accepts pull requests. // and base repository accepts pull requests.
if repo.BaseRepo != nil && repo.BaseRepo.AllowsPulls() { if repo.BaseRepo != nil && repo.BaseRepo.AllowsPulls(ctx) {
canCompare = true canCompare = true
ctx.Data["BaseRepo"] = repo.BaseRepo ctx.Data["BaseRepo"] = repo.BaseRepo
ctx.Repo.PullRequest.BaseRepo = repo.BaseRepo ctx.Repo.PullRequest.BaseRepo = repo.BaseRepo
ctx.Repo.PullRequest.Allowed = canPush ctx.Repo.PullRequest.Allowed = canPush
ctx.Repo.PullRequest.HeadInfoSubURL = url.PathEscape(ctx.Repo.Owner.Name) + ":" + util.PathEscapeSegments(ctx.Repo.BranchName) ctx.Repo.PullRequest.HeadInfoSubURL = url.PathEscape(ctx.Repo.Owner.Name) + ":" + util.PathEscapeSegments(ctx.Repo.BranchName)
} else if repo.AllowsPulls() { } else if repo.AllowsPulls(ctx) {
// Or, this is repository accepts pull requests between branches. // Or, this is repository accepts pull requests between branches.
canCompare = true canCompare = true
ctx.Data["BaseRepo"] = repo ctx.Data["BaseRepo"] = repo

View File

@ -83,8 +83,7 @@ func LoadRepo(t *testing.T, ctx gocontext.Context, repoID int64) {
ctx.Repo = repo ctx.Repo = repo
doer = ctx.Doer doer = ctx.Doer
default: default:
assert.Fail(t, "context is not *context.Context or *context.APIContext") assert.FailNow(t, "context is not *context.Context or *context.APIContext")
return
} }
repo.Repository = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repoID}) repo.Repository = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: repoID})
@ -105,8 +104,7 @@ func LoadRepoCommit(t *testing.T, ctx gocontext.Context) {
case *context.APIContext: case *context.APIContext:
repo = ctx.Repo repo = ctx.Repo
default: default:
assert.Fail(t, "context is not *context.Context or *context.APIContext") assert.FailNow(t, "context is not *context.Context or *context.APIContext")
return
} }
gitRepo, err := git.OpenRepository(ctx, repo.Repository.RepoPath()) gitRepo, err := git.OpenRepository(ctx, repo.Repository.RepoPath())
@ -130,8 +128,7 @@ func LoadUser(t *testing.T, ctx gocontext.Context, userID int64) {
case *context.APIContext: case *context.APIContext:
ctx.Doer = doer ctx.Doer = doer
default: default:
assert.Fail(t, "context is not *context.Context or *context.APIContext") assert.FailNow(t, "context is not *context.Context or *context.APIContext")
return
} }
} }

View File

@ -74,7 +74,7 @@ func checkPRMergeBase(ctx context.Context, logger log.Logger, autofix bool) erro
pr.MergeBase = strings.TrimSpace(pr.MergeBase) pr.MergeBase = strings.TrimSpace(pr.MergeBase)
if pr.MergeBase != oldMergeBase { if pr.MergeBase != oldMergeBase {
if autofix { if autofix {
if err := pr.UpdateCols("merge_base"); err != nil { if err := pr.UpdateCols(ctx, "merge_base"); err != nil {
logger.Critical("Failed to update merge_base. ERROR: %v", err) logger.Critical("Failed to update merge_base. ERROR: %v", err)
return fmt.Errorf("Failed to update merge_base. ERROR: %w", err) return fmt.Errorf("Failed to update merge_base. ERROR: %w", err)
} }

View File

@ -74,7 +74,7 @@ func checkHooks(ctx context.Context, logger log.Logger, autofix bool) error {
func checkUserStarNum(ctx context.Context, logger log.Logger, autofix bool) error { func checkUserStarNum(ctx context.Context, logger log.Logger, autofix bool) error {
if autofix { if autofix {
if err := models.DoctorUserStarNum(); err != nil { if err := models.DoctorUserStarNum(ctx); err != nil {
logger.Critical("Unable update User Stars numbers") logger.Critical("Unable update User Stars numbers")
return err return err
} }

View File

@ -27,7 +27,7 @@ func Test_nulSeparatedAttributeWriter_ReadAttribute(t *testing.T) {
assert.Equal(t, "linguist-vendored", attr.Attribute) assert.Equal(t, "linguist-vendored", attr.Attribute)
assert.Equal(t, "unspecified", attr.Value) assert.Equal(t, "unspecified", attr.Value)
case <-time.After(100 * time.Millisecond): case <-time.After(100 * time.Millisecond):
assert.Fail(t, "took too long to read an attribute from the list") assert.FailNow(t, "took too long to read an attribute from the list")
} }
// Write a second attribute again // Write a second attribute again
n, err = wr.Write([]byte(testStr)) n, err = wr.Write([]byte(testStr))
@ -41,7 +41,7 @@ func Test_nulSeparatedAttributeWriter_ReadAttribute(t *testing.T) {
assert.Equal(t, "linguist-vendored", attr.Attribute) assert.Equal(t, "linguist-vendored", attr.Attribute)
assert.Equal(t, "unspecified", attr.Value) assert.Equal(t, "unspecified", attr.Value)
case <-time.After(100 * time.Millisecond): case <-time.After(100 * time.Millisecond):
assert.Fail(t, "took too long to read an attribute from the list") assert.FailNow(t, "took too long to read an attribute from the list")
} }
// Write a partial attribute // Write a partial attribute
@ -52,14 +52,14 @@ func Test_nulSeparatedAttributeWriter_ReadAttribute(t *testing.T) {
select { select {
case <-wr.ReadAttribute(): case <-wr.ReadAttribute():
assert.Fail(t, "There should not be an attribute ready to read") assert.FailNow(t, "There should not be an attribute ready to read")
case <-time.After(100 * time.Millisecond): case <-time.After(100 * time.Millisecond):
} }
_, err = wr.Write([]byte("attribute\x00")) _, err = wr.Write([]byte("attribute\x00"))
assert.NoError(t, err) assert.NoError(t, err)
select { select {
case <-wr.ReadAttribute(): case <-wr.ReadAttribute():
assert.Fail(t, "There should not be an attribute ready to read") assert.FailNow(t, "There should not be an attribute ready to read")
case <-time.After(100 * time.Millisecond): case <-time.After(100 * time.Millisecond):
} }

View File

@ -71,7 +71,6 @@ func TestRepository_GetTag(t *testing.T) {
if lTag == nil { if lTag == nil {
assert.NotNil(t, lTag) assert.NotNil(t, lTag)
assert.FailNow(t, "nil lTag: %s", lTagName) assert.FailNow(t, "nil lTag: %s", lTagName)
return
} }
assert.EqualValues(t, lTagName, lTag.Name) assert.EqualValues(t, lTagName, lTag.Name)
assert.EqualValues(t, lTagCommitID, lTag.ID.String()) assert.EqualValues(t, lTagCommitID, lTag.ID.String())
@ -105,7 +104,6 @@ func TestRepository_GetTag(t *testing.T) {
if aTag == nil { if aTag == nil {
assert.NotNil(t, aTag) assert.NotNil(t, aTag)
assert.FailNow(t, "nil aTag: %s", aTagName) assert.FailNow(t, "nil aTag: %s", aTagName)
return
} }
assert.EqualValues(t, aTagName, aTag.Name) assert.EqualValues(t, aTagName, aTag.Name)
assert.EqualValues(t, aTagID, aTag.ID.String()) assert.EqualValues(t, aTagID, aTag.ID.String())

View File

@ -288,7 +288,7 @@ func populateRepoIndexer(ctx context.Context) {
return return
default: default:
} }
ids, err := repo_model.GetUnindexedRepos(repo_model.RepoIndexerTypeCode, maxRepoID, 0, 50) ids, err := repo_model.GetUnindexedRepos(ctx, repo_model.RepoIndexerTypeCode, maxRepoID, 0, 50)
if err != nil { if err != nil {
log.Error("populateRepoIndexer: %v", err) log.Error("populateRepoIndexer: %v", err)
return return

View File

@ -96,11 +96,10 @@ func TestBleveIndexAndSearch(t *testing.T) {
idx := bleve.NewIndexer(dir) idx := bleve.NewIndexer(dir)
_, err := idx.Init(context.Background()) _, err := idx.Init(context.Background())
if err != nil { if err != nil {
assert.Fail(t, "Unable to create bleve indexer Error: %v", err)
if idx != nil { if idx != nil {
idx.Close() idx.Close()
} }
return assert.FailNow(t, "Unable to create bleve indexer Error: %v", err)
} }
defer idx.Close() defer idx.Close()
@ -118,11 +117,10 @@ func TestESIndexAndSearch(t *testing.T) {
indexer := elasticsearch.NewIndexer(u, "gitea_codes") indexer := elasticsearch.NewIndexer(u, "gitea_codes")
if _, err := indexer.Init(context.Background()); err != nil { if _, err := indexer.Init(context.Background()); err != nil {
assert.Fail(t, "Unable to init ES indexer Error: %v", err)
if indexer != nil { if indexer != nil {
indexer.Close() indexer.Close()
} }
return assert.FailNow(t, "Unable to init ES indexer Error: %v", err)
} }
defer indexer.Close() defer indexer.Close()

View File

@ -107,7 +107,7 @@ func getIssueIndexerData(ctx context.Context, issueID int64) (*internal.IndexerD
NoLabel: len(labels) == 0, NoLabel: len(labels) == 0,
MilestoneID: issue.MilestoneID, MilestoneID: issue.MilestoneID,
ProjectID: projectID, ProjectID: projectID,
ProjectBoardID: issue.ProjectBoardID(), ProjectBoardID: issue.ProjectBoardID(ctx),
PosterID: issue.PosterID, PosterID: issue.PosterID,
AssigneeID: issue.AssigneeID, AssigneeID: issue.AssigneeID,
MentionIDs: mentionIDs, MentionIDs: mentionIDs,

View File

@ -68,7 +68,7 @@ func (db *DBIndexer) Index(id int64) error {
} }
return err return err
} }
err = repo_model.UpdateLanguageStats(repo, commitID, stats) err = repo_model.UpdateLanguageStats(ctx, repo, commitID, stats)
if err != nil { if err != nil {
log.Error("Unable to update language stats for ID %s for default branch %s in %s. Error: %v", commitID, repo.DefaultBranch, repo.RepoPath(), err) log.Error("Unable to update language stats for ID %s for default branch %s in %s. Error: %v", commitID, repo.DefaultBranch, repo.RepoPath(), err)
return err return err

View File

@ -4,6 +4,8 @@
package stats package stats
import ( import (
"context"
"code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo" repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/modules/graceful" "code.gitea.io/gitea/modules/graceful"
@ -28,14 +30,14 @@ func Init() error {
return err return err
} }
go populateRepoIndexer() go populateRepoIndexer(db.DefaultContext)
return nil return nil
} }
// populateRepoIndexer populate the repo indexer with pre-existing data. This // populateRepoIndexer populate the repo indexer with pre-existing data. This
// should only be run when the indexer is created for the first time. // should only be run when the indexer is created for the first time.
func populateRepoIndexer() { func populateRepoIndexer(ctx context.Context) {
log.Info("Populating the repo stats indexer with existing repositories") log.Info("Populating the repo stats indexer with existing repositories")
isShutdown := graceful.GetManager().IsShutdown() isShutdown := graceful.GetManager().IsShutdown()
@ -62,7 +64,7 @@ func populateRepoIndexer() {
return return
default: default:
} }
ids, err := repo_model.GetUnindexedRepos(repo_model.RepoIndexerTypeStats, maxRepoID, 0, 50) ids, err := repo_model.GetUnindexedRepos(ctx, repo_model.RepoIndexerTypeStats, maxRepoID, 0, 50)
if err != nil { if err != nil {
log.Error("populateRepoIndexer: %v", err) log.Error("populateRepoIndexer: %v", err)
return return

View File

@ -45,7 +45,7 @@ func TestRepoStatsIndex(t *testing.T) {
status, err := repo_model.GetIndexerStatus(db.DefaultContext, repo, repo_model.RepoIndexerTypeStats) status, err := repo_model.GetIndexerStatus(db.DefaultContext, repo, repo_model.RepoIndexerTypeStats)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, "65f1bf27bc3bf70f64657658635e66094edbcb4d", status.CommitSha) assert.Equal(t, "65f1bf27bc3bf70f64657658635e66094edbcb4d", status.CommitSha)
langs, err := repo_model.GetTopLanguageStats(repo, 5) langs, err := repo_model.GetTopLanguageStats(db.DefaultContext, repo, 5)
assert.NoError(t, err) assert.NoError(t, err)
assert.Empty(t, langs) assert.Empty(t, langs)
} }

View File

@ -50,7 +50,7 @@ func TestManager_Cancel(t *testing.T) {
select { select {
case <-ctx.Done(): case <-ctx.Done():
default: default:
assert.Fail(t, "Cancel should cancel the provided context") assert.FailNow(t, "Cancel should cancel the provided context")
} }
finished() finished()
@ -62,7 +62,7 @@ func TestManager_Cancel(t *testing.T) {
select { select {
case <-ctx.Done(): case <-ctx.Done():
default: default:
assert.Fail(t, "Cancel should cancel the provided context") assert.FailNow(t, "Cancel should cancel the provided context")
} }
finished() finished()
} }

View File

@ -46,7 +46,7 @@ CONN_STR = redis://
assert.Equal(t, "default", q.GetName()) assert.Equal(t, "default", q.GetName())
assert.Equal(t, "level", q.GetType()) assert.Equal(t, "level", q.GetType())
assert.Equal(t, filepath.Join(setting.AppDataPath, "queues/common"), q.baseConfig.DataFullDir) assert.Equal(t, filepath.Join(setting.AppDataPath, "queues/common"), q.baseConfig.DataFullDir)
assert.Equal(t, 100, q.baseConfig.Length) assert.Equal(t, 100000, q.baseConfig.Length)
assert.Equal(t, 20, q.batchLength) assert.Equal(t, 20, q.batchLength)
assert.Equal(t, "", q.baseConfig.ConnStr) assert.Equal(t, "", q.baseConfig.ConnStr)
assert.Equal(t, "default_queue", q.baseConfig.QueueFullName) assert.Equal(t, "default_queue", q.baseConfig.QueueFullName)

View File

@ -149,8 +149,9 @@ func EnvironmentToConfig(cfg ConfigProvider, envs []string) (changed bool) {
continue continue
} }
} }
key := section.Key(keyName) key := ConfigSectionKey(section, keyName)
if key == nil { if key == nil {
changed = true
key, err = section.NewKey(keyName, keyValue) key, err = section.NewKey(keyName, keyValue)
if err != nil { if err != nil {
log.Error("Error creating key: %s in section: %s with value: %s : %v", keyName, sectionName, keyValue, err) log.Error("Error creating key: %s in section: %s with value: %s : %v", keyName, sectionName, keyValue, err)

View File

@ -115,3 +115,29 @@ key = old
EnvironmentToConfig(cfg, []string{"GITEA__sec__key__FILE=" + tmpFile}) EnvironmentToConfig(cfg, []string{"GITEA__sec__key__FILE=" + tmpFile})
assert.Equal(t, "value-from-file\n", cfg.Section("sec").Key("key").String()) assert.Equal(t, "value-from-file\n", cfg.Section("sec").Key("key").String())
} }
func TestEnvironmentToConfigSubSecKey(t *testing.T) {
// the INI package has a quirk: by default, the keys are inherited.
// when maintaining the keys, the newly added sub key should not be affected by the parent key.
cfg, err := NewConfigProviderFromData(`
[sec]
key = some
`)
assert.NoError(t, err)
changed := EnvironmentToConfig(cfg, []string{"GITEA__sec_0X2E_sub__key=some"})
assert.True(t, changed)
tmpFile := t.TempDir() + "/test-sub-sec-key.ini"
defer os.Remove(tmpFile)
err = cfg.SaveTo(tmpFile)
assert.NoError(t, err)
bs, err := os.ReadFile(tmpFile)
assert.NoError(t, err)
assert.Equal(t, `[sec]
key = some
[sec.sub]
key = some
`, string(bs))
}

View File

@ -110,7 +110,7 @@ var OAuth2 = struct {
JWTSigningAlgorithm: "RS256", JWTSigningAlgorithm: "RS256",
JWTSigningPrivateKeyFile: "jwt/private.pem", JWTSigningPrivateKeyFile: "jwt/private.pem",
MaxTokenLength: math.MaxInt16, MaxTokenLength: math.MaxInt16,
DefaultApplications: []string{"git-credential-oauth", "git-credential-manager"}, DefaultApplications: []string{"git-credential-oauth", "git-credential-manager", "tea"},
} }
func loadOAuth2From(rootCfg ConfigProvider) { func loadOAuth2From(rootCfg ConfigProvider) {

View File

@ -30,7 +30,7 @@ func GetQueueSettings(rootCfg ConfigProvider, name string) (QueueSettings, error
queueSettingsDefault := QueueSettings{ queueSettingsDefault := QueueSettings{
Type: "level", // dummy, channel, level, redis Type: "level", // dummy, channel, level, redis
Datadir: "queues/common", // relative to AppDataPath Datadir: "queues/common", // relative to AppDataPath
Length: 100, // queue length before a channel queue will block Length: 100000, // queue length before a channel queue will block
QueueName: "_queue", QueueName: "_queue",
SetName: "_unique", SetName: "_unique",

View File

@ -16,13 +16,16 @@ const (
CommitStatusError CommitStatusState = "error" CommitStatusError CommitStatusState = "error"
// CommitStatusFailure is for when the CommitStatus is Failure // CommitStatusFailure is for when the CommitStatus is Failure
CommitStatusFailure CommitStatusState = "failure" CommitStatusFailure CommitStatusState = "failure"
// CommitStatusWarning is for when the CommitStatus is Warning
CommitStatusWarning CommitStatusState = "warning"
) )
var commitStatusPriorities = map[CommitStatusState]int{ var commitStatusPriorities = map[CommitStatusState]int{
CommitStatusError: 0, CommitStatusError: 0,
CommitStatusFailure: 1, CommitStatusFailure: 1,
CommitStatusPending: 2, CommitStatusWarning: 2,
CommitStatusSuccess: 3, CommitStatusPending: 3,
CommitStatusSuccess: 4,
} }
func (css CommitStatusState) String() string { func (css CommitStatusState) String() string {
@ -32,7 +35,7 @@ func (css CommitStatusState) String() string {
// NoBetterThan returns true if this State is no better than the given State // NoBetterThan returns true if this State is no better than the given State
// This function only handles the states defined in CommitStatusPriorities // This function only handles the states defined in CommitStatusPriorities
func (css CommitStatusState) NoBetterThan(css2 CommitStatusState) bool { func (css CommitStatusState) NoBetterThan(css2 CommitStatusState) bool {
// NoBetterThan only handles the 4 states above // NoBetterThan only handles the 5 states above
if _, exist := commitStatusPriorities[css]; !exist { if _, exist := commitStatusPriorities[css]; !exist {
return false return false
} }
@ -63,3 +66,8 @@ func (css CommitStatusState) IsError() bool {
func (css CommitStatusState) IsFailure() bool { func (css CommitStatusState) IsFailure() bool {
return css == CommitStatusFailure return css == CommitStatusFailure
} }
// IsWarning represents if commit status state is warning
func (css CommitStatusState) IsWarning() bool {
return css == CommitStatusWarning
}

View File

@ -74,27 +74,31 @@ func ActionIcon(opType activities_model.ActionType) string {
switch opType { switch opType {
case activities_model.ActionCreateRepo, activities_model.ActionTransferRepo, activities_model.ActionRenameRepo: case activities_model.ActionCreateRepo, activities_model.ActionTransferRepo, activities_model.ActionRenameRepo:
return "repo" return "repo"
case activities_model.ActionCommitRepo, activities_model.ActionPushTag, activities_model.ActionDeleteTag, activities_model.ActionDeleteBranch: case activities_model.ActionCommitRepo:
return "git-commit" return "git-commit"
case activities_model.ActionCreateIssue: case activities_model.ActionDeleteBranch:
return "issue-opened" return "git-branch"
case activities_model.ActionCreatePullRequest:
return "git-pull-request"
case activities_model.ActionCommentIssue, activities_model.ActionCommentPull:
return "comment-discussion"
case activities_model.ActionMergePullRequest, activities_model.ActionAutoMergePullRequest: case activities_model.ActionMergePullRequest, activities_model.ActionAutoMergePullRequest:
return "git-merge" return "git-merge"
case activities_model.ActionCloseIssue, activities_model.ActionClosePullRequest: case activities_model.ActionCreatePullRequest:
return "git-pull-request"
case activities_model.ActionClosePullRequest:
return "git-pull-request-closed"
case activities_model.ActionCreateIssue:
return "issue-opened"
case activities_model.ActionCloseIssue:
return "issue-closed" return "issue-closed"
case activities_model.ActionReopenIssue, activities_model.ActionReopenPullRequest: case activities_model.ActionReopenIssue, activities_model.ActionReopenPullRequest:
return "issue-reopened" return "issue-reopened"
case activities_model.ActionCommentIssue, activities_model.ActionCommentPull:
return "comment-discussion"
case activities_model.ActionMirrorSyncPush, activities_model.ActionMirrorSyncCreate, activities_model.ActionMirrorSyncDelete: case activities_model.ActionMirrorSyncPush, activities_model.ActionMirrorSyncCreate, activities_model.ActionMirrorSyncDelete:
return "mirror" return "mirror"
case activities_model.ActionApprovePullRequest: case activities_model.ActionApprovePullRequest:
return "check" return "check"
case activities_model.ActionRejectPullRequest: case activities_model.ActionRejectPullRequest:
return "diff" return "file-diff"
case activities_model.ActionPublishRelease: case activities_model.ActionPublishRelease, activities_model.ActionPushTag, activities_model.ActionDeleteTag:
return "tag" return "tag"
case activities_model.ActionPullReviewDismissed: case activities_model.ActionPullReviewDismissed:
return "x" return "x"

View File

@ -97,6 +97,7 @@ locked=Gesperrt
copy=Kopieren copy=Kopieren
copy_url=URL kopieren copy_url=URL kopieren
copy_hash=Hash kopieren
copy_content=Inhalt kopieren copy_content=Inhalt kopieren
copy_branch=Branchenname kopieren copy_branch=Branchenname kopieren
copy_success=Kopiert! copy_success=Kopiert!
@ -112,6 +113,7 @@ step2=Schritt 2:
error=Fehler error=Fehler
error404=Die Seite, die Du versuchst aufzurufen, <strong>existiert nicht</strong> oder <strong>Du bist nicht berechtigt</strong>, diese anzusehen. error404=Die Seite, die Du versuchst aufzurufen, <strong>existiert nicht</strong> oder <strong>Du bist nicht berechtigt</strong>, diese anzusehen.
go_back=Zurück
never=Niemals never=Niemals
unknown=Unbekannt unknown=Unbekannt
@ -183,6 +185,7 @@ network_error=Netzwerkfehler
[startpage] [startpage]
app_desc=Ein einfacher, selbst gehosteter Git-Service app_desc=Ein einfacher, selbst gehosteter Git-Service
install=Einfach zu installieren install=Einfach zu installieren
install_desc=Starte einfach <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.com/installation/install-from-binary">die Anwendung</a> für deine Plattform oder nutze <a target="_blank" rel="noopener noreferrer" href="https://github.com/go-gitea/gitea/tree/master/docker">Docker</a>. Es existieren auch <a target="_blank" rel="noopener noreferrer" href="https://docs.gitea.com/installation/install-from-package">paketierte Versionen</a>.
platform=Plattformübergreifend platform=Plattformübergreifend
platform_desc=Gitea läuft überall, wo <a target="_blank" rel="noopener noreferrer" href="http://golang.org/">Go</a> kompiliert: Windows, macOS, Linux, ARM, etc. Wähle das System, das dir am meisten gefällt! platform_desc=Gitea läuft überall, wo <a target="_blank" rel="noopener noreferrer" href="http://golang.org/">Go</a> kompiliert: Windows, macOS, Linux, ARM, etc. Wähle das System, das dir am meisten gefällt!
lightweight=Leichtgewicht lightweight=Leichtgewicht
@ -371,6 +374,7 @@ reset_password_mail_sent_prompt=Eine Bestätigungs-E-Mail wurde an <b>%s</b> ges
active_your_account=Aktiviere dein Konto active_your_account=Aktiviere dein Konto
account_activated=Konto wurde aktiviert account_activated=Konto wurde aktiviert
prohibit_login=Anmelden verboten prohibit_login=Anmelden verboten
prohibit_login_desc=Die Anmeldung mit diesem Konto ist nicht gestattet. Bitte kontaktiere den Administrator.
resent_limit_prompt=Du hast bereits eine Aktivierungs-E-Mail angefordert. Bitte warte 3 Minuten und probiere es dann nochmal. resent_limit_prompt=Du hast bereits eine Aktivierungs-E-Mail angefordert. Bitte warte 3 Minuten und probiere es dann nochmal.
has_unconfirmed_mail=Hallo %s, du hast eine unbestätigte E-Mail-Adresse (<b>%s</b>). Wenn du keine Bestätigungs-E-Mail erhalten hast oder eine neue senden möchtest, klicke bitte auf den folgenden Button. has_unconfirmed_mail=Hallo %s, du hast eine unbestätigte E-Mail-Adresse (<b>%s</b>). Wenn du keine Bestätigungs-E-Mail erhalten hast oder eine neue senden möchtest, klicke bitte auf den folgenden Button.
resend_mail=Aktivierungs-E-Mail erneut verschicken resend_mail=Aktivierungs-E-Mail erneut verschicken
@ -378,8 +382,10 @@ email_not_associate=Diese E-Mail-Adresse ist mit keinem Konto verknüpft.
send_reset_mail=Wiederherstellungs-E-Mail senden send_reset_mail=Wiederherstellungs-E-Mail senden
reset_password=Kontowiederherstellung reset_password=Kontowiederherstellung
invalid_code=Dein Bestätigungs-Code ist ungültig oder abgelaufen. invalid_code=Dein Bestätigungs-Code ist ungültig oder abgelaufen.
invalid_code_forgot_password=Dein Bestätigungscode ist ungültig oder abgelaufen. Klicke <a href="%s">hier</a>, um eine neue Sitzung zu starten.
invalid_password=Ihr Passwort stimmt nicht mit dem Passwort überein, das zur Erstellung des Kontos verwendet wurde. invalid_password=Ihr Passwort stimmt nicht mit dem Passwort überein, das zur Erstellung des Kontos verwendet wurde.
reset_password_helper=Konto wiederherstellen reset_password_helper=Konto wiederherstellen
reset_password_wrong_user=Du bist angemeldet als %s, aber der Link zur Kontowiederherstellung ist für %s
password_too_short=Das Passwort muss mindestens %d Zeichen lang sein. password_too_short=Das Passwort muss mindestens %d Zeichen lang sein.
non_local_account=Benutzer, die nicht von Gitea verwaltet werden können ihre Passwörter nicht über das Web Interface ändern. non_local_account=Benutzer, die nicht von Gitea verwaltet werden können ihre Passwörter nicht über das Web Interface ändern.
verify=Verifizieren verify=Verifizieren
@ -404,6 +410,7 @@ openid_connect_title=Mit bestehendem Konto verbinden
openid_connect_desc=Die gewählte OpenID-URI ist unbekannt. Ordne sie hier einem neuen Account zu. openid_connect_desc=Die gewählte OpenID-URI ist unbekannt. Ordne sie hier einem neuen Account zu.
openid_register_title=Neues Konto einrichten openid_register_title=Neues Konto einrichten
openid_register_desc=Die gewählte OpenID-URI ist unbekannt. Ordne sie hier einem neuen Account zu. openid_register_desc=Die gewählte OpenID-URI ist unbekannt. Ordne sie hier einem neuen Account zu.
openid_signin_desc=Gib deine OpenID-URI ein, zum Beispiel alice.openid.example.org oder https://openid.example.org/alice.
disable_forgot_password_mail=Die Kontowiederherstellung ist deaktiviert, da keine E-Mail eingerichtet ist. Bitte kontaktiere den zuständigen Administrator. disable_forgot_password_mail=Die Kontowiederherstellung ist deaktiviert, da keine E-Mail eingerichtet ist. Bitte kontaktiere den zuständigen Administrator.
disable_forgot_password_mail_admin=Die Kontowiederherstellung ist nur verfügbar, wenn eine E-Mail eingerichtet wurde. Bitte richte eine E-Mail Adresse ein, um die Kontowiederherstellung freizuschalten. disable_forgot_password_mail_admin=Die Kontowiederherstellung ist nur verfügbar, wenn eine E-Mail eingerichtet wurde. Bitte richte eine E-Mail Adresse ein, um die Kontowiederherstellung freizuschalten.
email_domain_blacklisted=Du kannst dich nicht mit deiner E-Mail-Adresse registrieren. email_domain_blacklisted=Du kannst dich nicht mit deiner E-Mail-Adresse registrieren.
@ -413,7 +420,9 @@ authorize_application_created_by=Diese Anwendung wurde von %s erstellt.
authorize_application_description=Wenn du diese Anwendung autorisierst, wird sie die Berechtigung erhalten, alle Informationen zu deinem Account zu bearbeiten oder zu lesen. Dies beinhaltet auch private Repositories und Organisationen. authorize_application_description=Wenn du diese Anwendung autorisierst, wird sie die Berechtigung erhalten, alle Informationen zu deinem Account zu bearbeiten oder zu lesen. Dies beinhaltet auch private Repositories und Organisationen.
authorize_title=`"%s" den Zugriff auf deinen Account gestatten?` authorize_title=`"%s" den Zugriff auf deinen Account gestatten?`
authorization_failed=Autorisierung fehlgeschlagen authorization_failed=Autorisierung fehlgeschlagen
authorization_failed_desc=Die Autorisierung ist fehlgeschlagen, da wir eine ungültige Anfrage erkannt haben. Bitte kontaktiere den Betreuer der App, die du zu autorisieren versucht hast.
sspi_auth_failed=SSPI-Authentifizierung fehlgeschlagen sspi_auth_failed=SSPI-Authentifizierung fehlgeschlagen
password_pwned=Das von dir gewählte Passwort befindet sich auf einer <a target="_blank" rel="noopener noreferrer" href="https://haveibeenpwned.com/Passwords">List gestohlener Passwörter</a>, die öffentlich verfügbar sind. Bitte versuche es erneut mit einem anderen Passwort und ziehe in Erwägung, auch anderswo deine Passwörter zu ändern.
password_pwned_err=Anfrage an HaveIBeenPwned konnte nicht abgeschlossen werden password_pwned_err=Anfrage an HaveIBeenPwned konnte nicht abgeschlossen werden
[mail] [mail]
@ -428,6 +437,7 @@ activate_account.text_1=Hallo <b>%[1]s</b>, danke für deine Registrierung bei %
activate_account.text_2=Bitte klicke innerhalb von <b>%s</b> auf folgenden Link, um dein Konto zu aktivieren: activate_account.text_2=Bitte klicke innerhalb von <b>%s</b> auf folgenden Link, um dein Konto zu aktivieren:
activate_email=Bestätige deine E-Mail-Adresse activate_email=Bestätige deine E-Mail-Adresse
activate_email.title=%s, bitte verifiziere deine E-Mail-Adresse
activate_email.text=Bitte klicke innerhalb von <b>%s</b> auf folgenden Link, um dein Konto zu aktivieren: activate_email.text=Bitte klicke innerhalb von <b>%s</b> auf folgenden Link, um dein Konto zu aktivieren:
register_notify=Willkommen bei Gitea register_notify=Willkommen bei Gitea
@ -597,6 +607,7 @@ user_bio=Biografie
disabled_public_activity=Dieser Benutzer hat die öffentliche Sichtbarkeit der Aktivität deaktiviert. disabled_public_activity=Dieser Benutzer hat die öffentliche Sichtbarkeit der Aktivität deaktiviert.
email_visibility.limited=Ihre E-Mail-Adresse ist für alle authentifizierten Benutzer sichtbar email_visibility.limited=Ihre E-Mail-Adresse ist für alle authentifizierten Benutzer sichtbar
email_visibility.private=Deine E-Mail-Adresse ist nur für Dich und Administratoren sichtbar email_visibility.private=Deine E-Mail-Adresse ist nur für Dich und Administratoren sichtbar
show_on_map=Diesen Ort auf einer Karte anzeigen
settings=Benutzereinstellungen settings=Benutzereinstellungen
form.name_reserved=Der Benutzername "%s" ist reserviert. form.name_reserved=Der Benutzername "%s" ist reserviert.
@ -619,9 +630,13 @@ delete=Konto löschen
twofa=Zwei-Faktor-Authentifizierung twofa=Zwei-Faktor-Authentifizierung
account_link=Verknüpfte Benutzerkonten account_link=Verknüpfte Benutzerkonten
organization=Organisationen organization=Organisationen
uid=UID
webauthn=Hardware-Sicherheitsschlüssel webauthn=Hardware-Sicherheitsschlüssel
public_profile=Öffentliches Profil public_profile=Öffentliches Profil
biography_placeholder=Erzähle uns ein wenig über Dich selbst! (Du kannst Markdown verwenden)
location_placeholder=Teile Deinen ungefähren Standort mit anderen
profile_desc=Lege fest, wie dein Profil anderen Benutzern angezeigt wird. Deine primäre E-Mail-Adresse wird für Benachrichtigungen, Passwort-Wiederherstellung und webbasierte Git-Operationen verwendet.
password_username_disabled=Benutzer, die nicht von Gitea verwaltet werden können ihren Benutzernamen nicht ändern. Bitte kontaktiere deinen Administrator für mehr Details. password_username_disabled=Benutzer, die nicht von Gitea verwaltet werden können ihren Benutzernamen nicht ändern. Bitte kontaktiere deinen Administrator für mehr Details.
full_name=Vollständiger Name full_name=Vollständiger Name
website=Webseite website=Webseite
@ -633,6 +648,8 @@ update_language_not_found=Sprache "%s" ist nicht verfügbar.
update_language_success=Sprache wurde aktualisiert. update_language_success=Sprache wurde aktualisiert.
update_profile_success=Dein Profil wurde aktualisiert. update_profile_success=Dein Profil wurde aktualisiert.
change_username=Dein Benutzername wurde geändert. change_username=Dein Benutzername wurde geändert.
change_username_prompt=Hinweis: Das Ändern deines Benutzernamen ändert auch deine Account-URL.
change_username_redirect_prompt=Der alte Benutzername wird auf den neuen Benutzernamen weiterleiten, bis er erneut als Benutzername verwendet wird.
continue=Weiter continue=Weiter
cancel=Abbrechen cancel=Abbrechen
language=Sprache language=Sprache
@ -657,6 +674,7 @@ comment_type_group_project=Projekt
comment_type_group_issue_ref=Issue-Referenz comment_type_group_issue_ref=Issue-Referenz
saved_successfully=Die Einstellungen wurden erfolgreich gespeichert. saved_successfully=Die Einstellungen wurden erfolgreich gespeichert.
privacy=Datenschutz privacy=Datenschutz
keep_activity_private=Aktivität auf der Profilseite ausblenden
keep_activity_private_popup=Macht die Aktivität nur für dich und die Administratoren sichtbar keep_activity_private_popup=Macht die Aktivität nur für dich und die Administratoren sichtbar
lookup_avatar_by_mail=Profilbild anhand der E-Mail-Addresse suchen lookup_avatar_by_mail=Profilbild anhand der E-Mail-Addresse suchen
@ -666,6 +684,7 @@ choose_new_avatar=Neues Profilbild auswählen
update_avatar=Profilbild aktualisieren update_avatar=Profilbild aktualisieren
delete_current_avatar=Aktuelles Profilbild löschen delete_current_avatar=Aktuelles Profilbild löschen
uploaded_avatar_not_a_image=Die hochgeladene Datei ist kein Bild. uploaded_avatar_not_a_image=Die hochgeladene Datei ist kein Bild.
uploaded_avatar_is_too_big=Die hochgeladene Dateigröße (%d KiB) überschreitet die maximale Größe (%d KiB).
update_avatar_success=Dein Profilbild wurde geändert. update_avatar_success=Dein Profilbild wurde geändert.
update_user_avatar_success=Der Avatar des Benutzers wurde aktualisiert. update_user_avatar_success=Der Avatar des Benutzers wurde aktualisiert.
@ -681,6 +700,7 @@ emails=E-Mail-Adressen
manage_emails=E-Mail-Adressen verwalten manage_emails=E-Mail-Adressen verwalten
manage_themes=Standard-Theme auswählen manage_themes=Standard-Theme auswählen
manage_openid=OpenID-Adressen verwalten manage_openid=OpenID-Adressen verwalten
email_desc=Deine primäre E-Mail-Adresse wird für Benachrichtigungen, Passwort-Wiederherstellung und, sofern sie nicht versteckt ist, web-basierte Git-Operationen verwendet.
theme_desc=Dies wird dein Standard-Theme auf der Seite sein. theme_desc=Dies wird dein Standard-Theme auf der Seite sein.
primary=Primär primary=Primär
activated=Aktiviert activated=Aktiviert
@ -688,6 +708,7 @@ requires_activation=Erfordert Aktivierung
primary_email=Als primäre E-Mail-Adresse verwenden primary_email=Als primäre E-Mail-Adresse verwenden
activate_email=Aktivierung senden activate_email=Aktivierung senden
activations_pending=Aktivierung ausstehend activations_pending=Aktivierung ausstehend
can_not_add_email_activations_pending=Es gibt eine ausstehende Aktivierung, versuche es in ein paar Minuten erneut, wenn du eine neue E-Mail hinzufügen möchtest.
delete_email=Löschen delete_email=Löschen
email_deletion=E-Mail-Adresse löschen email_deletion=E-Mail-Adresse löschen
email_deletion_desc=Die E-Mail-Adresse und die damit verbundenen Informationen werden von deinem Konto entfernt. Git-Commits von dieser E-Mail-Addresse bleiben unverändert. Fortfahren? email_deletion_desc=Die E-Mail-Adresse und die damit verbundenen Informationen werden von deinem Konto entfernt. Git-Commits von dieser E-Mail-Addresse bleiben unverändert. Fortfahren?
@ -706,6 +727,7 @@ add_email_success=Die neue E-Mail-Addresse wurde hinzugefügt.
email_preference_set_success=E-Mail-Einstellungen wurden erfolgreich aktualisiert. email_preference_set_success=E-Mail-Einstellungen wurden erfolgreich aktualisiert.
add_openid_success=Die neue OpenID-Adresse wurde hinzugefügt. add_openid_success=Die neue OpenID-Adresse wurde hinzugefügt.
keep_email_private=E-Mail-Adresse verbergen keep_email_private=E-Mail-Adresse verbergen
keep_email_private_popup=Dies wird Deine E-Mail-Adresse nicht nur in Deinem Profil ausblenden, sondern auch, wenn Du einen Pull Request erstellst oder eine Datei über das Web-Interface bearbeitest. Gepushte Commits werden nicht geändert.
openid_desc=Mit OpenID kannst du dich über einen Drittanbieter authentifizieren. openid_desc=Mit OpenID kannst du dich über einen Drittanbieter authentifizieren.
manage_ssh_keys=SSH-Schlüssel verwalten manage_ssh_keys=SSH-Schlüssel verwalten
@ -784,7 +806,9 @@ ssh_disabled=SSH ist deaktiviert
ssh_signonly=SSH ist derzeit deaktiviert, sodass diese Schlüssel nur zur Commit-Signaturverifizierung verwendet werden. ssh_signonly=SSH ist derzeit deaktiviert, sodass diese Schlüssel nur zur Commit-Signaturverifizierung verwendet werden.
ssh_externally_managed=Dieser SSH-Schlüssel wird extern für diesen Benutzer verwaltet ssh_externally_managed=Dieser SSH-Schlüssel wird extern für diesen Benutzer verwaltet
manage_social=Verknüpfte soziale Konten verwalten manage_social=Verknüpfte soziale Konten verwalten
social_desc=Diese sozialen Konten können verwendet werden, um sich bei deinem Konto anzumelden. Stelle sicher, dass du sie alle zuordnen kannst.
unbind=Trennen unbind=Trennen
unbind_success=Das soziale Konto wurde erfolgreich entfernt.
manage_access_token=Zugriffstokens verwalten manage_access_token=Zugriffstokens verwalten
generate_new_token=Neuen Token erzeugen generate_new_token=Neuen Token erzeugen
@ -805,6 +829,8 @@ permissions_access_all=Alle (öffentlich, privat und begrenzt)
select_permissions=Berechtigungen auswählen select_permissions=Berechtigungen auswählen
permission_no_access=Kein Zugriff permission_no_access=Kein Zugriff
permission_read=Gelesen permission_read=Gelesen
permission_write=Lesen und Schreiben
access_token_desc=Ausgewählte Token-Berechtigungen beschränken die Authentifizierung auf die entsprechenden <a %s>API</a>-Routen. Lies die <a %s>Dokumentation</a> für mehr Informationen.
at_least_one_permission=Du musst mindestens eine Berechtigung auswählen, um ein Token zu erstellen at_least_one_permission=Du musst mindestens eine Berechtigung auswählen, um ein Token zu erstellen
permissions_list=Berechtigungen: permissions_list=Berechtigungen:
@ -816,6 +842,8 @@ remove_oauth2_application_desc=Das Entfernen einer OAuth2-Anwendung wird den Zug
remove_oauth2_application_success=Die Anwendung wurde gelöscht. remove_oauth2_application_success=Die Anwendung wurde gelöscht.
create_oauth2_application=Neue OAuth2 Anwendung erstellen create_oauth2_application=Neue OAuth2 Anwendung erstellen
create_oauth2_application_button=Anwendung erstellen create_oauth2_application_button=Anwendung erstellen
create_oauth2_application_success=Du hast erfolgreich eine neue OAuth2-Anwendung erstellt.
update_oauth2_application_success=Du hast die OAuth2-Anwendung erfolgreich aktualisiert.
oauth2_application_name=Name der Anwendung oauth2_application_name=Name der Anwendung
oauth2_confidential_client=Vertraulicher Client. Für Anwendungen aktivieren, die das Geheimnis sicher speichern, z. B. Webanwendungen. Wähle diese Option nicht für native Anwendungen für PCs und Mobilgeräte. oauth2_confidential_client=Vertraulicher Client. Für Anwendungen aktivieren, die das Geheimnis sicher speichern, z. B. Webanwendungen. Wähle diese Option nicht für native Anwendungen für PCs und Mobilgeräte.
oauth2_redirect_uris=URIs für die Weiterleitung. Bitte verwende eine neue Zeile für jede URI. oauth2_redirect_uris=URIs für die Weiterleitung. Bitte verwende eine neue Zeile für jede URI.
@ -824,19 +852,25 @@ oauth2_client_id=Client-ID
oauth2_client_secret=Client-Secret oauth2_client_secret=Client-Secret
oauth2_regenerate_secret=Secret neu generieren oauth2_regenerate_secret=Secret neu generieren
oauth2_regenerate_secret_hint=Secret verloren? oauth2_regenerate_secret_hint=Secret verloren?
oauth2_client_secret_hint=Das Secret wird nach dem Verlassen oder Aktualisieren dieser Seite nicht mehr angezeigt. Bitte stelle sicher, dass du es gespeichert hast.
oauth2_application_edit=Bearbeiten oauth2_application_edit=Bearbeiten
oauth2_application_create_description=OAuth2 Anwendungen geben deiner Drittanwendung Zugriff auf Benutzeraccounts dieser Gitea-Instanz. oauth2_application_create_description=OAuth2 Anwendungen geben deiner Drittanwendung Zugriff auf Benutzeraccounts dieser Gitea-Instanz.
oauth2_application_remove_description=Das Entfernen einer OAuth2-Anwendung hat zur Folge, dass diese nicht mehr auf autorisierte Benutzeraccounts auf dieser Instanz zugreifen kann. Möchtest Du fortfahren?
oauth2_application_locked=Wenn es in der Konfiguration aktiviert ist, registriert Gitea einige OAuth2-Anwendungen beim Starten vor. Um unerwartetes Verhalten zu verhindern, können diese weder bearbeitet noch entfernt werden. Weitere Informationen findest Du in der OAuth2-Dokumentation.
authorized_oauth2_applications=Autorisierte OAuth2-Anwendungen authorized_oauth2_applications=Autorisierte OAuth2-Anwendungen
authorized_oauth2_applications_description=Den folgenden Drittanbieter-Apps hast Du Zugriff auf Deinen persönlichen Gitea-Account gewährt. Bitte widerrufe die Autorisierung für Apps, die Du nicht mehr nutzt.
revoke_key=Widerrufen revoke_key=Widerrufen
revoke_oauth2_grant=Autorisierung widerrufen revoke_oauth2_grant=Autorisierung widerrufen
revoke_oauth2_grant_description=Wenn du die Autorisierung widerrufst, kann die Anwendung nicht mehr auf deine Daten zugreifen. Bist du dir sicher? revoke_oauth2_grant_description=Wenn du die Autorisierung widerrufst, kann die Anwendung nicht mehr auf deine Daten zugreifen. Bist du dir sicher?
revoke_oauth2_grant_success=Zugriff erfolgreich widerrufen.
twofa_desc=Zwei-Faktor-Authentifizierung trägt zu einer höheren Accountsicherheit bei. twofa_desc=Zwei-Faktor-Authentifizierung trägt zu einer höheren Accountsicherheit bei.
twofa_is_enrolled=Für dein Konto ist die Zwei-Faktor-Authentifizierung <strong>eingeschaltet</strong>. twofa_is_enrolled=Für dein Konto ist die Zwei-Faktor-Authentifizierung <strong>eingeschaltet</strong>.
twofa_not_enrolled=Für dein Konto ist die Zwei-Faktor-Authentifizierung momentan nicht eingeschaltet. twofa_not_enrolled=Für dein Konto ist die Zwei-Faktor-Authentifizierung momentan nicht eingeschaltet.
twofa_disable=Zwei-Faktor-Authentifizierung deaktivieren twofa_disable=Zwei-Faktor-Authentifizierung deaktivieren
twofa_scratch_token_regenerate=Neues Einmalpasswort erstellen twofa_scratch_token_regenerate=Neues Einmalpasswort erstellen
twofa_scratch_token_regenerated=Dein temporärer Token ist jetzt %s. Speichere ihn an einem sicheren Ort, er wird nie wieder angezeigt.
twofa_enroll=Zwei-Faktor-Authentifizierung aktivieren twofa_enroll=Zwei-Faktor-Authentifizierung aktivieren
twofa_disable_note=Du kannst die Zwei-Faktor-Authentifizierung auch wieder deaktivieren. twofa_disable_note=Du kannst die Zwei-Faktor-Authentifizierung auch wieder deaktivieren.
twofa_disable_desc=Wenn du die Zwei-Faktor-Authentifizierung deaktivierst, wird die Sicherheit deines Kontos verringert. Fortfahren? twofa_disable_desc=Wenn du die Zwei-Faktor-Authentifizierung deaktivierst, wird die Sicherheit deines Kontos verringert. Fortfahren?
@ -863,8 +897,10 @@ remove_account_link=Verknüpften Account entfernen
remove_account_link_desc=Wenn du den verknüpften Account entfernst, wirst du darüber nicht mehr auf deinen Gitea-Account zugreifen können. Fortfahren? remove_account_link_desc=Wenn du den verknüpften Account entfernst, wirst du darüber nicht mehr auf deinen Gitea-Account zugreifen können. Fortfahren?
remove_account_link_success=Der verknüpfte Account wurde entfernt. remove_account_link_success=Der verknüpfte Account wurde entfernt.
hooks.desc=Webhooks hinzufügen, die für <strong>alle Repositories</strong>, die dir gehören, ausgelöst werden.
orgs_none=Du bist kein Mitglied in einer Organisation. orgs_none=Du bist kein Mitglied in einer Organisation.
repos_none=Du besitzt keine Repositories.
delete_account=Konto löschen delete_account=Konto löschen
delete_prompt=Wenn du fortfährst, wird dein Account permanent gelöscht. Dies <strong>KANN NICHT</strong> rückgängig gemacht werden. delete_prompt=Wenn du fortfährst, wird dein Account permanent gelöscht. Dies <strong>KANN NICHT</strong> rückgängig gemacht werden.
@ -883,9 +919,12 @@ visibility=Nutzer Sichtbarkeit
visibility.public=Öffentlich visibility.public=Öffentlich
visibility.public_tooltip=Für alle sichtbar visibility.public_tooltip=Für alle sichtbar
visibility.limited=Begrenzt visibility.limited=Begrenzt
visibility.limited_tooltip=Nur für authentifizierte Benutzer sichtbar
visibility.private=Privat visibility.private=Privat
visibility.private_tooltip=Sichtbar nur für Mitglieder von Organisationen, denen du beigetreten bist
[repo] [repo]
new_repo_helper=Ein Repository enthält alle Projektdateien, einschließlich des Änderungsverlaufs. Schon woanders vorhanden? <a href="%s">Migriere das Repository.</a>
owner=Besitzer owner=Besitzer
owner_helper=Einige Organisationen könnten in der Dropdown-Liste nicht angezeigt werden, da die Anzahl an Repositories begrenzt ist. owner_helper=Einige Organisationen könnten in der Dropdown-Liste nicht angezeigt werden, da die Anzahl an Repositories begrenzt ist.
repo_name=Repository-Name repo_name=Repository-Name
@ -897,6 +936,7 @@ template_helper=Repository zu einem Template machen
template_description=Template-Repositories erlauben es Benutzern, neue Repositories mit den gleichen Verzeichnisstrukturen, Dateien und optionalen Einstellungen zu erstellen. template_description=Template-Repositories erlauben es Benutzern, neue Repositories mit den gleichen Verzeichnisstrukturen, Dateien und optionalen Einstellungen zu erstellen.
visibility=Sichtbarkeit visibility=Sichtbarkeit
visibility_description=Nur der Besitzer oder Organisationsmitglieder mit entsprechender Berechtigung, werden in der Lage sein, es zu sehen. visibility_description=Nur der Besitzer oder Organisationsmitglieder mit entsprechender Berechtigung, werden in der Lage sein, es zu sehen.
visibility_helper=In privates Repository umwandeln
visibility_helper_forced=Auf dieser Gitea-Instanz können nur private Repositories angelegt werden. visibility_helper_forced=Auf dieser Gitea-Instanz können nur private Repositories angelegt werden.
visibility_fork_helper=(Eine Änderung dieses Wertes wirkt sich auf alle Forks aus) visibility_fork_helper=(Eine Änderung dieses Wertes wirkt sich auf alle Forks aus)
clone_helper=Benötigst du Hilfe beim Klonen? Öffne die <a target="_blank" rel="noopener noreferrer" href="%s">Hilfe</a>. clone_helper=Benötigst du Hilfe beim Klonen? Öffne die <a target="_blank" rel="noopener noreferrer" href="%s">Hilfe</a>.
@ -905,6 +945,9 @@ fork_from=Fork von
already_forked=Du hast bereits einen Fork von %s erstellt already_forked=Du hast bereits einen Fork von %s erstellt
fork_to_different_account=Fork in ein anderes Konto erstellen fork_to_different_account=Fork in ein anderes Konto erstellen
fork_visibility_helper=Die Sichtbarkeit eines geforkten Repositories kann nicht geändert werden. fork_visibility_helper=Die Sichtbarkeit eines geforkten Repositories kann nicht geändert werden.
fork_branch=Branch, der zum Fork geklont werden soll
all_branches=Alle Branches
fork_no_valid_owners=Dieses Repository kann nicht geforkt werden, da keine gültigen Besitzer vorhanden sind.
use_template=Dieses Template verwenden use_template=Dieses Template verwenden
clone_in_vsc=In VS Code klonen clone_in_vsc=In VS Code klonen
download_zip=ZIP herunterladen download_zip=ZIP herunterladen
@ -933,6 +976,7 @@ trust_model_helper_collaborator_committer=Mitarbeiter+Committer: Vertraue Signat
trust_model_helper_default=Standard: Verwende das Standardvertrauensmodell für diese Installation trust_model_helper_default=Standard: Verwende das Standardvertrauensmodell für diese Installation
create_repo=Repository erstellen create_repo=Repository erstellen
default_branch=Standardbranch default_branch=Standardbranch
default_branch_label=Standard
default_branch_helper=Der default Branch ist der Basisbranch für Pull-Requests und Commits. default_branch_helper=Der default Branch ist der Basisbranch für Pull-Requests und Commits.
mirror_prune=Entfernen mirror_prune=Entfernen
mirror_prune_desc=Entferne veraltete remote-tracking Referenzen mirror_prune_desc=Entferne veraltete remote-tracking Referenzen
@ -941,6 +985,8 @@ mirror_interval_invalid=Das Spiegel-Intervall ist ungültig.
mirror_sync_on_commit=Synchronisieren, wenn Commits gepusht wurden mirror_sync_on_commit=Synchronisieren, wenn Commits gepusht wurden
mirror_address=Klonen via URL mirror_address=Klonen via URL
mirror_address_desc=Gib alle erforderlichen Anmeldedaten im Abschnitt "Authentifizierung" ein. mirror_address_desc=Gib alle erforderlichen Anmeldedaten im Abschnitt "Authentifizierung" ein.
mirror_address_url_invalid=Die angegebene URL ist ungültig. Achte darauf, alle URL-Komponenten korrekt zu maskieren.
mirror_address_protocol_invalid=Die angegebene URL ist ungültig. Nur URLs beginnend mit http(s):// oder git:// sind möglich.
mirror_lfs=Großdatei-Speicher (LFS) mirror_lfs=Großdatei-Speicher (LFS)
mirror_lfs_desc=Mirroring von LFS-Dateien aktivieren. mirror_lfs_desc=Mirroring von LFS-Dateien aktivieren.
mirror_lfs_endpoint=LFS-Endpunkt mirror_lfs_endpoint=LFS-Endpunkt
@ -966,13 +1012,20 @@ delete_preexisting=Vorhandene Dateien löschen
delete_preexisting_content=Dateien in %s löschen delete_preexisting_content=Dateien in %s löschen
delete_preexisting_success=Nicht übernommene Dateien in %s gelöscht delete_preexisting_success=Nicht übernommene Dateien in %s gelöscht
blame_prior=Blame vor dieser Änderung anzeigen blame_prior=Blame vor dieser Änderung anzeigen
blame.ignore_revs=Revisionen in <a href="%s">.git-blame-ignore-revs</a> werden ignoriert. Klicke <a href="%s">hier, um das zu umgehen</a> und die normale Blame-Ansicht zu sehen.
blame.ignore_revs.failed=Fehler beim Ignorieren der Revisionen in <a href="%s">.git-blame-ignore-revs</a>.
author_search_tooltip=Zeigt maximal 30 Benutzer author_search_tooltip=Zeigt maximal 30 Benutzer
tree_path_not_found_commit=Pfad %[1]s existiert nicht in Commit%[2]s
tree_path_not_found_branch=Pfad %[1]s existiert nicht in Branch %[2]s
tree_path_not_found_tag=Pfad %[1]s existiert nicht in Tag %[2]s
transfer.accept=Übertragung Akzeptieren transfer.accept=Übertragung Akzeptieren
transfer.accept_desc=`Übertragung nach "%s"` transfer.accept_desc=`Übertragung nach "%s"`
transfer.reject=Übertragung Ablehnen transfer.reject=Übertragung Ablehnen
transfer.reject_desc=Übertragung nach "%s " abbrechen transfer.reject_desc=Übertragung nach "%s " abbrechen
transfer.no_permission_to_accept=Du hast keine Berechtigung, diesen Transfer anzunehmen.
transfer.no_permission_to_reject=Du hast keine Berechtigung, diesen Transfer abzulehnen.
desc.private=Privat desc.private=Privat
desc.public=Öffentlich desc.public=Öffentlich
@ -993,6 +1046,8 @@ template.issue_labels=Issue Label
template.one_item=Es muss mindestens ein Template ausgewählt werden template.one_item=Es muss mindestens ein Template ausgewählt werden
template.invalid=Es muss ein Template-Repository ausgewählt werden template.invalid=Es muss ein Template-Repository ausgewählt werden
archive.title=Dieses Repository ist archiviert. Du kannst Dateien ansehen und es klonen, kannst aber nicht pushen oder Issues/Pull-Requests öffnen.
archive.title_date=Dieses Repository wurde am %s archiviert. Du kannst Dateien ansehen und es klonen, aber nicht pushen oder Issues/Pull-Requests öffnen.
archive.issue.nocomment=Dieses Repo ist archiviert. Du kannst Issues nicht kommentieren. archive.issue.nocomment=Dieses Repo ist archiviert. Du kannst Issues nicht kommentieren.
archive.pull.nocomment=Dieses Repo ist archiviert. Du kannst Pull-Requests nicht kommentieren. archive.pull.nocomment=Dieses Repo ist archiviert. Du kannst Pull-Requests nicht kommentieren.
@ -1009,6 +1064,7 @@ migrate_options_lfs=LFS-Dateien migrieren
migrate_options_lfs_endpoint.label=LFS-Endpunkt migrate_options_lfs_endpoint.label=LFS-Endpunkt
migrate_options_lfs_endpoint.description=Migration wird versuchen, über den entfernten Git-Server <a target="_blank" rel="noopener noreferrer" href="%s">den LFS-Server zu bestimmen</a>. Du kannst auch einen eigenen Endpunkt angeben, wenn die LFS-Dateien woanders gespeichert werden. migrate_options_lfs_endpoint.description=Migration wird versuchen, über den entfernten Git-Server <a target="_blank" rel="noopener noreferrer" href="%s">den LFS-Server zu bestimmen</a>. Du kannst auch einen eigenen Endpunkt angeben, wenn die LFS-Dateien woanders gespeichert werden.
migrate_options_lfs_endpoint.description.local=Ein lokaler Serverpfad wird ebenfalls unterstützt. migrate_options_lfs_endpoint.description.local=Ein lokaler Serverpfad wird ebenfalls unterstützt.
migrate_options_lfs_endpoint.placeholder=Wenn leer gelassen, wird der Endpunkt von der Clone-URL abgeleitet
migrate_items=Migrationselemente migrate_items=Migrationselemente
migrate_items_wiki=Wiki migrate_items_wiki=Wiki
migrate_items_milestones=Meilensteine migrate_items_milestones=Meilensteine
@ -1111,6 +1167,10 @@ file_view_rendered=Ansicht rendern
file_view_raw=Originalformat anzeigen file_view_raw=Originalformat anzeigen
file_permalink=Permalink file_permalink=Permalink
file_too_large=Die Datei ist zu groß zum Anzeigen. file_too_large=Die Datei ist zu groß zum Anzeigen.
invisible_runes_header=`Diese Datei enthält unsichtbare Unicode-Zeichen`
invisible_runes_description=`Diese Datei enthält unsichtbare Unicode-Zeichen, die für Menschen nicht unterscheidbar sind, aber von einem Computer unterschiedlich verarbeitet werden können. Wenn du glaubst, dass das absichtlich so ist, kannst du diese Warnung ignorieren. Benutze den „Escape“-Button, um versteckte Zeichen anzuzeigen.`
ambiguous_runes_header=`Diese Datei enthält mehrdeutige Unicode-Zeichen`
ambiguous_runes_description=`Diese Datei enthält Unicode-Zeichen, die mit anderen Zeichen verwechselt werden können. Wenn du glaubst, dass das absichtlich so ist, kannst du diese Warnung ignorieren. Benutze den „Escape“-Button, um versteckte Zeichen anzuzeigen.`
invisible_runes_line=`Diese Zeile enthält unsichtbare Unicode-Zeichen` invisible_runes_line=`Diese Zeile enthält unsichtbare Unicode-Zeichen`
ambiguous_runes_line=`Diese Zeile enthält mehrdeutige Unicode-Zeichen` ambiguous_runes_line=`Diese Zeile enthält mehrdeutige Unicode-Zeichen`
ambiguous_character=`%[1]c [U+%04[1]X] kann mit %[2]c [U+%04[2]X] verwechselt werden` ambiguous_character=`%[1]c [U+%04[1]X] kann mit %[2]c [U+%04[2]X] verwechselt werden`
@ -1123,11 +1183,15 @@ video_not_supported_in_browser=Dein Browser unterstützt das HTML5 'video'-Tag n
audio_not_supported_in_browser=Dein Browser unterstützt den HTML5 'audio'-Tag nicht. audio_not_supported_in_browser=Dein Browser unterstützt den HTML5 'audio'-Tag nicht.
stored_lfs=Gespeichert mit Git LFS stored_lfs=Gespeichert mit Git LFS
symbolic_link=Softlink symbolic_link=Softlink
executable_file=Ausführbare Datei
commit_graph=Commit graph commit_graph=Commit graph
commit_graph.select=Branches auswählen commit_graph.select=Branches auswählen
commit_graph.hide_pr_refs=Pull-Requests ausblenden commit_graph.hide_pr_refs=Pull-Requests ausblenden
commit_graph.monochrome=Monochrom commit_graph.monochrome=Monochrom
commit_graph.color=Farbe commit_graph.color=Farbe
commit.contained_in=Dieser Commit ist enthalten in:
commit.contained_in_default_branch=Dieser Commit ist im Standard-Branch enthalten
commit.load_referencing_branches_and_tags=Lade Branches und Tags, die diesen Commit referenzieren
blame=Blame blame=Blame
download_file=Datei herunterladen download_file=Datei herunterladen
normal_view=Normale Ansicht normal_view=Normale Ansicht
@ -1220,6 +1284,7 @@ commits.signed_by_untrusted_user=Signiert von nicht vertrauenswürdigen Benutzer
commits.signed_by_untrusted_user_unmatched=Signiert von nicht vertrauenswürdigen Benutzern, der nicht mit dem Committer übereinstimmt commits.signed_by_untrusted_user_unmatched=Signiert von nicht vertrauenswürdigen Benutzern, der nicht mit dem Committer übereinstimmt
commits.gpg_key_id=GPG-Schlüssel-ID commits.gpg_key_id=GPG-Schlüssel-ID
commits.ssh_key_fingerprint=SSH-Key-Fingerabdruck commits.ssh_key_fingerprint=SSH-Key-Fingerabdruck
commits.view_path=An diesem Punkt im Verlauf anzeigen
commit.operations=Operationen commit.operations=Operationen
commit.revert=Zurücksetzen commit.revert=Zurücksetzen
@ -1381,6 +1446,7 @@ issues.filter_sort.moststars=Meiste Favoriten
issues.filter_sort.feweststars=Wenigste Favoriten issues.filter_sort.feweststars=Wenigste Favoriten
issues.filter_sort.mostforks=Meiste Forks issues.filter_sort.mostforks=Meiste Forks
issues.filter_sort.fewestforks=Wenigste Forks issues.filter_sort.fewestforks=Wenigste Forks
issues.keyword_search_unavailable=Zurzeit ist die Stichwort-Suche nicht verfügbar. Bitte wende dich an den Website-Administrator.
issues.action_open=Öffnen issues.action_open=Öffnen
issues.action_close=Schließen issues.action_close=Schließen
issues.action_label=Label issues.action_label=Label
@ -1429,8 +1495,17 @@ issues.ref_closed_from=`<a href="%[3]s">hat dieses Issue %[4]s geschlossen</a> <
issues.ref_reopened_from=`<a href="%[3]s">hat dieses Issue %[4]s</a> <a id="%[1]s" href="#%[1]s">%[2]s</a> wieder geöffnet` issues.ref_reopened_from=`<a href="%[3]s">hat dieses Issue %[4]s</a> <a id="%[1]s" href="#%[1]s">%[2]s</a> wieder geöffnet`
issues.ref_from=`von %[1]s` issues.ref_from=`von %[1]s`
issues.author=Autor issues.author=Autor
issues.author_helper=Dieser Benutzer ist der Autor.
issues.role.owner=Besitzer issues.role.owner=Besitzer
issues.role.owner_helper=Dieser Benutzer ist der Besitzer dieses Repositorys.
issues.role.member=Mitglied issues.role.member=Mitglied
issues.role.member_helper=Dieser Benutzer ist Mitglied der Organisation, die dieses Repository besitzt.
issues.role.collaborator=Mitarbeiter
issues.role.collaborator_helper=Dieser Benutzer wurde zur Zusammenarbeit am Repository eingeladen.
issues.role.first_time_contributor=Erstmaliger Mitwirkender
issues.role.first_time_contributor_helper=Dies ist der erste Beitrag dieses Benutzers zum Repository.
issues.role.contributor=Mitwirkender
issues.role.contributor_helper=Dieser Benutzer hat schon zuvor zu dem Repository beigetragen.
issues.re_request_review=Review erneut anfordern issues.re_request_review=Review erneut anfordern
issues.is_stale=Seit diesem Review gab es Änderungen an diesem PR issues.is_stale=Seit diesem Review gab es Änderungen an diesem PR
issues.remove_request_review=Review-Anfrage entfernen issues.remove_request_review=Review-Anfrage entfernen
@ -1445,6 +1520,9 @@ issues.label_title=Labelname
issues.label_description=Labelbeschreibung issues.label_description=Labelbeschreibung
issues.label_color=Labelfarbe issues.label_color=Labelfarbe
issues.label_exclusive=Exklusiv issues.label_exclusive=Exklusiv
issues.label_archive=Label archivieren
issues.label_archived_filter=Archivierte Labels anzeigen
issues.label_archive_tooltip=Archivierte Labels werden bei der Suche nach Label standardmäßig von den Vorschlägen ausgeschlossen.
issues.label_exclusive_desc=Nenne das Label <code>Bereich/Element</code> um es gegenseitig ausschließend mit anderen <code>Bereich/</code> Labels zu machen. issues.label_exclusive_desc=Nenne das Label <code>Bereich/Element</code> um es gegenseitig ausschließend mit anderen <code>Bereich/</code> Labels zu machen.
issues.label_exclusive_warning=Alle im Konflikt stehenden Labels werden beim Bearbeiten der Labels eines Issues oder eines Pull-Requests entfernt. issues.label_exclusive_warning=Alle im Konflikt stehenden Labels werden beim Bearbeiten der Labels eines Issues oder eines Pull-Requests entfernt.
issues.label_count=%d Label issues.label_count=%d Label
@ -1499,6 +1577,7 @@ issues.tracking_already_started=`Du hast die Zeiterfassung bereits in <a href="%
issues.stop_tracking=Zeiterfassung stoppen issues.stop_tracking=Zeiterfassung stoppen
issues.stop_tracking_history=hat die Zeiterfassung %s angehalten issues.stop_tracking_history=hat die Zeiterfassung %s angehalten
issues.cancel_tracking=Verwerfen issues.cancel_tracking=Verwerfen
issues.cancel_tracking_history=`hat die Zeiterfassung %s abgebrochen`
issues.add_time=Zeit manuell hinzufügen issues.add_time=Zeit manuell hinzufügen
issues.del_time=Diese Zeiterfassung löschen issues.del_time=Diese Zeiterfassung löschen
issues.add_time_short=Zeit hinzufügen issues.add_time_short=Zeit hinzufügen
@ -1522,6 +1601,7 @@ issues.due_date_form=JJJJ-MM-TT
issues.due_date_form_add=Fälligkeitsdatum hinzufügen issues.due_date_form_add=Fälligkeitsdatum hinzufügen
issues.due_date_form_edit=Bearbeiten issues.due_date_form_edit=Bearbeiten
issues.due_date_form_remove=Entfernen issues.due_date_form_remove=Entfernen
issues.due_date_not_writer=Du musst Schreibrechte für dieses Repository haben, um das Fälligkeitsdatum zu ändern.
issues.due_date_not_set=Kein Fälligkeitsdatum gesetzt. issues.due_date_not_set=Kein Fälligkeitsdatum gesetzt.
issues.due_date_added=hat %[2]s das Fälligkeitsdatum %[1]s hinzugefügt issues.due_date_added=hat %[2]s das Fälligkeitsdatum %[1]s hinzugefügt
issues.due_date_modified=ändert das Abgabedatum von %[2]s auf %[1]s %[3]s s issues.due_date_modified=ändert das Abgabedatum von %[2]s auf %[1]s %[3]s s
@ -1577,6 +1657,7 @@ issues.review.pending.tooltip=Dieser Kommentar ist derzeit nicht für andere Ben
issues.review.review=Review issues.review.review=Review
issues.review.reviewers=Reviewer issues.review.reviewers=Reviewer
issues.review.outdated=Veraltet issues.review.outdated=Veraltet
issues.review.outdated_description=Der Inhalt hat sich geändert, seit dieser Kommentar abgegeben wurde
issues.review.option.show_outdated_comments=Veraltete Kommentare anzeigen issues.review.option.show_outdated_comments=Veraltete Kommentare anzeigen
issues.review.option.hide_outdated_comments=Veraltete Kommentare ausblenden issues.review.option.hide_outdated_comments=Veraltete Kommentare ausblenden
issues.review.show_outdated=Veraltete anzeigen issues.review.show_outdated=Veraltete anzeigen
@ -1618,6 +1699,13 @@ pulls.switch_comparison_type=Vergleichstyp wechseln
pulls.switch_head_and_base=Head und Base vertauschen pulls.switch_head_and_base=Head und Base vertauschen
pulls.filter_branch=Branch filtern pulls.filter_branch=Branch filtern
pulls.no_results=Keine Ergebnisse verfügbar. pulls.no_results=Keine Ergebnisse verfügbar.
pulls.show_all_commits=Alle Commits anzeigen
pulls.show_changes_since_your_last_review=Zeige Änderungen seit deinem letzten Review
pulls.showing_only_single_commit=Nur Änderungen aus Commit %[1]s werden angezeigt
pulls.showing_specified_commit_range=Zeige nur die Änderungen zwischen %[1]s..%[2]s
pulls.select_commit_hold_shift_for_range=Commit auswählen. Halte Shift + klicke, um eine Reihe auszuwählen
pulls.review_only_possible_for_full_diff=Ein Review ist nur möglich, wenn das vollständige Diff angezeigt wird
pulls.filter_changes_by_commit=Nach Commit filtern
pulls.nothing_to_compare=Diese Branches sind identisch. Es muss kein Pull-Request erstellt werden. pulls.nothing_to_compare=Diese Branches sind identisch. Es muss kein Pull-Request erstellt werden.
pulls.nothing_to_compare_and_allow_empty_pr=Diese Branches sind gleich. Der Pull-Request wird leer sein. pulls.nothing_to_compare_and_allow_empty_pr=Diese Branches sind gleich. Der Pull-Request wird leer sein.
pulls.has_pull_request=`Es existiert bereits ein Pull-Request zwischen diesen beiden Branches: <a href="%[1]s">%[2]s#%[3]d</a>` pulls.has_pull_request=`Es existiert bereits ein Pull-Request zwischen diesen beiden Branches: <a href="%[1]s">%[2]s#%[3]d</a>`
@ -1649,6 +1737,12 @@ pulls.is_empty=Die Änderungen an diesem Branch sind bereits auf dem Zielbranch.
pulls.required_status_check_failed=Einige erforderliche Prüfungen waren nicht erfolgreich. pulls.required_status_check_failed=Einige erforderliche Prüfungen waren nicht erfolgreich.
pulls.required_status_check_missing=Einige erforderliche Prüfungen fehlen. pulls.required_status_check_missing=Einige erforderliche Prüfungen fehlen.
pulls.required_status_check_administrator=Als Administrator kannst du diesen Pull-Request weiterhin mergen. pulls.required_status_check_administrator=Als Administrator kannst du diesen Pull-Request weiterhin mergen.
pulls.blocked_by_approvals=Dieser Pull-Request hat noch nicht genügend Zustimmungen. %d von %d Zustimmungen erteilt.
pulls.blocked_by_rejection=Dieser Pull-Request hat Änderungen, die von einem offiziellen Reviewer angefragt wurden.
pulls.blocked_by_official_review_requests=Dieser Pull Request hat offizielle Review-Anfragen.
pulls.blocked_by_outdated_branch=Dieser Pull Request ist blockiert, da er veraltet ist.
pulls.blocked_by_changed_protected_files_1=Dieser Pull Request ist blockiert, weil er eine geschützte Datei ändert:
pulls.blocked_by_changed_protected_files_n=Dieser Pull Request ist blockiert, weil er geschützte Dateien ändert:
pulls.can_auto_merge_desc=Dieser Pull-Request kann automatisch gemergt werden. pulls.can_auto_merge_desc=Dieser Pull-Request kann automatisch gemergt werden.
pulls.cannot_auto_merge_desc=Dieser Pull-Request kann nicht automatisch gemergt werden, da es Konflikte gibt. pulls.cannot_auto_merge_desc=Dieser Pull-Request kann nicht automatisch gemergt werden, da es Konflikte gibt.
pulls.cannot_auto_merge_helper=Bitte manuell mergen, um die Konflikte zu beheben. pulls.cannot_auto_merge_helper=Bitte manuell mergen, um die Konflikte zu beheben.
@ -1683,6 +1777,7 @@ pulls.rebase_conflict_summary=Fehlermeldung
pulls.unrelated_histories=Merge fehlgeschlagen: Der Head des Merges und die Basis haben keinen gemeinsamen Verlauf. Hinweis: Versuche eine andere Strategie pulls.unrelated_histories=Merge fehlgeschlagen: Der Head des Merges und die Basis haben keinen gemeinsamen Verlauf. Hinweis: Versuche eine andere Strategie
pulls.merge_out_of_date=Merge fehlgeschlagen: Während des Mergens wurde die Basis aktualisiert. Hinweis: Versuche es erneut. pulls.merge_out_of_date=Merge fehlgeschlagen: Während des Mergens wurde die Basis aktualisiert. Hinweis: Versuche es erneut.
pulls.head_out_of_date=Mergen fehlgeschlagen: Der Head wurde aktualisiert während der Merge erstellt wurde. Tipp: Versuche es erneut. pulls.head_out_of_date=Mergen fehlgeschlagen: Der Head wurde aktualisiert während der Merge erstellt wurde. Tipp: Versuche es erneut.
pulls.has_merged=Fehler: Der Pull-Request wurde gemerged, du kannst den Zielbranch nicht wieder mergen oder ändern.
pulls.push_rejected=Mergen fehlgeschlagen: Der Push wurde abgelehnt. Überprüfe die Git Hooks für dieses Repository. pulls.push_rejected=Mergen fehlgeschlagen: Der Push wurde abgelehnt. Überprüfe die Git Hooks für dieses Repository.
pulls.push_rejected_summary=Vollständige Ablehnungsmeldung pulls.push_rejected_summary=Vollständige Ablehnungsmeldung
pulls.push_rejected_no_message=Mergen fehlgeschlagen: Der Push wurde abgelehnt, aber es gab keine Fehlermeldung.<br>Überprüfe die Git Hooks für dieses Repository pulls.push_rejected_no_message=Mergen fehlgeschlagen: Der Push wurde abgelehnt, aber es gab keine Fehlermeldung.<br>Überprüfe die Git Hooks für dieses Repository
@ -1723,6 +1818,7 @@ pulls.auto_merge_canceled_schedule_comment=`hat den Automerge für diesen Pull-R
pulls.delete.title=Diesen Pull-Request löschen? pulls.delete.title=Diesen Pull-Request löschen?
pulls.delete.text=Willst du diesen Pull-Request wirklich löschen? (Dies wird den Inhalt unwiderruflich löschen. Überlege, ob du ihn nicht lieber schließen willst, um ihn zu archivieren) pulls.delete.text=Willst du diesen Pull-Request wirklich löschen? (Dies wird den Inhalt unwiderruflich löschen. Überlege, ob du ihn nicht lieber schließen willst, um ihn zu archivieren)
pulls.recently_pushed_new_branches=Du hast auf den Branch <strong>%[1]s</strong> %[2]s gepusht
pull.deleted_branch=(gelöscht):%s pull.deleted_branch=(gelöscht):%s
@ -1732,6 +1828,7 @@ milestones.update_ago=%s aktualisiert
milestones.no_due_date=Kein Fälligkeitsdatum milestones.no_due_date=Kein Fälligkeitsdatum
milestones.open=Öffnen milestones.open=Öffnen
milestones.close=Schließen milestones.close=Schließen
milestones.new_subheader=Benutze Meilensteine, um Issues zu organisieren und den Fortschritt darzustellen.
milestones.completeness=%d%% abgeschlossen milestones.completeness=%d%% abgeschlossen
milestones.create=Meilenstein erstellen milestones.create=Meilenstein erstellen
milestones.title=Titel milestones.title=Titel
@ -1748,11 +1845,26 @@ milestones.edit_success=Meilenstein "%s" wurde aktualisiert.
milestones.deletion=Meilenstein löschen milestones.deletion=Meilenstein löschen
milestones.deletion_desc=Das Löschen des Meilensteins entfernt ihn von allen Issues. Fortfahren? milestones.deletion_desc=Das Löschen des Meilensteins entfernt ihn von allen Issues. Fortfahren?
milestones.deletion_success=Der Meilenstein wurde gelöscht. milestones.deletion_success=Der Meilenstein wurde gelöscht.
milestones.filter_sort.earliest_due_data=Frühestes Fälligkeitsdatum
milestones.filter_sort.latest_due_date=Spätestes Fälligkeitsdatum
milestones.filter_sort.least_complete=Am wenigsten vollständig milestones.filter_sort.least_complete=Am wenigsten vollständig
milestones.filter_sort.most_complete=Vollständigste milestones.filter_sort.most_complete=Vollständigste
milestones.filter_sort.most_issues=Meiste Issues milestones.filter_sort.most_issues=Meiste Issues
milestones.filter_sort.least_issues=Wenigste Issues milestones.filter_sort.least_issues=Wenigste Issues
signing.will_sign=Dieser Commit wird mit dem Key "%s" signiert werden.
signing.wont_sign.error=Es gab einen Fehler bei der Prüfung, ob der Commit signiert werden kann.
signing.wont_sign.nokey=Es ist kein Schlüssel zum Signieren dieses Commits verfügbar.
signing.wont_sign.never=Commits werden nie signiert.
signing.wont_sign.always=Commits werden immer signiert.
signing.wont_sign.pubkey=Der Commit wird nicht signiert, da du keinen öffentlichen Schlüssel mit deinem Account verknüpft hast.
signing.wont_sign.twofa=Du musst Zwei-Faktor-Authentifizierung aktivieren, damit Commits signiert werden.
signing.wont_sign.parentsigned=Der Commit wird nicht signiert werden, da der vorherige Commit nicht signiert ist.
signing.wont_sign.basesigned=Der Merge Commit wird nicht signiert werden, da der Basis-Commit nicht signiert ist.
signing.wont_sign.headsigned=Der Merge Commit wird nicht signiert werden, da der Head-Commit nicht signiert ist.
signing.wont_sign.commitssigned=Der Merge Commit wird nicht signiert werden, da alle zugehörigen Commits nicht signiert sind.
signing.wont_sign.approved=Der Merge Commit wird nicht signiert werden, da der Pull Request nicht genehmigt wurde.
signing.wont_sign.not_signed_in=Du bist nicht eingeloggt.
ext_wiki=Zugriff auf externes Wiki ext_wiki=Zugriff auf externes Wiki
ext_wiki.desc=Verweis auf externes Wiki. ext_wiki.desc=Verweis auf externes Wiki.
@ -1882,7 +1994,9 @@ settings.mirror_settings.docs.disabled_push_mirror.info=Push-Mirrors wurden von
settings.mirror_settings.docs.no_new_mirrors=Dein Repository spiegelt Änderungen von oder zu einem anderen Repository. Bitte beachte, dass du gerade keine neuen Mirror anlegen kannst. settings.mirror_settings.docs.no_new_mirrors=Dein Repository spiegelt Änderungen von oder zu einem anderen Repository. Bitte beachte, dass du gerade keine neuen Mirror anlegen kannst.
settings.mirror_settings.docs.can_still_use=Obwohl du existierende Mirrors gerade nicht bearbeiten oder neu anlegen kannst, sind bestehende Mirrors weiterhin nutzbar. settings.mirror_settings.docs.can_still_use=Obwohl du existierende Mirrors gerade nicht bearbeiten oder neu anlegen kannst, sind bestehende Mirrors weiterhin nutzbar.
settings.mirror_settings.docs.pull_mirror_instructions=Um einen Pull-Mirror einzurichten, konsultiere bitte: settings.mirror_settings.docs.pull_mirror_instructions=Um einen Pull-Mirror einzurichten, konsultiere bitte:
settings.mirror_settings.docs.more_information_if_disabled=Hier kannst du mehr über Push- und Pull-Mirrors erfahren:
settings.mirror_settings.docs.doc_link_title=Wie spiegele ich Repositories? settings.mirror_settings.docs.doc_link_title=Wie spiegele ich Repositories?
settings.mirror_settings.docs.doc_link_pull_section=den Abschnitt "Von einem entfernten Repository pullen" in der Dokumentation.
settings.mirror_settings.docs.pulling_remote_title=Aus einem Remote-Repository pullen settings.mirror_settings.docs.pulling_remote_title=Aus einem Remote-Repository pullen
settings.mirror_settings.mirrored_repository=Gespiegeltes Repository settings.mirror_settings.mirrored_repository=Gespiegeltes Repository
settings.mirror_settings.direction=Richtung settings.mirror_settings.direction=Richtung
@ -1892,8 +2006,11 @@ settings.mirror_settings.last_update=Letzte Aktualisierung
settings.mirror_settings.push_mirror.none=Keine Push-Mirrors konfiguriert settings.mirror_settings.push_mirror.none=Keine Push-Mirrors konfiguriert
settings.mirror_settings.push_mirror.remote_url=URL zum Git-Remote-Repository settings.mirror_settings.push_mirror.remote_url=URL zum Git-Remote-Repository
settings.mirror_settings.push_mirror.add=Push-Mirror hinzufügen settings.mirror_settings.push_mirror.add=Push-Mirror hinzufügen
settings.mirror_settings.push_mirror.edit_sync_time=Mirror-Sync-Intervall anpassen
settings.sync_mirror=Jetzt synchronisieren settings.sync_mirror=Jetzt synchronisieren
settings.pull_mirror_sync_in_progress=Aktuell werden Änderungen von %s gepullt.
settings.push_mirror_sync_in_progress=Aktuell werden Änderungen auf %s gepusht.
settings.site=Webseite settings.site=Webseite
settings.update_settings=Einstellungen speichern settings.update_settings=Einstellungen speichern
settings.update_mirror_settings=Mirror-Einstellungen aktualisieren settings.update_mirror_settings=Mirror-Einstellungen aktualisieren
@ -1960,6 +2077,7 @@ settings.transfer.rejected=Repository-Übertragung wurde abgelehnt.
settings.transfer.success=Repository-Übertragung war erfolgreich. settings.transfer.success=Repository-Übertragung war erfolgreich.
settings.transfer_abort=Übertragung abbrechen settings.transfer_abort=Übertragung abbrechen
settings.transfer_abort_invalid=Du kannst nur eingeleitete Repository-Übertragung abbrechen. settings.transfer_abort_invalid=Du kannst nur eingeleitete Repository-Übertragung abbrechen.
settings.transfer_abort_success=Die Repository-Übertragung zu %s wurde abgebrochen.
settings.transfer_desc=Übertrage dieses Repository auf einen anderen Benutzer oder eine Organisation, in der du Admin-Rechte hast. settings.transfer_desc=Übertrage dieses Repository auf einen anderen Benutzer oder eine Organisation, in der du Admin-Rechte hast.
settings.transfer_form_title=Gib den Repository-Namen zur Bestätigung ein: settings.transfer_form_title=Gib den Repository-Namen zur Bestätigung ein:
settings.transfer_in_progress=Es gibt derzeit eine laufende Übertragung. Bitte brich diese ab, wenn du dieses Repository an einen anderen Benutzer übertragen möchtest. settings.transfer_in_progress=Es gibt derzeit eine laufende Übertragung. Bitte brich diese ab, wenn du dieses Repository an einen anderen Benutzer übertragen möchtest.
@ -2026,12 +2144,14 @@ settings.webhook_deletion_desc=Das Entfernen eines Webhooks löscht seine Einste
settings.webhook_deletion_success=Webhook wurde entfernt. settings.webhook_deletion_success=Webhook wurde entfernt.
settings.webhook.test_delivery=Senden testen settings.webhook.test_delivery=Senden testen
settings.webhook.test_delivery_desc=Teste diesen Webhook mit einem Fake-Event. settings.webhook.test_delivery_desc=Teste diesen Webhook mit einem Fake-Event.
settings.webhook.test_delivery_desc_disabled=Um diesen Webhook mit einem Fake-Event zu testen, aktiviere ihn.
settings.webhook.request=Anfrage settings.webhook.request=Anfrage
settings.webhook.response=Antwort settings.webhook.response=Antwort
settings.webhook.headers=Kopfzeilen settings.webhook.headers=Kopfzeilen
settings.webhook.payload=Inhalt settings.webhook.payload=Inhalt
settings.webhook.body=Inhalt settings.webhook.body=Inhalt
settings.webhook.replay.description=Diesen Webhook wiederholen. settings.webhook.replay.description=Diesen Webhook wiederholen.
settings.webhook.replay.description_disabled=Um diesen Webhook wiederzugeben, aktiviere ihn.
settings.webhook.delivery.success=Ein Event wurde zur Sendungs-Warteschlange hinzugefügt. Es kann ein paar Sekunden dauern, bevor es im Verlauf erscheint. settings.webhook.delivery.success=Ein Event wurde zur Sendungs-Warteschlange hinzugefügt. Es kann ein paar Sekunden dauern, bevor es im Verlauf erscheint.
settings.githooks_desc=Git-Hooks werden von Git selbst bereitgestellt. Du kannst die Dateien der unterstützten Hooks in der Liste unten bearbeiten, um eigene Operationen einzubinden. settings.githooks_desc=Git-Hooks werden von Git selbst bereitgestellt. Du kannst die Dateien der unterstützten Hooks in der Liste unten bearbeiten, um eigene Operationen einzubinden.
settings.githook_edit_desc=Wenn ein Hook nicht aktiv ist, wird der Standardinhalt benutzt. Lasse den Inhalt leer, um den Hook zu deaktivieren. settings.githook_edit_desc=Wenn ein Hook nicht aktiv ist, wird der Standardinhalt benutzt. Lasse den Inhalt leer, um den Hook zu deaktivieren.
@ -2191,6 +2311,7 @@ settings.dismiss_stale_approvals_desc=Wenn neue Commits gepusht werden, die den
settings.require_signed_commits=Signierte Commits erforderlich settings.require_signed_commits=Signierte Commits erforderlich
settings.require_signed_commits_desc=Pushes auf diesen Branch ablehnen, wenn Commits nicht signiert oder nicht überprüfbar sind. settings.require_signed_commits_desc=Pushes auf diesen Branch ablehnen, wenn Commits nicht signiert oder nicht überprüfbar sind.
settings.protect_branch_name_pattern=Muster für geschützte Branchnamen settings.protect_branch_name_pattern=Muster für geschützte Branchnamen
settings.protect_branch_name_pattern_desc=Geschützte Branch-Namensmuster. Lies <a href="github.com/gobwas/glob">die Dokumentation</a> für die Muster-Syntax. Beispiele: main, release/**
settings.protect_patterns=Muster settings.protect_patterns=Muster
settings.protect_protected_file_patterns=Geschützte Dateimuster (durch Semikolon ';' getrennt): settings.protect_protected_file_patterns=Geschützte Dateimuster (durch Semikolon ';' getrennt):
settings.protect_protected_file_patterns_desc=Geschützte Dateien dürfen nicht direkt geändert werden, auch wenn der Benutzer Rechte hat, Dateien in diesem Branch hinzuzufügen, zu bearbeiten oder zu löschen. Mehrere Muster können mit Semikolon (';') getrennt werden. Siehe <a href='https://pkg.go.dev/github.com/gobwas/glob#Compile'>github.com/gobwas/glob</a> Dokumentation zur Mustersyntax. Beispiele: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>. settings.protect_protected_file_patterns_desc=Geschützte Dateien dürfen nicht direkt geändert werden, auch wenn der Benutzer Rechte hat, Dateien in diesem Branch hinzuzufügen, zu bearbeiten oder zu löschen. Mehrere Muster können mit Semikolon (';') getrennt werden. Siehe <a href='https://pkg.go.dev/github.com/gobwas/glob#Compile'>github.com/gobwas/glob</a> Dokumentation zur Mustersyntax. Beispiele: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>.
@ -2227,18 +2348,26 @@ settings.tags.protection.allowed.teams=Erlaubte Teams
settings.tags.protection.allowed.noone=Niemand settings.tags.protection.allowed.noone=Niemand
settings.tags.protection.create=Tag schützen settings.tags.protection.create=Tag schützen
settings.tags.protection.none=Es gibt keine geschützten Tags. settings.tags.protection.none=Es gibt keine geschützten Tags.
settings.tags.protection.pattern.description=Du kannst einen einzigen Namen oder ein globales Schema oder einen regulären Ausdruck verwenden, um mehrere Tags zu schützen. Mehr dazu im <a target="_blank" rel="noopener" href="https://docs.gitea.com/usage/protected-tags">Guide für geschützte Tags (Englisch)</a>.
settings.bot_token=Bot-Token settings.bot_token=Bot-Token
settings.chat_id=Chat-ID settings.chat_id=Chat-ID
settings.thread_id=Thread-ID
settings.matrix.homeserver_url=Homeserver-URL settings.matrix.homeserver_url=Homeserver-URL
settings.matrix.room_id=Raum-ID settings.matrix.room_id=Raum-ID
settings.matrix.message_type=Nachrichtentyp settings.matrix.message_type=Nachrichtentyp
settings.archive.button=Repo archivieren settings.archive.button=Repo archivieren
settings.archive.header=Dieses Repo archivieren settings.archive.header=Dieses Repo archivieren
settings.archive.text=Durch das Archivieren wird ein Repo vollständig schreibgeschützt. Es wird vom Dashboard versteckt. Niemand (nicht einmal du!) wird in der Lage sein, neue Commits zu erstellen oder Issues oder Pull-Requests zu öffnen.
settings.archive.success=Das Repo wurde erfolgreich archiviert. settings.archive.success=Das Repo wurde erfolgreich archiviert.
settings.archive.error=Beim Versuch, das Repository zu archivieren, ist ein Fehler aufgetreten. Weitere Details finden sich im Log. settings.archive.error=Beim Versuch, das Repository zu archivieren, ist ein Fehler aufgetreten. Weitere Details finden sich im Log.
settings.archive.error_ismirror=Du kannst keinen Repo-Mirror archivieren. settings.archive.error_ismirror=Du kannst keinen Repo-Mirror archivieren.
settings.archive.branchsettings_unavailable=Branch-Einstellungen sind nicht verfügbar wenn das Repo archiviert ist. settings.archive.branchsettings_unavailable=Branch-Einstellungen sind nicht verfügbar wenn das Repo archiviert ist.
settings.archive.tagsettings_unavailable=Tag Einstellungen sind nicht verfügbar, wenn das Repo archiviert wurde. settings.archive.tagsettings_unavailable=Tag Einstellungen sind nicht verfügbar, wenn das Repo archiviert wurde.
settings.unarchive.button=Archivieren rückgängig machen
settings.unarchive.header=Archivieren dieses Repositories rückgängig machen
settings.unarchive.text=Durch das Aufheben der Archivierung kann das Repo wieder Commits und Pushes sowie neue Issues und Pull-Requests empfangen.
settings.unarchive.success=Die Archivierung des Repos wurde erfolgreich wieder rückgängig gemacht.
settings.unarchive.error=Beim Versuch, die Archivierung des Repos aufzuheben, ist ein Fehler aufgetreten. Weitere Details finden sich im Log.
settings.update_avatar_success=Der Repository-Avatar wurde aktualisiert. settings.update_avatar_success=Der Repository-Avatar wurde aktualisiert.
settings.lfs=LFS settings.lfs=LFS
settings.lfs_filelist=LFS-Dateien, die in diesem Repository gespeichert sind settings.lfs_filelist=LFS-Dateien, die in diesem Repository gespeichert sind
@ -2305,6 +2434,7 @@ diff.show_more=Mehr anzeigen
diff.load=Diff laden diff.load=Diff laden
diff.generated=generiert diff.generated=generiert
diff.vendored=vendored diff.vendored=vendored
diff.comment.add_line_comment=Einzelnen Kommentar hinzufügen
diff.comment.placeholder=Kommentieren... diff.comment.placeholder=Kommentieren...
diff.comment.markdown_info=Styling mit Markdown wird unterstützt. diff.comment.markdown_info=Styling mit Markdown wird unterstützt.
diff.comment.add_single_comment=Einzelnen Kommentar hinzufügen diff.comment.add_single_comment=Einzelnen Kommentar hinzufügen
@ -2361,6 +2491,7 @@ release.edit_release=Release aktualisieren
release.delete_release=Release löschen release.delete_release=Release löschen
release.delete_tag=Tag löschen release.delete_tag=Tag löschen
release.deletion=Release löschen release.deletion=Release löschen
release.deletion_desc=Beim Entfernen wird ein Release nur von Gitea gelöscht. Es betrifft weder den Git-Tag, noch den Inhalt des Repos oder seinen Änderungsverlauf. Fortfahren?
release.deletion_success=Das Release wurde gelöscht. release.deletion_success=Das Release wurde gelöscht.
release.deletion_tag_desc=Löscht dieses Tag aus dem Projektarchiv. Repository-Inhalt und Verlauf bleiben unverändert. Fortfahren? release.deletion_tag_desc=Löscht dieses Tag aus dem Projektarchiv. Repository-Inhalt und Verlauf bleiben unverändert. Fortfahren?
release.deletion_tag_success=Der Tag wurde gelöscht. release.deletion_tag_success=Der Tag wurde gelöscht.
@ -2376,10 +2507,12 @@ release.releases_for=Releases für %s
release.tags_for=Tags für %s release.tags_for=Tags für %s
branch.name=Branchname branch.name=Branchname
branch.search=Branch suchen
branch.already_exists=Ein Branch mit dem Namen "%s" existiert bereits. branch.already_exists=Ein Branch mit dem Namen "%s" existiert bereits.
branch.delete_head=Löschen branch.delete_head=Löschen
branch.delete=Branch "%s" löschen branch.delete=Branch "%s" löschen
branch.delete_html=Branch löschen branch.delete_html=Branch löschen
branch.delete_desc=Das Löschen eines Branches ist permanent. Obwohl der Branch für eine kurze Zeit weiter existieren könnte, kann diese Aktion in den meisten Fällen NICHT rückgängig gemacht werden. Fortfahren?
branch.deletion_success=Branch "%s" wurde gelöscht. branch.deletion_success=Branch "%s" wurde gelöscht.
branch.deletion_failed=Branch "%s" konnte nicht gelöscht werden. branch.deletion_failed=Branch "%s" konnte nicht gelöscht werden.
branch.delete_branch_has_new_commits=Der Branch "%s" kann nicht gelöscht werden, da seit dem letzten Merge neue Commits hinzugefügt wurden. branch.delete_branch_has_new_commits=Der Branch "%s" kann nicht gelöscht werden, da seit dem letzten Merge neue Commits hinzugefügt wurden.
@ -2419,6 +2552,7 @@ tag.create_success=Tag "%s" wurde erstellt.
topic.manage_topics=Themen verwalten topic.manage_topics=Themen verwalten
topic.done=Fertig topic.done=Fertig
topic.count_prompt=Du kannst nicht mehr als 25 Themen auswählen topic.count_prompt=Du kannst nicht mehr als 25 Themen auswählen
topic.format_prompt=Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) und Punkte ('.') enthalten und bis zu 35 Zeichen lang sein. Nur Kleinbuchstaben sind zulässig.
find_file.go_to_file=Datei suchen find_file.go_to_file=Datei suchen
find_file.no_matching=Keine passende Datei gefunden find_file.no_matching=Keine passende Datei gefunden
@ -2457,6 +2591,7 @@ form.create_org_not_allowed=Du bist nicht berechtigt, eine Organisation zu erste
settings=Einstellungen settings=Einstellungen
settings.options=Organisation settings.options=Organisation
settings.full_name=Vollständiger Name settings.full_name=Vollständiger Name
settings.email=Kontakt-E-Mail-Adresse
settings.website=Webseite settings.website=Webseite
settings.location=Standort settings.location=Standort
settings.permission=Berechtigungen settings.permission=Berechtigungen
@ -2470,6 +2605,7 @@ settings.visibility.private_shortname=Privat
settings.update_settings=Einstellungen speichern settings.update_settings=Einstellungen speichern
settings.update_setting_success=Organisationseinstellungen wurden aktualisiert. settings.update_setting_success=Organisationseinstellungen wurden aktualisiert.
settings.change_orgname_prompt=Hinweis: Das Ändern des Organisationsnamens wird auch die URL deiner Organisation ändern und den alten Namen freigeben.
settings.change_orgname_redirect_prompt=Der alte Name wird weiterleiten, bis er wieder beansprucht wird. settings.change_orgname_redirect_prompt=Der alte Name wird weiterleiten, bis er wieder beansprucht wird.
settings.update_avatar_success=Der Organisationsavatar wurde aktualisiert. settings.update_avatar_success=Der Organisationsavatar wurde aktualisiert.
settings.delete=Organisation löschen settings.delete=Organisation löschen
@ -2545,15 +2681,19 @@ teams.all_repositories_helper=Team hat Zugriff auf alle Repositories. Wenn dies
teams.all_repositories_read_permission_desc=Dieses Team gewährt <strong>Lese</strong>-Zugriff auf <strong>Repositories</strong>: Mitglieder können Repositories ansehen und klonen. teams.all_repositories_read_permission_desc=Dieses Team gewährt <strong>Lese</strong>-Zugriff auf <strong>Repositories</strong>: Mitglieder können Repositories ansehen und klonen.
teams.all_repositories_write_permission_desc=Dieses Team gewährt <strong>Schreib</strong>-Zugriff auf <strong>alle Repositories</strong>: Mitglieder können Repositories lesen und auf sie pushen. teams.all_repositories_write_permission_desc=Dieses Team gewährt <strong>Schreib</strong>-Zugriff auf <strong>alle Repositories</strong>: Mitglieder können Repositories lesen und auf sie pushen.
teams.all_repositories_admin_permission_desc=Dieses Team gewährt <strong>Administrator</strong>-Zugriff auf <strong>alle Repositories</strong>: Mitglieder können Repositories lesen, auf sie pushen und Mitwirkende zu Repositorys hinzufügen. teams.all_repositories_admin_permission_desc=Dieses Team gewährt <strong>Administrator</strong>-Zugriff auf <strong>alle Repositories</strong>: Mitglieder können Repositories lesen, auf sie pushen und Mitwirkende zu Repositorys hinzufügen.
teams.invite.title=Du wurdest eingeladen, dem Team <strong>%s</strong> in der Organisation <strong>%s</strong> beizutreten.
teams.invite.by=Von %s eingeladen teams.invite.by=Von %s eingeladen
teams.invite.description=Bitte klicke auf die folgende Schaltfläche, um dem Team beizutreten. teams.invite.description=Bitte klicke auf die folgende Schaltfläche, um dem Team beizutreten.
[admin] [admin]
dashboard=Dashboard dashboard=Dashboard
identity_access=Identität & Zugriff
users=Benutzerkonten users=Benutzerkonten
organizations=Organisationen organizations=Organisationen
assets=Code-Assets
repositories=Repositories repositories=Repositories
hooks=Webhooks hooks=Webhooks
integrations=Integrationen
authentication=Authentifizierungsquellen authentication=Authentifizierungsquellen
emails=Benutzer E-Mails emails=Benutzer E-Mails
config=Konfiguration config=Konfiguration
@ -2562,6 +2702,7 @@ monitor=Monitoring
first_page=Erste first_page=Erste
last_page=Letzte last_page=Letzte
total=Gesamt: %d total=Gesamt: %d
settings=Administratoreinstellungen
dashboard.new_version_hint=Gitea %s ist jetzt verfügbar, deine derzeitige Version ist %s. Weitere Details findest du im <a target="_blank" rel="noreferrer" href="https://blog.gitea.io">Blog</a>. dashboard.new_version_hint=Gitea %s ist jetzt verfügbar, deine derzeitige Version ist %s. Weitere Details findest du im <a target="_blank" rel="noreferrer" href="https://blog.gitea.io">Blog</a>.
dashboard.statistic=Übersicht dashboard.statistic=Übersicht
@ -2574,11 +2715,13 @@ dashboard.clean_unbind_oauth=Nicht verbundene OAuth-Verbindungen löschen
dashboard.clean_unbind_oauth_success=Alle unverbundene OAuth-Verbindungen wurden gelöscht. dashboard.clean_unbind_oauth_success=Alle unverbundene OAuth-Verbindungen wurden gelöscht.
dashboard.task.started=Aufgabe gestartet: %[1]s dashboard.task.started=Aufgabe gestartet: %[1]s
dashboard.task.process=Aufgabe: %[1]s dashboard.task.process=Aufgabe: %[1]s
dashboard.task.cancelled=Aufgabe: %[1]s abgebrochen: %[3]s
dashboard.task.error=Fehler in Aufgabe: %[1]s: %[3]s dashboard.task.error=Fehler in Aufgabe: %[1]s: %[3]s
dashboard.task.finished=Aufgabe: %[1]s, gestartet von %[2]s, wurde beendet dashboard.task.finished=Aufgabe: %[1]s, gestartet von %[2]s, wurde beendet
dashboard.task.unknown=Unbekannte Aufgabe: %[1]s dashboard.task.unknown=Unbekannte Aufgabe: %[1]s
dashboard.cron.started=Cron gestartet: %[1]s dashboard.cron.started=Cron gestartet: %[1]s
dashboard.cron.process=Cron: %[1]s dashboard.cron.process=Cron: %[1]s
dashboard.cron.cancelled=Cron: %[1]s abgebrochen: %[3]s
dashboard.cron.error=Fehler in Cron: %s: %[3]s dashboard.cron.error=Fehler in Cron: %s: %[3]s
dashboard.cron.finished=Cron: %[1]s ist beendet dashboard.cron.finished=Cron: %[1]s ist beendet
dashboard.delete_inactive_accounts=Alle nicht aktivierten Konten löschen dashboard.delete_inactive_accounts=Alle nicht aktivierten Konten löschen
@ -2588,6 +2731,7 @@ dashboard.delete_repo_archives.started=Löschen aller Repository-Archive gestart
dashboard.delete_missing_repos=Alle Repository-Datensätze mit verloren gegangenen Git-Dateien löschen dashboard.delete_missing_repos=Alle Repository-Datensätze mit verloren gegangenen Git-Dateien löschen
dashboard.delete_missing_repos.started=Alle Repositories löschen, die den Git-File-Task nicht gestartet haben. dashboard.delete_missing_repos.started=Alle Repositories löschen, die den Git-File-Task nicht gestartet haben.
dashboard.delete_generated_repository_avatars=Generierte Repository-Avatare löschen dashboard.delete_generated_repository_avatars=Generierte Repository-Avatare löschen
dashboard.sync_repo_branches=Fehlende Branches aus den Git-Daten in die Datenbank synchronisieren
dashboard.update_mirrors=Mirrors aktualisieren dashboard.update_mirrors=Mirrors aktualisieren
dashboard.repo_health_check=Healthchecks für alle Repositories ausführen dashboard.repo_health_check=Healthchecks für alle Repositories ausführen
dashboard.check_repo_stats=Überprüfe alle Repository-Statistiken dashboard.check_repo_stats=Überprüfe alle Repository-Statistiken
@ -2604,6 +2748,7 @@ dashboard.reinit_missing_repos=Alle Git-Repositories neu einlesen, für die Eint
dashboard.sync_external_users=Externe Benutzerdaten synchronisieren dashboard.sync_external_users=Externe Benutzerdaten synchronisieren
dashboard.cleanup_hook_task_table=Hook-Task-Tabelle bereinigen dashboard.cleanup_hook_task_table=Hook-Task-Tabelle bereinigen
dashboard.cleanup_packages=Veraltete Pakete löschen dashboard.cleanup_packages=Veraltete Pakete löschen
dashboard.cleanup_actions=Abgelaufene Logs und Artefakte von Actions bereinigen
dashboard.server_uptime=Server-Uptime dashboard.server_uptime=Server-Uptime
dashboard.current_goroutine=Aktuelle Goroutinen dashboard.current_goroutine=Aktuelle Goroutinen
dashboard.current_memory_usage=Aktuelle Speichernutzung dashboard.current_memory_usage=Aktuelle Speichernutzung
@ -2641,6 +2786,9 @@ dashboard.gc_lfs=Garbage-Collection für LFS Meta-Objekte ausführen
dashboard.stop_zombie_tasks=Zombie-Aufgaben stoppen dashboard.stop_zombie_tasks=Zombie-Aufgaben stoppen
dashboard.stop_endless_tasks=Endlose Aufgaben stoppen dashboard.stop_endless_tasks=Endlose Aufgaben stoppen
dashboard.cancel_abandoned_jobs=Aufgegebene Jobs abbrechen dashboard.cancel_abandoned_jobs=Aufgegebene Jobs abbrechen
dashboard.start_schedule_tasks=Terminierte Aufgaben starten
dashboard.sync_branch.started=Synchronisierung der Branches gestartet
dashboard.rebuild_issue_indexer=Issue-Indexer neu bauen
users.user_manage_panel=Benutzerkontenverwaltung users.user_manage_panel=Benutzerkontenverwaltung
users.new_account=Benutzerkonto erstellen users.new_account=Benutzerkonto erstellen
@ -2649,6 +2797,9 @@ users.full_name=Vollständiger Name
users.activated=Aktiviert users.activated=Aktiviert
users.admin=Administrator users.admin=Administrator
users.restricted=Eingeschränkt users.restricted=Eingeschränkt
users.reserved=Reserviert
users.bot=Bot
users.remote=Remote
users.2fa=2FA users.2fa=2FA
users.repos=Repos users.repos=Repos
users.created=Registriert am users.created=Registriert am
@ -2695,6 +2846,7 @@ users.list_status_filter.is_prohibit_login=Login verbieten
users.list_status_filter.not_prohibit_login=Login erlaubt users.list_status_filter.not_prohibit_login=Login erlaubt
users.list_status_filter.is_2fa_enabled=2FA aktiviert users.list_status_filter.is_2fa_enabled=2FA aktiviert
users.list_status_filter.not_2fa_enabled=2FA deaktiviert users.list_status_filter.not_2fa_enabled=2FA deaktiviert
users.details=Benutzerdetails
emails.email_manage_panel=Benutzer-E-Mail-Verwaltung emails.email_manage_panel=Benutzer-E-Mail-Verwaltung
emails.primary=Primär emails.primary=Primär
@ -2726,10 +2878,12 @@ repos.stars=Favoriten
repos.forks=Forks repos.forks=Forks
repos.issues=Issues repos.issues=Issues
repos.size=Größe repos.size=Größe
repos.lfs_size=LFS-Größe
packages.package_manage_panel=Paketverwaltung packages.package_manage_panel=Paketverwaltung
packages.total_size=Gesamtgröße: %s packages.total_size=Gesamtgröße: %s
packages.unreferenced_size=Nicht referenzierte Größe: %s packages.unreferenced_size=Nicht referenzierte Größe: %s
packages.cleanup=Veraltete Daten löschen
packages.owner=Besitzer packages.owner=Besitzer
packages.creator=Ersteller packages.creator=Ersteller
packages.name=Name packages.name=Name
@ -2740,10 +2894,12 @@ packages.size=Größe
packages.published=Veröffentlicht packages.published=Veröffentlicht
defaulthooks=Standard-Webhooks defaulthooks=Standard-Webhooks
defaulthooks.desc=Webhooks senden automatisch eine HTTP-POST-Anfrage an einen Server, wenn bestimmte Gitea-Events ausgelöst werden. Hier definierte Webhooks sind die Standardwerte, die in alle neuen Repositories kopiert werden. Mehr Infos findest du in der <a target="_blank" rel="noopener" href="https://docs.gitea.com/usage/webhooks">Webhooks-Anleitung</a> (auf Englisch).
defaulthooks.add_webhook=Standard-Webhook hinzufügen defaulthooks.add_webhook=Standard-Webhook hinzufügen
defaulthooks.update_webhook=Standard-Webhook aktualisieren defaulthooks.update_webhook=Standard-Webhook aktualisieren
systemhooks=System-Webhooks systemhooks=System-Webhooks
systemhooks.desc=Webhooks senden automatisch HTTP-POST-Anfragen an einen Server, wenn bestimmte Gitea-Events ausgelöst werden. Hier definierte Webhooks werden auf alle Repositories des Systems übertragen, beachte daher mögliche Performance-Einbrüche. Mehr Infos findest du in der <a target="_blank" rel="noopener" href="https://docs.gitea.com/usage/webhooks">Webhooks-Anleitung</a> (auf Englisch).
systemhooks.add_webhook=System-Webhook hinzufügen systemhooks.add_webhook=System-Webhook hinzufügen
systemhooks.update_webhook=System-Webhook aktualisieren systemhooks.update_webhook=System-Webhook aktualisieren
@ -2836,6 +2992,7 @@ auths.sspi_default_language=Standardsprache für Benutzer
auths.sspi_default_language_helper=Standardsprache für Benutzer, die automatisch mit der SSPI Authentifizierungsmethode erstellt wurden. Leer lassen, wenn du es bevorzugst, dass eine Sprache automatisch erkannt wird. auths.sspi_default_language_helper=Standardsprache für Benutzer, die automatisch mit der SSPI Authentifizierungsmethode erstellt wurden. Leer lassen, wenn du es bevorzugst, dass eine Sprache automatisch erkannt wird.
auths.tips=Tipps auths.tips=Tipps
auths.tips.oauth2.general=OAuth2-Authentifizierung auths.tips.oauth2.general=OAuth2-Authentifizierung
auths.tips.oauth2.general.tip=Beim Registrieren einer OAuth2-Anwendung sollte die Callback-URL folgendermaßen lauten:
auths.tip.oauth2_provider=OAuth2-Anbieter auths.tip.oauth2_provider=OAuth2-Anbieter
auths.tip.bitbucket=Registriere einen neuen OAuth-Consumer unter https://bitbucket.org/account/user/<dein-benutzername>/oauth-consumers/new und füge die Berechtigung „Account“ „Read“ hinzu. auths.tip.bitbucket=Registriere einen neuen OAuth-Consumer unter https://bitbucket.org/account/user/<dein-benutzername>/oauth-consumers/new und füge die Berechtigung „Account“ „Read“ hinzu.
auths.tip.nextcloud=Registriere über das "Settings -> Security -> OAuth 2.0 client"-Menü einen neuen "OAuth consumer" auf der Nextcloud-Instanz auths.tip.nextcloud=Registriere über das "Settings -> Security -> OAuth 2.0 client"-Menü einen neuen "OAuth consumer" auf der Nextcloud-Instanz
@ -2847,6 +3004,7 @@ auths.tip.google_plus=Du erhältst die OAuth2-Client-Zugangsdaten in der Google-
auths.tip.openid_connect=Benutze die OpenID-Connect-Discovery-URL (<server>/.well-known/openid-configuration), um die Endpunkte zu spezifizieren auths.tip.openid_connect=Benutze die OpenID-Connect-Discovery-URL (<server>/.well-known/openid-configuration), um die Endpunkte zu spezifizieren
auths.tip.twitter=Gehe auf https://dev.twitter.com/apps, erstelle eine Anwendung und stelle sicher, dass die Option „Allow this application to be used to Sign in with Twitter“ aktiviert ist auths.tip.twitter=Gehe auf https://dev.twitter.com/apps, erstelle eine Anwendung und stelle sicher, dass die Option „Allow this application to be used to Sign in with Twitter“ aktiviert ist
auths.tip.discord=Erstelle unter https://discordapp.com/developers/applications/me eine neue Anwendung. auths.tip.discord=Erstelle unter https://discordapp.com/developers/applications/me eine neue Anwendung.
auths.tip.gitea=Registriere eine neue OAuth2-Anwendung. Eine Anleitung findest du unter https://docs.gitea.com/development/oauth2-provider/
auths.tip.yandex=`Erstelle eine neue Anwendung auf https://oauth.yandex.com/client/new. Wähle folgende Berechtigungen aus dem "Yandex.Passport API" Bereich: "Zugriff auf E-Mail-Adresse", "Zugriff auf Benutzeravatar" und "Zugriff auf Benutzername, Vor- und Nachname, Geschlecht"` auths.tip.yandex=`Erstelle eine neue Anwendung auf https://oauth.yandex.com/client/new. Wähle folgende Berechtigungen aus dem "Yandex.Passport API" Bereich: "Zugriff auf E-Mail-Adresse", "Zugriff auf Benutzeravatar" und "Zugriff auf Benutzername, Vor- und Nachname, Geschlecht"`
auths.tip.mastodon=Gebe eine benutzerdefinierte URL für die Mastodon-Instanz ein, mit der du dich authentifizieren möchtest (oder benutze die standardmäßige) auths.tip.mastodon=Gebe eine benutzerdefinierte URL für die Mastodon-Instanz ein, mit der du dich authentifizieren möchtest (oder benutze die standardmäßige)
auths.edit=Authentifikationsquelle bearbeiten auths.edit=Authentifikationsquelle bearbeiten
@ -2876,6 +3034,7 @@ config.disable_router_log=Router-Log deaktivieren
config.run_user=Ausführen als config.run_user=Ausführen als
config.run_mode=Laufzeit-Modus config.run_mode=Laufzeit-Modus
config.git_version=Git-Version config.git_version=Git-Version
config.app_data_path=App-Datenpfad
config.repo_root_path=Repository-Wurzelpfad config.repo_root_path=Repository-Wurzelpfad
config.lfs_root_path=LFS-Wurzelpfad config.lfs_root_path=LFS-Wurzelpfad
config.log_file_root_path=Logdateipfad config.log_file_root_path=Logdateipfad
@ -3027,8 +3186,10 @@ monitor.queue.name=Name
monitor.queue.type=Typ monitor.queue.type=Typ
monitor.queue.exemplar=Beispieltyp monitor.queue.exemplar=Beispieltyp
monitor.queue.numberworkers=Anzahl der Worker monitor.queue.numberworkers=Anzahl der Worker
monitor.queue.activeworkers=Aktive Worker
monitor.queue.maxnumberworkers=Maximale Anzahl der Worker monitor.queue.maxnumberworkers=Maximale Anzahl der Worker
monitor.queue.numberinqueue=Nummer in der Warteschlange monitor.queue.numberinqueue=Nummer in der Warteschlange
monitor.queue.review_add=Worker hinzufügen / prüfen
monitor.queue.settings.title=Pool-Einstellungen monitor.queue.settings.title=Pool-Einstellungen
monitor.queue.settings.desc=Pools wachsen dynamisch basierend auf der Blockierung der Arbeitswarteschlange. monitor.queue.settings.desc=Pools wachsen dynamisch basierend auf der Blockierung der Arbeitswarteschlange.
monitor.queue.settings.maxnumberworkers=Maximale Anzahl an Workern monitor.queue.settings.maxnumberworkers=Maximale Anzahl an Workern
@ -3149,6 +3310,7 @@ desc=Repository-Pakete verwalten.
empty=Noch keine Pakete vorhanden. empty=Noch keine Pakete vorhanden.
empty.documentation=Weitere Informationen zur Paket-Registry findest Du in der <a target="_blank" rel="noopener noreferrer" href="%s">Dokumentation</a>. empty.documentation=Weitere Informationen zur Paket-Registry findest Du in der <a target="_blank" rel="noopener noreferrer" href="%s">Dokumentation</a>.
empty.repo=Hast du ein Paket hochgeladen, das hier nicht angezeigt wird? Gehe zu den <a href="%[1]s">Paketeinstellungen</a> und verlinke es mit diesem Repo. empty.repo=Hast du ein Paket hochgeladen, das hier nicht angezeigt wird? Gehe zu den <a href="%[1]s">Paketeinstellungen</a> und verlinke es mit diesem Repo.
registry.documentation=Für weitere Informationen zur %s-Registry, schaue in der <a target="_blank" rel="noopener noreferrer" href="%s">Dokumentation</a> nach.
filter.type=Typ filter.type=Typ
filter.type.all=Alle filter.type.all=Alle
filter.no_result=Keine Ergebnisse mit diesen Kriterien gefunden. filter.no_result=Keine Ergebnisse mit diesen Kriterien gefunden.
@ -3238,6 +3400,8 @@ pub.install=Um das Paket mit Dart zu installieren, führe den folgenden Befehl a
pypi.requires=Erfordert Python pypi.requires=Erfordert Python
pypi.install=Nutze folgenden Befehl, um das Paket mit pip zu installieren: pypi.install=Nutze folgenden Befehl, um das Paket mit pip zu installieren:
rpm.registry=Diese Registry über die Kommandozeile einrichten: rpm.registry=Diese Registry über die Kommandozeile einrichten:
rpm.distros.redhat=auf RedHat-basierten Distributionen
rpm.distros.suse=auf SUSE-basierten Distributionen
rpm.install=Nutze folgenden Befehl, um das Paket zu installieren: rpm.install=Nutze folgenden Befehl, um das Paket zu installieren:
rubygems.install=Um das Paket mit gem zu installieren, führe den folgenden Befehl aus: rubygems.install=Um das Paket mit gem zu installieren, führe den folgenden Befehl aus:
rubygems.install2=oder füg es zum Gemfile hinzu: rubygems.install2=oder füg es zum Gemfile hinzu:
@ -3262,14 +3426,17 @@ settings.delete.success=Das Paket wurde gelöscht.
settings.delete.error=Löschen des Pakets fehlgeschlagen. settings.delete.error=Löschen des Pakets fehlgeschlagen.
owner.settings.cargo.title=Cargo-Registry-Index owner.settings.cargo.title=Cargo-Registry-Index
owner.settings.cargo.initialize=Index initialisieren owner.settings.cargo.initialize=Index initialisieren
owner.settings.cargo.initialize.description=Ein spezielles Index-Repository wird benötigt, um die Cargo-Registry zu nutzen. Diese Option wird dieses Repository (neu) erstellen und automatisch konfigurieren.
owner.settings.cargo.initialize.error=Cargo-Index konnte nicht initialisiert werden: %v owner.settings.cargo.initialize.error=Cargo-Index konnte nicht initialisiert werden: %v
owner.settings.cargo.initialize.success=Der Cargo-Index wurde erfolgreich erstellt. owner.settings.cargo.initialize.success=Der Cargo-Index wurde erfolgreich erstellt.
owner.settings.cargo.rebuild=Index neu erstellen owner.settings.cargo.rebuild=Index neu erstellen
owner.settings.cargo.rebuild.description=Neubauen kann hilfreich sein, wenn der Index nicht mit den gespeicherten Cargo-Paketen synchronisiert ist.
owner.settings.cargo.rebuild.error=Cargo-Index konnte nicht neu erstellt werden: %v owner.settings.cargo.rebuild.error=Cargo-Index konnte nicht neu erstellt werden: %v
owner.settings.cargo.rebuild.success=Der Cargo-Index wurde erfolgreich neu erstellt. owner.settings.cargo.rebuild.success=Der Cargo-Index wurde erfolgreich neu erstellt.
owner.settings.cleanuprules.title=Bereinigungsregeln verwalten owner.settings.cleanuprules.title=Bereinigungsregeln verwalten
owner.settings.cleanuprules.add=Bereinigungsregel hinzufügen owner.settings.cleanuprules.add=Bereinigungsregel hinzufügen
owner.settings.cleanuprules.edit=Bereinigungsregel bearbeiten owner.settings.cleanuprules.edit=Bereinigungsregel bearbeiten
owner.settings.cleanuprules.none=Keine Bereinigungs-Regeln verfügbar. Bitte konsultiere die Dokumentation.
owner.settings.cleanuprules.preview=Vorschau der Bereinigungsregel owner.settings.cleanuprules.preview=Vorschau der Bereinigungsregel
owner.settings.cleanuprules.preview.overview=%d Pakete sollen entfernt werden. owner.settings.cleanuprules.preview.overview=%d Pakete sollen entfernt werden.
owner.settings.cleanuprules.preview.none=Bereinigungsregel stimmt mit keinem Paket überein. owner.settings.cleanuprules.preview.none=Bereinigungsregel stimmt mit keinem Paket überein.
@ -3288,6 +3455,7 @@ owner.settings.cleanuprules.success.update=Bereinigungsregel wurde aktualisiert.
owner.settings.cleanuprules.success.delete=Bereinigungsregel wurde gelöscht. owner.settings.cleanuprules.success.delete=Bereinigungsregel wurde gelöscht.
owner.settings.chef.title=Chef-Registry owner.settings.chef.title=Chef-Registry
owner.settings.chef.keypair=Schlüsselpaar generieren owner.settings.chef.keypair=Schlüsselpaar generieren
owner.settings.chef.keypair.description=Ein Schlüsselpaar ist notwendig, um mit der Chef-Registry zu authentifizieren. Wenn du bereits eins erstellt hast, wird dieses durch eine Neuerstellung verworfen.
[secrets] [secrets]
secrets=Secrets secrets=Secrets
@ -3314,6 +3482,7 @@ status.waiting=Wartend
status.running=Laufend status.running=Laufend
status.success=Erfolg status.success=Erfolg
status.failure=Fehler status.failure=Fehler
status.cancelled=Abgebrochen
status.skipped=Übersprungen status.skipped=Übersprungen
status.blocked=Blockiert status.blocked=Blockiert
@ -3330,6 +3499,7 @@ runners.labels=Labels
runners.last_online=Letzte Online-Zeit runners.last_online=Letzte Online-Zeit
runners.runner_title=Runner runners.runner_title=Runner
runners.task_list=Letzte Aufgaben dieses Runners runners.task_list=Letzte Aufgaben dieses Runners
runners.task_list.no_tasks=Es gibt noch keine Aufgabe.
runners.task_list.run=Ausführen runners.task_list.run=Ausführen
runners.task_list.status=Status runners.task_list.status=Status
runners.task_list.repository=Repository runners.task_list.repository=Repository
@ -3350,17 +3520,45 @@ runners.status.idle=Inaktiv
runners.status.active=Aktiv runners.status.active=Aktiv
runners.status.offline=Offline runners.status.offline=Offline
runners.version=Version runners.version=Version
runners.reset_registration_token=Registrierungs-Token zurücksetzen
runners.reset_registration_token_success=Runner-Registrierungstoken erfolgreich zurückgesetzt runners.reset_registration_token_success=Runner-Registrierungstoken erfolgreich zurückgesetzt
runs.all_workflows=Alle Workflows runs.all_workflows=Alle Workflows
runs.commit=Commit runs.commit=Commit
runs.scheduled=Geplant
runs.pushed_by=gepusht von
runs.invalid_workflow_helper=Die Workflow-Konfigurationsdatei ist ungültig. Bitte überprüfe Deine Konfigurationsdatei: %s runs.invalid_workflow_helper=Die Workflow-Konfigurationsdatei ist ungültig. Bitte überprüfe Deine Konfigurationsdatei: %s
runs.no_matching_runner_helper=Kein passender Runner: %s runs.no_matching_runner_helper=Kein passender Runner: %s
runs.actor=Initiator
runs.status=Status runs.status=Status
runs.actors_no_select=Alle Initiatoren
runs.status_no_select=Alle Status
runs.no_results=Keine passenden Ergebnisse gefunden.
runs.no_runs=Der Workflow hat noch keine Ausführungen.
workflow.disable=Workflow deaktivieren
workflow.disable_success=Workflow '%s' erfolgreich deaktiviert.
workflow.enable=Workflow aktivieren
workflow.enable_success=Workflow '%s' erfolgreich aktiviert.
workflow.disabled=Workflow ist deaktiviert.
need_approval_desc=Um Workflows für den Pull-Request eines Forks auszuführen, ist eine Genehmigung erforderlich. need_approval_desc=Um Workflows für den Pull-Request eines Forks auszuführen, ist eine Genehmigung erforderlich.
variables=Variablen
variables.management=Variablenverwaltung
variables.creation=Variable hinzufügen
variables.none=Es gibt noch keine Variablen.
variables.deletion=Variable entfernen
variables.deletion.description=Das Entfernen einer Variable ist dauerhaft und kann nicht rückgängig gemacht werden. Fortfahren?
variables.description=Variablen werden an bestimmte Aktionen übergeben und können nicht anderweitig gelesen werden.
variables.id_not_exist=Variable mit ID %d existiert nicht.
variables.edit=Variable bearbeiten
variables.deletion.failed=Fehler beim Entfernen der Variable.
variables.deletion.success=Die Variable wurde entfernt.
variables.creation.failed=Fehler beim Hinzufügen der Variable.
variables.creation.success=Die Variable „%s“ wurde hinzugefügt.
variables.update.failed=Fehler beim Bearbeiten der Variable.
variables.update.success=Die Variable wurde bearbeitet.
[projects] [projects]
type-1.display_name=Individuelles Projekt type-1.display_name=Individuelles Projekt
@ -3368,5 +3566,10 @@ type-2.display_name=Repository-Projekt
type-3.display_name=Organisationsprojekt type-3.display_name=Organisationsprojekt
[git.filemode] [git.filemode]
changed_filemode=%[1]s → %[2]s
directory=Verzeichnis
normal_file=Normale Datei
executable_file=Ausführbare Datei
symbolic_link=Softlink symbolic_link=Softlink
submodule=Submodul

Some files were not shown because too many files have changed in this diff Show More