mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-03-09 16:02:06 +01:00
Compare commits
267 commits
Author | SHA1 | Date | |
---|---|---|---|
|
d595393bb6 | ||
|
83b614e1e8 | ||
|
dc15aefa3e | ||
|
29a0b0131e | ||
|
71dc491a09 | ||
|
d39571dc53 | ||
|
591b1f54a3 | ||
|
a5e26e3ad0 | ||
|
8e3d076750 | ||
|
2b66ddf352 | ||
|
d8ca6f0581 | ||
|
bf84528109 | ||
|
485ffc4bae | ||
|
bda9ee9b83 | ||
|
f5a32bd4fd | ||
|
02844b48c3 | ||
|
3beefb29b9 | ||
|
8fa76300ae | ||
|
e741d0a068 | ||
|
ad1aad7b1a | ||
|
48fa9c96a7 | ||
|
1de8d5b450 | ||
|
0ce1c56612 | ||
|
9b29e8add1 | ||
|
4069e1c934 | ||
|
74e1fd16b0 | ||
|
532c35c25a | ||
|
eeb3451a89 | ||
|
fe6f4fde20 | ||
|
c98bd3a11d | ||
|
5cffc09c37 | ||
|
d3e5d887ee | ||
|
72cbefe63e | ||
|
a167d7b91c | ||
|
c5f37b6cd8 | ||
|
a494510972 | ||
|
714308506e | ||
|
2374f8f47d | ||
|
1f9a1537a5 | ||
|
48872d11ca | ||
|
1c04f8f10a | ||
|
bf520f5184 | ||
|
c089228bfa | ||
|
934e92c346 | ||
|
219d07dc96 | ||
|
90db3f6132 | ||
|
73d9e14e80 | ||
|
ca45316707 | ||
|
6f825ab156 | ||
|
0b0eefd42b | ||
|
3e967fa4a0 | ||
|
ee753450a7 | ||
|
616348fc6f | ||
|
5b2db9d3ca | ||
|
53c5469511 | ||
|
0ca5b8496b | ||
|
35435c573a | ||
|
8cec637d08 | ||
|
9f05c76b7b | ||
|
6ac04b8c7d | ||
|
004fe296cc | ||
|
978542cae4 | ||
|
dc785fdae5 | ||
|
c9a3e963ec | ||
|
a887612b75 | ||
|
a27e4bb586 | ||
|
5058c76f3e | ||
|
90e05e7d52 | ||
|
6569f1f25f | ||
|
2f72bec100 | ||
|
42f3644409 | ||
|
1770117178 | ||
|
1379914c45 | ||
|
254bded75e | ||
|
a88e3e6ac0 | ||
|
6c75d1a504 | ||
|
36300be94e | ||
|
c8c8377acb | ||
|
fd4a68b4de | ||
|
78f69040fc | ||
|
3465f73e2c | ||
|
86496d701d | ||
|
de389f2ecc | ||
|
e43533cd1b | ||
|
2a78dba95b | ||
|
e9cd753b98 | ||
|
dac13b7fc3 | ||
|
0db515dfec | ||
|
336ccf45c8 | ||
|
70aefc810c | ||
|
6025b93664 | ||
|
e823122f19 | ||
|
ef9df01cd2 | ||
|
2e114bcaa0 | ||
|
91a12abdaf | ||
|
79bc6e8c35 | ||
|
770fa89dc8 | ||
|
9a7b0c3f02 | ||
|
8c51053739 | ||
|
3a4612cb2b | ||
|
c0113bfbbe | ||
|
08396d566b | ||
|
66b6917923 | ||
|
397b3cf88f | ||
|
bcb72df356 | ||
|
ed2d5f6b73 | ||
|
eda6b436dc | ||
|
09a35a7cb8 | ||
|
a68a37f59c | ||
|
2b86ff6768 | ||
|
8a65c4d28d | ||
|
d624a5edd6 | ||
|
11f71dcb09 | ||
|
7ec30b6ee9 | ||
|
13a5d9f3af | ||
|
a429dbad98 | ||
|
0c0fd333f3 | ||
|
d96cef1ac4 | ||
|
3f58b8d1bd | ||
|
908bd64238 | ||
|
be36f91bb7 | ||
|
8e4536fd98 | ||
|
f043fb4495 | ||
|
1dc03cc1c3 | ||
|
e4dac6a6ab | ||
|
ff585d0a20 | ||
|
5f9a2ad1db | ||
|
618eb8e72a | ||
|
d763886dae | ||
|
768402c884 | ||
|
9c6f2a132d | ||
|
d77096071d | ||
|
f0abba3eef | ||
|
5d211c101f | ||
|
01e9ac0561 | ||
|
a4e5b1b6bc | ||
|
1f62fe8ae0 | ||
|
96f0c76648 | ||
|
e37a344ce5 | ||
|
887a9576b8 | ||
|
edd468323f | ||
|
4b7f369290 | ||
|
ef8f366734 | ||
|
c5e4694327 | ||
|
9471083571 | ||
|
804051b9dd | ||
|
893d0941a8 | ||
|
1913399d81 | ||
|
4fe311e7c0 | ||
|
b8ffb88d1d | ||
|
fd8565c91a | ||
|
c87ff7dc1d | ||
|
7d3d8ef142 | ||
|
032bb17899 | ||
|
fa307f06ac | ||
|
d5c6036c53 | ||
|
f3b16e1363 | ||
|
240fbc2661 | ||
|
642dd61446 | ||
|
c7e52852bb | ||
|
5d85dc2d91 | ||
|
b692da7f6f | ||
|
2c5d47ec1f | ||
|
e740aa05a4 | ||
|
fb21899097 | ||
|
0f7020cbef | ||
|
e491b05935 | ||
|
7845659322 | ||
|
9011f73da3 | ||
|
b1ffd0f58f | ||
|
f5d83f395f | ||
|
348e083227 | ||
|
704910c7e9 | ||
|
12a277ed65 | ||
|
e43b9edc36 | ||
|
acd7e57295 | ||
|
c131de73a5 | ||
|
b8fc56885e | ||
|
7f4efb1c34 | ||
|
779ed6cf3f | ||
|
11bb77313e | ||
|
c2f99a5a1f | ||
|
d1c4670e45 | ||
|
fe35a17dbe | ||
|
d66a184f45 | ||
|
932801ae18 | ||
|
d6d6561295 | ||
|
18b60db6ae | ||
|
1b36e34fc4 | ||
|
d2d161ad28 | ||
|
f2f2d7dab2 | ||
|
1667fece88 | ||
|
044cd5cf7e | ||
|
dfd1b2fdcd | ||
|
bf1839aed3 | ||
|
26f0a7e779 | ||
|
a7f4346f5e | ||
|
d2ee58fb2a | ||
|
aec4a0dd59 | ||
|
5ffa1ee883 | ||
|
3cd20d7d37 | ||
|
d8c8fa9bae | ||
|
d7e2fd555c | ||
|
1f9104d96f | ||
|
ea5a8c7809 | ||
|
5ae3b81f3c | ||
|
6d2c29ae85 | ||
|
0496e72d15 | ||
|
e90a48fd4b | ||
|
e2ffe12e50 | ||
|
2c0c6f408e | ||
|
092cb967b0 | ||
|
d62cbfe923 | ||
|
43bad93715 | ||
|
eb80c9429e | ||
|
946a10a8d5 | ||
|
a7165d1fb0 | ||
|
47b67fcafc | ||
|
7d3a013e5e | ||
|
4cb10ff28a | ||
|
00e5c68060 | ||
|
700e9f027b | ||
|
9ee88e965e | ||
|
0ae05e1000 | ||
|
2ff9e77dba | ||
|
4ddf4a8fd3 | ||
|
4c7fef22f6 | ||
|
01e7095968 | ||
|
f1e413eb7c | ||
|
67b9b0c76e | ||
|
56f9ddc9af | ||
|
00749b3a8f | ||
|
8da48fead3 | ||
|
b835f0a1b0 | ||
|
f8c0a352ab | ||
|
859fa4e489 | ||
|
e8a67571a1 | ||
|
28c8a889bb | ||
|
3003195ad7 | ||
|
c400f26e6c | ||
|
0a0a3cea1b | ||
|
cb88d55837 | ||
|
e1e7299bd9 | ||
|
d8ae7d9e96 | ||
|
b28a070a52 | ||
|
b2483b2ae0 | ||
|
14c7055494 | ||
|
81b9977540 | ||
|
a75862bd7d | ||
|
99baeb47e5 | ||
|
7d45c1c6c7 | ||
|
5442b0a6b1 | ||
|
da0c4ab199 | ||
|
658ed564cb | ||
|
eb4f1de8ec | ||
|
ba7da0af31 | ||
|
74712e3400 | ||
|
6c16834d28 | ||
|
81308159fd | ||
|
2f1a737769 | ||
|
5b6d8a303d | ||
|
d26b7902ec | ||
|
1a8f1482af | ||
|
84718e7b17 | ||
|
232179aa3d | ||
|
300e01f733 | ||
|
d727757cfb |
320 changed files with 14709 additions and 4480 deletions
2
.forgejo/testdata/build-release/Dockerfile
vendored
2
.forgejo/testdata/build-release/Dockerfile
vendored
|
@ -3,4 +3,4 @@ ARG RELEASE_VERSION=unkown
|
||||||
LABEL maintainer="contact@forgejo.org" \
|
LABEL maintainer="contact@forgejo.org" \
|
||||||
org.opencontainers.image.version="${RELEASE_VERSION}"
|
org.opencontainers.image.version="${RELEASE_VERSION}"
|
||||||
RUN mkdir -p /app/gitea
|
RUN mkdir -p /app/gitea
|
||||||
RUN ( echo '#!/bin/sh' ; echo "echo forgejo v$RELEASE_VERSION" ) > /app/gitea/forgejo-cli ; chmod +x /app/gitea/forgejo-cli
|
RUN ( echo '#!/bin/sh' ; echo "echo forgejo v$RELEASE_VERSION" ) > /app/gitea/gitea ; chmod +x /app/gitea/gitea
|
||||||
|
|
2
.forgejo/testdata/build-release/go.mod
vendored
2
.forgejo/testdata/build-release/go.mod
vendored
|
@ -1,3 +1,3 @@
|
||||||
module code.gitea.io/gitea
|
module code.gitea.io/gitea
|
||||||
|
|
||||||
go 1.23.1
|
go 1.23.2
|
||||||
|
|
|
@ -31,7 +31,7 @@ on:
|
||||||
jobs:
|
jobs:
|
||||||
backporting:
|
backporting:
|
||||||
if: >
|
if: >
|
||||||
!startsWith(vars.ROLE, 'forgejo-') && (
|
( vars.ROLE == 'forgejo-coding' ) && (
|
||||||
github.event.pull_request.merged
|
github.event.pull_request.merged
|
||||||
&&
|
&&
|
||||||
contains(toJSON(github.event.pull_request.labels), 'backport/v')
|
contains(toJSON(github.event.pull_request.labels), 'backport/v')
|
||||||
|
|
|
@ -22,10 +22,10 @@ on:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release-simulation:
|
release-simulation:
|
||||||
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
if: vars.ROLE == 'forgejo-coding'
|
||||||
runs-on: self-hosted
|
runs-on: self-hosted
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- id: forgejo
|
- id: forgejo
|
||||||
uses: https://code.forgejo.org/actions/setup-forgejo@v1
|
uses: https://code.forgejo.org/actions/setup-forgejo@v1
|
||||||
|
|
|
@ -27,7 +27,7 @@ jobs:
|
||||||
# root is used for testing, allow it
|
# root is used for testing, allow it
|
||||||
if: vars.ROLE == 'forgejo-integration' || github.repository_owner == 'root'
|
if: vars.ROLE == 'forgejo-integration' || github.repository_owner == 'root'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ jobs:
|
||||||
repository="${{ github.repository }}"
|
repository="${{ github.repository }}"
|
||||||
echo "value=${repository##*/}" >> "$GITHUB_OUTPUT"
|
echo "value=${repository##*/}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- uses: https://code.forgejo.org/actions/setup-node@v3
|
- uses: https://code.forgejo.org/actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ jobs:
|
||||||
|
|
||||||
- name: cache node_modules
|
- name: cache node_modules
|
||||||
id: node
|
id: node
|
||||||
uses: https://code.forgejo.org/actions/cache@v3
|
uses: https://code.forgejo.org/actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
node_modules
|
node_modules
|
||||||
|
@ -170,7 +170,7 @@ jobs:
|
||||||
platforms: linux/amd64,linux/arm64,linux/arm/v6
|
platforms: linux/amd64,linux/arm64,linux/arm/v6
|
||||||
release-notes: "${{ steps.release-notes.outputs.value }}"
|
release-notes: "${{ steps.release-notes.outputs.value }}"
|
||||||
binary-name: forgejo
|
binary-name: forgejo
|
||||||
binary-path: /app/gitea/forgejo-cli
|
binary-path: /app/gitea/gitea
|
||||||
override: "${{ steps.release-info.outputs.override }}"
|
override: "${{ steps.release-info.outputs.override }}"
|
||||||
verify-labels: "maintainer=contact@forgejo.org,org.opencontainers.image.version=${{ steps.release-info.outputs.version }}"
|
verify-labels: "maintainer=contact@forgejo.org,org.opencontainers.image.version=${{ steps.release-info.outputs.version }}"
|
||||||
verbose: ${{ vars.VERBOSE || secrets.VERBOSE || 'false' }}
|
verbose: ${{ vars.VERBOSE || secrets.VERBOSE || 'false' }}
|
||||||
|
@ -194,7 +194,7 @@ jobs:
|
||||||
verbose: ${{ vars.VERBOSE || secrets.VERBOSE || 'false' }}
|
verbose: ${{ vars.VERBOSE || secrets.VERBOSE || 'false' }}
|
||||||
|
|
||||||
- name: end-to-end tests
|
- name: end-to-end tests
|
||||||
if: ${{ secrets.TOKEN != '' && vars.ROLE == 'forgejo-integration' }}
|
if: ${{ secrets.TOKEN != '' && vars.ROLE == 'forgejo-integration' && vars.SKIP_END_TO_END != 'true' }}
|
||||||
uses: https://code.forgejo.org/actions/cascading-pr@v2
|
uses: https://code.forgejo.org/actions/cascading-pr@v2
|
||||||
with:
|
with:
|
||||||
origin-url: ${{ env.GITHUB_SERVER_URL }}
|
origin-url: ${{ env.GITHUB_SERVER_URL }}
|
||||||
|
|
|
@ -24,7 +24,7 @@ on:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
info:
|
info:
|
||||||
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
if: vars.ROLE == 'forgejo-coding'
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
container:
|
container:
|
||||||
image: code.forgejo.org/oci/node:20-bookworm
|
image: code.forgejo.org/oci/node:20-bookworm
|
||||||
|
@ -44,7 +44,7 @@ jobs:
|
||||||
|
|
||||||
cascade:
|
cascade:
|
||||||
if: >
|
if: >
|
||||||
!startsWith(vars.ROLE, 'forgejo-') && (
|
vars.ROLE == 'forgejo-coding' && (
|
||||||
github.event_name == 'push' ||
|
github.event_name == 'push' ||
|
||||||
(
|
(
|
||||||
github.event.action == 'label_updated' && contains(github.event.pull_request.labels.*.name, 'run-end-to-end-tests')
|
github.event.action == 'label_updated' && contains(github.event.pull_request.labels.*.name, 'run-end-to-end-tests')
|
||||||
|
|
|
@ -14,7 +14,7 @@ on:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test-e2e:
|
test-e2e:
|
||||||
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
container:
|
container:
|
||||||
image: 'code.forgejo.org/oci/playwright:latest'
|
image: 'code.forgejo.org/oci/playwright:latest'
|
||||||
|
|
24
.forgejo/workflows/milestone.yml
Normal file
24
.forgejo/workflows/milestone.yml
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
# Copyright 2024 The Forgejo Authors
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
#
|
||||||
|
name: milestone
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request_target:
|
||||||
|
types:
|
||||||
|
- closed
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
set:
|
||||||
|
if: vars.ROLE == 'forgejo-coding' && github.event.pull_request.merged
|
||||||
|
runs-on: docker
|
||||||
|
container:
|
||||||
|
image: 'code.forgejo.org/oci/ci:1'
|
||||||
|
steps:
|
||||||
|
- uses: https://code.forgejo.org/forgejo/set-milestone@v1.0.0
|
||||||
|
with:
|
||||||
|
forgejo: https://codeberg.org
|
||||||
|
repository: forgejo/forgejo
|
||||||
|
token: ${{ secrets.SET_MILESTONE_TOKEN }}
|
||||||
|
pr-number: ${{ github.event.pull_request.number }}
|
||||||
|
verbose: ${{ vars.SET_MILESTONE_VERBOSE }}
|
|
@ -39,7 +39,7 @@ jobs:
|
||||||
runs-on: self-hosted
|
runs-on: self-hosted
|
||||||
if: vars.DOER != '' && vars.FORGEJO != '' && vars.TO_OWNER != '' && vars.FROM_OWNER != '' && secrets.TOKEN != ''
|
if: vars.DOER != '' && vars.FORGEJO != '' && vars.TO_OWNER != '' && vars.FROM_OWNER != '' && secrets.TOKEN != ''
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: copy & sign
|
- name: copy & sign
|
||||||
uses: https://code.forgejo.org/forgejo/forgejo-build-publish/publish@v5
|
uses: https://code.forgejo.org/forgejo/forgejo-build-publish/publish@v5
|
||||||
|
@ -59,30 +59,28 @@ jobs:
|
||||||
gpg-passphrase: ${{ secrets.GPG_PASSPHRASE }}
|
gpg-passphrase: ${{ secrets.GPG_PASSPHRASE }}
|
||||||
verbose: ${{ vars.VERBOSE }}
|
verbose: ${{ vars.VERBOSE }}
|
||||||
|
|
||||||
- name: upgrade v*.next.forgejo.org
|
- name: get trigger mirror issue
|
||||||
run: |
|
id: mirror
|
||||||
export DEBIAN_FRONTEND=noninteractive
|
uses: https://code.forgejo.org/infrastructure/issue-action/get@v1.1.0
|
||||||
apt-get update -qq
|
with:
|
||||||
apt-get -q install -y -qq curl
|
forgejo: https://code.forgejo.org
|
||||||
version="${{ github.ref_name }}"
|
repository: forgejo/forgejo
|
||||||
version=${version##*v}
|
labels: mirror-trigger
|
||||||
major=$(echo $version | sed -E -e 's/^([0-9]+).*/\1/')
|
|
||||||
# https://forgejo.org/docs/next/developer/infrastructure
|
|
||||||
curl -o /dev/null -sS https://v$major.next.forgejo.org/.well-known/wakeup-on-logs/forgejo-v$major
|
|
||||||
|
|
||||||
- name: set up go for the DNS update below
|
- name: trigger the mirror
|
||||||
if: vars.ROLE == 'forgejo-experimental' && secrets.OVH_APP_KEY != ''
|
uses: https://code.forgejo.org/infrastructure/issue-action/set@v1.1.0
|
||||||
uses: https://code.forgejo.org/actions/setup-go@v4
|
|
||||||
with:
|
with:
|
||||||
go-version-file: "go.mod"
|
forgejo: https://code.forgejo.org
|
||||||
- name: update the _release.experimental DNS record
|
repository: forgejo/forgejo
|
||||||
if: vars.ROLE == 'forgejo-experimental' && secrets.OVH_APP_KEY != ''
|
token: ${{ secrets.LABEL_ISSUE_FORGEJO_MIRROR_TOKEN }}
|
||||||
uses: https://code.forgejo.org/actions/ovh-dns-update@v1
|
numbers: ${{ steps.mirror.outputs.numbers }}
|
||||||
|
label-wait-if-exists: 3600
|
||||||
|
label: trigger
|
||||||
|
|
||||||
|
- name: upgrade v*.next.forgejo.org
|
||||||
|
uses: https://code.forgejo.org/infrastructure/next-digest@v1.1.0
|
||||||
with:
|
with:
|
||||||
subdomain: _release.experimental
|
url: https://placeholder:${{ secrets.TOKEN_NEXT_DIGEST }}@code.forgejo.org/infrastructure/next-digest
|
||||||
domain: forgejo.com # there is a CNAME from .org to .com (for security reasons)
|
ref_name: '${{ github.ref_name }}'
|
||||||
record-id: 5283602601
|
image: 'codeberg.org/forgejo-experimental/forgejo'
|
||||||
value: v=${{ github.ref_name }}
|
tag_suffix: '-rootless'
|
||||||
ovh-app-key: ${{ secrets.OVH_APP_KEY }}
|
|
||||||
ovh-app-secret: ${{ secrets.OVH_APP_SECRET }}
|
|
||||||
ovh-consumer-key: ${{ secrets.OVH_CON_KEY }}
|
|
||||||
|
|
|
@ -6,12 +6,12 @@ on:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release-notes:
|
release-notes:
|
||||||
if: ${{ !startsWith(vars.ROLE, 'forgejo-')
|
if: vars.ROLE == 'forgejo-coding'
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
container:
|
container:
|
||||||
image: 'code.forgejo.org/oci/node:20-bookworm'
|
image: 'code.forgejo.org/oci/node:20-bookworm'
|
||||||
steps:
|
steps:
|
||||||
- uses: https://code.forgejo.org/actions/checkout@v3
|
- uses: https://code.forgejo.org/actions/checkout@v4
|
||||||
|
|
||||||
- uses: https://code.forgejo.org/actions/setup-go@v4
|
- uses: https://code.forgejo.org/actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
|
|
|
@ -7,12 +7,12 @@ on:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release-notes:
|
release-notes:
|
||||||
if: ${{ !startsWith(vars.ROLE, 'forgejo-') && contains(github.event.pull_request.labels.*.name, 'worth a release-note') }}
|
if: ( vars.ROLE == 'forgejo-coding' ) && contains(github.event.pull_request.labels.*.name, 'worth a release-note')
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
container:
|
container:
|
||||||
image: 'code.forgejo.org/oci/node:20-bookworm'
|
image: 'code.forgejo.org/oci/node:20-bookworm'
|
||||||
steps:
|
steps:
|
||||||
- uses: https://code.forgejo.org/actions/checkout@v3
|
- uses: https://code.forgejo.org/actions/checkout@v4
|
||||||
|
|
||||||
- name: event
|
- name: event
|
||||||
run: |
|
run: |
|
||||||
|
|
|
@ -8,7 +8,9 @@ name: renovate
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- 'renovate/**' # self-test updates
|
- renovate/** # self-test updates
|
||||||
|
paths:
|
||||||
|
- .forgejo/workflows/renovate.yml
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 0/2 * * *'
|
- cron: '0 0/2 * * *'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
@ -19,7 +21,7 @@ env:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
renovate:
|
renovate:
|
||||||
if: ${{ secrets.RENOVATE_TOKEN != '' }}
|
if: vars.ROLE == 'forgejo-coding' && secrets.RENOVATE_TOKEN != ''
|
||||||
|
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
container:
|
container:
|
||||||
|
|
|
@ -9,7 +9,7 @@ on:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
backend-checks:
|
backend-checks:
|
||||||
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
container:
|
container:
|
||||||
image: 'code.forgejo.org/oci/node:20-bookworm'
|
image: 'code.forgejo.org/oci/node:20-bookworm'
|
||||||
|
@ -19,7 +19,7 @@ jobs:
|
||||||
cat <<'EOF'
|
cat <<'EOF'
|
||||||
${{ toJSON(github) }}
|
${{ toJSON(github) }}
|
||||||
EOF
|
EOF
|
||||||
- uses: https://code.forgejo.org/actions/checkout@v3
|
- uses: https://code.forgejo.org/actions/checkout@v4
|
||||||
- uses: https://code.forgejo.org/actions/setup-go@v4
|
- uses: https://code.forgejo.org/actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version-file: "go.mod"
|
go-version-file: "go.mod"
|
||||||
|
@ -34,19 +34,19 @@ jobs:
|
||||||
path: '/workspace/forgejo/forgejo/gitea'
|
path: '/workspace/forgejo/forgejo/gitea'
|
||||||
key: backend-build-${{ github.sha }}
|
key: backend-build-${{ github.sha }}
|
||||||
frontend-checks:
|
frontend-checks:
|
||||||
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
container:
|
container:
|
||||||
image: 'code.forgejo.org/oci/node:20-bookworm'
|
image: 'code.forgejo.org/oci/node:20-bookworm'
|
||||||
steps:
|
steps:
|
||||||
- uses: https://code.forgejo.org/actions/checkout@v3
|
- uses: https://code.forgejo.org/actions/checkout@v4
|
||||||
- run: make deps-frontend
|
- run: make deps-frontend
|
||||||
- run: make lint-frontend
|
- run: make lint-frontend
|
||||||
- run: make checks-frontend
|
- run: make checks-frontend
|
||||||
- run: make test-frontend-coverage
|
- run: make test-frontend-coverage
|
||||||
- run: make frontend
|
- run: make frontend
|
||||||
test-unit:
|
test-unit:
|
||||||
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
needs: [backend-checks, frontend-checks]
|
needs: [backend-checks, frontend-checks]
|
||||||
container:
|
container:
|
||||||
|
@ -66,7 +66,7 @@ jobs:
|
||||||
MINIO_ROOT_USER: 123456
|
MINIO_ROOT_USER: 123456
|
||||||
MINIO_ROOT_PASSWORD: 12345678
|
MINIO_ROOT_PASSWORD: 12345678
|
||||||
steps:
|
steps:
|
||||||
- uses: https://code.forgejo.org/actions/checkout@v3
|
- uses: https://code.forgejo.org/actions/checkout@v4
|
||||||
- uses: https://code.forgejo.org/actions/setup-go@v4
|
- uses: https://code.forgejo.org/actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version-file: "go.mod"
|
go-version-file: "go.mod"
|
||||||
|
@ -106,7 +106,7 @@ jobs:
|
||||||
TAGS: bindata
|
TAGS: bindata
|
||||||
TEST_ELASTICSEARCH_URL: http://elasticsearch:9200
|
TEST_ELASTICSEARCH_URL: http://elasticsearch:9200
|
||||||
test-remote-cacher:
|
test-remote-cacher:
|
||||||
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
needs: [backend-checks, frontend-checks]
|
needs: [backend-checks, frontend-checks]
|
||||||
container:
|
container:
|
||||||
|
@ -131,7 +131,7 @@ jobs:
|
||||||
image: ${{ matrix.cacher.image }}
|
image: ${{ matrix.cacher.image }}
|
||||||
options: ${{ matrix.cacher.options }}
|
options: ${{ matrix.cacher.options }}
|
||||||
steps:
|
steps:
|
||||||
- uses: https://code.forgejo.org/actions/checkout@v3
|
- uses: https://code.forgejo.org/actions/checkout@v4
|
||||||
- uses: https://code.forgejo.org/actions/setup-go@v4
|
- uses: https://code.forgejo.org/actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version-file: "go.mod"
|
go-version-file: "go.mod"
|
||||||
|
@ -167,7 +167,7 @@ jobs:
|
||||||
TAGS: bindata
|
TAGS: bindata
|
||||||
TEST_REDIS_SERVER: cacher:${{ matrix.cacher.port }}
|
TEST_REDIS_SERVER: cacher:${{ matrix.cacher.port }}
|
||||||
test-mysql:
|
test-mysql:
|
||||||
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
needs: [backend-checks, frontend-checks]
|
needs: [backend-checks, frontend-checks]
|
||||||
container:
|
container:
|
||||||
|
@ -183,7 +183,7 @@ jobs:
|
||||||
#
|
#
|
||||||
MYSQL_EXTRA_FLAGS: --innodb-adaptive-flushing=OFF --innodb-buffer-pool-size=4G --innodb-log-buffer-size=128M --innodb-flush-log-at-trx-commit=0 --innodb-flush-log-at-timeout=30 --innodb-flush-method=nosync --innodb-fsync-threshold=1000000000
|
MYSQL_EXTRA_FLAGS: --innodb-adaptive-flushing=OFF --innodb-buffer-pool-size=4G --innodb-log-buffer-size=128M --innodb-flush-log-at-trx-commit=0 --innodb-flush-log-at-timeout=30 --innodb-flush-method=nosync --innodb-fsync-threshold=1000000000
|
||||||
steps:
|
steps:
|
||||||
- uses: https://code.forgejo.org/actions/checkout@v3
|
- uses: https://code.forgejo.org/actions/checkout@v4
|
||||||
- uses: https://code.forgejo.org/actions/setup-go@v4
|
- uses: https://code.forgejo.org/actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version-file: "go.mod"
|
go-version-file: "go.mod"
|
||||||
|
@ -218,7 +218,7 @@ jobs:
|
||||||
env:
|
env:
|
||||||
USE_REPO_TEST_DIR: 1
|
USE_REPO_TEST_DIR: 1
|
||||||
test-pgsql:
|
test-pgsql:
|
||||||
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
needs: [backend-checks, frontend-checks]
|
needs: [backend-checks, frontend-checks]
|
||||||
container:
|
container:
|
||||||
|
@ -237,7 +237,7 @@ jobs:
|
||||||
POSTGRES_DB: test
|
POSTGRES_DB: test
|
||||||
POSTGRES_PASSWORD: postgres
|
POSTGRES_PASSWORD: postgres
|
||||||
steps:
|
steps:
|
||||||
- uses: https://code.forgejo.org/actions/checkout@v3
|
- uses: https://code.forgejo.org/actions/checkout@v4
|
||||||
- uses: https://code.forgejo.org/actions/setup-go@v4
|
- uses: https://code.forgejo.org/actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version-file: "go.mod"
|
go-version-file: "go.mod"
|
||||||
|
@ -274,13 +274,13 @@ jobs:
|
||||||
USE_REPO_TEST_DIR: 1
|
USE_REPO_TEST_DIR: 1
|
||||||
TEST_LDAP: 1
|
TEST_LDAP: 1
|
||||||
test-sqlite:
|
test-sqlite:
|
||||||
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
needs: [backend-checks, frontend-checks]
|
needs: [backend-checks, frontend-checks]
|
||||||
container:
|
container:
|
||||||
image: 'code.forgejo.org/oci/node:20-bookworm'
|
image: 'code.forgejo.org/oci/node:20-bookworm'
|
||||||
steps:
|
steps:
|
||||||
- uses: https://code.forgejo.org/actions/checkout@v3
|
- uses: https://code.forgejo.org/actions/checkout@v4
|
||||||
- uses: https://code.forgejo.org/actions/setup-go@v4
|
- uses: https://code.forgejo.org/actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version-file: "go.mod"
|
go-version-file: "go.mod"
|
||||||
|
@ -318,7 +318,7 @@ jobs:
|
||||||
TEST_TAGS: sqlite sqlite_unlock_notify
|
TEST_TAGS: sqlite sqlite_unlock_notify
|
||||||
USE_REPO_TEST_DIR: 1
|
USE_REPO_TEST_DIR: 1
|
||||||
security-check:
|
security-check:
|
||||||
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
needs:
|
needs:
|
||||||
- test-sqlite
|
- test-sqlite
|
||||||
|
@ -329,7 +329,7 @@ jobs:
|
||||||
container:
|
container:
|
||||||
image: 'code.forgejo.org/oci/node:20-bookworm'
|
image: 'code.forgejo.org/oci/node:20-bookworm'
|
||||||
steps:
|
steps:
|
||||||
- uses: https://code.forgejo.org/actions/checkout@v3
|
- uses: https://code.forgejo.org/actions/checkout@v4
|
||||||
- uses: https://code.forgejo.org/actions/setup-go@v4
|
- uses: https://code.forgejo.org/actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version-file: "go.mod"
|
go-version-file: "go.mod"
|
||||||
|
|
|
@ -51,7 +51,7 @@ RUN chmod 755 /tmp/local/usr/bin/entrypoint \
|
||||||
/go/src/code.gitea.io/gitea/environment-to-ini
|
/go/src/code.gitea.io/gitea/environment-to-ini
|
||||||
RUN chmod 644 /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete
|
RUN chmod 644 /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete
|
||||||
|
|
||||||
FROM code.forgejo.org/oci/golang:1.23-alpine3.20
|
FROM code.forgejo.org/oci/alpine:3.20
|
||||||
ARG RELEASE_VERSION
|
ARG RELEASE_VERSION
|
||||||
LABEL maintainer="contact@forgejo.org" \
|
LABEL maintainer="contact@forgejo.org" \
|
||||||
org.opencontainers.image.authors="Forgejo" \
|
org.opencontainers.image.authors="Forgejo" \
|
||||||
|
@ -103,6 +103,6 @@ CMD ["/bin/s6-svscan", "/etc/s6"]
|
||||||
COPY --from=build-env /tmp/local /
|
COPY --from=build-env /tmp/local /
|
||||||
RUN cd /usr/local/bin ; ln -s gitea forgejo
|
RUN cd /usr/local/bin ; ln -s gitea forgejo
|
||||||
COPY --from=build-env /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea
|
COPY --from=build-env /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea
|
||||||
RUN ln /app/gitea/gitea /app/gitea/forgejo-cli
|
RUN ln -s /app/gitea/gitea /app/gitea/forgejo-cli
|
||||||
COPY --from=build-env /go/src/code.gitea.io/gitea/environment-to-ini /usr/local/bin/environment-to-ini
|
COPY --from=build-env /go/src/code.gitea.io/gitea/environment-to-ini /usr/local/bin/environment-to-ini
|
||||||
COPY --from=build-env /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete /etc/profile.d/gitea_bash_autocomplete.sh
|
COPY --from=build-env /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete /etc/profile.d/gitea_bash_autocomplete.sh
|
||||||
|
|
|
@ -49,7 +49,7 @@ RUN chmod 755 /tmp/local/usr/local/bin/docker-entrypoint.sh \
|
||||||
/go/src/code.gitea.io/gitea/environment-to-ini
|
/go/src/code.gitea.io/gitea/environment-to-ini
|
||||||
RUN chmod 644 /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete
|
RUN chmod 644 /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete
|
||||||
|
|
||||||
FROM code.forgejo.org/oci/golang:1.23-alpine3.20
|
FROM code.forgejo.org/oci/alpine:3.20
|
||||||
LABEL maintainer="contact@forgejo.org" \
|
LABEL maintainer="contact@forgejo.org" \
|
||||||
org.opencontainers.image.authors="Forgejo" \
|
org.opencontainers.image.authors="Forgejo" \
|
||||||
org.opencontainers.image.url="https://forgejo.org" \
|
org.opencontainers.image.url="https://forgejo.org" \
|
||||||
|
@ -90,7 +90,7 @@ RUN chown git:git /var/lib/gitea /etc/gitea
|
||||||
COPY --from=build-env /tmp/local /
|
COPY --from=build-env /tmp/local /
|
||||||
RUN cd /usr/local/bin ; ln -s gitea forgejo
|
RUN cd /usr/local/bin ; ln -s gitea forgejo
|
||||||
COPY --from=build-env --chown=root:root /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea
|
COPY --from=build-env --chown=root:root /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea
|
||||||
RUN ln /app/gitea/gitea /app/gitea/forgejo-cli
|
RUN ln -s /app/gitea/gitea /app/gitea/forgejo-cli
|
||||||
COPY --from=build-env --chown=root:root /go/src/code.gitea.io/gitea/environment-to-ini /usr/local/bin/environment-to-ini
|
COPY --from=build-env --chown=root:root /go/src/code.gitea.io/gitea/environment-to-ini /usr/local/bin/environment-to-ini
|
||||||
COPY --from=build-env /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete /etc/profile.d/gitea_bash_autocomplete.sh
|
COPY --from=build-env /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete /etc/profile.d/gitea_bash_autocomplete.sh
|
||||||
|
|
||||||
|
|
11
cmd/serv.go
11
cmd/serv.go
|
@ -147,6 +147,12 @@ func runServ(c *cli.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if err := recover(); err != nil {
|
||||||
|
_ = fail(ctx, "Internal Server Error", "Panic: %v\n%s", err, log.Stack(2))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
keys := strings.Split(c.Args().First(), "-")
|
keys := strings.Split(c.Args().First(), "-")
|
||||||
if len(keys) != 2 || keys[0] != "key" {
|
if len(keys) != 2 || keys[0] != "key" {
|
||||||
return fail(ctx, "Key ID format error", "Invalid key argument: %s", c.Args().First())
|
return fail(ctx, "Key ID format error", "Invalid key argument: %s", c.Args().First())
|
||||||
|
@ -193,10 +199,7 @@ func runServ(c *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
verb := words[0]
|
verb := words[0]
|
||||||
repoPath := words[1]
|
repoPath := strings.TrimPrefix(words[1], "/")
|
||||||
if repoPath[0] == '/' {
|
|
||||||
repoPath = repoPath[1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
var lfsVerb string
|
var lfsVerb string
|
||||||
if verb == lfsAuthenticateVerb {
|
if verb == lfsAuthenticateVerb {
|
||||||
|
|
|
@ -529,7 +529,8 @@ INTERNAL_TOKEN =
|
||||||
;; HMAC to encode urls with, it **is required** if camo is enabled.
|
;; HMAC to encode urls with, it **is required** if camo is enabled.
|
||||||
;HMAC_KEY =
|
;HMAC_KEY =
|
||||||
;; Set to true to use camo for https too lese only non https urls are proxyed
|
;; Set to true to use camo for https too lese only non https urls are proxyed
|
||||||
;ALLWAYS = false
|
;; ALLWAYS is deprecated and will be removed in the future
|
||||||
|
;ALWAYS = false
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
18
go.mod
18
go.mod
|
@ -1,6 +1,6 @@
|
||||||
module code.gitea.io/gitea
|
module code.gitea.io/gitea
|
||||||
|
|
||||||
go 1.23.1
|
go 1.23.2
|
||||||
|
|
||||||
require (
|
require (
|
||||||
code.forgejo.org/f3/gof3/v3 v3.7.0
|
code.forgejo.org/f3/gof3/v3 v3.7.0
|
||||||
|
@ -45,6 +45,7 @@ require (
|
||||||
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-git/v5 v5.11.0
|
github.com/go-git/go-git/v5 v5.11.0
|
||||||
github.com/go-ldap/ldap/v3 v3.4.6
|
github.com/go-ldap/ldap/v3 v3.4.6
|
||||||
|
github.com/go-openapi/spec v0.20.14
|
||||||
github.com/go-sql-driver/mysql v1.8.1
|
github.com/go-sql-driver/mysql v1.8.1
|
||||||
github.com/go-swagger/go-swagger v0.30.5
|
github.com/go-swagger/go-swagger v0.30.5
|
||||||
github.com/go-testfixtures/testfixtures/v3 v3.12.0
|
github.com/go-testfixtures/testfixtures/v3 v3.12.0
|
||||||
|
@ -75,7 +76,7 @@ require (
|
||||||
github.com/meilisearch/meilisearch-go v0.28.0
|
github.com/meilisearch/meilisearch-go v0.28.0
|
||||||
github.com/mholt/archiver/v3 v3.5.1
|
github.com/mholt/archiver/v3 v3.5.1
|
||||||
github.com/microcosm-cc/bluemonday v1.0.27
|
github.com/microcosm-cc/bluemonday v1.0.27
|
||||||
github.com/minio/minio-go/v7 v7.0.74
|
github.com/minio/minio-go/v7 v7.0.77
|
||||||
github.com/msteinert/pam v1.2.0
|
github.com/msteinert/pam v1.2.0
|
||||||
github.com/nektos/act v0.2.52
|
github.com/nektos/act v0.2.52
|
||||||
github.com/niklasfasching/go-org v1.7.0
|
github.com/niklasfasching/go-org v1.7.0
|
||||||
|
@ -101,12 +102,12 @@ require (
|
||||||
github.com/yuin/goldmark v1.7.4
|
github.com/yuin/goldmark v1.7.4
|
||||||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
|
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
|
||||||
go.uber.org/mock v0.4.0
|
go.uber.org/mock v0.4.0
|
||||||
golang.org/x/crypto v0.27.0
|
golang.org/x/crypto v0.31.0
|
||||||
golang.org/x/image v0.20.0
|
golang.org/x/image v0.20.0
|
||||||
golang.org/x/net v0.29.0
|
golang.org/x/net v0.29.0
|
||||||
golang.org/x/oauth2 v0.23.0
|
golang.org/x/oauth2 v0.23.0
|
||||||
golang.org/x/sys v0.25.0
|
golang.org/x/sys v0.28.0
|
||||||
golang.org/x/text v0.18.0
|
golang.org/x/text v0.21.0
|
||||||
golang.org/x/tools v0.25.0
|
golang.org/x/tools v0.25.0
|
||||||
google.golang.org/grpc v1.66.2
|
google.golang.org/grpc v1.66.2
|
||||||
google.golang.org/protobuf v1.34.2
|
google.golang.org/protobuf v1.34.2
|
||||||
|
@ -187,7 +188,6 @@ require (
|
||||||
github.com/go-openapi/jsonreference v0.20.4 // indirect
|
github.com/go-openapi/jsonreference v0.20.4 // indirect
|
||||||
github.com/go-openapi/loads v0.21.5 // indirect
|
github.com/go-openapi/loads v0.21.5 // indirect
|
||||||
github.com/go-openapi/runtime v0.26.2 // indirect
|
github.com/go-openapi/runtime v0.26.2 // indirect
|
||||||
github.com/go-openapi/spec v0.20.14 // indirect
|
|
||||||
github.com/go-openapi/strfmt v0.22.0 // indirect
|
github.com/go-openapi/strfmt v0.22.0 // indirect
|
||||||
github.com/go-openapi/swag v0.22.7 // indirect
|
github.com/go-openapi/swag v0.22.7 // indirect
|
||||||
github.com/go-openapi/validate v0.22.6 // indirect
|
github.com/go-openapi/validate v0.22.6 // indirect
|
||||||
|
@ -250,7 +250,7 @@ require (
|
||||||
github.com/rhysd/actionlint v1.6.27 // indirect
|
github.com/rhysd/actionlint v1.6.27 // indirect
|
||||||
github.com/rivo/uniseg v0.4.7 // indirect
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
github.com/rogpeppe/go-internal v1.12.0 // indirect
|
github.com/rogpeppe/go-internal v1.12.0 // indirect
|
||||||
github.com/rs/xid v1.5.0 // indirect
|
github.com/rs/xid v1.6.0 // indirect
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||||
|
@ -281,7 +281,7 @@ require (
|
||||||
go.uber.org/zap v1.27.0 // indirect
|
go.uber.org/zap v1.27.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect
|
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect
|
||||||
golang.org/x/mod v0.21.0 // indirect
|
golang.org/x/mod v0.21.0 // indirect
|
||||||
golang.org/x/sync v0.8.0 // indirect
|
golang.org/x/sync v0.10.0 // indirect
|
||||||
golang.org/x/time v0.5.0 // indirect
|
golang.org/x/time v0.5.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 // indirect
|
||||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||||
|
@ -296,3 +296,5 @@ replace github.com/shurcooL/vfsgen => github.com/lunny/vfsgen v0.0.0-20220105142
|
||||||
replace github.com/nektos/act => code.forgejo.org/forgejo/act v1.21.3
|
replace github.com/nektos/act => code.forgejo.org/forgejo/act v1.21.3
|
||||||
|
|
||||||
replace github.com/mholt/archiver/v3 => code.forgejo.org/forgejo/archiver/v3 v3.5.1
|
replace github.com/mholt/archiver/v3 => code.forgejo.org/forgejo/archiver/v3 v3.5.1
|
||||||
|
|
||||||
|
replace github.com/gliderlabs/ssh => code.forgejo.org/forgejo/ssh v0.0.0-20241211213324-5fc306ca0616
|
||||||
|
|
32
go.sum
32
go.sum
|
@ -10,6 +10,8 @@ code.forgejo.org/forgejo/archiver/v3 v3.5.1 h1:UmmbA7D5550uf71SQjarmrn6yKwOGxtEj
|
||||||
code.forgejo.org/forgejo/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4=
|
code.forgejo.org/forgejo/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4=
|
||||||
code.forgejo.org/forgejo/reply v1.0.2 h1:dMhQCHV6/O3L5CLWNTol+dNzDAuyCK88z4J/lCdgFuQ=
|
code.forgejo.org/forgejo/reply v1.0.2 h1:dMhQCHV6/O3L5CLWNTol+dNzDAuyCK88z4J/lCdgFuQ=
|
||||||
code.forgejo.org/forgejo/reply v1.0.2/go.mod h1:RyZUfzQLc+fuLIGjTSQWDAJWPiL4WtKXB/FifT5fM7U=
|
code.forgejo.org/forgejo/reply v1.0.2/go.mod h1:RyZUfzQLc+fuLIGjTSQWDAJWPiL4WtKXB/FifT5fM7U=
|
||||||
|
code.forgejo.org/forgejo/ssh v0.0.0-20241211213324-5fc306ca0616 h1:kEZL84+02jY9RxXM4zHBWZ3Fml0B09cmP1LGkDsCfIA=
|
||||||
|
code.forgejo.org/forgejo/ssh v0.0.0-20241211213324-5fc306ca0616/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8=
|
||||||
code.forgejo.org/go-chi/cache v0.0.0-20240912103640-dcb08fba860d h1:nOu/2GX571t4intmtfvpctS148OqsBYrGUySVm93ifc=
|
code.forgejo.org/go-chi/cache v0.0.0-20240912103640-dcb08fba860d h1:nOu/2GX571t4intmtfvpctS148OqsBYrGUySVm93ifc=
|
||||||
code.forgejo.org/go-chi/cache v0.0.0-20240912103640-dcb08fba860d/go.mod h1:OVlZ/TqDYJ+RUJ+R+J+OLxtlyjo3pbjBeK7LAWAB+Vk=
|
code.forgejo.org/go-chi/cache v0.0.0-20240912103640-dcb08fba860d/go.mod h1:OVlZ/TqDYJ+RUJ+R+J+OLxtlyjo3pbjBeK7LAWAB+Vk=
|
||||||
code.forgejo.org/go-chi/captcha v0.0.0-20240905153133-df43b9250ed5 h1:A7P1liXCpJBHEJ5KIDsF0ujnQ8FQ/aX1UixTW0vGrDQ=
|
code.forgejo.org/go-chi/captcha v0.0.0-20240905153133-df43b9250ed5 h1:A7P1liXCpJBHEJ5KIDsF0ujnQ8FQ/aX1UixTW0vGrDQ=
|
||||||
|
@ -225,8 +227,6 @@ github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nos
|
||||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||||
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
|
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
|
||||||
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
|
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
|
||||||
github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE=
|
|
||||||
github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8=
|
|
||||||
github.com/go-ap/activitypub v0.0.0-20231114162308-e219254dc5c9 h1:j2TrkUG/NATGi/EQS+MvEoF79CxiRUmT16ErFroNcKI=
|
github.com/go-ap/activitypub v0.0.0-20231114162308-e219254dc5c9 h1:j2TrkUG/NATGi/EQS+MvEoF79CxiRUmT16ErFroNcKI=
|
||||||
github.com/go-ap/activitypub v0.0.0-20231114162308-e219254dc5c9/go.mod h1:cJ9Ye0ZNSMN7RzZDBRY3E+8M3Bpf/R1JX22Ir9yX6WI=
|
github.com/go-ap/activitypub v0.0.0-20231114162308-e219254dc5c9/go.mod h1:cJ9Ye0ZNSMN7RzZDBRY3E+8M3Bpf/R1JX22Ir9yX6WI=
|
||||||
github.com/go-ap/errors v0.0.0-20231003111023-183eef4b31b7 h1:I2nuhyVI/48VXoRCCZR2hYBgnSXa+EuDJf/VyX06TC0=
|
github.com/go-ap/errors v0.0.0-20231003111023-183eef4b31b7 h1:I2nuhyVI/48VXoRCCZR2hYBgnSXa+EuDJf/VyX06TC0=
|
||||||
|
@ -502,8 +502,8 @@ github.com/miekg/dns v1.1.59 h1:C9EXc/UToRwKLhK5wKU/I4QVsBUc8kE6MkHBkeypWZs=
|
||||||
github.com/miekg/dns v1.1.59/go.mod h1:nZpewl5p6IvctfgrckopVx2OlSEHPRO/U4SYkRklrEk=
|
github.com/miekg/dns v1.1.59/go.mod h1:nZpewl5p6IvctfgrckopVx2OlSEHPRO/U4SYkRklrEk=
|
||||||
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
|
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
|
||||||
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
|
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
|
||||||
github.com/minio/minio-go/v7 v7.0.74 h1:fTo/XlPBTSpo3BAMshlwKL5RspXRv9us5UeHEGYCFe0=
|
github.com/minio/minio-go/v7 v7.0.77 h1:GaGghJRg9nwDVlNbwYjSDJT1rqltQkBFDsypWX1v3Bw=
|
||||||
github.com/minio/minio-go/v7 v7.0.74/go.mod h1:qydcVzV8Hqtj1VtEocfxbmVFa2siu6HGa+LDEPogjD8=
|
github.com/minio/minio-go/v7 v7.0.77/go.mod h1:AVM3IUN6WwKzmwBxVdjzhH8xq+f57JSbbvzqvUzR6eg=
|
||||||
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
|
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
|
||||||
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
|
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
|
||||||
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
|
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
|
||||||
|
@ -599,8 +599,8 @@ github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4
|
||||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||||
github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=
|
github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
|
||||||
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
|
github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
|
||||||
|
@ -734,8 +734,8 @@ golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2Uz
|
||||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||||
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
|
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
||||||
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
|
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||||
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA=
|
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA=
|
||||||
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
|
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
|
||||||
golang.org/x/image v0.20.0 h1:7cVCUjQwfL18gyBJOmYvptfSHS8Fb3YUDtfLIZ7Nbpw=
|
golang.org/x/image v0.20.0 h1:7cVCUjQwfL18gyBJOmYvptfSHS8Fb3YUDtfLIZ7Nbpw=
|
||||||
|
@ -772,8 +772,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
|
||||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
@ -803,8 +803,8 @@ golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
|
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||||
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||||
|
@ -814,8 +814,8 @@ golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
||||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
||||||
golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM=
|
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
|
||||||
golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8=
|
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
@ -827,8 +827,8 @@ golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
|
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||||
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
|
|
@ -69,7 +69,7 @@ func CreateArtifact(ctx context.Context, t *ActionTask, artifactName, artifactPa
|
||||||
OwnerID: t.OwnerID,
|
OwnerID: t.OwnerID,
|
||||||
CommitSHA: t.CommitSHA,
|
CommitSHA: t.CommitSHA,
|
||||||
Status: int64(ArtifactStatusUploadPending),
|
Status: int64(ArtifactStatusUploadPending),
|
||||||
ExpiredUnix: timeutil.TimeStamp(time.Now().Unix() + 3600*24*expiredDays),
|
ExpiredUnix: timeutil.TimeStamp(time.Now().Unix() + timeutil.Day*expiredDays),
|
||||||
}
|
}
|
||||||
if _, err := db.GetEngine(ctx).Insert(artifact); err != nil {
|
if _, err := db.GetEngine(ctx).Insert(artifact); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -78,6 +78,13 @@ func CreateArtifact(ctx context.Context, t *ActionTask, artifactName, artifactPa
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if _, err := db.GetEngine(ctx).ID(artifact.ID).Cols("expired_unix").Update(&ActionArtifact{
|
||||||
|
ExpiredUnix: timeutil.TimeStamp(time.Now().Unix() + timeutil.Day*expiredDays),
|
||||||
|
}); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return artifact, nil
|
return artifact, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -146,7 +146,11 @@ func (run *ActionRun) GetPushEventPayload() (*api.PushPayload, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (run *ActionRun) GetPullRequestEventPayload() (*api.PullRequestPayload, error) {
|
func (run *ActionRun) GetPullRequestEventPayload() (*api.PullRequestPayload, error) {
|
||||||
if run.Event == webhook_module.HookEventPullRequest || run.Event == webhook_module.HookEventPullRequestSync {
|
if run.Event == webhook_module.HookEventPullRequest ||
|
||||||
|
run.Event == webhook_module.HookEventPullRequestSync ||
|
||||||
|
run.Event == webhook_module.HookEventPullRequestAssign ||
|
||||||
|
run.Event == webhook_module.HookEventPullRequestMilestone ||
|
||||||
|
run.Event == webhook_module.HookEventPullRequestLabel {
|
||||||
var payload api.PullRequestPayload
|
var payload api.PullRequestPayload
|
||||||
if err := json.Unmarshal([]byte(run.EventPayload), &payload); err != nil {
|
if err := json.Unmarshal([]byte(run.EventPayload), &payload); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -118,21 +118,23 @@ func DeleteScheduleTaskByRepo(ctx context.Context, id int64) error {
|
||||||
return committer.Commit()
|
return committer.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
func CleanRepoScheduleTasks(ctx context.Context, repo *repo_model.Repository) error {
|
func CleanRepoScheduleTasks(ctx context.Context, repo *repo_model.Repository, cancelPreviousJobs bool) error {
|
||||||
// If actions disabled when there is schedule task, this will remove the outdated schedule tasks
|
// If actions disabled when there is schedule task, this will remove the outdated schedule tasks
|
||||||
// There is no other place we can do this because the app.ini will be changed manually
|
// There is no other place we can do this because the app.ini will be changed manually
|
||||||
if err := DeleteScheduleTaskByRepo(ctx, repo.ID); err != nil {
|
if err := DeleteScheduleTaskByRepo(ctx, repo.ID); err != nil {
|
||||||
return fmt.Errorf("DeleteCronTaskByRepo: %v", err)
|
return fmt.Errorf("DeleteCronTaskByRepo: %v", err)
|
||||||
}
|
}
|
||||||
// cancel running cron jobs of this repository and delete old schedules
|
if cancelPreviousJobs {
|
||||||
if err := CancelPreviousJobs(
|
// cancel running cron jobs of this repository and delete old schedules
|
||||||
ctx,
|
if err := CancelPreviousJobs(
|
||||||
repo.ID,
|
ctx,
|
||||||
repo.DefaultBranch,
|
repo.ID,
|
||||||
"",
|
repo.DefaultBranch,
|
||||||
webhook_module.HookEventSchedule,
|
"",
|
||||||
); err != nil {
|
webhook_module.HookEventSchedule,
|
||||||
return fmt.Errorf("CancelPreviousJobs: %v", err)
|
); err != nil {
|
||||||
|
return fmt.Errorf("CancelPreviousJobs: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -250,6 +250,9 @@ func (a *Action) GetActDisplayNameTitle(ctx context.Context) string {
|
||||||
// GetRepoUserName returns the name of the action repository owner.
|
// GetRepoUserName returns the name of the action repository owner.
|
||||||
func (a *Action) GetRepoUserName(ctx context.Context) string {
|
func (a *Action) GetRepoUserName(ctx context.Context) string {
|
||||||
a.loadRepo(ctx)
|
a.loadRepo(ctx)
|
||||||
|
if a.Repo == nil {
|
||||||
|
return "(non-existing-repo)"
|
||||||
|
}
|
||||||
return a.Repo.OwnerName
|
return a.Repo.OwnerName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,6 +265,9 @@ func (a *Action) ShortRepoUserName(ctx context.Context) string {
|
||||||
// GetRepoName returns the name of the action repository.
|
// GetRepoName returns the name of the action repository.
|
||||||
func (a *Action) GetRepoName(ctx context.Context) string {
|
func (a *Action) GetRepoName(ctx context.Context) string {
|
||||||
a.loadRepo(ctx)
|
a.loadRepo(ctx)
|
||||||
|
if a.Repo == nil {
|
||||||
|
return "(non-existing-repo)"
|
||||||
|
}
|
||||||
return a.Repo.Name
|
return a.Repo.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ type ActivityStats struct {
|
||||||
OpenedPRAuthorCount int64
|
OpenedPRAuthorCount int64
|
||||||
MergedPRs issues_model.PullRequestList
|
MergedPRs issues_model.PullRequestList
|
||||||
MergedPRAuthorCount int64
|
MergedPRAuthorCount int64
|
||||||
|
ActiveIssues issues_model.IssueList
|
||||||
OpenedIssues issues_model.IssueList
|
OpenedIssues issues_model.IssueList
|
||||||
OpenedIssueAuthorCount int64
|
OpenedIssueAuthorCount int64
|
||||||
ClosedIssues issues_model.IssueList
|
ClosedIssues issues_model.IssueList
|
||||||
|
@ -172,7 +173,7 @@ func (stats *ActivityStats) MergedPRPerc() int {
|
||||||
|
|
||||||
// ActiveIssueCount returns total active issue count
|
// ActiveIssueCount returns total active issue count
|
||||||
func (stats *ActivityStats) ActiveIssueCount() int {
|
func (stats *ActivityStats) ActiveIssueCount() int {
|
||||||
return stats.OpenedIssueCount() + stats.ClosedIssueCount()
|
return len(stats.ActiveIssues)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenedIssueCount returns open issue count
|
// OpenedIssueCount returns open issue count
|
||||||
|
@ -285,13 +286,21 @@ func (stats *ActivityStats) FillIssues(ctx context.Context, repoID int64, fromTi
|
||||||
stats.ClosedIssueAuthorCount = count
|
stats.ClosedIssueAuthorCount = count
|
||||||
|
|
||||||
// New issues
|
// New issues
|
||||||
sess = issuesForActivityStatement(ctx, repoID, fromTime, false, false)
|
sess = newlyCreatedIssues(ctx, repoID, fromTime)
|
||||||
sess.OrderBy("issue.created_unix ASC")
|
sess.OrderBy("issue.created_unix ASC")
|
||||||
stats.OpenedIssues = make(issues_model.IssueList, 0)
|
stats.OpenedIssues = make(issues_model.IssueList, 0)
|
||||||
if err = sess.Find(&stats.OpenedIssues); err != nil {
|
if err = sess.Find(&stats.OpenedIssues); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Active issues
|
||||||
|
sess = activeIssues(ctx, repoID, fromTime)
|
||||||
|
sess.OrderBy("issue.created_unix ASC")
|
||||||
|
stats.ActiveIssues = make(issues_model.IssueList, 0)
|
||||||
|
if err = sess.Find(&stats.ActiveIssues); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Opened issue authors
|
// Opened issue authors
|
||||||
sess = issuesForActivityStatement(ctx, repoID, fromTime, false, false)
|
sess = issuesForActivityStatement(ctx, repoID, fromTime, false, false)
|
||||||
if _, err = sess.Select("count(distinct issue.poster_id) as `count`").Table("issue").Get(&count); err != nil {
|
if _, err = sess.Select("count(distinct issue.poster_id) as `count`").Table("issue").Get(&count); err != nil {
|
||||||
|
@ -317,6 +326,22 @@ func (stats *ActivityStats) FillUnresolvedIssues(ctx context.Context, repoID int
|
||||||
return sess.Find(&stats.UnresolvedIssues)
|
return sess.Find(&stats.UnresolvedIssues)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newlyCreatedIssues(ctx context.Context, repoID int64, fromTime time.Time) *xorm.Session {
|
||||||
|
sess := db.GetEngine(ctx).Where("issue.repo_id = ?", repoID).
|
||||||
|
And("issue.is_pull = ?", false). // Retain the is_pull check to exclude pull requests
|
||||||
|
And("issue.created_unix >= ?", fromTime.Unix()) // Include all issues created after fromTime
|
||||||
|
|
||||||
|
return sess
|
||||||
|
}
|
||||||
|
|
||||||
|
func activeIssues(ctx context.Context, repoID int64, fromTime time.Time) *xorm.Session {
|
||||||
|
sess := db.GetEngine(ctx).Where("issue.repo_id = ?", repoID).
|
||||||
|
And("issue.is_pull = ?", false).
|
||||||
|
And("issue.created_unix >= ? OR issue.closed_unix >= ?", fromTime.Unix(), fromTime.Unix())
|
||||||
|
|
||||||
|
return sess
|
||||||
|
}
|
||||||
|
|
||||||
func issuesForActivityStatement(ctx context.Context, repoID int64, fromTime time.Time, closed, unresolved bool) *xorm.Session {
|
func issuesForActivityStatement(ctx context.Context, repoID int64, fromTime time.Time, closed, unresolved bool) *xorm.Session {
|
||||||
sess := db.GetEngine(ctx).Where("issue.repo_id = ?", repoID).
|
sess := db.GetEngine(ctx).Where("issue.repo_id = ?", repoID).
|
||||||
And("issue.is_closed = ?", closed)
|
And("issue.is_closed = ?", closed)
|
||||||
|
|
30
models/activities/repo_activity_test.go
Normal file
30
models/activities/repo_activity_test.go
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package activities
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetActivityStats(t *testing.T) {
|
||||||
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||||
|
|
||||||
|
stats, err := GetActivityStats(db.DefaultContext, repo, time.Unix(0, 0), true, true, true, true)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
assert.EqualValues(t, 2, stats.ActiveIssueCount())
|
||||||
|
assert.EqualValues(t, 2, stats.OpenedIssueCount())
|
||||||
|
assert.EqualValues(t, 0, stats.ClosedIssueCount())
|
||||||
|
assert.EqualValues(t, 3, stats.ActivePRCount())
|
||||||
|
}
|
|
@ -23,3 +23,11 @@
|
||||||
redirect_uris: '["http://127.0.0.1", "https://127.0.0.1"]'
|
redirect_uris: '["http://127.0.0.1", "https://127.0.0.1"]'
|
||||||
created_unix: 1712358091
|
created_unix: 1712358091
|
||||||
updated_unix: 1712358091
|
updated_unix: 1712358091
|
||||||
|
-
|
||||||
|
id: 1003
|
||||||
|
uid: 0
|
||||||
|
name: "Global Auth source that should be kept"
|
||||||
|
client_id: "2f3467c1-7b3b-463d-ab04-2ae2b2712826"
|
||||||
|
redirect_uris: '["http://example.com/globalapp", "https://example.com/globalapp"]'
|
||||||
|
created_unix: 1732387292
|
||||||
|
updated_unix: 1732387292
|
||||||
|
|
|
@ -15,12 +15,31 @@ import (
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type AuthorizationPurpose string
|
||||||
|
|
||||||
|
var (
|
||||||
|
// Used to store long term authorization tokens.
|
||||||
|
LongTermAuthorization AuthorizationPurpose = "long_term_authorization"
|
||||||
|
|
||||||
|
// Used to activate a user account.
|
||||||
|
UserActivation AuthorizationPurpose = "user_activation"
|
||||||
|
|
||||||
|
// Used to reset the password.
|
||||||
|
PasswordReset AuthorizationPurpose = "password_reset"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Used to activate the specified email address for a user.
|
||||||
|
func EmailActivation(email string) AuthorizationPurpose {
|
||||||
|
return AuthorizationPurpose("email_activation:" + email)
|
||||||
|
}
|
||||||
|
|
||||||
// AuthorizationToken represents a authorization token to a user.
|
// AuthorizationToken represents a authorization token to a user.
|
||||||
type AuthorizationToken struct {
|
type AuthorizationToken struct {
|
||||||
ID int64 `xorm:"pk autoincr"`
|
ID int64 `xorm:"pk autoincr"`
|
||||||
UID int64 `xorm:"INDEX"`
|
UID int64 `xorm:"INDEX"`
|
||||||
LookupKey string `xorm:"INDEX UNIQUE"`
|
LookupKey string `xorm:"INDEX UNIQUE"`
|
||||||
HashedValidator string
|
HashedValidator string
|
||||||
|
Purpose AuthorizationPurpose `xorm:"NOT NULL DEFAULT 'long_term_authorization'"`
|
||||||
Expiry timeutil.TimeStamp
|
Expiry timeutil.TimeStamp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +60,7 @@ func (authToken *AuthorizationToken) IsExpired() bool {
|
||||||
// GenerateAuthToken generates a new authentication token for the given user.
|
// GenerateAuthToken generates a new authentication token for the given user.
|
||||||
// It returns the lookup key and validator values that should be passed to the
|
// It returns the lookup key and validator values that should be passed to the
|
||||||
// user via a long-term cookie.
|
// user via a long-term cookie.
|
||||||
func GenerateAuthToken(ctx context.Context, userID int64, expiry timeutil.TimeStamp) (lookupKey, validator string, err error) {
|
func GenerateAuthToken(ctx context.Context, userID int64, expiry timeutil.TimeStamp, purpose AuthorizationPurpose) (lookupKey, validator string, err error) {
|
||||||
// Request 64 random bytes. The first 32 bytes will be used for the lookupKey
|
// Request 64 random bytes. The first 32 bytes will be used for the lookupKey
|
||||||
// and the other 32 bytes will be used for the validator.
|
// and the other 32 bytes will be used for the validator.
|
||||||
rBytes, err := util.CryptoRandomBytes(64)
|
rBytes, err := util.CryptoRandomBytes(64)
|
||||||
|
@ -56,14 +75,15 @@ func GenerateAuthToken(ctx context.Context, userID int64, expiry timeutil.TimeSt
|
||||||
Expiry: expiry,
|
Expiry: expiry,
|
||||||
LookupKey: lookupKey,
|
LookupKey: lookupKey,
|
||||||
HashedValidator: HashValidator(rBytes[32:]),
|
HashedValidator: HashValidator(rBytes[32:]),
|
||||||
|
Purpose: purpose,
|
||||||
})
|
})
|
||||||
return lookupKey, validator, err
|
return lookupKey, validator, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindAuthToken will find a authorization token via the lookup key.
|
// FindAuthToken will find a authorization token via the lookup key.
|
||||||
func FindAuthToken(ctx context.Context, lookupKey string) (*AuthorizationToken, error) {
|
func FindAuthToken(ctx context.Context, lookupKey string, purpose AuthorizationPurpose) (*AuthorizationToken, error) {
|
||||||
var authToken AuthorizationToken
|
var authToken AuthorizationToken
|
||||||
has, err := db.GetEngine(ctx).Where("lookup_key = ?", lookupKey).Get(&authToken)
|
has, err := db.GetEngine(ctx).Where("lookup_key = ? AND purpose = ?", lookupKey, purpose).Get(&authToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if !has {
|
} else if !has {
|
||||||
|
|
|
@ -657,6 +657,7 @@ func CountOrphanedOAuth2Applications(ctx context.Context) (int64, error) {
|
||||||
Table("`oauth2_application`").
|
Table("`oauth2_application`").
|
||||||
Join("LEFT", "`user`", "`oauth2_application`.`uid` = `user`.`id`").
|
Join("LEFT", "`user`", "`oauth2_application`.`uid` = `user`.`id`").
|
||||||
Where(builder.IsNull{"`user`.id"}).
|
Where(builder.IsNull{"`user`.id"}).
|
||||||
|
Where(builder.Neq{"uid": 0}). // exclude instance-wide admin applications
|
||||||
Where(builder.NotIn("`oauth2_application`.`client_id`", BuiltinApplicationsClientIDs())).
|
Where(builder.NotIn("`oauth2_application`.`client_id`", BuiltinApplicationsClientIDs())).
|
||||||
Select("COUNT(`oauth2_application`.`id`)").
|
Select("COUNT(`oauth2_application`.`id`)").
|
||||||
Count()
|
Count()
|
||||||
|
@ -668,6 +669,7 @@ func DeleteOrphanedOAuth2Applications(ctx context.Context) (int64, error) {
|
||||||
From("`oauth2_application`").
|
From("`oauth2_application`").
|
||||||
Join("LEFT", "`user`", "`oauth2_application`.`uid` = `user`.`id`").
|
Join("LEFT", "`user`", "`oauth2_application`.`uid` = `user`.`id`").
|
||||||
Where(builder.IsNull{"`user`.id"}).
|
Where(builder.IsNull{"`user`.id"}).
|
||||||
|
Where(builder.Neq{"uid": 0}). // exclude instance-wide admin applications
|
||||||
Where(builder.NotIn("`oauth2_application`.`client_id`", BuiltinApplicationsClientIDs()))
|
Where(builder.NotIn("`oauth2_application`.`client_id`", BuiltinApplicationsClientIDs()))
|
||||||
|
|
||||||
b := builder.Delete(builder.In("id", subQuery)).From("`oauth2_application`")
|
b := builder.Delete(builder.In("id", subQuery)).From("`oauth2_application`")
|
||||||
|
|
|
@ -296,4 +296,5 @@ func TestOrphanedOAuth2Applications(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.EqualValues(t, 0, count)
|
assert.EqualValues(t, 0, count)
|
||||||
unittest.AssertExistsIf(t, false, &auth_model.OAuth2Application{ID: 1002})
|
unittest.AssertExistsIf(t, false, &auth_model.OAuth2Application{ID: 1002})
|
||||||
|
unittest.AssertExistsIf(t, true, &auth_model.OAuth2Application{ID: 1003})
|
||||||
}
|
}
|
||||||
|
|
|
@ -216,7 +216,7 @@ func CreateSource(ctx context.Context, source *Source) error {
|
||||||
return ErrSourceAlreadyExist{source.Name}
|
return ErrSourceAlreadyExist{source.Name}
|
||||||
}
|
}
|
||||||
// Synchronization is only available with LDAP for now
|
// Synchronization is only available with LDAP for now
|
||||||
if !source.IsLDAP() && !source.IsOAuth2() {
|
if !source.IsLDAP() {
|
||||||
source.IsSyncEnabled = false
|
source.IsSyncEnabled = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,22 @@
|
||||||
|
-
|
||||||
|
id: 46
|
||||||
|
attempt: 3
|
||||||
|
runner_id: 1
|
||||||
|
status: 3 # 3 is the status code for "cancelled"
|
||||||
|
started: 1683636528
|
||||||
|
stopped: 1683636626
|
||||||
|
repo_id: 4
|
||||||
|
owner_id: 1
|
||||||
|
commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0
|
||||||
|
is_fork_pull_request: 0
|
||||||
|
token_hash: 6d8ef48297195edcc8e22c70b3020eaa06c52976db67d39b4260c64a69a2cc1508825121b7b8394e48e00b1bf8718b2aaaaa
|
||||||
|
token_salt: eeeeeeee
|
||||||
|
token_last_eight: eeeeeeee
|
||||||
|
log_filename: artifact-test2/2f/47.log
|
||||||
|
log_in_storage: 1
|
||||||
|
log_length: 707
|
||||||
|
log_size: 90179
|
||||||
|
log_expired: 0
|
||||||
-
|
-
|
||||||
id: 47
|
id: 47
|
||||||
job_id: 192
|
job_id: 192
|
||||||
|
|
|
@ -94,3 +94,22 @@
|
||||||
content: "test markup light/dark-mode-only "
|
content: "test markup light/dark-mode-only "
|
||||||
created_unix: 946684813
|
created_unix: 946684813
|
||||||
updated_unix: 946684813
|
updated_unix: 946684813
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 11
|
||||||
|
type: 22 # review
|
||||||
|
poster_id: 5
|
||||||
|
issue_id: 3 # in repo_id 1
|
||||||
|
content: "reviewed by user5"
|
||||||
|
review_id: 21
|
||||||
|
created_unix: 946684816
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 12
|
||||||
|
type: 27 # review request
|
||||||
|
poster_id: 2
|
||||||
|
issue_id: 3 # in repo_id 1
|
||||||
|
content: "review request for user5"
|
||||||
|
review_id: 22
|
||||||
|
assignee_id: 5
|
||||||
|
created_unix: 946684817
|
||||||
|
|
|
@ -91,6 +91,8 @@
|
||||||
size: 0
|
size: 0
|
||||||
is_fsck_enabled: true
|
is_fsck_enabled: true
|
||||||
close_issues_via_commit_in_any_branch: false
|
close_issues_via_commit_in_any_branch: false
|
||||||
|
created_unix: 1700000001
|
||||||
|
updated_unix: 1700000001
|
||||||
|
|
||||||
-
|
-
|
||||||
id: 4
|
id: 4
|
||||||
|
@ -152,6 +154,8 @@
|
||||||
size: 0
|
size: 0
|
||||||
is_fsck_enabled: true
|
is_fsck_enabled: true
|
||||||
close_issues_via_commit_in_any_branch: false
|
close_issues_via_commit_in_any_branch: false
|
||||||
|
created_unix: 1700000002
|
||||||
|
updated_unix: 1700000002
|
||||||
|
|
||||||
-
|
-
|
||||||
id: 6
|
id: 6
|
||||||
|
@ -182,6 +186,8 @@
|
||||||
size: 0
|
size: 0
|
||||||
is_fsck_enabled: true
|
is_fsck_enabled: true
|
||||||
close_issues_via_commit_in_any_branch: false
|
close_issues_via_commit_in_any_branch: false
|
||||||
|
created_unix: 1710000001
|
||||||
|
updated_unix: 1710000001
|
||||||
|
|
||||||
-
|
-
|
||||||
id: 7
|
id: 7
|
||||||
|
@ -212,6 +218,8 @@
|
||||||
size: 0
|
size: 0
|
||||||
is_fsck_enabled: true
|
is_fsck_enabled: true
|
||||||
close_issues_via_commit_in_any_branch: false
|
close_issues_via_commit_in_any_branch: false
|
||||||
|
created_unix: 1710000003
|
||||||
|
updated_unix: 1710000003
|
||||||
|
|
||||||
-
|
-
|
||||||
id: 8
|
id: 8
|
||||||
|
@ -242,6 +250,8 @@
|
||||||
size: 0
|
size: 0
|
||||||
is_fsck_enabled: true
|
is_fsck_enabled: true
|
||||||
close_issues_via_commit_in_any_branch: false
|
close_issues_via_commit_in_any_branch: false
|
||||||
|
created_unix: 1710000002
|
||||||
|
updated_unix: 1710000002
|
||||||
|
|
||||||
-
|
-
|
||||||
id: 9
|
id: 9
|
||||||
|
@ -968,6 +978,8 @@
|
||||||
size: 0
|
size: 0
|
||||||
is_fsck_enabled: true
|
is_fsck_enabled: true
|
||||||
close_issues_via_commit_in_any_branch: false
|
close_issues_via_commit_in_any_branch: false
|
||||||
|
created_unix: 1700000003
|
||||||
|
updated_unix: 1700000003
|
||||||
|
|
||||||
-
|
-
|
||||||
id: 33
|
id: 33
|
||||||
|
@ -1811,4 +1823,4 @@
|
||||||
template_id: 0
|
template_id: 0
|
||||||
size: 0
|
size: 0
|
||||||
is_fsck_enabled: true
|
is_fsck_enabled: true
|
||||||
close_issues_via_commit_in_any_branch: false
|
close_issues_via_commit_in_any_branch: false
|
||||||
|
|
|
@ -179,3 +179,22 @@
|
||||||
content: "Review Comment"
|
content: "Review Comment"
|
||||||
updated_unix: 946684810
|
updated_unix: 946684810
|
||||||
created_unix: 946684810
|
created_unix: 946684810
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 21
|
||||||
|
type: 2
|
||||||
|
reviewer_id: 5
|
||||||
|
issue_id: 3
|
||||||
|
content: "reviewed by user5"
|
||||||
|
commit_id: 4a357436d925b5c974181ff12a994538ddc5a269
|
||||||
|
updated_unix: 946684816
|
||||||
|
created_unix: 946684816
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 22
|
||||||
|
type: 4
|
||||||
|
reviewer_id: 5
|
||||||
|
issue_id: 3
|
||||||
|
content: "review request for user5"
|
||||||
|
updated_unix: 946684817
|
||||||
|
created_unix: 946684817
|
||||||
|
|
|
@ -332,6 +332,7 @@
|
||||||
repo_admin_change_team_access: false
|
repo_admin_change_team_access: false
|
||||||
theme: ""
|
theme: ""
|
||||||
keep_activity_private: false
|
keep_activity_private: false
|
||||||
|
created_unix: 1730468968
|
||||||
|
|
||||||
-
|
-
|
||||||
id: 10
|
id: 10
|
||||||
|
|
11
models/issues/TestGetUIDsAndStopwatch/stopwatch.yml
Normal file
11
models/issues/TestGetUIDsAndStopwatch/stopwatch.yml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
-
|
||||||
|
id: 3
|
||||||
|
user_id: 1
|
||||||
|
issue_id: 2
|
||||||
|
created_unix: 1500988004
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 4
|
||||||
|
user_id: 3
|
||||||
|
issue_id: 0
|
||||||
|
created_unix: 1500988003
|
|
@ -111,9 +111,7 @@ func NewIssueLabel(ctx context.Context, issue *Issue, label *Label, doer *user_m
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
issue.isLabelsLoaded = false
|
if err = issue.ReloadLabels(ctx); err != nil {
|
||||||
issue.Labels = nil
|
|
||||||
if err = issue.LoadLabels(ctx); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,10 +159,7 @@ func NewIssueLabels(ctx context.Context, issue *Issue, labels []*Label, doer *us
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// reload all labels
|
if err = issue.ReloadLabels(ctx); err != nil {
|
||||||
issue.isLabelsLoaded = false
|
|
||||||
issue.Labels = nil
|
|
||||||
if err = issue.LoadLabels(ctx); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,8 +200,7 @@ func DeleteIssueLabel(ctx context.Context, issue *Issue, label *Label, doer *use
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
issue.Labels = nil
|
return issue.ReloadLabels(ctx)
|
||||||
return issue.LoadLabels(ctx)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteLabelsByRepoID deletes labels of some repository
|
// DeleteLabelsByRepoID deletes labels of some repository
|
||||||
|
@ -326,14 +320,23 @@ func FixIssueLabelWithOutsideLabels(ctx context.Context) (int64, error) {
|
||||||
return res.RowsAffected()
|
return res.RowsAffected()
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadLabels loads labels
|
// LoadLabels only if they are not already set
|
||||||
func (issue *Issue) LoadLabels(ctx context.Context) (err error) {
|
func (issue *Issue) LoadLabels(ctx context.Context) (err error) {
|
||||||
if !issue.isLabelsLoaded && issue.Labels == nil && issue.ID != 0 {
|
if !issue.isLabelsLoaded && issue.Labels == nil {
|
||||||
|
if err := issue.ReloadLabels(ctx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
issue.isLabelsLoaded = true
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (issue *Issue) ReloadLabels(ctx context.Context) (err error) {
|
||||||
|
if issue.ID != 0 {
|
||||||
issue.Labels, err = GetLabelsByIssueID(ctx, issue.ID)
|
issue.Labels, err = GetLabelsByIssueID(ctx, issue.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("getLabelsByIssueID [%d]: %w", issue.ID, err)
|
return fmt.Errorf("getLabelsByIssueID [%d]: %w", issue.ID, err)
|
||||||
}
|
}
|
||||||
issue.isLabelsLoaded = true
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -496,8 +499,7 @@ func ReplaceIssueLabels(ctx context.Context, issue *Issue, labels []*Label, doer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
issue.Labels = nil
|
if err = issue.ReloadLabels(ctx); err != nil {
|
||||||
if err = issue.LoadLabels(ctx); err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,114 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestIssueNewIssueLabels(t *testing.T) {
|
||||||
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2})
|
||||||
|
label1 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 1})
|
||||||
|
label2 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 4})
|
||||||
|
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
|
|
||||||
|
label3 := &issues_model.Label{RepoID: 1, Name: "label3", Color: "#123"}
|
||||||
|
require.NoError(t, issues_model.NewLabel(db.DefaultContext, label3))
|
||||||
|
|
||||||
|
// label1 is already set, do nothing
|
||||||
|
// label3 is new, add it
|
||||||
|
require.NoError(t, issues_model.NewIssueLabels(db.DefaultContext, issue, []*issues_model.Label{label1, label3}, doer))
|
||||||
|
|
||||||
|
assert.Len(t, issue.Labels, 3)
|
||||||
|
// check that the pre-existing label1 is still present
|
||||||
|
assert.Equal(t, label1.ID, issue.Labels[0].ID)
|
||||||
|
// check that new label3 was added
|
||||||
|
assert.Equal(t, label3.ID, issue.Labels[1].ID)
|
||||||
|
// check that pre-existing label2 was not removed
|
||||||
|
assert.Equal(t, label2.ID, issue.Labels[2].ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIssueNewIssueLabel(t *testing.T) {
|
||||||
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 3})
|
||||||
|
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
|
|
||||||
|
label := &issues_model.Label{RepoID: 1, Name: "label3", Color: "#123"}
|
||||||
|
require.NoError(t, issues_model.NewLabel(db.DefaultContext, label))
|
||||||
|
|
||||||
|
require.NoError(t, issues_model.NewIssueLabel(db.DefaultContext, issue, label, doer))
|
||||||
|
|
||||||
|
assert.Len(t, issue.Labels, 1)
|
||||||
|
assert.Equal(t, label.ID, issue.Labels[0].ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIssueReplaceIssueLabels(t *testing.T) {
|
||||||
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2})
|
||||||
|
label1 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 1})
|
||||||
|
label2 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 4})
|
||||||
|
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
|
|
||||||
|
label3 := &issues_model.Label{RepoID: 1, Name: "label3", Color: "#123"}
|
||||||
|
require.NoError(t, issues_model.NewLabel(db.DefaultContext, label3))
|
||||||
|
|
||||||
|
issue.LoadLabels(db.DefaultContext)
|
||||||
|
assert.Len(t, issue.Labels, 2)
|
||||||
|
assert.Equal(t, label1.ID, issue.Labels[0].ID)
|
||||||
|
assert.Equal(t, label2.ID, issue.Labels[1].ID)
|
||||||
|
|
||||||
|
// label1 is already set, do nothing
|
||||||
|
// label3 is new, add it
|
||||||
|
// label2 is not in the list but already set, remove it
|
||||||
|
require.NoError(t, issues_model.ReplaceIssueLabels(db.DefaultContext, issue, []*issues_model.Label{label1, label3}, doer))
|
||||||
|
|
||||||
|
assert.Len(t, issue.Labels, 2)
|
||||||
|
assert.Equal(t, label1.ID, issue.Labels[0].ID)
|
||||||
|
assert.Equal(t, label3.ID, issue.Labels[1].ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIssueDeleteIssueLabel(t *testing.T) {
|
||||||
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2})
|
||||||
|
label1 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 1})
|
||||||
|
label2 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 4})
|
||||||
|
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
|
|
||||||
|
issue.LoadLabels(db.DefaultContext)
|
||||||
|
assert.Len(t, issue.Labels, 2)
|
||||||
|
assert.Equal(t, label1.ID, issue.Labels[0].ID)
|
||||||
|
assert.Equal(t, label2.ID, issue.Labels[1].ID)
|
||||||
|
|
||||||
|
require.NoError(t, issues_model.DeleteIssueLabel(db.DefaultContext, issue, label2, doer))
|
||||||
|
|
||||||
|
assert.Len(t, issue.Labels, 1)
|
||||||
|
assert.Equal(t, label1.ID, issue.Labels[0].ID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIssueLoadLabels(t *testing.T) {
|
||||||
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2})
|
||||||
|
label1 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 1})
|
||||||
|
label2 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 4})
|
||||||
|
|
||||||
|
assert.Empty(t, issue.Labels)
|
||||||
|
issue.LoadLabels(db.DefaultContext)
|
||||||
|
assert.Len(t, issue.Labels, 2)
|
||||||
|
assert.Equal(t, label1.ID, issue.Labels[0].ID)
|
||||||
|
assert.Equal(t, label2.ID, issue.Labels[1].ID)
|
||||||
|
|
||||||
|
unittest.AssertSuccessfulDelete(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: label2.ID})
|
||||||
|
|
||||||
|
// the database change is not noticed because the labels are cached
|
||||||
|
issue.LoadLabels(db.DefaultContext)
|
||||||
|
assert.Len(t, issue.Labels, 2)
|
||||||
|
|
||||||
|
issue.ReloadLabels(db.DefaultContext)
|
||||||
|
assert.Len(t, issue.Labels, 1)
|
||||||
|
assert.Equal(t, label1.ID, issue.Labels[0].ID)
|
||||||
|
}
|
||||||
|
|
||||||
func TestNewIssueLabelsScope(t *testing.T) {
|
func TestNewIssueLabelsScope(t *testing.T) {
|
||||||
require.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
|
|
@ -408,7 +408,7 @@ func (pr *PullRequest) getReviewedByLines(ctx context.Context, writer io.Writer)
|
||||||
|
|
||||||
// Note: This doesn't page as we only expect a very limited number of reviews
|
// Note: This doesn't page as we only expect a very limited number of reviews
|
||||||
reviews, err := FindLatestReviews(ctx, FindReviewOptions{
|
reviews, err := FindLatestReviews(ctx, FindReviewOptions{
|
||||||
Type: ReviewTypeApprove,
|
Types: []ReviewType{ReviewTypeApprove},
|
||||||
IssueID: pr.IssueID,
|
IssueID: pr.IssueID,
|
||||||
OfficialOnly: setting.Repository.PullRequest.DefaultMergeMessageOfficialApproversOnly,
|
OfficialOnly: setting.Repository.PullRequest.DefaultMergeMessageOfficialApproversOnly,
|
||||||
})
|
})
|
||||||
|
|
|
@ -364,7 +364,7 @@ func GetCurrentReview(ctx context.Context, reviewer *user_model.User, issue *Iss
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
reviews, err := FindReviews(ctx, FindReviewOptions{
|
reviews, err := FindReviews(ctx, FindReviewOptions{
|
||||||
Type: ReviewTypePending,
|
Types: []ReviewType{ReviewTypePending},
|
||||||
IssueID: issue.ID,
|
IssueID: issue.ID,
|
||||||
ReviewerID: reviewer.ID,
|
ReviewerID: reviewer.ID,
|
||||||
})
|
})
|
||||||
|
|
|
@ -92,7 +92,7 @@ func (reviews ReviewList) LoadIssues(ctx context.Context) error {
|
||||||
// FindReviewOptions represent possible filters to find reviews
|
// FindReviewOptions represent possible filters to find reviews
|
||||||
type FindReviewOptions struct {
|
type FindReviewOptions struct {
|
||||||
db.ListOptions
|
db.ListOptions
|
||||||
Type ReviewType
|
Types []ReviewType
|
||||||
IssueID int64
|
IssueID int64
|
||||||
ReviewerID int64
|
ReviewerID int64
|
||||||
OfficialOnly bool
|
OfficialOnly bool
|
||||||
|
@ -107,8 +107,8 @@ func (opts *FindReviewOptions) toCond() builder.Cond {
|
||||||
if opts.ReviewerID > 0 {
|
if opts.ReviewerID > 0 {
|
||||||
cond = cond.And(builder.Eq{"reviewer_id": opts.ReviewerID})
|
cond = cond.And(builder.Eq{"reviewer_id": opts.ReviewerID})
|
||||||
}
|
}
|
||||||
if opts.Type != ReviewTypeUnknown {
|
if len(opts.Types) > 0 {
|
||||||
cond = cond.And(builder.Eq{"type": opts.Type})
|
cond = cond.And(builder.In("type", opts.Types))
|
||||||
}
|
}
|
||||||
if opts.OfficialOnly {
|
if opts.OfficialOnly {
|
||||||
cond = cond.And(builder.Eq{"official": true})
|
cond = cond.And(builder.Eq{"official": true})
|
||||||
|
|
|
@ -64,7 +64,7 @@ func TestReviewType_Icon(t *testing.T) {
|
||||||
func TestFindReviews(t *testing.T) {
|
func TestFindReviews(t *testing.T) {
|
||||||
require.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
reviews, err := issues_model.FindReviews(db.DefaultContext, issues_model.FindReviewOptions{
|
reviews, err := issues_model.FindReviews(db.DefaultContext, issues_model.FindReviewOptions{
|
||||||
Type: issues_model.ReviewTypeApprove,
|
Types: []issues_model.ReviewType{issues_model.ReviewTypeApprove},
|
||||||
IssueID: 2,
|
IssueID: 2,
|
||||||
ReviewerID: 1,
|
ReviewerID: 1,
|
||||||
})
|
})
|
||||||
|
@ -76,7 +76,7 @@ func TestFindReviews(t *testing.T) {
|
||||||
func TestFindLatestReviews(t *testing.T) {
|
func TestFindLatestReviews(t *testing.T) {
|
||||||
require.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
reviews, err := issues_model.FindLatestReviews(db.DefaultContext, issues_model.FindReviewOptions{
|
reviews, err := issues_model.FindLatestReviews(db.DefaultContext, issues_model.FindReviewOptions{
|
||||||
Type: issues_model.ReviewTypeApprove,
|
Types: []issues_model.ReviewType{issues_model.ReviewTypeApprove},
|
||||||
IssueID: 11,
|
IssueID: 11,
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
|
@ -60,34 +60,19 @@ func getStopwatch(ctx context.Context, userID, issueID int64) (sw *Stopwatch, ex
|
||||||
return sw, exists, err
|
return sw, exists, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// UserIDCount is a simple coalition of UserID and Count
|
|
||||||
type UserStopwatch struct {
|
|
||||||
UserID int64
|
|
||||||
StopWatches []*Stopwatch
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetUIDsAndNotificationCounts between the two provided times
|
// GetUIDsAndNotificationCounts between the two provided times
|
||||||
func GetUIDsAndStopwatch(ctx context.Context) ([]*UserStopwatch, error) {
|
func GetUIDsAndStopwatch(ctx context.Context) (map[int64][]*Stopwatch, error) {
|
||||||
sws := []*Stopwatch{}
|
sws := []*Stopwatch{}
|
||||||
if err := db.GetEngine(ctx).Where("issue_id != 0").Find(&sws); err != nil {
|
if err := db.GetEngine(ctx).Where("issue_id != 0").Find(&sws); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
res := map[int64][]*Stopwatch{}
|
||||||
if len(sws) == 0 {
|
if len(sws) == 0 {
|
||||||
return []*UserStopwatch{}, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
lastUserID := int64(-1)
|
|
||||||
res := []*UserStopwatch{}
|
|
||||||
for _, sw := range sws {
|
for _, sw := range sws {
|
||||||
if lastUserID == sw.UserID {
|
res[sw.UserID] = append(res[sw.UserID], sw)
|
||||||
lastUserStopwatch := res[len(res)-1]
|
|
||||||
lastUserStopwatch.StopWatches = append(lastUserStopwatch.StopWatches, sw)
|
|
||||||
} else {
|
|
||||||
res = append(res, &UserStopwatch{
|
|
||||||
UserID: sw.UserID,
|
|
||||||
StopWatches: []*Stopwatch{sw},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,12 +4,14 @@
|
||||||
package issues_test
|
package issues_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"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"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
@ -77,3 +79,41 @@ func TestCreateOrStopIssueStopwatch(t *testing.T) {
|
||||||
unittest.AssertNotExistsBean(t, &issues_model.Stopwatch{UserID: 2, IssueID: 2})
|
unittest.AssertNotExistsBean(t, &issues_model.Stopwatch{UserID: 2, IssueID: 2})
|
||||||
unittest.AssertExistsAndLoadBean(t, &issues_model.TrackedTime{UserID: 2, IssueID: 2})
|
unittest.AssertExistsAndLoadBean(t, &issues_model.TrackedTime{UserID: 2, IssueID: 2})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetUIDsAndStopwatch(t *testing.T) {
|
||||||
|
defer unittest.OverrideFixtures(
|
||||||
|
unittest.FixturesOptions{
|
||||||
|
Dir: filepath.Join(setting.AppWorkPath, "models/fixtures/"),
|
||||||
|
Base: setting.AppWorkPath,
|
||||||
|
Dirs: []string{"models/issues/TestGetUIDsAndStopwatch/"},
|
||||||
|
},
|
||||||
|
)()
|
||||||
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
uidStopwatches, err := issues_model.GetUIDsAndStopwatch(db.DefaultContext)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.EqualValues(t, map[int64][]*issues_model.Stopwatch{
|
||||||
|
1: {
|
||||||
|
{
|
||||||
|
ID: 1,
|
||||||
|
UserID: 1,
|
||||||
|
IssueID: 1,
|
||||||
|
CreatedUnix: timeutil.TimeStamp(1500988001),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: 3,
|
||||||
|
UserID: 1,
|
||||||
|
IssueID: 2,
|
||||||
|
CreatedUnix: timeutil.TimeStamp(1500988004),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
2: {
|
||||||
|
{
|
||||||
|
ID: 2,
|
||||||
|
UserID: 2,
|
||||||
|
IssueID: 2,
|
||||||
|
CreatedUnix: timeutil.TimeStamp(1500988002),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, uidStopwatches)
|
||||||
|
}
|
||||||
|
|
10
models/organization/TestInconsistentOwnerTeam/team.yml
Normal file
10
models/organization/TestInconsistentOwnerTeam/team.yml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
-
|
||||||
|
id: 1000
|
||||||
|
org_id: 1000
|
||||||
|
lower_name: owners
|
||||||
|
name: Owners
|
||||||
|
authorize: 4 # owner
|
||||||
|
num_repos: 0
|
||||||
|
num_members: 0
|
||||||
|
includes_all_repositories: true
|
||||||
|
can_create_org_repo: true
|
59
models/organization/TestInconsistentOwnerTeam/team_unit.yml
Normal file
59
models/organization/TestInconsistentOwnerTeam/team_unit.yml
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
-
|
||||||
|
id: 1000
|
||||||
|
team_id: 1000
|
||||||
|
type: 1
|
||||||
|
access_mode: 0 # None
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 1001
|
||||||
|
team_id: 1000
|
||||||
|
type: 2
|
||||||
|
access_mode: 0
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 1002
|
||||||
|
team_id: 1000
|
||||||
|
type: 3
|
||||||
|
access_mode: 0
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 1003
|
||||||
|
team_id: 1000
|
||||||
|
type: 4
|
||||||
|
access_mode: 0
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 1004
|
||||||
|
team_id: 1000
|
||||||
|
type: 5
|
||||||
|
access_mode: 0
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 1005
|
||||||
|
team_id: 1000
|
||||||
|
type: 6
|
||||||
|
access_mode: 0
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 1006
|
||||||
|
team_id: 1000
|
||||||
|
type: 7
|
||||||
|
access_mode: 0
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 1007
|
||||||
|
team_id: 1000
|
||||||
|
type: 8
|
||||||
|
access_mode: 0
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 1008
|
||||||
|
team_id: 1000
|
||||||
|
type: 9
|
||||||
|
access_mode: 0
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 1009
|
||||||
|
team_id: 1000
|
||||||
|
type: 10
|
||||||
|
access_mode: 0
|
|
@ -264,7 +264,7 @@ func (org *Organization) UnitPermission(ctx context.Context, doer *user_model.Us
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if org.Visibility.IsPublic() {
|
if org.Visibility.IsPublic() || (org.Visibility.IsLimited() && doer != nil) {
|
||||||
return perm.AccessModeRead
|
return perm.AccessModeRead
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,9 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/organization"
|
"code.gitea.io/gitea/models/organization"
|
||||||
|
"code.gitea.io/gitea/models/perm"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
|
"code.gitea.io/gitea/models/unit"
|
||||||
"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"
|
||||||
"code.gitea.io/gitea/modules/structs"
|
"code.gitea.io/gitea/modules/structs"
|
||||||
|
@ -299,8 +301,8 @@ func TestAccessibleReposEnv_RepoIDs(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, expectedRepoIDs, repoIDs)
|
assert.Equal(t, expectedRepoIDs, repoIDs)
|
||||||
}
|
}
|
||||||
testSuccess(2, []int64{3, 5, 32})
|
testSuccess(2, []int64{32, 5, 3})
|
||||||
testSuccess(4, []int64{3, 32})
|
testSuccess(4, []int64{32, 3})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAccessibleReposEnv_Repos(t *testing.T) {
|
func TestAccessibleReposEnv_Repos(t *testing.T) {
|
||||||
|
@ -318,8 +320,8 @@ func TestAccessibleReposEnv_Repos(t *testing.T) {
|
||||||
}
|
}
|
||||||
assert.Equal(t, expectedRepos, repos)
|
assert.Equal(t, expectedRepos, repos)
|
||||||
}
|
}
|
||||||
testSuccess(2, []int64{3, 5, 32})
|
testSuccess(2, []int64{32, 5, 3})
|
||||||
testSuccess(4, []int64{3, 32})
|
testSuccess(4, []int64{32, 3})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAccessibleReposEnv_MirrorRepos(t *testing.T) {
|
func TestAccessibleReposEnv_MirrorRepos(t *testing.T) {
|
||||||
|
@ -512,3 +514,35 @@ func TestCreateOrganization4(t *testing.T) {
|
||||||
assert.True(t, db.IsErrNameReserved(err))
|
assert.True(t, db.IsErrNameReserved(err))
|
||||||
unittest.CheckConsistencyFor(t, &organization.Organization{}, &organization.Team{})
|
unittest.CheckConsistencyFor(t, &organization.Organization{}, &organization.Team{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUnitPermission(t *testing.T) {
|
||||||
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
publicOrg := &organization.Organization{ID: 1001, Visibility: structs.VisibleTypePublic}
|
||||||
|
limitedOrg := &organization.Organization{ID: 1001, Visibility: structs.VisibleTypeLimited}
|
||||||
|
privateOrg := &organization.Organization{ID: 1001, Visibility: structs.VisibleTypePrivate}
|
||||||
|
user := &user_model.User{ID: 1001}
|
||||||
|
t.Run("Anonymous", func(t *testing.T) {
|
||||||
|
t.Run("Public", func(t *testing.T) {
|
||||||
|
assert.EqualValues(t, perm.AccessModeRead, publicOrg.UnitPermission(db.DefaultContext, nil, unit.TypeCode))
|
||||||
|
})
|
||||||
|
t.Run("Limited", func(t *testing.T) {
|
||||||
|
assert.EqualValues(t, perm.AccessModeNone, limitedOrg.UnitPermission(db.DefaultContext, nil, unit.TypeCode))
|
||||||
|
})
|
||||||
|
t.Run("Private", func(t *testing.T) {
|
||||||
|
assert.EqualValues(t, perm.AccessModeNone, privateOrg.UnitPermission(db.DefaultContext, nil, unit.TypeCode))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Logged in", func(t *testing.T) {
|
||||||
|
t.Run("Public", func(t *testing.T) {
|
||||||
|
assert.EqualValues(t, perm.AccessModeRead, publicOrg.UnitPermission(db.DefaultContext, user, unit.TypeCode))
|
||||||
|
})
|
||||||
|
t.Run("Limited", func(t *testing.T) {
|
||||||
|
assert.EqualValues(t, perm.AccessModeRead, limitedOrg.UnitPermission(db.DefaultContext, user, unit.TypeCode))
|
||||||
|
})
|
||||||
|
t.Run("Private", func(t *testing.T) {
|
||||||
|
assert.EqualValues(t, perm.AccessModeNone, privateOrg.UnitPermission(db.DefaultContext, user, unit.TypeCode))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -268,3 +268,43 @@ func IncrTeamRepoNum(ctx context.Context, teamID int64) error {
|
||||||
_, err := db.GetEngine(ctx).Incr("num_repos").ID(teamID).Update(new(Team))
|
_, err := db.GetEngine(ctx).Incr("num_repos").ID(teamID).Update(new(Team))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CountInconsistentOwnerTeams returns the amount of owner teams that have all of
|
||||||
|
// their access modes set to "None".
|
||||||
|
func CountInconsistentOwnerTeams(ctx context.Context) (int64, error) {
|
||||||
|
return db.GetEngine(ctx).Table("team").
|
||||||
|
Join("INNER", "team_unit", "`team`.id = `team_unit`.team_id").
|
||||||
|
Where("`team`.lower_name = ?", strings.ToLower(OwnerTeamName)).
|
||||||
|
GroupBy("`team_unit`.team_id").
|
||||||
|
Having("SUM(`team_unit`.access_mode) = 0").
|
||||||
|
Count()
|
||||||
|
}
|
||||||
|
|
||||||
|
// FixInconsistentOwnerTeams fixes inconsistent owner teams that have all of
|
||||||
|
// their access modes set to "None", it sets it back to "Owner".
|
||||||
|
func FixInconsistentOwnerTeams(ctx context.Context) (int64, error) {
|
||||||
|
teamIDs := []int64{}
|
||||||
|
if err := db.GetEngine(ctx).Table("team").
|
||||||
|
Select("`team`.id").
|
||||||
|
Join("INNER", "team_unit", "`team`.id = `team_unit`.team_id").
|
||||||
|
Where("`team`.lower_name = ?", strings.ToLower(OwnerTeamName)).
|
||||||
|
GroupBy("`team_unit`.team_id").
|
||||||
|
Having("SUM(`team_unit`.access_mode) = 0").
|
||||||
|
Find(&teamIDs); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := db.Iterate(ctx, builder.In("team_id", teamIDs), func(ctx context.Context, bean *TeamUnit) error {
|
||||||
|
if bean.Type == unit.TypeExternalTracker || bean.Type == unit.TypeExternalWiki {
|
||||||
|
bean.AccessMode = perm.AccessModeRead
|
||||||
|
} else {
|
||||||
|
bean.AccessMode = perm.AccessModeOwner
|
||||||
|
}
|
||||||
|
_, err := db.GetEngine(ctx).ID(bean.ID).Table("team_unit").Cols("access_mode").Update(bean)
|
||||||
|
return err
|
||||||
|
}); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return int64(len(teamIDs)), nil
|
||||||
|
}
|
||||||
|
|
|
@ -4,11 +4,14 @@
|
||||||
package organization_test
|
package organization_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/organization"
|
"code.gitea.io/gitea/models/organization"
|
||||||
|
"code.gitea.io/gitea/models/perm"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
@ -198,3 +201,50 @@ func TestUsersInTeamsCount(t *testing.T) {
|
||||||
test([]int64{1, 2, 3, 4, 5}, []int64{2, 5}, 2) // userid 2,4
|
test([]int64{1, 2, 3, 4, 5}, []int64{2, 5}, 2) // userid 2,4
|
||||||
test([]int64{1, 2, 3, 4, 5}, []int64{2, 3, 5}, 3) // userid 2,4,5
|
test([]int64{1, 2, 3, 4, 5}, []int64{2, 3, 5}, 3) // userid 2,4,5
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestInconsistentOwnerTeam(t *testing.T) {
|
||||||
|
defer unittest.OverrideFixtures(
|
||||||
|
unittest.FixturesOptions{
|
||||||
|
Dir: filepath.Join(setting.AppWorkPath, "models/fixtures/"),
|
||||||
|
Base: setting.AppWorkPath,
|
||||||
|
Dirs: []string{"models/organization/TestInconsistentOwnerTeam/"},
|
||||||
|
},
|
||||||
|
)()
|
||||||
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1000, TeamID: 1000, AccessMode: perm.AccessModeNone})
|
||||||
|
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1001, TeamID: 1000, AccessMode: perm.AccessModeNone})
|
||||||
|
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1002, TeamID: 1000, AccessMode: perm.AccessModeNone})
|
||||||
|
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1003, TeamID: 1000, AccessMode: perm.AccessModeNone})
|
||||||
|
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1004, TeamID: 1000, AccessMode: perm.AccessModeNone})
|
||||||
|
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1005, TeamID: 1000, AccessMode: perm.AccessModeNone})
|
||||||
|
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1006, TeamID: 1000, AccessMode: perm.AccessModeNone})
|
||||||
|
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1007, TeamID: 1000, AccessMode: perm.AccessModeNone})
|
||||||
|
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1008, TeamID: 1000, AccessMode: perm.AccessModeNone})
|
||||||
|
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1009, TeamID: 1000, AccessMode: perm.AccessModeNone})
|
||||||
|
|
||||||
|
count, err := organization.CountInconsistentOwnerTeams(db.DefaultContext)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.EqualValues(t, 1, count)
|
||||||
|
|
||||||
|
count, err = organization.FixInconsistentOwnerTeams(db.DefaultContext)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.EqualValues(t, 1, count)
|
||||||
|
|
||||||
|
count, err = organization.CountInconsistentOwnerTeams(db.DefaultContext)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.EqualValues(t, 0, count)
|
||||||
|
|
||||||
|
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1000, AccessMode: perm.AccessModeOwner})
|
||||||
|
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1001, AccessMode: perm.AccessModeOwner})
|
||||||
|
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1002, AccessMode: perm.AccessModeOwner})
|
||||||
|
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1003, AccessMode: perm.AccessModeOwner})
|
||||||
|
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1004, AccessMode: perm.AccessModeOwner})
|
||||||
|
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1007, AccessMode: perm.AccessModeOwner})
|
||||||
|
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1008, AccessMode: perm.AccessModeOwner})
|
||||||
|
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1009, AccessMode: perm.AccessModeOwner})
|
||||||
|
|
||||||
|
// External wiki and issue
|
||||||
|
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1005, AccessMode: perm.AccessModeRead})
|
||||||
|
unittest.AssertExistsAndLoadBean(t, &organization.TeamUnit{ID: 1006, AccessMode: perm.AccessModeRead})
|
||||||
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/packages"
|
"code.gitea.io/gitea/models/packages"
|
||||||
debian_module "code.gitea.io/gitea/modules/packages/debian"
|
debian_module "code.gitea.io/gitea/modules/packages/debian"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
)
|
)
|
||||||
|
@ -76,25 +77,41 @@ func ExistPackages(ctx context.Context, opts *PackageSearchOptions) (bool, error
|
||||||
|
|
||||||
// SearchPackages gets the packages matching the search options
|
// SearchPackages gets the packages matching the search options
|
||||||
func SearchPackages(ctx context.Context, opts *PackageSearchOptions, iter func(*packages.PackageFileDescriptor)) error {
|
func SearchPackages(ctx context.Context, opts *PackageSearchOptions, iter func(*packages.PackageFileDescriptor)) error {
|
||||||
return db.GetEngine(ctx).
|
var start int
|
||||||
Table("package_file").
|
batchSize := setting.Database.IterateBufferSize
|
||||||
Select("package_file.*").
|
for {
|
||||||
Join("INNER", "package_version", "package_version.id = package_file.version_id").
|
select {
|
||||||
Join("INNER", "package", "package.id = package_version.package_id").
|
case <-ctx.Done():
|
||||||
Where(opts.toCond()).
|
return ctx.Err()
|
||||||
Asc("package.lower_name", "package_version.created_unix").
|
default:
|
||||||
Iterate(new(packages.PackageFile), func(_ int, bean any) error {
|
beans := make([]*packages.PackageFile, 0, batchSize)
|
||||||
pf := bean.(*packages.PackageFile)
|
|
||||||
|
|
||||||
pfd, err := packages.GetPackageFileDescriptor(ctx, pf)
|
if err := db.GetEngine(ctx).
|
||||||
if err != nil {
|
Table("package_file").
|
||||||
|
Select("package_file.*").
|
||||||
|
Join("INNER", "package_version", "package_version.id = package_file.version_id").
|
||||||
|
Join("INNER", "package", "package.id = package_version.package_id").
|
||||||
|
Where(opts.toCond()).
|
||||||
|
Asc("package.lower_name", "package_version.created_unix").
|
||||||
|
Limit(batchSize, start).
|
||||||
|
Find(&beans); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if len(beans) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
start += len(beans)
|
||||||
|
|
||||||
iter(pfd)
|
for _, bean := range beans {
|
||||||
|
pfd, err := packages.GetPackageFileDescriptor(ctx, bean)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
iter(pfd)
|
||||||
})
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDistributions gets all available distributions
|
// GetDistributions gets all available distributions
|
||||||
|
|
93
models/packages/debian/search_test.go
Normal file
93
models/packages/debian/search_test.go
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
package debian
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models/db"
|
||||||
|
packages_model "code.gitea.io/gitea/models/packages"
|
||||||
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
"code.gitea.io/gitea/modules/packages"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
"code.gitea.io/gitea/modules/test"
|
||||||
|
packages_service "code.gitea.io/gitea/services/packages"
|
||||||
|
|
||||||
|
_ "code.gitea.io/gitea/models"
|
||||||
|
_ "code.gitea.io/gitea/models/actions"
|
||||||
|
_ "code.gitea.io/gitea/models/activities"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMain(m *testing.M) {
|
||||||
|
unittest.MainTest(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func preparePackage(t *testing.T, owner *user_model.User, name string) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
data, err := packages.CreateHashedBufferFromReader(strings.NewReader("data"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
_, _, err = packages_service.CreatePackageOrAddFileToExisting(
|
||||||
|
db.DefaultContext,
|
||||||
|
&packages_service.PackageCreationInfo{
|
||||||
|
PackageInfo: packages_service.PackageInfo{
|
||||||
|
Owner: owner,
|
||||||
|
PackageType: packages_model.TypeDebian,
|
||||||
|
Name: name,
|
||||||
|
},
|
||||||
|
Creator: owner,
|
||||||
|
},
|
||||||
|
&packages_service.PackageFileCreationInfo{
|
||||||
|
PackageFileInfo: packages_service.PackageFileInfo{
|
||||||
|
Filename: name,
|
||||||
|
},
|
||||||
|
Data: data,
|
||||||
|
Creator: owner,
|
||||||
|
IsLead: true,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSearchPackages(t *testing.T) {
|
||||||
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
defer test.MockVariableValue(&setting.Database.IterateBufferSize, 1)()
|
||||||
|
|
||||||
|
user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
|
user3 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3})
|
||||||
|
|
||||||
|
preparePackage(t, user2, "debian-1")
|
||||||
|
preparePackage(t, user2, "debian-2")
|
||||||
|
preparePackage(t, user3, "debian-1")
|
||||||
|
|
||||||
|
packageFiles := []string{}
|
||||||
|
require.NoError(t, SearchPackages(db.DefaultContext, &PackageSearchOptions{
|
||||||
|
OwnerID: user2.ID,
|
||||||
|
}, func(pfd *packages_model.PackageFileDescriptor) {
|
||||||
|
assert.NotNil(t, pfd)
|
||||||
|
packageFiles = append(packageFiles, pfd.File.Name)
|
||||||
|
}))
|
||||||
|
|
||||||
|
assert.Len(t, packageFiles, 2)
|
||||||
|
assert.Contains(t, packageFiles, "debian-1")
|
||||||
|
assert.Contains(t, packageFiles, "debian-2")
|
||||||
|
|
||||||
|
packageFiles = []string{}
|
||||||
|
require.NoError(t, SearchPackages(db.DefaultContext, &PackageSearchOptions{
|
||||||
|
OwnerID: user3.ID,
|
||||||
|
}, func(pfd *packages_model.PackageFileDescriptor) {
|
||||||
|
assert.NotNil(t, pfd)
|
||||||
|
packageFiles = append(packageFiles, pfd.File.Name)
|
||||||
|
}))
|
||||||
|
|
||||||
|
assert.Len(t, packageFiles, 1)
|
||||||
|
assert.Contains(t, packageFiles, "debian-1")
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
-
|
||||||
|
id: 1001
|
||||||
|
owner_id: 33
|
||||||
|
owner_name: user33
|
||||||
|
lower_name: repo1001
|
||||||
|
name: repo1001
|
||||||
|
default_branch: main
|
||||||
|
num_watches: 0
|
||||||
|
num_stars: 0
|
||||||
|
num_forks: 0
|
||||||
|
num_issues: 0
|
||||||
|
num_closed_issues: 0
|
||||||
|
num_pulls: 0
|
||||||
|
num_closed_pulls: 0
|
||||||
|
num_milestones: 0
|
||||||
|
num_closed_milestones: 0
|
||||||
|
num_projects: 0
|
||||||
|
num_closed_projects: 0
|
||||||
|
is_private: false
|
||||||
|
is_empty: false
|
||||||
|
is_archived: false
|
||||||
|
is_mirror: false
|
||||||
|
status: 0
|
||||||
|
is_fork: false
|
||||||
|
fork_id: 0
|
||||||
|
is_template: false
|
||||||
|
template_id: 0
|
||||||
|
size: 0
|
||||||
|
is_fsck_enabled: true
|
||||||
|
close_issues_via_commit_in_any_branch: false
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/unit"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
|
||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
|
@ -54,9 +55,9 @@ func GetUserFork(ctx context.Context, repoID, userID int64) (*Repository, error)
|
||||||
return &forkedRepo, nil
|
return &forkedRepo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetForks returns all the forks of the repository
|
// GetForks returns all the forks of the repository that are visible to the user.
|
||||||
func GetForks(ctx context.Context, repo *Repository, listOptions db.ListOptions) ([]*Repository, error) {
|
func GetForks(ctx context.Context, repo *Repository, user *user_model.User, listOptions db.ListOptions) ([]*Repository, int64, error) {
|
||||||
sess := db.GetEngine(ctx)
|
sess := db.GetEngine(ctx).Where(AccessibleRepositoryCondition(user, unit.TypeInvalid))
|
||||||
|
|
||||||
var forks []*Repository
|
var forks []*Repository
|
||||||
if listOptions.Page == 0 {
|
if listOptions.Page == 0 {
|
||||||
|
@ -66,7 +67,8 @@ func GetForks(ctx context.Context, repo *Repository, listOptions db.ListOptions)
|
||||||
sess = db.SetSessionPagination(sess, &listOptions)
|
sess = db.SetSessionPagination(sess, &listOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
return forks, sess.Find(&forks, &Repository{ForkID: repo.ID})
|
count, err := sess.FindAndCount(&forks, &Repository{ForkID: repo.ID})
|
||||||
|
return forks, count, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// IncrementRepoForkNum increment repository fork number
|
// IncrementRepoForkNum increment repository fork number
|
||||||
|
|
|
@ -641,12 +641,9 @@ func AccessibleRepositoryCondition(user *user_model.User, unitType unit.Type) bu
|
||||||
// 1. Be able to see all non-private repositories that either:
|
// 1. Be able to see all non-private repositories that either:
|
||||||
cond = cond.Or(builder.And(
|
cond = cond.Or(builder.And(
|
||||||
builder.Eq{"`repository`.is_private": false},
|
builder.Eq{"`repository`.is_private": false},
|
||||||
// 2. Aren't in an private organisation or limited organisation if we're not logged in
|
// 2. Aren't in an private organisation/user or limited organisation/user if the doer is not logged in.
|
||||||
builder.NotIn("`repository`.owner_id", builder.Select("id").From("`user`").Where(
|
builder.NotIn("`repository`.owner_id", builder.Select("id").From("`user`").Where(
|
||||||
builder.And(
|
builder.In("visibility", orgVisibilityLimit)))))
|
||||||
builder.Eq{"type": user_model.UserTypeOrganization},
|
|
||||||
builder.In("visibility", orgVisibilityLimit)),
|
|
||||||
))))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if user != nil {
|
if user != nil {
|
||||||
|
|
|
@ -4,13 +4,18 @@
|
||||||
package repo_test
|
package repo_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"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/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
"code.gitea.io/gitea/models/user"
|
||||||
"code.gitea.io/gitea/modules/optional"
|
"code.gitea.io/gitea/modules/optional"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
"code.gitea.io/gitea/modules/structs"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
@ -403,3 +408,43 @@ func TestSearchRepositoryByTopicName(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSearchRepositoryIDsByCondition(t *testing.T) {
|
||||||
|
defer unittest.OverrideFixtures(
|
||||||
|
unittest.FixturesOptions{
|
||||||
|
Dir: filepath.Join(setting.AppWorkPath, "models/fixtures/"),
|
||||||
|
Base: setting.AppWorkPath,
|
||||||
|
Dirs: []string{"models/repo/TestSearchRepositoryIDsByCondition/"},
|
||||||
|
},
|
||||||
|
)()
|
||||||
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
// Sanity check of the database
|
||||||
|
limitedUser := unittest.AssertExistsAndLoadBean(t, &user.User{ID: 33, Visibility: structs.VisibleTypeLimited})
|
||||||
|
unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1001, OwnerID: limitedUser.ID})
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
user *user.User
|
||||||
|
repoIDs []int64
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
user: nil,
|
||||||
|
repoIDs: []int64{1, 4, 8, 9, 10, 11, 12, 14, 17, 18, 21, 23, 25, 27, 29, 32, 33, 34, 35, 36, 37, 42, 44, 45, 46, 47, 48, 49, 50, 51, 53, 57, 58, 60, 61, 62, 1059},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
user: unittest.AssertExistsAndLoadBean(t, &user.User{ID: 4}),
|
||||||
|
repoIDs: []int64{1, 3, 4, 8, 9, 10, 11, 12, 14, 17, 18, 21, 23, 25, 27, 29, 32, 33, 34, 35, 36, 37, 38, 40, 42, 44, 45, 46, 47, 48, 49, 50, 51, 53, 57, 58, 60, 61, 62, 1001, 1059},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
user: unittest.AssertExistsAndLoadBean(t, &user.User{ID: 5}),
|
||||||
|
repoIDs: []int64{1, 4, 8, 9, 10, 11, 12, 14, 17, 18, 21, 23, 25, 27, 29, 32, 33, 34, 35, 36, 37, 38, 40, 42, 44, 45, 46, 47, 48, 49, 50, 51, 53, 57, 58, 60, 61, 62, 1001, 1059},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, testCase := range testCases {
|
||||||
|
repoIDs, err := repo_model.FindUserCodeAccessibleRepoIDs(db.DefaultContext, testCase.user)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
slices.Sort(repoIDs)
|
||||||
|
assert.EqualValues(t, testCase.repoIDs, repoIDs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@ var OrderByMap = map[string]map[string]db.SearchOrderBy{
|
||||||
var OrderByFlatMap = map[string]db.SearchOrderBy{
|
var OrderByFlatMap = map[string]db.SearchOrderBy{
|
||||||
"newest": OrderByMap["desc"]["created"],
|
"newest": OrderByMap["desc"]["created"],
|
||||||
"oldest": OrderByMap["asc"]["created"],
|
"oldest": OrderByMap["asc"]["created"],
|
||||||
|
"recentupdate": OrderByMap["desc"]["updated"],
|
||||||
"leastupdate": OrderByMap["asc"]["updated"],
|
"leastupdate": OrderByMap["asc"]["updated"],
|
||||||
"reversealphabetically": OrderByMap["desc"]["alpha"],
|
"reversealphabetically": OrderByMap["desc"]["alpha"],
|
||||||
"alphabetically": OrderByMap["asc"]["alpha"],
|
"alphabetically": OrderByMap["asc"]["alpha"],
|
||||||
|
|
|
@ -10,10 +10,8 @@ import (
|
||||||
"net/mail"
|
"net/mail"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/modules/base"
|
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/optional"
|
"code.gitea.io/gitea/modules/optional"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
@ -307,23 +305,6 @@ func updateActivation(ctx context.Context, email *EmailAddress, activate bool) e
|
||||||
return UpdateUserCols(ctx, user, "rands")
|
return UpdateUserCols(ctx, user, "rands")
|
||||||
}
|
}
|
||||||
|
|
||||||
// VerifyActiveEmailCode verifies active email code when active account
|
|
||||||
func VerifyActiveEmailCode(ctx context.Context, code, email string) *EmailAddress {
|
|
||||||
if user := GetVerifyUser(ctx, code); user != nil {
|
|
||||||
// time limit code
|
|
||||||
prefix := code[:base.TimeLimitCodeLength]
|
|
||||||
data := fmt.Sprintf("%d%s%s%s%s", user.ID, email, user.LowerName, user.Passwd, user.Rands)
|
|
||||||
|
|
||||||
if base.VerifyTimeLimitCode(time.Now(), data, setting.Service.ActiveCodeLives, prefix) {
|
|
||||||
emailAddress := &EmailAddress{UID: user.ID, Email: email}
|
|
||||||
if has, _ := db.GetEngine(ctx).Get(emailAddress); has {
|
|
||||||
return emailAddress
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// SearchEmailOrderBy is used to sort the results from SearchEmails()
|
// SearchEmailOrderBy is used to sort the results from SearchEmails()
|
||||||
type SearchEmailOrderBy string
|
type SearchEmailOrderBy string
|
||||||
|
|
||||||
|
|
|
@ -160,34 +160,12 @@ func UpdateExternalUserByExternalID(ctx context.Context, external *ExternalLogin
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnsureLinkExternalToUser link the external user to the user
|
|
||||||
func EnsureLinkExternalToUser(ctx context.Context, external *ExternalLoginUser) error {
|
|
||||||
has, err := db.Exist[ExternalLoginUser](ctx, builder.Eq{
|
|
||||||
"external_id": external.ExternalID,
|
|
||||||
"login_source_id": external.LoginSourceID,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if has {
|
|
||||||
_, err = db.GetEngine(ctx).Where("external_id=? AND login_source_id=?", external.ExternalID, external.LoginSourceID).AllCols().Update(external)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = db.GetEngine(ctx).Insert(external)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// FindExternalUserOptions represents an options to find external users
|
// FindExternalUserOptions represents an options to find external users
|
||||||
type FindExternalUserOptions struct {
|
type FindExternalUserOptions struct {
|
||||||
db.ListOptions
|
db.ListOptions
|
||||||
Provider string
|
Provider string
|
||||||
UserID int64
|
UserID int64
|
||||||
LoginSourceID int64
|
OrderBy string
|
||||||
HasRefreshToken bool
|
|
||||||
Expired bool
|
|
||||||
OrderBy string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (opts FindExternalUserOptions) ToConds() builder.Cond {
|
func (opts FindExternalUserOptions) ToConds() builder.Cond {
|
||||||
|
@ -198,22 +176,9 @@ func (opts FindExternalUserOptions) ToConds() builder.Cond {
|
||||||
if opts.UserID > 0 {
|
if opts.UserID > 0 {
|
||||||
cond = cond.And(builder.Eq{"user_id": opts.UserID})
|
cond = cond.And(builder.Eq{"user_id": opts.UserID})
|
||||||
}
|
}
|
||||||
if opts.Expired {
|
|
||||||
cond = cond.And(builder.Lt{"expires_at": time.Now()})
|
|
||||||
}
|
|
||||||
if opts.HasRefreshToken {
|
|
||||||
cond = cond.And(builder.Neq{"refresh_token": ""})
|
|
||||||
}
|
|
||||||
if opts.LoginSourceID != 0 {
|
|
||||||
cond = cond.And(builder.Eq{"login_source_id": opts.LoginSourceID})
|
|
||||||
}
|
|
||||||
return cond
|
return cond
|
||||||
}
|
}
|
||||||
|
|
||||||
func (opts FindExternalUserOptions) ToOrders() string {
|
func (opts FindExternalUserOptions) ToOrders() string {
|
||||||
return opts.OrderBy
|
return opts.OrderBy
|
||||||
}
|
}
|
||||||
|
|
||||||
func IterateExternalLogin(ctx context.Context, opts FindExternalUserOptions, f func(ctx context.Context, u *ExternalLoginUser) error) error {
|
|
||||||
return db.Iterate(ctx, opts.ToConds(), f)
|
|
||||||
}
|
|
||||||
|
|
|
@ -7,7 +7,9 @@ package user
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"crypto/subtle"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/mail"
|
"net/mail"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
@ -48,19 +50,19 @@ const (
|
||||||
UserTypeIndividual UserType = iota // Historic reason to make it starts at 0.
|
UserTypeIndividual UserType = iota // Historic reason to make it starts at 0.
|
||||||
|
|
||||||
// UserTypeOrganization defines an organization
|
// UserTypeOrganization defines an organization
|
||||||
UserTypeOrganization
|
UserTypeOrganization // 1
|
||||||
|
|
||||||
// UserTypeUserReserved reserves a (non-existing) user, i.e. to prevent a spam user from re-registering after being deleted, or to reserve the name until the user is actually created later on
|
// UserTypeUserReserved reserves a (non-existing) user, i.e. to prevent a spam user from re-registering after being deleted, or to reserve the name until the user is actually created later on
|
||||||
UserTypeUserReserved
|
UserTypeUserReserved // 2
|
||||||
|
|
||||||
// UserTypeOrganizationReserved reserves a (non-existing) organization, to be used in combination with UserTypeUserReserved
|
// UserTypeOrganizationReserved reserves a (non-existing) organization, to be used in combination with UserTypeUserReserved
|
||||||
UserTypeOrganizationReserved
|
UserTypeOrganizationReserved // 3
|
||||||
|
|
||||||
// UserTypeBot defines a bot user
|
// UserTypeBot defines a bot user
|
||||||
UserTypeBot
|
UserTypeBot // 4
|
||||||
|
|
||||||
// UserTypeRemoteUser defines a remote user for federated users
|
// UserTypeRemoteUser defines a remote user for federated users
|
||||||
UserTypeRemoteUser
|
UserTypeRemoteUser // 5
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -318,15 +320,14 @@ func (u *User) OrganisationLink() string {
|
||||||
return setting.AppSubURL + "/org/" + url.PathEscape(u.Name)
|
return setting.AppSubURL + "/org/" + url.PathEscape(u.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateEmailActivateCode generates an activate code based on user information and given e-mail.
|
// GenerateEmailAuthorizationCode generates an activation code based for the user for the specified purpose.
|
||||||
func (u *User) GenerateEmailActivateCode(email string) string {
|
// The standard expiry is ActiveCodeLives minutes.
|
||||||
code := base.CreateTimeLimitCode(
|
func (u *User) GenerateEmailAuthorizationCode(ctx context.Context, purpose auth.AuthorizationPurpose) (string, error) {
|
||||||
fmt.Sprintf("%d%s%s%s%s", u.ID, email, u.LowerName, u.Passwd, u.Rands),
|
lookup, validator, err := auth.GenerateAuthToken(ctx, u.ID, timeutil.TimeStampNow().Add(int64(setting.Service.ActiveCodeLives)*60), purpose)
|
||||||
setting.Service.ActiveCodeLives, time.Now(), nil)
|
if err != nil {
|
||||||
|
return "", err
|
||||||
// Add tail hex username
|
}
|
||||||
code += hex.EncodeToString([]byte(u.LowerName))
|
return lookup + ":" + validator, nil
|
||||||
return code
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUserFollowers returns range of user's followers.
|
// GetUserFollowers returns range of user's followers.
|
||||||
|
@ -421,6 +422,10 @@ func (u *User) IsIndividual() bool {
|
||||||
return u.Type == UserTypeIndividual
|
return u.Type == UserTypeIndividual
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *User) IsUser() bool {
|
||||||
|
return u.Type == UserTypeIndividual || u.Type == UserTypeBot
|
||||||
|
}
|
||||||
|
|
||||||
// IsBot returns whether or not the user is of type bot
|
// IsBot returns whether or not the user is of type bot
|
||||||
func (u *User) IsBot() bool {
|
func (u *User) IsBot() bool {
|
||||||
return u.Type == UserTypeBot
|
return u.Type == UserTypeBot
|
||||||
|
@ -832,35 +837,50 @@ func countUsers(ctx context.Context, opts *CountUserFilter) int64 {
|
||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetVerifyUser get user by verify code
|
// VerifyUserActiveCode verifies that the code is valid for the given purpose for this user.
|
||||||
func GetVerifyUser(ctx context.Context, code string) (user *User) {
|
// If delete is specified, the token will be deleted.
|
||||||
if len(code) <= base.TimeLimitCodeLength {
|
func VerifyUserAuthorizationToken(ctx context.Context, code string, purpose auth.AuthorizationPurpose, delete bool) (*User, error) {
|
||||||
return nil
|
lookupKey, validator, found := strings.Cut(code, ":")
|
||||||
|
if !found {
|
||||||
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// use tail hex username query user
|
authToken, err := auth.FindAuthToken(ctx, lookupKey, purpose)
|
||||||
hexStr := code[base.TimeLimitCodeLength:]
|
if err != nil {
|
||||||
if b, err := hex.DecodeString(hexStr); err == nil {
|
if errors.Is(err, util.ErrNotExist) {
|
||||||
if user, err = GetUserByName(ctx, string(b)); user != nil {
|
return nil, nil
|
||||||
return user
|
|
||||||
}
|
}
|
||||||
log.Error("user.getVerifyUser: %v", err)
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
if authToken.IsExpired() {
|
||||||
}
|
return nil, auth.DeleteAuthToken(ctx, authToken)
|
||||||
|
}
|
||||||
|
|
||||||
// VerifyUserActiveCode verifies active code when active account
|
rawValidator, err := hex.DecodeString(validator)
|
||||||
func VerifyUserActiveCode(ctx context.Context, code string) (user *User) {
|
if err != nil {
|
||||||
if user = GetVerifyUser(ctx, code); user != nil {
|
return nil, err
|
||||||
// time limit code
|
}
|
||||||
prefix := code[:base.TimeLimitCodeLength]
|
|
||||||
data := fmt.Sprintf("%d%s%s%s%s", user.ID, user.Email, user.LowerName, user.Passwd, user.Rands)
|
if subtle.ConstantTimeCompare([]byte(authToken.HashedValidator), []byte(auth.HashValidator(rawValidator))) == 0 {
|
||||||
if base.VerifyTimeLimitCode(time.Now(), data, setting.Service.ActiveCodeLives, prefix) {
|
return nil, errors.New("validator doesn't match")
|
||||||
return user
|
}
|
||||||
|
|
||||||
|
u, err := GetUserByID(ctx, authToken.UID)
|
||||||
|
if err != nil {
|
||||||
|
if IsErrUserNotExist(err) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if delete {
|
||||||
|
if err := auth.DeleteAuthToken(ctx, authToken); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
|
return u, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidateUser check if user is valid to insert / update into database
|
// ValidateUser check if user is valid to insert / update into database
|
||||||
|
@ -897,7 +917,13 @@ func UpdateUserCols(ctx context.Context, u *User, cols ...string) error {
|
||||||
|
|
||||||
// GetInactiveUsers gets all inactive users
|
// GetInactiveUsers gets all inactive users
|
||||||
func GetInactiveUsers(ctx context.Context, olderThan time.Duration) ([]*User, error) {
|
func GetInactiveUsers(ctx context.Context, olderThan time.Duration) ([]*User, error) {
|
||||||
var cond builder.Cond = builder.Eq{"is_active": false}
|
cond := builder.And(
|
||||||
|
builder.Eq{"is_active": false},
|
||||||
|
builder.Or( // only plain user
|
||||||
|
builder.Eq{"`type`": UserTypeIndividual},
|
||||||
|
builder.Eq{"`type`": UserTypeUserReserved},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
if olderThan > 0 {
|
if olderThan > 0 {
|
||||||
cond = cond.And(builder.Lt{"created_unix": time.Now().Add(-olderThan).Unix()})
|
cond = cond.And(builder.Lt{"created_unix": time.Now().Add(-olderThan).Unix()})
|
||||||
|
|
|
@ -7,6 +7,7 @@ package user_test
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -21,7 +22,9 @@ import (
|
||||||
"code.gitea.io/gitea/modules/optional"
|
"code.gitea.io/gitea/modules/optional"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/structs"
|
"code.gitea.io/gitea/modules/structs"
|
||||||
|
"code.gitea.io/gitea/modules/test"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
|
"code.gitea.io/gitea/modules/util"
|
||||||
"code.gitea.io/gitea/tests"
|
"code.gitea.io/gitea/tests"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
@ -699,3 +702,80 @@ func TestDisabledUserFeatures(t *testing.T) {
|
||||||
assert.True(t, user_model.IsFeatureDisabledWithLoginType(user, f))
|
assert.True(t, user_model.IsFeatureDisabledWithLoginType(user, f))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGenerateEmailAuthorizationCode(t *testing.T) {
|
||||||
|
defer test.MockVariableValue(&setting.Service.ActiveCodeLives, 2)()
|
||||||
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
|
|
||||||
|
code, err := user.GenerateEmailAuthorizationCode(db.DefaultContext, auth.UserActivation)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
lookupKey, validator, ok := strings.Cut(code, ":")
|
||||||
|
assert.True(t, ok)
|
||||||
|
|
||||||
|
rawValidator, err := hex.DecodeString(validator)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
authToken, err := auth.FindAuthToken(db.DefaultContext, lookupKey, auth.UserActivation)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.False(t, authToken.IsExpired())
|
||||||
|
assert.EqualValues(t, authToken.HashedValidator, auth.HashValidator(rawValidator))
|
||||||
|
|
||||||
|
authToken.Expiry = authToken.Expiry.Add(-int64(setting.Service.ActiveCodeLives) * 60)
|
||||||
|
assert.True(t, authToken.IsExpired())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVerifyUserAuthorizationToken(t *testing.T) {
|
||||||
|
defer test.MockVariableValue(&setting.Service.ActiveCodeLives, 2)()
|
||||||
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
|
|
||||||
|
code, err := user.GenerateEmailAuthorizationCode(db.DefaultContext, auth.UserActivation)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
lookupKey, _, ok := strings.Cut(code, ":")
|
||||||
|
assert.True(t, ok)
|
||||||
|
|
||||||
|
t.Run("Wrong purpose", func(t *testing.T) {
|
||||||
|
u, err := user_model.VerifyUserAuthorizationToken(db.DefaultContext, code, auth.PasswordReset, false)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Nil(t, u)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("No delete", func(t *testing.T) {
|
||||||
|
u, err := user_model.VerifyUserAuthorizationToken(db.DefaultContext, code, auth.UserActivation, false)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.EqualValues(t, user.ID, u.ID)
|
||||||
|
|
||||||
|
authToken, err := auth.FindAuthToken(db.DefaultContext, lookupKey, auth.UserActivation)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.NotNil(t, authToken)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("Delete", func(t *testing.T) {
|
||||||
|
u, err := user_model.VerifyUserAuthorizationToken(db.DefaultContext, code, auth.UserActivation, true)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.EqualValues(t, user.ID, u.ID)
|
||||||
|
|
||||||
|
authToken, err := auth.FindAuthToken(db.DefaultContext, lookupKey, auth.UserActivation)
|
||||||
|
require.ErrorIs(t, err, util.ErrNotExist)
|
||||||
|
assert.Nil(t, authToken)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetInactiveUsers(t *testing.T) {
|
||||||
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
// all inactive users
|
||||||
|
// user1's createdunix is 1730468968
|
||||||
|
users, err := user_model.GetInactiveUsers(db.DefaultContext, 0)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Len(t, users, 1)
|
||||||
|
interval := time.Now().Unix() - 1730468968 + 3600*24
|
||||||
|
users, err = user_model.GetInactiveUsers(db.DefaultContext, time.Duration(interval*int64(time.Second)))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Empty(t, users)
|
||||||
|
}
|
||||||
|
|
|
@ -18,8 +18,32 @@ func FullSteps(task *actions_model.ActionTask) []*actions_model.ActionTaskStep {
|
||||||
return fullStepsOfEmptySteps(task)
|
return fullStepsOfEmptySteps(task)
|
||||||
}
|
}
|
||||||
|
|
||||||
firstStep := task.Steps[0]
|
// firstStep is the first step that has run or running, not include preStep.
|
||||||
|
// For example,
|
||||||
|
// 1. preStep(Success) -> step1(Success) -> step2(Running) -> step3(Waiting) -> postStep(Waiting): firstStep is step1.
|
||||||
|
// 2. preStep(Success) -> step1(Skipped) -> step2(Success) -> postStep(Success): firstStep is step2.
|
||||||
|
// 3. preStep(Success) -> step1(Running) -> step2(Waiting) -> postStep(Waiting): firstStep is step1.
|
||||||
|
// 4. preStep(Success) -> step1(Skipped) -> step2(Skipped) -> postStep(Skipped): firstStep is nil.
|
||||||
|
// 5. preStep(Success) -> step1(Cancelled) -> step2(Cancelled) -> postStep(Cancelled): firstStep is nil.
|
||||||
|
var firstStep *actions_model.ActionTaskStep
|
||||||
|
// lastHasRunStep is the last step that has run.
|
||||||
|
// For example,
|
||||||
|
// 1. preStep(Success) -> step1(Success) -> step2(Running) -> step3(Waiting) -> postStep(Waiting): lastHasRunStep is step1.
|
||||||
|
// 2. preStep(Success) -> step1(Success) -> step2(Success) -> step3(Success) -> postStep(Success): lastHasRunStep is step3.
|
||||||
|
// 3. preStep(Success) -> step1(Success) -> step2(Failure) -> step3 -> postStep(Waiting): lastHasRunStep is step2.
|
||||||
|
// So its Stopped is the Started of postStep when there are no more steps to run.
|
||||||
|
var lastHasRunStep *actions_model.ActionTaskStep
|
||||||
|
|
||||||
var logIndex int64
|
var logIndex int64
|
||||||
|
for _, step := range task.Steps {
|
||||||
|
if firstStep == nil && (step.Status.HasRun() || step.Status.IsRunning()) {
|
||||||
|
firstStep = step
|
||||||
|
}
|
||||||
|
if step.Status.HasRun() {
|
||||||
|
lastHasRunStep = step
|
||||||
|
}
|
||||||
|
logIndex += step.LogLength
|
||||||
|
}
|
||||||
|
|
||||||
preStep := &actions_model.ActionTaskStep{
|
preStep := &actions_model.ActionTaskStep{
|
||||||
Name: preStepName,
|
Name: preStepName,
|
||||||
|
@ -28,32 +52,17 @@ func FullSteps(task *actions_model.ActionTask) []*actions_model.ActionTaskStep {
|
||||||
Status: actions_model.StatusRunning,
|
Status: actions_model.StatusRunning,
|
||||||
}
|
}
|
||||||
|
|
||||||
if firstStep.Status.HasRun() || firstStep.Status.IsRunning() {
|
// No step has run or is running, so preStep is equal to the task
|
||||||
|
if firstStep == nil {
|
||||||
|
preStep.Stopped = task.Stopped
|
||||||
|
preStep.Status = task.Status
|
||||||
|
} else {
|
||||||
preStep.LogLength = firstStep.LogIndex
|
preStep.LogLength = firstStep.LogIndex
|
||||||
preStep.Stopped = firstStep.Started
|
preStep.Stopped = firstStep.Started
|
||||||
preStep.Status = actions_model.StatusSuccess
|
preStep.Status = actions_model.StatusSuccess
|
||||||
} else if task.Status.IsDone() {
|
|
||||||
preStep.Stopped = task.Stopped
|
|
||||||
preStep.Status = actions_model.StatusFailure
|
|
||||||
if task.Status.IsSkipped() {
|
|
||||||
preStep.Status = actions_model.StatusSkipped
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
logIndex += preStep.LogLength
|
logIndex += preStep.LogLength
|
||||||
|
|
||||||
// lastHasRunStep is the last step that has run.
|
|
||||||
// For example,
|
|
||||||
// 1. preStep(Success) -> step1(Success) -> step2(Running) -> step3(Waiting) -> postStep(Waiting): lastHasRunStep is step1.
|
|
||||||
// 2. preStep(Success) -> step1(Success) -> step2(Success) -> step3(Success) -> postStep(Success): lastHasRunStep is step3.
|
|
||||||
// 3. preStep(Success) -> step1(Success) -> step2(Failure) -> step3 -> postStep(Waiting): lastHasRunStep is step2.
|
|
||||||
// So its Stopped is the Started of postStep when there are no more steps to run.
|
|
||||||
var lastHasRunStep *actions_model.ActionTaskStep
|
|
||||||
for _, step := range task.Steps {
|
|
||||||
if step.Status.HasRun() {
|
|
||||||
lastHasRunStep = step
|
|
||||||
}
|
|
||||||
logIndex += step.LogLength
|
|
||||||
}
|
|
||||||
if lastHasRunStep == nil {
|
if lastHasRunStep == nil {
|
||||||
lastHasRunStep = preStep
|
lastHasRunStep = preStep
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,6 +137,25 @@ func TestFullSteps(t *testing.T) {
|
||||||
{Name: postStepName, Status: actions_model.StatusSkipped, LogIndex: 0, LogLength: 0, Started: 0, Stopped: 0},
|
{Name: postStepName, Status: actions_model.StatusSkipped, LogIndex: 0, LogLength: 0, Started: 0, Stopped: 0},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "first step is skipped",
|
||||||
|
task: &actions_model.ActionTask{
|
||||||
|
Steps: []*actions_model.ActionTaskStep{
|
||||||
|
{Status: actions_model.StatusSkipped, LogIndex: 0, LogLength: 0, Started: 0, Stopped: 0},
|
||||||
|
{Status: actions_model.StatusSuccess, LogIndex: 10, LogLength: 80, Started: 10010, Stopped: 10090},
|
||||||
|
},
|
||||||
|
Status: actions_model.StatusSuccess,
|
||||||
|
Started: 10000,
|
||||||
|
Stopped: 10100,
|
||||||
|
LogLength: 100,
|
||||||
|
},
|
||||||
|
want: []*actions_model.ActionTaskStep{
|
||||||
|
{Name: preStepName, Status: actions_model.StatusSuccess, LogIndex: 0, LogLength: 10, Started: 10000, Stopped: 10010},
|
||||||
|
{Status: actions_model.StatusSkipped, LogIndex: 0, LogLength: 0, Started: 0, Stopped: 0},
|
||||||
|
{Status: actions_model.StatusSuccess, LogIndex: 10, LogLength: 80, Started: 10010, Stopped: 10090},
|
||||||
|
{Name: postStepName, Status: actions_model.StatusSuccess, LogIndex: 90, LogLength: 10, Started: 10090, Stopped: 10100},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
|
|
@ -4,26 +4,20 @@
|
||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/hmac"
|
|
||||||
"crypto/sha1"
|
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"crypto/subtle"
|
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"hash"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
|
||||||
|
|
||||||
"github.com/dustin/go-humanize"
|
"github.com/dustin/go-humanize"
|
||||||
)
|
)
|
||||||
|
@ -54,66 +48,6 @@ func BasicAuthDecode(encoded string) (string, string, error) {
|
||||||
return "", "", errors.New("invalid basic authentication")
|
return "", "", errors.New("invalid basic authentication")
|
||||||
}
|
}
|
||||||
|
|
||||||
// VerifyTimeLimitCode verify time limit code
|
|
||||||
func VerifyTimeLimitCode(now time.Time, data string, minutes int, code string) bool {
|
|
||||||
if len(code) <= 18 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
startTimeStr := code[:12]
|
|
||||||
aliveTimeStr := code[12:18]
|
|
||||||
aliveTime, _ := strconv.Atoi(aliveTimeStr) // no need to check err, if anything wrong, the following code check will fail soon
|
|
||||||
|
|
||||||
// check code
|
|
||||||
retCode := CreateTimeLimitCode(data, aliveTime, startTimeStr, nil)
|
|
||||||
if subtle.ConstantTimeCompare([]byte(retCode), []byte(code)) != 1 {
|
|
||||||
retCode = CreateTimeLimitCode(data, aliveTime, startTimeStr, sha1.New()) // TODO: this is only for the support of legacy codes, remove this in/after 1.23
|
|
||||||
if subtle.ConstantTimeCompare([]byte(retCode), []byte(code)) != 1 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check time is expired or not: startTime <= now && now < startTime + minutes
|
|
||||||
startTime, _ := time.ParseInLocation("200601021504", startTimeStr, time.Local)
|
|
||||||
return (startTime.Before(now) || startTime.Equal(now)) && now.Before(startTime.Add(time.Minute*time.Duration(minutes)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// TimeLimitCodeLength default value for time limit code
|
|
||||||
const TimeLimitCodeLength = 12 + 6 + 40
|
|
||||||
|
|
||||||
// CreateTimeLimitCode create a time-limited code.
|
|
||||||
// Format: 12 length date time string + 6 minutes string (not used) + 40 hash string, some other code depends on this fixed length
|
|
||||||
// If h is nil, then use the default hmac hash.
|
|
||||||
func CreateTimeLimitCode[T time.Time | string](data string, minutes int, startTimeGeneric T, h hash.Hash) string {
|
|
||||||
const format = "200601021504"
|
|
||||||
|
|
||||||
var start time.Time
|
|
||||||
var startTimeAny any = startTimeGeneric
|
|
||||||
if t, ok := startTimeAny.(time.Time); ok {
|
|
||||||
start = t
|
|
||||||
} else {
|
|
||||||
var err error
|
|
||||||
start, err = time.ParseInLocation(format, startTimeAny.(string), time.Local)
|
|
||||||
if err != nil {
|
|
||||||
return "" // return an invalid code because the "parse" failed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
startStr := start.Format(format)
|
|
||||||
end := start.Add(time.Minute * time.Duration(minutes))
|
|
||||||
|
|
||||||
if h == nil {
|
|
||||||
h = hmac.New(sha1.New, setting.GetGeneralTokenSigningSecret())
|
|
||||||
}
|
|
||||||
_, _ = fmt.Fprintf(h, "%s%s%s%s%d", data, hex.EncodeToString(setting.GetGeneralTokenSigningSecret()), startStr, end.Format(format), minutes)
|
|
||||||
encoded := hex.EncodeToString(h.Sum(nil))
|
|
||||||
|
|
||||||
code := fmt.Sprintf("%s%06d%s", startStr, minutes, encoded)
|
|
||||||
if len(code) != TimeLimitCodeLength {
|
|
||||||
panic("there is a hard requirement for the length of time-limited code") // it shouldn't happen
|
|
||||||
}
|
|
||||||
return code
|
|
||||||
}
|
|
||||||
|
|
||||||
// FileSize calculates the file size and generate user-friendly string.
|
// FileSize calculates the file size and generate user-friendly string.
|
||||||
func FileSize(s int64) string {
|
func FileSize(s int64) string {
|
||||||
return humanize.IBytes(uint64(s))
|
return humanize.IBytes(uint64(s))
|
||||||
|
|
|
@ -4,13 +4,7 @@
|
||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha1"
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
|
||||||
"code.gitea.io/gitea/modules/test"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
@ -46,57 +40,6 @@ func TestBasicAuthDecode(t *testing.T) {
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestVerifyTimeLimitCode(t *testing.T) {
|
|
||||||
defer test.MockVariableValue(&setting.InstallLock, true)()
|
|
||||||
initGeneralSecret := func(secret string) {
|
|
||||||
setting.InstallLock = true
|
|
||||||
setting.CfgProvider, _ = setting.NewConfigProviderFromData(fmt.Sprintf(`
|
|
||||||
[oauth2]
|
|
||||||
JWT_SECRET = %s
|
|
||||||
`, secret))
|
|
||||||
setting.LoadCommonSettings()
|
|
||||||
}
|
|
||||||
|
|
||||||
initGeneralSecret("KZb_QLUd4fYVyxetjxC4eZkrBgWM2SndOOWDNtgUUko")
|
|
||||||
now := time.Now()
|
|
||||||
|
|
||||||
t.Run("TestGenericParameter", func(t *testing.T) {
|
|
||||||
time2000 := time.Date(2000, 1, 2, 3, 4, 5, 0, time.Local)
|
|
||||||
assert.Equal(t, "2000010203040000026fa5221b2731b7cf80b1b506f5e39e38c115fee5", CreateTimeLimitCode("test-sha1", 2, time2000, sha1.New()))
|
|
||||||
assert.Equal(t, "2000010203040000026fa5221b2731b7cf80b1b506f5e39e38c115fee5", CreateTimeLimitCode("test-sha1", 2, "200001020304", sha1.New()))
|
|
||||||
assert.Equal(t, "2000010203040000024842227a2f87041ff82025199c0187410a9297bf", CreateTimeLimitCode("test-hmac", 2, time2000, nil))
|
|
||||||
assert.Equal(t, "2000010203040000024842227a2f87041ff82025199c0187410a9297bf", CreateTimeLimitCode("test-hmac", 2, "200001020304", nil))
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("TestInvalidCode", func(t *testing.T) {
|
|
||||||
assert.False(t, VerifyTimeLimitCode(now, "data", 2, ""))
|
|
||||||
assert.False(t, VerifyTimeLimitCode(now, "data", 2, "invalid code"))
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("TestCreateAndVerify", func(t *testing.T) {
|
|
||||||
code := CreateTimeLimitCode("data", 2, now, nil)
|
|
||||||
assert.False(t, VerifyTimeLimitCode(now.Add(-time.Minute), "data", 2, code)) // not started yet
|
|
||||||
assert.True(t, VerifyTimeLimitCode(now, "data", 2, code))
|
|
||||||
assert.True(t, VerifyTimeLimitCode(now.Add(time.Minute), "data", 2, code))
|
|
||||||
assert.False(t, VerifyTimeLimitCode(now.Add(time.Minute), "DATA", 2, code)) // invalid data
|
|
||||||
assert.False(t, VerifyTimeLimitCode(now.Add(2*time.Minute), "data", 2, code)) // expired
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("TestDifferentSecret", func(t *testing.T) {
|
|
||||||
// use another secret to ensure the code is invalid for different secret
|
|
||||||
verifyDataCode := func(c string) bool {
|
|
||||||
return VerifyTimeLimitCode(now, "data", 2, c)
|
|
||||||
}
|
|
||||||
code1 := CreateTimeLimitCode("data", 2, now, sha1.New())
|
|
||||||
code2 := CreateTimeLimitCode("data", 2, now, nil)
|
|
||||||
assert.True(t, verifyDataCode(code1))
|
|
||||||
assert.True(t, verifyDataCode(code2))
|
|
||||||
initGeneralSecret("000_QLUd4fYVyxetjxC4eZkrBgWM2SndOOWDNtgUUko")
|
|
||||||
assert.False(t, verifyDataCode(code1))
|
|
||||||
assert.False(t, verifyDataCode(code2))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFileSize(t *testing.T) {
|
func TestFileSize(t *testing.T) {
|
||||||
var size int64 = 512
|
var size int64 = 512
|
||||||
assert.Equal(t, "512 B", FileSize(size))
|
assert.Equal(t, "512 B", FileSize(size))
|
||||||
|
|
|
@ -90,8 +90,8 @@ loop:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, userStopwatches := range usersStopwatches {
|
for uid, stopwatches := range usersStopwatches {
|
||||||
apiSWs, err := convert.ToStopWatches(ctx, userStopwatches.StopWatches)
|
apiSWs, err := convert.ToStopWatches(ctx, stopwatches)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !issues_model.IsErrIssueNotExist(err) {
|
if !issues_model.IsErrIssueNotExist(err) {
|
||||||
log.Error("Unable to APIFormat stopwatches: %v", err)
|
log.Error("Unable to APIFormat stopwatches: %v", err)
|
||||||
|
@ -103,7 +103,7 @@ loop:
|
||||||
log.Error("Unable to marshal stopwatches: %v", err)
|
log.Error("Unable to marshal stopwatches: %v", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
m.SendMessage(userStopwatches.UserID, &Event{
|
m.SendMessage(uid, &Event{
|
||||||
Name: "stopwatches",
|
Name: "stopwatches",
|
||||||
Data: string(dataBs),
|
Data: string(dataBs),
|
||||||
})
|
})
|
||||||
|
|
|
@ -17,6 +17,8 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
|
"github.com/go-git/go-git/v5/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Commit represents a git commit.
|
// Commit represents a git commit.
|
||||||
|
@ -365,53 +367,48 @@ func (c *Commit) GetSubModules() (*ObjectCache, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
rd, err := entry.Blob().DataAsync()
|
content, err := entry.Blob().GetBlobContent(10 * 1024)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
defer rd.Close()
|
c.submoduleCache, err = parseSubmoduleContent([]byte(content))
|
||||||
scanner := bufio.NewScanner(rd)
|
if err != nil {
|
||||||
c.submoduleCache = newObjectCache()
|
return nil, err
|
||||||
var ismodule bool
|
|
||||||
var path string
|
|
||||||
for scanner.Scan() {
|
|
||||||
if strings.HasPrefix(scanner.Text(), "[submodule") {
|
|
||||||
ismodule = true
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if ismodule {
|
|
||||||
fields := strings.Split(scanner.Text(), "=")
|
|
||||||
k := strings.TrimSpace(fields[0])
|
|
||||||
if k == "path" {
|
|
||||||
path = strings.TrimSpace(fields[1])
|
|
||||||
} else if k == "url" {
|
|
||||||
c.submoduleCache.Set(path, &SubModule{path, strings.TrimSpace(fields[1])})
|
|
||||||
ismodule = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if err = scanner.Err(); err != nil {
|
|
||||||
return nil, fmt.Errorf("GetSubModules scan: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.submoduleCache, nil
|
return c.submoduleCache, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSubModule get the sub module according entryname
|
func parseSubmoduleContent(bs []byte) (*ObjectCache, error) {
|
||||||
func (c *Commit) GetSubModule(entryname string) (*SubModule, error) {
|
cfg := config.NewModules()
|
||||||
|
if err := cfg.Unmarshal(bs); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
submoduleCache := newObjectCache()
|
||||||
|
if len(cfg.Submodules) == 0 {
|
||||||
|
return nil, fmt.Errorf("no submodules found")
|
||||||
|
}
|
||||||
|
for _, subModule := range cfg.Submodules {
|
||||||
|
submoduleCache.Set(subModule.Path, subModule.URL)
|
||||||
|
}
|
||||||
|
|
||||||
|
return submoduleCache, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSubModule returns the URL to the submodule according entryname
|
||||||
|
func (c *Commit) GetSubModule(entryname string) (string, error) {
|
||||||
modules, err := c.GetSubModules()
|
modules, err := c.GetSubModules()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
if modules != nil {
|
if modules != nil {
|
||||||
module, has := modules.Get(entryname)
|
module, has := modules.Get(entryname)
|
||||||
if has {
|
if has {
|
||||||
return module.(*SubModule), nil
|
return module.(string), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBranchName gets the closest branch name (as returned by 'git name-rev --name-only')
|
// GetBranchName gets the closest branch name (as returned by 'git name-rev --name-only')
|
||||||
|
|
|
@ -72,17 +72,15 @@ func (tes Entries) GetCommitsInfo(ctx context.Context, commit *Commit, treePath
|
||||||
|
|
||||||
// If the entry if a submodule add a submodule file for this
|
// If the entry if a submodule add a submodule file for this
|
||||||
if entry.IsSubModule() {
|
if entry.IsSubModule() {
|
||||||
subModuleURL := ""
|
|
||||||
var fullPath string
|
var fullPath string
|
||||||
if len(treePath) > 0 {
|
if len(treePath) > 0 {
|
||||||
fullPath = treePath + "/" + entry.Name()
|
fullPath = treePath + "/" + entry.Name()
|
||||||
} else {
|
} else {
|
||||||
fullPath = entry.Name()
|
fullPath = entry.Name()
|
||||||
}
|
}
|
||||||
if subModule, err := commit.GetSubModule(fullPath); err != nil {
|
subModuleURL, err := commit.GetSubModule(fullPath)
|
||||||
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
} else if subModule != nil {
|
|
||||||
subModuleURL = subModule.URL
|
|
||||||
}
|
}
|
||||||
subModuleFile := NewSubModuleFile(commitsInfo[i].Commit, subModuleURL, entry.ID.String())
|
subModuleFile := NewSubModuleFile(commitsInfo[i].Commit, subModuleURL, entry.ID.String())
|
||||||
commitsInfo[i].SubModuleFile = subModuleFile
|
commitsInfo[i].SubModuleFile = subModuleFile
|
||||||
|
|
|
@ -369,3 +369,33 @@ func TestParseCommitRenames(t *testing.T) {
|
||||||
assert.Equal(t, testcase.renames, renames)
|
assert.Equal(t, testcase.renames, renames)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Test_parseSubmoduleContent(t *testing.T) {
|
||||||
|
submoduleFiles := []struct {
|
||||||
|
fileContent string
|
||||||
|
expectedPath string
|
||||||
|
expectedURL string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
fileContent: `[submodule "jakarta-servlet"]
|
||||||
|
url = ../../ALP-pool/jakarta-servlet
|
||||||
|
path = jakarta-servlet`,
|
||||||
|
expectedPath: "jakarta-servlet",
|
||||||
|
expectedURL: "../../ALP-pool/jakarta-servlet",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fileContent: `[submodule "jakarta-servlet"]
|
||||||
|
path = jakarta-servlet
|
||||||
|
url = ../../ALP-pool/jakarta-servlet`,
|
||||||
|
expectedPath: "jakarta-servlet",
|
||||||
|
expectedURL: "../../ALP-pool/jakarta-servlet",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, kase := range submoduleFiles {
|
||||||
|
submodule, err := parseSubmoduleContent([]byte(kase.fileContent))
|
||||||
|
require.NoError(t, err)
|
||||||
|
v, ok := submodule.Get(kase.expectedPath)
|
||||||
|
assert.True(t, ok)
|
||||||
|
assert.Equal(t, kase.expectedURL, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -272,6 +272,17 @@ func CutDiffAroundLine(originalDiff io.Reader, line int64, old bool, numbersOfLi
|
||||||
|
|
||||||
// GetAffectedFiles returns the affected files between two commits
|
// GetAffectedFiles returns the affected files between two commits
|
||||||
func GetAffectedFiles(repo *Repository, oldCommitID, newCommitID string, env []string) ([]string, error) {
|
func GetAffectedFiles(repo *Repository, oldCommitID, newCommitID string, env []string) ([]string, error) {
|
||||||
|
objectFormat, err := repo.GetObjectFormat()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the oldCommitID is empty, then we must assume its a new branch, so diff
|
||||||
|
// against the empty tree. So all changes of this new branch are included.
|
||||||
|
if oldCommitID == objectFormat.EmptyObjectID().String() {
|
||||||
|
oldCommitID = objectFormat.EmptyTree().String()
|
||||||
|
}
|
||||||
|
|
||||||
stdoutReader, stdoutWriter, err := os.Pipe()
|
stdoutReader, stdoutWriter, err := os.Pipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Unable to create os.Pipe for %s", repo.Path)
|
log.Error("Unable to create os.Pipe for %s", repo.Path)
|
||||||
|
|
|
@ -97,12 +97,12 @@ func SetExecutablePath(path string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if gitVersion.LessThan(versionRequired) {
|
if gitVersion.LessThan(versionRequired) {
|
||||||
moreHint := "get git: https://git-scm.com/download/"
|
moreHint := "get git: https://git-scm.com/downloads"
|
||||||
if runtime.GOOS == "linux" {
|
if runtime.GOOS == "linux" {
|
||||||
// there are a lot of CentOS/RHEL users using old git, so we add a special hint for them
|
// there are a lot of CentOS/RHEL users using old git, so we add a special hint for them
|
||||||
if _, err = os.Stat("/etc/redhat-release"); err == nil {
|
if _, err = os.Stat("/etc/redhat-release"); err == nil {
|
||||||
// ius.io is the recommended official(git-scm.com) method to install git
|
// ius.io is the recommended official(git-scm.com) method to install git
|
||||||
moreHint = "get git: https://git-scm.com/download/linux and https://ius.io"
|
moreHint = "get git: https://git-scm.com/downloads/linux and https://ius.io"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fmt.Errorf("installed git version %q is not supported, Gitea requires git version >= %q, %s", gitVersion.Original(), RequiredVersion, moreHint)
|
return fmt.Errorf("installed git version %q is not supported, Gitea requires git version >= %q, %s", gitVersion.Original(), RequiredVersion, moreHint)
|
||||||
|
|
|
@ -17,6 +17,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -30,7 +31,7 @@ type GrepResult struct {
|
||||||
type GrepOptions struct {
|
type GrepOptions struct {
|
||||||
RefName string
|
RefName string
|
||||||
MaxResultLimit int
|
MaxResultLimit int
|
||||||
MatchesPerFile int
|
MatchesPerFile int // >= git 2.38
|
||||||
ContextLineNumber int
|
ContextLineNumber int
|
||||||
IsFuzzy bool
|
IsFuzzy bool
|
||||||
PathSpec []setting.Glob
|
PathSpec []setting.Glob
|
||||||
|
@ -77,7 +78,14 @@ func GrepSearch(ctx context.Context, repo *Repository, search string, opts GrepO
|
||||||
"-I", "--null", "--break", "--heading", "--column",
|
"-I", "--null", "--break", "--heading", "--column",
|
||||||
"--fixed-strings", "--line-number", "--ignore-case", "--full-name")
|
"--fixed-strings", "--line-number", "--ignore-case", "--full-name")
|
||||||
cmd.AddOptionValues("--context", fmt.Sprint(opts.ContextLineNumber))
|
cmd.AddOptionValues("--context", fmt.Sprint(opts.ContextLineNumber))
|
||||||
cmd.AddOptionValues("--max-count", fmt.Sprint(opts.MatchesPerFile))
|
|
||||||
|
// --max-count requires at least git 2.38
|
||||||
|
if CheckGitVersionAtLeast("2.38.0") == nil {
|
||||||
|
cmd.AddOptionValues("--max-count", fmt.Sprint(opts.MatchesPerFile))
|
||||||
|
} else {
|
||||||
|
log.Warn("git-grep: --max-count requires at least git 2.38")
|
||||||
|
}
|
||||||
|
|
||||||
words := []string{search}
|
words := []string{search}
|
||||||
if opts.IsFuzzy {
|
if opts.IsFuzzy {
|
||||||
words = strings.Fields(search)
|
words = strings.Fields(search)
|
||||||
|
|
|
@ -254,7 +254,7 @@ func TestGitAttributeCheckerError(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
_, err = ac.CheckPath("i-am-a-python.p")
|
_, err = ac.CheckPath("i-am-a-python.p")
|
||||||
require.ErrorIs(t, err, context.Canceled)
|
require.Error(t, err)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Cancelled/DuringRun", func(t *testing.T) {
|
t.Run("Cancelled/DuringRun", func(t *testing.T) {
|
||||||
|
|
|
@ -96,7 +96,7 @@ func Code(fileName, language, code string) (output template.HTML, lexerName stri
|
||||||
}
|
}
|
||||||
|
|
||||||
if lexer == nil {
|
if lexer == nil {
|
||||||
lexer = lexers.Match(fileName)
|
lexer = lexers.Match(strings.ToLower(fileName))
|
||||||
if lexer == nil {
|
if lexer == nil {
|
||||||
lexer = lexers.Fallback
|
lexer = lexers.Fallback
|
||||||
}
|
}
|
||||||
|
@ -134,6 +134,12 @@ func CodeFromLexer(lexer chroma.Lexer, code string) template.HTML {
|
||||||
return template.HTML(strings.TrimSuffix(htmlbuf.String(), "\n"))
|
return template.HTML(strings.TrimSuffix(htmlbuf.String(), "\n"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For the case where Enry recognizes the language, but doesn't use the naming
|
||||||
|
// that Chroma expects.
|
||||||
|
var normalizeEnryToChroma = map[string]string{
|
||||||
|
"F#": "FSharp",
|
||||||
|
}
|
||||||
|
|
||||||
// File returns a slice of chroma syntax highlighted HTML lines of code and the matched lexer name
|
// File returns a slice of chroma syntax highlighted HTML lines of code and the matched lexer name
|
||||||
func File(fileName, language string, code []byte) ([]template.HTML, string, error) {
|
func File(fileName, language string, code []byte) ([]template.HTML, string, error) {
|
||||||
NewContext()
|
NewContext()
|
||||||
|
@ -162,10 +168,13 @@ func File(fileName, language string, code []byte) ([]template.HTML, string, erro
|
||||||
|
|
||||||
if lexer == nil {
|
if lexer == nil {
|
||||||
guessLanguage := analyze.GetCodeLanguage(fileName, code)
|
guessLanguage := analyze.GetCodeLanguage(fileName, code)
|
||||||
|
if normalizedGuessLanguage, ok := normalizeEnryToChroma[guessLanguage]; ok {
|
||||||
|
guessLanguage = normalizedGuessLanguage
|
||||||
|
}
|
||||||
|
|
||||||
lexer = lexers.Get(guessLanguage)
|
lexer = lexers.Get(guessLanguage)
|
||||||
if lexer == nil {
|
if lexer == nil {
|
||||||
lexer = lexers.Match(fileName)
|
lexer = lexers.Match(strings.ToLower(fileName))
|
||||||
if lexer == nil {
|
if lexer == nil {
|
||||||
lexer = lexers.Fallback
|
lexer = lexers.Fallback
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,6 +109,18 @@ c=2
|
||||||
),
|
),
|
||||||
lexerName: "Python",
|
lexerName: "Python",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "DOS.PAS",
|
||||||
|
code: "",
|
||||||
|
want: lines(""),
|
||||||
|
lexerName: "ObjectPascal",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "test.fs",
|
||||||
|
code: "module Crypt = let generateCryptTable: array<uint32> =",
|
||||||
|
want: lines(`<span class="k">module</span> <span class="nn">Crypt</span> <span class="o">=</span> <span class="k">let</span> <span class="nv">generateCryptTable</span><span class="o">:</span> <span class="n">array</span><span class="o"><</span><span class="kt">uint32</span><span class="o">></span> <span class="o">=</span>`),
|
||||||
|
lexerName: "FSharp",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
|
|
@ -76,7 +76,8 @@ func HandleGenericETagTimeCache(req *http.Request, w http.ResponseWriter, etag s
|
||||||
w.Header().Set("Etag", etag)
|
w.Header().Set("Etag", etag)
|
||||||
}
|
}
|
||||||
if lastModified != nil && !lastModified.IsZero() {
|
if lastModified != nil && !lastModified.IsZero() {
|
||||||
w.Header().Set("Last-Modified", lastModified.Format(http.TimeFormat))
|
// http.TimeFormat required a UTC time, refer to https://pkg.go.dev/net/http#TimeFormat
|
||||||
|
w.Header().Set("Last-Modified", lastModified.UTC().Format(http.TimeFormat))
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(etag) > 0 {
|
if len(etag) > 0 {
|
||||||
|
|
|
@ -79,6 +79,7 @@ func ServeSetHeaders(w http.ResponseWriter, opts *ServeHeaderOptions) {
|
||||||
httpcache.SetCacheControlInHeader(header, duration)
|
httpcache.SetCacheControlInHeader(header, duration)
|
||||||
|
|
||||||
if !opts.LastModified.IsZero() {
|
if !opts.LastModified.IsZero() {
|
||||||
|
// http.TimeFormat required a UTC time, refer to https://pkg.go.dev/net/http#TimeFormat
|
||||||
header.Set("Last-Modified", opts.LastModified.UTC().Format(http.TimeFormat))
|
header.Set("Last-Modified", opts.LastModified.UTC().Format(http.TimeFormat))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
indexer_internal "code.gitea.io/gitea/modules/indexer/internal"
|
indexer_internal "code.gitea.io/gitea/modules/indexer/internal"
|
||||||
inner_elasticsearch "code.gitea.io/gitea/modules/indexer/internal/elasticsearch"
|
inner_elasticsearch "code.gitea.io/gitea/modules/indexer/internal/elasticsearch"
|
||||||
"code.gitea.io/gitea/modules/json"
|
"code.gitea.io/gitea/modules/json"
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
"code.gitea.io/gitea/modules/typesniffer"
|
"code.gitea.io/gitea/modules/typesniffer"
|
||||||
|
@ -197,8 +198,33 @@ func (b *Indexer) Index(ctx context.Context, repo *repo_model.Repository, sha st
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete deletes indexes by ids
|
// Delete entries by repoId
|
||||||
func (b *Indexer) Delete(ctx context.Context, repoID int64) error {
|
func (b *Indexer) Delete(ctx context.Context, repoID int64) error {
|
||||||
|
if err := b.doDelete(ctx, repoID); err != nil {
|
||||||
|
// Maybe there is a conflict during the delete operation, so we should retry after a refresh
|
||||||
|
log.Warn("Deletion of entries of repo %v within index %v was erroneus. Trying to refresh index before trying again", repoID, b.inner.VersionedIndexName(), err)
|
||||||
|
if err := b.refreshIndex(ctx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := b.doDelete(ctx, repoID); err != nil {
|
||||||
|
log.Error("Could not delete entries of repo %v within index %v", repoID, b.inner.VersionedIndexName())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Indexer) refreshIndex(ctx context.Context) error {
|
||||||
|
if _, err := b.inner.Client.Refresh(b.inner.VersionedIndexName()).Do(ctx); err != nil {
|
||||||
|
log.Error("Error while trying to refresh index %v", b.inner.VersionedIndexName(), err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete entries by repoId
|
||||||
|
func (b *Indexer) doDelete(ctx context.Context, repoID int64) error {
|
||||||
_, err := b.inner.Client.DeleteByQuery(b.inner.VersionedIndexName()).
|
_, err := b.inner.Client.DeleteByQuery(b.inner.VersionedIndexName()).
|
||||||
Query(elastic.NewTermsQuery("repo_id", repoID)).
|
Query(elastic.NewTermsQuery("repo_id", repoID)).
|
||||||
Do(ctx)
|
Do(ctx)
|
||||||
|
|
|
@ -39,7 +39,7 @@ const (
|
||||||
// SanitizerRules implements markup.Renderer
|
// SanitizerRules implements markup.Renderer
|
||||||
func (Renderer) SanitizerRules() []setting.MarkupSanitizerRule {
|
func (Renderer) SanitizerRules() []setting.MarkupSanitizerRule {
|
||||||
return []setting.MarkupSanitizerRule{
|
return []setting.MarkupSanitizerRule{
|
||||||
{Element: "div", AllowAttr: "class", Regexp: regexp.MustCompile(playerClassName)},
|
{Element: "div", AllowAttr: "class", Regexp: regexp.MustCompile("^" + playerClassName + "$")},
|
||||||
{Element: "div", AllowAttr: playerSrcAttr},
|
{Element: "div", AllowAttr: playerSrcAttr},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ func camoHandleLink(link string) string {
|
||||||
if setting.Camo.Enabled {
|
if setting.Camo.Enabled {
|
||||||
lnkURL, err := url.Parse(link)
|
lnkURL, err := url.Parse(link)
|
||||||
if err == nil && lnkURL.IsAbs() && !strings.HasPrefix(link, setting.AppURL) &&
|
if err == nil && lnkURL.IsAbs() && !strings.HasPrefix(link, setting.AppURL) &&
|
||||||
(setting.Camo.Allways || lnkURL.Scheme != "https") {
|
(setting.Camo.Always || lnkURL.Scheme != "https") {
|
||||||
return CamoEncode(link)
|
return CamoEncode(link)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ func TestCamoHandleLink(t *testing.T) {
|
||||||
"https://image.proxy/eivin43gJwGVIjR9MiYYtFIk0mw/aHR0cDovL3Rlc3RpbWFnZXMub3JnL2ltZy5qcGc",
|
"https://image.proxy/eivin43gJwGVIjR9MiYYtFIk0mw/aHR0cDovL3Rlc3RpbWFnZXMub3JnL2ltZy5qcGc",
|
||||||
camoHandleLink("http://testimages.org/img.jpg"))
|
camoHandleLink("http://testimages.org/img.jpg"))
|
||||||
|
|
||||||
setting.Camo.Allways = true
|
setting.Camo.Always = true
|
||||||
assert.Equal(t,
|
assert.Equal(t,
|
||||||
"https://gitea.com/img.jpg",
|
"https://gitea.com/img.jpg",
|
||||||
camoHandleLink("https://gitea.com/img.jpg"))
|
camoHandleLink("https://gitea.com/img.jpg"))
|
||||||
|
|
|
@ -37,9 +37,9 @@ func (Renderer) Extensions() []string {
|
||||||
// SanitizerRules implements markup.Renderer
|
// SanitizerRules implements markup.Renderer
|
||||||
func (Renderer) SanitizerRules() []setting.MarkupSanitizerRule {
|
func (Renderer) SanitizerRules() []setting.MarkupSanitizerRule {
|
||||||
return []setting.MarkupSanitizerRule{
|
return []setting.MarkupSanitizerRule{
|
||||||
{Element: "table", AllowAttr: "class", Regexp: regexp.MustCompile(`data-table`)},
|
{Element: "table", AllowAttr: "class", Regexp: regexp.MustCompile(`^data-table$`)},
|
||||||
{Element: "th", AllowAttr: "class", Regexp: regexp.MustCompile(`line-num`)},
|
{Element: "th", AllowAttr: "class", Regexp: regexp.MustCompile(`^line-num$`)},
|
||||||
{Element: "td", AllowAttr: "class", Regexp: regexp.MustCompile(`line-num`)},
|
{Element: "td", AllowAttr: "class", Regexp: regexp.MustCompile(`^line-num$`)},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,14 @@ func (g *GitHubLegacyCalloutTransformer) Transform(node *ast.Document, reader te
|
||||||
attentionParagraph.AppendChild(attentionParagraph, calloutNode)
|
attentionParagraph.AppendChild(attentionParagraph, calloutNode)
|
||||||
firstParagraph.Parent().InsertBefore(firstParagraph.Parent(), firstParagraph, attentionParagraph)
|
firstParagraph.Parent().InsertBefore(firstParagraph.Parent(), firstParagraph, attentionParagraph)
|
||||||
firstParagraph.RemoveChild(firstParagraph, calloutNode)
|
firstParagraph.RemoveChild(firstParagraph, calloutNode)
|
||||||
|
|
||||||
|
// Remove softbreak line if there's one.
|
||||||
|
if firstParagraph.ChildCount() >= 1 {
|
||||||
|
softBreakNode, ok := firstParagraph.FirstChild().(*ast.Text)
|
||||||
|
if ok && softBreakNode.SoftLineBreak() {
|
||||||
|
firstParagraph.RemoveChild(firstParagraph, softBreakNode)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ast.WalkContinue, nil
|
return ast.WalkContinue, nil
|
||||||
|
|
|
@ -1356,4 +1356,10 @@ func TestCallout(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
test(">\n0", "<blockquote>\n</blockquote>\n<p>0</p>")
|
test(">\n0", "<blockquote>\n</blockquote>\n<p>0</p>")
|
||||||
|
test("> **Warning**\n> Bad stuff is brewing here", `<blockquote class="attention-header attention-warning"><p class="attention-title"><strong class="attention-warning">Warning</strong></p>
|
||||||
|
<p>Bad stuff is brewing here</p>
|
||||||
|
</blockquote>`)
|
||||||
|
test("> [!WARNING]\n> Bad stuff is brewing here", `<blockquote class="attention-header attention-warning"><p class="attention-title"><strong class="attention-warning">Warning</strong></p>
|
||||||
|
<p>Bad stuff is brewing here</p>
|
||||||
|
</blockquote>`)
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,10 +94,10 @@ func createDefaultPolicy() *bluemonday.Policy {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allow classes for anchors
|
// Allow classes for anchors
|
||||||
policy.AllowAttrs("class").Matching(regexp.MustCompile(`ref-issue( ref-external-issue)?`)).OnElements("a")
|
policy.AllowAttrs("class").Matching(regexp.MustCompile(`^ref-issue( ref-external-issue)?$`)).OnElements("a")
|
||||||
|
|
||||||
// Allow classes for task lists
|
// Allow classes for task lists
|
||||||
policy.AllowAttrs("class").Matching(regexp.MustCompile(`task-list-item`)).OnElements("li")
|
policy.AllowAttrs("class").Matching(regexp.MustCompile(`^task-list-item$`)).OnElements("li")
|
||||||
|
|
||||||
// Allow classes for org mode list item status.
|
// Allow classes for org mode list item status.
|
||||||
policy.AllowAttrs("class").Matching(regexp.MustCompile(`^(unchecked|checked|indeterminate)$`)).OnElements("li")
|
policy.AllowAttrs("class").Matching(regexp.MustCompile(`^(unchecked|checked|indeterminate)$`)).OnElements("li")
|
||||||
|
@ -106,7 +106,7 @@ func createDefaultPolicy() *bluemonday.Policy {
|
||||||
policy.AllowAttrs("class").Matching(regexp.MustCompile(`^icon(\s+[\p{L}\p{N}_-]+)+$`)).OnElements("i")
|
policy.AllowAttrs("class").Matching(regexp.MustCompile(`^icon(\s+[\p{L}\p{N}_-]+)+$`)).OnElements("i")
|
||||||
|
|
||||||
// Allow classes for emojis
|
// Allow classes for emojis
|
||||||
policy.AllowAttrs("class").Matching(regexp.MustCompile(`emoji`)).OnElements("img")
|
policy.AllowAttrs("class").Matching(regexp.MustCompile(`^emoji$`)).OnElements("img")
|
||||||
|
|
||||||
// Allow icons, emojis, chroma syntax and keyword markup on span
|
// Allow icons, emojis, chroma syntax and keyword markup on span
|
||||||
policy.AllowAttrs("class").Matching(regexp.MustCompile(`^((icon(\s+[\p{L}\p{N}_-]+)+)|(emoji)|(language-math display)|(language-math inline))$|^([a-z][a-z0-9]{0,2})$|^` + keywordClass + `$`)).OnElements("span")
|
policy.AllowAttrs("class").Matching(regexp.MustCompile(`^((icon(\s+[\p{L}\p{N}_-]+)+)|(emoji)|(language-math display)|(language-math inline))$|^([a-z][a-z0-9]{0,2})$|^` + keywordClass + `$`)).OnElements("span")
|
||||||
|
@ -122,13 +122,13 @@ func createDefaultPolicy() *bluemonday.Policy {
|
||||||
policy.AllowAttrs("class").Matching(regexp.MustCompile("^header$")).OnElements("div")
|
policy.AllowAttrs("class").Matching(regexp.MustCompile("^header$")).OnElements("div")
|
||||||
policy.AllowAttrs("data-line-number").Matching(regexp.MustCompile("^[0-9]+$")).OnElements("span")
|
policy.AllowAttrs("data-line-number").Matching(regexp.MustCompile("^[0-9]+$")).OnElements("span")
|
||||||
policy.AllowAttrs("class").Matching(regexp.MustCompile("^text small grey$")).OnElements("span")
|
policy.AllowAttrs("class").Matching(regexp.MustCompile("^text small grey$")).OnElements("span")
|
||||||
policy.AllowAttrs("class").Matching(regexp.MustCompile("^file-preview*")).OnElements("table")
|
policy.AllowAttrs("class").Matching(regexp.MustCompile("^file-preview$")).OnElements("table")
|
||||||
policy.AllowAttrs("class").Matching(regexp.MustCompile("^lines-escape$")).OnElements("td")
|
policy.AllowAttrs("class").Matching(regexp.MustCompile("^lines-escape$")).OnElements("td")
|
||||||
policy.AllowAttrs("class").Matching(regexp.MustCompile("^toggle-escape-button btn interact-bg$")).OnElements("button")
|
policy.AllowAttrs("class").Matching(regexp.MustCompile("^toggle-escape-button btn interact-bg$")).OnElements("button")
|
||||||
policy.AllowAttrs("title").OnElements("button")
|
policy.AllowAttrs("title").OnElements("button")
|
||||||
policy.AllowAttrs("class").Matching(regexp.MustCompile("^ambiguous-code-point$")).OnElements("span")
|
policy.AllowAttrs("class").Matching(regexp.MustCompile("^ambiguous-code-point$")).OnElements("span")
|
||||||
policy.AllowAttrs("data-tooltip-content").OnElements("span")
|
policy.AllowAttrs("data-tooltip-content").OnElements("span")
|
||||||
policy.AllowAttrs("class").Matching(regexp.MustCompile("muted|(text black)")).OnElements("a")
|
policy.AllowAttrs("class").Matching(regexp.MustCompile("^muted|(text black)$")).OnElements("a")
|
||||||
policy.AllowAttrs("class").Matching(regexp.MustCompile("^ui warning message tw-text-left$")).OnElements("div")
|
policy.AllowAttrs("class").Matching(regexp.MustCompile("^ui warning message tw-text-left$")).OnElements("div")
|
||||||
|
|
||||||
// Allow generally safe attributes
|
// Allow generally safe attributes
|
||||||
|
|
|
@ -39,8 +39,8 @@ const (
|
||||||
var (
|
var (
|
||||||
reName = regexp.MustCompile(`^[a-zA-Z0-9@._+-]+$`)
|
reName = regexp.MustCompile(`^[a-zA-Z0-9@._+-]+$`)
|
||||||
reVer = regexp.MustCompile(`^[a-zA-Z0-9:_.+]+-+[0-9]+$`)
|
reVer = regexp.MustCompile(`^[a-zA-Z0-9:_.+]+-+[0-9]+$`)
|
||||||
reOptDep = regexp.MustCompile(`^[a-zA-Z0-9@._+-]+([<>]?=?[a-zA-Z0-9@._+-]+)?(:.*)?$`)
|
reOptDep = regexp.MustCompile(`^[a-zA-Z0-9@._+-]+([<>]?=?([0-9]+:)?[a-zA-Z0-9@._+-]+)?(:.*)?$`)
|
||||||
rePkgVer = regexp.MustCompile(`^[a-zA-Z0-9@._+-]+([<>]?=?[a-zA-Z0-9@._+-]+)?$`)
|
rePkgVer = regexp.MustCompile(`^[a-zA-Z0-9@._+-]+([<>]?=?([0-9]+:)?[a-zA-Z0-9@._+-]+)?$`)
|
||||||
|
|
||||||
magicZSTD = []byte{0x28, 0xB5, 0x2F, 0xFD}
|
magicZSTD = []byte{0x28, 0xB5, 0x2F, 0xFD}
|
||||||
magicXZ = []byte{0xFD, 0x37, 0x7A, 0x58, 0x5A}
|
magicXZ = []byte{0xFD, 0x37, 0x7A, 0x58, 0x5A}
|
||||||
|
@ -71,7 +71,7 @@ type VersionMetadata struct {
|
||||||
Conflicts []string `json:"conflicts,omitempty"`
|
Conflicts []string `json:"conflicts,omitempty"`
|
||||||
Replaces []string `json:"replaces,omitempty"`
|
Replaces []string `json:"replaces,omitempty"`
|
||||||
Backup []string `json:"backup,omitempty"`
|
Backup []string `json:"backup,omitempty"`
|
||||||
Xdata []string `json:"xdata,omitempty"`
|
XData []string `json:"xdata,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// FileMetadata Metadata related to specific package file.
|
// FileMetadata Metadata related to specific package file.
|
||||||
|
@ -125,7 +125,7 @@ func ParsePackage(r *packages.HashedBuffer) (*Package, error) {
|
||||||
defer tarball.Close()
|
defer tarball.Close()
|
||||||
|
|
||||||
var pkg *Package
|
var pkg *Package
|
||||||
var mtree bool
|
var mTree bool
|
||||||
|
|
||||||
for {
|
for {
|
||||||
f, err := tarball.Read()
|
f, err := tarball.Read()
|
||||||
|
@ -135,24 +135,24 @@ func ParsePackage(r *packages.HashedBuffer) (*Package, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
switch f.Name() {
|
switch f.Name() {
|
||||||
case ".PKGINFO":
|
case ".PKGINFO":
|
||||||
pkg, err = ParsePackageInfo(tarballType, f)
|
pkg, err = ParsePackageInfo(tarballType, f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
_ = f.Close()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
case ".MTREE":
|
case ".MTREE":
|
||||||
mtree = true
|
mTree = true
|
||||||
}
|
}
|
||||||
|
_ = f.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
if pkg == nil {
|
if pkg == nil {
|
||||||
return nil, util.NewInvalidArgumentErrorf(".PKGINFO file not found")
|
return nil, util.NewInvalidArgumentErrorf(".PKGINFO file not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !mtree {
|
if !mTree {
|
||||||
return nil, util.NewInvalidArgumentErrorf(".MTREE file not found")
|
return nil, util.NewInvalidArgumentErrorf(".MTREE file not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,7 +220,7 @@ func ParsePackageInfo(compressType string, r io.Reader) (*Package, error) {
|
||||||
case "replaces":
|
case "replaces":
|
||||||
p.VersionMetadata.Replaces = append(p.VersionMetadata.Replaces, value)
|
p.VersionMetadata.Replaces = append(p.VersionMetadata.Replaces, value)
|
||||||
case "xdata":
|
case "xdata":
|
||||||
p.VersionMetadata.Xdata = append(p.VersionMetadata.Xdata, value)
|
p.VersionMetadata.XData = append(p.VersionMetadata.XData, value)
|
||||||
case "builddate":
|
case "builddate":
|
||||||
bd, err := strconv.ParseInt(value, 10, 64)
|
bd, err := strconv.ParseInt(value, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -260,48 +260,43 @@ func ValidatePackageSpec(p *Package) error {
|
||||||
return util.NewInvalidArgumentErrorf("invalid project URL")
|
return util.NewInvalidArgumentErrorf("invalid project URL")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, cd := range p.VersionMetadata.CheckDepends {
|
for _, checkDepend := range p.VersionMetadata.CheckDepends {
|
||||||
if !rePkgVer.MatchString(cd) {
|
if !rePkgVer.MatchString(checkDepend) {
|
||||||
return util.NewInvalidArgumentErrorf("invalid check dependency: %s", cd)
|
return util.NewInvalidArgumentErrorf("invalid check dependency: %s", checkDepend)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, d := range p.VersionMetadata.Depends {
|
for _, depend := range p.VersionMetadata.Depends {
|
||||||
if !rePkgVer.MatchString(d) {
|
if !rePkgVer.MatchString(depend) {
|
||||||
return util.NewInvalidArgumentErrorf("invalid dependency: %s", d)
|
return util.NewInvalidArgumentErrorf("invalid dependency: %s", depend)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, md := range p.VersionMetadata.MakeDepends {
|
for _, makeDepend := range p.VersionMetadata.MakeDepends {
|
||||||
if !rePkgVer.MatchString(md) {
|
if !rePkgVer.MatchString(makeDepend) {
|
||||||
return util.NewInvalidArgumentErrorf("invalid make dependency: %s", md)
|
return util.NewInvalidArgumentErrorf("invalid make dependency: %s", makeDepend)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, p := range p.VersionMetadata.Provides {
|
for _, provide := range p.VersionMetadata.Provides {
|
||||||
if !rePkgVer.MatchString(p) {
|
if !rePkgVer.MatchString(provide) {
|
||||||
return util.NewInvalidArgumentErrorf("invalid provides: %s", p)
|
return util.NewInvalidArgumentErrorf("invalid provides: %s", provide)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, p := range p.VersionMetadata.Conflicts {
|
for _, conflict := range p.VersionMetadata.Conflicts {
|
||||||
if !rePkgVer.MatchString(p) {
|
if !rePkgVer.MatchString(conflict) {
|
||||||
return util.NewInvalidArgumentErrorf("invalid conflicts: %s", p)
|
return util.NewInvalidArgumentErrorf("invalid conflicts: %s", conflict)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, p := range p.VersionMetadata.Replaces {
|
for _, replace := range p.VersionMetadata.Replaces {
|
||||||
if !rePkgVer.MatchString(p) {
|
if !rePkgVer.MatchString(replace) {
|
||||||
return util.NewInvalidArgumentErrorf("invalid replaces: %s", p)
|
return util.NewInvalidArgumentErrorf("invalid replaces: %s", replace)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, p := range p.VersionMetadata.Replaces {
|
for _, optDepend := range p.VersionMetadata.OptDepends {
|
||||||
if !rePkgVer.MatchString(p) {
|
if !reOptDep.MatchString(optDepend) {
|
||||||
return util.NewInvalidArgumentErrorf("invalid xdata: %s", p)
|
return util.NewInvalidArgumentErrorf("invalid optional dependency: %s", optDepend)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, od := range p.VersionMetadata.OptDepends {
|
for _, b := range p.VersionMetadata.Backup {
|
||||||
if !reOptDep.MatchString(od) {
|
if strings.HasPrefix(b, "/") {
|
||||||
return util.NewInvalidArgumentErrorf("invalid optional dependency: %s", od)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, bf := range p.VersionMetadata.Backup {
|
|
||||||
if strings.HasPrefix(bf, "/") {
|
|
||||||
return util.NewInvalidArgumentErrorf("backup file contains leading forward slash")
|
return util.NewInvalidArgumentErrorf("backup file contains leading forward slash")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,7 +96,7 @@ func parsePackage(r io.Reader) (*Package, error) {
|
||||||
Target *string `json:"target"`
|
Target *string `json:"target"`
|
||||||
Kind string `json:"kind"`
|
Kind string `json:"kind"`
|
||||||
Registry *string `json:"registry"`
|
Registry *string `json:"registry"`
|
||||||
ExplicitNameInToml string `json:"explicit_name_in_toml"`
|
ExplicitNameInToml *string `json:"explicit_name_in_toml"`
|
||||||
} `json:"deps"`
|
} `json:"deps"`
|
||||||
Features map[string][]string `json:"features"`
|
Features map[string][]string `json:"features"`
|
||||||
Authors []string `json:"authors"`
|
Authors []string `json:"authors"`
|
||||||
|
@ -136,8 +136,16 @@ func parsePackage(r io.Reader) (*Package, error) {
|
||||||
|
|
||||||
dependencies := make([]*Dependency, 0, len(meta.Deps))
|
dependencies := make([]*Dependency, 0, len(meta.Deps))
|
||||||
for _, dep := range meta.Deps {
|
for _, dep := range meta.Deps {
|
||||||
|
name := dep.Name
|
||||||
|
packageName := dep.ExplicitNameInToml
|
||||||
|
// If the explicit_name_in_toml field is set, the package is renamed and
|
||||||
|
// should be set accordingly.
|
||||||
|
if dep.ExplicitNameInToml != nil {
|
||||||
|
name = *dep.ExplicitNameInToml
|
||||||
|
packageName = &dep.Name
|
||||||
|
}
|
||||||
dependencies = append(dependencies, &Dependency{
|
dependencies = append(dependencies, &Dependency{
|
||||||
Name: dep.Name,
|
Name: name,
|
||||||
Req: dep.VersionReq,
|
Req: dep.VersionReq,
|
||||||
Features: dep.Features,
|
Features: dep.Features,
|
||||||
Optional: dep.Optional,
|
Optional: dep.Optional,
|
||||||
|
@ -145,6 +153,7 @@ func parsePackage(r io.Reader) (*Package, error) {
|
||||||
Target: dep.Target,
|
Target: dep.Target,
|
||||||
Kind: dep.Kind,
|
Kind: dep.Kind,
|
||||||
Registry: dep.Registry,
|
Registry: dep.Registry,
|
||||||
|
Package: packageName,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestParsePackage(t *testing.T) {
|
func TestParsePackage(t *testing.T) {
|
||||||
createPackage := func(name, version string) io.Reader {
|
createPackage := func(name, version, dependency string) io.Reader {
|
||||||
metadata := `{
|
metadata := `{
|
||||||
"name":"` + name + `",
|
"name":"` + name + `",
|
||||||
"vers":"` + version + `",
|
"vers":"` + version + `",
|
||||||
|
@ -32,7 +32,7 @@ func TestParsePackage(t *testing.T) {
|
||||||
{
|
{
|
||||||
"name":"dep",
|
"name":"dep",
|
||||||
"version_req":"1.0"
|
"version_req":"1.0"
|
||||||
}
|
}` + dependency + `
|
||||||
],
|
],
|
||||||
"homepage":"` + homepage + `",
|
"homepage":"` + homepage + `",
|
||||||
"license":"` + license + `"
|
"license":"` + license + `"
|
||||||
|
@ -48,7 +48,7 @@ func TestParsePackage(t *testing.T) {
|
||||||
|
|
||||||
t.Run("InvalidName", func(t *testing.T) {
|
t.Run("InvalidName", func(t *testing.T) {
|
||||||
for _, name := range []string{"", "0test", "-test", "_test", strings.Repeat("a", 65)} {
|
for _, name := range []string{"", "0test", "-test", "_test", strings.Repeat("a", 65)} {
|
||||||
data := createPackage(name, "1.0.0")
|
data := createPackage(name, "1.0.0", "")
|
||||||
|
|
||||||
cp, err := ParsePackage(data)
|
cp, err := ParsePackage(data)
|
||||||
assert.Nil(t, cp)
|
assert.Nil(t, cp)
|
||||||
|
@ -58,7 +58,7 @@ func TestParsePackage(t *testing.T) {
|
||||||
|
|
||||||
t.Run("InvalidVersion", func(t *testing.T) {
|
t.Run("InvalidVersion", func(t *testing.T) {
|
||||||
for _, version := range []string{"", "1.", "-1.0", "1.0.0/1"} {
|
for _, version := range []string{"", "1.", "-1.0", "1.0.0/1"} {
|
||||||
data := createPackage("test", version)
|
data := createPackage("test", version, "")
|
||||||
|
|
||||||
cp, err := ParsePackage(data)
|
cp, err := ParsePackage(data)
|
||||||
assert.Nil(t, cp)
|
assert.Nil(t, cp)
|
||||||
|
@ -67,7 +67,7 @@ func TestParsePackage(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Valid", func(t *testing.T) {
|
t.Run("Valid", func(t *testing.T) {
|
||||||
data := createPackage("test", "1.0.0")
|
data := createPackage("test", "1.0.0", "")
|
||||||
|
|
||||||
cp, err := ParsePackage(data)
|
cp, err := ParsePackage(data)
|
||||||
assert.NotNil(t, cp)
|
assert.NotNil(t, cp)
|
||||||
|
@ -84,4 +84,25 @@ func TestParsePackage(t *testing.T) {
|
||||||
content, _ := io.ReadAll(cp.Content)
|
content, _ := io.ReadAll(cp.Content)
|
||||||
assert.Equal(t, "test", string(content))
|
assert.Equal(t, "test", string(content))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("Renamed dependency", func(t *testing.T) {
|
||||||
|
data := createPackage("test", "1.0.0", `, {"name":"v4l2-sys", "version":"0.3.0", "explicit_name_in_toml":"v4l2-sys-mit"}`)
|
||||||
|
|
||||||
|
cp, err := ParsePackage(data)
|
||||||
|
assert.NotNil(t, cp)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, "test", cp.Name)
|
||||||
|
assert.Equal(t, "1.0.0", cp.Version)
|
||||||
|
assert.Equal(t, description, cp.Metadata.Description)
|
||||||
|
assert.Equal(t, []string{author}, cp.Metadata.Authors)
|
||||||
|
assert.Len(t, cp.Metadata.Dependencies, 2)
|
||||||
|
assert.Equal(t, "dep", cp.Metadata.Dependencies[0].Name)
|
||||||
|
assert.EqualValues(t, "v4l2-sys-mit", cp.Metadata.Dependencies[1].Name)
|
||||||
|
assert.EqualValues(t, "v4l2-sys", *cp.Metadata.Dependencies[1].Package)
|
||||||
|
assert.Equal(t, homepage, cp.Metadata.ProjectURL)
|
||||||
|
assert.Equal(t, license, cp.Metadata.License)
|
||||||
|
content, _ := io.ReadAll(cp.Content)
|
||||||
|
assert.Equal(t, "test", string(content))
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,7 @@ type Metadata struct {
|
||||||
Homepage string `json:"homepage,omitempty"`
|
Homepage string `json:"homepage,omitempty"`
|
||||||
License Licenses `json:"license,omitempty"`
|
License Licenses `json:"license,omitempty"`
|
||||||
Authors []Author `json:"authors,omitempty"`
|
Authors []Author `json:"authors,omitempty"`
|
||||||
|
Bin []string `json:"bin,omitempty"`
|
||||||
Autoload map[string]any `json:"autoload,omitempty"`
|
Autoload map[string]any `json:"autoload,omitempty"`
|
||||||
AutoloadDev map[string]any `json:"autoload-dev,omitempty"`
|
AutoloadDev map[string]any `json:"autoload-dev,omitempty"`
|
||||||
Extra map[string]any `json:"extra,omitempty"`
|
Extra map[string]any `json:"extra,omitempty"`
|
||||||
|
|
|
@ -3,18 +3,28 @@
|
||||||
|
|
||||||
package setting
|
package setting
|
||||||
|
|
||||||
import "code.gitea.io/gitea/modules/log"
|
import (
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
)
|
||||||
|
|
||||||
var Camo = struct {
|
var Camo = struct {
|
||||||
Enabled bool
|
Enabled bool
|
||||||
ServerURL string `ini:"SERVER_URL"`
|
ServerURL string `ini:"SERVER_URL"`
|
||||||
HMACKey string `ini:"HMAC_KEY"`
|
HMACKey string `ini:"HMAC_KEY"`
|
||||||
Allways bool
|
Always bool
|
||||||
}{}
|
}{}
|
||||||
|
|
||||||
func loadCamoFrom(rootCfg ConfigProvider) {
|
func loadCamoFrom(rootCfg ConfigProvider) {
|
||||||
mustMapSetting(rootCfg, "camo", &Camo)
|
mustMapSetting(rootCfg, "camo", &Camo)
|
||||||
if Camo.Enabled {
|
if Camo.Enabled {
|
||||||
|
oldValue := rootCfg.Section("camo").Key("ALLWAYS").MustString("")
|
||||||
|
if oldValue != "" {
|
||||||
|
log.Warn("camo.ALLWAYS is deprecated, use camo.ALWAYS instead")
|
||||||
|
Camo.Always, _ = strconv.ParseBool(oldValue)
|
||||||
|
}
|
||||||
|
|
||||||
if Camo.ServerURL == "" || Camo.HMACKey == "" {
|
if Camo.ServerURL == "" || Camo.HMACKey == "" {
|
||||||
log.Fatal(`Camo settings require "SERVER_URL" and HMAC_KEY`)
|
log.Fatal(`Camo settings require "SERVER_URL" and HMAC_KEY`)
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,6 +88,7 @@ var UI = struct {
|
||||||
Reactions: []string{`+1`, `-1`, `laugh`, `hooray`, `confused`, `heart`, `rocket`, `eyes`},
|
Reactions: []string{`+1`, `-1`, `laugh`, `hooray`, `confused`, `heart`, `rocket`, `eyes`},
|
||||||
CustomEmojis: []string{`git`, `gitea`, `codeberg`, `gitlab`, `github`, `gogs`, `forgejo`},
|
CustomEmojis: []string{`git`, `gitea`, `codeberg`, `gitlab`, `github`, `gogs`, `forgejo`},
|
||||||
CustomEmojisMap: map[string]string{"git": ":git:", "gitea": ":gitea:", "codeberg": ":codeberg:", "gitlab": ":gitlab:", "github": ":github:", "gogs": ":gogs:", "forgejo": ":forgejo:"},
|
CustomEmojisMap: map[string]string{"git": ":git:", "gitea": ":gitea:", "codeberg": ":codeberg:", "gitlab": ":gitlab:", "github": ":github:", "gogs": ":gogs:", "forgejo": ":forgejo:"},
|
||||||
|
ExploreDefaultSort: "recentupdate",
|
||||||
PreferredTimestampTense: "mixed",
|
PreferredTimestampTense: "mixed",
|
||||||
|
|
||||||
AmbiguousUnicodeDetection: true,
|
AmbiguousUnicodeDetection: true,
|
||||||
|
|
|
@ -11,7 +11,6 @@ import (
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/pem"
|
"encoding/pem"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
@ -33,10 +32,6 @@ import (
|
||||||
gossh "golang.org/x/crypto/ssh"
|
gossh "golang.org/x/crypto/ssh"
|
||||||
)
|
)
|
||||||
|
|
||||||
type contextKey string
|
|
||||||
|
|
||||||
const giteaKeyID = contextKey("gitea-key-id")
|
|
||||||
|
|
||||||
func getExitStatusFromError(err error) int {
|
func getExitStatusFromError(err error) int {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return 0
|
return 0
|
||||||
|
@ -62,7 +57,7 @@ func getExitStatusFromError(err error) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
func sessionHandler(session ssh.Session) {
|
func sessionHandler(session ssh.Session) {
|
||||||
keyID := fmt.Sprintf("%d", session.Context().Value(giteaKeyID).(int64))
|
keyID := session.ConnPermissions().Extensions["forgejo-key-id"]
|
||||||
|
|
||||||
command := session.RawCommand()
|
command := session.RawCommand()
|
||||||
|
|
||||||
|
@ -238,7 +233,10 @@ func publicKeyHandler(ctx ssh.Context, key ssh.PublicKey) bool {
|
||||||
if log.IsDebug() { // <- FingerprintSHA256 is kinda expensive so only calculate it if necessary
|
if log.IsDebug() { // <- FingerprintSHA256 is kinda expensive so only calculate it if necessary
|
||||||
log.Debug("Successfully authenticated: %s Certificate Fingerprint: %s Principal: %s", ctx.RemoteAddr(), gossh.FingerprintSHA256(key), principal)
|
log.Debug("Successfully authenticated: %s Certificate Fingerprint: %s Principal: %s", ctx.RemoteAddr(), gossh.FingerprintSHA256(key), principal)
|
||||||
}
|
}
|
||||||
ctx.SetValue(giteaKeyID, pkey.ID)
|
if ctx.Permissions().Extensions == nil {
|
||||||
|
ctx.Permissions().Extensions = map[string]string{}
|
||||||
|
}
|
||||||
|
ctx.Permissions().Extensions["forgejo-key-id"] = strconv.FormatInt(pkey.ID, 10)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -266,7 +264,10 @@ func publicKeyHandler(ctx ssh.Context, key ssh.PublicKey) bool {
|
||||||
if log.IsDebug() { // <- FingerprintSHA256 is kinda expensive so only calculate it if necessary
|
if log.IsDebug() { // <- FingerprintSHA256 is kinda expensive so only calculate it if necessary
|
||||||
log.Debug("Successfully authenticated: %s Public Key Fingerprint: %s", ctx.RemoteAddr(), gossh.FingerprintSHA256(key))
|
log.Debug("Successfully authenticated: %s Public Key Fingerprint: %s", ctx.RemoteAddr(), gossh.FingerprintSHA256(key))
|
||||||
}
|
}
|
||||||
ctx.SetValue(giteaKeyID, pkey.ID)
|
if ctx.Permissions().Extensions == nil {
|
||||||
|
ctx.Permissions().Extensions = map[string]string{}
|
||||||
|
}
|
||||||
|
ctx.Permissions().Extensions["forgejo-key-id"] = strconv.FormatInt(pkey.ID, 10)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -362,6 +362,7 @@ type IssuePayload struct {
|
||||||
Repository *Repository `json:"repository"`
|
Repository *Repository `json:"repository"`
|
||||||
Sender *User `json:"sender"`
|
Sender *User `json:"sender"`
|
||||||
CommitID string `json:"commit_id"`
|
CommitID string `json:"commit_id"`
|
||||||
|
Label *Label `json:"label,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// JSONPayload encodes the IssuePayload to JSON, with an indentation of two spaces.
|
// JSONPayload encodes the IssuePayload to JSON, with an indentation of two spaces.
|
||||||
|
@ -399,6 +400,7 @@ type PullRequestPayload struct {
|
||||||
Sender *User `json:"sender"`
|
Sender *User `json:"sender"`
|
||||||
CommitID string `json:"commit_id"`
|
CommitID string `json:"commit_id"`
|
||||||
Review *ReviewPayload `json:"review"`
|
Review *ReviewPayload `json:"review"`
|
||||||
|
Label *Label `json:"label,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// JSONPayload FIXME
|
// JSONPayload FIXME
|
||||||
|
|
|
@ -34,7 +34,7 @@ func AvatarHTML(src string, size int, class, name string) template.HTML {
|
||||||
name = "avatar"
|
name = "avatar"
|
||||||
}
|
}
|
||||||
|
|
||||||
return template.HTML(`<img class="` + class + `" src="` + src + `" title="` + html.EscapeString(name) + `" width="` + sizeStr + `" height="` + sizeStr + `"/>`)
|
return template.HTML(`<img loading="lazy" class="` + class + `" src="` + src + `" title="` + html.EscapeString(name) + `" width="` + sizeStr + `" height="` + sizeStr + `"/>`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Avatar renders user avatars. args: user, size (int), class (string)
|
// Avatar renders user avatars. args: user, size (int), class (string)
|
||||||
|
|
|
@ -131,6 +131,8 @@ var ignoredErrorMessage = []string{
|
||||||
`:SSHLog() [E] ssh: Not allowed to push to protected branch protected. HookPreReceive(last) failed: internal API error response, status=403`,
|
`:SSHLog() [E] ssh: Not allowed to push to protected branch protected. HookPreReceive(last) failed: internal API error response, status=403`,
|
||||||
// TestGit/HTTP/BranchProtectMerge
|
// TestGit/HTTP/BranchProtectMerge
|
||||||
`:SSHLog() [E] ssh: branch protected is protected from force push. HookPreReceive(last) failed: internal API error response, status=403`,
|
`:SSHLog() [E] ssh: branch protected is protected from force push. HookPreReceive(last) failed: internal API error response, status=403`,
|
||||||
|
// TestGit/HTTP/BranchProtect
|
||||||
|
`:SSHLog() [E] ssh: branch before-create-2 is protected from changing file protected-file-data-`,
|
||||||
// TestGit/HTTP/MergeFork/CreatePRAndMerge
|
// TestGit/HTTP/MergeFork/CreatePRAndMerge
|
||||||
`:DeleteBranchPost() [E] DeleteBranch: GetBranch: branch does not exist [repo_id: 1099 name: user2:master]`, // sqlite
|
`:DeleteBranchPost() [E] DeleteBranch: GetBranch: branch does not exist [repo_id: 1099 name: user2:master]`, // sqlite
|
||||||
"s/web/repo/branch.go:108:DeleteBranchPost() [E] DeleteBranch: GetBranch: branch does not exist [repo_id: 10000 name: user2:master]", // mysql
|
"s/web/repo/branch.go:108:DeleteBranchPost() [E] DeleteBranch: GetBranch: branch does not exist [repo_id: 10000 name: user2:master]", // mysql
|
||||||
|
|
|
@ -225,6 +225,15 @@ func Iif[T any](condition bool, trueVal, falseVal T) T {
|
||||||
return falseVal
|
return falseVal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IfZero returns "def" if "v" is a zero value, otherwise "v"
|
||||||
|
func IfZero[T comparable](v, def T) T {
|
||||||
|
var zero T
|
||||||
|
if v == zero {
|
||||||
|
return def
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
func ReserveLineBreakForTextarea(input string) string {
|
func ReserveLineBreakForTextarea(input string) string {
|
||||||
// Since the content is from a form which is a textarea, the line endings are \r\n.
|
// Since the content is from a form which is a textarea, the line endings are \r\n.
|
||||||
// It's a standard behavior of HTML.
|
// It's a standard behavior of HTML.
|
||||||
|
|
|
@ -1,6 +1,3 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[common]
|
[common]
|
||||||
language = لغة
|
language = لغة
|
||||||
passcode = رمز المرور
|
passcode = رمز المرور
|
||||||
|
@ -142,6 +139,11 @@ filter.not_fork = ليست اشتقاقات
|
||||||
filter.not_archived = ليس مؤرشف
|
filter.not_archived = ليس مؤرشف
|
||||||
filter.public = علني
|
filter.public = علني
|
||||||
filter.private = خاص
|
filter.private = خاص
|
||||||
|
new_repo.title = مستودع جديد
|
||||||
|
new_migrate.title = انتقال جديد
|
||||||
|
new_org.title = منظمة جديدة
|
||||||
|
new_repo.link = مستودع جديد
|
||||||
|
new_migrate.link = انتقال جديد
|
||||||
|
|
||||||
[install]
|
[install]
|
||||||
db_name = اسم قاعدة البيانات
|
db_name = اسم قاعدة البيانات
|
||||||
|
@ -1100,7 +1102,7 @@ activity.git_stats_pushed_1 = دفع
|
||||||
activity.git_stats_pushed_n = دفعوا
|
activity.git_stats_pushed_n = دفعوا
|
||||||
activity.git_stats_commit_1 = %d إيداع
|
activity.git_stats_commit_1 = %d إيداع
|
||||||
activity.git_stats_commit_n = %d إيداعا
|
activity.git_stats_commit_n = %d إيداعا
|
||||||
activity.git_stats_push_to_branch = إلى %s و
|
activity.git_stats_push_to_branch = `إلى %s و"`
|
||||||
activity.git_stats_push_to_all_branches = إلى كل الفروع.
|
activity.git_stats_push_to_all_branches = إلى كل الفروع.
|
||||||
activity.git_stats_on_default_branch = في %s،
|
activity.git_stats_on_default_branch = في %s،
|
||||||
activity.git_stats_file_1 = %d ملف
|
activity.git_stats_file_1 = %d ملف
|
||||||
|
@ -1110,7 +1112,7 @@ activity.git_stats_files_changed_n = تغيّروا
|
||||||
activity.git_stats_additions = وحدثت
|
activity.git_stats_additions = وحدثت
|
||||||
activity.git_stats_addition_1 = %d إضافة
|
activity.git_stats_addition_1 = %d إضافة
|
||||||
activity.git_stats_addition_n = %d إضافة
|
activity.git_stats_addition_n = %d إضافة
|
||||||
activity.git_stats_and_deletions = و
|
activity.git_stats_and_deletions = `و"`
|
||||||
activity.git_stats_deletion_1 = %d إزالة
|
activity.git_stats_deletion_1 = %d إزالة
|
||||||
activity.git_stats_deletion_n = %d إزالة
|
activity.git_stats_deletion_n = %d إزالة
|
||||||
settings.mirror_settings.direction = الاتجاه
|
settings.mirror_settings.direction = الاتجاه
|
||||||
|
@ -1982,4 +1984,10 @@ match_tooltip = قم بتضمين النتائج التي تطابق مصطلح
|
||||||
repo_kind = بحث في المستودعات...
|
repo_kind = بحث في المستودعات...
|
||||||
user_kind = بحث عن المستخدمين...
|
user_kind = بحث عن المستخدمين...
|
||||||
team_kind = بحث عن الفرق ...
|
team_kind = بحث عن الفرق ...
|
||||||
code_kind = بحث في الكود...
|
code_kind = بحث في الكود...
|
||||||
|
project_kind = البحث ضمن المشاريع...
|
||||||
|
branch_kind = البحث ضمن الفروع...
|
||||||
|
no_results = لا توجد نتائج مطابقة.
|
||||||
|
issue_kind = البحث ضمن الأعطال...
|
||||||
|
pull_kind = البحث ضمن طلبات السحب...
|
||||||
|
keyword_search_unavailable = البحث من خلال الكلمات المفتاحية ليس متوفر حالياً. رجاءاً تواصل مع مشرف الموقع.
|
|
@ -168,6 +168,7 @@ versions.view_all = Вижте всички
|
||||||
dependencies = Зависимости
|
dependencies = Зависимости
|
||||||
published_by_in = Публикуван %[1]s от <a href="%[2]s">%[3]s</a> в <a href="%[4]s"><strong>%[5]s</strong></a>
|
published_by_in = Публикуван %[1]s от <a href="%[2]s">%[3]s</a> в <a href="%[4]s"><strong>%[5]s</strong></a>
|
||||||
published_by = Публикуван %[1]s от <a href="%[2]s">%[3]s</a>
|
published_by = Публикуван %[1]s от <a href="%[2]s">%[3]s</a>
|
||||||
|
generic.download = Изтеглете пакета от командния ред:
|
||||||
|
|
||||||
[tool]
|
[tool]
|
||||||
hours = %d часа
|
hours = %d часа
|
||||||
|
@ -632,9 +633,9 @@ editor.file_delete_success = Файлът „%s“ е изтрит.
|
||||||
projects.type.uncategorized = Некатегоризирано
|
projects.type.uncategorized = Некатегоризирано
|
||||||
projects.column.set_default = Задаване по подразбиране
|
projects.column.set_default = Задаване по подразбиране
|
||||||
projects.column.assigned_to = Възложено на
|
projects.column.assigned_to = Възложено на
|
||||||
issues.reopen_comment_issue = Коментиране и отваряне
|
issues.reopen_comment_issue = Отваряне наново с коментар
|
||||||
issues.reopen_issue = Отваряне наново
|
issues.reopen_issue = Отваряне наново
|
||||||
issues.close_comment_issue = Коментиране и Затваряне
|
issues.close_comment_issue = Затваряне с коментар
|
||||||
milestones.filter_sort.latest_due_date = Най-далечен краен срок
|
milestones.filter_sort.latest_due_date = Най-далечен краен срок
|
||||||
diff.view_file = Преглед на файла
|
diff.view_file = Преглед на файла
|
||||||
release.deletion_success = Изданието е изтрито.
|
release.deletion_success = Изданието е изтрито.
|
||||||
|
@ -940,7 +941,7 @@ pulls.approve_count_1 = %d одобрение
|
||||||
pulls.can_auto_merge_desc = Тази заявка за сливане може да бъде слята автоматично.
|
pulls.can_auto_merge_desc = Тази заявка за сливане може да бъде слята автоматично.
|
||||||
pulls.num_conflicting_files_1 = %d конфликтен файл
|
pulls.num_conflicting_files_1 = %d конфликтен файл
|
||||||
activity.git_stats_commit_n = %d подавания
|
activity.git_stats_commit_n = %d подавания
|
||||||
settings.event_issues = Задачи
|
settings.event_issues = Модификация
|
||||||
branch.delete_head = Изтриване
|
branch.delete_head = Изтриване
|
||||||
branch.delete = Изтриване на клона „%s“
|
branch.delete = Изтриване на клона „%s“
|
||||||
branch.delete_html = Изтриване на клона
|
branch.delete_html = Изтриване на клона
|
||||||
|
@ -1020,7 +1021,7 @@ pulls.title_desc_one = иска да слее %[1]d подаване от <code>
|
||||||
pulls.showing_specified_commit_range = Показани са само промените между %[1]s..%[2]s
|
pulls.showing_specified_commit_range = Показани са само промените между %[1]s..%[2]s
|
||||||
pulls.merged_title_desc_one = сля %[1]d подаване от <code>%[2]s</code> в <code>%[3]s</code> %[4]s
|
pulls.merged_title_desc_one = сля %[1]d подаване от <code>%[2]s</code> в <code>%[3]s</code> %[4]s
|
||||||
pulls.no_merge_access = Не сте упълномощени за сливане на тази заявка за сливане.
|
pulls.no_merge_access = Не сте упълномощени за сливане на тази заявка за сливане.
|
||||||
activity.navbar.code_frequency = Честота на кода
|
activity.navbar.code_frequency = Честота на промените
|
||||||
activity.git_stats_pushed_1 = е изтласкал
|
activity.git_stats_pushed_1 = е изтласкал
|
||||||
activity.git_stats_push_to_branch = към %s и
|
activity.git_stats_push_to_branch = към %s и
|
||||||
contributors.contribution_type.commits = Подавания
|
contributors.contribution_type.commits = Подавания
|
||||||
|
@ -1081,11 +1082,11 @@ pulls.commit_ref_at = `спомена тази заявка за сливане
|
||||||
issues.change_ref_at = `промени препратката от <b><strike>%s</strike></b> на <b>%s</b> %s`
|
issues.change_ref_at = `промени препратката от <b><strike>%s</strike></b> на <b>%s</b> %s`
|
||||||
diff.review.reject = Поискване на промени
|
diff.review.reject = Поискване на промени
|
||||||
diff.bin_not_shown = Двоичният файл не е показан.
|
diff.bin_not_shown = Двоичният файл не е показан.
|
||||||
settings.units.units = Елементи на хранилището
|
settings.units.units = Елементи
|
||||||
settings.delete_notices_fork_1 = - Разклоненията на това хранилище ще станат независими след изтриване.
|
settings.delete_notices_fork_1 = - Разклоненията на това хранилище ще станат независими след изтриване.
|
||||||
settings.actions_desc = Включване на интегрираните CI/CD pipelines с Forgejo Actions
|
settings.actions_desc = Включване на интегрираните CI/CD pipelines с Forgejo Actions
|
||||||
settings.packages_desc = Включване на регистъра на пакетите за хранилището
|
settings.packages_desc = Включване на регистъра на пакетите за хранилището
|
||||||
settings.units.add_more = Добавяне...
|
settings.units.add_more = Включване на повече
|
||||||
settings.use_external_issue_tracker = Използване на външен тракер за задачи
|
settings.use_external_issue_tracker = Използване на външен тракер за задачи
|
||||||
settings.releases_desc = Включване на изданията за хранилището
|
settings.releases_desc = Включване на изданията за хранилището
|
||||||
settings.projects_desc = Включване на проектите за хранилището
|
settings.projects_desc = Включване на проектите за хранилището
|
||||||
|
@ -1183,6 +1184,19 @@ diff.hide_file_tree = Скриване на файловото дърво
|
||||||
tag.ahead.target = в %s след този маркер
|
tag.ahead.target = в %s след този маркер
|
||||||
diff.file_image_width = Широчина
|
diff.file_image_width = Широчина
|
||||||
activity.unresolved_conv_label = Отворено
|
activity.unresolved_conv_label = Отворено
|
||||||
|
invisible_runes_line = `Този ред съдържа невидими Уникод знаци`
|
||||||
|
code.desc = Достъп до програмния код, файловете, подаванията и клоновете.
|
||||||
|
settings.branches.update_default_branch = Обновяване на стандартния клон
|
||||||
|
settings.default_branch_desc = Изберете стандартен клон за хранилището, за заявки за сливане и подавания на код:
|
||||||
|
settings.transfer.button = Прехвърляне на притежанието
|
||||||
|
settings.transfer.modal.title = Прехвърляне на притежанието
|
||||||
|
ambiguous_runes_line = `Този ред съдържа двусмислени Уникод знаци`
|
||||||
|
ambiguous_character = `%[1]c [U+%04[1]X] може да бъде объркан с %[2]c [U+%04[2]X]`
|
||||||
|
invisible_runes_header = `Този файл съдържа невидими Уникод знаци`
|
||||||
|
issues.all_title = Общо
|
||||||
|
issues.new.assign_to_me = Възлагане на мен
|
||||||
|
ext_wiki = Външно уики
|
||||||
|
ext_issues = Външни задачи
|
||||||
|
|
||||||
[modal]
|
[modal]
|
||||||
confirm = Потвърждаване
|
confirm = Потвърждаване
|
||||||
|
@ -1279,6 +1293,7 @@ members.member = Участник
|
||||||
members.private_helper = Да е видим
|
members.private_helper = Да е видим
|
||||||
teams.no_desc = Този екип няма описание
|
teams.no_desc = Този екип няма описание
|
||||||
settings.delete_org_desc = Тази организация ще бъде изтрита перманентно. Продължаване?
|
settings.delete_org_desc = Тази организация ще бъде изтрита перманентно. Продължаване?
|
||||||
|
open_dashboard = Отваряне на таблото
|
||||||
|
|
||||||
[install]
|
[install]
|
||||||
admin_password = Парола
|
admin_password = Парола
|
||||||
|
@ -1378,6 +1393,7 @@ followers.title.few = Последователи
|
||||||
followers.title.one = Последовател
|
followers.title.one = Последовател
|
||||||
following.title.one = Следван
|
following.title.one = Следван
|
||||||
following.title.few = Следвани
|
following.title.few = Следвани
|
||||||
|
public_activity.visibility_hint.self_public = Вашата дейност е видима за всички, с изключение на взаимодействията в частни пространства. <a href="%s">Конфигуриране</a>.
|
||||||
|
|
||||||
[home]
|
[home]
|
||||||
filter = Други филтри
|
filter = Други филтри
|
||||||
|
@ -1544,6 +1560,8 @@ push_tag = изтласка маркер <a href="%[2]s">%[3]s</a> към <a hre
|
||||||
approve_pull_request = `одобри <a href="%[1]s">%[3]s#%[2]s</a>`
|
approve_pull_request = `одобри <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||||
reject_pull_request = `предложи промени за <a href="%[1]s">%[3]s#%[2]s</a>`
|
reject_pull_request = `предложи промени за <a href="%[1]s">%[3]s#%[2]s</a>`
|
||||||
compare_branch = Сравняване
|
compare_branch = Сравняване
|
||||||
|
compare_commits_general = Сравняване на подавания
|
||||||
|
compare_commits = Сравнете %d подавания
|
||||||
|
|
||||||
[auth]
|
[auth]
|
||||||
tab_openid = OpenID
|
tab_openid = OpenID
|
||||||
|
@ -1572,6 +1590,12 @@ tab_signin = Влизане
|
||||||
tab_signup = Регистриране
|
tab_signup = Регистриране
|
||||||
password_pwned = Паролата, която сте избрали, е в <a target="_blank" rel="noopener noreferrer" href="%s">списък с откраднати пароли</a>, разкрити преди това при публични пробиви на данни. Моля, опитайте отново с различна парола.
|
password_pwned = Паролата, която сте избрали, е в <a target="_blank" rel="noopener noreferrer" href="%s">списък с откраднати пароли</a>, разкрити преди това при публични пробиви на данни. Моля, опитайте отново с различна парола.
|
||||||
confirmation_mail_sent_prompt = Ново ел. писмо за потвърждение е изпратено до <b>%s</b>. За да завършите процеса на регистрация, моля, проверете входящата си кутия и последвайте предоставената връзка в рамките на следващите %s. Ако адресът за ел. поща е неправилен, можете да влезете и да поискате друго ел. писмо за потвърждение да бъде изпратено на различен адрес.
|
confirmation_mail_sent_prompt = Ново ел. писмо за потвърждение е изпратено до <b>%s</b>. За да завършите процеса на регистрация, моля, проверете входящата си кутия и последвайте предоставената връзка в рамките на следващите %s. Ако адресът за ел. поща е неправилен, можете да влезете и да поискате друго ел. писмо за потвърждение да бъде изпратено на различен адрес.
|
||||||
|
hint_login = Вече имате акаунт? <a href="%s">Влезте!</a>
|
||||||
|
hint_register = Нуждаете се от акаунт? <a href="%s">Регистрирайте се.</a>
|
||||||
|
sign_up_button = Регистрирайте се.
|
||||||
|
back_to_sign_in = Назад към Вход
|
||||||
|
sign_in_openid = Продължаване с OpenID
|
||||||
|
send_reset_mail = Изпращане на ел. писмо за възстановяване
|
||||||
|
|
||||||
[aria]
|
[aria]
|
||||||
footer.software = Относно този софтуер
|
footer.software = Относно този софтуер
|
||||||
|
@ -1582,7 +1606,7 @@ footer = Долен колонтитул
|
||||||
install = Лесен за инсталиране
|
install = Лесен за инсталиране
|
||||||
lightweight = Лек
|
lightweight = Лек
|
||||||
license = Отворен код
|
license = Отворен код
|
||||||
install_desc = Просто <a target="_blank" rel="noopener noreferrer" href="%[1]s">стартирайте двоичния файл</a> за вашата платформа, използвайте <a target="_blank" rel="noopener noreferrer" href="%[2]s">Docker</a>, или го получете <a target="_blank" rel="noopener noreferrer" href="%[3]s">пакетирано</a>.
|
install_desc = Просто <a target="_blank" rel="noopener noreferrer" href="%[1]s">стартирайте двоичния файл</a> за вашата платформа, използвайте <a target="_blank" rel="noopener noreferrer" href="%[2]s">Docker</a>, или го получете <a target="_blank" rel="noopener noreferrer" href="%[3]s">пакетиран</a>.
|
||||||
app_desc = Безпроблемна Git услуга със самостоятелен хостинг
|
app_desc = Безпроблемна Git услуга със самостоятелен хостинг
|
||||||
platform = Междуплатформен
|
platform = Междуплатформен
|
||||||
lightweight_desc = Forgejo има ниски минимални изисквания и може да работи на икономичен Raspberry Pi. Спестете енергията на вашата машина!
|
lightweight_desc = Forgejo има ниски минимални изисквания и може да работи на икономичен Raspberry Pi. Спестете енергията на вашата машина!
|
||||||
|
@ -1670,6 +1694,7 @@ contributors.what = приноси
|
||||||
recent_commits.what = скорошни подавания
|
recent_commits.what = скорошни подавания
|
||||||
component_loading = Зареждане на %s...
|
component_loading = Зареждане на %s...
|
||||||
component_loading_info = Това може да отнеме известно време…
|
component_loading_info = Това може да отнеме известно време…
|
||||||
|
code_frequency.what = честота на промените
|
||||||
|
|
||||||
[projects]
|
[projects]
|
||||||
type-1.display_name = Индивидуален проект
|
type-1.display_name = Индивидуален проект
|
||||||
|
|
|
@ -5,7 +5,7 @@ explore=Procházet
|
||||||
help=Nápověda
|
help=Nápověda
|
||||||
logo=Logo
|
logo=Logo
|
||||||
sign_in=Přihlášení
|
sign_in=Přihlášení
|
||||||
sign_in_with_provider=Přihlásit se pomocí %s
|
sign_in_with_provider = Přihlásit se přes %s
|
||||||
sign_in_or=nebo
|
sign_in_or=nebo
|
||||||
sign_out=Odhlásit se
|
sign_out=Odhlásit se
|
||||||
sign_up=Registrace
|
sign_up=Registrace
|
||||||
|
@ -23,7 +23,7 @@ create_new=Vytvořit…
|
||||||
user_profile_and_more=Profil a nastavení…
|
user_profile_and_more=Profil a nastavení…
|
||||||
signed_in_as=Přihlášen/a jako
|
signed_in_as=Přihlášen/a jako
|
||||||
enable_javascript=Tato stránka vyžaduje JavaScript.
|
enable_javascript=Tato stránka vyžaduje JavaScript.
|
||||||
toc=Obsah
|
toc=Tabulka obsahu
|
||||||
licenses=Licence
|
licenses=Licence
|
||||||
return_to_forgejo=Vrátit se do Forgejo
|
return_to_forgejo=Vrátit se do Forgejo
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ password=Heslo
|
||||||
access_token=Přístupový token
|
access_token=Přístupový token
|
||||||
re_type=Potvrzení hesla
|
re_type=Potvrzení hesla
|
||||||
captcha=CAPTCHA
|
captcha=CAPTCHA
|
||||||
twofa=Dvoufaktorové ověřování
|
twofa=Dvoufázové ověření
|
||||||
twofa_scratch=Dvoufaktorový kód
|
twofa_scratch=Dvoufaktorový kód
|
||||||
passcode=Přístupový kód
|
passcode=Přístupový kód
|
||||||
|
|
||||||
|
@ -124,8 +124,7 @@ pin=Připnout
|
||||||
unpin=Odepnout
|
unpin=Odepnout
|
||||||
|
|
||||||
artifacts=Artefakty
|
artifacts=Artefakty
|
||||||
confirm_delete_artifact=Jste si jisti, že chcete odstranit artefakt „%s“?
|
confirm_delete_artifact = Opravdu chcete odstranit artefakt „%s“?
|
||||||
|
|
||||||
archived=Archivováno
|
archived=Archivováno
|
||||||
|
|
||||||
concept_system_global=Globální
|
concept_system_global=Globální
|
||||||
|
@ -142,8 +141,6 @@ confirm_delete_selected=Potvrdit odstranění všech vybraných položek?
|
||||||
|
|
||||||
name=Název
|
name=Název
|
||||||
value=Hodnota
|
value=Hodnota
|
||||||
sign_in_with_provider = Přihlásit se přes %s
|
|
||||||
confirm_delete_artifact = Opravdu chcete odstranit artefakt „%s“?
|
|
||||||
toggle_menu = Přepnout nabídku
|
toggle_menu = Přepnout nabídku
|
||||||
filter = Filtr
|
filter = Filtr
|
||||||
filter.is_fork = Forky
|
filter.is_fork = Forky
|
||||||
|
@ -251,7 +248,7 @@ err_empty_db_path=Cesta k databázi SQLite3 nemůže být prázdná.
|
||||||
no_admin_and_disable_registration=Nelze vypnout registraci účtů bez vytvoření účtu administrátora.
|
no_admin_and_disable_registration=Nelze vypnout registraci účtů bez vytvoření účtu administrátora.
|
||||||
err_empty_admin_password=Heslo administrátora nemůže být prázdné.
|
err_empty_admin_password=Heslo administrátora nemůže být prázdné.
|
||||||
err_empty_admin_email=E-mail administrátora nemůže být prázdný.
|
err_empty_admin_email=E-mail administrátora nemůže být prázdný.
|
||||||
err_admin_name_is_reserved=Uživatelské jméno administrátora není platné, uživatelské jméno je rezervované
|
err_admin_name_is_reserved=Uživatelské jméno administrátora není platné, jméno je rezervované
|
||||||
err_admin_name_pattern_not_allowed=Uživatelské jméno administrátora je neplatné, uživatelské jméno odpovídá vyhrazenému vzoru
|
err_admin_name_pattern_not_allowed=Uživatelské jméno administrátora je neplatné, uživatelské jméno odpovídá vyhrazenému vzoru
|
||||||
err_admin_name_is_invalid=Uživatelské jméno administrátora není platné
|
err_admin_name_is_invalid=Uživatelské jméno administrátora není platné
|
||||||
|
|
||||||
|
@ -434,7 +431,7 @@ non_local_account=Externě ověřovaní uživatelé nemohou změnit své heslo p
|
||||||
verify=Ověřit
|
verify=Ověřit
|
||||||
scratch_code=Záložní kód
|
scratch_code=Záložní kód
|
||||||
use_scratch_code=Použít záložní kód
|
use_scratch_code=Použít záložní kód
|
||||||
twofa_scratch_used=Použili jste váš záložní kód. Byli jste přesměrování na stránku s nastavením dvoufaktorového ověřování, kde můžete odstranit registraci vašeho zařízení nebo vygenerovat nový záložní kód.
|
twofa_scratch_used=Použili jste svůj záložní kód. Byli jste přesměrování na stránku s nastavením dvoufázového ověření, kde můžete odstranit registraci vašeho zařízení nebo vygenerovat nový záložní kód.
|
||||||
twofa_passcode_incorrect=Vaše heslo je neplatné. Pokud jste ztratili vaše zařízení, použijte záložní kód k přihlášení.
|
twofa_passcode_incorrect=Vaše heslo je neplatné. Pokud jste ztratili vaše zařízení, použijte záložní kód k přihlášení.
|
||||||
twofa_scratch_token_incorrect=Váš záložní kód není správný.
|
twofa_scratch_token_incorrect=Váš záložní kód není správný.
|
||||||
login_userpass=Přihlásit se
|
login_userpass=Přihlásit se
|
||||||
|
@ -478,6 +475,8 @@ hint_register = Nemáte účet? <a href="%s">Zaregistrujte se nyní.</a>
|
||||||
sign_up_button = Zaregistrujte se nyní.
|
sign_up_button = Zaregistrujte se nyní.
|
||||||
back_to_sign_in = Zpět na přihlášení
|
back_to_sign_in = Zpět na přihlášení
|
||||||
sign_in_openid = Pokračovat s OpenID
|
sign_in_openid = Pokračovat s OpenID
|
||||||
|
unauthorized_credentials = Údaje jsou nesprávné nebo vypršely. Opakujte svůj příkaz nebo se podívejte na %s pro více informací
|
||||||
|
use_onetime_code = Použít jednorázový kód
|
||||||
|
|
||||||
[mail]
|
[mail]
|
||||||
view_it_on=Zobrazit na %s
|
view_it_on=Zobrazit na %s
|
||||||
|
@ -488,11 +487,11 @@ hi_user_x=Ahoj <b>%s</b>,
|
||||||
activate_account=Prosíme, aktivujte si váš účet
|
activate_account=Prosíme, aktivujte si váš účet
|
||||||
activate_account.title=%s, prosím aktivujte si váš účet
|
activate_account.title=%s, prosím aktivujte si váš účet
|
||||||
activate_account.text_1=Ahoj <b>%[1]s</b>, děkujeme za registraci na %[2]s!
|
activate_account.text_1=Ahoj <b>%[1]s</b>, děkujeme za registraci na %[2]s!
|
||||||
activate_account.text_2=Pro aktivaci vašeho účtu do <b>%s</b> klikněte na následující odkaz:
|
activate_account.text_2=Pro aktivaci vašeho účtu klikněte <b>%s</b> na následující odkaz :
|
||||||
|
|
||||||
activate_email=Ověřte vaši e-mailovou adresu
|
activate_email=Ověřte vaši e-mailovou adresu
|
||||||
activate_email.title=%s, prosím ověřte vaši e-mailovou adresu
|
activate_email.title=%s, prosím ověřte vaši e-mailovou adresu
|
||||||
activate_email.text=Pro aktivaci vašeho účtu do <b>%s</b> klikněte na následující odkaz:
|
activate_email.text=Pro ověření vaší e-mailové adresy klikněte <b>%s</b> na následující odkaz:
|
||||||
|
|
||||||
register_notify=Vítejte v %s
|
register_notify=Vítejte v %s
|
||||||
register_notify.title=%[1]s vítejte v %[2]s
|
register_notify.title=%[1]s vítejte v %[2]s
|
||||||
|
@ -622,7 +621,7 @@ repository_files_already_exist.adopt=Soubory pro tento repozitář již existuj
|
||||||
repository_files_already_exist.delete=Soubory pro tento repozitář již existují. Musíte je odstranit.
|
repository_files_already_exist.delete=Soubory pro tento repozitář již existují. Musíte je odstranit.
|
||||||
repository_files_already_exist.adopt_or_delete=Soubory pro tento repozitář již existují. Přijměte je, nebo je odstraňte.
|
repository_files_already_exist.adopt_or_delete=Soubory pro tento repozitář již existují. Přijměte je, nebo je odstraňte.
|
||||||
visit_rate_limit=Dosaženo limitu rychlosti dotazů při vzdáleném přístupu.
|
visit_rate_limit=Dosaženo limitu rychlosti dotazů při vzdáleném přístupu.
|
||||||
2fa_auth_required=Vzdálený přístup vyžaduje dvoufaktorové ověřování.
|
2fa_auth_required=Vzdálený přístup vyžaduje dvoufázové ověření.
|
||||||
org_name_been_taken=Název organizace je již použit.
|
org_name_been_taken=Název organizace je již použit.
|
||||||
team_name_been_taken=Název týmu je již použit.
|
team_name_been_taken=Název týmu je již použit.
|
||||||
team_no_units_error=Povolit přístup alespoň do jedné sekce repozitáře.
|
team_no_units_error=Povolit přístup alespoň do jedné sekce repozitáře.
|
||||||
|
@ -660,10 +659,9 @@ org_still_own_repo=Organizace stále vlastní jeden nebo více repozitářů. Ne
|
||||||
org_still_own_packages=Organizace stále vlastní jeden nebo více balíčků. Nejdříve je odstraňte.
|
org_still_own_packages=Organizace stále vlastní jeden nebo více balíčků. Nejdříve je odstraňte.
|
||||||
|
|
||||||
target_branch_not_exist=Cílová větev neexistuje.
|
target_branch_not_exist=Cílová větev neexistuje.
|
||||||
admin_cannot_delete_self = Nemůžete odstranit sami sebe, když jste administrátorem. Nejprve prosím odeberte svá práva administrátora.
|
admin_cannot_delete_self=Nemůžete se smazat, dokud jste správce. Nejdříve prosím odeberte svá administrátorská oprávnění.
|
||||||
username_error_no_dots = ` může obsahovat pouze alfanumerické znaky („0-9“, „a-z“, „A-Z“), pomlčky („-“) a podtržítka („_“). Nemůže začínat nebo končit nealfanumerickými znaky. Jsou také zakázány po sobě jdoucí nealfanumerické znaky.`
|
username_error_no_dots = ` může obsahovat pouze alfanumerické znaky („0-9“, „a-z“, „A-Z“), pomlčky („-“) a podtržítka („_“). Nemůže začínat nebo končit nealfanumerickými znaky. Jsou také zakázány po sobě jdoucí nealfanumerické znaky.`
|
||||||
|
|
||||||
admin_cannot_delete_self=Nemůžete se smazat, dokud jste správce. Nejdříve prosím odeberte svá administrátorská oprávnění.
|
|
||||||
unset_password = Tento uživatel nemá nastavené heslo.
|
unset_password = Tento uživatel nemá nastavené heslo.
|
||||||
unsupported_login_type = U tohoto typu účtu není funkce odstranění účtu podporována.
|
unsupported_login_type = U tohoto typu účtu není funkce odstranění účtu podporována.
|
||||||
required_prefix = Vstup musí začínat textem „%s“
|
required_prefix = Vstup musí začínat textem „%s“
|
||||||
|
@ -718,6 +716,7 @@ public_activity.visibility_hint.self_private = Vaše aktivita je viditelná pouz
|
||||||
public_activity.visibility_hint.admin_private = Tato aktivita je pro vás viditelná, protože jste administrátor, ale uživatel chce, aby zůstala soukromá.
|
public_activity.visibility_hint.admin_private = Tato aktivita je pro vás viditelná, protože jste administrátor, ale uživatel chce, aby zůstala soukromá.
|
||||||
public_activity.visibility_hint.self_public = Vaše aktivita je viditelná všem, mimo interakcí v soukromých prostorech. <a href="%s">Nastavení</a>.
|
public_activity.visibility_hint.self_public = Vaše aktivita je viditelná všem, mimo interakcí v soukromých prostorech. <a href="%s">Nastavení</a>.
|
||||||
public_activity.visibility_hint.admin_public = Tato aktivita je viditelná všem, ale jako administrátor také můžete vidět interakce v soukromých prostorech.
|
public_activity.visibility_hint.admin_public = Tato aktivita je viditelná všem, ale jako administrátor také můžete vidět interakce v soukromých prostorech.
|
||||||
|
public_activity.visibility_hint.self_private_profile = Vaše aktivita je viditelná pouze vám a správcům instance, protože váš profil je soukromý. <a href="%s">Nastavit</a>.
|
||||||
|
|
||||||
[settings]
|
[settings]
|
||||||
profile=Profil
|
profile=Profil
|
||||||
|
@ -732,11 +731,11 @@ applications=Aplikace
|
||||||
orgs=Organizace
|
orgs=Organizace
|
||||||
repos=Repozitáře
|
repos=Repozitáře
|
||||||
delete=Smazat účet
|
delete=Smazat účet
|
||||||
twofa=Dvoufaktorové ověřování (TOTP)
|
twofa=Dvoufázové ověření (TOTP)
|
||||||
account_link=Propojené účty
|
account_link=Propojené účty
|
||||||
organization=Organizace
|
organization=Organizace
|
||||||
uid=UID
|
uid=UID
|
||||||
webauthn=Dvoufaktorové ověřování (bezpečnostní klíče)
|
webauthn=Dvoufázové ověření (bezpečnostní klíče)
|
||||||
|
|
||||||
public_profile=Veřejný profil
|
public_profile=Veřejný profil
|
||||||
biography_placeholder=Řekněte nám něco o sobě! (Můžete použít Markdown)
|
biography_placeholder=Řekněte nám něco o sobě! (Můžete použít Markdown)
|
||||||
|
@ -806,7 +805,7 @@ manage_emails=Správa e-mailových adres
|
||||||
manage_themes=Výchozí motiv
|
manage_themes=Výchozí motiv
|
||||||
manage_openid=Adresy OpenID
|
manage_openid=Adresy OpenID
|
||||||
email_desc=Vaše hlavní e-mailová adresa bude použita pro oznámení, obnovení hesla, a pokud není skrytá, pro operace Gitu.
|
email_desc=Vaše hlavní e-mailová adresa bude použita pro oznámení, obnovení hesla, a pokud není skrytá, pro operace Gitu.
|
||||||
theme_desc=Toto bude váš výchozí motiv vzhledu napříč stránkou.
|
theme_desc=Toto bude váš výchozí motiv vzhledu na tomto webu.
|
||||||
primary=Hlavní
|
primary=Hlavní
|
||||||
activated=Aktivován
|
activated=Aktivován
|
||||||
requires_activation=Vyžaduje aktivaci
|
requires_activation=Vyžaduje aktivaci
|
||||||
|
@ -842,8 +841,8 @@ add_key=Přidat klíč
|
||||||
ssh_desc=Tyto veřejné klíče SSH jsou propojeny s vaším účtem. Odpovídající soukromé klíče umožní plný přístup k vašim repozitářům. Klíče SSH, které byly ověřeny, mohou být použity pro ověření Git commitů podepsaných přes SSH.
|
ssh_desc=Tyto veřejné klíče SSH jsou propojeny s vaším účtem. Odpovídající soukromé klíče umožní plný přístup k vašim repozitářům. Klíče SSH, které byly ověřeny, mohou být použity pro ověření Git commitů podepsaných přes SSH.
|
||||||
principal_desc=Tyto SSH Principal certifikáty jsou přidruženy k vašemu účtu a umožňují plný přístup do vašich repozitářů.
|
principal_desc=Tyto SSH Principal certifikáty jsou přidruženy k vašemu účtu a umožňují plný přístup do vašich repozitářů.
|
||||||
gpg_desc=Tyto veřejné klíče GPG jsou propojeny s vaším účtem a používají se k ověření vašich commitů. Uložte je na bezpečné místo, jelikož umožňují podepsat commity vaší identitou.
|
gpg_desc=Tyto veřejné klíče GPG jsou propojeny s vaším účtem a používají se k ověření vašich commitů. Uložte je na bezpečné místo, jelikož umožňují podepsat commity vaší identitou.
|
||||||
ssh_helper=<strong>Potřebujete pomoct?</strong> Podívejte se do příručky GitHubu na to <a href="%s">vytvoření vlastních klíčů SSH</a> nebo vyřešte <a href="%s">běžné problémy</a>, se kterými se můžete potkat při použití SSH.
|
ssh_helper=<strong>Potřebujete pomoct?</strong> Podívejte se do příručky, jak <a href="%s">vytvořit vlastní klíče SSH</a> nebo vyřešte <a href="%s">běžné problémy</a>, se kterými se můžete potkat při použití SSH.
|
||||||
gpg_helper=<strong>Potřebujete pomoct?</strong> Podívejte se do příručky GitHubu <a href="%s">o GPG</a>.
|
gpg_helper=<strong>Potřebujete pomoct?</strong> Podívejte se do příručky <a href="%s">o GPG</a>.
|
||||||
add_new_key=Přidat klíč SSH
|
add_new_key=Přidat klíč SSH
|
||||||
add_new_gpg_key=Přidat klíč GPG
|
add_new_gpg_key=Přidat klíč GPG
|
||||||
key_content_ssh_placeholder=Začíná s „ssh-ed25519“, „ssh-rsa“, „ecdsa-sha2-nistp256“, „ecdsa-sha2-nistp384“, „ecdsa-sha2-nistp521“, „sk-ecdsa-sha2-nistp256@openssh.com“ nebo „sk-ssh-ed25519@openssh.com“
|
key_content_ssh_placeholder=Začíná s „ssh-ed25519“, „ssh-rsa“, „ecdsa-sha2-nistp256“, „ecdsa-sha2-nistp384“, „ecdsa-sha2-nistp521“, „sk-ecdsa-sha2-nistp256@openssh.com“ nebo „sk-ssh-ed25519@openssh.com“
|
||||||
|
@ -898,7 +897,7 @@ ssh_principal_deletion_success=SSH Principal certifikát byl odstraněn.
|
||||||
added_on=Přidáno %s
|
added_on=Přidáno %s
|
||||||
valid_until_date=Platné do %s
|
valid_until_date=Platné do %s
|
||||||
valid_forever=Platné navždy
|
valid_forever=Platné navždy
|
||||||
last_used=Naposledy použito dne
|
last_used=Naposledy použito
|
||||||
no_activity=Žádná aktuální aktivita
|
no_activity=Žádná aktuální aktivita
|
||||||
can_read_info=Čtení
|
can_read_info=Čtení
|
||||||
can_write_info=Zápis
|
can_write_info=Zápis
|
||||||
|
@ -928,17 +927,17 @@ access_token_deletion_cancel_action=Zrušit
|
||||||
access_token_deletion_confirm_action=Smazat
|
access_token_deletion_confirm_action=Smazat
|
||||||
access_token_deletion_desc=Smazání tokenu zruší přístup k vašemu účtu pro aplikace, které jej používají. Tuto akci nelze vrátit. Pokračovat?
|
access_token_deletion_desc=Smazání tokenu zruší přístup k vašemu účtu pro aplikace, které jej používají. Tuto akci nelze vrátit. Pokračovat?
|
||||||
delete_token_success=Token byl odstraněn. Aplikace, které jej používají již nemají přístup k vašemu účtu.
|
delete_token_success=Token byl odstraněn. Aplikace, které jej používají již nemají přístup k vašemu účtu.
|
||||||
repo_and_org_access=Repozitář a přístup organizace
|
repo_and_org_access=Přístup k repozitářům a organizacím
|
||||||
permissions_public_only=Pouze veřejnost
|
permissions_public_only=Pouze veřejné
|
||||||
permissions_access_all=Vše (veřejné, soukromé a omezené)
|
permissions_access_all=Vše (veřejné, soukromé a omezené)
|
||||||
select_permissions=Vyberte oprávnění
|
select_permissions=Vyberte oprávnění
|
||||||
permission_no_access=Bez přístupu
|
permission_no_access=Žádný přístup
|
||||||
permission_read=Přečtené
|
permission_read=Čtení
|
||||||
permission_write=Čtení a zápis
|
permission_write=Čtení a zápis
|
||||||
at_least_one_permission=Musíte vybrat alespoň jedno oprávnění pro vytvoření tokenu
|
at_least_one_permission=Musíte vybrat alespoň jedno oprávnění pro vytvoření tokenu
|
||||||
permissions_list=Oprávnění:
|
permissions_list=Oprávnění:
|
||||||
|
|
||||||
manage_oauth2_applications=Spravovat aplikace OAuth2
|
manage_oauth2_applications=Správa aplikací OAuth2
|
||||||
edit_oauth2_application=Upravit OAuth2 aplikaci
|
edit_oauth2_application=Upravit OAuth2 aplikaci
|
||||||
oauth2_applications_desc=OAuth2 aplikace umožní aplikacím třetích stran bezpečně ověřit uživatele v této instanci Forgejo.
|
oauth2_applications_desc=OAuth2 aplikace umožní aplikacím třetích stran bezpečně ověřit uživatele v této instanci Forgejo.
|
||||||
remove_oauth2_application=Odstranit OAuth2 aplikaci
|
remove_oauth2_application=Odstranit OAuth2 aplikaci
|
||||||
|
@ -949,8 +948,8 @@ create_oauth2_application_button=Vytvořit aplikaci
|
||||||
create_oauth2_application_success=Úspěšně jste vytvořili novou OAuth2 aplikaci.
|
create_oauth2_application_success=Úspěšně jste vytvořili novou OAuth2 aplikaci.
|
||||||
update_oauth2_application_success=Úspěšně jste aktualizovali OAuth2 aplikaci.
|
update_oauth2_application_success=Úspěšně jste aktualizovali OAuth2 aplikaci.
|
||||||
oauth2_application_name=Název aplikace
|
oauth2_application_name=Název aplikace
|
||||||
oauth2_confidential_client=Důvěrný klient. Zvolte jej pro aplikace, které ukládají soubor secret, například webové aplikace. Nevybírejte jej pro nativní aplikace včetně aplikací pro počítače a mobilní zařízení.
|
oauth2_confidential_client=Důvěrný klient. Vyberte pro aplikace, které udržují tajný klíč v bezpečí, například webové aplikace. Nevybírejte pro nativní aplikace včetně aplikací pro počítače a mobilní zařízení.
|
||||||
oauth2_redirect_uris=Přesměrování URI. Použijte nový řádek pro každou URI.
|
oauth2_redirect_uris=Přesměrování URI. Zadejte každou URI na vlastní řádek.
|
||||||
save_application=Uložit
|
save_application=Uložit
|
||||||
oauth2_client_id=ID klienta
|
oauth2_client_id=ID klienta
|
||||||
oauth2_client_secret=Tajný klíč klienta
|
oauth2_client_secret=Tajný klíč klienta
|
||||||
|
@ -958,12 +957,12 @@ oauth2_regenerate_secret=Obnovit tajný klíč
|
||||||
oauth2_regenerate_secret_hint=Ztratili jste svůj tajný klíč?
|
oauth2_regenerate_secret_hint=Ztratili jste svůj tajný klíč?
|
||||||
oauth2_client_secret_hint=Tajný klíč se znovu nezobrazí po opuštění nebo obnovení této stránky. Ujistěte se, že jste si jej uložili.
|
oauth2_client_secret_hint=Tajný klíč se znovu nezobrazí po opuštění nebo obnovení této stránky. Ujistěte se, že jste si jej uložili.
|
||||||
oauth2_application_edit=Upravit
|
oauth2_application_edit=Upravit
|
||||||
oauth2_application_create_description=OAuth2 aplikace poskytuje přístup aplikacím třetích stran k uživatelským účtům na této instanci.
|
oauth2_application_create_description=Aplikace OAuth2 poskytují přístup vašim aplikacím třetích stran k uživatelským účtům na této instanci.
|
||||||
oauth2_application_remove_description=Odebráním OAuth2 aplikace zabrání přístupu ověřeným uživatelům na této instanci. Pokračovat?
|
oauth2_application_remove_description=Odebráním OAuth2 aplikace zabrání přístupu ověřeným uživatelům na této instanci. Pokračovat?
|
||||||
oauth2_application_locked=Gitea předregistruje některé OAuth2 aplikace při spuštění, pokud je to povoleno v konfiguraci. Aby se zabránilo neočekávanému chování, nelze je upravovat ani odstranit. Více informací naleznete v dokumentaci OAuth2.
|
oauth2_application_locked=Gitea předregistruje některé OAuth2 aplikace při spuštění, pokud je to povoleno v konfiguraci. Aby se zabránilo neočekávanému chování, nelze je upravovat ani odstranit. Více informací naleznete v dokumentaci OAuth2.
|
||||||
|
|
||||||
authorized_oauth2_applications=Autorizovat aplikaci OAuth2
|
authorized_oauth2_applications=Autorizované aplikace OAuth2
|
||||||
authorized_oauth2_applications_description=Úspěšně jste povolili přístup k vašemu osobnímu účtu této aplikaci třetí strany. Zrušte prosím přístup aplikacím, které již nejsou používány.
|
authorized_oauth2_applications_description=Těmto aplikacím třetích stran jste udělili přístup ke svému osobnímu účtu Forgejo. Zrušte prosím přístup aplikacím, které již nejsou používány.
|
||||||
revoke_key=Zrušit
|
revoke_key=Zrušit
|
||||||
revoke_oauth2_grant=Zrušit přístup
|
revoke_oauth2_grant=Zrušit přístup
|
||||||
revoke_oauth2_grant_description=Zrušením přístupu této aplikaci třetí strany ji zabráníte v přístupu k vašim datům. Jste si jisti?
|
revoke_oauth2_grant_description=Zrušením přístupu této aplikaci třetí strany ji zabráníte v přístupu k vašim datům. Jste si jisti?
|
||||||
|
@ -971,24 +970,24 @@ revoke_oauth2_grant_success=Přístup byl úspěšně zrušen.
|
||||||
|
|
||||||
twofa_desc=Dvoufaktorový způsob ověřování zvýší zabezpečení vašeho účtu.
|
twofa_desc=Dvoufaktorový způsob ověřování zvýší zabezpečení vašeho účtu.
|
||||||
twofa_recovery_tip=Pokud ztratíte své zařízení, budete moci použít jednorázový obnovovací klíč k získání přístupu k vašemu účtu.
|
twofa_recovery_tip=Pokud ztratíte své zařízení, budete moci použít jednorázový obnovovací klíč k získání přístupu k vašemu účtu.
|
||||||
twofa_is_enrolled=Váš účet aktuálně <strong>používá</strong> dvoufaktorové ověřování.
|
twofa_is_enrolled=Váš účet aktuálně <strong>používá</strong> dvoufázové ověření.
|
||||||
twofa_not_enrolled=Váš účet aktuálně nepoužívá dvoufaktorové ověřování.
|
twofa_not_enrolled=Váš účet aktuálně nepoužívá dvoufázové ověření.
|
||||||
twofa_disable=Zakázat dvoufaktorové ověřování
|
twofa_disable=Zakázat dvoufázové ověření
|
||||||
twofa_scratch_token_regenerate=Znovu vygenerovat jednorázový klíč pro obnovení
|
twofa_scratch_token_regenerate=Znovu vygenerovat jednorázový klíč pro obnovení
|
||||||
twofa_scratch_token_regenerated=Váš jednorázový klíč pro obnovení je nyní %s. Uložte jej na bezpečné místo, protože se znovu nezobrazí.
|
twofa_scratch_token_regenerated=Váš jednorázový klíč pro obnovení je nyní %s. Uložte jej na bezpečné místo, protože se znovu nezobrazí.
|
||||||
twofa_enroll=Povolit dvoufaktorové ověřování
|
twofa_enroll=Povolit dvoufázové ověření
|
||||||
twofa_disable_note=Dvoufaktorové ověřování můžete zakázat, když bude potřeba.
|
twofa_disable_note=Dvoufázové ověření můžete v případě potřeby zakázat.
|
||||||
twofa_disable_desc=Zakážete-li dvoufaktorové ověřování, bude váš účet méně zabezpečený. Pokračovat?
|
twofa_disable_desc=Zakázáním dvoufázového ověření bude váš účet méně bezpečný. Pokračovat?
|
||||||
regenerate_scratch_token_desc=Pokud jste ztratili svůj klíč pro obnovení nebo jste jej již použili k přihlášení, můžete jej resetovat zde.
|
regenerate_scratch_token_desc=Pokud jste ztratili svůj klíč pro obnovení nebo jste jej již použili k přihlášení, můžete jej resetovat zde.
|
||||||
twofa_disabled=Dvoufaktorové ověřování bylo zakázáno.
|
twofa_disabled=Dvoufázové ověření bylo zakázáno.
|
||||||
scan_this_image=Naskenujte tento obrázek s vaší ověřovací aplikací:
|
scan_this_image=Naskenujte tento obrázek s vaší ověřovací aplikací:
|
||||||
or_enter_secret=Nebo zadejte tajný kód: %s
|
or_enter_secret=Nebo zadejte tajný kód: %s
|
||||||
then_enter_passcode=A zadejte přístupový kód zobrazený ve vaší aplikaci:
|
then_enter_passcode=A zadejte přístupový kód zobrazený ve vaší aplikaci:
|
||||||
passcode_invalid=Přístupový kód není platný. Zkuste to znovu.
|
passcode_invalid=Přístupový kód není platný. Zkuste to znovu.
|
||||||
twofa_enrolled=Ve vašem účtu bylo povoleno dvoufaktorové ověřování. Uložte si jednorázový obnovovací klíč (%s) na bezpečné místo, jelikož již nebude znovu zobrazen.
|
twofa_enrolled=Ve vašem účtu bylo povoleno dvoufázové ověření. Uložte si jednorázový obnovovací klíč (%s) na bezpečné místo, jelikož již nebude znovu zobrazen.
|
||||||
twofa_failed_get_secret=Nepodařilo se získat tajemství.
|
twofa_failed_get_secret=Nepodařilo se získat tajemství.
|
||||||
|
|
||||||
webauthn_desc=Bezpečnostní klíče jsou hardwarová zařízení obsahující kryptografické klíče. Mohou být použity pro dvoufaktorové ověřování. Bezpečnostní klíče musí podporovat <a rel="noreferrer" target="_blank" href="%s">WebAuthn Authenticator</a> standard.
|
webauthn_desc=Bezpečnostní klíče jsou hardwarová zařízení obsahující kryptografické klíče. Mohou být použity pro dvoufázové ověření. Bezpečnostní klíče musí podporovat standard <a rel="noreferrer" target="_blank" href="%s">WebAuthn Authenticator</a>.
|
||||||
webauthn_register_key=Přidat bezpečnostní klíč
|
webauthn_register_key=Přidat bezpečnostní klíč
|
||||||
webauthn_nickname=Přezdívka
|
webauthn_nickname=Přezdívka
|
||||||
webauthn_delete_key=Odebrat bezpečnostní klíč
|
webauthn_delete_key=Odebrat bezpečnostní klíč
|
||||||
|
@ -997,7 +996,7 @@ webauthn_key_loss_warning=Pokud ztratíte své bezpečnostní klíče, ztratíte
|
||||||
webauthn_alternative_tip=Možná budete chtít nakonfigurovat další metodu ověřování.
|
webauthn_alternative_tip=Možná budete chtít nakonfigurovat další metodu ověřování.
|
||||||
|
|
||||||
manage_account_links=Propojené účty
|
manage_account_links=Propojené účty
|
||||||
manage_account_links_desc=Tyto externí účty jsou propojeny s vaším Forgejo účtem.
|
manage_account_links_desc=Tyto externí účty jsou propojeny s vaším účtem Forgejo.
|
||||||
account_links_not_available=K vašemu Forgejo účtu nejsou aktuálně připojené žádné externí účty.
|
account_links_not_available=K vašemu Forgejo účtu nejsou aktuálně připojené žádné externí účty.
|
||||||
link_account=Propojit účet
|
link_account=Propojit účet
|
||||||
remove_account_link=Odstranit propojený účet
|
remove_account_link=Odstranit propojený účet
|
||||||
|
@ -1009,7 +1008,7 @@ hooks.desc=Přidat webhooky, které budou spouštěny pro <strong>všechny repoz
|
||||||
orgs_none=Nejste členem žádné organizace.
|
orgs_none=Nejste členem žádné organizace.
|
||||||
repos_none=Nevlastníte žádné repozitáře.
|
repos_none=Nevlastníte žádné repozitáře.
|
||||||
|
|
||||||
delete_account=Odstranit svůj účet
|
delete_account=Odstranit účet
|
||||||
delete_prompt=Tato operace natrvalo odstraní váš uživatelský účet. <strong>NELZE</strong> ji vrátit zpět.
|
delete_prompt=Tato operace natrvalo odstraní váš uživatelský účet. <strong>NELZE</strong> ji vrátit zpět.
|
||||||
delete_with_all_comments=Váš účet je mladší než %s. Pro zabránění fantomovým komentářům budou společně s ním odstraněny všechny komentáře u problémů a ŽS.
|
delete_with_all_comments=Váš účet je mladší než %s. Pro zabránění fantomovým komentářům budou společně s ním odstraněny všechny komentáře u problémů a ŽS.
|
||||||
confirm_delete_account=Potvrdit odstranění
|
confirm_delete_account=Potvrdit odstranění
|
||||||
|
@ -1037,10 +1036,10 @@ access_token_desc = Oprávnění vybraného tokenu omezují autorizaci pouze na
|
||||||
blocked_users_none = Nemáte žádné zablokované uživatele.
|
blocked_users_none = Nemáte žádné zablokované uživatele.
|
||||||
blocked_since = Zablokován od %s
|
blocked_since = Zablokován od %s
|
||||||
hints = Nápovědy
|
hints = Nápovědy
|
||||||
additional_repo_units_hint = Navrhnout povolení dalších jednotek úložiště
|
additional_repo_units_hint = Navrhnout povolení dalších jednotek repozitáře
|
||||||
update_hints = Aktualizovat nápovědy
|
update_hints = Aktualizovat nápovědy
|
||||||
update_hints_success = Nápovědy byly aktualizovány.
|
update_hints_success = Nápovědy byly aktualizovány.
|
||||||
additional_repo_units_hint_description = Zobrazit tlačítko „Přidat další jednotky...“ u repozitářů, které nemají povolené všechny dostupné jednotky.
|
additional_repo_units_hint_description = Zobrazit tip „Povolit další“ u repozitářů, které nemají povolené všechny dostupné jednotky.
|
||||||
pronouns = Zájmena
|
pronouns = Zájmena
|
||||||
pronouns_custom = Vlastní
|
pronouns_custom = Vlastní
|
||||||
pronouns_unspecified = Neurčená
|
pronouns_unspecified = Neurčená
|
||||||
|
@ -1058,7 +1057,7 @@ repo_name_helper=Dobrý název repozitáře většinou používá krátká, zapa
|
||||||
repo_size=Velikost repozitáře
|
repo_size=Velikost repozitáře
|
||||||
template=Šablona
|
template=Šablona
|
||||||
template_select=Vyberte šablonu
|
template_select=Vyberte šablonu
|
||||||
template_helper=Z repozitáře vytvořit šablonu
|
template_helper=Nastavit repozitář jako šablonu
|
||||||
template_description=Šablony repozitářů umožňují uživatelům generovat nové repositáře se stejnou strukturou, soubory a volitelnými nastaveními.
|
template_description=Šablony repozitářů umožňují uživatelům generovat nové repositáře se stejnou strukturou, soubory a volitelnými nastaveními.
|
||||||
visibility=Viditelnost
|
visibility=Viditelnost
|
||||||
visibility_description=Pouze majitelé nebo členové organizace to budou moci vidět, pokud mají práva.
|
visibility_description=Pouze majitelé nebo členové organizace to budou moci vidět, pokud mají práva.
|
||||||
|
@ -1069,7 +1068,7 @@ clone_helper=Potřebujete pomoci s klonováním? Navštivte <a target="_blank" r
|
||||||
fork_repo=Fork repozitáře
|
fork_repo=Fork repozitáře
|
||||||
fork_from=Fork z
|
fork_from=Fork z
|
||||||
already_forked=Již jsi rozštěpil %s
|
already_forked=Již jsi rozštěpil %s
|
||||||
fork_to_different_account=Rozštěpit na jiný účet
|
fork_to_different_account=Vytvořit fork na jiném účtu
|
||||||
fork_visibility_helper=Viditelnost rozštěpeného repozitáře nemůže být změněna.
|
fork_visibility_helper=Viditelnost rozštěpeného repozitáře nemůže být změněna.
|
||||||
fork_branch=Větev, která má být klonována pro fork
|
fork_branch=Větev, která má být klonována pro fork
|
||||||
all_branches=Všechny větve
|
all_branches=Všechny větve
|
||||||
|
@ -1091,8 +1090,8 @@ issue_labels_helper=Vyberte sadu štítků
|
||||||
license=Licence
|
license=Licence
|
||||||
license_helper=Vyberte licenční soubor
|
license_helper=Vyberte licenční soubor
|
||||||
license_helper_desc=Licence řídí, co ostatní mohou a nemohou dělat s vaším kódem. Nejste si jisti, která je pro váš projekt správná? Podívejte se na <a target="_blank" rel="noopener noreferrer" href="%s">Zvolte licenci</a>
|
license_helper_desc=Licence řídí, co ostatní mohou a nemohou dělat s vaším kódem. Nejste si jisti, která je pro váš projekt správná? Podívejte se na <a target="_blank" rel="noopener noreferrer" href="%s">Zvolte licenci</a>
|
||||||
object_format=Formát objektu
|
object_format = Objektový formát
|
||||||
object_format_helper=Objektový formát repozitáře. Nelze později změnit. SHA1 je nejvíce kompatibilní.
|
object_format_helper = Objektový formát repozitáře. Později jej nelze změnit. Nejkompatibilnější je SHA1.
|
||||||
readme=README
|
readme=README
|
||||||
readme_helper=Vyberte šablonu souboru README
|
readme_helper=Vyberte šablonu souboru README
|
||||||
readme_helper_desc=Toto je místo, kde můžete napsat úplný popis vašeho projektu.
|
readme_helper_desc=Toto je místo, kde můžete napsat úplný popis vašeho projektu.
|
||||||
|
@ -1159,13 +1158,12 @@ desc.public=Veřejný
|
||||||
desc.template=Šablona
|
desc.template=Šablona
|
||||||
desc.internal=Interní
|
desc.internal=Interní
|
||||||
desc.archived=Archivováno
|
desc.archived=Archivováno
|
||||||
desc.sha256=SHA256
|
desc.sha256 = SHA256
|
||||||
|
|
||||||
template.items=Položky šablony
|
template.items=Položky šablony
|
||||||
template.git_content=Obsah Gitu (výchozí větev)
|
template.git_content=Obsah Gitu (výchozí větev)
|
||||||
template.git_hooks=Git hooks
|
template.git_hooks=Git hooks
|
||||||
template.git_hooks_tooltip=Momentálně nemůžete po přidání upravovat nebo odebírat Git hooky. Vyberte pouze v případě, že důvěřujete šabloně repozitáře.
|
template.git_hooks_tooltip=Momentálně nemůžete po přidání upravovat nebo odebírat Git hooky. Vyberte pouze v případě, že důvěřujete šabloně repozitáře.
|
||||||
template.webhooks=Webové háčky
|
template.webhooks=Webhooky
|
||||||
template.topics=Témata
|
template.topics=Témata
|
||||||
template.avatar=Avatar
|
template.avatar=Avatar
|
||||||
template.issue_labels=Štítky problémů
|
template.issue_labels=Štítky problémů
|
||||||
|
@ -1238,7 +1236,7 @@ migrate.cancel_migrating_confirm=Chcete zrušit tuto migraci?
|
||||||
mirror_from=zrcadlo
|
mirror_from=zrcadlo
|
||||||
forked_from=rozštěpen z
|
forked_from=rozštěpen z
|
||||||
generated_from=generováno z
|
generated_from=generováno z
|
||||||
fork_from_self=Nemůžete rozštěpit váš vlastní repozitář.
|
fork_from_self=Nemůžete vytvořit fork vašeho vlastního repozitáře.
|
||||||
fork_guest_user=Přihlaste se pro vytvoření forku tohoto repozitáře.
|
fork_guest_user=Přihlaste se pro vytvoření forku tohoto repozitáře.
|
||||||
watch_guest_user=Pro sledování tohoto repozitáře se přihlaste.
|
watch_guest_user=Pro sledování tohoto repozitáře se přihlaste.
|
||||||
star_guest_user=Pro hodnocení tohoto repozitáře se přihlaste.
|
star_guest_user=Pro hodnocení tohoto repozitáře se přihlaste.
|
||||||
|
@ -1246,7 +1244,7 @@ unwatch=Přestat sledovat
|
||||||
watch=Sledovat
|
watch=Sledovat
|
||||||
unstar=Oblíbené
|
unstar=Oblíbené
|
||||||
star=Oblíbit
|
star=Oblíbit
|
||||||
fork=Rozštěpit
|
fork=Fork
|
||||||
download_archive=Stáhnout repozitář
|
download_archive=Stáhnout repozitář
|
||||||
more_operations=Další operace
|
more_operations=Další operace
|
||||||
|
|
||||||
|
@ -1310,8 +1308,8 @@ audio_not_supported_in_browser=Váš prohlížeč nepodporuje značku HTML5 „a
|
||||||
stored_lfs=Uloženo pomocí Git LFS
|
stored_lfs=Uloženo pomocí Git LFS
|
||||||
symbolic_link=Symbolický odkaz
|
symbolic_link=Symbolický odkaz
|
||||||
executable_file=Spustitelný soubor
|
executable_file=Spustitelný soubor
|
||||||
vendored=Vendorováno
|
vendored = Vendorováno
|
||||||
generated=Generováno
|
generated = Generováno
|
||||||
commit_graph=Graf commitů
|
commit_graph=Graf commitů
|
||||||
commit_graph.select=Vybrat větve
|
commit_graph.select=Vybrat větve
|
||||||
commit_graph.hide_pr_refs=Skrýt žádosti o sloučení
|
commit_graph.hide_pr_refs=Skrýt žádosti o sloučení
|
||||||
|
@ -1337,7 +1335,7 @@ editor.cannot_edit_non_text_files=Binární soubory nemohou být upravovány př
|
||||||
editor.edit_this_file=Upravit soubor
|
editor.edit_this_file=Upravit soubor
|
||||||
editor.this_file_locked=Soubor je uzamčen
|
editor.this_file_locked=Soubor je uzamčen
|
||||||
editor.must_be_on_a_branch=Musíte mít zvolenu větev pro úpravu či návrh změn tohoto souboru.
|
editor.must_be_on_a_branch=Musíte mít zvolenu větev pro úpravu či návrh změn tohoto souboru.
|
||||||
editor.fork_before_edit=Musíte rozštěpit tento repozitář pro vytvoření nebo navržení změny tohoto souboru.
|
editor.fork_before_edit=Pro vytvoření nebo navržení změn v tomto souboru musíte vytvořit fork tohoto repozitáře.
|
||||||
editor.delete_this_file=Odstranit soubor
|
editor.delete_this_file=Odstranit soubor
|
||||||
editor.must_have_write_access=Musíte mít přístup pro zápis pro dělání či navrhování změn tohoto souboru.
|
editor.must_have_write_access=Musíte mít přístup pro zápis pro dělání či navrhování změn tohoto souboru.
|
||||||
editor.file_delete_success=Soubor „%s“ byl odstraněn.
|
editor.file_delete_success=Soubor „%s“ byl odstraněn.
|
||||||
|
@ -1345,9 +1343,9 @@ editor.name_your_file=Pojmenujte váš soubor…
|
||||||
editor.filename_help=Přidejte adresář zapsáním jeho jména následovaného lomítkem („/“). Adresář odeberete stiskem backspace na začátku vstupního pole.
|
editor.filename_help=Přidejte adresář zapsáním jeho jména následovaného lomítkem („/“). Adresář odeberete stiskem backspace na začátku vstupního pole.
|
||||||
editor.or=nebo
|
editor.or=nebo
|
||||||
editor.cancel_lower=Zrušit
|
editor.cancel_lower=Zrušit
|
||||||
editor.commit_signed_changes=Commitnout podepsané změny
|
editor.commit_signed_changes=Odeslat podepsané změny
|
||||||
editor.commit_changes=Commitnout změny
|
editor.commit_changes=Odeslat změny
|
||||||
editor.add_tmpl=Přidat „<nazevsouboru>“
|
editor.add_tmpl=Přidán „<filename>“
|
||||||
editor.add=Přidat %s
|
editor.add=Přidat %s
|
||||||
editor.update=Aktualizovat %s
|
editor.update=Aktualizovat %s
|
||||||
editor.delete=Odstranit %s
|
editor.delete=Odstranit %s
|
||||||
|
@ -1357,7 +1355,7 @@ editor.fail_to_apply_patch=Nelze použít záplatu „%s“
|
||||||
editor.new_patch=Nová záplata
|
editor.new_patch=Nová záplata
|
||||||
editor.commit_message_desc=Přidat volitelný rozšířený popis…
|
editor.commit_message_desc=Přidat volitelný rozšířený popis…
|
||||||
editor.signoff_desc=Přidat Signed-off-by podpis přispěvatele na konec zprávy o commitu.
|
editor.signoff_desc=Přidat Signed-off-by podpis přispěvatele na konec zprávy o commitu.
|
||||||
editor.commit_directly_to_this_branch=Odevzdat přímo do větve <strong class="branch-name">%s</strong>.
|
editor.commit_directly_to_this_branch=Odeslat přímo do větve <strong class="branch-name">%s</strong>.
|
||||||
editor.create_new_branch=Vytvořit <strong>novou větev</strong> pro tento commit a vytvořit žádost o sloučení.
|
editor.create_new_branch=Vytvořit <strong>novou větev</strong> pro tento commit a vytvořit žádost o sloučení.
|
||||||
editor.create_new_branch_np=Vytvořte <strong>novou větev</strong> z tohoto commitu.
|
editor.create_new_branch_np=Vytvořte <strong>novou větev</strong> z tohoto commitu.
|
||||||
editor.propose_file_change=Navrhnout změnu souboru
|
editor.propose_file_change=Navrhnout změnu souboru
|
||||||
|
@ -1375,8 +1373,8 @@ editor.file_editing_no_longer_exists=Upravovaný soubor „%s“ již není sou
|
||||||
editor.file_deleting_no_longer_exists=Odstraňovaný soubor „%s“ již není součástí tohoto repozitáře.
|
editor.file_deleting_no_longer_exists=Odstraňovaný soubor „%s“ již není součástí tohoto repozitáře.
|
||||||
editor.file_changed_while_editing=Obsah souboru se od zahájení úprav změnil. <a target="_blank" rel="noopener noreferrer" href="%s">Klikněte sem</a> pro jejich zobrazení nebo <strong>proveďte commit změn ještě jednou</strong> pro jejich přepsání.
|
editor.file_changed_while_editing=Obsah souboru se od zahájení úprav změnil. <a target="_blank" rel="noopener noreferrer" href="%s">Klikněte sem</a> pro jejich zobrazení nebo <strong>proveďte commit změn ještě jednou</strong> pro jejich přepsání.
|
||||||
editor.file_already_exists=Soubor „%s“ již existuje v tomto repozitáři.
|
editor.file_already_exists=Soubor „%s“ již existuje v tomto repozitáři.
|
||||||
editor.commit_empty_file_header=Odevzdat prázdný soubor
|
editor.commit_empty_file_header=Odeslat prázdný soubor
|
||||||
editor.commit_empty_file_text=Soubor, který se chystáte odevzdat, je prázdný. Pokračovat?
|
editor.commit_empty_file_text=Soubor, který se chystáte odeslat, je prázdný. Pokračovat?
|
||||||
editor.no_changes_to_show=Žádné změny k zobrazení.
|
editor.no_changes_to_show=Žádné změny k zobrazení.
|
||||||
editor.fail_to_update_file=Nepodařilo se aktualizovat/vytvořit soubor „%s“.
|
editor.fail_to_update_file=Nepodařilo se aktualizovat/vytvořit soubor „%s“.
|
||||||
editor.fail_to_update_file_summary=Chybová zpráva:
|
editor.fail_to_update_file_summary=Chybová zpráva:
|
||||||
|
@ -1386,9 +1384,9 @@ editor.push_rejected_summary=Úplná zpráva o zamítnutí:
|
||||||
editor.add_subdir=Přidat adresář…
|
editor.add_subdir=Přidat adresář…
|
||||||
editor.unable_to_upload_files=Nepodařilo se nahrát soubory do „%s“. Chyba: %v
|
editor.unable_to_upload_files=Nepodařilo se nahrát soubory do „%s“. Chyba: %v
|
||||||
editor.upload_file_is_locked=Soubor „%s“ je uzamčen uživatelem %s.
|
editor.upload_file_is_locked=Soubor „%s“ je uzamčen uživatelem %s.
|
||||||
editor.upload_files_to_dir=Nahrát soubory do „%s“
|
editor.upload_files_to_dir=Nahrány soubory do „%s“
|
||||||
editor.cannot_commit_to_protected_branch=Nelze vytvořit commit v chráněné větvi „%s“.
|
editor.cannot_commit_to_protected_branch=Nelze vytvořit commit v chráněné větvi „%s“.
|
||||||
editor.no_commit_to_branch=Nelze odevzdat přímo do větve, protože:
|
editor.no_commit_to_branch=Nepodařilo se odeslat přímo do větve:
|
||||||
editor.user_no_push_to_branch=Uživatel nemůže nahrávat do větve
|
editor.user_no_push_to_branch=Uživatel nemůže nahrávat do větve
|
||||||
editor.require_signed_commit=Větev vyžaduje podepsaný commit
|
editor.require_signed_commit=Větev vyžaduje podepsaný commit
|
||||||
editor.cherry_pick=Cherry-pick %s na:
|
editor.cherry_pick=Cherry-pick %s na:
|
||||||
|
@ -1427,7 +1425,7 @@ commitstatus.failure=Chyba
|
||||||
commitstatus.pending=Čekající
|
commitstatus.pending=Čekající
|
||||||
commitstatus.success=Úspěch
|
commitstatus.success=Úspěch
|
||||||
|
|
||||||
ext_issues=Přístup k externím problémům
|
ext_issues=Externí problémy
|
||||||
ext_issues.desc=Odkaz na externí systém problémů.
|
ext_issues.desc=Odkaz na externí systém problémů.
|
||||||
|
|
||||||
projects=Projekty
|
projects=Projekty
|
||||||
|
@ -1608,9 +1606,9 @@ issues.no_content=K dispozici není žádný popis.
|
||||||
issues.close=Zavřít problém
|
issues.close=Zavřít problém
|
||||||
issues.comment_pull_merged_at=sloučený commit %[1]s do %[2]s %[3]s
|
issues.comment_pull_merged_at=sloučený commit %[1]s do %[2]s %[3]s
|
||||||
issues.comment_manually_pull_merged_at=ručně sloučený commit %[1]s do %[2]s %[3]s
|
issues.comment_manually_pull_merged_at=ručně sloučený commit %[1]s do %[2]s %[3]s
|
||||||
issues.close_comment_issue=Okomentovat a zavřít
|
issues.close_comment_issue=Zavřít s komentářem
|
||||||
issues.reopen_issue=Znovu otevřít
|
issues.reopen_issue=Znovu otevřít
|
||||||
issues.reopen_comment_issue=Okomentovat a znovu otevřít
|
issues.reopen_comment_issue=Znovu otevřít s komentářem
|
||||||
issues.create_comment=Okomentovat
|
issues.create_comment=Okomentovat
|
||||||
issues.closed_at=`uzavřel/a tento problém <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
issues.closed_at=`uzavřel/a tento problém <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
||||||
issues.reopened_at=`znovu otevřel/a tento problém <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
issues.reopened_at=`znovu otevřel/a tento problém <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
||||||
|
@ -1647,11 +1645,11 @@ issues.label_title=Název štítku
|
||||||
issues.label_description=Popis štítku
|
issues.label_description=Popis štítku
|
||||||
issues.label_color=Barva štítku
|
issues.label_color=Barva štítku
|
||||||
issues.label_exclusive=Exkluzivní
|
issues.label_exclusive=Exkluzivní
|
||||||
issues.label_archive=Archivovat štítek
|
issues.label_archive = Štítek archivu
|
||||||
issues.label_archived_filter=Zobrazit archivované popisky
|
issues.label_archived_filter=Zobrazit archivované popisky
|
||||||
issues.label_archive_tooltip=Archivované štítky jsou ve výchozím nastavení vyloučeny z návrhů při hledání podle popisku.
|
issues.label_archive_tooltip = Štítek Archivováno jsou ve výchozím nastavení vyloučeny z návrhů při vyhledávání podle štítků.
|
||||||
issues.label_exclusive_desc=Pojmenujte štítek <code>rozsah/položka</code>, aby se stal vzájemně exkluzivním s jinými štítky <code>rozsah/</code>.
|
issues.label_exclusive_desc = Pojmenujte štítek <code>scope/item</code>, aby se vzájemně vylučoval s ostatními štítky <code>scope/</code>.
|
||||||
issues.label_exclusive_warning=Jakékoliv protichůdné rozsahy štítků budou odstraněny při úpravě štítků u úkolů nebo u požadavku na natažení.
|
issues.label_exclusive_warning = Při úpravě štítků problému nebo žádosti o sloučení budou odstraněny všechny konfliktní štítky.
|
||||||
issues.label_count=%d štítků
|
issues.label_count=%d štítků
|
||||||
issues.label_open_issues=%d otevřených problémů / žádostí o sloučení
|
issues.label_open_issues=%d otevřených problémů / žádostí o sloučení
|
||||||
issues.label_edit=Upravit
|
issues.label_edit=Upravit
|
||||||
|
@ -1752,7 +1750,7 @@ issues.dependency.issue_closing_blockedby=Uzavření tohoto problému je blokov
|
||||||
issues.dependency.issue_close_blocks=Tento problém blokuje uzavření následujících problémů
|
issues.dependency.issue_close_blocks=Tento problém blokuje uzavření následujících problémů
|
||||||
issues.dependency.pr_close_blocks=Tato žádost o sloučení blokuje uzavření následujících problémů
|
issues.dependency.pr_close_blocks=Tato žádost o sloučení blokuje uzavření následujících problémů
|
||||||
issues.dependency.issue_close_blocked=Aby bylo možné uzavřít tento problém, musíte uzavřít všechny ostatní problémy, které jej blokují.
|
issues.dependency.issue_close_blocked=Aby bylo možné uzavřít tento problém, musíte uzavřít všechny ostatní problémy, které jej blokují.
|
||||||
issues.dependency.issue_batch_close_blocked=Nelze uzavřít úkoly, které jste vybrali, protože úkol #%d má stále otevřené závislosti
|
issues.dependency.issue_batch_close_blocked = Nepodařilo se hromadně zavřít vybrané problémy, protože problém #%d má stále otevřené závislosti
|
||||||
issues.dependency.pr_close_blocked=Aby bylo možné sloučit tuto žádost, musíte uzavřít všechny problémy, které ji blokují.
|
issues.dependency.pr_close_blocked=Aby bylo možné sloučit tuto žádost, musíte uzavřít všechny problémy, které ji blokují.
|
||||||
issues.dependency.blocks_short=Blokuje
|
issues.dependency.blocks_short=Blokuje
|
||||||
issues.dependency.blocked_by_short=Závisí na
|
issues.dependency.blocked_by_short=Závisí na
|
||||||
|
@ -1776,8 +1774,8 @@ issues.review.left_comment=zanechal komentář
|
||||||
issues.review.content.empty=Je potřeba zanechat poznámku s uvedením požadované změny (požadovaných změn).
|
issues.review.content.empty=Je potřeba zanechat poznámku s uvedením požadované změny (požadovaných změn).
|
||||||
issues.review.reject=požádal/a o změny %s
|
issues.review.reject=požádal/a o změny %s
|
||||||
issues.review.wait=byl/a požádán/a o posouzení %s
|
issues.review.wait=byl/a požádán/a o posouzení %s
|
||||||
issues.review.add_review_request=požádal/a o posouzení od %s %s
|
issues.review.add_review_request=požádal/a o kontrolu od %[1]s %[2]s
|
||||||
issues.review.remove_review_request=odstranil/a žádost o posouzení na %s %s
|
issues.review.remove_review_request=odstranil/a žádost o kontrolu u %[1]s %[2]s
|
||||||
issues.review.remove_review_request_self=odmítl/a posoudit %s
|
issues.review.remove_review_request_self=odmítl/a posoudit %s
|
||||||
issues.review.pending=Čekající
|
issues.review.pending=Čekající
|
||||||
issues.review.pending.tooltip=Tento komentář není momentálně viditelný pro ostatní uživatele. Chcete-li odeslat Vaše čekající komentáře, vyberte „%s“ → „%s/%s/%s“ v horní části stránky.
|
issues.review.pending.tooltip=Tento komentář není momentálně viditelný pro ostatní uživatele. Chcete-li odeslat Vaše čekající komentáře, vyberte „%s“ → „%s/%s/%s“ v horní části stránky.
|
||||||
|
@ -1834,7 +1832,7 @@ pulls.select_commit_hold_shift_for_range=Vyberte commit. Podržte klávesu shift
|
||||||
pulls.review_only_possible_for_full_diff=Posouzení je možné pouze při zobrazení plného rozlišení
|
pulls.review_only_possible_for_full_diff=Posouzení je možné pouze při zobrazení plného rozlišení
|
||||||
pulls.filter_changes_by_commit=Filtrovat podle commitu
|
pulls.filter_changes_by_commit=Filtrovat podle commitu
|
||||||
pulls.nothing_to_compare=Tyto větve jsou stejné. Není třeba vytvářet žádost o sloučení.
|
pulls.nothing_to_compare=Tyto větve jsou stejné. Není třeba vytvářet žádost o sloučení.
|
||||||
pulls.nothing_to_compare_have_tag=Vybraná větev/značka je stejná.
|
pulls.nothing_to_compare_have_tag = Vybraná větev a značka jsou shodné.
|
||||||
pulls.nothing_to_compare_and_allow_empty_pr=Tyto větve jsou stejné. Tato žádost o sloučení bude prázdná.
|
pulls.nothing_to_compare_and_allow_empty_pr=Tyto větve jsou stejné. Tato žádost o sloučení bude prázdná.
|
||||||
pulls.has_pull_request=`Žádost o sloučení mezi těmito větvemi již existuje: <a href="%[1]s">%[2]s#%[3]d</a>`
|
pulls.has_pull_request=`Žádost o sloučení mezi těmito větvemi již existuje: <a href="%[1]s">%[2]s#%[3]d</a>`
|
||||||
pulls.create=Vytvořit žádost o sloučení
|
pulls.create=Vytvořit žádost o sloučení
|
||||||
|
@ -1909,7 +1907,7 @@ pulls.has_merged=Chyba: žádost byla sloučena, nelze ji znovu sloučit nebo zm
|
||||||
pulls.push_rejected=Push selhal: nahrání bylo zamítnuto. Zkontrolujte Git hooky pro tento repozitář.
|
pulls.push_rejected=Push selhal: nahrání bylo zamítnuto. Zkontrolujte Git hooky pro tento repozitář.
|
||||||
pulls.push_rejected_summary=Úplná zpráva o zamítnutí
|
pulls.push_rejected_summary=Úplná zpráva o zamítnutí
|
||||||
pulls.push_rejected_no_message=Push selhal: nahrání bylo odmítnuto, ale nebyla nalezena žádná vzdálená zpráva. Zkontrolujte Git hooky pro tento repozitář
|
pulls.push_rejected_no_message=Push selhal: nahrání bylo odmítnuto, ale nebyla nalezena žádná vzdálená zpráva. Zkontrolujte Git hooky pro tento repozitář
|
||||||
pulls.open_unmerged_pull_exists=`Nemůžete provést operaci znovuotevření protože je tu čekající požadavek na natažení (#%d) s identickými vlastnostmi.`
|
pulls.open_unmerged_pull_exists=`Nemůžete provést operaci opětovného otevření, protože máte čekající žádost o sloučení (#%d) s identickými vlastnostmi.`
|
||||||
pulls.status_checking=Některé kontroly jsou nedořešeny
|
pulls.status_checking=Některé kontroly jsou nedořešeny
|
||||||
pulls.status_checks_success=Všechny kontroly byly úspěšné
|
pulls.status_checks_success=Všechny kontroly byly úspěšné
|
||||||
pulls.status_checks_warning=Některé kontroly nahlásily varování
|
pulls.status_checks_warning=Některé kontroly nahlásily varování
|
||||||
|
@ -1925,8 +1923,8 @@ pulls.update_branch_success=Aktualizace větve byla úspěšná
|
||||||
pulls.update_not_allowed=Nemáte oprávnění aktualizovat větev
|
pulls.update_not_allowed=Nemáte oprávnění aktualizovat větev
|
||||||
pulls.outdated_with_base_branch=Tato větev je zastaralá oproti základní větvi
|
pulls.outdated_with_base_branch=Tato větev je zastaralá oproti základní větvi
|
||||||
pulls.close=Zavřít žádost o sloučení
|
pulls.close=Zavřít žádost o sloučení
|
||||||
pulls.closed_at=`uzavřel/a tento požadavek na natažení <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
pulls.closed_at=`uzavřel/a tuto žádost o sloučení <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
||||||
pulls.reopened_at=`znovuotevřel/a tento požadavek na natažení <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
pulls.reopened_at=`znovu otevřel/a tuto žádost o sloučení <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
||||||
pulls.cmd_instruction_hint=Zobrazit instrukce příkazové řádky
|
pulls.cmd_instruction_hint=Zobrazit instrukce příkazové řádky
|
||||||
pulls.cmd_instruction_checkout_desc=Z vašeho repositáře projektu se podívejte na novou větev a vyzkoušejte změny.
|
pulls.cmd_instruction_checkout_desc=Z vašeho repositáře projektu se podívejte na novou větev a vyzkoušejte změny.
|
||||||
pulls.cmd_instruction_merge_title=Sloučit
|
pulls.cmd_instruction_merge_title=Sloučit
|
||||||
|
@ -1935,18 +1933,18 @@ pulls.clear_merge_message=Vymazat zprávu o sloučení
|
||||||
|
|
||||||
pulls.auto_merge_button_when_succeed=(Když kontroly uspějí)
|
pulls.auto_merge_button_when_succeed=(Když kontroly uspějí)
|
||||||
pulls.auto_merge_when_succeed=Automaticky sloučit, když všechny kontroly uspějí
|
pulls.auto_merge_when_succeed=Automaticky sloučit, když všechny kontroly uspějí
|
||||||
pulls.auto_merge_newly_scheduled=Požadavek na natažení byl naplánován na sloučení, jakmile všechny kontroly uspějí.
|
pulls.auto_merge_newly_scheduled=Žádost o sloučení bude sloučena, jakmile budou všechny kontroly úspěšné.
|
||||||
pulls.auto_merge_has_pending_schedule=%[1]s naplánoval/a tento požadavek na natažení pro automatické sloučení, když všechny kontroly uspějí v %[2]s.
|
pulls.auto_merge_has_pending_schedule=%[1]s naplánoval/a tuto žádost o sloučení na automatické sloučení, jakmile budou všechny kontroly úspěšné %[2]s.
|
||||||
|
|
||||||
pulls.auto_merge_cancel_schedule=Zrušit automatické sloučení
|
pulls.auto_merge_cancel_schedule=Zrušit automatické sloučení
|
||||||
pulls.auto_merge_not_scheduled=Tento požadavek na natažení není naplánován na automatické sloučení.
|
pulls.auto_merge_not_scheduled=Tato žádost o sloučení nebude automaticky sloučena.
|
||||||
pulls.auto_merge_canceled_schedule=Automatické sloučení bylo zrušeno pro tento požadavek na natažení.
|
pulls.auto_merge_canceled_schedule=Automatické sloučení bylo u této žádosti o sloučení zrušeno.
|
||||||
|
|
||||||
pulls.auto_merge_newly_scheduled_comment=`požadavek na automatické sloučení tohoto požadavku na natažení je naplánován, když všechny kontroly uspějí %[1]s`
|
pulls.auto_merge_newly_scheduled_comment=`naplánoval/a tuto žádost o sloučení na automatické sloučení, jakmile budou všechny kontroly úspěšné %[1]s`
|
||||||
pulls.auto_merge_canceled_schedule_comment=`zrušil/a automatické sloučení tohoto požadavku na natažení, když všechny kontroly uspějí %[1]s`
|
pulls.auto_merge_canceled_schedule_comment=`zrušil/a automatické sloučení této žádosti o sloučení, jakmile budou všechny kontroly úspěšné %[1]s`
|
||||||
|
|
||||||
pulls.delete.title=Odstranit tento požadavek na natažení?
|
pulls.delete.title=Odstranit tuto žádost o sloučení?
|
||||||
pulls.delete.text=Opravdu chcete tento požadavek na natažení smazat? (Tím se trvale odstraní veškerý obsah. Pokud jej hodláte archivovat, zvažte raději jeho uzavření.)
|
pulls.delete.text=Opravdu chcete odstranit tuto žádost o sloučení? (Tímto trvale odstraníte všechen obsah. Pokud jej chcete archivovat, zvažte raději jeho uzavření)
|
||||||
|
|
||||||
|
|
||||||
pull.deleted_branch=(odstraněno):%s
|
pull.deleted_branch=(odstraněno):%s
|
||||||
|
@ -1957,7 +1955,7 @@ milestones.update_ago=Aktualizováno %s
|
||||||
milestones.no_due_date=Bez lhůty dokončení
|
milestones.no_due_date=Bez lhůty dokončení
|
||||||
milestones.open=Otevřít
|
milestones.open=Otevřít
|
||||||
milestones.close=Zavřít
|
milestones.close=Zavřít
|
||||||
milestones.new_subheader=Milníky vám pomohou organizovat úkoly a sledovat jejich pokrok.
|
milestones.new_subheader = Milníky vám pomohou zorganizovat problémy a sledovat jejich pokrok.
|
||||||
milestones.completeness=Dokončeno <strong>%d%%</strong>
|
milestones.completeness=Dokončeno <strong>%d%%</strong>
|
||||||
milestones.create=Vytvořit milník
|
milestones.create=Vytvořit milník
|
||||||
milestones.title=Název
|
milestones.title=Název
|
||||||
|
@ -1987,15 +1985,15 @@ signing.wont_sign.nokey=Tato instance nemá žádný klíč k podepsání tohoto
|
||||||
signing.wont_sign.never=Commity nejsou nikdy podepsány.
|
signing.wont_sign.never=Commity nejsou nikdy podepsány.
|
||||||
signing.wont_sign.always=Commity jsou vždy podepsány.
|
signing.wont_sign.always=Commity jsou vždy podepsány.
|
||||||
signing.wont_sign.pubkey=Commit nebude podepsán, protože nemáte veřejný klíč spojený s vaším účtem.
|
signing.wont_sign.pubkey=Commit nebude podepsán, protože nemáte veřejný klíč spojený s vaším účtem.
|
||||||
signing.wont_sign.twofa=Pro podepsání commitů musíte mít povoleno dvoufaktorové ověření.
|
signing.wont_sign.twofa=Pro podepisování commitů musíte mít zapnuto dvoufázové ověření.
|
||||||
signing.wont_sign.parentsigned=Commit nebude podepsán, protože nadřazený commit není podepsán.
|
signing.wont_sign.parentsigned=Commit nebude podepsán, protože nadřazený commit není podepsán.
|
||||||
signing.wont_sign.basesigned=Sloučení nebude podepsáno, protože základní commit není podepsaný.
|
signing.wont_sign.basesigned=Sloučení nebude podepsáno, protože základní commit není podepsaný.
|
||||||
signing.wont_sign.headsigned=Sloučení nebude podepsáno, protože hlavní revize není podepsána.
|
signing.wont_sign.headsigned=Sloučení nebude podepsáno, protože hlavní revize není podepsána.
|
||||||
signing.wont_sign.commitssigned=Sloučení nebude podepsáno, protože všechny přidružené revize nejsou podepsány.
|
signing.wont_sign.commitssigned=Sloučení nebude podepsáno, protože všechny přidružené revize nejsou podepsány.
|
||||||
signing.wont_sign.approved=Sloučení nebude podepsáno, protože požadavek na natažení není schválen.
|
signing.wont_sign.approved=Sloučení nebude podepsáno, protože žádost o sloučení není schválena.
|
||||||
signing.wont_sign.not_signed_in=Nejste přihlášeni.
|
signing.wont_sign.not_signed_in=Nejste přihlášeni.
|
||||||
|
|
||||||
ext_wiki=Přístup k externí Wiki
|
ext_wiki=Externí wiki
|
||||||
ext_wiki.desc=Odkaz do externí Wiki.
|
ext_wiki.desc=Odkaz do externí Wiki.
|
||||||
|
|
||||||
wiki=Wiki
|
wiki=Wiki
|
||||||
|
@ -2091,7 +2089,7 @@ activity.git_stats_and_deletions=a
|
||||||
activity.git_stats_deletion_1=%d odebrání
|
activity.git_stats_deletion_1=%d odebrání
|
||||||
activity.git_stats_deletion_n=%d odebrání
|
activity.git_stats_deletion_n=%d odebrání
|
||||||
|
|
||||||
contributors.contribution_type.filter_label=Typ příspěvku:
|
contributors.contribution_type.filter_label = Typ přispění:
|
||||||
contributors.contribution_type.commits=Commity
|
contributors.contribution_type.commits=Commity
|
||||||
|
|
||||||
search=Vyhledat
|
search=Vyhledat
|
||||||
|
@ -2114,10 +2112,10 @@ settings.collaboration.write=Zápis
|
||||||
settings.collaboration.read=Čtení
|
settings.collaboration.read=Čtení
|
||||||
settings.collaboration.owner=Vlastník
|
settings.collaboration.owner=Vlastník
|
||||||
settings.collaboration.undefined=Neurčeno
|
settings.collaboration.undefined=Neurčeno
|
||||||
settings.hooks=Webové háčky
|
settings.hooks=Webhooky
|
||||||
settings.githooks=Git hooky
|
settings.githooks=Git hooky
|
||||||
settings.basic_settings=Základní nastavení
|
settings.basic_settings=Základní nastavení
|
||||||
settings.mirror_settings=Nastavení zrcadla
|
settings.mirror_settings=Nastavení zrcadel
|
||||||
settings.mirror_settings.docs=Nastavte repozitář pro automatickou synchronizaci commitů, značek a větví s jiným repozitářem.
|
settings.mirror_settings.docs=Nastavte repozitář pro automatickou synchronizaci commitů, značek a větví s jiným repozitářem.
|
||||||
settings.mirror_settings.docs.disabled_pull_mirror.instructions=Nastavte váš projekt pro automatické nahrávání commitů, značek a větví do jiného repozitáře. Správce webu zakázal zrcadla pro natažení.
|
settings.mirror_settings.docs.disabled_pull_mirror.instructions=Nastavte váš projekt pro automatické nahrávání commitů, značek a větví do jiného repozitáře. Správce webu zakázal zrcadla pro natažení.
|
||||||
settings.mirror_settings.docs.disabled_push_mirror.instructions=Nastavte svůj projekt pro automatické natažení commitů, značek a větví z jiného repozitáře.
|
settings.mirror_settings.docs.disabled_push_mirror.instructions=Nastavte svůj projekt pro automatické natažení commitů, značek a větví z jiného repozitáře.
|
||||||
|
@ -2125,7 +2123,7 @@ settings.mirror_settings.docs.no_new_mirrors=Váš repozitář zrcadlí změny d
|
||||||
settings.mirror_settings.docs.can_still_use=I když nemůžete upravit stávající zrcadla nebo vytvořit nová, stále můžete použít své stávající zrcadlo.
|
settings.mirror_settings.docs.can_still_use=I když nemůžete upravit stávající zrcadla nebo vytvořit nová, stále můžete použít své stávající zrcadlo.
|
||||||
settings.mirror_settings.docs.more_information_if_disabled=Více informací o zrcadlech pro nahrání a natažení naleznete zde:
|
settings.mirror_settings.docs.more_information_if_disabled=Více informací o zrcadlech pro nahrání a natažení naleznete zde:
|
||||||
settings.mirror_settings.docs.doc_link_title=Jak mohu zrcadlit repozitáře?
|
settings.mirror_settings.docs.doc_link_title=Jak mohu zrcadlit repozitáře?
|
||||||
settings.mirror_settings.docs.pulling_remote_title=Stažení ze vzdáleného úložiště
|
settings.mirror_settings.docs.pulling_remote_title=Stahování ze vzdáleného repozitáře
|
||||||
settings.mirror_settings.mirrored_repository=Zrcadlený repozitář
|
settings.mirror_settings.mirrored_repository=Zrcadlený repozitář
|
||||||
settings.mirror_settings.direction=Směr
|
settings.mirror_settings.direction=Směr
|
||||||
settings.mirror_settings.direction.pull=Natáhnout
|
settings.mirror_settings.direction.pull=Natáhnout
|
||||||
|
@ -2264,23 +2262,23 @@ settings.delete_team_tip=Tento tým má přístup ke všem repositářům a nem
|
||||||
settings.remove_team_success=Přístup týmu k repozitáři byl odstraněn.
|
settings.remove_team_success=Přístup týmu k repozitáři byl odstraněn.
|
||||||
settings.add_webhook=Přidat webhook
|
settings.add_webhook=Přidat webhook
|
||||||
settings.add_webhook.invalid_channel_name=Kanál webového háčku nemůže být prázdný a nemůže obsahovat pouze znak #.
|
settings.add_webhook.invalid_channel_name=Kanál webového háčku nemůže být prázdný a nemůže obsahovat pouze znak #.
|
||||||
settings.hooks_desc=Webové háčky automaticky vytvářejí dotazy HTTP POST na server, když nastane určitá událost v Forgejo. Čtěte více v <a target="_blank" rel="noopener noreferrer" href="%s">příručce webových háčků</a>.
|
settings.hooks_desc=Webhooky automaticky vytvářejí dotazy HTTP POST na server, když nastane určitá událost ve Forgejo. Více informací v <a target="_blank" rel="noopener noreferrer" href="%s">příručce webhooků</a>.
|
||||||
settings.webhook_deletion=Odstranit webhook
|
settings.webhook_deletion=Odstranit webhook
|
||||||
settings.webhook_deletion_desc=Odstranění webového háčku smaže jeho nastavení a historii doručení. Pokračovat?
|
settings.webhook_deletion_desc=Odstranění webového háčku smaže jeho nastavení a historii doručení. Pokračovat?
|
||||||
settings.webhook_deletion_success=Webový háček byl smazán.
|
settings.webhook_deletion_success=Webhook byl smazán.
|
||||||
settings.webhook.test_delivery=Test doručitelnosti
|
settings.webhook.test_delivery=Test doručitelnosti
|
||||||
settings.webhook.test_delivery_desc=Vyzkoušet tento webový háček pomocí falešné události.
|
settings.webhook.test_delivery_desc=Otestovat tento webhook pomocí falešné události.
|
||||||
settings.webhook.test_delivery_desc_disabled=Chcete-li tento webový háček otestovat s falešnou událostí, aktivujte ho.
|
settings.webhook.test_delivery_desc_disabled=Chcete-li pomocí falešné události otestovat tento webhook, aktivujte ho.
|
||||||
settings.webhook.request=Požadavek
|
settings.webhook.request=Požadavek
|
||||||
settings.webhook.response=Odpověď
|
settings.webhook.response=Odpověď
|
||||||
settings.webhook.headers=Hlavičky
|
settings.webhook.headers=Hlavičky
|
||||||
settings.webhook.payload=Obsah
|
settings.webhook.payload=Obsah
|
||||||
settings.webhook.body=Tělo zprávy
|
settings.webhook.body=Tělo zprávy
|
||||||
settings.webhook.replay.description=Zopakovat tento webový háček.
|
settings.webhook.replay.description=Zopakovat tento webhook.
|
||||||
settings.webhook.replay.description_disabled=Chcete-li znovu spustit tento webový háček, aktivujte jej.
|
settings.webhook.replay.description_disabled=Chcete-li zopakovat tento webhook, aktivujte jej.
|
||||||
settings.webhook.delivery.success=Událost byla přidána do fronty doručení. Může to trvat několik sekund, než se zobrazí v historii doručení.
|
settings.webhook.delivery.success=Událost byla přidána do fronty doručení. Může to trvat několik sekund, než se zobrazí v historii doručení.
|
||||||
settings.githooks_desc=Git hooks jsou spravovány samotným Gitem. Níže můžete upravit soubory hooků pro nastavení vlastních operací.
|
settings.githooks_desc=Git hooks jsou spravovány samotným Gitem. Níže můžete upravit soubory hooků pro nastavení vlastních operací.
|
||||||
settings.githook_edit_desc=Je-li háček neaktivní, bude zobrazen vzorový obsah. Nebude-li zadán žádný obsah, háček bude vypnut.
|
settings.githook_edit_desc=Je-li webhook neaktivní, bude zobrazen vzorový obsah. Ponechte prázdné pro zakázání tohoto webhooku.
|
||||||
settings.githook_name=Název hooku
|
settings.githook_name=Název hooku
|
||||||
settings.githook_content=Obsah hooku
|
settings.githook_content=Obsah hooku
|
||||||
settings.update_githook=Upravit hook
|
settings.update_githook=Upravit hook
|
||||||
|
@ -2303,7 +2301,7 @@ settings.event_create=Vytvořit
|
||||||
settings.event_create_desc=Větev nebo značka vytvořena.
|
settings.event_create_desc=Větev nebo značka vytvořena.
|
||||||
settings.event_delete=Smazat
|
settings.event_delete=Smazat
|
||||||
settings.event_delete_desc=Větev nebo značka smazána.
|
settings.event_delete_desc=Větev nebo značka smazána.
|
||||||
settings.event_fork=Rozštěpit
|
settings.event_fork=Fork
|
||||||
settings.event_fork_desc=Repozitář rozštěpen.
|
settings.event_fork_desc=Repozitář rozštěpen.
|
||||||
settings.event_wiki=Wiki
|
settings.event_wiki=Wiki
|
||||||
settings.event_wiki_desc=Wiki stránka vytvořena, přejmenována nebo smazána.
|
settings.event_wiki_desc=Wiki stránka vytvořena, přejmenována nebo smazána.
|
||||||
|
@ -2314,32 +2312,32 @@ settings.event_push_desc=Nahrání pomocí Gitu do repozitáře.
|
||||||
settings.event_repository=Repozitář
|
settings.event_repository=Repozitář
|
||||||
settings.event_repository_desc=Repozitář vytvořen nebo smazán.
|
settings.event_repository_desc=Repozitář vytvořen nebo smazán.
|
||||||
settings.event_header_issue=Události problémů
|
settings.event_header_issue=Události problémů
|
||||||
settings.event_issues=Problémy
|
settings.event_issues=Úprava
|
||||||
settings.event_issues_desc=Problém otevřen, uzavřen, znovu otevřen nebo upraven.
|
settings.event_issues_desc=Problém otevřen, uzavřen, znovu otevřen nebo upraven.
|
||||||
settings.event_issue_assign=Problém přiřazen
|
settings.event_issue_assign=Přiřazení
|
||||||
settings.event_issue_assign_desc=Problém přiřazen nebo nepřiřazen.
|
settings.event_issue_assign_desc=Problém přiřazen nebo nepřiřazen.
|
||||||
settings.event_issue_label=Problém označen
|
settings.event_issue_label=Štítky
|
||||||
settings.event_issue_label_desc=Štítky problému upraveny nebo vymazány.
|
settings.event_issue_label_desc=Štítky problému přidány nebo odstraněny.
|
||||||
settings.event_issue_milestone=K problému přidán milník
|
settings.event_issue_milestone=Milníky
|
||||||
settings.event_issue_milestone_desc=K problému přidán nebo odebrán milník.
|
settings.event_issue_milestone_desc=Milník přidán, odstraněn nebo upraven.
|
||||||
settings.event_issue_comment=Komentář k problému
|
settings.event_issue_comment=Komentáře
|
||||||
settings.event_issue_comment_desc=Přidán, upraven nebo smazán komentář problému.
|
settings.event_issue_comment_desc=Přidán, upraven nebo smazán komentář problému.
|
||||||
settings.event_header_pull_request=Události žádosti o sloučení
|
settings.event_header_pull_request=Události žádosti o sloučení
|
||||||
settings.event_pull_request=Žádost o sloučení
|
settings.event_pull_request=Úprava
|
||||||
settings.event_pull_request_desc=Požadavek na natažení otevřen, uzavřen, znovu otevřen nebo upraven.
|
settings.event_pull_request_desc=Požadavek na natažení otevřen, uzavřen, znovu otevřen nebo upraven.
|
||||||
settings.event_pull_request_assign=Žádost o sloučení přiřazena
|
settings.event_pull_request_assign=Přiřazení
|
||||||
settings.event_pull_request_assign_desc=Požadavek na natažení přiřazen nebo nepřiřazen.
|
settings.event_pull_request_assign_desc=Požadavek na natažení přiřazen nebo nepřiřazen.
|
||||||
settings.event_pull_request_label=Žádost o sloučení označena
|
settings.event_pull_request_label=Štítky
|
||||||
settings.event_pull_request_label_desc=Štítky požadavku na natažení aktualizovány nebo vymazány.
|
settings.event_pull_request_label_desc=Štítky žádosti o sloučení přidány nebo odstraněny.
|
||||||
settings.event_pull_request_milestone=K žádosti o sloučení přidán milník
|
settings.event_pull_request_milestone=Milníky
|
||||||
settings.event_pull_request_milestone_desc=Požadavku na natažení přidán nebo odebrán milník.
|
settings.event_pull_request_milestone_desc=Milník přidán, odstraněn nebo upraven.
|
||||||
settings.event_pull_request_comment=Žádost o sloučení okomentována
|
settings.event_pull_request_comment=Komentáře
|
||||||
settings.event_pull_request_comment_desc=Komentář požadavku na natažení vytvořen, upraven nebo odstraněn.
|
settings.event_pull_request_comment_desc=Komentář požadavku na natažení vytvořen, upraven nebo odstraněn.
|
||||||
settings.event_pull_request_review=Žádost o sloučení zkontrolována
|
settings.event_pull_request_review=Kontroly
|
||||||
settings.event_pull_request_review_desc=Požadavek na natažení schválen, odmítnut nebo zkontrolován.
|
settings.event_pull_request_review_desc=Žádost o sloučení schválena, zamítnuta nebo byl přidán komentář kontroly.
|
||||||
settings.event_pull_request_sync=Žádost o sloučení synchronizována
|
settings.event_pull_request_sync=Synchronizováno
|
||||||
settings.event_pull_request_sync_desc=Požadavek na natažení synchronizován.
|
settings.event_pull_request_sync_desc=Větev automaticky aktualizována s cílovou větví.
|
||||||
settings.event_pull_request_review_request=Vyžádána kontrola žádosti o sloučení
|
settings.event_pull_request_review_request=Žádosti o kontrolu
|
||||||
settings.event_package=Balíček
|
settings.event_package=Balíček
|
||||||
settings.event_package_desc=Balíček vytvořen nebo odstraněn v repozitáři.
|
settings.event_package_desc=Balíček vytvořen nebo odstraněn v repozitáři.
|
||||||
settings.branch_filter=Filtr větví
|
settings.branch_filter=Filtr větví
|
||||||
|
@ -2348,9 +2346,9 @@ settings.authorization_header=Autorizační hlavička
|
||||||
settings.authorization_header_desc=Pokud vyplněno, bude připojeno k požadavkům jako autorizační hlavička. Příklady: %s.
|
settings.authorization_header_desc=Pokud vyplněno, bude připojeno k požadavkům jako autorizační hlavička. Příklady: %s.
|
||||||
settings.active=Aktivní
|
settings.active=Aktivní
|
||||||
settings.active_helper=Informace o spuštěných událostech budou odeslány na URL webového háčku.
|
settings.active_helper=Informace o spuštěných událostech budou odeslány na URL webového háčku.
|
||||||
settings.add_hook_success=Webový háček byl přidán.
|
settings.add_hook_success=Webhook byl přidán.
|
||||||
settings.update_webhook=Upravit webhook
|
settings.update_webhook=Upravit webhook
|
||||||
settings.update_hook_success=Webový háček byl aktualizován.
|
settings.update_hook_success=Webhook byl aktualizován.
|
||||||
settings.delete_webhook=Odstranit webhook
|
settings.delete_webhook=Odstranit webhook
|
||||||
settings.recent_deliveries=Nedávná doručení
|
settings.recent_deliveries=Nedávná doručení
|
||||||
settings.hook_type=Typ hooku
|
settings.hook_type=Typ hooku
|
||||||
|
@ -2436,7 +2434,7 @@ settings.protect_branch_name_pattern=Vzor jména chráněné větve
|
||||||
settings.protect_branch_name_pattern_desc=Vzory názvů chráněných větví. Pro vzorovou syntaxi viz <a href="%s">dokumentace</a>. Příklady: main, release/**
|
settings.protect_branch_name_pattern_desc=Vzory názvů chráněných větví. Pro vzorovou syntaxi viz <a href="%s">dokumentace</a>. Příklady: main, release/**
|
||||||
settings.protect_patterns=Vzory
|
settings.protect_patterns=Vzory
|
||||||
settings.protect_protected_file_patterns=Vzory chráněných souborů (oddělené středníkem „;“)
|
settings.protect_protected_file_patterns=Vzory chráněných souborů (oddělené středníkem „;“)
|
||||||
settings.protect_protected_file_patterns_desc=Chráněné soubory, které nemají povoleno být měněny přímo, i když uživatel má právo přidávat, upravovat nebo mazat soubory v této větvi. Více vzorů lze oddělit pomocí středníku („;“). Podívejte se na <a href="%s">github.com/gobwas/glob</a> dokumentaci pro syntaxi vzoru. Příklady: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>.
|
settings.protect_protected_file_patterns_desc=Chráněné soubory, které nemají povoleno být měněny přímo, i když uživatel má právo přidávat, upravovat nebo mazat soubory v této větvi. Více vzorů lze oddělit pomocí středníku („;“). Podívejte se na dokumentaci <a href="%[1]s">%[2]s</a> pro syntaxi vzoru. Příklady: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>.
|
||||||
settings.protect_unprotected_file_patterns=Vzory nechráněných souborů (oddělené středníkem „;“)
|
settings.protect_unprotected_file_patterns=Vzory nechráněných souborů (oddělené středníkem „;“)
|
||||||
settings.protect_unprotected_file_patterns_desc=Nechráněné soubory, které je možné měnit přímo, pokud má uživatel právo zápisu, čímž se obejde omezení push. Více vzorů lze oddělit pomocí středníku („;“). Podívejte se na <a href="%[1]s">%[2]s</a> dokumentaci pro syntaxi vzoru. Příklady: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>.
|
settings.protect_unprotected_file_patterns_desc=Nechráněné soubory, které je možné měnit přímo, pokud má uživatel právo zápisu, čímž se obejde omezení push. Více vzorů lze oddělit pomocí středníku („;“). Podívejte se na <a href="%[1]s">%[2]s</a> dokumentaci pro syntaxi vzoru. Příklady: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>.
|
||||||
settings.add_protected_branch=Zapnout ochranu
|
settings.add_protected_branch=Zapnout ochranu
|
||||||
|
@ -2479,7 +2477,7 @@ settings.matrix.room_id=ID místnosti
|
||||||
settings.matrix.message_type=Typ zprávy
|
settings.matrix.message_type=Typ zprávy
|
||||||
settings.archive.button=Archivovat repozitář
|
settings.archive.button=Archivovat repozitář
|
||||||
settings.archive.header=Archivovat tento repozitář
|
settings.archive.header=Archivovat tento repozitář
|
||||||
settings.archive.text=Archivace repozitáře způsobí, že bude zcela určen pouze pro čtení. Bude skryt z ovládacího panelu. Nikdo (ani vy!) nebude moci vytvářet nové revize ani otevírat nové úkoly nebo žádosti o natažení.
|
settings.archive.text = Archivováním repozitáře jej celý převedete do stavu pouze pro čtení. Bude skryt z nástěnky. Nikdo (ani vy!) nebude moci vytvářet nové commity ani otevírat problémy a žádosti o sloučení.
|
||||||
settings.archive.success=Repozitář byl úspěšně archivován.
|
settings.archive.success=Repozitář byl úspěšně archivován.
|
||||||
settings.archive.error=Nastala chyba při archivování repozitáře. Prohlédněte si záznam pro více detailů.
|
settings.archive.error=Nastala chyba při archivování repozitáře. Prohlédněte si záznam pro více detailů.
|
||||||
settings.archive.error_ismirror=Nemůžete archivovat zrcadlený repozitář.
|
settings.archive.error_ismirror=Nemůžete archivovat zrcadlený repozitář.
|
||||||
|
@ -2558,7 +2556,7 @@ diff.generated=vygenerováno
|
||||||
diff.vendored=vendorováno
|
diff.vendored=vendorováno
|
||||||
diff.comment.add_line_comment=Přidat jednořádkový komentář
|
diff.comment.add_line_comment=Přidat jednořádkový komentář
|
||||||
diff.comment.placeholder=Zanechat komentář
|
diff.comment.placeholder=Zanechat komentář
|
||||||
diff.comment.markdown_info=Je podporována úprava vzhledu pomocí markdown.
|
diff.comment.markdown_info=Je podporováno stylování pomocí Markdown.
|
||||||
diff.comment.add_single_comment=Přidat jeden komentář
|
diff.comment.add_single_comment=Přidat jeden komentář
|
||||||
diff.comment.add_review_comment=Přidat komentář
|
diff.comment.add_review_comment=Přidat komentář
|
||||||
diff.comment.start_review=Začít posuzování
|
diff.comment.start_review=Začít posuzování
|
||||||
|
@ -2582,14 +2580,14 @@ diff.hide_file_tree=Skrýt souborový strom
|
||||||
|
|
||||||
releases.desc=Sledování verzí projektu a souborů ke stažení.
|
releases.desc=Sledování verzí projektu a souborů ke stažení.
|
||||||
release.releases=Vydání
|
release.releases=Vydání
|
||||||
release.detail=Podrobnosti vydání
|
release.detail=Podrobnosti o vydání
|
||||||
release.tags=Značky
|
release.tags=Značky
|
||||||
release.new_release=Nové vydání
|
release.new_release=Nové vydání
|
||||||
release.draft=Koncept
|
release.draft=Koncept
|
||||||
release.prerelease=Předběžná verze
|
release.prerelease=Předběžná verze
|
||||||
release.stable=Stabilní
|
release.stable=Stabilní
|
||||||
release.compare=Porovnat
|
release.compare=Porovnat
|
||||||
release.edit=upravit
|
release.edit=Upravit
|
||||||
release.ahead.commits=<strong>%d</strong> revizí
|
release.ahead.commits=<strong>%d</strong> revizí
|
||||||
release.ahead.target=do %s od tohoto vydání
|
release.ahead.target=do %s od tohoto vydání
|
||||||
tag.ahead.target=do %s od této značky
|
tag.ahead.target=do %s od této značky
|
||||||
|
@ -2685,40 +2683,28 @@ error.csv.invalid_field_count=Soubor nelze vykreslit, protože má nesprávný p
|
||||||
pulls.made_using_agit = AGit
|
pulls.made_using_agit = AGit
|
||||||
settings.confirm_wiki_branch_rename = Přejmenovat větev Wiki
|
settings.confirm_wiki_branch_rename = Přejmenovat větev Wiki
|
||||||
issues.comment.blocked_by_user = U tohoto problému nemůžete vytvořit komentář, protože jste byl/a zablokován/a majitelem repozitáře nebo autorem problému.
|
issues.comment.blocked_by_user = U tohoto problému nemůžete vytvořit komentář, protože jste byl/a zablokován/a majitelem repozitáře nebo autorem problému.
|
||||||
contributors.contribution_type.filter_label = Typ přispění:
|
|
||||||
contributors.contribution_type.additions = Přidání
|
contributors.contribution_type.additions = Přidání
|
||||||
admin.manage_flags = Spravovat vlajky
|
admin.manage_flags = Spravovat vlajky
|
||||||
admin.enabled_flags = Vlajky povolené v repozitáři:
|
admin.enabled_flags = Vlajky povolené v repozitáři:
|
||||||
admin.update_flags = Upravit vlajky
|
admin.update_flags = Upravit vlajky
|
||||||
admin.failed_to_replace_flags = Nepodařilo se nahradit vlajky repozitáře
|
admin.failed_to_replace_flags = Nepodařilo se nahradit vlajky repozitáře
|
||||||
admin.flags_replaced = Vlajky repozitáře nahrazeny
|
admin.flags_replaced = Vlajky repozitáře nahrazeny
|
||||||
desc.sha256 = SHA256
|
|
||||||
issues.label_exclusive_warning = Při úpravě štítků problému nebo žádosti o sloučení budou odstraněny všechny konfliktní štítky.
|
|
||||||
pulls.cmd_instruction_checkout_title = Kontrola
|
pulls.cmd_instruction_checkout_title = Kontrola
|
||||||
settings.mirror_settings.docs.disabled_push_mirror.info = Push zrcadla byla zakázána administrátorem vašeho webu.
|
settings.mirror_settings.docs.disabled_push_mirror.info = Push zrcadla byla zakázána administrátorem vašeho webu.
|
||||||
generated = Generováno
|
|
||||||
clone_in_vscodium = Klonovat do VSCodium
|
clone_in_vscodium = Klonovat do VSCodium
|
||||||
settings.wiki_rename_branch_main_notices_1 = Tato operace je <strong>NEVRATNÁ</strong>.
|
settings.wiki_rename_branch_main_notices_1 = Tato operace je <strong>NEVRATNÁ</strong>.
|
||||||
settings.wiki_branch_rename_success = Název větve Wiki repozitáře byl úspěšně normalizován.
|
settings.wiki_branch_rename_success = Název větve Wiki repozitáře byl úspěšně normalizován.
|
||||||
object_format = Objektový formát
|
|
||||||
rss.must_be_on_branch = Abyste mohli mít zdroj RSS, musíte se nacházet ve větvi.
|
rss.must_be_on_branch = Abyste mohli mít zdroj RSS, musíte se nacházet ve větvi.
|
||||||
object_format_helper = Objektový formát repozitáře. Později jej nelze změnit. Nejkompatibilnější je SHA1.
|
|
||||||
issues.blocked_by_user = V tomto repozitáři nemůžete vytvořit problém, protože jste byl/a jeho majitelem zablokován/a.
|
issues.blocked_by_user = V tomto repozitáři nemůžete vytvořit problém, protože jste byl/a jeho majitelem zablokován/a.
|
||||||
migrate.forgejo.description = Migrovat data z codeberg.org nebo jiných instancí Forgejo.
|
migrate.forgejo.description = Migrovat data z codeberg.org nebo jiných instancí Forgejo.
|
||||||
mirror_sync = synchronizováno
|
mirror_sync = synchronizováno
|
||||||
blame.ignore_revs = Ignorování revizí v souboru <a href="%s">.git-blame-ignore-revs</a>. Klikněte <a href="%s">sem pro udělení výjimky</a> a zobrazení normálního přehledu blame.
|
blame.ignore_revs = Ignorování revizí v souboru <a href="%s">.git-blame-ignore-revs</a>. Klikněte <a href="%s">sem pro udělení výjimky</a> a zobrazení normálního přehledu blame.
|
||||||
commits.browse_further = Procházet dále
|
commits.browse_further = Procházet dále
|
||||||
issues.role.first_time_contributor = První přispěvatel
|
issues.role.first_time_contributor = První přispěvatel
|
||||||
vendored = Vendorováno
|
|
||||||
editor.invalid_commit_mail = Neplatný e-mail pro vytvoření commitu.
|
editor.invalid_commit_mail = Neplatný e-mail pro vytvoření commitu.
|
||||||
commits.renamed_from = Přejmenováno z %s
|
commits.renamed_from = Přejmenováno z %s
|
||||||
issues.label_exclusive_desc = Pojmenujte štítek <code>scope/item</code>, aby se vzájemně vylučoval s ostatními štítky <code>scope/</code>.
|
|
||||||
issues.label_archive_tooltip = Štítek Archivováno jsou ve výchozím nastavení vyloučeny z návrhů při vyhledávání podle štítků.
|
|
||||||
issues.label_archive = Štítek archivu
|
|
||||||
milestones.new_subheader = Milníky vám pomohou zorganizovat problémy a sledovat jejich pokrok.
|
|
||||||
pulls.nothing_to_compare_have_tag = Vybraná větev a značka jsou shodné.
|
|
||||||
activity.navbar.recent_commits = Nedávné commity
|
activity.navbar.recent_commits = Nedávné commity
|
||||||
settings.units.units = Jednotky repozitáře
|
settings.units.units = Jednotky
|
||||||
pulls.blocked_by_user = V tomto repozitáři nemůžete vytvořit žádost o sloučení, protože jste byli zablokováni jeho majitelem.
|
pulls.blocked_by_user = V tomto repozitáři nemůžete vytvořit žádost o sloučení, protože jste byli zablokováni jeho majitelem.
|
||||||
pulls.clear_merge_message_hint = Vymazáním zprávy o sloučení pouze odstraníte obsah zprávy commitu a ponecháte vygenerované git trailery, jako „Co-Authored-By …“.
|
pulls.clear_merge_message_hint = Vymazáním zprávy o sloučení pouze odstraníte obsah zprávy commitu a ponecháte vygenerované git trailery, jako „Co-Authored-By …“.
|
||||||
pulls.agit_explanation = Vytvořeno pomocí workflow AGit. AGit umožňuje přispěvatelům navrhovat změny pomocí „git push“ bez vytváření forku nebo nové větve.
|
pulls.agit_explanation = Vytvořeno pomocí workflow AGit. AGit umožňuje přispěvatelům navrhovat změny pomocí „git push“ bez vytváření forku nebo nové větve.
|
||||||
|
@ -2727,7 +2713,7 @@ settings.pull_mirror_sync_in_progress = Probíhá načítání změn ze vzdálen
|
||||||
settings.enter_repo_name = Zadejte majitele a repozitář přesně tak, jak je vidíte níže:
|
settings.enter_repo_name = Zadejte majitele a repozitář přesně tak, jak je vidíte níže:
|
||||||
settings.mirror_settings.docs.disabled_push_mirror.pull_mirror_warning = Tuto akci lze v současné chvíli provést pouze v nabídce „Nová migrace“. Pro více informací viz:
|
settings.mirror_settings.docs.disabled_push_mirror.pull_mirror_warning = Tuto akci lze v současné chvíli provést pouze v nabídce „Nová migrace“. Pro více informací viz:
|
||||||
settings.new_owner_blocked_doer = Nový majitel vás zablokoval.
|
settings.new_owner_blocked_doer = Nový majitel vás zablokoval.
|
||||||
settings.mirror_settings.pushed_repository = Pushnutý repozitář
|
settings.mirror_settings.pushed_repository = Odeslaný repozitář
|
||||||
settings.add_collaborator_blocked_our = Nepodařilo se přidat spolupracovníka, jelikož byl zablokován majitelem repozitáře.
|
settings.add_collaborator_blocked_our = Nepodařilo se přidat spolupracovníka, jelikož byl zablokován majitelem repozitáře.
|
||||||
pulls.commit_ref_at = `se odkázal na tuto žádost o sloučení z commitu <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
pulls.commit_ref_at = `se odkázal na tuto žádost o sloučení z commitu <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
||||||
settings.wiki_rename_branch_main = Normalizovat název větve Wiki
|
settings.wiki_rename_branch_main = Normalizovat název větve Wiki
|
||||||
|
@ -2735,7 +2721,6 @@ settings.wiki_rename_branch_main_desc = Přejmenovat větev interně používano
|
||||||
pulls.fast_forward_only_merge_pull_request = Pouze zrychlené
|
pulls.fast_forward_only_merge_pull_request = Pouze zrychlené
|
||||||
pulls.reopen_failed.head_branch = Tuto žádost o sloučení nelze znovu otevřít, protože hlavní větev již neexistuje.
|
pulls.reopen_failed.head_branch = Tuto žádost o sloučení nelze znovu otevřít, protože hlavní větev již neexistuje.
|
||||||
pulls.reopen_failed.base_branch = Tuto žádost o sloučení nelze znovu otevřít, protože základní větev již neexistuje.
|
pulls.reopen_failed.base_branch = Tuto žádost o sloučení nelze znovu otevřít, protože základní větev již neexistuje.
|
||||||
issues.dependency.issue_batch_close_blocked = Nepodařilo se hromadně zavřít vybrané problémy, protože problém #%d má stále otevřené závislosti
|
|
||||||
pulls.recently_pushed_new_branches = Pushnuli jste do větve <a href="%[3]s"><strong>%[1]s</strong></a> %[2]s
|
pulls.recently_pushed_new_branches = Pushnuli jste do větve <a href="%[3]s"><strong>%[1]s</strong></a> %[2]s
|
||||||
wiki.cancel = Zrušit
|
wiki.cancel = Zrušit
|
||||||
activity.navbar.pulse = Pulz
|
activity.navbar.pulse = Pulz
|
||||||
|
@ -2744,7 +2729,7 @@ activity.navbar.contributors = Přispěvatelé
|
||||||
settings.mirror_settings.docs.pull_mirror_instructions = Pro nastavení pull zrcadla viz:
|
settings.mirror_settings.docs.pull_mirror_instructions = Pro nastavení pull zrcadla viz:
|
||||||
settings.mirror_settings.docs.doc_link_pull_section = sekci „Pulling from a remote repository“ v dokumentaci.
|
settings.mirror_settings.docs.doc_link_pull_section = sekci „Pulling from a remote repository“ v dokumentaci.
|
||||||
settings.units.overview = Přehled
|
settings.units.overview = Přehled
|
||||||
settings.units.add_more = Přidat další...
|
settings.units.add_more = Povolit další
|
||||||
settings.push_mirror_sync_in_progress = Probíhá odesílání změn na vzdálený %s.
|
settings.push_mirror_sync_in_progress = Probíhá odesílání změn na vzdálený %s.
|
||||||
settings.wiki_globally_editable = Umožnit komukoli editovat wiki
|
settings.wiki_globally_editable = Umožnit komukoli editovat wiki
|
||||||
settings.confirmation_string = Potvrzovací řetězec
|
settings.confirmation_string = Potvrzovací řetězec
|
||||||
|
@ -2759,7 +2744,6 @@ file_follow = Následovat symbolický odkaz
|
||||||
settings.protect_status_check_patterns_desc = Zadejte vzorce pro upřesnění kontrol, které musí projít před sloučením větví do větve, která se shoduje s tímto pravidlem. Na každý řádek zadejte jeden vzorec. Vzorce nesmí být prázdné.
|
settings.protect_status_check_patterns_desc = Zadejte vzorce pro upřesnění kontrol, které musí projít před sloučením větví do větve, která se shoduje s tímto pravidlem. Na každý řádek zadejte jeden vzorec. Vzorce nesmí být prázdné.
|
||||||
settings.archive.mirrors_unavailable = Zrcadla nejsou dostupná, když je repozitář archivován.
|
settings.archive.mirrors_unavailable = Zrcadla nejsou dostupná, když je repozitář archivován.
|
||||||
settings.protect_enable_merge_desc = Kdokoli s přístupem k zápisu bude moci slučovat žádosti o sloučení do této větve.
|
settings.protect_enable_merge_desc = Kdokoli s přístupem k zápisu bude moci slučovat žádosti o sloučení do této větve.
|
||||||
settings.archive.text = Archivováním repozitáře jej celý převedete do stavu pouze pro čtení. Bude skryt z nástěnky. Nikdo (ani vy!) nebude moci vytvářet nové commity ani otevírat problémy a žádosti o sloučení.
|
|
||||||
settings.event_pull_request_review_request_desc = Bylo požádáno o posouzení žádosti o sloučení nebo bylo toto požádání odstraněno.
|
settings.event_pull_request_review_request_desc = Bylo požádáno o posouzení žádosti o sloučení nebo bylo toto požádání odstraněno.
|
||||||
error.broken_git_hook = Zdá se, že u tohoto repozitáře jsou rozbité Git hooks. Pro jejich opravení se prosím řiďte pokyny v <a target="_blank" rel="noreferrer" href="%s">dokumentaci</a> a poté odešlete několik commitů pro obnovení stavu.
|
error.broken_git_hook = Zdá se, že u tohoto repozitáře jsou rozbité Git hooks. Pro jejich opravení se prosím řiďte pokyny v <a target="_blank" rel="noreferrer" href="%s">dokumentaci</a> a poté odešlete několik commitů pro obnovení stavu.
|
||||||
pulls.title_desc_one = žádá o sloučení %[1]d commitu z <code>%[2]s</code> do <code id="branch_target">%[3]s</code>
|
pulls.title_desc_one = žádá o sloučení %[1]d commitu z <code>%[2]s</code> do <code id="branch_target">%[3]s</code>
|
||||||
|
@ -2783,8 +2767,8 @@ settings.enforce_on_admins_desc = Správci repozitáře nemohou obejít toto pra
|
||||||
issues.num_participants_one = %d účastník
|
issues.num_participants_one = %d účastník
|
||||||
size_format = %[1]s: %[2]s, %[3]s: %[4]s
|
size_format = %[1]s: %[2]s, %[3]s: %[4]s
|
||||||
issues.archived_label_description = (Archivován) %s
|
issues.archived_label_description = (Archivován) %s
|
||||||
release.download_count_one = %d stažení
|
release.download_count_one = %s stažení
|
||||||
release.download_count_few = %d stažení
|
release.download_count_few = %s stažení
|
||||||
release.system_generated = Tato příloha byla automaticky vygenerována.
|
release.system_generated = Tato příloha byla automaticky vygenerována.
|
||||||
settings.add_webhook.invalid_path = Cesta nesmí obsahovat část, která je „.“ nebo „..“ nebo prázdný řetězec. Nesmí začínat ani končit lomítkem.
|
settings.add_webhook.invalid_path = Cesta nesmí obsahovat část, která je „.“ nebo „..“ nebo prázdný řetězec. Nesmí začínat ani končit lomítkem.
|
||||||
settings.web_hook_name_sourcehut_builds = Sestavení SourceHut
|
settings.web_hook_name_sourcehut_builds = Sestavení SourceHut
|
||||||
|
@ -2829,7 +2813,7 @@ activity.published_tag_label = Štítek
|
||||||
settings.pull_mirror_sync_quota_exceeded = Kvóta překročena, nestahuji změny.
|
settings.pull_mirror_sync_quota_exceeded = Kvóta překročena, nestahuji změny.
|
||||||
settings.transfer_quota_exceeded = Nový majitel (%s) překročil kvótu. Repozitář nebyl převeden.
|
settings.transfer_quota_exceeded = Nový majitel (%s) překročil kvótu. Repozitář nebyl převeden.
|
||||||
release.asset_name = Název přílohy
|
release.asset_name = Název přílohy
|
||||||
release.invalid_external_url = Neplatná externí URL: „%s“
|
release.invalid_external_url = Neplatná externí adresa URL: „%s“
|
||||||
no_eol.text = Žádný EOL
|
no_eol.text = Žádný EOL
|
||||||
no_eol.tooltip = Tento soubor neobsahuje koncový znak ukončení řádku.
|
no_eol.tooltip = Tento soubor neobsahuje koncový znak ukončení řádku.
|
||||||
pulls.cmd_instruction_merge_warning = <b>Varování:</b> Nastavení „Autodetekce ručního sloučení“ není u tohoto repozitáře povoleno, tuto žádost o sloučení budete muset poté označit jako ručně sloučenou.
|
pulls.cmd_instruction_merge_warning = <b>Varování:</b> Nastavení „Autodetekce ručního sloučení“ není u tohoto repozitáře povoleno, tuto žádost o sloučení budete muset poté označit jako ručně sloučenou.
|
||||||
|
@ -2841,6 +2825,15 @@ mirror_denied_combination = Nelze použít kombinaci ověřování pomocí veře
|
||||||
mirror_public_key = Veřejný klíč SSH
|
mirror_public_key = Veřejný klíč SSH
|
||||||
settings.mirror_settings.push_mirror.none_ssh = Žádné
|
settings.mirror_settings.push_mirror.none_ssh = Žádné
|
||||||
mirror_use_ssh.not_available = Ověřování SSH není dostupné.
|
mirror_use_ssh.not_available = Ověřování SSH není dostupné.
|
||||||
|
issues.new.assign_to_me = Přiřadit mně
|
||||||
|
issues.all_title = Vše
|
||||||
|
settings.discord_icon_url.exceeds_max_length = Adresa URL ikony musí mít méně než 2048 znaků
|
||||||
|
issues.review.add_review_requests = požádal/a o kontroly od %[1]s %[2]s
|
||||||
|
issues.review.remove_review_requests = odstranil/a žádosti o kontrolu u %[1]s %[2]s
|
||||||
|
issues.review.add_remove_review_requests = požádal/a o kontroly od %[1]s a odstranil/a žádosti u %[2]s %[3]s
|
||||||
|
pulls.delete_after_merge.head_branch.is_default = Větev hlavy, kterou chcete odstranit, je výchozí větví a nelze ji odstranit.
|
||||||
|
pulls.delete_after_merge.head_branch.is_protected = Větev hlavy, kterou chcete odstranit, je chráněnou větví a nelze ji odstranit.
|
||||||
|
pulls.delete_after_merge.head_branch.insufficient_branch = Nemáte oprávnění k odstranění větve hlavy.
|
||||||
|
|
||||||
[graphs]
|
[graphs]
|
||||||
component_loading_info = Tohle může chvíli trvat…
|
component_loading_info = Tohle může chvíli trvat…
|
||||||
|
@ -2885,7 +2878,7 @@ settings.email=Kontaktní e-mail
|
||||||
settings.website=Webové stránky
|
settings.website=Webové stránky
|
||||||
settings.location=Umístění
|
settings.location=Umístění
|
||||||
settings.permission=Oprávnění
|
settings.permission=Oprávnění
|
||||||
settings.repoadminchangeteam=Správce úložišť může týmům přidávat a odebírat přístup
|
settings.repoadminchangeteam=Správce repozitářů může týmům přidávat a odebírat přístup
|
||||||
settings.visibility=Viditelnost
|
settings.visibility=Viditelnost
|
||||||
settings.visibility.public=Veřejná
|
settings.visibility.public=Veřejná
|
||||||
settings.visibility.limited=Omezená (viditelné pouze pro ověřené uživatele)
|
settings.visibility.limited=Omezená (viditelné pouze pro ověřené uživatele)
|
||||||
|
@ -2904,7 +2897,7 @@ settings.delete_prompt=Organizace bude trvale odstraněna. Tato změna <strong>N
|
||||||
settings.confirm_delete_account=Potvrdit odstranění
|
settings.confirm_delete_account=Potvrdit odstranění
|
||||||
settings.delete_org_title=Odstranit organizaci
|
settings.delete_org_title=Odstranit organizaci
|
||||||
settings.delete_org_desc=Tato organizace bude trvale smazána. Pokračovat?
|
settings.delete_org_desc=Tato organizace bude trvale smazána. Pokračovat?
|
||||||
settings.hooks_desc=Přidat webové háčky, které budou spouštěny pro <strong>všechny repozitáře</strong> v této organizaci.
|
settings.hooks_desc=Přidat webhooky, které budou spouštěny pro <strong>všechny repozitáře</strong> v této organizaci.
|
||||||
|
|
||||||
settings.labels_desc=Přidejte štítky, které mohou být použity pro problémy <strong>všech repozitářů</strong> v rámci této organizace.
|
settings.labels_desc=Přidejte štítky, které mohou být použity pro problémy <strong>všech repozitářů</strong> v rámci této organizace.
|
||||||
|
|
||||||
|
@ -2983,7 +2976,7 @@ identity_access=Identita a přístup
|
||||||
users=Uživatelské účty
|
users=Uživatelské účty
|
||||||
organizations=Organizace
|
organizations=Organizace
|
||||||
repositories=Repozitáře
|
repositories=Repozitáře
|
||||||
hooks=Webové háčky
|
hooks=Webhooky
|
||||||
integrations=Integrace
|
integrations=Integrace
|
||||||
authentication=Zdroje ověření
|
authentication=Zdroje ověření
|
||||||
emails=Uživatelské e-maily
|
emails=Uživatelské e-maily
|
||||||
|
@ -3022,7 +3015,7 @@ dashboard.delete_repo_archives.started=Spuštěna úloha smazání všech archiv
|
||||||
dashboard.delete_missing_repos=Smazat všechny repozitáře, které nemají Git soubory
|
dashboard.delete_missing_repos=Smazat všechny repozitáře, které nemají Git soubory
|
||||||
dashboard.delete_missing_repos.started=Spuštěna úloha mazání všech repozitářů, které nemají Git soubory.
|
dashboard.delete_missing_repos.started=Spuštěna úloha mazání všech repozitářů, které nemají Git soubory.
|
||||||
dashboard.delete_generated_repository_avatars=Odstranit vygenerované avatary repozitářů
|
dashboard.delete_generated_repository_avatars=Odstranit vygenerované avatary repozitářů
|
||||||
dashboard.sync_repo_tags=Synchronizovat značky z git dat do databáze
|
dashboard.sync_repo_tags = Synchronizovat značky z dat Gitu do databáze
|
||||||
dashboard.update_mirrors=Upravit zrcadla
|
dashboard.update_mirrors=Upravit zrcadla
|
||||||
dashboard.repo_health_check=Kontrola stavu všech repozitářů
|
dashboard.repo_health_check=Kontrola stavu všech repozitářů
|
||||||
dashboard.check_repo_stats=Zkontrolovat všechny statistiky repositáře
|
dashboard.check_repo_stats=Zkontrolovat všechny statistiky repositáře
|
||||||
|
@ -3070,15 +3063,14 @@ dashboard.delete_old_actions=Odstranit všechny staré aktivity z databáze
|
||||||
dashboard.delete_old_actions.started=Spuštěno odstraňování všech starých aktivit z databáze.
|
dashboard.delete_old_actions.started=Spuštěno odstraňování všech starých aktivit z databáze.
|
||||||
dashboard.update_checker=Kontrola aktualizací
|
dashboard.update_checker=Kontrola aktualizací
|
||||||
dashboard.delete_old_system_notices=Odstranit všechna stará systémová upozornění z databáze
|
dashboard.delete_old_system_notices=Odstranit všechna stará systémová upozornění z databáze
|
||||||
dashboard.gc_lfs=Úklid LFS meta objektů
|
dashboard.gc_lfs = Sbírat garbage z LFS meta objektů
|
||||||
dashboard.stop_zombie_tasks=Zastavit akce zombie úloh
|
dashboard.stop_zombie_tasks=Zastavit akce zombie úloh
|
||||||
dashboard.stop_endless_tasks=Zastavit akce nekonečných úloh
|
dashboard.stop_endless_tasks=Zastavit akce nekonečných úloh
|
||||||
dashboard.cancel_abandoned_jobs=Zrušit akce opuštěných úloh
|
dashboard.cancel_abandoned_jobs=Zrušit akce opuštěných úloh
|
||||||
dashboard.start_schedule_tasks=Spustit akce naplánovaných úloh
|
dashboard.start_schedule_tasks=Spustit akce naplánovaných úloh
|
||||||
dashboard.sync_branch.started=Synchronizace větví spuštěna
|
dashboard.sync_branch.started=Synchronizace větví spuštěna
|
||||||
dashboard.sync_tag.started=Synchronizace značek spuštěna
|
dashboard.sync_tag.started = Synchronizace značek spuštěna
|
||||||
dashboard.rebuild_issue_indexer=Znovu sestavit index úkolů
|
dashboard.rebuild_issue_indexer = Přestavit indexer vydání
|
||||||
|
|
||||||
users.user_manage_panel=Správa uživatelských účtů
|
users.user_manage_panel=Správa uživatelských účtů
|
||||||
users.new_account=Vytvořit uživatelský účet
|
users.new_account=Vytvořit uživatelský účet
|
||||||
users.name=Uživatelské jméno
|
users.name=Uživatelské jméno
|
||||||
|
@ -3183,12 +3175,12 @@ packages.size=Velikost
|
||||||
packages.published=Publikováno
|
packages.published=Publikováno
|
||||||
|
|
||||||
defaulthooks=Výchozí webhooky
|
defaulthooks=Výchozí webhooky
|
||||||
defaulthooks.add_webhook=Přidat výchozí webový háček
|
defaulthooks.add_webhook=Přidat výchozí webhook
|
||||||
defaulthooks.update_webhook=Aktualizovat výchozí webový háček
|
defaulthooks.update_webhook=Aktualizovat výchozí webhook
|
||||||
|
|
||||||
systemhooks=Systémové webhooky
|
systemhooks=Systémové webhooky
|
||||||
systemhooks.add_webhook=Přidat systémový webový háček
|
systemhooks.add_webhook=Přidat systémový webhook
|
||||||
systemhooks.update_webhook=Aktualizovat systémový webový háček
|
systemhooks.update_webhook=Aktualizovat systémový webhook
|
||||||
|
|
||||||
auths.auth_manage_panel=Správa zdrojů ověřování
|
auths.auth_manage_panel=Správa zdrojů ověřování
|
||||||
auths.new=Přidat zdroj ověřování
|
auths.new=Přidat zdroj ověřování
|
||||||
|
@ -3496,8 +3488,6 @@ notices.desc=Popis
|
||||||
notices.op=Akce
|
notices.op=Akce
|
||||||
notices.delete_success=Systémové upozornění bylo smazáno.
|
notices.delete_success=Systémové upozornění bylo smazáno.
|
||||||
dashboard.sync_repo_branches = Synchronizovat vynechané větve z dat Gitu do databáze
|
dashboard.sync_repo_branches = Synchronizovat vynechané větve z dat Gitu do databáze
|
||||||
dashboard.sync_repo_tags = Synchronizovat značky z dat Gitu do databáze
|
|
||||||
dashboard.gc_lfs = Sbírat garbage z LFS meta objektů
|
|
||||||
monitor.queue.activeworkers = Aktivní workery
|
monitor.queue.activeworkers = Aktivní workery
|
||||||
defaulthooks.desc = Webhooky automaticky vytvářejí žádosti HTTP POST na server, kde se spustí určité události Forgejo. Webhooky zde definované jsou výchozí a budou zkopírovány do všech nových repozitářů. Více informací zjistíte v <a target="_blank" rel="noopener" href="%s">návodu webhooků</a>.
|
defaulthooks.desc = Webhooky automaticky vytvářejí žádosti HTTP POST na server, kde se spustí určité události Forgejo. Webhooky zde definované jsou výchozí a budou zkopírovány do všech nových repozitářů. Více informací zjistíte v <a target="_blank" rel="noopener" href="%s">návodu webhooků</a>.
|
||||||
systemhooks.desc = Webhooky automaticky vytvářejí žádosti HTTP POST na server, kde se spustí určité události Forgejo. Webhooky zde definované budou aktivní u všech repozitářů v systému, zvažte tedy prosím všechny vlivy na výkon, které může tato funkce způsobit. Více informací zjistíte v <a target="_blank" rel="noopener" href="%s">návodu webhooků</a>.
|
systemhooks.desc = Webhooky automaticky vytvářejí žádosti HTTP POST na server, kde se spustí určité události Forgejo. Webhooky zde definované budou aktivní u všech repozitářů v systému, zvažte tedy prosím všechny vlivy na výkon, které může tato funkce způsobit. Více informací zjistíte v <a target="_blank" rel="noopener" href="%s">návodu webhooků</a>.
|
||||||
|
@ -3506,22 +3496,15 @@ dashboard.cleanup_actions = Vymazat prošlé protokoly a artefakty z akcí
|
||||||
packages.cleanup.success = Prošlá data úspěšně vymazána
|
packages.cleanup.success = Prošlá data úspěšně vymazána
|
||||||
config.logger_name_fmt = Logger: %S
|
config.logger_name_fmt = Logger: %S
|
||||||
monitor.download_diagnosis_report = Stáhnout hlášení o diagnóze
|
monitor.download_diagnosis_report = Stáhnout hlášení o diagnóze
|
||||||
self_check.no_problem_found = Zatím nenalezen žádný problém.
|
self_check.no_problem_found=Zatím nebyl nalezen žádný problém.
|
||||||
self_check.database_collation_mismatch = Očekává se, že databáze použije collation: %s
|
self_check.database_collation_mismatch=Očekávejte, že databáze použije collation: %s
|
||||||
self_check.database_inconsistent_collation_columns = Databáze používá collation %s, tyto sloupce nicméně používají rozdílné collationy. Toto může způsobit neočekávané problémy.
|
self_check.database_inconsistent_collation_columns=Databáze používá collation %s, ale tyto sloupce používají chybné collation. To může způsobit neočekávané problémy.
|
||||||
self_check.database_fix_mysql = Uživatelé MySQL/MariaDB mohou použít příkaz „gitea doctor convert“ pro automatické opravení problémů s collation. Problém také můžete vyřešit ručně SQL příkazy „ALTER ... COLLATE ...“.
|
self_check.database_fix_mysql=Pro uživatele MySQL/MariaDB můžete použít příkaz "gitea doctor convert", který opraví problémy s collation, nebo můžete také problém vyřešit příkazem "ALTER ... COLLATE ..." SQL ručně.
|
||||||
self_check = Vlastní kontrola
|
self_check = Vlastní kontrola
|
||||||
dashboard.sync_tag.started = Synchronizace značek spuštěna
|
self_check.database_collation_case_insensitive=Databáze používá collation %s, což je collation nerozlišující velká a malá písmena. Ačkoli s ní Gitea může pracovat, mohou se vyskytnout vzácné případy, kdy nebude fungovat podle očekávání.
|
||||||
dashboard.rebuild_issue_indexer = Přestavit indexer vydání
|
|
||||||
self_check.database_collation_case_insensitive = Databáze používá collation %s. Jedná se o intenzivní collation. Ačkoli s ní Forgejo nejspíše bude pracovat, mohou nastat určité vzácné případy, kdy nebude pracovat tak, jak má.
|
|
||||||
auths.oauth2_map_group_to_team = Zmapovat zabrané skupiny u týmů organizací (volitelné - vyžaduje název claimu výše)
|
auths.oauth2_map_group_to_team = Zmapovat zabrané skupiny u týmů organizací (volitelné - vyžaduje název claimu výše)
|
||||||
monitor.queue.settings.desc = Pooly dynamicky rostou podle blokování fronty jejich workerů.
|
monitor.queue.settings.desc = Pooly dynamicky rostou podle blokování fronty jejich workerů.
|
||||||
|
|
||||||
self_check.no_problem_found=Zatím nebyl nalezen žádný problém.
|
|
||||||
self_check.database_collation_mismatch=Očekávejte, že databáze použije collation: %s
|
|
||||||
self_check.database_collation_case_insensitive=Databáze používá collation %s, což je collation nerozlišující velká a malá písmena. Ačkoli s ní Gitea může pracovat, mohou se vyskytnout vzácné případy, kdy nebude fungovat podle očekávání.
|
|
||||||
self_check.database_inconsistent_collation_columns=Databáze používá collation %s, ale tyto sloupce používají chybné collation. To může způsobit neočekávané problémy.
|
|
||||||
self_check.database_fix_mysql=Pro uživatele MySQL/MariaDB můžete použít příkaz "gitea doctor convert", který opraví problémy s collation, nebo můžete také problém vyřešit příkazem "ALTER ... COLLATE ..." SQL ručně.
|
|
||||||
auths.tips.gmail_settings = Nastavení služby Gmail:
|
auths.tips.gmail_settings = Nastavení služby Gmail:
|
||||||
config_summary = Souhrn
|
config_summary = Souhrn
|
||||||
config.open_with_editor_app_help = Editory v nabídce „Otevřít pomocí“ v nabídce klonování. Ponechte prázdné pro použití výchozího editoru (zobrazíte jej rozšířením).
|
config.open_with_editor_app_help = Editory v nabídce „Otevřít pomocí“ v nabídce klonování. Ponechte prázdné pro použití výchozího editoru (zobrazíte jej rozšířením).
|
||||||
|
@ -3589,7 +3572,7 @@ future=budoucí
|
||||||
1y=1 rokem
|
1y=1 rokem
|
||||||
seconds=%d sekundami
|
seconds=%d sekundami
|
||||||
minutes=%d minutami
|
minutes=%d minutami
|
||||||
hours=%d hodinami
|
hours=%d hodin
|
||||||
days=%d dny
|
days=%d dny
|
||||||
weeks=%d týdny
|
weeks=%d týdny
|
||||||
months=%d měsíci
|
months=%d měsíci
|
||||||
|
@ -3636,7 +3619,7 @@ error.unit_not_allowed=Nejste oprávněni přistupovat k této části repozitá
|
||||||
[packages]
|
[packages]
|
||||||
title=Balíčky
|
title=Balíčky
|
||||||
desc=Správa balíčků repozitáře.
|
desc=Správa balíčků repozitáře.
|
||||||
empty=Zatím nejsou žádné balíčky.
|
empty=Zatím zde nejsou žádné balíčky.
|
||||||
empty.documentation=Další informace o registru balíčků naleznete v <a target="_blank" rel="noopener noreferrer" href="%s">dokumentaci</a>.
|
empty.documentation=Další informace o registru balíčků naleznete v <a target="_blank" rel="noopener noreferrer" href="%s">dokumentaci</a>.
|
||||||
empty.repo=Nahráli jste balíček, ale nezobrazil se zde? Přejděte na <a href="%[1]s">nastavení balíčku</a> a propojte jej s tímto repozitářem.
|
empty.repo=Nahráli jste balíček, ale nezobrazil se zde? Přejděte na <a href="%[1]s">nastavení balíčku</a> a propojte jej s tímto repozitářem.
|
||||||
registry.documentation=Další informace o registru %s naleznete v <a target="_blank" rel="noopener noreferrer" href="%s">dokumentaci</a>.
|
registry.documentation=Další informace o registru %s naleznete v <a target="_blank" rel="noopener noreferrer" href="%s">dokumentaci</a>.
|
||||||
|
@ -3730,7 +3713,7 @@ rpm.distros.suse=na distribuce založené na SUSE
|
||||||
rpm.install=Pro instalaci balíčku spusťte následující příkaz:
|
rpm.install=Pro instalaci balíčku spusťte následující příkaz:
|
||||||
rpm.repository=Informace o repozitáři
|
rpm.repository=Informace o repozitáři
|
||||||
rpm.repository.architectures=Architektury
|
rpm.repository.architectures=Architektury
|
||||||
rpm.repository.multiple_groups=Tento balíček je k dispozici ve více skupinách.
|
rpm.repository.multiple_groups = Tento balíček je dostupný v několika skupinách.
|
||||||
rubygems.install=Pro instalaci balíčku pomocí gem spusťte následující příkaz:
|
rubygems.install=Pro instalaci balíčku pomocí gem spusťte následující příkaz:
|
||||||
rubygems.install2=nebo ho přidejte do Gemfie:
|
rubygems.install2=nebo ho přidejte do Gemfie:
|
||||||
rubygems.dependencies.runtime=Běhové závislosti
|
rubygems.dependencies.runtime=Běhové závislosti
|
||||||
|
@ -3754,7 +3737,7 @@ settings.delete.success=Balíček byl odstraněn.
|
||||||
settings.delete.error=Nepodařilo se odstranit balíček.
|
settings.delete.error=Nepodařilo se odstranit balíček.
|
||||||
owner.settings.cargo.title=Index registru Cargo
|
owner.settings.cargo.title=Index registru Cargo
|
||||||
owner.settings.cargo.initialize=Inicializovat index
|
owner.settings.cargo.initialize=Inicializovat index
|
||||||
owner.settings.cargo.initialize.description=Pro použití Cargo registru je zapotřebí speciální index Git. Použití této možnosti (znovu)vytvoří repozitář a automaticky jej nastaví.
|
owner.settings.cargo.initialize.description=Pro použití registru Cargo je zapotřebí speciální index Git. Použití této možnosti (znovu) vytvoří repozitář a automaticky jej nastaví.
|
||||||
owner.settings.cargo.initialize.error=Nepodařilo se inicializovat Cargo index: %v
|
owner.settings.cargo.initialize.error=Nepodařilo se inicializovat Cargo index: %v
|
||||||
owner.settings.cargo.initialize.success=Index Cargo byl úspěšně vytvořen.
|
owner.settings.cargo.initialize.success=Index Cargo byl úspěšně vytvořen.
|
||||||
owner.settings.cargo.rebuild=Znovu vytvořit index
|
owner.settings.cargo.rebuild=Znovu vytvořit index
|
||||||
|
@ -3783,7 +3766,6 @@ owner.settings.cleanuprules.success.delete=Pravidlo pro čištění bylo odstran
|
||||||
owner.settings.chef.title=Registr Chef
|
owner.settings.chef.title=Registr Chef
|
||||||
owner.settings.chef.keypair=Generovat pár klíčů
|
owner.settings.chef.keypair=Generovat pár klíčů
|
||||||
owner.settings.chef.keypair.description=Pro autentizaci do registru Chef je zapotřebí pár klíčů. Pokud jste předtím vytvořili pár klíčů, nově vygenerovaný pár klíčů vyřadí starý pár klíčů.
|
owner.settings.chef.keypair.description=Pro autentizaci do registru Chef je zapotřebí pár klíčů. Pokud jste předtím vytvořili pár klíčů, nově vygenerovaný pár klíčů vyřadí starý pár klíčů.
|
||||||
rpm.repository.multiple_groups = Tento balíček je dostupný v několika skupinách.
|
|
||||||
owner.settings.cargo.rebuild.description = Opětovné sestavení může být užitečné, pokud není index synchronizován s uloženými balíčky Cargo.
|
owner.settings.cargo.rebuild.description = Opětovné sestavení může být užitečné, pokud není index synchronizován s uloženými balíčky Cargo.
|
||||||
owner.settings.cargo.rebuild.no_index = Opětovné vytvoření selhalo, nebyl inicializován žádný index.
|
owner.settings.cargo.rebuild.no_index = Opětovné vytvoření selhalo, nebyl inicializován žádný index.
|
||||||
npm.dependencies.bundle = Přidružené závislosti
|
npm.dependencies.bundle = Přidružené závislosti
|
||||||
|
@ -3822,7 +3804,7 @@ management=Správa tajných klíčů
|
||||||
[actions]
|
[actions]
|
||||||
actions=Akce
|
actions=Akce
|
||||||
|
|
||||||
unit.desc=Spravovat integrované pipeliny CI/CD pomocí funkce Forgejo Actions
|
unit.desc=Spravovat integrované pipeliny CI/CD pomocí funkce Forgejo Actions.
|
||||||
|
|
||||||
status.unknown=Neznámý
|
status.unknown=Neznámý
|
||||||
status.waiting=Čekání
|
status.waiting=Čekání
|
||||||
|
@ -3878,8 +3860,8 @@ runs.actors_no_select=Všichni aktéři
|
||||||
runs.status_no_select=Všechny stavy
|
runs.status_no_select=Všechny stavy
|
||||||
runs.no_results=Nebyly nalezeny žádné výsledky.
|
runs.no_results=Nebyly nalezeny žádné výsledky.
|
||||||
runs.no_workflows=Zatím neexistují žádné pracovní postupy.
|
runs.no_workflows=Zatím neexistují žádné pracovní postupy.
|
||||||
runs.no_workflows.quick_start=Nevíte jak začít s Gitea Actions? Podívejte se na <a target="_blank" rel="noopener noreferrer" href="%s">průvodce rychlým startem</a>.
|
runs.no_workflows.quick_start = Nevíte jak začít s Gitea Action? Podívejte se na <a target="_blank" rel="noopener noreferrer" href="%s">průvodce rychlým startem</a>.
|
||||||
runs.no_workflows.documentation=Další informace o Gitea Actions naleznete v <a target="_blank" rel="noopener noreferrer" href="%s">dokumentaci</a>.
|
runs.no_workflows.documentation = Další informace o Gitea Action, viz <a target="_blank" rel="noopener noreferrer" href="%s">dokumentace</a>.
|
||||||
runs.no_runs=Pracovní postup zatím nebyl spuštěn.
|
runs.no_runs=Pracovní postup zatím nebyl spuštěn.
|
||||||
runs.empty_commit_message=(prázdná zpráva commitu)
|
runs.empty_commit_message=(prázdná zpráva commitu)
|
||||||
|
|
||||||
|
@ -3893,11 +3875,11 @@ workflow.disabled=Pracovní postup je zakázán.
|
||||||
variables=Proměnné
|
variables=Proměnné
|
||||||
variables.management=Správa proměnných
|
variables.management=Správa proměnných
|
||||||
variables.creation=Přidat proměnnou
|
variables.creation=Přidat proměnnou
|
||||||
variables.none=Zatím nejsou žádné proměnné.
|
variables.none=Zatím zde nejsou žádné proměnné.
|
||||||
variables.deletion=Odstranit proměnnou
|
variables.deletion=Odstranit proměnnou
|
||||||
variables.deletion.description=Odstranění proměnné je trvalé a nelze jej vrátit zpět. Pokračovat?
|
variables.deletion.description=Odstranění proměnné je trvalé a nelze jej vrátit zpět. Pokračovat?
|
||||||
variables.description=Proměnné budou předány určitým akcím a nelze je přečíst jinak.
|
variables.description=Proměnné budou předány určitým akcím a nelze je přečíst jinak.
|
||||||
variables.id_not_exist=Proměnná s ID %d neexistuje.
|
variables.id_not_exist = Proměnná s id %d neexistuje.
|
||||||
variables.edit=Upravit proměnnou
|
variables.edit=Upravit proměnnou
|
||||||
variables.deletion.failed=Nepodařilo se odstranit proměnnou.
|
variables.deletion.failed=Nepodařilo se odstranit proměnnou.
|
||||||
variables.deletion.success=Proměnná byla odstraněna.
|
variables.deletion.success=Proměnná byla odstraněna.
|
||||||
|
@ -3905,9 +3887,6 @@ variables.creation.failed=Přidání proměnné se nezdařilo.
|
||||||
variables.creation.success=Proměnná „%s“ byla přidána.
|
variables.creation.success=Proměnná „%s“ byla přidána.
|
||||||
variables.update.failed=Úprava proměnné se nezdařila.
|
variables.update.failed=Úprava proměnné se nezdařila.
|
||||||
variables.update.success=Proměnná byla upravena.
|
variables.update.success=Proměnná byla upravena.
|
||||||
runs.no_workflows.quick_start = Nevíte jak začít s Gitea Action? Podívejte se na <a target="_blank" rel="noopener noreferrer" href="%s">průvodce rychlým startem</a>.
|
|
||||||
variables.id_not_exist = Proměnná s id %d neexistuje.
|
|
||||||
runs.no_workflows.documentation = Další informace o Gitea Action, viz <a target="_blank" rel="noopener noreferrer" href="%s">dokumentace</a>.
|
|
||||||
runners.none = Nejsou dostupné žádné runnery
|
runners.none = Nejsou dostupné žádné runnery
|
||||||
runs.workflow = Workflow
|
runs.workflow = Workflow
|
||||||
runners = Runnery
|
runners = Runnery
|
||||||
|
@ -3933,7 +3912,6 @@ deleted.display_name = Smazaný projekt
|
||||||
|
|
||||||
[git.filemode]
|
[git.filemode]
|
||||||
changed_filemode=%[1]s → %[2]s
|
changed_filemode=%[1]s → %[2]s
|
||||||
; Ordered by git filemode value, ascending. E.g. directory has "040000", normal file has "100644", …
|
|
||||||
directory=Adresář
|
directory=Adresář
|
||||||
normal_file=Normální soubor
|
normal_file=Normální soubor
|
||||||
executable_file=Spustitelný soubor
|
executable_file=Spustitelný soubor
|
||||||
|
@ -3970,6 +3948,8 @@ pull_kind = Hledat pully...
|
||||||
union = Sdružené
|
union = Sdružené
|
||||||
union_tooltip = Zahrnout výsledky, které odpovídají jakýmkoli slovům odděleným mezerami
|
union_tooltip = Zahrnout výsledky, které odpovídají jakýmkoli slovům odděleným mezerami
|
||||||
milestone_kind = Hledat milníky...
|
milestone_kind = Hledat milníky...
|
||||||
|
regexp = RegExp
|
||||||
|
regexp_tooltip = Interpretovat hledaný výraz jako regulární výraz
|
||||||
|
|
||||||
[markup]
|
[markup]
|
||||||
filepreview.lines = Řádky %[1]d až %[2]d v souboru %[3]s
|
filepreview.lines = Řádky %[1]d až %[2]d v souboru %[3]s
|
||||||
|
@ -3987,4 +3967,24 @@ eib = EiB
|
||||||
|
|
||||||
|
|
||||||
[translation_meta]
|
[translation_meta]
|
||||||
test = diky vsem za pomoc :)
|
test = diky vsem za pomoc :)
|
||||||
|
|
||||||
|
[repo.permissions]
|
||||||
|
pulls.write = <b>Zapisovat:</b> Zavírat žádosti o sloučení a spravovat metadata jako štítky, milníky, zpracovatele, data dokončení a závislosti.
|
||||||
|
packages.write = <b>Zapisovat:</b> Zveřejňovat a mazat balíčky připojené k repozitáři.
|
||||||
|
projects.read = <b>Číst:</b> Přístup k projektovým nástěnkám repozitáře.
|
||||||
|
code.write = <b>Zapisovat:</b> Odesílat změny do repozitáře, vytvářet větve a značky.
|
||||||
|
issues.write = <b>Zapisovat:</b> Zavírat problémy a spravovat metadata jako štítky, milníky, zpracovatele, data dokončení a závislosti.
|
||||||
|
pulls.read = <b>Číst:</b> Číst a vytvářet žádosti o sloučení.
|
||||||
|
releases.read = <b>Číst:</b> Zobrazovat a stahovat vydání.
|
||||||
|
releases.write = <b>Zapisovat:</b> Zveřejňovat, upravovat a mazat vydání a jejich soubory.
|
||||||
|
wiki.read = <b>Číst:</b> Číst integrovanou wiki a její historii.
|
||||||
|
wiki.write = <b>Zapisovat:</b> Vytvářet, aktualizovat a mazat stránky v integrované wiki.
|
||||||
|
projects.write = <b>Zapisovat:</b> Vytvářet projekty a sloupce a upravovat je.
|
||||||
|
packages.read = <b>Číst:</b> Zobrazovat a stahovat balíčky připojené k repozitáři.
|
||||||
|
actions.read = <b>Číst:</b> Zobrazovat integrované pipeliny CI/CD a jejich protokoly.
|
||||||
|
actions.write = <b>Zapisovat:</b> Ručně spouštět, restartovat, rušit nebo schvalovat čekající pipeliny CI/CD.
|
||||||
|
ext_wiki = Přístup k odkazu v externí wiki. Oprávnění jsou spravována externě.
|
||||||
|
code.read = <b>Číst:</b> Přístup a klonování kódu v repozitáři.
|
||||||
|
issues.read = <b>Číst:</b> Číst a vytvářet problémy a komentáře.
|
||||||
|
ext_issues = Přístup k odkazu v externím sledovacím systému problémů. Oprávnění jsou spravována externě.
|
|
@ -318,7 +318,7 @@ run_user_not_match=Der „Ausführen als“-Benutzername ist nicht der aktuelle
|
||||||
internal_token_failed=Fehler beim Generieren des internen Tokens: %v
|
internal_token_failed=Fehler beim Generieren des internen Tokens: %v
|
||||||
secret_key_failed=Fehler beim Generieren des geheimen Schlüssels: %v
|
secret_key_failed=Fehler beim Generieren des geheimen Schlüssels: %v
|
||||||
save_config_failed=Fehler beim Speichern der Konfiguration: %v
|
save_config_failed=Fehler beim Speichern der Konfiguration: %v
|
||||||
invalid_admin_setting=Administrator-Konto Einstellungen sind ungültig: %v
|
invalid_admin_setting=Die Administratorkonto-Einstellungen sind ungültig: %v
|
||||||
invalid_log_root_path=Pfad zum Log-Verzeichnis ist ungültig: %v
|
invalid_log_root_path=Pfad zum Log-Verzeichnis ist ungültig: %v
|
||||||
default_keep_email_private=E-Mail-Adressen standardmäßig verbergen
|
default_keep_email_private=E-Mail-Adressen standardmäßig verbergen
|
||||||
default_keep_email_private.description=E-Mail-Adressen von neuen Benutzern standardmäßig verbergen, damit diese nicht direkt nach der Registrierung öffentlich wird.
|
default_keep_email_private.description=E-Mail-Adressen von neuen Benutzern standardmäßig verbergen, damit diese nicht direkt nach der Registrierung öffentlich wird.
|
||||||
|
@ -476,6 +476,8 @@ back_to_sign_in = Zurück zur Anmeldung
|
||||||
sign_in_openid = Mit OpenID fortfahren
|
sign_in_openid = Mit OpenID fortfahren
|
||||||
hint_login = Hast du bereits ein Konto? <a href="%s">Jetzt anmelden!</a>
|
hint_login = Hast du bereits ein Konto? <a href="%s">Jetzt anmelden!</a>
|
||||||
hint_register = Brauchst du ein Konto? <a href="%s">Jetzt registrieren.</a>
|
hint_register = Brauchst du ein Konto? <a href="%s">Jetzt registrieren.</a>
|
||||||
|
unauthorized_credentials = Die Zugangsdaten sind inkorrekt oder abgelaufen. Versuchen es erneut oder siehe %s für mehr Informationen
|
||||||
|
use_onetime_code = Einen One-Time-Code benutzen
|
||||||
|
|
||||||
[mail]
|
[mail]
|
||||||
view_it_on=Auf %s ansehen
|
view_it_on=Auf %s ansehen
|
||||||
|
@ -716,6 +718,7 @@ public_activity.visibility_hint.self_public = Deine Aktivität ist sichtbar für
|
||||||
public_activity.visibility_hint.admin_public = Diese Aktivität ist sichtbar für alle, aber als Administrator kannst du außerdem Interaktionen in privaten Räumen sehen.
|
public_activity.visibility_hint.admin_public = Diese Aktivität ist sichtbar für alle, aber als Administrator kannst du außerdem Interaktionen in privaten Räumen sehen.
|
||||||
public_activity.visibility_hint.self_private = Deine Aktivität ist nur sichtbar für dich und den Instanzadministratoren. <a href="%s">Konfigurieren</a>.
|
public_activity.visibility_hint.self_private = Deine Aktivität ist nur sichtbar für dich und den Instanzadministratoren. <a href="%s">Konfigurieren</a>.
|
||||||
public_activity.visibility_hint.admin_private = Diese Aktivität ist sichtbar für dich, weil du ein Administrator bist, aber der Benutzer will sie privat halten.
|
public_activity.visibility_hint.admin_private = Diese Aktivität ist sichtbar für dich, weil du ein Administrator bist, aber der Benutzer will sie privat halten.
|
||||||
|
public_activity.visibility_hint.self_private_profile = Deine Aktivität ist nur für dich und die Instanzadministratoren sichtbar, weil den Profil privat ist. <a href="%s">Konfigurieren</a>.
|
||||||
|
|
||||||
[settings]
|
[settings]
|
||||||
profile=Profil
|
profile=Profil
|
||||||
|
@ -1038,7 +1041,7 @@ hints = Hinweise
|
||||||
additional_repo_units_hint = Aktivierung zusätzlicher Repository-Einheiten vorschlagen
|
additional_repo_units_hint = Aktivierung zusätzlicher Repository-Einheiten vorschlagen
|
||||||
update_hints = Hinweise aktualisieren
|
update_hints = Hinweise aktualisieren
|
||||||
update_hints_success = Hinweise wurden aktualisiert.
|
update_hints_success = Hinweise wurden aktualisiert.
|
||||||
additional_repo_units_hint_description = Einen „Mehr Einheiten hinzufügen …“-Button für Repositorys, welche nicht alle verfügbaren Einheiten aktiviert haben, anzeigen.
|
additional_repo_units_hint_description = Einen „Mehr aktivieren“-Hinweis für Repositories, welche nicht alle verfügbaren Einheiten aktiviert haben, anzeigen.
|
||||||
pronouns = Pronomen
|
pronouns = Pronomen
|
||||||
pronouns_custom = Eigene
|
pronouns_custom = Eigene
|
||||||
pronouns_unspecified = Nicht spezifiziert
|
pronouns_unspecified = Nicht spezifiziert
|
||||||
|
@ -1208,12 +1211,12 @@ migrate.migrate_items_options=Zugangs-Token wird benötigt, um zusätzliche Elem
|
||||||
migrated_from=Migriert von <a href="%[1]s">%[2]s</a>
|
migrated_from=Migriert von <a href="%[1]s">%[2]s</a>
|
||||||
migrated_from_fake=Migriert von %[1]s
|
migrated_from_fake=Migriert von %[1]s
|
||||||
migrate.migrate=Migrieren von %s
|
migrate.migrate=Migrieren von %s
|
||||||
migrate.migrating=Migriere von <b>%s</b> ...
|
migrate.migrating=Migriere von <b>%s</b> …
|
||||||
migrate.migrating_failed=Migrieren von <b>%s</b> fehlgeschlagen.
|
migrate.migrating_failed=Migrieren von <b>%s</b> fehlgeschlagen.
|
||||||
migrate.migrating_failed.error=Migration fehlgeschlagen: %s
|
migrate.migrating_failed.error=Migration fehlgeschlagen: %s
|
||||||
migrate.migrating_failed_no_addr=Migration fehlgeschlagen.
|
migrate.migrating_failed_no_addr=Migration fehlgeschlagen.
|
||||||
migrate.github.description=Daten von github.com oder GitHub-Enterprise-Server migrieren.
|
migrate.github.description=Daten von github.com oder GitHub-Enterprise-Server migrieren.
|
||||||
migrate.git.description=Ein Repository von einem beliebigen Git Service klonen.
|
migrate.git.description=Ein Repository von einem beliebigen Git-Service klonen.
|
||||||
migrate.gitlab.description=Daten von gitlab.com oder anderen GitLab-Instanzen migrieren.
|
migrate.gitlab.description=Daten von gitlab.com oder anderen GitLab-Instanzen migrieren.
|
||||||
migrate.gitea.description=Daten von gitea.com oder anderen Gitea-Instanzen migrieren.
|
migrate.gitea.description=Daten von gitea.com oder anderen Gitea-Instanzen migrieren.
|
||||||
migrate.gogs.description=Daten von notabug.org oder anderen Gogs-Instanzen migrieren.
|
migrate.gogs.description=Daten von notabug.org oder anderen Gogs-Instanzen migrieren.
|
||||||
|
@ -1275,7 +1278,7 @@ org_labels_desc_manage=verwalten
|
||||||
milestones=Meilensteine
|
milestones=Meilensteine
|
||||||
commits=Commits
|
commits=Commits
|
||||||
commit=Commit
|
commit=Commit
|
||||||
release=Erscheinungsdatum
|
release=Release
|
||||||
releases=Releases
|
releases=Releases
|
||||||
tag=Tag
|
tag=Tag
|
||||||
released_this=hat released
|
released_this=hat released
|
||||||
|
@ -1299,7 +1302,7 @@ ambiguous_character=`%[1]c [U+%04[1]X] kann mit %[2]c [U+%04[2]X] verwechselt we
|
||||||
escape_control_characters=Escapen
|
escape_control_characters=Escapen
|
||||||
unescape_control_characters=Unescapen
|
unescape_control_characters=Unescapen
|
||||||
file_copy_permalink=Permalink kopieren
|
file_copy_permalink=Permalink kopieren
|
||||||
view_git_blame=Git Blame ansehen
|
view_git_blame=„git blame“ ansehen
|
||||||
video_not_supported_in_browser=Dein Browser unterstützt das HTML5-„video“-Tag nicht.
|
video_not_supported_in_browser=Dein Browser unterstützt das HTML5-„video“-Tag nicht.
|
||||||
audio_not_supported_in_browser=Dein Browser unterstützt das HTML5-„audio“-Tag nicht.
|
audio_not_supported_in_browser=Dein Browser unterstützt das HTML5-„audio“-Tag nicht.
|
||||||
stored_lfs=Gespeichert mit Git LFS
|
stored_lfs=Gespeichert mit Git LFS
|
||||||
|
@ -1316,7 +1319,7 @@ commit.load_referencing_branches_and_tags=Lade Branches und Tags, die diesen Com
|
||||||
blame=Blame
|
blame=Blame
|
||||||
download_file=Datei herunterladen
|
download_file=Datei herunterladen
|
||||||
normal_view=Normale Ansicht
|
normal_view=Normale Ansicht
|
||||||
line=zeile
|
line=Zeile
|
||||||
lines=Zeilen
|
lines=Zeilen
|
||||||
from_comment=(Kommentar)
|
from_comment=(Kommentar)
|
||||||
|
|
||||||
|
@ -1420,7 +1423,7 @@ commitstatus.failure=Fehler
|
||||||
commitstatus.pending=Ausstehend
|
commitstatus.pending=Ausstehend
|
||||||
commitstatus.success=Erfolg
|
commitstatus.success=Erfolg
|
||||||
|
|
||||||
ext_issues=Zugriff auf Externe Issues
|
ext_issues=Externe Issues
|
||||||
ext_issues.desc=Link zu externem Issuetracker.
|
ext_issues.desc=Link zu externem Issuetracker.
|
||||||
|
|
||||||
projects=Projekte
|
projects=Projekte
|
||||||
|
@ -1521,7 +1524,7 @@ issues.remove_milestone_at=`hat dieses Issue %[2]s vom <b>%[1]s</b> Meilenstein
|
||||||
issues.remove_project_at=`hat dies vom Projekt <b>%s</b> %s entfernt`
|
issues.remove_project_at=`hat dies vom Projekt <b>%s</b> %s entfernt`
|
||||||
issues.deleted_milestone=`(gelöscht)`
|
issues.deleted_milestone=`(gelöscht)`
|
||||||
issues.deleted_project=`(gelöscht)`
|
issues.deleted_project=`(gelöscht)`
|
||||||
issues.self_assign_at=`hat sich das Issue %s selbst zugewiesen`
|
issues.self_assign_at=`hat sich %s selbst zugewiesen`
|
||||||
issues.add_assignee_at=`wurde von <b>%s</b> %s zugewiesen`
|
issues.add_assignee_at=`wurde von <b>%s</b> %s zugewiesen`
|
||||||
issues.remove_assignee_at=`wurde von <b>%s</b> von der Zuweisung %s befreit`
|
issues.remove_assignee_at=`wurde von <b>%s</b> von der Zuweisung %s befreit`
|
||||||
issues.remove_self_assignment=`hat die Selbstzuweisung %s entfernt`
|
issues.remove_self_assignment=`hat die Selbstzuweisung %s entfernt`
|
||||||
|
@ -1601,9 +1604,9 @@ issues.no_content=Keine Beschreibung angegeben.
|
||||||
issues.close=Issue schließen
|
issues.close=Issue schließen
|
||||||
issues.comment_pull_merged_at=hat Commit %[1]s in %[2]s %[3]s zusammengeführt
|
issues.comment_pull_merged_at=hat Commit %[1]s in %[2]s %[3]s zusammengeführt
|
||||||
issues.comment_manually_pull_merged_at=hat Commit %[1]s in %[2]s %[3]s manuell zusammengeführt
|
issues.comment_manually_pull_merged_at=hat Commit %[1]s in %[2]s %[3]s manuell zusammengeführt
|
||||||
issues.close_comment_issue=Kommentieren und schließen
|
issues.close_comment_issue=Mit Kommentar schließen
|
||||||
issues.reopen_issue=Wieder öffnen
|
issues.reopen_issue=Wieder öffnen
|
||||||
issues.reopen_comment_issue=Kommentieren und wieder öffnen
|
issues.reopen_comment_issue=Mit Kommentar wieder öffnen
|
||||||
issues.create_comment=Kommentieren
|
issues.create_comment=Kommentieren
|
||||||
issues.closed_at=`hat diesen Issue <a id="%[1]s" href="#%[1]s">%[2]s</a> geschlossen`
|
issues.closed_at=`hat diesen Issue <a id="%[1]s" href="#%[1]s">%[2]s</a> geschlossen`
|
||||||
issues.reopened_at=`hat dieses Issue <a id="%[1]s" href="#%[1]s">%[2]s</a> wieder geöffnet`
|
issues.reopened_at=`hat dieses Issue <a id="%[1]s" href="#%[1]s">%[2]s</a> wieder geöffnet`
|
||||||
|
@ -1647,7 +1650,7 @@ issues.label_archive_tooltip=Archivierte Labels werden bei der Suche nach Labels
|
||||||
issues.label_exclusive_desc=Nenn das Label <code>Bereich/Element</code>, um es gegenseitig ausschließend mit anderen <code>Bereich/</code>-Labels zu machen.
|
issues.label_exclusive_desc=Nenn 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 Labels
|
issues.label_count=%d Labels
|
||||||
issues.label_open_issues=%d offene Issues
|
issues.label_open_issues=%d offene Issues/Pull-Requests
|
||||||
issues.label_edit=Bearbeiten
|
issues.label_edit=Bearbeiten
|
||||||
issues.label_delete=Löschen
|
issues.label_delete=Löschen
|
||||||
issues.label_modify=Label bearbeiten
|
issues.label_modify=Label bearbeiten
|
||||||
|
@ -1770,8 +1773,8 @@ issues.review.left_comment=hat einen Kommentar hinterlassen
|
||||||
issues.review.content.empty=Du musst einen Kommentar hinterlassen, der die gewünschte(n) Änderung(en) beschreibt.
|
issues.review.content.empty=Du musst einen Kommentar hinterlassen, der die gewünschte(n) Änderung(en) beschreibt.
|
||||||
issues.review.reject=hat %s Änderungen angefragt
|
issues.review.reject=hat %s Änderungen angefragt
|
||||||
issues.review.wait=wurde für ein Review %s angefragt
|
issues.review.wait=wurde für ein Review %s angefragt
|
||||||
issues.review.add_review_request=hat ein Review von %s %s angefragt
|
issues.review.add_review_request=hat ein Review von %[1]s %[2]s angefragt
|
||||||
issues.review.remove_review_request=hat die Aufforderung zum Review an %s %s entfernt
|
issues.review.remove_review_request=hat die Aufforderung zum Review an %[1]s %[2]s entfernt
|
||||||
issues.review.remove_review_request_self=hat das Review verweigert %s
|
issues.review.remove_review_request_self=hat das Review verweigert %s
|
||||||
issues.review.pending=Ausstehend
|
issues.review.pending=Ausstehend
|
||||||
issues.review.pending.tooltip=Dieser Kommentar ist derzeit nicht für andere Benutzer sichtbar. Um deine ausstehenden Kommentare einzureichen, wähle „%s“ -> „%s/%s/%s“ oben auf der Seite.
|
issues.review.pending.tooltip=Dieser Kommentar ist derzeit nicht für andere Benutzer sichtbar. Um deine ausstehenden Kommentare einzureichen, wähle „%s“ -> „%s/%s/%s“ oben auf der Seite.
|
||||||
|
@ -1851,7 +1854,7 @@ pulls.still_in_progress=Noch in Bearbeitung?
|
||||||
pulls.add_prefix=Präfix „<strong>%s</strong>“ hinzufügen
|
pulls.add_prefix=Präfix „<strong>%s</strong>“ hinzufügen
|
||||||
pulls.remove_prefix=Präfix „<strong>%s</strong>“ entfernen
|
pulls.remove_prefix=Präfix „<strong>%s</strong>“ entfernen
|
||||||
pulls.data_broken=Dieser Pull-Requests ist kaputt, da Fork-Informationen gelöscht wurden.
|
pulls.data_broken=Dieser Pull-Requests ist kaputt, da Fork-Informationen gelöscht wurden.
|
||||||
pulls.files_conflicted=Dieser Pull-Request hat Änderungen, die im Widerspruch zum Ziel-Branch stehen.
|
pulls.files_conflicted=Dieser Pull-Request hat Änderungen, die Konflikte mit dem Ziel-Branch haben.
|
||||||
pulls.is_checking=Die Merge-Konfliktprüfung läuft noch. Bitte aktualisiere die Seite in wenigen Augenblicken.
|
pulls.is_checking=Die Merge-Konfliktprüfung läuft noch. Bitte aktualisiere die Seite in wenigen Augenblicken.
|
||||||
pulls.is_ancestor=Dieser Branch ist bereits im Zielbranch enthalten. Es existiert nichts zusammenzuführen.
|
pulls.is_ancestor=Dieser Branch ist bereits im Zielbranch enthalten. Es existiert nichts zusammenzuführen.
|
||||||
pulls.is_empty=Die Änderungen an diesem Branch sind bereits auf dem Zielbranch. Dies wird ein leerer Commit sein.
|
pulls.is_empty=Die Änderungen an diesem Branch sind bereits auf dem Zielbranch. Dies wird ein leerer Commit sein.
|
||||||
|
@ -1984,7 +1987,7 @@ signing.wont_sign.commitssigned=Der Merge-Commit wird nicht signiert werden, da
|
||||||
signing.wont_sign.approved=Der Merge-Commit wird nicht signiert werden, da der Pull-Request nicht genehmigt wurde.
|
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.
|
signing.wont_sign.not_signed_in=Du bist nicht eingeloggt.
|
||||||
|
|
||||||
ext_wiki=Zugriff auf externes Wiki
|
ext_wiki=Externes Wiki
|
||||||
ext_wiki.desc=Verweis auf externes Wiki.
|
ext_wiki.desc=Verweis auf externes Wiki.
|
||||||
|
|
||||||
wiki=Wiki
|
wiki=Wiki
|
||||||
|
@ -2308,32 +2311,32 @@ settings.event_push_desc=Git push in ein Repository.
|
||||||
settings.event_repository=Repository
|
settings.event_repository=Repository
|
||||||
settings.event_repository_desc=Repository erstellt oder gelöscht.
|
settings.event_repository_desc=Repository erstellt oder gelöscht.
|
||||||
settings.event_header_issue=Issue-Ereignisse
|
settings.event_header_issue=Issue-Ereignisse
|
||||||
settings.event_issues=Issues
|
settings.event_issues=Änderung
|
||||||
settings.event_issues_desc=Issue geöffnet, geschlossen, wieder geöffnet oder bearbeitet.
|
settings.event_issues_desc=Issue geöffnet, geschlossen, wieder geöffnet oder bearbeitet.
|
||||||
settings.event_issue_assign=Issue zugewiesen
|
settings.event_issue_assign=Zuweisung
|
||||||
settings.event_issue_assign_desc=Issue zugewiesen oder Zuweisung entfernt.
|
settings.event_issue_assign_desc=Issue zugewiesen oder Zuweisung entfernt.
|
||||||
settings.event_issue_label=Issue mit Label versehen
|
settings.event_issue_label=Labels
|
||||||
settings.event_issue_label_desc=Issue-Labels aktualisiert oder geleert.
|
settings.event_issue_label_desc=Issue-Labels hinzugefügt oder entfernt.
|
||||||
settings.event_issue_milestone=Meilenstein einem Issue zugewiesen
|
settings.event_issue_milestone=Meilensteine
|
||||||
settings.event_issue_milestone_desc=Meilenstein zu Issue hinzugefügt oder entfernt.
|
settings.event_issue_milestone_desc=Meilenstein hinzugefügt, entfernt oder verändert.
|
||||||
settings.event_issue_comment=Issue-Kommentar
|
settings.event_issue_comment=Kommentare
|
||||||
settings.event_issue_comment_desc=Issue-Kommentar angelegt, geändert oder gelöscht.
|
settings.event_issue_comment_desc=Issue-Kommentar angelegt, geändert oder gelöscht.
|
||||||
settings.event_header_pull_request=Pull-Request-Ereignisse
|
settings.event_header_pull_request=Pull-Request-Ereignisse
|
||||||
settings.event_pull_request=Pull-Request
|
settings.event_pull_request=Änderung
|
||||||
settings.event_pull_request_desc=Pull-Request geöffnet, geschlossen, wieder geöffnet oder bearbeitet.
|
settings.event_pull_request_desc=Pull-Request geöffnet, geschlossen, wieder geöffnet oder bearbeitet.
|
||||||
settings.event_pull_request_assign=Pull-Request zugewiesen
|
settings.event_pull_request_assign=Zuweisung
|
||||||
settings.event_pull_request_assign_desc=Pull-Request zugewiesen oder Zuweisung entfernt.
|
settings.event_pull_request_assign_desc=Pull-Request zugewiesen oder Zuweisung entfernt.
|
||||||
settings.event_pull_request_label=Pull-Request mit Label versehen
|
settings.event_pull_request_label=Labels
|
||||||
settings.event_pull_request_label_desc=Pull-Request-Labels aktualisiert oder geleert.
|
settings.event_pull_request_label_desc=Pull-Request-Labels hinzugefügt oder entfernt.
|
||||||
settings.event_pull_request_milestone=Pull-Request zum Meilenstein hinzugefügt
|
settings.event_pull_request_milestone=Meilensteine
|
||||||
settings.event_pull_request_milestone_desc=Pull-Request zum Meilenstein hinzugefügt oder entfernt.
|
settings.event_pull_request_milestone_desc=Meilenstein hinzugefügt, entfernt oder bearbeitet.
|
||||||
settings.event_pull_request_comment=Pull-Request-Kommentar
|
settings.event_pull_request_comment=Kommentare
|
||||||
settings.event_pull_request_comment_desc=Pull-Request-Kommentar angelegt, geändert oder gelöscht.
|
settings.event_pull_request_comment_desc=Pull-Request-Kommentar angelegt, geändert oder gelöscht.
|
||||||
settings.event_pull_request_review=Pull-Request überprüft
|
settings.event_pull_request_review=Reviews
|
||||||
settings.event_pull_request_review_desc=Pull-Request genehmigt, abgelehnt oder Kommentar hinterlassen.
|
settings.event_pull_request_review_desc=Pull-Request genehmigt, abgelehnt oder Review-Kommentare hinterlassen.
|
||||||
settings.event_pull_request_sync=Pull-Request synchronisiert
|
settings.event_pull_request_sync=Synchronisiert
|
||||||
settings.event_pull_request_sync_desc=Pull-Request synchronisiert.
|
settings.event_pull_request_sync_desc=Branch automatisch mit Zielbranch aktualisiert.
|
||||||
settings.event_pull_request_review_request=Überprüfung des Pull-Requests angefragt
|
settings.event_pull_request_review_request=Review-Anfragen
|
||||||
settings.event_pull_request_review_request_desc=Überprüfung des Pull-Requests angefragt oder die Anfrage entfernt.
|
settings.event_pull_request_review_request_desc=Überprüfung des Pull-Requests angefragt oder die Anfrage entfernt.
|
||||||
settings.event_pull_request_approvals=Genehmigungen zum Pull-Request
|
settings.event_pull_request_approvals=Genehmigungen zum Pull-Request
|
||||||
settings.event_pull_request_merge=Pull-Request-Merge
|
settings.event_pull_request_merge=Pull-Request-Merge
|
||||||
|
@ -2434,7 +2437,7 @@ settings.require_signed_commits_desc=Pushes auf diesen Branch ablehnen, wenn Com
|
||||||
settings.protect_branch_name_pattern=Muster für geschützte Branchnamen
|
settings.protect_branch_name_pattern=Muster für geschützte Branchnamen
|
||||||
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="%s">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="%s">%s</a> Dokumentation zur Mustersyntax. Beispiele: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>.
|
||||||
settings.protect_unprotected_file_patterns=Ungeschützte Dateimuster (durch Semikolon „;“ getrennt)
|
settings.protect_unprotected_file_patterns=Ungeschützte Dateimuster (durch Semikolon „;“ getrennt)
|
||||||
settings.protect_unprotected_file_patterns_desc=Ungeschützte Dateien, die direkt geändert werden dürfen, wenn der Benutzer Schreibzugriff hat, können die Push-Beschränkung umgehen. Mehrere Muster können mit Semikolon („;“) getrennt werden. Siehe <a href="%[1]s">%[2]s</a> Dokumentation zur Mustersyntax. Beispiele: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>.
|
settings.protect_unprotected_file_patterns_desc=Ungeschützte Dateien, die direkt geändert werden dürfen, wenn der Benutzer Schreibzugriff hat, können die Push-Beschränkung umgehen. Mehrere Muster können mit Semikolon („;“) getrennt werden. Siehe <a href="%[1]s">%[2]s</a> Dokumentation zur Mustersyntax. Beispiele: <code>.drone.yml</code>, <code>/docs/**/*.txt</code>.
|
||||||
settings.add_protected_branch=Schutz aktivieren
|
settings.add_protected_branch=Schutz aktivieren
|
||||||
|
@ -2503,7 +2506,7 @@ settings.lfs_invalid_locking_path=Ungültiger Pfad: %s
|
||||||
settings.lfs_invalid_lock_directory=Verzeichnis kann nicht gesperrt werden: %s
|
settings.lfs_invalid_lock_directory=Verzeichnis kann nicht gesperrt werden: %s
|
||||||
settings.lfs_lock_already_exists=Sperre existiert bereits: %s
|
settings.lfs_lock_already_exists=Sperre existiert bereits: %s
|
||||||
settings.lfs_lock=Sperren
|
settings.lfs_lock=Sperren
|
||||||
settings.lfs_lock_path=Zu sperrender Dateipfad...
|
settings.lfs_lock_path=Zu sperrender Dateipfad …
|
||||||
settings.lfs_locks_no_locks=Keine Sperren
|
settings.lfs_locks_no_locks=Keine Sperren
|
||||||
settings.lfs_lock_file_no_exist=Gesperrte Datei existiert nicht im Standard-Branch
|
settings.lfs_lock_file_no_exist=Gesperrte Datei existiert nicht im Standard-Branch
|
||||||
settings.lfs_force_unlock=Freigabe erzwingen
|
settings.lfs_force_unlock=Freigabe erzwingen
|
||||||
|
@ -2587,7 +2590,7 @@ release.draft=Entwurf
|
||||||
release.prerelease=Pre-Release
|
release.prerelease=Pre-Release
|
||||||
release.stable=Stabil
|
release.stable=Stabil
|
||||||
release.compare=Vergleichen
|
release.compare=Vergleichen
|
||||||
release.edit=bearbeiten
|
release.edit=Bearbeiten
|
||||||
release.ahead.commits=<strong>%d</strong> Commits
|
release.ahead.commits=<strong>%d</strong> Commits
|
||||||
release.ahead.target=zu %s seit dieser Version
|
release.ahead.target=zu %s seit dieser Version
|
||||||
tag.ahead.target=auf %s seit diesem Tag
|
tag.ahead.target=auf %s seit diesem Tag
|
||||||
|
@ -2684,7 +2687,7 @@ rss.must_be_on_branch = Du musst auf einem Branch sein, um einen RSS-Feed zu hab
|
||||||
new_repo_helper = Ein Repository enthält alle Projektdateien inklusive der Revisionshistorie. Bereits woanders gehostet? <a href="%s">Repository migrieren.</a>
|
new_repo_helper = Ein Repository enthält alle Projektdateien inklusive der Revisionshistorie. Bereits woanders gehostet? <a href="%s">Repository migrieren.</a>
|
||||||
issues.comment.blocked_by_user = Du kannst kein Kommentar für dieses Issue erstellen, weil du vom Repository-Besitzer oder dem Autoren des Issues blockiert wurdest.
|
issues.comment.blocked_by_user = Du kannst kein Kommentar für dieses Issue erstellen, weil du vom Repository-Besitzer oder dem Autoren des Issues blockiert wurdest.
|
||||||
clone_in_vscodium = In VSCodium klonen
|
clone_in_vscodium = In VSCodium klonen
|
||||||
settings.units.add_more = Mehr hinzufügen …
|
settings.units.add_more = Mehr aktivieren
|
||||||
settings.wiki_rename_branch_main_desc = Den Branch, der intern vom Wiki benutzt wird, zu „%s“ umbenennen. Dies ist permanent und kann nicht rückgängig gemacht werden.
|
settings.wiki_rename_branch_main_desc = Den Branch, der intern vom Wiki benutzt wird, zu „%s“ umbenennen. Dies ist permanent und kann nicht rückgängig gemacht werden.
|
||||||
desc.sha256 = SHA256
|
desc.sha256 = SHA256
|
||||||
object_format_helper = Objektformat des Repositorys. Kann später nicht geändert werden. SHA1 ist am kompatibelsten.
|
object_format_helper = Objektformat des Repositorys. Kann später nicht geändert werden. SHA1 ist am kompatibelsten.
|
||||||
|
@ -2727,7 +2730,7 @@ pulls.fast_forward_only_merge_pull_request = Nur Fast-forward
|
||||||
pulls.cmd_instruction_checkout_desc = Checke einen neuen Branch aus deinem Projekt-Repository aus und teste die Änderungen.
|
pulls.cmd_instruction_checkout_desc = Checke einen neuen Branch aus deinem Projekt-Repository aus und teste die Änderungen.
|
||||||
pulls.cmd_instruction_merge_title = Zusammenführen
|
pulls.cmd_instruction_merge_title = Zusammenführen
|
||||||
pulls.cmd_instruction_merge_desc = Die Änderungen zusammenführen und auf Forgejo aktualisieren.
|
pulls.cmd_instruction_merge_desc = Die Änderungen zusammenführen und auf Forgejo aktualisieren.
|
||||||
settings.units.units = Repository-Einheiten
|
settings.units.units = Einheiten
|
||||||
settings.units.overview = Übersicht
|
settings.units.overview = Übersicht
|
||||||
settings.wiki_rename_branch_main_notices_1 = Diese Aktion <strong>KANN NICHT</strong> rückgängig gemacht werden.
|
settings.wiki_rename_branch_main_notices_1 = Diese Aktion <strong>KANN NICHT</strong> rückgängig gemacht werden.
|
||||||
settings.wiki_rename_branch_main_notices_2 = Dies wird den internen Branch des Repository-Wikis von %s permanent umbenennen. Existierende Checkouts müssen aktualisiert werden.
|
settings.wiki_rename_branch_main_notices_2 = Dies wird den internen Branch des Repository-Wikis von %s permanent umbenennen. Existierende Checkouts müssen aktualisiert werden.
|
||||||
|
@ -2826,6 +2829,15 @@ mirror_denied_combination = Authentifizierung mittels öffentlichem Schlüssel u
|
||||||
settings.mirror_settings.push_mirror.none_ssh = Nichts
|
settings.mirror_settings.push_mirror.none_ssh = Nichts
|
||||||
settings.mirror_settings.push_mirror.copy_public_key = Öffentlichen Schlüssel kopieren
|
settings.mirror_settings.push_mirror.copy_public_key = Öffentlichen Schlüssel kopieren
|
||||||
mirror_use_ssh.not_available = SSH-Authentifizierung ist nicht verfügbar.
|
mirror_use_ssh.not_available = SSH-Authentifizierung ist nicht verfügbar.
|
||||||
|
issues.new.assign_to_me = Mir selbst zuweisen
|
||||||
|
issues.all_title = Alle
|
||||||
|
settings.discord_icon_url.exceeds_max_length = Die Icon-URL darf eine Länge von 2048 Zeichen nicht überschreiten
|
||||||
|
issues.review.add_review_requests = hat Reviews von %[1]s %[2]s angefragt
|
||||||
|
issues.review.remove_review_requests = hat Aufforderungen zum Review an %[1]s %[2]s entfernt
|
||||||
|
issues.review.add_remove_review_requests = hat Reviews von %[1]s angefragt und hat die Aufforderungen zum Review an %[2]s %[3]s entfernt
|
||||||
|
pulls.delete_after_merge.head_branch.is_default = Der Head-Branch, den Sie löschen wollen, ist der Standardbranch und kann nicht gelöscht werden.
|
||||||
|
pulls.delete_after_merge.head_branch.is_protected = Der Head-Branch, den Sie löschen wollen, ist ein geschützter Branch und kann nicht gelöscht werden.
|
||||||
|
pulls.delete_after_merge.head_branch.insufficient_branch = Sie haben keine Erlaubnis, den Head-Branch zu löschen.
|
||||||
|
|
||||||
[graphs]
|
[graphs]
|
||||||
|
|
||||||
|
@ -3265,12 +3277,12 @@ auths.tip.bitbucket=Registriere einen neuen OAuth-Consumer unter %s
|
||||||
auths.tip.nextcloud=Registriere einen neuen OAuth-Consumer auf deiner Instanz über das folgende Menü: „Settings -> Security -> OAuth 2.0 client“
|
auths.tip.nextcloud=Registriere einen neuen OAuth-Consumer auf deiner Instanz über das folgende Menü: „Settings -> Security -> OAuth 2.0 client“
|
||||||
auths.tip.dropbox=Erstelle eine neue App auf %s
|
auths.tip.dropbox=Erstelle eine neue App auf %s
|
||||||
auths.tip.facebook=Erstelle eine neue Anwendung auf %s und füge das Produkt „Facebook Login“ hinzu
|
auths.tip.facebook=Erstelle eine neue Anwendung auf %s und füge das Produkt „Facebook Login“ hinzu
|
||||||
auths.tip.github=Erstelle unter %s eine neue OAuth-Anwendung.
|
auths.tip.github=Registriere unter %s eine neue OAuth-Anwendung
|
||||||
auths.tip.gitlab=Erstelle unter https://gitlab.com/profile/applications eine neue Anwendung.
|
auths.tip.gitlab=Erstelle unter https://gitlab.com/profile/applications eine neue Anwendung.
|
||||||
auths.tip.google_plus=Du erhältst die OAuth2-Client-Zugangsdaten in der Google-API-Konsole unter %s
|
auths.tip.google_plus=Du erhältst die OAuth2-Client-Zugangsdaten in der Google-API-Konsole unter %s
|
||||||
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 %s, 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 %s, 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 %s eine neue Anwendung.
|
auths.tip.discord=Registriere unter %s eine neue Anwendung
|
||||||
auths.tip.gitea=Registriere eine neue OAuth2-Anwendung. Eine Anleitung findest du unter %s
|
auths.tip.gitea=Registriere eine neue OAuth2-Anwendung. Eine Anleitung findest du unter %s
|
||||||
auths.tip.yandex=`Erstelle eine neue Anwendung auf %s. Wähle folgende Berechtigungen aus dem Abschnitt „Yandex.Passport API“: „Zugriff auf E-Mail-Adresse“, „Zugriff auf Benutzeravatar“ und „Zugriff auf Benutzername, Vor- und Nachname, Geschlecht“`
|
auths.tip.yandex=`Erstelle eine neue Anwendung auf %s. Wähle folgende Berechtigungen aus dem Abschnitt „Yandex.Passport API“: „Zugriff auf E-Mail-Adresse“, „Zugriff auf Benutzeravatar“ und „Zugriff auf Benutzername, Vor- und Nachname, Geschlecht“`
|
||||||
auths.tip.mastodon=Gib eine benutzerdefinierte URL für die Mastodon-Instanz ein, mit der du dich authentifizieren möchtest (oder benutze die standardmäßige)
|
auths.tip.mastodon=Gib eine benutzerdefinierte URL für die Mastodon-Instanz ein, mit der du dich authentifizieren möchtest (oder benutze die standardmäßige)
|
||||||
|
@ -3792,7 +3804,7 @@ management=Secrets verwalten
|
||||||
[actions]
|
[actions]
|
||||||
actions=Actions
|
actions=Actions
|
||||||
|
|
||||||
unit.desc=Integrierte CI/CD-Pipelines mit Forgejo-Actions verwalten
|
unit.desc=Integrierte CI/CD-Pipelines mit Forgejo-Actions verwalten.
|
||||||
|
|
||||||
status.unknown=Unbekannt
|
status.unknown=Unbekannt
|
||||||
status.waiting=Wartend
|
status.waiting=Wartend
|
||||||
|
@ -3947,6 +3959,8 @@ pull_kind = Pulls durchsuchen …
|
||||||
union = Vereinigungsmenge
|
union = Vereinigungsmenge
|
||||||
union_tooltip = Ergebnisse, die auf ein beliebiges von den Whitespace getrennten Schlüsselwörtern passen, einbinden
|
union_tooltip = Ergebnisse, die auf ein beliebiges von den Whitespace getrennten Schlüsselwörtern passen, einbinden
|
||||||
milestone_kind = Meilensteine suchen …
|
milestone_kind = Meilensteine suchen …
|
||||||
|
regexp = RegExp
|
||||||
|
regexp_tooltip = Suchbegriff als regulären Ausdruck interpretieren
|
||||||
|
|
||||||
[markup]
|
[markup]
|
||||||
filepreview.line = Zeile %[1]d in %[2]s
|
filepreview.line = Zeile %[1]d in %[2]s
|
||||||
|
@ -3964,4 +3978,24 @@ eib = EiB
|
||||||
|
|
||||||
|
|
||||||
[translation_meta]
|
[translation_meta]
|
||||||
test = ok
|
test = ok
|
||||||
|
|
||||||
|
[repo.permissions]
|
||||||
|
code.write = <b>Schreiben:</b> In das Repository pushen, Branches und Tags erstellen.
|
||||||
|
code.read = <b>Lesen:</b> Zugriff auf das Repository und Klonen.
|
||||||
|
issues.read = <b>Lesen:</b> Issues und Kommentare lesen und erstellen.
|
||||||
|
issues.write = <b>Schreiben:</b> Issues schließen und Metadaten wie Labels, Meilensteine, Zuweisungen, Fälligkeitsdaten und Abhängigkeiten verwalten.
|
||||||
|
pulls.read = <b>Lesen:</b> Pull-Requests lesen und erstellen.
|
||||||
|
releases.read = <b>Lesen:</b> Releases ansehen und herunterladen.
|
||||||
|
releases.write = <b>Schreiben:</b> Releases und ihre Assets veröffentlichen, bearbeiten und löschen.
|
||||||
|
wiki.read = <b>Lesen:</b> Das integrierte Wiki und seine Historie lesen.
|
||||||
|
wiki.write = <b>Schreiben:</b> Seiten im integrierten Wiki erstellen, aktualisieren und löschen.
|
||||||
|
projects.read = <b>Lesen:</b> Zugriff auf Projektboards des Repositories.
|
||||||
|
projects.write = <b>Schreiben:</b> Projekte und Spalten erstellen und bearbeiten.
|
||||||
|
packages.read = <b>Lesen:</b> Pakete dieses Repositories betrachten und herunterladen.
|
||||||
|
packages.write = <b>Schreiben:</b> Pakete dieses Repositories veröffentlichen und löschen.
|
||||||
|
actions.read = <b>Lesen:</b> Integrierte CI/CD-Pipelines und ihre Logs betrachten.
|
||||||
|
actions.write = <b>Schreiben:</b> Ausstehende CI/CD-Pipelines manuell auslösen, neustarten, abbrechen oder genehmigen.
|
||||||
|
ext_issues = Zugriff auf den Link zu einem externen Issue-Tracker. Die Berechtigungen werden extern verwaltet.
|
||||||
|
ext_wiki = Zugriff auf den Link zu einem externen Wiki. Die Berechtigungen werden extern verwaltet.
|
||||||
|
pulls.write = <b>Schreiben:</b> Pull-Requests schließen und Metadaten wie Labels, Meilensteine, Zuweisungen, Fälligkeitsdaten und Abhängigkeiten verwalten.
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue