Compare commits
4 commits
forgejo
...
tn-fix-bra
Author | SHA1 | Date | |
---|---|---|---|
3b47057ffa | |||
7635150699 | |||
19ed5ae3be | |||
07a030af63 |
559 changed files with 6614 additions and 11631 deletions
|
@ -137,6 +137,9 @@ code.gitea.io/gitea/modules/git
|
||||||
AddChangesWithArgs
|
AddChangesWithArgs
|
||||||
CommitChanges
|
CommitChanges
|
||||||
CommitChangesWithArgs
|
CommitChangesWithArgs
|
||||||
|
IsErrExecTimeout
|
||||||
|
ErrExecTimeout.Error
|
||||||
|
ErrUnsupportedVersion.Error
|
||||||
SetUpdateHook
|
SetUpdateHook
|
||||||
openRepositoryWithDefaultContext
|
openRepositoryWithDefaultContext
|
||||||
IsTagExist
|
IsTagExist
|
||||||
|
@ -247,9 +250,6 @@ code.gitea.io/gitea/modules/translation
|
||||||
MockLocale.TrSize
|
MockLocale.TrSize
|
||||||
MockLocale.PrettyNumber
|
MockLocale.PrettyNumber
|
||||||
|
|
||||||
code.gitea.io/gitea/modules/util
|
|
||||||
OptionalArg
|
|
||||||
|
|
||||||
code.gitea.io/gitea/modules/util/filebuffer
|
code.gitea.io/gitea/modules/util/filebuffer
|
||||||
CreateFromReader
|
CreateFromReader
|
||||||
|
|
||||||
|
|
2
.forgejo/testdata/build-release/go.mod
vendored
2
.forgejo/testdata/build-release/go.mod
vendored
|
@ -1,3 +1,3 @@
|
||||||
module code.gitea.io/gitea
|
module code.gitea.io/gitea
|
||||||
|
|
||||||
go 1.23.3
|
go 1.23.2
|
||||||
|
|
|
@ -31,7 +31,7 @@ on:
|
||||||
jobs:
|
jobs:
|
||||||
backporting:
|
backporting:
|
||||||
if: >
|
if: >
|
||||||
( vars.ROLE == 'forgejo-coding' ) && (
|
!startsWith(vars.ROLE, 'forgejo-') && (
|
||||||
github.event.pull_request.merged
|
github.event.pull_request.merged
|
||||||
&&
|
&&
|
||||||
contains(toJSON(github.event.pull_request.labels), 'backport/v')
|
contains(toJSON(github.event.pull_request.labels), 'backport/v')
|
||||||
|
@ -45,7 +45,7 @@ jobs:
|
||||||
cat <<'EOF'
|
cat <<'EOF'
|
||||||
${{ toJSON(github) }}
|
${{ toJSON(github) }}
|
||||||
EOF
|
EOF
|
||||||
- uses: https://code.forgejo.org/actions/git-backporting@v4.8.4
|
- uses: https://code.forgejo.org/actions/git-backporting@v4.8.2
|
||||||
with:
|
with:
|
||||||
target-branch-pattern: "^backport/(?<target>(v.*))$"
|
target-branch-pattern: "^backport/(?<target>(v.*))$"
|
||||||
strategy: ort
|
strategy: ort
|
||||||
|
|
|
@ -22,7 +22,7 @@ on:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release-simulation:
|
release-simulation:
|
||||||
if: vars.ROLE == 'forgejo-coding'
|
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
||||||
runs-on: self-hosted
|
runs-on: self-hosted
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
|
@ -12,10 +12,8 @@
|
||||||
# whatever is in the default branch instead
|
# whatever is in the default branch instead
|
||||||
#
|
#
|
||||||
# - after it is merged, double check it works by setting the
|
# - after it is merged, double check it works by setting the
|
||||||
# run-end-to-end-test on a pull request (any pull request will do)
|
# run-end-to-end-test on a pull request (any pull request will doe
|
||||||
#
|
#
|
||||||
name: end-to-end
|
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
@ -26,7 +24,7 @@ on:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
info:
|
info:
|
||||||
if: vars.ROLE == 'forgejo-coding'
|
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
container:
|
container:
|
||||||
image: code.forgejo.org/oci/node:20-bookworm
|
image: code.forgejo.org/oci/node:20-bookworm
|
||||||
|
@ -35,9 +33,10 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
echo github.event.pull_request.head.repo.fork = ${{ github.event.pull_request.head.repo.fork }}
|
echo github.event.pull_request.head.repo.fork = ${{ github.event.pull_request.head.repo.fork }}
|
||||||
echo github.event.action = ${{ github.event.action }}
|
echo github.event.action = ${{ github.event.action }}
|
||||||
echo github.event.label
|
echo github.event.pull_request.merged = ${{ github.event.pull_request.merged }}
|
||||||
|
echo github.event.pull_request.labels.*.name
|
||||||
cat <<'EOF'
|
cat <<'EOF'
|
||||||
${{ toJSON(github.event.label) }}
|
${{ toJSON(github.event.pull_request.labels.*.name) }}
|
||||||
EOF
|
EOF
|
||||||
cat <<'EOF'
|
cat <<'EOF'
|
||||||
${{ toJSON(github.event) }}
|
${{ toJSON(github.event) }}
|
||||||
|
@ -45,10 +44,10 @@ jobs:
|
||||||
|
|
||||||
cascade:
|
cascade:
|
||||||
if: >
|
if: >
|
||||||
vars.ROLE == 'forgejo-coding' && (
|
!startsWith(vars.ROLE, 'forgejo-') && (
|
||||||
github.event_name == 'push' ||
|
github.event_name == 'push' ||
|
||||||
(
|
(
|
||||||
github.event.action == 'label_updated' && github.event.label.name == 'run-end-to-end-tests'
|
github.event.action == 'label_updated' && contains(github.event.pull_request.labels.*.name, 'run-end-to-end-tests')
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
|
|
|
@ -1,45 +0,0 @@
|
||||||
# Copyright 2024 The Forgejo Authors
|
|
||||||
# SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
name: requirements
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
types:
|
|
||||||
- labeled
|
|
||||||
- edited
|
|
||||||
- opened
|
|
||||||
- synchronize
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
merge-conditions:
|
|
||||||
if: vars.ROLE == 'forgejo-coding'
|
|
||||||
runs-on: docker
|
|
||||||
container:
|
|
||||||
image: 'code.forgejo.org/oci/node:20-bookworm'
|
|
||||||
steps:
|
|
||||||
- name: Debug output
|
|
||||||
run: |
|
|
||||||
cat <<'EOF'
|
|
||||||
${{ toJSON(github.event) }}
|
|
||||||
EOF
|
|
||||||
- name: Missing test label
|
|
||||||
if: >
|
|
||||||
!(
|
|
||||||
contains(toJSON(github.event.pull_request.labels), 'test/present')
|
|
||||||
|| contains(toJSON(github.event.pull_request.labels), 'test/not-needed')
|
|
||||||
|| contains(toJSON(github.event.pull_request.labels), 'test/manual')
|
|
||||||
)
|
|
||||||
run: |
|
|
||||||
echo "Test label must be set to either 'present', 'not-needed' or 'manual'."
|
|
||||||
exit 1
|
|
||||||
- name: Missing manual test instructions
|
|
||||||
if: >
|
|
||||||
(
|
|
||||||
contains(toJSON(github.event.pull_request.labels), 'test/manual')
|
|
||||||
&& !contains(toJSON(github.event.pull_request.body), '# Test')
|
|
||||||
)
|
|
||||||
run: |
|
|
||||||
echo "Manual test label is set. The PR description needs to contain test steps introduced by a heading like:"
|
|
||||||
echo "# Testing"
|
|
||||||
exit 1
|
|
|
@ -59,31 +59,16 @@ jobs:
|
||||||
gpg-passphrase: ${{ secrets.GPG_PASSPHRASE }}
|
gpg-passphrase: ${{ secrets.GPG_PASSPHRASE }}
|
||||||
verbose: ${{ vars.VERBOSE }}
|
verbose: ${{ vars.VERBOSE }}
|
||||||
|
|
||||||
- name: get trigger mirror issue
|
|
||||||
id: mirror
|
|
||||||
uses: https://code.forgejo.org/infrastructure/issue-action/get@v1.1.0
|
|
||||||
with:
|
|
||||||
forgejo: https://code.forgejo.org
|
|
||||||
repository: forgejo/forgejo
|
|
||||||
labels: mirror-trigger
|
|
||||||
|
|
||||||
- name: trigger the mirror
|
|
||||||
uses: https://code.forgejo.org/infrastructure/issue-action/set@v1.1.0
|
|
||||||
with:
|
|
||||||
forgejo: https://code.forgejo.org
|
|
||||||
repository: forgejo/forgejo
|
|
||||||
token: ${{ secrets.LABEL_ISSUE_FORGEJO_MIRROR_TOKEN }}
|
|
||||||
numbers: ${{ steps.mirror.outputs.numbers }}
|
|
||||||
label-wait-if-exists: 3600
|
|
||||||
label: trigger
|
|
||||||
|
|
||||||
- name: upgrade v*.next.forgejo.org
|
- name: upgrade v*.next.forgejo.org
|
||||||
uses: https://code.forgejo.org/infrastructure/next-digest@v1.1.0
|
run: |
|
||||||
with:
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
url: https://placeholder:${{ secrets.TOKEN_NEXT_DIGEST }}@code.forgejo.org/infrastructure/next-digest
|
apt-get update -qq
|
||||||
ref_name: '${{ github.ref_name }}'
|
apt-get -q install -y -qq curl
|
||||||
image: 'codeberg.org/forgejo-experimental/forgejo'
|
version="${{ github.ref_name }}"
|
||||||
tag_suffix: '-rootless'
|
version=${version##*v}
|
||||||
|
major=$(echo $version | sed -E -e 's/^([0-9]+).*/\1/')
|
||||||
|
# https://forgejo.org/docs/next/developer/infrastructure
|
||||||
|
curl -o /dev/null -sS https://v$major.next.forgejo.org/.well-known/wakeup-on-logs/forgejo-v$major
|
||||||
|
|
||||||
- name: set up go for the DNS update below
|
- name: set up go for the DNS update below
|
||||||
if: vars.ROLE == 'forgejo-experimental' && secrets.OVH_APP_KEY != ''
|
if: vars.ROLE == 'forgejo-experimental' && secrets.OVH_APP_KEY != ''
|
||||||
|
|
|
@ -6,7 +6,7 @@ on:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release-notes:
|
release-notes:
|
||||||
if: vars.ROLE == 'forgejo-coding'
|
if: ${{ !startsWith(vars.ROLE, 'forgejo-')
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
container:
|
container:
|
||||||
image: 'code.forgejo.org/oci/node:20-bookworm'
|
image: 'code.forgejo.org/oci/node:20-bookworm'
|
||||||
|
|
|
@ -7,7 +7,7 @@ on:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release-notes:
|
release-notes:
|
||||||
if: ( vars.ROLE == 'forgejo-coding' ) && contains(github.event.pull_request.labels.*.name, 'worth a release-note')
|
if: ${{ !startsWith(vars.ROLE, 'forgejo-') && contains(github.event.pull_request.labels.*.name, 'worth a release-note') }}
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
container:
|
container:
|
||||||
image: 'code.forgejo.org/oci/node:20-bookworm'
|
image: 'code.forgejo.org/oci/node:20-bookworm'
|
||||||
|
|
|
@ -8,9 +8,7 @@ name: renovate
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- renovate/** # self-test updates
|
- 'renovate/**' # self-test updates
|
||||||
paths:
|
|
||||||
- .forgejo/workflows/renovate.yml
|
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 0/2 * * *'
|
- cron: '0 0/2 * * *'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
@ -21,11 +19,11 @@ env:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
renovate:
|
renovate:
|
||||||
if: vars.ROLE == 'forgejo-coding' && secrets.RENOVATE_TOKEN != ''
|
if: ${{ secrets.RENOVATE_TOKEN != '' }}
|
||||||
|
|
||||||
runs-on: docker-runner-one
|
runs-on: docker
|
||||||
container:
|
container:
|
||||||
image: code.forgejo.org/forgejo-contrib/renovate:39.9.1
|
image: code.forgejo.org/forgejo-contrib/renovate:38.128.6
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Load renovate repo cache
|
- name: Load renovate repo cache
|
||||||
|
|
|
@ -10,7 +10,7 @@ on:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
backend-checks:
|
backend-checks:
|
||||||
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
|
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
container:
|
container:
|
||||||
image: 'code.forgejo.org/oci/node:20-bookworm'
|
image: 'code.forgejo.org/oci/node:20-bookworm'
|
||||||
|
@ -26,7 +26,7 @@ jobs:
|
||||||
- run: su forgejo -c 'make --always-make -j$(nproc) lint-backend tidy-check swagger-check fmt-check swagger-validate' # ensure the "go-licenses" make target runs
|
- run: su forgejo -c 'make --always-make -j$(nproc) lint-backend tidy-check swagger-check fmt-check swagger-validate' # ensure the "go-licenses" make target runs
|
||||||
- uses: ./.forgejo/workflows-composite/build-backend
|
- uses: ./.forgejo/workflows-composite/build-backend
|
||||||
frontend-checks:
|
frontend-checks:
|
||||||
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
|
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
container:
|
container:
|
||||||
image: 'code.forgejo.org/oci/node:20-bookworm'
|
image: 'code.forgejo.org/oci/node:20-bookworm'
|
||||||
|
@ -49,22 +49,21 @@ jobs:
|
||||||
path: ${{github.workspace}}/public/assets
|
path: ${{github.workspace}}/public/assets
|
||||||
key: frontend-build-${{ github.sha }}
|
key: frontend-build-${{ github.sha }}
|
||||||
test-unit:
|
test-unit:
|
||||||
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
|
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
needs: [backend-checks, frontend-checks]
|
needs: [backend-checks, frontend-checks]
|
||||||
container:
|
container:
|
||||||
image: 'code.forgejo.org/oci/node:20-bookworm'
|
image: 'code.forgejo.org/oci/node:20-bookworm'
|
||||||
services:
|
services:
|
||||||
elasticsearch:
|
elasticsearch:
|
||||||
image: code.forgejo.org/oci/bitnami/elasticsearch:7
|
image: docker.io/bitnami/elasticsearch:7
|
||||||
options: --tmpfs /bitnami/elasticsearch/data
|
|
||||||
env:
|
env:
|
||||||
discovery.type: single-node
|
discovery.type: single-node
|
||||||
ES_JAVA_OPTS: "-Xms512m -Xmx512m"
|
ES_JAVA_OPTS: "-Xms512m -Xmx512m"
|
||||||
minio:
|
minio:
|
||||||
image: code.forgejo.org/oci/bitnami/minio:2024.8.17
|
image: docker.io/bitnami/minio:2024.8.17
|
||||||
options: >-
|
options: >-
|
||||||
--hostname gitea.minio --tmpfs /bitnami/minio/data
|
--hostname gitea.minio
|
||||||
env:
|
env:
|
||||||
MINIO_DOMAIN: minio
|
MINIO_DOMAIN: minio
|
||||||
MINIO_ROOT_USER: 123456
|
MINIO_ROOT_USER: 123456
|
||||||
|
@ -83,13 +82,13 @@ jobs:
|
||||||
- uses: ./.forgejo/workflows-composite/build-backend
|
- uses: ./.forgejo/workflows-composite/build-backend
|
||||||
- run: |
|
- run: |
|
||||||
su forgejo -c 'make test-backend test-check'
|
su forgejo -c 'make test-backend test-check'
|
||||||
timeout-minutes: 120
|
timeout-minutes: 50
|
||||||
env:
|
env:
|
||||||
RACE_ENABLED: 'true'
|
RACE_ENABLED: 'true'
|
||||||
TAGS: bindata
|
TAGS: bindata
|
||||||
TEST_ELASTICSEARCH_URL: http://elasticsearch:9200
|
TEST_ELASTICSEARCH_URL: http://elasticsearch:9200
|
||||||
test-e2e:
|
test-e2e:
|
||||||
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
|
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
needs: [backend-checks, frontend-checks]
|
needs: [backend-checks, frontend-checks]
|
||||||
container:
|
container:
|
||||||
|
@ -117,40 +116,32 @@ jobs:
|
||||||
separator: '\n'
|
separator: '\n'
|
||||||
- run: |
|
- run: |
|
||||||
su forgejo -c 'make generate test-e2e-sqlite'
|
su forgejo -c 'make generate test-e2e-sqlite'
|
||||||
timeout-minutes: 120
|
timeout-minutes: 40
|
||||||
env:
|
env:
|
||||||
USE_REPO_TEST_DIR: 1
|
USE_REPO_TEST_DIR: 1
|
||||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
|
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
|
||||||
CHANGED_FILES: ${{steps.changed-files.outputs.all_changed_files}}
|
CHANGED_FILES: ${{steps.changed-files.outputs.all_changed_files}}
|
||||||
- name: Upload test artifacts on failure
|
|
||||||
if: failure()
|
|
||||||
uses: https://code.forgejo.org/forgejo/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: test-artifacts.zip
|
|
||||||
path: tests/e2e/test-artifacts/
|
|
||||||
retention-days: 3
|
|
||||||
test-remote-cacher:
|
test-remote-cacher:
|
||||||
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
|
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
needs: [backend-checks, frontend-checks, test-unit]
|
needs: [backend-checks, frontend-checks, test-unit]
|
||||||
container:
|
container:
|
||||||
image: 'code.forgejo.org/oci/node:20-bookworm'
|
image: 'code.forgejo.org/oci/node:20-bookworm'
|
||||||
name: ${{ format('test-remote-cacher ({0})', matrix.cacher.name) }}
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
cacher:
|
cacher:
|
||||||
- name: redis
|
# redis
|
||||||
image: code.forgejo.org/oci/bitnami/redis:7.2
|
- image: docker.io/bitnami/redis:7.2
|
||||||
options: --tmpfs /bitnami/redis/data
|
port: 6379
|
||||||
- name: redict
|
# redict
|
||||||
image: registry.redict.io/redict:7.3.0-scratch
|
- image: registry.redict.io/redict:7.3.0-scratch
|
||||||
options: --tmpfs /data
|
port: 6379
|
||||||
- name: valkey
|
# valkey
|
||||||
image: code.forgejo.org/oci/bitnami/valkey:7.2
|
- image: docker.io/bitnami/valkey:7.2
|
||||||
options: --tmpfs /bitnami/redis/data
|
port: 6379
|
||||||
- name: garnet
|
# garnet
|
||||||
image: ghcr.io/microsoft/garnet-alpine:1.0.14
|
- image: ghcr.io/microsoft/garnet-alpine:1.0.14
|
||||||
options: --tmpfs /data
|
port: 6379
|
||||||
services:
|
services:
|
||||||
cacher:
|
cacher:
|
||||||
image: ${{ matrix.cacher.image }}
|
image: ${{ matrix.cacher.image }}
|
||||||
|
@ -165,28 +156,27 @@ jobs:
|
||||||
- uses: ./.forgejo/workflows-composite/build-backend
|
- uses: ./.forgejo/workflows-composite/build-backend
|
||||||
- run: |
|
- run: |
|
||||||
su forgejo -c 'make test-remote-cacher test-check'
|
su forgejo -c 'make test-remote-cacher test-check'
|
||||||
timeout-minutes: 120
|
timeout-minutes: 50
|
||||||
env:
|
env:
|
||||||
RACE_ENABLED: 'true'
|
RACE_ENABLED: 'true'
|
||||||
TAGS: bindata
|
TAGS: bindata
|
||||||
TEST_REDIS_SERVER: cacher:${{ matrix.cacher.port }}
|
TEST_REDIS_SERVER: cacher:${{ matrix.cacher.port }}
|
||||||
test-mysql:
|
test-mysql:
|
||||||
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
|
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
needs: [backend-checks, frontend-checks]
|
needs: [backend-checks, frontend-checks]
|
||||||
container:
|
container:
|
||||||
image: 'code.forgejo.org/oci/node:20-bookworm'
|
image: 'code.forgejo.org/oci/node:20-bookworm'
|
||||||
services:
|
services:
|
||||||
mysql:
|
mysql:
|
||||||
image: 'code.forgejo.org/oci/bitnami/mysql:8.4'
|
image: 'docker.io/bitnami/mysql:8.4'
|
||||||
env:
|
env:
|
||||||
ALLOW_EMPTY_PASSWORD: yes
|
ALLOW_EMPTY_PASSWORD: yes
|
||||||
MYSQL_DATABASE: testgitea
|
MYSQL_DATABASE: testgitea
|
||||||
#
|
#
|
||||||
# See also https://codeberg.org/forgejo/forgejo/issues/976
|
# See also https://codeberg.org/forgejo/forgejo/issues/976
|
||||||
#
|
#
|
||||||
MYSQL_EXTRA_FLAGS: --innodb-adaptive-flushing=OFF --innodb-buffer-pool-size=4G --innodb-log-buffer-size=128M --innodb-flush-log-at-trx-commit=0 --innodb-flush-log-at-timeout=30 --innodb-flush-method=nosync --innodb-fsync-threshold=1000000000 --disable-log-bin
|
MYSQL_EXTRA_FLAGS: --innodb-adaptive-flushing=OFF --innodb-buffer-pool-size=4G --innodb-log-buffer-size=128M --innodb-flush-log-at-trx-commit=0 --innodb-flush-log-at-timeout=30 --innodb-flush-method=nosync --innodb-fsync-threshold=1000000000
|
||||||
options: --tmpfs /bitnami/mysql/data
|
|
||||||
steps:
|
steps:
|
||||||
- uses: https://code.forgejo.org/actions/checkout@v4
|
- uses: https://code.forgejo.org/actions/checkout@v4
|
||||||
- uses: ./.forgejo/workflows-composite/setup-env
|
- uses: ./.forgejo/workflows-composite/setup-env
|
||||||
|
@ -197,30 +187,28 @@ jobs:
|
||||||
- uses: ./.forgejo/workflows-composite/build-backend
|
- uses: ./.forgejo/workflows-composite/build-backend
|
||||||
- run: |
|
- run: |
|
||||||
su forgejo -c 'make test-mysql-migration test-mysql'
|
su forgejo -c 'make test-mysql-migration test-mysql'
|
||||||
timeout-minutes: 120
|
timeout-minutes: 50
|
||||||
env:
|
env:
|
||||||
USE_REPO_TEST_DIR: 1
|
USE_REPO_TEST_DIR: 1
|
||||||
test-pgsql:
|
test-pgsql:
|
||||||
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
|
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
needs: [backend-checks, frontend-checks]
|
needs: [backend-checks, frontend-checks]
|
||||||
container:
|
container:
|
||||||
image: 'code.forgejo.org/oci/node:20-bookworm'
|
image: 'code.forgejo.org/oci/node:20-bookworm'
|
||||||
services:
|
services:
|
||||||
minio:
|
minio:
|
||||||
image: code.forgejo.org/oci/bitnami/minio:2024.8.17
|
image: docker.io/bitnami/minio:2024.8.17
|
||||||
env:
|
env:
|
||||||
MINIO_ROOT_USER: 123456
|
MINIO_ROOT_USER: 123456
|
||||||
MINIO_ROOT_PASSWORD: 12345678
|
MINIO_ROOT_PASSWORD: 12345678
|
||||||
options: --tmpfs /bitnami/minio/data
|
|
||||||
ldap:
|
ldap:
|
||||||
image: code.forgejo.org/oci/test-openldap:latest
|
image: docker.io/gitea/test-openldap:latest
|
||||||
pgsql:
|
pgsql:
|
||||||
image: 'code.forgejo.org/oci/postgres:15'
|
image: 'code.forgejo.org/oci/postgres:15'
|
||||||
env:
|
env:
|
||||||
POSTGRES_DB: test
|
POSTGRES_DB: test
|
||||||
POSTGRES_PASSWORD: postgres
|
POSTGRES_PASSWORD: postgres
|
||||||
options: --tmpfs /var/lib/postgresql/data
|
|
||||||
steps:
|
steps:
|
||||||
- uses: https://code.forgejo.org/actions/checkout@v4
|
- uses: https://code.forgejo.org/actions/checkout@v4
|
||||||
- uses: ./.forgejo/workflows-composite/setup-env
|
- uses: ./.forgejo/workflows-composite/setup-env
|
||||||
|
@ -231,13 +219,13 @@ jobs:
|
||||||
- uses: ./.forgejo/workflows-composite/build-backend
|
- uses: ./.forgejo/workflows-composite/build-backend
|
||||||
- run: |
|
- run: |
|
||||||
su forgejo -c 'make test-pgsql-migration test-pgsql'
|
su forgejo -c 'make test-pgsql-migration test-pgsql'
|
||||||
timeout-minutes: 120
|
timeout-minutes: 50
|
||||||
env:
|
env:
|
||||||
RACE_ENABLED: true
|
RACE_ENABLED: true
|
||||||
USE_REPO_TEST_DIR: 1
|
USE_REPO_TEST_DIR: 1
|
||||||
TEST_LDAP: 1
|
TEST_LDAP: 1
|
||||||
test-sqlite:
|
test-sqlite:
|
||||||
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
|
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
needs: [backend-checks, frontend-checks]
|
needs: [backend-checks, frontend-checks]
|
||||||
container:
|
container:
|
||||||
|
@ -252,14 +240,14 @@ jobs:
|
||||||
- uses: ./.forgejo/workflows-composite/build-backend
|
- uses: ./.forgejo/workflows-composite/build-backend
|
||||||
- run: |
|
- run: |
|
||||||
su forgejo -c 'make test-sqlite-migration test-sqlite'
|
su forgejo -c 'make test-sqlite-migration test-sqlite'
|
||||||
timeout-minutes: 120
|
timeout-minutes: 50
|
||||||
env:
|
env:
|
||||||
TAGS: sqlite sqlite_unlock_notify
|
TAGS: sqlite sqlite_unlock_notify
|
||||||
RACE_ENABLED: true
|
RACE_ENABLED: true
|
||||||
TEST_TAGS: sqlite sqlite_unlock_notify
|
TEST_TAGS: sqlite sqlite_unlock_notify
|
||||||
USE_REPO_TEST_DIR: 1
|
USE_REPO_TEST_DIR: 1
|
||||||
security-check:
|
security-check:
|
||||||
if: vars.ROLE == 'forgejo-coding' || vars.ROLE == 'forgejo-testing'
|
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
needs:
|
needs:
|
||||||
- test-sqlite
|
- test-sqlite
|
||||||
|
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -115,9 +115,6 @@ prime/
|
||||||
*_source.tar.bz2
|
*_source.tar.bz2
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
# Direnv configuration
|
|
||||||
/.envrc
|
|
||||||
|
|
||||||
# nix-direnv generated files
|
# nix-direnv generated files
|
||||||
.direnv/
|
.direnv/
|
||||||
|
|
||||||
|
|
|
@ -77,8 +77,6 @@ linters-settings:
|
||||||
- name: unreachable-code
|
- name: unreachable-code
|
||||||
- name: var-declaration
|
- name: var-declaration
|
||||||
- name: var-naming
|
- name: var-naming
|
||||||
- name: redefines-builtin-id
|
|
||||||
disabled: true
|
|
||||||
gofumpt:
|
gofumpt:
|
||||||
extra-rules: true
|
extra-rules: true
|
||||||
depguard:
|
depguard:
|
||||||
|
|
38
.woodpecker/.build.yaml
Normal file
38
.woodpecker/.build.yaml
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
---
|
||||||
|
steps:
|
||||||
|
- name: build (prod)
|
||||||
|
image: woodpeckerci/plugin-docker-buildx
|
||||||
|
settings:
|
||||||
|
registry: git.ar21.de
|
||||||
|
username:
|
||||||
|
from_secret: REGISTRY_USER
|
||||||
|
password:
|
||||||
|
from_secret: REGISTRY_PASS
|
||||||
|
repo: git.ar21.de/tom/forkjo
|
||||||
|
platforms:
|
||||||
|
- linux/amd64
|
||||||
|
tags:
|
||||||
|
- latest
|
||||||
|
- ${CI_PIPELINE_NUMBER}
|
||||||
|
when:
|
||||||
|
- branch: forgejo
|
||||||
|
event: push
|
||||||
|
|
||||||
|
- name: build (experimental)
|
||||||
|
image: woodpeckerci/plugin-docker-buildx
|
||||||
|
settings:
|
||||||
|
registry: git.ar21.de
|
||||||
|
username:
|
||||||
|
from_secret: REGISTRY_USER
|
||||||
|
password:
|
||||||
|
from_secret: REGISTRY_PASS
|
||||||
|
repo: git.ar21.de/tom/forkjo
|
||||||
|
platforms:
|
||||||
|
- linux/amd64
|
||||||
|
tags:
|
||||||
|
- experimental
|
||||||
|
- experimental-${CI_PIPELINE_NUMBER}
|
||||||
|
when:
|
||||||
|
- branch:
|
||||||
|
exclude: forgejo
|
||||||
|
event: push
|
19
Makefile
19
Makefile
|
@ -39,7 +39,7 @@ XGO_VERSION := go-1.21.x
|
||||||
AIR_PACKAGE ?= github.com/air-verse/air@v1 # renovate: datasource=go
|
AIR_PACKAGE ?= github.com/air-verse/air@v1 # renovate: datasource=go
|
||||||
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v3/cmd/editorconfig-checker@v3.0.3 # renovate: datasource=go
|
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/v3/cmd/editorconfig-checker@v3.0.3 # renovate: datasource=go
|
||||||
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.7.0 # renovate: datasource=go
|
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@v0.7.0 # renovate: datasource=go
|
||||||
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.62.0 # renovate: datasource=go
|
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@v1.61.0 # renovate: datasource=go
|
||||||
GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11 # renovate: datasource=go
|
GXZ_PACKAGE ?= github.com/ulikunitz/xz/cmd/gxz@v0.5.11 # renovate: datasource=go
|
||||||
MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.6.0 # renovate: datasource=go
|
MISSPELL_PACKAGE ?= github.com/golangci/misspell/cmd/misspell@v0.6.0 # renovate: datasource=go
|
||||||
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.31.0 # renovate: datasource=go
|
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/swagger@v0.31.0 # renovate: datasource=go
|
||||||
|
@ -49,7 +49,7 @@ GOVULNCHECK_PACKAGE ?= golang.org/x/vuln/cmd/govulncheck@v1 # renovate: datasour
|
||||||
DEADCODE_PACKAGE ?= golang.org/x/tools/cmd/deadcode@v0.26.0 # renovate: datasource=go
|
DEADCODE_PACKAGE ?= golang.org/x/tools/cmd/deadcode@v0.26.0 # renovate: datasource=go
|
||||||
GOMOCK_PACKAGE ?= go.uber.org/mock/mockgen@v0.4.0 # renovate: datasource=go
|
GOMOCK_PACKAGE ?= go.uber.org/mock/mockgen@v0.4.0 # renovate: datasource=go
|
||||||
GOPLS_PACKAGE ?= golang.org/x/tools/gopls@v0.16.2 # renovate: datasource=go
|
GOPLS_PACKAGE ?= golang.org/x/tools/gopls@v0.16.2 # renovate: datasource=go
|
||||||
RENOVATE_NPM_PACKAGE ?= renovate@39.9.1 # renovate: datasource=docker packageName=code.forgejo.org/forgejo-contrib/renovate
|
RENOVATE_NPM_PACKAGE ?= renovate@38.128.6 # renovate: datasource=docker packageName=code.forgejo.org/forgejo-contrib/renovate
|
||||||
|
|
||||||
ifeq ($(HAS_GO), yes)
|
ifeq ($(HAS_GO), yes)
|
||||||
CGO_EXTRA_CFLAGS := -DSQLITE_MAX_VARIABLE_NUMBER=32766
|
CGO_EXTRA_CFLAGS := -DSQLITE_MAX_VARIABLE_NUMBER=32766
|
||||||
|
@ -164,8 +164,9 @@ TAR_EXCLUDES := .git data indexers queues log node_modules $(EXECUTABLE) $(FOMAN
|
||||||
GO_DIRS := build cmd models modules routers services tests
|
GO_DIRS := build cmd models modules routers services tests
|
||||||
WEB_DIRS := web_src/js web_src/css
|
WEB_DIRS := web_src/js web_src/css
|
||||||
|
|
||||||
|
ESLINT_FILES := web_src/js tools *.js *.mjs tests/e2e/*.js tests/e2e/shared/*.js
|
||||||
STYLELINT_FILES := web_src/css web_src/js/components/*.vue
|
STYLELINT_FILES := web_src/css web_src/js/components/*.vue
|
||||||
SPELLCHECK_FILES := $(GO_DIRS) $(WEB_DIRS) docs/content templates options/locale/locale_en-US.ini .github $(wildcard *.go *.js *.ts *.vue *.md *.yml *.yaml *.toml)
|
SPELLCHECK_FILES := $(GO_DIRS) $(WEB_DIRS) docs/content templates options/locale/locale_en-US.ini .github $(wildcard *.go *.js *.md *.yml *.yaml *.toml)
|
||||||
|
|
||||||
GO_SOURCES := $(wildcard *.go)
|
GO_SOURCES := $(wildcard *.go)
|
||||||
GO_SOURCES += $(shell find $(GO_DIRS) -type f -name "*.go" ! -path modules/options/bindata.go ! -path modules/public/bindata.go ! -path modules/templates/bindata.go)
|
GO_SOURCES += $(shell find $(GO_DIRS) -type f -name "*.go" ! -path modules/options/bindata.go ! -path modules/public/bindata.go ! -path modules/templates/bindata.go)
|
||||||
|
@ -417,7 +418,7 @@ lint-frontend: lint-js lint-css
|
||||||
lint-frontend-fix: lint-js-fix lint-css-fix
|
lint-frontend-fix: lint-js-fix lint-css-fix
|
||||||
|
|
||||||
.PHONY: lint-backend
|
.PHONY: lint-backend
|
||||||
lint-backend: lint-go lint-go-vet lint-editorconfig lint-renovate lint-locale
|
lint-backend: lint-go lint-go-vet lint-editorconfig lint-renovate
|
||||||
|
|
||||||
.PHONY: lint-backend-fix
|
.PHONY: lint-backend-fix
|
||||||
lint-backend-fix: lint-go-fix lint-go-vet lint-editorconfig
|
lint-backend-fix: lint-go-fix lint-go-vet lint-editorconfig
|
||||||
|
@ -436,11 +437,11 @@ lint-codespell-fix-i:
|
||||||
|
|
||||||
.PHONY: lint-js
|
.PHONY: lint-js
|
||||||
lint-js: node_modules
|
lint-js: node_modules
|
||||||
npx eslint --color --max-warnings=0
|
npx eslint --color --max-warnings=0 $(ESLINT_FILES)
|
||||||
|
|
||||||
.PHONY: lint-js-fix
|
.PHONY: lint-js-fix
|
||||||
lint-js-fix: node_modules
|
lint-js-fix: node_modules
|
||||||
npx eslint --color --max-warnings=0 --fix
|
npx eslint --color --max-warnings=0 $(ESLINT_FILES) --fix
|
||||||
|
|
||||||
.PHONY: lint-css
|
.PHONY: lint-css
|
||||||
lint-css: node_modules
|
lint-css: node_modules
|
||||||
|
@ -460,10 +461,6 @@ lint-renovate: node_modules
|
||||||
@if grep --quiet --extended-regexp -e '^( WARN:|ERROR:)' .lint-renovate ; then cat .lint-renovate ; rm .lint-renovate ; exit 1 ; fi
|
@if grep --quiet --extended-regexp -e '^( WARN:|ERROR:)' .lint-renovate ; then cat .lint-renovate ; rm .lint-renovate ; exit 1 ; fi
|
||||||
@rm .lint-renovate
|
@rm .lint-renovate
|
||||||
|
|
||||||
.PHONY: lint-locale
|
|
||||||
lint-locale:
|
|
||||||
$(GO) run build/lint-locale.go
|
|
||||||
|
|
||||||
.PHONY: lint-md
|
.PHONY: lint-md
|
||||||
lint-md: node_modules
|
lint-md: node_modules
|
||||||
npx markdownlint docs *.md
|
npx markdownlint docs *.md
|
||||||
|
@ -660,7 +657,6 @@ generate-ini-pgsql:
|
||||||
-e 's|{{REPO_TEST_DIR}}|${REPO_TEST_DIR}|g' \
|
-e 's|{{REPO_TEST_DIR}}|${REPO_TEST_DIR}|g' \
|
||||||
-e 's|{{TEST_LOGGER}}|$(or $(TEST_LOGGER),test$(COMMA)file)|g' \
|
-e 's|{{TEST_LOGGER}}|$(or $(TEST_LOGGER),test$(COMMA)file)|g' \
|
||||||
-e 's|{{TEST_TYPE}}|$(or $(TEST_TYPE),integration)|g' \
|
-e 's|{{TEST_TYPE}}|$(or $(TEST_TYPE),integration)|g' \
|
||||||
-e 's|{{TEST_STORAGE_TYPE}}|$(or $(TEST_STORAGE_TYPE),minio)|g' \
|
|
||||||
tests/pgsql.ini.tmpl > tests/pgsql.ini
|
tests/pgsql.ini.tmpl > tests/pgsql.ini
|
||||||
|
|
||||||
.PHONY: test-pgsql
|
.PHONY: test-pgsql
|
||||||
|
@ -716,6 +712,7 @@ test-e2e-pgsql\#%: playwright e2e.pgsql.test generate-ini-pgsql
|
||||||
|
|
||||||
.PHONY: test-e2e-debugserver
|
.PHONY: test-e2e-debugserver
|
||||||
test-e2e-debugserver: e2e.sqlite.test generate-ini-sqlite
|
test-e2e-debugserver: e2e.sqlite.test generate-ini-sqlite
|
||||||
|
sed -i s/3003/3000/g tests/sqlite.ini
|
||||||
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./e2e.sqlite.test -test.run TestDebugserver -test.timeout 24h
|
GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini ./e2e.sqlite.test -test.run TestDebugserver -test.timeout 24h
|
||||||
|
|
||||||
.PHONY: bench-sqlite
|
.PHONY: bench-sqlite
|
||||||
|
|
|
@ -6,14 +6,6 @@ A [patch or minor release](https://semver.org/spec/v2.0.0.html) (e.g. upgrading
|
||||||
|
|
||||||
The release notes of each release [are available in the corresponding milestone](https://codeberg.org/forgejo/forgejo/milestones), starting with [Forgejo 7.0.7](https://codeberg.org/forgejo/forgejo/milestone/7683) and [Forgejo 8.0.1](https://codeberg.org/forgejo/forgejo/milestone/7682).
|
The release notes of each release [are available in the corresponding milestone](https://codeberg.org/forgejo/forgejo/milestones), starting with [Forgejo 7.0.7](https://codeberg.org/forgejo/forgejo/milestone/7683) and [Forgejo 8.0.1](https://codeberg.org/forgejo/forgejo/milestone/7682).
|
||||||
|
|
||||||
## 9.0.2
|
|
||||||
|
|
||||||
The Forgejo v9.0.2 release notes are [available in the v9.0.2 milestone](https://codeberg.org/forgejo/forgejo/milestone/8610).
|
|
||||||
|
|
||||||
## 9.0.1
|
|
||||||
|
|
||||||
The Forgejo v9.0.1 release notes are [available in the v9.0.1 milestone](https://codeberg.org/forgejo/forgejo/milestone/8544).
|
|
||||||
|
|
||||||
## 9.0.0
|
## 9.0.0
|
||||||
|
|
||||||
The Forgejo v9.0.0 release notes are [available in the v9.0.0 milestone](https://codeberg.org/forgejo/forgejo/milestone/7235).
|
The Forgejo v9.0.0 release notes are [available in the v9.0.0 milestone](https://codeberg.org/forgejo/forgejo/milestone/7235).
|
||||||
|
@ -167,14 +159,6 @@ A [companion blog post](https://forgejo.org/2024-07-release-v8-0/) provides addi
|
||||||
- [PR](https://codeberg.org/forgejo/forgejo/pulls/2937): <!--number 2937 --><!--number--><!--description -->31 March updates<!--description-->
|
- [PR](https://codeberg.org/forgejo/forgejo/pulls/2937): <!--number 2937 --><!--number--><!--description -->31 March updates<!--description-->
|
||||||
<!--end release-notes-assistant-->
|
<!--end release-notes-assistant-->
|
||||||
|
|
||||||
## 7.0.11
|
|
||||||
|
|
||||||
The Forgejo v7.0.11 release notes are [available in the v7.0.11 milestone](https://codeberg.org/forgejo/forgejo/milestone/8609).
|
|
||||||
|
|
||||||
## 7.0.10
|
|
||||||
|
|
||||||
The Forgejo v7.0.10 release notes are [available in the v7.0.10 milestone](https://codeberg.org/forgejo/forgejo/milestone/8286).
|
|
||||||
|
|
||||||
## 7.0.9
|
## 7.0.9
|
||||||
|
|
||||||
The Forgejo v7.0.9 release notes are [available in the v7.0.9 milestone](https://codeberg.org/forgejo/forgejo/milestone/8232).
|
The Forgejo v7.0.9 release notes are [available in the v7.0.9 milestone](https://codeberg.org/forgejo/forgejo/milestone/8232).
|
||||||
|
|
12
assets/go-licenses.json
generated
12
assets/go-licenses.json
generated
File diff suppressed because one or more lines are too long
|
@ -53,6 +53,8 @@ func (e Emoji) MarshalJSON() ([]byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
var err error
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
// generate data
|
// generate data
|
||||||
|
@ -81,6 +83,8 @@ var replacer = strings.NewReplacer(
|
||||||
var emojiRE = regexp.MustCompile(`\{Emoji:"([^"]*)"`)
|
var emojiRE = regexp.MustCompile(`\{Emoji:"([^"]*)"`)
|
||||||
|
|
||||||
func generate() ([]byte, error) {
|
func generate() ([]byte, error) {
|
||||||
|
var err error
|
||||||
|
|
||||||
// load gemoji data
|
// load gemoji data
|
||||||
res, err := http.Get(gemojiURL)
|
res, err := http.Get(gemojiURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -1,156 +0,0 @@
|
||||||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
//nolint:forbidigo
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"html"
|
|
||||||
"io/fs"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"regexp"
|
|
||||||
"slices"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/microcosm-cc/bluemonday"
|
|
||||||
"github.com/sergi/go-diff/diffmatchpatch"
|
|
||||||
"gopkg.in/ini.v1" //nolint:depguard
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
policy *bluemonday.Policy
|
|
||||||
tagRemover *strings.Replacer
|
|
||||||
safeURL = "https://TO-BE-REPLACED.COM"
|
|
||||||
|
|
||||||
// Matches href="", href="#", href="%s", href="#%s", href="%[1]s" and href="#%[1]s".
|
|
||||||
placeHolderRegex = regexp.MustCompile(`href="#?(%s|%\[\d\]s)?"`)
|
|
||||||
)
|
|
||||||
|
|
||||||
func initBlueMondayPolicy() {
|
|
||||||
policy = bluemonday.NewPolicy()
|
|
||||||
|
|
||||||
policy.RequireParseableURLs(true)
|
|
||||||
policy.AllowURLSchemes("https")
|
|
||||||
|
|
||||||
// Only allow safe URL on href.
|
|
||||||
// Only allow target="_blank".
|
|
||||||
// Only allow rel="nopener noreferrer", rel="noopener" and rel="noreferrer".
|
|
||||||
// Only allow placeholder on id and class.
|
|
||||||
policy.AllowAttrs("href").Matching(regexp.MustCompile("^" + regexp.QuoteMeta(safeURL) + "$")).OnElements("a")
|
|
||||||
policy.AllowAttrs("target").Matching(regexp.MustCompile("^_blank$")).OnElements("a")
|
|
||||||
policy.AllowAttrs("rel").Matching(regexp.MustCompile("^(noopener|noreferrer|noopener noreferrer)$")).OnElements("a")
|
|
||||||
policy.AllowAttrs("id", "class").Matching(regexp.MustCompile(`^%s|%\[\d\]s$`)).OnElements("a")
|
|
||||||
|
|
||||||
// Only allow positional placeholder as class.
|
|
||||||
positionalPlaceholderRe := regexp.MustCompile(`^%\[\d\]s$`)
|
|
||||||
policy.AllowAttrs("class").Matching(positionalPlaceholderRe).OnElements("strong")
|
|
||||||
policy.AllowAttrs("id").Matching(positionalPlaceholderRe).OnElements("code")
|
|
||||||
|
|
||||||
// Allowed elements with no attributes. Must be a recognized tagname.
|
|
||||||
policy.AllowElements("strong", "br", "b", "strike", "code", "i")
|
|
||||||
|
|
||||||
// TODO: Remove <c> in `actions.workflow.dispatch.trigger_found`.
|
|
||||||
policy.AllowNoAttrs().OnElements("c")
|
|
||||||
}
|
|
||||||
|
|
||||||
func initRemoveTags() {
|
|
||||||
oldnew := []string{}
|
|
||||||
for _, el := range []string{
|
|
||||||
"email@example.com", "correu@example.com", "epasts@domens.lv", "email@exemplo.com", "eposta@ornek.com", "email@példa.hu", "email@esempio.it",
|
|
||||||
"user", "utente", "lietotājs", "gebruiker", "usuário", "Benutzer", "Bruker",
|
|
||||||
"server", "servidor", "kiszolgáló", "serveris",
|
|
||||||
"label", "etichetta", "etiķete", "rótulo", "Label", "utilizador",
|
|
||||||
"filename", "bestandsnaam", "dosyaadi", "fails", "nome do arquivo", "datnes nosaukums",
|
|
||||||
} {
|
|
||||||
oldnew = append(oldnew, "<"+el+">", "REPLACED-TAG")
|
|
||||||
}
|
|
||||||
|
|
||||||
tagRemover = strings.NewReplacer(oldnew...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func preprocessTranslationValue(value string) string {
|
|
||||||
// href should be a parsable URL, replace placeholder strings with a safe url.
|
|
||||||
value = placeHolderRegex.ReplaceAllString(value, `href="`+safeURL+`"`)
|
|
||||||
|
|
||||||
// Remove tags that aren't tags but will be parsed as tags. We already know they are safe and sound.
|
|
||||||
value = tagRemover.Replace(value)
|
|
||||||
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkLocaleContent(localeContent []byte) []string {
|
|
||||||
// Same configuration as Forgejo uses.
|
|
||||||
cfg := ini.Empty(ini.LoadOptions{
|
|
||||||
IgnoreContinuation: true,
|
|
||||||
})
|
|
||||||
cfg.NameMapper = ini.SnackCase
|
|
||||||
|
|
||||||
if err := cfg.Append(localeContent); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
dmp := diffmatchpatch.New()
|
|
||||||
errors := []string{}
|
|
||||||
|
|
||||||
for _, section := range cfg.Sections() {
|
|
||||||
for _, key := range section.Keys() {
|
|
||||||
var trKey string
|
|
||||||
if section.Name() == "" || section.Name() == "DEFAULT" || section.Name() == "common" {
|
|
||||||
trKey = key.Name()
|
|
||||||
} else {
|
|
||||||
trKey = section.Name() + "." + key.Name()
|
|
||||||
}
|
|
||||||
|
|
||||||
keyValue := preprocessTranslationValue(key.Value())
|
|
||||||
|
|
||||||
if html.UnescapeString(policy.Sanitize(keyValue)) != keyValue {
|
|
||||||
// Create a nice diff of the difference.
|
|
||||||
diffs := dmp.DiffMain(keyValue, html.UnescapeString(policy.Sanitize(keyValue)), false)
|
|
||||||
diffs = dmp.DiffCleanupSemantic(diffs)
|
|
||||||
diffs = dmp.DiffCleanupEfficiency(diffs)
|
|
||||||
|
|
||||||
errors = append(errors, trKey+": "+dmp.DiffPrettyText(diffs))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return errors
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
initBlueMondayPolicy()
|
|
||||||
initRemoveTags()
|
|
||||||
|
|
||||||
localeDir := filepath.Join("options", "locale")
|
|
||||||
localeFiles, err := os.ReadDir(localeDir)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !slices.ContainsFunc(localeFiles, func(e fs.DirEntry) bool { return strings.HasSuffix(e.Name(), ".ini") }) {
|
|
||||||
fmt.Println("No locale files found")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
exitCode := 0
|
|
||||||
for _, localeFile := range localeFiles {
|
|
||||||
if !strings.HasSuffix(localeFile.Name(), ".ini") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
localeContent, err := os.ReadFile(filepath.Join(localeDir, localeFile.Name()))
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := checkLocaleContent(localeContent); len(err) > 0 {
|
|
||||||
fmt.Println(localeFile.Name())
|
|
||||||
fmt.Println(strings.Join(err, "\n"))
|
|
||||||
fmt.Println()
|
|
||||||
exitCode = 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
os.Exit(exitCode)
|
|
||||||
}
|
|
|
@ -1,65 +0,0 @@
|
||||||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestLocalizationPolicy(t *testing.T) {
|
|
||||||
initBlueMondayPolicy()
|
|
||||||
initRemoveTags()
|
|
||||||
|
|
||||||
t.Run("Remove tags", func(t *testing.T) {
|
|
||||||
assert.Empty(t, checkLocaleContent([]byte(`hidden_comment_types_description = Comment types checked here will not be shown inside issue pages. Checking "Label" for example removes all "<user> added/removed <label>" comments.`)))
|
|
||||||
|
|
||||||
assert.EqualValues(t, []string{"key: \x1b[31m<not-an-allowed-key>\x1b[0m REPLACED-TAG"}, checkLocaleContent([]byte(`key = "<not-an-allowed-key> <label>"`)))
|
|
||||||
assert.EqualValues(t, []string{"key: \x1b[31m<user@example.com>\x1b[0m REPLACED-TAG"}, checkLocaleContent([]byte(`key = "<user@example.com> <email@example.com>"`)))
|
|
||||||
assert.EqualValues(t, []string{"key: \x1b[31m<tag>\x1b[0m REPLACED-TAG \x1b[31m</tag>\x1b[0m"}, checkLocaleContent([]byte(`key = "<tag> <email@example.com> </tag>"`)))
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("Specific exception", func(t *testing.T) {
|
|
||||||
assert.Empty(t, checkLocaleContent([]byte(`workflow.dispatch.trigger_found = This workflow has a <c>workflow_dispatch</c> event trigger.`)))
|
|
||||||
assert.Empty(t, checkLocaleContent([]byte(`pulls.title_desc_one = wants to merge %[1]d commit from <code>%[2]s</code> into <code id="%[4]s">%[3]s</code>`)))
|
|
||||||
assert.Empty(t, checkLocaleContent([]byte(`editor.commit_directly_to_this_branch = Commit directly to the <strong class="%[2]s">%[1]s</strong> branch.`)))
|
|
||||||
|
|
||||||
assert.EqualValues(t, []string{"workflow.dispatch.trigger_found: This workflow has a \x1b[31m<d>\x1b[0mworkflow_dispatch\x1b[31m</d>\x1b[0m event trigger."}, checkLocaleContent([]byte(`workflow.dispatch.trigger_found = This workflow has a <d>workflow_dispatch</d> event trigger.`)))
|
|
||||||
assert.EqualValues(t, []string{"key: <code\x1b[31m id=\"branch_targe\"\x1b[0m>%[3]s</code>"}, checkLocaleContent([]byte(`key = <code id="branch_targe">%[3]s</code>`)))
|
|
||||||
assert.EqualValues(t, []string{"key: <a\x1b[31m class=\"ui sh\"\x1b[0m href=\"https://TO-BE-REPLACED.COM\">"}, checkLocaleContent([]byte(`key = <a class="ui sh" href="%[3]s">`)))
|
|
||||||
assert.EqualValues(t, []string{"key: <a\x1b[31m class=\"js-click-me\"\x1b[0m href=\"https://TO-BE-REPLACED.COM\">"}, checkLocaleContent([]byte(`key = <a class="js-click-me" href="%[3]s">`)))
|
|
||||||
assert.EqualValues(t, []string{"key: <strong\x1b[31m class=\"branch-target\"\x1b[0m>%[1]s</strong>"}, checkLocaleContent([]byte(`key = <strong class="branch-target">%[1]s</strong>`)))
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("General safe tags", func(t *testing.T) {
|
|
||||||
assert.Empty(t, checkLocaleContent([]byte("error404 = The page you are trying to reach either <strong>does not exist</strong> or <strong>you are not authorized</strong> to view it.")))
|
|
||||||
assert.Empty(t, checkLocaleContent([]byte("teams.specific_repositories_helper = Members will only have access to repositories explicitly added to the team. Selecting this <strong>will not</strong> automatically remove repositories already added with <i>All repositories</i>.")))
|
|
||||||
assert.Empty(t, checkLocaleContent([]byte("sqlite_helper = File path for the SQLite3 database.<br>Enter an absolute path if you run Forgejo as a service.")))
|
|
||||||
assert.Empty(t, checkLocaleContent([]byte("hi_user_x = Hi <b>%s</b>,")))
|
|
||||||
|
|
||||||
assert.EqualValues(t, []string{"error404: The page you are trying to reach either <strong\x1b[31m title='aaa'\x1b[0m>does not exist</strong> or <strong>you are not authorized</strong> to view it."}, checkLocaleContent([]byte("error404 = The page you are trying to reach either <strong title='aaa'>does not exist</strong> or <strong>you are not authorized</strong> to view it.")))
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("<a>", func(t *testing.T) {
|
|
||||||
assert.Empty(t, checkLocaleContent([]byte(`admin.new_user.text = Please <a href="%s">click here</a> to manage this user from the admin panel.`)))
|
|
||||||
assert.Empty(t, checkLocaleContent([]byte(`access_token_desc = Selected token permissions limit authorization only to the corresponding <a href="%[1]s" target="_blank">API</a> routes. Read the <a href="%[2]s" target="_blank">documentation</a> for more information.`)))
|
|
||||||
assert.Empty(t, checkLocaleContent([]byte(`webauthn_desc = Security keys are hardware devices containing cryptographic keys. They can be used for two-factor authentication. Security keys must support the <a rel="noreferrer" target="_blank" href="%s">WebAuthn Authenticator</a> standard.`)))
|
|
||||||
assert.Empty(t, checkLocaleContent([]byte("issues.closed_at = `closed this issue <a id=\"%[1]s\" href=\"#%[1]s\">%[2]s</a>`")))
|
|
||||||
|
|
||||||
assert.EqualValues(t, []string{"key: \x1b[31m<a href=\"https://example.com\">\x1b[0m"}, checkLocaleContent([]byte(`key = <a href="https://example.com">`)))
|
|
||||||
assert.EqualValues(t, []string{"key: \x1b[31m<a href=\"javascript:alert('1')\">\x1b[0m"}, checkLocaleContent([]byte(`key = <a href="javascript:alert('1')">`)))
|
|
||||||
assert.EqualValues(t, []string{"key: <a href=\"https://TO-BE-REPLACED.COM\"\x1b[31m download\x1b[0m>"}, checkLocaleContent([]byte(`key = <a href="%s" download>`)))
|
|
||||||
assert.EqualValues(t, []string{"key: <a href=\"https://TO-BE-REPLACED.COM\"\x1b[31m target=\"_self\"\x1b[0m>"}, checkLocaleContent([]byte(`key = <a href="%s" target="_self">`)))
|
|
||||||
assert.EqualValues(t, []string{"key: \x1b[31m<a href=\"https://example.com/%s\">\x1b[0m"}, checkLocaleContent([]byte(`key = <a href="https://example.com/%s">`)))
|
|
||||||
assert.EqualValues(t, []string{"key: \x1b[31m<a href=\"https://example.com/?q=%s\">\x1b[0m"}, checkLocaleContent([]byte(`key = <a href="https://example.com/?q=%s">`)))
|
|
||||||
assert.EqualValues(t, []string{"key: \x1b[31m<a href=\"%s/open-redirect\">\x1b[0m"}, checkLocaleContent([]byte(`key = <a href="%s/open-redirect">`)))
|
|
||||||
assert.EqualValues(t, []string{"key: \x1b[31m<a href=\"%s?q=open-redirect\">\x1b[0m"}, checkLocaleContent([]byte(`key = <a href="%s?q=open-redirect">`)))
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("Escaped HTML characters", func(t *testing.T) {
|
|
||||||
assert.Empty(t, checkLocaleContent([]byte("activity.git_stats_push_to_branch = `إلى %s و\"`")))
|
|
||||||
|
|
||||||
assert.EqualValues(t, []string{"key: و\x1b[31m \x1b[0m\x1b[32m\u00a0\x1b[0m"}, checkLocaleContent([]byte(`key = و `)))
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -386,7 +386,7 @@ func (a *authService) addLdapSimpleAuth(c *cli.Context) error {
|
||||||
return a.createAuthSource(ctx, authSource)
|
return a.createAuthSource(ctx, authSource)
|
||||||
}
|
}
|
||||||
|
|
||||||
// updateLdapSimpleAuth updates a new LDAP (simple auth) authentication source.
|
// updateLdapBindDn updates a new LDAP (simple auth) authentication source.
|
||||||
func (a *authService) updateLdapSimpleAuth(c *cli.Context) error {
|
func (a *authService) updateLdapSimpleAuth(c *cli.Context) error {
|
||||||
ctx, cancel := installSignals()
|
ctx, cancel := installSignals()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
|
@ -91,7 +91,7 @@ func TestMigrateActionsArtifacts(t *testing.T) {
|
||||||
|
|
||||||
srcStorage, _ := createLocalStorage(t)
|
srcStorage, _ := createLocalStorage(t)
|
||||||
defer test.MockVariableValue(&storage.ActionsArtifacts, srcStorage)()
|
defer test.MockVariableValue(&storage.ActionsArtifacts, srcStorage)()
|
||||||
id := int64(42)
|
id := int64(0)
|
||||||
|
|
||||||
addArtifact := func(storagePath string, status actions.ArtifactStatus) {
|
addArtifact := func(storagePath string, status actions.ArtifactStatus) {
|
||||||
id++
|
id++
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
{
|
{
|
||||||
"go.buildTags": "sqlite,sqlite_unlock_notify",
|
"go.buildTags": "sqlite,sqlite_unlock_notify",
|
||||||
"go.testFlags": ["-v"],
|
"go.testFlags": ["-v"]
|
||||||
"go.lintTool": "golangci-lint",
|
|
||||||
"go.lintFlags": ["--fast"]
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -328,10 +328,6 @@ RUN_USER = ; git
|
||||||
;; Maximum number of locks returned per page
|
;; Maximum number of locks returned per page
|
||||||
;LFS_LOCKS_PAGING_NUM = 50
|
;LFS_LOCKS_PAGING_NUM = 50
|
||||||
;;
|
;;
|
||||||
;; When clients make lfs batch requests, reject them if there are more pointers than this number
|
|
||||||
;; zero means 'unlimited'
|
|
||||||
;LFS_MAX_BATCH_SIZE = 0
|
|
||||||
;;
|
|
||||||
;; Allow graceful restarts using SIGHUP to fork
|
;; Allow graceful restarts using SIGHUP to fork
|
||||||
;ALLOW_GRACEFUL_RESTARTS = true
|
;ALLOW_GRACEFUL_RESTARTS = true
|
||||||
;;
|
;;
|
||||||
|
@ -353,25 +349,16 @@ RUN_USER = ; git
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;
|
;;
|
||||||
;; Database to use. Either "sqlite3", "mySQL" or "postgres".
|
;; Database to use. Either "mysql", "postgres", "mssql" or "sqlite3".
|
||||||
;;
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
;;
|
|
||||||
;; SQLite Configuration
|
|
||||||
;;
|
|
||||||
DB_TYPE = sqlite3
|
|
||||||
;PATH= ; defaults to data/forgejo.db
|
|
||||||
;SQLITE_TIMEOUT = ; Query timeout defaults to: 500
|
|
||||||
;SQLITE_JOURNAL_MODE = ; defaults to sqlite database default (often DELETE), can be used to enable WAL mode. https://www.sqlite.org/pragma.html#pragma_journal_mode
|
|
||||||
;;
|
;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;
|
;;
|
||||||
;; MySQL Configuration
|
;; MySQL Configuration
|
||||||
;;
|
;;
|
||||||
;DB_TYPE = mysql
|
DB_TYPE = mysql
|
||||||
;HOST = 127.0.0.1:3306 ; can use socket e.g. /var/run/mysqld/mysqld.sock
|
HOST = 127.0.0.1:3306 ; can use socket e.g. /var/run/mysqld/mysqld.sock
|
||||||
;NAME = gitea
|
NAME = gitea
|
||||||
;USER = root
|
USER = root
|
||||||
;PASSWD = ;Use PASSWD = `your password` for quoting if you use special characters in the password.
|
;PASSWD = ;Use PASSWD = `your password` for quoting if you use special characters in the password.
|
||||||
;SSL_MODE = false ; either "false" (default), "true", or "skip-verify"
|
;SSL_MODE = false ; either "false" (default), "true", or "skip-verify"
|
||||||
;CHARSET_COLLATION = ; Empty as default, Gitea will try to find a case-sensitive collation. Don't change it unless you clearly know what you need.
|
;CHARSET_COLLATION = ; Empty as default, Gitea will try to find a case-sensitive collation. Don't change it unless you clearly know what you need.
|
||||||
|
@ -390,6 +377,26 @@ DB_TYPE = sqlite3
|
||||||
;;
|
;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;
|
;;
|
||||||
|
;; SQLite Configuration
|
||||||
|
;;
|
||||||
|
;DB_TYPE = sqlite3
|
||||||
|
;PATH= ; defaults to data/forgejo.db
|
||||||
|
;SQLITE_TIMEOUT = ; Query timeout defaults to: 500
|
||||||
|
;SQLITE_JOURNAL_MODE = ; defaults to sqlite database default (often DELETE), can be used to enable WAL mode. https://www.sqlite.org/pragma.html#pragma_journal_mode
|
||||||
|
;;
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;;
|
||||||
|
;; MSSQL Configuration
|
||||||
|
;;
|
||||||
|
;DB_TYPE = mssql
|
||||||
|
;HOST = 172.17.0.2:1433
|
||||||
|
;NAME = gitea
|
||||||
|
;USER = SA
|
||||||
|
;PASSWD = MwantsaSecurePassword1
|
||||||
|
;CHARSET_COLLATION = ; Empty as default, Gitea will try to find a case-sensitive collation. Don't change it unless you clearly know what you need.
|
||||||
|
;;
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
;;
|
||||||
;; Other settings
|
;; Other settings
|
||||||
;;
|
;;
|
||||||
;; For iterate buffer, default is 50
|
;; For iterate buffer, default is 50
|
||||||
|
@ -918,24 +925,6 @@ LEVEL = Info
|
||||||
;; Valid site url schemes for user profiles
|
;; Valid site url schemes for user profiles
|
||||||
;VALID_SITE_URL_SCHEMES=http,https
|
;VALID_SITE_URL_SCHEMES=http,https
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
;[service.explore]
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
;;
|
|
||||||
;; Only allow signed in users to view the explore pages.
|
|
||||||
;REQUIRE_SIGNIN_VIEW = false
|
|
||||||
;;
|
|
||||||
;; Disable the users explore page.
|
|
||||||
;DISABLE_USERS_PAGE = false
|
|
||||||
;;
|
|
||||||
;; Disable the organizations explore page.
|
|
||||||
;DISABLE_ORGANIZATIONS_PAGE = false
|
|
||||||
;;
|
|
||||||
;; Disable the code explore page.
|
|
||||||
;DISABLE_CODE_PAGE = false
|
|
||||||
;;
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -1938,7 +1927,7 @@ LEVEL = Info
|
||||||
;ENABLED = true
|
;ENABLED = true
|
||||||
;;
|
;;
|
||||||
;; Comma-separated list of allowed file extensions (`.zip`), mime types (`text/plain`) or wildcard type (`image/*`, `audio/*`, `video/*`). Empty value or `*/*` allows all types.
|
;; Comma-separated list of allowed file extensions (`.zip`), mime types (`text/plain`) or wildcard type (`image/*`, `audio/*`, `video/*`). Empty value or `*/*` allows all types.
|
||||||
;ALLOWED_TYPES = .avif,.cpuprofile,.csv,.dmp,.docx,.fodg,.fodp,.fods,.fodt,.gif,.gz,.jpeg,.jpg,.json,.jsonc,.log,.md,.mov,.mp4,.odf,.odg,.odp,.ods,.odt,.patch,.pdf,.png,.pptx,.svg,.tgz,.txt,.webm,.xls,.xlsx,.zip
|
;ALLOWED_TYPES = .cpuprofile,.csv,.dmp,.docx,.fodg,.fodp,.fods,.fodt,.gif,.gz,.jpeg,.jpg,.json,.jsonc,.log,.md,.mov,.mp4,.odf,.odg,.odp,.ods,.odt,.patch,.pdf,.png,.pptx,.svg,.tgz,.txt,.webm,.xls,.xlsx,.zip
|
||||||
;;
|
;;
|
||||||
;; Max size of each file. Defaults to 2048MB
|
;; Max size of each file. Defaults to 2048MB
|
||||||
;MAX_SIZE = 2048
|
;MAX_SIZE = 2048
|
||||||
|
@ -2665,10 +2654,6 @@ LEVEL = Info
|
||||||
;; override the minio base path if storage type is minio
|
;; override the minio base path if storage type is minio
|
||||||
;MINIO_BASE_PATH = lfs/
|
;MINIO_BASE_PATH = lfs/
|
||||||
|
|
||||||
;[lfs_client]
|
|
||||||
;; When mirroring an upstream lfs endpoint, limit the number of pointers in each batch request to this number
|
|
||||||
;BATCH_SIZE = 20
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; settings for packages, will override storage setting
|
;; settings for packages, will override storage setting
|
||||||
|
|
|
@ -14,15 +14,10 @@ import wc from 'eslint-plugin-wc';
|
||||||
import globals from 'globals';
|
import globals from 'globals';
|
||||||
import vue from 'eslint-plugin-vue';
|
import vue from 'eslint-plugin-vue';
|
||||||
import vueScopedCss from 'eslint-plugin-vue-scoped-css';
|
import vueScopedCss from 'eslint-plugin-vue-scoped-css';
|
||||||
import tseslint from 'typescript-eslint';
|
|
||||||
|
|
||||||
export default tseslint.config(
|
export default [{
|
||||||
...tseslint.configs.recommended,
|
ignores: ['web_src/js/vendor', 'web_src/fomantic', 'public/assets/js'],
|
||||||
eslintPluginImportX.flatConfigs.typescript,
|
}, {
|
||||||
{
|
|
||||||
ignores: ['web_src/js/vendor', 'web_src/fomantic', 'public/assets/js', 'tests/e2e/reports/'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
plugins: {
|
plugins: {
|
||||||
'@eslint-community/eslint-comments': eslintCommunityEslintPluginEslintComments,
|
'@eslint-community/eslint-comments': eslintCommunityEslintPluginEslintComments,
|
||||||
'@stylistic/js': stylisticEslintPluginJs,
|
'@stylistic/js': stylisticEslintPluginJs,
|
||||||
|
@ -57,8 +52,6 @@ export default tseslint.config(
|
||||||
sourceType: 'module',
|
sourceType: 'module',
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
'@typescript-eslint/no-unused-vars': 'off', // TODO: enable this rule again
|
|
||||||
|
|
||||||
'@eslint-community/eslint-comments/disable-enable-pair': [2],
|
'@eslint-community/eslint-comments/disable-enable-pair': [2],
|
||||||
'@eslint-community/eslint-comments/no-aggregating-enable': [2],
|
'@eslint-community/eslint-comments/no-aggregating-enable': [2],
|
||||||
'@eslint-community/eslint-comments/no-duplicate-disable': [2],
|
'@eslint-community/eslint-comments/no-duplicate-disable': [2],
|
||||||
|
@ -1038,7 +1031,6 @@ export default tseslint.config(
|
||||||
rules: {
|
rules: {
|
||||||
'import-x/no-unused-modules': [0],
|
'import-x/no-unused-modules': [0],
|
||||||
'import-x/no-unresolved': [0],
|
'import-x/no-unresolved': [0],
|
||||||
'import-x/no-named-as-default': [0],
|
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
files: ['**/*.test.*', 'web_src/js/test/setup.js'],
|
files: ['**/*.test.*', 'web_src/js/test/setup.js'],
|
||||||
|
@ -1112,7 +1104,7 @@ export default tseslint.config(
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
files: ['tests/e2e/**/*.ts'],
|
files: ['tests/e2e/**/*.js'],
|
||||||
languageOptions: {
|
languageOptions: {
|
||||||
globals: {
|
globals: {
|
||||||
...globals.browser,
|
...globals.browser,
|
||||||
|
@ -1125,8 +1117,7 @@ export default tseslint.config(
|
||||||
...playwright.configs['flat/recommended'].rules,
|
...playwright.configs['flat/recommended'].rules,
|
||||||
'playwright/no-conditional-in-test': [0],
|
'playwright/no-conditional-in-test': [0],
|
||||||
'playwright/no-conditional-expect': [0],
|
'playwright/no-conditional-expect': [0],
|
||||||
// allow grouping helper functions with tests
|
'playwright/no-networkidle': [0],
|
||||||
'unicorn/consistent-function-scoping': [0],
|
|
||||||
|
|
||||||
'playwright/no-skipped-test': [
|
'playwright/no-skipped-test': [
|
||||||
2,
|
2,
|
||||||
|
@ -1167,4 +1158,4 @@ export default tseslint.config(
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
);
|
];
|
||||||
|
|
50
go.mod
50
go.mod
|
@ -1,20 +1,20 @@
|
||||||
module code.gitea.io/gitea
|
module code.gitea.io/gitea
|
||||||
|
|
||||||
go 1.23.3
|
go 1.23.2
|
||||||
|
|
||||||
require (
|
require (
|
||||||
code.forgejo.org/f3/gof3/v3 v3.7.0
|
code.forgejo.org/f3/gof3/v3 v3.7.0
|
||||||
code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20191008002943-06d1c002b251
|
code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20191008002943-06d1c002b251
|
||||||
code.forgejo.org/forgejo/reply v1.0.2
|
code.forgejo.org/forgejo/reply v1.0.2
|
||||||
code.forgejo.org/go-chi/binding v1.0.0
|
code.forgejo.org/go-chi/cache v0.0.0-20240912103640-dcb08fba860d
|
||||||
code.forgejo.org/go-chi/cache v1.0.0
|
code.forgejo.org/go-chi/captcha v0.0.0-20240905153133-df43b9250ed5
|
||||||
code.forgejo.org/go-chi/captcha v1.0.0
|
code.forgejo.org/go-chi/session v0.0.0-20241017103059-2a992261fc26
|
||||||
code.forgejo.org/go-chi/session v1.0.0
|
|
||||||
code.gitea.io/actions-proto-go v0.4.0
|
code.gitea.io/actions-proto-go v0.4.0
|
||||||
code.gitea.io/gitea-vet v0.2.3
|
code.gitea.io/gitea-vet v0.2.3
|
||||||
code.gitea.io/sdk/gitea v0.17.1
|
code.gitea.io/sdk/gitea v0.17.1
|
||||||
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570
|
codeberg.org/gusted/mcaptcha v0.0.0-20220723083913-4f3072e1d570
|
||||||
connectrpc.com/connect v1.17.0
|
connectrpc.com/connect v1.17.0
|
||||||
|
gitea.com/go-chi/binding v0.0.0-20240430071103-39a851e106ed
|
||||||
gitea.com/lunny/levelqueue v0.4.2-0.20230414023320-3c0159fe0fe4
|
gitea.com/lunny/levelqueue v0.4.2-0.20230414023320-3c0159fe0fe4
|
||||||
github.com/42wim/sshsig v0.0.0-20211121163825-841cf5bbc121
|
github.com/42wim/sshsig v0.0.0-20211121163825-841cf5bbc121
|
||||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358
|
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358
|
||||||
|
@ -23,8 +23,8 @@ require (
|
||||||
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.7.2
|
github.com/SaveTheRbtz/zstd-seekable-format-go/pkg v0.7.2
|
||||||
github.com/alecthomas/chroma/v2 v2.14.0
|
github.com/alecthomas/chroma/v2 v2.14.0
|
||||||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
|
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb
|
||||||
github.com/blevesearch/bleve/v2 v2.4.3
|
github.com/blevesearch/bleve/v2 v2.4.2
|
||||||
github.com/buildkite/terminal-to-html/v3 v3.16.4
|
github.com/buildkite/terminal-to-html/v3 v3.16.3
|
||||||
github.com/caddyserver/certmagic v0.21.4
|
github.com/caddyserver/certmagic v0.21.4
|
||||||
github.com/chi-middleware/proxy v1.1.1
|
github.com/chi-middleware/proxy v1.1.1
|
||||||
github.com/djherbis/buffer v1.2.0
|
github.com/djherbis/buffer v1.2.0
|
||||||
|
@ -34,7 +34,7 @@ require (
|
||||||
github.com/editorconfig/editorconfig-core-go/v2 v2.6.2
|
github.com/editorconfig/editorconfig-core-go/v2 v2.6.2
|
||||||
github.com/emersion/go-imap v1.2.1
|
github.com/emersion/go-imap v1.2.1
|
||||||
github.com/felixge/fgprof v0.9.5
|
github.com/felixge/fgprof v0.9.5
|
||||||
github.com/fsnotify/fsnotify v1.8.0
|
github.com/fsnotify/fsnotify v1.7.0
|
||||||
github.com/gliderlabs/ssh v0.3.7
|
github.com/gliderlabs/ssh v0.3.7
|
||||||
github.com/go-ap/activitypub v0.0.0-20231114162308-e219254dc5c9
|
github.com/go-ap/activitypub v0.0.0-20231114162308-e219254dc5c9
|
||||||
github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73
|
github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73
|
||||||
|
@ -57,7 +57,7 @@ require (
|
||||||
github.com/google/pprof v0.0.0-20241017200806-017d972448fc
|
github.com/google/pprof v0.0.0-20241017200806-017d972448fc
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/gorilla/feeds v1.2.0
|
github.com/gorilla/feeds v1.2.0
|
||||||
github.com/gorilla/sessions v1.4.0
|
github.com/gorilla/sessions v1.2.2
|
||||||
github.com/h2non/gock v1.2.0
|
github.com/h2non/gock v1.2.0
|
||||||
github.com/hashicorp/go-version v1.6.0
|
github.com/hashicorp/go-version v1.6.0
|
||||||
github.com/hashicorp/golang-lru/v2 v2.0.7
|
github.com/hashicorp/golang-lru/v2 v2.0.7
|
||||||
|
@ -72,7 +72,7 @@ require (
|
||||||
github.com/markbates/goth v1.80.0
|
github.com/markbates/goth v1.80.0
|
||||||
github.com/mattn/go-isatty v0.0.20
|
github.com/mattn/go-isatty v0.0.20
|
||||||
github.com/mattn/go-sqlite3 v1.14.24
|
github.com/mattn/go-sqlite3 v1.14.24
|
||||||
github.com/meilisearch/meilisearch-go v0.29.0
|
github.com/meilisearch/meilisearch-go v0.28.0
|
||||||
github.com/mholt/archiver/v3 v3.5.1
|
github.com/mholt/archiver/v3 v3.5.1
|
||||||
github.com/microcosm-cc/bluemonday v1.0.27
|
github.com/microcosm-cc/bluemonday v1.0.27
|
||||||
github.com/minio/minio-go/v7 v7.0.78
|
github.com/minio/minio-go/v7 v7.0.78
|
||||||
|
@ -97,17 +97,17 @@ require (
|
||||||
github.com/valyala/fastjson v1.6.4
|
github.com/valyala/fastjson v1.6.4
|
||||||
github.com/xanzy/go-gitlab v0.109.0
|
github.com/xanzy/go-gitlab v0.109.0
|
||||||
github.com/yohcop/openid-go v1.0.1
|
github.com/yohcop/openid-go v1.0.1
|
||||||
github.com/yuin/goldmark v1.7.8
|
github.com/yuin/goldmark v1.7.4
|
||||||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
|
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
|
||||||
go.uber.org/mock v0.4.0
|
go.uber.org/mock v0.4.0
|
||||||
golang.org/x/crypto v0.29.0
|
golang.org/x/crypto v0.28.0
|
||||||
golang.org/x/image v0.21.0
|
golang.org/x/image v0.21.0
|
||||||
golang.org/x/net v0.31.0
|
golang.org/x/net v0.30.0
|
||||||
golang.org/x/oauth2 v0.23.0
|
golang.org/x/oauth2 v0.23.0
|
||||||
golang.org/x/sys v0.27.0
|
golang.org/x/sys v0.26.0
|
||||||
golang.org/x/text v0.20.0
|
golang.org/x/text v0.19.0
|
||||||
golang.org/x/tools v0.26.0
|
golang.org/x/tools v0.26.0
|
||||||
google.golang.org/grpc v1.68.0
|
google.golang.org/grpc v1.67.1
|
||||||
google.golang.org/protobuf v1.35.1
|
google.golang.org/protobuf v1.35.1
|
||||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||||
gopkg.in/ini.v1 v1.67.0
|
gopkg.in/ini.v1 v1.67.0
|
||||||
|
@ -137,13 +137,13 @@ require (
|
||||||
github.com/aymerick/douceur v0.2.0 // indirect
|
github.com/aymerick/douceur v0.2.0 // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/bits-and-blooms/bitset v1.13.0 // indirect
|
github.com/bits-and-blooms/bitset v1.13.0 // indirect
|
||||||
github.com/blevesearch/bleve_index_api v1.1.12 // indirect
|
github.com/blevesearch/bleve_index_api v1.1.10 // indirect
|
||||||
github.com/blevesearch/geo v0.1.20 // indirect
|
github.com/blevesearch/geo v0.1.20 // indirect
|
||||||
github.com/blevesearch/go-faiss v1.0.23 // indirect
|
github.com/blevesearch/go-faiss v1.0.20 // indirect
|
||||||
github.com/blevesearch/go-porterstemmer v1.0.3 // indirect
|
github.com/blevesearch/go-porterstemmer v1.0.3 // indirect
|
||||||
github.com/blevesearch/gtreap v0.1.1 // indirect
|
github.com/blevesearch/gtreap v0.1.1 // indirect
|
||||||
github.com/blevesearch/mmap-go v1.0.4 // indirect
|
github.com/blevesearch/mmap-go v1.0.4 // indirect
|
||||||
github.com/blevesearch/scorch_segment_api/v2 v2.2.16 // indirect
|
github.com/blevesearch/scorch_segment_api/v2 v2.2.15 // indirect
|
||||||
github.com/blevesearch/segment v0.9.1 // indirect
|
github.com/blevesearch/segment v0.9.1 // indirect
|
||||||
github.com/blevesearch/snowballstem v0.9.0 // indirect
|
github.com/blevesearch/snowballstem v0.9.0 // indirect
|
||||||
github.com/blevesearch/upsidedown_store_api v1.0.2 // indirect
|
github.com/blevesearch/upsidedown_store_api v1.0.2 // indirect
|
||||||
|
@ -152,8 +152,8 @@ require (
|
||||||
github.com/blevesearch/zapx/v12 v12.3.10 // indirect
|
github.com/blevesearch/zapx/v12 v12.3.10 // indirect
|
||||||
github.com/blevesearch/zapx/v13 v13.3.10 // indirect
|
github.com/blevesearch/zapx/v13 v13.3.10 // indirect
|
||||||
github.com/blevesearch/zapx/v14 v14.3.10 // indirect
|
github.com/blevesearch/zapx/v14 v14.3.10 // indirect
|
||||||
github.com/blevesearch/zapx/v15 v15.3.16 // indirect
|
github.com/blevesearch/zapx/v15 v15.3.13 // indirect
|
||||||
github.com/blevesearch/zapx/v16 v16.1.8 // indirect
|
github.com/blevesearch/zapx/v16 v16.1.5 // indirect
|
||||||
github.com/boombuler/barcode v1.0.1 // indirect
|
github.com/boombuler/barcode v1.0.1 // indirect
|
||||||
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 // indirect
|
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 // indirect
|
||||||
github.com/caddyserver/zerossl v0.1.3 // indirect
|
github.com/caddyserver/zerossl v0.1.3 // indirect
|
||||||
|
@ -281,9 +281,9 @@ require (
|
||||||
go.uber.org/zap v1.27.0 // indirect
|
go.uber.org/zap v1.27.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect
|
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect
|
||||||
golang.org/x/mod v0.21.0 // indirect
|
golang.org/x/mod v0.21.0 // indirect
|
||||||
golang.org/x/sync v0.9.0 // indirect
|
golang.org/x/sync v0.8.0 // indirect
|
||||||
golang.org/x/time v0.5.0 // indirect
|
golang.org/x/time v0.5.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect
|
||||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
|
@ -293,8 +293,6 @@ replace github.com/hashicorp/go-version => github.com/6543/go-version v1.3.1
|
||||||
|
|
||||||
replace github.com/shurcooL/vfsgen => github.com/lunny/vfsgen v0.0.0-20220105142115-2c99e1ffdfa0
|
replace github.com/shurcooL/vfsgen => github.com/lunny/vfsgen v0.0.0-20220105142115-2c99e1ffdfa0
|
||||||
|
|
||||||
replace github.com/nektos/act => code.forgejo.org/forgejo/act v1.22.0
|
replace github.com/nektos/act => code.forgejo.org/forgejo/act v1.21.3
|
||||||
|
|
||||||
replace github.com/mholt/archiver/v3 => code.forgejo.org/forgejo/archiver/v3 v3.5.1
|
replace github.com/mholt/archiver/v3 => code.forgejo.org/forgejo/archiver/v3 v3.5.1
|
||||||
|
|
||||||
replace github.com/goccy/go-json => github.com/grafana/go-json v0.0.0-20241115232854-f14426c40ff2
|
|
||||||
|
|
100
go.sum
100
go.sum
|
@ -4,20 +4,18 @@ code.forgejo.org/f3/gof3/v3 v3.7.0 h1:ZfuCP8CGm8ZJbWmL+V0pUu3E0X4FCAA7GfRDy/y5/K
|
||||||
code.forgejo.org/f3/gof3/v3 v3.7.0/go.mod h1:oNhOeqD4DZYjVcNjQXIOdDX9b/1tqxi9ITLS8H9/Csw=
|
code.forgejo.org/f3/gof3/v3 v3.7.0/go.mod h1:oNhOeqD4DZYjVcNjQXIOdDX9b/1tqxi9ITLS8H9/Csw=
|
||||||
code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20191008002943-06d1c002b251 h1:HTZl3CBk3ABNYtFI6TPLvJgGKFIhKT5CBk0sbOtkDKU=
|
code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20191008002943-06d1c002b251 h1:HTZl3CBk3ABNYtFI6TPLvJgGKFIhKT5CBk0sbOtkDKU=
|
||||||
code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20191008002943-06d1c002b251/go.mod h1:PphB88CPbx601QrWPMZATeorACeVmQlyv3u+uUMbSaM=
|
code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20191008002943-06d1c002b251/go.mod h1:PphB88CPbx601QrWPMZATeorACeVmQlyv3u+uUMbSaM=
|
||||||
code.forgejo.org/forgejo/act v1.22.0 h1:NbUf0+vQ48+ddwe4zVkINqnxKYl/to+NUvW7iisPA60=
|
code.forgejo.org/forgejo/act v1.21.3 h1:EeJbrz0aar2QhIcBlOW5gjK1rjrQxcAvQSPpG/R1h5w=
|
||||||
code.forgejo.org/forgejo/act v1.22.0/go.mod h1:+PcvJ9iv+NTFeJSh79ra9Jbk9l0vvyA9D9me5/dbxYM=
|
code.forgejo.org/forgejo/act v1.21.3/go.mod h1:+PcvJ9iv+NTFeJSh79ra9Jbk9l0vvyA9D9me5/dbxYM=
|
||||||
code.forgejo.org/forgejo/archiver/v3 v3.5.1 h1:UmmbA7D5550uf71SQjarmrn6yKwOGxtEjb3jaYYtmSE=
|
code.forgejo.org/forgejo/archiver/v3 v3.5.1 h1:UmmbA7D5550uf71SQjarmrn6yKwOGxtEjb3jaYYtmSE=
|
||||||
code.forgejo.org/forgejo/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4=
|
code.forgejo.org/forgejo/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4=
|
||||||
code.forgejo.org/forgejo/reply v1.0.2 h1:dMhQCHV6/O3L5CLWNTol+dNzDAuyCK88z4J/lCdgFuQ=
|
code.forgejo.org/forgejo/reply v1.0.2 h1:dMhQCHV6/O3L5CLWNTol+dNzDAuyCK88z4J/lCdgFuQ=
|
||||||
code.forgejo.org/forgejo/reply v1.0.2/go.mod h1:RyZUfzQLc+fuLIGjTSQWDAJWPiL4WtKXB/FifT5fM7U=
|
code.forgejo.org/forgejo/reply v1.0.2/go.mod h1:RyZUfzQLc+fuLIGjTSQWDAJWPiL4WtKXB/FifT5fM7U=
|
||||||
code.forgejo.org/go-chi/binding v1.0.0 h1:EIDJtk9brK7WsT7rvS/D4cxX8XlnhY3LMy8ex1jeHu0=
|
code.forgejo.org/go-chi/cache v0.0.0-20240912103640-dcb08fba860d h1:nOu/2GX571t4intmtfvpctS148OqsBYrGUySVm93ifc=
|
||||||
code.forgejo.org/go-chi/binding v1.0.0/go.mod h1:fWwqaHj0H1/KeCpBqdvKunflq8pYfciEHI5v3UUeE2E=
|
code.forgejo.org/go-chi/cache v0.0.0-20240912103640-dcb08fba860d/go.mod h1:OVlZ/TqDYJ+RUJ+R+J+OLxtlyjo3pbjBeK7LAWAB+Vk=
|
||||||
code.forgejo.org/go-chi/cache v1.0.0 h1:akLfGxNlHcacmtutovNtYFSTMsbdcp5MGjAEsP4pxnE=
|
code.forgejo.org/go-chi/captcha v0.0.0-20240905153133-df43b9250ed5 h1:A7P1liXCpJBHEJ5KIDsF0ujnQ8FQ/aX1UixTW0vGrDQ=
|
||||||
code.forgejo.org/go-chi/cache v1.0.0/go.mod h1:OVlZ/TqDYJ+RUJ+R+J+OLxtlyjo3pbjBeK7LAWAB+Vk=
|
code.forgejo.org/go-chi/captcha v0.0.0-20240905153133-df43b9250ed5/go.mod h1:YLOsiln/arX3egGtxG4QNp49G2CIqP9pqD2VL56obLc=
|
||||||
code.forgejo.org/go-chi/captcha v1.0.0 h1:ZKVznXrPfruc1RMavCFBEINGxB3RAYr4I+WQAK8+eP0=
|
code.forgejo.org/go-chi/session v0.0.0-20241017103059-2a992261fc26 h1:6XCLWu8A0nPM862Uh68kQmxsBsaQNfPPFwYjzG8M8QE=
|
||||||
code.forgejo.org/go-chi/captcha v1.0.0/go.mod h1:YLOsiln/arX3egGtxG4QNp49G2CIqP9pqD2VL56obLc=
|
code.forgejo.org/go-chi/session v0.0.0-20241017103059-2a992261fc26/go.mod h1:lS76JFHZqGXYJTBHqwZ910UG046hIXAaYIN6J0Lf8sI=
|
||||||
code.forgejo.org/go-chi/session v1.0.0 h1:1hjLWHpXkb4vs/g9rk/unhRL4AoKEqVUPJ+opI8UO3Y=
|
|
||||||
code.forgejo.org/go-chi/session v1.0.0/go.mod h1:lS76JFHZqGXYJTBHqwZ910UG046hIXAaYIN6J0Lf8sI=
|
|
||||||
code.gitea.io/actions-proto-go v0.4.0 h1:OsPBPhodXuQnsspG1sQ4eRE1PeoZyofd7+i73zCwnsU=
|
code.gitea.io/actions-proto-go v0.4.0 h1:OsPBPhodXuQnsspG1sQ4eRE1PeoZyofd7+i73zCwnsU=
|
||||||
code.gitea.io/actions-proto-go v0.4.0/go.mod h1:mn7Wkqz6JbnTOHQpot3yDeHx+O5C9EGhMEE+htvHBas=
|
code.gitea.io/actions-proto-go v0.4.0/go.mod h1:mn7Wkqz6JbnTOHQpot3yDeHx+O5C9EGhMEE+htvHBas=
|
||||||
code.gitea.io/gitea-vet v0.2.3 h1:gdFmm6WOTM65rE8FUBTRzeQZYzXePKSSB1+r574hWwI=
|
code.gitea.io/gitea-vet v0.2.3 h1:gdFmm6WOTM65rE8FUBTRzeQZYzXePKSSB1+r574hWwI=
|
||||||
|
@ -34,6 +32,8 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||||
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 h1:cliQ4HHsCo6xi2oWZYKWW4bly/Ory9FuTpFPRxj/mAg=
|
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 h1:cliQ4HHsCo6xi2oWZYKWW4bly/Ory9FuTpFPRxj/mAg=
|
||||||
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078/go.mod h1:g/V2Hjas6Z1UHUp4yIx6bATpNzJ7DYtD0FG3+xARWxs=
|
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078/go.mod h1:g/V2Hjas6Z1UHUp4yIx6bATpNzJ7DYtD0FG3+xARWxs=
|
||||||
|
gitea.com/go-chi/binding v0.0.0-20240430071103-39a851e106ed h1:EZZBtilMLSZNWtHHcgq2mt6NSGhJSZBuduAlinMEmso=
|
||||||
|
gitea.com/go-chi/binding v0.0.0-20240430071103-39a851e106ed/go.mod h1:E3i3cgB04dDx0v3CytCgRTTn9Z/9x891aet3r456RVw=
|
||||||
gitea.com/lunny/levelqueue v0.4.2-0.20230414023320-3c0159fe0fe4 h1:IFT+hup2xejHqdhS7keYWioqfmxdnfblFDTGoOwcZ+o=
|
gitea.com/lunny/levelqueue v0.4.2-0.20230414023320-3c0159fe0fe4 h1:IFT+hup2xejHqdhS7keYWioqfmxdnfblFDTGoOwcZ+o=
|
||||||
gitea.com/lunny/levelqueue v0.4.2-0.20230414023320-3c0159fe0fe4/go.mod h1:HBqmLbz56JWpfEGG0prskAV97ATNRoj5LDmPicD22hU=
|
gitea.com/lunny/levelqueue v0.4.2-0.20230414023320-3c0159fe0fe4/go.mod h1:HBqmLbz56JWpfEGG0prskAV97ATNRoj5LDmPicD22hU=
|
||||||
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s=
|
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s=
|
||||||
|
@ -98,22 +98,22 @@ github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJR
|
||||||
github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
|
github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
|
||||||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb h1:m935MPodAbYS46DG4pJSv7WO+VECIWUQ7OJYSoTrMh4=
|
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb h1:m935MPodAbYS46DG4pJSv7WO+VECIWUQ7OJYSoTrMh4=
|
||||||
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI=
|
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI=
|
||||||
github.com/blevesearch/bleve/v2 v2.4.3 h1:XDYj+1prgX84L2Cf+V3ojrOPqXxy0qxyd2uLMmeuD+4=
|
github.com/blevesearch/bleve/v2 v2.4.2 h1:NooYP1mb3c0StkiY9/xviiq2LGSaE8BQBCc/pirMx0U=
|
||||||
github.com/blevesearch/bleve/v2 v2.4.3/go.mod h1:hEPDPrbYw3vyrm5VOa36GyS4bHWuIf4Fflp7460QQXY=
|
github.com/blevesearch/bleve/v2 v2.4.2/go.mod h1:ATNKj7Yl2oJv/lGuF4kx39bST2dveX6w0th2FFYLkc8=
|
||||||
github.com/blevesearch/bleve_index_api v1.1.12 h1:P4bw9/G/5rulOF7SJ9l4FsDoo7UFJ+5kexNy1RXfegY=
|
github.com/blevesearch/bleve_index_api v1.1.10 h1:PDLFhVjrjQWr6jCuU7TwlmByQVCSEURADHdCqVS9+g0=
|
||||||
github.com/blevesearch/bleve_index_api v1.1.12/go.mod h1:PbcwjIcRmjhGbkS/lJCpfgVSMROV6TRubGGAODaK1W8=
|
github.com/blevesearch/bleve_index_api v1.1.10/go.mod h1:PbcwjIcRmjhGbkS/lJCpfgVSMROV6TRubGGAODaK1W8=
|
||||||
github.com/blevesearch/geo v0.1.20 h1:paaSpu2Ewh/tn5DKn/FB5SzvH0EWupxHEIwbCk/QPqM=
|
github.com/blevesearch/geo v0.1.20 h1:paaSpu2Ewh/tn5DKn/FB5SzvH0EWupxHEIwbCk/QPqM=
|
||||||
github.com/blevesearch/geo v0.1.20/go.mod h1:DVG2QjwHNMFmjo+ZgzrIq2sfCh6rIHzy9d9d0B59I6w=
|
github.com/blevesearch/geo v0.1.20/go.mod h1:DVG2QjwHNMFmjo+ZgzrIq2sfCh6rIHzy9d9d0B59I6w=
|
||||||
github.com/blevesearch/go-faiss v1.0.23 h1:Wmc5AFwDLKGl2L6mjLX1Da3vCL0EKa2uHHSorcIS1Uc=
|
github.com/blevesearch/go-faiss v1.0.20 h1:AIkdTQFWuZ5LQmKQSebgMR4RynGNw8ZseJXaan5kvtI=
|
||||||
github.com/blevesearch/go-faiss v1.0.23/go.mod h1:OMGQwOaRRYxrmeNdMrXJPvVx8gBnvE5RYrr0BahNnkk=
|
github.com/blevesearch/go-faiss v1.0.20/go.mod h1:jrxHrbl42X/RnDPI+wBoZU8joxxuRwedrxqswQ3xfU8=
|
||||||
github.com/blevesearch/go-porterstemmer v1.0.3 h1:GtmsqID0aZdCSNiY8SkuPJ12pD4jI+DdXTAn4YRcHCo=
|
github.com/blevesearch/go-porterstemmer v1.0.3 h1:GtmsqID0aZdCSNiY8SkuPJ12pD4jI+DdXTAn4YRcHCo=
|
||||||
github.com/blevesearch/go-porterstemmer v1.0.3/go.mod h1:angGc5Ht+k2xhJdZi511LtmxuEf0OVpvUUNrwmM1P7M=
|
github.com/blevesearch/go-porterstemmer v1.0.3/go.mod h1:angGc5Ht+k2xhJdZi511LtmxuEf0OVpvUUNrwmM1P7M=
|
||||||
github.com/blevesearch/gtreap v0.1.1 h1:2JWigFrzDMR+42WGIN/V2p0cUvn4UP3C4Q5nmaZGW8Y=
|
github.com/blevesearch/gtreap v0.1.1 h1:2JWigFrzDMR+42WGIN/V2p0cUvn4UP3C4Q5nmaZGW8Y=
|
||||||
github.com/blevesearch/gtreap v0.1.1/go.mod h1:QaQyDRAT51sotthUWAH4Sj08awFSSWzgYICSZ3w0tYk=
|
github.com/blevesearch/gtreap v0.1.1/go.mod h1:QaQyDRAT51sotthUWAH4Sj08awFSSWzgYICSZ3w0tYk=
|
||||||
github.com/blevesearch/mmap-go v1.0.4 h1:OVhDhT5B/M1HNPpYPBKIEJaD0F3Si+CrEKULGCDPWmc=
|
github.com/blevesearch/mmap-go v1.0.4 h1:OVhDhT5B/M1HNPpYPBKIEJaD0F3Si+CrEKULGCDPWmc=
|
||||||
github.com/blevesearch/mmap-go v1.0.4/go.mod h1:EWmEAOmdAS9z/pi/+Toxu99DnsbhG1TIxUoRmJw/pSs=
|
github.com/blevesearch/mmap-go v1.0.4/go.mod h1:EWmEAOmdAS9z/pi/+Toxu99DnsbhG1TIxUoRmJw/pSs=
|
||||||
github.com/blevesearch/scorch_segment_api/v2 v2.2.16 h1:uGvKVvG7zvSxCwcm4/ehBa9cCEuZVE+/zvrSl57QUVY=
|
github.com/blevesearch/scorch_segment_api/v2 v2.2.15 h1:prV17iU/o+A8FiZi9MXmqbagd8I0bCqM7OKUYPbnb5Y=
|
||||||
github.com/blevesearch/scorch_segment_api/v2 v2.2.16/go.mod h1:VF5oHVbIFTu+znY1v30GjSpT5+9YFs9dV2hjvuh34F0=
|
github.com/blevesearch/scorch_segment_api/v2 v2.2.15/go.mod h1:db0cmP03bPNadXrCDuVkKLV6ywFSiRgPFT1YVrestBc=
|
||||||
github.com/blevesearch/segment v0.9.1 h1:+dThDy+Lvgj5JMxhmOVlgFfkUtZV2kw49xax4+jTfSU=
|
github.com/blevesearch/segment v0.9.1 h1:+dThDy+Lvgj5JMxhmOVlgFfkUtZV2kw49xax4+jTfSU=
|
||||||
github.com/blevesearch/segment v0.9.1/go.mod h1:zN21iLm7+GnBHWTao9I+Au/7MBiL8pPFtJBJTsk6kQw=
|
github.com/blevesearch/segment v0.9.1/go.mod h1:zN21iLm7+GnBHWTao9I+Au/7MBiL8pPFtJBJTsk6kQw=
|
||||||
github.com/blevesearch/snowballstem v0.9.0 h1:lMQ189YspGP6sXvZQ4WZ+MLawfV8wOmPoD/iWeNXm8s=
|
github.com/blevesearch/snowballstem v0.9.0 h1:lMQ189YspGP6sXvZQ4WZ+MLawfV8wOmPoD/iWeNXm8s=
|
||||||
|
@ -130,10 +130,10 @@ github.com/blevesearch/zapx/v13 v13.3.10 h1:0KY9tuxg06rXxOZHg3DwPJBjniSlqEgVpxIq
|
||||||
github.com/blevesearch/zapx/v13 v13.3.10/go.mod h1:w2wjSDQ/WBVeEIvP0fvMJZAzDwqwIEzVPnCPrz93yAk=
|
github.com/blevesearch/zapx/v13 v13.3.10/go.mod h1:w2wjSDQ/WBVeEIvP0fvMJZAzDwqwIEzVPnCPrz93yAk=
|
||||||
github.com/blevesearch/zapx/v14 v14.3.10 h1:SG6xlsL+W6YjhX5N3aEiL/2tcWh3DO75Bnz77pSwwKU=
|
github.com/blevesearch/zapx/v14 v14.3.10 h1:SG6xlsL+W6YjhX5N3aEiL/2tcWh3DO75Bnz77pSwwKU=
|
||||||
github.com/blevesearch/zapx/v14 v14.3.10/go.mod h1:qqyuR0u230jN1yMmE4FIAuCxmahRQEOehF78m6oTgns=
|
github.com/blevesearch/zapx/v14 v14.3.10/go.mod h1:qqyuR0u230jN1yMmE4FIAuCxmahRQEOehF78m6oTgns=
|
||||||
github.com/blevesearch/zapx/v15 v15.3.16 h1:Ct3rv7FUJPfPk99TI/OofdC+Kpb4IdyfdMH48sb+FmE=
|
github.com/blevesearch/zapx/v15 v15.3.13 h1:6EkfaZiPlAxqXz0neniq35my6S48QI94W/wyhnpDHHQ=
|
||||||
github.com/blevesearch/zapx/v15 v15.3.16/go.mod h1:Turk/TNRKj9es7ZpKK95PS7f6D44Y7fAFy8F4LXQtGg=
|
github.com/blevesearch/zapx/v15 v15.3.13/go.mod h1:Turk/TNRKj9es7ZpKK95PS7f6D44Y7fAFy8F4LXQtGg=
|
||||||
github.com/blevesearch/zapx/v16 v16.1.8 h1:Bxzpw6YQpFs7UjoCV1+RvDw6fmAT2GZxldwX8b3wVBM=
|
github.com/blevesearch/zapx/v16 v16.1.5 h1:b0sMcarqNFxuXvjoXsF8WtwVahnxyhEvBSRJi/AUHjU=
|
||||||
github.com/blevesearch/zapx/v16 v16.1.8/go.mod h1:JqQlOqlRVaYDkpLIl3JnKql8u4zKTNlVEa3nLsi0Gn8=
|
github.com/blevesearch/zapx/v16 v16.1.5/go.mod h1:J4mSF39w1QELc11EWRSBFkPeZuO7r/NPKkHzDCoiaI8=
|
||||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||||
github.com/boombuler/barcode v1.0.1 h1:NDBbPmhS+EqABEs5Kg3n/5ZNjy73Pz7SIV+KCeqyXcs=
|
github.com/boombuler/barcode v1.0.1 h1:NDBbPmhS+EqABEs5Kg3n/5ZNjy73Pz7SIV+KCeqyXcs=
|
||||||
github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||||
|
@ -143,8 +143,8 @@ github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
|
||||||
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
|
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
|
||||||
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
|
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
|
||||||
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
|
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
|
||||||
github.com/buildkite/terminal-to-html/v3 v3.16.4 h1:QFYO8IGvRnp7tGgiQb8g9uFU8kY9wOzxsFFx17+yy6Q=
|
github.com/buildkite/terminal-to-html/v3 v3.16.3 h1:IGuJjboHjuMLWOGsKZKNxbbn41emOLiHzXPmQZk31fk=
|
||||||
github.com/buildkite/terminal-to-html/v3 v3.16.4/go.mod h1:r/J7cC9c3EzBzP3/wDz0RJLPwv5PUAMp+KF2w+ntMc0=
|
github.com/buildkite/terminal-to-html/v3 v3.16.3/go.mod h1:r/J7cC9c3EzBzP3/wDz0RJLPwv5PUAMp+KF2w+ntMc0=
|
||||||
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
||||||
github.com/caddyserver/certmagic v0.21.4 h1:e7VobB8rffHv8ZZpSiZtEwnLDHUwLVYLWzWSa1FfKI0=
|
github.com/caddyserver/certmagic v0.21.4 h1:e7VobB8rffHv8ZZpSiZtEwnLDHUwLVYLWzWSa1FfKI0=
|
||||||
github.com/caddyserver/certmagic v0.21.4/go.mod h1:swUXjQ1T9ZtMv95qj7/InJvWLXURU85r+CfG0T+ZbDE=
|
github.com/caddyserver/certmagic v0.21.4/go.mod h1:swUXjQ1T9ZtMv95qj7/InJvWLXURU85r+CfG0T+ZbDE=
|
||||||
|
@ -221,8 +221,8 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk
|
||||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||||
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
|
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||||
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||||
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
|
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
|
||||||
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
|
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
|
||||||
github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE=
|
github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE=
|
||||||
|
@ -307,6 +307,8 @@ github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJA
|
||||||
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
|
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
|
||||||
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
||||||
github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY=
|
github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY=
|
||||||
|
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
|
||||||
|
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||||
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f h1:3BSP1Tbs2djlpprl7wCLuiqMaUh5SJkkzI2gDs+FgLs=
|
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f h1:3BSP1Tbs2djlpprl7wCLuiqMaUh5SJkkzI2gDs+FgLs=
|
||||||
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f/go.mod h1:Pcatq5tYkCW2Q6yrR2VRHlbHpZ/R4/7qyL1TCF7vl14=
|
github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f/go.mod h1:Pcatq5tYkCW2Q6yrR2VRHlbHpZ/R4/7qyL1TCF7vl14=
|
||||||
|
@ -379,10 +381,8 @@ github.com/gorilla/pat v0.0.0-20180118222023-199c85a7f6d1 h1:LqbZZ9sNMWVjeXS4NN5
|
||||||
github.com/gorilla/pat v0.0.0-20180118222023-199c85a7f6d1/go.mod h1:YeAe0gNeiNT5hoiZRI4yiOky6jVdNvfO2N6Kav/HmxY=
|
github.com/gorilla/pat v0.0.0-20180118222023-199c85a7f6d1/go.mod h1:YeAe0gNeiNT5hoiZRI4yiOky6jVdNvfO2N6Kav/HmxY=
|
||||||
github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=
|
github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=
|
||||||
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
|
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
|
||||||
github.com/gorilla/sessions v1.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ=
|
github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY=
|
||||||
github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik=
|
github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ=
|
||||||
github.com/grafana/go-json v0.0.0-20241115232854-f14426c40ff2 h1:8xGrYqQ1GM4aaMk7pNDfecBdL/VGhEbpvvGBoqO6BIY=
|
|
||||||
github.com/grafana/go-json v0.0.0-20241115232854-f14426c40ff2/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
|
||||||
github.com/h2non/gock v1.2.0 h1:K6ol8rfrRkUOefooBC8elXoaNGYkpp7y2qcxGG6BzUE=
|
github.com/h2non/gock v1.2.0 h1:K6ol8rfrRkUOefooBC8elXoaNGYkpp7y2qcxGG6BzUE=
|
||||||
github.com/h2non/gock v1.2.0/go.mod h1:tNhoxHYW2W42cYkYb1WqzdbYIieALC99kpYr7rH/BQk=
|
github.com/h2non/gock v1.2.0/go.mod h1:tNhoxHYW2W42cYkYb1WqzdbYIieALC99kpYr7rH/BQk=
|
||||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
|
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
|
||||||
|
@ -491,8 +491,8 @@ github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6T
|
||||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM=
|
github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM=
|
||||||
github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||||
github.com/meilisearch/meilisearch-go v0.29.0 h1:HZ9NEKN59USINQ/DXJge/aaXq8IrsKbXGTdAoBaaDz4=
|
github.com/meilisearch/meilisearch-go v0.28.0 h1:f3XJ66ZM+R8bANAOLqsjvoq/HhQNpVJPYoNt6QgNzME=
|
||||||
github.com/meilisearch/meilisearch-go v0.29.0/go.mod h1:2cRCAn4ddySUsFfNDLVPod/plRibQsJkXF/4gLhxbOk=
|
github.com/meilisearch/meilisearch-go v0.28.0/go.mod h1:Szcc9CaDiKIfjdgdt49jlmDKpEzjD+x+b6Y6heMdlQ0=
|
||||||
github.com/mholt/acmez/v2 v2.0.3 h1:CgDBlEwg3QBp6s45tPQmFIBrkRIkBT4rW4orMM6p4sw=
|
github.com/mholt/acmez/v2 v2.0.3 h1:CgDBlEwg3QBp6s45tPQmFIBrkRIkBT4rW4orMM6p4sw=
|
||||||
github.com/mholt/acmez/v2 v2.0.3/go.mod h1:pQ1ysaDeGrIMvJ9dfJMk5kJNkn7L2sb3UhyrX6Q91cw=
|
github.com/mholt/acmez/v2 v2.0.3/go.mod h1:pQ1ysaDeGrIMvJ9dfJMk5kJNkn7L2sb3UhyrX6Q91cw=
|
||||||
github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=
|
github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=
|
||||||
|
@ -692,8 +692,8 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
github.com/yuin/goldmark v1.4.15/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.15/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic=
|
github.com/yuin/goldmark v1.7.4 h1:BDXOHExt+A7gwPCJgPIIq7ENvceR7we7rOS9TNoLZeg=
|
||||||
github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
github.com/yuin/goldmark v1.7.4/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
||||||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc h1:+IAOyRda+RLrxa1WC7umKOZRsGq4QrFFMYApOeHzQwQ=
|
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc h1:+IAOyRda+RLrxa1WC7umKOZRsGq4QrFFMYApOeHzQwQ=
|
||||||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc/go.mod h1:ovIvrum6DQJA4QsJSovrkC4saKHQVs7TvcaeO8AIl5I=
|
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc/go.mod h1:ovIvrum6DQJA4QsJSovrkC4saKHQVs7TvcaeO8AIl5I=
|
||||||
github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY=
|
github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY=
|
||||||
|
@ -733,8 +733,8 @@ golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2Uz
|
||||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||||
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
|
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
|
||||||
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
|
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
|
||||||
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA=
|
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA=
|
||||||
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
|
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
|
||||||
golang.org/x/image v0.21.0 h1:c5qV36ajHpdj4Qi0GnE0jUc/yuo33OLFaa0d+crTD5s=
|
golang.org/x/image v0.21.0 h1:c5qV36ajHpdj4Qi0GnE0jUc/yuo33OLFaa0d+crTD5s=
|
||||||
|
@ -760,8 +760,8 @@ golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||||
golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo=
|
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
|
||||||
golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
|
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
|
||||||
golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
|
golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
|
||||||
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
@ -771,8 +771,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
|
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||||
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
@ -801,8 +801,8 @@ golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
|
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
||||||
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||||
|
@ -812,8 +812,8 @@ golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
||||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
||||||
golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU=
|
golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24=
|
||||||
golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E=
|
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
@ -825,8 +825,8 @@ golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
|
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
|
||||||
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
|
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
@ -843,10 +843,10 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 h1:e7S5W7MGGLaSu8j3YjdezkZ+m1/Nm0uRVRMEMGk26Xs=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
|
||||||
google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0=
|
google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E=
|
||||||
google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA=
|
google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
|
|
|
@ -146,11 +146,7 @@ func (run *ActionRun) GetPushEventPayload() (*api.PushPayload, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (run *ActionRun) GetPullRequestEventPayload() (*api.PullRequestPayload, error) {
|
func (run *ActionRun) GetPullRequestEventPayload() (*api.PullRequestPayload, error) {
|
||||||
if run.Event == webhook_module.HookEventPullRequest ||
|
if run.Event == webhook_module.HookEventPullRequest || run.Event == webhook_module.HookEventPullRequestSync {
|
||||||
run.Event == webhook_module.HookEventPullRequestSync ||
|
|
||||||
run.Event == webhook_module.HookEventPullRequestAssign ||
|
|
||||||
run.Event == webhook_module.HookEventPullRequestMilestone ||
|
|
||||||
run.Event == webhook_module.HookEventPullRequestLabel {
|
|
||||||
var payload api.PullRequestPayload
|
var payload api.PullRequestPayload
|
||||||
if err := json.Unmarshal([]byte(run.EventPayload), &payload); err != nil {
|
if err := json.Unmarshal([]byte(run.EventPayload), &payload); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -10,7 +10,6 @@ import (
|
||||||
|
|
||||||
_ "code.gitea.io/gitea/models"
|
_ "code.gitea.io/gitea/models"
|
||||||
_ "code.gitea.io/gitea/models/actions"
|
_ "code.gitea.io/gitea/models/actions"
|
||||||
_ "code.gitea.io/gitea/models/forgefed"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
|
|
|
@ -96,6 +96,6 @@ func TestGetUserHeatmapDataByUser(t *testing.T) {
|
||||||
// Test JSON rendering
|
// Test JSON rendering
|
||||||
jsonData, err := json.Marshal(heatmap)
|
jsonData, err := json.Marshal(heatmap)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.JSONEq(t, tc.JSONResult, string(jsonData))
|
assert.Equal(t, tc.JSONResult, string(jsonData))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,31 +15,12 @@ import (
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AuthorizationPurpose string
|
|
||||||
|
|
||||||
var (
|
|
||||||
// Used to store long term authorization tokens.
|
|
||||||
LongTermAuthorization AuthorizationPurpose = "long_term_authorization"
|
|
||||||
|
|
||||||
// Used to activate a user account.
|
|
||||||
UserActivation AuthorizationPurpose = "user_activation"
|
|
||||||
|
|
||||||
// Used to reset the password.
|
|
||||||
PasswordReset AuthorizationPurpose = "password_reset"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Used to activate the specified email address for a user.
|
|
||||||
func EmailActivation(email string) AuthorizationPurpose {
|
|
||||||
return AuthorizationPurpose("email_activation:" + email)
|
|
||||||
}
|
|
||||||
|
|
||||||
// AuthorizationToken represents a authorization token to a user.
|
// AuthorizationToken represents a authorization token to a user.
|
||||||
type AuthorizationToken struct {
|
type AuthorizationToken struct {
|
||||||
ID int64 `xorm:"pk autoincr"`
|
ID int64 `xorm:"pk autoincr"`
|
||||||
UID int64 `xorm:"INDEX"`
|
UID int64 `xorm:"INDEX"`
|
||||||
LookupKey string `xorm:"INDEX UNIQUE"`
|
LookupKey string `xorm:"INDEX UNIQUE"`
|
||||||
HashedValidator string
|
HashedValidator string
|
||||||
Purpose AuthorizationPurpose `xorm:"NOT NULL DEFAULT 'long_term_authorization'"`
|
|
||||||
Expiry timeutil.TimeStamp
|
Expiry timeutil.TimeStamp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,7 +41,7 @@ func (authToken *AuthorizationToken) IsExpired() bool {
|
||||||
// GenerateAuthToken generates a new authentication token for the given user.
|
// GenerateAuthToken generates a new authentication token for the given user.
|
||||||
// It returns the lookup key and validator values that should be passed to the
|
// It returns the lookup key and validator values that should be passed to the
|
||||||
// user via a long-term cookie.
|
// user via a long-term cookie.
|
||||||
func GenerateAuthToken(ctx context.Context, userID int64, expiry timeutil.TimeStamp, purpose AuthorizationPurpose) (lookupKey, validator string, err error) {
|
func GenerateAuthToken(ctx context.Context, userID int64, expiry timeutil.TimeStamp) (lookupKey, validator string, err error) {
|
||||||
// Request 64 random bytes. The first 32 bytes will be used for the lookupKey
|
// Request 64 random bytes. The first 32 bytes will be used for the lookupKey
|
||||||
// and the other 32 bytes will be used for the validator.
|
// and the other 32 bytes will be used for the validator.
|
||||||
rBytes, err := util.CryptoRandomBytes(64)
|
rBytes, err := util.CryptoRandomBytes(64)
|
||||||
|
@ -75,15 +56,14 @@ func GenerateAuthToken(ctx context.Context, userID int64, expiry timeutil.TimeSt
|
||||||
Expiry: expiry,
|
Expiry: expiry,
|
||||||
LookupKey: lookupKey,
|
LookupKey: lookupKey,
|
||||||
HashedValidator: HashValidator(rBytes[32:]),
|
HashedValidator: HashValidator(rBytes[32:]),
|
||||||
Purpose: purpose,
|
|
||||||
})
|
})
|
||||||
return lookupKey, validator, err
|
return lookupKey, validator, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindAuthToken will find a authorization token via the lookup key.
|
// FindAuthToken will find a authorization token via the lookup key.
|
||||||
func FindAuthToken(ctx context.Context, lookupKey string, purpose AuthorizationPurpose) (*AuthorizationToken, error) {
|
func FindAuthToken(ctx context.Context, lookupKey string) (*AuthorizationToken, error) {
|
||||||
var authToken AuthorizationToken
|
var authToken AuthorizationToken
|
||||||
has, err := db.GetEngine(ctx).Where("lookup_key = ? AND purpose = ?", lookupKey, purpose).Get(&authToken)
|
has, err := db.GetEngine(ctx).Where("lookup_key = ?", lookupKey).Get(&authToken)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else if !has {
|
} else if !has {
|
||||||
|
|
|
@ -12,7 +12,6 @@ import (
|
||||||
_ "code.gitea.io/gitea/models/actions"
|
_ "code.gitea.io/gitea/models/actions"
|
||||||
_ "code.gitea.io/gitea/models/activities"
|
_ "code.gitea.io/gitea/models/activities"
|
||||||
_ "code.gitea.io/gitea/models/auth"
|
_ "code.gitea.io/gitea/models/auth"
|
||||||
_ "code.gitea.io/gitea/models/forgefed"
|
|
||||||
_ "code.gitea.io/gitea/models/perm/access"
|
_ "code.gitea.io/gitea/models/perm/access"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,71 +0,0 @@
|
||||||
-
|
|
||||||
id: 1
|
|
||||||
run_id: 791
|
|
||||||
runner_id: 1
|
|
||||||
repo_id: 4
|
|
||||||
owner_id: 1
|
|
||||||
commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0
|
|
||||||
storage_path: "26/1/1712166500347189545.chunk"
|
|
||||||
file_size: 1024
|
|
||||||
file_compressed_size: 1024
|
|
||||||
content_encoding: ""
|
|
||||||
artifact_path: "abc.txt"
|
|
||||||
artifact_name: "artifact-download"
|
|
||||||
status: 1
|
|
||||||
created_unix: 1712338649
|
|
||||||
updated_unix: 1712338649
|
|
||||||
expired_unix: 1720114649
|
|
||||||
|
|
||||||
-
|
|
||||||
id: 19
|
|
||||||
run_id: 791
|
|
||||||
runner_id: 1
|
|
||||||
repo_id: 4
|
|
||||||
owner_id: 1
|
|
||||||
commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0
|
|
||||||
storage_path: "26/19/1712348022422036662.chunk"
|
|
||||||
file_size: 1024
|
|
||||||
file_compressed_size: 1024
|
|
||||||
content_encoding: ""
|
|
||||||
artifact_path: "abc.txt"
|
|
||||||
artifact_name: "multi-file-download"
|
|
||||||
status: 2
|
|
||||||
created_unix: 1712348022
|
|
||||||
updated_unix: 1712348022
|
|
||||||
expired_unix: 1720124022
|
|
||||||
|
|
||||||
-
|
|
||||||
id: 20
|
|
||||||
run_id: 791
|
|
||||||
runner_id: 1
|
|
||||||
repo_id: 4
|
|
||||||
owner_id: 1
|
|
||||||
commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0
|
|
||||||
storage_path: "26/20/1712348022423431524.chunk"
|
|
||||||
file_size: 1024
|
|
||||||
file_compressed_size: 1024
|
|
||||||
content_encoding: ""
|
|
||||||
artifact_path: "xyz/def.txt"
|
|
||||||
artifact_name: "multi-file-download"
|
|
||||||
status: 2
|
|
||||||
created_unix: 1712348022
|
|
||||||
updated_unix: 1712348022
|
|
||||||
expired_unix: 1720124022
|
|
||||||
|
|
||||||
-
|
|
||||||
id: 22
|
|
||||||
run_id: 792
|
|
||||||
runner_id: 1
|
|
||||||
repo_id: 4
|
|
||||||
owner_id: 1
|
|
||||||
commit_sha: c2d72f548424103f01ee1dc02889c1e2bff816b0
|
|
||||||
storage_path: "27/5/1730330775594233150.chunk"
|
|
||||||
file_size: 1024
|
|
||||||
file_compressed_size: 1024
|
|
||||||
content_encoding: "application/zip"
|
|
||||||
artifact_path: "artifact-v4-download.zip"
|
|
||||||
artifact_name: "artifact-v4-download"
|
|
||||||
status: 2
|
|
||||||
created_unix: 1730330775
|
|
||||||
updated_unix: 1730330775
|
|
||||||
expired_unix: 1738106775
|
|
|
@ -7,7 +7,6 @@
|
||||||
target_url: https://example.com/builds/
|
target_url: https://example.com/builds/
|
||||||
description: My awesome CI-service
|
description: My awesome CI-service
|
||||||
context: ci/awesomeness
|
context: ci/awesomeness
|
||||||
context_hash: c65f4d64a3b14a3eced0c9b36799e66e1bd5ced7
|
|
||||||
creator_id: 2
|
creator_id: 2
|
||||||
|
|
||||||
-
|
-
|
||||||
|
@ -19,7 +18,6 @@
|
||||||
target_url: https://example.com/coverage/
|
target_url: https://example.com/coverage/
|
||||||
description: My awesome Coverage service
|
description: My awesome Coverage service
|
||||||
context: cov/awesomeness
|
context: cov/awesomeness
|
||||||
context_hash: 3929ac7bccd3fa1bf9b38ddedb77973b1b9a8cfe
|
|
||||||
creator_id: 2
|
creator_id: 2
|
||||||
|
|
||||||
-
|
-
|
||||||
|
@ -31,7 +29,6 @@
|
||||||
target_url: https://example.com/coverage/
|
target_url: https://example.com/coverage/
|
||||||
description: My awesome Coverage service
|
description: My awesome Coverage service
|
||||||
context: cov/awesomeness
|
context: cov/awesomeness
|
||||||
context_hash: 3929ac7bccd3fa1bf9b38ddedb77973b1b9a8cfe
|
|
||||||
creator_id: 2
|
creator_id: 2
|
||||||
|
|
||||||
-
|
-
|
||||||
|
@ -43,7 +40,6 @@
|
||||||
target_url: https://example.com/builds/
|
target_url: https://example.com/builds/
|
||||||
description: My awesome CI-service
|
description: My awesome CI-service
|
||||||
context: ci/awesomeness
|
context: ci/awesomeness
|
||||||
context_hash: c65f4d64a3b14a3eced0c9b36799e66e1bd5ced7
|
|
||||||
creator_id: 2
|
creator_id: 2
|
||||||
|
|
||||||
-
|
-
|
||||||
|
@ -55,41 +51,15 @@
|
||||||
target_url: https://example.com/builds/
|
target_url: https://example.com/builds/
|
||||||
description: My awesome deploy service
|
description: My awesome deploy service
|
||||||
context: deploy/awesomeness
|
context: deploy/awesomeness
|
||||||
context_hash: ae9547713a6665fc4261d0756904932085a41cf2
|
|
||||||
creator_id: 2
|
creator_id: 2
|
||||||
|
|
||||||
-
|
-
|
||||||
id: 6
|
id: 6
|
||||||
index: 1
|
index: 6
|
||||||
repo_id: 62
|
repo_id: 62
|
||||||
state: "failure"
|
state: "failure"
|
||||||
sha: "774f93df12d14931ea93259ae93418da4482fcc1"
|
sha: "774f93df12d14931ea93259ae93418da4482fcc1"
|
||||||
target_url: "/user2/test_workflows/actions"
|
target_url: "/user2/test_workflows/actions"
|
||||||
description: My awesome deploy service
|
description: My awesome deploy service
|
||||||
context: deploy/awesomeness
|
context: deploy/awesomeness
|
||||||
context_hash: ae9547713a6665fc4261d0756904932085a41cf2
|
|
||||||
creator_id: 2
|
|
||||||
|
|
||||||
-
|
|
||||||
id: 7
|
|
||||||
index: 6
|
|
||||||
repo_id: 1
|
|
||||||
state: "pending"
|
|
||||||
sha: "1234123412341234123412341234123412341234"
|
|
||||||
target_url: https://example.com/builds/
|
|
||||||
description: My awesome deploy service
|
|
||||||
context: deploy/awesomeness
|
|
||||||
context_hash: ae9547713a6665fc4261d0756904932085a41cf2
|
|
||||||
creator_id: 2
|
|
||||||
|
|
||||||
-
|
|
||||||
id: 8
|
|
||||||
index: 2
|
|
||||||
repo_id: 62
|
|
||||||
state: "error"
|
|
||||||
sha: "774f93df12d14931ea93259ae93418da4482fcc1"
|
|
||||||
target_url: "/user2/test_workflows/actions"
|
|
||||||
description: "My awesome deploy service - v2"
|
|
||||||
context: deploy/awesomeness
|
|
||||||
context_hash: ae9547713a6665fc4261d0756904932085a41cf2
|
|
||||||
creator_id: 2
|
creator_id: 2
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
[] # empty
|
|
|
@ -1 +0,0 @@
|
||||||
[] # empty
|
|
|
@ -29,8 +29,7 @@
|
||||||
size: 7597
|
size: 7597
|
||||||
is_fsck_enabled: true
|
is_fsck_enabled: true
|
||||||
close_issues_via_commit_in_any_branch: false
|
close_issues_via_commit_in_any_branch: false
|
||||||
created_unix: 1731254961
|
|
||||||
updated_unix: 1731254961
|
|
||||||
-
|
-
|
||||||
id: 2
|
id: 2
|
||||||
owner_id: 2
|
owner_id: 2
|
||||||
|
|
|
@ -10,7 +10,6 @@ import (
|
||||||
_ "code.gitea.io/gitea/models"
|
_ "code.gitea.io/gitea/models"
|
||||||
_ "code.gitea.io/gitea/models/actions"
|
_ "code.gitea.io/gitea/models/actions"
|
||||||
_ "code.gitea.io/gitea/models/activities"
|
_ "code.gitea.io/gitea/models/activities"
|
||||||
_ "code.gitea.io/gitea/models/forgefed"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
|
|
|
@ -84,8 +84,6 @@ var migrations = []*Migration{
|
||||||
NewMigration("Add `legacy` to `web_authn_credential` table", AddLegacyToWebAuthnCredential),
|
NewMigration("Add `legacy` to `web_authn_credential` table", AddLegacyToWebAuthnCredential),
|
||||||
// v23 -> v24
|
// v23 -> v24
|
||||||
NewMigration("Add `delete_branch_after_merge` to `auto_merge` table", AddDeleteBranchAfterMergeToAutoMerge),
|
NewMigration("Add `delete_branch_after_merge` to `auto_merge` table", AddDeleteBranchAfterMergeToAutoMerge),
|
||||||
// v24 -> v25
|
|
||||||
NewMigration("Add `purpose` column to `forgejo_auth_token` table", AddPurposeToForgejoAuthToken),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCurrentDBVersion returns the current Forgejo database version.
|
// GetCurrentDBVersion returns the current Forgejo database version.
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
package forgejo_migrations //nolint:revive
|
|
||||||
|
|
||||||
import "xorm.io/xorm"
|
|
||||||
|
|
||||||
func AddPurposeToForgejoAuthToken(x *xorm.Engine) error {
|
|
||||||
type ForgejoAuthToken struct {
|
|
||||||
ID int64 `xorm:"pk autoincr"`
|
|
||||||
Purpose string `xorm:"NOT NULL DEFAULT 'long_term_authorization'"`
|
|
||||||
}
|
|
||||||
if err := x.Sync(new(ForgejoAuthToken)); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := x.Exec("UPDATE `forgejo_auth_token` SET purpose = 'long_term_authorization' WHERE purpose = ''")
|
|
||||||
return err
|
|
||||||
}
|
|
|
@ -288,18 +288,27 @@ func GetLatestCommitStatus(ctx context.Context, repoID int64, sha string, listOp
|
||||||
|
|
||||||
// GetLatestCommitStatusForPairs returns all statuses with a unique context for a given list of repo-sha pairs
|
// GetLatestCommitStatusForPairs returns all statuses with a unique context for a given list of repo-sha pairs
|
||||||
func GetLatestCommitStatusForPairs(ctx context.Context, repoSHAs []RepoSHA) (map[int64][]*CommitStatus, error) {
|
func GetLatestCommitStatusForPairs(ctx context.Context, repoSHAs []RepoSHA) (map[int64][]*CommitStatus, error) {
|
||||||
results := []*CommitStatus{}
|
type result struct {
|
||||||
|
Index int64
|
||||||
|
RepoID int64
|
||||||
|
SHA string
|
||||||
|
}
|
||||||
|
|
||||||
|
results := make([]result, 0, len(repoSHAs))
|
||||||
|
|
||||||
|
getBase := func() *xorm.Session {
|
||||||
|
return db.GetEngine(ctx).Table(&CommitStatus{})
|
||||||
|
}
|
||||||
|
|
||||||
// Create a disjunction of conditions for each repoID and SHA pair
|
// Create a disjunction of conditions for each repoID and SHA pair
|
||||||
conds := make([]builder.Cond, 0, len(repoSHAs))
|
conds := make([]builder.Cond, 0, len(repoSHAs))
|
||||||
for _, repoSHA := range repoSHAs {
|
for _, repoSHA := range repoSHAs {
|
||||||
conds = append(conds, builder.Eq{"repo_id": repoSHA.RepoID, "sha": repoSHA.SHA})
|
conds = append(conds, builder.Eq{"repo_id": repoSHA.RepoID, "sha": repoSHA.SHA})
|
||||||
}
|
}
|
||||||
|
sess := getBase().Where(builder.Or(conds...)).
|
||||||
|
Select("max( `index` ) as `index`, repo_id, sha").
|
||||||
|
GroupBy("context_hash, repo_id, sha").OrderBy("max( `index` ) desc")
|
||||||
|
|
||||||
sess := db.GetEngine(ctx).Table(&CommitStatus{}).
|
|
||||||
Select("MAX(`index`) AS `index`, *").
|
|
||||||
Where(builder.Or(conds...)).
|
|
||||||
GroupBy("context_hash, repo_id, sha").OrderBy("MAX(`index`) DESC")
|
|
||||||
err := sess.Find(&results)
|
err := sess.Find(&results)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -307,10 +316,28 @@ func GetLatestCommitStatusForPairs(ctx context.Context, repoSHAs []RepoSHA) (map
|
||||||
|
|
||||||
repoStatuses := make(map[int64][]*CommitStatus)
|
repoStatuses := make(map[int64][]*CommitStatus)
|
||||||
|
|
||||||
|
if len(results) > 0 {
|
||||||
|
statuses := make([]*CommitStatus, 0, len(results))
|
||||||
|
|
||||||
|
conds = make([]builder.Cond, 0, len(results))
|
||||||
|
for _, result := range results {
|
||||||
|
cond := builder.Eq{
|
||||||
|
"`index`": result.Index,
|
||||||
|
"repo_id": result.RepoID,
|
||||||
|
"sha": result.SHA,
|
||||||
|
}
|
||||||
|
conds = append(conds, cond)
|
||||||
|
}
|
||||||
|
err = getBase().Where(builder.Or(conds...)).Find(&statuses)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// Group the statuses by repo ID
|
// Group the statuses by repo ID
|
||||||
for _, status := range results {
|
for _, status := range statuses {
|
||||||
repoStatuses[status.RepoID] = append(repoStatuses[status.RepoID], status)
|
repoStatuses[status.RepoID] = append(repoStatuses[status.RepoID], status)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return repoStatuses, nil
|
return repoStatuses, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,8 +35,8 @@ func TestGetCommitStatuses(t *testing.T) {
|
||||||
SHA: sha1,
|
SHA: sha1,
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.EqualValues(t, 6, maxResults)
|
assert.Equal(t, 5, int(maxResults))
|
||||||
assert.Len(t, statuses, 6)
|
assert.Len(t, statuses, 5)
|
||||||
|
|
||||||
assert.Equal(t, "ci/awesomeness", statuses[0].Context)
|
assert.Equal(t, "ci/awesomeness", statuses[0].Context)
|
||||||
assert.Equal(t, structs.CommitStatusPending, statuses[0].State)
|
assert.Equal(t, structs.CommitStatusPending, statuses[0].State)
|
||||||
|
@ -58,17 +58,13 @@ func TestGetCommitStatuses(t *testing.T) {
|
||||||
assert.Equal(t, structs.CommitStatusError, statuses[4].State)
|
assert.Equal(t, structs.CommitStatusError, statuses[4].State)
|
||||||
assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[4].APIURL(db.DefaultContext))
|
assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[4].APIURL(db.DefaultContext))
|
||||||
|
|
||||||
assert.Equal(t, "deploy/awesomeness", statuses[5].Context)
|
|
||||||
assert.Equal(t, structs.CommitStatusPending, statuses[5].State)
|
|
||||||
assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[5].APIURL(db.DefaultContext))
|
|
||||||
|
|
||||||
statuses, maxResults, err = db.FindAndCount[git_model.CommitStatus](db.DefaultContext, &git_model.CommitStatusOptions{
|
statuses, maxResults, err = db.FindAndCount[git_model.CommitStatus](db.DefaultContext, &git_model.CommitStatusOptions{
|
||||||
ListOptions: db.ListOptions{Page: 2, PageSize: 50},
|
ListOptions: db.ListOptions{Page: 2, PageSize: 50},
|
||||||
RepoID: repo1.ID,
|
RepoID: repo1.ID,
|
||||||
SHA: sha1,
|
SHA: sha1,
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.EqualValues(t, 6, maxResults)
|
assert.Equal(t, 5, int(maxResults))
|
||||||
assert.Empty(t, statuses)
|
assert.Empty(t, statuses)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,148 +265,3 @@ func TestCommitStatusesHideActionsURL(t *testing.T) {
|
||||||
assert.Empty(t, statuses[0].TargetURL)
|
assert.Empty(t, statuses[0].TargetURL)
|
||||||
assert.Equal(t, "https://mycicd.org/1", statuses[1].TargetURL)
|
assert.Equal(t, "https://mycicd.org/1", statuses[1].TargetURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetLatestCommitStatusForPairs(t *testing.T) {
|
|
||||||
require.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
t.Run("All", func(t *testing.T) {
|
|
||||||
pairs, err := git_model.GetLatestCommitStatusForPairs(db.DefaultContext, nil)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
assert.EqualValues(t, map[int64][]*git_model.CommitStatus{
|
|
||||||
1: {
|
|
||||||
{
|
|
||||||
ID: 7,
|
|
||||||
Index: 6,
|
|
||||||
RepoID: 1,
|
|
||||||
State: structs.CommitStatusPending,
|
|
||||||
SHA: "1234123412341234123412341234123412341234",
|
|
||||||
TargetURL: "https://example.com/builds/",
|
|
||||||
Description: "My awesome deploy service",
|
|
||||||
ContextHash: "ae9547713a6665fc4261d0756904932085a41cf2",
|
|
||||||
Context: "deploy/awesomeness",
|
|
||||||
CreatorID: 2,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ID: 4,
|
|
||||||
Index: 4,
|
|
||||||
State: structs.CommitStatusFailure,
|
|
||||||
TargetURL: "https://example.com/builds/",
|
|
||||||
Description: "My awesome CI-service",
|
|
||||||
Context: "ci/awesomeness",
|
|
||||||
CreatorID: 2,
|
|
||||||
RepoID: 1,
|
|
||||||
SHA: "1234123412341234123412341234123412341234",
|
|
||||||
ContextHash: "c65f4d64a3b14a3eced0c9b36799e66e1bd5ced7",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ID: 3,
|
|
||||||
Index: 3,
|
|
||||||
State: structs.CommitStatusSuccess,
|
|
||||||
TargetURL: "https://example.com/coverage/",
|
|
||||||
Description: "My awesome Coverage service",
|
|
||||||
Context: "cov/awesomeness",
|
|
||||||
CreatorID: 2,
|
|
||||||
RepoID: 1,
|
|
||||||
SHA: "1234123412341234123412341234123412341234",
|
|
||||||
ContextHash: "3929ac7bccd3fa1bf9b38ddedb77973b1b9a8cfe",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
62: {
|
|
||||||
{
|
|
||||||
ID: 8,
|
|
||||||
Index: 2,
|
|
||||||
RepoID: 62,
|
|
||||||
State: structs.CommitStatusError,
|
|
||||||
TargetURL: "/user2/test_workflows/actions",
|
|
||||||
Description: "My awesome deploy service - v2",
|
|
||||||
Context: "deploy/awesomeness",
|
|
||||||
SHA: "774f93df12d14931ea93259ae93418da4482fcc1",
|
|
||||||
ContextHash: "ae9547713a6665fc4261d0756904932085a41cf2",
|
|
||||||
CreatorID: 2,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}, pairs)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("Repo 1", func(t *testing.T) {
|
|
||||||
pairs, err := git_model.GetLatestCommitStatusForPairs(db.DefaultContext, []git_model.RepoSHA{{1, "1234123412341234123412341234123412341234"}})
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
assert.EqualValues(t, map[int64][]*git_model.CommitStatus{
|
|
||||||
1: {
|
|
||||||
{
|
|
||||||
ID: 7,
|
|
||||||
Index: 6,
|
|
||||||
RepoID: 1,
|
|
||||||
State: structs.CommitStatusPending,
|
|
||||||
SHA: "1234123412341234123412341234123412341234",
|
|
||||||
TargetURL: "https://example.com/builds/",
|
|
||||||
Description: "My awesome deploy service",
|
|
||||||
ContextHash: "ae9547713a6665fc4261d0756904932085a41cf2",
|
|
||||||
Context: "deploy/awesomeness",
|
|
||||||
CreatorID: 2,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ID: 4,
|
|
||||||
Index: 4,
|
|
||||||
State: structs.CommitStatusFailure,
|
|
||||||
TargetURL: "https://example.com/builds/",
|
|
||||||
Description: "My awesome CI-service",
|
|
||||||
Context: "ci/awesomeness",
|
|
||||||
CreatorID: 2,
|
|
||||||
RepoID: 1,
|
|
||||||
SHA: "1234123412341234123412341234123412341234",
|
|
||||||
ContextHash: "c65f4d64a3b14a3eced0c9b36799e66e1bd5ced7",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ID: 3,
|
|
||||||
Index: 3,
|
|
||||||
State: structs.CommitStatusSuccess,
|
|
||||||
TargetURL: "https://example.com/coverage/",
|
|
||||||
Description: "My awesome Coverage service",
|
|
||||||
Context: "cov/awesomeness",
|
|
||||||
CreatorID: 2,
|
|
||||||
RepoID: 1,
|
|
||||||
SHA: "1234123412341234123412341234123412341234",
|
|
||||||
ContextHash: "3929ac7bccd3fa1bf9b38ddedb77973b1b9a8cfe",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}, pairs)
|
|
||||||
})
|
|
||||||
t.Run("Repo 62", func(t *testing.T) {
|
|
||||||
pairs, err := git_model.GetLatestCommitStatusForPairs(db.DefaultContext, []git_model.RepoSHA{{62, "774f93df12d14931ea93259ae93418da4482fcc1"}})
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
assert.EqualValues(t, map[int64][]*git_model.CommitStatus{
|
|
||||||
62: {
|
|
||||||
{
|
|
||||||
ID: 8,
|
|
||||||
Index: 2,
|
|
||||||
RepoID: 62,
|
|
||||||
State: structs.CommitStatusError,
|
|
||||||
TargetURL: "/user2/test_workflows/actions",
|
|
||||||
Description: "My awesome deploy service - v2",
|
|
||||||
Context: "deploy/awesomeness",
|
|
||||||
SHA: "774f93df12d14931ea93259ae93418da4482fcc1",
|
|
||||||
ContextHash: "ae9547713a6665fc4261d0756904932085a41cf2",
|
|
||||||
CreatorID: 2,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}, pairs)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("Repo 62 nonexistant sha", func(t *testing.T) {
|
|
||||||
pairs, err := git_model.GetLatestCommitStatusForPairs(db.DefaultContext, []git_model.RepoSHA{{62, "774f93df12d14931ea93259ae93418da4482fcc"}})
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
assert.EqualValues(t, map[int64][]*git_model.CommitStatus{}, pairs)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("SHA with non existant repo id", func(t *testing.T) {
|
|
||||||
pairs, err := git_model.GetLatestCommitStatusForPairs(db.DefaultContext, []git_model.RepoSHA{{1, "774f93df12d14931ea93259ae93418da4482fcc1"}})
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
assert.EqualValues(t, map[int64][]*git_model.CommitStatus{}, pairs)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
|
@ -136,6 +136,8 @@ var ErrLFSObjectNotExist = db.ErrNotExist{Resource: "LFS Meta object"}
|
||||||
// NewLFSMetaObject stores a given populated LFSMetaObject structure in the database
|
// NewLFSMetaObject stores a given populated LFSMetaObject structure in the database
|
||||||
// if it is not already present.
|
// if it is not already present.
|
||||||
func NewLFSMetaObject(ctx context.Context, repoID int64, p lfs.Pointer) (*LFSMetaObject, error) {
|
func NewLFSMetaObject(ctx context.Context, repoID int64, p lfs.Pointer) (*LFSMetaObject, error) {
|
||||||
|
var err error
|
||||||
|
|
||||||
ctx, committer, err := db.TxContext(ctx)
|
ctx, committer, err := db.TxContext(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -11,7 +11,6 @@ import (
|
||||||
_ "code.gitea.io/gitea/models"
|
_ "code.gitea.io/gitea/models"
|
||||||
_ "code.gitea.io/gitea/models/actions"
|
_ "code.gitea.io/gitea/models/actions"
|
||||||
_ "code.gitea.io/gitea/models/activities"
|
_ "code.gitea.io/gitea/models/activities"
|
||||||
_ "code.gitea.io/gitea/models/forgefed"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
|
|
|
@ -75,32 +75,3 @@ func TestBranchRuleMatchPriority(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBranchRuleSort(t *testing.T) {
|
|
||||||
in := []*ProtectedBranch{{
|
|
||||||
RuleName: "b",
|
|
||||||
CreatedUnix: 1,
|
|
||||||
}, {
|
|
||||||
RuleName: "b/*",
|
|
||||||
CreatedUnix: 3,
|
|
||||||
}, {
|
|
||||||
RuleName: "a/*",
|
|
||||||
CreatedUnix: 2,
|
|
||||||
}, {
|
|
||||||
RuleName: "c",
|
|
||||||
CreatedUnix: 0,
|
|
||||||
}, {
|
|
||||||
RuleName: "a",
|
|
||||||
CreatedUnix: 4,
|
|
||||||
}}
|
|
||||||
expect := []string{"c", "b", "a", "a/*", "b/*"}
|
|
||||||
|
|
||||||
pbr := ProtectedBranchRules(in)
|
|
||||||
pbr.sort()
|
|
||||||
|
|
||||||
var got []string
|
|
||||||
for i := range pbr {
|
|
||||||
got = append(got, pbr[i].RuleName)
|
|
||||||
}
|
|
||||||
assert.Equal(t, expect, got)
|
|
||||||
}
|
|
|
@ -79,21 +79,15 @@ func IsRuleNameSpecial(ruleName string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (protectBranch *ProtectedBranch) loadGlob() {
|
func (protectBranch *ProtectedBranch) loadGlob() {
|
||||||
if protectBranch.isPlainName || protectBranch.globRule != nil {
|
if protectBranch.globRule == nil {
|
||||||
return
|
|
||||||
}
|
|
||||||
// detect if it is not glob
|
|
||||||
if !IsRuleNameSpecial(protectBranch.RuleName) {
|
|
||||||
protectBranch.isPlainName = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// now we load the glob
|
|
||||||
var err error
|
var err error
|
||||||
protectBranch.globRule, err = glob.Compile(protectBranch.RuleName, '/')
|
protectBranch.globRule, err = glob.Compile(protectBranch.RuleName, '/')
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn("Invalid glob rule for ProtectedBranch[%d]: %s %v", protectBranch.ID, protectBranch.RuleName, err)
|
log.Warn("Invalid glob rule for ProtectedBranch[%d]: %s %v", protectBranch.ID, protectBranch.RuleName, err)
|
||||||
protectBranch.globRule = glob.MustCompile(glob.QuoteMeta(protectBranch.RuleName), '/')
|
protectBranch.globRule = glob.MustCompile(glob.QuoteMeta(protectBranch.RuleName), '/')
|
||||||
}
|
}
|
||||||
|
protectBranch.isPlainName = !IsRuleNameSpecial(protectBranch.RuleName)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Match tests if branchName matches the rule
|
// Match tests if branchName matches the rule
|
||||||
|
|
|
@ -875,7 +875,7 @@ func GetPinnedIssues(ctx context.Context, repoID int64, isPull bool) (IssueList,
|
||||||
return issues, nil
|
return issues, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsNewPinAllowed returns if a new Issue or Pull request can be pinned
|
// IsNewPinnedAllowed returns if a new Issue or Pull request can be pinned
|
||||||
func IsNewPinAllowed(ctx context.Context, repoID int64, isPull bool) (bool, error) {
|
func IsNewPinAllowed(ctx context.Context, repoID int64, isPull bool) (bool, error) {
|
||||||
var maxPin int
|
var maxPin int
|
||||||
_, err := db.GetEngine(ctx).SQL("SELECT COUNT(pin_order) FROM issue WHERE repo_id = ? AND is_pull = ? AND pin_order > 0", repoID, isPull).Get(&maxPin)
|
_, err := db.GetEngine(ctx).SQL("SELECT COUNT(pin_order) FROM issue WHERE repo_id = ? AND is_pull = ? AND pin_order > 0", repoID, isPull).Get(&maxPin)
|
||||||
|
|
|
@ -111,7 +111,9 @@ func NewIssueLabel(ctx context.Context, issue *Issue, label *Label, doer *user_m
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = issue.ReloadLabels(ctx); err != nil {
|
issue.isLabelsLoaded = false
|
||||||
|
issue.Labels = nil
|
||||||
|
if err = issue.LoadLabels(ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,7 +161,10 @@ func NewIssueLabels(ctx context.Context, issue *Issue, labels []*Label, doer *us
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = issue.ReloadLabels(ctx); err != nil {
|
// reload all labels
|
||||||
|
issue.isLabelsLoaded = false
|
||||||
|
issue.Labels = nil
|
||||||
|
if err = issue.LoadLabels(ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,7 +205,8 @@ func DeleteIssueLabel(ctx context.Context, issue *Issue, label *Label, doer *use
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return issue.ReloadLabels(ctx)
|
issue.Labels = nil
|
||||||
|
return issue.LoadLabels(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteLabelsByRepoID deletes labels of some repository
|
// DeleteLabelsByRepoID deletes labels of some repository
|
||||||
|
@ -320,23 +326,14 @@ func FixIssueLabelWithOutsideLabels(ctx context.Context) (int64, error) {
|
||||||
return res.RowsAffected()
|
return res.RowsAffected()
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadLabels only if they are not already set
|
// LoadLabels loads labels
|
||||||
func (issue *Issue) LoadLabels(ctx context.Context) (err error) {
|
func (issue *Issue) LoadLabels(ctx context.Context) (err error) {
|
||||||
if !issue.isLabelsLoaded && issue.Labels == nil {
|
if !issue.isLabelsLoaded && issue.Labels == nil && issue.ID != 0 {
|
||||||
if err := issue.ReloadLabels(ctx); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
issue.isLabelsLoaded = true
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (issue *Issue) ReloadLabels(ctx context.Context) (err error) {
|
|
||||||
if issue.ID != 0 {
|
|
||||||
issue.Labels, err = GetLabelsByIssueID(ctx, issue.ID)
|
issue.Labels, err = GetLabelsByIssueID(ctx, issue.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("getLabelsByIssueID [%d]: %w", issue.ID, err)
|
return fmt.Errorf("getLabelsByIssueID [%d]: %w", issue.ID, err)
|
||||||
}
|
}
|
||||||
|
issue.isLabelsLoaded = true
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -499,7 +496,8 @@ func ReplaceIssueLabels(ctx context.Context, issue *Issue, labels []*Label, doer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = issue.ReloadLabels(ctx); err != nil {
|
issue.Labels = nil
|
||||||
|
if err = issue.LoadLabels(ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,114 +15,6 @@ import (
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestIssueNewIssueLabels(t *testing.T) {
|
|
||||||
require.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2})
|
|
||||||
label1 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 1})
|
|
||||||
label2 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 4})
|
|
||||||
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
|
||||||
|
|
||||||
label3 := &issues_model.Label{RepoID: 1, Name: "label3", Color: "#123"}
|
|
||||||
require.NoError(t, issues_model.NewLabel(db.DefaultContext, label3))
|
|
||||||
|
|
||||||
// label1 is already set, do nothing
|
|
||||||
// label3 is new, add it
|
|
||||||
require.NoError(t, issues_model.NewIssueLabels(db.DefaultContext, issue, []*issues_model.Label{label1, label3}, doer))
|
|
||||||
|
|
||||||
assert.Len(t, issue.Labels, 3)
|
|
||||||
// check that the pre-existing label1 is still present
|
|
||||||
assert.Equal(t, label1.ID, issue.Labels[0].ID)
|
|
||||||
// check that new label3 was added
|
|
||||||
assert.Equal(t, label3.ID, issue.Labels[1].ID)
|
|
||||||
// check that pre-existing label2 was not removed
|
|
||||||
assert.Equal(t, label2.ID, issue.Labels[2].ID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIssueNewIssueLabel(t *testing.T) {
|
|
||||||
require.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 3})
|
|
||||||
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
|
||||||
|
|
||||||
label := &issues_model.Label{RepoID: 1, Name: "label3", Color: "#123"}
|
|
||||||
require.NoError(t, issues_model.NewLabel(db.DefaultContext, label))
|
|
||||||
|
|
||||||
require.NoError(t, issues_model.NewIssueLabel(db.DefaultContext, issue, label, doer))
|
|
||||||
|
|
||||||
assert.Len(t, issue.Labels, 1)
|
|
||||||
assert.Equal(t, label.ID, issue.Labels[0].ID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIssueReplaceIssueLabels(t *testing.T) {
|
|
||||||
require.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2})
|
|
||||||
label1 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 1})
|
|
||||||
label2 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 4})
|
|
||||||
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
|
||||||
|
|
||||||
label3 := &issues_model.Label{RepoID: 1, Name: "label3", Color: "#123"}
|
|
||||||
require.NoError(t, issues_model.NewLabel(db.DefaultContext, label3))
|
|
||||||
|
|
||||||
issue.LoadLabels(db.DefaultContext)
|
|
||||||
assert.Len(t, issue.Labels, 2)
|
|
||||||
assert.Equal(t, label1.ID, issue.Labels[0].ID)
|
|
||||||
assert.Equal(t, label2.ID, issue.Labels[1].ID)
|
|
||||||
|
|
||||||
// label1 is already set, do nothing
|
|
||||||
// label3 is new, add it
|
|
||||||
// label2 is not in the list but already set, remove it
|
|
||||||
require.NoError(t, issues_model.ReplaceIssueLabels(db.DefaultContext, issue, []*issues_model.Label{label1, label3}, doer))
|
|
||||||
|
|
||||||
assert.Len(t, issue.Labels, 2)
|
|
||||||
assert.Equal(t, label1.ID, issue.Labels[0].ID)
|
|
||||||
assert.Equal(t, label3.ID, issue.Labels[1].ID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIssueDeleteIssueLabel(t *testing.T) {
|
|
||||||
require.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2})
|
|
||||||
label1 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 1})
|
|
||||||
label2 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 4})
|
|
||||||
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
|
||||||
|
|
||||||
issue.LoadLabels(db.DefaultContext)
|
|
||||||
assert.Len(t, issue.Labels, 2)
|
|
||||||
assert.Equal(t, label1.ID, issue.Labels[0].ID)
|
|
||||||
assert.Equal(t, label2.ID, issue.Labels[1].ID)
|
|
||||||
|
|
||||||
require.NoError(t, issues_model.DeleteIssueLabel(db.DefaultContext, issue, label2, doer))
|
|
||||||
|
|
||||||
assert.Len(t, issue.Labels, 1)
|
|
||||||
assert.Equal(t, label1.ID, issue.Labels[0].ID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIssueLoadLabels(t *testing.T) {
|
|
||||||
require.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2})
|
|
||||||
label1 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 1})
|
|
||||||
label2 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 4})
|
|
||||||
|
|
||||||
assert.Empty(t, issue.Labels)
|
|
||||||
issue.LoadLabels(db.DefaultContext)
|
|
||||||
assert.Len(t, issue.Labels, 2)
|
|
||||||
assert.Equal(t, label1.ID, issue.Labels[0].ID)
|
|
||||||
assert.Equal(t, label2.ID, issue.Labels[1].ID)
|
|
||||||
|
|
||||||
unittest.AssertSuccessfulDelete(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: label2.ID})
|
|
||||||
|
|
||||||
// the database change is not noticed because the labels are cached
|
|
||||||
issue.LoadLabels(db.DefaultContext)
|
|
||||||
assert.Len(t, issue.Labels, 2)
|
|
||||||
|
|
||||||
issue.ReloadLabels(db.DefaultContext)
|
|
||||||
assert.Len(t, issue.Labels, 1)
|
|
||||||
assert.Equal(t, label1.ID, issue.Labels[0].ID)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNewIssueLabelsScope(t *testing.T) {
|
func TestNewIssueLabelsScope(t *testing.T) {
|
||||||
require.NoError(t, unittest.PrepareTestDatabase())
|
require.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
|
|
@ -231,7 +231,8 @@ func TestGetLabelsByOrgID(t *testing.T) {
|
||||||
testSuccess(3, "reversealphabetically", []int64{4, 3})
|
testSuccess(3, "reversealphabetically", []int64{4, 3})
|
||||||
testSuccess(3, "default", []int64{3, 4})
|
testSuccess(3, "default", []int64{3, 4})
|
||||||
|
|
||||||
_, err := issues_model.GetLabelsByOrgID(db.DefaultContext, 0, "leastissues", db.ListOptions{})
|
var err error
|
||||||
|
_, err = issues_model.GetLabelsByOrgID(db.DefaultContext, 0, "leastissues", db.ListOptions{})
|
||||||
assert.True(t, issues_model.IsErrOrgLabelNotExist(err))
|
assert.True(t, issues_model.IsErrOrgLabelNotExist(err))
|
||||||
|
|
||||||
_, err = issues_model.GetLabelsByOrgID(db.DefaultContext, -1, "leastissues", db.ListOptions{})
|
_, err = issues_model.GetLabelsByOrgID(db.DefaultContext, -1, "leastissues", db.ListOptions{})
|
||||||
|
|
|
@ -689,7 +689,7 @@ func GetPullRequestByIssueID(ctx context.Context, issueID int64) (*PullRequest,
|
||||||
return pr, pr.LoadAttributes(ctx)
|
return pr, pr.LoadAttributes(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPullRequestByBaseHeadInfo returns the pull request by given base and head
|
// GetPullRequestsByBaseHeadInfo returns the pull request by given base and head
|
||||||
func GetPullRequestByBaseHeadInfo(ctx context.Context, baseID, headID int64, base, head string) (*PullRequest, error) {
|
func GetPullRequestByBaseHeadInfo(ctx context.Context, baseID, headID int64, base, head string) (*PullRequest, error) {
|
||||||
pr := &PullRequest{}
|
pr := &PullRequest{}
|
||||||
sess := db.GetEngine(ctx).
|
sess := db.GetEngine(ctx).
|
||||||
|
|
|
@ -13,7 +13,6 @@ import (
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
|
||||||
_ "code.gitea.io/gitea/models/actions"
|
_ "code.gitea.io/gitea/models/actions"
|
||||||
_ "code.gitea.io/gitea/models/forgefed"
|
|
||||||
_ "code.gitea.io/gitea/models/system"
|
_ "code.gitea.io/gitea/models/system"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
|
@ -38,15 +38,25 @@ import (
|
||||||
|
|
||||||
const minDBVersion = 70 // Gitea 1.5.3
|
const minDBVersion = 70 // Gitea 1.5.3
|
||||||
|
|
||||||
|
// Migration describes on migration from lower version to high version
|
||||||
|
type Migration interface {
|
||||||
|
Description() string
|
||||||
|
Migrate(*xorm.Engine) error
|
||||||
|
}
|
||||||
|
|
||||||
type migration struct {
|
type migration struct {
|
||||||
idNumber int64 // DB version is "the last migration's idNumber" + 1
|
|
||||||
description string
|
description string
|
||||||
migrate func(*xorm.Engine) error
|
migrate func(*xorm.Engine) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// newMigration creates a new migration
|
// NewMigration creates a new migration
|
||||||
func newMigration(idNumber int64, desc string, fn func(*xorm.Engine) error) *migration {
|
func NewMigration(desc string, fn func(*xorm.Engine) error) Migration {
|
||||||
return &migration{idNumber, desc, fn}
|
return &migration{desc, fn}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Description returns the migration's description
|
||||||
|
func (m *migration) Description() string {
|
||||||
|
return m.description
|
||||||
}
|
}
|
||||||
|
|
||||||
// Migrate executes the migration
|
// Migrate executes the migration
|
||||||
|
@ -57,313 +67,538 @@ func (m *migration) Migrate(x *xorm.Engine) error {
|
||||||
// Version describes the version table. Should have only one row with id==1
|
// Version describes the version table. Should have only one row with id==1
|
||||||
type Version struct {
|
type Version struct {
|
||||||
ID int64 `xorm:"pk autoincr"`
|
ID int64 `xorm:"pk autoincr"`
|
||||||
Version int64 // DB version is "the last migration's idNumber" + 1
|
Version int64
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use noopMigration when there is a migration that has been no-oped
|
// Use noopMigration when there is a migration that has been no-oped
|
||||||
var noopMigration = func(_ *xorm.Engine) error { return nil }
|
var noopMigration = func(_ *xorm.Engine) error { return nil }
|
||||||
|
|
||||||
var preparedMigrations []*migration
|
|
||||||
|
|
||||||
// This is a sequence of migrations. Add new migrations to the bottom of the list.
|
// This is a sequence of migrations. Add new migrations to the bottom of the list.
|
||||||
// If you want to "retire" a migration, remove it from the top of the list and
|
// If you want to "retire" a migration, remove it from the top of the list and
|
||||||
// update minDBVersion accordingly
|
// update minDBVersion accordingly
|
||||||
func prepareMigrationTasks() []*migration {
|
var migrations = []Migration{
|
||||||
if preparedMigrations != nil {
|
// Gitea 1.5.0 ends at v69
|
||||||
return preparedMigrations
|
|
||||||
}
|
|
||||||
preparedMigrations = []*migration{
|
|
||||||
// Gitea 1.5.0 ends at database version 69
|
|
||||||
|
|
||||||
newMigration(70, "add issue_dependencies", v1_6.AddIssueDependencies),
|
// v70 -> v71
|
||||||
newMigration(71, "protect each scratch token", v1_6.AddScratchHash),
|
NewMigration("add issue_dependencies", v1_6.AddIssueDependencies),
|
||||||
newMigration(72, "add review", v1_6.AddReview),
|
// v71 -> v72
|
||||||
|
NewMigration("protect each scratch token", v1_6.AddScratchHash),
|
||||||
|
// v72 -> v73
|
||||||
|
NewMigration("add review", v1_6.AddReview),
|
||||||
|
|
||||||
// Gitea 1.6.0 ends at database version 73
|
// Gitea 1.6.0 ends at v73
|
||||||
|
|
||||||
newMigration(73, "add must_change_password column for users table", v1_7.AddMustChangePassword),
|
// v73 -> v74
|
||||||
newMigration(74, "add approval whitelists to protected branches", v1_7.AddApprovalWhitelistsToProtectedBranches),
|
NewMigration("add must_change_password column for users table", v1_7.AddMustChangePassword),
|
||||||
newMigration(75, "clear nonused data which not deleted when user was deleted", v1_7.ClearNonusedData),
|
// v74 -> v75
|
||||||
|
NewMigration("add approval whitelists to protected branches", v1_7.AddApprovalWhitelistsToProtectedBranches),
|
||||||
|
// v75 -> v76
|
||||||
|
NewMigration("clear nonused data which not deleted when user was deleted", v1_7.ClearNonusedData),
|
||||||
|
|
||||||
// Gitea 1.7.0 ends at database version 76
|
// Gitea 1.7.0 ends at v76
|
||||||
|
|
||||||
newMigration(76, "add pull request rebase with merge commit", v1_8.AddPullRequestRebaseWithMerge),
|
// v76 -> v77
|
||||||
newMigration(77, "add theme to users", v1_8.AddUserDefaultTheme),
|
NewMigration("add pull request rebase with merge commit", v1_8.AddPullRequestRebaseWithMerge),
|
||||||
newMigration(78, "rename repo is_bare to repo is_empty", v1_8.RenameRepoIsBareToIsEmpty),
|
// v77 -> v78
|
||||||
newMigration(79, "add can close issues via commit in any branch", v1_8.AddCanCloseIssuesViaCommitInAnyBranch),
|
NewMigration("add theme to users", v1_8.AddUserDefaultTheme),
|
||||||
newMigration(80, "add is locked to issues", v1_8.AddIsLockedToIssues),
|
// v78 -> v79
|
||||||
newMigration(81, "update U2F counter type", v1_8.ChangeU2FCounterType),
|
NewMigration("rename repo is_bare to repo is_empty", v1_8.RenameRepoIsBareToIsEmpty),
|
||||||
|
// v79 -> v80
|
||||||
|
NewMigration("add can close issues via commit in any branch", v1_8.AddCanCloseIssuesViaCommitInAnyBranch),
|
||||||
|
// v80 -> v81
|
||||||
|
NewMigration("add is locked to issues", v1_8.AddIsLockedToIssues),
|
||||||
|
// v81 -> v82
|
||||||
|
NewMigration("update U2F counter type", v1_8.ChangeU2FCounterType),
|
||||||
|
|
||||||
// Gitea 1.8.0 ends at database version 82
|
// Gitea 1.8.0 ends at v82
|
||||||
|
|
||||||
newMigration(82, "hot fix for wrong release sha1 on release table", v1_9.FixReleaseSha1OnReleaseTable),
|
// v82 -> v83
|
||||||
newMigration(83, "add uploader id for table attachment", v1_9.AddUploaderIDForAttachment),
|
NewMigration("hot fix for wrong release sha1 on release table", v1_9.FixReleaseSha1OnReleaseTable),
|
||||||
newMigration(84, "add table to store original imported gpg keys", v1_9.AddGPGKeyImport),
|
// v83 -> v84
|
||||||
newMigration(85, "hash application token", v1_9.HashAppToken),
|
NewMigration("add uploader id for table attachment", v1_9.AddUploaderIDForAttachment),
|
||||||
newMigration(86, "add http method to webhook", v1_9.AddHTTPMethodToWebhook),
|
// v84 -> v85
|
||||||
newMigration(87, "add avatar field to repository", v1_9.AddAvatarFieldToRepository),
|
NewMigration("add table to store original imported gpg keys", v1_9.AddGPGKeyImport),
|
||||||
|
// v85 -> v86
|
||||||
|
NewMigration("hash application token", v1_9.HashAppToken),
|
||||||
|
// v86 -> v87
|
||||||
|
NewMigration("add http method to webhook", v1_9.AddHTTPMethodToWebhook),
|
||||||
|
// v87 -> v88
|
||||||
|
NewMigration("add avatar field to repository", v1_9.AddAvatarFieldToRepository),
|
||||||
|
|
||||||
// Gitea 1.9.0 ends at database version 88
|
// Gitea 1.9.0 ends at v88
|
||||||
|
|
||||||
newMigration(88, "add commit status context field to commit_status", v1_10.AddCommitStatusContext),
|
// v88 -> v89
|
||||||
newMigration(89, "add original author/url migration info to issues, comments, and repo ", v1_10.AddOriginalMigrationInfo),
|
NewMigration("add commit status context field to commit_status", v1_10.AddCommitStatusContext),
|
||||||
newMigration(90, "change length of some repository columns", v1_10.ChangeSomeColumnsLengthOfRepo),
|
// v89 -> v90
|
||||||
newMigration(91, "add index on owner_id of repository and type, review_id of comment", v1_10.AddIndexOnRepositoryAndComment),
|
NewMigration("add original author/url migration info to issues, comments, and repo ", v1_10.AddOriginalMigrationInfo),
|
||||||
newMigration(92, "remove orphaned repository index statuses", v1_10.RemoveLingeringIndexStatus),
|
// v90 -> v91
|
||||||
newMigration(93, "add email notification enabled preference to user", v1_10.AddEmailNotificationEnabledToUser),
|
NewMigration("change length of some repository columns", v1_10.ChangeSomeColumnsLengthOfRepo),
|
||||||
newMigration(94, "add enable_status_check, status_check_contexts to protected_branch", v1_10.AddStatusCheckColumnsForProtectedBranches),
|
// v91 -> v92
|
||||||
newMigration(95, "add table columns for cross referencing issues", v1_10.AddCrossReferenceColumns),
|
NewMigration("add index on owner_id of repository and type, review_id of comment", v1_10.AddIndexOnRepositoryAndComment),
|
||||||
newMigration(96, "delete orphaned attachments", v1_10.DeleteOrphanedAttachments),
|
// v92 -> v93
|
||||||
newMigration(97, "add repo_admin_change_team_access to user", v1_10.AddRepoAdminChangeTeamAccessColumnForUser),
|
NewMigration("remove orphaned repository index statuses", v1_10.RemoveLingeringIndexStatus),
|
||||||
newMigration(98, "add original author name and id on migrated release", v1_10.AddOriginalAuthorOnMigratedReleases),
|
// v93 -> v94
|
||||||
newMigration(99, "add task table and status column for repository table", v1_10.AddTaskTable),
|
NewMigration("add email notification enabled preference to user", v1_10.AddEmailNotificationEnabledToUser),
|
||||||
newMigration(100, "update migration repositories' service type", v1_10.UpdateMigrationServiceTypes),
|
// v94 -> v95
|
||||||
newMigration(101, "change length of some external login users columns", v1_10.ChangeSomeColumnsLengthOfExternalLoginUser),
|
NewMigration("add enable_status_check, status_check_contexts to protected_branch", v1_10.AddStatusCheckColumnsForProtectedBranches),
|
||||||
|
// v95 -> v96
|
||||||
|
NewMigration("add table columns for cross referencing issues", v1_10.AddCrossReferenceColumns),
|
||||||
|
// v96 -> v97
|
||||||
|
NewMigration("delete orphaned attachments", v1_10.DeleteOrphanedAttachments),
|
||||||
|
// v97 -> v98
|
||||||
|
NewMigration("add repo_admin_change_team_access to user", v1_10.AddRepoAdminChangeTeamAccessColumnForUser),
|
||||||
|
// v98 -> v99
|
||||||
|
NewMigration("add original author name and id on migrated release", v1_10.AddOriginalAuthorOnMigratedReleases),
|
||||||
|
// v99 -> v100
|
||||||
|
NewMigration("add task table and status column for repository table", v1_10.AddTaskTable),
|
||||||
|
// v100 -> v101
|
||||||
|
NewMigration("update migration repositories' service type", v1_10.UpdateMigrationServiceTypes),
|
||||||
|
// v101 -> v102
|
||||||
|
NewMigration("change length of some external login users columns", v1_10.ChangeSomeColumnsLengthOfExternalLoginUser),
|
||||||
|
|
||||||
// Gitea 1.10.0 ends at database version 102
|
// Gitea 1.10.0 ends at v102
|
||||||
|
|
||||||
newMigration(102, "update migration repositories' service type", v1_11.DropColumnHeadUserNameOnPullRequest),
|
// v102 -> v103
|
||||||
newMigration(103, "Add WhitelistDeployKeys to protected branch", v1_11.AddWhitelistDeployKeysToBranches),
|
NewMigration("update migration repositories' service type", v1_11.DropColumnHeadUserNameOnPullRequest),
|
||||||
newMigration(104, "remove unnecessary columns from label", v1_11.RemoveLabelUneededCols),
|
// v103 -> v104
|
||||||
newMigration(105, "add includes_all_repositories to teams", v1_11.AddTeamIncludesAllRepositories),
|
NewMigration("Add WhitelistDeployKeys to protected branch", v1_11.AddWhitelistDeployKeysToBranches),
|
||||||
newMigration(106, "add column `mode` to table watch", v1_11.AddModeColumnToWatch),
|
// v104 -> v105
|
||||||
newMigration(107, "Add template options to repository", v1_11.AddTemplateToRepo),
|
NewMigration("remove unnecessary columns from label", v1_11.RemoveLabelUneededCols),
|
||||||
newMigration(108, "Add comment_id on table notification", v1_11.AddCommentIDOnNotification),
|
// v105 -> v106
|
||||||
newMigration(109, "add can_create_org_repo to team", v1_11.AddCanCreateOrgRepoColumnForTeam),
|
NewMigration("add includes_all_repositories to teams", v1_11.AddTeamIncludesAllRepositories),
|
||||||
newMigration(110, "change review content type to text", v1_11.ChangeReviewContentToText),
|
// v106 -> v107
|
||||||
newMigration(111, "update branch protection for can push and whitelist enable", v1_11.AddBranchProtectionCanPushAndEnableWhitelist),
|
NewMigration("add column `mode` to table watch", v1_11.AddModeColumnToWatch),
|
||||||
newMigration(112, "remove release attachments which repository deleted", v1_11.RemoveAttachmentMissedRepo),
|
// v107 -> v108
|
||||||
newMigration(113, "new feature: change target branch of pull requests", v1_11.FeatureChangeTargetBranch),
|
NewMigration("Add template options to repository", v1_11.AddTemplateToRepo),
|
||||||
newMigration(114, "Remove authentication credentials from stored URL", v1_11.SanitizeOriginalURL),
|
// v108 -> v109
|
||||||
newMigration(115, "add user_id prefix to existing user avatar name", v1_11.RenameExistingUserAvatarName),
|
NewMigration("Add comment_id on table notification", v1_11.AddCommentIDOnNotification),
|
||||||
newMigration(116, "Extend TrackedTimes", v1_11.ExtendTrackedTimes),
|
// v109 -> v110
|
||||||
|
NewMigration("add can_create_org_repo to team", v1_11.AddCanCreateOrgRepoColumnForTeam),
|
||||||
|
// v110 -> v111
|
||||||
|
NewMigration("change review content type to text", v1_11.ChangeReviewContentToText),
|
||||||
|
// v111 -> v112
|
||||||
|
NewMigration("update branch protection for can push and whitelist enable", v1_11.AddBranchProtectionCanPushAndEnableWhitelist),
|
||||||
|
// v112 -> v113
|
||||||
|
NewMigration("remove release attachments which repository deleted", v1_11.RemoveAttachmentMissedRepo),
|
||||||
|
// v113 -> v114
|
||||||
|
NewMigration("new feature: change target branch of pull requests", v1_11.FeatureChangeTargetBranch),
|
||||||
|
// v114 -> v115
|
||||||
|
NewMigration("Remove authentication credentials from stored URL", v1_11.SanitizeOriginalURL),
|
||||||
|
// v115 -> v116
|
||||||
|
NewMigration("add user_id prefix to existing user avatar name", v1_11.RenameExistingUserAvatarName),
|
||||||
|
// v116 -> v117
|
||||||
|
NewMigration("Extend TrackedTimes", v1_11.ExtendTrackedTimes),
|
||||||
|
|
||||||
// Gitea 1.11.0 ends at database version 117
|
// Gitea 1.11.0 ends at v117
|
||||||
|
|
||||||
newMigration(117, "Add block on rejected reviews branch protection", v1_12.AddBlockOnRejectedReviews),
|
// v117 -> v118
|
||||||
newMigration(118, "Add commit id and stale to reviews", v1_12.AddReviewCommitAndStale),
|
NewMigration("Add block on rejected reviews branch protection", v1_12.AddBlockOnRejectedReviews),
|
||||||
newMigration(119, "Fix migrated repositories' git service type", v1_12.FixMigratedRepositoryServiceType),
|
// v118 -> v119
|
||||||
newMigration(120, "Add owner_name on table repository", v1_12.AddOwnerNameOnRepository),
|
NewMigration("Add commit id and stale to reviews", v1_12.AddReviewCommitAndStale),
|
||||||
newMigration(121, "add is_restricted column for users table", v1_12.AddIsRestricted),
|
// v119 -> v120
|
||||||
newMigration(122, "Add Require Signed Commits to ProtectedBranch", v1_12.AddRequireSignedCommits),
|
NewMigration("Fix migrated repositories' git service type", v1_12.FixMigratedRepositoryServiceType),
|
||||||
newMigration(123, "Add original information for reactions", v1_12.AddReactionOriginals),
|
// v120 -> v121
|
||||||
newMigration(124, "Add columns to user and repository", v1_12.AddUserRepoMissingColumns),
|
NewMigration("Add owner_name on table repository", v1_12.AddOwnerNameOnRepository),
|
||||||
newMigration(125, "Add some columns on review for migration", v1_12.AddReviewMigrateInfo),
|
// v121 -> v122
|
||||||
newMigration(126, "Fix topic repository count", v1_12.FixTopicRepositoryCount),
|
NewMigration("add is_restricted column for users table", v1_12.AddIsRestricted),
|
||||||
newMigration(127, "add repository code language statistics", v1_12.AddLanguageStats),
|
// v122 -> v123
|
||||||
newMigration(128, "fix merge base for pull requests", v1_12.FixMergeBase),
|
NewMigration("Add Require Signed Commits to ProtectedBranch", v1_12.AddRequireSignedCommits),
|
||||||
newMigration(129, "remove dependencies from deleted repositories", v1_12.PurgeUnusedDependencies),
|
// v123 -> v124
|
||||||
newMigration(130, "Expand webhooks for more granularity", v1_12.ExpandWebhooks),
|
NewMigration("Add original information for reactions", v1_12.AddReactionOriginals),
|
||||||
newMigration(131, "Add IsSystemWebhook column to webhooks table", v1_12.AddSystemWebhookColumn),
|
// v124 -> v125
|
||||||
newMigration(132, "Add Branch Protection Protected Files Column", v1_12.AddBranchProtectionProtectedFilesColumn),
|
NewMigration("Add columns to user and repository", v1_12.AddUserRepoMissingColumns),
|
||||||
newMigration(133, "Add EmailHash Table", v1_12.AddEmailHashTable),
|
// v125 -> v126
|
||||||
newMigration(134, "Refix merge base for merged pull requests", v1_12.RefixMergeBase),
|
NewMigration("Add some columns on review for migration", v1_12.AddReviewMigrateInfo),
|
||||||
newMigration(135, "Add OrgID column to Labels table", v1_12.AddOrgIDLabelColumn),
|
// v126 -> v127
|
||||||
newMigration(136, "Add CommitsAhead and CommitsBehind Column to PullRequest Table", v1_12.AddCommitDivergenceToPulls),
|
NewMigration("Fix topic repository count", v1_12.FixTopicRepositoryCount),
|
||||||
newMigration(137, "Add Branch Protection Block Outdated Branch", v1_12.AddBlockOnOutdatedBranch),
|
// v127 -> v128
|
||||||
newMigration(138, "Add ResolveDoerID to Comment table", v1_12.AddResolveDoerIDCommentColumn),
|
NewMigration("add repository code language statistics", v1_12.AddLanguageStats),
|
||||||
newMigration(139, "prepend refs/heads/ to issue refs", v1_12.PrependRefsHeadsToIssueRefs),
|
// v128 -> v129
|
||||||
|
NewMigration("fix merge base for pull requests", v1_12.FixMergeBase),
|
||||||
|
// v129 -> v130
|
||||||
|
NewMigration("remove dependencies from deleted repositories", v1_12.PurgeUnusedDependencies),
|
||||||
|
// v130 -> v131
|
||||||
|
NewMigration("Expand webhooks for more granularity", v1_12.ExpandWebhooks),
|
||||||
|
// v131 -> v132
|
||||||
|
NewMigration("Add IsSystemWebhook column to webhooks table", v1_12.AddSystemWebhookColumn),
|
||||||
|
// v132 -> v133
|
||||||
|
NewMigration("Add Branch Protection Protected Files Column", v1_12.AddBranchProtectionProtectedFilesColumn),
|
||||||
|
// v133 -> v134
|
||||||
|
NewMigration("Add EmailHash Table", v1_12.AddEmailHashTable),
|
||||||
|
// v134 -> v135
|
||||||
|
NewMigration("Refix merge base for merged pull requests", v1_12.RefixMergeBase),
|
||||||
|
// v135 -> v136
|
||||||
|
NewMigration("Add OrgID column to Labels table", v1_12.AddOrgIDLabelColumn),
|
||||||
|
// v136 -> v137
|
||||||
|
NewMigration("Add CommitsAhead and CommitsBehind Column to PullRequest Table", v1_12.AddCommitDivergenceToPulls),
|
||||||
|
// v137 -> v138
|
||||||
|
NewMigration("Add Branch Protection Block Outdated Branch", v1_12.AddBlockOnOutdatedBranch),
|
||||||
|
// v138 -> v139
|
||||||
|
NewMigration("Add ResolveDoerID to Comment table", v1_12.AddResolveDoerIDCommentColumn),
|
||||||
|
// v139 -> v140
|
||||||
|
NewMigration("prepend refs/heads/ to issue refs", v1_12.PrependRefsHeadsToIssueRefs),
|
||||||
|
|
||||||
// Gitea 1.12.0 ends at database version 140
|
// Gitea 1.12.0 ends at v140
|
||||||
|
|
||||||
newMigration(140, "Save detected language file size to database instead of percent", v1_13.FixLanguageStatsToSaveSize),
|
// v140 -> v141
|
||||||
newMigration(141, "Add KeepActivityPrivate to User table", v1_13.AddKeepActivityPrivateUserColumn),
|
NewMigration("Save detected language file size to database instead of percent", v1_13.FixLanguageStatsToSaveSize),
|
||||||
newMigration(142, "Ensure Repository.IsArchived is not null", v1_13.SetIsArchivedToFalse),
|
// v141 -> v142
|
||||||
newMigration(143, "recalculate Stars number for all user", v1_13.RecalculateStars),
|
NewMigration("Add KeepActivityPrivate to User table", v1_13.AddKeepActivityPrivateUserColumn),
|
||||||
newMigration(144, "update Matrix Webhook http method to 'PUT'", v1_13.UpdateMatrixWebhookHTTPMethod),
|
// v142 -> v143
|
||||||
newMigration(145, "Increase Language field to 50 in LanguageStats", v1_13.IncreaseLanguageField),
|
NewMigration("Ensure Repository.IsArchived is not null", v1_13.SetIsArchivedToFalse),
|
||||||
newMigration(146, "Add projects info to repository table", v1_13.AddProjectsInfo),
|
// v143 -> v144
|
||||||
newMigration(147, "create review for 0 review id code comments", v1_13.CreateReviewsForCodeComments),
|
NewMigration("recalculate Stars number for all user", v1_13.RecalculateStars),
|
||||||
newMigration(148, "remove issue dependency comments who refer to non existing issues", v1_13.PurgeInvalidDependenciesComments),
|
// v144 -> v145
|
||||||
newMigration(149, "Add Created and Updated to Milestone table", v1_13.AddCreatedAndUpdatedToMilestones),
|
NewMigration("update Matrix Webhook http method to 'PUT'", v1_13.UpdateMatrixWebhookHTTPMethod),
|
||||||
newMigration(150, "add primary key to repo_topic", v1_13.AddPrimaryKeyToRepoTopic),
|
// v145 -> v146
|
||||||
newMigration(151, "set default password algorithm to Argon2", v1_13.SetDefaultPasswordToArgon2),
|
NewMigration("Increase Language field to 50 in LanguageStats", v1_13.IncreaseLanguageField),
|
||||||
newMigration(152, "add TrustModel field to Repository", v1_13.AddTrustModelToRepository),
|
// v146 -> v147
|
||||||
newMigration(153, "add Team review request support", v1_13.AddTeamReviewRequestSupport),
|
NewMigration("Add projects info to repository table", v1_13.AddProjectsInfo),
|
||||||
newMigration(154, "add timestamps to Star, Label, Follow, Watch and Collaboration", v1_13.AddTimeStamps),
|
// v147 -> v148
|
||||||
|
NewMigration("create review for 0 review id code comments", v1_13.CreateReviewsForCodeComments),
|
||||||
|
// v148 -> v149
|
||||||
|
NewMigration("remove issue dependency comments who refer to non existing issues", v1_13.PurgeInvalidDependenciesComments),
|
||||||
|
// v149 -> v150
|
||||||
|
NewMigration("Add Created and Updated to Milestone table", v1_13.AddCreatedAndUpdatedToMilestones),
|
||||||
|
// v150 -> v151
|
||||||
|
NewMigration("add primary key to repo_topic", v1_13.AddPrimaryKeyToRepoTopic),
|
||||||
|
// v151 -> v152
|
||||||
|
NewMigration("set default password algorithm to Argon2", v1_13.SetDefaultPasswordToArgon2),
|
||||||
|
// v152 -> v153
|
||||||
|
NewMigration("add TrustModel field to Repository", v1_13.AddTrustModelToRepository),
|
||||||
|
// v153 > v154
|
||||||
|
NewMigration("add Team review request support", v1_13.AddTeamReviewRequestSupport),
|
||||||
|
// v154 > v155
|
||||||
|
NewMigration("add timestamps to Star, Label, Follow, Watch and Collaboration", v1_13.AddTimeStamps),
|
||||||
|
|
||||||
// Gitea 1.13.0 ends at database version 155
|
// Gitea 1.13.0 ends at v155
|
||||||
|
|
||||||
newMigration(155, "add changed_protected_files column for pull_request table", v1_14.AddChangedProtectedFilesPullRequestColumn),
|
// v155 -> v156
|
||||||
newMigration(156, "fix publisher ID for tag releases", v1_14.FixPublisherIDforTagReleases),
|
NewMigration("add changed_protected_files column for pull_request table", v1_14.AddChangedProtectedFilesPullRequestColumn),
|
||||||
newMigration(157, "ensure repo topics are up-to-date", v1_14.FixRepoTopics),
|
// v156 -> v157
|
||||||
newMigration(158, "code comment replies should have the commitID of the review they are replying to", v1_14.UpdateCodeCommentReplies),
|
NewMigration("fix publisher ID for tag releases", v1_14.FixPublisherIDforTagReleases),
|
||||||
newMigration(159, "update reactions constraint", v1_14.UpdateReactionConstraint),
|
// v157 -> v158
|
||||||
newMigration(160, "Add block on official review requests branch protection", v1_14.AddBlockOnOfficialReviewRequests),
|
NewMigration("ensure repo topics are up-to-date", v1_14.FixRepoTopics),
|
||||||
newMigration(161, "Convert task type from int to string", v1_14.ConvertTaskTypeToString),
|
// v158 -> v159
|
||||||
newMigration(162, "Convert webhook task type from int to string", v1_14.ConvertWebhookTaskTypeToString),
|
NewMigration("code comment replies should have the commitID of the review they are replying to", v1_14.UpdateCodeCommentReplies),
|
||||||
newMigration(163, "Convert topic name from 25 to 50", v1_14.ConvertTopicNameFrom25To50),
|
// v159 -> v160
|
||||||
newMigration(164, "Add scope and nonce columns to oauth2_grant table", v1_14.AddScopeAndNonceColumnsToOAuth2Grant),
|
NewMigration("update reactions constraint", v1_14.UpdateReactionConstraint),
|
||||||
newMigration(165, "Convert hook task type from char(16) to varchar(16) and trim the column", v1_14.ConvertHookTaskTypeToVarcharAndTrim),
|
// v160 -> v161
|
||||||
newMigration(166, "Where Password is Valid with Empty String delete it", v1_14.RecalculateUserEmptyPWD),
|
NewMigration("Add block on official review requests branch protection", v1_14.AddBlockOnOfficialReviewRequests),
|
||||||
newMigration(167, "Add user redirect", v1_14.AddUserRedirect),
|
// v161 -> v162
|
||||||
newMigration(168, "Recreate user table to fix default values", v1_14.RecreateUserTableToFixDefaultValues),
|
NewMigration("Convert task type from int to string", v1_14.ConvertTaskTypeToString),
|
||||||
newMigration(169, "Update DeleteBranch comments to set the old_ref to the commit_sha", v1_14.CommentTypeDeleteBranchUseOldRef),
|
// v162 -> v163
|
||||||
newMigration(170, "Add Dismissed to Review table", v1_14.AddDismissedReviewColumn),
|
NewMigration("Convert webhook task type from int to string", v1_14.ConvertWebhookTaskTypeToString),
|
||||||
newMigration(171, "Add Sorting to ProjectBoard table", v1_14.AddSortingColToProjectBoard),
|
// v163 -> v164
|
||||||
newMigration(172, "Add sessions table for go-chi/session", v1_14.AddSessionTable),
|
NewMigration("Convert topic name from 25 to 50", v1_14.ConvertTopicNameFrom25To50),
|
||||||
newMigration(173, "Add time_id column to Comment", v1_14.AddTimeIDCommentColumn),
|
// v164 -> v165
|
||||||
newMigration(174, "Create repo transfer table", v1_14.AddRepoTransfer),
|
NewMigration("Add scope and nonce columns to oauth2_grant table", v1_14.AddScopeAndNonceColumnsToOAuth2Grant),
|
||||||
newMigration(175, "Fix Postgres ID Sequences broken by recreate-table", v1_14.FixPostgresIDSequences),
|
// v165 -> v166
|
||||||
newMigration(176, "Remove invalid labels from comments", v1_14.RemoveInvalidLabels),
|
NewMigration("Convert hook task type from char(16) to varchar(16) and trim the column", v1_14.ConvertHookTaskTypeToVarcharAndTrim),
|
||||||
newMigration(177, "Delete orphaned IssueLabels", v1_14.DeleteOrphanedIssueLabels),
|
// v166 -> v167
|
||||||
|
NewMigration("Where Password is Valid with Empty String delete it", v1_14.RecalculateUserEmptyPWD),
|
||||||
|
// v167 -> v168
|
||||||
|
NewMigration("Add user redirect", v1_14.AddUserRedirect),
|
||||||
|
// v168 -> v169
|
||||||
|
NewMigration("Recreate user table to fix default values", v1_14.RecreateUserTableToFixDefaultValues),
|
||||||
|
// v169 -> v170
|
||||||
|
NewMigration("Update DeleteBranch comments to set the old_ref to the commit_sha", v1_14.CommentTypeDeleteBranchUseOldRef),
|
||||||
|
// v170 -> v171
|
||||||
|
NewMigration("Add Dismissed to Review table", v1_14.AddDismissedReviewColumn),
|
||||||
|
// v171 -> v172
|
||||||
|
NewMigration("Add Sorting to ProjectBoard table", v1_14.AddSortingColToProjectBoard),
|
||||||
|
// v172 -> v173
|
||||||
|
NewMigration("Add sessions table for go-chi/session", v1_14.AddSessionTable),
|
||||||
|
// v173 -> v174
|
||||||
|
NewMigration("Add time_id column to Comment", v1_14.AddTimeIDCommentColumn),
|
||||||
|
// v174 -> v175
|
||||||
|
NewMigration("Create repo transfer table", v1_14.AddRepoTransfer),
|
||||||
|
// v175 -> v176
|
||||||
|
NewMigration("Fix Postgres ID Sequences broken by recreate-table", v1_14.FixPostgresIDSequences),
|
||||||
|
// v176 -> v177
|
||||||
|
NewMigration("Remove invalid labels from comments", v1_14.RemoveInvalidLabels),
|
||||||
|
// v177 -> v178
|
||||||
|
NewMigration("Delete orphaned IssueLabels", v1_14.DeleteOrphanedIssueLabels),
|
||||||
|
|
||||||
// Gitea 1.14.0 ends at database version 178
|
// Gitea 1.14.0 ends at v178
|
||||||
|
|
||||||
newMigration(178, "Add LFS columns to Mirror", v1_15.AddLFSMirrorColumns),
|
// v178 -> v179
|
||||||
newMigration(179, "Convert avatar url to text", v1_15.ConvertAvatarURLToText),
|
NewMigration("Add LFS columns to Mirror", v1_15.AddLFSMirrorColumns),
|
||||||
newMigration(180, "Delete credentials from past migrations", v1_15.DeleteMigrationCredentials),
|
// v179 -> v180
|
||||||
newMigration(181, "Always save primary email on email address table", v1_15.AddPrimaryEmail2EmailAddress),
|
NewMigration("Convert avatar url to text", v1_15.ConvertAvatarURLToText),
|
||||||
newMigration(182, "Add issue resource index table", v1_15.AddIssueResourceIndexTable),
|
// v180 -> v181
|
||||||
newMigration(183, "Create PushMirror table", v1_15.CreatePushMirrorTable),
|
NewMigration("Delete credentials from past migrations", v1_15.DeleteMigrationCredentials),
|
||||||
newMigration(184, "Rename Task errors to message", v1_15.RenameTaskErrorsToMessage),
|
// v181 -> v182
|
||||||
newMigration(185, "Add new table repo_archiver", v1_15.AddRepoArchiver),
|
NewMigration("Always save primary email on email address table", v1_15.AddPrimaryEmail2EmailAddress),
|
||||||
newMigration(186, "Create protected tag table", v1_15.CreateProtectedTagTable),
|
// v182 -> v183
|
||||||
newMigration(187, "Drop unneeded webhook related columns", v1_15.DropWebhookColumns),
|
NewMigration("Add issue resource index table", v1_15.AddIssueResourceIndexTable),
|
||||||
newMigration(188, "Add key is verified to gpg key", v1_15.AddKeyIsVerified),
|
// v183 -> v184
|
||||||
|
NewMigration("Create PushMirror table", v1_15.CreatePushMirrorTable),
|
||||||
|
// v184 -> v185
|
||||||
|
NewMigration("Rename Task errors to message", v1_15.RenameTaskErrorsToMessage),
|
||||||
|
// v185 -> v186
|
||||||
|
NewMigration("Add new table repo_archiver", v1_15.AddRepoArchiver),
|
||||||
|
// v186 -> v187
|
||||||
|
NewMigration("Create protected tag table", v1_15.CreateProtectedTagTable),
|
||||||
|
// v187 -> v188
|
||||||
|
NewMigration("Drop unneeded webhook related columns", v1_15.DropWebhookColumns),
|
||||||
|
// v188 -> v189
|
||||||
|
NewMigration("Add key is verified to gpg key", v1_15.AddKeyIsVerified),
|
||||||
|
|
||||||
// Gitea 1.15.0 ends at database version 189
|
// Gitea 1.15.0 ends at v189
|
||||||
|
|
||||||
newMigration(189, "Unwrap ldap.Sources", v1_16.UnwrapLDAPSourceCfg),
|
// v189 -> v190
|
||||||
newMigration(190, "Add agit flow pull request support", v1_16.AddAgitFlowPullRequest),
|
NewMigration("Unwrap ldap.Sources", v1_16.UnwrapLDAPSourceCfg),
|
||||||
newMigration(191, "Alter issue/comment table TEXT fields to LONGTEXT", v1_16.AlterIssueAndCommentTextFieldsToLongText),
|
// v190 -> v191
|
||||||
newMigration(192, "RecreateIssueResourceIndexTable to have a primary key instead of an unique index", v1_16.RecreateIssueResourceIndexTable),
|
NewMigration("Add agit flow pull request support", v1_16.AddAgitFlowPullRequest),
|
||||||
newMigration(193, "Add repo id column for attachment table", v1_16.AddRepoIDForAttachment),
|
// v191 -> v192
|
||||||
newMigration(194, "Add Branch Protection Unprotected Files Column", v1_16.AddBranchProtectionUnprotectedFilesColumn),
|
NewMigration("Alter issue/comment table TEXT fields to LONGTEXT", v1_16.AlterIssueAndCommentTextFieldsToLongText),
|
||||||
newMigration(195, "Add table commit_status_index", v1_16.AddTableCommitStatusIndex),
|
// v192 -> v193
|
||||||
newMigration(196, "Add Color to ProjectBoard table", v1_16.AddColorColToProjectBoard),
|
NewMigration("RecreateIssueResourceIndexTable to have a primary key instead of an unique index", v1_16.RecreateIssueResourceIndexTable),
|
||||||
newMigration(197, "Add renamed_branch table", v1_16.AddRenamedBranchTable),
|
// v193 -> v194
|
||||||
newMigration(198, "Add issue content history table", v1_16.AddTableIssueContentHistory),
|
NewMigration("Add repo id column for attachment table", v1_16.AddRepoIDForAttachment),
|
||||||
newMigration(199, "No-op (remote version is using AppState now)", noopMigration),
|
// v194 -> v195
|
||||||
newMigration(200, "Add table app_state", v1_16.AddTableAppState),
|
NewMigration("Add Branch Protection Unprotected Files Column", v1_16.AddBranchProtectionUnprotectedFilesColumn),
|
||||||
newMigration(201, "Drop table remote_version (if exists)", v1_16.DropTableRemoteVersion),
|
// v195 -> v196
|
||||||
newMigration(202, "Create key/value table for user settings", v1_16.CreateUserSettingsTable),
|
NewMigration("Add table commit_status_index", v1_16.AddTableCommitStatusIndex),
|
||||||
newMigration(203, "Add Sorting to ProjectIssue table", v1_16.AddProjectIssueSorting),
|
// v196 -> v197
|
||||||
newMigration(204, "Add key is verified to ssh key", v1_16.AddSSHKeyIsVerified),
|
NewMigration("Add Color to ProjectBoard table", v1_16.AddColorColToProjectBoard),
|
||||||
newMigration(205, "Migrate to higher varchar on user struct", v1_16.MigrateUserPasswordSalt),
|
// v197 -> v198
|
||||||
newMigration(206, "Add authorize column to team_unit table", v1_16.AddAuthorizeColForTeamUnit),
|
NewMigration("Add renamed_branch table", v1_16.AddRenamedBranchTable),
|
||||||
newMigration(207, "Add webauthn table and migrate u2f data to webauthn - NO-OPED", v1_16.AddWebAuthnCred),
|
// v198 -> v199
|
||||||
newMigration(208, "Use base32.HexEncoding instead of base64 encoding for cred ID as it is case insensitive - NO-OPED", v1_16.UseBase32HexForCredIDInWebAuthnCredential),
|
NewMigration("Add issue content history table", v1_16.AddTableIssueContentHistory),
|
||||||
newMigration(209, "Increase WebAuthentication CredentialID size to 410 - NO-OPED", v1_16.IncreaseCredentialIDTo410),
|
// v199 -> v200
|
||||||
newMigration(210, "v208 was completely broken - remigrate", v1_16.RemigrateU2FCredentials),
|
NewMigration("No-op (remote version is using AppState now)", noopMigration),
|
||||||
|
// v200 -> v201
|
||||||
|
NewMigration("Add table app_state", v1_16.AddTableAppState),
|
||||||
|
// v201 -> v202
|
||||||
|
NewMigration("Drop table remote_version (if exists)", v1_16.DropTableRemoteVersion),
|
||||||
|
// v202 -> v203
|
||||||
|
NewMigration("Create key/value table for user settings", v1_16.CreateUserSettingsTable),
|
||||||
|
// v203 -> v204
|
||||||
|
NewMigration("Add Sorting to ProjectIssue table", v1_16.AddProjectIssueSorting),
|
||||||
|
// v204 -> v205
|
||||||
|
NewMigration("Add key is verified to ssh key", v1_16.AddSSHKeyIsVerified),
|
||||||
|
// v205 -> v206
|
||||||
|
NewMigration("Migrate to higher varchar on user struct", v1_16.MigrateUserPasswordSalt),
|
||||||
|
// v206 -> v207
|
||||||
|
NewMigration("Add authorize column to team_unit table", v1_16.AddAuthorizeColForTeamUnit),
|
||||||
|
// v207 -> v208
|
||||||
|
NewMigration("Add webauthn table and migrate u2f data to webauthn - NO-OPED", v1_16.AddWebAuthnCred),
|
||||||
|
// v208 -> v209
|
||||||
|
NewMigration("Use base32.HexEncoding instead of base64 encoding for cred ID as it is case insensitive - NO-OPED", v1_16.UseBase32HexForCredIDInWebAuthnCredential),
|
||||||
|
// v209 -> v210
|
||||||
|
NewMigration("Increase WebAuthentication CredentialID size to 410 - NO-OPED", v1_16.IncreaseCredentialIDTo410),
|
||||||
|
// v210 -> v211
|
||||||
|
NewMigration("v208 was completely broken - remigrate", v1_16.RemigrateU2FCredentials),
|
||||||
|
|
||||||
// Gitea 1.16.2 ends at database version 211
|
// Gitea 1.16.2 ends at v211
|
||||||
|
|
||||||
newMigration(211, "Create ForeignReference table", v1_17.CreateForeignReferenceTable),
|
// v211 -> v212
|
||||||
newMigration(212, "Add package tables", v1_17.AddPackageTables),
|
NewMigration("Create ForeignReference table", v1_17.CreateForeignReferenceTable),
|
||||||
newMigration(213, "Add allow edits from maintainers to PullRequest table", v1_17.AddAllowMaintainerEdit),
|
// v212 -> v213
|
||||||
newMigration(214, "Add auto merge table", v1_17.AddAutoMergeTable),
|
NewMigration("Add package tables", v1_17.AddPackageTables),
|
||||||
newMigration(215, "allow to view files in PRs", v1_17.AddReviewViewedFiles),
|
// v213 -> v214
|
||||||
newMigration(216, "No-op (Improve Action table indices v1)", noopMigration),
|
NewMigration("Add allow edits from maintainers to PullRequest table", v1_17.AddAllowMaintainerEdit),
|
||||||
newMigration(217, "Alter hook_task table TEXT fields to LONGTEXT", v1_17.AlterHookTaskTextFieldsToLongText),
|
// v214 -> v215
|
||||||
newMigration(218, "Improve Action table indices v2", v1_17.ImproveActionTableIndices),
|
NewMigration("Add auto merge table", v1_17.AddAutoMergeTable),
|
||||||
newMigration(219, "Add sync_on_commit column to push_mirror table", v1_17.AddSyncOnCommitColForPushMirror),
|
// v215 -> v216
|
||||||
newMigration(220, "Add container repository property", v1_17.AddContainerRepositoryProperty),
|
NewMigration("allow to view files in PRs", v1_17.AddReviewViewedFiles),
|
||||||
newMigration(221, "Store WebAuthentication CredentialID as bytes and increase size to at least 1024", v1_17.StoreWebauthnCredentialIDAsBytes),
|
// v216 -> v217
|
||||||
newMigration(222, "Drop old CredentialID column", v1_17.DropOldCredentialIDColumn),
|
NewMigration("No-op (Improve Action table indices v1)", noopMigration),
|
||||||
newMigration(223, "Rename CredentialIDBytes column to CredentialID", v1_17.RenameCredentialIDBytes),
|
// v217 -> v218
|
||||||
|
NewMigration("Alter hook_task table TEXT fields to LONGTEXT", v1_17.AlterHookTaskTextFieldsToLongText),
|
||||||
|
// v218 -> v219
|
||||||
|
NewMigration("Improve Action table indices v2", v1_17.ImproveActionTableIndices),
|
||||||
|
// v219 -> v220
|
||||||
|
NewMigration("Add sync_on_commit column to push_mirror table", v1_17.AddSyncOnCommitColForPushMirror),
|
||||||
|
// v220 -> v221
|
||||||
|
NewMigration("Add container repository property", v1_17.AddContainerRepositoryProperty),
|
||||||
|
// v221 -> v222
|
||||||
|
NewMigration("Store WebAuthentication CredentialID as bytes and increase size to at least 1024", v1_17.StoreWebauthnCredentialIDAsBytes),
|
||||||
|
// v222 -> v223
|
||||||
|
NewMigration("Drop old CredentialID column", v1_17.DropOldCredentialIDColumn),
|
||||||
|
// v223 -> v224
|
||||||
|
NewMigration("Rename CredentialIDBytes column to CredentialID", v1_17.RenameCredentialIDBytes),
|
||||||
|
|
||||||
// Gitea 1.17.0 ends at database version 224
|
// Gitea 1.17.0 ends at v224
|
||||||
|
|
||||||
newMigration(224, "Add badges to users", v1_18.CreateUserBadgesTable),
|
// v224 -> v225
|
||||||
newMigration(225, "Alter gpg_key/public_key content TEXT fields to MEDIUMTEXT", v1_18.AlterPublicGPGKeyContentFieldsToMediumText),
|
NewMigration("Add badges to users", v1_18.CreateUserBadgesTable),
|
||||||
newMigration(226, "Conan and generic packages do not need to be semantically versioned", v1_18.FixPackageSemverField),
|
// v225 -> v226
|
||||||
newMigration(227, "Create key/value table for system settings", v1_18.CreateSystemSettingsTable),
|
NewMigration("Alter gpg_key/public_key content TEXT fields to MEDIUMTEXT", v1_18.AlterPublicGPGKeyContentFieldsToMediumText),
|
||||||
newMigration(228, "Add TeamInvite table", v1_18.AddTeamInviteTable),
|
// v226 -> v227
|
||||||
newMigration(229, "Update counts of all open milestones", v1_18.UpdateOpenMilestoneCounts),
|
NewMigration("Conan and generic packages do not need to be semantically versioned", v1_18.FixPackageSemverField),
|
||||||
newMigration(230, "Add ConfidentialClient column (default true) to OAuth2Application table", v1_18.AddConfidentialClientColumnToOAuth2ApplicationTable),
|
// v227 -> v228
|
||||||
|
NewMigration("Create key/value table for system settings", v1_18.CreateSystemSettingsTable),
|
||||||
|
// v228 -> v229
|
||||||
|
NewMigration("Add TeamInvite table", v1_18.AddTeamInviteTable),
|
||||||
|
// v229 -> v230
|
||||||
|
NewMigration("Update counts of all open milestones", v1_18.UpdateOpenMilestoneCounts),
|
||||||
|
// v230 -> v231
|
||||||
|
NewMigration("Add ConfidentialClient column (default true) to OAuth2Application table", v1_18.AddConfidentialClientColumnToOAuth2ApplicationTable),
|
||||||
|
|
||||||
// Gitea 1.18.0 ends at database version 231
|
// Gitea 1.18.0 ends at v231
|
||||||
|
|
||||||
newMigration(231, "Add index for hook_task", v1_19.AddIndexForHookTask),
|
// v231 -> v232
|
||||||
newMigration(232, "Alter package_version.metadata_json to LONGTEXT", v1_19.AlterPackageVersionMetadataToLongText),
|
NewMigration("Add index for hook_task", v1_19.AddIndexForHookTask),
|
||||||
newMigration(233, "Add header_authorization_encrypted column to webhook table", v1_19.AddHeaderAuthorizationEncryptedColWebhook),
|
// v232 -> v233
|
||||||
newMigration(234, "Add package cleanup rule table", v1_19.CreatePackageCleanupRuleTable),
|
NewMigration("Alter package_version.metadata_json to LONGTEXT", v1_19.AlterPackageVersionMetadataToLongText),
|
||||||
newMigration(235, "Add index for access_token", v1_19.AddIndexForAccessToken),
|
// v233 -> v234
|
||||||
newMigration(236, "Create secrets table", v1_19.CreateSecretsTable),
|
NewMigration("Add header_authorization_encrypted column to webhook table", v1_19.AddHeaderAuthorizationEncryptedColWebhook),
|
||||||
newMigration(237, "Drop ForeignReference table", v1_19.DropForeignReferenceTable),
|
// v234 -> v235
|
||||||
newMigration(238, "Add updated unix to LFSMetaObject", v1_19.AddUpdatedUnixToLFSMetaObject),
|
NewMigration("Add package cleanup rule table", v1_19.CreatePackageCleanupRuleTable),
|
||||||
newMigration(239, "Add scope for access_token", v1_19.AddScopeForAccessTokens),
|
// v235 -> v236
|
||||||
newMigration(240, "Add actions tables", v1_19.AddActionsTables),
|
NewMigration("Add index for access_token", v1_19.AddIndexForAccessToken),
|
||||||
newMigration(241, "Add card_type column to project table", v1_19.AddCardTypeToProjectTable),
|
// v236 -> v237
|
||||||
newMigration(242, "Alter gpg_key_import content TEXT field to MEDIUMTEXT", v1_19.AlterPublicGPGKeyImportContentFieldToMediumText),
|
NewMigration("Create secrets table", v1_19.CreateSecretsTable),
|
||||||
newMigration(243, "Add exclusive label", v1_19.AddExclusiveLabel),
|
// v237 -> v238
|
||||||
|
NewMigration("Drop ForeignReference table", v1_19.DropForeignReferenceTable),
|
||||||
|
// v238 -> v239
|
||||||
|
NewMigration("Add updated unix to LFSMetaObject", v1_19.AddUpdatedUnixToLFSMetaObject),
|
||||||
|
// v239 -> v240
|
||||||
|
NewMigration("Add scope for access_token", v1_19.AddScopeForAccessTokens),
|
||||||
|
// v240 -> v241
|
||||||
|
NewMigration("Add actions tables", v1_19.AddActionsTables),
|
||||||
|
// v241 -> v242
|
||||||
|
NewMigration("Add card_type column to project table", v1_19.AddCardTypeToProjectTable),
|
||||||
|
// v242 -> v243
|
||||||
|
NewMigration("Alter gpg_key_import content TEXT field to MEDIUMTEXT", v1_19.AlterPublicGPGKeyImportContentFieldToMediumText),
|
||||||
|
// v243 -> v244
|
||||||
|
NewMigration("Add exclusive label", v1_19.AddExclusiveLabel),
|
||||||
|
|
||||||
// Gitea 1.19.0 ends at database version 244
|
// Gitea 1.19.0 ends at v244
|
||||||
|
|
||||||
newMigration(244, "Add NeedApproval to actions tables", v1_20.AddNeedApprovalToActionRun),
|
// v244 -> v245
|
||||||
newMigration(245, "Rename Webhook org_id to owner_id", v1_20.RenameWebhookOrgToOwner),
|
NewMigration("Add NeedApproval to actions tables", v1_20.AddNeedApprovalToActionRun),
|
||||||
newMigration(246, "Add missed column owner_id for project table", v1_20.AddNewColumnForProject),
|
// v245 -> v246
|
||||||
newMigration(247, "Fix incorrect project type", v1_20.FixIncorrectProjectType),
|
NewMigration("Rename Webhook org_id to owner_id", v1_20.RenameWebhookOrgToOwner),
|
||||||
newMigration(248, "Add version column to action_runner table", v1_20.AddVersionToActionRunner),
|
// v246 -> v247
|
||||||
newMigration(249, "Improve Action table indices v3", v1_20.ImproveActionTableIndices),
|
NewMigration("Add missed column owner_id for project table", v1_20.AddNewColumnForProject),
|
||||||
newMigration(250, "Change Container Metadata", v1_20.ChangeContainerMetadataMultiArch),
|
// v247 -> v248
|
||||||
newMigration(251, "Fix incorrect owner team unit access mode", v1_20.FixIncorrectOwnerTeamUnitAccessMode),
|
NewMigration("Fix incorrect project type", v1_20.FixIncorrectProjectType),
|
||||||
newMigration(252, "Fix incorrect admin team unit access mode", v1_20.FixIncorrectAdminTeamUnitAccessMode),
|
// v248 -> v249
|
||||||
newMigration(253, "Fix ExternalTracker and ExternalWiki accessMode in owner and admin team", v1_20.FixExternalTrackerAndExternalWikiAccessModeInOwnerAndAdminTeam),
|
NewMigration("Add version column to action_runner table", v1_20.AddVersionToActionRunner),
|
||||||
newMigration(254, "Add ActionTaskOutput table", v1_20.AddActionTaskOutputTable),
|
// v249 -> v250
|
||||||
newMigration(255, "Add ArchivedUnix Column", v1_20.AddArchivedUnixToRepository),
|
NewMigration("Improve Action table indices v3", v1_20.ImproveActionTableIndices),
|
||||||
newMigration(256, "Add is_internal column to package", v1_20.AddIsInternalColumnToPackage),
|
// v250 -> v251
|
||||||
newMigration(257, "Add Actions Artifact table", v1_20.CreateActionArtifactTable),
|
NewMigration("Change Container Metadata", v1_20.ChangeContainerMetadataMultiArch),
|
||||||
newMigration(258, "Add PinOrder Column", v1_20.AddPinOrderToIssue),
|
// v251 -> v252
|
||||||
newMigration(259, "Convert scoped access tokens", v1_20.ConvertScopedAccessTokens),
|
NewMigration("Fix incorrect owner team unit access mode", v1_20.FixIncorrectOwnerTeamUnitAccessMode),
|
||||||
|
// v252 -> v253
|
||||||
|
NewMigration("Fix incorrect admin team unit access mode", v1_20.FixIncorrectAdminTeamUnitAccessMode),
|
||||||
|
// v253 -> v254
|
||||||
|
NewMigration("Fix ExternalTracker and ExternalWiki accessMode in owner and admin team", v1_20.FixExternalTrackerAndExternalWikiAccessModeInOwnerAndAdminTeam),
|
||||||
|
// v254 -> v255
|
||||||
|
NewMigration("Add ActionTaskOutput table", v1_20.AddActionTaskOutputTable),
|
||||||
|
// v255 -> v256
|
||||||
|
NewMigration("Add ArchivedUnix Column", v1_20.AddArchivedUnixToRepository),
|
||||||
|
// v256 -> v257
|
||||||
|
NewMigration("Add is_internal column to package", v1_20.AddIsInternalColumnToPackage),
|
||||||
|
// v257 -> v258
|
||||||
|
NewMigration("Add Actions Artifact table", v1_20.CreateActionArtifactTable),
|
||||||
|
// v258 -> v259
|
||||||
|
NewMigration("Add PinOrder Column", v1_20.AddPinOrderToIssue),
|
||||||
|
// v259 -> v260
|
||||||
|
NewMigration("Convert scoped access tokens", v1_20.ConvertScopedAccessTokens),
|
||||||
|
|
||||||
// Gitea 1.20.0 ends at database version 260
|
// Gitea 1.20.0 ends at 260
|
||||||
|
|
||||||
newMigration(260, "Drop custom_labels column of action_runner table", v1_21.DropCustomLabelsColumnOfActionRunner),
|
// v260 -> v261
|
||||||
newMigration(261, "Add variable table", v1_21.CreateVariableTable),
|
NewMigration("Drop custom_labels column of action_runner table", v1_21.DropCustomLabelsColumnOfActionRunner),
|
||||||
newMigration(262, "Add TriggerEvent to action_run table", v1_21.AddTriggerEventToActionRun),
|
// v261 -> v262
|
||||||
newMigration(263, "Add git_size and lfs_size columns to repository table", v1_21.AddGitSizeAndLFSSizeToRepositoryTable),
|
NewMigration("Add variable table", v1_21.CreateVariableTable),
|
||||||
newMigration(264, "Add branch table", v1_21.AddBranchTable),
|
// v262 -> v263
|
||||||
newMigration(265, "Alter Actions Artifact table", v1_21.AlterActionArtifactTable),
|
NewMigration("Add TriggerEvent to action_run table", v1_21.AddTriggerEventToActionRun),
|
||||||
newMigration(266, "Reduce commit status", v1_21.ReduceCommitStatus),
|
// v263 -> v264
|
||||||
newMigration(267, "Add action_tasks_version table", v1_21.CreateActionTasksVersionTable),
|
NewMigration("Add git_size and lfs_size columns to repository table", v1_21.AddGitSizeAndLFSSizeToRepositoryTable),
|
||||||
newMigration(268, "Update Action Ref", v1_21.UpdateActionsRefIndex),
|
// v264 -> v265
|
||||||
newMigration(269, "Drop deleted branch table", v1_21.DropDeletedBranchTable),
|
NewMigration("Add branch table", v1_21.AddBranchTable),
|
||||||
newMigration(270, "Fix PackageProperty typo", v1_21.FixPackagePropertyTypo),
|
// v265 -> v266
|
||||||
newMigration(271, "Allow archiving labels", v1_21.AddArchivedUnixColumInLabelTable),
|
NewMigration("Alter Actions Artifact table", v1_21.AlterActionArtifactTable),
|
||||||
newMigration(272, "Add Version to ActionRun table", v1_21.AddVersionToActionRunTable),
|
// v266 -> v267
|
||||||
newMigration(273, "Add Action Schedule Table", v1_21.AddActionScheduleTable),
|
NewMigration("Reduce commit status", v1_21.ReduceCommitStatus),
|
||||||
newMigration(274, "Add Actions artifacts expiration date", v1_21.AddExpiredUnixColumnInActionArtifactTable),
|
// v267 -> v268
|
||||||
newMigration(275, "Add ScheduleID for ActionRun", v1_21.AddScheduleIDForActionRun),
|
NewMigration("Add action_tasks_version table", v1_21.CreateActionTasksVersionTable),
|
||||||
newMigration(276, "Add RemoteAddress to mirrors", v1_21.AddRemoteAddressToMirrors),
|
// v268 -> v269
|
||||||
newMigration(277, "Add Index to issue_user.issue_id", v1_21.AddIndexToIssueUserIssueID),
|
NewMigration("Update Action Ref", v1_21.UpdateActionsRefIndex),
|
||||||
newMigration(278, "Add Index to comment.dependent_issue_id", v1_21.AddIndexToCommentDependentIssueID),
|
// v269 -> v270
|
||||||
newMigration(279, "Add Index to action.user_id", v1_21.AddIndexToActionUserID),
|
NewMigration("Drop deleted branch table", v1_21.DropDeletedBranchTable),
|
||||||
|
// v270 -> v271
|
||||||
|
NewMigration("Fix PackageProperty typo", v1_21.FixPackagePropertyTypo),
|
||||||
|
// v271 -> v272
|
||||||
|
NewMigration("Allow archiving labels", v1_21.AddArchivedUnixColumInLabelTable),
|
||||||
|
// v272 -> v273
|
||||||
|
NewMigration("Add Version to ActionRun table", v1_21.AddVersionToActionRunTable),
|
||||||
|
// v273 -> v274
|
||||||
|
NewMigration("Add Action Schedule Table", v1_21.AddActionScheduleTable),
|
||||||
|
// v274 -> v275
|
||||||
|
NewMigration("Add Actions artifacts expiration date", v1_21.AddExpiredUnixColumnInActionArtifactTable),
|
||||||
|
// v275 -> v276
|
||||||
|
NewMigration("Add ScheduleID for ActionRun", v1_21.AddScheduleIDForActionRun),
|
||||||
|
// v276 -> v277
|
||||||
|
NewMigration("Add RemoteAddress to mirrors", v1_21.AddRemoteAddressToMirrors),
|
||||||
|
// v277 -> v278
|
||||||
|
NewMigration("Add Index to issue_user.issue_id", v1_21.AddIndexToIssueUserIssueID),
|
||||||
|
// v278 -> v279
|
||||||
|
NewMigration("Add Index to comment.dependent_issue_id", v1_21.AddIndexToCommentDependentIssueID),
|
||||||
|
// v279 -> v280
|
||||||
|
NewMigration("Add Index to action.user_id", v1_21.AddIndexToActionUserID),
|
||||||
|
|
||||||
// Gitea 1.21.0 ends at database version 280
|
// Gitea 1.21.0 ends at 280
|
||||||
|
|
||||||
newMigration(280, "Rename user themes", v1_22.RenameUserThemes),
|
// v280 -> v281
|
||||||
newMigration(281, "Add auth_token table", v1_22.CreateAuthTokenTable),
|
NewMigration("Rename user themes", v1_22.RenameUserThemes),
|
||||||
newMigration(282, "Add Index to pull_auto_merge.doer_id", v1_22.AddIndexToPullAutoMergeDoerID),
|
// v281 -> v282
|
||||||
newMigration(283, "Add combined Index to issue_user.uid and issue_id", v1_22.AddCombinedIndexToIssueUser),
|
NewMigration("Add auth_token table", v1_22.CreateAuthTokenTable),
|
||||||
newMigration(284, "Add ignore stale approval column on branch table", v1_22.AddIgnoreStaleApprovalsColumnToProtectedBranchTable),
|
// v282 -> v283
|
||||||
newMigration(285, "Add PreviousDuration to ActionRun", v1_22.AddPreviousDurationToActionRun),
|
NewMigration("Add Index to pull_auto_merge.doer_id", v1_22.AddIndexToPullAutoMergeDoerID),
|
||||||
newMigration(286, "Add support for SHA256 git repositories", v1_22.AdjustDBForSha256),
|
// v283 -> v284
|
||||||
newMigration(287, "Use Slug instead of ID for Badges", v1_22.UseSlugInsteadOfIDForBadges),
|
NewMigration("Add combined Index to issue_user.uid and issue_id", v1_22.AddCombinedIndexToIssueUser),
|
||||||
newMigration(288, "Add user_blocking table", v1_22.AddUserBlockingTable),
|
// v284 -> v285
|
||||||
newMigration(289, "Add default_wiki_branch to repository table", v1_22.AddDefaultWikiBranch),
|
NewMigration("Add ignore stale approval column on branch table", v1_22.AddIgnoreStaleApprovalsColumnToProtectedBranchTable),
|
||||||
newMigration(290, "Add PayloadVersion to HookTask", v1_22.AddPayloadVersionToHookTaskTable),
|
// v285 -> v286
|
||||||
newMigration(291, "Add Index to attachment.comment_id", v1_22.AddCommentIDIndexofAttachment),
|
NewMigration("Add PreviousDuration to ActionRun", v1_22.AddPreviousDurationToActionRun),
|
||||||
newMigration(292, "Ensure every project has exactly one default column - No Op", noopMigration),
|
// v286 -> v287
|
||||||
newMigration(293, "Ensure every project has exactly one default column", v1_22.CheckProjectColumnsConsistency),
|
NewMigration("Add support for SHA256 git repositories", v1_22.AdjustDBForSha256),
|
||||||
|
// v287 -> v288
|
||||||
|
NewMigration("Use Slug instead of ID for Badges", v1_22.UseSlugInsteadOfIDForBadges),
|
||||||
|
// v288 -> v289
|
||||||
|
NewMigration("Add user_blocking table", v1_22.AddUserBlockingTable),
|
||||||
|
// v289 -> v290
|
||||||
|
NewMigration("Add default_wiki_branch to repository table", v1_22.AddDefaultWikiBranch),
|
||||||
|
// v290 -> v291
|
||||||
|
NewMigration("Add PayloadVersion to HookTask", v1_22.AddPayloadVersionToHookTaskTable),
|
||||||
|
// v291 -> v292
|
||||||
|
NewMigration("Add Index to attachment.comment_id", v1_22.AddCommentIDIndexofAttachment),
|
||||||
|
// v292 -> v293
|
||||||
|
NewMigration("Ensure every project has exactly one default column - No Op", noopMigration),
|
||||||
|
// v293 -> v294
|
||||||
|
NewMigration("Ensure every project has exactly one default column", v1_22.CheckProjectColumnsConsistency),
|
||||||
|
|
||||||
// Gitea 1.22.0-rc0 ends at database version 294
|
// Gitea 1.22.0-rc0 ends at 294
|
||||||
|
|
||||||
newMigration(294, "Add unique index for project issue table", v1_22.AddUniqueIndexForProjectIssue),
|
// v294 -> v295
|
||||||
newMigration(295, "Add commit status summary table", v1_22.AddCommitStatusSummary),
|
NewMigration("Add unique index for project issue table", v1_22.AddUniqueIndexForProjectIssue),
|
||||||
newMigration(296, "Add missing field of commit status summary table", v1_22.AddCommitStatusSummary2),
|
// v295 -> v296
|
||||||
newMigration(297, "Add everyone_access_mode for repo_unit", noopMigration),
|
NewMigration("Add commit status summary table", v1_22.AddCommitStatusSummary),
|
||||||
newMigration(298, "Drop wrongly created table o_auth2_application", v1_22.DropWronglyCreatedTable),
|
// v296 -> v297
|
||||||
|
NewMigration("Add missing field of commit status summary table", v1_22.AddCommitStatusSummary2),
|
||||||
|
// v297 -> v298
|
||||||
|
NewMigration("Add everyone_access_mode for repo_unit", noopMigration),
|
||||||
|
// v298 -> v299
|
||||||
|
NewMigration("Drop wrongly created table o_auth2_application", v1_22.DropWronglyCreatedTable),
|
||||||
|
|
||||||
// Gitea 1.22.0-rc1 ends at migration ID number 298 (database version 299)
|
// Gitea 1.22.0-rc1 ends at 299
|
||||||
|
|
||||||
newMigration(299, "Add content version to issue and comment table", v1_23.AddContentVersionToIssueAndComment),
|
// v299 -> v300
|
||||||
newMigration(300, "Add force-push branch protection support", v1_23.AddForcePushBranchProtection),
|
NewMigration("Add content version to issue and comment table", v1_23.AddContentVersionToIssueAndComment),
|
||||||
newMigration(301, "Add skip_secondary_authorization option to oauth2 application table", v1_23.AddSkipSecondaryAuthColumnToOAuth2ApplicationTable),
|
// v300 -> v301
|
||||||
newMigration(302, "Add index to action_task stopped log_expired", v1_23.AddIndexToActionTaskStoppedLogExpired),
|
NewMigration("Add force-push branch protection support", v1_23.AddForcePushBranchProtection),
|
||||||
}
|
// v301 -> v302
|
||||||
return preparedMigrations
|
NewMigration("Add skip_secondary_authorization option to oauth2 application table", v1_23.AddSkipSecondaryAuthColumnToOAuth2ApplicationTable),
|
||||||
|
// v302 -> v303
|
||||||
|
NewMigration("Add index to action_task stopped log_expired", v1_23.AddIndexToActionTaskStoppedLogExpired),
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCurrentDBVersion returns the current db version
|
// GetCurrentDBVersion returns the current db version
|
||||||
|
@ -383,20 +618,9 @@ func GetCurrentDBVersion(x *xorm.Engine) (int64, error) {
|
||||||
return currentVersion.Version, nil
|
return currentVersion.Version, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func calcDBVersion(migrations []*migration) int64 {
|
// ExpectedVersion returns the expected db version
|
||||||
dbVer := int64(minDBVersion + len(migrations))
|
func ExpectedVersion() int64 {
|
||||||
if migrations[0].idNumber != minDBVersion {
|
return int64(minDBVersion + len(migrations))
|
||||||
panic("migrations should start at minDBVersion")
|
|
||||||
}
|
|
||||||
if dbVer != migrations[len(migrations)-1].idNumber+1 {
|
|
||||||
panic("migrations are not in order")
|
|
||||||
}
|
|
||||||
return dbVer
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExpectedDBVersion returns the expected db version
|
|
||||||
func ExpectedDBVersion() int64 {
|
|
||||||
return calcDBVersion(prepareMigrationTasks())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnsureUpToDate will check if the db is at the correct version
|
// EnsureUpToDate will check if the db is at the correct version
|
||||||
|
@ -407,35 +631,24 @@ func EnsureUpToDate(x *xorm.Engine) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if currentDB < 0 {
|
if currentDB < 0 {
|
||||||
return fmt.Errorf("database has not been initialized")
|
return fmt.Errorf("Database has not been initialized")
|
||||||
}
|
}
|
||||||
|
|
||||||
if minDBVersion > currentDB {
|
if minDBVersion > currentDB {
|
||||||
return fmt.Errorf("DB version %d (<= %d) is too old for auto-migration. Upgrade to Gitea 1.6.4 first then upgrade to this version", currentDB, minDBVersion)
|
return fmt.Errorf("DB version %d (<= %d) is too old for auto-migration. Upgrade to Gitea 1.6.4 first then upgrade to this version", currentDB, minDBVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedDB := ExpectedDBVersion()
|
expected := ExpectedVersion()
|
||||||
|
|
||||||
if currentDB != expectedDB {
|
if currentDB != expected {
|
||||||
return fmt.Errorf(`current database version %d is not equal to the expected version %d. Please run "forgejo [--config /path/to/app.ini] migrate" to update the database version`, currentDB, expectedDB)
|
return fmt.Errorf(`Current database version %d is not equal to the expected version %d. Please run "forgejo [--config /path/to/app.ini] migrate" to update the database version`, currentDB, expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
return forgejo_migrations.EnsureUpToDate(x)
|
return forgejo_migrations.EnsureUpToDate(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getPendingMigrations(curDBVer int64, migrations []*migration) []*migration {
|
|
||||||
return migrations[curDBVer-minDBVersion:]
|
|
||||||
}
|
|
||||||
|
|
||||||
func migrationIDNumberToDBVersion(idNumber int64) int64 {
|
|
||||||
return idNumber + 1
|
|
||||||
}
|
|
||||||
|
|
||||||
// Migrate database to current version
|
// Migrate database to current version
|
||||||
func Migrate(x *xorm.Engine) error {
|
func Migrate(x *xorm.Engine) error {
|
||||||
migrations := prepareMigrationTasks()
|
|
||||||
maxDBVer := calcDBVersion(migrations)
|
|
||||||
|
|
||||||
// Set a new clean the default mapper to GonicMapper as that is the default for Gitea.
|
// Set a new clean the default mapper to GonicMapper as that is the default for Gitea.
|
||||||
x.SetMapper(names.GonicMapper{})
|
x.SetMapper(names.GonicMapper{})
|
||||||
if err := x.Sync(new(Version)); err != nil {
|
if err := x.Sync(new(Version)); err != nil {
|
||||||
|
@ -448,10 +661,11 @@ func Migrate(x *xorm.Engine) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("get: %w", err)
|
return fmt.Errorf("get: %w", err)
|
||||||
} else if !has {
|
} else if !has {
|
||||||
// If the version record does not exist, it is a fresh installation, and we can skip all migrations.
|
// If the version record does not exist we think
|
||||||
// XORM model framework will create all tables when initializing.
|
// it is a fresh installation and we can skip all migrations.
|
||||||
currentVersion.ID = 0
|
currentVersion.ID = 0
|
||||||
currentVersion.Version = maxDBVer
|
currentVersion.Version = int64(minDBVersion + len(migrations))
|
||||||
|
|
||||||
if _, err = x.InsertOne(currentVersion); err != nil {
|
if _, err = x.InsertOne(currentVersion); err != nil {
|
||||||
return fmt.Errorf("insert: %w", err)
|
return fmt.Errorf("insert: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -459,20 +673,19 @@ func Migrate(x *xorm.Engine) error {
|
||||||
previousVersion = currentVersion.Version
|
previousVersion = currentVersion.Version
|
||||||
}
|
}
|
||||||
|
|
||||||
curDBVer := currentVersion.Version
|
v := currentVersion.Version
|
||||||
// Outdated Forgejo database version is not supported
|
if minDBVersion > v {
|
||||||
if curDBVer < minDBVersion {
|
|
||||||
log.Fatal(`Forgejo no longer supports auto-migration from your previously installed version.
|
log.Fatal(`Forgejo no longer supports auto-migration from your previously installed version.
|
||||||
Please try upgrading to a lower version first (suggested v1.6.4), then upgrade to this version.`)
|
Please try upgrading to a lower version first (suggested v1.6.4), then upgrade to this version.`)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Downgrading Forgejo's database version not supported
|
// Downgrading Forgejo database version is not supported
|
||||||
if maxDBVer < curDBVer {
|
if int(v-minDBVersion) > len(migrations) {
|
||||||
msg := fmt.Sprintf("Your database (migration version: %d) is for a newer Forgejo, you can not use the newer database for this old Forgejo release (%d).", curDBVer, maxDBVer)
|
msg := fmt.Sprintf("Your database (migration version: %d) is for a newer Forgejo, you can not use the newer database for this old Forgejo release (%d).", v, minDBVersion+len(migrations))
|
||||||
msg += "\nForgejo will exit to keep your database safe and unchanged. Please use the correct Forgejo release, do not change the migration version manually (incorrect manual operation may lose data)."
|
msg += "\nForgejo will exit to keep your database safe and unchanged. Please use the correct Forgejo release, do not change the migration version manually (incorrect manual operation may lose data)."
|
||||||
if !setting.IsProd {
|
if !setting.IsProd {
|
||||||
msg += fmt.Sprintf("\nIf you are in development and really know what you're doing, you can force changing the migration version by executing: UPDATE version SET version=%d WHERE id=1;", maxDBVer)
|
msg += fmt.Sprintf("\nIf you are in development and really know what you're doing, you can force changing the migration version by executing: UPDATE version SET version=%d WHERE id=1;", minDBVersion+len(migrations))
|
||||||
}
|
}
|
||||||
log.Fatal("Migration Error: %s", msg)
|
log.Fatal("Migration Error: %s", msg)
|
||||||
return nil
|
return nil
|
||||||
|
@ -490,14 +703,14 @@ Please try upgrading to a lower version first (suggested v1.6.4), then upgrade t
|
||||||
}
|
}
|
||||||
|
|
||||||
// Migrate
|
// Migrate
|
||||||
for _, m := range getPendingMigrations(curDBVer, migrations) {
|
for i, m := range migrations[v-minDBVersion:] {
|
||||||
log.Info("Migration[%d]: %s", m.idNumber, m.description)
|
log.Info("Migration[%d]: %s", v+int64(i), m.Description())
|
||||||
// Reset the mapper between each migration - migrations are not supposed to depend on each other
|
// Reset the mapper between each migration - migrations are not supposed to depend on each other
|
||||||
x.SetMapper(names.GonicMapper{})
|
x.SetMapper(names.GonicMapper{})
|
||||||
if err = m.Migrate(x); err != nil {
|
if err = m.Migrate(x); err != nil {
|
||||||
return fmt.Errorf("migration[%d]: %s failed: %w", m.idNumber, m.description, err)
|
return fmt.Errorf("migration[%d]: %s failed: %w", v+int64(i), m.Description(), err)
|
||||||
}
|
}
|
||||||
currentVersion.Version = migrationIDNumberToDBVersion(m.idNumber)
|
currentVersion.Version = v + int64(i) + 1
|
||||||
if _, err = x.ID(1).Update(currentVersion); err != nil {
|
if _, err = x.ID(1).Update(currentVersion); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
// Copyright 2024 The Gitea Authors. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
package migrations
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/test"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestMigrations(t *testing.T) {
|
|
||||||
defer test.MockVariableValue(&preparedMigrations, []*migration{
|
|
||||||
{idNumber: 70},
|
|
||||||
{idNumber: 71},
|
|
||||||
})()
|
|
||||||
assert.EqualValues(t, 72, calcDBVersion(preparedMigrations))
|
|
||||||
assert.EqualValues(t, 72, ExpectedDBVersion())
|
|
||||||
|
|
||||||
assert.EqualValues(t, 71, migrationIDNumberToDBVersion(70))
|
|
||||||
|
|
||||||
assert.EqualValues(t, []*migration{{idNumber: 70}, {idNumber: 71}}, getPendingMigrations(70, preparedMigrations))
|
|
||||||
assert.EqualValues(t, []*migration{{idNumber: 71}}, getPendingMigrations(71, preparedMigrations))
|
|
||||||
assert.EqualValues(t, []*migration{}, getPendingMigrations(72, preparedMigrations))
|
|
||||||
}
|
|
|
@ -11,7 +11,6 @@ import (
|
||||||
_ "code.gitea.io/gitea/models"
|
_ "code.gitea.io/gitea/models"
|
||||||
_ "code.gitea.io/gitea/models/actions"
|
_ "code.gitea.io/gitea/models/actions"
|
||||||
_ "code.gitea.io/gitea/models/activities"
|
_ "code.gitea.io/gitea/models/activities"
|
||||||
_ "code.gitea.io/gitea/models/forgefed"
|
|
||||||
_ "code.gitea.io/gitea/models/organization"
|
_ "code.gitea.io/gitea/models/organization"
|
||||||
_ "code.gitea.io/gitea/models/repo"
|
_ "code.gitea.io/gitea/models/repo"
|
||||||
_ "code.gitea.io/gitea/models/user"
|
_ "code.gitea.io/gitea/models/user"
|
||||||
|
|
|
@ -19,7 +19,6 @@ import (
|
||||||
_ "code.gitea.io/gitea/models"
|
_ "code.gitea.io/gitea/models"
|
||||||
_ "code.gitea.io/gitea/models/actions"
|
_ "code.gitea.io/gitea/models/actions"
|
||||||
_ "code.gitea.io/gitea/models/activities"
|
_ "code.gitea.io/gitea/models/activities"
|
||||||
_ "code.gitea.io/gitea/models/forgefed"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
|
@ -16,7 +16,6 @@ import (
|
||||||
_ "code.gitea.io/gitea/models"
|
_ "code.gitea.io/gitea/models"
|
||||||
_ "code.gitea.io/gitea/models/actions"
|
_ "code.gitea.io/gitea/models/actions"
|
||||||
_ "code.gitea.io/gitea/models/activities"
|
_ "code.gitea.io/gitea/models/activities"
|
||||||
_ "code.gitea.io/gitea/models/forgefed"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
|
@ -11,7 +11,6 @@ import (
|
||||||
_ "code.gitea.io/gitea/models"
|
_ "code.gitea.io/gitea/models"
|
||||||
_ "code.gitea.io/gitea/models/actions"
|
_ "code.gitea.io/gitea/models/actions"
|
||||||
_ "code.gitea.io/gitea/models/activities"
|
_ "code.gitea.io/gitea/models/activities"
|
||||||
_ "code.gitea.io/gitea/models/forgefed"
|
|
||||||
_ "code.gitea.io/gitea/models/repo"
|
_ "code.gitea.io/gitea/models/repo"
|
||||||
_ "code.gitea.io/gitea/models/user"
|
_ "code.gitea.io/gitea/models/user"
|
||||||
)
|
)
|
||||||
|
|
|
@ -5,6 +5,7 @@ package project
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
@ -123,5 +124,5 @@ func Test_NewColumn(t *testing.T) {
|
||||||
ProjectID: project1.ID,
|
ProjectID: project1.ID,
|
||||||
})
|
})
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
assert.Contains(t, err.Error(), "maximum number of columns reached")
|
assert.True(t, strings.Contains(err.Error(), "maximum number of columns reached"))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
-
|
|
||||||
id: 1001
|
|
||||||
owner_id: 33
|
|
||||||
owner_name: user33
|
|
||||||
lower_name: repo1001
|
|
||||||
name: repo1001
|
|
||||||
default_branch: main
|
|
||||||
num_watches: 0
|
|
||||||
num_stars: 0
|
|
||||||
num_forks: 0
|
|
||||||
num_issues: 0
|
|
||||||
num_closed_issues: 0
|
|
||||||
num_pulls: 0
|
|
||||||
num_closed_pulls: 0
|
|
||||||
num_milestones: 0
|
|
||||||
num_closed_milestones: 0
|
|
||||||
num_projects: 0
|
|
||||||
num_closed_projects: 0
|
|
||||||
is_private: false
|
|
||||||
is_empty: false
|
|
||||||
is_archived: false
|
|
||||||
is_mirror: false
|
|
||||||
status: 0
|
|
||||||
is_fork: false
|
|
||||||
fork_id: 0
|
|
||||||
is_template: false
|
|
||||||
template_id: 0
|
|
||||||
size: 0
|
|
||||||
is_fsck_enabled: true
|
|
||||||
close_issues_via_commit_in_any_branch: false
|
|
|
@ -7,7 +7,6 @@ import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/models/unit"
|
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
|
||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
|
@ -55,9 +54,9 @@ func GetUserFork(ctx context.Context, repoID, userID int64) (*Repository, error)
|
||||||
return &forkedRepo, nil
|
return &forkedRepo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetForks returns all the forks of the repository that are visible to the user.
|
// GetForks returns all the forks of the repository
|
||||||
func GetForks(ctx context.Context, repo *Repository, user *user_model.User, listOptions db.ListOptions) ([]*Repository, int64, error) {
|
func GetForks(ctx context.Context, repo *Repository, listOptions db.ListOptions) ([]*Repository, error) {
|
||||||
sess := db.GetEngine(ctx).Where(AccessibleRepositoryCondition(user, unit.TypeInvalid))
|
sess := db.GetEngine(ctx)
|
||||||
|
|
||||||
var forks []*Repository
|
var forks []*Repository
|
||||||
if listOptions.Page == 0 {
|
if listOptions.Page == 0 {
|
||||||
|
@ -67,8 +66,7 @@ func GetForks(ctx context.Context, repo *Repository, user *user_model.User, list
|
||||||
sess = db.SetSessionPagination(sess, &listOptions)
|
sess = db.SetSessionPagination(sess, &listOptions)
|
||||||
}
|
}
|
||||||
|
|
||||||
count, err := sess.FindAndCount(&forks, &Repository{ForkID: repo.ID})
|
return forks, sess.Find(&forks, &Repository{ForkID: repo.ID})
|
||||||
return forks, count, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IncrementRepoForkNum increment repository fork number
|
// IncrementRepoForkNum increment repository fork number
|
||||||
|
|
|
@ -11,7 +11,6 @@ import (
|
||||||
_ "code.gitea.io/gitea/models" // register table model
|
_ "code.gitea.io/gitea/models" // register table model
|
||||||
_ "code.gitea.io/gitea/models/actions"
|
_ "code.gitea.io/gitea/models/actions"
|
||||||
_ "code.gitea.io/gitea/models/activities"
|
_ "code.gitea.io/gitea/models/activities"
|
||||||
_ "code.gitea.io/gitea/models/forgefed"
|
|
||||||
_ "code.gitea.io/gitea/models/perm/access" // register table model
|
_ "code.gitea.io/gitea/models/perm/access" // register table model
|
||||||
_ "code.gitea.io/gitea/models/repo" // register table model
|
_ "code.gitea.io/gitea/models/repo" // register table model
|
||||||
_ "code.gitea.io/gitea/models/user" // register table model
|
_ "code.gitea.io/gitea/models/user" // register table model
|
||||||
|
|
|
@ -249,7 +249,6 @@ type FindReleasesOptions struct {
|
||||||
IsDraft optional.Option[bool]
|
IsDraft optional.Option[bool]
|
||||||
TagNames []string
|
TagNames []string
|
||||||
HasSha1 optional.Option[bool] // useful to find draft releases which are created with existing tags
|
HasSha1 optional.Option[bool] // useful to find draft releases which are created with existing tags
|
||||||
Keyword string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (opts FindReleasesOptions) ToConds() builder.Cond {
|
func (opts FindReleasesOptions) ToConds() builder.Cond {
|
||||||
|
@ -277,15 +276,6 @@ func (opts FindReleasesOptions) ToConds() builder.Cond {
|
||||||
cond = cond.And(builder.Eq{"sha1": ""})
|
cond = cond.And(builder.Eq{"sha1": ""})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.Keyword != "" {
|
|
||||||
keywordCond := builder.NewCond()
|
|
||||||
keywordCond = keywordCond.Or(builder.Like{"lower_tag_name", strings.ToLower(opts.Keyword)})
|
|
||||||
keywordCond = keywordCond.Or(db.BuildCaseInsensitiveLike("title", opts.Keyword))
|
|
||||||
keywordCond = keywordCond.Or(db.BuildCaseInsensitiveLike("note", opts.Keyword))
|
|
||||||
cond = cond.And(keywordCond)
|
|
||||||
}
|
|
||||||
|
|
||||||
return cond
|
return cond
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -641,9 +641,12 @@ func AccessibleRepositoryCondition(user *user_model.User, unitType unit.Type) bu
|
||||||
// 1. Be able to see all non-private repositories that either:
|
// 1. Be able to see all non-private repositories that either:
|
||||||
cond = cond.Or(builder.And(
|
cond = cond.Or(builder.And(
|
||||||
builder.Eq{"`repository`.is_private": false},
|
builder.Eq{"`repository`.is_private": false},
|
||||||
// 2. Aren't in an private organisation/user or limited organisation/user if the doer is not logged in.
|
// 2. Aren't in an private organisation or limited organisation if we're not logged in
|
||||||
builder.NotIn("`repository`.owner_id", builder.Select("id").From("`user`").Where(
|
builder.NotIn("`repository`.owner_id", builder.Select("id").From("`user`").Where(
|
||||||
builder.In("visibility", orgVisibilityLimit)))))
|
builder.And(
|
||||||
|
builder.Eq{"type": user_model.UserTypeOrganization},
|
||||||
|
builder.In("visibility", orgVisibilityLimit)),
|
||||||
|
))))
|
||||||
}
|
}
|
||||||
|
|
||||||
if user != nil {
|
if user != nil {
|
||||||
|
|
|
@ -4,18 +4,13 @@
|
||||||
package repo_test
|
package repo_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"path/filepath"
|
|
||||||
"slices"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
"code.gitea.io/gitea/models/user"
|
|
||||||
"code.gitea.io/gitea/modules/optional"
|
"code.gitea.io/gitea/modules/optional"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
|
||||||
"code.gitea.io/gitea/modules/structs"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
@ -408,43 +403,3 @@ func TestSearchRepositoryByTopicName(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSearchRepositoryIDsByCondition(t *testing.T) {
|
|
||||||
defer unittest.OverrideFixtures(
|
|
||||||
unittest.FixturesOptions{
|
|
||||||
Dir: filepath.Join(setting.AppWorkPath, "models/fixtures/"),
|
|
||||||
Base: setting.AppWorkPath,
|
|
||||||
Dirs: []string{"models/repo/TestSearchRepositoryIDsByCondition/"},
|
|
||||||
},
|
|
||||||
)()
|
|
||||||
require.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
// Sanity check of the database
|
|
||||||
limitedUser := unittest.AssertExistsAndLoadBean(t, &user.User{ID: 33, Visibility: structs.VisibleTypeLimited})
|
|
||||||
unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1001, OwnerID: limitedUser.ID})
|
|
||||||
|
|
||||||
testCases := []struct {
|
|
||||||
user *user.User
|
|
||||||
repoIDs []int64
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
user: nil,
|
|
||||||
repoIDs: []int64{1, 4, 8, 9, 10, 11, 12, 14, 17, 18, 21, 23, 25, 27, 29, 32, 33, 34, 35, 36, 37, 42, 44, 45, 46, 47, 48, 49, 50, 51, 53, 57, 58, 60, 61, 62, 1059},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
user: unittest.AssertExistsAndLoadBean(t, &user.User{ID: 4}),
|
|
||||||
repoIDs: []int64{1, 3, 4, 8, 9, 10, 11, 12, 14, 17, 18, 21, 23, 25, 27, 29, 32, 33, 34, 35, 36, 37, 38, 40, 42, 44, 45, 46, 47, 48, 49, 50, 51, 53, 57, 58, 60, 61, 62, 1001, 1059},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
user: unittest.AssertExistsAndLoadBean(t, &user.User{ID: 5}),
|
|
||||||
repoIDs: []int64{1, 4, 8, 9, 10, 11, 12, 14, 17, 18, 21, 23, 25, 27, 29, 32, 33, 34, 35, 36, 37, 38, 40, 42, 44, 45, 46, 47, 48, 49, 50, 51, 53, 57, 58, 60, 61, 62, 1001, 1059},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, testCase := range testCases {
|
|
||||||
repoIDs, err := repo_model.FindUserCodeAccessibleRepoIDs(db.DefaultContext, testCase.user)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
slices.Sort(repoIDs)
|
|
||||||
assert.EqualValues(t, testCase.repoIDs, repoIDs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -75,10 +75,6 @@ func GetRepoAssignees(ctx context.Context, repo *Repository) (_ []*user_model.Us
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
uniqueUserIDs := make(container.Set[int64])
|
|
||||||
uniqueUserIDs.AddMultiple(userIDs...)
|
|
||||||
|
|
||||||
if repo.Owner.IsOrganization() {
|
|
||||||
additionalUserIDs := make([]int64, 0, 10)
|
additionalUserIDs := make([]int64, 0, 10)
|
||||||
if err = e.Table("team_user").
|
if err = e.Table("team_user").
|
||||||
Join("INNER", "team_repo", "`team_repo`.team_id = `team_user`.team_id").
|
Join("INNER", "team_repo", "`team_repo`.team_id = `team_user`.team_id").
|
||||||
|
@ -90,13 +86,15 @@ func GetRepoAssignees(ctx context.Context, repo *Repository) (_ []*user_model.Us
|
||||||
Find(&additionalUserIDs); err != nil {
|
Find(&additionalUserIDs); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uniqueUserIDs := make(container.Set[int64])
|
||||||
|
uniqueUserIDs.AddMultiple(userIDs...)
|
||||||
uniqueUserIDs.AddMultiple(additionalUserIDs...)
|
uniqueUserIDs.AddMultiple(additionalUserIDs...)
|
||||||
}
|
|
||||||
|
|
||||||
// Leave a seat for owner itself to append later, but if owner is an organization
|
// Leave a seat for owner itself to append later, but if owner is an organization
|
||||||
// and just waste 1 unit is cheaper than re-allocate memory once.
|
// and just waste 1 unit is cheaper than re-allocate memory once.
|
||||||
users := make([]*user_model.User, 0, len(uniqueUserIDs)+1)
|
users := make([]*user_model.User, 0, len(uniqueUserIDs)+1)
|
||||||
if len(uniqueUserIDs) > 0 {
|
if len(userIDs) > 0 {
|
||||||
if err = e.In("id", uniqueUserIDs.Values()).
|
if err = e.In("id", uniqueUserIDs.Values()).
|
||||||
Where(builder.Eq{"`user`.is_active": true}).
|
Where(builder.Eq{"`user`.is_active": true}).
|
||||||
OrderBy(user_model.GetOrderByName()).
|
OrderBy(user_model.GetOrderByName()).
|
||||||
|
|
|
@ -11,7 +11,6 @@ import (
|
||||||
_ "code.gitea.io/gitea/models" // register models
|
_ "code.gitea.io/gitea/models" // register models
|
||||||
_ "code.gitea.io/gitea/models/actions"
|
_ "code.gitea.io/gitea/models/actions"
|
||||||
_ "code.gitea.io/gitea/models/activities"
|
_ "code.gitea.io/gitea/models/activities"
|
||||||
_ "code.gitea.io/gitea/models/forgefed"
|
|
||||||
_ "code.gitea.io/gitea/models/system" // register models of system
|
_ "code.gitea.io/gitea/models/system" // register models of system
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -4,12 +4,99 @@
|
||||||
package unittest
|
package unittest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Copy copies file from source to target path.
|
||||||
|
func Copy(src, dest string) error {
|
||||||
|
// Gather file information to set back later.
|
||||||
|
si, err := os.Lstat(src)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle symbolic link.
|
||||||
|
if si.Mode()&os.ModeSymlink != 0 {
|
||||||
|
target, err := os.Readlink(src)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// NOTE: os.Chmod and os.Chtimes don't recognize symbolic link,
|
||||||
|
// which will lead "no such file or directory" error.
|
||||||
|
return os.Symlink(target, dest)
|
||||||
|
}
|
||||||
|
|
||||||
|
sr, err := os.Open(src)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer sr.Close()
|
||||||
|
|
||||||
|
dw, err := os.Create(dest)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer dw.Close()
|
||||||
|
|
||||||
|
if _, err = io.Copy(dw, sr); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set back file information.
|
||||||
|
if err = os.Chtimes(dest, si.ModTime(), si.ModTime()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return os.Chmod(dest, si.Mode())
|
||||||
|
}
|
||||||
|
|
||||||
// CopyDir copy files recursively from source to target directory.
|
// CopyDir copy files recursively from source to target directory.
|
||||||
//
|
//
|
||||||
|
// The filter accepts a function that process the path info.
|
||||||
|
// and should return true for need to filter.
|
||||||
|
//
|
||||||
// It returns error when error occurs in underlying functions.
|
// It returns error when error occurs in underlying functions.
|
||||||
func CopyDir(srcPath, destPath string) error {
|
func CopyDir(srcPath, destPath string, filters ...func(filePath string) bool) error {
|
||||||
return os.CopyFS(destPath, os.DirFS(srcPath))
|
// Check if target directory exists.
|
||||||
|
if _, err := os.Stat(destPath); !errors.Is(err, os.ErrNotExist) {
|
||||||
|
return util.NewAlreadyExistErrorf("file or directory already exists: %s", destPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := os.MkdirAll(destPath, os.ModePerm)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gather directory info.
|
||||||
|
infos, err := util.StatDir(srcPath, true)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var filter func(filePath string) bool
|
||||||
|
if len(filters) > 0 {
|
||||||
|
filter = filters[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, info := range infos {
|
||||||
|
if filter != nil && filter(info) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
curPath := path.Join(destPath, info)
|
||||||
|
if strings.HasSuffix(info, "/") {
|
||||||
|
err = os.MkdirAll(curPath, os.ModePerm)
|
||||||
|
} else {
|
||||||
|
err = Copy(path.Join(srcPath, info), curPath)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,11 +33,6 @@ func NewMockWebServer(t *testing.T, liveServerBaseURL, testDataDir string, liveM
|
||||||
|
|
||||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
path := NormalizedFullPath(r.URL)
|
path := NormalizedFullPath(r.URL)
|
||||||
isGh := liveServerBaseURL == "https://api.github.com"
|
|
||||||
if isGh {
|
|
||||||
// Workaround for GitHub: trim `/api/v3` from the path
|
|
||||||
path = strings.TrimPrefix(path, "/api/v3")
|
|
||||||
}
|
|
||||||
log.Info("Mock HTTP Server: got request for path %s", r.URL.Path)
|
log.Info("Mock HTTP Server: got request for path %s", r.URL.Path)
|
||||||
// TODO check request method (support POST?)
|
// TODO check request method (support POST?)
|
||||||
fixturePath := fmt.Sprintf("%s/%s_%s", testDataDir, r.Method, url.PathEscape(path))
|
fixturePath := fmt.Sprintf("%s/%s_%s", testDataDir, r.Method, url.PathEscape(path))
|
||||||
|
@ -91,10 +86,6 @@ func NewMockWebServer(t *testing.T, liveServerBaseURL, testDataDir string, liveM
|
||||||
|
|
||||||
// replace any mention of the live HTTP service by the mocked host
|
// replace any mention of the live HTTP service by the mocked host
|
||||||
stringFixture := strings.ReplaceAll(string(fixture), liveServerBaseURL, mockServerBaseURL)
|
stringFixture := strings.ReplaceAll(string(fixture), liveServerBaseURL, mockServerBaseURL)
|
||||||
if isGh {
|
|
||||||
// Workaround for GitHub: replace github.com by the mock server's base URL
|
|
||||||
stringFixture = strings.ReplaceAll(stringFixture, "https://github.com", mockServerBaseURL)
|
|
||||||
}
|
|
||||||
// parse back the fixture file into a series of HTTP headers followed by response body
|
// parse back the fixture file into a series of HTTP headers followed by response body
|
||||||
lines := strings.Split(stringFixture, "\n")
|
lines := strings.Split(stringFixture, "\n")
|
||||||
for idx, line := range lines {
|
for idx, line := range lines {
|
||||||
|
|
|
@ -8,8 +8,10 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/modules/base"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/optional"
|
"code.gitea.io/gitea/modules/optional"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
@ -244,6 +246,23 @@ func updateActivation(ctx context.Context, email *EmailAddress, activate bool) e
|
||||||
return UpdateUserCols(ctx, user, "rands")
|
return UpdateUserCols(ctx, user, "rands")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VerifyActiveEmailCode verifies active email code when active account
|
||||||
|
func VerifyActiveEmailCode(ctx context.Context, code, email string) *EmailAddress {
|
||||||
|
if user := GetVerifyUser(ctx, code); user != nil {
|
||||||
|
// time limit code
|
||||||
|
prefix := code[:base.TimeLimitCodeLength]
|
||||||
|
data := fmt.Sprintf("%d%s%s%s%s", user.ID, email, user.LowerName, user.Passwd, user.Rands)
|
||||||
|
|
||||||
|
if base.VerifyTimeLimitCode(time.Now(), data, setting.Service.ActiveCodeLives, prefix) {
|
||||||
|
emailAddress := &EmailAddress{UID: user.ID, Email: email}
|
||||||
|
if has, _ := db.GetEngine(ctx).Get(emailAddress); has {
|
||||||
|
return emailAddress
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// SearchEmailOrderBy is used to sort the results from SearchEmails()
|
// SearchEmailOrderBy is used to sort the results from SearchEmails()
|
||||||
type SearchEmailOrderBy string
|
type SearchEmailOrderBy string
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,7 @@ package user
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/subtle"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/mail"
|
"net/mail"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
@ -320,14 +318,15 @@ func (u *User) OrganisationLink() string {
|
||||||
return setting.AppSubURL + "/org/" + url.PathEscape(u.Name)
|
return setting.AppSubURL + "/org/" + url.PathEscape(u.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateEmailAuthorizationCode generates an activation code based for the user for the specified purpose.
|
// GenerateEmailActivateCode generates an activate code based on user information and given e-mail.
|
||||||
// The standard expiry is ActiveCodeLives minutes.
|
func (u *User) GenerateEmailActivateCode(email string) string {
|
||||||
func (u *User) GenerateEmailAuthorizationCode(ctx context.Context, purpose auth.AuthorizationPurpose) (string, error) {
|
code := base.CreateTimeLimitCode(
|
||||||
lookup, validator, err := auth.GenerateAuthToken(ctx, u.ID, timeutil.TimeStampNow().Add(int64(setting.Service.ActiveCodeLives)*60), purpose)
|
fmt.Sprintf("%d%s%s%s%s", u.ID, email, u.LowerName, u.Passwd, u.Rands),
|
||||||
if err != nil {
|
setting.Service.ActiveCodeLives, time.Now(), nil)
|
||||||
return "", err
|
|
||||||
}
|
// Add tail hex username
|
||||||
return lookup + ":" + validator, nil
|
code += hex.EncodeToString([]byte(u.LowerName))
|
||||||
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUserFollowers returns range of user's followers.
|
// GetUserFollowers returns range of user's followers.
|
||||||
|
@ -839,50 +838,35 @@ func countUsers(ctx context.Context, opts *CountUserFilter) int64 {
|
||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
// VerifyUserActiveCode verifies that the code is valid for the given purpose for this user.
|
// GetVerifyUser get user by verify code
|
||||||
// If delete is specified, the token will be deleted.
|
func GetVerifyUser(ctx context.Context, code string) (user *User) {
|
||||||
func VerifyUserAuthorizationToken(ctx context.Context, code string, purpose auth.AuthorizationPurpose, delete bool) (*User, error) {
|
if len(code) <= base.TimeLimitCodeLength {
|
||||||
lookupKey, validator, found := strings.Cut(code, ":")
|
return nil
|
||||||
if !found {
|
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
authToken, err := auth.FindAuthToken(ctx, lookupKey, purpose)
|
// use tail hex username query user
|
||||||
if err != nil {
|
hexStr := code[base.TimeLimitCodeLength:]
|
||||||
if errors.Is(err, util.ErrNotExist) {
|
if b, err := hex.DecodeString(hexStr); err == nil {
|
||||||
return nil, nil
|
if user, err = GetUserByName(ctx, string(b)); user != nil {
|
||||||
|
return user
|
||||||
}
|
}
|
||||||
return nil, err
|
log.Error("user.getVerifyUser: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if authToken.IsExpired() {
|
return nil
|
||||||
return nil, auth.DeleteAuthToken(ctx, authToken)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rawValidator, err := hex.DecodeString(validator)
|
// VerifyUserActiveCode verifies active code when active account
|
||||||
if err != nil {
|
func VerifyUserActiveCode(ctx context.Context, code string) (user *User) {
|
||||||
return nil, err
|
if user = GetVerifyUser(ctx, code); user != nil {
|
||||||
}
|
// time limit code
|
||||||
|
prefix := code[:base.TimeLimitCodeLength]
|
||||||
if subtle.ConstantTimeCompare([]byte(authToken.HashedValidator), []byte(auth.HashValidator(rawValidator))) == 0 {
|
data := fmt.Sprintf("%d%s%s%s%s", user.ID, user.Email, user.LowerName, user.Passwd, user.Rands)
|
||||||
return nil, errors.New("validator doesn't match")
|
if base.VerifyTimeLimitCode(time.Now(), data, setting.Service.ActiveCodeLives, prefix) {
|
||||||
}
|
return user
|
||||||
|
|
||||||
u, err := GetUserByID(ctx, authToken.UID)
|
|
||||||
if err != nil {
|
|
||||||
if IsErrUserNotExist(err) {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if delete {
|
|
||||||
if err := auth.DeleteAuthToken(ctx, authToken); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
return u, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidateUser check if user is valid to insert / update into database
|
// ValidateUser check if user is valid to insert / update into database
|
||||||
|
|
|
@ -7,7 +7,6 @@ package user_test
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -22,9 +21,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/optional"
|
"code.gitea.io/gitea/modules/optional"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/structs"
|
"code.gitea.io/gitea/modules/structs"
|
||||||
"code.gitea.io/gitea/modules/test"
|
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
"code.gitea.io/gitea/modules/util"
|
|
||||||
"code.gitea.io/gitea/modules/validation"
|
"code.gitea.io/gitea/modules/validation"
|
||||||
"code.gitea.io/gitea/tests"
|
"code.gitea.io/gitea/tests"
|
||||||
|
|
||||||
|
@ -703,66 +700,3 @@ func TestDisabledUserFeatures(t *testing.T) {
|
||||||
assert.True(t, user_model.IsFeatureDisabledWithLoginType(user, f))
|
assert.True(t, user_model.IsFeatureDisabledWithLoginType(user, f))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGenerateEmailAuthorizationCode(t *testing.T) {
|
|
||||||
defer test.MockVariableValue(&setting.Service.ActiveCodeLives, 2)()
|
|
||||||
require.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
|
||||||
|
|
||||||
code, err := user.GenerateEmailAuthorizationCode(db.DefaultContext, auth.UserActivation)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
lookupKey, validator, ok := strings.Cut(code, ":")
|
|
||||||
assert.True(t, ok)
|
|
||||||
|
|
||||||
rawValidator, err := hex.DecodeString(validator)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
authToken, err := auth.FindAuthToken(db.DefaultContext, lookupKey, auth.UserActivation)
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.False(t, authToken.IsExpired())
|
|
||||||
assert.EqualValues(t, authToken.HashedValidator, auth.HashValidator(rawValidator))
|
|
||||||
|
|
||||||
authToken.Expiry = authToken.Expiry.Add(-int64(setting.Service.ActiveCodeLives) * 60)
|
|
||||||
assert.True(t, authToken.IsExpired())
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestVerifyUserAuthorizationToken(t *testing.T) {
|
|
||||||
defer test.MockVariableValue(&setting.Service.ActiveCodeLives, 2)()
|
|
||||||
require.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
|
||||||
|
|
||||||
code, err := user.GenerateEmailAuthorizationCode(db.DefaultContext, auth.UserActivation)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
lookupKey, _, ok := strings.Cut(code, ":")
|
|
||||||
assert.True(t, ok)
|
|
||||||
|
|
||||||
t.Run("Wrong purpose", func(t *testing.T) {
|
|
||||||
u, err := user_model.VerifyUserAuthorizationToken(db.DefaultContext, code, auth.PasswordReset, false)
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.Nil(t, u)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("No delete", func(t *testing.T) {
|
|
||||||
u, err := user_model.VerifyUserAuthorizationToken(db.DefaultContext, code, auth.UserActivation, false)
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.EqualValues(t, user.ID, u.ID)
|
|
||||||
|
|
||||||
authToken, err := auth.FindAuthToken(db.DefaultContext, lookupKey, auth.UserActivation)
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.NotNil(t, authToken)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("Delete", func(t *testing.T) {
|
|
||||||
u, err := user_model.VerifyUserAuthorizationToken(db.DefaultContext, code, auth.UserActivation, true)
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.EqualValues(t, user.ID, u.ID)
|
|
||||||
|
|
||||||
authToken, err := auth.FindAuthToken(db.DefaultContext, lookupKey, auth.UserActivation)
|
|
||||||
require.ErrorIs(t, err, util.ErrNotExist)
|
|
||||||
assert.Nil(t, authToken)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
|
"regexp"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -118,7 +119,7 @@ func TestActivityPubSignedPost(t *testing.T) {
|
||||||
|
|
||||||
expected := "BODY"
|
expected := "BODY"
|
||||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
assert.Regexp(t, "^"+setting.Federation.DigestAlgorithm, r.Header.Get("Digest"))
|
assert.Regexp(t, regexp.MustCompile("^"+setting.Federation.DigestAlgorithm), r.Header.Get("Digest"))
|
||||||
assert.Contains(t, r.Header.Get("Signature"), pubID)
|
assert.Contains(t, r.Header.Get("Signature"), pubID)
|
||||||
assert.Equal(t, ActivityStreamsContentType, r.Header.Get("Content-Type"))
|
assert.Equal(t, ActivityStreamsContentType, r.Header.Get("Content-Type"))
|
||||||
body, err := io.ReadAll(r.Body)
|
body, err := io.ReadAll(r.Body)
|
||||||
|
|
|
@ -11,7 +11,6 @@ import (
|
||||||
_ "code.gitea.io/gitea/models"
|
_ "code.gitea.io/gitea/models"
|
||||||
_ "code.gitea.io/gitea/models/actions"
|
_ "code.gitea.io/gitea/models/actions"
|
||||||
_ "code.gitea.io/gitea/models/activities"
|
_ "code.gitea.io/gitea/models/activities"
|
||||||
_ "code.gitea.io/gitea/models/forgefed"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
|
|
|
@ -4,20 +4,26 @@
|
||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/hmac"
|
||||||
|
"crypto/sha1"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
|
"crypto/subtle"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"hash"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
"github.com/dustin/go-humanize"
|
"github.com/dustin/go-humanize"
|
||||||
)
|
)
|
||||||
|
@ -48,6 +54,66 @@ func BasicAuthDecode(encoded string) (string, string, error) {
|
||||||
return "", "", errors.New("invalid basic authentication")
|
return "", "", errors.New("invalid basic authentication")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VerifyTimeLimitCode verify time limit code
|
||||||
|
func VerifyTimeLimitCode(now time.Time, data string, minutes int, code string) bool {
|
||||||
|
if len(code) <= 18 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
startTimeStr := code[:12]
|
||||||
|
aliveTimeStr := code[12:18]
|
||||||
|
aliveTime, _ := strconv.Atoi(aliveTimeStr) // no need to check err, if anything wrong, the following code check will fail soon
|
||||||
|
|
||||||
|
// check code
|
||||||
|
retCode := CreateTimeLimitCode(data, aliveTime, startTimeStr, nil)
|
||||||
|
if subtle.ConstantTimeCompare([]byte(retCode), []byte(code)) != 1 {
|
||||||
|
retCode = CreateTimeLimitCode(data, aliveTime, startTimeStr, sha1.New()) // TODO: this is only for the support of legacy codes, remove this in/after 1.23
|
||||||
|
if subtle.ConstantTimeCompare([]byte(retCode), []byte(code)) != 1 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check time is expired or not: startTime <= now && now < startTime + minutes
|
||||||
|
startTime, _ := time.ParseInLocation("200601021504", startTimeStr, time.Local)
|
||||||
|
return (startTime.Before(now) || startTime.Equal(now)) && now.Before(startTime.Add(time.Minute*time.Duration(minutes)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// TimeLimitCodeLength default value for time limit code
|
||||||
|
const TimeLimitCodeLength = 12 + 6 + 40
|
||||||
|
|
||||||
|
// CreateTimeLimitCode create a time-limited code.
|
||||||
|
// Format: 12 length date time string + 6 minutes string (not used) + 40 hash string, some other code depends on this fixed length
|
||||||
|
// If h is nil, then use the default hmac hash.
|
||||||
|
func CreateTimeLimitCode[T time.Time | string](data string, minutes int, startTimeGeneric T, h hash.Hash) string {
|
||||||
|
const format = "200601021504"
|
||||||
|
|
||||||
|
var start time.Time
|
||||||
|
var startTimeAny any = startTimeGeneric
|
||||||
|
if t, ok := startTimeAny.(time.Time); ok {
|
||||||
|
start = t
|
||||||
|
} else {
|
||||||
|
var err error
|
||||||
|
start, err = time.ParseInLocation(format, startTimeAny.(string), time.Local)
|
||||||
|
if err != nil {
|
||||||
|
return "" // return an invalid code because the "parse" failed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
startStr := start.Format(format)
|
||||||
|
end := start.Add(time.Minute * time.Duration(minutes))
|
||||||
|
|
||||||
|
if h == nil {
|
||||||
|
h = hmac.New(sha1.New, setting.GetGeneralTokenSigningSecret())
|
||||||
|
}
|
||||||
|
_, _ = fmt.Fprintf(h, "%s%s%s%s%d", data, hex.EncodeToString(setting.GetGeneralTokenSigningSecret()), startStr, end.Format(format), minutes)
|
||||||
|
encoded := hex.EncodeToString(h.Sum(nil))
|
||||||
|
|
||||||
|
code := fmt.Sprintf("%s%06d%s", startStr, minutes, encoded)
|
||||||
|
if len(code) != TimeLimitCodeLength {
|
||||||
|
panic("there is a hard requirement for the length of time-limited code") // it shouldn't happen
|
||||||
|
}
|
||||||
|
return code
|
||||||
|
}
|
||||||
|
|
||||||
// FileSize calculates the file size and generate user-friendly string.
|
// FileSize calculates the file size and generate user-friendly string.
|
||||||
func FileSize(s int64) string {
|
func FileSize(s int64) string {
|
||||||
return humanize.IBytes(uint64(s))
|
return humanize.IBytes(uint64(s))
|
||||||
|
|
|
@ -4,7 +4,13 @@
|
||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/sha1"
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
"code.gitea.io/gitea/modules/test"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
@ -40,6 +46,57 @@ func TestBasicAuthDecode(t *testing.T) {
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestVerifyTimeLimitCode(t *testing.T) {
|
||||||
|
defer test.MockVariableValue(&setting.InstallLock, true)()
|
||||||
|
initGeneralSecret := func(secret string) {
|
||||||
|
setting.InstallLock = true
|
||||||
|
setting.CfgProvider, _ = setting.NewConfigProviderFromData(fmt.Sprintf(`
|
||||||
|
[oauth2]
|
||||||
|
JWT_SECRET = %s
|
||||||
|
`, secret))
|
||||||
|
setting.LoadCommonSettings()
|
||||||
|
}
|
||||||
|
|
||||||
|
initGeneralSecret("KZb_QLUd4fYVyxetjxC4eZkrBgWM2SndOOWDNtgUUko")
|
||||||
|
now := time.Now()
|
||||||
|
|
||||||
|
t.Run("TestGenericParameter", func(t *testing.T) {
|
||||||
|
time2000 := time.Date(2000, 1, 2, 3, 4, 5, 0, time.Local)
|
||||||
|
assert.Equal(t, "2000010203040000026fa5221b2731b7cf80b1b506f5e39e38c115fee5", CreateTimeLimitCode("test-sha1", 2, time2000, sha1.New()))
|
||||||
|
assert.Equal(t, "2000010203040000026fa5221b2731b7cf80b1b506f5e39e38c115fee5", CreateTimeLimitCode("test-sha1", 2, "200001020304", sha1.New()))
|
||||||
|
assert.Equal(t, "2000010203040000024842227a2f87041ff82025199c0187410a9297bf", CreateTimeLimitCode("test-hmac", 2, time2000, nil))
|
||||||
|
assert.Equal(t, "2000010203040000024842227a2f87041ff82025199c0187410a9297bf", CreateTimeLimitCode("test-hmac", 2, "200001020304", nil))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("TestInvalidCode", func(t *testing.T) {
|
||||||
|
assert.False(t, VerifyTimeLimitCode(now, "data", 2, ""))
|
||||||
|
assert.False(t, VerifyTimeLimitCode(now, "data", 2, "invalid code"))
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("TestCreateAndVerify", func(t *testing.T) {
|
||||||
|
code := CreateTimeLimitCode("data", 2, now, nil)
|
||||||
|
assert.False(t, VerifyTimeLimitCode(now.Add(-time.Minute), "data", 2, code)) // not started yet
|
||||||
|
assert.True(t, VerifyTimeLimitCode(now, "data", 2, code))
|
||||||
|
assert.True(t, VerifyTimeLimitCode(now.Add(time.Minute), "data", 2, code))
|
||||||
|
assert.False(t, VerifyTimeLimitCode(now.Add(time.Minute), "DATA", 2, code)) // invalid data
|
||||||
|
assert.False(t, VerifyTimeLimitCode(now.Add(2*time.Minute), "data", 2, code)) // expired
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("TestDifferentSecret", func(t *testing.T) {
|
||||||
|
// use another secret to ensure the code is invalid for different secret
|
||||||
|
verifyDataCode := func(c string) bool {
|
||||||
|
return VerifyTimeLimitCode(now, "data", 2, c)
|
||||||
|
}
|
||||||
|
code1 := CreateTimeLimitCode("data", 2, now, sha1.New())
|
||||||
|
code2 := CreateTimeLimitCode("data", 2, now, nil)
|
||||||
|
assert.True(t, verifyDataCode(code1))
|
||||||
|
assert.True(t, verifyDataCode(code2))
|
||||||
|
initGeneralSecret("000_QLUd4fYVyxetjxC4eZkrBgWM2SndOOWDNtgUUko")
|
||||||
|
assert.False(t, verifyDataCode(code1))
|
||||||
|
assert.False(t, verifyDataCode(code2))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestFileSize(t *testing.T) {
|
func TestFileSize(t *testing.T) {
|
||||||
var size int64 = 512
|
var size int64 = 512
|
||||||
assert.Equal(t, "512 B", FileSize(size))
|
assert.Equal(t, "512 B", FileSize(size))
|
||||||
|
|
|
@ -41,12 +41,14 @@ func TestMaybeRemoveBOM(t *testing.T) {
|
||||||
|
|
||||||
func TestToUTF8(t *testing.T) {
|
func TestToUTF8(t *testing.T) {
|
||||||
resetDefaultCharsetsOrder()
|
resetDefaultCharsetsOrder()
|
||||||
|
var res string
|
||||||
|
var err error
|
||||||
|
|
||||||
// Note: golang compiler seems so behave differently depending on the current
|
// Note: golang compiler seems so behave differently depending on the current
|
||||||
// locale, so some conversions might behave differently. For that reason, we don't
|
// locale, so some conversions might behave differently. For that reason, we don't
|
||||||
// depend on particular conversions but in expected behaviors.
|
// depend on particular conversions but in expected behaviors.
|
||||||
|
|
||||||
res, err := ToUTF8([]byte{0x41, 0x42, 0x43}, ConvertOpts{})
|
res, err = ToUTF8([]byte{0x41, 0x42, 0x43}, ConvertOpts{})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, "ABC", res)
|
assert.Equal(t, "ABC", res)
|
||||||
|
|
||||||
|
|
|
@ -4,14 +4,28 @@
|
||||||
package git
|
package git
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ErrExecTimeout error when exec timed out
|
||||||
|
type ErrExecTimeout struct {
|
||||||
|
Duration time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsErrExecTimeout if some error is ErrExecTimeout
|
||||||
|
func IsErrExecTimeout(err error) bool {
|
||||||
|
_, ok := err.(ErrExecTimeout)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err ErrExecTimeout) Error() string {
|
||||||
|
return fmt.Sprintf("execution is timeout [duration: %v]", err.Duration)
|
||||||
|
}
|
||||||
|
|
||||||
// ErrNotExist commit not exist error
|
// ErrNotExist commit not exist error
|
||||||
type ErrNotExist struct {
|
type ErrNotExist struct {
|
||||||
ID string
|
ID string
|
||||||
|
@ -48,6 +62,21 @@ func IsErrBadLink(err error) bool {
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ErrUnsupportedVersion error when required git version not matched
|
||||||
|
type ErrUnsupportedVersion struct {
|
||||||
|
Required string
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsErrUnsupportedVersion if some error is ErrUnsupportedVersion
|
||||||
|
func IsErrUnsupportedVersion(err error) bool {
|
||||||
|
_, ok := err.(ErrUnsupportedVersion)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err ErrUnsupportedVersion) Error() string {
|
||||||
|
return fmt.Sprintf("Operation requires higher version [required: %s]", err.Required)
|
||||||
|
}
|
||||||
|
|
||||||
// ErrBranchNotExist represents a "BranchNotExist" kind of error.
|
// ErrBranchNotExist represents a "BranchNotExist" kind of error.
|
||||||
type ErrBranchNotExist struct {
|
type ErrBranchNotExist struct {
|
||||||
Name string
|
Name string
|
||||||
|
@ -156,10 +185,3 @@ func IsErrMoreThanOne(err error) bool {
|
||||||
func (err *ErrMoreThanOne) Error() string {
|
func (err *ErrMoreThanOne) Error() string {
|
||||||
return fmt.Sprintf("ErrMoreThanOne Error: %v: %s\n%s", err.Err, err.StdErr, err.StdOut)
|
return fmt.Sprintf("ErrMoreThanOne Error: %v: %s\n%s", err.Err, err.StdErr, err.StdOut)
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsErrCanceledOrKilled(err error) bool {
|
|
||||||
// When "cancel()" a git command's context, the returned error of "Run()" could be one of them:
|
|
||||||
// - context.Canceled
|
|
||||||
// - *exec.ExitError: "signal: killed"
|
|
||||||
return err != nil && (errors.Is(err, context.Canceled) || err.Error() == "signal: killed")
|
|
||||||
}
|
|
||||||
|
|
|
@ -17,7 +17,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/log"
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -39,7 +38,7 @@ const (
|
||||||
type GrepOptions struct {
|
type GrepOptions struct {
|
||||||
RefName string
|
RefName string
|
||||||
MaxResultLimit int
|
MaxResultLimit int
|
||||||
MatchesPerFile int // >= git 2.38
|
MatchesPerFile int
|
||||||
ContextLineNumber int
|
ContextLineNumber int
|
||||||
Mode grepMode
|
Mode grepMode
|
||||||
PathSpec []setting.Glob
|
PathSpec []setting.Glob
|
||||||
|
@ -93,16 +92,8 @@ func GrepSearch(ctx context.Context, repo *Repository, search string, opts GrepO
|
||||||
} else {
|
} else {
|
||||||
cmd.AddArguments("--fixed-strings", "--column")
|
cmd.AddArguments("--fixed-strings", "--column")
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.AddOptionValues("--context", fmt.Sprint(opts.ContextLineNumber))
|
cmd.AddOptionValues("--context", fmt.Sprint(opts.ContextLineNumber))
|
||||||
|
|
||||||
// --max-count requires at least git 2.38
|
|
||||||
if CheckGitVersionAtLeast("2.38.0") == nil {
|
|
||||||
cmd.AddOptionValues("--max-count", fmt.Sprint(opts.MatchesPerFile))
|
cmd.AddOptionValues("--max-count", fmt.Sprint(opts.MatchesPerFile))
|
||||||
} else {
|
|
||||||
log.Warn("git-grep: --max-count requires at least git 2.38")
|
|
||||||
}
|
|
||||||
|
|
||||||
words := []string{search}
|
words := []string{search}
|
||||||
if opts.Mode == FixedAnyGrepMode {
|
if opts.Mode == FixedAnyGrepMode {
|
||||||
words = strings.Fields(search)
|
words = strings.Fields(search)
|
||||||
|
|
|
@ -250,7 +250,7 @@ func (repo *Repository) GitAttributeChecker(treeish string, attributes ...string
|
||||||
err = e
|
err = e
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil && !IsErrCanceledOrKilled(err) { // decorate the returned error
|
if err != nil { // decorate the returned error
|
||||||
err = fmt.Errorf("git check-attr (stderr: %q): %w", strings.TrimSpace(stdErr.String()), err)
|
err = fmt.Errorf("git check-attr (stderr: %q): %w", strings.TrimSpace(stdErr.String()), err)
|
||||||
ac.err.Store(err)
|
ac.err.Store(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,35 +50,25 @@ func (repo *Repository) readTreeToIndex(id ObjectID, indexFilename ...string) er
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadTreeToTemporaryIndex reads a treeish to a temporary index file
|
// ReadTreeToTemporaryIndex reads a treeish to a temporary index file
|
||||||
func (repo *Repository) ReadTreeToTemporaryIndex(treeish string) (tmpIndexFilename, tmpDir string, cancel context.CancelFunc, err error) {
|
func (repo *Repository) ReadTreeToTemporaryIndex(treeish string) (filename, tmpDir string, cancel context.CancelFunc, err error) {
|
||||||
defer func() {
|
|
||||||
// if error happens and there is a cancel function, do clean up
|
|
||||||
if err != nil && cancel != nil {
|
|
||||||
cancel()
|
|
||||||
cancel = nil
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
removeDirFn := func(dir string) func() { // it can't use the return value "tmpDir" directly because it is empty when error occurs
|
|
||||||
return func() {
|
|
||||||
if err := util.RemoveAll(dir); err != nil {
|
|
||||||
log.Error("failed to remove tmp index dir: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpDir, err = os.MkdirTemp("", "index")
|
tmpDir, err = os.MkdirTemp("", "index")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", nil, err
|
return filename, tmpDir, cancel, err
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpIndexFilename = filepath.Join(tmpDir, ".tmp-index")
|
filename = filepath.Join(tmpDir, ".tmp-index")
|
||||||
cancel = removeDirFn(tmpDir)
|
cancel = func() {
|
||||||
err = repo.ReadTreeToIndex(treeish, tmpIndexFilename)
|
err := util.RemoveAll(tmpDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", cancel, err
|
log.Error("failed to remove tmp index file: %v", err)
|
||||||
}
|
}
|
||||||
return tmpIndexFilename, tmpDir, cancel, err
|
}
|
||||||
|
err = repo.ReadTreeToIndex(treeish, filename)
|
||||||
|
if err != nil {
|
||||||
|
defer cancel()
|
||||||
|
return "", "", func() {}, err
|
||||||
|
}
|
||||||
|
return filename, tmpDir, cancel, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// EmptyIndex empties the index
|
// EmptyIndex empties the index
|
||||||
|
|
|
@ -16,7 +16,7 @@ import (
|
||||||
|
|
||||||
// GetCommitGraph return a list of commit (GraphItems) from all branches
|
// GetCommitGraph return a list of commit (GraphItems) from all branches
|
||||||
func GetCommitGraph(r *git.Repository, page, maxAllowedColors int, hidePRRefs bool, branches, files []string) (*Graph, error) {
|
func GetCommitGraph(r *git.Repository, page, maxAllowedColors int, hidePRRefs bool, branches, files []string) (*Graph, error) {
|
||||||
format := "DATA:%D|%H|%aD|%h|%s"
|
format := "DATA:%D|%H|%ad|%h|%s"
|
||||||
|
|
||||||
if page == 0 {
|
if page == 0 {
|
||||||
page = 1
|
page = 1
|
||||||
|
|
|
@ -8,7 +8,6 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
asymkey_model "code.gitea.io/gitea/models/asymkey"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
@ -199,11 +198,6 @@ func NewCommit(row, column int, line []byte) (*Commit, error) {
|
||||||
if len(data) < 5 {
|
if len(data) < 5 {
|
||||||
return nil, fmt.Errorf("malformed data section on line %d with commit: %s", row, string(line))
|
return nil, fmt.Errorf("malformed data section on line %d with commit: %s", row, string(line))
|
||||||
}
|
}
|
||||||
// Format is a slight modifcation from RFC1123Z
|
|
||||||
t, err := time.Parse("Mon, _2 Jan 2006 15:04:05 -0700", string(data[2]))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("could not parse date of commit: %w", err)
|
|
||||||
}
|
|
||||||
return &Commit{
|
return &Commit{
|
||||||
Row: row,
|
Row: row,
|
||||||
Column: column,
|
Column: column,
|
||||||
|
@ -211,8 +205,8 @@ func NewCommit(row, column int, line []byte) (*Commit, error) {
|
||||||
Refs: newRefsFromRefNames(data[0]),
|
Refs: newRefsFromRefNames(data[0]),
|
||||||
// 1 matches git log --pretty=format:%H => commit hash
|
// 1 matches git log --pretty=format:%H => commit hash
|
||||||
Rev: string(data[1]),
|
Rev: string(data[1]),
|
||||||
// 2 matches git log --pretty=format:%aD => author date, RFC2822 style
|
// 2 matches git log --pretty=format:%ad => author date (format respects --date= option)
|
||||||
Date: t,
|
Date: string(data[2]),
|
||||||
// 3 matches git log --pretty=format:%h => abbreviated commit hash
|
// 3 matches git log --pretty=format:%h => abbreviated commit hash
|
||||||
ShortRev: string(data[3]),
|
ShortRev: string(data[3]),
|
||||||
// 4 matches git log --pretty=format:%s => subject
|
// 4 matches git log --pretty=format:%s => subject
|
||||||
|
@ -251,7 +245,7 @@ type Commit struct {
|
||||||
Column int
|
Column int
|
||||||
Refs []git.Reference
|
Refs []git.Reference
|
||||||
Rev string
|
Rev string
|
||||||
Date time.Time
|
Date string
|
||||||
ShortRev string
|
ShortRev string
|
||||||
Subject string
|
Subject string
|
||||||
}
|
}
|
||||||
|
|
|
@ -241,7 +241,7 @@ func TestParseGlyphs(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCommitStringParsing(t *testing.T) {
|
func TestCommitStringParsing(t *testing.T) {
|
||||||
dataFirstPart := "* DATA:|4e61bacab44e9b4730e44a6615d04098dd3a8eaf|Tue, 20 Dec 2016 21:10:41 +0100|4e61bac|"
|
dataFirstPart := "* DATA:|4e61bacab44e9b4730e44a6615d04098dd3a8eaf|2016-12-20 21:10:41 +0100|4e61bac|"
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
shouldPass bool
|
shouldPass bool
|
||||||
testName string
|
testName string
|
||||||
|
|
|
@ -18,7 +18,6 @@ import (
|
||||||
_ "code.gitea.io/gitea/models"
|
_ "code.gitea.io/gitea/models"
|
||||||
_ "code.gitea.io/gitea/models/actions"
|
_ "code.gitea.io/gitea/models/actions"
|
||||||
_ "code.gitea.io/gitea/models/activities"
|
_ "code.gitea.io/gitea/models/activities"
|
||||||
_ "code.gitea.io/gitea/models/forgefed"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
|
@ -19,15 +19,6 @@ func NumericEqualityQuery(value int64, field string) *query.NumericRangeQuery {
|
||||||
return q
|
return q
|
||||||
}
|
}
|
||||||
|
|
||||||
// MatchQuery generates a match query for the given phrase, field and analyzer
|
|
||||||
func MatchQuery(matchTerm, field, analyzer string, fuzziness int) *query.MatchQuery {
|
|
||||||
q := bleve.NewMatchQuery(matchTerm)
|
|
||||||
q.FieldVal = field
|
|
||||||
q.Analyzer = analyzer
|
|
||||||
q.Fuzziness = fuzziness
|
|
||||||
return q
|
|
||||||
}
|
|
||||||
|
|
||||||
// MatchPhraseQuery generates a match phrase query for the given phrase, field and analyzer
|
// MatchPhraseQuery generates a match phrase query for the given phrase, field and analyzer
|
||||||
func MatchPhraseQuery(matchPhrase, field, analyzer string, fuzziness int) *query.MatchPhraseQuery {
|
func MatchPhraseQuery(matchPhrase, field, analyzer string, fuzziness int) *query.MatchPhraseQuery {
|
||||||
q := bleve.NewMatchPhraseQuery(matchPhrase)
|
q := bleve.NewMatchPhraseQuery(matchPhrase)
|
||||||
|
|
|
@ -35,7 +35,13 @@ func addUnicodeNormalizeTokenFilter(m *mapping.IndexMappingImpl) error {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const maxBatchSize = 16
|
const (
|
||||||
|
maxBatchSize = 16
|
||||||
|
// fuzzyDenominator determines the levenshtein distance per each character of a keyword
|
||||||
|
fuzzyDenominator = 4
|
||||||
|
// see https://github.com/blevesearch/bleve/issues/1563#issuecomment-786822311
|
||||||
|
maxFuzziness = 2
|
||||||
|
)
|
||||||
|
|
||||||
// IndexerData an update to the issue indexer
|
// IndexerData an update to the issue indexer
|
||||||
type IndexerData internal.IndexerData
|
type IndexerData internal.IndexerData
|
||||||
|
@ -156,25 +162,16 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
|
||||||
var queries []query.Query
|
var queries []query.Query
|
||||||
|
|
||||||
if options.Keyword != "" {
|
if options.Keyword != "" {
|
||||||
|
fuzziness := 0
|
||||||
if options.IsFuzzyKeyword {
|
if options.IsFuzzyKeyword {
|
||||||
fuzziness := 1
|
fuzziness = min(maxFuzziness, len(options.Keyword)/fuzzyDenominator)
|
||||||
if kl := len(options.Keyword); kl > 3 {
|
|
||||||
fuzziness = 2
|
|
||||||
} else if kl < 2 {
|
|
||||||
fuzziness = 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
queries = append(queries, bleve.NewDisjunctionQuery([]query.Query{
|
queries = append(queries, bleve.NewDisjunctionQuery([]query.Query{
|
||||||
inner_bleve.MatchQuery(options.Keyword, "title", issueIndexerAnalyzer, fuzziness),
|
inner_bleve.MatchPhraseQuery(options.Keyword, "title", issueIndexerAnalyzer, fuzziness),
|
||||||
inner_bleve.MatchQuery(options.Keyword, "content", issueIndexerAnalyzer, fuzziness),
|
inner_bleve.MatchPhraseQuery(options.Keyword, "content", issueIndexerAnalyzer, fuzziness),
|
||||||
inner_bleve.MatchQuery(options.Keyword, "comments", issueIndexerAnalyzer, fuzziness),
|
inner_bleve.MatchPhraseQuery(options.Keyword, "comments", issueIndexerAnalyzer, fuzziness),
|
||||||
}...))
|
}...))
|
||||||
} else {
|
|
||||||
queries = append(queries, bleve.NewDisjunctionQuery([]query.Query{
|
|
||||||
inner_bleve.MatchPhraseQuery(options.Keyword, "title", issueIndexerAnalyzer, 0),
|
|
||||||
inner_bleve.MatchPhraseQuery(options.Keyword, "content", issueIndexerAnalyzer, 0),
|
|
||||||
inner_bleve.MatchPhraseQuery(options.Keyword, "comments", issueIndexerAnalyzer, 0),
|
|
||||||
}...))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(options.RepoIDs) > 0 || options.AllPublic {
|
if len(options.RepoIDs) > 0 || options.AllPublic {
|
||||||
|
|
|
@ -78,9 +78,7 @@ func ToSearchOptions(keyword string, opts *issues_model.IssuesOptions) *SearchOp
|
||||||
searchOpt.Paginator = opts.Paginator
|
searchOpt.Paginator = opts.Paginator
|
||||||
|
|
||||||
switch opts.SortType {
|
switch opts.SortType {
|
||||||
case "", "relevance":
|
case "", "latest":
|
||||||
searchOpt.SortBy = SortByScore
|
|
||||||
case "latest":
|
|
||||||
searchOpt.SortBy = SortByCreatedDesc
|
searchOpt.SortBy = SortByCreatedDesc
|
||||||
case "oldest":
|
case "oldest":
|
||||||
searchOpt.SortBy = SortByCreatedAsc
|
searchOpt.SortBy = SortByCreatedAsc
|
||||||
|
|
|
@ -236,7 +236,7 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.SortBy == "" {
|
if options.SortBy == "" {
|
||||||
options.SortBy = internal.SortByScore
|
options.SortBy = internal.SortByCreatedAsc
|
||||||
}
|
}
|
||||||
sortBy := []elastic.Sorter{
|
sortBy := []elastic.Sorter{
|
||||||
parseSortBy(options.SortBy),
|
parseSortBy(options.SortBy),
|
||||||
|
|
|
@ -269,7 +269,6 @@ func IsAvailable(ctx context.Context) bool {
|
||||||
type SearchOptions = internal.SearchOptions
|
type SearchOptions = internal.SearchOptions
|
||||||
|
|
||||||
const (
|
const (
|
||||||
SortByScore = internal.SortByScore
|
|
||||||
SortByCreatedDesc = internal.SortByCreatedDesc
|
SortByCreatedDesc = internal.SortByCreatedDesc
|
||||||
SortByUpdatedDesc = internal.SortByUpdatedDesc
|
SortByUpdatedDesc = internal.SortByUpdatedDesc
|
||||||
SortByCommentsDesc = internal.SortByCommentsDesc
|
SortByCommentsDesc = internal.SortByCommentsDesc
|
||||||
|
|
|
@ -17,7 +17,6 @@ import (
|
||||||
_ "code.gitea.io/gitea/models"
|
_ "code.gitea.io/gitea/models"
|
||||||
_ "code.gitea.io/gitea/models/actions"
|
_ "code.gitea.io/gitea/models/actions"
|
||||||
_ "code.gitea.io/gitea/models/activities"
|
_ "code.gitea.io/gitea/models/activities"
|
||||||
_ "code.gitea.io/gitea/models/forgefed"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
|
@ -127,7 +127,6 @@ func (o *SearchOptions) Copy(edit ...func(options *SearchOptions)) *SearchOption
|
||||||
type SortBy string
|
type SortBy string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
SortByScore SortBy = "-_score"
|
|
||||||
SortByCreatedDesc SortBy = "-created_unix"
|
SortByCreatedDesc SortBy = "-created_unix"
|
||||||
SortByUpdatedDesc SortBy = "-updated_unix"
|
SortByUpdatedDesc SortBy = "-updated_unix"
|
||||||
SortByCommentsDesc SortBy = "-comment_count"
|
SortByCommentsDesc SortBy = "-comment_count"
|
||||||
|
|
|
@ -126,7 +126,6 @@ var cases = []*testIndexerCase{
|
||||||
},
|
},
|
||||||
SearchOptions: &internal.SearchOptions{
|
SearchOptions: &internal.SearchOptions{
|
||||||
Keyword: "hello",
|
Keyword: "hello",
|
||||||
SortBy: internal.SortByCreatedDesc,
|
|
||||||
},
|
},
|
||||||
ExpectedIDs: []int64{1002, 1001, 1000},
|
ExpectedIDs: []int64{1002, 1001, 1000},
|
||||||
ExpectedTotal: 3,
|
ExpectedTotal: 3,
|
||||||
|
@ -140,7 +139,6 @@ var cases = []*testIndexerCase{
|
||||||
},
|
},
|
||||||
SearchOptions: &internal.SearchOptions{
|
SearchOptions: &internal.SearchOptions{
|
||||||
Keyword: "hello world",
|
Keyword: "hello world",
|
||||||
SortBy: internal.SortByCreatedDesc,
|
|
||||||
IsFuzzyKeyword: true,
|
IsFuzzyKeyword: true,
|
||||||
},
|
},
|
||||||
ExpectedIDs: []int64{1002, 1001, 1000},
|
ExpectedIDs: []int64{1002, 1001, 1000},
|
||||||
|
@ -159,7 +157,6 @@ var cases = []*testIndexerCase{
|
||||||
},
|
},
|
||||||
SearchOptions: &internal.SearchOptions{
|
SearchOptions: &internal.SearchOptions{
|
||||||
Keyword: "hello",
|
Keyword: "hello",
|
||||||
SortBy: internal.SortByCreatedDesc,
|
|
||||||
RepoIDs: []int64{1, 4},
|
RepoIDs: []int64{1, 4},
|
||||||
},
|
},
|
||||||
ExpectedIDs: []int64{1006, 1002, 1001},
|
ExpectedIDs: []int64{1006, 1002, 1001},
|
||||||
|
@ -178,7 +175,6 @@ var cases = []*testIndexerCase{
|
||||||
},
|
},
|
||||||
SearchOptions: &internal.SearchOptions{
|
SearchOptions: &internal.SearchOptions{
|
||||||
Keyword: "hello",
|
Keyword: "hello",
|
||||||
SortBy: internal.SortByCreatedDesc,
|
|
||||||
RepoIDs: []int64{1, 4},
|
RepoIDs: []int64{1, 4},
|
||||||
AllPublic: true,
|
AllPublic: true,
|
||||||
},
|
},
|
||||||
|
@ -601,22 +597,6 @@ var cases = []*testIndexerCase{
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
Name: "SortByScore",
|
|
||||||
SearchOptions: &internal.SearchOptions{
|
|
||||||
Paginator: &db.ListOptionsAll,
|
|
||||||
SortBy: internal.SortByScore,
|
|
||||||
},
|
|
||||||
Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) {
|
|
||||||
assert.Equal(t, len(data), len(result.Hits))
|
|
||||||
assert.Equal(t, len(data), int(result.Total))
|
|
||||||
for i, v := range result.Hits {
|
|
||||||
if i < len(result.Hits)-1 {
|
|
||||||
assert.GreaterOrEqual(t, v.Score, result.Hits[i+1].Score)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
Name: "SortByCreatedAsc",
|
Name: "SortByCreatedAsc",
|
||||||
SearchOptions: &internal.SearchOptions{
|
SearchOptions: &internal.SearchOptions{
|
||||||
|
|
|
@ -208,19 +208,13 @@ func (b *Indexer) Search(ctx context.Context, options *internal.SearchOptions) (
|
||||||
query.And(inner_meilisearch.NewFilterLte("updated_unix", options.UpdatedBeforeUnix.Value()))
|
query.And(inner_meilisearch.NewFilterLte("updated_unix", options.UpdatedBeforeUnix.Value()))
|
||||||
}
|
}
|
||||||
|
|
||||||
var sortBy []string
|
if options.SortBy == "" {
|
||||||
switch options.SortBy {
|
options.SortBy = internal.SortByCreatedAsc
|
||||||
// sort by relevancy (no explicit sorting)
|
}
|
||||||
case internal.SortByScore:
|
sortBy := []string{
|
||||||
fallthrough
|
|
||||||
case "":
|
|
||||||
sortBy = []string{}
|
|
||||||
default:
|
|
||||||
sortBy = []string{
|
|
||||||
parseSortBy(options.SortBy),
|
parseSortBy(options.SortBy),
|
||||||
"id:desc",
|
"id:desc",
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
skip, limit := indexer_internal.ParsePaginator(options.Paginator, maxTotalHits)
|
skip, limit := indexer_internal.ParsePaginator(options.Paginator, maxTotalHits)
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,6 @@ import (
|
||||||
_ "code.gitea.io/gitea/models"
|
_ "code.gitea.io/gitea/models"
|
||||||
_ "code.gitea.io/gitea/models/actions"
|
_ "code.gitea.io/gitea/models/actions"
|
||||||
_ "code.gitea.io/gitea/models/activities"
|
_ "code.gitea.io/gitea/models/activities"
|
||||||
_ "code.gitea.io/gitea/models/forgefed"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
|
@ -13,7 +13,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/container"
|
"code.gitea.io/gitea/modules/container"
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
|
|
||||||
"code.forgejo.org/go-chi/binding"
|
"gitea.com/go-chi/binding"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Validate checks whether an IssueTemplate is considered valid, and returns the first error
|
// Validate checks whether an IssueTemplate is considered valid, and returns the first error
|
||||||
|
|
|
@ -16,9 +16,10 @@ import (
|
||||||
"code.gitea.io/gitea/modules/json"
|
"code.gitea.io/gitea/modules/json"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/proxy"
|
"code.gitea.io/gitea/modules/proxy"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const httpBatchSize = 20
|
||||||
|
|
||||||
// HTTPClient is used to communicate with the LFS server
|
// HTTPClient is used to communicate with the LFS server
|
||||||
// https://github.com/git-lfs/git-lfs/blob/main/docs/api/batch.md
|
// https://github.com/git-lfs/git-lfs/blob/main/docs/api/batch.md
|
||||||
type HTTPClient struct {
|
type HTTPClient struct {
|
||||||
|
@ -29,7 +30,7 @@ type HTTPClient struct {
|
||||||
|
|
||||||
// BatchSize returns the preferred size of batchs to process
|
// BatchSize returns the preferred size of batchs to process
|
||||||
func (c *HTTPClient) BatchSize() int {
|
func (c *HTTPClient) BatchSize() int {
|
||||||
return setting.LFSClient.BatchSize
|
return httpBatchSize
|
||||||
}
|
}
|
||||||
|
|
||||||
func newHTTPClient(endpoint *url.URL, httpTransport *http.Transport) *HTTPClient {
|
func newHTTPClient(endpoint *url.URL, httpTransport *http.Transport) *HTTPClient {
|
||||||
|
|
|
@ -267,7 +267,7 @@ func TestHTTPClientDownload(t *testing.T) {
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if len(c.expectederror) > 0 {
|
if len(c.expectederror) > 0 {
|
||||||
assert.Contains(t, err.Error(), c.expectederror, "case %d: '%s' should contain '%s'", n, err.Error(), c.expectederror)
|
assert.True(t, strings.Contains(err.Error(), c.expectederror), "case %d: '%s' should contain '%s'", n, err.Error(), c.expectederror)
|
||||||
} else {
|
} else {
|
||||||
require.NoError(t, err, "case %d", n)
|
require.NoError(t, err, "case %d", n)
|
||||||
}
|
}
|
||||||
|
@ -369,7 +369,7 @@ func TestHTTPClientUpload(t *testing.T) {
|
||||||
return io.NopCloser(new(bytes.Buffer)), objectError
|
return io.NopCloser(new(bytes.Buffer)), objectError
|
||||||
})
|
})
|
||||||
if len(c.expectederror) > 0 {
|
if len(c.expectederror) > 0 {
|
||||||
assert.Contains(t, err.Error(), c.expectederror, "case %d: '%s' should contain '%s'", n, err.Error(), c.expectederror)
|
assert.True(t, strings.Contains(err.Error(), c.expectederror), "case %d: '%s' should contain '%s'", n, err.Error(), c.expectederror)
|
||||||
} else {
|
} else {
|
||||||
require.NoError(t, err, "case %d", n)
|
require.NoError(t, err, "case %d", n)
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,7 @@ func TestBasicTransferAdapter(t *testing.T) {
|
||||||
for n, c := range cases {
|
for n, c := range cases {
|
||||||
_, err := a.Download(context.Background(), c.link)
|
_, err := a.Download(context.Background(), c.link)
|
||||||
if len(c.expectederror) > 0 {
|
if len(c.expectederror) > 0 {
|
||||||
assert.Contains(t, err.Error(), c.expectederror, "case %d: '%s' should contain '%s'", n, err.Error(), c.expectederror)
|
assert.True(t, strings.Contains(err.Error(), c.expectederror), "case %d: '%s' should contain '%s'", n, err.Error(), c.expectederror)
|
||||||
} else {
|
} else {
|
||||||
require.NoError(t, err, "case %d", n)
|
require.NoError(t, err, "case %d", n)
|
||||||
}
|
}
|
||||||
|
@ -130,7 +130,7 @@ func TestBasicTransferAdapter(t *testing.T) {
|
||||||
for n, c := range cases {
|
for n, c := range cases {
|
||||||
err := a.Upload(context.Background(), c.link, p, bytes.NewBufferString("dummy"))
|
err := a.Upload(context.Background(), c.link, p, bytes.NewBufferString("dummy"))
|
||||||
if len(c.expectederror) > 0 {
|
if len(c.expectederror) > 0 {
|
||||||
assert.Contains(t, err.Error(), c.expectederror, "case %d: '%s' should contain '%s'", n, err.Error(), c.expectederror)
|
assert.True(t, strings.Contains(err.Error(), c.expectederror), "case %d: '%s' should contain '%s'", n, err.Error(), c.expectederror)
|
||||||
} else {
|
} else {
|
||||||
require.NoError(t, err, "case %d", n)
|
require.NoError(t, err, "case %d", n)
|
||||||
}
|
}
|
||||||
|
@ -163,7 +163,7 @@ func TestBasicTransferAdapter(t *testing.T) {
|
||||||
for n, c := range cases {
|
for n, c := range cases {
|
||||||
err := a.Verify(context.Background(), c.link, p)
|
err := a.Verify(context.Background(), c.link, p)
|
||||||
if len(c.expectederror) > 0 {
|
if len(c.expectederror) > 0 {
|
||||||
assert.Contains(t, err.Error(), c.expectederror, "case %d: '%s' should contain '%s'", n, err.Error(), c.expectederror)
|
assert.True(t, strings.Contains(err.Error(), c.expectederror), "case %d: '%s' should contain '%s'", n, err.Error(), c.expectederror)
|
||||||
} else {
|
} else {
|
||||||
require.NoError(t, err, "case %d", n)
|
require.NoError(t, err, "case %d", n)
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue