mirror of
https://github.com/go-gitea/gitea.git
synced 2026-07-30 20:53:54 +02:00
Merge remote-tracking branch 'upstream/main' into limit-repo-size
This commit is contained in:
+67
-59
@@ -10,6 +10,7 @@ parserOptions:
|
||||
|
||||
plugins:
|
||||
- "@eslint-community/eslint-plugin-eslint-comments"
|
||||
- "@stylistic/eslint-plugin-js"
|
||||
- eslint-plugin-array-func
|
||||
- eslint-plugin-i
|
||||
- eslint-plugin-jquery
|
||||
@@ -114,11 +115,74 @@ rules:
|
||||
"@eslint-community/eslint-comments/no-unused-enable": [2]
|
||||
"@eslint-community/eslint-comments/no-use": [0]
|
||||
"@eslint-community/eslint-comments/require-description": [0]
|
||||
"@stylistic/js/array-bracket-newline": [0]
|
||||
"@stylistic/js/array-bracket-spacing": [2, never]
|
||||
"@stylistic/js/array-element-newline": [0]
|
||||
"@stylistic/js/arrow-parens": [2, always]
|
||||
"@stylistic/js/arrow-spacing": [2, {before: true, after: true}]
|
||||
"@stylistic/js/block-spacing": [0]
|
||||
"@stylistic/js/brace-style": [2, 1tbs, {allowSingleLine: true}]
|
||||
"@stylistic/js/comma-dangle": [2, only-multiline]
|
||||
"@stylistic/js/comma-spacing": [2, {before: false, after: true}]
|
||||
"@stylistic/js/comma-style": [2, last]
|
||||
"@stylistic/js/computed-property-spacing": [2, never]
|
||||
"@stylistic/js/dot-location": [2, property]
|
||||
"@stylistic/js/eol-last": [2]
|
||||
"@stylistic/js/func-call-spacing": [2, never]
|
||||
"@stylistic/js/function-call-argument-newline": [0]
|
||||
"@stylistic/js/function-paren-newline": [0]
|
||||
"@stylistic/js/generator-star-spacing": [0]
|
||||
"@stylistic/js/implicit-arrow-linebreak": [0]
|
||||
"@stylistic/js/indent": [2, 2, {ignoreComments: true, SwitchCase: 1}]
|
||||
"@stylistic/js/key-spacing": [2]
|
||||
"@stylistic/js/keyword-spacing": [2]
|
||||
"@stylistic/js/linebreak-style": [2, unix]
|
||||
"@stylistic/js/lines-around-comment": [0]
|
||||
"@stylistic/js/lines-between-class-members": [0]
|
||||
"@stylistic/js/max-len": [0]
|
||||
"@stylistic/js/max-statements-per-line": [0]
|
||||
"@stylistic/js/multiline-ternary": [0]
|
||||
"@stylistic/js/new-parens": [2]
|
||||
"@stylistic/js/newline-per-chained-call": [0]
|
||||
"@stylistic/js/no-confusing-arrow": [0]
|
||||
"@stylistic/js/no-extra-parens": [0]
|
||||
"@stylistic/js/no-extra-semi": [2]
|
||||
"@stylistic/js/no-floating-decimal": [0]
|
||||
"@stylistic/js/no-mixed-operators": [0]
|
||||
"@stylistic/js/no-mixed-spaces-and-tabs": [2]
|
||||
"@stylistic/js/no-multi-spaces": [2, {ignoreEOLComments: true, exceptions: {Property: true}}]
|
||||
"@stylistic/js/no-multiple-empty-lines": [2, {max: 1, maxEOF: 0, maxBOF: 0}]
|
||||
"@stylistic/js/no-tabs": [2]
|
||||
"@stylistic/js/no-trailing-spaces": [2]
|
||||
"@stylistic/js/no-whitespace-before-property": [2]
|
||||
"@stylistic/js/nonblock-statement-body-position": [2]
|
||||
"@stylistic/js/object-curly-newline": [0]
|
||||
"@stylistic/js/object-curly-spacing": [2, never]
|
||||
"@stylistic/js/object-property-newline": [0]
|
||||
"@stylistic/js/one-var-declaration-per-line": [0]
|
||||
"@stylistic/js/operator-linebreak": [2, after]
|
||||
"@stylistic/js/padded-blocks": [2, never]
|
||||
"@stylistic/js/padding-line-between-statements": [0]
|
||||
"@stylistic/js/quote-props": [0]
|
||||
"@stylistic/js/quotes": [2, single, {avoidEscape: true, allowTemplateLiterals: true}]
|
||||
"@stylistic/js/rest-spread-spacing": [2, never]
|
||||
"@stylistic/js/semi": [2, always, {omitLastInOneLineBlock: true}]
|
||||
"@stylistic/js/semi-spacing": [2, {before: false, after: true}]
|
||||
"@stylistic/js/semi-style": [2, last]
|
||||
"@stylistic/js/space-before-blocks": [2, always]
|
||||
"@stylistic/js/space-before-function-paren": [0]
|
||||
"@stylistic/js/space-in-parens": [2, never]
|
||||
"@stylistic/js/space-infix-ops": [2]
|
||||
"@stylistic/js/space-unary-ops": [2]
|
||||
"@stylistic/js/spaced-comment": [2, always]
|
||||
"@stylistic/js/switch-colon-spacing": [2]
|
||||
"@stylistic/js/template-curly-spacing": [2, never]
|
||||
"@stylistic/js/template-tag-spacing": [2, never]
|
||||
"@stylistic/js/wrap-iife": [2, inside]
|
||||
"@stylistic/js/wrap-regex": [0]
|
||||
"@stylistic/js/yield-star-spacing": [2, after]
|
||||
accessor-pairs: [2]
|
||||
array-bracket-newline: [0]
|
||||
array-bracket-spacing: [2, never]
|
||||
array-callback-return: [2, {checkForEach: true}]
|
||||
array-element-newline: [0]
|
||||
array-func/avoid-reverse: [2]
|
||||
array-func/from-map: [2]
|
||||
array-func/no-unnecessary-this-arg: [2]
|
||||
@@ -126,18 +190,11 @@ rules:
|
||||
array-func/prefer-flat-map: [0] # handled by unicorn/prefer-array-flat-map
|
||||
array-func/prefer-flat: [0] # handled by unicorn/prefer-array-flat
|
||||
arrow-body-style: [0]
|
||||
arrow-parens: [2, always]
|
||||
arrow-spacing: [2, {before: true, after: true}]
|
||||
block-scoped-var: [2]
|
||||
brace-style: [2, 1tbs, {allowSingleLine: true}]
|
||||
camelcase: [0]
|
||||
capitalized-comments: [0]
|
||||
class-methods-use-this: [0]
|
||||
comma-dangle: [2, only-multiline]
|
||||
comma-spacing: [2, {before: false, after: true}]
|
||||
comma-style: [2, last]
|
||||
complexity: [0]
|
||||
computed-property-spacing: [2, never]
|
||||
consistent-return: [0]
|
||||
consistent-this: [0]
|
||||
constructor-super: [2]
|
||||
@@ -145,25 +202,18 @@ rules:
|
||||
default-case-last: [2]
|
||||
default-case: [0]
|
||||
default-param-last: [0]
|
||||
dot-location: [2, property]
|
||||
dot-notation: [0]
|
||||
eol-last: [2]
|
||||
eqeqeq: [2]
|
||||
for-direction: [2]
|
||||
func-call-spacing: [2, never]
|
||||
func-name-matching: [2]
|
||||
func-names: [0]
|
||||
func-style: [0]
|
||||
function-call-argument-newline: [0]
|
||||
function-paren-newline: [0]
|
||||
generator-star-spacing: [0]
|
||||
getter-return: [2]
|
||||
grouped-accessor-pairs: [2]
|
||||
guard-for-in: [0]
|
||||
id-blacklist: [0]
|
||||
id-length: [0]
|
||||
id-match: [0]
|
||||
implicit-arrow-linebreak: [0]
|
||||
i/consistent-type-specifier-style: [0]
|
||||
i/default: [0]
|
||||
i/dynamic-import-chunkname: [0]
|
||||
@@ -207,7 +257,6 @@ rules:
|
||||
i/order: [0]
|
||||
i/prefer-default-export: [0]
|
||||
i/unambiguous: [0]
|
||||
indent: [2, 2, {SwitchCase: 1}]
|
||||
init-declarations: [0]
|
||||
jquery/no-ajax-events: [2]
|
||||
jquery/no-ajax: [0]
|
||||
@@ -258,27 +307,17 @@ rules:
|
||||
jquery/no-val: [0]
|
||||
jquery/no-when: [2]
|
||||
jquery/no-wrap: [2]
|
||||
key-spacing: [2]
|
||||
keyword-spacing: [2]
|
||||
line-comment-position: [0]
|
||||
linebreak-style: [2, unix]
|
||||
lines-around-comment: [0]
|
||||
lines-between-class-members: [0]
|
||||
logical-assignment-operators: [0]
|
||||
max-classes-per-file: [0]
|
||||
max-depth: [0]
|
||||
max-len: [0]
|
||||
max-lines-per-function: [0]
|
||||
max-lines: [0]
|
||||
max-nested-callbacks: [0]
|
||||
max-params: [0]
|
||||
max-statements-per-line: [0]
|
||||
max-statements: [0]
|
||||
multiline-comment-style: [2, separate-lines]
|
||||
multiline-ternary: [0]
|
||||
new-cap: [0]
|
||||
new-parens: [2]
|
||||
newline-per-chained-call: [0]
|
||||
no-alert: [0]
|
||||
no-array-constructor: [2]
|
||||
no-async-promise-executor: [0]
|
||||
@@ -290,7 +329,6 @@ rules:
|
||||
no-class-assign: [2]
|
||||
no-compare-neg-zero: [2]
|
||||
no-cond-assign: [2, except-parens]
|
||||
no-confusing-arrow: [0]
|
||||
no-console: [1, {allow: [debug, info, warn, error]}]
|
||||
no-const-assign: [2]
|
||||
no-constant-binary-expression: [2]
|
||||
@@ -320,10 +358,7 @@ rules:
|
||||
no-extra-bind: [2]
|
||||
no-extra-boolean-cast: [2]
|
||||
no-extra-label: [0]
|
||||
no-extra-parens: [0]
|
||||
no-extra-semi: [2]
|
||||
no-fallthrough: [2]
|
||||
no-floating-decimal: [0]
|
||||
no-func-assign: [2]
|
||||
no-global-assign: [2]
|
||||
no-implicit-coercion: [2]
|
||||
@@ -437,10 +472,7 @@ rules:
|
||||
no-loss-of-precision: [2]
|
||||
no-magic-numbers: [0]
|
||||
no-misleading-character-class: [2]
|
||||
no-mixed-operators: [0]
|
||||
no-mixed-spaces-and-tabs: [2]
|
||||
no-multi-assign: [0]
|
||||
no-multi-spaces: [2, {ignoreEOLComments: true, exceptions: {Property: true}}]
|
||||
no-multi-str: [2]
|
||||
no-negated-condition: [0]
|
||||
no-nested-ternary: [0]
|
||||
@@ -474,12 +506,10 @@ rules:
|
||||
no-shadow-restricted-names: [2]
|
||||
no-shadow: [0]
|
||||
no-sparse-arrays: [2]
|
||||
no-tabs: [2]
|
||||
no-template-curly-in-string: [2]
|
||||
no-ternary: [0]
|
||||
no-this-before-super: [2]
|
||||
no-throw-literal: [2]
|
||||
no-trailing-spaces: [2]
|
||||
no-undef-init: [2]
|
||||
no-undef: [2, {typeof: true}]
|
||||
no-undefined: [0]
|
||||
@@ -509,18 +539,12 @@ rules:
|
||||
no-var: [2]
|
||||
no-void: [2]
|
||||
no-warning-comments: [0]
|
||||
no-whitespace-before-property: [2]
|
||||
no-with: [0] # handled by no-restricted-syntax
|
||||
nonblock-statement-body-position: [2]
|
||||
object-curly-newline: [0]
|
||||
object-curly-spacing: [2, never]
|
||||
object-shorthand: [2, always]
|
||||
one-var-declaration-per-line: [0]
|
||||
one-var: [0]
|
||||
operator-assignment: [2, always]
|
||||
operator-linebreak: [2, after]
|
||||
padded-blocks: [2, never]
|
||||
padding-line-between-statements: [0]
|
||||
prefer-arrow-callback: [2, {allowNamedFunctions: true, allowUnboundThis: true}]
|
||||
prefer-const: [2, {destructuring: all, ignoreReadBeforeAssign: true}]
|
||||
prefer-destructuring: [0]
|
||||
@@ -534,7 +558,6 @@ rules:
|
||||
prefer-rest-params: [2]
|
||||
prefer-spread: [2]
|
||||
prefer-template: [2]
|
||||
quote-props: [0]
|
||||
quotes: [2, single, {avoidEscape: true, allowTemplateLiterals: true}]
|
||||
radix: [2, as-needed]
|
||||
regexp/confusing-quantifier: [2]
|
||||
@@ -620,10 +643,6 @@ rules:
|
||||
require-await: [0]
|
||||
require-unicode-regexp: [0]
|
||||
require-yield: [2]
|
||||
rest-spread-spacing: [2, never]
|
||||
semi-spacing: [2, {before: false, after: true}]
|
||||
semi-style: [2, last]
|
||||
semi: [2, always, {omitLastInOneLineBlock: true}]
|
||||
sonarjs/cognitive-complexity: [0]
|
||||
sonarjs/elseif-without-else: [0]
|
||||
sonarjs/max-switch-cases: [0]
|
||||
@@ -659,16 +678,8 @@ rules:
|
||||
sort-imports: [0]
|
||||
sort-keys: [0]
|
||||
sort-vars: [0]
|
||||
space-before-blocks: [2, always]
|
||||
space-in-parens: [2, never]
|
||||
space-infix-ops: [2]
|
||||
space-unary-ops: [2]
|
||||
spaced-comment: [2, always]
|
||||
strict: [0]
|
||||
switch-colon-spacing: [2]
|
||||
symbol-description: [2]
|
||||
template-curly-spacing: [2, never]
|
||||
template-tag-spacing: [2, never]
|
||||
unicode-bom: [2, never]
|
||||
unicorn/better-regex: [0]
|
||||
unicorn/catch-error-name: [0]
|
||||
@@ -807,7 +818,4 @@ rules:
|
||||
wc/no-typos: [2]
|
||||
wc/require-listener-teardown: [2]
|
||||
wc/tag-name-matches-class: [2]
|
||||
wrap-iife: [2, inside]
|
||||
wrap-regex: [0]
|
||||
yield-star-spacing: [2, after]
|
||||
yoda: [2, never]
|
||||
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
- run: make generate-license generate-gitignore
|
||||
timeout-minutes: 40
|
||||
- name: push translations to repo
|
||||
uses: appleboy/git-push-action@v0.0.2
|
||||
uses: appleboy/git-push-action@v0.0.3
|
||||
with:
|
||||
author_email: "teabot@gitea.io"
|
||||
author_name: GiteaBot
|
||||
|
||||
@@ -22,7 +22,7 @@ jobs:
|
||||
- name: update locales
|
||||
run: ./build/update-locales.sh
|
||||
- name: push translations to repo
|
||||
uses: appleboy/git-push-action@v0.0.2
|
||||
uses: appleboy/git-push-action@v0.0.3
|
||||
with:
|
||||
author_email: "teabot@gitea.io"
|
||||
author_name: GiteaBot
|
||||
|
||||
@@ -58,7 +58,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
- run: make deps-frontend
|
||||
@@ -115,7 +115,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
- run: make deps-frontend
|
||||
@@ -162,7 +162,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
- run: make deps-frontend
|
||||
|
||||
@@ -16,8 +16,8 @@ jobs:
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: docker/setup-buildx-action@v2
|
||||
- uses: docker/build-push-action@v4
|
||||
- uses: docker/setup-buildx-action@v3
|
||||
- uses: docker/build-push-action@v5
|
||||
with:
|
||||
push: false
|
||||
tags: gitea/gitea:linux-amd64
|
||||
@@ -27,8 +27,8 @@ jobs:
|
||||
needs: files-changed
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: docker/setup-buildx-action@v2
|
||||
- uses: docker/build-push-action@v4
|
||||
- uses: docker/setup-buildx-action@v3
|
||||
- uses: docker/build-push-action@v5
|
||||
with:
|
||||
push: false
|
||||
file: Dockerfile.rootless
|
||||
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
check-latest: true
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
- run: make deps-frontend frontend deps-backend
|
||||
|
||||
@@ -2,7 +2,7 @@ name: release-nightly
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, release/v* ]
|
||||
branches: [main, release/v*]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
@@ -22,7 +22,7 @@ jobs:
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
check-latest: true
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
- run: make deps-frontend deps-backend
|
||||
@@ -32,7 +32,7 @@ jobs:
|
||||
TAGS: bindata sqlite sqlite_unlock_notify
|
||||
- name: import gpg key
|
||||
id: import_gpg
|
||||
uses: crazy-max/ghaction-import-gpg@v5
|
||||
uses: crazy-max/ghaction-import-gpg@v6
|
||||
with:
|
||||
gpg_private_key: ${{ secrets.GPGSIGN_KEY }}
|
||||
passphrase: ${{ secrets.GPGSIGN_PASSPHRASE }}
|
||||
@@ -68,8 +68,8 @@ jobs:
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
check-latest: true
|
||||
- uses: docker/setup-qemu-action@v2
|
||||
- uses: docker/setup-buildx-action@v2
|
||||
- uses: docker/setup-qemu-action@v3
|
||||
- uses: docker/setup-buildx-action@v3
|
||||
- name: Get cleaned branch name
|
||||
id: clean_name
|
||||
run: |
|
||||
@@ -81,14 +81,14 @@ jobs:
|
||||
REF_NAME=$(echo "${{ github.ref }}" | sed -e 's/refs\/heads\///' -e 's/refs\/tags\///' -e 's/release\/v//')
|
||||
echo "branch=${REF_NAME}-nightly" >> "$GITHUB_OUTPUT"
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: fetch go modules
|
||||
run: make vendor
|
||||
- name: build rootful docker image
|
||||
uses: docker/build-push-action@v4
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
@@ -105,8 +105,8 @@ jobs:
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
check-latest: true
|
||||
- uses: docker/setup-qemu-action@v2
|
||||
- uses: docker/setup-buildx-action@v2
|
||||
- uses: docker/setup-qemu-action@v3
|
||||
- uses: docker/setup-buildx-action@v3
|
||||
- name: Get cleaned branch name
|
||||
id: clean_name
|
||||
run: |
|
||||
@@ -118,14 +118,14 @@ jobs:
|
||||
REF_NAME=$(echo "${{ github.ref }}" | sed -e 's/refs\/heads\///' -e 's/refs\/tags\///' -e 's/release\/v//')
|
||||
echo "branch=${REF_NAME}-nightly" >> "$GITHUB_OUTPUT"
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: fetch go modules
|
||||
run: make vendor
|
||||
- name: build rootless docker image
|
||||
uses: docker/build-push-action@v4
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
|
||||
@@ -3,7 +3,7 @@ name: release-tag-rc
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v1*-rc*'
|
||||
- "v1*-rc*"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
@@ -21,7 +21,7 @@ jobs:
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
check-latest: true
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
- run: make deps-frontend deps-backend
|
||||
@@ -31,7 +31,7 @@ jobs:
|
||||
TAGS: bindata sqlite sqlite_unlock_notify
|
||||
- name: import gpg key
|
||||
id: import_gpg
|
||||
uses: crazy-max/ghaction-import-gpg@v5
|
||||
uses: crazy-max/ghaction-import-gpg@v6
|
||||
with:
|
||||
gpg_private_key: ${{ secrets.GPGSIGN_KEY }}
|
||||
passphrase: ${{ secrets.GPGSIGN_PASSPHRASE }}
|
||||
@@ -68,8 +68,8 @@ jobs:
|
||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
||||
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
|
||||
- run: git fetch --unshallow --quiet --tags --force
|
||||
- uses: docker/setup-qemu-action@v2
|
||||
- uses: docker/setup-buildx-action@v2
|
||||
- uses: docker/setup-qemu-action@v3
|
||||
- uses: docker/setup-buildx-action@v3
|
||||
- uses: docker/metadata-action@v5
|
||||
id: meta
|
||||
with:
|
||||
@@ -78,12 +78,12 @@ jobs:
|
||||
tags: |
|
||||
type=semver,pattern={{version}}
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: build rootful docker image
|
||||
uses: docker/build-push-action@v4
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
@@ -97,8 +97,8 @@ jobs:
|
||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
||||
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
|
||||
- run: git fetch --unshallow --quiet --tags --force
|
||||
- uses: docker/setup-qemu-action@v2
|
||||
- uses: docker/setup-buildx-action@v2
|
||||
- uses: docker/setup-qemu-action@v3
|
||||
- uses: docker/setup-buildx-action@v3
|
||||
- uses: docker/metadata-action@v5
|
||||
id: meta
|
||||
with:
|
||||
@@ -110,12 +110,12 @@ jobs:
|
||||
tags: |
|
||||
type=semver,pattern={{version}}
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: build rootless docker image
|
||||
uses: docker/build-push-action@v4
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
|
||||
@@ -3,9 +3,9 @@ name: release-tag-version
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v1.*'
|
||||
- '!v1*-rc*'
|
||||
- '!v1*-dev'
|
||||
- "v1.*"
|
||||
- "!v1*-rc*"
|
||||
- "!v1*-dev"
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
check-latest: true
|
||||
- uses: actions/setup-node@v3
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
- run: make deps-frontend deps-backend
|
||||
@@ -33,7 +33,7 @@ jobs:
|
||||
TAGS: bindata sqlite sqlite_unlock_notify
|
||||
- name: import gpg key
|
||||
id: import_gpg
|
||||
uses: crazy-max/ghaction-import-gpg@v5
|
||||
uses: crazy-max/ghaction-import-gpg@v6
|
||||
with:
|
||||
gpg_private_key: ${{ secrets.GPGSIGN_KEY }}
|
||||
passphrase: ${{ secrets.GPGSIGN_PASSPHRASE }}
|
||||
@@ -70,8 +70,8 @@ jobs:
|
||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
||||
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
|
||||
- run: git fetch --unshallow --quiet --tags --force
|
||||
- uses: docker/setup-qemu-action@v2
|
||||
- uses: docker/setup-buildx-action@v2
|
||||
- uses: docker/setup-qemu-action@v3
|
||||
- uses: docker/setup-buildx-action@v3
|
||||
- uses: docker/metadata-action@v5
|
||||
id: meta
|
||||
with:
|
||||
@@ -87,12 +87,12 @@ jobs:
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{version}}
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: build rootful docker image
|
||||
uses: docker/build-push-action@v4
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
@@ -106,8 +106,8 @@ jobs:
|
||||
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
|
||||
# fetch all tags to ensure that "git describe" reports expected Gitea version, eg. v1.21.0-dev-1-g1234567
|
||||
- run: git fetch --unshallow --quiet --tags --force
|
||||
- uses: docker/setup-qemu-action@v2
|
||||
- uses: docker/setup-buildx-action@v2
|
||||
- uses: docker/setup-qemu-action@v3
|
||||
- uses: docker/setup-buildx-action@v3
|
||||
- uses: docker/metadata-action@v5
|
||||
id: meta
|
||||
with:
|
||||
@@ -126,12 +126,12 @@ jobs:
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{version}}
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
- name: build rootless docker image
|
||||
uses: docker/build-push-action@v4
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
|
||||
@@ -29,7 +29,6 @@ linters:
|
||||
fast: false
|
||||
|
||||
run:
|
||||
go: "1.21"
|
||||
timeout: 10m
|
||||
skip-dirs:
|
||||
- node_modules
|
||||
@@ -75,7 +74,6 @@ linters-settings:
|
||||
- name: modifies-value-receiver
|
||||
gofumpt:
|
||||
extra-rules: true
|
||||
lang-version: "1.21"
|
||||
depguard:
|
||||
rules:
|
||||
main:
|
||||
|
||||
+26
-10
@@ -1,4 +1,4 @@
|
||||
#Build stage
|
||||
# Build stage
|
||||
FROM docker.io/library/golang:1.21-alpine3.18 AS build-env
|
||||
|
||||
ARG GOPROXY
|
||||
@@ -9,20 +9,38 @@ ARG TAGS="sqlite sqlite_unlock_notify"
|
||||
ENV TAGS "bindata timetzdata $TAGS"
|
||||
ARG CGO_EXTRA_CFLAGS
|
||||
|
||||
#Build deps
|
||||
RUN apk --no-cache add build-base git nodejs npm
|
||||
# Build deps
|
||||
RUN apk --no-cache add \
|
||||
build-base \
|
||||
git \
|
||||
nodejs \
|
||||
npm \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
|
||||
#Setup repo
|
||||
# Setup repo
|
||||
COPY . ${GOPATH}/src/code.gitea.io/gitea
|
||||
WORKDIR ${GOPATH}/src/code.gitea.io/gitea
|
||||
|
||||
#Checkout version if set
|
||||
# Checkout version if set
|
||||
RUN if [ -n "${GITEA_VERSION}" ]; then git checkout "${GITEA_VERSION}"; fi \
|
||||
&& make clean-all build
|
||||
|
||||
# Begin env-to-ini build
|
||||
RUN go build contrib/environment-to-ini/environment-to-ini.go
|
||||
|
||||
# Copy local files
|
||||
COPY docker/root /tmp/local
|
||||
|
||||
# Set permissions
|
||||
RUN chmod 755 /tmp/local/usr/bin/entrypoint \
|
||||
/tmp/local/usr/local/bin/gitea \
|
||||
/tmp/local/etc/s6/gitea/* \
|
||||
/tmp/local/etc/s6/openssh/* \
|
||||
/tmp/local/etc/s6/.s6-svscan/* \
|
||||
/go/src/code.gitea.io/gitea/gitea \
|
||||
/go/src/code.gitea.io/gitea/environment-to-ini
|
||||
RUN chmod 644 /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete
|
||||
|
||||
FROM docker.io/library/alpine:3.18
|
||||
LABEL maintainer="maintainers@gitea.io"
|
||||
|
||||
@@ -39,7 +57,8 @@ RUN apk --no-cache add \
|
||||
s6 \
|
||||
sqlite \
|
||||
su-exec \
|
||||
gnupg
|
||||
gnupg \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
|
||||
RUN addgroup \
|
||||
-S -g 1000 \
|
||||
@@ -61,10 +80,7 @@ VOLUME ["/data"]
|
||||
ENTRYPOINT ["/usr/bin/entrypoint"]
|
||||
CMD ["/bin/s6-svscan", "/etc/s6"]
|
||||
|
||||
COPY docker/root /
|
||||
COPY --from=build-env /tmp/local /
|
||||
COPY --from=build-env /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea
|
||||
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
|
||||
RUN chmod 755 /usr/bin/entrypoint /app/gitea/gitea /usr/local/bin/gitea /usr/local/bin/environment-to-ini
|
||||
RUN chmod 755 /etc/s6/gitea/* /etc/s6/openssh/* /etc/s6/.s6-svscan/*
|
||||
RUN chmod 644 /etc/profile.d/gitea_bash_autocomplete.sh
|
||||
|
||||
+25
-11
@@ -1,4 +1,4 @@
|
||||
#Build stage
|
||||
# Build stage
|
||||
FROM docker.io/library/golang:1.21-alpine3.18 AS build-env
|
||||
|
||||
ARG GOPROXY
|
||||
@@ -10,19 +10,35 @@ ENV TAGS "bindata timetzdata $TAGS"
|
||||
ARG CGO_EXTRA_CFLAGS
|
||||
|
||||
#Build deps
|
||||
RUN apk --no-cache add build-base git nodejs npm
|
||||
RUN apk --no-cache add \
|
||||
build-base \
|
||||
git \
|
||||
nodejs \
|
||||
npm \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
|
||||
#Setup repo
|
||||
# Setup repo
|
||||
COPY . ${GOPATH}/src/code.gitea.io/gitea
|
||||
WORKDIR ${GOPATH}/src/code.gitea.io/gitea
|
||||
|
||||
#Checkout version if set
|
||||
# Checkout version if set
|
||||
RUN if [ -n "${GITEA_VERSION}" ]; then git checkout "${GITEA_VERSION}"; fi \
|
||||
&& make clean-all build
|
||||
|
||||
# Begin env-to-ini build
|
||||
RUN go build contrib/environment-to-ini/environment-to-ini.go
|
||||
|
||||
# Copy local files
|
||||
COPY docker/rootless /tmp/local
|
||||
|
||||
# Set permissions
|
||||
RUN chmod 755 /tmp/local/usr/local/bin/docker-entrypoint.sh \
|
||||
/tmp/local/usr/local/bin/docker-setup.sh \
|
||||
/tmp/local/usr/local/bin/gitea \
|
||||
/go/src/code.gitea.io/gitea/gitea \
|
||||
/go/src/code.gitea.io/gitea/environment-to-ini
|
||||
RUN chmod 644 /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete
|
||||
|
||||
FROM docker.io/library/alpine:3.18
|
||||
LABEL maintainer="maintainers@gitea.io"
|
||||
|
||||
@@ -35,7 +51,8 @@ RUN apk --no-cache add \
|
||||
gettext \
|
||||
git \
|
||||
curl \
|
||||
gnupg
|
||||
gnupg \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
|
||||
RUN addgroup \
|
||||
-S -g 1000 \
|
||||
@@ -51,21 +68,19 @@ RUN addgroup \
|
||||
RUN mkdir -p /var/lib/gitea /etc/gitea
|
||||
RUN chown git:git /var/lib/gitea /etc/gitea
|
||||
|
||||
COPY docker/rootless /
|
||||
COPY --from=build-env /tmp/local /
|
||||
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/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
|
||||
RUN chmod 755 /usr/local/bin/docker-entrypoint.sh /usr/local/bin/docker-setup.sh /app/gitea/gitea /usr/local/bin/gitea /usr/local/bin/environment-to-ini
|
||||
RUN chmod 644 /etc/profile.d/gitea_bash_autocomplete.sh
|
||||
|
||||
#git:git
|
||||
# git:git
|
||||
USER 1000:1000
|
||||
ENV GITEA_WORK_DIR /var/lib/gitea
|
||||
ENV GITEA_CUSTOM /var/lib/gitea/custom
|
||||
ENV GITEA_TEMP /tmp/gitea
|
||||
ENV TMPDIR /tmp/gitea
|
||||
|
||||
#TODO add to docs the ability to define the ini to load (useful to test and revert a config)
|
||||
# TODO add to docs the ability to define the ini to load (useful to test and revert a config)
|
||||
ENV GITEA_APP_INI /etc/gitea/app.ini
|
||||
ENV HOME "/var/lib/gitea/git"
|
||||
VOLUME ["/var/lib/gitea", "/etc/gitea"]
|
||||
@@ -73,4 +88,3 @@ WORKDIR /var/lib/gitea
|
||||
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--", "/usr/local/bin/docker-entrypoint.sh"]
|
||||
CMD []
|
||||
|
||||
|
||||
@@ -875,7 +875,7 @@ node_modules: package-lock.json
|
||||
@touch node_modules
|
||||
|
||||
.venv: poetry.lock
|
||||
poetry install
|
||||
poetry install --no-root
|
||||
@touch .venv
|
||||
|
||||
.PHONY: update
|
||||
@@ -892,7 +892,7 @@ update-js: node-check | node_modules
|
||||
update-py: node-check | node_modules
|
||||
npx updates -u -f pyproject.toml
|
||||
rm -rf .venv poetry.lock
|
||||
poetry install
|
||||
poetry install --no-root
|
||||
@touch .venv
|
||||
|
||||
.PHONY: fomantic
|
||||
|
||||
+1
-1
@@ -62,7 +62,7 @@ func runListAuth(c *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
authSources, err := auth_model.Sources(ctx)
|
||||
authSources, err := auth_model.FindSources(ctx, auth_model.FindSourcesOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -47,24 +47,28 @@ func main() {
|
||||
on the configuration cheat sheet.`
|
||||
app.Flags = []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "custom-path, C",
|
||||
Value: setting.CustomPath,
|
||||
Usage: "Custom path file path",
|
||||
Name: "custom-path",
|
||||
Aliases: []string{"C"},
|
||||
Value: setting.CustomPath,
|
||||
Usage: "Custom path file path",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "config, c",
|
||||
Value: setting.CustomConf,
|
||||
Usage: "Custom configuration file path",
|
||||
Name: "config",
|
||||
Aliases: []string{"c"},
|
||||
Value: setting.CustomConf,
|
||||
Usage: "Custom configuration file path",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "work-path, w",
|
||||
Value: setting.AppWorkPath,
|
||||
Usage: "Set the gitea working path",
|
||||
Name: "work-path",
|
||||
Aliases: []string{"w"},
|
||||
Value: setting.AppWorkPath,
|
||||
Usage: "Set the gitea working path",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "out, o",
|
||||
Value: "",
|
||||
Usage: "Destination file to write to",
|
||||
Name: "out",
|
||||
Aliases: []string{"o"},
|
||||
Value: "",
|
||||
Usage: "Destination file to write to",
|
||||
},
|
||||
}
|
||||
app.Action = runEnvironmentToIni
|
||||
|
||||
@@ -1230,6 +1230,9 @@ LEVEL = Info
|
||||
;; For custom reactions, add a tightly cropped square image to public/assets/img/emoji/reaction_name.png
|
||||
;REACTIONS = +1, -1, laugh, hooray, confused, heart, rocket, eyes
|
||||
;;
|
||||
;; Change the number of users that are displayed in reactions tooltip (triggered by mouse hover).
|
||||
;REACTION_MAX_USER_NUM = 10
|
||||
;;
|
||||
;; Additional Emojis not defined in the utf8 standard
|
||||
;; By default we support gitea (:gitea:), to add more copy them to public/assets/img/emoji/emoji_name.png and add it to this config.
|
||||
;; Dont mistake it for Reactions.
|
||||
|
||||
@@ -7,7 +7,7 @@ if [ ! -x /bin/sh ]; then
|
||||
fi
|
||||
|
||||
if [ "${USER}" != "git" ]; then
|
||||
# rename user
|
||||
# Rename user
|
||||
sed -i -e "s/^git\:/${USER}\:/g" /etc/passwd
|
||||
fi
|
||||
|
||||
@@ -19,13 +19,13 @@ if [ -z "${USER_UID}" ]; then
|
||||
USER_UID="`id -u ${USER}`"
|
||||
fi
|
||||
|
||||
## Change GID for USER?
|
||||
# Change GID for USER?
|
||||
if [ -n "${USER_GID}" ] && [ "${USER_GID}" != "`id -g ${USER}`" ]; then
|
||||
sed -i -e "s/^${USER}:\([^:]*\):[0-9]*/${USER}:\1:${USER_GID}/" /etc/group
|
||||
sed -i -e "s/^${USER}:\([^:]*\):\([0-9]*\):[0-9]*/${USER}:\1:\2:${USER_GID}/" /etc/passwd
|
||||
fi
|
||||
|
||||
## Change UID for USER?
|
||||
# Change UID for USER?
|
||||
if [ -n "${USER_UID}" ] && [ "${USER_UID}" != "`id -u ${USER}`" ]; then
|
||||
sed -i -e "s/^${USER}:\([^:]*\):[0-9]*:\([0-9]*\)/${USER}:\1:${USER_UID}:\2/" /etc/passwd
|
||||
fi
|
||||
|
||||
@@ -226,6 +226,7 @@ The following configuration set `Content-Type: application/vnd.android.package-a
|
||||
- `REACTIONS`: All available reactions users can choose on issues/prs and comments
|
||||
Values can be emoji alias (:smile:) or a unicode emoji.
|
||||
For custom reactions, add a tightly cropped square image to public/assets/img/emoji/reaction_name.png
|
||||
- `REACTION_MAX_USER_NUM`: **10**: Change the number of users that are displayed in reactions tooltip (triggered by mouse hover).
|
||||
- `CUSTOM_EMOJIS`: **gitea, codeberg, gitlab, git, github, gogs**: Additional Emojis not defined in the utf8 standard.
|
||||
By default, we support Gitea (:gitea:), to add more copy them to public/assets/img/emoji/emoji_name.png and
|
||||
add it to this config.
|
||||
@@ -427,7 +428,7 @@ The following configuration set `Content-Type: application/vnd.android.package-a
|
||||
## Database (`database`)
|
||||
|
||||
- `DB_TYPE`: **mysql**: The database type in use \[mysql, postgres, mssql, sqlite3\].
|
||||
- `HOST`: **127.0.0.1:3306**: Database host address and port or absolute path for unix socket \[mysql, postgres\] (ex: /var/run/mysqld/mysqld.sock).
|
||||
- `HOST`: **127.0.0.1:3306**: Database host address and port or absolute path for unix socket \[mysql, postgres[^1]\] (ex: /var/run/mysqld/mysqld.sock).
|
||||
- `NAME`: **gitea**: Database name.
|
||||
- `USER`: **root**: Database username.
|
||||
- `PASSWD`: **_empty_**: Database user password. Use \`your password\` or """your password""" for quoting if you use special characters in the password.
|
||||
@@ -458,6 +459,8 @@ The following configuration set `Content-Type: application/vnd.android.package-a
|
||||
- `CONN_MAX_LIFETIME` **0 or 3s**: Sets the maximum amount of time a DB connection may be reused - default is 0, meaning there is no limit (except on MySQL where it is 3s - see #6804 & #7071).
|
||||
- `AUTO_MIGRATION` **true**: Whether execute database models migrations automatically.
|
||||
|
||||
[^1]: It may be necessary to specify a hostport even when listening on a unix socket, as the port is part of the socket name. see [#24552](https://github.com/go-gitea/gitea/issues/24552#issuecomment-1681649367) for additional details.
|
||||
|
||||
Please see #8540 & #8273 for further discussion of the appropriate values for `MAX_OPEN_CONNS`, `MAX_IDLE_CONNS` & `CONN_MAX_LIFETIME` and their
|
||||
relation to port exhaustion.
|
||||
|
||||
|
||||
@@ -114,6 +114,12 @@ If you cannot see the settings page, please make sure that you have the right pe
|
||||
|
||||
The format of the registration token is a random string `D0gvfu2iHfUjNqCYVljVyRV14fISpJxxxxxxxxxx`.
|
||||
|
||||
A registration token can also be obtained from the gitea [command-line interface](../../administration/command-line.en-us.md#actions-generate-runner-token):
|
||||
|
||||
```
|
||||
gitea --config /etc/gitea/app.ini actions generate-runner-token
|
||||
```
|
||||
|
||||
### Register the runner
|
||||
|
||||
The act runner can be registered by running the following command:
|
||||
@@ -262,6 +268,40 @@ The runner will fetch jobs from the Gitea instance and run them automatically.
|
||||
|
||||
Since act runner is still in development, it is recommended to check the latest version and upgrade it regularly.
|
||||
|
||||
## Systemd service
|
||||
|
||||
It is also possible to run act-runner as a [systemd](https://en.wikipedia.org/wiki/Systemd) service. Create an unprivileged `act_runner` user on your system, and the following file in `/etc/systemd/system/act_runner.service`. The paths in `ExecStart` and `WorkingDirectory` may need to be adjusted depending on where you installed the `act_runner` binary, its configuration file, and the home directory of the `act_runner` user.
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=Gitea Actions runner
|
||||
Documentation=https://gitea.com/gitea/act_runner
|
||||
After=docker.service
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/local/bin/act_runner daemon --config /etc/act_runner/config.yaml
|
||||
ExecReload=/bin/kill -s HUP $MAINPID
|
||||
WorkingDirectory=/var/lib/act_runner
|
||||
TimeoutSec=0
|
||||
RestartSec=10
|
||||
Restart=always
|
||||
User=act_runner
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
Then:
|
||||
|
||||
```bash
|
||||
# load the new systemd unit file
|
||||
sudo systemctl daemon-reload
|
||||
# start the service and enable it at boot
|
||||
sudo systemctl enable act_runner --now
|
||||
```
|
||||
|
||||
If using Docker, the `act_runner` user should also be added to the `docker` group before starting the service. Keep in mind that this effectively gives `act_runner` root access to the system [[1]](https://docs.docker.com/engine/security/#docker-daemon-attack-surface).
|
||||
|
||||
## Configuration variable
|
||||
|
||||
You can create configuration variables on the user, organization and repository level.
|
||||
|
||||
@@ -113,6 +113,8 @@ Runner级别决定了从哪里获取注册令牌。
|
||||
|
||||
注册令牌的格式是一个随机字符串 `D0gvfu2iHfUjNqCYVljVyRV14fISpJxxxxxxxxxx`。
|
||||
|
||||
注册令牌也可以通过 Gitea 的 [命令行](../../administration/command-line.en-us.md#actions-generate-runner-token) 获得:
|
||||
|
||||
### 注册Runner
|
||||
|
||||
可以通过运行以下命令来注册Act Runner:
|
||||
|
||||
@@ -130,34 +130,3 @@ More details about the `[actions].DEFAULT_ACTIONS_URL` configuration can be foun
|
||||
|
||||
Context availability is not checked, so you can use the env context on more places.
|
||||
See [Context availability](https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability).
|
||||
|
||||
## Known issues
|
||||
|
||||
### `docker/build-push-action@v4`
|
||||
|
||||
See [act_runner#119](https://gitea.com/gitea/act_runner/issues/119#issuecomment-738294).
|
||||
|
||||
`ACTIONS_RUNTIME_TOKEN` is a random string in Gitea Actions, not a JWT.
|
||||
But the `docker/build-push-action@v4` tries to parse the token as JWT and doesn't handle the error, so the job fails.
|
||||
|
||||
There are two workarounds:
|
||||
|
||||
Set the `ACTIONS_RUNTIME_TOKEN` to empty manually, like:
|
||||
|
||||
``` yml
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
env:
|
||||
ACTIONS_RUNTIME_TOKEN: ''
|
||||
with:
|
||||
...
|
||||
```
|
||||
|
||||
The bug has been fixed in a newer [commit](https://gitea.com/docker/build-push-action/commit/d8823bfaed2a82c6f5d4799a2f8e86173c461aba?style=split&whitespace=show-all#diff-1af9a5bdf96ddff3a2f3427ed520b7005e9564ad), but it has not been released. So you could use the latest version by specifying the branch name, like:
|
||||
|
||||
``` yml
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@master
|
||||
with:
|
||||
...
|
||||
```
|
||||
|
||||
@@ -132,34 +132,3 @@ Gitea Actions目前不支持此功能。
|
||||
|
||||
不检查上下文可用性,因此您可以在更多地方使用env上下文。
|
||||
请参阅[上下文可用性](https://docs.github.com/en/actions/learn-github-actions/contexts#context-availability)。
|
||||
|
||||
## 已知问题
|
||||
|
||||
### `docker/build-push-action@v4`
|
||||
|
||||
请参阅[act_runner#119](https://gitea.com/gitea/act_runner/issues/119#issuecomment-738294)。
|
||||
|
||||
`ACTIONS_RUNTIME_TOKEN`在Gitea Actions中是一个随机字符串,而不是JWT。
|
||||
但是`DOCKER/BUILD-PUSH-ACTION@V4尝试将令牌解析为JWT,并且不处理错误,因此Job失败。
|
||||
|
||||
有两种解决方法:
|
||||
|
||||
手动将`ACTIONS_RUNTIME_TOKEN`设置为空字符串,例如:
|
||||
|
||||
``` yml
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
env:
|
||||
ACTIONS_RUNTIME_TOKEN: ''
|
||||
with:
|
||||
...
|
||||
```
|
||||
|
||||
该问题已在较新的[提交](https://gitea.com/docker/build-push-action/commit/d8823bfaed2a82c6f5d4799a2f8e86173c461aba?style=split&whitespace=show-all#diff-1af9a5bdf96ddff3a2f3427ed520b7005e9564ad)中修复,但尚未发布。因此,您可以通过指定分支名称来使用最新版本,例如:
|
||||
|
||||
``` yml
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@master
|
||||
with:
|
||||
...
|
||||
```
|
||||
|
||||
@@ -17,7 +17,7 @@ require (
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358
|
||||
github.com/NYTimes/gziphandler v1.1.1
|
||||
github.com/PuerkitoBio/goquery v1.8.1
|
||||
github.com/alecthomas/chroma/v2 v2.9.1
|
||||
github.com/alecthomas/chroma/v2 v2.10.0
|
||||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
|
||||
github.com/blevesearch/bleve/v2 v2.3.10
|
||||
github.com/bufbuild/connect-go v1.10.0
|
||||
@@ -36,7 +36,7 @@ require (
|
||||
github.com/ethantkoenig/rupture v1.0.1
|
||||
github.com/felixge/fgprof v0.9.3
|
||||
github.com/fsnotify/fsnotify v1.6.0
|
||||
github.com/gliderlabs/ssh v0.3.5
|
||||
github.com/gliderlabs/ssh v0.3.6-0.20230927171611-ece6c7995e46
|
||||
github.com/go-ap/activitypub v0.0.0-20231003111253-1fba3772399b
|
||||
github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73
|
||||
github.com/go-chi/chi/v5 v5.0.10
|
||||
@@ -121,7 +121,7 @@ require (
|
||||
mvdan.cc/xurls/v2 v2.5.0
|
||||
strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251
|
||||
xorm.io/builder v0.3.13
|
||||
xorm.io/xorm v1.3.4-0.20231017094142-dbe499091a7e
|
||||
xorm.io/xorm v1.3.4
|
||||
)
|
||||
|
||||
require (
|
||||
|
||||
@@ -118,8 +118,8 @@ github.com/acomagu/bufpipe v1.0.4/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ
|
||||
github.com/alecthomas/assert/v2 v2.2.1 h1:XivOgYcduV98QCahG8T5XTezV5bylXe+lBxLG2K2ink=
|
||||
github.com/alecthomas/assert/v2 v2.2.1/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ=
|
||||
github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs=
|
||||
github.com/alecthomas/chroma/v2 v2.9.1 h1:0O3lTQh9FxazJ4BYE/MOi/vDGuHn7B+6Bu902N2UZvU=
|
||||
github.com/alecthomas/chroma/v2 v2.9.1/go.mod h1:4TQu7gdfuPjSh76j78ietmqh9LiurGF0EpseFXdKMBw=
|
||||
github.com/alecthomas/chroma/v2 v2.10.0 h1:T2iQOCCt4pRmRMfL55gTodMtc7cU0y7lc1Jb8/mK/64=
|
||||
github.com/alecthomas/chroma/v2 v2.10.0/go.mod h1:4TQu7gdfuPjSh76j78ietmqh9LiurGF0EpseFXdKMBw=
|
||||
github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
|
||||
github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk=
|
||||
github.com/alecthomas/repr v0.2.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
||||
@@ -329,8 +329,8 @@ github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4
|
||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
github.com/fxamacker/cbor/v2 v2.5.0 h1:oHsG0V/Q6E/wqTS2O1Cozzsy69nqCiguo5Q1a1ADivE=
|
||||
github.com/fxamacker/cbor/v2 v2.5.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo=
|
||||
github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY=
|
||||
github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4=
|
||||
github.com/gliderlabs/ssh v0.3.6-0.20230927171611-ece6c7995e46 h1:fYiA820jw7wmAvdXrHwMItxjJkra7dT9y8yiXhtzb94=
|
||||
github.com/gliderlabs/ssh v0.3.6-0.20230927171611-ece6c7995e46/go.mod h1:i/TCLcdiX9Up/vs+Rp8c3yMbqp2Y4Y7Nh9uzGFCa5pM=
|
||||
github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE=
|
||||
github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24=
|
||||
github.com/go-ap/activitypub v0.0.0-20231003111253-1fba3772399b h1:VLD6IPBDkqEsOZ+EfLO6MayuHycZ0cv4BStTlRoZduo=
|
||||
@@ -1237,7 +1237,6 @@ golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qx
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
@@ -1337,9 +1336,7 @@ golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@@ -1353,7 +1350,6 @@ golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-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-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||
@@ -1648,5 +1644,5 @@ strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251/go.mod h1:
|
||||
xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
||||
xorm.io/builder v0.3.13 h1:a3jmiVVL19psGeXx8GIurTp7p0IIgqeDmwhcR6BAOAo=
|
||||
xorm.io/builder v0.3.13/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
||||
xorm.io/xorm v1.3.4-0.20231017094142-dbe499091a7e h1:oL+ktEW+iSrCXU6IauJ9csZFATEmawkhsq/MAoHTdwo=
|
||||
xorm.io/xorm v1.3.4-0.20231017094142-dbe499091a7e/go.mod h1:qFJGFoVYbbIdnz2vaL5OxSQ2raleMpyRRalnq3n9OJo=
|
||||
xorm.io/xorm v1.3.4 h1:vWFKzR3DhGUDl5b4srhUjhDwjxkZAc4C7BFszpu0swI=
|
||||
xorm.io/xorm v1.3.4/go.mod h1:qFJGFoVYbbIdnz2vaL5OxSQ2raleMpyRRalnq3n9OJo=
|
||||
|
||||
@@ -266,3 +266,27 @@ func CreateRunner(ctx context.Context, t *ActionRunner) error {
|
||||
_, err := db.GetEngine(ctx).Insert(t)
|
||||
return err
|
||||
}
|
||||
|
||||
func CountRunnersWithoutBelongingOwner(ctx context.Context) (int64, error) {
|
||||
// Only affect action runners were a owner ID is set, as actions runners
|
||||
// could also be created on a repository.
|
||||
return db.GetEngine(ctx).Table("action_runner").
|
||||
Join("LEFT", "user", "`action_runner`.owner_id = `user`.id").
|
||||
Where("`action_runner`.owner_id != ?", 0).
|
||||
And(builder.IsNull{"`user`.id"}).
|
||||
Count(new(ActionRunner))
|
||||
}
|
||||
|
||||
func FixRunnersWithoutBelongingOwner(ctx context.Context) (int64, error) {
|
||||
subQuery := builder.Select("`action_runner`.id").
|
||||
From("`action_runner`").
|
||||
Join("LEFT", "user", "`action_runner`.owner_id = `user`.id").
|
||||
Where(builder.Neq{"`action_runner`.owner_id": 0}).
|
||||
And(builder.IsNull{"`user`.id"})
|
||||
b := builder.Delete(builder.In("id", subQuery)).From("`action_runner`")
|
||||
res, err := db.GetEngine(ctx).Exec(b)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return res.RowsAffected()
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ func GetStatistic(ctx context.Context) (stats Statistic) {
|
||||
stats.Counter.Follow, _ = e.Count(new(user_model.Follow))
|
||||
stats.Counter.Mirror, _ = e.Count(new(repo_model.Mirror))
|
||||
stats.Counter.Release, _ = e.Count(new(repo_model.Release))
|
||||
stats.Counter.AuthSource = auth.CountSources(ctx)
|
||||
stats.Counter.AuthSource = auth.CountSources(ctx, auth.FindSourcesOptions{})
|
||||
stats.Counter.Webhook, _ = e.Count(new(webhook.Webhook))
|
||||
stats.Counter.Milestone, _ = e.Count(new(issues_model.Milestone))
|
||||
stats.Counter.Label, _ = e.Count(new(issues_model.Label))
|
||||
|
||||
@@ -631,15 +631,6 @@ func (err ErrOAuthApplicationNotFound) Unwrap() error {
|
||||
return util.ErrNotExist
|
||||
}
|
||||
|
||||
// GetActiveOAuth2ProviderSources returns all actived LoginOAuth2 sources
|
||||
func GetActiveOAuth2ProviderSources(ctx context.Context) ([]*Source, error) {
|
||||
sources := make([]*Source, 0, 1)
|
||||
if err := db.GetEngine(ctx).Where("is_active = ? and type = ?", true, OAuth2).Find(&sources); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return sources, nil
|
||||
}
|
||||
|
||||
// GetActiveOAuth2SourceByName returns a OAuth2 AuthSource based on the given name
|
||||
func GetActiveOAuth2SourceByName(ctx context.Context, name string) (*Source, error) {
|
||||
authSource := new(Source)
|
||||
|
||||
+26
-33
@@ -14,6 +14,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"xorm.io/builder"
|
||||
"xorm.io/xorm"
|
||||
"xorm.io/xorm/convert"
|
||||
)
|
||||
@@ -240,37 +241,26 @@ func CreateSource(ctx context.Context, source *Source) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// Sources returns a slice of all login sources found in DB.
|
||||
func Sources(ctx context.Context) ([]*Source, error) {
|
||||
type FindSourcesOptions struct {
|
||||
IsActive util.OptionalBool
|
||||
LoginType Type
|
||||
}
|
||||
|
||||
func (opts FindSourcesOptions) ToConds() builder.Cond {
|
||||
conds := builder.NewCond()
|
||||
if !opts.IsActive.IsNone() {
|
||||
conds = conds.And(builder.Eq{"is_active": opts.IsActive.IsTrue()})
|
||||
}
|
||||
if opts.LoginType != NoType {
|
||||
conds = conds.And(builder.Eq{"`type`": opts.LoginType})
|
||||
}
|
||||
return conds
|
||||
}
|
||||
|
||||
// FindSources returns a slice of login sources found in DB according to given conditions.
|
||||
func FindSources(ctx context.Context, opts FindSourcesOptions) ([]*Source, error) {
|
||||
auths := make([]*Source, 0, 6)
|
||||
return auths, db.GetEngine(ctx).Find(&auths)
|
||||
}
|
||||
|
||||
// SourcesByType returns all sources of the specified type
|
||||
func SourcesByType(ctx context.Context, loginType Type) ([]*Source, error) {
|
||||
sources := make([]*Source, 0, 1)
|
||||
if err := db.GetEngine(ctx).Where("type = ?", loginType).Find(&sources); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return sources, nil
|
||||
}
|
||||
|
||||
// AllActiveSources returns all active sources
|
||||
func AllActiveSources(ctx context.Context) ([]*Source, error) {
|
||||
sources := make([]*Source, 0, 5)
|
||||
if err := db.GetEngine(ctx).Where("is_active = ?", true).Find(&sources); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return sources, nil
|
||||
}
|
||||
|
||||
// ActiveSources returns all active sources of the specified type
|
||||
func ActiveSources(ctx context.Context, tp Type) ([]*Source, error) {
|
||||
sources := make([]*Source, 0, 1)
|
||||
if err := db.GetEngine(ctx).Where("is_active = ? and type = ?", true, tp).Find(&sources); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return sources, nil
|
||||
return auths, db.GetEngine(ctx).Where(opts.ToConds()).Find(&auths)
|
||||
}
|
||||
|
||||
// IsSSPIEnabled returns true if there is at least one activated login
|
||||
@@ -279,7 +269,10 @@ func IsSSPIEnabled(ctx context.Context) bool {
|
||||
if !db.HasEngine {
|
||||
return false
|
||||
}
|
||||
sources, err := ActiveSources(ctx, SSPI)
|
||||
sources, err := FindSources(ctx, FindSourcesOptions{
|
||||
IsActive: util.OptionalBoolTrue,
|
||||
LoginType: SSPI,
|
||||
})
|
||||
if err != nil {
|
||||
log.Error("ActiveSources: %v", err)
|
||||
return false
|
||||
@@ -354,8 +347,8 @@ func UpdateSource(ctx context.Context, source *Source) error {
|
||||
}
|
||||
|
||||
// CountSources returns number of login sources.
|
||||
func CountSources(ctx context.Context) int64 {
|
||||
count, _ := db.GetEngine(ctx).Count(new(Source))
|
||||
func CountSources(ctx context.Context, opts FindSourcesOptions) int64 {
|
||||
count, _ := db.GetEngine(ctx).Where(opts.ToConds()).Count(new(Source))
|
||||
return count
|
||||
}
|
||||
|
||||
|
||||
@@ -235,7 +235,7 @@ func GetCommitStatuses(ctx context.Context, repo *repo_model.Repository, sha str
|
||||
|
||||
countSession := listCommitStatusesStatement(ctx, repo, sha, opts)
|
||||
countSession = db.SetSessionPagination(countSession, opts)
|
||||
maxResults, err := countSession.OrderBy("1").Count(new(CommitStatus))
|
||||
maxResults, err := countSession.Count(new(CommitStatus))
|
||||
if err != nil {
|
||||
log.Error("Count PRs: %v", err)
|
||||
return nil, maxResults, err
|
||||
|
||||
+2
-10
@@ -142,22 +142,14 @@ type Issue struct {
|
||||
}
|
||||
|
||||
var (
|
||||
issueTasksPat *regexp.Regexp
|
||||
issueTasksDonePat *regexp.Regexp
|
||||
)
|
||||
|
||||
const (
|
||||
issueTasksRegexpStr = `(^\s*[-*]\s\[[\sxX]\]\s.)|(\n\s*[-*]\s\[[\sxX]\]\s.)`
|
||||
issueTasksDoneRegexpStr = `(^\s*[-*]\s\[[xX]\]\s.)|(\n\s*[-*]\s\[[xX]\]\s.)`
|
||||
issueTasksPat = regexp.MustCompile(`(^\s*[-*]\s\[[\sxX]\]\s.)|(\n\s*[-*]\s\[[\sxX]\]\s.)`)
|
||||
issueTasksDonePat = regexp.MustCompile(`(^\s*[-*]\s\[[xX]\]\s.)|(\n\s*[-*]\s\[[xX]\]\s.)`)
|
||||
)
|
||||
|
||||
// IssueIndex represents the issue index table
|
||||
type IssueIndex db.ResourceIndex
|
||||
|
||||
func init() {
|
||||
issueTasksPat = regexp.MustCompile(issueTasksRegexpStr)
|
||||
issueTasksDonePat = regexp.MustCompile(issueTasksDoneRegexpStr)
|
||||
|
||||
db.RegisterModel(new(Issue))
|
||||
db.RegisterModel(new(IssueIndex))
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@ func applyProjectBoardCondition(sess *xorm.Session, opts *IssuesOptions) *xorm.S
|
||||
if opts.ProjectBoardID > 0 {
|
||||
sess.In("issue.id", builder.Select("issue_id").From("project_issue").Where(builder.Eq{"project_board_id": opts.ProjectBoardID}))
|
||||
} else if opts.ProjectBoardID == db.NoConditionID {
|
||||
sess.In("issue.id", builder.Select("issue_id").From("project_issue").Where(builder.Neq{"project_board_id": 0}))
|
||||
sess.In("issue.id", builder.Select("issue_id").From("project_issue").Where(builder.Eq{"project_board_id": 0}))
|
||||
}
|
||||
return sess
|
||||
}
|
||||
|
||||
@@ -897,6 +897,16 @@ func DeleteReview(ctx context.Context, r *Review) error {
|
||||
return err
|
||||
}
|
||||
|
||||
opts = FindCommentsOptions{
|
||||
Type: CommentTypeDismissReview,
|
||||
IssueID: r.IssueID,
|
||||
ReviewID: r.ID,
|
||||
}
|
||||
|
||||
if _, err := sess.Where(opts.ToConds()).Delete(new(Comment)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := sess.ID(r.ID).Delete(new(Review)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
|
||||
"code.gitea.io/gitea/models/db"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
|
||||
@@ -258,3 +259,32 @@ func TestDeleteReview(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, review1.Official)
|
||||
}
|
||||
|
||||
func TestDeleteDismissedReview(t *testing.T) {
|
||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||
|
||||
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2})
|
||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1})
|
||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: issue.RepoID})
|
||||
review, err := issues_model.CreateReview(db.DefaultContext, issues_model.CreateReviewOptions{
|
||||
Content: "reject",
|
||||
Type: issues_model.ReviewTypeReject,
|
||||
Official: false,
|
||||
Issue: issue,
|
||||
Reviewer: user,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, issues_model.DismissReview(db.DefaultContext, review, true))
|
||||
comment, err := issues_model.CreateComment(db.DefaultContext, &issues_model.CreateCommentOptions{
|
||||
Type: issues_model.CommentTypeDismissReview,
|
||||
Doer: user,
|
||||
Repo: repo,
|
||||
Issue: issue,
|
||||
ReviewID: review.ID,
|
||||
Content: "dismiss",
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
unittest.AssertExistsAndLoadBean(t, &issues_model.Comment{ID: comment.ID})
|
||||
assert.NoError(t, issues_model.DeleteReview(db.DefaultContext, review))
|
||||
unittest.AssertNotExistsBean(t, &issues_model.Comment{ID: comment.ID})
|
||||
}
|
||||
|
||||
@@ -548,6 +548,8 @@ var migrations = []Migration{
|
||||
NewMigration("Rename user themes", v1_22.RenameUserThemes),
|
||||
// v281 -> v282
|
||||
NewMigration("Add auth_token table", v1_22.CreateAuthTokenTable),
|
||||
// v282 -> v283
|
||||
NewMigration("Add Index to pull_auto_merge.doer_id", v1_22.AddIndexToPullAutoMergeDoerID),
|
||||
// to modify later
|
||||
NewMigration("Add size limit on repository", v1_22.AddSizeLimitOnRepo),
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v1_22 //nolint
|
||||
|
||||
import (
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
func AddIndexToPullAutoMergeDoerID(x *xorm.Engine) error {
|
||||
type PullAutoMerge struct {
|
||||
DoerID int64 `xorm:"INDEX NOT NULL"`
|
||||
}
|
||||
|
||||
return x.Sync(&PullAutoMerge{})
|
||||
}
|
||||
+11
-19
@@ -14,12 +14,11 @@ import (
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
)
|
||||
|
||||
func removeOrgUser(ctx context.Context, orgID, userID int64) error {
|
||||
// RemoveOrgUser removes user from given organization.
|
||||
func RemoveOrgUser(ctx context.Context, orgID, userID int64) error {
|
||||
ou := new(organization.OrgUser)
|
||||
|
||||
sess := db.GetEngine(ctx)
|
||||
|
||||
has, err := sess.
|
||||
has, err := db.GetEngine(ctx).
|
||||
Where("uid=?", userID).
|
||||
And("org_id=?", orgID).
|
||||
Get(ou)
|
||||
@@ -52,7 +51,13 @@ func removeOrgUser(ctx context.Context, orgID, userID int64) error {
|
||||
}
|
||||
}
|
||||
|
||||
if _, err := sess.ID(ou.ID).Delete(ou); err != nil {
|
||||
ctx, committer, err := db.TxContext(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer committer.Close()
|
||||
|
||||
if _, err := db.GetEngine(ctx).ID(ou.ID).Delete(ou); err != nil {
|
||||
return err
|
||||
} else if _, err = db.Exec(ctx, "UPDATE `user` SET num_members=num_members-1 WHERE id=?", orgID); err != nil {
|
||||
return err
|
||||
@@ -74,7 +79,7 @@ func removeOrgUser(ctx context.Context, orgID, userID int64) error {
|
||||
}
|
||||
|
||||
if len(repoIDs) > 0 {
|
||||
if _, err = sess.
|
||||
if _, err = db.GetEngine(ctx).
|
||||
Where("user_id = ?", userID).
|
||||
In("repo_id", repoIDs).
|
||||
Delete(new(access_model.Access)); err != nil {
|
||||
@@ -93,18 +98,5 @@ func removeOrgUser(ctx context.Context, orgID, userID int64) error {
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveOrgUser removes user from given organization.
|
||||
func RemoveOrgUser(ctx context.Context, orgID, userID int64) error {
|
||||
ctx, committer, err := db.TxContext(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer committer.Close()
|
||||
if err := removeOrgUser(ctx, orgID, userID); err != nil {
|
||||
return err
|
||||
}
|
||||
return committer.Commit()
|
||||
}
|
||||
|
||||
+1
-1
@@ -502,7 +502,7 @@ func removeInvalidOrgUser(ctx context.Context, userID, orgID int64) error {
|
||||
}); err != nil {
|
||||
return err
|
||||
} else if count == 0 {
|
||||
return removeOrgUser(ctx, orgID, userID)
|
||||
return RemoveOrgUser(ctx, orgID, userID)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -207,6 +207,9 @@ func (opts *ImageTagsSearchOptions) configureOrderBy(e db.Engine) {
|
||||
default:
|
||||
e.Desc("package_version.created_unix")
|
||||
}
|
||||
|
||||
// Sort by id for stable order with duplicates in the other field
|
||||
e.Asc("package_version.id")
|
||||
}
|
||||
|
||||
// SearchImageTags gets a sorted list of the tags of an image
|
||||
|
||||
@@ -21,8 +21,7 @@ type PackageSearchOptions struct {
|
||||
Architecture string
|
||||
}
|
||||
|
||||
// SearchLatestPackages gets the latest packages matching the search options
|
||||
func SearchLatestPackages(ctx context.Context, opts *PackageSearchOptions) ([]*packages.PackageFileDescriptor, error) {
|
||||
func (opts *PackageSearchOptions) toCond() builder.Cond {
|
||||
var cond builder.Cond = builder.Eq{
|
||||
"package_file.is_lead": true,
|
||||
"package.type": packages.TypeDebian,
|
||||
@@ -62,28 +61,40 @@ func SearchLatestPackages(ctx context.Context, opts *PackageSearchOptions) ([]*p
|
||||
})
|
||||
}
|
||||
|
||||
cond = cond.
|
||||
And(builder.Expr("pv2.id IS NULL"))
|
||||
return cond
|
||||
}
|
||||
|
||||
joinCond := builder.
|
||||
Expr("package_version.package_id = pv2.package_id AND (package_version.created_unix < pv2.created_unix OR (package_version.created_unix = pv2.created_unix AND package_version.id < pv2.id))").
|
||||
And(builder.Eq{"pv2.is_internal": false})
|
||||
// ExistPackages tests if there are packages matching the search options
|
||||
func ExistPackages(ctx context.Context, opts *PackageSearchOptions) (bool, error) {
|
||||
return db.GetEngine(ctx).
|
||||
Table("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()).
|
||||
Exist(new(packages.PackageFile))
|
||||
}
|
||||
|
||||
pfs := make([]*packages.PackageFile, 0, 10)
|
||||
err := db.GetEngine(ctx).
|
||||
// SearchPackages gets the packages matching the search options
|
||||
func SearchPackages(ctx context.Context, opts *PackageSearchOptions, iter func(*packages.PackageFileDescriptor)) error {
|
||||
return db.GetEngine(ctx).
|
||||
Table("package_file").
|
||||
Select("package_file.*").
|
||||
Join("INNER", "package_version", "package_version.id = package_file.version_id").
|
||||
Join("LEFT", "package_version pv2", joinCond).
|
||||
Join("INNER", "package", "package.id = package_version.package_id").
|
||||
Where(cond).
|
||||
Desc("package_version.created_unix").
|
||||
Find(&pfs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
Where(opts.toCond()).
|
||||
Asc("package.lower_name", "package_version.created_unix").
|
||||
Iterate(new(packages.PackageFile), func(_ int, bean any) error {
|
||||
pf := bean.(*packages.PackageFile)
|
||||
|
||||
return packages.GetPackageFileDescriptors(ctx, pfs)
|
||||
pfd, err := packages.GetPackageFileDescriptor(ctx, pf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
iter(pfd)
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// GetDistributions gets all available distributions
|
||||
|
||||
@@ -278,6 +278,9 @@ func (opts *PackageSearchOptions) configureOrderBy(e db.Engine) {
|
||||
default:
|
||||
e.Desc("package_version.created_unix")
|
||||
}
|
||||
|
||||
// Sort by id for stable order with duplicates in the other field
|
||||
e.Asc("package_version.id")
|
||||
}
|
||||
|
||||
// SearchVersions gets all versions of packages matching the search options
|
||||
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
type AutoMerge struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
PullID int64 `xorm:"UNIQUE"`
|
||||
DoerID int64 `xorm:"NOT NULL"`
|
||||
DoerID int64 `xorm:"INDEX NOT NULL"`
|
||||
Doer *user_model.User `xorm:"-"`
|
||||
MergeStyle repo_model.MergeStyle `xorm:"varchar(30)"`
|
||||
Message string `xorm:"LONGTEXT"`
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"code.gitea.io/gitea/models/auth"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unit"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
@@ -211,32 +210,6 @@ func (ctx *APIContext) SetLinkHeader(total, pageSize int) {
|
||||
}
|
||||
}
|
||||
|
||||
// CheckForOTP validates OTP
|
||||
func (ctx *APIContext) CheckForOTP() {
|
||||
if skip, ok := ctx.Data["SkipLocalTwoFA"]; ok && skip.(bool) {
|
||||
return // Skip 2FA
|
||||
}
|
||||
|
||||
otpHeader := ctx.Req.Header.Get("X-Gitea-OTP")
|
||||
twofa, err := auth.GetTwoFactorByUID(ctx, ctx.Doer.ID)
|
||||
if err != nil {
|
||||
if auth.IsErrTwoFactorNotEnrolled(err) {
|
||||
return // No 2FA enrollment for this user
|
||||
}
|
||||
ctx.Error(http.StatusInternalServerError, "GetTwoFactorByUID", err)
|
||||
return
|
||||
}
|
||||
ok, err := twofa.ValidateTOTP(otpHeader)
|
||||
if err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "ValidateTOTP", err)
|
||||
return
|
||||
}
|
||||
if !ok {
|
||||
ctx.Error(http.StatusUnauthorized, "", nil)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// APIContexter returns apicontext as middleware
|
||||
func APIContexter() func(http.Handler) http.Handler {
|
||||
return func(next http.Handler) http.Handler {
|
||||
|
||||
@@ -157,7 +157,6 @@ func Contexter() func(next http.Handler) http.Handler {
|
||||
ctx.Data["Context"] = ctx // TODO: use "ctx" in template and remove this
|
||||
ctx.Data["CurrentURL"] = setting.AppSubURL + req.URL.RequestURI()
|
||||
ctx.Data["Link"] = ctx.Link
|
||||
ctx.Data["locale"] = ctx.Locale
|
||||
|
||||
// PageData is passed by reference, and it will be rendered to `window.config.pageData` in `head.tmpl` for JavaScript modules
|
||||
ctx.PageData = map[string]any{}
|
||||
|
||||
@@ -6,6 +6,7 @@ package doctor
|
||||
import (
|
||||
"context"
|
||||
|
||||
actions_model "code.gitea.io/gitea/models/actions"
|
||||
activities_model "code.gitea.io/gitea/models/activities"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
@@ -151,6 +152,12 @@ func checkDBConsistency(ctx context.Context, logger log.Logger, autofix bool) er
|
||||
Fixer: activities_model.FixActionCreatedUnixString,
|
||||
FixedMessage: "Set to zero",
|
||||
},
|
||||
{
|
||||
Name: "Action Runners without existing owner",
|
||||
Counter: actions_model.CountRunnersWithoutBelongingOwner,
|
||||
Fixer: actions_model.FixRunnersWithoutBelongingOwner,
|
||||
FixedMessage: "Removed",
|
||||
},
|
||||
}
|
||||
|
||||
// TODO: function to recalc all counters
|
||||
|
||||
@@ -382,6 +382,12 @@ func searchIssueInProject(t *testing.T) {
|
||||
},
|
||||
[]int64{1},
|
||||
},
|
||||
{
|
||||
SearchOptions{
|
||||
ProjectBoardID: int64Pointer(0), // issue with in default board
|
||||
},
|
||||
[]int64{2},
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
issueIDs, _, err := SearchIssues(context.TODO(), &test.opts)
|
||||
|
||||
@@ -32,7 +32,7 @@ func NewHashedBuffer() (*HashedBuffer, error) {
|
||||
return NewHashedBufferWithSize(DefaultMemorySize)
|
||||
}
|
||||
|
||||
// NewHashedBuffer creates a hashed buffer with a specific memory size
|
||||
// NewHashedBufferWithSize creates a hashed buffer with a specific memory size
|
||||
func NewHashedBufferWithSize(maxMemorySize int) (*HashedBuffer, error) {
|
||||
b, err := filebuffer.New(maxMemorySize)
|
||||
if err != nil {
|
||||
|
||||
+26
-14
@@ -6,6 +6,7 @@ package setting
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
@@ -135,15 +136,18 @@ func DBConnStr() (string, error) {
|
||||
// parsePostgreSQLHostPort parses given input in various forms defined in
|
||||
// https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING
|
||||
// and returns proper host and port number.
|
||||
func parsePostgreSQLHostPort(info string) (string, string) {
|
||||
host, port := "127.0.0.1", "5432"
|
||||
if strings.Contains(info, ":") && !strings.HasSuffix(info, "]") {
|
||||
idx := strings.LastIndex(info, ":")
|
||||
host = info[:idx]
|
||||
port = info[idx+1:]
|
||||
} else if len(info) > 0 {
|
||||
func parsePostgreSQLHostPort(info string) (host, port string) {
|
||||
if h, p, err := net.SplitHostPort(info); err == nil {
|
||||
host, port = h, p
|
||||
} else {
|
||||
// treat the "info" as "host", if it's an IPv6 address, remove the wrapper
|
||||
host = info
|
||||
if strings.HasPrefix(host, "[") && strings.HasSuffix(host, "]") {
|
||||
host = host[1 : len(host)-1]
|
||||
}
|
||||
}
|
||||
|
||||
// set fallback values
|
||||
if host == "" {
|
||||
host = "127.0.0.1"
|
||||
}
|
||||
@@ -155,14 +159,22 @@ func parsePostgreSQLHostPort(info string) (string, string) {
|
||||
|
||||
func getPostgreSQLConnectionString(dbHost, dbUser, dbPasswd, dbName, dbParam, dbsslMode string) (connStr string) {
|
||||
host, port := parsePostgreSQLHostPort(dbHost)
|
||||
if host[0] == '/' { // looks like a unix socket
|
||||
connStr = fmt.Sprintf("postgres://%s:%s@:%s/%s%ssslmode=%s&host=%s",
|
||||
url.PathEscape(dbUser), url.PathEscape(dbPasswd), port, dbName, dbParam, dbsslMode, host)
|
||||
} else {
|
||||
connStr = fmt.Sprintf("postgres://%s:%s@%s:%s/%s%ssslmode=%s",
|
||||
url.PathEscape(dbUser), url.PathEscape(dbPasswd), host, port, dbName, dbParam, dbsslMode)
|
||||
connURL := url.URL{
|
||||
Scheme: "postgres",
|
||||
User: url.UserPassword(dbUser, dbPasswd),
|
||||
Host: net.JoinHostPort(host, port),
|
||||
Path: dbName,
|
||||
OmitHost: false,
|
||||
RawQuery: dbParam,
|
||||
}
|
||||
return connStr
|
||||
query := connURL.Query()
|
||||
if dbHost[0] == '/' { // looks like a unix socket
|
||||
query.Add("host", dbHost)
|
||||
connURL.Host = ":" + port
|
||||
}
|
||||
query.Set("sslmode", dbsslMode)
|
||||
connURL.RawQuery = query.Encode()
|
||||
return connURL.String()
|
||||
}
|
||||
|
||||
// ParseMSSQLHostPort splits the host into host and port
|
||||
|
||||
@@ -10,46 +10,49 @@ import (
|
||||
)
|
||||
|
||||
func Test_parsePostgreSQLHostPort(t *testing.T) {
|
||||
tests := []struct {
|
||||
tests := map[string]struct {
|
||||
HostPort string
|
||||
Host string
|
||||
Port string
|
||||
}{
|
||||
{
|
||||
"host-port": {
|
||||
HostPort: "127.0.0.1:1234",
|
||||
Host: "127.0.0.1",
|
||||
Port: "1234",
|
||||
},
|
||||
{
|
||||
"no-port": {
|
||||
HostPort: "127.0.0.1",
|
||||
Host: "127.0.0.1",
|
||||
Port: "5432",
|
||||
},
|
||||
{
|
||||
"ipv6-port": {
|
||||
HostPort: "[::1]:1234",
|
||||
Host: "[::1]",
|
||||
Host: "::1",
|
||||
Port: "1234",
|
||||
},
|
||||
{
|
||||
"ipv6-no-port": {
|
||||
HostPort: "[::1]",
|
||||
Host: "[::1]",
|
||||
Host: "::1",
|
||||
Port: "5432",
|
||||
},
|
||||
{
|
||||
"unix-socket": {
|
||||
HostPort: "/tmp/pg.sock:1234",
|
||||
Host: "/tmp/pg.sock",
|
||||
Port: "1234",
|
||||
},
|
||||
{
|
||||
"unix-socket-no-port": {
|
||||
HostPort: "/tmp/pg.sock",
|
||||
Host: "/tmp/pg.sock",
|
||||
Port: "5432",
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
host, port := parsePostgreSQLHostPort(test.HostPort)
|
||||
assert.Equal(t, test.Host, host)
|
||||
assert.Equal(t, test.Port, port)
|
||||
for k, test := range tests {
|
||||
t.Run(k, func(t *testing.T) {
|
||||
t.Log(test.HostPort)
|
||||
host, port := parsePostgreSQLHostPort(test.HostPort)
|
||||
assert.Equal(t, test.Host, host)
|
||||
assert.Equal(t, test.Port, port)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,7 +75,7 @@ func Test_getPostgreSQLConnectionString(t *testing.T) {
|
||||
Name: "gitea",
|
||||
Param: "",
|
||||
SSLMode: "false",
|
||||
Output: "postgres://testuser:space%20space%20%21%23$%25%5E%5E%25%5E%60%60%60-=%3F=@:5432/giteasslmode=false&host=/tmp/pg.sock",
|
||||
Output: "postgres://testuser:space%20space%20%21%23$%25%5E%5E%25%5E%60%60%60-=%3F=@:5432/gitea?host=%2Ftmp%2Fpg.sock&sslmode=false",
|
||||
},
|
||||
{
|
||||
Host: "localhost",
|
||||
@@ -82,7 +85,7 @@ func Test_getPostgreSQLConnectionString(t *testing.T) {
|
||||
Name: "gitea",
|
||||
Param: "",
|
||||
SSLMode: "true",
|
||||
Output: "postgres://pgsqlusername:I%20love%20Gitea%21@localhost:5432/giteasslmode=true",
|
||||
Output: "postgres://pgsqlusername:I%20love%20Gitea%21@localhost:5432/gitea?sslmode=true",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// StorageType is a type of Storage
|
||||
@@ -249,14 +250,24 @@ func getStorageForMinio(targetSec, overrideSec ConfigSection, tp targetSecType,
|
||||
return nil, fmt.Errorf("map minio config failed: %v", err)
|
||||
}
|
||||
|
||||
if storage.MinioConfig.BasePath == "" {
|
||||
storage.MinioConfig.BasePath = name + "/"
|
||||
var defaultPath string
|
||||
if storage.MinioConfig.BasePath != "" {
|
||||
if tp == targetSecIsStorage || tp == targetSecIsDefault {
|
||||
defaultPath = strings.TrimSuffix(storage.MinioConfig.BasePath, "/") + "/" + name + "/"
|
||||
} else {
|
||||
defaultPath = storage.MinioConfig.BasePath
|
||||
}
|
||||
}
|
||||
if defaultPath == "" {
|
||||
defaultPath = name + "/"
|
||||
}
|
||||
|
||||
if overrideSec != nil {
|
||||
storage.MinioConfig.ServeDirect = ConfigSectionKeyBool(overrideSec, "SERVE_DIRECT", storage.MinioConfig.ServeDirect)
|
||||
storage.MinioConfig.BasePath = ConfigSectionKeyString(overrideSec, "MINIO_BASE_PATH", storage.MinioConfig.BasePath)
|
||||
storage.MinioConfig.BasePath = ConfigSectionKeyString(overrideSec, "MINIO_BASE_PATH", defaultPath)
|
||||
storage.MinioConfig.Bucket = ConfigSectionKeyString(overrideSec, "MINIO_BUCKET", storage.MinioConfig.Bucket)
|
||||
} else {
|
||||
storage.MinioConfig.BasePath = defaultPath
|
||||
}
|
||||
return &storage, nil
|
||||
}
|
||||
|
||||
@@ -412,3 +412,56 @@ MINIO_USE_SSL = true
|
||||
assert.EqualValues(t, true, RepoArchive.Storage.MinioConfig.UseSSL)
|
||||
assert.EqualValues(t, "repo-archive/", RepoArchive.Storage.MinioConfig.BasePath)
|
||||
}
|
||||
|
||||
func Test_getStorageConfiguration28(t *testing.T) {
|
||||
cfg, err := NewConfigProviderFromData(`
|
||||
[storage]
|
||||
STORAGE_TYPE = minio
|
||||
MINIO_ACCESS_KEY_ID = my_access_key
|
||||
MINIO_SECRET_ACCESS_KEY = my_secret_key
|
||||
MINIO_USE_SSL = true
|
||||
MINIO_BASE_PATH = /prefix
|
||||
`)
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, loadRepoArchiveFrom(cfg))
|
||||
assert.EqualValues(t, "my_access_key", RepoArchive.Storage.MinioConfig.AccessKeyID)
|
||||
assert.EqualValues(t, "my_secret_key", RepoArchive.Storage.MinioConfig.SecretAccessKey)
|
||||
assert.EqualValues(t, true, RepoArchive.Storage.MinioConfig.UseSSL)
|
||||
assert.EqualValues(t, "/prefix/repo-archive/", RepoArchive.Storage.MinioConfig.BasePath)
|
||||
|
||||
cfg, err = NewConfigProviderFromData(`
|
||||
[storage]
|
||||
STORAGE_TYPE = minio
|
||||
MINIO_ACCESS_KEY_ID = my_access_key
|
||||
MINIO_SECRET_ACCESS_KEY = my_secret_key
|
||||
MINIO_USE_SSL = true
|
||||
MINIO_BASE_PATH = /prefix
|
||||
|
||||
[lfs]
|
||||
MINIO_BASE_PATH = /lfs
|
||||
`)
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, loadLFSFrom(cfg))
|
||||
assert.EqualValues(t, "my_access_key", LFS.Storage.MinioConfig.AccessKeyID)
|
||||
assert.EqualValues(t, "my_secret_key", LFS.Storage.MinioConfig.SecretAccessKey)
|
||||
assert.EqualValues(t, true, LFS.Storage.MinioConfig.UseSSL)
|
||||
assert.EqualValues(t, "/lfs", LFS.Storage.MinioConfig.BasePath)
|
||||
|
||||
cfg, err = NewConfigProviderFromData(`
|
||||
[storage]
|
||||
STORAGE_TYPE = minio
|
||||
MINIO_ACCESS_KEY_ID = my_access_key
|
||||
MINIO_SECRET_ACCESS_KEY = my_secret_key
|
||||
MINIO_USE_SSL = true
|
||||
MINIO_BASE_PATH = /prefix
|
||||
|
||||
[storage.lfs]
|
||||
MINIO_BASE_PATH = /lfs
|
||||
`)
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, loadLFSFrom(cfg))
|
||||
assert.EqualValues(t, "my_access_key", LFS.Storage.MinioConfig.AccessKeyID)
|
||||
assert.EqualValues(t, "my_secret_key", LFS.Storage.MinioConfig.SecretAccessKey)
|
||||
assert.EqualValues(t, true, LFS.Storage.MinioConfig.UseSSL)
|
||||
assert.EqualValues(t, "/lfs", LFS.Storage.MinioConfig.BasePath)
|
||||
}
|
||||
|
||||
+2
-7
@@ -17,7 +17,6 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -165,10 +164,6 @@ func sessionHandler(session ssh.Session) {
|
||||
}
|
||||
|
||||
func publicKeyHandler(ctx ssh.Context, key ssh.PublicKey) bool {
|
||||
// FIXME: the "ssh.Context" is not thread-safe, so db operations should use the immutable parent "Context"
|
||||
// TODO: Remove after https://github.com/gliderlabs/ssh/pull/211
|
||||
parentCtx := reflect.ValueOf(ctx).Elem().FieldByName("Context").Interface().(context.Context)
|
||||
|
||||
if log.IsDebug() { // <- FingerprintSHA256 is kinda expensive so only calculate it if necessary
|
||||
log.Debug("Handle Public Key: Fingerprint: %s from %s", gossh.FingerprintSHA256(key), ctx.RemoteAddr())
|
||||
}
|
||||
@@ -200,7 +195,7 @@ func publicKeyHandler(ctx ssh.Context, key ssh.PublicKey) bool {
|
||||
// look for the exact principal
|
||||
principalLoop:
|
||||
for _, principal := range cert.ValidPrincipals {
|
||||
pkey, err := asymkey_model.SearchPublicKeyByContentExact(parentCtx, principal)
|
||||
pkey, err := asymkey_model.SearchPublicKeyByContentExact(ctx, principal)
|
||||
if err != nil {
|
||||
if asymkey_model.IsErrKeyNotExist(err) {
|
||||
log.Debug("Principal Rejected: %s Unknown Principal: %s", ctx.RemoteAddr(), principal)
|
||||
@@ -257,7 +252,7 @@ func publicKeyHandler(ctx ssh.Context, key ssh.PublicKey) bool {
|
||||
log.Debug("Handle Public Key: %s Fingerprint: %s is not a certificate", ctx.RemoteAddr(), gossh.FingerprintSHA256(key))
|
||||
}
|
||||
|
||||
pkey, err := asymkey_model.SearchPublicKeyByContent(parentCtx, strings.TrimSpace(string(gossh.MarshalAuthorizedKey(key))))
|
||||
pkey, err := asymkey_model.SearchPublicKeyByContent(ctx, strings.TrimSpace(string(gossh.MarshalAuthorizedKey(key))))
|
||||
if err != nil {
|
||||
if asymkey_model.IsErrKeyNotExist(err) {
|
||||
log.Warn("Unknown public key: %s from %s", gossh.FingerprintSHA256(key), ctx.RemoteAddr())
|
||||
|
||||
@@ -16,6 +16,7 @@ type Package struct {
|
||||
Type string `json:"type"`
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
HTMLURL string `json:"html_url"`
|
||||
// swagger:strfmt date-time
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
}
|
||||
|
||||
@@ -110,9 +110,6 @@ write = Write
|
||||
preview = Preview
|
||||
loading = Loading…
|
||||
|
||||
step1 = Step 1:
|
||||
step2 = Step 2:
|
||||
|
||||
error = Error
|
||||
error404 = The page you are trying to reach either <strong>does not exist</strong> or <strong>you are not authorized</strong> to view it.
|
||||
go_back = Go Back
|
||||
@@ -729,7 +726,7 @@ add_email_success = The new email address has been added.
|
||||
email_preference_set_success = Email preference has been set successfully.
|
||||
add_openid_success = The new OpenID address has been added.
|
||||
keep_email_private = Hide Email Address
|
||||
keep_email_private_popup = This will hide your email address from your profile, as well as when you make a pull request or edit a file using the web interface. Pushed commits will not be modified.
|
||||
keep_email_private_popup = This will hide your email address from your profile, as well as when you make a pull request or edit a file using the web interface. Pushed commits will not be modified. Use %s in commits to associate them with your account.
|
||||
openid_desc = OpenID lets you delegate authentication to an external provider.
|
||||
|
||||
manage_ssh_keys = Manage SSH Keys
|
||||
@@ -1792,6 +1789,8 @@ pulls.status_checks_failure = Some checks failed
|
||||
pulls.status_checks_error = Some checks reported errors
|
||||
pulls.status_checks_requested = Required
|
||||
pulls.status_checks_details = Details
|
||||
pulls.status_checks_hide_all = Hide all checks
|
||||
pulls.status_checks_show_all = Show all checks
|
||||
pulls.update_branch = Update branch by merge
|
||||
pulls.update_branch_rebase = Update branch by rebase
|
||||
pulls.update_branch_success = Branch update was successful
|
||||
@@ -1800,9 +1799,11 @@ pulls.outdated_with_base_branch = This branch is out-of-date with the base branc
|
||||
pulls.close = Close Pull Request
|
||||
pulls.closed_at = `closed this pull request <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
||||
pulls.reopened_at = `reopened this pull request <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
||||
pulls.merge_instruction_hint = `You can also view <a class="show-instruction">command line instructions</a>.`
|
||||
pulls.merge_instruction_step1_desc = From your project repository, check out a new branch and test the changes.
|
||||
pulls.merge_instruction_step2_desc = Merge the changes and update on Gitea.
|
||||
pulls.cmd_instruction_hint = `View <a class="show-instruction">command line instructions</a>.`
|
||||
pulls.cmd_instruction_checkout_title = Checkout
|
||||
pulls.cmd_instruction_checkout_desc = From your project repository, check out a new branch and test the changes.
|
||||
pulls.cmd_instruction_merge_title = Merge
|
||||
pulls.cmd_instruction_merge_desc = Merge the changes and update on Gitea.
|
||||
pulls.clear_merge_message = Clear merge message
|
||||
pulls.clear_merge_message_hint = Clearing the merge message will only remove the commit message content and keep generated git trailers such as "Co-Authored-By …".
|
||||
|
||||
@@ -2860,7 +2861,7 @@ emails.updated = Email updated
|
||||
emails.not_updated = Failed to update the requested email address: %v
|
||||
emails.duplicate_active = This email address is already active for a different user.
|
||||
emails.change_email_header = Update Email Properties
|
||||
emails.change_email_text = Are your sure you want to update this email address?
|
||||
emails.change_email_text = Are you sure you want to update this email address?
|
||||
|
||||
orgs.org_manage_panel = Organization Management
|
||||
orgs.name = Name
|
||||
@@ -3351,8 +3352,6 @@ alpine.repository.repositories = Repositories
|
||||
alpine.repository.architectures = Architectures
|
||||
cargo.registry = Setup this registry in the Cargo configuration file (for example <code>~/.cargo/config.toml</code>):
|
||||
cargo.install = To install the package using Cargo, run the following command:
|
||||
cargo.details.repository_site = Repository Site
|
||||
cargo.details.documentation_site = Documentation Site
|
||||
chef.registry = Setup this registry in your <code>~/.chef/config.rb</code> file:
|
||||
chef.install = To install the package, run the following command:
|
||||
composer.registry = Setup this registry in your <code>~/.composer/config.json</code> file:
|
||||
@@ -3364,8 +3363,6 @@ conan.registry = Setup this registry from the command line:
|
||||
conan.install = To install the package using Conan, run the following command:
|
||||
conda.registry = Setup this registry as a Conda repository in your <code>.condarc</code> file:
|
||||
conda.install = To install the package using Conda, run the following command:
|
||||
conda.details.repository_site = Repository Site
|
||||
conda.details.documentation_site = Documentation Site
|
||||
container.details.type = Image Type
|
||||
container.details.platform = Platform
|
||||
container.pull = Pull the image from the command line:
|
||||
|
||||
@@ -456,7 +456,7 @@ issue_assigned.pull=@%[1]s vous a assigné à la demande d’ajout %[2]s dans le
|
||||
issue_assigned.issue=@%[1]s vous a assigné le ticket %[2]s dans le dépôt %[3]s.
|
||||
|
||||
issue.x_mentioned_you=<b>@%s</b> vous a mentionné:
|
||||
issue.action.force_push=<b>%[1]s</b> a forcé la mise à jour de <b>%[2]s</b> depuis %[3]s vers %[4]s.
|
||||
issue.action.force_push=<b>%[1]s</b> a forcé <b>%[2]s</b> de %[3]s vers %[4]s.
|
||||
issue.action.push_1=<b>@%[1]s</b> a soumis %[3]d révision sur %[2]s
|
||||
issue.action.push_n=<b>@%[1]s</b> a soumis %[3]d révisions sur %[2]s
|
||||
issue.action.close=<b>@%[1]s</b> a fermé #%[2]d.
|
||||
@@ -856,7 +856,7 @@ oauth2_client_secret_hint=Le secret ne sera plus affiché après avoir quitté o
|
||||
oauth2_application_edit=Éditer
|
||||
oauth2_application_create_description=Les applications OAuth2 permettent à votre application tierce d'accéder aux comptes d'utilisateurs de cette instance.
|
||||
oauth2_application_remove_description=La suppression d'une application OAuth2 l'empêchera d'accéder aux comptes d'utilisateurs autorisés sur cette instance. Poursuivre ?
|
||||
oauth2_application_locked=Gitea préinstalle des applications OAuth2 au démarrage si elles sont activées dans la configuration. Pour éviter des comportements inattendus, celles-ci ne peuvent ni être éditées ni supprimées. Veuillez vous référer à la documentation OAuth2 pour plus d'informations.
|
||||
oauth2_application_locked=Gitea préinstalle des applications OAuth2 au démarrage si elles sont activées dans la configuration. Pour éviter des comportements inattendus, celles-ci ne peuvent être éditées ni supprimées. Veuillez vous référer à la documentation OAuth2 pour plus d'informations.
|
||||
|
||||
authorized_oauth2_applications=Applications OAuth2 autorisées
|
||||
authorized_oauth2_applications_description=Vous avez autorisé l'accès à votre compte personnel Gitea à ces applications tierces. Veuillez révoquer l'accès aux applications dont vous n'avez plus besoin.
|
||||
@@ -937,7 +937,7 @@ template_description=Les référentiels de modèles permettent aux utilisateurs
|
||||
visibility=Visibilité
|
||||
visibility_description=Seuls le propriétaire ou les membres de l'organisation, s'ils ont des droits, seront en mesure de le voir.
|
||||
visibility_helper=Rendre le dépôt privé
|
||||
visibility_helper_forced=L'administrateur de votre serveur impose que les nouveaux dépôts soient privés.
|
||||
visibility_helper_forced=L’administrateur requière que les nouveaux dépôts soient privés.
|
||||
visibility_fork_helper=(Changer ceci affectera toutes les bifurcations.)
|
||||
clone_helper=Besoin d'aide pour dupliquer ? Visitez <a target="_blank" rel="noopener noreferrer" href="%s">l'aide</a>.
|
||||
fork_repo=Bifurquer le dépôt
|
||||
@@ -1595,7 +1595,7 @@ issues.error_modifying_due_date=Impossible de modifier l'échéance.
|
||||
issues.error_removing_due_date=Impossible de supprimer l'échéance.
|
||||
issues.push_commit_1=a ajouté %d révision %s
|
||||
issues.push_commits_n=a ajouté %d révisions %s
|
||||
issues.force_push_codes=`a forcé la soumission de %[1]s depuis <a class="ui sha" href="%[3]s"><code>%[2]s</code></a> à <a class="ui sha" href="%[5]s"><code>%[4]s</code></a> %[6]s.`
|
||||
issues.force_push_codes=`a forcé %[1]s de <a class="ui sha" href="%[3]s"><code>%[2]s</code></a> à <a class="ui sha" href="%[5]s"><code>%[4]s</code></a> %[6]s.`
|
||||
issues.force_push_compare=Comparer
|
||||
issues.due_date_form=aaaa-mm-jj
|
||||
issues.due_date_form_add=Ajouter une échéance
|
||||
@@ -1725,7 +1725,7 @@ pulls.manually_merged=Fusionné manuellement
|
||||
pulls.merged_info_text=La branche %s peut maintenant être supprimée.
|
||||
pulls.is_closed=La demande d’ajout a été fermée.
|
||||
pulls.title_wip_desc=`<a href="#">Préfixer le titre par <strong>%s</strong></a> pour empêcher cette demande d'ajout d'être fusionnée par erreur.`
|
||||
pulls.cannot_merge_work_in_progress=Cette demande d'ajout est marquée comme en cours de chantier.
|
||||
pulls.cannot_merge_work_in_progress=Cette demande d’ajout est en chantier.
|
||||
pulls.still_in_progress=Toujours en cours ?
|
||||
pulls.add_prefix=Ajouter le préfixe <strong>%s</strong>
|
||||
pulls.remove_prefix=Enlever le préfixe <strong>%s</strong>
|
||||
@@ -1758,7 +1758,7 @@ pulls.wrong_commit_id=l'ID de la révision doit être un ID de révision sur la
|
||||
|
||||
pulls.no_merge_desc=Cette demande d’ajout ne peut être fusionnée car toutes les options de fusion du dépôt sont désactivées.
|
||||
pulls.no_merge_helper=Activez des options de fusion dans les paramètres du dépôt ou fusionnez la demande manuellement.
|
||||
pulls.no_merge_wip=Cette demande d'ajout ne peut pas être fusionnée car elle est marquée comme en cours de chantier.
|
||||
pulls.no_merge_wip=Cette demande d’ajout ne peut pas être fusionnée car elle est marquée en chantier.
|
||||
pulls.no_merge_not_ready=Cette demande d’ajout n’est pas prête à être fusionnée, vérifiez les évaluations en cours et le contrôle qualité.
|
||||
pulls.no_merge_access=Vous n'êtes pas autorisé⋅e à fusionner cette demande d'ajout.
|
||||
pulls.merge_pull_request=Créer une révision de fusion
|
||||
@@ -2278,11 +2278,11 @@ settings.protect_this_branch_desc=Empêche les suppressions et limite les pouss
|
||||
settings.protect_disable_push=Désactiver la soumission
|
||||
settings.protect_disable_push_desc=Aucune soumission ne sera possible sur cette branche.
|
||||
settings.protect_enable_push=Activer la soumission
|
||||
settings.protect_enable_push_desc=Toute personne ayant un accès en écriture sera autorisée à soumettre sur cette branche (mais pas de soumission de force).
|
||||
settings.protect_enable_push_desc=Toute personne ayant un accès en écriture sera autorisée à soumettre sur cette branche (sans forcer).
|
||||
settings.protect_enable_merge=Activer la fusion
|
||||
settings.protect_enable_merge_desc=Toute personne ayant un accès en écriture sera autorisée à fusionner les demandes d'ajout dans cette branche.
|
||||
settings.protect_whitelist_committers=Liste blanche des soumissions
|
||||
settings.protect_whitelist_committers_desc=Seuls les utilisateurs ou les équipes autorisés pourront soumettre sur cette branche (mais pas de soumission de force).
|
||||
settings.protect_whitelist_committers_desc=Seuls les utilisateurs ou les équipes autorisés pourront soumettre sur cette branche (sans forcer).
|
||||
settings.protect_whitelist_deploy_keys=Mettez les clés de déploiement sur liste blanche avec accès en écriture pour soumettre.
|
||||
settings.protect_whitelist_users=Utilisateurs sur liste blanche :
|
||||
settings.protect_whitelist_search_users=Rechercher des utilisateurs…
|
||||
@@ -3404,8 +3404,8 @@ rubygems.install=Pour installer le paquet en utilisant gem, exécutez la command
|
||||
rubygems.install2=ou ajoutez-le au Gemfile :
|
||||
rubygems.dependencies.runtime=Dépendances d'exécution
|
||||
rubygems.dependencies.development=Dépendances de développement
|
||||
rubygems.required.ruby=Nécessite la version de Ruby
|
||||
rubygems.required.rubygems=Nécessite la version de RubyGem
|
||||
rubygems.required.ruby=Nécessite Ruby en version
|
||||
rubygems.required.rubygems=Nécessite RubyGem en version
|
||||
swift.registry=Configurez ce registre à partir d'un terminal :
|
||||
swift.install=Ajoutez le paquet dans votre fichier <code>Package.swift</code>:
|
||||
swift.install2=et exécutez la commande suivante :
|
||||
@@ -3460,7 +3460,7 @@ description=Les secrets seront transmis à certaines actions et ne pourront pas
|
||||
none=Il n'y a pas encore de secrets.
|
||||
creation=Ajouter un secret
|
||||
creation.name_placeholder=Caractères alphanumériques ou tirets bas uniquement, insensibles à la casse, ne peut commencer par GITEA_ ou GITHUB_.
|
||||
creation.value_placeholder=Entrez n'importe quoi. Les blancs cernant seront taillés.
|
||||
creation.value_placeholder=Entrez n’importe quoi. Les blancs cernant seront taillés.
|
||||
creation.success=Le secret "%s" a été ajouté.
|
||||
creation.failed=Impossible d'ajouter le secret.
|
||||
deletion=Supprimer le secret
|
||||
|
||||
@@ -4,6 +4,7 @@ explore=Explorar
|
||||
help=Ajuda
|
||||
logo=Logotipo
|
||||
sign_in=Acessar
|
||||
sign_in_with_provider=Entrar com %s
|
||||
sign_in_or=ou
|
||||
sign_out=Sair
|
||||
sign_up=Cadastrar
|
||||
@@ -79,6 +80,7 @@ milestones=Marcos
|
||||
|
||||
ok=Ok
|
||||
cancel=Cancelar
|
||||
retry=Tentar novamente
|
||||
rerun=Reexecutar
|
||||
rerun_all=Reexecutar todas as tarefas
|
||||
save=Salvar
|
||||
@@ -91,6 +93,7 @@ edit=Editar
|
||||
|
||||
enabled=Habilitado
|
||||
disabled=Desabilitado
|
||||
locked=Bloqueado
|
||||
|
||||
copy=Copiar
|
||||
copy_url=Copiar URL
|
||||
@@ -130,7 +133,9 @@ concept_user_organization=Organização
|
||||
show_timestamps=Mostrar data/hora
|
||||
show_log_seconds=Mostrar segundos
|
||||
show_full_screen=Mostrar tela cheia
|
||||
download_logs=Baixar logs
|
||||
|
||||
confirm_delete_selected=Confirma a exclusão de todos os itens selecionados?
|
||||
|
||||
name=Nome
|
||||
value=Valor
|
||||
@@ -169,6 +174,7 @@ string.desc=Z - A
|
||||
|
||||
[error]
|
||||
occurred=Ocorreu um erro
|
||||
report_message=Se você acredita que esse é um falha do Gitea, pesquise por issues no <a href="https://github.com/go-gitea/gitea/issues" target="_blank">GitHub</a> ou abra uma nova issue, se necessário.
|
||||
missing_csrf=Pedido inválido: não tem token CSRF presente
|
||||
invalid_csrf=Requisição Inválida: token CSRF inválido
|
||||
not_found=Não foi possível encontrar o destino.
|
||||
@@ -221,6 +227,7 @@ repo_path_helper=Todos os repositórios remotos do Git serão salvos neste diret
|
||||
lfs_path=Caminho raiz do Git LFS
|
||||
lfs_path_helper=Os arquivos armazenados com o Git LFS serão armazenados neste diretório. Deixe em branco para desabilitar.
|
||||
run_user=Executar como nome de usuário
|
||||
run_user_helper=O nome de usuário do sistema operacional com o qual o Gitea é executado. Observe que este usuário deve ter acesso ao caminho da raiz do repositório.
|
||||
domain=Domínio do servidor
|
||||
domain_helper=Domínio ou endereço de host para o servidor.
|
||||
ssh_port=Porta do servidor SSH
|
||||
@@ -292,6 +299,8 @@ invalid_password_algorithm=Algoritmo de hash de senha inválido
|
||||
password_algorithm_helper=Escolha o algoritmo de hash para as senhas. Diferentes algoritmos têm requerimentos e forças diversos. O algoritmo argon2 é bastante seguro, mas usa muita memória e pode ser inapropriado para sistemas com menos recursos.
|
||||
enable_update_checker=Habilitar Verificador de Atualizações
|
||||
enable_update_checker_helper=Procura por novas versões periodicamente conectando-se ao gitea.io.
|
||||
env_config_keys=Configuração do ambiente
|
||||
env_config_keys_prompt=As seguintes variáveis de ambiente também serão aplicadas ao seu arquivo de configuração:
|
||||
|
||||
[home]
|
||||
uname_holder=Usuário ou e-mail
|
||||
@@ -354,6 +363,7 @@ remember_me=Lembrar deste Dispositivo
|
||||
forgot_password_title=Esqueci minha senha
|
||||
forgot_password=Esqueceu sua senha?
|
||||
sign_up_now=Precisa de uma conta? Cadastre-se agora.
|
||||
sign_up_successful=A conta foi criada com sucesso. Bem-vindo!
|
||||
confirmation_mail_sent_prompt=Um novo e-mail de confirmação foi enviado para <b>%s</b>. Por favor, verifique sua caixa de e-mail nas próximas %s horas para finalizar o processo de cadastro.
|
||||
must_change_password=Redefina sua senha
|
||||
allow_password_change=Exigir que o usuário redefina a senha (recomendado)
|
||||
@@ -361,6 +371,7 @@ reset_password_mail_sent_prompt=Um e-mail de confirmação foi enviado para <b>%
|
||||
active_your_account=Ativar sua conta
|
||||
account_activated=Conta foi ativada
|
||||
prohibit_login=Acesso proibido
|
||||
prohibit_login_desc=Sua conta está proibida de fazer login, entre em contato com o administrador do site.
|
||||
resent_limit_prompt=Você já solicitou recentemente um e-mail de ativação. Por favor, aguarde 3 minutos e tente novamente.
|
||||
has_unconfirmed_mail=Oi %s, você possui um endereço de e-mail não confirmado (<b>%s</b>). Se você não recebeu um e-mail de confirmação ou precisa reenviar um novo, clique no botão abaixo.
|
||||
resend_mail=Clique aqui para reenviar seu e-mail de ativação
|
||||
@@ -368,8 +379,10 @@ email_not_associate=O endereço de e-mail não está associado à nenhuma conta.
|
||||
send_reset_mail=Enviar e-mail de recuperação de conta
|
||||
reset_password=Recuperação de conta
|
||||
invalid_code=Seu código de confirmação é inválido ou expirou.
|
||||
invalid_code_forgot_password=Seu código de confirmação expirou ou está inválido. Clique <a href="%s">aqui</a> para iniciar uma nova sessão.
|
||||
invalid_password=Sua senha não coincide com a senha que foi usada para criar a conta.
|
||||
reset_password_helper=Recuperar conta
|
||||
reset_password_wrong_user=Você está conectado como %s, mas o link de recuperação de conta é destinado a %s
|
||||
password_too_short=A senha deve ter %d ou mais caracteres.
|
||||
non_local_account=Usuários não-locais não podem atualizar sua senha através da interface web do Gitea.
|
||||
verify=Verificar
|
||||
@@ -394,6 +407,7 @@ openid_connect_title=Conectar à uma conta existente
|
||||
openid_connect_desc=O URI do OpenID escolhido é desconhecido. Associe-o com uma nova conta aqui.
|
||||
openid_register_title=Criar uma nova conta
|
||||
openid_register_desc=O URI do OpenID escolhido é desconhecido. Associe-o com uma nova conta aqui.
|
||||
openid_signin_desc=Digite o URI do seu OpenID. Por exemplo: alice.openid.example.org ou https://openid.example.org/alice.
|
||||
disable_forgot_password_mail=A recuperação de conta está desativada porque nenhum e-mail está configurado. Por favor, contate o administrador do site.
|
||||
disable_forgot_password_mail_admin=A recuperação de conta só está disponível quando o e-mail está configurado. Por favor, configure o e-mail para permitir a recuperação de conta.
|
||||
email_domain_blacklisted=Você não pode se cadastrar com seu endereço de e-mail.
|
||||
@@ -403,7 +417,9 @@ authorize_application_created_by=Este aplicativo foi criado por %s.
|
||||
authorize_application_description=Se você conceder o acesso, ele será capaz de acessar e escrever em todas as informações da sua conta, incluindo repositórios privados e organizações.
|
||||
authorize_title=Autorizar "%s" para acessar sua conta?
|
||||
authorization_failed=Autorização falhou
|
||||
authorization_failed_desc=A autorização falhou porque detectamos uma solicitação inválida. Entre em contato com o responsável do aplicativo que você tentou autorizar.
|
||||
sspi_auth_failed=Falha de autenticação SSPI
|
||||
password_pwned=A senha que você escolheu faz parte de uma <a target="_blank" rel="noopener noreferrer" href="https://haveibeenpwned.com/Passwords">lista de senhas roubadas</a> expostas anteriormente em violações de dados. Tente novamente com uma senha diferente e considere alterar essa senha em outro lugar também.
|
||||
password_pwned_err=Não foi possível concluir a requisição ao HaveIBeenPwned
|
||||
|
||||
[mail]
|
||||
@@ -418,6 +434,7 @@ activate_account.text_1=Olá <b>%[1]s</b>, obrigado por se registrar em %[2]s!
|
||||
activate_account.text_2=Por favor clique no link a seguir para ativar sua conta em <b>%s</b>:
|
||||
|
||||
activate_email=Verifique seu endereço de e-mail
|
||||
activate_email.title=%s, por favor verifique o seu endereço de e-mail
|
||||
activate_email.text=Por favor clique no link a seguir para verificar o seu endereço de e-mail em <b>%s</b>:
|
||||
|
||||
register_notify=Bem-vindo ao Gitea
|
||||
@@ -587,6 +604,8 @@ user_bio=Biografia
|
||||
disabled_public_activity=Este usuário desativou a visibilidade pública da atividade.
|
||||
email_visibility.limited=Seu endereço de e-mail está visível para todos os usuários autenticados
|
||||
email_visibility.private=Seu endereço de e-mail é visível apenas para você e administradores
|
||||
show_on_map=Mostrar este lugar em um mapa
|
||||
settings=Configurações do usuário
|
||||
|
||||
form.name_reserved=O nome de usuário "%s" está reservado.
|
||||
form.name_pattern_not_allowed=O padrão de "%s" não é permitido em um nome de usuário.
|
||||
@@ -608,9 +627,13 @@ delete=Excluir conta
|
||||
twofa=Autenticação de dois fatores
|
||||
account_link=Contas vinculadas
|
||||
organization=Organizações
|
||||
uid=UID
|
||||
webauthn=Chaves de segurança
|
||||
|
||||
public_profile=Perfil público
|
||||
biography_placeholder=Conte-nos um pouco sobre você! (Você pode usar Markdown)
|
||||
location_placeholder=Compartilhe sua localização aproximada com outras pessoas
|
||||
profile_desc=Controle como o seu perfil é exibido para outros usuários. Seu endereço de e-mail principal será usado para notificações, recuperação de senha e operações do Git baseadas na Web.
|
||||
password_username_disabled=Usuários não-locais não podem alterar seus nomes de usuário. Por favor contate o administrador do site para mais informações.
|
||||
full_name=Nome completo
|
||||
website=Site
|
||||
@@ -622,6 +645,8 @@ update_language_not_found=Idioma "%s" não está disponível.
|
||||
update_language_success=O idioma foi atualizado.
|
||||
update_profile_success=Seu perfil foi atualizado.
|
||||
change_username=Seu nome de usuário foi alterado.
|
||||
change_username_prompt=Observação: a alteração do seu nome de usuário também altera o URL da sua conta.
|
||||
change_username_redirect_prompt=O nome de usuário antigo irá redirecionar até que alguém comece a usá-lo.
|
||||
continue=Continuar
|
||||
cancel=Cancelar
|
||||
language=Idioma
|
||||
@@ -646,6 +671,7 @@ comment_type_group_project=Projeto
|
||||
comment_type_group_issue_ref=Referência do issue
|
||||
saved_successfully=Suas configurações foram salvas com sucesso.
|
||||
privacy=Privacidade
|
||||
keep_activity_private=Ocultar atividade da página de perfil
|
||||
keep_activity_private_popup=Torna a atividade visível somente para você e os administradores
|
||||
|
||||
lookup_avatar_by_mail=Procurar o avatar do endereço de e-mail
|
||||
@@ -655,12 +681,14 @@ choose_new_avatar=Escolha um novo avatar
|
||||
update_avatar=Atualizar o avatar
|
||||
delete_current_avatar=Excluir o avatar atual
|
||||
uploaded_avatar_not_a_image=O arquivo enviado não é uma imagem.
|
||||
uploaded_avatar_is_too_big=O tamanho do arquivo enviado (%d KiB) excede o tamanho máximo permitido (%d KiB).
|
||||
update_avatar_success=Seu avatar foi atualizado.
|
||||
update_user_avatar_success=O avatar do usuário foi atualizado.
|
||||
|
||||
change_password=Atualizar senha
|
||||
old_password=Senha atual
|
||||
new_password=Nova senha
|
||||
retype_new_password=Confirmar nova senha
|
||||
password_incorrect=A senha atual está incorreta.
|
||||
change_password_success=Sua senha foi atualizada. Acesse usando sua nova senha de agora em diante.
|
||||
password_change_disabled=Contas não-locais não podem alterar sua senha através da interface web do Gitea.
|
||||
@@ -669,6 +697,7 @@ emails=Endereços de e-mail
|
||||
manage_emails=Gerenciar endereços de e-mail
|
||||
manage_themes=Selecione o tema padrão
|
||||
manage_openid=Gerencia endereços OpenID
|
||||
email_desc=Seu endereço de e-mail principal será usado para notificações, recuperação de senha e, desde que não esteja oculto, para operações do Git baseadas na Web.
|
||||
theme_desc=Este será o seu tema padrão em todo o site.
|
||||
primary=Principal
|
||||
activated=Ativado
|
||||
@@ -676,6 +705,7 @@ requires_activation=Requer ativação
|
||||
primary_email=Tornar Principal
|
||||
activate_email=Enviar Ativação
|
||||
activations_pending=Ativações pendentes
|
||||
can_not_add_email_activations_pending=Há uma ativação pendente, tente novamente em alguns minutos se quiser adicionar um novo e-mail.
|
||||
delete_email=Remover
|
||||
email_deletion=Remover endereço de e-mail
|
||||
email_deletion_desc=O endereço de e-mail e informações relacionadas serão removidos de sua conta. Commits aplicados por este endereço de e-mail permanecerão inalterados. Continuar?
|
||||
@@ -694,6 +724,7 @@ add_email_success=O novo endereço de e-mail foi adicionado.
|
||||
email_preference_set_success=Preferência de e-mail definida com sucesso.
|
||||
add_openid_success=O novo endereço de OpenID foi adicionado.
|
||||
keep_email_private=Ocultar endereço de e-mail
|
||||
keep_email_private_popup=Isso ocultará seu endereço de e-mail do seu perfil, bem como quando você fizer um pull request ou editar um arquivo usando a interface Web. Os commits enviados não serão modificados.
|
||||
openid_desc=OpenID permite delegar autenticação para um provedor externo.
|
||||
|
||||
manage_ssh_keys=Gerenciar Chaves SSH
|
||||
@@ -772,7 +803,9 @@ ssh_disabled=SSH desabilitado
|
||||
ssh_signonly=O SSH está desativado no momento, portanto, essas chaves são usadas apenas para verificação de assinatura de confirmação.
|
||||
ssh_externally_managed=Esta chave SSH para este usuário é gerenciada externamente
|
||||
manage_social=Gerenciar contas sociais associadas
|
||||
social_desc=Essas contas sociais podem ser usadas para fazer login em sua conta. Certifique-se de reconhecer todas elas.
|
||||
unbind=Desvincular
|
||||
unbind_success=A conta social foi removida com sucesso.
|
||||
|
||||
manage_access_token=Gerenciar tokens de acesso
|
||||
generate_new_token=Gerar novo token
|
||||
@@ -791,8 +824,9 @@ repo_and_org_access=Acesso ao Repositório e Organização
|
||||
permissions_public_only=Apenas público
|
||||
permissions_access_all=Todos (público, privado e limitado)
|
||||
select_permissions=Selecionar permissões
|
||||
permission_no_access=Sem Acesso
|
||||
permission_read=Lidas
|
||||
permission_no_access=Sem acesso
|
||||
permission_read=Ler
|
||||
permission_write=Ler e escrever
|
||||
at_least_one_permission=Você deve selecionar pelo menos uma permissão para criar um token
|
||||
permissions_list=Permissões:
|
||||
|
||||
@@ -804,6 +838,8 @@ remove_oauth2_application_desc=Remover um aplicativo OAuth2 irá revogar o acess
|
||||
remove_oauth2_application_success=O aplicativo foi excluído.
|
||||
create_oauth2_application=Criar um novo aplicativo OAuth2
|
||||
create_oauth2_application_button=Criar aplicativo
|
||||
create_oauth2_application_success=Você criou um aplicativo OAuth2 com sucesso.
|
||||
update_oauth2_application_success=Você atualizou o aplicativo OAuth2 com sucesso.
|
||||
oauth2_application_name=Nome do aplicativo
|
||||
oauth2_confidential_client=Cliente Confidencial. Selecione para aplicativos que mantêm a confidencialidade do segredo, como aplicativos web. Não selecione para aplicativos nativos, incluindo aplicativos desktop e celulares.
|
||||
oauth2_redirect_uris=URIs de redirecionamento. Por favor use uma nova linha para cada URI.
|
||||
@@ -812,19 +848,25 @@ oauth2_client_id=Client ID
|
||||
oauth2_client_secret=Client Secret
|
||||
oauth2_regenerate_secret=Gerar novamente o Client Secret
|
||||
oauth2_regenerate_secret_hint=Perdeu seu Client Secret?
|
||||
oauth2_client_secret_hint=O segredo não será exibido novamente depois que você sair ou atualizar esta página. Certifique-se de que você o salvou.
|
||||
oauth2_application_edit=Editar
|
||||
oauth2_application_create_description=Os aplicativos OAuth2 fornecem ao seus aplicativos de terceiros acesso a contas de usuário nesta instância.
|
||||
oauth2_application_remove_description=A remoção de um aplicativo OAuth2 impedirá que ele acesse contas de usuários autorizados nesta instância. Continuar?
|
||||
oauth2_application_locked=O Gitea pré-registra alguns aplicativos OAuth2 na inicialização, se habilitados na configuração. Para evitar um comportamento inesperado, eles não podem ser editados nem removidos. Consulte a documentação do OAuth2 para obter mais informações.
|
||||
|
||||
authorized_oauth2_applications=Aplicações OAuth2 autorizadas
|
||||
authorized_oauth2_applications_description=Você concedeu acesso à sua conta pessoal da Gitea para esses aplicativos de terceiros. Revogue o acesso aos aplicativos de que não precisa mais.
|
||||
revoke_key=Revogar
|
||||
revoke_oauth2_grant=Revogar acesso
|
||||
revoke_oauth2_grant_description=Revogando o acesso para este aplicativo de terceiros impedirá este aplicativo de acessar seus dados. Tem certeza?
|
||||
revoke_oauth2_grant_success=Acesso revogado com sucesso.
|
||||
|
||||
twofa_desc=Autenticação de dois fatores melhora a segurança de sua conta.
|
||||
twofa_is_enrolled=Sua conta está atualmente <strong>habilitada</strong> com autenticação de dois fatores.
|
||||
twofa_not_enrolled=Sua conta não está atualmente inscrita para a autenticação em duas etapas.
|
||||
twofa_disable=Desabilitar a autenticação de dois fatores
|
||||
twofa_scratch_token_regenerate=Gerar novamente o token de backup
|
||||
twofa_scratch_token_regenerated=Seu token agora é %s. Guarde-a em um local seguro, pois ela nunca mais será exibido.
|
||||
twofa_enroll=Inscrever para a autenticação de dois fatores
|
||||
twofa_disable_note=Você pode desabilitar a autenticação de dois fatores se necessário.
|
||||
twofa_disable_desc=Desabilitar a autenticação de dois fatores tornará sua conta menos segura. Tem certeza que deseja continuar?
|
||||
@@ -851,8 +893,10 @@ remove_account_link=Remover conta vinculada
|
||||
remove_account_link_desc=A exclusão da chave SSH revogará o acesso à sua conta. Continuar?
|
||||
remove_account_link_success=A conta vinculada foi removida.
|
||||
|
||||
hooks.desc=Adicione webhooks que serão acionados para <strong>todos os repositórios</strong> que você possui.
|
||||
|
||||
orgs_none=Você não é membro de nenhuma organização.
|
||||
repos_none=Você não é proprietário de nenhum repositório.
|
||||
|
||||
delete_account=Excluir sua conta
|
||||
delete_prompt=Esta operação irá apagar permanentemente a sua conta de usuário. Isto <strong>NÃO PODERÁ</strong> ser desfeito.
|
||||
@@ -871,9 +915,12 @@ visibility=Visibilidade do usuário
|
||||
visibility.public=Pública
|
||||
visibility.public_tooltip=Visível para todos
|
||||
visibility.limited=Limitada
|
||||
visibility.limited_tooltip=Visível apenas para usuários autenticados
|
||||
visibility.private=Privada
|
||||
visibility.private_tooltip=Visível apenas para membros das organizações às quais você se associou
|
||||
|
||||
[repo]
|
||||
new_repo_helper=Um repositório contém todos os arquivos do projeto, inclusive o histórico de revisões. Já está hospedando um em outro lugar? <a href="%s">Migre o repositório.</a>
|
||||
owner=Proprietário
|
||||
owner_helper=Algumas organizações podem não aparecer no menu devido a um limite de contagem dos repositórios.
|
||||
repo_name=Nome do repositório
|
||||
@@ -885,6 +932,7 @@ template_helper=Tornar repositório um modelo
|
||||
template_description=Os repositórios de modelo permitem que os usuários gerem novos repositórios com a mesma estrutura de diretório, arquivos e configurações opcionais.
|
||||
visibility=Visibilidade
|
||||
visibility_description=Somente o proprietário ou os membros da organização, se tiverem direitos, poderão vê-lo.
|
||||
visibility_helper=Tornar o repositório privado
|
||||
visibility_helper_forced=O administrador do site força novos repositórios a serem privados.
|
||||
visibility_fork_helper=(Esta alteração irá afetar todos os forks.)
|
||||
clone_helper=Precisa de ajuda com o clone? Visite a <a target="_blank" rel="noopener noreferrer" href="%s">Ajuda</a>.
|
||||
@@ -893,6 +941,7 @@ fork_from=Fork de
|
||||
already_forked=Você já fez o fork de %s
|
||||
fork_to_different_account=Faça um fork para uma conta diferente
|
||||
fork_visibility_helper=A visibilidade do fork de um repositório não pode ser alterada.
|
||||
fork_no_valid_owners=Não é possível fazer um fork desse repositório porque não há proprietários validos.
|
||||
use_template=Usar este modelo
|
||||
clone_in_vsc=Clonar no VS Code
|
||||
download_zip=Baixar ZIP
|
||||
@@ -921,6 +970,7 @@ trust_model_helper_collaborator_committer=Colaborador+Committer: Confiar em assi
|
||||
trust_model_helper_default=Padrão: Usar o modelo de confiança padrão para esta instalação
|
||||
create_repo=Criar repositório
|
||||
default_branch=Branch Padrão
|
||||
default_branch_label=padrão
|
||||
default_branch_helper=O branch padrão é o branch base para pull requests e commits de código.
|
||||
mirror_prune=Varrer
|
||||
mirror_prune_desc=Remover referências obsoletas de controle remoto
|
||||
@@ -929,6 +979,8 @@ mirror_interval_invalid=O intervalo do espelhamento não é válido.
|
||||
mirror_sync_on_commit=Sincronizar quando commits forem enviados
|
||||
mirror_address=Clonar de URL
|
||||
mirror_address_desc=Coloque todas as credenciais necessárias na seção de autorização.
|
||||
mirror_address_url_invalid=O URL fornecido é inválido. Você deve escapar todos os componentes do URL corretamente.
|
||||
mirror_address_protocol_invalid=O URL fornecido é inválido. Somente locais http(s):// ou git:// podem ser usados para espelhamento.
|
||||
mirror_lfs=Armazenamento de Arquivo Grande (LFS)
|
||||
mirror_lfs_desc=Ativar espelhamento de dados LFS.
|
||||
mirror_lfs_endpoint=Destino LFS
|
||||
@@ -961,6 +1013,8 @@ transfer.accept=Aceitar transferência
|
||||
transfer.accept_desc=`Transferir para "%s"`
|
||||
transfer.reject=Rejeitar transferência
|
||||
transfer.reject_desc=`Cancelar a transferência para "%s"`
|
||||
transfer.no_permission_to_accept=Você não tem permissão para aceitar essa transferência.
|
||||
transfer.no_permission_to_reject=Você não tem permissão para rejeitar essa transferência.
|
||||
|
||||
desc.private=Privado
|
||||
desc.public=Público
|
||||
@@ -981,6 +1035,8 @@ template.issue_labels=Etiquetas de issue
|
||||
template.one_item=Deve-se selecionar pelo menos um item de modelo
|
||||
template.invalid=Deve-se selecionar um repositório de modelo
|
||||
|
||||
archive.title=Este repositório está arquivado. Você pode visualizar arquivos e cloná-lo, mas não pode fazer push, abrir issues ou pull requests.
|
||||
archive.title_date=Este repositório foi arquivado em %s. Você pode visualizar arquivos e cloná-lo, mas não pode fazer push, abrir issues ou pull requests.
|
||||
archive.issue.nocomment=Este repositório está arquivado. Você não pode comentar nas issues.
|
||||
archive.pull.nocomment=Este repositório está arquivado. Você não pode comentar nos pull requests.
|
||||
|
||||
@@ -997,6 +1053,7 @@ migrate_options_lfs=Migrar arquivos LFS
|
||||
migrate_options_lfs_endpoint.label=Destino LFS
|
||||
migrate_options_lfs_endpoint.description=A migração tentará usar seu controle remoto Git para <a target="_blank" rel="noopener noreferrer" href="%s">determinar o servidor LFS</a>. Você também pode especificar um destino personalizado se os dados do repositório LFS forem armazenados em outro lugar.
|
||||
migrate_options_lfs_endpoint.description.local=Um caminho de servidor local também é suportado.
|
||||
migrate_options_lfs_endpoint.placeholder=Se for deixado em branco, o endpoint será derivado do URL do clone
|
||||
migrate_items=Itens da migração
|
||||
migrate_items_wiki=Wiki
|
||||
migrate_items_milestones=Marcos
|
||||
@@ -1099,6 +1156,10 @@ file_view_rendered=Ver Renderizado
|
||||
file_view_raw=Ver original
|
||||
file_permalink=Link permanente
|
||||
file_too_large=O arquivo é muito grande para ser mostrado.
|
||||
invisible_runes_header=`Este arquivo contém caracteres Unicode invisíveis`
|
||||
invisible_runes_description=`Este arquivo contém caracteres Unicode invisíveis que são indistinguíveis para humanos, mas que podem ser processados de forma diferente por um computador. Se você acha que isso é intencional, pode ignorar esse aviso com segurança. Use o botão Escapar para revelá-los
|
||||
ambiguous_runes_header=`Este arquivo contém caracteres Unicode ambíguos`
|
||||
ambiguous_runes_description=`Este arquivo contém caracteres Unicode que podem ser confundidos com outros caracteres. Se você acha que isso é intencional, pode ignorar esse aviso com segurança. Use o botão Escapar para revelá-los
|
||||
invisible_runes_line=`Esta linha tem caracteres unicode invisíveis`
|
||||
ambiguous_runes_line=`Esta linha tem caracteres unicode ambíguos`
|
||||
ambiguous_character=`%[1]c [U+%04[1]X] é confundível com o %[2]c [U+%04[2]X]`
|
||||
@@ -1111,11 +1172,15 @@ video_not_supported_in_browser=Seu navegador não suporta a tag 'video' do HTML5
|
||||
audio_not_supported_in_browser=Seu navegador não suporta a tag 'audio' do HTML5.
|
||||
stored_lfs=Armazenado com Git LFS
|
||||
symbolic_link=Link simbólico
|
||||
executable_file=Arquivo executável
|
||||
commit_graph=Gráfico de commits
|
||||
commit_graph.select=Selecionar branches
|
||||
commit_graph.hide_pr_refs=Esconder Pull Requests
|
||||
commit_graph.monochrome=Monocromático
|
||||
commit_graph.color=Colorido
|
||||
commit.contained_in=Esse commit está contido em:
|
||||
commit.contained_in_default_branch=Esse commit faz parte do branch padrão
|
||||
commit.load_referencing_branches_and_tags=Carregar branches e tags que fazem referência a este commit
|
||||
blame=Anotar
|
||||
download_file=Baixar arquivo
|
||||
normal_view=Visão normal
|
||||
@@ -1195,6 +1260,7 @@ commits.commits=Commits
|
||||
commits.no_commits=Nenhum commit em comum. "%s" e "%s" tem históricos completamente diferentes.
|
||||
commits.nothing_to_compare=Estes branches são iguais.
|
||||
commits.search=Pesquisar commits...
|
||||
commits.search.tooltip=Você pode prefixar as palavras-chave com "author:" (autor da mudança), "committer:" (autor do commit), "after:" (depois) ou "before:" (antes). Por exemplo: "revert author:Ana before:2019-01-13".\
|
||||
commits.find=Pesquisar
|
||||
commits.search_all=Todos os branches
|
||||
commits.author=Autor
|
||||
@@ -1251,8 +1317,10 @@ projects.column.edit_title=Nome
|
||||
projects.column.new_title=Nome
|
||||
projects.column.new_submit=Criar coluna
|
||||
projects.column.new=Nova Coluna
|
||||
projects.column.set_default=Definir padrão
|
||||
projects.column.set_default=Atribuir como padrão
|
||||
projects.column.set_default_desc=Definir esta coluna como padrão para pull e issues sem categoria
|
||||
projects.column.unset_default=Desatribuir padrão
|
||||
projects.column.unset_default_desc=Desatribuir esta coluna como padrão
|
||||
projects.column.delete=Excluir coluna
|
||||
projects.column.deletion_desc=Excluir uma coluna do projeto move todas as issues relacionadas para 'Sem categoria'. Continuar?
|
||||
projects.column.color=Cor
|
||||
@@ -1331,6 +1399,7 @@ issues.delete_branch_at=`excluiu branch <b>%s</b> %s`
|
||||
issues.filter_label=Etiqueta
|
||||
issues.filter_label_exclude=`Use <code>alt</code> + <code>clique/enter</code> para excluir etiquetas`
|
||||
issues.filter_label_no_select=Todas as etiquetas
|
||||
issues.filter_label_select_no_label=Sem etiqueta
|
||||
issues.filter_milestone=Marco
|
||||
issues.filter_milestone_all=Todos os marcos
|
||||
issues.filter_milestone_none=Sem marcos
|
||||
@@ -1364,6 +1433,7 @@ issues.filter_sort.moststars=Mais estrelas
|
||||
issues.filter_sort.feweststars=Menos estrelas
|
||||
issues.filter_sort.mostforks=Mais forks
|
||||
issues.filter_sort.fewestforks=Menos forks
|
||||
issues.keyword_search_unavailable=A pesquisa por palavra-chave não está disponível no momento. Entre em contato com o administrador do site.
|
||||
issues.action_open=Abrir
|
||||
issues.action_close=Fechar
|
||||
issues.action_label=Etiqueta
|
||||
@@ -1384,6 +1454,7 @@ issues.next=Próximo
|
||||
issues.open_title=Aberto
|
||||
issues.closed_title=Fechado
|
||||
issues.draft_title=Rascunho
|
||||
issues.num_comments_1=%d comentário
|
||||
issues.num_comments=%d comentários
|
||||
issues.commented_at=`comentou <a href="#%s">%s</a>`
|
||||
issues.delete_comment_confirm=Tem certeza que deseja excluir este comentário?
|
||||
@@ -1392,6 +1463,7 @@ issues.context.quote_reply=Citar resposta
|
||||
issues.context.reference_issue=Referência em uma nova issue
|
||||
issues.context.edit=Editar
|
||||
issues.context.delete=Excluir
|
||||
issues.no_content=Nenhuma descrição fornecida.
|
||||
issues.close=Fechar issue
|
||||
issues.comment_pull_merged_at=aplicou o merge do commit %[1]s em %[2]s %[3]s
|
||||
issues.comment_manually_pull_merged_at=aplicou o merge manual do commit %[1]s em %[2]s %[3]s
|
||||
@@ -1410,7 +1482,9 @@ issues.ref_closed_from=`<a href="%[3]s">fechou esta issue %[4]s</a> <a id="%[1]s
|
||||
issues.ref_reopened_from=`<a href="%[3]s">reabriu esta issue %[4]s</a> <a id="%[1]s" href="#%[1]s">%[2]s</a>`
|
||||
issues.ref_from=`de %[1]s`
|
||||
issues.author=Autor
|
||||
issues.author_helper=Este usuário é o autor.
|
||||
issues.role.owner=Proprietário
|
||||
issues.role.owner_helper=Este usuário é o dono deste repositório.
|
||||
issues.role.member=Membro
|
||||
issues.re_request_review=Re-solicitar revisão
|
||||
issues.is_stale=Houve alterações nessa PR desde essa revisão
|
||||
@@ -1426,6 +1500,7 @@ issues.label_title=Nome da etiqueta
|
||||
issues.label_description=Descrição da etiqueta
|
||||
issues.label_color=Cor da etiqueta
|
||||
issues.label_exclusive=Exclusivo
|
||||
issues.label_archive=Arquivar etiqueta
|
||||
issues.label_exclusive_desc=Nomeie o rótulo <code>escopo/item</code> para torná-lo mutuamente exclusivo com outros rótulos do <code>escopo/</code>.
|
||||
issues.label_exclusive_warning=Quaisquer rótulos com escopo conflitantes serão removidos ao editar os rótulos de uma issue ou pull request.
|
||||
issues.label_count=%d etiquetas
|
||||
@@ -1480,6 +1555,7 @@ issues.tracking_already_started=`Você já iniciou o cronômetro em <a href="%s"
|
||||
issues.stop_tracking=Parar Cronômetro
|
||||
issues.stop_tracking_history=`parou de trabalhar %s`
|
||||
issues.cancel_tracking=Descartar
|
||||
issues.cancel_tracking_history=`cronômetro cancelado %s`
|
||||
issues.add_time=Adicionar tempo manualmente
|
||||
issues.del_time=Apagar este registro de tempo
|
||||
issues.add_time_short=Adicionar tempo
|
||||
@@ -1526,6 +1602,7 @@ issues.dependency.issue_closing_blockedby=Fechamento desta issue está bloqueado
|
||||
issues.dependency.issue_close_blocks=Esta issue bloqueia o fechamento das seguintes issues
|
||||
issues.dependency.pr_close_blocks=Este pull request bloqueia o fechamento das seguintes issues
|
||||
issues.dependency.issue_close_blocked=Você precisa fechar todas as issues que bloqueiam esta issue antes de poder fechá-la.
|
||||
issues.dependency.issue_batch_close_blocked=Não é possível fechar as issues que você escolheu, porque a issue #%d ainda tem dependências abertas
|
||||
issues.dependency.pr_close_blocked=Você precisa fechar todas issues que bloqueiam este pull request antes de poder fazer o merge.
|
||||
issues.dependency.blocks_short=Bloqueia
|
||||
issues.dependency.blocked_by_short=Depende de
|
||||
@@ -1557,6 +1634,9 @@ issues.review.pending.tooltip=Este comentário não está atualmente visível pa
|
||||
issues.review.review=Revisão
|
||||
issues.review.reviewers=Revisores
|
||||
issues.review.outdated=Desatualizado
|
||||
issues.review.outdated_description=O conteúdo foi alterado desde que este comentário foi feito
|
||||
issues.review.option.show_outdated_comments=Mostrar comentários desatualizados
|
||||
issues.review.option.hide_outdated_comments=Ocultar comentários desatualizados
|
||||
issues.review.show_outdated=Mostrar desatualizado
|
||||
issues.review.hide_outdated=Ocultar desatualizado
|
||||
issues.review.show_resolved=Mostrar resolvidas
|
||||
@@ -1596,6 +1676,13 @@ pulls.switch_comparison_type=Mudar tipo de comparação
|
||||
pulls.switch_head_and_base=Trocar cabeça e base
|
||||
pulls.filter_branch=Filtrar branch
|
||||
pulls.no_results=Nada encontrado.
|
||||
pulls.show_all_commits=Mostrar todos os commits
|
||||
pulls.show_changes_since_your_last_review=Mostrar alterações desde sua última revisão
|
||||
pulls.showing_only_single_commit=Mostrando apenas as alterações do commit %[1]s
|
||||
pulls.showing_specified_commit_range=Mostrando apenas as alterações entre %[1]s..%[2]s
|
||||
pulls.select_commit_hold_shift_for_range=Selecionar commit. Mantenha pressionado shift + clique para selecionar um intervalo
|
||||
pulls.review_only_possible_for_full_diff=A revisão só é possível ao visualizar todas as diferenças
|
||||
pulls.filter_changes_by_commit=Filtrar por commit
|
||||
pulls.nothing_to_compare=Estes branches são iguais. Não há nenhuma necessidade para criar um pull request.
|
||||
pulls.nothing_to_compare_and_allow_empty_pr=Estes branches são iguais. Este PR ficará vazio.
|
||||
pulls.has_pull_request=`Um pull request entre esses branches já existe: <a href="%[1]s">%[2]s#%[3]d</a>`
|
||||
@@ -1627,6 +1714,12 @@ pulls.is_empty=As alterações neste branch já estão na branch de destino. Est
|
||||
pulls.required_status_check_failed=Algumas verificações necessárias não foram bem sucedidas.
|
||||
pulls.required_status_check_missing=Estão faltando algumas verificações necessárias.
|
||||
pulls.required_status_check_administrator=Como administrador, você ainda pode aplicar o merge deste pull request.
|
||||
pulls.blocked_by_approvals=Este pull request ainda não tem aprovações suficientes. %d de %d aprovações concedidas.
|
||||
pulls.blocked_by_rejection=Este pull request tem alterações solicitadas por um revisor oficial.
|
||||
pulls.blocked_by_official_review_requests=Este pull request tem solicitações de revisão oficiais.
|
||||
pulls.blocked_by_outdated_branch=Este pull request está bloqueado porque está desatualizado.
|
||||
pulls.blocked_by_changed_protected_files_1=Este pull request está bloqueado porque altera um arquivo protegido:
|
||||
pulls.blocked_by_changed_protected_files_n=Este pull request está bloqueado porque altera arquivos protegidos:
|
||||
pulls.can_auto_merge_desc=O merge deste pull request pode ser aplicado automaticamente.
|
||||
pulls.cannot_auto_merge_desc=O merge deste pull request não pode ser aplicado automaticamente pois há conflitos.
|
||||
pulls.cannot_auto_merge_helper=Faça o merge manualmente para resolver os conflitos.
|
||||
@@ -1701,7 +1794,9 @@ pulls.auto_merge_canceled_schedule_comment=`cancelou o merge automático deste p
|
||||
pulls.delete.title=Excluir este pull request?
|
||||
pulls.delete.text=Você realmente deseja excluir este pull request? (Isto irá remover permanentemente todo o conteúdo. Considere fechá-la em vez disso, se você pretende mantê-la arquivado)
|
||||
|
||||
pulls.recently_pushed_new_branches=Você fez push no branch <strong>%[1]s</strong> %[2]s
|
||||
|
||||
pull.deleted_branch=(excluído):%s
|
||||
|
||||
milestones.new=Novo marco
|
||||
milestones.closed=Fechado %s
|
||||
@@ -1709,6 +1804,7 @@ milestones.update_ago=Atualizado há %s
|
||||
milestones.no_due_date=Sem data limite
|
||||
milestones.open=Reabrir
|
||||
milestones.close=Fechar
|
||||
milestones.new_subheader=Os marcos podem ajudá-lo a organizar os problemas e acompanhar seu progresso.
|
||||
milestones.completeness=%d%% concluído
|
||||
milestones.create=Criar marco
|
||||
milestones.title=Título
|
||||
@@ -1725,11 +1821,25 @@ milestones.edit_success=O marco "%s" foi atualizado.
|
||||
milestones.deletion=Excluir marco
|
||||
milestones.deletion_desc=A exclusão deste marco irá removê-lo de todas as issues. Tem certeza que deseja continuar?
|
||||
milestones.deletion_success=O marco foi excluído.
|
||||
milestones.filter_sort.earliest_due_data=Data limite mais próxima
|
||||
milestones.filter_sort.latest_due_date=Data limite mais distante
|
||||
milestones.filter_sort.least_complete=Menos completo
|
||||
milestones.filter_sort.most_complete=Mais completo
|
||||
milestones.filter_sort.most_issues=Com mais issues
|
||||
milestones.filter_sort.least_issues=Com menos issues
|
||||
|
||||
signing.will_sign=Esse commit será assinado com a chave "%s".
|
||||
signing.wont_sign.error=Ocorreu um erro ao verificar se o commit poderia ser assinado.
|
||||
signing.wont_sign.nokey=Não há nenhuma chave disponível para assinar esse commit.
|
||||
signing.wont_sign.never=Commits nunca são assinados.
|
||||
signing.wont_sign.always=Commits são sempre assinados.
|
||||
signing.wont_sign.pubkey=O commit não será assinado porque você não tem uma chave pública associada à sua conta.
|
||||
signing.wont_sign.twofa=Você deve ter a autenticação de dois fatores ativada para que os commits sejam assinados.
|
||||
signing.wont_sign.parentsigned=O commit não será assinado, pois o commit pai não está assinado.
|
||||
signing.wont_sign.basesigned=O merge não será assinado, pois o commit base não está assinado.
|
||||
signing.wont_sign.commitssigned=O merge não será assinado, pois todos os commits associados não estão assinados.
|
||||
signing.wont_sign.approved=O merge não será assinado porque o PR não foi aprovado.
|
||||
signing.wont_sign.not_signed_in=Você não está conectado.
|
||||
|
||||
ext_wiki=Acesso a Wiki Externo
|
||||
ext_wiki.desc=Link para uma wiki externa.
|
||||
@@ -1852,6 +1962,8 @@ settings.githooks=Hooks do Git
|
||||
settings.basic_settings=Configurações básicas
|
||||
settings.mirror_settings=Opções de espelhamento
|
||||
settings.mirror_settings.docs=Configure o seu repositório para sincronizar automaticamente commits, tags e branches de outro repositório.
|
||||
settings.mirror_settings.docs.disabled_push_mirror.pull_mirror_warning=No momento, isso só pode ser feito no menu "Nova migração". Para obter mais informações, consulte:
|
||||
settings.mirror_settings.docs.can_still_use=Embora não seja possível modificar os espelhos existentes ou criar novos espelhos, você ainda pode usar o espelho existente.
|
||||
settings.mirror_settings.docs.doc_link_title=Como posso espelhar repositórios?
|
||||
settings.mirror_settings.mirrored_repository=Repositório espelhado
|
||||
settings.mirror_settings.direction=Sentido
|
||||
@@ -1861,6 +1973,7 @@ settings.mirror_settings.last_update=Última atualização
|
||||
settings.mirror_settings.push_mirror.none=Nenhum espelhamento de push configurado
|
||||
settings.mirror_settings.push_mirror.remote_url=URL do repositório do Git remoto
|
||||
settings.mirror_settings.push_mirror.add=Adicionar Espelho de Push
|
||||
settings.mirror_settings.push_mirror.edit_sync_time=Editar intervalo de sincronização de espelhos
|
||||
|
||||
settings.sync_mirror=Sincronizar agora
|
||||
settings.site=Site
|
||||
@@ -2507,6 +2620,7 @@ users=Contas de usuário
|
||||
organizations=Organizações
|
||||
repositories=Repositórios
|
||||
hooks=Webhooks
|
||||
integrations=Integrações
|
||||
authentication=Fontes de autenticação
|
||||
emails=E-mails do Usuário
|
||||
config=Configuração
|
||||
@@ -2600,6 +2714,7 @@ users.full_name=Nome Completo
|
||||
users.activated=Ativado
|
||||
users.admin=Administrador
|
||||
users.restricted=Restrito
|
||||
users.remote=Remoto
|
||||
users.2fa=2FA
|
||||
users.repos=Repositórios
|
||||
users.created=Criado
|
||||
@@ -2646,6 +2761,7 @@ users.list_status_filter.is_prohibit_login=Proibir login
|
||||
users.list_status_filter.not_prohibit_login=Permitir login
|
||||
users.list_status_filter.is_2fa_enabled=2FA Ativado
|
||||
users.list_status_filter.not_2fa_enabled=2FA Desativado
|
||||
users.details=Detalhes do usuário
|
||||
|
||||
emails.email_manage_panel=Gerenciamento de E-mail de Usuário
|
||||
emails.primary=Principal
|
||||
@@ -2677,10 +2793,12 @@ repos.stars=Favoritos
|
||||
repos.forks=Forks
|
||||
repos.issues=Issues
|
||||
repos.size=Tamanho
|
||||
repos.lfs_size=Tamanho do LFS
|
||||
|
||||
packages.package_manage_panel=Gerenciamento de Pacotes
|
||||
packages.total_size=Tamanho Total: %s
|
||||
packages.unreferenced_size=Tamanho Não Referenciado: %s
|
||||
packages.cleanup=Limpar dados expirados
|
||||
packages.owner=Proprietário
|
||||
packages.creator=Criador
|
||||
packages.name=Nome
|
||||
@@ -2754,7 +2872,7 @@ auths.pam_email_domain=Domínio de e-mail do PAM (opcional)
|
||||
auths.oauth2_provider=Provedor OAuth2
|
||||
auths.oauth2_icon_url=URL do Ícone
|
||||
auths.oauth2_clientID=ID do cliente (chave)
|
||||
auths.oauth2_clientSecret=Senha do cliente
|
||||
auths.oauth2_clientSecret=Client Secret
|
||||
auths.openIdConnectAutoDiscoveryURL=URL do OpenID Connect Auto Discovery
|
||||
auths.oauth2_use_custom_url=Usar URLs personalizadas em vez de URLs padrão
|
||||
auths.oauth2_tokenURL=URL do Token
|
||||
@@ -2787,6 +2905,7 @@ auths.sspi_default_language=Idioma padrão do usuário
|
||||
auths.sspi_default_language_helper=Idioma padrão para usuários criados automaticamente pelo método de autenticação SSPI. Deixe em branco se você prefere que o idioma seja detectado automaticamente.
|
||||
auths.tips=Dicas
|
||||
auths.tips.oauth2.general=Autenticação OAuth2
|
||||
auths.tips.oauth2.general.tip=Ao registrar uma nova autenticação OAuth2, o URL de retorno de chamada/redirecionamento deve ser:
|
||||
auths.tip.oauth2_provider=Provedor OAuth2
|
||||
auths.tip.bitbucket=Cadastrar um novo consumidor de OAuth em https://bitbucket.org/account/user/<seu nome de usuário> e adicionar a permissão 'Account' - 'Read'
|
||||
auths.tip.nextcloud=`Registre um novo consumidor OAuth em sua instância usando o seguinte menu "Configurações -> Segurança -> Cliente OAuth 2.0"`
|
||||
@@ -2802,6 +2921,7 @@ auths.tip.yandex=`Crie um novo aplicativo em https://oauth.yandex.com/client/new
|
||||
auths.tip.mastodon=Insira a URL da instância personalizada do mastodon que você deseja usar para autenticar (ou use o padrão)
|
||||
auths.edit=Editar fonte de autenticação
|
||||
auths.activated=Esta fonte de autenticação está ativada
|
||||
auths.new_success=A fonte de autenticação "%s" foi adicionada.
|
||||
auths.update_success=A fonte de autenticação foi atualizada.
|
||||
auths.update=Atualizar fonte de autenticação
|
||||
auths.delete=Excluir fonte de autenticação
|
||||
@@ -2809,6 +2929,7 @@ auths.delete_auth_title=Excluir a Fonte de Autenticação
|
||||
auths.delete_auth_desc=A exclusão de uma fonte de autenticação impede que os usuários a usem para acessar. Continuar?
|
||||
auths.still_in_used=A fonte de autenticação ainda está em uso. Converta ou exclua todos os usuários que usam essa fonte de autenticação primeiro.
|
||||
auths.deletion_success=A fonte de autenticação foi excluída.
|
||||
auths.login_source_exist=A fonte de autenticação "%s" já existe.
|
||||
auths.login_source_of_type_exist=Uma fonte de autenticação deste tipo já existe.
|
||||
auths.unable_to_initialize_openid=Não é possível inicializar o Provedor OpenID Connect: %s
|
||||
auths.invalid_openIdConnectAutoDiscoveryURL=URL do Auto Discovery inválida (deve ser uma URL válida, começando com http:// ou https://)
|
||||
@@ -3185,6 +3306,8 @@ pub.install=Para instalar o pacote usando Dart, execute o seguinte comando:
|
||||
pypi.requires=Requer Python
|
||||
pypi.install=Para instalar o pacote usando pip, execute o seguinte comando:
|
||||
rpm.registry=Configure este registro pela linha de comando:
|
||||
rpm.distros.redhat=em distribuições baseadas no RedHat
|
||||
rpm.distros.suse=em distribuições baseadas no SUSE
|
||||
rpm.install=Para instalar o pacote, execute o seguinte comando:
|
||||
rubygems.install=Para instalar o pacote usando gem, execute o seguinte comando:
|
||||
rubygems.install2=ou adicione-o ao Gemfile:
|
||||
@@ -3261,6 +3384,7 @@ status.waiting=Em espera
|
||||
status.running=Rodando
|
||||
status.success=Sucesso
|
||||
status.failure=Falha
|
||||
status.cancelled=Cancelado
|
||||
status.skipped=Ignorado
|
||||
status.blocked=Bloqueado
|
||||
|
||||
@@ -3277,6 +3401,7 @@ runners.labels=Rótulos
|
||||
runners.last_online=Última Vez Online
|
||||
runners.runner_title=Runner
|
||||
runners.task_list=Tarefas recentes neste runner
|
||||
runners.task_list.no_tasks=Ainda não há nenhuma tarefa.
|
||||
runners.task_list.run=Executar
|
||||
runners.task_list.status=Status
|
||||
runners.task_list.repository=Repositório
|
||||
@@ -3301,6 +3426,7 @@ runners.reset_registration_token_success=Token de registro de runner redefinido
|
||||
|
||||
runs.all_workflows=Todos os Workflows
|
||||
runs.commit=Commit
|
||||
runs.pushed_by=push feito por
|
||||
runs.invalid_workflow_helper=O arquivo de configuração do workflow é inválido. Por favor, verifique seu arquivo de configuração: %s
|
||||
runs.no_matching_runner_helper=Nenhum runner correspondente: %s
|
||||
runs.status=Status
|
||||
|
||||
@@ -77,20 +77,24 @@ milestones=Míľniky
|
||||
|
||||
ok=OK
|
||||
cancel=Zrušiť
|
||||
retry=Opakovať
|
||||
save=Uložiť
|
||||
add=Pridať
|
||||
add_all=Pridať všetko
|
||||
remove=Odstrániť
|
||||
remove_all=Odstrániť všetko
|
||||
remove_label_str=Odstrániť položku „%s“
|
||||
edit=Upraviť
|
||||
|
||||
enabled=Povolené
|
||||
|
||||
copy=Kopírovať
|
||||
copy_url=Kopírovať URL
|
||||
copy_content=Kopírovať obsah
|
||||
copy_branch=Kopírovať meno vetvy
|
||||
copy_success=Skopírované!
|
||||
copy_error=Kopírovanie zlyhalo
|
||||
copy_type_unsupported=Tento typ súboru nie je možné skopírovať
|
||||
|
||||
write=Zapísať
|
||||
preview=Náhľad
|
||||
|
||||
Generated
+645
-524
File diff suppressed because it is too large
Load Diff
+20
-19
@@ -5,8 +5,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@citation-js/core": "0.7.1",
|
||||
"@citation-js/plugin-bibtex": "0.7.1",
|
||||
"@citation-js/plugin-csl": "0.7.1",
|
||||
"@citation-js/plugin-bibtex": "0.7.2",
|
||||
"@citation-js/plugin-csl": "0.7.2",
|
||||
"@citation-js/plugin-software-formats": "0.6.1",
|
||||
"@claviska/jquery-minicolors": "2.3.6",
|
||||
"@github/markdown-toolbar-element": "2.2.1",
|
||||
@@ -17,7 +17,7 @@
|
||||
"@webcomponents/custom-elements": "1.6.0",
|
||||
"add-asset-webpack-plugin": "2.0.1",
|
||||
"ansi_up": "6.0.2",
|
||||
"asciinema-player": "3.6.2",
|
||||
"asciinema-player": "3.6.3",
|
||||
"clippie": "4.0.6",
|
||||
"css-loader": "6.8.1",
|
||||
"dropzone": "6.0.0-beta.2",
|
||||
@@ -29,7 +29,7 @@
|
||||
"katex": "0.16.9",
|
||||
"license-checker-webpack-plugin": "0.2.1",
|
||||
"lightningcss-loader": "2.1.0",
|
||||
"mermaid": "10.5.0",
|
||||
"mermaid": "10.6.0",
|
||||
"mini-css-extract-plugin": "2.7.6",
|
||||
"minimatch": "9.0.3",
|
||||
"monaco-editor": "0.44.0",
|
||||
@@ -37,49 +37,50 @@
|
||||
"pdfobject": "2.2.12",
|
||||
"pretty-ms": "8.0.0",
|
||||
"sortablejs": "1.15.0",
|
||||
"swagger-ui-dist": "5.9.0",
|
||||
"swagger-ui-dist": "5.9.1",
|
||||
"throttle-debounce": "5.0.0",
|
||||
"tinycolor2": "1.6.0",
|
||||
"tippy.js": "6.3.7",
|
||||
"toastify-js": "1.12.0",
|
||||
"tributejs": "5.1.3",
|
||||
"uint8-to-base64": "0.2.0",
|
||||
"vue": "3.3.4",
|
||||
"vue": "3.3.7",
|
||||
"vue-bar-graph": "2.0.0",
|
||||
"vue-loader": "17.3.0",
|
||||
"vue-loader": "17.3.1",
|
||||
"vue3-calendar-heatmap": "2.0.5",
|
||||
"webpack": "5.88.2",
|
||||
"webpack": "5.89.0",
|
||||
"webpack-cli": "5.1.4",
|
||||
"wrap-ansi": "8.1.0"
|
||||
"wrap-ansi": "9.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint-community/eslint-plugin-eslint-comments": "4.1.0",
|
||||
"@playwright/test": "1.38.1",
|
||||
"@playwright/test": "1.39.0",
|
||||
"@stoplight/spectral-cli": "6.11.0",
|
||||
"@stylistic/eslint-plugin-js": "1.0.0",
|
||||
"@vitejs/plugin-vue": "4.4.0",
|
||||
"eslint": "8.51.0",
|
||||
"eslint": "8.53.0",
|
||||
"eslint-plugin-array-func": "4.0.0",
|
||||
"eslint-plugin-i": "2.28.1",
|
||||
"eslint-plugin-i": "2.29.0",
|
||||
"eslint-plugin-jquery": "1.5.1",
|
||||
"eslint-plugin-no-jquery": "2.7.0",
|
||||
"eslint-plugin-no-use-extend-native": "0.5.0",
|
||||
"eslint-plugin-regexp": "2.0.0",
|
||||
"eslint-plugin-sonarjs": "0.21.0",
|
||||
"eslint-plugin-unicorn": "48.0.1",
|
||||
"eslint-plugin-vitest": "0.3.2",
|
||||
"eslint-plugin-regexp": "2.1.1",
|
||||
"eslint-plugin-sonarjs": "0.23.0",
|
||||
"eslint-plugin-unicorn": "49.0.0",
|
||||
"eslint-plugin-vitest": "0.3.9",
|
||||
"eslint-plugin-vitest-globals": "1.4.0",
|
||||
"eslint-plugin-vue": "9.17.0",
|
||||
"eslint-plugin-vue": "9.18.1",
|
||||
"eslint-plugin-vue-scoped-css": "2.5.1",
|
||||
"eslint-plugin-wc": "2.0.4",
|
||||
"jsdom": "22.1.0",
|
||||
"markdownlint-cli": "0.37.0",
|
||||
"postcss-html": "1.5.0",
|
||||
"stylelint": "15.10.3",
|
||||
"stylelint": "15.11.0",
|
||||
"stylelint-declaration-block-no-ignored-properties": "2.7.0",
|
||||
"stylelint-declaration-strict-value": "1.9.2",
|
||||
"stylelint-stylistic": "0.4.3",
|
||||
"svgo": "3.0.2",
|
||||
"updates": "15.0.2",
|
||||
"updates": "15.0.4",
|
||||
"vite-string-plugin": "1.1.2",
|
||||
"vitest": "0.34.6"
|
||||
},
|
||||
|
||||
Generated
+1
-1
@@ -1,4 +1,4 @@
|
||||
# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand.
|
||||
# This file is automatically @generated by Poetry 1.7.0 and should not be changed by hand.
|
||||
|
||||
[[package]]
|
||||
name = "click"
|
||||
|
||||
@@ -58,7 +58,8 @@ func validateArtifactHash(ctx *ArtifactContext, artifactName string) bool {
|
||||
func parseArtifactItemPath(ctx *ArtifactContext) (string, string, bool) {
|
||||
// itemPath is generated from upload-artifact action
|
||||
// it's formatted as {artifact_name}/{artfict_path_in_runner}
|
||||
itemPath := util.PathJoinRel(ctx.Req.URL.Query().Get("itemPath"))
|
||||
// act_runner in host mode on Windows, itemPath is joined by Windows slash '\'
|
||||
itemPath := util.PathJoinRelX(ctx.Req.URL.Query().Get("itemPath"))
|
||||
artifactName := strings.Split(itemPath, "/")[0]
|
||||
artifactPath := strings.TrimPrefix(itemPath, artifactName+"/")
|
||||
if !validateArtifactHash(ctx, artifactName) {
|
||||
|
||||
+1
-37
@@ -316,10 +316,6 @@ func reqToken() func(ctx *context.APIContext) {
|
||||
return
|
||||
}
|
||||
|
||||
if ctx.IsBasicAuth {
|
||||
ctx.CheckForOTP()
|
||||
return
|
||||
}
|
||||
if ctx.IsSigned {
|
||||
return
|
||||
}
|
||||
@@ -344,7 +340,6 @@ func reqBasicOrRevProxyAuth() func(ctx *context.APIContext) {
|
||||
ctx.Error(http.StatusUnauthorized, "reqBasicAuth", "auth required")
|
||||
return
|
||||
}
|
||||
ctx.CheckForOTP()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -701,12 +696,6 @@ func bind[T any](_ T) any {
|
||||
}
|
||||
}
|
||||
|
||||
// The OAuth2 plugin is expected to be executed first, as it must ignore the user id stored
|
||||
// in the session (if there is a user id stored in session other plugins might return the user
|
||||
// object for that id).
|
||||
//
|
||||
// The Session plugin is expected to be executed second, in order to skip authentication
|
||||
// for users that have already signed in.
|
||||
func buildAuthGroup() *auth.Group {
|
||||
group := auth.NewGroup(
|
||||
&auth.OAuth2{},
|
||||
@@ -786,31 +775,6 @@ func verifyAuthWithOptions(options *common.VerifyOptions) func(ctx *context.APIC
|
||||
})
|
||||
return
|
||||
}
|
||||
if ctx.IsSigned && ctx.IsBasicAuth {
|
||||
if skip, ok := ctx.Data["SkipLocalTwoFA"]; ok && skip.(bool) {
|
||||
return // Skip 2FA
|
||||
}
|
||||
twofa, err := auth_model.GetTwoFactorByUID(ctx, ctx.Doer.ID)
|
||||
if err != nil {
|
||||
if auth_model.IsErrTwoFactorNotEnrolled(err) {
|
||||
return // No 2FA enrollment for this user
|
||||
}
|
||||
ctx.InternalServerError(err)
|
||||
return
|
||||
}
|
||||
otpHeader := ctx.Req.Header.Get("X-Gitea-OTP")
|
||||
ok, err := twofa.ValidateTOTP(otpHeader)
|
||||
if err != nil {
|
||||
ctx.InternalServerError(err)
|
||||
return
|
||||
}
|
||||
if !ok {
|
||||
ctx.JSON(http.StatusForbidden, map[string]string{
|
||||
"message": "Only signed in user is allowed to call APIs.",
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if options.AdminRequired {
|
||||
@@ -961,7 +925,7 @@ func Routes() *web.Route {
|
||||
m.Group("/actions/secrets", func() {
|
||||
m.Combo("/{secretname}").
|
||||
Put(bind(api.CreateOrUpdateSecretOption{}), user.CreateOrUpdateSecret).
|
||||
Delete(repo.DeleteSecret)
|
||||
Delete(user.DeleteSecret)
|
||||
})
|
||||
|
||||
m.Get("/followers", user.ListMyFollowers)
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/modules/context"
|
||||
"code.gitea.io/gitea/modules/httpcache"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
@@ -35,20 +36,18 @@ func RenderPanicErrorPage(w http.ResponseWriter, req *http.Request, err any) {
|
||||
httpcache.SetCacheControlInHeader(w.Header(), 0, "no-transform")
|
||||
w.Header().Set(`X-Frame-Options`, setting.CORSConfig.XFrameOptions)
|
||||
|
||||
data := middleware.GetContextData(req.Context())
|
||||
if data["locale"] == nil {
|
||||
data = middleware.CommonTemplateContextData()
|
||||
data["locale"] = middleware.Locale(w, req)
|
||||
}
|
||||
tmplCtx := context.TemplateContext{}
|
||||
tmplCtx["Locale"] = middleware.Locale(w, req)
|
||||
ctxData := middleware.GetContextData(req.Context())
|
||||
|
||||
// This recovery handler could be called without Gitea's web context, so we shouldn't touch that context too much.
|
||||
// Otherwise, the 500-page may cause new panics, eg: cache.GetContextWithData, it makes the developer&users couldn't find the original panic.
|
||||
user, _ := data[middleware.ContextDataKeySignedUser].(*user_model.User)
|
||||
user, _ := ctxData[middleware.ContextDataKeySignedUser].(*user_model.User)
|
||||
if !setting.IsProd || (user != nil && user.IsAdmin) {
|
||||
data["ErrorMsg"] = "PANIC: " + combinedErr
|
||||
ctxData["ErrorMsg"] = "PANIC: " + combinedErr
|
||||
}
|
||||
|
||||
err = templates.HTMLRenderer().HTML(w, http.StatusInternalServerError, string(tplStatus500), data, nil)
|
||||
err = templates.HTMLRenderer().HTML(w, http.StatusInternalServerError, string(tplStatus500), ctxData, tmplCtx)
|
||||
if err != nil {
|
||||
log.Error("Error occurs again when rendering error page: %v", err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
|
||||
@@ -26,6 +26,7 @@ func TestRenderPanicErrorPage(t *testing.T) {
|
||||
respContent := w.Body.String()
|
||||
assert.Contains(t, respContent, `class="page-content status-page-500"`)
|
||||
assert.Contains(t, respContent, `</html>`)
|
||||
assert.Contains(t, respContent, `lang="en-US"`) // make sure the locale work
|
||||
|
||||
// the 500 page doesn't have normal pages footer, it makes it easier to distinguish a normal page and a failed page.
|
||||
// especially when a sub-template causes page error, the HTTP response code is still 200,
|
||||
|
||||
@@ -48,13 +48,13 @@ func Authentications(ctx *context.Context) {
|
||||
ctx.Data["PageIsAdminAuthentications"] = true
|
||||
|
||||
var err error
|
||||
ctx.Data["Sources"], err = auth.Sources(ctx)
|
||||
ctx.Data["Sources"], err = auth.FindSources(ctx, auth.FindSourcesOptions{})
|
||||
if err != nil {
|
||||
ctx.ServerError("auth.Sources", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Data["Total"] = auth.CountSources(ctx)
|
||||
ctx.Data["Total"] = auth.CountSources(ctx, auth.FindSourcesOptions{})
|
||||
ctx.HTML(http.StatusOK, tplAuths)
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ func NewAuthSource(ctx *context.Context) {
|
||||
ctx.Data["AuthSources"] = authSources
|
||||
ctx.Data["SecurityProtocols"] = securityProtocols
|
||||
ctx.Data["SMTPAuths"] = smtp.Authenticators
|
||||
oauth2providers := oauth2.GetOAuth2Providers()
|
||||
oauth2providers := oauth2.GetSupportedOAuth2Providers()
|
||||
ctx.Data["OAuth2Providers"] = oauth2providers
|
||||
|
||||
ctx.Data["SSPIAutoCreateUsers"] = true
|
||||
@@ -242,7 +242,7 @@ func NewAuthSourcePost(ctx *context.Context) {
|
||||
ctx.Data["AuthSources"] = authSources
|
||||
ctx.Data["SecurityProtocols"] = securityProtocols
|
||||
ctx.Data["SMTPAuths"] = smtp.Authenticators
|
||||
oauth2providers := oauth2.GetOAuth2Providers()
|
||||
oauth2providers := oauth2.GetSupportedOAuth2Providers()
|
||||
ctx.Data["OAuth2Providers"] = oauth2providers
|
||||
|
||||
ctx.Data["SSPIAutoCreateUsers"] = true
|
||||
@@ -284,7 +284,7 @@ func NewAuthSourcePost(ctx *context.Context) {
|
||||
ctx.RenderWithErr(err.Error(), tplAuthNew, form)
|
||||
return
|
||||
}
|
||||
existing, err := auth.SourcesByType(ctx, auth.SSPI)
|
||||
existing, err := auth.FindSources(ctx, auth.FindSourcesOptions{LoginType: auth.SSPI})
|
||||
if err != nil || len(existing) > 0 {
|
||||
ctx.Data["Err_Type"] = true
|
||||
ctx.RenderWithErr(ctx.Tr("admin.auths.login_source_of_type_exist"), tplAuthNew, form)
|
||||
@@ -334,7 +334,7 @@ func EditAuthSource(ctx *context.Context) {
|
||||
|
||||
ctx.Data["SecurityProtocols"] = securityProtocols
|
||||
ctx.Data["SMTPAuths"] = smtp.Authenticators
|
||||
oauth2providers := oauth2.GetOAuth2Providers()
|
||||
oauth2providers := oauth2.GetSupportedOAuth2Providers()
|
||||
ctx.Data["OAuth2Providers"] = oauth2providers
|
||||
|
||||
source, err := auth.GetSourceByID(ctx, ctx.ParamsInt64(":authid"))
|
||||
@@ -368,7 +368,7 @@ func EditAuthSourcePost(ctx *context.Context) {
|
||||
ctx.Data["PageIsAdminAuthentications"] = true
|
||||
|
||||
ctx.Data["SMTPAuths"] = smtp.Authenticators
|
||||
oauth2providers := oauth2.GetOAuth2Providers()
|
||||
oauth2providers := oauth2.GetSupportedOAuth2Providers()
|
||||
ctx.Data["OAuth2Providers"] = oauth2providers
|
||||
|
||||
source, err := auth.GetSourceByID(ctx, ctx.ParamsInt64(":authid"))
|
||||
|
||||
@@ -90,7 +90,9 @@ func NewUser(ctx *context.Context) {
|
||||
|
||||
ctx.Data["login_type"] = "0-0"
|
||||
|
||||
sources, err := auth.Sources(ctx)
|
||||
sources, err := auth.FindSources(ctx, auth.FindSourcesOptions{
|
||||
IsActive: util.OptionalBoolTrue,
|
||||
})
|
||||
if err != nil {
|
||||
ctx.ServerError("auth.Sources", err)
|
||||
return
|
||||
@@ -109,7 +111,9 @@ func NewUserPost(ctx *context.Context) {
|
||||
ctx.Data["DefaultUserVisibilityMode"] = setting.Service.DefaultUserVisibilityMode
|
||||
ctx.Data["AllowedUserVisibilityModes"] = setting.Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice()
|
||||
|
||||
sources, err := auth.Sources(ctx)
|
||||
sources, err := auth.FindSources(ctx, auth.FindSourcesOptions{
|
||||
IsActive: util.OptionalBoolTrue,
|
||||
})
|
||||
if err != nil {
|
||||
ctx.ServerError("auth.Sources", err)
|
||||
return
|
||||
@@ -230,7 +234,7 @@ func prepareUserInfo(ctx *context.Context) *user_model.User {
|
||||
ctx.Data["LoginSource"] = &auth.Source{}
|
||||
}
|
||||
|
||||
sources, err := auth.Sources(ctx)
|
||||
sources, err := auth.FindSources(ctx, auth.FindSourcesOptions{})
|
||||
if err != nil {
|
||||
ctx.ServerError("auth.Sources", err)
|
||||
return nil
|
||||
|
||||
@@ -160,12 +160,11 @@ func SignIn(ctx *context.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
orderedOAuth2Names, oauth2Providers, err := oauth2.GetActiveOAuth2Providers(ctx)
|
||||
oauth2Providers, err := oauth2.GetOAuth2Providers(ctx, util.OptionalBoolTrue)
|
||||
if err != nil {
|
||||
ctx.ServerError("UserSignIn", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["OrderedOAuth2Names"] = orderedOAuth2Names
|
||||
ctx.Data["OAuth2Providers"] = oauth2Providers
|
||||
ctx.Data["Title"] = ctx.Tr("sign_in")
|
||||
ctx.Data["SignInLink"] = setting.AppSubURL + "/user/login"
|
||||
@@ -184,12 +183,11 @@ func SignIn(ctx *context.Context) {
|
||||
func SignInPost(ctx *context.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("sign_in")
|
||||
|
||||
orderedOAuth2Names, oauth2Providers, err := oauth2.GetActiveOAuth2Providers(ctx)
|
||||
oauth2Providers, err := oauth2.GetOAuth2Providers(ctx, util.OptionalBoolTrue)
|
||||
if err != nil {
|
||||
ctx.ServerError("UserSignIn", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["OrderedOAuth2Names"] = orderedOAuth2Names
|
||||
ctx.Data["OAuth2Providers"] = oauth2Providers
|
||||
ctx.Data["Title"] = ctx.Tr("sign_in")
|
||||
ctx.Data["SignInLink"] = setting.AppSubURL + "/user/login"
|
||||
@@ -408,13 +406,12 @@ func SignUp(ctx *context.Context) {
|
||||
|
||||
ctx.Data["SignUpLink"] = setting.AppSubURL + "/user/sign_up"
|
||||
|
||||
orderedOAuth2Names, oauth2Providers, err := oauth2.GetActiveOAuth2Providers(ctx)
|
||||
oauth2Providers, err := oauth2.GetOAuth2Providers(ctx, util.OptionalBoolTrue)
|
||||
if err != nil {
|
||||
ctx.ServerError("UserSignUp", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Data["OrderedOAuth2Names"] = orderedOAuth2Names
|
||||
ctx.Data["OAuth2Providers"] = oauth2Providers
|
||||
context.SetCaptchaData(ctx)
|
||||
|
||||
@@ -438,13 +435,12 @@ func SignUpPost(ctx *context.Context) {
|
||||
|
||||
ctx.Data["SignUpLink"] = setting.AppSubURL + "/user/sign_up"
|
||||
|
||||
orderedOAuth2Names, oauth2Providers, err := oauth2.GetActiveOAuth2Providers(ctx)
|
||||
oauth2Providers, err := oauth2.GetOAuth2Providers(ctx, util.OptionalBoolTrue)
|
||||
if err != nil {
|
||||
ctx.ServerError("UserSignUp", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Data["OrderedOAuth2Names"] = orderedOAuth2Names
|
||||
ctx.Data["OAuth2Providers"] = oauth2Providers
|
||||
context.SetCaptchaData(ctx)
|
||||
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package web
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"code.gitea.io/gitea/modules/context"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/web"
|
||||
"code.gitea.io/gitea/routers/web/repo"
|
||||
context_service "code.gitea.io/gitea/services/context"
|
||||
)
|
||||
|
||||
func requireSignIn(ctx *context.Context) {
|
||||
if !setting.Service.RequireSignInView {
|
||||
return
|
||||
}
|
||||
|
||||
// rely on the results of Contexter
|
||||
if !ctx.IsSigned {
|
||||
// TODO: support digit auth - which would be Authorization header with digit
|
||||
ctx.Resp.Header().Set("WWW-Authenticate", `Basic realm="Gitea"`)
|
||||
ctx.Error(http.StatusUnauthorized)
|
||||
}
|
||||
}
|
||||
|
||||
func gitHTTPRouters(m *web.Route) {
|
||||
m.Group("", func() {
|
||||
m.PostOptions("/git-upload-pack", repo.ServiceUploadPack)
|
||||
m.PostOptions("/git-receive-pack", repo.ServiceReceivePack)
|
||||
m.GetOptions("/info/refs", repo.GetInfoRefs)
|
||||
m.GetOptions("/HEAD", repo.GetTextFile("HEAD"))
|
||||
m.GetOptions("/objects/info/alternates", repo.GetTextFile("objects/info/alternates"))
|
||||
m.GetOptions("/objects/info/http-alternates", repo.GetTextFile("objects/info/http-alternates"))
|
||||
m.GetOptions("/objects/info/packs", repo.GetInfoPacks)
|
||||
m.GetOptions("/objects/info/{file:[^/]*}", repo.GetTextFile(""))
|
||||
m.GetOptions("/objects/{head:[0-9a-f]{2}}/{hash:[0-9a-f]{38}}", repo.GetLooseObject)
|
||||
m.GetOptions("/objects/pack/pack-{file:[0-9a-f]{40}}.pack", repo.GetPackFile)
|
||||
m.GetOptions("/objects/pack/pack-{file:[0-9a-f]{40}}.idx", repo.GetIdxFile)
|
||||
}, ignSignInAndCsrf, requireSignIn, repo.HTTPGitEnabledHandler, repo.CorsHandler(), context_service.UserAssignmentWeb())
|
||||
}
|
||||
@@ -1773,7 +1773,7 @@ func ViewIssue(ctx *context.Context) {
|
||||
pull := issue.PullRequest
|
||||
pull.Issue = issue
|
||||
canDelete := false
|
||||
ctx.Data["AllowMerge"] = false
|
||||
allowMerge := false
|
||||
|
||||
if ctx.IsSigned {
|
||||
if err := pull.LoadHeadRepo(ctx); err != nil {
|
||||
@@ -1806,7 +1806,7 @@ func ViewIssue(ctx *context.Context) {
|
||||
ctx.ServerError("GetUserRepoPermission", err)
|
||||
return
|
||||
}
|
||||
ctx.Data["AllowMerge"], err = pull_service.IsUserAllowedToMerge(ctx, pull, perm, ctx.Doer)
|
||||
allowMerge, err = pull_service.IsUserAllowedToMerge(ctx, pull, perm, ctx.Doer)
|
||||
if err != nil {
|
||||
ctx.ServerError("IsUserAllowedToMerge", err)
|
||||
return
|
||||
@@ -1818,6 +1818,8 @@ func ViewIssue(ctx *context.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
ctx.Data["AllowMerge"] = allowMerge
|
||||
|
||||
prUnit, err := repo.GetUnit(ctx, unit.TypePullRequests)
|
||||
if err != nil {
|
||||
ctx.ServerError("GetUnit", err)
|
||||
@@ -1927,7 +1929,7 @@ func ViewIssue(ctx *context.Context) {
|
||||
if pull.CanAutoMerge() || pull.IsWorkInProgress(ctx) || pull.IsChecking() {
|
||||
return false
|
||||
}
|
||||
if (ctx.Doer.IsAdmin || ctx.Repo.IsAdmin()) && prConfig.AllowManualMerge {
|
||||
if allowMerge && prConfig.AllowManualMerge {
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@@ -716,14 +716,11 @@ func checkCitationFile(ctx *context.Context, entry *git.TreeEntry) {
|
||||
return
|
||||
}
|
||||
defer dataRc.Close()
|
||||
buf := make([]byte, 1024)
|
||||
n, err := util.ReadAtMost(dataRc, buf)
|
||||
ctx.PageData["citationFileContent"], err = blob.GetBlobContent(setting.UI.MaxDisplayFileSize)
|
||||
if err != nil {
|
||||
ctx.ServerError("ReadAtMost", err)
|
||||
ctx.ServerError("GetBlobContent", err)
|
||||
return
|
||||
}
|
||||
buf = buf[:n]
|
||||
ctx.PageData["citationFileContent"] = string(buf)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,12 +6,14 @@ package security
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"sort"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/modules/context"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/services/auth/source/oauth2"
|
||||
)
|
||||
|
||||
@@ -105,11 +107,31 @@ func loadSecurityData(ctx *context.Context) {
|
||||
}
|
||||
ctx.Data["AccountLinks"] = sources
|
||||
|
||||
orderedOAuth2Names, oauth2Providers, err := oauth2.GetActiveOAuth2Providers(ctx)
|
||||
authSources, err := auth_model.FindSources(ctx, auth_model.FindSourcesOptions{
|
||||
IsActive: util.OptionalBoolNone,
|
||||
LoginType: auth_model.OAuth2,
|
||||
})
|
||||
if err != nil {
|
||||
ctx.ServerError("GetActiveOAuth2Providers", err)
|
||||
ctx.ServerError("FindSources", err)
|
||||
return
|
||||
}
|
||||
|
||||
var orderedOAuth2Names []string
|
||||
oauth2Providers := make(map[string]oauth2.Provider)
|
||||
for _, source := range authSources {
|
||||
provider, err := oauth2.CreateProviderFromSource(source)
|
||||
if err != nil {
|
||||
ctx.ServerError("CreateProviderFromSource", err)
|
||||
return
|
||||
}
|
||||
oauth2Providers[source.Name] = provider
|
||||
if source.IsActive {
|
||||
orderedOAuth2Names = append(orderedOAuth2Names, source.Name)
|
||||
}
|
||||
}
|
||||
|
||||
sort.Strings(orderedOAuth2Names)
|
||||
|
||||
ctx.Data["OrderedOAuth2Names"] = orderedOAuth2Names
|
||||
ctx.Data["OAuth2Providers"] = oauth2Providers
|
||||
|
||||
|
||||
+4
-14
@@ -276,6 +276,8 @@ func Routes() *web.Route {
|
||||
return routes
|
||||
}
|
||||
|
||||
var ignSignInAndCsrf = verifyAuthWithOptions(&common.VerifyOptions{DisableCSRF: true})
|
||||
|
||||
// registerRoutes register routes
|
||||
func registerRoutes(m *web.Route) {
|
||||
reqSignIn := verifyAuthWithOptions(&common.VerifyOptions{SignInRequired: true})
|
||||
@@ -283,7 +285,7 @@ func registerRoutes(m *web.Route) {
|
||||
// TODO: rename them to "optSignIn", which means that the "sign-in" could be optional, depends on the VerifyOptions (RequireSignInView)
|
||||
ignSignIn := verifyAuthWithOptions(&common.VerifyOptions{SignInRequired: setting.Service.RequireSignInView})
|
||||
ignExploreSignIn := verifyAuthWithOptions(&common.VerifyOptions{SignInRequired: setting.Service.RequireSignInView || setting.Service.Explore.RequireSigninView})
|
||||
ignSignInAndCsrf := verifyAuthWithOptions(&common.VerifyOptions{DisableCSRF: true})
|
||||
|
||||
validation.AddBindingRules()
|
||||
|
||||
linkAccountEnabled := func(ctx *context.Context) {
|
||||
@@ -1513,19 +1515,7 @@ func registerRoutes(m *web.Route) {
|
||||
})
|
||||
}, ignSignInAndCsrf, lfsServerEnabled)
|
||||
|
||||
m.Group("", func() {
|
||||
m.PostOptions("/git-upload-pack", repo.ServiceUploadPack)
|
||||
m.PostOptions("/git-receive-pack", repo.ServiceReceivePack)
|
||||
m.GetOptions("/info/refs", repo.GetInfoRefs)
|
||||
m.GetOptions("/HEAD", repo.GetTextFile("HEAD"))
|
||||
m.GetOptions("/objects/info/alternates", repo.GetTextFile("objects/info/alternates"))
|
||||
m.GetOptions("/objects/info/http-alternates", repo.GetTextFile("objects/info/http-alternates"))
|
||||
m.GetOptions("/objects/info/packs", repo.GetInfoPacks)
|
||||
m.GetOptions("/objects/info/{file:[^/]*}", repo.GetTextFile(""))
|
||||
m.GetOptions("/objects/{head:[0-9a-f]{2}}/{hash:[0-9a-f]{38}}", repo.GetLooseObject)
|
||||
m.GetOptions("/objects/pack/pack-{file:[0-9a-f]{40}}.pack", repo.GetPackFile)
|
||||
m.GetOptions("/objects/pack/pack-{file:[0-9a-f]{40}}.idx", repo.GetIdxFile)
|
||||
}, ignSignInAndCsrf, repo.HTTPGitEnabledHandler, repo.CorsHandler(), context_service.UserAssignmentWeb())
|
||||
gitHTTPRouters(m)
|
||||
})
|
||||
})
|
||||
// ***** END: Repository *****
|
||||
|
||||
+22
-2
@@ -15,6 +15,7 @@ import (
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/modules/web/middleware"
|
||||
)
|
||||
|
||||
@@ -131,11 +132,30 @@ func (b *Basic) Verify(req *http.Request, w http.ResponseWriter, store DataStore
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if skipper, ok := source.Cfg.(LocalTwoFASkipper); ok && skipper.IsSkipLocalTwoFA() {
|
||||
store.GetData()["SkipLocalTwoFA"] = true
|
||||
if skipper, ok := source.Cfg.(LocalTwoFASkipper); !ok || !skipper.IsSkipLocalTwoFA() {
|
||||
if err := validateTOTP(req, u); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
log.Trace("Basic Authorization: Logged in user %-v", u)
|
||||
|
||||
return u, nil
|
||||
}
|
||||
|
||||
func validateTOTP(req *http.Request, u *user_model.User) error {
|
||||
twofa, err := auth_model.GetTwoFactorByUID(req.Context(), u.ID)
|
||||
if err != nil {
|
||||
if auth_model.IsErrTwoFactorNotEnrolled(err) {
|
||||
// No 2FA enrollment for this user
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
if ok, err := twofa.ValidateTOTP(req.Header.Get("X-Gitea-OTP")); err != nil {
|
||||
return err
|
||||
} else if !ok {
|
||||
return util.NewInvalidArgumentErrorf("invalid provided OTP")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"code.gitea.io/gitea/models/db"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/services/auth/source/oauth2"
|
||||
"code.gitea.io/gitea/services/auth/source/smtp"
|
||||
|
||||
@@ -85,7 +86,9 @@ func UserSignIn(ctx context.Context, username, password string) (*user_model.Use
|
||||
}
|
||||
}
|
||||
|
||||
sources, err := auth.AllActiveSources(ctx)
|
||||
sources, err := auth.FindSources(ctx, auth.FindSourcesOptions{
|
||||
IsActive: util.OptionalBoolTrue,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/gorilla/sessions"
|
||||
@@ -63,7 +64,13 @@ func ResetOAuth2(ctx context.Context) error {
|
||||
|
||||
// initOAuth2Sources is used to load and register all active OAuth2 providers
|
||||
func initOAuth2Sources(ctx context.Context) error {
|
||||
authSources, _ := auth.GetActiveOAuth2ProviderSources(ctx)
|
||||
authSources, err := auth.FindSources(ctx, auth.FindSourcesOptions{
|
||||
IsActive: util.OptionalBoolTrue,
|
||||
LoginType: auth.OAuth2,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, source := range authSources {
|
||||
oauth2Source, ok := source.Cfg.(*Source)
|
||||
if !ok {
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"github.com/markbates/goth"
|
||||
)
|
||||
@@ -80,10 +81,10 @@ func RegisterGothProvider(provider GothProvider) {
|
||||
gothProviders[provider.Name()] = provider
|
||||
}
|
||||
|
||||
// GetOAuth2Providers returns the map of unconfigured OAuth2 providers
|
||||
// GetSupportedOAuth2Providers returns the map of unconfigured OAuth2 providers
|
||||
// key is used as technical name (like in the callbackURL)
|
||||
// values to display
|
||||
func GetOAuth2Providers() []Provider {
|
||||
func GetSupportedOAuth2Providers() []Provider {
|
||||
providers := make([]Provider, 0, len(gothProviders))
|
||||
|
||||
for _, provider := range gothProviders {
|
||||
@@ -95,33 +96,39 @@ func GetOAuth2Providers() []Provider {
|
||||
return providers
|
||||
}
|
||||
|
||||
// GetActiveOAuth2Providers returns the map of configured active OAuth2 providers
|
||||
// key is used as technical name (like in the callbackURL)
|
||||
// values to display
|
||||
func GetActiveOAuth2Providers(ctx context.Context) ([]string, map[string]Provider, error) {
|
||||
// Maybe also separate used and unused providers so we can force the registration of only 1 active provider for each type
|
||||
func CreateProviderFromSource(source *auth.Source) (Provider, error) {
|
||||
oauth2Cfg, ok := source.Cfg.(*Source)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid OAuth2 source config: %v", oauth2Cfg)
|
||||
}
|
||||
gothProv := gothProviders[oauth2Cfg.Provider]
|
||||
return &AuthSourceProvider{GothProvider: gothProv, sourceName: source.Name, iconURL: oauth2Cfg.IconURL}, nil
|
||||
}
|
||||
|
||||
authSources, err := auth.GetActiveOAuth2ProviderSources(ctx)
|
||||
// GetOAuth2Providers returns the list of configured OAuth2 providers
|
||||
func GetOAuth2Providers(ctx context.Context, isActive util.OptionalBool) ([]Provider, error) {
|
||||
authSources, err := auth.FindSources(ctx, auth.FindSourcesOptions{
|
||||
IsActive: isActive,
|
||||
LoginType: auth.OAuth2,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var orderedKeys []string
|
||||
providers := make(map[string]Provider)
|
||||
providers := make([]Provider, 0, len(authSources))
|
||||
for _, source := range authSources {
|
||||
oauth2Cfg, ok := source.Cfg.(*Source)
|
||||
if !ok {
|
||||
log.Error("Invalid OAuth2 source config: %v", oauth2Cfg)
|
||||
continue
|
||||
provider, err := CreateProviderFromSource(source)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
gothProv := gothProviders[oauth2Cfg.Provider]
|
||||
providers[source.Name] = &AuthSourceProvider{GothProvider: gothProv, sourceName: source.Name, iconURL: oauth2Cfg.IconURL}
|
||||
orderedKeys = append(orderedKeys, source.Name)
|
||||
providers = append(providers, provider)
|
||||
}
|
||||
|
||||
sort.Strings(orderedKeys)
|
||||
sort.Slice(providers, func(i, j int) bool {
|
||||
return providers[i].Name() < providers[j].Name()
|
||||
})
|
||||
|
||||
return orderedKeys, providers, nil
|
||||
return providers, nil
|
||||
}
|
||||
|
||||
// RegisterProviderWithGothic register a OAuth2 provider in goth lib
|
||||
|
||||
@@ -130,7 +130,10 @@ func (s *SSPI) Verify(req *http.Request, w http.ResponseWriter, store DataStore,
|
||||
|
||||
// getConfig retrieves the SSPI configuration from login sources
|
||||
func (s *SSPI) getConfig(ctx context.Context) (*sspi.Source, error) {
|
||||
sources, err := auth.ActiveSources(ctx, auth.SSPI)
|
||||
sources, err := auth.FindSources(ctx, auth.FindSourcesOptions{
|
||||
IsActive: util.OptionalBoolTrue,
|
||||
LoginType: auth.SSPI,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
func SyncExternalUsers(ctx context.Context, updateExisting bool) error {
|
||||
log.Trace("Doing: SyncExternalUsers")
|
||||
|
||||
ls, err := auth.Sources(ctx)
|
||||
ls, err := auth.FindSources(ctx, auth.FindSourcesOptions{})
|
||||
if err != nil {
|
||||
log.Error("SyncExternalUsers: %v", err)
|
||||
return err
|
||||
|
||||
@@ -35,6 +35,7 @@ func ToPackage(ctx context.Context, pd *packages.PackageDescriptor, doer *user_m
|
||||
Name: pd.Package.Name,
|
||||
Version: pd.Version.Version,
|
||||
CreatedAt: pd.Version.CreatedUnix.AsTime(),
|
||||
HTMLURL: pd.FullWebLink(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
+6
-22
@@ -26,7 +26,6 @@ import (
|
||||
"code.gitea.io/gitea/modules/markup"
|
||||
"code.gitea.io/gitea/modules/markup/markdown"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/templates"
|
||||
"code.gitea.io/gitea/modules/timeutil"
|
||||
"code.gitea.io/gitea/modules/translation"
|
||||
incoming_payload "code.gitea.io/gitea/services/mailer/incoming/payload"
|
||||
@@ -68,15 +67,12 @@ func SendTestMail(email string) error {
|
||||
func sendUserMail(language string, u *user_model.User, tpl base.TplName, code, subject, info string) {
|
||||
locale := translation.NewLocale(language)
|
||||
data := map[string]any{
|
||||
"locale": locale,
|
||||
"DisplayName": u.DisplayName(),
|
||||
"ActiveCodeLives": timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, locale),
|
||||
"ResetPwdCodeLives": timeutil.MinutesToFriendly(setting.Service.ResetPwdCodeLives, locale),
|
||||
"Code": code,
|
||||
"Language": locale.Language(),
|
||||
// helper
|
||||
"locale": locale,
|
||||
"Str2html": templates.Str2html,
|
||||
"DotEscape": templates.DotEscape,
|
||||
}
|
||||
|
||||
var content bytes.Buffer
|
||||
@@ -119,15 +115,12 @@ func SendActivateEmailMail(u *user_model.User, email *user_model.EmailAddress) {
|
||||
}
|
||||
locale := translation.NewLocale(u.Language)
|
||||
data := map[string]any{
|
||||
"locale": locale,
|
||||
"DisplayName": u.DisplayName(),
|
||||
"ActiveCodeLives": timeutil.MinutesToFriendly(setting.Service.ActiveCodeLives, locale),
|
||||
"Code": u.GenerateEmailActivateCode(email.Email),
|
||||
"Email": email.Email,
|
||||
"Language": locale.Language(),
|
||||
// helper
|
||||
"locale": locale,
|
||||
"Str2html": templates.Str2html,
|
||||
"DotEscape": templates.DotEscape,
|
||||
}
|
||||
|
||||
var content bytes.Buffer
|
||||
@@ -152,13 +145,10 @@ func SendRegisterNotifyMail(u *user_model.User) {
|
||||
locale := translation.NewLocale(u.Language)
|
||||
|
||||
data := map[string]any{
|
||||
"locale": locale,
|
||||
"DisplayName": u.DisplayName(),
|
||||
"Username": u.Name,
|
||||
"Language": locale.Language(),
|
||||
// helper
|
||||
"locale": locale,
|
||||
"Str2html": templates.Str2html,
|
||||
"DotEscape": templates.DotEscape,
|
||||
}
|
||||
|
||||
var content bytes.Buffer
|
||||
@@ -185,14 +175,11 @@ func SendCollaboratorMail(u, doer *user_model.User, repo *repo_model.Repository)
|
||||
|
||||
subject := locale.Tr("mail.repo.collaborator.added.subject", doer.DisplayName(), repoName)
|
||||
data := map[string]any{
|
||||
"locale": locale,
|
||||
"Subject": subject,
|
||||
"RepoName": repoName,
|
||||
"Link": repo.HTMLURL(),
|
||||
"Language": locale.Language(),
|
||||
// helper
|
||||
"locale": locale,
|
||||
"Str2html": templates.Str2html,
|
||||
"DotEscape": templates.DotEscape,
|
||||
}
|
||||
|
||||
var content bytes.Buffer
|
||||
@@ -259,6 +246,7 @@ func composeIssueCommentMessages(ctx *mailCommentContext, lang string, recipient
|
||||
locale := translation.NewLocale(lang)
|
||||
|
||||
mailMeta := map[string]any{
|
||||
"locale": locale,
|
||||
"FallbackSubject": fallback,
|
||||
"Body": body,
|
||||
"Link": link,
|
||||
@@ -275,10 +263,6 @@ func composeIssueCommentMessages(ctx *mailCommentContext, lang string, recipient
|
||||
"ReviewComments": reviewComments,
|
||||
"Language": locale.Language(),
|
||||
"CanReply": setting.IncomingEmail.Enabled && commentType != issues_model.CommentTypePullRequestPush,
|
||||
// helper
|
||||
"locale": locale,
|
||||
"Str2html": templates.Str2html,
|
||||
"DotEscape": templates.DotEscape,
|
||||
}
|
||||
|
||||
var mailSubject bytes.Buffer
|
||||
@@ -469,7 +453,7 @@ func SendIssueAssignedMail(ctx context.Context, issue *issues_model.Issue, doer
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
SendAsyncs(msgs)
|
||||
SendAsync(msgs...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -162,7 +162,7 @@ func mailIssueCommentBatch(ctx *mailCommentContext, users []*user_model.User, vi
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
SendAsyncs(msgs)
|
||||
SendAsync(msgs...)
|
||||
receivers = receivers[:i]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
"code.gitea.io/gitea/modules/markup"
|
||||
"code.gitea.io/gitea/modules/markup/markdown"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/templates"
|
||||
"code.gitea.io/gitea/modules/translation"
|
||||
)
|
||||
|
||||
@@ -69,13 +68,10 @@ func mailNewRelease(ctx context.Context, lang string, tos []string, rel *repo_mo
|
||||
|
||||
subject := locale.Tr("mail.release.new.subject", rel.TagName, rel.Repo.FullName())
|
||||
mailMeta := map[string]any{
|
||||
"locale": locale,
|
||||
"Release": rel,
|
||||
"Subject": subject,
|
||||
"Language": locale.Language(),
|
||||
// helper
|
||||
"locale": locale,
|
||||
"Str2html": templates.Str2html,
|
||||
"DotEscape": templates.DotEscape,
|
||||
}
|
||||
|
||||
var mailBody bytes.Buffer
|
||||
@@ -95,5 +91,5 @@ func mailNewRelease(ctx context.Context, lang string, tos []string, rel *repo_mo
|
||||
msgs = append(msgs, msg)
|
||||
}
|
||||
|
||||
SendAsyncs(msgs)
|
||||
SendAsync(msgs...)
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/templates"
|
||||
"code.gitea.io/gitea/modules/translation"
|
||||
)
|
||||
|
||||
@@ -65,6 +64,7 @@ func sendRepoTransferNotifyMailPerLang(lang string, newOwner, doer *user_model.U
|
||||
}
|
||||
|
||||
data := map[string]any{
|
||||
"locale": locale,
|
||||
"Doer": doer,
|
||||
"User": repo.Owner,
|
||||
"Repo": repo.FullName(),
|
||||
@@ -72,10 +72,6 @@ func sendRepoTransferNotifyMailPerLang(lang string, newOwner, doer *user_model.U
|
||||
"Subject": subject,
|
||||
"Language": locale.Language(),
|
||||
"Destination": destination,
|
||||
// helper
|
||||
"locale": locale,
|
||||
"Str2html": templates.Str2html,
|
||||
"DotEscape": templates.DotEscape,
|
||||
}
|
||||
|
||||
if err := bodyTemplates.ExecuteTemplate(&content, string(mailRepoTransferNotify), data); err != nil {
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/templates"
|
||||
"code.gitea.io/gitea/modules/translation"
|
||||
)
|
||||
|
||||
@@ -53,16 +52,13 @@ func MailTeamInvite(ctx context.Context, inviter *user_model.User, team *org_mod
|
||||
|
||||
subject := locale.Tr("mail.team_invite.subject", inviter.DisplayName(), org.DisplayName())
|
||||
mailMeta := map[string]any{
|
||||
"locale": locale,
|
||||
"Inviter": inviter,
|
||||
"Organization": org,
|
||||
"Team": team,
|
||||
"Invite": invite,
|
||||
"Subject": subject,
|
||||
"InviteURL": inviteURL,
|
||||
// helper
|
||||
"locale": locale,
|
||||
"Str2html": templates.Str2html,
|
||||
"DotEscape": templates.DotEscape,
|
||||
}
|
||||
|
||||
var mailBody bytes.Buffer
|
||||
|
||||
@@ -425,15 +425,12 @@ func NewContext(ctx context.Context) {
|
||||
go graceful.GetManager().RunWithCancel(mailQueue)
|
||||
}
|
||||
|
||||
// SendAsync send mail asynchronously
|
||||
func SendAsync(msg *Message) {
|
||||
SendAsyncs([]*Message{msg})
|
||||
}
|
||||
// SendAsync send emails asynchronously (make it mockable)
|
||||
var SendAsync = sendAsync
|
||||
|
||||
// SendAsyncs send mails asynchronously
|
||||
func SendAsyncs(msgs []*Message) {
|
||||
func sendAsync(msgs ...*Message) {
|
||||
if setting.MailService == nil {
|
||||
log.Error("Mailer: SendAsyncs is being invoked but mail service hasn't been initialized")
|
||||
log.Error("Mailer: SendAsync is being invoked but mail service hasn't been initialized")
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -282,6 +282,8 @@ func (g *GiteaDownloader) convertGiteaRelease(rel *gitea_sdk.Release) *base.Rele
|
||||
httpClient := NewMigrationHTTPClient()
|
||||
|
||||
for _, asset := range rel.Attachments {
|
||||
assetID := asset.ID // Don't optimize this, for closure we need a local variable
|
||||
assetDownloadURL := asset.DownloadURL
|
||||
size := int(asset.Size)
|
||||
dlCount := int(asset.DownloadCount)
|
||||
r.Assets = append(r.Assets, &base.ReleaseAsset{
|
||||
@@ -292,18 +294,18 @@ func (g *GiteaDownloader) convertGiteaRelease(rel *gitea_sdk.Release) *base.Rele
|
||||
Created: asset.Created,
|
||||
DownloadURL: &asset.DownloadURL,
|
||||
DownloadFunc: func() (io.ReadCloser, error) {
|
||||
asset, _, err := g.client.GetReleaseAttachment(g.repoOwner, g.repoName, rel.ID, asset.ID)
|
||||
asset, _, err := g.client.GetReleaseAttachment(g.repoOwner, g.repoName, rel.ID, assetID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !hasBaseURL(asset.DownloadURL, g.baseURL) {
|
||||
WarnAndNotice("Unexpected AssetURL for assetID[%d] in %s: %s", asset.ID, g, asset.DownloadURL)
|
||||
if !hasBaseURL(assetDownloadURL, g.baseURL) {
|
||||
WarnAndNotice("Unexpected AssetURL for assetID[%d] in %s: %s", assetID, g, assetDownloadURL)
|
||||
return io.NopCloser(strings.NewReader(asset.DownloadURL)), nil
|
||||
}
|
||||
|
||||
// FIXME: for a private download?
|
||||
req, err := http.NewRequest("GET", asset.DownloadURL, nil)
|
||||
req, err := http.NewRequest("GET", assetDownloadURL, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -310,6 +310,7 @@ func (g *GitlabDownloader) convertGitlabRelease(rel *gitlab.Release) *base.Relea
|
||||
httpClient := NewMigrationHTTPClient()
|
||||
|
||||
for k, asset := range rel.Assets.Links {
|
||||
assetID := asset.ID // Don't optimize this, for closure we need a local variable
|
||||
r.Assets = append(r.Assets, &base.ReleaseAsset{
|
||||
ID: int64(asset.ID),
|
||||
Name: asset.Name,
|
||||
@@ -317,13 +318,13 @@ func (g *GitlabDownloader) convertGitlabRelease(rel *gitlab.Release) *base.Relea
|
||||
Size: &zero,
|
||||
DownloadCount: &zero,
|
||||
DownloadFunc: func() (io.ReadCloser, error) {
|
||||
link, _, err := g.client.ReleaseLinks.GetReleaseLink(g.repoID, rel.TagName, asset.ID, gitlab.WithContext(g.ctx))
|
||||
link, _, err := g.client.ReleaseLinks.GetReleaseLink(g.repoID, rel.TagName, assetID, gitlab.WithContext(g.ctx))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !hasBaseURL(link.URL, g.baseURL) {
|
||||
WarnAndNotice("Unexpected AssetURL for assetID[%d] in %s: %s", asset.ID, g, link.URL)
|
||||
WarnAndNotice("Unexpected AssetURL for assetID[%d] in %s: %s", assetID, g, link.URL)
|
||||
return io.NopCloser(strings.NewReader(link.URL)), nil
|
||||
}
|
||||
|
||||
@@ -528,11 +529,13 @@ func (g *GitlabDownloader) GetPullRequests(page, perPage int) ([]*base.PullReque
|
||||
perPage = g.maxPerPage
|
||||
}
|
||||
|
||||
view := "simple"
|
||||
opt := &gitlab.ListProjectMergeRequestsOptions{
|
||||
ListOptions: gitlab.ListOptions{
|
||||
PerPage: perPage,
|
||||
Page: page,
|
||||
},
|
||||
View: &view,
|
||||
}
|
||||
|
||||
allPRs := make([]*base.PullRequest, 0, perPage)
|
||||
@@ -541,7 +544,13 @@ func (g *GitlabDownloader) GetPullRequests(page, perPage int) ([]*base.PullReque
|
||||
if err != nil {
|
||||
return nil, false, fmt.Errorf("error while listing merge requests: %w", err)
|
||||
}
|
||||
for _, pr := range prs {
|
||||
for _, simplePR := range prs {
|
||||
// Load merge request again by itself, as not all fields are populated in the ListProjectMergeRequests endpoint.
|
||||
// See https://gitlab.com/gitlab-org/gitlab/-/issues/29620
|
||||
pr, _, err := g.client.MergeRequests.GetMergeRequest(g.repoID, simplePR.IID, nil)
|
||||
if err != nil {
|
||||
return nil, false, fmt.Errorf("error while loading merge request: %w", err)
|
||||
}
|
||||
|
||||
labels := make([]*base.Label, 0, len(pr.Labels))
|
||||
for _, l := range pr.Labels {
|
||||
@@ -566,6 +575,11 @@ func (g *GitlabDownloader) GetPullRequests(page, perPage int) ([]*base.PullReque
|
||||
closeTime = pr.UpdatedAt
|
||||
}
|
||||
|
||||
mergeCommitSHA := pr.MergeCommitSHA
|
||||
if mergeCommitSHA == "" {
|
||||
mergeCommitSHA = pr.SquashCommitSHA
|
||||
}
|
||||
|
||||
var locked bool
|
||||
if pr.State == "locked" {
|
||||
locked = true
|
||||
@@ -608,7 +622,7 @@ func (g *GitlabDownloader) GetPullRequests(page, perPage int) ([]*base.PullReque
|
||||
Closed: closeTime,
|
||||
Labels: labels,
|
||||
Merged: merged,
|
||||
MergeCommitSHA: pr.MergeCommitSHA,
|
||||
MergeCommitSHA: mergeCommitSHA,
|
||||
MergedTime: mergeTime,
|
||||
IsLocked: locked,
|
||||
Reactions: g.awardsToReactions(reactions),
|
||||
|
||||
@@ -238,6 +238,8 @@ func buildPackagesIndex(ctx context.Context, ownerID int64, repoVersion *package
|
||||
}
|
||||
|
||||
unsignedIndexContent, _ := packages_module.NewHashedBuffer()
|
||||
defer unsignedIndexContent.Close()
|
||||
|
||||
h := sha1.New()
|
||||
|
||||
if err := writeGzipStream(io.MultiWriter(unsignedIndexContent, h), "APKINDEX", buf.Bytes(), true); err != nil {
|
||||
@@ -275,6 +277,7 @@ func buildPackagesIndex(ctx context.Context, ownerID int64, repoVersion *package
|
||||
}
|
||||
|
||||
signedIndexContent, _ := packages_module.NewHashedBuffer()
|
||||
defer signedIndexContent.Close()
|
||||
|
||||
if err := writeGzipStream(
|
||||
signedIndexContent,
|
||||
|
||||
@@ -165,18 +165,17 @@ func buildRepositoryFiles(ctx context.Context, ownerID int64, repoVersion *packa
|
||||
|
||||
// https://wiki.debian.org/DebianRepository/Format#A.22Packages.22_Indices
|
||||
func buildPackagesIndices(ctx context.Context, ownerID int64, repoVersion *packages_model.PackageVersion, distribution, component, architecture string) error {
|
||||
pfds, err := debian_model.SearchLatestPackages(ctx, &debian_model.PackageSearchOptions{
|
||||
opts := &debian_model.PackageSearchOptions{
|
||||
OwnerID: ownerID,
|
||||
Distribution: distribution,
|
||||
Component: component,
|
||||
Architecture: architecture,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Delete the package indices if there are no packages
|
||||
if len(pfds) == 0 {
|
||||
if has, err := debian_model.ExistPackages(ctx, opts); err != nil {
|
||||
return err
|
||||
} else if !has {
|
||||
key := fmt.Sprintf("%s|%s|%s", distribution, component, architecture)
|
||||
for _, filename := range []string{"Packages", "Packages.gz", "Packages.xz"} {
|
||||
pf, err := packages_model.GetFileForVersionByName(ctx, repoVersion.ID, filename, key)
|
||||
@@ -196,17 +195,22 @@ func buildPackagesIndices(ctx context.Context, ownerID int64, repoVersion *packa
|
||||
}
|
||||
|
||||
packagesContent, _ := packages_module.NewHashedBuffer()
|
||||
defer packagesContent.Close()
|
||||
|
||||
packagesGzipContent, _ := packages_module.NewHashedBuffer()
|
||||
defer packagesGzipContent.Close()
|
||||
|
||||
gzw := gzip.NewWriter(packagesGzipContent)
|
||||
|
||||
packagesXzContent, _ := packages_module.NewHashedBuffer()
|
||||
defer packagesXzContent.Close()
|
||||
|
||||
xzw, _ := xz.NewWriter(packagesXzContent)
|
||||
|
||||
w := io.MultiWriter(packagesContent, gzw, xzw)
|
||||
|
||||
addSeparator := false
|
||||
for _, pfd := range pfds {
|
||||
if err := debian_model.SearchPackages(ctx, opts, func(pfd *packages_model.PackageFileDescriptor) {
|
||||
if addSeparator {
|
||||
fmt.Fprintln(w)
|
||||
}
|
||||
@@ -220,6 +224,8 @@ func buildPackagesIndices(ctx context.Context, ownerID int64, repoVersion *packa
|
||||
fmt.Fprintf(w, "SHA1: %s\n", pfd.Blob.HashSHA1)
|
||||
fmt.Fprintf(w, "SHA256: %s\n", pfd.Blob.HashSHA256)
|
||||
fmt.Fprintf(w, "SHA512: %s\n", pfd.Blob.HashSHA512)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
gzw.Close()
|
||||
@@ -233,7 +239,7 @@ func buildPackagesIndices(ctx context.Context, ownerID int64, repoVersion *packa
|
||||
{"Packages.gz", packagesGzipContent},
|
||||
{"Packages.xz", packagesXzContent},
|
||||
} {
|
||||
_, err = packages_service.AddFileToPackageVersionInternal(
|
||||
_, err := packages_service.AddFileToPackageVersionInternal(
|
||||
ctx,
|
||||
repoVersion,
|
||||
&packages_service.PackageFileCreationInfo{
|
||||
@@ -323,6 +329,8 @@ func buildReleaseFiles(ctx context.Context, ownerID int64, repoVersion *packages
|
||||
}
|
||||
|
||||
inReleaseContent, _ := packages_module.NewHashedBuffer()
|
||||
defer inReleaseContent.Close()
|
||||
|
||||
sw, err := clearsign.Encode(inReleaseContent, e.PrivateKey, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -367,11 +375,14 @@ func buildReleaseFiles(ctx context.Context, ownerID int64, repoVersion *packages
|
||||
sw.Close()
|
||||
|
||||
releaseGpgContent, _ := packages_module.NewHashedBuffer()
|
||||
defer releaseGpgContent.Close()
|
||||
|
||||
if err := openpgp.ArmoredDetachSign(releaseGpgContent, e, bytes.NewReader(buf.Bytes()), nil); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
releaseContent, _ := packages_module.CreateHashedBufferFromReader(&buf)
|
||||
defer releaseContent.Close()
|
||||
|
||||
for _, file := range []struct {
|
||||
Name string
|
||||
|
||||
@@ -258,11 +258,14 @@ func buildRepomd(ctx context.Context, pv *packages_model.PackageVersion, ownerID
|
||||
}
|
||||
|
||||
repomdAscContent, _ := packages_module.NewHashedBuffer()
|
||||
defer repomdAscContent.Close()
|
||||
|
||||
if err := openpgp.ArmoredDetachSign(repomdAscContent, e, bytes.NewReader(buf.Bytes()), nil); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
repomdContent, _ := packages_module.CreateHashedBufferFromReader(&buf)
|
||||
defer repomdContent.Close()
|
||||
|
||||
for _, file := range []struct {
|
||||
Name string
|
||||
@@ -548,6 +551,8 @@ func (wc *writtenCounter) Written() int64 {
|
||||
|
||||
func addDataAsFileToRepo(ctx context.Context, pv *packages_model.PackageVersion, filetype string, obj any) (*repoData, error) {
|
||||
content, _ := packages_module.NewHashedBuffer()
|
||||
defer content.Close()
|
||||
|
||||
gzw := gzip.NewWriter(content)
|
||||
wc := &writtenCounter{}
|
||||
h := sha256.New()
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
|
||||
_ "image/jpeg" // Needed for jpeg support
|
||||
|
||||
actions_model "code.gitea.io/gitea/models/actions"
|
||||
activities_model "code.gitea.io/gitea/models/activities"
|
||||
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
@@ -90,6 +91,7 @@ func deleteUser(ctx context.Context, u *user_model.User, purge bool) (err error)
|
||||
&pull_model.AutoMerge{DoerID: u.ID},
|
||||
&pull_model.ReviewState{UserID: u.ID},
|
||||
&user_model.Redirect{RedirectUserID: u.ID},
|
||||
&actions_model.ActionRunner{OwnerID: u.ID},
|
||||
); err != nil {
|
||||
return fmt.Errorf("deleteBeans: %w", err)
|
||||
}
|
||||
|
||||
@@ -173,6 +173,12 @@ func (d *DingtalkPayload) Release(p *api.ReleasePayload) (api.Payloader, error)
|
||||
return createDingtalkPayload(text, text, "view release", p.Release.HTMLURL), nil
|
||||
}
|
||||
|
||||
func (d *DingtalkPayload) Package(p *api.PackagePayload) (api.Payloader, error) {
|
||||
text, _ := getPackagePayloadInfo(p, noneLinkFormatter, true)
|
||||
|
||||
return createDingtalkPayload(text, text, "view package", p.Package.HTMLURL), nil
|
||||
}
|
||||
|
||||
func createDingtalkPayload(title, text, singleTitle, singleURL string) *DingtalkPayload {
|
||||
return &DingtalkPayload{
|
||||
MsgType: "actionCard",
|
||||
|
||||
@@ -256,6 +256,12 @@ func (d *DiscordPayload) Release(p *api.ReleasePayload) (api.Payloader, error) {
|
||||
return d.createPayload(p.Sender, text, p.Release.Note, p.Release.HTMLURL, color), nil
|
||||
}
|
||||
|
||||
func (d *DiscordPayload) Package(p *api.PackagePayload) (api.Payloader, error) {
|
||||
text, color := getPackagePayloadInfo(p, noneLinkFormatter, false)
|
||||
|
||||
return d.createPayload(p.Sender, text, "", p.Package.HTMLURL, color), nil
|
||||
}
|
||||
|
||||
// GetDiscordPayload converts a discord webhook into a DiscordPayload
|
||||
func GetDiscordPayload(p api.Payloader, event webhook_module.HookEventType, meta string) (api.Payloader, error) {
|
||||
s := new(DiscordPayload)
|
||||
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
type (
|
||||
// FeishuPayload represents
|
||||
FeishuPayload struct {
|
||||
MsgType string `json:"msg_type"` // text / post / image / share_chat / interactive
|
||||
MsgType string `json:"msg_type"` // text / post / image / share_chat / interactive / file /audio / media
|
||||
Content struct {
|
||||
Text string `json:"text"`
|
||||
} `json:"content"`
|
||||
@@ -175,6 +175,12 @@ func (f *FeishuPayload) Release(p *api.ReleasePayload) (api.Payloader, error) {
|
||||
return newFeishuTextPayload(text), nil
|
||||
}
|
||||
|
||||
func (f *FeishuPayload) Package(p *api.PackagePayload) (api.Payloader, error) {
|
||||
text, _ := getPackagePayloadInfo(p, noneLinkFormatter, true)
|
||||
|
||||
return newFeishuTextPayload(text), nil
|
||||
}
|
||||
|
||||
// GetFeishuPayload converts a ding talk webhook into a FeishuPayload
|
||||
func GetFeishuPayload(p api.Payloader, event webhook_module.HookEventType, _ string) (api.Payloader, error) {
|
||||
return convertPayloader(new(FeishuPayload), p, event)
|
||||
|
||||
@@ -293,6 +293,24 @@ func getIssueCommentPayloadInfo(p *api.IssueCommentPayload, linkFormatter linkFo
|
||||
return text, issueTitle, color
|
||||
}
|
||||
|
||||
func getPackagePayloadInfo(p *api.PackagePayload, linkFormatter linkFormatter, withSender bool) (text string, color int) {
|
||||
refLink := linkFormatter(p.Package.HTMLURL, p.Package.Name+":"+p.Package.Version)
|
||||
|
||||
switch p.Action {
|
||||
case api.HookPackageCreated:
|
||||
text = fmt.Sprintf("Package created: %s", refLink)
|
||||
color = greenColor
|
||||
case api.HookPackageDeleted:
|
||||
text = fmt.Sprintf("Package deleted: %s", refLink)
|
||||
color = redColor
|
||||
}
|
||||
if withSender {
|
||||
text += fmt.Sprintf(" by %s", linkFormatter(setting.AppURL+url.PathEscape(p.Sender.UserName), p.Sender.UserName))
|
||||
}
|
||||
|
||||
return text, color
|
||||
}
|
||||
|
||||
// ToHook convert models.Webhook to api.Hook
|
||||
// This function is not part of the convert package to prevent an import cycle
|
||||
func ToHook(repoLink string, w *webhook_model.Webhook) (*api.Hook, error) {
|
||||
|
||||
@@ -210,6 +210,21 @@ func (m *MatrixPayload) Repository(p *api.RepositoryPayload) (api.Payloader, err
|
||||
return getMatrixPayload(text, nil, m.MsgType), nil
|
||||
}
|
||||
|
||||
func (m *MatrixPayload) Package(p *api.PackagePayload) (api.Payloader, error) {
|
||||
senderLink := MatrixLinkFormatter(setting.AppURL+p.Sender.UserName, p.Sender.UserName)
|
||||
repoLink := MatrixLinkFormatter(p.Repository.HTMLURL, p.Repository.FullName)
|
||||
var text string
|
||||
|
||||
switch p.Action {
|
||||
case api.HookPackageCreated:
|
||||
text = fmt.Sprintf("[%s] Package published by %s", repoLink, senderLink)
|
||||
case api.HookPackageDeleted:
|
||||
text = fmt.Sprintf("[%s] Package deleted by %s", repoLink, senderLink)
|
||||
}
|
||||
|
||||
return getMatrixPayload(text, nil, m.MsgType), nil
|
||||
}
|
||||
|
||||
// GetMatrixPayload converts a Matrix webhook into a MatrixPayload
|
||||
func GetMatrixPayload(p api.Payloader, event webhook_module.HookEventType, meta string) (api.Payloader, error) {
|
||||
s := new(MatrixPayload)
|
||||
|
||||
@@ -296,6 +296,20 @@ func (m *MSTeamsPayload) Release(p *api.ReleasePayload) (api.Payloader, error) {
|
||||
), nil
|
||||
}
|
||||
|
||||
func (m *MSTeamsPayload) Package(p *api.PackagePayload) (api.Payloader, error) {
|
||||
title, color := getPackagePayloadInfo(p, noneLinkFormatter, false)
|
||||
|
||||
return createMSTeamsPayload(
|
||||
p.Repository,
|
||||
p.Sender,
|
||||
title,
|
||||
"",
|
||||
p.Package.HTMLURL,
|
||||
color,
|
||||
&MSTeamsFact{"Package:", p.Package.Name},
|
||||
), nil
|
||||
}
|
||||
|
||||
// GetMSTeamsPayload converts a MSTeams webhook into a MSTeamsPayload
|
||||
func GetMSTeamsPayload(p api.Payloader, event webhook_module.HookEventType, _ string) (api.Payloader, error) {
|
||||
return convertPayloader(new(MSTeamsPayload), p, event)
|
||||
|
||||
@@ -104,6 +104,10 @@ func (f *PackagistPayload) Release(_ *api.ReleasePayload) (api.Payloader, error)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (f *PackagistPayload) Package(_ *api.PackagePayload) (api.Payloader, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// GetPackagistPayload converts a packagist webhook into a PackagistPayload
|
||||
func GetPackagistPayload(p api.Payloader, event webhook_module.HookEventType, meta string) (api.Payloader, error) {
|
||||
s := new(PackagistPayload)
|
||||
|
||||
@@ -22,6 +22,7 @@ type PayloadConvertor interface {
|
||||
Repository(*api.RepositoryPayload) (api.Payloader, error)
|
||||
Release(*api.ReleasePayload) (api.Payloader, error)
|
||||
Wiki(*api.WikiPayload) (api.Payloader, error)
|
||||
Package(*api.PackagePayload) (api.Payloader, error)
|
||||
}
|
||||
|
||||
func convertPayloader(s PayloadConvertor, p api.Payloader, event webhook_module.HookEventType) (api.Payloader, error) {
|
||||
@@ -53,6 +54,8 @@ func convertPayloader(s PayloadConvertor, p api.Payloader, event webhook_module.
|
||||
return s.Release(p.(*api.ReleasePayload))
|
||||
case webhook_module.HookEventWiki:
|
||||
return s.Wiki(p.(*api.WikiPayload))
|
||||
case webhook_module.HookEventPackage:
|
||||
return s.Package(p.(*api.PackagePayload))
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user