diff --git a/.eslintrc.yaml b/.eslintrc.yaml index 689a4f919ca80..f9d2d30e9ec60 100644 --- a/.eslintrc.yaml +++ b/.eslintrc.yaml @@ -476,7 +476,7 @@ rules: prefer-exponentiation-operator: [2] prefer-named-capture-group: [0] prefer-numeric-literals: [2] - prefer-object-has-own: [0] + prefer-object-has-own: [2] prefer-object-spread: [2] prefer-promise-reject-errors: [2, {allowEmptyReject: false}] prefer-regex-literals: [2] diff --git a/.github/actionlint.yaml b/.github/actionlint.yaml index 24c80bc60a7de..023fb05a2969a 100644 --- a/.github/actionlint.yaml +++ b/.github/actionlint.yaml @@ -2,3 +2,4 @@ self-hosted-runner: labels: - actuated-4cpu-8gb - actuated-4cpu-16gb + - nscloud diff --git a/.github/workflows/disk-clean.yml b/.github/workflows/disk-clean.yml new file mode 100644 index 0000000000000..0f10c905f1bdc --- /dev/null +++ b/.github/workflows/disk-clean.yml @@ -0,0 +1,37 @@ +name: disk-clean + +on: + workflow_call: + +jobs: + triage: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + # FIXME: https://github.com/jlumbroso/free-disk-space/issues/17 + - name: same as 'large-packages' but without 'google-cloud-sdk' + shell: bash + run: | + sudo apt-get remove -y '^dotnet-.*' + sudo apt-get remove -y '^llvm-.*' + sudo apt-get remove -y 'php.*' + sudo apt-get remove -y '^mongodb-.*' + sudo apt-get remove -y '^mysql-.*' + sudo apt-get remove -y azure-cli google-chrome-stable firefox powershell mono-devel libgl1-mesa-dri + sudo apt-get autoremove -y + sudo apt-get clean + - name: Free Disk Space (Ubuntu) + uses: jlumbroso/free-disk-space@main + with: + # this might remove tools that are actually needed, + # if set to "true" but frees about 6 GB + tool-cache: false + + # all of these default to true, but feel free to set to + # "false" if necessary for your workflow + android: true + dotnet: true + haskell: true + large-packages: false + docker-images: false + swap-storage: true diff --git a/.github/workflows/pull-db-tests.yml b/.github/workflows/pull-db-tests.yml index a6fb85937cd26..9fcdea44ee11b 100644 --- a/.github/workflows/pull-db-tests.yml +++ b/.github/workflows/pull-db-tests.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest services: pgsql: - image: postgres:15 + image: postgres:12 env: POSTGRES_DB: test POSTGRES_PASSWORD: postgres @@ -31,10 +31,10 @@ jobs: minio: # as github actions doesn't support "entrypoint", we need to use a non-official image # that has a custom entrypoint set to "minio server /data" - image: bitnami/minio:2021.3.17 + image: bitnami/minio:2023.8.31 env: - MINIO_ACCESS_KEY: 123456 - MINIO_SECRET_KEY: 12345678 + MINIO_ROOT_USER: 123456 + MINIO_ROOT_PASSWORD: 12345678 ports: - "9000:9000" steps: @@ -85,13 +85,6 @@ jobs: needs: files-changed runs-on: ubuntu-latest services: - mysql: - image: mysql:5.7 - env: - MYSQL_ALLOW_EMPTY_PASSWORD: true - MYSQL_DATABASE: test - ports: - - "3306:3306" elasticsearch: image: elasticsearch:7.5.0 env: @@ -104,13 +97,6 @@ jobs: MEILI_ENV: development # disable auth ports: - "7700:7700" - smtpimap: - image: tabascoterrier/docker-imap-devel:latest - ports: - - "25:25" - - "143:143" - - "587:587" - - "993:993" redis: image: redis options: >- # wait until redis has started @@ -152,16 +138,16 @@ jobs: RACE_ENABLED: true GITHUB_READ_TOKEN: ${{ secrets.GITHUB_READ_TOKEN }} - test-mysql5: + test-mysql: if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true' needs: files-changed runs-on: ubuntu-latest services: mysql: - image: mysql:5.7 + image: mysql:8.0 env: MYSQL_ALLOW_EMPTY_PASSWORD: true - MYSQL_DATABASE: test + MYSQL_DATABASE: testgitea ports: - "3306:3306" elasticsearch: @@ -197,43 +183,13 @@ jobs: USE_REPO_TEST_DIR: 1 TEST_INDEXER_CODE_ES_URL: "http://elastic:changeme@elasticsearch:9200" - test-mysql8: - if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true' - needs: files-changed - runs-on: ubuntu-latest - services: - mysql8: - image: mysql:8 - env: - MYSQL_ALLOW_EMPTY_PASSWORD: true - MYSQL_DATABASE: testgitea - ports: - - "3306:3306" - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-go@v4 - with: - go-version: "~1.21" - check-latest: true - - name: Add hosts to /etc/hosts - run: '[ -e "/.dockerenv" ] || [ -e "/run/.containerenv" ] || echo "127.0.0.1 mysql8" | sudo tee -a /etc/hosts' - - run: make deps-backend - - run: make backend - env: - TAGS: bindata - - run: make test-mysql8-migration test-mysql8 - timeout-minutes: 50 - env: - TAGS: bindata - USE_REPO_TEST_DIR: 1 - test-mssql: if: needs.files-changed.outputs.backend == 'true' || needs.files-changed.outputs.actions == 'true' needs: files-changed runs-on: ubuntu-latest services: mssql: - image: mcr.microsoft.com/mssql/server:latest + image: mcr.microsoft.com/mssql/server:2017-latest env: ACCEPT_EULA: Y MSSQL_PID: Standard diff --git a/.github/workflows/release-nightly.yml b/.github/workflows/release-nightly.yml index ef3db2db73e03..1b467e644d1fa 100644 --- a/.github/workflows/release-nightly.yml +++ b/.github/workflows/release-nightly.yml @@ -9,8 +9,10 @@ concurrency: cancel-in-progress: true jobs: + disk-clean: + uses: ./.github/workflows/disk-clean.yml nightly-binary: - runs-on: actuated-4cpu-16gb + runs-on: nscloud steps: - uses: actions/checkout@v4 # fetch all commits instead of only the last as some branches are long lived and could have many between versions @@ -56,7 +58,7 @@ jobs: SOURCE_DIR: dist/release DEST_DIR: gitea/${{ steps.clean_name.outputs.branch }} nightly-docker-rootful: - runs-on: actuated-4cpu-16gb + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 # fetch all commits instead of only the last as some branches are long lived and could have many between versions @@ -93,7 +95,7 @@ jobs: push: true tags: gitea/gitea:${{ steps.clean_name.outputs.branch }} nightly-docker-rootless: - runs-on: actuated-4cpu-16gb + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 # fetch all commits instead of only the last as some branches are long lived and could have many between versions diff --git a/.markdownlint.yaml b/.markdownlint.yaml index 7ccdd53e89793..0af8bcd6fe255 100644 --- a/.markdownlint.yaml +++ b/.markdownlint.yaml @@ -6,7 +6,6 @@ line-length: {code_blocks: false, tables: false, stern: true, line_length: -1} no-alt-text: false no-bare-urls: false no-blanks-blockquote: false -no-duplicate-header: {allow_different_nesting: true} no-emphasis-as-header: false no-empty-links: false no-hard-tabs: {code_blocks: false} diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ef677b88cac5..ea0f80c0c9124 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,33 @@ This changelog goes through all the changes that have been made in each release without substantial changes to our git log; to see the highlights of what has been added to each release, please refer to the [blog](https://blog.gitea.com). +## [1.20.5](https://github.com/go-gitea/gitea/releases/tag/v1.20.5) - 2023-10-03 + +* ENHANCEMENTS + * Fix z-index on markdown completion (#27237) (#27242 & #27238) + * Use secure cookie for HTTPS sites (#26999) (#27013) +* BUGFIXES + * Fix git 2.11 error when checking IsEmpty (#27393) (#27396) + * Allow get release download files and lfs files with oauth2 token format (#26430) (#27378) + * Fix orphan check for deleted branch (#27310) (#27320) + * Quote table `release` in sql queries (#27205) (#27219) + * Fix release URL in webhooks (#27182) (#27184) + * Fix successful return value for `SyncAndGetUserSpecificDiff` (#27152) (#27156) + * fix pagination for followers and following (#27127) (#27138) + * Fix issue templates when blank isses are disabled (#27061) (#27082) + * Fix context cache bug & enable context cache for dashabord commits' authors(#26991) (#27017) + * Fix INI parsing for value with trailing slash (#26995) (#27001) + * Fix PushEvent NullPointerException jenkinsci/github-plugin (#27203) (#27249) + * Fix organization field being null in POST /orgs/{orgid}/teams (#27150) (#27167 & #27162) + * Fix bug of review request number (#27406) (#27104) +* TESTING + * services/wiki: Close() after error handling (#27129) (#27137) +* DOCS + * Improve actions docs related to `pull_request` event (#27126) (#27145) +* MISC + * Add logs for data broken of comment review (#27326) (#27344) + * Load reviewer before sending notification (#27063) (#27064) + ## [1.20.4](https://github.com/go-gitea/gitea/releases/tag/v1.20.4) - 2023-09-08 * SECURITY diff --git a/MAINTAINERS b/MAINTAINERS index 5f38c28beb65a..8d45c03826690 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -57,3 +57,4 @@ Punit Inani (@puni9869) CaiCandong <1290147055@qq.com> (@caicandong) Rui Chen (@chenrui333) Nanguan Lin (@lng2020) +kerwin612 (@kerwin612) diff --git a/Makefile b/Makefile index 7a4a2f9d30e18..0662da5536fb7 100644 --- a/Makefile +++ b/Makefile @@ -49,10 +49,14 @@ ifeq ($(HAS_GO), yes) CGO_CFLAGS ?= $(shell $(GO) env CGO_CFLAGS) $(CGO_EXTRA_CFLAGS) endif -ifeq ($(OS), Windows_NT) - GOFLAGS := -v -buildmode=exe - EXECUTABLE ?= gitea.exe -else ifeq ($(OS), Windows) +ifeq ($(GOOS),windows) + IS_WINDOWS := yes +else ifeq ($(patsubst Windows%,Windows,$(OS)),Windows) + ifeq ($(GOOS),) + IS_WINDOWS := yes + endif +endif +ifeq ($(IS_WINDOWS),yes) GOFLAGS := -v -buildmode=exe EXECUTABLE ?= gitea.exe else @@ -167,10 +171,6 @@ TEST_MYSQL_HOST ?= mysql:3306 TEST_MYSQL_DBNAME ?= testgitea TEST_MYSQL_USERNAME ?= root TEST_MYSQL_PASSWORD ?= -TEST_MYSQL8_HOST ?= mysql8:3306 -TEST_MYSQL8_DBNAME ?= testgitea -TEST_MYSQL8_USERNAME ?= root -TEST_MYSQL8_PASSWORD ?= TEST_PGSQL_HOST ?= pgsql:5432 TEST_PGSQL_DBNAME ?= testgitea TEST_PGSQL_USERNAME ?= postgres @@ -282,12 +282,12 @@ clean: rm -rf $(EXECUTABLE) $(DIST) $(BINDATA_DEST) $(BINDATA_HASH) \ integrations*.test \ e2e*.test \ - tests/integration/gitea-integration-pgsql/ tests/integration/gitea-integration-mysql/ tests/integration/gitea-integration-mysql8/ tests/integration/gitea-integration-sqlite/ \ - tests/integration/gitea-integration-mssql/ tests/integration/indexers-mysql/ tests/integration/indexers-mysql8/ tests/integration/indexers-pgsql tests/integration/indexers-sqlite \ - tests/integration/indexers-mssql tests/mysql.ini tests/mysql8.ini tests/pgsql.ini tests/mssql.ini man/ \ - tests/e2e/gitea-e2e-pgsql/ tests/e2e/gitea-e2e-mysql/ tests/e2e/gitea-e2e-mysql8/ tests/e2e/gitea-e2e-sqlite/ \ - tests/e2e/gitea-e2e-mssql/ tests/e2e/indexers-mysql/ tests/e2e/indexers-mysql8/ tests/e2e/indexers-pgsql/ tests/e2e/indexers-sqlite/ \ - tests/e2e/indexers-mssql/ tests/e2e/reports/ tests/e2e/test-artifacts/ tests/e2e/test-snapshots/ + tests/integration/gitea-integration-* \ + tests/integration/indexers-* \ + tests/mysql.ini tests/pgsql.ini tests/mssql.ini man/ \ + tests/e2e/gitea-e2e-*/ \ + tests/e2e/indexers-*/ \ + tests/e2e/reports/ tests/e2e/test-artifacts/ tests/e2e/test-snapshots/ .PHONY: fmt fmt: @@ -551,27 +551,6 @@ test-mysql\#%: integrations.mysql.test generate-ini-mysql .PHONY: test-mysql-migration test-mysql-migration: migrations.mysql.test migrations.individual.mysql.test -generate-ini-mysql8: - sed -e 's|{{TEST_MYSQL8_HOST}}|${TEST_MYSQL8_HOST}|g' \ - -e 's|{{TEST_MYSQL8_DBNAME}}|${TEST_MYSQL8_DBNAME}|g' \ - -e 's|{{TEST_MYSQL8_USERNAME}}|${TEST_MYSQL8_USERNAME}|g' \ - -e 's|{{TEST_MYSQL8_PASSWORD}}|${TEST_MYSQL8_PASSWORD}|g' \ - -e 's|{{REPO_TEST_DIR}}|${REPO_TEST_DIR}|g' \ - -e 's|{{TEST_LOGGER}}|$(or $(TEST_LOGGER),test$(COMMA)file)|g' \ - -e 's|{{TEST_TYPE}}|$(or $(TEST_TYPE),integration)|g' \ - tests/mysql8.ini.tmpl > tests/mysql8.ini - -.PHONY: test-mysql8 -test-mysql8: integrations.mysql8.test generate-ini-mysql8 - GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql8.ini ./integrations.mysql8.test - -.PHONY: test-mysql8\#% -test-mysql8\#%: integrations.mysql8.test generate-ini-mysql8 - GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql8.ini ./integrations.mysql8.test -test.run $(subst .,/,$*) - -.PHONY: test-mysql8-migration -test-mysql8-migration: migrations.mysql8.test migrations.individual.mysql8.test - generate-ini-pgsql: sed -e 's|{{TEST_PGSQL_HOST}}|${TEST_PGSQL_HOST}|g' \ -e 's|{{TEST_PGSQL_DBNAME}}|${TEST_PGSQL_DBNAME}|g' \ @@ -644,14 +623,6 @@ test-e2e-mysql: playwright e2e.mysql.test generate-ini-mysql test-e2e-mysql\#%: playwright e2e.mysql.test generate-ini-mysql GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./e2e.mysql.test -test.run TestE2e/$* -.PHONY: test-e2e-mysql8 -test-e2e-mysql8: playwright e2e.mysql8.test generate-ini-mysql8 - GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql8.ini ./e2e.mysql8.test - -.PHONY: test-e2e-mysql8\#% -test-e2e-mysql8\#%: playwright e2e.mysql8.test generate-ini-mysql8 - GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql8.ini ./e2e.mysql8.test -test.run TestE2e/$* - .PHONY: test-e2e-pgsql test-e2e-pgsql: playwright e2e.pgsql.test generate-ini-pgsql GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/pgsql.ini ./e2e.pgsql.test @@ -695,9 +666,6 @@ integration-test-coverage-sqlite: integrations.cover.sqlite.test generate-ini-sq integrations.mysql.test: git-check $(GO_SOURCES) $(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -o integrations.mysql.test -integrations.mysql8.test: git-check $(GO_SOURCES) - $(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -o integrations.mysql8.test - integrations.pgsql.test: git-check $(GO_SOURCES) $(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration -o integrations.pgsql.test @@ -718,11 +686,6 @@ migrations.mysql.test: $(GO_SOURCES) generate-ini-mysql $(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.mysql.test GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini ./migrations.mysql.test -.PHONY: migrations.mysql8.test -migrations.mysql8.test: $(GO_SOURCES) generate-ini-mysql8 - $(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.mysql8.test - GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql8.ini ./migrations.mysql8.test - .PHONY: migrations.pgsql.test migrations.pgsql.test: $(GO_SOURCES) generate-ini-pgsql $(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/integration/migration-test -o migrations.pgsql.test @@ -744,13 +707,7 @@ migrations.individual.mysql.test: $(GO_SOURCES) GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg; \ done -.PHONY: migrations.individual.mysql8.test -migrations.individual.mysql8.test: $(GO_SOURCES) - for pkg in $(shell $(GO) list code.gitea.io/gitea/models/migrations/...); do \ - GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/mysql8.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' $$pkg; \ - done - -.PHONY: migrations.individual.mysql8.test\#% +.PHONY: migrations.individual.sqlite.test\#% migrations.individual.sqlite.test\#%: $(GO_SOURCES) generate-ini-sqlite GITEA_ROOT="$(CURDIR)" GITEA_CONF=tests/sqlite.ini $(GO) test $(GOTESTFLAGS) -tags '$(TEST_TAGS)' code.gitea.io/gitea/models/migrations/$* @@ -788,9 +745,6 @@ migrations.individual.sqlite.test\#%: $(GO_SOURCES) generate-ini-sqlite e2e.mysql.test: $(GO_SOURCES) $(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/e2e -o e2e.mysql.test -e2e.mysql8.test: $(GO_SOURCES) - $(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/e2e -o e2e.mysql8.test - e2e.pgsql.test: $(GO_SOURCES) $(GO) test $(GOTESTFLAGS) -c code.gitea.io/gitea/tests/e2e -o e2e.pgsql.test diff --git a/SECURITY.md b/SECURITY.md index 5bee4a7f39f42..4c7d437844d39 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -12,7 +12,7 @@ Please **DO NOT** file a public issue, instead send your report privately to `se ## Protecting Security Information -Due to the sensitive nature of security information, you can use below GPG public key encrypt your mail body. +Due to the sensitive nature of security information, you can use the below GPG public key to encrypt your mail body. The PGP key is valid until June 24, 2024. diff --git a/assets/go-licenses.json b/assets/go-licenses.json index 8a17148e1bc76..ee1e503f2a672 100644 --- a/assets/go-licenses.json +++ b/assets/go-licenses.json @@ -289,6 +289,11 @@ "path": "github.com/cpuguy83/go-md2man/v2/md2man/LICENSE.md", "licenseText": "The MIT License (MIT)\n\nCopyright (c) 2014 Brian Goff\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n" }, + { + "name": "github.com/cyphar/filepath-securejoin", + "path": "github.com/cyphar/filepath-securejoin/LICENSE", + "licenseText": "Copyright (C) 2014-2015 Docker Inc \u0026 Go Authors. All rights reserved.\nCopyright (C) 2017 SUSE LLC. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n * Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n * Redistributions in binary form must reproduce the above\ncopyright notice, this list of conditions and the following disclaimer\nin the documentation and/or other materials provided with the\ndistribution.\n * Neither the name of Google Inc. nor the names of its\ncontributors may be used to endorse or promote products derived from\nthis software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" + }, { "name": "github.com/davecgh/go-spew/spew", "path": "github.com/davecgh/go-spew/spew/LICENSE", @@ -589,21 +594,11 @@ "path": "github.com/gorilla/sessions/LICENSE", "licenseText": "Copyright (c) 2012-2018 The Gorilla Authors. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n\t * Redistributions of source code must retain the above copyright\nnotice, this list of conditions and the following disclaimer.\n\t * Redistributions in binary form must reproduce the above\ncopyright notice, this list of conditions and the following disclaimer\nin the documentation and/or other materials provided with the\ndistribution.\n\t * Neither the name of Google Inc. nor the names of its\ncontributors may be used to endorse or promote products derived from\nthis software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" }, - { - "name": "github.com/hashicorp/errwrap", - "path": "github.com/hashicorp/errwrap/LICENSE", - "licenseText": "Mozilla Public License, version 2.0\n\n1. Definitions\n\n1.1. “Contributor”\n\n means each individual or legal entity that creates, contributes to the\n creation of, or owns Covered Software.\n\n1.2. “Contributor Version”\n\n means the combination of the Contributions of others (if any) used by a\n Contributor and that particular Contributor’s Contribution.\n\n1.3. “Contribution”\n\n means Covered Software of a particular Contributor.\n\n1.4. “Covered Software”\n\n means Source Code Form to which the initial Contributor has attached the\n notice in Exhibit A, the Executable Form of such Source Code Form, and\n Modifications of such Source Code Form, in each case including portions\n thereof.\n\n1.5. “Incompatible With Secondary Licenses”\n means\n\n a. that the initial Contributor has attached the notice described in\n Exhibit B to the Covered Software; or\n\n b. that the Covered Software was made available under the terms of version\n 1.1 or earlier of the License, but not also under the terms of a\n Secondary License.\n\n1.6. “Executable Form”\n\n means any form of the work other than Source Code Form.\n\n1.7. “Larger Work”\n\n means a work that combines Covered Software with other material, in a separate\n file or files, that is not Covered Software.\n\n1.8. “License”\n\n means this document.\n\n1.9. “Licensable”\n\n means having the right to grant, to the maximum extent possible, whether at the\n time of the initial grant or subsequently, any and all of the rights conveyed by\n this License.\n\n1.10. “Modifications”\n\n means any of the following:\n\n a. any file in Source Code Form that results from an addition to, deletion\n from, or modification of the contents of Covered Software; or\n\n b. any new file in Source Code Form that contains any Covered Software.\n\n1.11. “Patent Claims” of a Contributor\n\n means any patent claim(s), including without limitation, method, process,\n and apparatus claims, in any patent Licensable by such Contributor that\n would be infringed, but for the grant of the License, by the making,\n using, selling, offering for sale, having made, import, or transfer of\n either its Contributions or its Contributor Version.\n\n1.12. “Secondary License”\n\n means either the GNU General Public License, Version 2.0, the GNU Lesser\n General Public License, Version 2.1, the GNU Affero General Public\n License, Version 3.0, or any later versions of those licenses.\n\n1.13. “Source Code Form”\n\n means the form of the work preferred for making modifications.\n\n1.14. “You” (or “Your”)\n\n means an individual or a legal entity exercising rights under this\n License. For legal entities, “You” includes any entity that controls, is\n controlled by, or is under common control with You. For purposes of this\n definition, “control” means (a) the power, direct or indirect, to cause\n the direction or management of such entity, whether by contract or\n otherwise, or (b) ownership of more than fifty percent (50%) of the\n outstanding shares or beneficial ownership of such entity.\n\n\n2. License Grants and Conditions\n\n2.1. Grants\n\n Each Contributor hereby grants You a world-wide, royalty-free,\n non-exclusive license:\n\n a. under intellectual property rights (other than patent or trademark)\n Licensable by such Contributor to use, reproduce, make available,\n modify, display, perform, distribute, and otherwise exploit its\n Contributions, either on an unmodified basis, with Modifications, or as\n part of a Larger Work; and\n\n b. under Patent Claims of such Contributor to make, use, sell, offer for\n sale, have made, import, and otherwise transfer either its Contributions\n or its Contributor Version.\n\n2.2. Effective Date\n\n The licenses granted in Section 2.1 with respect to any Contribution become\n effective for each Contribution on the date the Contributor first distributes\n such Contribution.\n\n2.3. Limitations on Grant Scope\n\n The licenses granted in this Section 2 are the only rights granted under this\n License. No additional rights or licenses will be implied from the distribution\n or licensing of Covered Software under this License. Notwithstanding Section\n 2.1(b) above, no patent license is granted by a Contributor:\n\n a. for any code that a Contributor has removed from Covered Software; or\n\n b. for infringements caused by: (i) Your and any other third party’s\n modifications of Covered Software, or (ii) the combination of its\n Contributions with other software (except as part of its Contributor\n Version); or\n\n c. under Patent Claims infringed by Covered Software in the absence of its\n Contributions.\n\n This License does not grant any rights in the trademarks, service marks, or\n logos of any Contributor (except as may be necessary to comply with the\n notice requirements in Section 3.4).\n\n2.4. Subsequent Licenses\n\n No Contributor makes additional grants as a result of Your choice to\n distribute the Covered Software under a subsequent version of this License\n (see Section 10.2) or under the terms of a Secondary License (if permitted\n under the terms of Section 3.3).\n\n2.5. Representation\n\n Each Contributor represents that the Contributor believes its Contributions\n are its original creation(s) or it has sufficient rights to grant the\n rights to its Contributions conveyed by this License.\n\n2.6. Fair Use\n\n This License is not intended to limit any rights You have under applicable\n copyright doctrines of fair use, fair dealing, or other equivalents.\n\n2.7. Conditions\n\n Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in\n Section 2.1.\n\n\n3. Responsibilities\n\n3.1. Distribution of Source Form\n\n All distribution of Covered Software in Source Code Form, including any\n Modifications that You create or to which You contribute, must be under the\n terms of this License. You must inform recipients that the Source Code Form\n of the Covered Software is governed by the terms of this License, and how\n they can obtain a copy of this License. You may not attempt to alter or\n restrict the recipients’ rights in the Source Code Form.\n\n3.2. Distribution of Executable Form\n\n If You distribute Covered Software in Executable Form then:\n\n a. such Covered Software must also be made available in Source Code Form,\n as described in Section 3.1, and You must inform recipients of the\n Executable Form how they can obtain a copy of such Source Code Form by\n reasonable means in a timely manner, at a charge no more than the cost\n of distribution to the recipient; and\n\n b. You may distribute such Executable Form under the terms of this License,\n or sublicense it under different terms, provided that the license for\n the Executable Form does not attempt to limit or alter the recipients’\n rights in the Source Code Form under this License.\n\n3.3. Distribution of a Larger Work\n\n You may create and distribute a Larger Work under terms of Your choice,\n provided that You also comply with the requirements of this License for the\n Covered Software. If the Larger Work is a combination of Covered Software\n with a work governed by one or more Secondary Licenses, and the Covered\n Software is not Incompatible With Secondary Licenses, this License permits\n You to additionally distribute such Covered Software under the terms of\n such Secondary License(s), so that the recipient of the Larger Work may, at\n their option, further distribute the Covered Software under the terms of\n either this License or such Secondary License(s).\n\n3.4. Notices\n\n You may not remove or alter the substance of any license notices (including\n copyright notices, patent notices, disclaimers of warranty, or limitations\n of liability) contained within the Source Code Form of the Covered\n Software, except that You may alter any license notices to the extent\n required to remedy known factual inaccuracies.\n\n3.5. Application of Additional Terms\n\n You may choose to offer, and to charge a fee for, warranty, support,\n indemnity or liability obligations to one or more recipients of Covered\n Software. However, You may do so only on Your own behalf, and not on behalf\n of any Contributor. You must make it absolutely clear that any such\n warranty, support, indemnity, or liability obligation is offered by You\n alone, and You hereby agree to indemnify every Contributor for any\n liability incurred by such Contributor as a result of warranty, support,\n indemnity or liability terms You offer. You may include additional\n disclaimers of warranty and limitations of liability specific to any\n jurisdiction.\n\n4. Inability to Comply Due to Statute or Regulation\n\n If it is impossible for You to comply with any of the terms of this License\n with respect to some or all of the Covered Software due to statute, judicial\n order, or regulation then You must: (a) comply with the terms of this License\n to the maximum extent possible; and (b) describe the limitations and the code\n they affect. Such description must be placed in a text file included with all\n distributions of the Covered Software under this License. Except to the\n extent prohibited by statute or regulation, such description must be\n sufficiently detailed for a recipient of ordinary skill to be able to\n understand it.\n\n5. Termination\n\n5.1. The rights granted under this License will terminate automatically if You\n fail to comply with any of its terms. However, if You become compliant,\n then the rights granted under this License from a particular Contributor\n are reinstated (a) provisionally, unless and until such Contributor\n explicitly and finally terminates Your grants, and (b) on an ongoing basis,\n if such Contributor fails to notify You of the non-compliance by some\n reasonable means prior to 60 days after You have come back into compliance.\n Moreover, Your grants from a particular Contributor are reinstated on an\n ongoing basis if such Contributor notifies You of the non-compliance by\n some reasonable means, this is the first time You have received notice of\n non-compliance with this License from such Contributor, and You become\n compliant prior to 30 days after Your receipt of the notice.\n\n5.2. If You initiate litigation against any entity by asserting a patent\n infringement claim (excluding declaratory judgment actions, counter-claims,\n and cross-claims) alleging that a Contributor Version directly or\n indirectly infringes any patent, then the rights granted to You by any and\n all Contributors for the Covered Software under Section 2.1 of this License\n shall terminate.\n\n5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user\n license agreements (excluding distributors and resellers) which have been\n validly granted by You or Your distributors under this License prior to\n termination shall survive termination.\n\n6. Disclaimer of Warranty\n\n Covered Software is provided under this License on an “as is” basis, without\n warranty of any kind, either expressed, implied, or statutory, including,\n without limitation, warranties that the Covered Software is free of defects,\n merchantable, fit for a particular purpose or non-infringing. The entire\n risk as to the quality and performance of the Covered Software is with You.\n Should any Covered Software prove defective in any respect, You (not any\n Contributor) assume the cost of any necessary servicing, repair, or\n correction. This disclaimer of warranty constitutes an essential part of this\n License. No use of any Covered Software is authorized under this License\n except under this disclaimer.\n\n7. Limitation of Liability\n\n Under no circumstances and under no legal theory, whether tort (including\n negligence), contract, or otherwise, shall any Contributor, or anyone who\n distributes Covered Software as permitted above, be liable to You for any\n direct, indirect, special, incidental, or consequential damages of any\n character including, without limitation, damages for lost profits, loss of\n goodwill, work stoppage, computer failure or malfunction, or any and all\n other commercial damages or losses, even if such party shall have been\n informed of the possibility of such damages. This limitation of liability\n shall not apply to liability for death or personal injury resulting from such\n party’s negligence to the extent applicable law prohibits such limitation.\n Some jurisdictions do not allow the exclusion or limitation of incidental or\n consequential damages, so this exclusion and limitation may not apply to You.\n\n8. Litigation\n\n Any litigation relating to this License may be brought only in the courts of\n a jurisdiction where the defendant maintains its principal place of business\n and such litigation shall be governed by laws of that jurisdiction, without\n reference to its conflict-of-law provisions. Nothing in this Section shall\n prevent a party’s ability to bring cross-claims or counter-claims.\n\n9. Miscellaneous\n\n This License represents the complete agreement concerning the subject matter\n hereof. If any provision of this License is held to be unenforceable, such\n provision shall be reformed only to the extent necessary to make it\n enforceable. Any law or regulation which provides that the language of a\n contract shall be construed against the drafter shall not be used to construe\n this License against a Contributor.\n\n\n10. Versions of the License\n\n10.1. New Versions\n\n Mozilla Foundation is the license steward. Except as provided in Section\n 10.3, no one other than the license steward has the right to modify or\n publish new versions of this License. Each version will be given a\n distinguishing version number.\n\n10.2. Effect of New Versions\n\n You may distribute the Covered Software under the terms of the version of\n the License under which You originally received the Covered Software, or\n under the terms of any subsequent version published by the license\n steward.\n\n10.3. Modified Versions\n\n If you create software not governed by this License, and you want to\n create a new license for such software, you may create and use a modified\n version of this License if you rename the license and remove any\n references to the name of the license steward (except to note that such\n modified license differs from this License).\n\n10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses\n If You choose to distribute Source Code Form that is Incompatible With\n Secondary Licenses under the terms of this version of the License, the\n notice described in Exhibit B of this License must be attached.\n\nExhibit A - Source Code Form License Notice\n\n This Source Code Form is subject to the\n terms of the Mozilla Public License, v.\n 2.0. If a copy of the MPL was not\n distributed with this file, You can\n obtain one at\n http://mozilla.org/MPL/2.0/.\n\nIf it is not possible or desirable to put the notice in a particular file, then\nYou may include the notice in a location (such as a LICENSE file in a relevant\ndirectory) where a recipient would be likely to look for such a notice.\n\nYou may add additional accurate notices of copyright ownership.\n\nExhibit B - “Incompatible With Secondary Licenses” Notice\n\n This Source Code Form is “Incompatible\n With Secondary Licenses”, as defined by\n the Mozilla Public License, v. 2.0.\n\n" - }, { "name": "github.com/hashicorp/go-cleanhttp", "path": "github.com/hashicorp/go-cleanhttp/LICENSE", "licenseText": "Mozilla Public License, version 2.0\n\n1. Definitions\n\n1.1. \"Contributor\"\n\n means each individual or legal entity that creates, contributes to the\n creation of, or owns Covered Software.\n\n1.2. \"Contributor Version\"\n\n means the combination of the Contributions of others (if any) used by a\n Contributor and that particular Contributor's Contribution.\n\n1.3. \"Contribution\"\n\n means Covered Software of a particular Contributor.\n\n1.4. \"Covered Software\"\n\n means Source Code Form to which the initial Contributor has attached the\n notice in Exhibit A, the Executable Form of such Source Code Form, and\n Modifications of such Source Code Form, in each case including portions\n thereof.\n\n1.5. \"Incompatible With Secondary Licenses\"\n means\n\n a. that the initial Contributor has attached the notice described in\n Exhibit B to the Covered Software; or\n\n b. that the Covered Software was made available under the terms of\n version 1.1 or earlier of the License, but not also under the terms of\n a Secondary License.\n\n1.6. \"Executable Form\"\n\n means any form of the work other than Source Code Form.\n\n1.7. \"Larger Work\"\n\n means a work that combines Covered Software with other material, in a\n separate file or files, that is not Covered Software.\n\n1.8. \"License\"\n\n means this document.\n\n1.9. \"Licensable\"\n\n means having the right to grant, to the maximum extent possible, whether\n at the time of the initial grant or subsequently, any and all of the\n rights conveyed by this License.\n\n1.10. \"Modifications\"\n\n means any of the following:\n\n a. any file in Source Code Form that results from an addition to,\n deletion from, or modification of the contents of Covered Software; or\n\n b. any new file in Source Code Form that contains any Covered Software.\n\n1.11. \"Patent Claims\" of a Contributor\n\n means any patent claim(s), including without limitation, method,\n process, and apparatus claims, in any patent Licensable by such\n Contributor that would be infringed, but for the grant of the License,\n by the making, using, selling, offering for sale, having made, import,\n or transfer of either its Contributions or its Contributor Version.\n\n1.12. \"Secondary License\"\n\n means either the GNU General Public License, Version 2.0, the GNU Lesser\n General Public License, Version 2.1, the GNU Affero General Public\n License, Version 3.0, or any later versions of those licenses.\n\n1.13. \"Source Code Form\"\n\n means the form of the work preferred for making modifications.\n\n1.14. \"You\" (or \"Your\")\n\n means an individual or a legal entity exercising rights under this\n License. For legal entities, \"You\" includes any entity that controls, is\n controlled by, or is under common control with You. For purposes of this\n definition, \"control\" means (a) the power, direct or indirect, to cause\n the direction or management of such entity, whether by contract or\n otherwise, or (b) ownership of more than fifty percent (50%) of the\n outstanding shares or beneficial ownership of such entity.\n\n\n2. License Grants and Conditions\n\n2.1. Grants\n\n Each Contributor hereby grants You a world-wide, royalty-free,\n non-exclusive license:\n\n a. under intellectual property rights (other than patent or trademark)\n Licensable by such Contributor to use, reproduce, make available,\n modify, display, perform, distribute, and otherwise exploit its\n Contributions, either on an unmodified basis, with Modifications, or\n as part of a Larger Work; and\n\n b. under Patent Claims of such Contributor to make, use, sell, offer for\n sale, have made, import, and otherwise transfer either its\n Contributions or its Contributor Version.\n\n2.2. Effective Date\n\n The licenses granted in Section 2.1 with respect to any Contribution\n become effective for each Contribution on the date the Contributor first\n distributes such Contribution.\n\n2.3. Limitations on Grant Scope\n\n The licenses granted in this Section 2 are the only rights granted under\n this License. No additional rights or licenses will be implied from the\n distribution or licensing of Covered Software under this License.\n Notwithstanding Section 2.1(b) above, no patent license is granted by a\n Contributor:\n\n a. for any code that a Contributor has removed from Covered Software; or\n\n b. for infringements caused by: (i) Your and any other third party's\n modifications of Covered Software, or (ii) the combination of its\n Contributions with other software (except as part of its Contributor\n Version); or\n\n c. under Patent Claims infringed by Covered Software in the absence of\n its Contributions.\n\n This License does not grant any rights in the trademarks, service marks,\n or logos of any Contributor (except as may be necessary to comply with\n the notice requirements in Section 3.4).\n\n2.4. Subsequent Licenses\n\n No Contributor makes additional grants as a result of Your choice to\n distribute the Covered Software under a subsequent version of this\n License (see Section 10.2) or under the terms of a Secondary License (if\n permitted under the terms of Section 3.3).\n\n2.5. Representation\n\n Each Contributor represents that the Contributor believes its\n Contributions are its original creation(s) or it has sufficient rights to\n grant the rights to its Contributions conveyed by this License.\n\n2.6. Fair Use\n\n This License is not intended to limit any rights You have under\n applicable copyright doctrines of fair use, fair dealing, or other\n equivalents.\n\n2.7. Conditions\n\n Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in\n Section 2.1.\n\n\n3. Responsibilities\n\n3.1. Distribution of Source Form\n\n All distribution of Covered Software in Source Code Form, including any\n Modifications that You create or to which You contribute, must be under\n the terms of this License. You must inform recipients that the Source\n Code Form of the Covered Software is governed by the terms of this\n License, and how they can obtain a copy of this License. You may not\n attempt to alter or restrict the recipients' rights in the Source Code\n Form.\n\n3.2. Distribution of Executable Form\n\n If You distribute Covered Software in Executable Form then:\n\n a. such Covered Software must also be made available in Source Code Form,\n as described in Section 3.1, and You must inform recipients of the\n Executable Form how they can obtain a copy of such Source Code Form by\n reasonable means in a timely manner, at a charge no more than the cost\n of distribution to the recipient; and\n\n b. You may distribute such Executable Form under the terms of this\n License, or sublicense it under different terms, provided that the\n license for the Executable Form does not attempt to limit or alter the\n recipients' rights in the Source Code Form under this License.\n\n3.3. Distribution of a Larger Work\n\n You may create and distribute a Larger Work under terms of Your choice,\n provided that You also comply with the requirements of this License for\n the Covered Software. If the Larger Work is a combination of Covered\n Software with a work governed by one or more Secondary Licenses, and the\n Covered Software is not Incompatible With Secondary Licenses, this\n License permits You to additionally distribute such Covered Software\n under the terms of such Secondary License(s), so that the recipient of\n the Larger Work may, at their option, further distribute the Covered\n Software under the terms of either this License or such Secondary\n License(s).\n\n3.4. Notices\n\n You may not remove or alter the substance of any license notices\n (including copyright notices, patent notices, disclaimers of warranty, or\n limitations of liability) contained within the Source Code Form of the\n Covered Software, except that You may alter any license notices to the\n extent required to remedy known factual inaccuracies.\n\n3.5. Application of Additional Terms\n\n You may choose to offer, and to charge a fee for, warranty, support,\n indemnity or liability obligations to one or more recipients of Covered\n Software. However, You may do so only on Your own behalf, and not on\n behalf of any Contributor. You must make it absolutely clear that any\n such warranty, support, indemnity, or liability obligation is offered by\n You alone, and You hereby agree to indemnify every Contributor for any\n liability incurred by such Contributor as a result of warranty, support,\n indemnity or liability terms You offer. You may include additional\n disclaimers of warranty and limitations of liability specific to any\n jurisdiction.\n\n4. Inability to Comply Due to Statute or Regulation\n\n If it is impossible for You to comply with any of the terms of this License\n with respect to some or all of the Covered Software due to statute,\n judicial order, or regulation then You must: (a) comply with the terms of\n this License to the maximum extent possible; and (b) describe the\n limitations and the code they affect. Such description must be placed in a\n text file included with all distributions of the Covered Software under\n this License. Except to the extent prohibited by statute or regulation,\n such description must be sufficiently detailed for a recipient of ordinary\n skill to be able to understand it.\n\n5. Termination\n\n5.1. The rights granted under this License will terminate automatically if You\n fail to comply with any of its terms. However, if You become compliant,\n then the rights granted under this License from a particular Contributor\n are reinstated (a) provisionally, unless and until such Contributor\n explicitly and finally terminates Your grants, and (b) on an ongoing\n basis, if such Contributor fails to notify You of the non-compliance by\n some reasonable means prior to 60 days after You have come back into\n compliance. Moreover, Your grants from a particular Contributor are\n reinstated on an ongoing basis if such Contributor notifies You of the\n non-compliance by some reasonable means, this is the first time You have\n received notice of non-compliance with this License from such\n Contributor, and You become compliant prior to 30 days after Your receipt\n of the notice.\n\n5.2. If You initiate litigation against any entity by asserting a patent\n infringement claim (excluding declaratory judgment actions,\n counter-claims, and cross-claims) alleging that a Contributor Version\n directly or indirectly infringes any patent, then the rights granted to\n You by any and all Contributors for the Covered Software under Section\n 2.1 of this License shall terminate.\n\n5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user\n license agreements (excluding distributors and resellers) which have been\n validly granted by You or Your distributors under this License prior to\n termination shall survive termination.\n\n6. Disclaimer of Warranty\n\n Covered Software is provided under this License on an \"as is\" basis,\n without warranty of any kind, either expressed, implied, or statutory,\n including, without limitation, warranties that the Covered Software is free\n of defects, merchantable, fit for a particular purpose or non-infringing.\n The entire risk as to the quality and performance of the Covered Software\n is with You. Should any Covered Software prove defective in any respect,\n You (not any Contributor) assume the cost of any necessary servicing,\n repair, or correction. This disclaimer of warranty constitutes an essential\n part of this License. No use of any Covered Software is authorized under\n this License except under this disclaimer.\n\n7. Limitation of Liability\n\n Under no circumstances and under no legal theory, whether tort (including\n negligence), contract, or otherwise, shall any Contributor, or anyone who\n distributes Covered Software as permitted above, be liable to You for any\n direct, indirect, special, incidental, or consequential damages of any\n character including, without limitation, damages for lost profits, loss of\n goodwill, work stoppage, computer failure or malfunction, or any and all\n other commercial damages or losses, even if such party shall have been\n informed of the possibility of such damages. This limitation of liability\n shall not apply to liability for death or personal injury resulting from\n such party's negligence to the extent applicable law prohibits such\n limitation. Some jurisdictions do not allow the exclusion or limitation of\n incidental or consequential damages, so this exclusion and limitation may\n not apply to You.\n\n8. Litigation\n\n Any litigation relating to this License may be brought only in the courts\n of a jurisdiction where the defendant maintains its principal place of\n business and such litigation shall be governed by laws of that\n jurisdiction, without reference to its conflict-of-law provisions. Nothing\n in this Section shall prevent a party's ability to bring cross-claims or\n counter-claims.\n\n9. Miscellaneous\n\n This License represents the complete agreement concerning the subject\n matter hereof. If any provision of this License is held to be\n unenforceable, such provision shall be reformed only to the extent\n necessary to make it enforceable. Any law or regulation which provides that\n the language of a contract shall be construed against the drafter shall not\n be used to construe this License against a Contributor.\n\n\n10. Versions of the License\n\n10.1. New Versions\n\n Mozilla Foundation is the license steward. Except as provided in Section\n 10.3, no one other than the license steward has the right to modify or\n publish new versions of this License. Each version will be given a\n distinguishing version number.\n\n10.2. Effect of New Versions\n\n You may distribute the Covered Software under the terms of the version\n of the License under which You originally received the Covered Software,\n or under the terms of any subsequent version published by the license\n steward.\n\n10.3. Modified Versions\n\n If you create software not governed by this License, and you want to\n create a new license for such software, you may create and use a\n modified version of this License if you rename the license and remove\n any references to the name of the license steward (except to note that\n such modified license differs from this License).\n\n10.4. Distributing Source Code Form that is Incompatible With Secondary\n Licenses If You choose to distribute Source Code Form that is\n Incompatible With Secondary Licenses under the terms of this version of\n the License, the notice described in Exhibit B of this License must be\n attached.\n\nExhibit A - Source Code Form License Notice\n\n This Source Code Form is subject to the\n terms of the Mozilla Public License, v.\n 2.0. If a copy of the MPL was not\n distributed with this file, You can\n obtain one at\n http://mozilla.org/MPL/2.0/.\n\nIf it is not possible or desirable to put the notice in a particular file,\nthen You may include the notice in a location (such as a LICENSE file in a\nrelevant directory) where a recipient would be likely to look for such a\nnotice.\n\nYou may add additional accurate notices of copyright ownership.\n\nExhibit B - \"Incompatible With Secondary Licenses\" Notice\n\n This Source Code Form is \"Incompatible\n With Secondary Licenses\", as defined by\n the Mozilla Public License, v. 2.0.\n\n" }, - { - "name": "github.com/hashicorp/go-multierror", - "path": "github.com/hashicorp/go-multierror/LICENSE", - "licenseText": "Mozilla Public License, version 2.0\n\n1. Definitions\n\n1.1. “Contributor”\n\n means each individual or legal entity that creates, contributes to the\n creation of, or owns Covered Software.\n\n1.2. “Contributor Version”\n\n means the combination of the Contributions of others (if any) used by a\n Contributor and that particular Contributor’s Contribution.\n\n1.3. “Contribution”\n\n means Covered Software of a particular Contributor.\n\n1.4. “Covered Software”\n\n means Source Code Form to which the initial Contributor has attached the\n notice in Exhibit A, the Executable Form of such Source Code Form, and\n Modifications of such Source Code Form, in each case including portions\n thereof.\n\n1.5. “Incompatible With Secondary Licenses”\n means\n\n a. that the initial Contributor has attached the notice described in\n Exhibit B to the Covered Software; or\n\n b. that the Covered Software was made available under the terms of version\n 1.1 or earlier of the License, but not also under the terms of a\n Secondary License.\n\n1.6. “Executable Form”\n\n means any form of the work other than Source Code Form.\n\n1.7. “Larger Work”\n\n means a work that combines Covered Software with other material, in a separate\n file or files, that is not Covered Software.\n\n1.8. “License”\n\n means this document.\n\n1.9. “Licensable”\n\n means having the right to grant, to the maximum extent possible, whether at the\n time of the initial grant or subsequently, any and all of the rights conveyed by\n this License.\n\n1.10. “Modifications”\n\n means any of the following:\n\n a. any file in Source Code Form that results from an addition to, deletion\n from, or modification of the contents of Covered Software; or\n\n b. any new file in Source Code Form that contains any Covered Software.\n\n1.11. “Patent Claims” of a Contributor\n\n means any patent claim(s), including without limitation, method, process,\n and apparatus claims, in any patent Licensable by such Contributor that\n would be infringed, but for the grant of the License, by the making,\n using, selling, offering for sale, having made, import, or transfer of\n either its Contributions or its Contributor Version.\n\n1.12. “Secondary License”\n\n means either the GNU General Public License, Version 2.0, the GNU Lesser\n General Public License, Version 2.1, the GNU Affero General Public\n License, Version 3.0, or any later versions of those licenses.\n\n1.13. “Source Code Form”\n\n means the form of the work preferred for making modifications.\n\n1.14. “You” (or “Your”)\n\n means an individual or a legal entity exercising rights under this\n License. For legal entities, “You” includes any entity that controls, is\n controlled by, or is under common control with You. For purposes of this\n definition, “control” means (a) the power, direct or indirect, to cause\n the direction or management of such entity, whether by contract or\n otherwise, or (b) ownership of more than fifty percent (50%) of the\n outstanding shares or beneficial ownership of such entity.\n\n\n2. License Grants and Conditions\n\n2.1. Grants\n\n Each Contributor hereby grants You a world-wide, royalty-free,\n non-exclusive license:\n\n a. under intellectual property rights (other than patent or trademark)\n Licensable by such Contributor to use, reproduce, make available,\n modify, display, perform, distribute, and otherwise exploit its\n Contributions, either on an unmodified basis, with Modifications, or as\n part of a Larger Work; and\n\n b. under Patent Claims of such Contributor to make, use, sell, offer for\n sale, have made, import, and otherwise transfer either its Contributions\n or its Contributor Version.\n\n2.2. Effective Date\n\n The licenses granted in Section 2.1 with respect to any Contribution become\n effective for each Contribution on the date the Contributor first distributes\n such Contribution.\n\n2.3. Limitations on Grant Scope\n\n The licenses granted in this Section 2 are the only rights granted under this\n License. No additional rights or licenses will be implied from the distribution\n or licensing of Covered Software under this License. Notwithstanding Section\n 2.1(b) above, no patent license is granted by a Contributor:\n\n a. for any code that a Contributor has removed from Covered Software; or\n\n b. for infringements caused by: (i) Your and any other third party’s\n modifications of Covered Software, or (ii) the combination of its\n Contributions with other software (except as part of its Contributor\n Version); or\n\n c. under Patent Claims infringed by Covered Software in the absence of its\n Contributions.\n\n This License does not grant any rights in the trademarks, service marks, or\n logos of any Contributor (except as may be necessary to comply with the\n notice requirements in Section 3.4).\n\n2.4. Subsequent Licenses\n\n No Contributor makes additional grants as a result of Your choice to\n distribute the Covered Software under a subsequent version of this License\n (see Section 10.2) or under the terms of a Secondary License (if permitted\n under the terms of Section 3.3).\n\n2.5. Representation\n\n Each Contributor represents that the Contributor believes its Contributions\n are its original creation(s) or it has sufficient rights to grant the\n rights to its Contributions conveyed by this License.\n\n2.6. Fair Use\n\n This License is not intended to limit any rights You have under applicable\n copyright doctrines of fair use, fair dealing, or other equivalents.\n\n2.7. Conditions\n\n Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in\n Section 2.1.\n\n\n3. Responsibilities\n\n3.1. Distribution of Source Form\n\n All distribution of Covered Software in Source Code Form, including any\n Modifications that You create or to which You contribute, must be under the\n terms of this License. You must inform recipients that the Source Code Form\n of the Covered Software is governed by the terms of this License, and how\n they can obtain a copy of this License. You may not attempt to alter or\n restrict the recipients’ rights in the Source Code Form.\n\n3.2. Distribution of Executable Form\n\n If You distribute Covered Software in Executable Form then:\n\n a. such Covered Software must also be made available in Source Code Form,\n as described in Section 3.1, and You must inform recipients of the\n Executable Form how they can obtain a copy of such Source Code Form by\n reasonable means in a timely manner, at a charge no more than the cost\n of distribution to the recipient; and\n\n b. You may distribute such Executable Form under the terms of this License,\n or sublicense it under different terms, provided that the license for\n the Executable Form does not attempt to limit or alter the recipients’\n rights in the Source Code Form under this License.\n\n3.3. Distribution of a Larger Work\n\n You may create and distribute a Larger Work under terms of Your choice,\n provided that You also comply with the requirements of this License for the\n Covered Software. If the Larger Work is a combination of Covered Software\n with a work governed by one or more Secondary Licenses, and the Covered\n Software is not Incompatible With Secondary Licenses, this License permits\n You to additionally distribute such Covered Software under the terms of\n such Secondary License(s), so that the recipient of the Larger Work may, at\n their option, further distribute the Covered Software under the terms of\n either this License or such Secondary License(s).\n\n3.4. Notices\n\n You may not remove or alter the substance of any license notices (including\n copyright notices, patent notices, disclaimers of warranty, or limitations\n of liability) contained within the Source Code Form of the Covered\n Software, except that You may alter any license notices to the extent\n required to remedy known factual inaccuracies.\n\n3.5. Application of Additional Terms\n\n You may choose to offer, and to charge a fee for, warranty, support,\n indemnity or liability obligations to one or more recipients of Covered\n Software. However, You may do so only on Your own behalf, and not on behalf\n of any Contributor. You must make it absolutely clear that any such\n warranty, support, indemnity, or liability obligation is offered by You\n alone, and You hereby agree to indemnify every Contributor for any\n liability incurred by such Contributor as a result of warranty, support,\n indemnity or liability terms You offer. You may include additional\n disclaimers of warranty and limitations of liability specific to any\n jurisdiction.\n\n4. Inability to Comply Due to Statute or Regulation\n\n If it is impossible for You to comply with any of the terms of this License\n with respect to some or all of the Covered Software due to statute, judicial\n order, or regulation then You must: (a) comply with the terms of this License\n to the maximum extent possible; and (b) describe the limitations and the code\n they affect. Such description must be placed in a text file included with all\n distributions of the Covered Software under this License. Except to the\n extent prohibited by statute or regulation, such description must be\n sufficiently detailed for a recipient of ordinary skill to be able to\n understand it.\n\n5. Termination\n\n5.1. The rights granted under this License will terminate automatically if You\n fail to comply with any of its terms. However, if You become compliant,\n then the rights granted under this License from a particular Contributor\n are reinstated (a) provisionally, unless and until such Contributor\n explicitly and finally terminates Your grants, and (b) on an ongoing basis,\n if such Contributor fails to notify You of the non-compliance by some\n reasonable means prior to 60 days after You have come back into compliance.\n Moreover, Your grants from a particular Contributor are reinstated on an\n ongoing basis if such Contributor notifies You of the non-compliance by\n some reasonable means, this is the first time You have received notice of\n non-compliance with this License from such Contributor, and You become\n compliant prior to 30 days after Your receipt of the notice.\n\n5.2. If You initiate litigation against any entity by asserting a patent\n infringement claim (excluding declaratory judgment actions, counter-claims,\n and cross-claims) alleging that a Contributor Version directly or\n indirectly infringes any patent, then the rights granted to You by any and\n all Contributors for the Covered Software under Section 2.1 of this License\n shall terminate.\n\n5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user\n license agreements (excluding distributors and resellers) which have been\n validly granted by You or Your distributors under this License prior to\n termination shall survive termination.\n\n6. Disclaimer of Warranty\n\n Covered Software is provided under this License on an “as is” basis, without\n warranty of any kind, either expressed, implied, or statutory, including,\n without limitation, warranties that the Covered Software is free of defects,\n merchantable, fit for a particular purpose or non-infringing. The entire\n risk as to the quality and performance of the Covered Software is with You.\n Should any Covered Software prove defective in any respect, You (not any\n Contributor) assume the cost of any necessary servicing, repair, or\n correction. This disclaimer of warranty constitutes an essential part of this\n License. No use of any Covered Software is authorized under this License\n except under this disclaimer.\n\n7. Limitation of Liability\n\n Under no circumstances and under no legal theory, whether tort (including\n negligence), contract, or otherwise, shall any Contributor, or anyone who\n distributes Covered Software as permitted above, be liable to You for any\n direct, indirect, special, incidental, or consequential damages of any\n character including, without limitation, damages for lost profits, loss of\n goodwill, work stoppage, computer failure or malfunction, or any and all\n other commercial damages or losses, even if such party shall have been\n informed of the possibility of such damages. This limitation of liability\n shall not apply to liability for death or personal injury resulting from such\n party’s negligence to the extent applicable law prohibits such limitation.\n Some jurisdictions do not allow the exclusion or limitation of incidental or\n consequential damages, so this exclusion and limitation may not apply to You.\n\n8. Litigation\n\n Any litigation relating to this License may be brought only in the courts of\n a jurisdiction where the defendant maintains its principal place of business\n and such litigation shall be governed by laws of that jurisdiction, without\n reference to its conflict-of-law provisions. Nothing in this Section shall\n prevent a party’s ability to bring cross-claims or counter-claims.\n\n9. Miscellaneous\n\n This License represents the complete agreement concerning the subject matter\n hereof. If any provision of this License is held to be unenforceable, such\n provision shall be reformed only to the extent necessary to make it\n enforceable. Any law or regulation which provides that the language of a\n contract shall be construed against the drafter shall not be used to construe\n this License against a Contributor.\n\n\n10. Versions of the License\n\n10.1. New Versions\n\n Mozilla Foundation is the license steward. Except as provided in Section\n 10.3, no one other than the license steward has the right to modify or\n publish new versions of this License. Each version will be given a\n distinguishing version number.\n\n10.2. Effect of New Versions\n\n You may distribute the Covered Software under the terms of the version of\n the License under which You originally received the Covered Software, or\n under the terms of any subsequent version published by the license\n steward.\n\n10.3. Modified Versions\n\n If you create software not governed by this License, and you want to\n create a new license for such software, you may create and use a modified\n version of this License if you rename the license and remove any\n references to the name of the license steward (except to note that such\n modified license differs from this License).\n\n10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses\n If You choose to distribute Source Code Form that is Incompatible With\n Secondary Licenses under the terms of this version of the License, the\n notice described in Exhibit B of this License must be attached.\n\nExhibit A - Source Code Form License Notice\n\n This Source Code Form is subject to the\n terms of the Mozilla Public License, v.\n 2.0. If a copy of the MPL was not\n distributed with this file, You can\n obtain one at\n http://mozilla.org/MPL/2.0/.\n\nIf it is not possible or desirable to put the notice in a particular file, then\nYou may include the notice in a location (such as a LICENSE file in a relevant\ndirectory) where a recipient would be likely to look for such a notice.\n\nYou may add additional accurate notices of copyright ownership.\n\nExhibit B - “Incompatible With Secondary Licenses” Notice\n\n This Source Code Form is “Incompatible\n With Secondary Licenses”, as defined by\n the Mozilla Public License, v. 2.0.\n" - }, { "name": "github.com/hashicorp/go-retryablehttp", "path": "github.com/hashicorp/go-retryablehttp/LICENSE", @@ -904,11 +899,6 @@ "path": "github.com/rivo/uniseg/LICENSE.txt", "licenseText": "MIT License\n\nCopyright (c) 2019 Oliver Kuederle\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n" }, - { - "name": "github.com/robfig/cron", - "path": "github.com/robfig/cron/LICENSE", - "licenseText": "Copyright (C) 2012 Rob Figueiredo\nAll Rights Reserved.\n\nMIT LICENSE\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n" - }, { "name": "github.com/robfig/cron/v3", "path": "github.com/robfig/cron/v3/LICENSE", diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini index cd6b2a914d237..dca530151bfa4 100644 --- a/custom/conf/app.example.ini +++ b/custom/conf/app.example.ini @@ -548,7 +548,8 @@ ENABLE = true ;; Pre-register OAuth2 applications for some universally useful services ;; * https://github.com/hickford/git-credential-oauth ;; * https://github.com/git-ecosystem/git-credential-manager -;DEFAULT_APPLICATIONS = git-credential-oauth, git-credential-manager +;; * https://gitea.com/gitea/tea +;DEFAULT_APPLICATIONS = git-credential-oauth, git-credential-manager, tea ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -1209,10 +1210,10 @@ LEVEL = Info ;SHOW_USER_EMAIL = true ;; ;; Set the default theme for the Gitea install -;DEFAULT_THEME = auto +;DEFAULT_THEME = gitea-auto ;; ;; All available themes. Allow users select personalized themes regardless of the value of `DEFAULT_THEME`. -;THEMES = auto,gitea,arc-green +;THEMES = gitea-auto,gitea-light,gitea-dark ;; ;; All available reactions users can choose on issues/prs and comments. ;; Values can be emoji alias (:smile:) or a unicode emoji. @@ -2568,6 +2569,12 @@ LEVEL = Info ;DEFAULT_ACTIONS_URL = github ;; Default artifact retention time in days, default is 90 days ;ARTIFACT_RETENTION_DAYS = 90 +;; Timeout to stop the task which have running status, but haven't been updated for a long time +;ZOMBIE_TASK_TIMEOUT = 10m +;; Timeout to stop the tasks which have running status and continuous updates, but don't end for a long time +;ENDLESS_TASK_TIMEOUT = 3h +;; Timeout to cancel the jobs which have waiting status, but haven't been picked by a runner for a long time +;ABANDONED_JOB_TIMEOUT = 24h ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/docs/content/administration/cmd-embedded.en-us.md b/docs/content/administration/cmd-embedded.en-us.md index fabb7148ad87f..b7f6836144f92 100644 --- a/docs/content/administration/cmd-embedded.en-us.md +++ b/docs/content/administration/cmd-embedded.en-us.md @@ -50,7 +50,7 @@ a special meaning for your command shell. If no pattern is provided, all files are listed. -### Example +### Example: Listing all embedded files Listing all embedded files with `openid` in their path: @@ -101,7 +101,7 @@ When Gitea is upgraded to a new version (by replacing the executable), many of t embedded files will suffer changes. Gitea will honor and use any files found in the `custom` directory, even if they are old and incompatible. -### Example +### Example: Extracting mail templates Extracting mail templates to a temporary directory: diff --git a/docs/content/administration/cmd-embedded.zh-cn.md b/docs/content/administration/cmd-embedded.zh-cn.md index 27ee61040edf7..4570bb58a39ed 100644 --- a/docs/content/administration/cmd-embedded.zh-cn.md +++ b/docs/content/administration/cmd-embedded.zh-cn.md @@ -43,7 +43,7 @@ gitea embedded list [--include-vendored] [patterns...] 如果未提供模式,则列出所有文件。 -### 示例 +### 示例:列出所有嵌入文件 列出所有路径中包含 `openid` 的嵌入文件: @@ -83,7 +83,7 @@ gitea [--config {file}] embedded extract [--destination {dir}|--custom] [--overw 请确保**只提取需要自定义的文件**。位于 `custom` 目录中的文件不会受到 Gitea 的升级过程的影响。当 Gitea 升级到新版本(通过替换可执行文件)时,许多嵌入文件将发生变化。Gitea 将尊重并使用在 `custom` 目录中找到的任何文件,即使这些文件是旧的和不兼容的。 -### 示例 +### 示例:提取邮件模板 将邮件模板提取到临时目录: diff --git a/docs/content/administration/config-cheat-sheet.en-us.md b/docs/content/administration/config-cheat-sheet.en-us.md index aa29f8be4b8ca..3c864582cebfe 100644 --- a/docs/content/administration/config-cheat-sheet.en-us.md +++ b/docs/content/administration/config-cheat-sheet.en-us.md @@ -215,9 +215,9 @@ The following configuration set `Content-Type: application/vnd.android.package-a - `SITEMAP_PAGING_NUM`: **20**: Number of items that are displayed in a single subsitemap. - `GRAPH_MAX_COMMIT_NUM`: **100**: Number of maximum commits shown in the commit graph. - `CODE_COMMENT_LINES`: **4**: Number of line of codes shown for a code comment. -- `DEFAULT_THEME`: **auto**: \[auto, gitea, arc-green\]: Set the default theme for the Gitea install. +- `DEFAULT_THEME`: **gitea-auto**: \[gitea-auto, gitea-light, gitea-dark\]: Set the default theme for the Gitea installation. - `SHOW_USER_EMAIL`: **true**: Whether the email of the user should be shown in the Explore Users page. -- `THEMES`: **auto,gitea,arc-green**: All available themes. Allow users select personalized themes. +- `THEMES`: **gitea-auto,gitea-light,gitea-dark**: All available themes. Allow users select personalized themes. regardless of the value of `DEFAULT_THEME`. - `MAX_DISPLAY_FILE_SIZE`: **8388608**: Max size of files to be displayed (default is 8MiB) - `REACTIONS`: All available reactions users can choose on issues/prs and comments @@ -1107,7 +1107,7 @@ This section only does "set" config, a removed config key from this section won' - `JWT_SECRET_URI`: **_empty_**: Instead of defining JWT_SECRET in the configuration, this configuration option can be used to give Gitea a path to a file that contains the secret (example value: `file:/etc/gitea/oauth2_jwt_secret`) - `JWT_SIGNING_PRIVATE_KEY_FILE`: **jwt/private.pem**: Private key file path used to sign OAuth2 tokens. The path is relative to `APP_DATA_PATH`. This setting is only needed if `JWT_SIGNING_ALGORITHM` is set to `RS256`, `RS384`, `RS512`, `ES256`, `ES384` or `ES512`. The file must contain a RSA or ECDSA private key in the PKCS8 format. If no key exists a 4096 bit key will be created for you. - `MAX_TOKEN_LENGTH`: **32767**: Maximum length of token/cookie to accept from OAuth2 provider -- `DEFAULT_APPLICATIONS`: **git-credential-oauth, git-credential-manager**: Pre-register OAuth applications for some services on startup. See the [OAuth2 documentation](/development/oauth2-provider.md) for the list of available options. +- `DEFAULT_APPLICATIONS`: **git-credential-oauth, git-credential-manager, tea**: Pre-register OAuth applications for some services on startup. See the [OAuth2 documentation](/development/oauth2-provider.md) for the list of available options. ## i18n (`i18n`) @@ -1389,6 +1389,9 @@ PROXY_HOSTS = *.github.com - `STORAGE_TYPE`: **local**: Storage type for actions logs, `local` for local disk or `minio` for s3 compatible object storage service, default is `local` or other name defined with `[storage.xxx]` - `MINIO_BASE_PATH`: **actions_log/**: Minio base path on the bucket only available when STORAGE_TYPE is `minio` - `ARTIFACT_RETENTION_DAYS`: **90**: Number of days to keep artifacts. Set to 0 to disable artifact retention. Default is 90 days if not set. +- `ZOMBIE_TASK_TIMEOUT`: **10m**: Timeout to stop the task which have running status, but haven't been updated for a long time +- `ENDLESS_TASK_TIMEOUT`: **3h**: Timeout to stop the tasks which have running status and continuous updates, but don't end for a long time +- `ABANDONED_JOB_TIMEOUT`: **24h**: Timeout to cancel the jobs which have waiting status, but haven't been picked by a runner for a long time `DEFAULT_ACTIONS_URL` indicates where the Gitea Actions runners should find the actions with relative path. For example, `uses: actions/checkout@v3` means `https://github.com/actions/checkout@v3` since the value of `DEFAULT_ACTIONS_URL` is `github`. diff --git a/docs/content/administration/config-cheat-sheet.zh-cn.md b/docs/content/administration/config-cheat-sheet.zh-cn.md index 2849752c0ab5f..48df750343f1b 100644 --- a/docs/content/administration/config-cheat-sheet.zh-cn.md +++ b/docs/content/administration/config-cheat-sheet.zh-cn.md @@ -214,9 +214,9 @@ menu: - `SITEMAP_PAGING_NUM`: **20**: 在单个子SiteMap中显示的项数。 - `GRAPH_MAX_COMMIT_NUM`: **100**: 提交图中显示的最大commit数量。 - `CODE_COMMENT_LINES`: **4**: 在代码评论中能够显示的最大代码行数。 -- `DEFAULT_THEME`: **auto**: \[auto, gitea, arc-green\]: 在Gitea安装时候设置的默认主题。 +- `DEFAULT_THEME`: **gitea-auto**: \[gitea-auto, gitea-light, gitea-dark\]: 在Gitea安装时候设置的默认主题。 - `SHOW_USER_EMAIL`: **true**: 用户的电子邮件是否应该显示在`Explore Users`页面中。 -- `THEMES`: **auto,gitea,arc-green**: 所有可用的主题。允许用户选择个性化的主题, +- `THEMES`: **gitea-auto,gitea-light,gitea-dark**: 所有可用的主题。允许用户选择个性化的主题, 而不受DEFAULT_THEME 值的影响。 - `MAX_DISPLAY_FILE_SIZE`: **8388608**: 能够显示文件的最大大小(默认为8MiB)。 - `REACTIONS`: 用户可以在问题(Issue)、Pull Request(PR)以及评论中选择的所有可选的反应。 @@ -1056,7 +1056,7 @@ Gitea 创建以下非唯一队列: - `JWT_SECRET_URI`:**_empty_**:可以使用此配置选项,而不是在配置中定义`JWT_SECRET`,以向Gitea提供包含密钥的文件的路径(示例值:`file:/etc/gitea/oauth2_jwt_secret`)。 - `JWT_SIGNING_PRIVATE_KEY_FILE`:**jwt/private.pem**:用于签署OAuth2令牌的私钥文件路径。路径相对于`APP_DATA_PATH`。仅当`JWT_SIGNING_ALGORITHM`设置为`RS256`,`RS384`,`RS512`,`ES256`,`ES384`或`ES512`时才需要此设置。文件必须包含PKCS8格式的RSA或ECDSA私钥。如果不存在密钥,则将为您创建一个4096位密钥。 - `MAX_TOKEN_LENGTH`:**32767**:从OAuth2提供者接受的令牌/cookie的最大长度。 -- `DEFAULT_APPLICATIONS`:**git-credential-oauth,git-credential-manager**:在启动时预注册用于某些服务的OAuth应用程序。有关可用选项列表,请参阅[OAuth2文档](/development/oauth2-provider.md)。 +- `DEFAULT_APPLICATIONS`:**git-credential-oauth,git-credential-manager, tea**:在启动时预注册用于某些服务的OAuth应用程序。有关可用选项列表,请参阅[OAuth2文档](/development/oauth2-provider.md)。 ## i18n (`i18n`) diff --git a/docs/content/administration/customizing-gitea.en-us.md b/docs/content/administration/customizing-gitea.en-us.md index 4c2d7ed0c418b..d122fb4bfaac0 100644 --- a/docs/content/administration/customizing-gitea.en-us.md +++ b/docs/content/administration/customizing-gitea.en-us.md @@ -370,7 +370,8 @@ A full list of supported emoji's is at [emoji list](https://gitea.com/gitea/gite ## Customizing the look of Gitea -The default built-in themes are `gitea` (light), `arc-green` (dark), and `auto` (chooses light or dark depending on operating system settings). +The built-in themes are `gitea-light`, `gitea-dark`, and `gitea-auto` (which automatically adapts to OS settings). + The default theme can be changed via `DEFAULT_THEME` in the [ui](administration/config-cheat-sheet.md#ui-ui) section of `app.ini`. Gitea also has support for user themes, which means every user can select which theme should be used. @@ -384,7 +385,7 @@ To make a custom theme available to all users: Community themes are listed in [gitea/awesome-gitea#themes](https://gitea.com/gitea/awesome-gitea#themes). -The `arc-green` theme source can be found [here](https://github.com/go-gitea/gitea/blob/main/web_src/css/themes/theme-arc-green.css). +The default theme sources can be found [here](https://github.com/go-gitea/gitea/blob/main/web_src/css/themes). If your custom theme is considered a dark theme, set the global css variable `--is-dark-theme` to `true`. This allows Gitea to adjust the Monaco code editor's theme accordingly. diff --git a/docs/content/administration/customizing-gitea.zh-cn.md b/docs/content/administration/customizing-gitea.zh-cn.md index 2babf03da79bf..d828704557cfa 100644 --- a/docs/content/administration/customizing-gitea.zh-cn.md +++ b/docs/content/administration/customizing-gitea.zh-cn.md @@ -86,5 +86,6 @@ Gitea 引用 `custom` 目录中的自定义配置文件来覆盖配置、模板 ## 更改 Gitea 外观 -Gitea 目前由两种内置主题,分别为默认 `gitea` 主题和深色主题 `arc-green`,您可以通过修改 -`app.ini` [ui](administration/config-cheat-sheet.md#ui-ui) 部分的 `DEFAULT_THEME` 的值来变更至一个可用的 Gitea 外观。 +内置主题是“gitea-light”、“gitea-dark”和“gitea-auto”(自动适应操作系统设置)。 + +默认主题可以通过 `app.ini` 的 [ui](administration/config-cheat-sheet.md#ui-ui) 部分中的 `DEFAULT_THEME` 进行更改。 diff --git a/docs/content/development/oauth2-provider.en-us.md b/docs/content/development/oauth2-provider.en-us.md index 053c1d8d7e286..54674f9246b48 100644 --- a/docs/content/development/oauth2-provider.en-us.md +++ b/docs/content/development/oauth2-provider.en-us.md @@ -86,6 +86,7 @@ Gitea creates OAuth applications for the following services by default on startu |-----------|-----------|---------| |[git-credential-oauth](https://github.com/hickford/git-credential-oauth)|Git credential helper|`a4792ccc-144e-407e-86c9-5e7d8d9c3269`| |[Git Credential Manager](https://github.com/git-ecosystem/git-credential-manager)|Git credential helper|`e90ee53c-94e2-48ac-9358-a874fb9e0662`| +|[tea](https://gitea.com/gitea/tea)|tea|`d57cb8c4-630c-4168-8324-ec79935e18d4`| To prevent unexpected behavior, they are being displayed as locked in the UI and their creation can instead be controlled by the `DEFAULT_APPLICATIONS` parameter in `app.ini`. diff --git a/docs/content/help/faq.en-us.md b/docs/content/help/faq.en-us.md index c83f8549e20d1..b4f5171bcfd92 100644 --- a/docs/content/help/faq.en-us.md +++ b/docs/content/help/faq.en-us.md @@ -181,7 +181,7 @@ Use [Fail2Ban](administration/fail2ban-setup.md) to monitor and stop automated l ## How to add/use custom themes -Gitea supports three official themes right now, `gitea` (light), `arc-green` (dark), and `auto` (automatically switches between the previous two depending on operating system settings). +Gitea supports three official themes right now, `gitea-light`, `gitea-dark`, and `gitea-auto` (automatically switches between the previous two depending on operating system settings). To add your own theme, currently the only way is to provide a complete theme (not just color overrides) As an example, let's say our theme is `arc-blue` (this is a real theme, and can be found [in this issue](https://github.com/go-gitea/gitea/issues/6011)) diff --git a/docs/content/help/faq.zh-cn.md b/docs/content/help/faq.zh-cn.md index 36610db8e0b8e..ff53fc1d03969 100644 --- a/docs/content/help/faq.zh-cn.md +++ b/docs/content/help/faq.zh-cn.md @@ -185,7 +185,7 @@ Gitea不提供内置的Pages服务器。您需要一个专用的域名来提供 ## 如何添加/使用自定义主题 -Gitea 目前支持三个官方主题,分别是 `gitea`(亮色)、`arc-green`(暗色)和 `auto`(根据操作系统设置自动切换前两个主题)。 +Gitea 目前支持三个官方主题,分别是 `gitea-light`、`gitea-dark` 和 `gitea-auto`(根据操作系统设置自动切换前两个主题)。 要添加自己的主题,目前唯一的方法是提供一个完整的主题(不仅仅是颜色覆盖)。 假设我们的主题是 `arc-blue`(这是一个真实的主题,可以在[此问题](https://github.com/go-gitea/gitea/issues/6011)中找到) diff --git a/docs/content/installation/comparison.en-us.md b/docs/content/installation/comparison.en-us.md index 80fa9b7054d1c..e48410ba6fa12 100644 --- a/docs/content/installation/comparison.en-us.md +++ b/docs/content/installation/comparison.en-us.md @@ -33,117 +33,117 @@ _Symbols used in table:_ ## General Features -| Feature | Gitea | Gogs | GitHub EE | GitLab CE | GitLab EE | BitBucket | RhodeCode CE | -| ------------------------------------------------ | --------------------------------------------------- | ---- | --------- | --------- | --------- | --------- | ------------ | -| Open source and free | ✓ | ✓ | ✘ | ✓ | ✘ | ✘ | ✓ | -| Low RAM/ CPU usage | ✓ | ✓ | ✘ | ✘ | ✘ | ✘ | ✘ | -| Multiple database support | ✓ | ✓ | ✘ | ⁄ | ⁄ | ✓ | ✓ | -| Multiple OS support | ✓ | ✓ | ✘ | ✘ | ✘ | ✘ | ✓ | -| Easy upgrades | ✓ | ✓ | ✘ | ✓ | ✓ | ✘ | ✓ | -| Telemetry | **✘** | ✘ | ✓ | ✓ | ✓ | ✓ | ? | -| Third-party render tool support | ✓ | ✘ | ✘ | ✘ | ✘ | ✓ | ? | -| WebAuthn (2FA) | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ? | -| Extensive API | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| Built-in Package/Container Registry | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ | -| Sync commits to an external repo (push mirror) | ✓ | ✓ | ✘ | ✓ | ✓ | ✘ | ✓ | -| Sync commits from an external repo (pull mirror) | ✓ | ✘ | ✘ | ✓ | ✓ | ✘ | ? | -| Light and Dark Theme | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ? | -| Custom Theme Support | ✓ | ✓ | ✘ | ✘ | ✘ | ✓ | ✘ | -| Markdown support | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| CSV support | ✓ | ✘ | ✓ | ✘ | ✘ | ✓ | ? | -| 'GitHub / GitLab pages' | [⚙️][gitea-pages-server], [⚙️][gitea-caddy-plugin] | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ | -| Repo-specific wiki (as a repo itself) | ✓ | ✓ | ✓ | ✓ | ✓ | / | ✘ | -| Deploy Tokens | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| Repository Tokens with write rights | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ | -| RSS Feeds | ✓ | ✘ | ✓ | ✘ | ✘ | ✘ | ✘ | -| Built-in CI/CD | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ | -| Subgroups: groups within groups | [✘](https://github.com/go-gitea/gitea/issues/1872) | ✘ | ✘ | ✓ | ✓ | ✘ | ✓ | -| Interaction with other instances | [/](https://github.com/go-gitea/gitea/issues/18240) | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | -| Mermaid diagrams in Markdown | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ | -| Math syntax in Markdown | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ | +| Feature | Gitea | Gogs | GitHub EE | GitLab CE | GitLab EE | BitBucket | RhodeCode CE | RhodeCode EE | +| ------------------------------------------------ | --------------------------------------------------- | ---- | --------- | --------- | --------- | --------- | ------------ | ------------ | +| Open source and free | ✓ | ✓ | ✘ | ✓ | ✘ | ✘ | ✓ | ✓ | +| Low RAM/ CPU usage | ✓ | ✓ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | +| Multiple database support | ✓ | ✓ | ✘ | ⁄ | ⁄ | ✓ | ✓ | ✓ | +| Multiple OS support | ✓ | ✓ | ✘ | ✘ | ✘ | ✘ | ✓ | ✓ | +| Easy upgrades | ✓ | ✓ | ✘ | ✓ | ✓ | ✘ | ✓ | ✓ | +| Telemetry | **✘** | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ | ✘ | +| Third-party render tool support | ✓ | ✘ | ✘ | ✘ | ✘ | ✓ | ✘ | ✘ | +| WebAuthn (2FA) | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ | ✓ | +| Extensive API | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| Built-in Package/Container Registry | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ | ✘ | +| Sync commits to an external repo (push mirror) | ✓ | ✓ | ✘ | ✓ | ✓ | ✘ | ✓ | ✓ | +| Sync commits from an external repo (pull mirror) | ✓ | ✘ | ✘ | ✓ | ✓ | ✘ | ✓ | ✓ | +| Light and Dark Theme | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ | ✘ | +| Custom Theme Support | ✓ | ✓ | ✘ | ✘ | ✘ | ✓ | ✓ | ✓ | +| Markdown support | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| CSV support | ✓ | ✘ | ✓ | ✘ | ✘ | ✓ | ✘ | ✘ | +| 'GitHub / GitLab pages' | [⚙️][gitea-pages-server], [⚙️][gitea-caddy-plugin] | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ | ✘ | +| Repo-specific wiki (as a repo itself) | ✓ | ✓ | ✓ | ✓ | ✓ | / | ✘ | ✘ | +| Deploy Tokens | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| Repository Tokens with write rights | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| RSS Feeds | ✓ | ✘ | ✓ | ✘ | ✘ | ✘ | ✓ | ✓ | +| Built-in CI/CD | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ | ✘ | +| Subgroups: groups within groups | [✘](https://github.com/go-gitea/gitea/issues/1872) | ✘ | ✘ | ✓ | ✓ | ✘ | ✓ | ✓ | +| Interaction with other instances | [/](https://github.com/go-gitea/gitea/issues/18240) | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | +| Mermaid diagrams in Markdown | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ | ✘ | +| Math syntax in Markdown | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✓ | ✓ | ## Code management -| Feature | Gitea | Gogs | GitHub EE | GitLab CE | GitLab EE | BitBucket | RhodeCode CE | -| ------------------------------------------- | --------------------------------------------------- | ---- | --------- | --------- | --------- | --------- | ------------ | -| Repository topics | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ | -| Repository code search | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ | -| Global code search | ✓ | ✘ | ✓ | ✘ | ✓ | ✓ | ✓ | -| Git LFS 2.0 | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ | -| Group Milestones | [✘](https://github.com/go-gitea/gitea/issues/14622) | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ | -| Granular user roles (Code, Issues, Wiki, …) | ✓ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ | -| Verified Committer | ⁄ | ✘ | ? | ✓ | ✓ | ✓ | ✘ | -| GPG Signed Commits | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ | -| SSH Signed Commits | ✓ | ✘ | ✓ | ✓ | ✓ | ? | ? | -| Reject unsigned commits | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ | -| Migrating repos from other services | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ | -| Repository Activity page | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ | -| Branch manager | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ | -| Create new branches | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ | -| Web code editor | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| Commit graph | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ | -| Template Repositories | ✓ | ✘ | ✓ | ✘ | ✓ | ✓ | ✘ | -| Git Blame | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ | -| Visual comparison of image changes | ✓ | ✘ | ✓ | ? | ? | ? | ? | +| Feature | Gitea | Gogs | GitHub EE | GitLab CE | GitLab EE | BitBucket | RhodeCode CE | RhodeCode EE | +| ------------------------------------------- | --------------------------------------------------- | ---- | --------- | --------- | --------- | --------- | ------------ | ------------ | +| Repository topics | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ | ✘ | +| Repository code search | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| Global code search | ✓ | ✘ | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | +| Git LFS 2.0 | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| Group Milestones | [✘](https://github.com/go-gitea/gitea/issues/14622) | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ | ✘ | +| Granular user roles (Code, Issues, Wiki, …) | ✓ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ | ✘ | +| Verified Committer | ⁄ | ✘ | ? | ✓ | ✓ | ✓ | ✘ | ✘ | +| GPG Signed Commits | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| SSH Signed Commits | ✓ | ✘ | ✓ | ✓ | ✓ | ? | ✘ | ✘ | +| Reject unsigned commits | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| Migrating repos from other services | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| Repository Activity page | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| Branch manager | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| Create new branches | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ | ✘ | +| Web code editor | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| Commit graph | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| Template Repositories | ✓ | ✘ | ✓ | ✘ | ✓ | ✓ | ✘ | ✘ | +| Git Blame | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| Visual comparison of image changes | ✓ | ✘ | ✓ | ? | ? | ? | ✘ | ✘ | ## Issue Tracker -| Feature | Gitea | Gogs | GitHub EE | GitLab CE | GitLab EE | BitBucket | RhodeCode CE | -| ----------------------------- | --------------------------------------------------- | ---- | --------- | --------- | --------- | --------- | ------------ | -| Issue tracker | ✓ | ✓ | ✓ | ✓ | ✓ | / | ✘ | -| Issue templates | ✓ | ✓ | ✓ | ✓ | ✓ | ✘ | ✘ | -| Labels | ✓ | ✓ | ✓ | ✓ | ✓ | ✘ | ✘ | -| Time tracking | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ | -| Multiple assignees for issues | ✓ | ✘ | ✓ | ✘ | ✓ | ✘ | ✘ | -| Related issues | ✘ | ✘ | ⁄ | ✓ | ✓ | ✘ | ✘ | -| Confidential issues | [✘](https://github.com/go-gitea/gitea/issues/3217) | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ | -| Comment reactions | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ | -| Lock Discussion | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ | -| Batch issue handling | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ | -| Issue Boards (Kanban) | [/](https://github.com/go-gitea/gitea/issues/14710) | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ | -| Create branch from issue | [✘](https://github.com/go-gitea/gitea/issues/20226) | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ | -| Convert comment to new issue | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ | -| Issue search | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ | -| Global issue search | [/](https://github.com/go-gitea/gitea/issues/2434) | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ | -| Issue dependency | ✓ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | -| Create issue via email | [✘](https://github.com/go-gitea/gitea/issues/6226) | ✘ | ✘ | ✓ | ✓ | ✓ | ✘ | -| Service Desk | [✘](https://github.com/go-gitea/gitea/issues/6219) | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ | +| Feature | Gitea | Gogs | GitHub EE | GitLab CE | GitLab EE | BitBucket | RhodeCode CE | RhodeCode EE | +| ----------------------------- | --------------------------------------------------- | ---- | --------- | --------- | --------- | --------- | ------------ | ------------ | +| Issue tracker | ✓ | ✓ | ✓ | ✓ | ✓ | / | ✘ | ✘ | +| Issue templates | ✓ | ✓ | ✓ | ✓ | ✓ | ✘ | ✘ | ✘ | +| Labels | ✓ | ✓ | ✓ | ✓ | ✓ | ✘ | ✘ | ✘ | +| Time tracking | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ | ✘ | +| Multiple assignees for issues | ✓ | ✘ | ✓ | ✘ | ✓ | ✘ | ✘ | ✘ | +| Related issues | ✘ | ✘ | ⁄ | ✓ | ✓ | ✘ | ✘ | ✘ | +| Confidential issues | [✘](https://github.com/go-gitea/gitea/issues/3217) | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ | ✘ | +| Comment reactions | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ | ✘ | +| Lock Discussion | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ | ✘ | +| Batch issue handling | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ | ✘ | +| Issue Boards (Kanban) | [/](https://github.com/go-gitea/gitea/issues/14710) | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ | ✘ | +| Create branch from issue | [✘](https://github.com/go-gitea/gitea/issues/20226) | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ | ✘ | +| Convert comment to new issue | ✓ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ | ✘ | +| Issue search | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ | ✘ | +| Global issue search | [/](https://github.com/go-gitea/gitea/issues/2434) | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ | ✘ | +| Issue dependency | ✓ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | ✘ | +| Create issue via email | [✘](https://github.com/go-gitea/gitea/issues/6226) | ✘ | ✘ | ✓ | ✓ | ✓ | ✘ | ✘ | +| Service Desk | [✘](https://github.com/go-gitea/gitea/issues/6219) | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ | ✘ | ## Pull/Merge requests -| Feature | Gitea | Gogs | GitHub EE | GitLab CE | GitLab EE | BitBucket | RhodeCode CE | -| ----------------------------------------------- | -------------------------------------------------- | ---- | --------- | --------- | --------- | --------- | ------------ | -| Pull/Merge requests | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| Squash merging | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ | -| Rebase merging | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| Pull/Merge request inline comments | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ | -| Pull/Merge request approval | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ | -| Pull/Merge require approval | ✓ | ✘ | ✓ | ✘ | ✓ | ✓ | ✓ | -| Pull/Merge multiple reviewers | ✓ | ✓ | ✓ | ✘ | ✓ | ✓ | ✓ | -| Merge conflict resolution | [✘](https://github.com/go-gitea/gitea/issues/9014) | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ | -| Restrict push and merge access to certain users | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ | -| Revert specific commits | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ | -| Pull/Merge requests templates | ✓ | ✓ | ✓ | ✓ | ✓ | ✘ | ✘ | -| Cherry-picking changes | ✓ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ | -| Download Patch | ✓ | ✘ | ✓ | ✓ | ✓ | / | ✘ | -| Merge queues | ✘ | ✘ | ✓ | ✘ | ✓ | ✘ | ✘ | +| Feature | Gitea | Gogs | GitHub EE | GitLab CE | GitLab EE | BitBucket | RhodeCode CE | RhodeCode EE | +| ----------------------------------------------- | -------------------------------------------------- | ---- | --------- | --------- | --------- | --------- | ------------ | ------------ | +| Pull/Merge requests | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| Squash merging | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| Rebase merging | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| Pull/Merge request inline comments | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| Pull/Merge request approval | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| Pull/Merge require approval | ✓ | ✘ | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | +| Pull/Merge multiple reviewers | ✓ | ✓ | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | +| Merge conflict resolution | [✘](https://github.com/go-gitea/gitea/issues/9014) | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ | ✘ | +| Restrict push and merge access to certain users | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| Revert specific commits | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ | ✘ | +| Pull/Merge requests templates | ✓ | ✓ | ✓ | ✓ | ✓ | ✘ | ✘ | ✘ | +| Cherry-picking changes | ✓ | ✘ | ✘ | ✓ | ✓ | ✘ | ✘ | ✓ | +| Download Patch | ✓ | ✘ | ✓ | ✓ | ✓ | / | ✓ | ✓ | +| Merge queues | ✘ | ✘ | ✓ | ✘ | ✓ | ✘ | ✘ | ✘ | ## 3rd-party integrations -| Feature | Gitea | Gogs | GitHub EE | GitLab CE | GitLab EE | BitBucket | RhodeCode CE | -| ---------------------------------------------- | ------------------------------------------------ | ---- | --------- | --------- | --------- | --------- | ------------ | -| Webhooks | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| Git Hooks | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| AD / LDAP integration | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | -| Multiple LDAP / AD server support | ✓ | ✓ | ✘ | ✘ | ✓ | ✓ | ✓ | -| LDAP user synchronization | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ | -| SAML 2.0 service provider | [✘](https://github.com/go-gitea/gitea/issues/5512) | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ | -| OpenID Connect support | ✓ | ✘ | ✓ | ✓ | ✓ | ? | ✘ | -| OAuth 2.0 integration (external authorization) | ✓ | ✘ | ⁄ | ✓ | ✓ | ? | ✓ | -| Act as OAuth 2.0 provider | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ | -| Two factor authentication (2FA) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✘ | -| Integration with the most common services | ✓ | / | ⁄ | ✓ | ✓ | ⁄ | ✓ | -| Incorporate external CI/CD | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ | +| Feature | Gitea | Gogs | GitHub EE | GitLab CE | GitLab EE | BitBucket | RhodeCode CE | RhodeCode EE | +| ---------------------------------------------- | ------------------------------------------------ | ---- | --------- | --------- | --------- | --------- | ------------ | ------------ | +| Webhooks | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| Git Hooks | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| AD / LDAP integration | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | +| Multiple LDAP / AD server support | ✓ | ✓ | ✘ | ✘ | ✓ | ✓ | ✓ | ✓ | +| LDAP user synchronization | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ | ✓ | +| SAML 2.0 service provider | [✘](https://github.com/go-gitea/gitea/issues/5512) | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ | ✓ | +| OpenID Connect support | ✓ | ✘ | ✓ | ✓ | ✓ | ? | ✘ | ✓ | +| OAuth 2.0 integration (external authorization) | ✓ | ✘ | ⁄ | ✓ | ✓ | ? | ✘ | ✓ | +| Act as OAuth 2.0 provider | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✘ | ✘ | +| Two factor authentication (2FA) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✘ | ✓ | +| Integration with the most common services | ✓ | / | ⁄ | ✓ | ✓ | ⁄ | ✓ | ✓ | +| Incorporate external CI/CD | ✓ | ✘ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | [gitea-caddy-plugin]: https://github.com/42wim/caddy-gitea [gitea-pages-server]: https://codeberg.org/Codeberg/pages-server diff --git a/docs/content/installation/database-preparation.en-us.md b/docs/content/installation/database-preparation.en-us.md index c980bf5ad1822..25b163793eeac 100644 --- a/docs/content/installation/database-preparation.en-us.md +++ b/docs/content/installation/database-preparation.en-us.md @@ -17,7 +17,9 @@ menu: # Database Preparation -You need a database to use Gitea. Gitea supports PostgreSQL (>=10), MySQL (>=5.7), MariaDB, SQLite, and MSSQL (>=2008R2 SP3). This page will guide into preparing database. Only PostgreSQL and MySQL will be covered here since those database engines are widely-used in production. If you plan to use SQLite, you can ignore this chapter. +You need a database to use Gitea. Gitea supports PostgreSQL (>= 12), MySQL (>= 8.0), MariaDB, SQLite, and MSSQL (>= 2012 SP4). This page will guide into preparing database. Only PostgreSQL and MySQL will be covered here since those database engines are widely-used in production. If you plan to use SQLite, you can ignore this chapter. + +If you use an unsupported database version, please [get in touch](/help/support) with us for information on our Extended Support Contracts. We can provide testing and support for older databases and integrate those fixes into the Gitea codebase. Database instance can be on same machine as Gitea (local database setup), or on different machine (remote database). @@ -182,7 +184,7 @@ If the communication between Gitea and your database instance is performed throu - On the database server certificate, one of `Subject Alternative Name` or `Common Name` entries must be the fully-qualified domain name (FQDN) of the database instance (e.g. `db.example.com`). On the database client certificate, one of the entries mentioned above must contain the database username that Gitea will be using to connect. - You need domain name mappings of both Gitea and database servers to their respective IP addresses. Either set up DNS records for them or add local mappings to `/etc/hosts` (`%WINDIR%\System32\drivers\etc\hosts` in Windows) on each system. This allows the database connections to be performed by domain name instead of IP address. See documentation of your system for details. -### PostgreSQL +### PostgreSQL TLS The PostgreSQL driver used by Gitea supports two-way TLS. In two-way TLS, both database client and server authenticate each other by sending their respective certificates to their respective opposite for validation. In other words, the server verifies client certificate, and the client verifies server certificate. @@ -250,7 +252,7 @@ The PostgreSQL driver used by Gitea supports two-way TLS. In two-way TLS, both d You should be prompted to enter password for the database user, and then be connected to the database. -### MySQL +### MySQL/MariaDB TLS While the MySQL driver used by Gitea also supports two-way TLS, Gitea currently supports only one-way TLS. See issue #10828 for details. diff --git a/docs/content/installation/database-preparation.zh-cn.md b/docs/content/installation/database-preparation.zh-cn.md index b5e8b73f1f6b1..b58344133ee70 100644 --- a/docs/content/installation/database-preparation.zh-cn.md +++ b/docs/content/installation/database-preparation.zh-cn.md @@ -17,13 +17,13 @@ menu: # 数据库准备 -在使用 Gitea 前,您需要准备一个数据库。Gitea 支持 PostgreSQL(>=10)、MySQL(>=5.7)、SQLite 和 MSSQL(>=2008R2 SP3)这几种数据库。本页将指导您准备数据库。由于 PostgreSQL 和 MySQL 在生产环境中被广泛使用,因此本文档将仅涵盖这两种数据库。如果您计划使用 SQLite,则可以忽略本章内容。 +在使用 Gitea 前,您需要准备一个数据库。Gitea 支持 PostgreSQL(>= 12)、MySQL(>= 8.0)、SQLite 和 MSSQL(>= 2012 SP4)这几种数据库。本页将指导您准备数据库。由于 PostgreSQL 和 MySQL 在生产环境中被广泛使用,因此本文档将仅涵盖这两种数据库。如果您计划使用 SQLite,则可以忽略本章内容。 数据库实例可以与 Gitea 实例在相同机器上(本地数据库),也可以与 Gitea 实例在不同机器上(远程数据库)。 注意:以下所有步骤要求您的选择的数据库引擎已安装在您的系统上。对于远程数据库设置,请在数据库实例上安装服务器应用程序,在 Gitea 服务器上安装客户端程序。客户端程序用于测试 Gitea 服务器与数据库之间的连接,而 Gitea 本身使用 Go 提供的数据库驱动程序完成相同的任务。此外,请确保服务器和客户端使用相同的引擎版本,以使某些引擎功能正常工作。出于安全原因,请使用安全密码保护 `root`(MySQL)或 `postgres`(PostgreSQL)数据库超级用户。以下步骤假设您在数据库和 Gitea 服务器上都使用 Linux。 -## MySQL +## MySQL/MariaDB 1. 对于远程数据库设置,您需要让 MySQL 监听您的 IP 地址。编辑数据库实例上的 `/etc/mysql/my.cnf` 文件中的 `bind-address` 选项为: @@ -182,7 +182,7 @@ menu: - 在数据库服务器证书中,`Subject Alternative Name` 或 `Common Name` 条目之一必须是数据库实例的完全限定域名(FQDN)(例如 `db.example.com`)。在数据库客户端证书中,上述提到的条目之一必须包含 Gitea 将用于连接的数据库用户名。 - 您需要将 Gitea 和数据库服务器的域名映射到它们各自的 IP 地址。可以为它们设置 DNS 记录,也可以在每个系统上的 `/etc/hosts`(Windows 中的 `%WINDIR%\System32\drivers\etc\hosts`)中添加本地映射。这样可以通过域名而不是 IP 地址进行数据库连接。有关详细信息,请参阅您系统的文档。 -### PostgreSQL +### PostgreSQL TLS Gitea 使用的 PostgreSQL 驱动程序支持双向 TLS。在双向 TLS 中,数据库客户端和服务器通过将各自的证书发送给对方进行验证来相互认证。换句话说,服务器验证客户端证书,客户端验证服务器证书。 @@ -250,7 +250,7 @@ Gitea 使用的 PostgreSQL 驱动程序支持双向 TLS。在双向 TLS 中, 您将被提示输入数据库用户的密码,然后连接到数据库。 -### MySQL +### MySQL/MariaDB TLS 虽然 Gitea 使用的MySQL驱动程序也支持双向 TLS,但目前 Gitea 仅支持单向 TLS。有关详细信息,请参见工单#10828。 diff --git a/docs/content/installation/from-package.en-us.md b/docs/content/installation/from-package.en-us.md index aa559f28336df..aceb2029d27d4 100644 --- a/docs/content/installation/from-package.en-us.md +++ b/docs/content/installation/from-package.en-us.md @@ -15,9 +15,11 @@ menu: identifier: "install-from-package" --- -# Official packages +# Installation from Package -## macOS +## Official packages + +### macOS Currently, the only supported method of installation on MacOS is [Homebrew](http://brew.sh/). Following the [deployment from binary](installation/from-binary.md) guide may work, @@ -27,9 +29,9 @@ but is not supported. To install Gitea via `brew`: brew install gitea ``` -# Unofficial packages +## Unofficial packages -## Alpine Linux +### Alpine Linux Alpine Linux has [Gitea](https://pkgs.alpinelinux.org/packages?name=gitea&branch=edge) in its community repository which follows the latest stable version. @@ -37,7 +39,7 @@ Alpine Linux has [Gitea](https://pkgs.alpinelinux.org/packages?name=gitea&branch apk add gitea ``` -## Arch Linux +### Arch Linux The rolling release distribution has [Gitea](https://www.archlinux.org/packages/extra/x86_64/gitea/) in their official extra repository and package updates are provided with new Gitea releases. @@ -45,7 +47,7 @@ The rolling release distribution has [Gitea](https://www.archlinux.org/packages/ pacman -S gitea ``` -## Arch Linux ARM +### Arch Linux ARM Arch Linux ARM provides packages for [aarch64](https://archlinuxarm.org/packages/aarch64/gitea), [armv7h](https://archlinuxarm.org/packages/armv7h/gitea) and [armv6h](https://archlinuxarm.org/packages/armv6h/gitea). @@ -53,7 +55,7 @@ Arch Linux ARM provides packages for [aarch64](https://archlinuxarm.org/packages pacman -S gitea ``` -## Gentoo Linux +### Gentoo Linux The rolling release distribution has [Gitea](https://packages.gentoo.org/packages/www-apps/gitea) in their official community repository and package updates are provided with new Gitea releases. @@ -61,20 +63,21 @@ The rolling release distribution has [Gitea](https://packages.gentoo.org/package emerge gitea -va ``` -## Canonical Snap +### Canonical Snap There is a [Gitea Snap](https://snapcraft.io/gitea) package which follows the latest stable version. +*Note: The Gitea snap package is [strictly confined](https://snapcraft.io/docs/snap-confinement). Strictly confined snaps run in complete isolation, so some of the Gitea functionals may not work with the confinement* ```sh snap install gitea ``` -## SUSE and openSUSE +### SUSE and openSUSE OpenSUSE build service provides packages for [openSUSE and SLE](https://software.opensuse.org/download/package?package=gitea&project=devel%3Atools%3Ascm) in the Development Software Configuration Management Repository -## Windows +### Windows There is a [Gitea](https://chocolatey.org/packages/gitea) package for Windows by [Chocolatey](https://chocolatey.org/). @@ -84,7 +87,7 @@ choco install gitea Or follow the [deployment from binary](installation/from-binary.md) guide. -## FreeBSD +### FreeBSD A FreeBSD port `www/gitea` is available. To install the pre-built binary package: @@ -107,7 +110,7 @@ is in `/usr/local/etc/rc.d/gitea`. To enable Gitea to run as a service, run `sysrc gitea_enable=YES` and start it with `service gitea start`. -## Others +### Others Various other third-party packages of Gitea exist. To see a curated list, head over to [awesome-gitea](https://gitea.com/gitea/awesome-gitea/src/branch/master/README.md#user-content-packages). diff --git a/docs/content/installation/upgrade-from-gogs.en-us.md b/docs/content/installation/upgrade-from-gogs.en-us.md deleted file mode 100644 index 47cddc1c30522..0000000000000 --- a/docs/content/installation/upgrade-from-gogs.en-us.md +++ /dev/null @@ -1,112 +0,0 @@ ---- -date: "2016-12-01T16:00:00+02:00" -title: "Upgrade from Gogs" -slug: "upgrade-from-gogs" -sidebar_position: 101 -toc: false -draft: false -aliases: - - /en-us/upgrade-from-gogs -menu: - sidebar: - parent: "installation" - name: "Upgrade From Gogs" - sidebar_position: 101 - identifier: "upgrade-from-gogs" ---- - -# Upgrade from Gogs - -Gogs, version 0.9.146 and older, can be easily migrated to Gitea. - -There are some basic steps to follow. On a Linux system run as the Gogs user: - -* Create a Gogs backup with `gogs backup`. This creates `gogs-backup-[timestamp].zip` file - containing all important Gogs data. You would need it if you wanted to move to the `gogs` back later. -* Download the file matching the destination platform from the [downloads page](https://dl.gitea.com/gitea/). - It should be `1.0.x` version. Migrating from `gogs` to any other version is impossible. -* Put the binary at the desired install location. -* Copy `gogs/custom/conf/app.ini` to `gitea/custom/conf/app.ini`. -* Copy custom `templates, public` from `gogs/custom/` to `gitea/custom/`. -* For any other custom folders, such as `gitignore, label, license, locale, readme` in - `gogs/custom/conf`, copy them to `gitea/custom/options`. -* Copy `gogs/data/` to `gitea/data/`. It contains issue attachments and avatars. -* Verify by starting Gitea with `gitea web`. -* Enter Gitea admin panel on the UI, run `Rewrite '.ssh/authorized_keys' file`. -* Launch every major version of the binary ( `1.1.4` → `1.2.3` → `1.3.4` → `1.4.2` → etc ) to migrate database. -* If custom or config path was changed, run `Rewrite all update hook of repositories`. - -## Change gogs specific information - -* Rename `gogs-repositories/` to `gitea-repositories/` -* Rename `gogs-data/` to `gitea-data/` -* In `gitea/custom/conf/app.ini` change: - - FROM: - - ```ini - [database] - PATH = /home/:USER/gogs/data/:DATABASE.db - [attachment] - PATH = /home/:USER/gogs-data/attachments - [picture] - AVATAR_UPLOAD_PATH = /home/:USER/gogs-data/avatars - [log] - ROOT_PATH = /home/:USER/gogs/log - ``` - - TO: - - ```ini - [database] - PATH = /home/:USER/gitea/data/:DATABASE.db - [attachment] - PATH = /home/:USER/gitea-data/attachments - [picture] - AVATAR_UPLOAD_PATH = /home/:USER/gitea-data/avatars - [log] - ROOT_PATH = /home/:USER/gitea/log - ``` - -* Verify by starting Gitea with `gitea web` - -## Upgrading to most recent `gitea` version - -After successful migration from `gogs` to `gitea 1.0.x`, it is possible to upgrade `gitea` to a modern version -in a two steps process. - -Upgrade to [`gitea 1.6.4`](https://dl.gitea.com/gitea/1.6.4/) first. Download the file matching -the destination platform from the [downloads page](https://dl.gitea.com/gitea/1.6.4/) and replace the binary. -Run Gitea at least once and check that everything works as expected. - -Then repeat the procedure, but this time using the [latest release](https://dl.gitea.com/gitea/@version@/). - -## Upgrading from a more recent version of Gogs - -Upgrading from a more recent version of Gogs (up to `0.11.x`) may also be possible, but will require a bit more work. -See [#4286](https://github.com/go-gitea/gitea/issues/4286), which includes various Gogs `0.11.x` versions. - -Upgrading from Gogs `0.12.x` and above will be increasingly more difficult as the projects diverge further apart in configuration and schema. - -## Troubleshooting - -* If errors are encountered relating to custom templates in the `gitea/custom/templates` - folder, try moving the templates causing the errors away one by one. They may not be - compatible with Gitea or an update. - -## Add Gitea to startup on Unix - -Update the appropriate file from [gitea/contrib](https://github.com/go-gitea/gitea/tree/main/contrib) -with the right environment variables. - -For distros with systemd: - -* Copy the updated script to `/etc/systemd/system/gitea.service` -* Add the service to the startup with: `sudo systemctl enable gitea` -* Disable old gogs startup script: `sudo systemctl disable gogs` - -For distros with SysVinit: - -* Copy the updated script to `/etc/init.d/gitea` -* Add the service to the startup with: `sudo rc-update add gitea` -* Disable old gogs startup script: `sudo rc-update del gogs` diff --git a/docs/content/installation/upgrade-from-gogs.fr-fr.md b/docs/content/installation/upgrade-from-gogs.fr-fr.md deleted file mode 100644 index a5cd87598251d..0000000000000 --- a/docs/content/installation/upgrade-from-gogs.fr-fr.md +++ /dev/null @@ -1,85 +0,0 @@ ---- -date: "2017-08-23T09:00:00+02:00" -title: "Mise à jour depuis Gogs" -slug: "upgrade-from-gogs" -sidebar_position: 101 -toc: false -draft: false -aliases: - - /fr-fr/upgrade-from-gogs -menu: - sidebar: - parent: "installation" - name: "Depuis Gogs" - sidebar_position: 101 - identifier: "upgrade-from-gogs" ---- - -# Mise à jour depuis Gogs - -À partir de la version 0.9.146 (schéma de la base de données : version 15) de Gogs, Il est possible de migrer vers Gitea simplement et sans encombre. - -Veuillez suivre les étapes ci-dessous. Sur Unix, toute les commandes s'exécutent en tant que l'utilisateur utilisé pour votre installation de Gogs : - -* Crééer une sauvegarde de Gogs avec la commande `gogs dump`. Le fichier nouvellement créé `gogs-dump-[timestamp].zip` contient toutes les données de votre instance de Gogs. -* Téléchargez le fichier correspondant à votre plateforme à partir de la [page de téléchargements](https://dl.gitea.com/gitea). -* Mettez la binaire dans le répertoire d'installation souhaité. -* Copiez le fichier `gogs/custom/conf/app.ini` vers `gitea/custom/conf/app.ini`. -* Si vous avez personnalisé les répertoires `templates, public` dans `gogs/custom/`, copiez-les vers `gitea/custom/`. -* Si vous avez d'autres répertoires personnalisés comme `gitignore, label, license, locale, readme` dans `gogs/custom/conf` copiez-les vers `gitea/custom/options`. -* Copiez le répertoire `gogs/data/` vers `gitea/data/`. -* Vérifiez votre installation en exécutant Gitea avec la commande `gitea web`. -* Lancez le binaire de version majeure en version majeure ( `1.1.4` → `1.2.3` → `1.3.4` → `1.4.2` → etc ) afin de récupérer les migrations de base de données. -* Connectez vous au panel d'administration de Gitea et exécutez l'action `Rewrite '.ssh/authorized_keys' file`, puis l'action `Rewrite all update hook of repositories` (obligatoire si le chemin menant à votre configuration personnalisée à changé). - -## Modifier les informations spécifiques de gogs - -* Renommez `gogs-repositories/` vers `gitea-repositories/` -* Renommez `gogs-data/` to `gitea-data/` -* Dans votre fichier `gitea/custom/conf/app.ini`, modifiez les éléments suivants: - - DE : - - ```ini - [database] - PATH = /home/:USER/gogs/data/:DATABASE.db - [attachment] - PATH = /home/:USER/gogs-data/attachments - [picture] - AVATAR_UPLOAD_PATH = /home/:USER/gogs-data/avatars - [log] - ROOT_PATH = /home/:USER/gogs/log - ``` - - VERS : - - ```ini - [database] - PATH = /home/:USER/gitea/data/:DATABASE.db - [attachment] - PATH = /home/:USER/gitea-data/attachments - [picture] - AVATAR_UPLOAD_PATH = /home/:USER/gitea-data/avatars - [log] - ROOT_PATH = /home/:USER/gitea/log - ``` - -* Vérifiez votre installation en exécutant Gitea avec la commande `gitea web`. - -## Dépannage - -* Si vous rencontrez des erreurs relatives à des modèles personnalisés dans le dossier `gitea/custom/templates`, essayez de déplacer un par un les modèles provoquant les erreurs. Il est possible qu'ils ne soient pas compatibles avec Gitea. - -## Démarrer automatiquement Gitea (Unix) - -Distributions utilisant systemd: - -* Copiez le script mis à jour vers `/etc/systemd/system/gitea.service` -* Ajoutez le service avec la commande `sudo systemctl enable gitea` -* Désactivez Gogs avec la commande `sudo systemctl disable gogs` - -Distributions utilisant SysVinit: - -* Copiez le script mis à jour vers `/etc/init.d/gitea` -* Ajoutez le service avec la commande `sudo rc-update add gitea` -* Désactivez Gogs avec la commande `sudo rc-update del gogs` diff --git a/docs/content/installation/upgrade-from-gogs.zh-cn.md b/docs/content/installation/upgrade-from-gogs.zh-cn.md deleted file mode 100644 index 29788c929f244..0000000000000 --- a/docs/content/installation/upgrade-from-gogs.zh-cn.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -date: "2016-12-01T16:00:00+02:00" -title: "从 Gogs 升级" -slug: "upgrade-from-gogs" -sidebar_position: 101 -toc: false -draft: false -aliases: - - /zh-cn/upgrade-from-gogs -menu: - sidebar: - parent: "installation" - name: "从 Gogs 升级" - sidebar_position: 101 - identifier: "upgrade-from-gogs" ---- - -# 从 Gogs 升级 - -如果你正在运行Gogs 0.9.146以下版本,你可以平滑的升级到Gitea。该升级需要如下的步骤: - -* 使用 `gogs backup` 创建 Gogs 备份。这会创建一个名为 `gogs-backup-[时间戳].zip` 的文件,其中包含所有重要的 Gogs 数据。如果您将来想要返回到 `gogs`,您会需要这个备份文件。 -* 从 [下载页面](https://dl.gitea.com/gitea/) 下载适用于目标平台的文件。应该选择 `1.0.x` 版本。从 `gogs` 迁移到其他任何版本是不可能的。 -* 将二进制文件放置在所需的安装位置。 -* 将 `gogs/custom/conf/app.ini` 复制到 `gitea/custom/conf/app.ini`。 -* 将 `gogs/custom/` 中的自定义 `templates, public` 复制到 `gitea/custom/`。 -* 对于其他自定义文件夹,例如 `gogs/custom/conf` 中的 `gitignore, label, license, locale, readme`,将它们复制到 `gitea/custom/options`。 -* 将 `gogs/data/` 复制到 `gitea/data/`。其中包含问题附件和头像。 -* 使用 `gitea web` 启动 Gitea 进行验证。 -* 在 UI 上进入 Gitea 管理面板,运行 `Rewrite '.ssh/authorized_keys' file`。 -* 启动每个主要版本的二进制文件(例如 `1.1.4` → `1.2.3` → `1.3.4` → `1.4.2` → 等)以迁移数据库。 -* 如果自定义或配置路径已更改,请运行 `Rewrite all update hook of repositories`。 - -## 更改特定于 Gogs 的信息 - -* 将 `gogs-repositories/` 重命名为 `gitea-repositories/` -* 将 `gogs-data/` 重命名为 `gitea-data/` -* 在 `gitea/custom/conf/app.ini` 中进行更改: -从: - - ```ini - [database] - PATH = /home/:USER/gogs/data/:DATABASE.db - [attachment] - PATH = /home/:USER/gogs-data/attachments - [picture] - AVATAR_UPLOAD_PATH = /home/:USER/gogs-data/avatars - [log] - ROOT_PATH = /home/:USER/gogs/log - ``` - -到: - - ```ini - [database] - PATH = /home/:USER/gitea/data/:DATABASE.db - [attachment] - PATH = /home/:USER/gitea-data/attachments - [picture] - AVATAR_UPLOAD_PATH = /home/:USER/gitea-data/avatars - [log] - ROOT_PATH = /home/:USER/gitea/log - ``` - -* 使用 `gitea web` 启动 Gitea 进行验证 - -## 升级到最新版本的 `gitea` - -在成功从 `gogs` 迁移到 `gitea 1.0.x` 之后,可以通过两步过程将 `gitea` 升级到现代版本。 - -首先升级到 [`gitea 1.6.4`](https://dl.gitea.com/gitea/1.6.4/)。从 [下载页面](https://dl.gitea.com/gitea/1.6.4/) 下载适用于目标平台的文件,并替换二进制文件。至少运行一次 Gitea 并检查是否一切正常。 - -然后重复这个过程,但这次使用 [最新版本](https://dl.gitea.com/gitea/@version@/)。 - -## 从较新的 Gogs 版本升级 - -从较新的 Gogs 版本(最高到 `0.11.x`)可能也是可能的,但需要更多的工作。 -请参见 [#4286](https://github.com/go-gitea/gitea/issues/4286),其中包括各种 Gogs `0.11.x` 版本。 - -从 Gogs `0.12.x` 及更高版本升级将变得越来越困难,因为项目在配置和架构上逐渐分歧。 - -## 故障排除 - -* 如果在 `gitea/custom/templates` 文件夹中遇到与自定义模板相关的错误,请尝试逐个移除引发错误的模板。 - 它们可能与 Gitea 或更新不兼容。 - -## 将 Gitea 添加到 Unix 的启动项 - -从 [gitea/contrib](https://github.com/go-gitea/gitea/tree/main/contrib) 更新适当的文件,确保正确的环境变量。 - -对于使用 systemd 的发行版: - -* 将更新后的脚本复制到 `/etc/systemd/system/gitea.service` -* 使用以下命令将服务添加到启动项:`sudo systemctl enable gitea` -* 禁用旧的 gogs 启动脚本:`sudo systemctl disable gogs` - -对于使用 SysVinit 的发行版: - -* 将更新后的脚本复制到 `/etc/init.d/gitea` -* 使用以下命令将服务添加到启动项:`sudo rc-update add gitea` -* 禁用旧的 gogs 启动脚本:`sudo rc-update del gogs` diff --git a/docs/content/installation/upgrade-from-gogs.zh-tw.md b/docs/content/installation/upgrade-from-gogs.zh-tw.md deleted file mode 100644 index ef5737bc6d2da..0000000000000 --- a/docs/content/installation/upgrade-from-gogs.zh-tw.md +++ /dev/null @@ -1,107 +0,0 @@ ---- -date: "2016-12-01T16:00:00+02:00" -title: "從 Gogs 升級" -slug: "upgrade-from-gogs" -sidebar_position: 101 -toc: false -draft: false -aliases: - - /zh-tw/upgrade-from-gogs -menu: - sidebar: - parent: "installation" - name: "從 Gogs 升級" - sidebar_position: 101 - identifier: "upgrade-from-gogs" ---- - -# 從 Gogs 升級 - -**目錄** - -若您正在執行 Gogs 0.9.146 以下版本,您可以很簡單地遷移到 Gitea。 - -請參考下列步驟。在 Linux 系統上請以 Gogs 的使用者身份執行: - -- 使用 `gogs backup` 建立 Gogs 的備份。這會建立檔案 `gogs-backup-[timestamp].zip` 包含所有重要的 Gogs 資料。 - 如果稍後您要恢復到 `gogs` 時會用到它。 -- 從[下載頁](https://dl.gitea.com/gitea/)下載對應您平臺的檔案。請下載 `1.0.x` 版,從 `gogs` 遷移到其它版本是不可行的。 -- 將二進位檔放到適當的安裝位置。 -- 複製 `gogs/custom/conf/app.ini` 到 `gitea/custom/conf/app.ini`。 -- 從 `gogs/custom/` 複製自訂 `templates, public` 到 `gitea/custom/`。 -- `gogs/custom/conf` 中的其它自訂資料夾如: `gitignore, label, license, locale, readme`, - 請複製到 `gitea/custom/options`。 -- 複製 `gogs/data/` 到 `gitea/data/`。它包含了問題附件和大頭貼。 -- 以指令 `gitea web` 啟動 Gitea 驗證上列設定是否正確。 -- 從網頁 UI 進入 Gitea 管理員面板, 執行 `Rewrite '.ssh/authorized_keys' file`。 -- 執行每個主要版本的二進位檔 ( `1.1.4` → `1.2.3` → `1.3.4` → `1.4.2` → 等等 ) 以遷移資料庫。 -- 如果變更了自訂檔、設定檔路徑,請執行 `Rewrite all update hook of repositories`。 - -## 修改指定的 gogs 資訊 - -- 重新命名 `gogs-repositories/` 為 `gitea-repositories/` -- 重新命名 `gogs-data/` 為 `gitea-data/` -- 在 `gitea/custom/conf/app.ini` 中修改: - - 修改前: - - ```ini - [database] - PATH = /home/:USER/gogs/data/:DATABASE.db - [attachment] - PATH = /home/:USER/gogs-data/attachments - [picture] - AVATAR_UPLOAD_PATH = /home/:USER/gogs-data/avatars - [log] - ROOT_PATH = /home/:USER/gogs/log - ``` - - 修改後: - - ```ini - [database] - PATH = /home/:USER/gitea/data/:DATABASE.db - [attachment] - PATH = /home/:USER/gitea-data/attachments - [picture] - AVATAR_UPLOAD_PATH = /home/:USER/gitea-data/avatars - [log] - ROOT_PATH = /home/:USER/gitea/log - ``` - -- 執行 `gitea web` 啟動 Gitea 檢查是否正確執行 - -## 升級到最新版的 `gitea` - -成功從 `gogs` 升級到 `gitea 1.0.x` 後再用 2 個步驟即可升級到最新版的 `gitea`。 - -請先升級到 [`gitea 1.6.4`](https://dl.gitea.com/gitea/1.6.4/),先從[下載頁](https://dl.gitea.com/gitea/1.6.4/)下載 -您平臺的二進位檔取代既有的。至少執行一次 Gitea 並確認一切符合預期。 - -接著重複上述步驟,但這次請使用[最新發行版本](https://dl.gitea.com/gitea/@version@/)。 - -## 從更新版本的 Gogs 升級 - -您也可以從更新版本的 Gogs 升級,但需要更多步驟。 -請參考 [#4286](https://github.com/go-gitea/gitea/issues/4286)。 - -## 疑難排解 - -- 如果錯誤和 `gitea/custom/templates` 中 的自訂樣板有關,請試著逐一移除它們。 - 它們可能和 Gitea 或更新不相容。 - -## 在 Unix 啟動時執行 Gitea - -從 [gitea/contrib](https://github.com/go-gitea/gitea/tree/master/contrib) 更新必要的檔案以取得正確的環境變數。 - -使用 systemd 的發行版: - -- 複製新的腳本到 `/etc/systemd/system/gitea.service` -- 啟動系統時執行服務: `sudo systemctl enable gitea` -- 停用舊的 gogs 腳本: `sudo systemctl disable gogs` - -使用 SysVinit 的發行版: - -- 複製新的腳本到 `/etc/init.d/gitea` -- 啟動系統時執行服務: `sudo rc-update add gitea` -- 停用舊的 gogs 腳本: `sudo rc-update del gogs` diff --git a/docs/content/usage/linked-references.zh-cn.md b/docs/content/usage/linked-references.zh-cn.md index 4d63d7540668d..2f1b888047c6f 100644 --- a/docs/content/usage/linked-references.zh-cn.md +++ b/docs/content/usage/linked-references.zh-cn.md @@ -113,7 +113,7 @@ menu: ## 外部跟踪器 -Gitea 支持使用外部工单跟踪器,并可以在合并请求中创建对外部托管的工单的引用。但是,如果外部跟踪器使用数字来标识工单,那么它们将与 Gitea 中托管的合并请求无法区分。为了解决这个工单,Gitea 允许使用 `!` 标记来标识合并请求。例如: +Gitea 支持使用外部工单跟踪器,并可以在合并请求中创建对外部托管的工单的引用。但是,如果外部跟踪器使用数字来标识工单,那么它们将与 Gitea 中托管的合并请求无法区分。为了解决这个问题,Gitea 允许使用 `!` 标记来标识合并请求。例如: > 这是工单 [#1234](#),并链接到外部跟踪器。 > 这是合并请求 [!1234](#),并链接到 Gitea 中的合并请求。 diff --git a/docs/content/usage/template-repositories.en-us.md b/docs/content/usage/template-repositories.en-us.md index 4618d10f3199d..e57ed85cc9cf9 100644 --- a/docs/content/usage/template-repositories.en-us.md +++ b/docs/content/usage/template-repositories.en-us.md @@ -17,9 +17,14 @@ menu: # Template Repositories -Gitea `1.11.0` and above includes template repositories, and one feature implemented with them is auto-expansion of specific variables within your template files. +Gitea (starting with version `1.11.0`) supports creating template repositories +which can be used to generate repositories based on the template, complete with +variable expansion of certain pre-defined variables. -To tell Gitea which files to expand, you must include a `template` file inside the `.gitea` directory of the template repository. +All files in the template repository are included in a generated repository from the +template except for the `.gitea/template` file. The `.gitea/template` file tells +Gitea which files are subject to the variable expansion when creating a +repository from the template. Gitea uses [gobwas/glob](https://github.com/gobwas/glob) for its glob syntax. It closely resembles a traditional `.gitignore`, however there may be slight differences. @@ -28,7 +33,7 @@ Gitea uses [gobwas/glob](https://github.com/gobwas/glob) for its glob syntax. It All paths are relative to the base of the repository ```gitignore -# All .go files, anywhere in the repository +# Expand all .go files, anywhere in the repository **.go # All text files in the text directory @@ -41,8 +46,6 @@ a/b/c/d.json **.[bB][aA][tT] ``` -**NOTE:** The `template` file will be removed from the `.gitea` directory when a repository is generated from the template. - ## Variable Expansion In any file matched by the above globs, certain variables will be expanded. diff --git a/go.mod b/go.mod index 94ee158cb8037..38afc33b36269 100644 --- a/go.mod +++ b/go.mod @@ -30,23 +30,23 @@ require ( github.com/djherbis/nio/v3 v3.0.1 github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 github.com/dustin/go-humanize v1.0.1 - github.com/editorconfig/editorconfig-core-go/v2 v2.5.2 + github.com/editorconfig/editorconfig-core-go/v2 v2.6.0 github.com/emersion/go-imap v1.2.1 github.com/emirpasic/gods v1.18.1 github.com/ethantkoenig/rupture v1.0.1 github.com/felixge/fgprof v0.9.3 github.com/fsnotify/fsnotify v1.6.0 github.com/gliderlabs/ssh v0.3.5 - github.com/go-ap/activitypub v0.0.0-20230807182453-602f717f6ca3 + github.com/go-ap/activitypub v0.0.0-20231003111253-1fba3772399b github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73 github.com/go-chi/chi/v5 v5.0.10 github.com/go-chi/cors v1.2.1 github.com/go-co-op/gocron v1.31.1 - github.com/go-enry/go-enry/v2 v2.8.5 + github.com/go-enry/go-enry/v2 v2.8.6 github.com/go-fed/httpsig v1.1.1-0.20201223112313-55836744818e - github.com/go-git/go-billy/v5 v5.4.1 - github.com/go-git/go-git/v5 v5.8.1 - github.com/go-ldap/ldap/v3 v3.4.5 + github.com/go-git/go-billy/v5 v5.5.0 + github.com/go-git/go-git/v5 v5.9.0 + github.com/go-ldap/ldap/v3 v3.4.6 github.com/go-sql-driver/mysql v1.7.1 github.com/go-swagger/go-swagger v0.30.5 github.com/go-testfixtures/testfixtures/v3 v3.9.0 @@ -56,40 +56,40 @@ require ( github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85 github.com/golang-jwt/jwt/v5 v5.0.0 github.com/google/go-github/v53 v53.2.0 - github.com/google/pprof v0.0.0-20230901174712-0191c66da455 + github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98 github.com/google/uuid v1.3.1 github.com/gorilla/feeds v1.1.1 github.com/gorilla/sessions v1.2.1 github.com/hashicorp/go-version v1.6.0 - github.com/hashicorp/golang-lru/v2 v2.0.6 + github.com/hashicorp/golang-lru/v2 v2.0.7 github.com/huandu/xstrings v1.4.0 github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056 - github.com/jhillyerd/enmime v1.0.0 + github.com/jhillyerd/enmime v1.0.1 github.com/json-iterator/go v1.1.12 github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 github.com/keybase/go-crypto v0.0.0-20200123153347-de78d2cb44f4 - github.com/klauspost/compress v1.16.7 + github.com/klauspost/compress v1.17.0 github.com/klauspost/cpuid/v2 v2.2.5 github.com/lib/pq v1.10.9 - github.com/markbates/goth v1.77.0 + github.com/markbates/goth v1.78.0 github.com/mattn/go-isatty v0.0.19 github.com/mattn/go-sqlite3 v1.14.17 - github.com/meilisearch/meilisearch-go v0.25.0 + github.com/meilisearch/meilisearch-go v0.25.1 github.com/mholt/archiver/v3 v3.5.1 github.com/microcosm-cc/bluemonday v1.0.25 github.com/minio/minio-go/v7 v7.0.63 github.com/minio/sha256-simd v1.0.1 - github.com/msteinert/pam v1.1.0 - github.com/nektos/act v0.2.48 + github.com/msteinert/pam v1.2.0 + github.com/nektos/act v0.2.52 github.com/niklasfasching/go-org v1.7.0 github.com/olivere/elastic/v7 v7.0.32 github.com/opencontainers/go-digest v1.0.0 - github.com/opencontainers/image-spec v1.1.0-rc4 + github.com/opencontainers/image-spec v1.1.0-rc5 github.com/pkg/errors v0.9.1 github.com/pquerna/otp v1.4.0 - github.com/prometheus/client_golang v1.16.0 + github.com/prometheus/client_golang v1.17.0 github.com/quasoft/websspi v1.1.2 - github.com/redis/go-redis/v9 v9.1.0 + github.com/redis/go-redis/v9 v9.2.1 github.com/robfig/cron/v3 v3.0.1 github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 github.com/sassoftware/go-rpmutils v0.2.0 @@ -100,19 +100,19 @@ require ( github.com/tstranex/u2f v1.0.0 github.com/ulikunitz/xz v0.5.11 github.com/urfave/cli/v2 v2.25.7 - github.com/xanzy/go-gitlab v0.91.0 + github.com/xanzy/go-gitlab v0.93.0 github.com/xeipuuv/gojsonschema v1.2.0 github.com/yohcop/openid-go v1.0.1 github.com/yuin/goldmark v1.5.6 github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc github.com/yuin/goldmark-meta v1.1.0 - golang.org/x/crypto v0.12.0 + golang.org/x/crypto v0.14.0 golang.org/x/image v0.11.0 - golang.org/x/net v0.14.0 - golang.org/x/oauth2 v0.11.0 - golang.org/x/sys v0.12.0 + golang.org/x/net v0.16.0 + golang.org/x/oauth2 v0.13.0 + golang.org/x/sys v0.13.0 golang.org/x/text v0.13.0 - golang.org/x/tools v0.12.0 + golang.org/x/tools v0.14.0 google.golang.org/grpc v1.57.0 google.golang.org/protobuf v1.31.0 gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df @@ -130,14 +130,14 @@ require ( dario.cat/mergo v1.0.0 // indirect git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 // indirect github.com/ClickHouse/ch-go v0.58.2 // indirect - github.com/ClickHouse/clickhouse-go/v2 v2.13.4 // indirect + github.com/ClickHouse/clickhouse-go/v2 v2.14.2 // indirect github.com/DataDog/zstd v1.5.5 // indirect github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver/v3 v3.2.1 // indirect github.com/Masterminds/sprig/v3 v3.2.3 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect - github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect - github.com/RoaringBitmap/roaring v1.5.0 // indirect + github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c // indirect + github.com/RoaringBitmap/roaring v1.6.0 // indirect github.com/acomagu/bufpipe v1.0.4 // indirect github.com/andybalholm/brotli v1.0.5 // indirect github.com/andybalholm/cascadia v1.3.2 // indirect @@ -170,6 +170,7 @@ require ( github.com/couchbase/gomemcached v0.2.1 // indirect github.com/couchbase/goutils v0.1.2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect + github.com/cyphar/filepath-securejoin v0.2.4 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/dlclark/regexp2 v1.10.0 // indirect @@ -177,8 +178,8 @@ require ( github.com/fatih/color v1.15.0 // indirect github.com/felixge/httpsnoop v1.0.3 // indirect github.com/fxamacker/cbor/v2 v2.5.0 // indirect - github.com/go-ap/errors v0.0.0-20221205040414-01c1adfc98ea // indirect - github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect + github.com/go-ap/errors v0.0.0-20231003111023-183eef4b31b7 // indirect + github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect github.com/go-enry/go-oniguruma v1.2.1 // indirect github.com/go-faster/city v1.0.1 // indirect github.com/go-faster/errors v0.6.1 // indirect @@ -209,9 +210,7 @@ require ( github.com/gorilla/handlers v1.5.1 // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/gorilla/securecookie v1.1.1 // indirect - github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-retryablehttp v0.7.4 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/imdario/mergo v0.3.16 // indirect @@ -230,7 +229,7 @@ require ( github.com/mattn/go-runewidth v0.0.15 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mholt/acmez v1.2.0 // indirect - github.com/miekg/dns v1.1.55 // indirect + github.com/miekg/dns v1.1.56 // indirect github.com/minio/md5-simd v1.1.2 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect @@ -243,18 +242,16 @@ require ( github.com/oklog/ulid v1.3.1 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/onsi/ginkgo v1.16.5 // indirect - github.com/onsi/gomega v1.27.8 // indirect github.com/paulmach/orb v0.10.0 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect github.com/pierrec/lz4/v4 v4.1.18 // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_model v0.4.0 // indirect + github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect github.com/prometheus/common v0.44.0 // indirect github.com/prometheus/procfs v0.11.1 // indirect - github.com/rhysd/actionlint v1.6.25 // indirect + github.com/rhysd/actionlint v1.6.26 // indirect github.com/rivo/uniseg v0.4.4 // indirect - github.com/robfig/cron v1.2.0 // indirect github.com/rogpeppe/go-internal v1.11.0 // indirect github.com/rs/xid v1.5.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect @@ -262,7 +259,7 @@ require ( github.com/shopspring/decimal v1.3.1 // indirect github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c // indirect github.com/sirupsen/logrus v1.9.3 // indirect - github.com/skeema/knownhosts v1.2.0 // indirect + github.com/skeema/knownhosts v1.2.1 // indirect github.com/spf13/afero v1.9.5 // indirect github.com/spf13/cast v1.5.1 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect @@ -273,7 +270,7 @@ require ( github.com/toqueteos/webbrowser v1.2.0 // indirect github.com/unknwon/com v1.0.1 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect - github.com/valyala/fasthttp v1.49.0 // indirect + github.com/valyala/fasthttp v1.50.0 // indirect github.com/valyala/fastjson v1.6.4 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect @@ -284,15 +281,15 @@ require ( github.com/zeebo/blake3 v0.2.3 // indirect go.etcd.io/bbolt v1.3.7 // indirect go.mongodb.org/mongo-driver v1.12.1 // indirect - go.opentelemetry.io/otel v1.17.0 // indirect - go.opentelemetry.io/otel/trace v1.17.0 // indirect + go.opentelemetry.io/otel v1.19.0 // indirect + go.opentelemetry.io/otel/trace v1.19.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.25.0 // indirect - golang.org/x/mod v0.12.0 // indirect - golang.org/x/sync v0.3.0 // indirect + go.uber.org/zap v1.26.0 // indirect + golang.org/x/mod v0.13.0 // indirect + golang.org/x/sync v0.4.0 // indirect golang.org/x/time v0.3.0 // indirect - google.golang.org/appengine v1.6.7 // indirect + google.golang.org/appengine v1.6.8 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/warnings.v0 v0.1.2 // indirect @@ -303,7 +300,7 @@ 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/nektos/act => gitea.com/gitea/act v0.243.4 +replace github.com/nektos/act => gitea.com/gitea/act v0.2.51 exclude github.com/gofrs/uuid v3.2.0+incompatible diff --git a/go.sum b/go.sum index 44bfa1029f91d..ae3bb5541baad 100644 --- a/go.sum +++ b/go.sum @@ -54,8 +54,8 @@ dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= 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= -gitea.com/gitea/act v0.243.4 h1:MuBHBLCJfpa6mzwwvs4xqQynrSP2RRzpHpWfTV16PmI= -gitea.com/gitea/act v0.243.4/go.mod h1:mabw6AZAiDgxGlK83orWLrNERSPvgBJzEUS3S7u2bHI= +gitea.com/gitea/act v0.2.51 h1:gXc/B4OlTciTTzAx9cmNyw04n2SDO7exPjAsR5Idu+c= +gitea.com/gitea/act v0.2.51/go.mod h1:CoaX2053jqBlD6JMgu4d4UgFL/rp2I14Kt5mMqcs0Z0= gitea.com/go-chi/binding v0.0.0-20230415142243-04b515c6d669 h1:RUBX+MK/TsDxpHmymaOaydfigEbbzqUnG1OTZU/HAeo= gitea.com/go-chi/binding v0.0.0-20230415142243-04b515c6d669/go.mod h1:77TZu701zMXWJFvB8gvTbQ92zQ3DQq/H7l5wAEjQRKc= gitea.com/go-chi/cache v0.0.0-20210110083709-82c4c9ce2d5e/go.mod h1:k2V/gPDEtXGjjMGuBJiapffAXTv76H4snSmlJRLUhH0= @@ -85,8 +85,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/ClickHouse/ch-go v0.58.2 h1:jSm2szHbT9MCAB1rJ3WuCJqmGLi5UTjlNu+f530UTS0= github.com/ClickHouse/ch-go v0.58.2/go.mod h1:Ap/0bEmiLa14gYjCiRkYGbXvbe8vwdrfTYWhsuQ99aw= -github.com/ClickHouse/clickhouse-go/v2 v2.13.4 h1:NcvYN9ONZn3vlPMfQVUBSG5LKz+1y2wk4vaaz5QZXIg= -github.com/ClickHouse/clickhouse-go/v2 v2.13.4/go.mod h1:u1AUh8E0XqN1sU1EDzbiGLTI4KWOd+lOHimNSsdyJec= +github.com/ClickHouse/clickhouse-go/v2 v2.14.2 h1:iYGP2bgPYJ33y6rCfZTQAPrnHt8wmsM3Ut4cLoYhWY0= +github.com/ClickHouse/clickhouse-go/v2 v2.14.2/go.mod h1:ZLn63wODwGxVdnGB0EIYmFL5tjtlLcLBuwQUH6B2sYk= github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= @@ -104,16 +104,16 @@ github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migc github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= -github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg= -github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= +github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c h1:kMFnB0vCcX7IL/m9Y5LO+KQYv+t1CQOiFe6+SV2J7bE= +github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= github.com/PuerkitoBio/goquery v1.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAcwmWM= github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/RoaringBitmap/roaring v0.4.23/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06Mq5mKs52e1TwOo= github.com/RoaringBitmap/roaring v0.7.1/go.mod h1:jdT9ykXwHFNdJbEtxePexlFYH9LXucApeS0/+/g+p1I= -github.com/RoaringBitmap/roaring v1.5.0 h1:V0VCSiHjroItEYCM3guC8T83ehi5QMt3oM9EefTTOms= -github.com/RoaringBitmap/roaring v1.5.0/go.mod h1:plvDsJQpxOC5bw8LRteu/MLWHsHez/3y6cubLI4/1yE= +github.com/RoaringBitmap/roaring v1.6.0 h1:dc7kRiroETgJcHhWX6BerXkZz2b3JgLGg9nTURJL/og= +github.com/RoaringBitmap/roaring v1.6.0/go.mod h1:plvDsJQpxOC5bw8LRteu/MLWHsHez/3y6cubLI4/1yE= github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ= github.com/acomagu/bufpipe v1.0.4/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= github.com/alecthomas/assert/v2 v2.2.1 h1:XivOgYcduV98QCahG8T5XTezV5bylXe+lBxLG2K2ink= @@ -143,8 +143,6 @@ github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3d github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= -github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= -github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bits-and-blooms/bitset v1.1.10/go.mod h1:w0XsmFg8qg6cmpTtJ0z3pKgjTDBMMnI/+I2syrE6XBE= @@ -204,10 +202,10 @@ github.com/boombuler/barcode v1.0.1/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl github.com/bradfitz/gomemcache v0.0.0-20190329173943-551aad21a668/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA= github.com/bradfitz/gomemcache v0.0.0-20230611145640-acc696258285 h1:Dr+ezPI5ivhMn/3WOoB86XzMhie146DNaBbhaQWZHMY= github.com/bradfitz/gomemcache v0.0.0-20230611145640-acc696258285/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA= -github.com/bsm/ginkgo/v2 v2.9.5 h1:rtVBYPs3+TC5iLUVOis1B9tjLTup7Cj5IfzosKtvTJ0= -github.com/bsm/ginkgo/v2 v2.9.5/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= -github.com/bsm/gomega v1.26.0 h1:LhQm+AFcgV2M0WyKroMASzAzCAJVpAxQXv4SaI9a69Y= -github.com/bsm/gomega v1.26.0/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= +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/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= +github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= github.com/bufbuild/connect-go v1.10.0 h1:QAJ3G9A1OYQW2Jbk3DeoJbkCxuKArrvZgDt47mjdTbg= github.com/bufbuild/connect-go v1.10.0/go.mod h1:CAIePUgkDR5pAFaylSMtNK45ANQjp9JvpluG20rhpV8= github.com/buildkite/terminal-to-html/v3 v3.9.1 h1:8SOCKFK9ntpYvPE3yUAXHiZYdQI4xf9o9S3wOX7x12A= @@ -258,6 +256,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76/go.mod h1:vYwsqCOLxGiisLwp9rITslkFNpZD5rz43tf41QFkTWY= +github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= +github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -287,12 +287,12 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/dvyukov/go-fuzz v0.0.0-20210429054444-fca39067bc72/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw= -github.com/editorconfig/editorconfig-core-go/v2 v2.5.2 h1:Z/G8cwnwOzGgTtvTutUhWPJ1ySUzuermioYMra7TuDQ= -github.com/editorconfig/editorconfig-core-go/v2 v2.5.2/go.mod h1:DoNm5QtDjTkizv0Oo1O+OJ92feoyUz3V4StZpOmP69E= +github.com/editorconfig/editorconfig-core-go/v2 v2.6.0 h1:5O8paxMLmi/5ONoKXzWNYxoSZU7+ITVbGcPga0IrzfE= +github.com/editorconfig/editorconfig-core-go/v2 v2.6.0/go.mod h1:hdTKe+hwa3mMnMn4JUQziT+yc3pF+6EVmK2LPbLZthE= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/elazarl/go-bindata-assetfs v1.0.1/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= -github.com/elazarl/goproxy v0.0.0-20221015165544-a0805db90819 h1:RIB4cRk+lBqKK3Oy0r2gRX4ui7tuhiZq2SuTtTCi0/0= -github.com/elazarl/goproxy v0.0.0-20221015165544-a0805db90819/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= +github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU= +github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= github.com/emersion/go-imap v1.2.1 h1:+s9ZjMEjOB8NzZMVTM3cCenz2JrQIGGo5j1df19WjTA= github.com/emersion/go-imap v1.2.1/go.mod h1:Qlx1FSx2FTxjnjWpIlVNEuX+ylerZQNFE5NsmKFSejY= github.com/emersion/go-message v0.15.0/go.mod h1:wQUEfE+38+7EW8p8aZ96ptg6bAb1iwdgej19uXASlE4= @@ -331,14 +331,14 @@ github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY= github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4= github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE= github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= -github.com/go-ap/activitypub v0.0.0-20230807182453-602f717f6ca3 h1:Lxp2XxNZ+2bqlpJbKeQme5kMf9NqPJQB1l2eZLJ7W/A= -github.com/go-ap/activitypub v0.0.0-20230807182453-602f717f6ca3/go.mod h1:qw0WNf+PTG69Xu6mVqUluDuKl1VwVYdgntOZQFBZQ48= -github.com/go-ap/errors v0.0.0-20221205040414-01c1adfc98ea h1:ywGtLGVjJjMrq4mu35Qmu+NtlhlTk/gTayE6Bb4tQZk= -github.com/go-ap/errors v0.0.0-20221205040414-01c1adfc98ea/go.mod h1:SaTNjEEkp0q+w3pUS1ccyEL/lUrHteORlDq/e21mCc8= +github.com/go-ap/activitypub v0.0.0-20231003111253-1fba3772399b h1:VLD6IPBDkqEsOZ+EfLO6MayuHycZ0cv4BStTlRoZduo= +github.com/go-ap/activitypub v0.0.0-20231003111253-1fba3772399b/go.mod h1:cJ9Ye0ZNSMN7RzZDBRY3E+8M3Bpf/R1JX22Ir9yX6WI= +github.com/go-ap/errors v0.0.0-20231003111023-183eef4b31b7 h1:I2nuhyVI/48VXoRCCZR2hYBgnSXa+EuDJf/VyX06TC0= +github.com/go-ap/errors v0.0.0-20231003111023-183eef4b31b7/go.mod h1:5x8a6P/dhmMGFxWLcyYlyOuJ2lRNaHGhRv+yu8BaTSI= github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73 h1:GMKIYXyXPGIp+hYiWOhfqK4A023HdgisDT4YGgf99mw= github.com/go-ap/jsonld v0.0.0-20221030091449-f2a191312c73/go.mod h1:jyveZeGw5LaADntW+UEsMjl3IlIwk+DxlYNsbofQkGA= -github.com/go-asn1-ber/asn1-ber v1.5.4 h1:vXT6d/FNDiELJnLb6hGNa309LMsrCoYFvpwHDF0+Y1A= -github.com/go-asn1-ber/asn1-ber v1.5.4/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= +github.com/go-asn1-ber/asn1-ber v1.5.5 h1:MNHlNMBDgEKD4TcKr36vQN68BA00aDfjIt3/bD50WnA= +github.com/go-asn1-ber/asn1-ber v1.5.5/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= github.com/go-chi/chi/v5 v5.0.1/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-chi/chi/v5 v5.0.4/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk= @@ -347,8 +347,8 @@ github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4= github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58= github.com/go-co-op/gocron v1.31.1 h1:LZAuBlU0t3SPGUMJGhrJ6VuCc3CsrYzkzicygvVWlfA= github.com/go-co-op/gocron v1.31.1/go.mod h1:39f6KNSGVOU1LO/ZOoZfcSxwlsJDQOKSu8erN0SH48Y= -github.com/go-enry/go-enry/v2 v2.8.5 h1:jtYXblst2+d9k7ZgEgkv6Q5hKRKPf0qHRjt715BZEX4= -github.com/go-enry/go-enry/v2 v2.8.5/go.mod h1:9yrj4ES1YrbNb1Wb7/PWYr2bpaCXUGRt0uafN0ISyG8= +github.com/go-enry/go-enry/v2 v2.8.6 h1:T6ljs5+qNiUTDqpfK5GUD5EvLNdDbf804u8iC30vw7U= +github.com/go-enry/go-enry/v2 v2.8.6/go.mod h1:9yrj4ES1YrbNb1Wb7/PWYr2bpaCXUGRt0uafN0ISyG8= github.com/go-enry/go-oniguruma v1.2.1 h1:k8aAMuJfMrqm/56SG2lV9Cfti6tC4x8673aHCcBk+eo= github.com/go-enry/go-oniguruma v1.2.1/go.mod h1:bWDhYP+S6xZQgiRL7wlTScFYBe023B6ilRZbCAD5Hf4= github.com/go-faster/city v1.0.1 h1:4WAxSZ3V2Ws4QRDrscLEDcibJY8uf41H6AhXDrNDcGw= @@ -359,18 +359,18 @@ github.com/go-fed/httpsig v1.1.1-0.20201223112313-55836744818e h1:oRq/fiirun5Hql github.com/go-fed/httpsig v1.1.1-0.20201223112313-55836744818e/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7xsT7bM= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= -github.com/go-git/go-billy/v5 v5.4.1 h1:Uwp5tDRkPr+l/TnbHOQzp+tmJfLceOlbVucgpTz8ix4= -github.com/go-git/go-billy/v5 v5.4.1/go.mod h1:vjbugF6Fz7JIflbVpl1hJsGjSHNltrSw45YK/ukIvQg= +github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= +github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20230305113008-0c11038e723f h1:Pz0DHeFij3XFhoBRGUDPzSJ+w2UcK5/0JvF8DRI58r8= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20230305113008-0c11038e723f/go.mod h1:8LHG1a3SRW71ettAD/jW13h8c6AqjVSeL11RAdgaqpo= -github.com/go-git/go-git/v5 v5.8.1 h1:Zo79E4p7TRk0xoRgMq0RShiTHGKcKI4+DI6BfJc/Q+A= -github.com/go-git/go-git/v5 v5.8.1/go.mod h1:FHFuoD6yGz5OSKEBK+aWN9Oah0q54Jxl0abmj6GnqAo= +github.com/go-git/go-git/v5 v5.9.0 h1:cD9SFA7sHVRdJ7AYck1ZaAa/yeuBvGPxwXDL8cxrObY= +github.com/go-git/go-git/v5 v5.9.0/go.mod h1:RKIqga24sWdMGZF+1Ekv9kylsDz6LzdTSI2s/OsZWE0= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-ldap/ldap/v3 v3.4.5 h1:ekEKmaDrpvR2yf5Nc/DClsGG9lAmdDixe44mLzlW5r8= -github.com/go-ldap/ldap/v3 v3.4.5/go.mod h1:bMGIq3AGbytbaMwf8wdv5Phdxz0FWHTIYMSzyrYgnQs= +github.com/go-ldap/ldap/v3 v3.4.6 h1:ert95MdbiG7aWo/oPYp9btL3KJlMPKnP58r09rI8T+A= +github.com/go-ldap/ldap/v3 v3.4.6/go.mod h1:IGMQANNtxpsOzj7uUAMjpGBaOVTC4DYyIy8VsTdxmtc= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-openapi/analysis v0.21.2/go.mod h1:HZwRk4RRisyG8vx2Oe6aqeSQcoxRp47Xkp3+K6q+LdY= github.com/go-openapi/analysis v0.21.4 h1:ZDFLvSNxpDaomuCueM0BlSXxpANBlFYiBvr+GXrvIHc= @@ -425,8 +425,8 @@ github.com/go-swagger/go-swagger v0.30.5/go.mod h1:cWUhSyCNqV7J1wkkxfr5QmbcnCewe github.com/go-swagger/scan-repo-boundary v0.0.0-20180623220736-973b3573c013 h1:l9rI6sNaZgNC0LnF3MiE+qTmyBA/tZAg1rtyrGbUMK0= github.com/go-swagger/scan-repo-boundary v0.0.0-20180623220736-973b3573c013/go.mod h1:b65mBPzqzZWxOZGxSWrqs4GInLIn+u99Q9q7p+GKni0= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/go-test/deep v1.0.7 h1:/VSMRlnY/JSyqxQUzQLKVMAskpY/NZKFA5j2P+0pP2M= -github.com/go-test/deep v1.0.7/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V36o8= +github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg= +github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/go-testfixtures/testfixtures/v3 v3.9.0 h1:938g5V+GWLVejm3Hc+nWCuEXRlcglZDDlN/t1gWzcSY= github.com/go-testfixtures/testfixtures/v3 v3.9.0/go.mod h1:cdsKD2ApFBjdog9jRsz6EJqF+LClq/hrwE9K/1Dzo4s= github.com/go-webauthn/webauthn v0.8.6 h1:bKMtL1qzd2WTFkf1mFTVbreYrwn7dsYmEPjTq6QN90E= @@ -509,6 +509,7 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -554,8 +555,8 @@ github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= -github.com/google/pprof v0.0.0-20230901174712-0191c66da455 h1:YhRUmI1ttDC4sxKY2V62BTI8hCXnyZBV9h38eAanInE= -github.com/google/pprof v0.0.0-20230901174712-0191c66da455/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= +github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98 h1:pUa4ghanp6q4IJHwE9RwLgmVFfReJN+KbQ8ExNEUUoQ= +github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -588,22 +589,17 @@ github.com/gorilla/sessions v1.1.1/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI= github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= -github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-hclog v1.2.0 h1:La19f8d7WIlm4ogzNHB0JGqs5AUDAZ2UfCY4sJXcJdM= github.com/hashicorp/go-hclog v1.2.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= -github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-retryablehttp v0.7.4 h1:ZQgVdpTdAL7WpMIwLzCfbalOcSUdkDZnpUv3/+BxzFA= github.com/hashicorp/go-retryablehttp v0.7.4/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru/v2 v2.0.6 h1:3xi/Cafd1NaoEnS/yDssIiuVeDVywU0QdFGl3aQaQHM= -github.com/hashicorp/golang-lru/v2 v2.0.6/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= @@ -677,8 +673,8 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOl github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc= github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= -github.com/jhillyerd/enmime v1.0.0 h1:8swYgO1fm68PllCKz5jiLzgD3axNUS388jr6BtRSsl8= -github.com/jhillyerd/enmime v1.0.0/go.mod h1:EktNOa/V6ka9yCrfoB2uxgefp1lno6OVdszW0iQ5LnM= +github.com/jhillyerd/enmime v1.0.1 h1:y6RyqIgBOI2hIinOXIzmeB+ITRVls0zTJIm5GwgXnjE= +github.com/jhillyerd/enmime v1.0.1/go.mod h1:LMMbm6oTlzWHghPavqHtOrP/NosVv3l42CUrZjn03/Q= github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= @@ -707,8 +703,8 @@ github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYs github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.15.6/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= -github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= -github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= +github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= @@ -761,8 +757,8 @@ github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJ github.com/markbates/going v1.0.0/go.mod h1:I6mnB4BPnEeqo85ynXIx1ZFLLbtiLHNXVgWeFO9OGOA= github.com/markbates/going v1.0.3 h1:mY45T5TvW+Xz5A6jY7lf4+NLg9D8+iuStIHyR7M8qsE= github.com/markbates/going v1.0.3/go.mod h1:fQiT6v6yQar9UD6bd/D4Z5Afbk9J6BBVBtLiyY4gp2o= -github.com/markbates/goth v1.77.0 h1:s3scqnWv/Zq/a5M766V0FKsLfOdFNdh/HEkuWCKbvT8= -github.com/markbates/goth v1.77.0/go.mod h1:X6xdNgpapSENS0O35iTBBcMHoJDQDfI9bJl+APCkYMc= +github.com/markbates/goth v1.78.0 h1:7VEIFDycJp9deyVv3YraGBPdD0ZYQW93Y3Aw1eVP3BY= +github.com/markbates/goth v1.78.0/go.mod h1:X6xdNgpapSENS0O35iTBBcMHoJDQDfI9bJl+APCkYMc= github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE= github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A= @@ -787,16 +783,16 @@ github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6 github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/meilisearch/meilisearch-go v0.25.0 h1:xIp+8YWterHuDvpdYlwQ4Qp7im3JlRHmSKiP0NvjyXs= -github.com/meilisearch/meilisearch-go v0.25.0/go.mod h1:SxuSqDcPBIykjWz1PX+KzsYzArNLSCadQodWs8extS0= +github.com/meilisearch/meilisearch-go v0.25.1 h1:D5wY22sn5kkpRH3uYMGlwltdUEq5regIFmO7awHz3Vo= +github.com/meilisearch/meilisearch-go v0.25.1/go.mod h1:SxuSqDcPBIykjWz1PX+KzsYzArNLSCadQodWs8extS0= github.com/mholt/acmez v1.2.0 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30= github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE= github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo= github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4= github.com/microcosm-cc/bluemonday v1.0.25 h1:4NEwSfiJ+Wva0VxN5B8OwMicaJvD8r9tlJWm9rtloEg= github.com/microcosm-cc/bluemonday v1.0.25/go.mod h1:ZIOjCQp1OrzBBPIJmfX4qDYFuhU02nx4bn030ixfHLE= -github.com/miekg/dns v1.1.55 h1:GoQ4hpsj0nFLYe+bWiCToyrBEJXkQfOOIvFGFy0lEgo= -github.com/miekg/dns v1.1.55/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY= +github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE= +github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY= github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34= github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM= github.com/minio/minio-go/v7 v7.0.63 h1:GbZ2oCvaUdgT5640WJOpyDhhDxvknAJU2/T3yurwcbQ= @@ -828,8 +824,8 @@ github.com/mrjones/oauth v0.0.0-20190623134757-126b35219450/go.mod h1:skjdDftzkF github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM= github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw= -github.com/msteinert/pam v1.1.0 h1:VhLun/0n0kQYxiRBJJvVpC2jR6d21SWJFjpvUVj20Kc= -github.com/msteinert/pam v1.1.0/go.mod h1:M4FPeAW8g2ITO68W8gACDz13NDJyOQM9IQsQhrR6TOI= +github.com/msteinert/pam v1.2.0 h1:mYfjlvN2KYs2Pb9G6nb/1f/nPfAttT/Jee5Sq9r3bGE= +github.com/msteinert/pam v1.2.0/go.mod h1:d2n0DCUK8rGecChV3JzvmsDjOY4R7AYbsNxAT+ftQl0= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/niklasfasching/go-org v1.7.0 h1:vyMdcMWWTe/XmANk19F4k8XGBYg0GQ/gJGMimOjGMek= github.com/niklasfasching/go-org v1.7.0/go.mod h1:WuVm4d45oePiE0eX25GqTDQIt/qPW1T9DGkRscqLW5o= @@ -857,12 +853,12 @@ github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= -github.com/onsi/gomega v1.27.8 h1:gegWiwZjBsf2DgiSbf5hpokZ98JVDMcWkUiigk6/KXc= -github.com/onsi/gomega v1.27.8/go.mod h1:2J8vzI/s+2shY9XHRApDkdgPo1TKT7P2u6fXeJKFnNQ= +github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= +github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.0-rc4 h1:oOxKUJWnFC4YGHCCMNql1x4YaDfYBTS5Y4x/Cgeo1E0= -github.com/opencontainers/image-spec v1.1.0-rc4/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= +github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= +github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= github.com/paulmach/orb v0.10.0 h1:guVYVqzxHE/CQ1KpfGO077TR0ATHSNjp4s6XGLn3W9s= github.com/paulmach/orb v0.10.0/go.mod h1:5mULz1xQfs3bmQm63QEJA6lNGujuRafwA5S/EnuLaLU= github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY= @@ -888,11 +884,11 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pquerna/otp v1.4.0 h1:wZvl1TIVxKRThZIBiwOOHOGP/1+nZyWBil9Y2XNEDzg= github.com/pquerna/otp v1.4.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= +github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= +github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 h1:v7DLqVdK4VrYkVD5diGdl4sxJurKJEMnODWRJlxV9oM= +github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= @@ -900,18 +896,16 @@ github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/ github.com/quasoft/websspi v1.1.2 h1:/mA4w0LxWlE3novvsoEL6BBA1WnjJATbjkh1kFrTidw= github.com/quasoft/websspi v1.1.2/go.mod h1:HmVdl939dQ0WIXZhyik+ARdI03M6bQzaSEKcgpFmewk= github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/redis/go-redis/v9 v9.1.0 h1:137FnGdk+EQdCbye1FW+qOEcY5S+SpY9T0NiuqvtfMY= -github.com/redis/go-redis/v9 v9.1.0/go.mod h1:urWj3He21Dj5k4TK1y59xH8Uj6ATueP8AH1cY3lZl4c= +github.com/redis/go-redis/v9 v9.2.1 h1:WlYJg71ODF0dVspZZCpYmoF1+U1Jjk9Rwd7pq6QmlCg= +github.com/redis/go-redis/v9 v9.2.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/rhysd/actionlint v1.6.25 h1:0Is99a51w1iocdxKUzNYiBNwjoSlO2Klqzll98joVj4= -github.com/rhysd/actionlint v1.6.25/go.mod h1:Q+MtZKm1MdmJ9woOSKxLscMW7kU44/PShvjNy5ZKHA8= +github.com/rhysd/actionlint v1.6.26 h1:zi7jPZf3Ks14gCXYAAL47uBziyFlX7+Xwilqhexct9g= +github.com/rhysd/actionlint v1.6.26/go.mod h1:TIj1DlCgtYLOv5CH9wCK+WJTOr1qAdnFzkGi0IgSCO4= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/robertkrimen/godocdown v0.0.0-20130622164427-0bfa04905481/go.mod h1:C9WhFzY47SzYBIvzFqSvHIR6ROgDo4TtdTuRaOMjF/s= -github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ= -github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -955,8 +949,8 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/skeema/knownhosts v1.2.0 h1:h9r9cf0+u7wSE+M183ZtMGgOJKiL96brpaz5ekfJCpM= -github.com/skeema/knownhosts v1.2.0/go.mod h1:g4fPeYpque7P0xefxtGzV81ihjC8sX2IqpAoNkjxbMo= +github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ= +github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v1.1.1 h1:T/YLemO5Yp7KPzS+lVtu+WsHn8yoSwTfItdAd1r3cck= @@ -1026,17 +1020,16 @@ github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6S github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.37.1-0.20220607072126-8a320890c08d/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I= -github.com/valyala/fasthttp v1.49.0 h1:9FdvCpmxB74LH4dPb7IJ1cOSsluR07XG3I1txXWwJpE= -github.com/valyala/fasthttp v1.49.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA= -github.com/valyala/fastjson v1.6.3/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY= +github.com/valyala/fasthttp v1.50.0 h1:H7fweIlBm0rXLs2q0XbalvJ6r0CUPFWK3/bB4N13e9M= +github.com/valyala/fasthttp v1.50.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA= github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ= github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY= github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= -github.com/xanzy/go-gitlab v0.91.0 h1:o8S6TeaPq/b1cGcZ0UWnj4cBP5urtBdYqwmoLZyCdDY= -github.com/xanzy/go-gitlab v0.91.0/go.mod h1:5ryv+MnpZStBH8I/77HuQBsMbBGANtVpLWC15qOjWAw= +github.com/xanzy/go-gitlab v0.93.0 h1:/Fy4akqKIQasZgQ2xj2xJBrEZ+iCW+iC+9qLEt19tgo= +github.com/xanzy/go-gitlab v0.93.0/go.mod h1:5ryv+MnpZStBH8I/77HuQBsMbBGANtVpLWC15qOjWAw= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= @@ -1097,10 +1090,10 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opentelemetry.io/otel v0.14.0/go.mod h1:vH5xEuwy7Rts0GNtsCW3HYQoZDY+OmBJ6t1bFGGlxgw= -go.opentelemetry.io/otel v1.17.0 h1:MW+phZ6WZ5/uk2nd93ANk/6yJ+dVrvNWUjGhnnFU5jM= -go.opentelemetry.io/otel v1.17.0/go.mod h1:I2vmBGtFaODIVMBSTPVDlJSzBDNf93k60E6Ft0nyjo0= -go.opentelemetry.io/otel/trace v1.17.0 h1:/SWhSRHmDPOImIAetP1QAeMnZYiQXrTy4fMMYOdSKWQ= -go.opentelemetry.io/otel/trace v1.17.0/go.mod h1:I/4vKTgFclIsXRVucpH25X0mpFSczM7aHeaz0ZBLWjY= +go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs= +go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY= +go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= +go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= @@ -1120,8 +1113,8 @@ go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9E go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c= -go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -1148,8 +1141,9 @@ golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4 golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= -golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1187,8 +1181,8 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= +golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1237,8 +1231,9 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= 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.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14= -golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.16.0 h1:7eBu7KsSvFDtSXUIDbh3aqlK4DPsZ1rByC8PFfBThos= +golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1248,8 +1243,8 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.11.0 h1:vPL4xzxBM4niKCW6g9whtaWVXTJf1U5e4aZxxFx/gbU= -golang.org/x/oauth2 v0.11.0/go.mod h1:LdF7O/8bLR/qWK9DrpXmbHLTouvRHK0SgJl0GmDBchk= +golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY= +golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1264,8 +1259,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/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-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.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= +golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1339,8 +1334,10 @@ golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= +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.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -1349,8 +1346,10 @@ golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= -golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0= -golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= +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.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1440,8 +1439,8 @@ golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.12.0 h1:YW6HUoUmYBpwSgyaGaZq1fHjrBjX1rlpZ54T6mu2kss= -golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= +golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= +golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1474,8 +1473,9 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= diff --git a/models/activities/action.go b/models/activities/action.go index 07c8053425602..1bfd62438bf2a 100644 --- a/models/activities/action.go +++ b/models/activities/action.go @@ -140,7 +140,7 @@ func (at ActionType) InActions(actions ...string) bool { // used in template render. type Action struct { ID int64 `xorm:"pk autoincr"` - UserID int64 // Receiver user id. + UserID int64 `xorm:"INDEX"` // Receiver user id. OpType ActionType ActUserID int64 // Action user id. ActUser *user_model.User `xorm:"-"` @@ -208,91 +208,91 @@ func (a *Action) loadRepo(ctx context.Context) { } // GetActFullName gets the action's user full name. -func (a *Action) GetActFullName() string { - a.LoadActUser(db.DefaultContext) +func (a *Action) GetActFullName(ctx context.Context) string { + a.LoadActUser(ctx) return a.ActUser.FullName } // GetActUserName gets the action's user name. -func (a *Action) GetActUserName() string { - a.LoadActUser(db.DefaultContext) +func (a *Action) GetActUserName(ctx context.Context) string { + a.LoadActUser(ctx) return a.ActUser.Name } // ShortActUserName gets the action's user name trimmed to max 20 // chars. -func (a *Action) ShortActUserName() string { - return base.EllipsisString(a.GetActUserName(), 20) +func (a *Action) ShortActUserName(ctx context.Context) string { + return base.EllipsisString(a.GetActUserName(ctx), 20) } // GetDisplayName gets the action's display name based on DEFAULT_SHOW_FULL_NAME, or falls back to the username if it is blank. -func (a *Action) GetDisplayName() string { +func (a *Action) GetDisplayName(ctx context.Context) string { if setting.UI.DefaultShowFullName { - trimmedFullName := strings.TrimSpace(a.GetActFullName()) + trimmedFullName := strings.TrimSpace(a.GetActFullName(ctx)) if len(trimmedFullName) > 0 { return trimmedFullName } } - return a.ShortActUserName() + return a.ShortActUserName(ctx) } // GetDisplayNameTitle gets the action's display name used for the title (tooltip) based on DEFAULT_SHOW_FULL_NAME -func (a *Action) GetDisplayNameTitle() string { +func (a *Action) GetDisplayNameTitle(ctx context.Context) string { if setting.UI.DefaultShowFullName { - return a.ShortActUserName() + return a.ShortActUserName(ctx) } - return a.GetActFullName() + return a.GetActFullName(ctx) } // GetRepoUserName returns the name of the action repository owner. -func (a *Action) GetRepoUserName() string { - a.loadRepo(db.DefaultContext) +func (a *Action) GetRepoUserName(ctx context.Context) string { + a.loadRepo(ctx) return a.Repo.OwnerName } // ShortRepoUserName returns the name of the action repository owner // trimmed to max 20 chars. -func (a *Action) ShortRepoUserName() string { - return base.EllipsisString(a.GetRepoUserName(), 20) +func (a *Action) ShortRepoUserName(ctx context.Context) string { + return base.EllipsisString(a.GetRepoUserName(ctx), 20) } // GetRepoName returns the name of the action repository. -func (a *Action) GetRepoName() string { - a.loadRepo(db.DefaultContext) +func (a *Action) GetRepoName(ctx context.Context) string { + a.loadRepo(ctx) return a.Repo.Name } // ShortRepoName returns the name of the action repository // trimmed to max 33 chars. -func (a *Action) ShortRepoName() string { - return base.EllipsisString(a.GetRepoName(), 33) +func (a *Action) ShortRepoName(ctx context.Context) string { + return base.EllipsisString(a.GetRepoName(ctx), 33) } // GetRepoPath returns the virtual path to the action repository. -func (a *Action) GetRepoPath() string { - return path.Join(a.GetRepoUserName(), a.GetRepoName()) +func (a *Action) GetRepoPath(ctx context.Context) string { + return path.Join(a.GetRepoUserName(ctx), a.GetRepoName(ctx)) } // ShortRepoPath returns the virtual path to the action repository // trimmed to max 20 + 1 + 33 chars. -func (a *Action) ShortRepoPath() string { - return path.Join(a.ShortRepoUserName(), a.ShortRepoName()) +func (a *Action) ShortRepoPath(ctx context.Context) string { + return path.Join(a.ShortRepoUserName(ctx), a.ShortRepoName(ctx)) } // GetRepoLink returns relative link to action repository. -func (a *Action) GetRepoLink() string { +func (a *Action) GetRepoLink(ctx context.Context) string { // path.Join will skip empty strings - return path.Join(setting.AppSubURL, "/", url.PathEscape(a.GetRepoUserName()), url.PathEscape(a.GetRepoName())) + return path.Join(setting.AppSubURL, "/", url.PathEscape(a.GetRepoUserName(ctx)), url.PathEscape(a.GetRepoName(ctx))) } // GetRepoAbsoluteLink returns the absolute link to action repository. -func (a *Action) GetRepoAbsoluteLink() string { - return setting.AppURL + url.PathEscape(a.GetRepoUserName()) + "/" + url.PathEscape(a.GetRepoName()) +func (a *Action) GetRepoAbsoluteLink(ctx context.Context) string { + return setting.AppURL + url.PathEscape(a.GetRepoUserName(ctx)) + "/" + url.PathEscape(a.GetRepoName(ctx)) } // GetCommentHTMLURL returns link to action comment. -func (a *Action) GetCommentHTMLURL() string { - return a.getCommentHTMLURL(db.DefaultContext) +func (a *Action) GetCommentHTMLURL(ctx context.Context) string { + return a.getCommentHTMLURL(ctx) } func (a *Action) loadComment(ctx context.Context) (err error) { @@ -309,7 +309,7 @@ func (a *Action) getCommentHTMLURL(ctx context.Context) string { } _ = a.loadComment(ctx) if a.Comment != nil { - return a.Comment.HTMLURL() + return a.Comment.HTMLURL(ctx) } if len(a.GetIssueInfos()) == 0 { return "#" @@ -334,8 +334,8 @@ func (a *Action) getCommentHTMLURL(ctx context.Context) string { } // GetCommentLink returns link to action comment. -func (a *Action) GetCommentLink() string { - return a.getCommentLink(db.DefaultContext) +func (a *Action) GetCommentLink(ctx context.Context) string { + return a.getCommentLink(ctx) } func (a *Action) getCommentLink(ctx context.Context) string { @@ -344,7 +344,7 @@ func (a *Action) getCommentLink(ctx context.Context) string { } _ = a.loadComment(ctx) if a.Comment != nil { - return a.Comment.Link() + return a.Comment.Link(ctx) } if len(a.GetIssueInfos()) == 0 { return "#" @@ -374,8 +374,8 @@ func (a *Action) GetBranch() string { } // GetRefLink returns the action's ref link. -func (a *Action) GetRefLink() string { - return git.RefURL(a.GetRepoLink(), a.RefName) +func (a *Action) GetRefLink(ctx context.Context) string { + return git.RefURL(a.GetRepoLink(ctx), a.RefName) } // GetTag returns the action's repository tag. @@ -399,11 +399,10 @@ func (a *Action) GetIssueInfos() []string { return strings.SplitN(a.Content, "|", 3) } -// GetIssueTitle returns the title of first issue associated -// with the action. This function will be invoked in template so keep db.DefaultContext here -func (a *Action) GetIssueTitle() string { +// GetIssueTitle returns the title of first issue associated with the action. +func (a *Action) GetIssueTitle(ctx context.Context) string { index, _ := strconv.ParseInt(a.GetIssueInfos()[0], 10, 64) - issue, err := issues_model.GetIssueByIndex(db.DefaultContext, a.RepoID, index) + issue, err := issues_model.GetIssueByIndex(ctx, a.RepoID, index) if err != nil { log.Error("GetIssueByIndex: %v", err) return "500 when get issue" @@ -442,7 +441,7 @@ func GetFeeds(ctx context.Context, opts GetFeedsOptions) (ActionList, int64, err return nil, 0, fmt.Errorf("need at least one of these filters: RequestedUser, RequestedTeam, RequestedRepo") } - cond, err := activityQueryCondition(opts) + cond, err := activityQueryCondition(ctx, opts) if err != nil { return nil, 0, err } @@ -473,11 +472,11 @@ func ActivityReadable(user, doer *user_model.User) bool { doer != nil && (doer.IsAdmin || user.ID == doer.ID) } -func activityQueryCondition(opts GetFeedsOptions) (builder.Cond, error) { +func activityQueryCondition(ctx context.Context, opts GetFeedsOptions) (builder.Cond, error) { cond := builder.NewCond() if opts.RequestedTeam != nil && opts.RequestedUser == nil { - org, err := user_model.GetUserByID(db.DefaultContext, opts.RequestedTeam.OrgID) + org, err := user_model.GetUserByID(ctx, opts.RequestedTeam.OrgID) if err != nil { return nil, err } @@ -525,7 +524,7 @@ func activityQueryCondition(opts GetFeedsOptions) (builder.Cond, error) { } if opts.RequestedTeam != nil { - env := organization.OrgFromUser(opts.RequestedUser).AccessibleTeamReposEnv(opts.RequestedTeam) + env := organization.OrgFromUser(opts.RequestedUser).AccessibleTeamReposEnv(ctx, opts.RequestedTeam) teamRepoIDs, err := env.RepoIDs(1, opts.RequestedUser.NumRepos) if err != nil { return nil, fmt.Errorf("GetTeamRepositories: %w", err) @@ -564,12 +563,12 @@ func activityQueryCondition(opts GetFeedsOptions) (builder.Cond, error) { } // DeleteOldActions deletes all old actions from database. -func DeleteOldActions(olderThan time.Duration) (err error) { +func DeleteOldActions(ctx context.Context, olderThan time.Duration) (err error) { if olderThan <= 0 { return nil } - _, err = db.GetEngine(db.DefaultContext).Where("created_unix < ?", time.Now().Add(-olderThan).Unix()).Delete(&Action{}) + _, err = db.GetEngine(ctx).Where("created_unix < ?", time.Now().Add(-olderThan).Unix()).Delete(&Action{}) return err } @@ -679,8 +678,8 @@ func NotifyWatchers(ctx context.Context, actions ...*Action) error { } // NotifyWatchersActions creates batch of actions for every watcher. -func NotifyWatchersActions(acts []*Action) error { - ctx, committer, err := db.TxContext(db.DefaultContext) +func NotifyWatchersActions(ctx context.Context, acts []*Action) error { + ctx, committer, err := db.TxContext(ctx) if err != nil { return err } diff --git a/models/activities/action_test.go b/models/activities/action_test.go index 9a42740880048..5467bd35fb855 100644 --- a/models/activities/action_test.go +++ b/models/activities/action_test.go @@ -24,7 +24,7 @@ func TestAction_GetRepoPath(t *testing.T) { repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) action := &activities_model.Action{RepoID: repo.ID} - assert.Equal(t, path.Join(owner.Name, repo.Name), action.GetRepoPath()) + assert.Equal(t, path.Join(owner.Name, repo.Name), action.GetRepoPath(db.DefaultContext)) } func TestAction_GetRepoLink(t *testing.T) { @@ -35,9 +35,9 @@ func TestAction_GetRepoLink(t *testing.T) { action := &activities_model.Action{RepoID: repo.ID, CommentID: comment.ID} setting.AppSubURL = "/suburl" expected := path.Join(setting.AppSubURL, owner.Name, repo.Name) - assert.Equal(t, expected, action.GetRepoLink()) - assert.Equal(t, repo.HTMLURL(), action.GetRepoAbsoluteLink()) - assert.Equal(t, comment.HTMLURL(), action.GetCommentHTMLURL()) + assert.Equal(t, expected, action.GetRepoLink(db.DefaultContext)) + assert.Equal(t, repo.HTMLURL(), action.GetRepoAbsoluteLink(db.DefaultContext)) + assert.Equal(t, comment.HTMLURL(db.DefaultContext), action.GetCommentHTMLURL(db.DefaultContext)) } func TestGetFeeds(t *testing.T) { diff --git a/models/activities/notification.go b/models/activities/notification.go index ef263ef735c3d..7c794564b6737 100644 --- a/models/activities/notification.go +++ b/models/activities/notification.go @@ -175,8 +175,8 @@ func CreateRepoTransferNotification(ctx context.Context, doer, newOwner *user_mo // CreateOrUpdateIssueNotifications creates an issue notification // for each watcher, or updates it if already exists // receiverID > 0 just send to receiver, else send to all watcher -func CreateOrUpdateIssueNotifications(issueID, commentID, notificationAuthorID, receiverID int64) error { - ctx, committer, err := db.TxContext(db.DefaultContext) +func CreateOrUpdateIssueNotifications(ctx context.Context, issueID, commentID, notificationAuthorID, receiverID int64) error { + ctx, committer, err := db.TxContext(ctx) if err != nil { return err } @@ -435,21 +435,21 @@ func (n *Notification) loadUser(ctx context.Context) (err error) { } // GetRepo returns the repo of the notification -func (n *Notification) GetRepo() (*repo_model.Repository, error) { - return n.Repository, n.loadRepo(db.DefaultContext) +func (n *Notification) GetRepo(ctx context.Context) (*repo_model.Repository, error) { + return n.Repository, n.loadRepo(ctx) } // GetIssue returns the issue of the notification -func (n *Notification) GetIssue() (*issues_model.Issue, error) { - return n.Issue, n.loadIssue(db.DefaultContext) +func (n *Notification) GetIssue(ctx context.Context) (*issues_model.Issue, error) { + return n.Issue, n.loadIssue(ctx) } // HTMLURL formats a URL-string to the notification -func (n *Notification) HTMLURL() string { +func (n *Notification) HTMLURL(ctx context.Context) string { switch n.Source { case NotificationSourceIssue, NotificationSourcePullRequest: if n.Comment != nil { - return n.Comment.HTMLURL() + return n.Comment.HTMLURL(ctx) } return n.Issue.HTMLURL() case NotificationSourceCommit: @@ -461,11 +461,11 @@ func (n *Notification) HTMLURL() string { } // Link formats a relative URL-string to the notification -func (n *Notification) Link() string { +func (n *Notification) Link(ctx context.Context) string { switch n.Source { case NotificationSourceIssue, NotificationSourcePullRequest: if n.Comment != nil { - return n.Comment.Link() + return n.Comment.Link(ctx) } return n.Issue.Link() case NotificationSourceCommit: @@ -733,12 +733,12 @@ type UserIDCount struct { } // GetUIDsAndNotificationCounts between the two provided times -func GetUIDsAndNotificationCounts(since, until timeutil.TimeStamp) ([]UserIDCount, error) { +func GetUIDsAndNotificationCounts(ctx context.Context, since, until timeutil.TimeStamp) ([]UserIDCount, error) { sql := `SELECT user_id, count(*) AS count FROM notification ` + `WHERE user_id IN (SELECT user_id FROM notification WHERE updated_unix >= ? AND ` + `updated_unix < ?) AND status = ? GROUP BY user_id` var res []UserIDCount - return res, db.GetEngine(db.DefaultContext).SQL(sql, since, until, NotificationStatusUnread).Find(&res) + return res, db.GetEngine(ctx).SQL(sql, since, until, NotificationStatusUnread).Find(&res) } // SetIssueReadBy sets issue to be read by given user. diff --git a/models/activities/notification_test.go b/models/activities/notification_test.go index 2d4c369a99b04..b90ce70536f8f 100644 --- a/models/activities/notification_test.go +++ b/models/activities/notification_test.go @@ -20,7 +20,7 @@ func TestCreateOrUpdateIssueNotifications(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1}) - assert.NoError(t, activities_model.CreateOrUpdateIssueNotifications(issue.ID, 0, 2, 0)) + assert.NoError(t, activities_model.CreateOrUpdateIssueNotifications(db.DefaultContext, issue.ID, 0, 2, 0)) // User 9 is inactive, thus notifications for user 1 and 4 are created notf := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{UserID: 1, IssueID: issue.ID}) @@ -50,7 +50,7 @@ func TestNotificationsForUser(t *testing.T) { func TestNotification_GetRepo(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) notf := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{RepoID: 1}) - repo, err := notf.GetRepo() + repo, err := notf.GetRepo(db.DefaultContext) assert.NoError(t, err) assert.Equal(t, repo, notf.Repository) assert.EqualValues(t, notf.RepoID, repo.ID) @@ -59,7 +59,7 @@ func TestNotification_GetRepo(t *testing.T) { func TestNotification_GetIssue(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) notf := unittest.AssertExistsAndLoadBean(t, &activities_model.Notification{RepoID: 1}) - issue, err := notf.GetIssue() + issue, err := notf.GetIssue(db.DefaultContext) assert.NoError(t, err) assert.Equal(t, issue, notf.Issue) assert.EqualValues(t, notf.IssueID, issue.ID) diff --git a/models/activities/statistic.go b/models/activities/statistic.go index 5479db20ebae1..ea13f3ed5c8f2 100644 --- a/models/activities/statistic.go +++ b/models/activities/statistic.go @@ -52,7 +52,7 @@ type IssueByRepositoryCount struct { func GetStatistic(ctx context.Context) (stats Statistic) { e := db.GetEngine(ctx) stats.Counter.User = user_model.CountUsers(ctx, nil) - stats.Counter.Org, _ = organization.CountOrgs(organization.FindOrgOptions{IncludePrivate: true}) + stats.Counter.Org, _ = organization.CountOrgs(ctx, organization.FindOrgOptions{IncludePrivate: true}) stats.Counter.PublicKey, _ = e.Count(new(asymkey_model.PublicKey)) stats.Counter.Repo, _ = repo_model.CountRepositories(ctx, repo_model.CountRepositoryOptions{}) stats.Counter.Watch, _ = e.Count(new(repo_model.Watch)) diff --git a/models/activities/user_heatmap.go b/models/activities/user_heatmap.go index 9f7b8bbdc4410..78fcd76d43ace 100644 --- a/models/activities/user_heatmap.go +++ b/models/activities/user_heatmap.go @@ -47,7 +47,7 @@ func getUserHeatmapData(ctx context.Context, user *user_model.User, team *organi groupByName = groupBy } - cond, err := activityQueryCondition(GetFeedsOptions{ + cond, err := activityQueryCondition(ctx, GetFeedsOptions{ RequestedUser: user, RequestedTeam: team, Actor: doer, diff --git a/models/auth/oauth2.go b/models/auth/oauth2.go index 9c419eff69af0..7ac1d3a5fcbbc 100644 --- a/models/auth/oauth2.go +++ b/models/auth/oauth2.go @@ -66,6 +66,11 @@ func BuiltinApplications() map[string]*BuiltinOAuth2Application { DisplayName: "Git Credential Manager", RedirectURIs: []string{"http://127.0.0.1", "https://127.0.0.1"}, } + m["d57cb8c4-630c-4168-8324-ec79935e18d4"] = &BuiltinOAuth2Application{ + ConfigName: "tea", + DisplayName: "tea", + RedirectURIs: []string{"http://127.0.0.1", "https://127.0.0.1"}, + } return m } diff --git a/models/avatars/avatar.go b/models/avatars/avatar.go index e40aa3f542432..b0bfa4408971e 100644 --- a/models/avatars/avatar.go +++ b/models/avatars/avatar.go @@ -5,18 +5,20 @@ package avatars import ( "context" + "fmt" "net/url" "path" "strconv" "strings" - "sync" + "sync/atomic" "code.gitea.io/gitea/models/db" - system_model "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/cache" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" + + "strk.kbt.io/projects/go/libravatar" ) const ( @@ -36,24 +38,54 @@ func init() { db.RegisterModel(new(EmailHash)) } -var ( +type avatarSettingStruct struct { defaultAvatarLink string - once sync.Once -) + gravatarSource string + gravatarSourceURL *url.URL + libravatar *libravatar.Libravatar +} -// DefaultAvatarLink the default avatar link -func DefaultAvatarLink() string { - once.Do(func() { +var avatarSettingAtomic atomic.Pointer[avatarSettingStruct] + +func loadAvatarSetting() (*avatarSettingStruct, error) { + s := avatarSettingAtomic.Load() + if s == nil || s.gravatarSource != setting.GravatarSource { + s = &avatarSettingStruct{} u, err := url.Parse(setting.AppSubURL) if err != nil { - log.Error("Can not parse AppSubURL: %v", err) - return + return nil, fmt.Errorf("unable to parse AppSubURL: %w", err) } u.Path = path.Join(u.Path, "/assets/img/avatar_default.png") - defaultAvatarLink = u.String() - }) - return defaultAvatarLink + s.defaultAvatarLink = u.String() + + s.gravatarSourceURL, err = url.Parse(setting.GravatarSource) + if err != nil { + return nil, fmt.Errorf("unable to parse GravatarSource %q: %w", setting.GravatarSource, err) + } + + s.libravatar = libravatar.New() + if s.gravatarSourceURL.Scheme == "https" { + s.libravatar.SetUseHTTPS(true) + s.libravatar.SetSecureFallbackHost(s.gravatarSourceURL.Host) + } else { + s.libravatar.SetUseHTTPS(false) + s.libravatar.SetFallbackHost(s.gravatarSourceURL.Host) + } + + avatarSettingAtomic.Store(s) + } + return s, nil +} + +// DefaultAvatarLink the default avatar link +func DefaultAvatarLink() string { + a, err := loadAvatarSetting() + if err != nil { + log.Error("Failed to loadAvatarSetting: %v", err) + return "" + } + return a.defaultAvatarLink } // HashEmail hashes email address to MD5 string. https://en.gravatar.com/site/implement/hash/ @@ -76,7 +108,11 @@ func GetEmailForHash(md5Sum string) (string, error) { // LibravatarURL returns the URL for the given email. Slow due to the DNS lookup. // This function should only be called if a federated avatar service is enabled. func LibravatarURL(email string) (*url.URL, error) { - urlStr, err := system_model.LibravatarService.FromEmail(email) + a, err := loadAvatarSetting() + if err != nil { + return nil, err + } + urlStr, err := a.libravatar.FromEmail(email) if err != nil { log.Error("LibravatarService.FromEmail(email=%s): error %v", email, err) return nil, err @@ -153,15 +189,13 @@ func generateEmailAvatarLink(ctx context.Context, email string, size int, final return DefaultAvatarLink() } - disableGravatar := system_model.GetSettingWithCacheBool(ctx, system_model.KeyPictureDisableGravatar, - setting.GetDefaultDisableGravatar(), - ) - - enableFederatedAvatar := system_model.GetSettingWithCacheBool(ctx, system_model.KeyPictureEnableFederatedAvatar, - setting.GetDefaultEnableFederatedAvatar(disableGravatar)) + avatarSetting, err := loadAvatarSetting() + if err != nil { + return DefaultAvatarLink() + } - var err error - if enableFederatedAvatar && system_model.LibravatarService != nil { + enableFederatedAvatar := setting.Config().Picture.EnableFederatedAvatar.Value(ctx) + if enableFederatedAvatar { emailHash := saveEmailHash(email) if final { // for final link, we can spend more time on slow external query @@ -179,9 +213,10 @@ func generateEmailAvatarLink(ctx context.Context, email string, size int, final return urlStr } + disableGravatar := setting.Config().Picture.DisableGravatar.Value(ctx) if !disableGravatar { // copy GravatarSourceURL, because we will modify its Path. - avatarURLCopy := *system_model.GravatarSourceURL + avatarURLCopy := *avatarSetting.gravatarSourceURL avatarURLCopy.Path = path.Join(avatarURLCopy.Path, HashEmail(email)) return generateRecognizedAvatarURL(avatarURLCopy, size) } diff --git a/models/avatars/avatar_test.go b/models/avatars/avatar_test.go index 59daaeb6695a6..c8f7a6574bfe7 100644 --- a/models/avatars/avatar_test.go +++ b/models/avatars/avatar_test.go @@ -10,6 +10,7 @@ import ( "code.gitea.io/gitea/models/db" system_model "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/setting/config" "github.com/stretchr/testify/assert" ) @@ -17,19 +18,16 @@ import ( const gravatarSource = "https://secure.gravatar.com/avatar/" func disableGravatar(t *testing.T) { - err := system_model.SetSettingNoVersion(db.DefaultContext, system_model.KeyPictureEnableFederatedAvatar, "false") + err := system_model.SetSettings(db.DefaultContext, map[string]string{setting.Config().Picture.EnableFederatedAvatar.DynKey(): "false"}) assert.NoError(t, err) - err = system_model.SetSettingNoVersion(db.DefaultContext, system_model.KeyPictureDisableGravatar, "true") + err = system_model.SetSettings(db.DefaultContext, map[string]string{setting.Config().Picture.DisableGravatar.DynKey(): "true"}) assert.NoError(t, err) - system_model.LibravatarService = nil } func enableGravatar(t *testing.T) { - err := system_model.SetSettingNoVersion(db.DefaultContext, system_model.KeyPictureDisableGravatar, "false") + err := system_model.SetSettings(db.DefaultContext, map[string]string{setting.Config().Picture.DisableGravatar.DynKey(): "false"}) assert.NoError(t, err) setting.GravatarSource = gravatarSource - err = system_model.Init(db.DefaultContext) - assert.NoError(t, err) } func TestHashEmail(t *testing.T) { @@ -47,10 +45,12 @@ func TestSizedAvatarLink(t *testing.T) { setting.AppSubURL = "/testsuburl" disableGravatar(t) + config.GetDynGetter().InvalidateCache() assert.Equal(t, "/testsuburl/assets/img/avatar_default.png", avatars_model.GenerateEmailAvatarFastLink(db.DefaultContext, "gitea@example.com", 100)) enableGravatar(t) + config.GetDynGetter().InvalidateCache() assert.Equal(t, "https://secure.gravatar.com/avatar/353cbad9b58e69c96154ad99f92bedc7?d=identicon&s=100", avatars_model.GenerateEmailAvatarFastLink(db.DefaultContext, "gitea@example.com", 100), diff --git a/models/fixtures/attachment.yml b/models/fixtures/attachment.yml index 9ad43fa2b7eb6..7882d8bff2089 100644 --- a/models/fixtures/attachment.yml +++ b/models/fixtures/attachment.yml @@ -140,3 +140,16 @@ download_count: 0 size: 0 created_unix: 946684800 + +- + id: 12 + uuid: a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a22 + repo_id: 2 + issue_id: 0 + release_id: 11 + uploader_id: 2 + comment_id: 0 + name: README.md + download_count: 0 + size: 0 + created_unix: 946684800 diff --git a/models/fixtures/release.yml b/models/fixtures/release.yml index 4ed7df440dbd3..372a79509f0a8 100644 --- a/models/fixtures/release.yml +++ b/models/fixtures/release.yml @@ -136,3 +136,17 @@ is_prerelease: false is_tag: false created_unix: 946684803 + +- id: 11 + repo_id: 2 + publisher_id: 2 + tag_name: "v1.1" + lower_tag_name: "v1.1" + target: "" + title: "v1.1" + sha1: "205ac761f3326a7ebe416e8673760016450b5cec" + num_commits: 2 + is_draft: false + is_prerelease: false + is_tag: false + created_unix: 946684803 diff --git a/models/fixtures/repo_unit.yml b/models/fixtures/repo_unit.yml index c22eb8c2a2f08..0104419550572 100644 --- a/models/fixtures/repo_unit.yml +++ b/models/fixtures/repo_unit.yml @@ -649,3 +649,23 @@ repo_id: 49 type: 2 created_unix: 946684810 + +- + id: 98 + repo_id: 1 + type: 8 + created_unix: 946684810 + +- + id: 99 + repo_id: 1 + type: 9 + config: "{}" + created_unix: 946684810 + +- + id: 100 + repo_id: 1 + type: 10 + config: "{}" + created_unix: 946684810 diff --git a/models/git/commit_status.go b/models/git/commit_status.go index 24fee8c3b4f24..acb011020056e 100644 --- a/models/git/commit_status.go +++ b/models/git/commit_status.go @@ -514,7 +514,7 @@ func ConvertFromGitCommit(ctx context.Context, commits []*git.Commit, repo *repo user_model.ValidateCommitsWithEmails(ctx, commits), repo.GetTrustModel(), func(user *user_model.User) (bool, error) { - return repo_model.IsOwnerMemberCollaborator(repo, user.ID) + return repo_model.IsOwnerMemberCollaborator(ctx, repo, user.ID) }, ), repo, diff --git a/models/issues/assignees_test.go b/models/issues/assignees_test.go index 65a5ddba31ac2..3898e814c3137 100644 --- a/models/issues/assignees_test.go +++ b/models/issues/assignees_test.go @@ -18,7 +18,7 @@ func TestUpdateAssignee(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) // Fake issue with assignees - issue, err := issues_model.GetIssueWithAttrsByID(1) + issue, err := issues_model.GetIssueWithAttrsByID(db.DefaultContext, 1) assert.NoError(t, err) // Assign multiple users diff --git a/models/issues/comment.go b/models/issues/comment.go index 66b3a8527ffd2..901958dc5d5fe 100644 --- a/models/issues/comment.go +++ b/models/issues/comment.go @@ -246,7 +246,7 @@ type Comment struct { NewTitle string OldRef string NewRef string - DependentIssueID int64 + DependentIssueID int64 `xorm:"index"` // This is used by issue_service.deleteIssue DependentIssue *Issue `xorm:"-"` CommitID int64 @@ -371,42 +371,42 @@ func (c *Comment) AfterDelete(ctx context.Context) { } // HTMLURL formats a URL-string to the issue-comment -func (c *Comment) HTMLURL() string { - err := c.LoadIssue(db.DefaultContext) +func (c *Comment) HTMLURL(ctx context.Context) string { + err := c.LoadIssue(ctx) if err != nil { // Silently dropping errors :unamused: log.Error("LoadIssue(%d): %v", c.IssueID, err) return "" } - err = c.Issue.LoadRepo(db.DefaultContext) + err = c.Issue.LoadRepo(ctx) if err != nil { // Silently dropping errors :unamused: log.Error("loadRepo(%d): %v", c.Issue.RepoID, err) return "" } - return c.Issue.HTMLURL() + c.hashLink() + return c.Issue.HTMLURL() + c.hashLink(ctx) } // Link formats a relative URL-string to the issue-comment -func (c *Comment) Link() string { - err := c.LoadIssue(db.DefaultContext) +func (c *Comment) Link(ctx context.Context) string { + err := c.LoadIssue(ctx) if err != nil { // Silently dropping errors :unamused: log.Error("LoadIssue(%d): %v", c.IssueID, err) return "" } - err = c.Issue.LoadRepo(db.DefaultContext) + err = c.Issue.LoadRepo(ctx) if err != nil { // Silently dropping errors :unamused: log.Error("loadRepo(%d): %v", c.Issue.RepoID, err) return "" } - return c.Issue.Link() + c.hashLink() + return c.Issue.Link() + c.hashLink(ctx) } -func (c *Comment) hashLink() string { +func (c *Comment) hashLink(ctx context.Context) string { if c.Type == CommentTypeCode { if c.ReviewID == 0 { return "/files#" + c.HashTag() } if c.Review == nil { - if err := c.LoadReview(); err != nil { + if err := c.LoadReview(ctx); err != nil { log.Warn("LoadReview(%d): %v", c.ReviewID, err) return "/files#" + c.HashTag() } @@ -419,13 +419,13 @@ func (c *Comment) hashLink() string { } // APIURL formats a API-string to the issue-comment -func (c *Comment) APIURL() string { - err := c.LoadIssue(db.DefaultContext) +func (c *Comment) APIURL(ctx context.Context) string { + err := c.LoadIssue(ctx) if err != nil { // Silently dropping errors :unamused: log.Error("LoadIssue(%d): %v", c.IssueID, err) return "" } - err = c.Issue.LoadRepo(db.DefaultContext) + err = c.Issue.LoadRepo(ctx) if err != nil { // Silently dropping errors :unamused: log.Error("loadRepo(%d): %v", c.Issue.RepoID, err) return "" @@ -435,8 +435,8 @@ func (c *Comment) APIURL() string { } // IssueURL formats a URL-string to the issue -func (c *Comment) IssueURL() string { - err := c.LoadIssue(db.DefaultContext) +func (c *Comment) IssueURL(ctx context.Context) string { + err := c.LoadIssue(ctx) if err != nil { // Silently dropping errors :unamused: log.Error("LoadIssue(%d): %v", c.IssueID, err) return "" @@ -446,7 +446,7 @@ func (c *Comment) IssueURL() string { return "" } - err = c.Issue.LoadRepo(db.DefaultContext) + err = c.Issue.LoadRepo(ctx) if err != nil { // Silently dropping errors :unamused: log.Error("loadRepo(%d): %v", c.Issue.RepoID, err) return "" @@ -455,14 +455,14 @@ func (c *Comment) IssueURL() string { } // PRURL formats a URL-string to the pull-request -func (c *Comment) PRURL() string { - err := c.LoadIssue(db.DefaultContext) +func (c *Comment) PRURL(ctx context.Context) string { + err := c.LoadIssue(ctx) if err != nil { // Silently dropping errors :unamused: log.Error("LoadIssue(%d): %v", c.IssueID, err) return "" } - err = c.Issue.LoadRepo(db.DefaultContext) + err = c.Issue.LoadRepo(ctx) if err != nil { // Silently dropping errors :unamused: log.Error("loadRepo(%d): %v", c.Issue.RepoID, err) return "" @@ -490,9 +490,9 @@ func (c *Comment) EventTag() string { } // LoadLabel if comment.Type is CommentTypeLabel, then load Label -func (c *Comment) LoadLabel() error { +func (c *Comment) LoadLabel(ctx context.Context) error { var label Label - has, err := db.GetEngine(db.DefaultContext).ID(c.LabelID).Get(&label) + has, err := db.GetEngine(ctx).ID(c.LabelID).Get(&label) if err != nil { return err } else if has { @@ -506,10 +506,10 @@ func (c *Comment) LoadLabel() error { } // LoadProject if comment.Type is CommentTypeProject, then load project. -func (c *Comment) LoadProject() error { +func (c *Comment) LoadProject(ctx context.Context) error { if c.OldProjectID > 0 { var oldProject project_model.Project - has, err := db.GetEngine(db.DefaultContext).ID(c.OldProjectID).Get(&oldProject) + has, err := db.GetEngine(ctx).ID(c.OldProjectID).Get(&oldProject) if err != nil { return err } else if has { @@ -519,7 +519,7 @@ func (c *Comment) LoadProject() error { if c.ProjectID > 0 { var project project_model.Project - has, err := db.GetEngine(db.DefaultContext).ID(c.ProjectID).Get(&project) + has, err := db.GetEngine(ctx).ID(c.ProjectID).Get(&project) if err != nil { return err } else if has { @@ -569,8 +569,8 @@ func (c *Comment) LoadAttachments(ctx context.Context) error { } // UpdateAttachments update attachments by UUIDs for the comment -func (c *Comment) UpdateAttachments(uuids []string) error { - ctx, committer, err := db.TxContext(db.DefaultContext) +func (c *Comment) UpdateAttachments(ctx context.Context, uuids []string) error { + ctx, committer, err := db.TxContext(ctx) if err != nil { return err } @@ -591,11 +591,11 @@ func (c *Comment) UpdateAttachments(uuids []string) error { } // LoadAssigneeUserAndTeam if comment.Type is CommentTypeAssignees, then load assignees -func (c *Comment) LoadAssigneeUserAndTeam() error { +func (c *Comment) LoadAssigneeUserAndTeam(ctx context.Context) error { var err error if c.AssigneeID > 0 && c.Assignee == nil { - c.Assignee, err = user_model.GetUserByID(db.DefaultContext, c.AssigneeID) + c.Assignee, err = user_model.GetUserByID(ctx, c.AssigneeID) if err != nil { if !user_model.IsErrUserNotExist(err) { return err @@ -603,20 +603,20 @@ func (c *Comment) LoadAssigneeUserAndTeam() error { c.Assignee = user_model.NewGhostUser() } } else if c.AssigneeTeamID > 0 && c.AssigneeTeam == nil { - if err = c.LoadIssue(db.DefaultContext); err != nil { + if err = c.LoadIssue(ctx); err != nil { return err } - if err = c.Issue.LoadRepo(db.DefaultContext); err != nil { + if err = c.Issue.LoadRepo(ctx); err != nil { return err } - if err = c.Issue.Repo.LoadOwner(db.DefaultContext); err != nil { + if err = c.Issue.Repo.LoadOwner(ctx); err != nil { return err } if c.Issue.Repo.Owner.IsOrganization() { - c.AssigneeTeam, err = organization.GetTeamByID(db.DefaultContext, c.AssigneeTeamID) + c.AssigneeTeam, err = organization.GetTeamByID(ctx, c.AssigneeTeamID) if err != nil && !organization.IsErrTeamNotExist(err) { return err } @@ -626,11 +626,11 @@ func (c *Comment) LoadAssigneeUserAndTeam() error { } // LoadResolveDoer if comment.Type is CommentTypeCode and ResolveDoerID not zero, then load resolveDoer -func (c *Comment) LoadResolveDoer() (err error) { +func (c *Comment) LoadResolveDoer(ctx context.Context) (err error) { if c.ResolveDoerID == 0 || c.Type != CommentTypeCode { return nil } - c.ResolveDoer, err = user_model.GetUserByID(db.DefaultContext, c.ResolveDoerID) + c.ResolveDoer, err = user_model.GetUserByID(ctx, c.ResolveDoerID) if err != nil { if user_model.IsErrUserNotExist(err) { c.ResolveDoer = user_model.NewGhostUser() @@ -646,21 +646,21 @@ func (c *Comment) IsResolved() bool { } // LoadDepIssueDetails loads Dependent Issue Details -func (c *Comment) LoadDepIssueDetails() (err error) { +func (c *Comment) LoadDepIssueDetails(ctx context.Context) (err error) { if c.DependentIssueID <= 0 || c.DependentIssue != nil { return nil } - c.DependentIssue, err = GetIssueByID(db.DefaultContext, c.DependentIssueID) + c.DependentIssue, err = GetIssueByID(ctx, c.DependentIssueID) return err } // LoadTime loads the associated time for a CommentTypeAddTimeManual -func (c *Comment) LoadTime() error { +func (c *Comment) LoadTime(ctx context.Context) error { if c.Time != nil || c.TimeID == 0 { return nil } var err error - c.Time, err = GetTrackedTimeByID(c.TimeID) + c.Time, err = GetTrackedTimeByID(ctx, c.TimeID) return err } @@ -683,8 +683,8 @@ func (c *Comment) loadReactions(ctx context.Context, repo *repo_model.Repository } // LoadReactions loads comment reactions -func (c *Comment) LoadReactions(repo *repo_model.Repository) error { - return c.loadReactions(db.DefaultContext, repo) +func (c *Comment) LoadReactions(ctx context.Context, repo *repo_model.Repository) error { + return c.loadReactions(ctx, repo) } func (c *Comment) loadReview(ctx context.Context) (err error) { @@ -698,8 +698,8 @@ func (c *Comment) loadReview(ctx context.Context) (err error) { } // LoadReview loads the associated review -func (c *Comment) LoadReview() error { - return c.loadReview(db.DefaultContext) +func (c *Comment) LoadReview(ctx context.Context) error { + return c.loadReview(ctx) } // DiffSide returns "previous" if Comment.Line is a LOC of the previous changes and "proposed" if it is a LOC of the proposed changes. @@ -719,13 +719,13 @@ func (c *Comment) UnsignedLine() uint64 { } // CodeCommentLink returns the url to a comment in code -func (c *Comment) CodeCommentLink() string { - err := c.LoadIssue(db.DefaultContext) +func (c *Comment) CodeCommentLink(ctx context.Context) string { + err := c.LoadIssue(ctx) if err != nil { // Silently dropping errors :unamused: log.Error("LoadIssue(%d): %v", c.IssueID, err) return "" } - err = c.Issue.LoadRepo(db.DefaultContext) + err = c.Issue.LoadRepo(ctx) if err != nil { // Silently dropping errors :unamused: log.Error("loadRepo(%d): %v", c.Issue.RepoID, err) return "" @@ -1074,8 +1074,8 @@ func FindComments(ctx context.Context, opts *FindCommentsOptions) (CommentList, } // CountComments count all comments according options by ignoring pagination -func CountComments(opts *FindCommentsOptions) (int64, error) { - sess := db.GetEngine(db.DefaultContext).Where(opts.ToConds()) +func CountComments(ctx context.Context, opts *FindCommentsOptions) (int64, error) { + sess := db.GetEngine(ctx).Where(opts.ToConds()) if opts.RepoID > 0 { sess.Join("INNER", "issue", "issue.id = comment.issue_id") } @@ -1089,8 +1089,8 @@ func UpdateCommentInvalidate(ctx context.Context, c *Comment) error { } // UpdateComment updates information of comment. -func UpdateComment(c *Comment, doer *user_model.User) error { - ctx, committer, err := db.TxContext(db.DefaultContext) +func UpdateComment(ctx context.Context, c *Comment, doer *user_model.User) error { + ctx, committer, err := db.TxContext(ctx) if err != nil { return err } @@ -1147,8 +1147,8 @@ func DeleteComment(ctx context.Context, comment *Comment) error { } // UpdateCommentsMigrationsByType updates comments' migrations information via given git service type and original id and poster id -func UpdateCommentsMigrationsByType(tp structs.GitServiceType, originalAuthorID string, posterID int64) error { - _, err := db.GetEngine(db.DefaultContext).Table("comment"). +func UpdateCommentsMigrationsByType(ctx context.Context, tp structs.GitServiceType, originalAuthorID string, posterID int64) error { + _, err := db.GetEngine(ctx).Table("comment"). Where(builder.In("issue_id", builder.Select("issue.id"). From("issue"). @@ -1250,7 +1250,7 @@ func (c *Comment) HasOriginalAuthor() bool { } // InsertIssueComments inserts many comments of issues. -func InsertIssueComments(comments []*Comment) error { +func InsertIssueComments(ctx context.Context, comments []*Comment) error { if len(comments) == 0 { return nil } @@ -1260,7 +1260,7 @@ func InsertIssueComments(comments []*Comment) error { issueIDs.Add(comment.IssueID) } - ctx, committer, err := db.TxContext(db.DefaultContext) + ctx, committer, err := db.TxContext(ctx) if err != nil { return err } diff --git a/models/issues/comment_code.go b/models/issues/comment_code.go index d447d7542cd26..49927fbbe2f43 100644 --- a/models/issues/comment_code.go +++ b/models/issues/comment_code.go @@ -99,11 +99,11 @@ func findCodeComments(ctx context.Context, opts FindCommentsOptions, issue *Issu comments[n] = comment n++ - if err := comment.LoadResolveDoer(); err != nil { + if err := comment.LoadResolveDoer(ctx); err != nil { return nil, err } - if err := comment.LoadReactions(issue.Repo); err != nil { + if err := comment.LoadReactions(ctx, issue.Repo); err != nil { return nil, err } diff --git a/models/issues/comment_list.go b/models/issues/comment_list.go index 6f1d350eb42fb..93af45870ed69 100644 --- a/models/issues/comment_list.go +++ b/models/issues/comment_list.go @@ -10,6 +10,7 @@ import ( repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/container" + "code.gitea.io/gitea/modules/log" ) // CommentList defines a list of comments @@ -422,37 +423,18 @@ func (comments CommentList) loadReviews(ctx context.Context) error { reviewIDs := comments.getReviewIDs() reviews := make(map[int64]*Review, len(reviewIDs)) - left := len(reviewIDs) - for left > 0 { - limit := db.DefaultMaxInSize - if left < limit { - limit = left - } - rows, err := db.GetEngine(ctx). - In("id", reviewIDs[:limit]). - Rows(new(Review)) - if err != nil { - return err - } - - for rows.Next() { - var review Review - err = rows.Scan(&review) - if err != nil { - _ = rows.Close() - return err - } - - reviews[review.ID] = &review - } - _ = rows.Close() - - left -= limit - reviewIDs = reviewIDs[limit:] + if err := db.GetEngine(ctx).In("id", reviewIDs).Find(&reviews); err != nil { + return err } for _, comment := range comments { comment.Review = reviews[comment.ReviewID] + if comment.Review == nil { + if comment.ReviewID > 0 { + log.Error("comment with review id [%d] but has no review record", comment.ReviewID) + } + continue + } // If the comment dismisses a review, we need to load the reviewer to show whose review has been dismissed. // Otherwise, the reviewer is the poster of the comment, so we don't need to load it. diff --git a/models/issues/comment_test.go b/models/issues/comment_test.go index 90db47657134f..c5bbfdedc28ec 100644 --- a/models/issues/comment_test.go +++ b/models/issues/comment_test.go @@ -89,7 +89,7 @@ func TestMigrate_InsertIssueComments(t *testing.T) { Reactions: []*issues_model.Reaction{reaction}, } - err := issues_model.InsertIssueComments([]*issues_model.Comment{comment}) + err := issues_model.InsertIssueComments(db.DefaultContext, []*issues_model.Comment{comment}) assert.NoError(t, err) issueModified := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1}) diff --git a/models/issues/issue.go b/models/issues/issue.go index 341ec8547a183..6d9c8727b33f0 100644 --- a/models/issues/issue.go +++ b/models/issues/issue.go @@ -201,12 +201,12 @@ func (issue *Issue) IsTimetrackerEnabled(ctx context.Context) bool { } // GetPullRequest returns the issue pull request -func (issue *Issue) GetPullRequest() (pr *PullRequest, err error) { +func (issue *Issue) GetPullRequest(ctx context.Context) (pr *PullRequest, err error) { if !issue.IsPull { return nil, fmt.Errorf("Issue is not a pull request") } - pr, err = GetPullRequestByIssueID(db.DefaultContext, issue.ID) + pr, err = GetPullRequestByIssueID(ctx, issue.ID) if err != nil { return nil, err } @@ -369,9 +369,9 @@ func (issue *Issue) LoadAttributes(ctx context.Context) (err error) { } // GetIsRead load the `IsRead` field of the issue -func (issue *Issue) GetIsRead(userID int64) error { +func (issue *Issue) GetIsRead(ctx context.Context, userID int64) error { issueUser := &IssueUser{IssueID: issue.ID, UID: userID} - if has, err := db.GetEngine(db.DefaultContext).Get(issueUser); err != nil { + if has, err := db.GetEngine(ctx).Get(issueUser); err != nil { return err } else if !has { issue.IsRead = false @@ -382,9 +382,9 @@ func (issue *Issue) GetIsRead(userID int64) error { } // APIURL returns the absolute APIURL to this issue. -func (issue *Issue) APIURL() string { +func (issue *Issue) APIURL(ctx context.Context) string { if issue.Repo == nil { - err := issue.LoadRepo(db.DefaultContext) + err := issue.LoadRepo(ctx) if err != nil { log.Error("Issue[%d].APIURL(): %v", issue.ID, err) return "" @@ -479,9 +479,9 @@ func (issue *Issue) GetLastEventLabel() string { } // GetLastComment return last comment for the current issue. -func (issue *Issue) GetLastComment() (*Comment, error) { +func (issue *Issue) GetLastComment(ctx context.Context) (*Comment, error) { var c Comment - exist, err := db.GetEngine(db.DefaultContext).Where("type = ?", CommentTypeComment). + exist, err := db.GetEngine(ctx).Where("type = ?", CommentTypeComment). And("issue_id = ?", issue.ID).Desc("created_unix").Get(&c) if err != nil { return nil, err @@ -543,12 +543,12 @@ func GetIssueByID(ctx context.Context, id int64) (*Issue, error) { } // GetIssueWithAttrsByID returns an issue with attributes by given ID. -func GetIssueWithAttrsByID(id int64) (*Issue, error) { - issue, err := GetIssueByID(db.DefaultContext, id) +func GetIssueWithAttrsByID(ctx context.Context, id int64) (*Issue, error) { + issue, err := GetIssueByID(ctx, id) if err != nil { return nil, err } - return issue, issue.LoadAttributes(db.DefaultContext) + return issue, issue.LoadAttributes(ctx) } // GetIssuesByIDs return issues with the given IDs. @@ -600,8 +600,8 @@ func GetParticipantsIDsByIssueID(ctx context.Context, issueID int64) ([]int64, e } // IsUserParticipantsOfIssue return true if user is participants of an issue -func IsUserParticipantsOfIssue(user *user_model.User, issue *Issue) bool { - userIDs, err := issue.GetParticipantIDsByIssue(db.DefaultContext) +func IsUserParticipantsOfIssue(ctx context.Context, user *user_model.User, issue *Issue) bool { + userIDs, err := issue.GetParticipantIDsByIssue(ctx) if err != nil { log.Error(err.Error()) return false @@ -894,8 +894,8 @@ func IsErrIssueMaxPinReached(err error) bool { } // InsertIssues insert issues to database -func InsertIssues(issues ...*Issue) error { - ctx, committer, err := db.TxContext(db.DefaultContext) +func InsertIssues(ctx context.Context, issues ...*Issue) error { + ctx, committer, err := db.TxContext(ctx) if err != nil { return err } diff --git a/models/issues/issue_label.go b/models/issues/issue_label.go index 119a13adf2227..0a2ffdb35fd40 100644 --- a/models/issues/issue_label.go +++ b/models/issues/issue_label.go @@ -54,6 +54,8 @@ func newIssueLabel(ctx context.Context, issue *Issue, label *Label, doer *user_m return err } + issue.Labels = append(issue.Labels, label) + return updateLabelCols(ctx, label, "num_issues", "num_closed_issue") } @@ -122,6 +124,11 @@ func newIssueLabels(ctx context.Context, issue *Issue, labels []*Label, doer *us if err = issue.LoadRepo(ctx); err != nil { return err } + + if err = issue.LoadLabels(ctx); err != nil { + return err + } + for _, l := range labels { // Don't add already present labels and invalid labels if HasIssueLabel(ctx, issue.ID, l.ID) || @@ -129,6 +136,10 @@ func newIssueLabels(ctx context.Context, issue *Issue, labels []*Label, doer *us continue } + if err = RemoveDuplicateExclusiveIssueLabels(ctx, issue, l, doer); err != nil { + return err + } + if err = newIssueLabel(ctx, issue, l, doer); err != nil { return fmt.Errorf("newIssueLabel: %w", err) } diff --git a/models/issues/issue_label_test.go b/models/issues/issue_label_test.go new file mode 100644 index 0000000000000..0d991b7c4fca3 --- /dev/null +++ b/models/issues/issue_label_test.go @@ -0,0 +1,28 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package issues_test + +import ( + "testing" + + issues_model "code.gitea.io/gitea/models/issues" + "code.gitea.io/gitea/models/unittest" + user_model "code.gitea.io/gitea/models/user" + + "github.com/stretchr/testify/assert" +) + +func TestNewIssueLabelsScope(t *testing.T) { + assert.NoError(t, unittest.PrepareTestDatabase()) + + issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 18}) + label1 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 7}) + label2 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 8}) + doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) + + assert.NoError(t, issues_model.NewIssueLabels(issue, []*issues_model.Label{label1, label2}, doer)) + + assert.Len(t, issue.Labels, 1) + assert.Equal(t, label2.ID, issue.Labels[0].ID) +} diff --git a/models/issues/issue_test.go b/models/issues/issue_test.go index 7301995524d46..4e98442c11ffc 100644 --- a/models/issues/issue_test.go +++ b/models/issues/issue_test.go @@ -65,7 +65,7 @@ func TestIssueAPIURL(t *testing.T) { err := issue.LoadAttributes(db.DefaultContext) assert.NoError(t, err) - assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/issues/1", issue.APIURL()) + assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/issues/1", issue.APIURL(db.DefaultContext)) } func TestGetIssuesByIDs(t *testing.T) { @@ -253,7 +253,7 @@ func testInsertIssue(t *testing.T, title, content string, expectIndex int64) *is Title: title, Content: content, } - err := issues_model.NewIssue(repo, &issue, nil, nil) + err := issues_model.NewIssue(db.DefaultContext, repo, &issue, nil, nil) assert.NoError(t, err) has, err := db.GetEngine(db.DefaultContext).ID(issue.ID).Get(&newIssue) @@ -477,7 +477,7 @@ func assertCreateIssues(t *testing.T, isPull bool) { Labels: []*issues_model.Label{label}, Reactions: []*issues_model.Reaction{reaction}, } - err := issues_model.InsertIssues(is) + err := issues_model.InsertIssues(db.DefaultContext, is) assert.NoError(t, err) i := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{Title: title}) diff --git a/models/issues/issue_update.go b/models/issues/issue_update.go index 9607b21a67585..b258dc882cb2c 100644 --- a/models/issues/issue_update.go +++ b/models/issues/issue_update.go @@ -165,8 +165,8 @@ func ChangeIssueTitle(ctx context.Context, issue *Issue, doer *user_model.User, } // ChangeIssueRef changes the branch of this issue, as the given user. -func ChangeIssueRef(issue *Issue, doer *user_model.User, oldRef string) (err error) { - ctx, committer, err := db.TxContext(db.DefaultContext) +func ChangeIssueRef(ctx context.Context, issue *Issue, doer *user_model.User, oldRef string) (err error) { + ctx, committer, err := db.TxContext(ctx) if err != nil { return err } @@ -215,8 +215,8 @@ func AddDeletePRBranchComment(ctx context.Context, doer *user_model.User, repo * } // UpdateIssueAttachments update attachments by UUIDs for the issue -func UpdateIssueAttachments(issueID int64, uuids []string) (err error) { - ctx, committer, err := db.TxContext(db.DefaultContext) +func UpdateIssueAttachments(ctx context.Context, issueID int64, uuids []string) (err error) { + ctx, committer, err := db.TxContext(ctx) if err != nil { return err } @@ -235,8 +235,8 @@ func UpdateIssueAttachments(issueID int64, uuids []string) (err error) { } // ChangeIssueContent changes issue content, as the given user. -func ChangeIssueContent(issue *Issue, doer *user_model.User, content string) (err error) { - ctx, committer, err := db.TxContext(db.DefaultContext) +func ChangeIssueContent(ctx context.Context, issue *Issue, doer *user_model.User, content string) (err error) { + ctx, committer, err := db.TxContext(ctx) if err != nil { return err } @@ -381,8 +381,8 @@ func NewIssueWithIndex(ctx context.Context, doer *user_model.User, opts NewIssue } // NewIssue creates new issue with labels for repository. -func NewIssue(repo *repo_model.Repository, issue *Issue, labelIDs []int64, uuids []string) (err error) { - ctx, committer, err := db.TxContext(db.DefaultContext) +func NewIssue(ctx context.Context, repo *repo_model.Repository, issue *Issue, labelIDs []int64, uuids []string) (err error) { + ctx, committer, err := db.TxContext(ctx) if err != nil { return err } @@ -432,8 +432,8 @@ func UpdateIssueMentions(ctx context.Context, issueID int64, mentions []*user_mo // UpdateIssueByAPI updates all allowed fields of given issue. // If the issue status is changed a statusChangeComment is returned // similarly if the title is changed the titleChanged bool is set to true -func UpdateIssueByAPI(issue *Issue, doer *user_model.User) (statusChangeComment *Comment, titleChanged bool, err error) { - ctx, committer, err := db.TxContext(db.DefaultContext) +func UpdateIssueByAPI(ctx context.Context, issue *Issue, doer *user_model.User) (statusChangeComment *Comment, titleChanged bool, err error) { + ctx, committer, err := db.TxContext(ctx) if err != nil { return nil, false, err } @@ -486,12 +486,12 @@ func UpdateIssueByAPI(issue *Issue, doer *user_model.User) (statusChangeComment } // UpdateIssueDeadline updates an issue deadline and adds comments. Setting a deadline to 0 means deleting it. -func UpdateIssueDeadline(issue *Issue, deadlineUnix timeutil.TimeStamp, doer *user_model.User) (err error) { +func UpdateIssueDeadline(ctx context.Context, issue *Issue, deadlineUnix timeutil.TimeStamp, doer *user_model.User) (err error) { // if the deadline hasn't changed do nothing if issue.DeadlineUnix == deadlineUnix { return nil } - ctx, committer, err := db.TxContext(db.DefaultContext) + ctx, committer, err := db.TxContext(ctx) if err != nil { return err } @@ -510,17 +510,6 @@ func UpdateIssueDeadline(issue *Issue, deadlineUnix timeutil.TimeStamp, doer *us return committer.Commit() } -// DeleteInIssue delete records in beans with external key issue_id = ? -func DeleteInIssue(ctx context.Context, issueID int64, beans ...any) error { - e := db.GetEngine(ctx) - for _, bean := range beans { - if _, err := e.In("issue_id", issueID).Delete(bean); err != nil { - return err - } - } - return nil -} - // FindAndUpdateIssueMentions finds users mentioned in the given content string, and saves them in the database. func FindAndUpdateIssueMentions(ctx context.Context, issue *Issue, doer *user_model.User, content string) (mentions []*user_model.User, err error) { rawMentions := references.FindAllMentionsMarkdown(content) @@ -669,8 +658,8 @@ func ResolveIssueMentionsByVisibility(ctx context.Context, issue *Issue, doer *u } // UpdateIssuesMigrationsByType updates all migrated repositories' issues from gitServiceType to replace originalAuthorID to posterID -func UpdateIssuesMigrationsByType(gitServiceType api.GitServiceType, originalAuthorID string, posterID int64) error { - _, err := db.GetEngine(db.DefaultContext).Table("issue"). +func UpdateIssuesMigrationsByType(ctx context.Context, gitServiceType api.GitServiceType, originalAuthorID string, posterID int64) error { + _, err := db.GetEngine(ctx).Table("issue"). Where("repo_id IN (SELECT id FROM repository WHERE original_service_type = ?)", gitServiceType). And("original_author_id = ?", originalAuthorID). Update(map[string]any{ @@ -682,8 +671,8 @@ func UpdateIssuesMigrationsByType(gitServiceType api.GitServiceType, originalAut } // UpdateReactionsMigrationsByType updates all migrated repositories' reactions from gitServiceType to replace originalAuthorID to posterID -func UpdateReactionsMigrationsByType(gitServiceType api.GitServiceType, originalAuthorID string, userID int64) error { - _, err := db.GetEngine(db.DefaultContext).Table("reaction"). +func UpdateReactionsMigrationsByType(ctx context.Context, gitServiceType api.GitServiceType, originalAuthorID string, userID int64) error { + _, err := db.GetEngine(ctx).Table("reaction"). Where("original_author_id = ?", originalAuthorID). And(migratedIssueCond(gitServiceType)). Update(map[string]any{ @@ -696,85 +685,100 @@ func UpdateReactionsMigrationsByType(gitServiceType api.GitServiceType, original // DeleteIssuesByRepoID deletes issues by repositories id func DeleteIssuesByRepoID(ctx context.Context, repoID int64) (attachmentPaths []string, err error) { - deleteCond := builder.Select("id").From("issue").Where(builder.Eq{"issue.repo_id": repoID}) - + // MariaDB has a performance bug: https://jira.mariadb.org/browse/MDEV-16289 + // so here it uses "DELETE ... WHERE IN" with pre-queried IDs. sess := db.GetEngine(ctx) - // Delete content histories - if _, err = sess.In("issue_id", deleteCond). - Delete(&ContentHistory{}); err != nil { - return nil, err - } - // Delete comments and attachments - if _, err = sess.In("issue_id", deleteCond). - Delete(&Comment{}); err != nil { - return nil, err - } + for { + issueIDs := make([]int64, 0, db.DefaultMaxInSize) - // Dependencies for issues in this repository - if _, err = sess.In("issue_id", deleteCond). - Delete(&IssueDependency{}); err != nil { - return nil, err - } + err := sess.Table(&Issue{}).Where("repo_id = ?", repoID).OrderBy("id").Limit(db.DefaultMaxInSize).Cols("id").Find(&issueIDs) + if err != nil { + return nil, err + } - // Delete dependencies for issues in other repositories - if _, err = sess.In("dependency_id", deleteCond). - Delete(&IssueDependency{}); err != nil { - return nil, err - } + if len(issueIDs) == 0 { + break + } - if _, err = sess.In("issue_id", deleteCond). - Delete(&IssueUser{}); err != nil { - return nil, err - } + // Delete content histories + _, err = sess.In("issue_id", issueIDs).Delete(&ContentHistory{}) + if err != nil { + return nil, err + } - if _, err = sess.In("issue_id", deleteCond). - Delete(&Reaction{}); err != nil { - return nil, err - } + // Delete comments and attachments + _, err = sess.In("issue_id", issueIDs).Delete(&Comment{}) + if err != nil { + return nil, err + } - if _, err = sess.In("issue_id", deleteCond). - Delete(&IssueWatch{}); err != nil { - return nil, err - } + // Dependencies for issues in this repository + _, err = sess.In("issue_id", issueIDs).Delete(&IssueDependency{}) + if err != nil { + return nil, err + } - if _, err = sess.In("issue_id", deleteCond). - Delete(&Stopwatch{}); err != nil { - return nil, err - } + // Delete dependencies for issues in other repositories + _, err = sess.In("dependency_id", issueIDs).Delete(&IssueDependency{}) + if err != nil { + return nil, err + } - if _, err = sess.In("issue_id", deleteCond). - Delete(&TrackedTime{}); err != nil { - return nil, err - } + _, err = sess.In("issue_id", issueIDs).Delete(&IssueUser{}) + if err != nil { + return nil, err + } - if _, err = sess.In("issue_id", deleteCond). - Delete(&project_model.ProjectIssue{}); err != nil { - return nil, err - } + _, err = sess.In("issue_id", issueIDs).Delete(&Reaction{}) + if err != nil { + return nil, err + } - if _, err = sess.In("dependent_issue_id", deleteCond). - Delete(&Comment{}); err != nil { - return nil, err - } + _, err = sess.In("issue_id", issueIDs).Delete(&IssueWatch{}) + if err != nil { + return nil, err + } - var attachments []*repo_model.Attachment - if err = sess.In("issue_id", deleteCond). - Find(&attachments); err != nil { - return nil, err - } + _, err = sess.In("issue_id", issueIDs).Delete(&Stopwatch{}) + if err != nil { + return nil, err + } - for j := range attachments { - attachmentPaths = append(attachmentPaths, attachments[j].RelativePath()) - } + _, err = sess.In("issue_id", issueIDs).Delete(&TrackedTime{}) + if err != nil { + return nil, err + } - if _, err = sess.In("issue_id", deleteCond). - Delete(&repo_model.Attachment{}); err != nil { - return nil, err - } + _, err = sess.In("issue_id", issueIDs).Delete(&project_model.ProjectIssue{}) + if err != nil { + return nil, err + } - if _, err = db.DeleteByBean(ctx, &Issue{RepoID: repoID}); err != nil { - return nil, err + _, err = sess.In("dependent_issue_id", issueIDs).Delete(&Comment{}) + if err != nil { + return nil, err + } + + var attachments []*repo_model.Attachment + err = sess.In("issue_id", issueIDs).Find(&attachments) + if err != nil { + return nil, err + } + + for j := range attachments { + attachmentPaths = append(attachmentPaths, attachments[j].RelativePath()) + } + + _, err = sess.In("issue_id", issueIDs).Delete(&repo_model.Attachment{}) + if err != nil { + return nil, err + } + + _, err = sess.In("id", issueIDs).Delete(&Issue{}) + if err != nil { + return nil, err + } } return attachmentPaths, err @@ -809,7 +813,7 @@ func DeleteOrphanedIssues(ctx context.Context) error { // Remove issue attachment files. for i := range attachmentPaths { - system_model.RemoveAllWithNotice(db.DefaultContext, "Delete issue attachment", attachmentPaths[i]) + system_model.RemoveAllWithNotice(ctx, "Delete issue attachment", attachmentPaths[i]) } return nil } diff --git a/models/issues/issue_watch.go b/models/issues/issue_watch.go index b7e9504c6762b..9e616a0eb1319 100644 --- a/models/issues/issue_watch.go +++ b/models/issues/issue_watch.go @@ -81,7 +81,7 @@ func CheckIssueWatch(ctx context.Context, user *user_model.User, issue *Issue) ( if err != nil { return false, err } - return repo_model.IsWatchMode(w.Mode) || IsUserParticipantsOfIssue(user, issue), nil + return repo_model.IsWatchMode(w.Mode) || IsUserParticipantsOfIssue(ctx, user, issue), nil } // GetIssueWatchersIDs returns IDs of subscribers or explicit unsubscribers to a given issue id diff --git a/models/issues/issue_xref.go b/models/issues/issue_xref.go index a1086f9e8120a..77ef53a013239 100644 --- a/models/issues/issue_xref.go +++ b/models/issues/issue_xref.go @@ -252,22 +252,22 @@ func (c *Comment) neuterCrossReferences(ctx context.Context) error { } // LoadRefComment loads comment that created this reference from database -func (c *Comment) LoadRefComment() (err error) { +func (c *Comment) LoadRefComment(ctx context.Context) (err error) { if c.RefComment != nil { return nil } - c.RefComment, err = GetCommentByID(db.DefaultContext, c.RefCommentID) + c.RefComment, err = GetCommentByID(ctx, c.RefCommentID) return err } // LoadRefIssue loads comment that created this reference from database -func (c *Comment) LoadRefIssue() (err error) { +func (c *Comment) LoadRefIssue(ctx context.Context) (err error) { if c.RefIssue != nil { return nil } - c.RefIssue, err = GetIssueByID(db.DefaultContext, c.RefIssueID) + c.RefIssue, err = GetIssueByID(ctx, c.RefIssueID) if err == nil { - err = c.RefIssue.LoadRepo(db.DefaultContext) + err = c.RefIssue.LoadRepo(ctx) } return err } @@ -278,21 +278,21 @@ func CommentTypeIsRef(t CommentType) bool { } // RefCommentLink returns the relative URL for the comment that created this reference -func (c *Comment) RefCommentLink() string { +func (c *Comment) RefCommentLink(ctx context.Context) string { // Edge case for when the reference is inside the title or the description of the referring issue if c.RefCommentID == 0 { - return c.RefIssueLink() + return c.RefIssueLink(ctx) } - if err := c.LoadRefComment(); err != nil { // Silently dropping errors :unamused: + if err := c.LoadRefComment(ctx); err != nil { // Silently dropping errors :unamused: log.Error("LoadRefComment(%d): %v", c.RefCommentID, err) return "" } - return c.RefComment.Link() + return c.RefComment.Link(ctx) } // RefIssueLink returns the relative URL of the issue where this reference was created -func (c *Comment) RefIssueLink() string { - if err := c.LoadRefIssue(); err != nil { // Silently dropping errors :unamused: +func (c *Comment) RefIssueLink(ctx context.Context) string { + if err := c.LoadRefIssue(ctx); err != nil { // Silently dropping errors :unamused: log.Error("LoadRefIssue(%d): %v", c.RefCommentID, err) return "" } @@ -300,8 +300,8 @@ func (c *Comment) RefIssueLink() string { } // RefIssueTitle returns the title of the issue where this reference was created -func (c *Comment) RefIssueTitle() string { - if err := c.LoadRefIssue(); err != nil { // Silently dropping errors :unamused: +func (c *Comment) RefIssueTitle(ctx context.Context) string { + if err := c.LoadRefIssue(ctx); err != nil { // Silently dropping errors :unamused: log.Error("LoadRefIssue(%d): %v", c.RefCommentID, err) return "" } @@ -309,8 +309,8 @@ func (c *Comment) RefIssueTitle() string { } // RefIssueIdent returns the user friendly identity (e.g. "#1234") of the issue where this reference was created -func (c *Comment) RefIssueIdent() string { - if err := c.LoadRefIssue(); err != nil { // Silently dropping errors :unamused: +func (c *Comment) RefIssueIdent(ctx context.Context) string { + if err := c.LoadRefIssue(ctx); err != nil { // Silently dropping errors :unamused: log.Error("LoadRefIssue(%d): %v", c.RefCommentID, err) return "" } diff --git a/models/issues/pull.go b/models/issues/pull.go index 3ca0847652f34..9adcaee1a1af0 100644 --- a/models/issues/pull.go +++ b/models/issues/pull.go @@ -1040,7 +1040,7 @@ func ParseCodeOwnersLine(ctx context.Context, tokens []string) (*CodeOwnerRule, warnings = append(warnings, fmt.Sprintf("incorrect codeowner organization: %s", user)) continue } - teams, err := org.LoadTeams() + teams, err := org.LoadTeams(ctx) if err != nil { warnings = append(warnings, fmt.Sprintf("incorrect codeowner team: %s", user)) continue diff --git a/models/issues/review.go b/models/issues/review.go index 931f1a2ba72e4..8b64ba8048989 100644 --- a/models/issues/review.go +++ b/models/issues/review.go @@ -231,7 +231,7 @@ type CreateReviewOptions struct { } // IsOfficialReviewer check if at least one of the provided reviewers can make official reviews in issue (counts towards required approvals) -func IsOfficialReviewer(ctx context.Context, issue *Issue, reviewers ...*user_model.User) (bool, error) { +func IsOfficialReviewer(ctx context.Context, issue *Issue, reviewer *user_model.User) (bool, error) { pr, err := GetPullRequestByIssueID(ctx, issue.ID) if err != nil { return false, err @@ -242,14 +242,21 @@ func IsOfficialReviewer(ctx context.Context, issue *Issue, reviewers ...*user_mo return false, err } if rule == nil { - return false, nil + // if no rule is found, then user with write access can make official reviews + err := pr.LoadBaseRepo(ctx) + if err != nil { + return false, err + } + writeAccess, err := access_model.HasAccessUnit(ctx, reviewer, pr.BaseRepo, unit.TypeCode, perm.AccessModeWrite) + if err != nil { + return false, err + } + return writeAccess, nil } - for _, reviewer := range reviewers { - official, err := git_model.IsUserOfficialReviewer(ctx, rule, reviewer) - if official || err != nil { - return official, err - } + official, err := git_model.IsUserOfficialReviewer(ctx, rule, reviewer) + if official || err != nil { + return official, err } return false, nil @@ -322,8 +329,8 @@ func GetCurrentReview(ctx context.Context, reviewer *user_model.User, issue *Iss } // ReviewExists returns whether a review exists for a particular line of code in the PR -func ReviewExists(issue *Issue, treePath string, line int64) (bool, error) { - return db.GetEngine(db.DefaultContext).Cols("id").Exist(&Comment{IssueID: issue.ID, TreePath: treePath, Line: line, Type: CommentTypeCode}) +func ReviewExists(ctx context.Context, issue *Issue, treePath string, line int64) (bool, error) { + return db.GetEngine(ctx).Cols("id").Exist(&Comment{IssueID: issue.ID, TreePath: treePath, Line: line, Type: CommentTypeCode}) } // ContentEmptyErr represents an content empty error @@ -340,8 +347,8 @@ func IsContentEmptyErr(err error) bool { } // SubmitReview creates a review out of the existing pending review or creates a new one if no pending review exist -func SubmitReview(doer *user_model.User, issue *Issue, reviewType ReviewType, content, commitID string, stale bool, attachmentUUIDs []string) (*Review, *Comment, error) { - ctx, committer, err := db.TxContext(db.DefaultContext) +func SubmitReview(ctx context.Context, doer *user_model.User, issue *Issue, reviewType ReviewType, content, commitID string, stale bool, attachmentUUIDs []string) (*Review, *Comment, error) { + ctx, committer, err := db.TxContext(ctx) if err != nil { return nil, nil, err } @@ -487,15 +494,15 @@ func GetTeamReviewerByIssueIDAndTeamID(ctx context.Context, issueID, teamID int6 } // MarkReviewsAsStale marks existing reviews as stale -func MarkReviewsAsStale(issueID int64) (err error) { - _, err = db.GetEngine(db.DefaultContext).Exec("UPDATE `review` SET stale=? WHERE issue_id=?", true, issueID) +func MarkReviewsAsStale(ctx context.Context, issueID int64) (err error) { + _, err = db.GetEngine(ctx).Exec("UPDATE `review` SET stale=? WHERE issue_id=?", true, issueID) return err } // MarkReviewsAsNotStale marks existing reviews as not stale for a giving commit SHA -func MarkReviewsAsNotStale(issueID int64, commitID string) (err error) { - _, err = db.GetEngine(db.DefaultContext).Exec("UPDATE `review` SET stale=? WHERE issue_id=? AND commit_id=?", false, issueID, commitID) +func MarkReviewsAsNotStale(ctx context.Context, issueID int64, commitID string) (err error) { + _, err = db.GetEngine(ctx).Exec("UPDATE `review` SET stale=? WHERE issue_id=? AND commit_id=?", false, issueID, commitID) return err } @@ -518,8 +525,8 @@ func DismissReview(ctx context.Context, review *Review, isDismiss bool) (err err } // InsertReviews inserts review and review comments -func InsertReviews(reviews []*Review) error { - ctx, committer, err := db.TxContext(db.DefaultContext) +func InsertReviews(ctx context.Context, reviews []*Review) error { + ctx, committer, err := db.TxContext(ctx) if err != nil { return err } @@ -578,7 +585,9 @@ func AddReviewRequest(ctx context.Context, issue *Issue, reviewer, doer *user_mo return nil, nil } - official, err := IsOfficialReviewer(ctx, issue, reviewer, doer) + // if the reviewer is an official reviewer, + // remove the official flag in the all previous reviews + official, err := IsOfficialReviewer(ctx, issue, reviewer) if err != nil { return nil, err } else if official { @@ -794,7 +803,7 @@ func RemoveTeamReviewRequest(ctx context.Context, issue *Issue, reviewer *organi } // MarkConversation Add or remove Conversation mark for a code comment -func MarkConversation(comment *Comment, doer *user_model.User, isResolve bool) (err error) { +func MarkConversation(ctx context.Context, comment *Comment, doer *user_model.User, isResolve bool) (err error) { if comment.Type != CommentTypeCode { return nil } @@ -804,7 +813,7 @@ func MarkConversation(comment *Comment, doer *user_model.User, isResolve bool) ( return nil } - if _, err = db.GetEngine(db.DefaultContext).Exec("UPDATE `comment` SET resolve_doer_id=? WHERE id=?", doer.ID, comment.ID); err != nil { + if _, err = db.GetEngine(ctx).Exec("UPDATE `comment` SET resolve_doer_id=? WHERE id=?", doer.ID, comment.ID); err != nil { return err } } else { @@ -812,7 +821,7 @@ func MarkConversation(comment *Comment, doer *user_model.User, isResolve bool) ( return nil } - if _, err = db.GetEngine(db.DefaultContext).Exec("UPDATE `comment` SET resolve_doer_id=? WHERE id=?", 0, comment.ID); err != nil { + if _, err = db.GetEngine(ctx).Exec("UPDATE `comment` SET resolve_doer_id=? WHERE id=?", 0, comment.ID); err != nil { return err } } @@ -822,24 +831,24 @@ func MarkConversation(comment *Comment, doer *user_model.User, isResolve bool) ( // CanMarkConversation Add or remove Conversation mark for a code comment permission check // the PR writer , offfcial reviewer and poster can do it -func CanMarkConversation(issue *Issue, doer *user_model.User) (permResult bool, err error) { +func CanMarkConversation(ctx context.Context, issue *Issue, doer *user_model.User) (permResult bool, err error) { if doer == nil || issue == nil { return false, fmt.Errorf("issue or doer is nil") } if doer.ID != issue.PosterID { - if err = issue.LoadRepo(db.DefaultContext); err != nil { + if err = issue.LoadRepo(ctx); err != nil { return false, err } - p, err := access_model.GetUserRepoPermission(db.DefaultContext, issue.Repo, doer) + p, err := access_model.GetUserRepoPermission(ctx, issue.Repo, doer) if err != nil { return false, err } permResult = p.CanAccess(perm.AccessModeWrite, unit.TypePullRequests) if !permResult { - if permResult, err = IsOfficialReviewer(db.DefaultContext, issue, doer); err != nil { + if permResult, err = IsOfficialReviewer(ctx, issue, doer); err != nil { return false, err } } @@ -853,8 +862,8 @@ func CanMarkConversation(issue *Issue, doer *user_model.User) (permResult bool, } // DeleteReview delete a review and it's code comments -func DeleteReview(r *Review) error { - ctx, committer, err := db.TxContext(db.DefaultContext) +func DeleteReview(ctx context.Context, r *Review) error { + ctx, committer, err := db.TxContext(ctx) if err != nil { return err } @@ -903,7 +912,7 @@ func DeleteReview(r *Review) error { } // GetCodeCommentsCount return count of CodeComments a Review has -func (r *Review) GetCodeCommentsCount() int { +func (r *Review) GetCodeCommentsCount(ctx context.Context) int { opts := FindCommentsOptions{ Type: CommentTypeCode, IssueID: r.IssueID, @@ -914,7 +923,7 @@ func (r *Review) GetCodeCommentsCount() int { conds = conds.And(builder.Eq{"invalidated": false}) } - count, err := db.GetEngine(db.DefaultContext).Where(conds).Count(new(Comment)) + count, err := db.GetEngine(ctx).Where(conds).Count(new(Comment)) if err != nil { return 0 } @@ -922,18 +931,18 @@ func (r *Review) GetCodeCommentsCount() int { } // HTMLURL formats a URL-string to the related review issue-comment -func (r *Review) HTMLURL() string { +func (r *Review) HTMLURL(ctx context.Context) string { opts := FindCommentsOptions{ Type: CommentTypeReview, IssueID: r.IssueID, ReviewID: r.ID, } comment := new(Comment) - has, err := db.GetEngine(db.DefaultContext).Where(opts.ToConds()).Get(comment) + has, err := db.GetEngine(ctx).Where(opts.ToConds()).Get(comment) if err != nil || !has { return "" } - return comment.HTMLURL() + return comment.HTMLURL(ctx) } // RemapExternalUser ExternalUserRemappable interface @@ -954,8 +963,8 @@ func (r *Review) GetExternalName() string { return r.OriginalAuthor } func (r *Review) GetExternalID() int64 { return r.OriginalAuthorID } // UpdateReviewsMigrationsByType updates reviews' migrations information via given git service type and original id and poster id -func UpdateReviewsMigrationsByType(tp structs.GitServiceType, originalAuthorID string, posterID int64) error { - _, err := db.GetEngine(db.DefaultContext).Table("review"). +func UpdateReviewsMigrationsByType(ctx context.Context, tp structs.GitServiceType, originalAuthorID string, posterID int64) error { + _, err := db.GetEngine(ctx).Table("review"). Where("original_author_id = ?", originalAuthorID). And(migratedIssueCond(tp)). Update(map[string]any{ diff --git a/models/issues/review_test.go b/models/issues/review_test.go index cd5b221bcd9d8..63e2aef2cce02 100644 --- a/models/issues/review_test.go +++ b/models/issues/review_test.go @@ -248,7 +248,7 @@ func TestDeleteReview(t *testing.T) { }) assert.NoError(t, err) - assert.NoError(t, issues_model.DeleteReview(review2)) + assert.NoError(t, issues_model.DeleteReview(db.DefaultContext, review2)) _, err = issues_model.GetReviewByID(db.DefaultContext, review2.ID) assert.Error(t, err) diff --git a/models/issues/tracked_time.go b/models/issues/tracked_time.go index 58c6b775f0778..89c99c5cd1313 100644 --- a/models/issues/tracked_time.go +++ b/models/issues/tracked_time.go @@ -198,9 +198,9 @@ func addTime(ctx context.Context, user *user_model.User, issue *Issue, amount in return tt, db.Insert(ctx, tt) } -// TotalTimes returns the spent time in seconds for each user by an issue -func TotalTimes(options *FindTrackedTimesOptions) (map[*user_model.User]int64, error) { - trackedTimes, err := GetTrackedTimes(db.DefaultContext, options) +// TotalTimesForEachUser returns the spent time in seconds for each user by an issue +func TotalTimesForEachUser(ctx context.Context, options *FindTrackedTimesOptions) (map[*user_model.User]int64, error) { + trackedTimes, err := GetTrackedTimes(ctx, options) if err != nil { return nil, err } @@ -213,7 +213,7 @@ func TotalTimes(options *FindTrackedTimesOptions) (map[*user_model.User]int64, e totalTimes := make(map[*user_model.User]int64) // Fetching User and making time human readable for userID, total := range totalTimesByUser { - user, err := user_model.GetUserByID(db.DefaultContext, userID) + user, err := user_model.GetUserByID(ctx, userID) if err != nil { if user_model.IsErrUserNotExist(err) { continue @@ -226,8 +226,8 @@ func TotalTimes(options *FindTrackedTimesOptions) (map[*user_model.User]int64, e } // DeleteIssueUserTimes deletes times for issue -func DeleteIssueUserTimes(issue *Issue, user *user_model.User) error { - ctx, committer, err := db.TxContext(db.DefaultContext) +func DeleteIssueUserTimes(ctx context.Context, issue *Issue, user *user_model.User) error { + ctx, committer, err := db.TxContext(ctx) if err != nil { return err } @@ -265,8 +265,8 @@ func DeleteIssueUserTimes(issue *Issue, user *user_model.User) error { } // DeleteTime delete a specific Time -func DeleteTime(t *TrackedTime) error { - ctx, committer, err := db.TxContext(db.DefaultContext) +func DeleteTime(ctx context.Context, t *TrackedTime) error { + ctx, committer, err := db.TxContext(ctx) if err != nil { return err } @@ -315,9 +315,9 @@ func deleteTime(ctx context.Context, t *TrackedTime) error { } // GetTrackedTimeByID returns raw TrackedTime without loading attributes by id -func GetTrackedTimeByID(id int64) (*TrackedTime, error) { +func GetTrackedTimeByID(ctx context.Context, id int64) (*TrackedTime, error) { time := new(TrackedTime) - has, err := db.GetEngine(db.DefaultContext).ID(id).Get(time) + has, err := db.GetEngine(ctx).ID(id).Get(time) if err != nil { return nil, err } else if !has { diff --git a/models/issues/tracked_time_test.go b/models/issues/tracked_time_test.go index caced78c9e899..cc2cb918e0744 100644 --- a/models/issues/tracked_time_test.go +++ b/models/issues/tracked_time_test.go @@ -79,10 +79,10 @@ func TestGetTrackedTimes(t *testing.T) { assert.Len(t, times, 0) } -func TestTotalTimes(t *testing.T) { +func TestTotalTimesForEachUser(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - total, err := issues_model.TotalTimes(&issues_model.FindTrackedTimesOptions{IssueID: 1}) + total, err := issues_model.TotalTimesForEachUser(db.DefaultContext, &issues_model.FindTrackedTimesOptions{IssueID: 1}) assert.NoError(t, err) assert.Len(t, total, 1) for user, time := range total { @@ -90,7 +90,7 @@ func TestTotalTimes(t *testing.T) { assert.EqualValues(t, 400, time) } - total, err = issues_model.TotalTimes(&issues_model.FindTrackedTimesOptions{IssueID: 2}) + total, err = issues_model.TotalTimesForEachUser(db.DefaultContext, &issues_model.FindTrackedTimesOptions{IssueID: 2}) assert.NoError(t, err) assert.Len(t, total, 2) for user, time := range total { @@ -103,7 +103,7 @@ func TestTotalTimes(t *testing.T) { } } - total, err = issues_model.TotalTimes(&issues_model.FindTrackedTimesOptions{IssueID: 5}) + total, err = issues_model.TotalTimesForEachUser(db.DefaultContext, &issues_model.FindTrackedTimesOptions{IssueID: 5}) assert.NoError(t, err) assert.Len(t, total, 1) for user, time := range total { @@ -111,7 +111,7 @@ func TestTotalTimes(t *testing.T) { assert.EqualValues(t, 1, time) } - total, err = issues_model.TotalTimes(&issues_model.FindTrackedTimesOptions{IssueID: 4}) + total, err = issues_model.TotalTimesForEachUser(db.DefaultContext, &issues_model.FindTrackedTimesOptions{IssueID: 4}) assert.NoError(t, err) assert.Len(t, total, 2) } diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index 38fff37bed066..a8037fa67ed17 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -20,6 +20,7 @@ import ( "code.gitea.io/gitea/models/migrations/v1_19" "code.gitea.io/gitea/models/migrations/v1_20" "code.gitea.io/gitea/models/migrations/v1_21" + "code.gitea.io/gitea/models/migrations/v1_22" "code.gitea.io/gitea/models/migrations/v1_6" "code.gitea.io/gitea/models/migrations/v1_7" "code.gitea.io/gitea/models/migrations/v1_8" @@ -536,6 +537,15 @@ var migrations = []Migration{ 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 280 + + // v280 -> v281 + NewMigration("Rename user themes", v1_22.RenameUserThemes), } // GetCurrentDBVersion returns the current db version diff --git a/models/migrations/v1_18/v227.go b/models/migrations/v1_18/v227.go index 78c80f74ece34..5fe5dcd0c9563 100644 --- a/models/migrations/v1_18/v227.go +++ b/models/migrations/v1_18/v227.go @@ -4,10 +4,6 @@ package v1_18 //nolint import ( - "fmt" - "strconv" - - "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" "xorm.io/xorm" @@ -22,42 +18,6 @@ type SystemSetting struct { Updated timeutil.TimeStamp `xorm:"updated"` } -func insertSettingsIfNotExist(x *xorm.Engine, sysSettings []*SystemSetting) error { - sess := x.NewSession() - defer sess.Close() - if err := sess.Begin(); err != nil { - return err - } - for _, setting := range sysSettings { - exist, err := sess.Table("system_setting").Where("setting_key=?", setting.SettingKey).Exist() - if err != nil { - return err - } - if !exist { - if _, err := sess.Insert(setting); err != nil { - return err - } - } - } - return sess.Commit() -} - func CreateSystemSettingsTable(x *xorm.Engine) error { - if err := x.Sync(new(SystemSetting)); err != nil { - return fmt.Errorf("sync2: %w", err) - } - - // migrate xx to database - sysSettings := []*SystemSetting{ - { - SettingKey: "picture.disable_gravatar", - SettingValue: strconv.FormatBool(setting.DisableGravatar), - }, - { - SettingKey: "picture.enable_federated_avatar", - SettingValue: strconv.FormatBool(setting.EnableFederatedAvatar), - }, - } - - return insertSettingsIfNotExist(x, sysSettings) + return x.Sync(new(SystemSetting)) } diff --git a/models/migrations/v1_21/v278.go b/models/migrations/v1_21/v278.go new file mode 100644 index 0000000000000..d6a462d1e7e60 --- /dev/null +++ b/models/migrations/v1_21/v278.go @@ -0,0 +1,16 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package v1_21 //nolint + +import ( + "xorm.io/xorm" +) + +func AddIndexToCommentDependentIssueID(x *xorm.Engine) error { + type Comment struct { + DependentIssueID int64 `xorm:"index"` + } + + return x.Sync(new(Comment)) +} diff --git a/models/migrations/v1_21/v279.go b/models/migrations/v1_21/v279.go new file mode 100644 index 0000000000000..19647225c9a95 --- /dev/null +++ b/models/migrations/v1_21/v279.go @@ -0,0 +1,16 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package v1_21 //nolint + +import ( + "xorm.io/xorm" +) + +func AddIndexToActionUserID(x *xorm.Engine) error { + type Action struct { + UserID int64 `xorm:"INDEX"` + } + + return x.Sync(new(Action)) +} diff --git a/models/migrations/v1_22/v280.go b/models/migrations/v1_22/v280.go new file mode 100644 index 0000000000000..a8ee4a3bf7dac --- /dev/null +++ b/models/migrations/v1_22/v280.go @@ -0,0 +1,29 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package v1_22 //nolint + +import ( + "xorm.io/xorm" +) + +func RenameUserThemes(x *xorm.Engine) error { + sess := x.NewSession() + defer sess.Close() + + if err := sess.Begin(); err != nil { + return err + } + + if _, err := sess.Exec("UPDATE `user` SET `theme` = 'gitea-light' WHERE `theme` = 'gitea'"); err != nil { + return err + } + if _, err := sess.Exec("UPDATE `user` SET `theme` = 'gitea-dark' WHERE `theme` = 'arc-green'"); err != nil { + return err + } + if _, err := sess.Exec("UPDATE `user` SET `theme` = 'gitea-auto' WHERE `theme` = 'auto'"); err != nil { + return err + } + + return sess.Commit() +} diff --git a/models/org_team.go b/models/org_team.go index ea7391843582c..acbab560892df 100644 --- a/models/org_team.go +++ b/models/org_team.go @@ -362,7 +362,7 @@ func AddTeamMember(ctx context.Context, team *organization.Team, userID int64) e return err } - if err := organization.AddOrgUser(team.OrgID, userID); err != nil { + if err := organization.AddOrgUser(ctx, team.OrgID, userID); err != nil { return err } diff --git a/models/organization/org.go b/models/organization/org.go index 260571b4b242a..07091194ebccf 100644 --- a/models/organization/org.go +++ b/models/organization/org.go @@ -96,23 +96,23 @@ func (Organization) TableName() string { } // IsOwnedBy returns true if given user is in the owner team. -func (org *Organization) IsOwnedBy(uid int64) (bool, error) { - return IsOrganizationOwner(db.DefaultContext, org.ID, uid) +func (org *Organization) IsOwnedBy(ctx context.Context, uid int64) (bool, error) { + return IsOrganizationOwner(ctx, org.ID, uid) } // IsOrgAdmin returns true if given user is in the owner team or an admin team. -func (org *Organization) IsOrgAdmin(uid int64) (bool, error) { - return IsOrganizationAdmin(db.DefaultContext, org.ID, uid) +func (org *Organization) IsOrgAdmin(ctx context.Context, uid int64) (bool, error) { + return IsOrganizationAdmin(ctx, org.ID, uid) } // IsOrgMember returns true if given user is member of organization. -func (org *Organization) IsOrgMember(uid int64) (bool, error) { - return IsOrganizationMember(db.DefaultContext, org.ID, uid) +func (org *Organization) IsOrgMember(ctx context.Context, uid int64) (bool, error) { + return IsOrganizationMember(ctx, org.ID, uid) } // CanCreateOrgRepo returns true if given user can create repo in organization -func (org *Organization) CanCreateOrgRepo(uid int64) (bool, error) { - return CanCreateOrgRepo(db.DefaultContext, org.ID, uid) +func (org *Organization) CanCreateOrgRepo(ctx context.Context, uid int64) (bool, error) { + return CanCreateOrgRepo(ctx, org.ID, uid) } // GetTeam returns named team of organization. @@ -135,8 +135,8 @@ func FindOrgTeams(ctx context.Context, orgID int64) ([]*Team, error) { } // LoadTeams load teams if not loaded. -func (org *Organization) LoadTeams() ([]*Team, error) { - return FindOrgTeams(db.DefaultContext, org.ID) +func (org *Organization) LoadTeams(ctx context.Context) ([]*Team, error) { + return FindOrgTeams(ctx, org.ID) } // GetMembers returns all members of organization. @@ -147,8 +147,8 @@ func (org *Organization) GetMembers(ctx context.Context) (user_model.UserList, m } // HasMemberWithUserID returns true if user with userID is part of the u organisation. -func (org *Organization) HasMemberWithUserID(userID int64) bool { - return org.hasMemberWithUserID(db.DefaultContext, userID) +func (org *Organization) HasMemberWithUserID(ctx context.Context, userID int64) bool { + return org.hasMemberWithUserID(ctx, userID) } func (org *Organization) hasMemberWithUserID(ctx context.Context, userID int64) bool { @@ -199,8 +199,8 @@ type FindOrgMembersOpts struct { } // CountOrgMembers counts the organization's members -func CountOrgMembers(opts *FindOrgMembersOpts) (int64, error) { - sess := db.GetEngine(db.DefaultContext).Where("org_id=?", opts.OrgID) +func CountOrgMembers(ctx context.Context, opts *FindOrgMembersOpts) (int64, error) { + sess := db.GetEngine(ctx).Where("org_id=?", opts.OrgID) if opts.PublicOnly { sess.And("is_public = ?", true) } @@ -271,7 +271,7 @@ func (org *Organization) UnitPermission(ctx context.Context, doer *user_model.Us } // CreateOrganization creates record of a new organization. -func CreateOrganization(org *Organization, owner *user_model.User) (err error) { +func CreateOrganization(ctx context.Context, org *Organization, owner *user_model.User) (err error) { if !owner.CanCreateOrganization() { return ErrUserNotAllowedCreateOrg{} } @@ -280,7 +280,7 @@ func CreateOrganization(org *Organization, owner *user_model.User) (err error) { return err } - isExist, err := user_model.IsUserExist(db.DefaultContext, 0, org.Name) + isExist, err := user_model.IsUserExist(ctx, 0, org.Name) if err != nil { return err } else if isExist { @@ -300,7 +300,7 @@ func CreateOrganization(org *Organization, owner *user_model.User) (err error) { org.NumMembers = 1 org.Type = user_model.UserTypeOrganization - ctx, committer, err := db.TxContext(db.DefaultContext) + ctx, committer, err := db.TxContext(ctx) if err != nil { return err } @@ -412,9 +412,9 @@ func DeleteOrganization(ctx context.Context, org *Organization) error { } // GetOrgUserMaxAuthorizeLevel returns highest authorize level of user in an organization -func (org *Organization) GetOrgUserMaxAuthorizeLevel(uid int64) (perm.AccessMode, error) { +func (org *Organization) GetOrgUserMaxAuthorizeLevel(ctx context.Context, uid int64) (perm.AccessMode, error) { var authorize perm.AccessMode - _, err := db.GetEngine(db.DefaultContext). + _, err := db.GetEngine(ctx). Select("max(team.authorize)"). Table("team"). Join("INNER", "team_user", "team_user.team_id = team.id"). @@ -468,9 +468,9 @@ func (opts FindOrgOptions) toConds() builder.Cond { } // FindOrgs returns a list of organizations according given conditions -func FindOrgs(opts FindOrgOptions) ([]*Organization, error) { +func FindOrgs(ctx context.Context, opts FindOrgOptions) ([]*Organization, error) { orgs := make([]*Organization, 0, 10) - sess := db.GetEngine(db.DefaultContext). + sess := db.GetEngine(ctx). Where(opts.toConds()). Asc("`user`.name") if opts.Page > 0 && opts.PageSize > 0 { @@ -480,8 +480,8 @@ func FindOrgs(opts FindOrgOptions) ([]*Organization, error) { } // CountOrgs returns total count organizations according options -func CountOrgs(opts FindOrgOptions) (int64, error) { - return db.GetEngine(db.DefaultContext). +func CountOrgs(ctx context.Context, opts FindOrgOptions) (int64, error) { + return db.GetEngine(ctx). Where(opts.toConds()). Count(new(Organization)) } @@ -505,13 +505,13 @@ func HasOrgOrUserVisible(ctx context.Context, orgOrUser, user *user_model.User) } // HasOrgsVisible tells if the given user can see at least one of the orgs provided -func HasOrgsVisible(orgs []*Organization, user *user_model.User) bool { +func HasOrgsVisible(ctx context.Context, orgs []*Organization, user *user_model.User) bool { if len(orgs) == 0 { return false } for _, org := range orgs { - if HasOrgOrUserVisible(db.DefaultContext, org.AsUser(), user) { + if HasOrgOrUserVisible(ctx, org.AsUser(), user) { return true } } @@ -550,9 +550,9 @@ func GetOrgUsersByOrgID(ctx context.Context, opts *FindOrgMembersOpts) ([]*OrgUs } // ChangeOrgUserStatus changes public or private membership status. -func ChangeOrgUserStatus(orgID, uid int64, public bool) error { +func ChangeOrgUserStatus(ctx context.Context, orgID, uid int64, public bool) error { ou := new(OrgUser) - has, err := db.GetEngine(db.DefaultContext). + has, err := db.GetEngine(ctx). Where("uid=?", uid). And("org_id=?", orgID). Get(ou) @@ -563,18 +563,18 @@ func ChangeOrgUserStatus(orgID, uid int64, public bool) error { } ou.IsPublic = public - _, err = db.GetEngine(db.DefaultContext).ID(ou.ID).Cols("is_public").Update(ou) + _, err = db.GetEngine(ctx).ID(ou.ID).Cols("is_public").Update(ou) return err } // AddOrgUser adds new user to given organization. -func AddOrgUser(orgID, uid int64) error { - isAlreadyMember, err := IsOrganizationMember(db.DefaultContext, orgID, uid) +func AddOrgUser(ctx context.Context, orgID, uid int64) error { + isAlreadyMember, err := IsOrganizationMember(ctx, orgID, uid) if err != nil || isAlreadyMember { return err } - ctx, committer, err := db.TxContext(db.DefaultContext) + ctx, committer, err := db.TxContext(ctx) if err != nil { return err } @@ -669,19 +669,19 @@ func (org *Organization) getUserTeamIDs(ctx context.Context, userID int64) ([]in } // TeamsWithAccessToRepo returns all teams that have given access level to the repository. -func (org *Organization) TeamsWithAccessToRepo(repoID int64, mode perm.AccessMode) ([]*Team, error) { - return GetTeamsWithAccessToRepo(db.DefaultContext, org.ID, repoID, mode) +func (org *Organization) TeamsWithAccessToRepo(ctx context.Context, repoID int64, mode perm.AccessMode) ([]*Team, error) { + return GetTeamsWithAccessToRepo(ctx, org.ID, repoID, mode) } // GetUserTeamIDs returns of all team IDs of the organization that user is member of. -func (org *Organization) GetUserTeamIDs(userID int64) ([]int64, error) { - return org.getUserTeamIDs(db.DefaultContext, userID) +func (org *Organization) GetUserTeamIDs(ctx context.Context, userID int64) ([]int64, error) { + return org.getUserTeamIDs(ctx, userID) } // GetUserTeams returns all teams that belong to user, // and that the user has joined. -func (org *Organization) GetUserTeams(userID int64) ([]*Team, error) { - return org.getUserTeams(db.DefaultContext, userID) +func (org *Organization) GetUserTeams(ctx context.Context, userID int64) ([]*Team, error) { + return org.getUserTeams(ctx, userID) } // AccessibleReposEnvironment operations involving the repositories that are @@ -733,11 +733,11 @@ func AccessibleReposEnv(ctx context.Context, org *Organization, userID int64) (A // AccessibleTeamReposEnv an AccessibleReposEnvironment for the repositories in `org` // that are accessible to the specified team. -func (org *Organization) AccessibleTeamReposEnv(team *Team) AccessibleReposEnvironment { +func (org *Organization) AccessibleTeamReposEnv(ctx context.Context, team *Team) AccessibleReposEnvironment { return &accessibleReposEnv{ org: org, team: team, - ctx: db.DefaultContext, + ctx: ctx, orderBy: db.SearchOrderByRecentUpdated, } } diff --git a/models/organization/org_test.go b/models/organization/org_test.go index b5dff9ec01a23..aa72fc467ea7a 100644 --- a/models/organization/org_test.go +++ b/models/organization/org_test.go @@ -31,7 +31,7 @@ func TestUser_IsOwnedBy(t *testing.T) { {2, 3, false}, } { org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: testCase.OrgID}) - isOwner, err := org.IsOwnedBy(testCase.UserID) + isOwner, err := org.IsOwnedBy(db.DefaultContext, testCase.UserID) assert.NoError(t, err) assert.Equal(t, testCase.ExpectedOwner, isOwner) } @@ -52,7 +52,7 @@ func TestUser_IsOrgMember(t *testing.T) { {2, 3, false}, } { org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: testCase.OrgID}) - isMember, err := org.IsOrgMember(testCase.UserID) + isMember, err := org.IsOrgMember(db.DefaultContext, testCase.UserID) assert.NoError(t, err) assert.Equal(t, testCase.ExpectedMember, isMember) } @@ -89,7 +89,7 @@ func TestUser_GetOwnerTeam(t *testing.T) { func TestUser_GetTeams(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3}) - teams, err := org.LoadTeams() + teams, err := org.LoadTeams(db.DefaultContext) assert.NoError(t, err) if assert.Len(t, teams, 5) { assert.Equal(t, int64(1), teams[0].ID) @@ -131,7 +131,7 @@ func TestCountOrganizations(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) expected, err := db.GetEngine(db.DefaultContext).Where("type=?", user_model.UserTypeOrganization).Count(&organization.Organization{}) assert.NoError(t, err) - cnt, err := organization.CountOrgs(organization.FindOrgOptions{IncludePrivate: true}) + cnt, err := organization.CountOrgs(db.DefaultContext, organization.FindOrgOptions{IncludePrivate: true}) assert.NoError(t, err) assert.Equal(t, expected, cnt) } @@ -168,7 +168,7 @@ func TestIsOrganizationMember(t *testing.T) { func TestIsPublicMembership(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) test := func(orgID, userID int64, expected bool) { - isMember, err := organization.IsPublicMembership(orgID, userID) + isMember, err := organization.IsPublicMembership(db.DefaultContext, orgID, userID) assert.NoError(t, err) assert.EqualValues(t, expected, isMember) } @@ -183,7 +183,7 @@ func TestIsPublicMembership(t *testing.T) { func TestFindOrgs(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - orgs, err := organization.FindOrgs(organization.FindOrgOptions{ + orgs, err := organization.FindOrgs(db.DefaultContext, organization.FindOrgOptions{ UserID: 4, IncludePrivate: true, }) @@ -192,14 +192,14 @@ func TestFindOrgs(t *testing.T) { assert.EqualValues(t, 3, orgs[0].ID) } - orgs, err = organization.FindOrgs(organization.FindOrgOptions{ + orgs, err = organization.FindOrgs(db.DefaultContext, organization.FindOrgOptions{ UserID: 4, IncludePrivate: false, }) assert.NoError(t, err) assert.Len(t, orgs, 0) - total, err := organization.CountOrgs(organization.FindOrgOptions{ + total, err := organization.CountOrgs(db.DefaultContext, organization.FindOrgOptions{ UserID: 4, IncludePrivate: true, }) @@ -250,7 +250,7 @@ func TestChangeOrgUserStatus(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) testSuccess := func(orgID, userID int64, public bool) { - assert.NoError(t, organization.ChangeOrgUserStatus(orgID, userID, public)) + assert.NoError(t, organization.ChangeOrgUserStatus(db.DefaultContext, orgID, userID, public)) orgUser := unittest.AssertExistsAndLoadBean(t, &organization.OrgUser{OrgID: orgID, UID: userID}) assert.Equal(t, public, orgUser.IsPublic) } @@ -258,14 +258,14 @@ func TestChangeOrgUserStatus(t *testing.T) { testSuccess(3, 2, false) testSuccess(3, 2, false) testSuccess(3, 4, true) - assert.NoError(t, organization.ChangeOrgUserStatus(unittest.NonexistentID, unittest.NonexistentID, true)) + assert.NoError(t, organization.ChangeOrgUserStatus(db.DefaultContext, unittest.NonexistentID, unittest.NonexistentID, true)) } func TestUser_GetUserTeamIDs(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) org := unittest.AssertExistsAndLoadBean(t, &organization.Organization{ID: 3}) testSuccess := func(userID int64, expected []int64) { - teamIDs, err := org.GetUserTeamIDs(userID) + teamIDs, err := org.GetUserTeamIDs(db.DefaultContext, userID) assert.NoError(t, err) assert.Equal(t, expected, teamIDs) } @@ -352,7 +352,7 @@ func TestHasOrgVisibleTypePublic(t *testing.T) { } unittest.AssertNotExistsBean(t, &user_model.User{Name: org.Name, Type: user_model.UserTypeOrganization}) - assert.NoError(t, organization.CreateOrganization(org, owner)) + assert.NoError(t, organization.CreateOrganization(db.DefaultContext, org, owner)) org = unittest.AssertExistsAndLoadBean(t, &organization.Organization{Name: org.Name, Type: user_model.UserTypeOrganization}) test1 := organization.HasOrgOrUserVisible(db.DefaultContext, org.AsUser(), owner) @@ -375,7 +375,7 @@ func TestHasOrgVisibleTypeLimited(t *testing.T) { } unittest.AssertNotExistsBean(t, &user_model.User{Name: org.Name, Type: user_model.UserTypeOrganization}) - assert.NoError(t, organization.CreateOrganization(org, owner)) + assert.NoError(t, organization.CreateOrganization(db.DefaultContext, org, owner)) org = unittest.AssertExistsAndLoadBean(t, &organization.Organization{Name: org.Name, Type: user_model.UserTypeOrganization}) test1 := organization.HasOrgOrUserVisible(db.DefaultContext, org.AsUser(), owner) @@ -398,7 +398,7 @@ func TestHasOrgVisibleTypePrivate(t *testing.T) { } unittest.AssertNotExistsBean(t, &user_model.User{Name: org.Name, Type: user_model.UserTypeOrganization}) - assert.NoError(t, organization.CreateOrganization(org, owner)) + assert.NoError(t, organization.CreateOrganization(db.DefaultContext, org, owner)) org = unittest.AssertExistsAndLoadBean(t, &organization.Organization{Name: org.Name, Type: user_model.UserTypeOrganization}) test1 := organization.HasOrgOrUserVisible(db.DefaultContext, org.AsUser(), owner) @@ -461,7 +461,7 @@ func TestCreateOrganization(t *testing.T) { } unittest.AssertNotExistsBean(t, &user_model.User{Name: newOrgName, Type: user_model.UserTypeOrganization}) - assert.NoError(t, organization.CreateOrganization(org, owner)) + assert.NoError(t, organization.CreateOrganization(db.DefaultContext, org, owner)) org = unittest.AssertExistsAndLoadBean(t, &organization.Organization{Name: newOrgName, Type: user_model.UserTypeOrganization}) ownerTeam := unittest.AssertExistsAndLoadBean(t, @@ -481,7 +481,7 @@ func TestCreateOrganization2(t *testing.T) { } unittest.AssertNotExistsBean(t, &organization.Organization{Name: newOrgName, Type: user_model.UserTypeOrganization}) - err := organization.CreateOrganization(org, owner) + err := organization.CreateOrganization(db.DefaultContext, org, owner) assert.Error(t, err) assert.True(t, organization.IsErrUserNotAllowedCreateOrg(err)) unittest.AssertNotExistsBean(t, &organization.Organization{Name: newOrgName, Type: user_model.UserTypeOrganization}) @@ -495,7 +495,7 @@ func TestCreateOrganization3(t *testing.T) { owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) org := &organization.Organization{Name: "org3"} // should already exist unittest.AssertExistsAndLoadBean(t, &user_model.User{Name: org.Name}) // sanity check - err := organization.CreateOrganization(org, owner) + err := organization.CreateOrganization(db.DefaultContext, org, owner) assert.Error(t, err) assert.True(t, user_model.IsErrUserAlreadyExist(err)) unittest.CheckConsistencyFor(t, &user_model.User{}, &organization.Team{}) @@ -506,7 +506,7 @@ func TestCreateOrganization4(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - err := organization.CreateOrganization(&organization.Organization{Name: "assets"}, owner) + err := organization.CreateOrganization(db.DefaultContext, &organization.Organization{Name: "assets"}, owner) assert.Error(t, err) assert.True(t, db.IsErrNameReserved(err)) unittest.CheckConsistencyFor(t, &organization.Organization{}, &organization.Team{}) diff --git a/models/organization/org_user.go b/models/organization/org_user.go index d0598ab5d11f0..5fe3a178d2b58 100644 --- a/models/organization/org_user.go +++ b/models/organization/org_user.go @@ -78,8 +78,8 @@ func IsOrganizationMember(ctx context.Context, orgID, uid int64) (bool, error) { } // IsPublicMembership returns true if the given user's membership of given org is public. -func IsPublicMembership(orgID, uid int64) (bool, error) { - return db.GetEngine(db.DefaultContext). +func IsPublicMembership(ctx context.Context, orgID, uid int64) (bool, error) { + return db.GetEngine(ctx). Where("uid=?", uid). And("org_id=?", orgID). And("is_public=?", true). @@ -98,12 +98,12 @@ func CanCreateOrgRepo(ctx context.Context, orgID, uid int64) (bool, error) { } // IsUserOrgOwner returns true if user is in the owner team of given organization. -func IsUserOrgOwner(users user_model.UserList, orgID int64) map[int64]bool { +func IsUserOrgOwner(ctx context.Context, users user_model.UserList, orgID int64) map[int64]bool { results := make(map[int64]bool, len(users)) for _, user := range users { results[user.ID] = false // Set default to false } - ownerMaps, err := loadOrganizationOwners(db.DefaultContext, users, orgID) + ownerMaps, err := loadOrganizationOwners(ctx, users, orgID) if err == nil { for _, owner := range ownerMaps { results[owner.UID] = true diff --git a/models/organization/org_user_test.go b/models/organization/org_user_test.go index 1c3cf2798d215..7924517f31209 100644 --- a/models/organization/org_user_test.go +++ b/models/organization/org_user_test.go @@ -39,7 +39,7 @@ func TestUserIsPublicMember(t *testing.T) { func testUserIsPublicMember(t *testing.T, uid, orgID int64, expected bool) { user, err := user_model.GetUserByID(db.DefaultContext, uid) assert.NoError(t, err) - is, err := organization.IsPublicMembership(orgID, user.ID) + is, err := organization.IsPublicMembership(db.DefaultContext, orgID, user.ID) assert.NoError(t, err) assert.Equal(t, expected, is) } @@ -123,7 +123,7 @@ func testUserListIsUserOrgOwner(t *testing.T, orgID int64, expected map[int64]bo assert.NoError(t, err) members, _, err := org.GetMembers(db.DefaultContext) assert.NoError(t, err) - assert.Equal(t, expected, organization.IsUserOrgOwner(members, orgID)) + assert.Equal(t, expected, organization.IsUserOrgOwner(db.DefaultContext, members, orgID)) } func TestAddOrgUser(t *testing.T) { @@ -134,7 +134,7 @@ func TestAddOrgUser(t *testing.T) { if !unittest.BeanExists(t, &organization.OrgUser{OrgID: orgID, UID: userID}) { expectedNumMembers++ } - assert.NoError(t, organization.AddOrgUser(orgID, userID)) + assert.NoError(t, organization.AddOrgUser(db.DefaultContext, orgID, userID)) ou := &organization.OrgUser{OrgID: orgID, UID: userID} unittest.AssertExistsAndLoadBean(t, ou) assert.Equal(t, isPublic, ou.IsPublic) diff --git a/models/organization/team.go b/models/organization/team.go index 3624fdc46663d..72afc673693c5 100644 --- a/models/organization/team.go +++ b/models/organization/team.go @@ -144,8 +144,8 @@ func (t *Team) IsOwnerTeam() bool { } // IsMember returns true if given user is a member of team. -func (t *Team) IsMember(userID int64) bool { - isMember, err := IsTeamMember(db.DefaultContext, t.OrgID, t.ID, userID) +func (t *Team) IsMember(ctx context.Context, userID int64) bool { + isMember, err := IsTeamMember(ctx, t.OrgID, t.ID, userID) if err != nil { log.Error("IsMember: %v", err) return false @@ -217,10 +217,10 @@ func GetTeam(ctx context.Context, orgID int64, name string) (*Team, error) { } // GetTeamIDsByNames returns a slice of team ids corresponds to names. -func GetTeamIDsByNames(orgID int64, names []string, ignoreNonExistent bool) ([]int64, error) { +func GetTeamIDsByNames(ctx context.Context, orgID int64, names []string, ignoreNonExistent bool) ([]int64, error) { ids := make([]int64, 0, len(names)) for _, name := range names { - u, err := GetTeam(db.DefaultContext, orgID, name) + u, err := GetTeam(ctx, orgID, name) if err != nil { if ignoreNonExistent { continue @@ -251,13 +251,13 @@ func GetTeamByID(ctx context.Context, teamID int64) (*Team, error) { } // GetTeamNamesByID returns team's lower name from a list of team ids. -func GetTeamNamesByID(teamIDs []int64) ([]string, error) { +func GetTeamNamesByID(ctx context.Context, teamIDs []int64) ([]string, error) { if len(teamIDs) == 0 { return []string{}, nil } var teamNames []string - err := db.GetEngine(db.DefaultContext).Table("team"). + err := db.GetEngine(ctx).Table("team"). Select("lower_name"). In("id", teamIDs). Asc("name"). diff --git a/models/organization/team_test.go b/models/organization/team_test.go index af69715ca9b97..23a6affe24807 100644 --- a/models/organization/team_test.go +++ b/models/organization/team_test.go @@ -27,14 +27,14 @@ func TestTeam_IsMember(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 1}) - assert.True(t, team.IsMember(2)) - assert.False(t, team.IsMember(4)) - assert.False(t, team.IsMember(unittest.NonexistentID)) + assert.True(t, team.IsMember(db.DefaultContext, 2)) + assert.False(t, team.IsMember(db.DefaultContext, 4)) + assert.False(t, team.IsMember(db.DefaultContext, unittest.NonexistentID)) team = unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 2}) - assert.True(t, team.IsMember(2)) - assert.True(t, team.IsMember(4)) - assert.False(t, team.IsMember(unittest.NonexistentID)) + assert.True(t, team.IsMember(db.DefaultContext, 2)) + assert.True(t, team.IsMember(db.DefaultContext, 4)) + assert.False(t, team.IsMember(db.DefaultContext, unittest.NonexistentID)) } func TestTeam_GetRepositories(t *testing.T) { @@ -188,7 +188,7 @@ func TestUsersInTeamsCount(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) test := func(teamIDs, userIDs []int64, expected int64) { - count, err := organization.UsersInTeamsCount(teamIDs, userIDs) + count, err := organization.UsersInTeamsCount(db.DefaultContext, teamIDs, userIDs) assert.NoError(t, err) assert.Equal(t, expected, count) } diff --git a/models/organization/team_unit.go b/models/organization/team_unit.go index 7668ca74835d6..3087b70770c90 100644 --- a/models/organization/team_unit.go +++ b/models/organization/team_unit.go @@ -30,8 +30,8 @@ func getUnitsByTeamID(ctx context.Context, teamID int64) (units []*TeamUnit, err } // UpdateTeamUnits updates a teams's units -func UpdateTeamUnits(team *Team, units []TeamUnit) (err error) { - ctx, committer, err := db.TxContext(db.DefaultContext) +func UpdateTeamUnits(ctx context.Context, team *Team, units []TeamUnit) (err error) { + ctx, committer, err := db.TxContext(ctx) if err != nil { return err } diff --git a/models/organization/team_user.go b/models/organization/team_user.go index 768dc24c507b1..ab767db200044 100644 --- a/models/organization/team_user.go +++ b/models/organization/team_user.go @@ -78,9 +78,9 @@ func IsUserInTeams(ctx context.Context, userID int64, teamIDs []int64) (bool, er } // UsersInTeamsCount counts the number of users which are in userIDs and teamIDs -func UsersInTeamsCount(userIDs, teamIDs []int64) (int64, error) { +func UsersInTeamsCount(ctx context.Context, userIDs, teamIDs []int64) (int64, error) { var ids []int64 - if err := db.GetEngine(db.DefaultContext).In("uid", userIDs).In("team_id", teamIDs). + if err := db.GetEngine(ctx).In("uid", userIDs).In("team_id", teamIDs). Table("team_user"). Cols("uid").GroupBy("uid").Find(&ids); err != nil { return 0, err diff --git a/models/perm/access/repo_permission.go b/models/perm/access/repo_permission.go index 2027b87ecb43c..395ecdf1a5031 100644 --- a/models/perm/access/repo_permission.go +++ b/models/perm/access/repo_permission.go @@ -261,16 +261,16 @@ func GetUserRepoPermission(ctx context.Context, repo *repo_model.Repository, use } // IsUserRealRepoAdmin check if this user is real repo admin -func IsUserRealRepoAdmin(repo *repo_model.Repository, user *user_model.User) (bool, error) { +func IsUserRealRepoAdmin(ctx context.Context, repo *repo_model.Repository, user *user_model.User) (bool, error) { if repo.OwnerID == user.ID { return true, nil } - if err := repo.LoadOwner(db.DefaultContext); err != nil { + if err := repo.LoadOwner(ctx); err != nil { return false, err } - accessMode, err := accessLevel(db.DefaultContext, user, repo) + accessMode, err := accessLevel(ctx, user, repo) if err != nil { return false, err } @@ -394,13 +394,13 @@ func getUsersWithAccessMode(ctx context.Context, repo *repo_model.Repository, mo } // GetRepoReaders returns all users that have explicit read access or higher to the repository. -func GetRepoReaders(repo *repo_model.Repository) (_ []*user_model.User, err error) { - return getUsersWithAccessMode(db.DefaultContext, repo, perm_model.AccessModeRead) +func GetRepoReaders(ctx context.Context, repo *repo_model.Repository) (_ []*user_model.User, err error) { + return getUsersWithAccessMode(ctx, repo, perm_model.AccessModeRead) } // GetRepoWriters returns all users that have write access to the repository. -func GetRepoWriters(repo *repo_model.Repository) (_ []*user_model.User, err error) { - return getUsersWithAccessMode(db.DefaultContext, repo, perm_model.AccessModeWrite) +func GetRepoWriters(ctx context.Context, repo *repo_model.Repository) (_ []*user_model.User, err error) { + return getUsersWithAccessMode(ctx, repo, perm_model.AccessModeWrite) } // IsRepoReader returns true if user has explicit read access or higher to the repository. diff --git a/models/project/board.go b/models/project/board.go index 2ab1d5c7b5136..3e2d8e0472c51 100644 --- a/models/project/board.go +++ b/models/project/board.go @@ -69,8 +69,8 @@ func (Board) TableName() string { } // NumIssues return counter of all issues assigned to the board -func (b *Board) NumIssues() int { - c, err := db.GetEngine(db.DefaultContext).Table("project_issue"). +func (b *Board) NumIssues(ctx context.Context) int { + c, err := db.GetEngine(ctx).Table("project_issue"). Where("project_id=?", b.ProjectID). And("project_board_id=?", b.ID). GroupBy("issue_id"). @@ -142,18 +142,18 @@ func createBoardsForProjectsType(ctx context.Context, project *Project) error { } // NewBoard adds a new project board to a given project -func NewBoard(board *Board) error { +func NewBoard(ctx context.Context, board *Board) error { if len(board.Color) != 0 && !BoardColorPattern.MatchString(board.Color) { return fmt.Errorf("bad color code: %s", board.Color) } - _, err := db.GetEngine(db.DefaultContext).Insert(board) + _, err := db.GetEngine(ctx).Insert(board) return err } // DeleteBoardByID removes all issues references to the project board. -func DeleteBoardByID(boardID int64) error { - ctx, committer, err := db.TxContext(db.DefaultContext) +func DeleteBoardByID(ctx context.Context, boardID int64) error { + ctx, committer, err := db.TxContext(ctx) if err != nil { return err } @@ -265,8 +265,8 @@ func (p *Project) getDefaultBoard(ctx context.Context) (*Board, error) { // SetDefaultBoard represents a board for issues not assigned to one // if boardID is 0 unset default -func SetDefaultBoard(projectID, boardID int64) error { - _, err := db.GetEngine(db.DefaultContext).Where(builder.Eq{ +func SetDefaultBoard(ctx context.Context, projectID, boardID int64) error { + _, err := db.GetEngine(ctx).Where(builder.Eq{ "project_id": projectID, "`default`": true, }).Cols("`default`").Update(&Board{Default: false}) @@ -275,7 +275,7 @@ func SetDefaultBoard(projectID, boardID int64) error { } if boardID > 0 { - _, err = db.GetEngine(db.DefaultContext).ID(boardID).Where(builder.Eq{"project_id": projectID}). + _, err = db.GetEngine(ctx).ID(boardID).Where(builder.Eq{"project_id": projectID}). Cols("`default`").Update(&Board{Default: true}) } @@ -283,9 +283,9 @@ func SetDefaultBoard(projectID, boardID int64) error { } // UpdateBoardSorting update project board sorting -func UpdateBoardSorting(bs BoardList) error { +func UpdateBoardSorting(ctx context.Context, bs BoardList) error { for i := range bs { - _, err := db.GetEngine(db.DefaultContext).ID(bs[i].ID).Cols( + _, err := db.GetEngine(ctx).ID(bs[i].ID).Cols( "sorting", ).Update(bs[i]) if err != nil { diff --git a/models/project/issue.go b/models/project/issue.go index 3269197d6cde3..ebc9719de55d0 100644 --- a/models/project/issue.go +++ b/models/project/issue.go @@ -34,8 +34,8 @@ func deleteProjectIssuesByProjectID(ctx context.Context, projectID int64) error } // NumIssues return counter of all issues assigned to a project -func (p *Project) NumIssues() int { - c, err := db.GetEngine(db.DefaultContext).Table("project_issue"). +func (p *Project) NumIssues(ctx context.Context) int { + c, err := db.GetEngine(ctx).Table("project_issue"). Where("project_id=?", p.ID). GroupBy("issue_id"). Cols("issue_id"). @@ -48,8 +48,8 @@ func (p *Project) NumIssues() int { } // NumClosedIssues return counter of closed issues assigned to a project -func (p *Project) NumClosedIssues() int { - c, err := db.GetEngine(db.DefaultContext).Table("project_issue"). +func (p *Project) NumClosedIssues(ctx context.Context) int { + c, err := db.GetEngine(ctx).Table("project_issue"). Join("INNER", "issue", "project_issue.issue_id=issue.id"). Where("project_issue.project_id=? AND issue.is_closed=?", p.ID, true). Cols("issue_id"). @@ -62,8 +62,8 @@ func (p *Project) NumClosedIssues() int { } // NumOpenIssues return counter of open issues assigned to a project -func (p *Project) NumOpenIssues() int { - c, err := db.GetEngine(db.DefaultContext).Table("project_issue"). +func (p *Project) NumOpenIssues(ctx context.Context) int { + c, err := db.GetEngine(ctx).Table("project_issue"). Join("INNER", "issue", "project_issue.issue_id=issue.id"). Where("project_issue.project_id=? AND issue.is_closed=?", p.ID, false). Cols("issue_id"). @@ -76,8 +76,8 @@ func (p *Project) NumOpenIssues() int { } // MoveIssuesOnProjectBoard moves or keeps issues in a column and sorts them inside that column -func MoveIssuesOnProjectBoard(board *Board, sortedIssueIDs map[int64]int64) error { - return db.WithTx(db.DefaultContext, func(ctx context.Context) error { +func MoveIssuesOnProjectBoard(ctx context.Context, board *Board, sortedIssueIDs map[int64]int64) error { + return db.WithTx(ctx, func(ctx context.Context) error { sess := db.GetEngine(ctx) issueIDs := make([]int64, 0, len(sortedIssueIDs)) diff --git a/models/project/project.go b/models/project/project.go index 8056aba252d00..3a1bfe1dbd3ff 100644 --- a/models/project/project.go +++ b/models/project/project.go @@ -124,9 +124,9 @@ func (p *Project) LoadRepo(ctx context.Context) (err error) { } // Link returns the project's relative URL. -func (p *Project) Link() string { +func (p *Project) Link(ctx context.Context) string { if p.OwnerID > 0 { - err := p.LoadOwner(db.DefaultContext) + err := p.LoadOwner(ctx) if err != nil { log.Error("LoadOwner: %v", err) return "" @@ -134,7 +134,7 @@ func (p *Project) Link() string { return fmt.Sprintf("%s/-/projects/%d", p.Owner.HomeLink(), p.ID) } if p.RepoID > 0 { - err := p.LoadRepo(db.DefaultContext) + err := p.LoadRepo(ctx) if err != nil { log.Error("LoadRepo: %v", err) return "" @@ -261,7 +261,7 @@ func FindProjects(ctx context.Context, opts SearchOptions) ([]*Project, int64, e } // NewProject creates a new Project -func NewProject(p *Project) error { +func NewProject(ctx context.Context, p *Project) error { if !IsBoardTypeValid(p.BoardType) { p.BoardType = BoardTypeNone } @@ -274,7 +274,7 @@ func NewProject(p *Project) error { return util.NewInvalidArgumentErrorf("project type is not valid") } - ctx, committer, err := db.TxContext(db.DefaultContext) + ctx, committer, err := db.TxContext(ctx) if err != nil { return err } @@ -348,8 +348,8 @@ func updateRepositoryProjectCount(ctx context.Context, repoID int64) error { } // ChangeProjectStatusByRepoIDAndID toggles a project between opened and closed -func ChangeProjectStatusByRepoIDAndID(repoID, projectID int64, isClosed bool) error { - ctx, committer, err := db.TxContext(db.DefaultContext) +func ChangeProjectStatusByRepoIDAndID(ctx context.Context, repoID, projectID int64, isClosed bool) error { + ctx, committer, err := db.TxContext(ctx) if err != nil { return err } @@ -372,8 +372,8 @@ func ChangeProjectStatusByRepoIDAndID(repoID, projectID int64, isClosed bool) er } // ChangeProjectStatus toggle a project between opened and closed -func ChangeProjectStatus(p *Project, isClosed bool) error { - ctx, committer, err := db.TxContext(db.DefaultContext) +func ChangeProjectStatus(ctx context.Context, p *Project, isClosed bool) error { + ctx, committer, err := db.TxContext(ctx) if err != nil { return err } diff --git a/models/project/project_test.go b/models/project/project_test.go index d1a471565367c..6b5bd5b371dd2 100644 --- a/models/project/project_test.go +++ b/models/project/project_test.go @@ -60,7 +60,7 @@ func TestProject(t *testing.T) { CreatorID: 2, } - assert.NoError(t, NewProject(project)) + assert.NoError(t, NewProject(db.DefaultContext, project)) _, err := GetProjectByID(db.DefaultContext, project.ID) assert.NoError(t, err) @@ -74,7 +74,7 @@ func TestProject(t *testing.T) { assert.Equal(t, project.Title, projectFromDB.Title) - assert.NoError(t, ChangeProjectStatus(project, true)) + assert.NoError(t, ChangeProjectStatus(db.DefaultContext, project, true)) // Retrieve from DB afresh to check if it is truly closed projectFromDB, err = GetProjectByID(db.DefaultContext, project.ID) diff --git a/models/repo.go b/models/repo.go index de0f7ee3452c4..82433ca0552af 100644 --- a/models/repo.go +++ b/models/repo.go @@ -16,7 +16,6 @@ import ( issues_model "code.gitea.io/gitea/models/issues" access_model "code.gitea.io/gitea/models/perm/access" repo_model "code.gitea.io/gitea/models/repo" - system_model "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/models/unit" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/log" @@ -24,10 +23,7 @@ import ( // Init initialize model func Init(ctx context.Context) error { - if err := unit.LoadUnitConfig(); err != nil { - return err - } - return system_model.Init(ctx) + return unit.LoadUnitConfig() } type repoChecker struct { diff --git a/models/repo/collaboration.go b/models/repo/collaboration.go index 7989e5bdf9c5d..2018ae2a7db15 100644 --- a/models/repo/collaboration.go +++ b/models/repo/collaboration.go @@ -62,8 +62,8 @@ func GetCollaborators(ctx context.Context, repoID int64, listOptions db.ListOpti } // CountCollaborators returns total number of collaborators for a repository -func CountCollaborators(repoID int64) (int64, error) { - return db.GetEngine(db.DefaultContext).Where("repo_id = ? ", repoID).Count(&Collaboration{}) +func CountCollaborators(ctx context.Context, repoID int64) (int64, error) { + return db.GetEngine(ctx).Where("repo_id = ? ", repoID).Count(&Collaboration{}) } // GetCollaboration get collaboration for a repository id with a user id @@ -138,11 +138,11 @@ func ChangeCollaborationAccessMode(ctx context.Context, repo *Repository, uid in } // IsOwnerMemberCollaborator checks if a provided user is the owner, a collaborator or a member of a team in a repository -func IsOwnerMemberCollaborator(repo *Repository, userID int64) (bool, error) { +func IsOwnerMemberCollaborator(ctx context.Context, repo *Repository, userID int64) (bool, error) { if repo.OwnerID == userID { return true, nil } - teamMember, err := db.GetEngine(db.DefaultContext).Join("INNER", "team_repo", "team_repo.team_id = team_user.team_id"). + teamMember, err := db.GetEngine(ctx).Join("INNER", "team_repo", "team_repo.team_id = team_user.team_id"). Join("INNER", "team_unit", "team_unit.team_id = team_user.team_id"). Where("team_repo.repo_id = ?", repo.ID). And("team_unit.`type` = ?", unit.TypeCode). @@ -154,5 +154,5 @@ func IsOwnerMemberCollaborator(repo *Repository, userID int64) (bool, error) { return true, nil } - return db.GetEngine(db.DefaultContext).Get(&Collaboration{RepoID: repo.ID, UserID: userID}) + return db.GetEngine(ctx).Get(&Collaboration{RepoID: repo.ID, UserID: userID}) } diff --git a/models/repo/collaboration_test.go b/models/repo/collaboration_test.go index a29dfe99a50f1..38114c307f6e1 100644 --- a/models/repo/collaboration_test.go +++ b/models/repo/collaboration_test.go @@ -89,17 +89,17 @@ func TestRepository_CountCollaborators(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4}) - count, err := repo_model.CountCollaborators(repo1.ID) + count, err := repo_model.CountCollaborators(db.DefaultContext, repo1.ID) assert.NoError(t, err) assert.EqualValues(t, 2, count) repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 22}) - count, err = repo_model.CountCollaborators(repo2.ID) + count, err = repo_model.CountCollaborators(db.DefaultContext, repo2.ID) assert.NoError(t, err) assert.EqualValues(t, 2, count) // Non-existent repository. - count, err = repo_model.CountCollaborators(unittest.NonexistentID) + count, err = repo_model.CountCollaborators(db.DefaultContext, unittest.NonexistentID) assert.NoError(t, err) assert.EqualValues(t, 0, count) } @@ -110,31 +110,31 @@ func TestRepository_IsOwnerMemberCollaborator(t *testing.T) { repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}) // Organisation owner. - actual, err := repo_model.IsOwnerMemberCollaborator(repo1, 2) + actual, err := repo_model.IsOwnerMemberCollaborator(db.DefaultContext, repo1, 2) assert.NoError(t, err) assert.True(t, actual) // Team member. - actual, err = repo_model.IsOwnerMemberCollaborator(repo1, 4) + actual, err = repo_model.IsOwnerMemberCollaborator(db.DefaultContext, repo1, 4) assert.NoError(t, err) assert.True(t, actual) // Normal user. - actual, err = repo_model.IsOwnerMemberCollaborator(repo1, 1) + actual, err = repo_model.IsOwnerMemberCollaborator(db.DefaultContext, repo1, 1) assert.NoError(t, err) assert.False(t, actual) repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4}) // Collaborator. - actual, err = repo_model.IsOwnerMemberCollaborator(repo2, 4) + actual, err = repo_model.IsOwnerMemberCollaborator(db.DefaultContext, repo2, 4) assert.NoError(t, err) assert.True(t, actual) repo3 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 15}) // Repository owner. - actual, err = repo_model.IsOwnerMemberCollaborator(repo3, 2) + actual, err = repo_model.IsOwnerMemberCollaborator(db.DefaultContext, repo3, 2) assert.NoError(t, err) assert.True(t, actual) } diff --git a/models/repo/mirror.go b/models/repo/mirror.go index fffc7577c7b09..be7b785612727 100644 --- a/models/repo/mirror.go +++ b/models/repo/mirror.go @@ -47,12 +47,12 @@ func (m *Mirror) BeforeInsert() { } // GetRepository returns the repository. -func (m *Mirror) GetRepository() *Repository { +func (m *Mirror) GetRepository(ctx context.Context) *Repository { if m.Repo != nil { return m.Repo } var err error - m.Repo, err = GetRepositoryByID(db.DefaultContext, m.RepoID) + m.Repo, err = GetRepositoryByID(ctx, m.RepoID) if err != nil { log.Error("getRepositoryByID[%d]: %v", m.ID, err) } @@ -99,14 +99,14 @@ func TouchMirror(ctx context.Context, m *Mirror) error { } // DeleteMirrorByRepoID deletes a mirror by repoID -func DeleteMirrorByRepoID(repoID int64) error { - _, err := db.GetEngine(db.DefaultContext).Delete(&Mirror{RepoID: repoID}) +func DeleteMirrorByRepoID(ctx context.Context, repoID int64) error { + _, err := db.GetEngine(ctx).Delete(&Mirror{RepoID: repoID}) return err } // MirrorsIterate iterates all mirror repositories. -func MirrorsIterate(limit int, f func(idx int, bean any) error) error { - sess := db.GetEngine(db.DefaultContext). +func MirrorsIterate(ctx context.Context, limit int, f func(idx int, bean any) error) error { + sess := db.GetEngine(ctx). Where("next_update_unix<=?", time.Now().Unix()). And("next_update_unix!=0"). OrderBy("updated_unix ASC") diff --git a/models/repo/pushmirror.go b/models/repo/pushmirror.go index 73c1384444ddc..61cf1849b0054 100644 --- a/models/repo/pushmirror.go +++ b/models/repo/pushmirror.go @@ -58,12 +58,12 @@ func init() { } // GetRepository returns the path of the repository. -func (m *PushMirror) GetRepository() *Repository { +func (m *PushMirror) GetRepository(ctx context.Context) *Repository { if m.Repo != nil { return m.Repo } var err error - m.Repo, err = GetRepositoryByID(db.DefaultContext, m.RepoID) + m.Repo, err = GetRepositoryByID(ctx, m.RepoID) if err != nil { log.Error("getRepositoryByID[%d]: %v", m.ID, err) } diff --git a/models/repo/repo_unit.go b/models/repo/repo_unit.go index b8804c6df1194..89f28b8fcaee4 100644 --- a/models/repo/repo_unit.go +++ b/models/repo/repo_unit.go @@ -279,14 +279,14 @@ func getUnitsByRepoID(ctx context.Context, repoID int64) (units []*RepoUnit, err } // UpdateRepoUnit updates the provided repo unit -func UpdateRepoUnit(unit *RepoUnit) error { - _, err := db.GetEngine(db.DefaultContext).ID(unit.ID).Update(unit) +func UpdateRepoUnit(ctx context.Context, unit *RepoUnit) error { + _, err := db.GetEngine(ctx).ID(unit.ID).Update(unit) return err } // UpdateRepositoryUnits updates a repository's units -func UpdateRepositoryUnits(repo *Repository, units []RepoUnit, deleteUnitTypes []unit.Type) (err error) { - ctx, committer, err := db.TxContext(db.DefaultContext) +func UpdateRepositoryUnits(ctx context.Context, repo *Repository, units []RepoUnit, deleteUnitTypes []unit.Type) (err error) { + ctx, committer, err := db.TxContext(ctx) if err != nil { return err } diff --git a/models/system/notice.go b/models/system/notice.go index b0c0bfb95d5f5..058b78e67717a 100644 --- a/models/system/notice.go +++ b/models/system/notice.go @@ -88,8 +88,8 @@ func RemoveStorageWithNotice(ctx context.Context, bucket storage.ObjectStorage, } // CountNotices returns number of notices. -func CountNotices() int64 { - count, _ := db.GetEngine(db.DefaultContext).Count(new(Notice)) +func CountNotices(ctx context.Context) int64 { + count, _ := db.GetEngine(ctx).Count(new(Notice)) return count } diff --git a/models/system/notice_test.go b/models/system/notice_test.go index 871ffa54ce1bd..e8ce05d33248e 100644 --- a/models/system/notice_test.go +++ b/models/system/notice_test.go @@ -49,7 +49,7 @@ func TestCreateRepositoryNotice(t *testing.T) { func TestCountNotices(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - assert.Equal(t, int64(3), system.CountNotices()) + assert.Equal(t, int64(3), system.CountNotices(db.DefaultContext)) } func TestNotices(t *testing.T) { diff --git a/models/system/setting.go b/models/system/setting.go index 9fffa74e94afa..1ae6f5c652836 100644 --- a/models/system/setting.go +++ b/models/system/setting.go @@ -5,26 +5,21 @@ package system import ( "context" - "fmt" - "net/url" - "strconv" - "strings" + "math" + "sync" + "time" "code.gitea.io/gitea/models/db" - "code.gitea.io/gitea/modules/cache" - setting_module "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/setting/config" "code.gitea.io/gitea/modules/timeutil" - - "strk.kbt.io/projects/go/libravatar" - "xorm.io/builder" ) -// Setting is a key value store of user settings type Setting struct { ID int64 `xorm:"pk autoincr"` - SettingKey string `xorm:"varchar(255) unique"` // ensure key is always lowercase + SettingKey string `xorm:"varchar(255) unique"` // key should be lowercase SettingValue string `xorm:"text"` - Version int `xorm:"version"` // prevent to override + Version int `xorm:"version"` Created timeutil.TimeStamp `xorm:"created"` Updated timeutil.TimeStamp `xorm:"updated"` } @@ -34,281 +29,119 @@ func (s *Setting) TableName() string { return "system_setting" } -func (s *Setting) GetValueBool() bool { - if s == nil { - return false - } - - b, _ := strconv.ParseBool(s.SettingValue) - return b -} - func init() { db.RegisterModel(new(Setting)) } -// ErrSettingIsNotExist represents an error that a setting is not exist with special key -type ErrSettingIsNotExist struct { - Key string -} - -// Error implements error -func (err ErrSettingIsNotExist) Error() string { - return fmt.Sprintf("System setting[%s] is not exist", err.Key) -} - -// IsErrSettingIsNotExist return true if err is ErrSettingIsNotExist -func IsErrSettingIsNotExist(err error) bool { - _, ok := err.(ErrSettingIsNotExist) - return ok -} - -// ErrDataExpired represents an error that update a record which has been updated by another thread -type ErrDataExpired struct { - Key string -} - -// Error implements error -func (err ErrDataExpired) Error() string { - return fmt.Sprintf("System setting[%s] has been updated by another thread", err.Key) -} - -// IsErrDataExpired return true if err is ErrDataExpired -func IsErrDataExpired(err error) bool { - _, ok := err.(ErrDataExpired) - return ok -} - -// GetSetting returns specific setting without using the cache -func GetSetting(ctx context.Context, key string) (*Setting, error) { - v, err := GetSettings(ctx, []string{key}) - if err != nil { - return nil, err - } - if len(v) == 0 { - return nil, ErrSettingIsNotExist{key} - } - return v[strings.ToLower(key)], nil -} - -const contextCacheKey = "system_setting" - -// GetSettingWithCache returns the setting value via the key -func GetSettingWithCache(ctx context.Context, key, defaultVal string) (string, error) { - return cache.GetWithContextCache(ctx, contextCacheKey, key, func() (string, error) { - return cache.GetString(genSettingCacheKey(key), func() (string, error) { - res, err := GetSetting(ctx, key) - if err != nil { - if IsErrSettingIsNotExist(err) { - return defaultVal, nil - } - return "", err - } - return res.SettingValue, nil - }) - }) -} +const keyRevision = "revision" -// GetSettingBool return bool value of setting, -// none existing keys and errors are ignored and result in false -func GetSettingBool(ctx context.Context, key string, defaultVal bool) (bool, error) { - s, err := GetSetting(ctx, key) - switch { - case err == nil: - v, _ := strconv.ParseBool(s.SettingValue) - return v, nil - case IsErrSettingIsNotExist(err): - return defaultVal, nil - default: - return false, err +func GetRevision(ctx context.Context) int { + revision := &Setting{SettingKey: keyRevision} + if has, err := db.GetByBean(ctx, revision); err != nil { + return 0 + } else if !has { + err = db.Insert(ctx, &Setting{SettingKey: keyRevision, Version: 1}) + if err != nil { + return 0 + } + return 1 + } else if revision.Version <= 0 || revision.Version >= math.MaxInt-1 { + _, err = db.Exec(ctx, "UPDATE system_setting SET version=1 WHERE setting_key=?", keyRevision) + if err != nil { + return 0 + } + return 1 } + return revision.Version } -func GetSettingWithCacheBool(ctx context.Context, key string, defaultVal bool) bool { - s, _ := GetSettingWithCache(ctx, key, strconv.FormatBool(defaultVal)) - v, _ := strconv.ParseBool(s) - return v -} - -// GetSettings returns specific settings -func GetSettings(ctx context.Context, keys []string) (map[string]*Setting, error) { - for i := 0; i < len(keys); i++ { - keys[i] = strings.ToLower(keys[i]) - } - settings := make([]*Setting, 0, len(keys)) +func GetAllSettings(ctx context.Context) (revision int, res map[string]string, err error) { + _ = GetRevision(ctx) // prepare the "revision" key ahead + var settings []*Setting if err := db.GetEngine(ctx). - Where(builder.In("setting_key", keys)). Find(&settings); err != nil { - return nil, err + return 0, nil, err } - settingsMap := make(map[string]*Setting) + res = make(map[string]string) for _, s := range settings { - settingsMap[s.SettingKey] = s - } - return settingsMap, nil -} - -type AllSettings map[string]*Setting - -func (settings AllSettings) Get(key string) Setting { - if v, ok := settings[strings.ToLower(key)]; ok { - return *v - } - return Setting{} -} - -func (settings AllSettings) GetBool(key string) bool { - b, _ := strconv.ParseBool(settings.Get(key).SettingValue) - return b -} - -func (settings AllSettings) GetVersion(key string) int { - return settings.Get(key).Version -} - -// GetAllSettings returns all settings from user -func GetAllSettings(ctx context.Context) (AllSettings, error) { - settings := make([]*Setting, 0, 5) - if err := db.GetEngine(ctx). - Find(&settings); err != nil { - return nil, err - } - settingsMap := make(map[string]*Setting) - for _, s := range settings { - settingsMap[s.SettingKey] = s - } - return settingsMap, nil -} - -// DeleteSetting deletes a specific setting for a user -func DeleteSetting(ctx context.Context, setting *Setting) error { - cache.RemoveContextData(ctx, contextCacheKey, setting.SettingKey) - cache.Remove(genSettingCacheKey(setting.SettingKey)) - _, err := db.GetEngine(ctx).Delete(setting) - return err -} - -func SetSettingNoVersion(ctx context.Context, key, value string) error { - s, err := GetSetting(ctx, key) - if IsErrSettingIsNotExist(err) { - return SetSetting(ctx, &Setting{ - SettingKey: key, - SettingValue: value, - }) - } - if err != nil { - return err - } - s.SettingValue = value - return SetSetting(ctx, s) -} - -// SetSetting updates a users' setting for a specific key -func SetSetting(ctx context.Context, setting *Setting) error { - if err := upsertSettingValue(ctx, strings.ToLower(setting.SettingKey), setting.SettingValue, setting.Version); err != nil { - return err - } - - setting.Version++ - - cc := cache.GetCache() - if cc != nil { - if err := cc.Put(genSettingCacheKey(setting.SettingKey), setting.SettingValue, setting_module.CacheService.TTLSeconds()); err != nil { - return err + if s.SettingKey == keyRevision { + revision = s.Version } + res[s.SettingKey] = s.SettingValue } - cache.SetContextData(ctx, contextCacheKey, setting.SettingKey, setting.SettingValue) - return nil + return revision, res, nil } -func upsertSettingValue(parentCtx context.Context, key, value string, version int) error { - return db.WithTx(parentCtx, func(ctx context.Context) error { +func SetSettings(ctx context.Context, settings map[string]string) error { + _ = GetRevision(ctx) // prepare the "revision" key ahead + return db.WithTx(ctx, func(ctx context.Context) error { e := db.GetEngine(ctx) - - // here we use a general method to do a safe upsert for different databases (and most transaction levels) - // 1. try to UPDATE the record and acquire the transaction write lock - // if UPDATE returns non-zero rows are changed, OK, the setting is saved correctly - // if UPDATE returns "0 rows changed", two possibilities: (a) record doesn't exist (b) value is not changed - // 2. do a SELECT to check if the row exists or not (we already have the transaction lock) - // 3. if the row doesn't exist, do an INSERT (we are still protected by the transaction lock, so it's safe) - // - // to optimize the SELECT in step 2, we can use an extra column like `revision=revision+1` - // to make sure the UPDATE always returns a non-zero value for existing (unchanged) records. - - res, err := e.Exec("UPDATE system_setting SET setting_value=?, version = version+1 WHERE setting_key=? AND version=?", value, key, version) - if err != nil { - return err - } - rows, _ := res.RowsAffected() - if rows > 0 { - // the existing row is updated, so we can return - return nil - } - - // in case the value isn't changed, update would return 0 rows changed, so we need this check - has, err := e.Exist(&Setting{SettingKey: key}) + _, err := db.Exec(ctx, "UPDATE system_setting SET version=version+1 WHERE setting_key=?", keyRevision) if err != nil { return err } - if has { - return ErrDataExpired{Key: key} + for k, v := range settings { + res, err := e.Exec("UPDATE system_setting SET setting_value=? WHERE setting_key=?", v, k) + if err != nil { + return err + } + rows, _ := res.RowsAffected() + if rows == 0 { // if no existing row, insert a new row + if _, err = e.Insert(&Setting{SettingKey: k, SettingValue: v}); err != nil { + return err + } + } } - - // if no existing row, insert a new row - _, err = e.Insert(&Setting{SettingKey: key, SettingValue: value}) - return err + return nil }) } -var ( - GravatarSourceURL *url.URL - LibravatarService *libravatar.Libravatar -) +type dbConfigCachedGetter struct { + mu sync.RWMutex -func Init(ctx context.Context) error { - disableGravatar, err := GetSettingBool(ctx, KeyPictureDisableGravatar, setting_module.GetDefaultDisableGravatar()) - if err != nil { - return err - } + cacheTime time.Time + revision int + settings map[string]string +} - enableFederatedAvatar, err := GetSettingBool(ctx, KeyPictureEnableFederatedAvatar, setting_module.GetDefaultEnableFederatedAvatar(disableGravatar)) - if err != nil { - return err - } +var _ config.DynKeyGetter = (*dbConfigCachedGetter)(nil) - if setting_module.OfflineMode { - if !disableGravatar { - if err := SetSettingNoVersion(ctx, KeyPictureDisableGravatar, "true"); err != nil { - return fmt.Errorf("failed to set setting %q: %w", KeyPictureDisableGravatar, err) - } - } - disableGravatar = true +func (d *dbConfigCachedGetter) GetValue(ctx context.Context, key string) (v string, has bool) { + d.mu.RLock() + defer d.mu.RUnlock() + v, has = d.settings[key] + return v, has +} - if enableFederatedAvatar { - if err := SetSettingNoVersion(ctx, KeyPictureEnableFederatedAvatar, "false"); err != nil { - return fmt.Errorf("failed to set setting %q: %w", KeyPictureEnableFederatedAvatar, err) - } - } - enableFederatedAvatar = false +func (d *dbConfigCachedGetter) GetRevision(ctx context.Context) int { + d.mu.RLock() + defer d.mu.RUnlock() + if time.Since(d.cacheTime) < time.Second { + return d.revision } - - if enableFederatedAvatar || !disableGravatar { - var err error - GravatarSourceURL, err = url.Parse(setting_module.GravatarSource) + if GetRevision(ctx) != d.revision { + d.mu.RUnlock() + d.mu.Lock() + rev, set, err := GetAllSettings(ctx) if err != nil { - return fmt.Errorf("failed to parse Gravatar URL(%s): %w", setting_module.GravatarSource, err) - } - } - - if GravatarSourceURL != nil && enableFederatedAvatar { - LibravatarService = libravatar.New() - if GravatarSourceURL.Scheme == "https" { - LibravatarService.SetUseHTTPS(true) - LibravatarService.SetSecureFallbackHost(GravatarSourceURL.Host) + log.Error("Unable to get all settings: %v", err) } else { - LibravatarService.SetUseHTTPS(false) - LibravatarService.SetFallbackHost(GravatarSourceURL.Host) + d.cacheTime = time.Now() + d.revision = rev + d.settings = set } + d.mu.Unlock() + d.mu.RLock() } - return nil + return d.revision +} + +func (d *dbConfigCachedGetter) InvalidateCache() { + d.mu.Lock() + d.cacheTime = time.Time{} + d.mu.Unlock() +} + +func NewDatabaseDynKeyGetter() config.DynKeyGetter { + return &dbConfigCachedGetter{} } diff --git a/models/system/setting_key.go b/models/system/setting_key.go deleted file mode 100644 index ad083ed1ead98..0000000000000 --- a/models/system/setting_key.go +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2022 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package system - -// enumerate all system setting keys -const ( - KeyPictureDisableGravatar = "picture.disable_gravatar" - KeyPictureEnableFederatedAvatar = "picture.enable_federated_avatar" -) - -// genSettingCacheKey returns the cache key for some configuration -func genSettingCacheKey(key string) string { - return "system.setting." + key -} diff --git a/models/system/setting_test.go b/models/system/setting_test.go index e6997ad783264..4117420e5f24b 100644 --- a/models/system/setting_test.go +++ b/models/system/setting_test.go @@ -4,7 +4,6 @@ package system_test import ( - "strings" "testing" "code.gitea.io/gitea/models/db" @@ -15,43 +14,29 @@ import ( ) func TestSettings(t *testing.T) { - keyName := "server.LFS_LOCKS_PAGING_NUM" + keyName := "test.key" assert.NoError(t, unittest.PrepareTestDatabase()) - newSetting := &system.Setting{SettingKey: keyName, SettingValue: "50"} + assert.NoError(t, db.TruncateBeans(db.DefaultContext, &system.Setting{})) - // create setting - err := system.SetSetting(db.DefaultContext, newSetting) + rev, settings, err := system.GetAllSettings(db.DefaultContext) assert.NoError(t, err) - // test about saving unchanged values - err = system.SetSetting(db.DefaultContext, newSetting) - assert.NoError(t, err) - - // get specific setting - settings, err := system.GetSettings(db.DefaultContext, []string{keyName}) - assert.NoError(t, err) - assert.Len(t, settings, 1) - assert.EqualValues(t, newSetting.SettingValue, settings[strings.ToLower(keyName)].SettingValue) + assert.EqualValues(t, 1, rev) + assert.Len(t, settings, 1) // there is only one "revision" key - // updated setting - updatedSetting := &system.Setting{SettingKey: keyName, SettingValue: "100", Version: settings[strings.ToLower(keyName)].Version} - err = system.SetSetting(db.DefaultContext, updatedSetting) + err = system.SetSettings(db.DefaultContext, map[string]string{keyName: "true"}) assert.NoError(t, err) - - value, err := system.GetSetting(db.DefaultContext, keyName) + rev, settings, err = system.GetAllSettings(db.DefaultContext) assert.NoError(t, err) - assert.EqualValues(t, updatedSetting.SettingValue, value.SettingValue) - - // get all settings - settings, err = system.GetAllSettings(db.DefaultContext) - assert.NoError(t, err) - assert.Len(t, settings, 3) - assert.EqualValues(t, updatedSetting.SettingValue, settings[strings.ToLower(updatedSetting.SettingKey)].SettingValue) + assert.EqualValues(t, 2, rev) + assert.Len(t, settings, 2) + assert.EqualValues(t, "true", settings[keyName]) - // delete setting - err = system.DeleteSetting(db.DefaultContext, &system.Setting{SettingKey: strings.ToLower(keyName)}) + err = system.SetSettings(db.DefaultContext, map[string]string{keyName: "false"}) assert.NoError(t, err) - settings, err = system.GetAllSettings(db.DefaultContext) + rev, settings, err = system.GetAllSettings(db.DefaultContext) assert.NoError(t, err) + assert.EqualValues(t, 3, rev) assert.Len(t, settings, 2) + assert.EqualValues(t, "false", settings[keyName]) } diff --git a/models/unittest/testdb.go b/models/unittest/testdb.go index 6db99cd393e57..4c668ad04bf1e 100644 --- a/models/unittest/testdb.go +++ b/models/unittest/testdb.go @@ -13,11 +13,12 @@ import ( "testing" "code.gitea.io/gitea/models/db" - system_model "code.gitea.io/gitea/models/system" + "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/modules/auth/password/hash" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/setting/config" "code.gitea.io/gitea/modules/storage" "code.gitea.io/gitea/modules/util" @@ -145,13 +146,11 @@ func MainTest(m *testing.M, testOpts ...*TestOptions) { setting.IncomingEmail.ReplyToAddress = "incoming+%{token}@localhost" + config.SetDynGetter(system.NewDatabaseDynKeyGetter()) + if err = storage.Init(); err != nil { fatalTestError("storage.Init: %v\n", err) } - if err = system_model.Init(db.DefaultContext); err != nil { - fatalTestError("models.Init: %v\n", err) - } - if err = util.RemoveAll(repoRootPath); err != nil { fatalTestError("util.RemoveAll: %v\n", err) } diff --git a/models/user/avatar.go b/models/user/avatar.go index 7f996fa79ab7f..8c9abecbea9cb 100644 --- a/models/user/avatar.go +++ b/models/user/avatar.go @@ -13,7 +13,6 @@ import ( "code.gitea.io/gitea/models/avatars" "code.gitea.io/gitea/models/db" - system_model "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/modules/avatar" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" @@ -67,9 +66,7 @@ func (u *User) AvatarLinkWithSize(ctx context.Context, size int) string { useLocalAvatar := false autoGenerateAvatar := false - disableGravatar := system_model.GetSettingWithCacheBool(ctx, system_model.KeyPictureDisableGravatar, - setting.GetDefaultDisableGravatar(), - ) + disableGravatar := setting.Config().Picture.DisableGravatar.Value(ctx) switch { case u.UseCustomAvatar: diff --git a/models/user/user.go b/models/user/user.go index 9499efa60ef67..5e88077ee122e 100644 --- a/models/user/user.go +++ b/models/user/user.go @@ -42,7 +42,7 @@ const ( // UserTypeOrganization defines an organization UserTypeOrganization - // UserTypeReserved reserves a (non-existing) user, i.e. to prevent a spam user from re-registering after being deleted, or to reserve the name until the user is actually created later on + // UserTypeUserReserved reserves a (non-existing) user, i.e. to prevent a spam user from re-registering after being deleted, or to reserve the name until the user is actually created later on UserTypeUserReserved // UserTypeOrganizationReserved reserves a (non-existing) organization, to be used in combination with UserTypeUserReserved diff --git a/modules/context/org.go b/modules/context/org.go index c27d07e5385aa..d068646577ef5 100644 --- a/modules/context/org.go +++ b/modules/context/org.go @@ -128,7 +128,7 @@ func HandleOrgAssignment(ctx *Context, args ...bool) { ctx.Org.IsTeamAdmin = true ctx.Org.CanCreateOrgRepo = true } else if ctx.IsSigned { - ctx.Org.IsOwner, err = org.IsOwnedBy(ctx.Doer.ID) + ctx.Org.IsOwner, err = org.IsOwnedBy(ctx, ctx.Doer.ID) if err != nil { ctx.ServerError("IsOwnedBy", err) return @@ -140,12 +140,12 @@ func HandleOrgAssignment(ctx *Context, args ...bool) { ctx.Org.IsTeamAdmin = true ctx.Org.CanCreateOrgRepo = true } else { - ctx.Org.IsMember, err = org.IsOrgMember(ctx.Doer.ID) + ctx.Org.IsMember, err = org.IsOrgMember(ctx, ctx.Doer.ID) if err != nil { ctx.ServerError("IsOrgMember", err) return } - ctx.Org.CanCreateOrgRepo, err = org.CanCreateOrgRepo(ctx.Doer.ID) + ctx.Org.CanCreateOrgRepo, err = org.CanCreateOrgRepo(ctx, ctx.Doer.ID) if err != nil { ctx.ServerError("CanCreateOrgRepo", err) return @@ -165,7 +165,7 @@ func HandleOrgAssignment(ctx *Context, args ...bool) { ctx.Data["IsPackageEnabled"] = setting.Packages.Enabled ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled ctx.Data["IsPublicMember"] = func(uid int64) bool { - is, _ := organization.IsPublicMembership(ctx.Org.Organization.ID, uid) + is, _ := organization.IsPublicMembership(ctx, ctx.Org.Organization.ID, uid) return is } ctx.Data["CanCreateOrgRepo"] = ctx.Org.CanCreateOrgRepo @@ -179,7 +179,7 @@ func HandleOrgAssignment(ctx *Context, args ...bool) { OrgID: org.ID, PublicOnly: ctx.Org.PublicMemberOnly, } - ctx.Data["NumMembers"], err = organization.CountOrgMembers(opts) + ctx.Data["NumMembers"], err = organization.CountOrgMembers(ctx, opts) if err != nil { ctx.ServerError("CountOrgMembers", err) return @@ -191,7 +191,7 @@ func HandleOrgAssignment(ctx *Context, args ...bool) { if ctx.Org.IsOwner { shouldSeeAllTeams = true } else { - teams, err := org.GetUserTeams(ctx.Doer.ID) + teams, err := org.GetUserTeams(ctx, ctx.Doer.ID) if err != nil { ctx.ServerError("GetUserTeams", err) return @@ -204,13 +204,13 @@ func HandleOrgAssignment(ctx *Context, args ...bool) { } } if shouldSeeAllTeams { - ctx.Org.Teams, err = org.LoadTeams() + ctx.Org.Teams, err = org.LoadTeams(ctx) if err != nil { ctx.ServerError("LoadTeams", err) return } } else { - ctx.Org.Teams, err = org.GetUserTeams(ctx.Doer.ID) + ctx.Org.Teams, err = org.GetUserTeams(ctx, ctx.Doer.ID) if err != nil { ctx.ServerError("GetUserTeams", err) return diff --git a/modules/context/package.go b/modules/context/package.go index c0813fb2da6ba..87e817c1cd688 100644 --- a/modules/context/package.go +++ b/modules/context/package.go @@ -109,7 +109,7 @@ func determineAccessMode(ctx *Base, pkg *Package, doer *user_model.User) (perm.A if doer != nil && !doer.IsGhost() { // 1. If user is logged in, check all team packages permissions var err error - accessMode, err = org.GetOrgUserMaxAuthorizeLevel(doer.ID) + accessMode, err = org.GetOrgUserMaxAuthorizeLevel(ctx, doer.ID) if err != nil { return accessMode, err } diff --git a/modules/context/repo.go b/modules/context/repo.go index 44ae624568ac0..18b6650b6efa6 100644 --- a/modules/context/repo.go +++ b/modules/context/repo.go @@ -545,7 +545,10 @@ func RepoAssignment(ctx *Context) context.CancelFunc { ctx.ServerError("GetReleaseCountByRepoID", err) return nil } - ctx.Data["NumReleases"], err = repo_model.GetReleaseCountByRepoID(ctx, ctx.Repo.Repository.ID, repo_model.FindReleasesOptions{}) + ctx.Data["NumReleases"], err = repo_model.GetReleaseCountByRepoID(ctx, ctx.Repo.Repository.ID, repo_model.FindReleasesOptions{ + // only show draft releases for users who can write, read-only users shouldn't see draft releases. + IncludeDrafts: ctx.Repo.CanWrite(unit_model.TypeReleases), + }) if err != nil { ctx.ServerError("GetReleaseCountByRepoID", err) return nil @@ -773,6 +776,8 @@ const ( RepoRefBlob ) +const headRefName = "HEAD" + // RepoRef handles repository reference names when the ref name is not // explicitly given func RepoRef() func(*Context) context.CancelFunc { @@ -833,6 +838,14 @@ func getRefName(ctx *Base, repo *Repository, pathType RepoRefType) string { case RepoRefBranch: ref := getRefNameFromPath(ctx, repo, path, repo.GitRepo.IsBranchExist) if len(ref) == 0 { + + // check if ref is HEAD + parts := strings.Split(path, "/") + if parts[0] == headRefName { + repo.TreePath = strings.Join(parts[1:], "/") + return repo.Repository.DefaultBranch + } + // maybe it's a renamed branch return getRefNameFromPath(ctx, repo, path, func(s string) bool { b, exist, err := git_model.FindRenamedBranch(ctx, repo.Repository.ID, s) @@ -861,6 +874,16 @@ func getRefName(ctx *Base, repo *Repository, pathType RepoRefType) string { repo.TreePath = strings.Join(parts[1:], "/") return parts[0] } + + if len(parts) > 0 && parts[0] == headRefName { + // HEAD ref points to last default branch commit + commit, err := repo.GitRepo.GetBranchCommit(repo.Repository.DefaultBranch) + if err != nil { + return "" + } + repo.TreePath = strings.Join(parts[1:], "/") + return commit.ID.String() + } case RepoRefBlob: _, err := repo.GitRepo.GetBlob(path) if err != nil { diff --git a/modules/doctor/fix16961.go b/modules/doctor/fix16961.go index 562c78dd76597..d3f36d8d5cdfb 100644 --- a/modules/doctor/fix16961.go +++ b/modules/doctor/fix16961.go @@ -290,7 +290,7 @@ func fixBrokenRepoUnits16961(ctx context.Context, logger log.Logger, autofix boo return nil } - return repo_model.UpdateRepoUnit(repoUnit) + return repo_model.UpdateRepoUnit(ctx, repoUnit) }, ) if err != nil { diff --git a/modules/eventsource/manager_run.go b/modules/eventsource/manager_run.go index 2785836b89c47..bef1a00c5b914 100644 --- a/modules/eventsource/manager_run.go +++ b/modules/eventsource/manager_run.go @@ -71,7 +71,7 @@ loop: now := timeutil.TimeStampNow().Add(-2) - uidCounts, err := activities_model.GetUIDsAndNotificationCounts(then, now) + uidCounts, err := activities_model.GetUIDsAndNotificationCounts(ctx, then, now) if err != nil { log.Error("Unable to get UIDcounts: %v", err) } diff --git a/modules/git/repo.go b/modules/git/repo.go index 5681d39c3b717..32f0e7007eb0b 100644 --- a/modules/git/repo.go +++ b/modules/git/repo.go @@ -86,7 +86,8 @@ func (repo *Repository) IsEmpty() (bool, error) { Stdout: &output, Stderr: &errbuf, }); err != nil { - if err.Error() == "exit status 1" && errbuf.String() == "" { + if (err.Error() == "exit status 1" && strings.TrimSpace(errbuf.String()) == "") || err.Error() == "exit status 129" { + // git 2.11 exits with 129 if the repo is empty return true, nil } return true, fmt.Errorf("check empty: %w - %s", err, errbuf.String()) diff --git a/modules/git/repo_commit.go b/modules/git/repo_commit.go index 6fc3063629115..6b06fef656ec6 100644 --- a/modules/git/repo_commit.go +++ b/modules/git/repo_commit.go @@ -116,17 +116,13 @@ func (repo *Repository) searchCommits(id SHA1, opts SearchCommitsOptions) ([]*Co c.AddArguments("-i") // add authors if present in search query - if len(opts.Authors) > 0 { - for _, v := range opts.Authors { - c.AddOptionFormat("--author=%s", v) - } + for _, v := range opts.Authors { + c.AddOptionFormat("--author=%s", v) } // add committers if present in search query - if len(opts.Committers) > 0 { - for _, v := range opts.Committers { - c.AddOptionFormat("--committer=%s", v) - } + for _, v := range opts.Committers { + c.AddOptionFormat("--committer=%s", v) } // add time constraints if present in search query @@ -150,10 +146,8 @@ func (repo *Repository) searchCommits(id SHA1, opts SearchCommitsOptions) ([]*Co // add remaining keywords from search string // note this is done only for command created above - if len(opts.Keywords) > 0 { - for _, v := range opts.Keywords { - cmd.AddOptionFormat("--grep=%s", v) - } + for _, v := range opts.Keywords { + cmd.AddOptionFormat("--grep=%s", v) } // search for commits matching given constraints and keywords in commit msg @@ -168,25 +162,23 @@ func (repo *Repository) searchCommits(id SHA1, opts SearchCommitsOptions) ([]*Co // if there are any keywords (ie not committer:, author:, time:) // then let's iterate over them - if len(opts.Keywords) > 0 { - for _, v := range opts.Keywords { - // ignore anything not matching a valid sha pattern - if IsValidSHAPattern(v) { - // create new git log command with 1 commit limit - hashCmd := NewCommand(repo.Ctx, "log", "-1", prettyLogFormat) - // add previous arguments except for --grep and --all - addCommonSearchArgs(hashCmd) - // add keyword as - hashCmd.AddDynamicArguments(v) - - // search with given constraints for commit matching sha hash of v - hashMatching, _, err := hashCmd.RunStdBytes(&RunOpts{Dir: repo.Path}) - if err != nil || bytes.Contains(stdout, hashMatching) { - continue - } - stdout = append(stdout, hashMatching...) - stdout = append(stdout, '\n') + for _, v := range opts.Keywords { + // ignore anything not matching a valid sha pattern + if IsValidSHAPattern(v) { + // create new git log command with 1 commit limit + hashCmd := NewCommand(repo.Ctx, "log", "-1", prettyLogFormat) + // add previous arguments except for --grep and --all + addCommonSearchArgs(hashCmd) + // add keyword as + hashCmd.AddDynamicArguments(v) + + // search with given constraints for commit matching sha hash of v + hashMatching, _, err := hashCmd.RunStdBytes(&RunOpts{Dir: repo.Path}) + if err != nil || bytes.Contains(stdout, hashMatching) { + continue } + stdout = append(stdout, hashMatching...) + stdout = append(stdout, '\n') } } diff --git a/modules/gitgraph/graph_models.go b/modules/gitgraph/graph_models.go index 0e3e9878e88ca..e48fef8b9d0cc 100644 --- a/modules/gitgraph/graph_models.go +++ b/modules/gitgraph/graph_models.go @@ -116,7 +116,7 @@ func (graph *Graph) LoadAndProcessCommits(ctx context.Context, repository *repo_ c.Verification = asymkey_model.ParseCommitWithSignature(ctx, c.Commit) _ = asymkey_model.CalculateTrustStatus(c.Verification, repository.GetTrustModel(), func(user *user_model.User) (bool, error) { - return repo_model.IsOwnerMemberCollaborator(repository, user.ID) + return repo_model.IsOwnerMemberCollaborator(ctx, repository, user.ID) }, &keyMap) statuses, _, err := git_model.GetLatestCommitStatus(ctx, repository.ID, c.Commit.ID.String(), db.ListOptions{}) diff --git a/modules/repository/collaborator_test.go b/modules/repository/collaborator_test.go index c772806819329..622f6abce4796 100644 --- a/modules/repository/collaborator_test.go +++ b/modules/repository/collaborator_test.go @@ -244,7 +244,7 @@ func TestRepoPermissionPrivateOrgRepo(t *testing.T) { // update team information and then check permission team := unittest.AssertExistsAndLoadBean(t, &organization.Team{ID: 5}) - err = organization.UpdateTeamUnits(team, nil) + err = organization.UpdateTeamUnits(db.DefaultContext, team, nil) assert.NoError(t, err) perm, err = access_model.GetUserRepoPermission(db.DefaultContext, repo, owner) assert.NoError(t, err) diff --git a/modules/repository/commits_test.go b/modules/repository/commits_test.go index 0931092597101..827b2a98493b0 100644 --- a/modules/repository/commits_test.go +++ b/modules/repository/commits_test.go @@ -12,7 +12,6 @@ import ( "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" - system_model "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/setting" @@ -103,12 +102,6 @@ func TestPushCommits_ToAPIPayloadCommits(t *testing.T) { assert.EqualValues(t, []string{"readme.md"}, headCommit.Modified) } -func initGravatarSource(t *testing.T) { - setting.GravatarSource = "https://secure.gravatar.com/avatar" - err := system_model.Init(db.DefaultContext) - assert.NoError(t, err) -} - func TestPushCommits_AvatarLink(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) @@ -132,7 +125,7 @@ func TestPushCommits_AvatarLink(t *testing.T) { }, } - initGravatarSource(t) + setting.GravatarSource = "https://secure.gravatar.com/avatar" assert.Equal(t, "https://secure.gravatar.com/avatar/ab53a2911ddf9b4817ac01ddcd3d975f?d=identicon&s="+strconv.Itoa(28*setting.Avatar.RenderedSizeFactor), diff --git a/modules/repository/delete.go b/modules/repository/delete.go index 43c52c933d142..04af98beefed9 100644 --- a/modules/repository/delete.go +++ b/modules/repository/delete.go @@ -22,7 +22,7 @@ func CanUserDelete(ctx context.Context, repo *repo_model.Repository, user *user_ } if repo.Owner.IsOrganization() { - isAdmin, err := organization.OrgFromUser(repo.Owner).IsOrgAdmin(user.ID) + isAdmin, err := organization.OrgFromUser(repo.Owner).IsOrgAdmin(ctx, user.ID) if err != nil { return false, err } diff --git a/modules/setting/actions.go b/modules/setting/actions.go index 28c84f01491aa..026bab4bfcfdc 100644 --- a/modules/setting/actions.go +++ b/modules/setting/actions.go @@ -6,6 +6,7 @@ package setting import ( "fmt" "strings" + "time" "code.gitea.io/gitea/modules/log" ) @@ -18,6 +19,9 @@ var ( ArtifactRetentionDays int64 `ini:"ARTIFACT_RETENTION_DAYS"` Enabled bool DefaultActionsURL defaultActionsURL `ini:"DEFAULT_ACTIONS_URL"` + ZombieTaskTimeout time.Duration `ini:"ZOMBIE_TASK_TIMEOUT"` + EndlessTaskTimeout time.Duration `ini:"ENDLESS_TASK_TIMEOUT"` + AbandonedJobTimeout time.Duration `ini:"ABANDONED_JOB_TIMEOUT"` }{ Enabled: true, DefaultActionsURL: defaultActionsURLGitHub, @@ -82,5 +86,9 @@ func loadActionsFrom(rootCfg ConfigProvider) error { Actions.ArtifactRetentionDays = 90 } + Actions.ZombieTaskTimeout = sec.Key("ZOMBIE_TASK_TIMEOUT").MustDuration(10 * time.Minute) + Actions.EndlessTaskTimeout = sec.Key("ENDLESS_TASK_TIMEOUT").MustDuration(3 * time.Hour) + Actions.AbandonedJobTimeout = sec.Key("ABANDONED_JOB_TIMEOUT").MustDuration(24 * time.Hour) + return err } diff --git a/modules/setting/config.go b/modules/setting/config.go new file mode 100644 index 0000000000000..db189f44ac522 --- /dev/null +++ b/modules/setting/config.go @@ -0,0 +1,55 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package setting + +import ( + "sync" + + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/setting/config" +) + +type PictureStruct struct { + DisableGravatar *config.Value[bool] + EnableFederatedAvatar *config.Value[bool] +} + +type ConfigStruct struct { + Picture *PictureStruct +} + +var ( + defaultConfig *ConfigStruct + defaultConfigOnce sync.Once +) + +func initDefaultConfig() { + config.SetCfgSecKeyGetter(&cfgSecKeyGetter{}) + defaultConfig = &ConfigStruct{ + Picture: &PictureStruct{ + DisableGravatar: config.Bool(false, config.CfgSecKey{Sec: "picture", Key: "DISABLE_GRAVATAR"}, "picture.disable_gravatar"), + EnableFederatedAvatar: config.Bool(false, config.CfgSecKey{Sec: "picture", Key: "ENABLE_FEDERATED_AVATAR"}, "picture.enable_federated_avatar"), + }, + } +} + +func Config() *ConfigStruct { + defaultConfigOnce.Do(initDefaultConfig) + return defaultConfig +} + +type cfgSecKeyGetter struct{} + +func (c cfgSecKeyGetter) GetValue(sec, key string) (v string, has bool) { + cfgSec, err := CfgProvider.GetSection(sec) + if err != nil { + log.Error("Unable to get config section: %q", sec) + return "", false + } + cfgKey := ConfigSectionKey(cfgSec, key) + if cfgKey == nil { + return "", false + } + return cfgKey.Value(), true +} diff --git a/modules/setting/config/getter.go b/modules/setting/config/getter.go new file mode 100644 index 0000000000000..99f9a4775a884 --- /dev/null +++ b/modules/setting/config/getter.go @@ -0,0 +1,49 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package config + +import ( + "context" + "sync" +) + +var getterMu sync.RWMutex + +type CfgSecKeyGetter interface { + GetValue(sec, key string) (v string, has bool) +} + +var cfgSecKeyGetterInternal CfgSecKeyGetter + +func SetCfgSecKeyGetter(p CfgSecKeyGetter) { + getterMu.Lock() + cfgSecKeyGetterInternal = p + getterMu.Unlock() +} + +func GetCfgSecKeyGetter() CfgSecKeyGetter { + getterMu.RLock() + defer getterMu.RUnlock() + return cfgSecKeyGetterInternal +} + +type DynKeyGetter interface { + GetValue(ctx context.Context, key string) (v string, has bool) + GetRevision(ctx context.Context) int + InvalidateCache() +} + +var dynKeyGetterInternal DynKeyGetter + +func SetDynGetter(p DynKeyGetter) { + getterMu.Lock() + dynKeyGetterInternal = p + getterMu.Unlock() +} + +func GetDynGetter() DynKeyGetter { + getterMu.RLock() + defer getterMu.RUnlock() + return dynKeyGetterInternal +} diff --git a/modules/setting/config/value.go b/modules/setting/config/value.go new file mode 100644 index 0000000000000..817fcdb7862df --- /dev/null +++ b/modules/setting/config/value.go @@ -0,0 +1,81 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package config + +import ( + "context" + "strconv" + "sync" +) + +type CfgSecKey struct { + Sec, Key string +} + +type Value[T any] struct { + mu sync.RWMutex + + cfgSecKey CfgSecKey + dynKey string + + def, value T + revision int +} + +func (value *Value[T]) parse(s string) (v T) { + switch any(v).(type) { + case bool: + b, _ := strconv.ParseBool(s) + return any(b).(T) + default: + panic("unsupported config type, please complete the code") + } +} + +func (value *Value[T]) Value(ctx context.Context) (v T) { + dg := GetDynGetter() + if dg == nil { + // this is an edge case: the database is not initialized but the system setting is going to be used + // it should panic to avoid inconsistent config values (from config / system setting) and fix the code + panic("no config dyn value getter") + } + + rev := dg.GetRevision(ctx) + + // if the revision in database doesn't change, use the last value + value.mu.RLock() + if rev == value.revision { + v = value.value + value.mu.RUnlock() + return v + } + value.mu.RUnlock() + + // try to parse the config and cache it + var valStr *string + if dynVal, has := dg.GetValue(ctx, value.dynKey); has { + valStr = &dynVal + } else if cfgVal, has := GetCfgSecKeyGetter().GetValue(value.cfgSecKey.Sec, value.cfgSecKey.Key); has { + valStr = &cfgVal + } + if valStr == nil { + v = value.def + } else { + v = value.parse(*valStr) + } + + value.mu.Lock() + value.value = v + value.revision = rev + value.mu.Unlock() + return v +} + +func (value *Value[T]) DynKey() string { + return value.dynKey +} + +func Bool(def bool, cfgSecKey CfgSecKey, dynKey string) *Value[bool] { + return &Value[bool]{def: def, cfgSecKey: cfgSecKey, dynKey: dynKey} +} diff --git a/modules/setting/config_provider.go b/modules/setting/config_provider.go index 8d64286288df7..132f4acea1c79 100644 --- a/modules/setting/config_provider.go +++ b/modules/setting/config_provider.go @@ -213,11 +213,9 @@ func NewConfigProviderFromFile(file string, extraConfigs ...string) (ConfigProvi } } - if len(extraConfigs) > 0 { - for _, s := range extraConfigs { - if err := cfg.Append([]byte(s)); err != nil { - return nil, fmt.Errorf("unable to append more config: %v", err) - } + for _, s := range extraConfigs { + if err := cfg.Append([]byte(s)); err != nil { + return nil, fmt.Errorf("unable to append more config: %v", err) } } diff --git a/modules/setting/oauth2.go b/modules/setting/oauth2.go index ab82393106fac..aea76b989ce6a 100644 --- a/modules/setting/oauth2.go +++ b/modules/setting/oauth2.go @@ -110,7 +110,7 @@ var OAuth2 = struct { JWTSigningAlgorithm: "RS256", JWTSigningPrivateKeyFile: "jwt/private.pem", MaxTokenLength: math.MaxInt16, - DefaultApplications: []string{"git-credential-oauth", "git-credential-manager"}, + DefaultApplications: []string{"git-credential-oauth", "git-credential-manager", "tea"}, } func loadOAuth2From(rootCfg ConfigProvider) { diff --git a/modules/setting/ui.go b/modules/setting/ui.go index 41438db40d5e7..231698bf60589 100644 --- a/modules/setting/ui.go +++ b/modules/setting/ui.go @@ -76,8 +76,8 @@ var UI = struct { CodeCommentLines: 4, ReactionMaxUserNum: 10, MaxDisplayFileSize: 8388608, - DefaultTheme: `auto`, - Themes: []string{`auto`, `gitea`, `arc-green`}, + DefaultTheme: `gitea-auto`, + Themes: []string{`gitea-auto`, `gitea-light`, `gitea-dark`}, Reactions: []string{`+1`, `-1`, `laugh`, `hooray`, `confused`, `heart`, `rocket`, `eyes`}, CustomEmojis: []string{`git`, `gitea`, `codeberg`, `gitlab`, `github`, `gogs`}, CustomEmojisMap: map[string]string{"git": ":git:", "gitea": ":gitea:", "codeberg": ":codeberg:", "gitlab": ":gitlab:", "github": ":github:", "gogs": ":gogs:"}, diff --git a/modules/templates/helper.go b/modules/templates/helper.go index bb1411cbfdb3e..235fd96b73d8f 100644 --- a/modules/templates/helper.go +++ b/modules/templates/helper.go @@ -12,6 +12,7 @@ import ( "strings" "time" + user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/emoji" "code.gitea.io/gitea/modules/markup" @@ -131,8 +132,11 @@ func NewFuncMap() template.FuncMap { "DisableImportLocal": func() bool { return !setting.ImportLocalPaths }, - "DefaultTheme": func() string { - return setting.UI.DefaultTheme + "ThemeName": func(user *user_model.User) string { + if user == nil || user.Theme == "" { + return setting.UI.DefaultTheme + } + return user.Theme }, "NotificationSettings": func() map[string]any { return map[string]any{ diff --git a/modules/templates/util_misc.go b/modules/templates/util_misc.go index 7700a13932b82..6c1b4ab240e34 100644 --- a/modules/templates/util_misc.go +++ b/modules/templates/util_misc.go @@ -58,11 +58,11 @@ func IsMultilineCommitMessage(msg string) bool { // Actioner describes an action type Actioner interface { GetOpType() activities_model.ActionType - GetActUserName() string - GetRepoUserName() string - GetRepoName() string - GetRepoPath() string - GetRepoLink() string + GetActUserName(ctx context.Context) string + GetRepoUserName(ctx context.Context) string + GetRepoName(ctx context.Context) string + GetRepoPath(ctx context.Context) string + GetRepoLink(ctx context.Context) string GetBranch() string GetContent() string GetCreate() time.Time @@ -74,27 +74,31 @@ func ActionIcon(opType activities_model.ActionType) string { switch opType { case activities_model.ActionCreateRepo, activities_model.ActionTransferRepo, activities_model.ActionRenameRepo: return "repo" - case activities_model.ActionCommitRepo, activities_model.ActionPushTag, activities_model.ActionDeleteTag, activities_model.ActionDeleteBranch: + case activities_model.ActionCommitRepo: return "git-commit" - case activities_model.ActionCreateIssue: - return "issue-opened" - case activities_model.ActionCreatePullRequest: - return "git-pull-request" - case activities_model.ActionCommentIssue, activities_model.ActionCommentPull: - return "comment-discussion" + case activities_model.ActionDeleteBranch: + return "git-branch" case activities_model.ActionMergePullRequest, activities_model.ActionAutoMergePullRequest: return "git-merge" - case activities_model.ActionCloseIssue, activities_model.ActionClosePullRequest: + case activities_model.ActionCreatePullRequest: + return "git-pull-request" + case activities_model.ActionClosePullRequest: + return "git-pull-request-closed" + case activities_model.ActionCreateIssue: + return "issue-opened" + case activities_model.ActionCloseIssue: return "issue-closed" case activities_model.ActionReopenIssue, activities_model.ActionReopenPullRequest: return "issue-reopened" + case activities_model.ActionCommentIssue, activities_model.ActionCommentPull: + return "comment-discussion" case activities_model.ActionMirrorSyncPush, activities_model.ActionMirrorSyncCreate, activities_model.ActionMirrorSyncDelete: return "mirror" case activities_model.ActionApprovePullRequest: return "check" case activities_model.ActionRejectPullRequest: - return "diff" - case activities_model.ActionPublishRelease: + return "file-diff" + case activities_model.ActionPublishRelease, activities_model.ActionPushTag, activities_model.ActionDeleteTag: return "tag" case activities_model.ActionPullReviewDismissed: return "x" diff --git a/options/license/Adobe-Utopia b/options/license/Adobe-Utopia new file mode 100644 index 0000000000000..4aa04503b54cb --- /dev/null +++ b/options/license/Adobe-Utopia @@ -0,0 +1,12 @@ +Permission to use, reproduce, display and distribute the listed typefaces +is hereby granted, provided that the Adobe Copyright notice appears in all +whole and partial copies of the software and that the following trademark +symbol and attribution appear in all unmodified copies of the software: + +The Adobe typefaces (Type 1 font program, bitmaps and Adobe Font Metric +files) donated are: + + Utopia Regular + Utopia Italic + Utopia Bold + Utopia Bold Italic diff --git a/options/license/BSD-3-Clause-HP b/options/license/BSD-3-Clause-HP new file mode 100644 index 0000000000000..e16195729ade7 --- /dev/null +++ b/options/license/BSD-3-Clause-HP @@ -0,0 +1,23 @@ +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. Neither the name of the HP nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PATENT INFRINGEMENT; PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/options/license/BSD-Inferno-Nettverk b/options/license/BSD-Inferno-Nettverk new file mode 100644 index 0000000000000..d10fe158a115c --- /dev/null +++ b/options/license/BSD-Inferno-Nettverk @@ -0,0 +1,41 @@ + Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, + 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 + 2017, 2018, 2019, 2020 + Inferno Nettverk A/S, Norway. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. The above copyright notice, this list of conditions and the following + disclaimer must appear in all copies of the software, derivative works + or modified versions, and any portions thereof, aswell as in all + supporting documentation. + 2. All advertising materials mentioning features or use of this software + must display the following acknowledgement: + This product includes software developed by + Inferno Nettverk A/S, Norway. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + Inferno Nettverk A/S requests users of this software to return to + + Software Distribution Coordinator or sdc@inet.no + Inferno Nettverk A/S + Oslo Research Park + Gaustadalléen 21 + NO-0349 Oslo + Norway + + any improvements or extensions that they make and grant Inferno Nettverk A/S + the rights to redistribute these changes. diff --git a/options/license/Cronyx b/options/license/Cronyx new file mode 100644 index 0000000000000..10fa8e706733e --- /dev/null +++ b/options/license/Cronyx @@ -0,0 +1,11 @@ +This package contains a set of Russian fonts for X11 Release 6. +Copyright (C) 1994-1995 Cronyx Ltd. +Changes Copyright (C) 1996 by Sergey Vovk +Changes Copyright (C) 1999-2000 by Serge Winitzki +Changes Copyright (C) 1996-2000 by Andrey A. Chernov, Moscow, Russia. + +This software may be used, modified, copied, distributed, and sold, +in both source and binary form provided that the copyright +and these terms are retained. Under no circumstances is the author +responsible for the proper functioning of this software, nor does +the author assume any responsibility for damages incurred with its use. diff --git a/options/license/Furuseth b/options/license/Furuseth new file mode 100644 index 0000000000000..55feeef90b85d --- /dev/null +++ b/options/license/Furuseth @@ -0,0 +1,13 @@ +Portions Copyright 1999-2008 Howard Y.H. Chu. +Portions Copyright 1999-2008 Symas Corporation. +Portions Copyright 1998-2003 Hallvard B. Furuseth. +Portions Copyright 2007-2011 Gavin Henry. +Portions Copyright 2007-2011 Suretec Systems Ltd. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that this notice is preserved. +The names of the copyright holders may not be used to endorse or +promote products derived from this software without their specific +prior written permission. This software is provided ``as is'' +without express or implied warranty. diff --git a/options/license/HPND b/options/license/HPND index 74abede5f6b24..ff9ae1b7134a5 100644 --- a/options/license/HPND +++ b/options/license/HPND @@ -1,7 +1,7 @@ Historical Permission Notice and Disclaimer - +Copyright -Permission to use, copy, modify and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies, and that both that the copyright notice and this permission notice appear in supporting documentation, and that the name of or not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. +Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies, and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of or not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. makes no representations about the suitability of this software for any purpose. It is provided "as is" without express or implied warranty. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,. IN NO EVENT SHALL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/options/license/HPND-DEC b/options/license/HPND-DEC new file mode 100644 index 0000000000000..d014f1fabce80 --- /dev/null +++ b/options/license/HPND-DEC @@ -0,0 +1,22 @@ +COPYRIGHT 1990 +DIGITAL EQUIPMENT CORPORATION +MAYNARD, MASSACHUSETTS +ALL RIGHTS RESERVED. + +THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION. +DIGITAL MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE +FOR ANY PURPOSE. IT IS SUPPLIED "AS IS" WITHOUT EXPRESS OR IMPLIED +WARRANTY. + +IF THE SOFTWARE IS MODIFIED IN A MANNER CREATING DERIVATIVE COPYRIGHT +RIGHTS, APPROPRIATE LEGENDS MAY BE PLACED ON THE DERIVATIVE WORK IN +ADDITION TO THAT SET FORTH ABOVE. + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies +and that both that copyright notice and this permission notice appear in supporting +documentation, +and that the name of Digital Equipment Corporation not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. diff --git a/options/license/HPND-Pbmplus b/options/license/HPND-Pbmplus new file mode 100644 index 0000000000000..5627d2646f825 --- /dev/null +++ b/options/license/HPND-Pbmplus @@ -0,0 +1,8 @@ +Copyright (C) 1991 by Jef Poskanzer. + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, provided +that the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. This software is provided "as is" without express or +implied warranty. diff --git a/options/license/HPND-UC b/options/license/HPND-UC new file mode 100644 index 0000000000000..adfbd2386288a --- /dev/null +++ b/options/license/HPND-UC @@ -0,0 +1,8 @@ +Copyright 1989 Regents of the University of California + +Permission to use, +copy, modify, and distribute this software and its documentation for any +purpose and without fee is hereby granted, provided that the above +copyright notice appear in all copies. The University of California makes +no representations about the suitability of this software for any purpose. +It is provided "as is" without express or implied warranty. diff --git a/options/license/HPND-doc b/options/license/HPND-doc new file mode 100644 index 0000000000000..bd85a2816e52d --- /dev/null +++ b/options/license/HPND-doc @@ -0,0 +1,8 @@ +Copyright + +Permission to use, copy, modify, and distribute this documentation for +any purpose and without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + makes no representations about the suitability for +any purpose of the information in this document. This documentation is +provided ``as is'' without express or implied warranty. diff --git a/options/license/HPND-doc-sell b/options/license/HPND-doc-sell new file mode 100644 index 0000000000000..ad4aed3e608e9 --- /dev/null +++ b/options/license/HPND-doc-sell @@ -0,0 +1,9 @@ +Copyright + +Permission to use, copy, modify, distribute, and sell this +documentation for any purpose is hereby granted without fee, +provided that the above copyright notice and this permission +notice appear in all copies. +makes no representations about the suitability for any purpose +of the information in this document. This documentation +is provided "as is" without express or implied warranty. diff --git a/options/license/HPND-export-US-modify b/options/license/HPND-export-US-modify new file mode 100644 index 0000000000000..3c62651c0f40c --- /dev/null +++ b/options/license/HPND-export-US-modify @@ -0,0 +1,24 @@ +Copyright (C) 1994 CyberSAFE Corporation. +Copyright 1990,1991,2007,2008 by the Massachusetts +Institute of Technology. +All Rights Reserved. + +Export of this software from the United States of America may +require a specific license from the United States Government. It +is the responsibility of any person or organization +contemplating export to obtain such a license before exporting. + +WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +distribute this software and its documentation for any purpose and +without fee is hereby granted, provided that the above copyright +notice appear in all copies and that both that copyright notice and +this permission notice appear in supporting documentation, and that +the name of M.I.T. not be used in advertising or publicity +pertaining to distribution of the software without specific, +written prior permission. Furthermore if you modify this software +you must label your software as modified software and not +distribute it in such a fashion that it might be confused with the +original M.I.T. software. Neither M.I.T., the Open Computing +Security Group, nor CyberSAFE Corporation make any representations +about the suitability of this software for any purpose. It is +provided "as is" without express or implied warranty. diff --git a/options/license/HPND-sell-regexpr b/options/license/HPND-sell-regexpr new file mode 100644 index 0000000000000..b0cd0fb1126b8 --- /dev/null +++ b/options/license/HPND-sell-regexpr @@ -0,0 +1,9 @@ +Author: Tatu Ylonen + +Copyright (c) 1991 Tatu Ylonen, Espoo, Finland + +Permission to use, copy, modify, distribute, and sell this software +and its documentation for any purpose is hereby granted without +fee, provided that the above copyright notice appear in all copies. +This software is provided "as is" without express or implied +warranty. diff --git a/options/license/Kastrup b/options/license/Kastrup new file mode 100644 index 0000000000000..46d1e9e0e49e6 --- /dev/null +++ b/options/license/Kastrup @@ -0,0 +1,3 @@ +Copyright(c) 2001 by David Kastrup +Any use of the code is permitted as long as this copyright +notice is preserved in the code. diff --git a/options/license/Lucida-Bitmap-Fonts b/options/license/Lucida-Bitmap-Fonts new file mode 100644 index 0000000000000..35be63ed33db1 --- /dev/null +++ b/options/license/Lucida-Bitmap-Fonts @@ -0,0 +1,53 @@ +This is the LEGAL NOTICE pertaining to the Lucida fonts from Bigelow & Holmes: + + NOTICE TO USER: The source code, including the glyphs or icons + forming a par of the OPEN LOOK TM Graphic User Interface, on this + tape and in these files is copyrighted under U.S. and international + laws. Sun Microsystems, Inc. of Mountain View, California owns + the copyright and has design patents pending on many of the icons. + AT&T is the owner of the OPEN LOOK trademark associated with the + materials on this tape. Users and possessors of this source code + are hereby granted a nonexclusive, royalty-free copyright and + design patent license to use this code in individual and + commercial software. A royalty-free, nonexclusive trademark + license to refer to the code and output as "OPEN LOOK" compatible + is available from AT&T if, and only if, the appearance of the + icons or glyphs is not changed in any manner except as absolutely + necessary to accommodate the standard resolution of the screen or + other output device, the code and output is not changed except as + authorized herein, and the code and output is validated by AT&T. + Bigelow & Holmes is the owner of the Lucida (R) trademark for the + fonts and bit-mapped images associated with the materials on this + tape. Users are granted a royalty-free, nonexclusive license to use + the trademark only to identify the fonts and bit-mapped images if, + and only if, the fonts and bit-mapped images are not modified in any + way by the user. + + Any use of this source code must include, in the user documentation + and internal comments to the code, notices to the end user as + follows: + + (c) Copyright 1989 Sun Microsystems, Inc. Sun design patents + pending in the U.S. and foreign countries. OPEN LOOK is a + trademark of AT&T. Used by written permission of the owners. + + (c) Copyright Bigelow & Holmes 1986, 1985. Lucida is a registered + trademark of Bigelow & Holmes. Permission to use the Lucida + trademark is hereby granted only in association with the images + and fonts described in this file. + + SUN MICROSYSTEMS, INC., AT&T, AND BIGELOW & HOLMES + MAKE NO REPRESENTATIONS ABOUT THE SUITABILITY OF + THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" + WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. + SUN MICROSYSTEMS, INC., AT&T AND BIGELOW & HOLMES, + SEVERALLY AND INDIVIDUALLY, DISCLAIM ALL WARRANTIES + WITH REGARD TO THIS SOURCE CODE, INCLUDING ALL IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE. IN NO EVENT SHALL SUN MICROSYSTEMS, + INC., AT&T OR BIGELOW & HOLMES BE LIABLE FOR ANY + SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, + OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA + OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. diff --git a/options/license/McPhee-slideshow b/options/license/McPhee-slideshow new file mode 100644 index 0000000000000..0ddf7ba35065d --- /dev/null +++ b/options/license/McPhee-slideshow @@ -0,0 +1,6 @@ +Copyright 2001, Patrick TJ McPhee +everyone is welcome to use this code for any purpose, to modify it, and +to copy it in whole or in part for use in other macro sets, with the +conditions that this copyright notice be preserved with any significant +portion of the code, and that modifications to this file be clearly +marked. diff --git a/options/license/PADL b/options/license/PADL new file mode 100644 index 0000000000000..84ba0b4db99f0 --- /dev/null +++ b/options/license/PADL @@ -0,0 +1,6 @@ +Portions (C) Copyright PADL Software Pty Ltd. 1999 + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that this notice is preserved +and that due credit is given to PADL Software Pty Ltd. This software +is provided ``as is'' without express or implied warranty. diff --git a/options/license/SGI-OpenGL b/options/license/SGI-OpenGL new file mode 100644 index 0000000000000..2b4c542aa0325 --- /dev/null +++ b/options/license/SGI-OpenGL @@ -0,0 +1,34 @@ +(c) Copyright 1993, Silicon Graphics, Inc. +ALL RIGHTS RESERVED +Permission to use, copy, modify, and distribute this software for +any purpose and without fee is hereby granted, provided that the above +copyright notice appear in all copies and that both the copyright notice +and this permission notice appear in supporting documentation, and that +the name of Silicon Graphics, Inc. not be used in advertising +or publicity pertaining to distribution of the software without specific, +written prior permission. + +THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU "AS-IS" +AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR OTHERWISE, +INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY OR +FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE ELSE FOR ANY DIRECT, +SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY +KIND, OR ANY DAMAGES WHATSOEVER, INCLUDING WITHOUT LIMITATION, +LOSS OF PROFIT, LOSS OF USE, SAVINGS OR REVENUE, OR THE CLAIMS OF +THIRD PARTIES, WHETHER OR NOT SILICON GRAPHICS, INC. HAS BEEN +ADVISED OF THE POSSIBILITY OF SUCH LOSS, HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE +POSSESSION, USE OR PERFORMANCE OF THIS SOFTWARE. + +US Government Users Restricted Rights +Use, duplication, or disclosure by the Government is subject to +restrictions set forth in FAR 52.227.19(c)(2) or subparagraph +(c)(1)(ii) of the Rights in Technical Data and Computer Software +clause at DFARS 252.227-7013 and/or in similar or successor +clauses in the FAR or the DOD or NASA FAR Supplement. +Unpublished-- rights reserved under the copyright laws of the +United States. Contractor/manufacturer is Silicon Graphics, +Inc., 2011 N. Shoreline Blvd., Mountain View, CA 94039-7311. + +OpenGL(TM) is a trademark of Silicon Graphics, Inc. diff --git a/options/license/UBDL-exception b/options/license/UBDL-exception new file mode 100644 index 0000000000000..780ddcd775ab2 --- /dev/null +++ b/options/license/UBDL-exception @@ -0,0 +1,59 @@ +UNMODIFIED BINARY DISTRIBUTION LICENCE + + +PREAMBLE + +The GNU General Public License provides a legal guarantee that +software covered by it remains free (in the sense of freedom, not +price). It achieves this guarantee by imposing obligations on anyone +who chooses to distribute the software. + +Some of these obligations may be seen as unnecessarily burdensome. In +particular, when the source code for the software is already publicly +and freely available, there is minimal value in imposing upon each +distributor the obligation to provide the complete source code (or an +equivalent written offer to provide the complete source code). + +This Licence allows for the distribution of unmodified binaries built +from publicly available source code, without imposing the obligations +of the GNU General Public License upon anyone who chooses to +distribute only the unmodified binaries built from that source code. + +The extra permissions granted by this Licence apply only to unmodified +binaries built from source code which has already been made available +to the public in accordance with the terms of the GNU General Public +Licence. Nothing in this Licence allows for the creation of +closed-source modified versions of the Program. Any modified versions +of the Program are subject to the usual terms and conditions of the +GNU General Public License. + + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +This Licence applies to any Program or other work which contains a +notice placed by the copyright holder saying it may be distributed +under the terms of this Unmodified Binary Distribution Licence. All +terms used in the text of this Licence are to be interpreted as they +are used in version 2 of the GNU General Public License as published +by the Free Software Foundation. + +If you have made this Program available to the public in both source +code and executable form in accordance with the terms of the GNU +General Public License as published by the Free Software Foundation; +either version 2 of the License, or (at your option) any later +version, then you are hereby granted an additional permission to use, +copy, and distribute the unmodified executable form of this Program +(the "Unmodified Binary") without restriction, including the right to +permit persons to whom the Unmodified Binary is furnished to do +likewise, subject to the following conditions: + +- when started running, the Program must display an announcement which + includes the details of your existing publication of the Program + made in accordance with the terms of the GNU General Public License. + For example, the Program could display the URL of the publicly + available source code from which the Unmodified Binary was built. + +- when exercising your right to grant permissions under this Licence, + you do not need to refer directly to the text of this Licence, but + you may not grant permissions beyond those granted to you by this + Licence. diff --git a/options/license/fwlw b/options/license/fwlw new file mode 100644 index 0000000000000..472a85a56449e --- /dev/null +++ b/options/license/fwlw @@ -0,0 +1,5 @@ +Copyright (C) 1993,1995 by Donald Arseneau +Vancouver, Canada, email asnd@triumf.ca + +This software package may be freely used, transmitted, reproduced, or modified provided that +this notice is left intact. diff --git a/options/license/lsof b/options/license/lsof new file mode 100644 index 0000000000000..279721a90a600 --- /dev/null +++ b/options/license/lsof @@ -0,0 +1,26 @@ +Copyright 2002 Purdue Research Foundation, West Lafayette, +Indiana 47907. All rights reserved. + +Written by Victor A. Abell + +This software is not subject to any license of the American +Telephone and Telegraph Company or the Regents of the +University of California. + +Permission is granted to anyone to use this software for +any purpose on any computer system, and to alter it and +redistribute it freely, subject to the following +restrictions: + +1. Neither the authors nor Purdue University are responsible + for any consequences of the use of this software. + +2. The origin of this software must not be misrepresented, + either by explicit claim or by omission. Credit to the + authors and Purdue University must appear in documentation + and sources. + +3. Altered versions must be plainly marked as such, and must + not be misrepresented as being the original software. + +4. This notice may not be removed or altered. diff --git a/options/license/magaz b/options/license/magaz new file mode 100644 index 0000000000000..34d033c03eb11 --- /dev/null +++ b/options/license/magaz @@ -0,0 +1,4 @@ +Copyright 1999-2011, Donald Arseneau, asnd@triumf.ca, Vancouver, Canada + +This software may be freely used, transmitted, reproduced, or modified provided that +the copyright notice and this permission is retained. diff --git a/options/license/python-ldap b/options/license/python-ldap new file mode 100644 index 0000000000000..733e8cfc0affe --- /dev/null +++ b/options/license/python-ldap @@ -0,0 +1,10 @@ +The python-ldap package is distributed under Python-style license. + +Standard disclaimer: + This software is made available by the author(s) to the public for free + and "as is". All users of this free software are solely and entirely + responsible for their own choice and use of this software for their + own purposes. By using this software, each user agrees that the + author(s) shall not be liable for damages of any kind in relation to + its use or performance. The author(s) do not warrant that this software + is fit for any purpose. diff --git a/options/license/ssh-keyscan b/options/license/ssh-keyscan new file mode 100644 index 0000000000000..6c97472c1eb1c --- /dev/null +++ b/options/license/ssh-keyscan @@ -0,0 +1,5 @@ +* Copyright 1995, 1996 by David Mazieres . +* +* Modification and redistribution in source and binary forms is +* permitted provided that due credit is given to the author and the +* OpenBSD project by leaving this copyright notice intact. diff --git a/options/license/swrule b/options/license/swrule new file mode 100644 index 0000000000000..aebc5fd6d3d22 --- /dev/null +++ b/options/license/swrule @@ -0,0 +1 @@ +The style package is copyrighted but may be used and extended in any way, as long as a pointer to the original author is maintained. The author is not liable for any problem that may or may not result from using this package. Use at your own risk. diff --git a/options/license/ulem b/options/license/ulem new file mode 100644 index 0000000000000..ee49efe8dd275 --- /dev/null +++ b/options/license/ulem @@ -0,0 +1,4 @@ +Copyright 1989-2019 by Donald Arseneau (Vancouver, Canada, asnd@triumf.ca) + +This software may be freely transmitted, reproduced, or modified +for any purpose provided that this copyright notice is left intact. diff --git a/options/locale/locale_cs-CZ.ini b/options/locale/locale_cs-CZ.ini index 57c1635c1cd76..5cbed22187785 100644 --- a/options/locale/locale_cs-CZ.ini +++ b/options/locale/locale_cs-CZ.ini @@ -120,6 +120,8 @@ unpin=Odepnout artifacts=Artefakty +archived=Archivováno + concept_system_global=Globální concept_user_individual=Individuální concept_code_repository=Repozitář @@ -307,7 +309,6 @@ filter_by_team_repositories=Filtrovat podle repozitářů týmu feed_of=Kanál z „%s“ show_archived=Archivováno -archived=Archivováno show_both_archived_unarchived=Zobrazeny jak archivované tak nearchivované show_only_archived=Zobrazeny pouze archivované show_only_unarchived=Zobrazeny pouze nearchivované @@ -942,6 +943,7 @@ delete_preexisting_success=Smazány nepřijaté soubory v %s blame_prior=Zobrazit blame před touto změnou author_search_tooltip=Zobrazí maximálně 30 uživatelů + transfer.accept=Přijmout převod transfer.accept_desc=Převést do „%s“ transfer.reject=Odmítnout převod @@ -1823,7 +1825,6 @@ settings.mirror_settings.push_mirror.remote_url=URL vzdáleného Git repozitář settings.mirror_settings.push_mirror.add=Přidat zrcadlo pro nahrání settings.sync_mirror=Synchronizovat nyní -settings.mirror_sync_in_progress=Právě probíhá synchronizace zrcadla. Zkuste to za chvíli. settings.site=Webová stránka settings.update_settings=Aktualizovat nastavení settings.update_mirror_settings=Aktualizovat nastavení zrcadla @@ -2269,7 +2270,6 @@ release.add_tag=Vytvořit pouze značku release.tags_for=Značky pro %s branch.name=Jméno větve -branch.search=Hledat větve branch.delete_head=Smazat branch.delete_html=Smazat větev branch.create_branch=Vytvořit větev %s diff --git a/options/locale/locale_de-DE.ini b/options/locale/locale_de-DE.ini index e3ee15a873c36..c312c4728c3c5 100644 --- a/options/locale/locale_de-DE.ini +++ b/options/locale/locale_de-DE.ini @@ -123,6 +123,8 @@ unpin=Loslösen artifacts=Artefakte +archived=Archiviert + concept_system_global=Global concept_user_individual=Individuum concept_code_repository=Repository @@ -316,7 +318,6 @@ filter_by_team_repositories=Nach Team-Repositories filtern feed_of=`Feed von "%s"` show_archived=Archiviert -archived=Archiviert show_both_archived_unarchived=Archivierte und nicht archivierte anzeigen show_only_archived=Nur archivierte anzeigen show_only_unarchived=Nur nicht archivierte anzeigen @@ -967,6 +968,7 @@ delete_preexisting_success=Nicht übernommene Dateien in %s gelöscht blame_prior=Blame vor dieser Änderung anzeigen author_search_tooltip=Zeigt maximal 30 Benutzer + transfer.accept=Übertragung Akzeptieren transfer.accept_desc=`Übertragung nach "%s"` transfer.reject=Übertragung Ablehnen @@ -1892,7 +1894,6 @@ settings.mirror_settings.push_mirror.remote_url=URL zum Git-Remote-Repository settings.mirror_settings.push_mirror.add=Push-Mirror hinzufügen settings.sync_mirror=Jetzt synchronisieren -settings.mirror_sync_in_progress=Mirror-Synchronisierung wird zurzeit ausgeführt. Komm in ein paar Minuten zurück. settings.site=Webseite settings.update_settings=Einstellungen speichern settings.update_mirror_settings=Mirror-Einstellungen aktualisieren @@ -2375,7 +2376,6 @@ release.releases_for=Releases für %s release.tags_for=Tags für %s branch.name=Branchname -branch.search=Branches durchsuchen branch.already_exists=Ein Branch mit dem Namen "%s" existiert bereits. branch.delete_head=Löschen branch.delete=Branch "%s" löschen diff --git a/options/locale/locale_el-GR.ini b/options/locale/locale_el-GR.ini index 63cc1ca2e53de..c8c5ba368979f 100644 --- a/options/locale/locale_el-GR.ini +++ b/options/locale/locale_el-GR.ini @@ -120,6 +120,8 @@ unpin=Άφεση artifacts=Αντικείμενα +archived=Αρχειοθετήθηκε + concept_system_global=Γενικό concept_user_individual=Ατομικό concept_code_repository=Αποθετήριο @@ -290,6 +292,7 @@ invalid_password_algorithm=Μη έγκυρος αλγόριθμος κωδικο password_algorithm_helper=Ορίστε τον αλγόριθμο κατακερματισμού για το κωδικό πρόσβασης. Οι αλγόριθμοι διαφέρουν σε απαιτήσεις και αντοχή. Ο αλγόριθμος argon2 είναι αρκετά ασφαλής, αλλά χρησιμοποιεί πολλή μνήμη και μπορεί να είναι ακατάλληλος για μικρά συστήματα. enable_update_checker=Ενεργοποίηση Ελεγκτή Ενημερώσεων enable_update_checker_helper=Ελέγχει περιοδικά για νέες εκδόσεις κάνοντας σύνδεση στο gitea.io. +env_config_keys=Ρυθμίσεις Περιβάλλοντος [home] uname_holder=Όνομα Χρήστη ή Διεύθυνση Email @@ -307,7 +310,6 @@ filter_by_team_repositories=Φιλτράρισμα ανά αποθετήρια feed_of=`Τροφοδοσία του "%s"` show_archived=Αρχειοθετήθηκε -archived=Αρχειοθετήθηκε show_both_archived_unarchived=Εμφάνιση και αρχειοθετημένων και μη αρχειοθετημένων show_only_archived=Εμφάνιση μόνο αρχειοθετημένων show_only_unarchived=Εμφάνιση μόνο μη αρχειοθετημένων @@ -955,6 +957,7 @@ delete_preexisting_success=Διαγράφηκαν τα μη υιοθετημέν blame_prior=Προβολή ευθύνης πριν από αυτή την αλλαγή author_search_tooltip=Εμφάνιση το πολύ 30 χρηστών + transfer.accept=Αποδοχή Μεταφοράς transfer.accept_desc=`Μεταφορά στο "%s"` transfer.reject=Απόρριψη Μεταφοράς @@ -1874,7 +1877,6 @@ settings.mirror_settings.push_mirror.remote_url=URL Απομακρυσμένου settings.mirror_settings.push_mirror.add=Προσθήκη Είδωλου Push settings.sync_mirror=Συγχρονισμός Τώρα -settings.mirror_sync_in_progress=Ο συγχρονισμός ειδώλου είναι σε εξέλιξη. Ελέγξτε ξανά σε λίγο. settings.site=Ιστοσελίδα settings.update_settings=Ενημέρωση Ρυθμίσεων settings.update_mirror_settings=Ενημέρωση Ρυθμίσεων Ειδώλου @@ -2357,7 +2359,6 @@ release.releases_for=Κυκλοφορίες για %s release.tags_for=Ετικέτες για %s branch.name=Όνομα Κλάδου -branch.search=Αναζήτηση κλάδων branch.already_exists=Ήδη υπάρχει ένας κλάδος με το όνομα "%s". branch.delete_head=Διαγραφή branch.delete=`Διαγραφή του Κλάδου "%s"` diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index de25392d884cc..4420af1588d61 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -97,6 +97,7 @@ locked = Locked copy = Copy copy_url = Copy URL +copy_hash = Copy hash copy_content = Copy content copy_branch = Copy branch name copy_success = Copied! @@ -112,6 +113,7 @@ step2 = Step 2: error = Error error404 = The page you are trying to reach either does not exist or you are not authorized to view it. +go_back = Go Back never = Never unknown = Unknown @@ -943,6 +945,8 @@ fork_from = Fork From already_forked = You've already forked %s fork_to_different_account = Fork to a different account fork_visibility_helper = The visibility of a forked repository cannot be changed. +fork_branch = Branch to be cloned to the fork +all_branches = All branches fork_no_valid_owners = This repository can not be forked because there are no valid owners. use_template = Use this template clone_in_vsc = Clone in VS Code @@ -1012,6 +1016,10 @@ blame.ignore_revs = Ignoring revisions in .git-blame-ignore-revs.git-blame-ignore-revs. author_search_tooltip = Shows a maximum of 30 users +tree_path_not_found_commit = Path %[1]s doesn't exist in commit %[2]s +tree_path_not_found_branch = Path %[1]s doesn't exist in branch %[2]s +tree_path_not_found_tag = Path %[1]s doesn't exist in tag %[2]s + transfer.accept = Accept Transfer transfer.accept_desc = Transfer to "%s" transfer.reject = Reject Transfer @@ -1276,6 +1284,7 @@ commits.signed_by_untrusted_user = Signed by untrusted user commits.signed_by_untrusted_user_unmatched = Signed by untrusted user who does not match committer commits.gpg_key_id = GPG Key ID commits.ssh_key_fingerprint = SSH Key Fingerprint +commits.view_path=View at this point in history commit.operations = Operations commit.revert = Revert @@ -1512,7 +1521,8 @@ issues.label_description = Description issues.label_color = Color issues.label_exclusive = Exclusive issues.label_archive = Archive Label -issues.label_archive_tooltip= Archived labels are excluded from the label search when applying labels to an issue. Existing labels on issues remain unaffected, allowing you to retire obsolete labels without losing information. +issues.label_archived_filter = Show archived labels +issues.label_archive_tooltip = Archived labels are excluded by default from the suggestions when searching by label. issues.label_exclusive_desc = Name the label scope/item to make it mutually exclusive with other scope/ labels. issues.label_exclusive_warning = Any conflicting scoped labels will be removed when editing the labels of an issue or pull request. issues.label_count = %d labels @@ -1999,7 +2009,8 @@ settings.mirror_settings.push_mirror.add = Add Push Mirror settings.mirror_settings.push_mirror.edit_sync_time = Edit mirror sync interval settings.sync_mirror = Synchronize Now -settings.mirror_sync_in_progress = Mirror synchronization is in progress. Check back in a minute. +settings.pull_mirror_sync_in_progress = Pulling changes from the remote %s at the moment. +settings.push_mirror_sync_in_progress = Pushing changes to the remote %s at the moment. settings.site = Website settings.update_settings = Update Settings settings.update_mirror_settings = Update Mirror Settings @@ -2300,6 +2311,7 @@ settings.dismiss_stale_approvals_desc = When new commits that change the content settings.require_signed_commits = Require Signed Commits settings.require_signed_commits_desc = Reject pushes to this branch if they are unsigned or unverifiable. settings.protect_branch_name_pattern = Protected Branch Name Pattern +settings.protect_branch_name_pattern_desc = "Protected branch name patterns. See the documentation for pattern syntax. Examples: main, release/**" settings.protect_patterns = Patterns settings.protect_protected_file_patterns = "Protected file patterns (separated using semicolon ';'):" settings.protect_protected_file_patterns_desc = "Protected files are not allowed to be changed directly even if user has rights to add, edit, or delete files in this branch. Multiple patterns can be separated using semicolon (';'). See github.com/gobwas/glob documentation for pattern syntax. Examples: .drone.yml, /docs/**/*.txt." @@ -3145,7 +3157,6 @@ config.access_log_mode = Access Log Mode config.access_log_template = Access Log Template config.xorm_log_sql = Log SQL -config.get_setting_failed = Get setting %s failed config.set_setting_failed = Set setting %s failed monitor.stats = Stats diff --git a/options/locale/locale_es-ES.ini b/options/locale/locale_es-ES.ini index c8ff04c1574a4..89e8937da328b 100644 --- a/options/locale/locale_es-ES.ini +++ b/options/locale/locale_es-ES.ini @@ -109,6 +109,8 @@ rss_feed=Fuentes RSS +archived=Archivado + concept_code_repository=Repositorio concept_user_organization=Organización @@ -263,7 +265,6 @@ filter_by_team_repositories=Filtrar por repositorios de equipo feed_of=`Suministro de noticias de "%s"` show_archived=Archivado -archived=Archivado show_both_archived_unarchived=Mostrar respositorios archivados y desarchivados show_only_archived=Mostrar sólo repositorios archivados show_only_unarchived=Mostrar sólo repositorios desarchivados @@ -862,6 +863,7 @@ delete_preexisting_content=Eliminar archivos en %s delete_preexisting_success=Eliminó archivos no adoptados en %s blame_prior=Ver la culpa antes de este cambio + transfer.accept=Aceptar transferencia transfer.accept_desc=`Transferir a "%s"` transfer.reject=Rechazar transferencia @@ -1679,7 +1681,6 @@ settings.mirror_settings.push_mirror.remote_url=URL del repositorio remoto de Gi settings.mirror_settings.push_mirror.add=Añadir Réplica de Push settings.sync_mirror=Sincronizar ahora -settings.mirror_sync_in_progress=La sincronización del repositorio replicado está en curso. Vuelva a intentarlo más tarde. settings.site=Sitio web settings.update_settings=Actualizar configuración settings.branches.update_default_branch=Actualizar rama por defecto @@ -2116,7 +2117,6 @@ release.add_tag_msg=Utilice el título y el contenido de la liberación como men release.add_tag=Crear solo etiqueta branch.name=Nombre de la rama -branch.search=Buscar ramas branch.delete_head=Eliminar branch.delete_html=Eliminar rama branch.create_branch=Crear rama %s diff --git a/options/locale/locale_fa-IR.ini b/options/locale/locale_fa-IR.ini index 46601a8cc703d..94f1ff0b88ea0 100644 --- a/options/locale/locale_fa-IR.ini +++ b/options/locale/locale_fa-IR.ini @@ -94,6 +94,8 @@ never=هرگز +archived=بایگانی شده + concept_code_repository=مخزن concept_user_organization=سازمان @@ -240,7 +242,6 @@ filter_by_team_repositories=فیلتر کردن با مخازن تیم‌ها feed_of=`خوراک از "%s"` show_archived=بایگانی شده -archived=بایگانی شده show_both_archived_unarchived=نمایش دادن موارد بایگانی شده و غیر بایگانی نشده show_only_archived=نمایش دادن موارد بایگانی شده show_only_unarchived=نمایش دادن موارد بایگانی نشده @@ -790,6 +791,7 @@ delete_preexisting_content=حذف فایلهای موجود در %s delete_preexisting_success=فایل های تصویب نشده پاک شده در %s blame_prior=قبل از این تغییر، سرزنش را مشاهده کنید + transfer.accept=تایید انتقال transfer.accept_desc=انتقال به %s transfer.reject=رد انتقال @@ -1535,7 +1537,6 @@ settings.mirror_settings.push_mirror.remote_url=Git Remote Repository URL settings.mirror_settings.push_mirror.add=اضافه کردن Push Mirror settings.sync_mirror=همگام سازی کن -settings.mirror_sync_in_progress=همگام سازی قرینه در حالت پردازش است. یک دقیقه دیگر مجددا بررسی کنید. settings.site=تارنما settings.update_settings=به‌ روزرسانی تنظیمات settings.branches.update_default_branch=بروزرسانی شاخه پیش فرض @@ -1934,7 +1935,6 @@ release.add_tag_msg=از عنوان و محتوای انتشار به عنوان release.add_tag=فقط تگ ایجاد کنید branch.name=نام شاخه -branch.search=جستجوی شاخه ها branch.delete_head=حذف branch.delete_html=حذف شاخه branch.create_branch=ساختن شاخه %s diff --git a/options/locale/locale_fi-FI.ini b/options/locale/locale_fi-FI.ini index cce13fb88a389..640739d5e73fc 100644 --- a/options/locale/locale_fi-FI.ini +++ b/options/locale/locale_fi-FI.ini @@ -108,6 +108,8 @@ rss_feed=RSS-syöte +archived=Arkistoidut + concept_code_repository=Repo concept_user_organization=Organisaatio @@ -250,7 +252,6 @@ filter_by_team_repositories=Suodata tiimin repojen mukaan feed_of=`Syöte "%s"` show_archived=Arkistoidut -archived=Arkistoidut show_both_archived_unarchived=Näytetään arkistoidut ja arkistoimattomat show_only_archived=Näytetään vain arkistoidut show_only_unarchived=Näytetään vain arkistoimattomat @@ -680,6 +681,7 @@ forks=Haarat delete_preexisting_label=Poista + desc.private=Yksityinen desc.public=Julkinen desc.private_template=Yksityinen malli diff --git a/options/locale/locale_fr-FR.ini b/options/locale/locale_fr-FR.ini index 69787e9ebcb57..355b76639fca4 100644 --- a/options/locale/locale_fr-FR.ini +++ b/options/locale/locale_fr-FR.ini @@ -123,6 +123,8 @@ unpin=Désépingler artifacts=Artefacts +archived=Archivé + concept_system_global=Global concept_user_individual=Individuel concept_code_repository=Dépôt @@ -316,7 +318,6 @@ filter_by_team_repositories=Dépôts filtrés par équipe feed_of=Flux de « %s » show_archived=Archivé -archived=Archivé show_both_archived_unarchived=Afficher à la fois archivé et non archivé show_only_archived=Afficher uniquement les archivés show_only_unarchived=Afficher uniquement les non archivés @@ -378,6 +379,7 @@ email_not_associate=L’adresse courriel n’est associée à aucun compte. send_reset_mail=Envoyer un courriel de récupération du compte reset_password=Récupération du compte invalid_code=Votre code de confirmation est invalide ou a expiré. +invalid_code_forgot_password=Votre code de confirmation est invalide ou a expiré. Cliquez ici pour démarrer une nouvelle session. invalid_password=Votre mot de passe ne correspond pas à celui utilisé pour créer le compte. reset_password_helper=Récupérer un compte reset_password_wrong_user=Vous êtes connecté en tant que %s, mais le lien de récupération est pour %s @@ -679,6 +681,7 @@ choose_new_avatar=Sélectionner un nouvel avatar update_avatar=Modifier l’avatar delete_current_avatar=Supprimer l'avatar actuel uploaded_avatar_not_a_image=Le fichier téléchargé n'est pas une image. +uploaded_avatar_is_too_big=La taille du fichier téléversé (%d Kio) dépasse la taille maximale (%d Kio). update_avatar_success=Votre avatar a été mis à jour. update_user_avatar_success=L'avatar de l'utilisateur a été mis à jour. @@ -968,6 +971,7 @@ trust_model_helper_collaborator_committer=Collaborateur et Auteur : ne se fier q trust_model_helper_default=Par défaut : valeur configurée par défaut pour cette instance Gitea create_repo=Créer un dépôt default_branch=Branche par défaut +default_branch_label=défaut default_branch_helper=La branche par défaut est la branche de base pour les demandes d'ajout et les révisions de code. mirror_prune=Purger mirror_prune_desc=Supprimer les références externes obsolètes @@ -1005,6 +1009,7 @@ delete_preexisting_success=Fichiers dépossédés supprimés dans %s. blame_prior=Voir le blame avant cette modification author_search_tooltip=Affiche un maximum de 30 utilisateurs + transfer.accept=Accepter le transfert transfer.accept_desc=`Transférer à "%s"` transfer.reject=Refuser le transfert @@ -1479,8 +1484,17 @@ issues.ref_closed_from=`a fermé ce ticket %[4]s a rouvert ce ticket %[4]s %[2]s.` issues.ref_from=`de %[1]s` issues.author=Auteur +issues.author_helper=Cet utilisateur est l’auteur. issues.role.owner=Propriétaire +issues.role.owner_helper=Cet utilisateur est le propriétaire de ce dépôt. issues.role.member=Membre +issues.role.member_helper=Cet utilisateur est membre de l’organisation propriétaire de ce dépôt. +issues.role.collaborator=Collaborateur +issues.role.collaborator_helper=Cet utilisateur a été invité à collaborer sur le dépôt. +issues.role.first_time_contributor=Première contribution +issues.role.first_time_contributor_helper=C'est la première contribution de cet utilisateur au dépôt. +issues.role.contributor=Contributeur +issues.role.contributor_helper=Cet utilisateur a déjà des révisions dans le dépôt. issues.re_request_review=Redemander une évaluation issues.is_stale=Cette demande d’ajout a été corrigée depuis sa dernière évaluation. issues.remove_request_review=Retirer la demande d’évaluation @@ -1496,7 +1510,6 @@ issues.label_description=Description de l’étiquette issues.label_color=Couleur de l'étiquette issues.label_exclusive=Exclusif issues.label_archive=Archivé -issues.label_archive_tooltip=En archivant une étiquette, celle-ci devient inutilisable. Cependant, pour ne pas dégrader les tickets ou demandes d'ajouts, de telles étiquettes ne leur sont pas retirée. issues.label_exclusive_desc=Remarque: Pour rendre des étiquettes mutuellement exclusives, préfixez leur nom avec une portée de votre choix de la façon suivante : portée/étiquette issues.label_exclusive_warning=Toute étiquette d'une portée en conflit sera retirée lors de la modification des étiquettes d’un ticket ou d’une demande d’ajout. issues.label_count=%d étiquettes @@ -1818,6 +1831,8 @@ milestones.edit_success=Le jalon "%s" a été mis à jour. milestones.deletion=Supprimer un Jalon milestones.deletion_desc=Supprimer un jalon le retire de tous les tickets. Continuer ? milestones.deletion_success=Le jalon a été supprimé. +milestones.filter_sort.earliest_due_data=Date d’échéance la plus ancienne +milestones.filter_sort.latest_due_date=Date d’échéance la plus récente milestones.filter_sort.least_complete=Le moins complété milestones.filter_sort.most_complete=Le plus complété milestones.filter_sort.most_issues=Le plus de tickets @@ -1980,7 +1995,6 @@ settings.mirror_settings.push_mirror.add=Ajouter un miroir push settings.mirror_settings.push_mirror.edit_sync_time=Modifier la fréquence de synchronisation du miroir settings.sync_mirror=Synchroniser maintenant -settings.mirror_sync_in_progress=La synchronisation est en cours. Revenez dans une minute. settings.site=Site Web settings.update_settings=Valider settings.update_mirror_settings=Mettre à jour les paramètres du miroir @@ -2315,6 +2329,7 @@ settings.tags.protection.allowed.teams=Équipes autorisées settings.tags.protection.allowed.noone=Personne settings.tags.protection.create=Protéger l'étiquette settings.tags.protection.none=Il n'y a pas d'étiquettes protégées. +settings.tags.protection.pattern.description=Vous pouvez utiliser soit un nom unique, soit un motif de glob ou une expresion régulière qui correspondront à plusieurs étiquettes. Pour plus d'informations, veuillez vous reporter au guide sur les étiquettes protégées. settings.bot_token=Jeton de Bot settings.chat_id=ID de conversation settings.thread_id=ID du fil @@ -2473,7 +2488,6 @@ release.releases_for=Versions pour %s release.tags_for=Étiquettes pour %s branch.name=Nom de la branche -branch.search=Rechercher des branches branch.already_exists=Une branche nommée "%s" existe déjà. branch.delete_head=Supprimer branch.delete=`Supprimer la branche "%s"` @@ -2712,6 +2726,7 @@ dashboard.reinit_missing_repos=Réinitialiser tous les dépôts Git manquants po dashboard.sync_external_users=Synchroniser les données de l’utilisateur externe dashboard.cleanup_hook_task_table=Nettoyer la table hook_task dashboard.cleanup_packages=Nettoyer des paquets expirés +dashboard.cleanup_actions=Nettoyer les journaux et les artefacts des actions obsolètes dashboard.server_uptime=Uptime du serveur dashboard.current_goroutine=Goroutines actuelles dashboard.current_memory_usage=Utilisation Mémoire actuelle @@ -2749,7 +2764,9 @@ dashboard.gc_lfs=Épousseter les métaobjets LFS dashboard.stop_zombie_tasks=Arrêter les tâches zombies dashboard.stop_endless_tasks=Arrêter les tâches sans fin dashboard.cancel_abandoned_jobs=Annuler les jobs abandonnés +dashboard.start_schedule_tasks=Démarrer les tâches planifiées dashboard.sync_branch.started=Début de la synchronisation des branches +dashboard.rebuild_issue_indexer=Reconstruire l’indexeur des tickets users.user_manage_panel=Gestion du compte utilisateur users.new_account=Créer un compte @@ -2758,6 +2775,9 @@ users.full_name=Non Complet users.activated=Activé users.admin=Administrateur users.restricted=Restreint +users.reserved=Réservé +users.bot=Robot +users.remote=Distant users.2fa=2FA users.repos=Dépôts users.created=Créés @@ -2804,6 +2824,7 @@ users.list_status_filter.is_prohibit_login=Interdit de connexion users.list_status_filter.not_prohibit_login=Autorisé à se connecter users.list_status_filter.is_2fa_enabled=2FA Activé users.list_status_filter.not_2fa_enabled=2FA désactivé +users.details=Informations de l’utilisateur emails.email_manage_panel=Gestion des emails des utilisateurs emails.primary=Principale @@ -2959,6 +2980,7 @@ auths.tip.google_plus=Obtenez des identifiants OAuth2 sur la console API de Goog auths.tip.openid_connect=Utilisez l'URL de découvert OpenID (/.well-known/openid-configuration) pour spécifier les points d'accès auths.tip.twitter=Rendez-vous sur https://dev.twitter.com/apps, créez une application et assurez-vous que l'option "Autoriser l'application à être utilisée avec Twitter Connect" est activée auths.tip.discord=Enregistrer une nouvelle application sur https://discordapp.com/developers/applications/me +auths.tip.gitea=Enregistrez une nouvelle application OAuth2. Le guide peut être trouvé sur https://docs.gitea.com/development/oauth2-provider auths.tip.yandex=`Créez une nouvelle application sur https://oauth.yandex.com/client/new. Sélectionnez les autorisations suivantes dans la section "Yandex API passport" : "Accès à l'adresse e-mail", "Accès à l'avatar de l'utilisateur" et "Accès au nom d'utilisateur, prénom et prénom, genre"` auths.tip.mastodon=Entrez une URL d'instance personnalisée pour l'instance mastodon avec laquelle vous voulez vous authentifier (ou utiliser celle par défaut) auths.edit=Mettre à jour la source d'authentification @@ -3140,8 +3162,10 @@ monitor.queue.name=Nom monitor.queue.type=Type monitor.queue.exemplar=Type d'exemple monitor.queue.numberworkers=Nombre de processus +monitor.queue.activeworkers=Processus actifs monitor.queue.maxnumberworkers=Nombre maximale de processus monitor.queue.numberinqueue=Position dans la queue +monitor.queue.review_add=Examiner / ajouter des processus monitor.queue.settings.title=Paramètres du réservoir monitor.queue.settings.desc=Les bassins croissent proportionnellement au besoin de leurs exécuteurs. monitor.queue.settings.maxnumberworkers=Nombre maximale de processus @@ -3476,6 +3500,7 @@ runners.reset_registration_token_success=Le jeton d’inscription de l’exécut runs.all_workflows=Tous les flux de travail runs.commit=Révision +runs.scheduled=Planifié runs.pushed_by=soumis par runs.invalid_workflow_helper=La configuration du flux de travail est invalide. Veuillez vérifier votre fichier %s. runs.no_matching_runner_helper=Aucun exécuteur correspondant : %s @@ -3490,6 +3515,7 @@ workflow.disable=Désactiver le flux de travail workflow.disable_success=Le flux de travail « %s » a bien été désactivé. workflow.enable=Activer le flux de travail workflow.enable_success=Le flux de travail « %s » a bien été activé. +workflow.disabled=Le flux de travail est désactivé. need_approval_desc=Besoin d’approbation pour exécuter des flux de travail pour une demande d’ajout de bifurcation. diff --git a/options/locale/locale_hu-HU.ini b/options/locale/locale_hu-HU.ini index b53d34f1a2f83..c22a049817671 100644 --- a/options/locale/locale_hu-HU.ini +++ b/options/locale/locale_hu-HU.ini @@ -84,6 +84,8 @@ error404=Az elérni kívánt oldal vagy nem létezik, vagy %s létrehozása diff --git a/options/locale/locale_id-ID.ini b/options/locale/locale_id-ID.ini index 020ad59cedb29..a5efde6d07b82 100644 --- a/options/locale/locale_id-ID.ini +++ b/options/locale/locale_id-ID.ini @@ -77,6 +77,7 @@ loading=Memuat… + concept_code_repository=Repositori @@ -531,6 +532,7 @@ unit_disabled=Administrator web menonaktifkan bagian repositori ini. delete_preexisting_label=Hapus + desc.private=Pribadi desc.public_template=Contoh @@ -943,7 +945,6 @@ release.save_draft=Simpan Draft release.deletion_success=Rilis ini telah dihapus. release.downloads=Unduhan -branch.search=Cari cabang branch.delete_head=Hapus branch.delete_html=Hapus cabang branch.create_branch=Membuat cabang %s diff --git a/options/locale/locale_is-IS.ini b/options/locale/locale_is-IS.ini index d0031dd65508d..28ce5ae7f7ac7 100644 --- a/options/locale/locale_is-IS.ini +++ b/options/locale/locale_is-IS.ini @@ -105,6 +105,8 @@ never=Aldrei +archived=Safnvistað + concept_code_repository=Hugbúnaðarsafn @@ -229,7 +231,6 @@ search_repos=Finna hugbúnaðarsafn… filter=Aðrar Síur show_archived=Safnvistað -archived=Safnvistað show_private=Einka show_only_private=Að sýna aðeins einka @@ -608,6 +609,7 @@ delete_preexisting_label=Eyða delete_preexisting_content=Eyða skrám í %s + desc.private=Einka desc.public=Opinbert desc.private_template=Einka sniðmát diff --git a/options/locale/locale_it-IT.ini b/options/locale/locale_it-IT.ini index 95a3f5dee4cbc..825d858cd38e6 100644 --- a/options/locale/locale_it-IT.ini +++ b/options/locale/locale_it-IT.ini @@ -109,6 +109,8 @@ rss_feed=Feed RSS +archived=Archiviato + concept_code_repository=Repository concept_user_organization=Organizzazione @@ -261,7 +263,6 @@ filter_by_team_repositories=Filtra per repository del team feed_of=`Feed di "%s"` show_archived=Archiviato -archived=Archiviato show_both_archived_unarchived=Mostra sia gli archiviati che i non archiviati show_only_archived=Visualizzazione solo archiviati show_only_unarchived=Visualizzazione solo non archiviati @@ -849,6 +850,7 @@ delete_preexisting_content=Elimina file in %s delete_preexisting_success=Eliminato file non adottati in %s blame_prior=Visualizza la colpa prima di questa modifica + transfer.accept=Accetta trasferimento transfer.accept_desc=`Trasferisci a "%s"` transfer.reject=Rifiuta trasferimento @@ -1661,7 +1663,6 @@ settings.mirror_settings.push_mirror.remote_url=Url Del Repository Remoto Git settings.mirror_settings.push_mirror.add=Aggiungi Push Mirror settings.sync_mirror=Sincronizza ora -settings.mirror_sync_in_progress=Sincronizzazione del mirror in corso. Torna tra qualche minuto. settings.site=Sito web settings.update_settings=Aggiorna Impostazioni settings.branches.update_default_branch=Aggiorna Ramo Predefinito @@ -2096,7 +2097,6 @@ release.add_tag_msg=Utilizzare il titolo e il contenuto del rilascio come messag release.add_tag=Crea Solo Branch branch.name=Nome branch -branch.search=Cerca branch branch.delete_head=Elimina branch.delete_html=Elimina branch branch.create_branch=Crea branch %s diff --git a/options/locale/locale_ja-JP.ini b/options/locale/locale_ja-JP.ini index 940ff5116818e..1ea9c4ebb2797 100644 --- a/options/locale/locale_ja-JP.ini +++ b/options/locale/locale_ja-JP.ini @@ -123,6 +123,8 @@ unpin=ピン留め解除 artifacts=成果物 +archived=アーカイブ + concept_system_global=グローバル concept_user_individual=個人 concept_code_repository=リポジトリ @@ -317,7 +319,6 @@ filter_by_team_repositories=チームリポジトリで絞り込み feed_of=`"%s" のフィード` show_archived=アーカイブ -archived=アーカイブ show_both_archived_unarchived=アーカイブと非アーカイブの両方を表示 show_only_archived=アーカイブのみ表示 show_only_unarchived=非アーカイブのみ表示 @@ -1009,6 +1010,7 @@ delete_preexisting_success=%s の未登録ファイルを削除しました blame_prior=この変更より前のBlameを表示 author_search_tooltip=最大30人までのユーザーを表示 + transfer.accept=移転を承認 transfer.accept_desc=`"%s" に移転` transfer.reject=移転を拒否 @@ -1156,6 +1158,10 @@ file_view_rendered=レンダリング表示 file_view_raw=Rawデータを見る file_permalink=パーマリンク file_too_large=このファイルは大きすぎるため、表示できません。 +invisible_runes_header=このファイルには不可視のUnicode文字が含まれています +invisible_runes_description=このファイルには人間が識別できない不可視のUnicode文字が含まれており、コンピューターによって特殊な処理が行われる可能性があります。 それが意図的なものと考えられる場合は、この警告を無視して構いません。 不可視文字を表示するにはエスケープボタンを使用します。 +ambiguous_runes_header=このファイルには曖昧(ambiguous)なUnicode文字が含まれています +ambiguous_runes_description=このファイルには、他の文字と見間違える可能性があるUnicode文字が含まれています。 それが意図的なものと考えられる場合は、この警告を無視して構いません。 それらの文字を表示するにはエスケープボタンを使用します。 invisible_runes_line=`この行には不可視のUnicode文字があります` ambiguous_runes_line=`この行には曖昧(ambiguous)なUnicode文字があります` ambiguous_character=`%[1]c [U+%04[1]X] は %[2]c [U+%04[2]X] と混同するおそれがあります` @@ -1168,11 +1174,15 @@ video_not_supported_in_browser=このブラウザはHTML5のvideoタグをサポ audio_not_supported_in_browser=このブラウザーはHTML5のaudioタグをサポートしていません。 stored_lfs=Git LFSで保管されています symbolic_link=シンボリック リンク +executable_file=実行ファイル commit_graph=コミットグラフ commit_graph.select=ブランチを選択 commit_graph.hide_pr_refs=プルリクエストを非表示 commit_graph.monochrome=モノクロ commit_graph.color=カラー +commit.contained_in=このコミットが含まれているのは: +commit.contained_in_default_branch=このコミットはデフォルトブランチに含まれています +commit.load_referencing_branches_and_tags=このコミットを参照しているブランチやタグを取得 blame=Blame download_file=ファイルをダウンロード normal_view=通常表示 @@ -1392,6 +1402,7 @@ issues.delete_branch_at=`がブランチ %[1]s を削除 %[2]s` issues.filter_label=ラベル issues.filter_label_exclude=`ラベルで除外するには alt + click/enter` issues.filter_label_no_select=すべてのラベル +issues.filter_label_select_no_label=ラベルなし issues.filter_milestone=マイルストーン issues.filter_milestone_all=すべてのマイルストーン issues.filter_milestone_none=マイルストーンなし @@ -1446,6 +1457,7 @@ issues.next=次ページ issues.open_title=オープン issues.closed_title=クローズ issues.draft_title=ドラフト +issues.num_comments_1=%d件のコメント issues.num_comments=%d件のコメント issues.commented_at=`がコメント %s` issues.delete_comment_confirm=このコメントを削除してよろしいですか? @@ -1454,6 +1466,7 @@ issues.context.quote_reply=引用して返信 issues.context.reference_issue=新しいイシューから参照 issues.context.edit=編集 issues.context.delete=削除 +issues.no_content=説明はありません。 issues.close=イシューをクローズ issues.comment_pull_merged_at=がコミット %[1]s を %[2]s にマージ %[3]s issues.comment_manually_pull_merged_at=がコミット %[1]s を %[2]s に手動マージ %[3]s @@ -1497,6 +1510,7 @@ issues.label_title=名前 issues.label_description=説明 issues.label_color=カラー issues.label_exclusive=排他 +issues.label_archive=アーカイブ ラベル issues.label_exclusive_desc=ラベル名を スコープ/アイテム の形にすることで、他の スコープ/ ラベルと排他的になります。 issues.label_exclusive_warning=イシューやプルリクエストのラベル編集では、競合するスコープ付きラベルは解除されます。 issues.label_count=ラベル %d件 @@ -1983,7 +1997,6 @@ settings.mirror_settings.push_mirror.add=プッシュミラーを追加 settings.mirror_settings.push_mirror.edit_sync_time=ミラー同期の間隔を編集 settings.sync_mirror=今すぐ同期 -settings.mirror_sync_in_progress=ミラー同期を実行しています。 しばらくあとでまた確認してください。 settings.site=Webサイト settings.update_settings=設定を更新 settings.update_mirror_settings=ミラーリング設定を更新 @@ -2117,12 +2130,14 @@ settings.webhook_deletion_desc=Webhook設定と配信履歴が削除されます settings.webhook_deletion_success=Webhookを削除しました。 settings.webhook.test_delivery=テスト配信 settings.webhook.test_delivery_desc=ダミーのイベントでこのWebhookをテストします。 +settings.webhook.test_delivery_desc_disabled=このWebhookをダミーのイベントでテストするには、有効にしてください。 settings.webhook.request=リクエスト settings.webhook.response=レスポンス settings.webhook.headers=ヘッダー settings.webhook.payload=内容 settings.webhook.body=ボディ settings.webhook.replay.description=このWebhookを再実行します。 +settings.webhook.replay.description_disabled=このWebhookを再実行するには、有効にしてください。 settings.webhook.delivery.success=イベントを配信キューに追加しました。 配信履歴に表示されるまで数秒かかります。 settings.githooks_desc=GitのフックはGit自体が提供する仕組みです。 以下のフックファイルを編集するとカスタム処理を設定できます。 settings.githook_edit_desc=もしフックがアクティブではない場合はサンプルの内容が表示されます。 内容を空にするとフックが無効になります。 @@ -2282,6 +2297,7 @@ settings.dismiss_stale_approvals_desc=プルリクエストの内容を変える settings.require_signed_commits=コミット署名必須 settings.require_signed_commits_desc=署名されていない場合、または署名が検証できなかった場合は、このブランチへのプッシュを拒否します。 settings.protect_branch_name_pattern=保護ブランチ名のパターン +settings.protect_branch_name_pattern_desc=保護ブランチ名のパターン。書き方についてはドキュメント を参照してください。例: main, release/** settings.protect_patterns=パターン settings.protect_protected_file_patterns=保護されるファイルのパターン (セミコロン';'で区切る): settings.protect_protected_file_patterns_desc=保護されたファイルは、このブランチにファイルを追加・編集・削除する権限を持つユーザーであっても、直接変更することができなくなります。 セミコロン(';')で区切って複数のパターンを指定できます。 パターンの文法については github.com/gobwas/glob を参照してください。 例: .drone.yml, /docs/**/*.txt @@ -3490,6 +3506,7 @@ runners.status.idle=アイドル runners.status.active=稼働中 runners.status.offline=オフライン runners.version=バージョン +runners.reset_registration_token=登録トークンをリセット runners.reset_registration_token_success=ランナー登録トークンをリセットしました runs.all_workflows=すべてのワークフロー diff --git a/options/locale/locale_ko-KR.ini b/options/locale/locale_ko-KR.ini index b9fd36e83d8f2..d33bf0f850bc3 100644 --- a/options/locale/locale_ko-KR.ini +++ b/options/locale/locale_ko-KR.ini @@ -77,6 +77,7 @@ loading=불러오는 중... + concept_code_repository=저장소 concept_user_organization=조직 @@ -575,6 +576,7 @@ language_other=기타 delete_preexisting_label=삭제 + desc.private=비공개 desc.public_template=템플릿 @@ -969,7 +971,6 @@ settings.basic_settings=기본 설정 settings.mirror_settings=미러 설정 settings.sync_mirror=지금 동기화 -settings.mirror_sync_in_progress=미러 동기화 진행중입니다. 잠시 후 다시 확인해주십시오. settings.site=웹 사이트 settings.update_settings=설정 저장 settings.advanced_settings=고급 설정 @@ -1149,7 +1150,6 @@ release.tag_name_invalid=태그명이 올바르지 않습니다. release.downloads=다운로드 branch.name=브랜치명 -branch.search=브랜치 검색 branch.delete_head=삭제 branch.delete_html=브랜치 삭제 branch.create_branch=%s 브랜치 생성 diff --git a/options/locale/locale_lv-LV.ini b/options/locale/locale_lv-LV.ini index 2cc8085c18705..7b3722a8b119d 100644 --- a/options/locale/locale_lv-LV.ini +++ b/options/locale/locale_lv-LV.ini @@ -120,6 +120,8 @@ unpin=Atspraust artifacts=Artefakti +archived=Arhivētie + concept_system_global=Globāls concept_user_individual=Individuāls concept_code_repository=Repozitorijs @@ -307,7 +309,6 @@ filter_by_team_repositories=Filtrēt pēc komandas repozitorijiem feed_of=`"%s" plūsma` show_archived=Arhivētie -archived=Arhivētie show_both_archived_unarchived=Attēlot gan arhivētos, gan nearhivētos show_only_archived=Attēlot tikai arhivētos show_only_unarchived=Attēlot tikai nearhivētos @@ -955,6 +956,7 @@ delete_preexisting_success=Dzēst nepārņemtos failus direktorijā %s blame_prior=Aplūkot vainīgo par izmaiņām pirms šīs revīzijas author_search_tooltip=Tiks attēloti ne vairāk kā 30 lietotāji + transfer.accept=Apstiprināt īpašnieka maiņu transfer.accept_desc=`Mainīt īpašnieku uz "%s"` transfer.reject=Noraidīt īpašnieka maiņu @@ -1874,7 +1876,6 @@ settings.mirror_settings.push_mirror.remote_url=Git attālinātā repozitorija U settings.mirror_settings.push_mirror.add=Pievienot iesūtīšanas spoguli settings.sync_mirror=Sinhronizēt tagad -settings.mirror_sync_in_progress=Notiek spoguļa sinhronizācija. Atjaunojiet lapu, lai pārbaudītu atkārtoti, pēc brīža. settings.site=Mājas lapa settings.update_settings=Mainīt iestatījumus settings.update_mirror_settings=Atjaunot spoguļa iestatījumus @@ -2357,7 +2358,6 @@ release.releases_for=Repozitorja %s laidieni release.tags_for=Repozitorija %s tagi branch.name=Atzara nosaukums -branch.search=Meklēt atzarus branch.already_exists=Atzars ar nosaukumu "%s" jau eksistē. branch.delete_head=Dzēst branch.delete=`Dzēst atzaru "%s"` diff --git a/options/locale/locale_nl-NL.ini b/options/locale/locale_nl-NL.ini index aa94a542f182b..393beb563a456 100644 --- a/options/locale/locale_nl-NL.ini +++ b/options/locale/locale_nl-NL.ini @@ -109,6 +109,8 @@ rss_feed=RSS Feed +archived=Gearchiveerd + concept_code_repository=Opslagplaats concept_user_organization=Organisatie @@ -260,7 +262,6 @@ filter_by_team_repositories=Filter op team repositories feed_of=`Feed van "%s"` show_archived=Gearchiveerd -archived=Gearchiveerd show_both_archived_unarchived=Toont zowel gearchiveerd als niet-gearchiveerd show_only_archived=Toon alleen gearchiveerd show_only_unarchived=Toon alleen niet gearchiveerd @@ -847,6 +848,7 @@ delete_preexisting_content=Verwijder bestanden in %s delete_preexisting_success=Niet-geadopteerde bestanden verwijderd in %s blame_prior=Bekijk de schuld voorafgaand aan deze verandering + transfer.accept=Accepteer overdracht transfer.accept_desc=`Overmaken naar "%s"` transfer.reject=Overdracht afwijzen @@ -1655,7 +1657,6 @@ settings.mirror_settings.push_mirror.none=Geen spiegels geconfigureerd settings.mirror_settings.push_mirror.add=Voeg Push Mirror toe settings.sync_mirror=Synchroniseer -settings.mirror_sync_in_progress=Mirror-synchronisatie is momenteel bezig - kom later terug. settings.site=Website settings.update_settings=Instellingen bewerken settings.branches.update_default_branch=Standaard branch bijwerken @@ -2023,7 +2024,6 @@ release.downloads=Downloads release.download_count=Downloads: %s branch.name=Branch naam -branch.search=Zoek branches branch.delete_head=Verwijder branch.delete_html=Verwijder branch branch.create_branch=Maak branch %s diff --git a/options/locale/locale_pl-PL.ini b/options/locale/locale_pl-PL.ini index 255f36598c9af..0c3ed27658f34 100644 --- a/options/locale/locale_pl-PL.ini +++ b/options/locale/locale_pl-PL.ini @@ -107,6 +107,8 @@ never=Nigdy +archived=Zarchiwizowane + concept_code_repository=Repozytorium concept_user_organization=Organizacja @@ -258,7 +260,6 @@ filter_by_team_repositories=Filtruj według repozytoriów zespołu feed_of=`Kanał "%s"` show_archived=Zarchiwizowane -archived=Zarchiwizowane show_both_archived_unarchived=Wyświetlanie zarchiwizowanych i niezarchiwizowanych show_only_archived=Wyświetlanie tylko zarchiwizowanych show_only_unarchived=Wyświetlanie tylko niezarchiwizowanych @@ -793,6 +794,7 @@ delete_preexisting=Usuń istniejące pliki delete_preexisting_content=Usuń pliki w %s delete_preexisting_success=Usunięto nieprzyjęte pliki w %s + transfer.accept=Akceptuj transfer transfer.accept_desc=`Przenieś do "%s"` transfer.reject=Odrzuć transfer @@ -1503,7 +1505,6 @@ settings.mirror_settings.push_mirror.none=Brak skonfigurowanych kopii zapasowych settings.mirror_settings.push_mirror.remote_url=Adres URL zdalnego repozytorium Git settings.sync_mirror=Synchronizuj teraz -settings.mirror_sync_in_progress=Synchronizacja kopii lustrzanych jest w toku. Sprawdź ponownie za minutę. settings.site=Strona settings.update_settings=Aktualizuj ustawienia settings.branches.update_default_branch=Aktualizuj domyślną gałąź @@ -1884,7 +1885,6 @@ release.add_tag_msg=Użyj tytułu i zawartości wydania jako wiadomości znaczni release.add_tag=Utwórz tylko znacznik branch.name=Nazwa gałęzi -branch.search=Szukaj gałęzi branch.delete_head=Usuń branch.delete_html=Usuń gałąź branch.create_branch=Utwórz gałąź %s diff --git a/options/locale/locale_pt-BR.ini b/options/locale/locale_pt-BR.ini index 91881310778f6..0758c05b37af4 100644 --- a/options/locale/locale_pt-BR.ini +++ b/options/locale/locale_pt-BR.ini @@ -120,6 +120,8 @@ unpin=Desfixar artifacts=Artefatos +archived=Arquivado + concept_system_global=Global concept_user_individual=Individual concept_code_repository=Repositório @@ -307,7 +309,6 @@ filter_by_team_repositories=Filtrar por repositórios da equipe feed_of=`Feed de "%s"` show_archived=Arquivado -archived=Arquivado show_both_archived_unarchived=Mostrando arquivados e não arquivados show_only_archived=Mostrando somente arquivados show_only_unarchived=Mostrando somente não arquivados @@ -955,6 +956,7 @@ delete_preexisting_success=Arquivos órfãos excluídos em %s blame_prior=Ver a responsabilização anterior a esta modificação author_search_tooltip=Mostra um máximo de 30 usuários + transfer.accept=Aceitar transferência transfer.accept_desc=`Transferir para "%s"` transfer.reject=Rejeitar transferência @@ -1861,7 +1863,6 @@ settings.mirror_settings.push_mirror.remote_url=URL do repositório do Git remot settings.mirror_settings.push_mirror.add=Adicionar Espelho de Push settings.sync_mirror=Sincronizar agora -settings.mirror_sync_in_progress=Sincronização do espelhamento está em andamento. Verifique novamente em um minuto. settings.site=Site settings.update_settings=Atualizar configurações settings.update_mirror_settings=Atualizar espelho @@ -2331,7 +2332,6 @@ release.releases_for=Versões para %s release.tags_for=Tags para %s branch.name=Nome do Branch -branch.search=Pesquisar branches branch.already_exists=Um branch com o nome "%s" já existe. branch.delete_head=Excluir branch.delete=`Excluir branch "%s"` diff --git a/options/locale/locale_pt-PT.ini b/options/locale/locale_pt-PT.ini index eeb2a3ce8bfa1..af0a9b16da7ff 100644 --- a/options/locale/locale_pt-PT.ini +++ b/options/locale/locale_pt-PT.ini @@ -97,6 +97,7 @@ locked=Bloqueado copy=Copiar copy_url=Copiar URL +copy_hash=Copiar hash copy_content=Copiar conteúdo copy_branch=Copiar nome do ramo copy_success=Copiado! @@ -112,6 +113,7 @@ step2=Passo 2: error=Erro error404=A página que pretende aceder não existe ou não tem autorização para a ver. +go_back=Voltar never=Nunca unknown=Desconhecido @@ -123,6 +125,8 @@ unpin=Desafixar artifacts=Artefactos +archived=Arquivado + concept_system_global=Global concept_user_individual=Individual concept_code_repository=Repositório @@ -317,7 +321,6 @@ filter_by_team_repositories=Filtrar por repositórios da equipa feed_of=`Fonte de "%s"` show_archived=Arquivado -archived=Arquivado show_both_archived_unarchived=Apresentando arquivados e não arquivados show_only_archived=Apresentando somente os arquivados show_only_unarchived=Apresentando somente os não arquivados @@ -942,6 +945,8 @@ fork_from=Derivar de already_forked=Você já tinha feito uma derivação do repositório %s, anteriormente fork_to_different_account=Fazer uma derivação para uma conta diferente fork_visibility_helper=A visibilidade de um repositório derivado não poderá ser alterada posteriormente. +fork_branch=Ramo a ser clonado para a derivação +all_branches=Todos os ramos fork_no_valid_owners=Não pode fazer uma derivação deste repositório porque não existem proprietários válidos. use_template=Usar este modelo clone_in_vsc=Clonar no VS Code @@ -1007,8 +1012,14 @@ delete_preexisting=Eliminar ficheiros pré-existentes delete_preexisting_content=Eliminar ficheiros em %s delete_preexisting_success=Eliminados os ficheiros não adoptados em %s blame_prior=Ver a responsabilização anterior a esta modificação +blame.ignore_revs=Ignorando as revisões em .git-blame-ignore-revs. Clique aqui para contornar e ver a vista normal de responsabilização. +blame.ignore_revs.failed=Falhou ao ignorar as revisões em .git-blame-ignore-revs. author_search_tooltip=Mostra um máximo de 30 utilizadores +tree_path_not_found_commit=A localização %[1]s não existe no cometimento %[2]s +tree_path_not_found_branch=A localização %[1]s não existe no ramo %[2]s +tree_path_not_found_tag=A localização %[1]s não existe na etiqueta %[2]s + transfer.accept=Aceitar transferência transfer.accept_desc=`Transferir para "%s"` transfer.reject=Rejeitar transferência @@ -1273,6 +1284,7 @@ commits.signed_by_untrusted_user=Assinado por um utilizador não fiável commits.signed_by_untrusted_user_unmatched=Assinado por um utilizador não fiável que não corresponde a quem comete commits.gpg_key_id=ID da chave GPG commits.ssh_key_fingerprint=Identificação digital da chave SSH +commits.view_path=Vista neste ponto do histórico commit.operations=Operações commit.revert=Reverter @@ -1509,7 +1521,8 @@ issues.label_description=Descrição do rótulo issues.label_color=Cor do rótulo issues.label_exclusive=Exclusivo issues.label_archive=Rótulo de arquivo -issues.label_archive_tooltip=Os rótulos de arquivo são excluídos da pesquisa de rótulos quando está a aplicar rótulos à questão. Os rótulos existentes das questões não são alterados, permitindo-lhe retirar rótulos obsoletos sem que perca informação. +issues.label_archived_filter=Mostrar rótulos arquivados +issues.label_archive_tooltip=Os rótulos arquivados são, por norma, excluídos das sugestões ao pesquisar por rótulo. issues.label_exclusive_desc=Nomeie o rótulo âmbito/item para torná-lo mutuamente exclusivo com outros rótulos do âmbito/. issues.label_exclusive_warning=Quaisquer rótulos com âmbito que estejam em conflito irão ser removidos ao editar os rótulos de uma questão ou de um pedido de integração. issues.label_count=%d rótulos @@ -1996,7 +2009,8 @@ settings.mirror_settings.push_mirror.add=Adicionar réplica deste repositório settings.mirror_settings.push_mirror.edit_sync_time=Editar intervalo entre sincronizações da réplica settings.sync_mirror=Sincronizar agora -settings.mirror_sync_in_progress=A sincronização da réplica está em andamento. Volte a verificar daqui a um minuto. +settings.pull_mirror_sync_in_progress=Puxando modificações a partir do repositório remoto %s, neste momento. +settings.push_mirror_sync_in_progress=Enviando modificações para o repositório remoto %s, neste momento. settings.site=Sítio web settings.update_settings=Modificar configurações settings.update_mirror_settings=Modificar configurações da réplica @@ -2130,12 +2144,14 @@ settings.webhook_deletion_desc=Remover um automatismo web elimina as configuraç settings.webhook_deletion_success=O automatismo web foi removido. settings.webhook.test_delivery=Entrega de teste settings.webhook.test_delivery_desc=Testar este automatismo web com um evento falso. +settings.webhook.test_delivery_desc_disabled=Para testar este automatismo web com um evento falso, habilite-o. settings.webhook.request=Pedido settings.webhook.response=Resposta settings.webhook.headers=Cabeçalhos settings.webhook.payload=Conteúdo settings.webhook.body=Corpo settings.webhook.replay.description=Voltar a executar este automatismo web. +settings.webhook.replay.description_disabled=Para reexecutar este automatismo web, habilite-o. settings.webhook.delivery.success=Foi adicionado um evento à fila de entrega. Pode demorar alguns segundos a aparecer no histórico de entregas. settings.githooks_desc=Os Automatismos do Git são executados pelo próprio Git. Pode editar os ficheiros de automatismo abaixo para configurar operações personalizadas. settings.githook_edit_desc=Se o automatismo estiver desligado, será apresentado um conteúdo de teste. Deixar o conteúdo em branco irá desabilitar este automatismo. @@ -2295,6 +2311,7 @@ settings.dismiss_stale_approvals_desc=Quando novos cometimentos que mudam o cont settings.require_signed_commits=Exigir cometimentos assinados settings.require_signed_commits_desc=Rejeitar envios para este ramo que não estejam assinados ou que não sejam validáveis. settings.protect_branch_name_pattern=Padrão do nome do ramo protegido +settings.protect_branch_name_pattern_desc=Padrões de nomes de ramos protegidos. Consulte a documentação para ver a sintaxe dos padrões. Exemplos: main, release/** settings.protect_patterns=Padrões settings.protect_protected_file_patterns=Padrões de ficheiros protegidos (separados com ponto e vírgula ';'): settings.protect_protected_file_patterns_desc=Ficheiros protegidos não podem ser modificados imediatamente, mesmo que o utilizador tenha direitos para adicionar, editar ou eliminar ficheiros neste ramo. Múltiplos padrões podem ser separados com ponto e vírgula (';'). Veja a documentação em github.com/gobwas/glob para ver a sintaxe. Exemplos: .drone.yml, /docs/**/*.txt. @@ -2490,7 +2507,7 @@ release.releases_for=Lançamentos para %s release.tags_for=Etiquetas para %s branch.name=Nome do ramo -branch.search=Procurar ramos +branch.search=Pesquisar ramo branch.already_exists=Já existe um ramo com o nome "%s". branch.delete_head=Eliminar branch.delete=`Eliminar o ramo "%s"` @@ -3503,6 +3520,7 @@ runners.status.idle=Parada runners.status.active=Em funcionamento runners.status.offline=Desconectada runners.version=Versão +runners.reset_registration_token=Repor código de registo runners.reset_registration_token_success=O código de incrição do executor foi reposto com sucesso runs.all_workflows=Todas as sequências de trabalho diff --git a/options/locale/locale_ru-RU.ini b/options/locale/locale_ru-RU.ini index 709a173df3d1e..4b773a70479f9 100644 --- a/options/locale/locale_ru-RU.ini +++ b/options/locale/locale_ru-RU.ini @@ -4,6 +4,7 @@ explore=Обзор help=Помощь logo=Логотип sign_in=Вход +sign_in_with_provider=Войти с помощью %s sign_in_or=или sign_out=Выход sign_up=Регистрация @@ -79,6 +80,7 @@ milestones=Этапы ok=ОК cancel=Отмена +retry=Повторить rerun=Перезапустить rerun_all=Перезапустить все задания save=Сохранить @@ -91,9 +93,11 @@ edit=Изменить enabled=Включено disabled=Отключен +locked=Заблокировано copy=Скопировать copy_url=Скопировать URL +copy_hash=Копировать хеш copy_content=Скопировать содержимое copy_branch=Скопировать имя ветки copy_success=Скопировано! @@ -109,6 +113,7 @@ step2=Шаг 2: error=Ошибка error404=Либо страница, которую вы пытаетесь открыть, не существует, либо у вас недостаточно прав для ее просмотра. +go_back=Назад never=Никогда unknown=Неизвестно @@ -120,6 +125,8 @@ unpin=Открепить artifacts=Артефакты +archived=Архивировано + concept_system_global=Глобально concept_user_individual=Индивидуально concept_code_repository=Репозиторий @@ -128,7 +135,9 @@ concept_user_organization=Организация show_timestamps=Отображать время show_log_seconds=Показывать секунды show_full_screen=Показать во весь экран +download_logs=Скачать журналы +confirm_delete_selected=Вы уверены, что хотите удалить все выбранные элементы? name=Название value=Значение @@ -167,6 +176,7 @@ string.desc=Я - А [error] occurred=Произошла ошибка +report_message=Если вы считаете, что это баг Gitea, пожалуйста, поищите задачу на GitHub или создайте новую при необходимости. missing_csrf=Некорректный запрос: отсутствует токен CSRF invalid_csrf=Некорректный запрос: неверный токен CSRF not_found=Цель не найдена. @@ -175,6 +185,7 @@ network_error=Ошибка сети [startpage] app_desc=Удобный сервис собственного хостинга репозиториев Git install=Простой в установке +install_desc=Просто запустите исполняемый файл для вашей платформы, разверните через Docker, или установите с помощью менеджера пакетов. platform=Кроссплатформенный platform_desc=Gitea работает на любой платформе, поддерживаемой Go: Windows, macOS, Linux, ARM и т. д. Выбирайте, что вам больше нравится! lightweight=Легковесный @@ -219,6 +230,7 @@ repo_path_helper=Все удалённые Git репозитории будут lfs_path=Путь к корневому каталогу Git LFS lfs_path_helper=В этом каталоге будут храниться файлы Git LFS. Оставьте пустым, чтобы отключить LFS. run_user=Запуск от имени пользователя +run_user_helper=Имя пользователя операционной системы, под которым работает Gitea. Обратите внимание, что этот пользователь должен иметь доступ к корневому пути репозиториев. domain=Домен сервера domain_helper=Домен или адрес хоста для сервера. ssh_port=Порт SSH сервера @@ -248,7 +260,7 @@ disable_gravatar_popup=Отключить Gravatar и сторонние ист federated_avatar_lookup=Включить федеративные аватары federated_avatar_lookup_popup=Включите поиск федеративного аватара для использования службы с открытым исходным кодом на основе libravatar. disable_registration=Отключить самостоятельную регистрацию -disable_registration_popup=Отключить самостоятельную регистрацию. Только администраторы смогут создавать новые учетные записи пользователей. +disable_registration_popup=Отключить самостоятельную регистрацию. Только администраторы смогут создавать новые учётные записи пользователей. allow_only_external_registration_popup=Разрешить регистрацию только через сторонние сервисы openid_signin=Включить вход через OpenID openid_signin_popup=Включить вход через OpenID. @@ -258,7 +270,7 @@ enable_captcha=Включить CAPTCHA при регистрации enable_captcha_popup=Запрашивать капчу при регистрации пользователя. require_sign_in_view=Требовать авторизации для просмотра страниц require_sign_in_view_popup=Ограничить доступ к странице только вошедшими пользователями. Посетители увидят лишь страницы входа и регистрации. -admin_setting_desc=Создание учетной записи администратора необязательно. Первый зарегистрированный пользователь автоматически становится администратором. +admin_setting_desc=Создание учётной записи администратора необязательно. Первый зарегистрированный пользователь автоматически становится администратором. admin_title=Настройки учётной записи администратора admin_name=Логин администратора admin_password=Пароль @@ -278,9 +290,9 @@ save_config_failed=Не удалось сохранить конфигураци invalid_admin_setting=Некорректные настройки учётной записи администратора: %v invalid_log_root_path=Недопустимый путь для логов: %v default_keep_email_private=Скрывать адреса электронной почты по умолчанию -default_keep_email_private_popup=Скрывать адреса электронной почты новых учетных записей по умолчанию. +default_keep_email_private_popup=Скрывать адреса электронной почты новых учётных записей по умолчанию. default_allow_create_organization=Разрешить создание организаций по умолчанию -default_allow_create_organization_popup=Разрешить новым учетным записям пользователей создавать организации по умолчанию. +default_allow_create_organization_popup=Разрешить новым учётным записям пользователей создавать организации по умолчанию. default_enable_timetracking=Включить отслеживание времени по умолчанию default_enable_timetracking_popup=Включить отслеживание времени для новых репозиториев по умолчанию. no_reply_address=Скрытый почтовый домен @@ -290,6 +302,8 @@ invalid_password_algorithm=Некорректный алгоритм хешир password_algorithm_helper=Задайте алгоритм хеширования паролей. Алгоритмы имеют различные требования и стойкость. Алгоритм argon2 довольно безопасен, но он использует много памяти и может не подходить для слабых систем. enable_update_checker=Включить проверку обновлений enable_update_checker_helper=Периодически проверяет наличие новых версий, подключаясь к gitea.io. +env_config_keys=Настройка окружения +env_config_keys_prompt=Следующие переменные окружения также будут применены к вашему конфигурационному файлу: [home] uname_holder=Имя пользователя / Адрес эл. почты @@ -307,7 +321,6 @@ filter_by_team_repositories=Фильтровать по репозиториям feed_of=Лента «%s» show_archived=Архивировано -archived=Архивировано show_both_archived_unarchived=Показаны архивированные и разархивированные show_only_archived=Показаны только архивированные show_only_unarchived=Показаны только разархивированные @@ -353,6 +366,7 @@ remember_me=Запомнить это устройство forgot_password_title=Восстановить пароль forgot_password=Забыли пароль? sign_up_now=Нужен аккаунт? Зарегистрируйтесь. +sign_up_successful=Учётная запись успешно создана. Добро пожаловать! confirmation_mail_sent_prompt=Новое письмо для подтверждения направлено на %s. Пожалуйста, проверьте ваш почтовый ящик в течение %s для завершения регистрации. must_change_password=Обновить пароль allow_password_change=Требовать смену пароля пользователем (рекомендуется) @@ -360,15 +374,18 @@ reset_password_mail_sent_prompt=Письмо с подтверждением о active_your_account=Активируйте свой аккаунт account_activated=Учётная запись активирована prohibit_login=Вход запрещён +prohibit_login_desc=Вход в вашу учётную запись запрещен, пожалуйста, свяжитесь с администратором сайта. resent_limit_prompt=Извините, вы уже запросили активацию по электронной почте недавно. Пожалуйста, подождите 3 минуты, а затем повторите попытку. has_unconfirmed_mail=Здравствуйте, %s! У вас есть неподтвержденный адрес электронной почты (%s). Если вам не приходило письмо с подтверждением или нужно выслать новое письмо, нажмите на кнопку ниже. resend_mail=Нажмите здесь, чтобы переотправить активационное письмо -email_not_associate=Этот адрес электронной почты не связан ни с одной учетной записью. +email_not_associate=Этот адрес электронной почты не связан ни с одной учётной записью. send_reset_mail=Отправить письмо для восстановления аккаунта reset_password=Восстановление аккаунта invalid_code=Код подтверждения недействителен или истёк. +invalid_code_forgot_password=Ваш код подтверждения недействителен или истек. Нажмите здесь для начала новой сессии. invalid_password=Ваш пароль не совпадает с паролем, который был использован для создания учётной записи. reset_password_helper=Восстановить аккаунт +reset_password_wrong_user=Вы вошли как %s, но ссылка для восстановления учётной записи предназначена для %s password_too_short=Пароль не может быть короче %d символов. non_local_account=Нелокальные аккаунты не могут изменить пароль через Gitea. verify=Проверить @@ -389,12 +406,13 @@ oauth.signin.error=Произошла ошибка при обработке з oauth.signin.error.access_denied=Запрос на авторизацию был отклонен. oauth.signin.error.temporarily_unavailable=Произошла ошибка авторизации, так как сервер аутентификации временно недоступен. Пожалуйста, повторите попытку позже. openid_connect_submit=Подключить -openid_connect_title=Подключение к существующей учетной записи -openid_connect_desc=Выбранный OpenID URI неизвестен. Свяжите с новой учетной записью здесь. +openid_connect_title=Подключение к существующей учётной записи +openid_connect_desc=Выбранный OpenID URI неизвестен. Свяжите с новой учётной записью здесь. openid_register_title=Создать новый аккаунт -openid_register_desc=Выбранный OpenID URI неизвестен. Свяжите с новой учетной записью здесь. +openid_register_desc=Выбранный OpenID URI неизвестен. Свяжите с новой учётной записью здесь. +openid_signin_desc=Введите ваш OpenID URI. Например: alice.openid.example.org или https://openid.example.org/alice. disable_forgot_password_mail=Восстановление учётной записи отключено, потому что электронная почта не настроена. Пожалуйста, свяжитесь с администратором сайта. -disable_forgot_password_mail_admin=Восстановление учетной записи доступно только при настройке электронной почты. Пожалуйста, настройте электронную почту, чтобы включить восстановление аккаунта. +disable_forgot_password_mail_admin=Восстановление учётной записи доступно только при настройке электронной почты. Пожалуйста, настройте электронную почту, чтобы включить восстановление аккаунта. email_domain_blacklisted=С данным адресом электронной почты регистрация невозможна. authorize_application=Авторизация приложения authorize_redirect_notice=Вы будете перенаправлены на %s, если вы авторизуете это приложение. @@ -402,7 +420,9 @@ authorize_application_created_by=Это приложение было созда authorize_application_description=Если вы предоставите доступ, оно сможет получить доступ и редактировать любую информацию о вашей учётной записи, включая содержимое частных репозиториев и организаций. authorize_title=Разрешить «%s» доступ к вашей учётной записи? authorization_failed=Ошибка авторизации +authorization_failed_desc=Ошибка авторизации, обнаружен неверный запрос. Пожалуйста, свяжитесь с автором приложения, которое вы пытались авторизовать. sspi_auth_failed=Аутентификация SSPI не удалась +password_pwned=Выбранный вами пароль находится в списке украденных паролей из ранее опубликованных утечек. Повторите попытку с другим паролем. Также рекомендуем сменить этот пароль в других местах. password_pwned_err=Не удалось завершить запрос к HaveIBeenPwned [mail] @@ -412,22 +432,23 @@ link_not_working_do_paste=Не работает? Попробуйте скопи hi_user_x=Привет %s, activate_account=Пожалуйста активируйте свой аккаунт -activate_account.title=%s, пожалуйста, активируйте вашу учетную запись +activate_account.title=%s, пожалуйста, активируйте вашу учётную запись activate_account.text_1=Привет, %[1]s, спасибо за регистрацию в %[2]s! -activate_account.text_2=Пожалуйста, перейдите по ссылке, чтобы активировать свою учетную запись в течение %s: +activate_account.text_2=Пожалуйста, перейдите по ссылке, чтобы активировать свою учётную запись в течение %s: activate_email=Подтвердите адрес своей электронной почты +activate_email.title=%s, пожалуйста, подтвердите ваш адрес электронной почты activate_email.text=Пожалуйста, перейдите по ссылке, чтобы подтвердить ваш адрес электронной почты в течение %s: register_notify=Добро пожаловать на Gitea register_notify.title=%[1]s, добро пожаловать в %[2]s register_notify.text_1=это письмо с вашим подтверждением регистрации в %s! register_notify.text_2=Теперь вы можете войти через логин: %s. -register_notify.text_3=Если эта учетная запись была создана для вас, пожалуйста, сначала установите пароль. +register_notify.text_3=Если эта учётная запись была создана для вас, пожалуйста, сначала установите пароль. reset_password=Восстановить учётную запись -reset_password.title=%s, вы запросили восстановление вашей учетной записи -reset_password.text=Пожалуйста, перейдите по ссылке, чтобы восстановить учетную запись в течение %s: +reset_password.title=%s, вы запросили восстановление вашей учётной записи +reset_password.text=Пожалуйста, перейдите по ссылке, чтобы восстановить учётную запись в течение %s: register_success=Регистрация прошла успешно @@ -586,6 +607,8 @@ user_bio=О себе disabled_public_activity=Этот пользователь отключил публичную видимость активности. email_visibility.limited=Ваш адрес электронной почты виден всем выполнившим вход пользователям email_visibility.private=Ваш адрес электронной почты виден только вам и администраторам +show_on_map=Показать это место на карте +settings=Параметры пользователя form.name_reserved=Имя пользователя «%s» зарезервировано. form.name_pattern_not_allowed=Шаблон «%s» не допускается в имени пользователя. @@ -607,9 +630,13 @@ delete=Удалить аккаунт twofa=Двухфакторная аутентификация account_link=Привязанные аккаунты organization=Организации +uid=UID webauthn=Ключи безопасности public_profile=Открытый профиль +biography_placeholder=Расскажите немного о себе! (Можно использовать Markdown) +location_placeholder=Поделитесь своим приблизительным местоположением с другими +profile_desc=Контролируйте, как ваш профиль будет отображаться другим пользователям. Ваш основной адрес электронной почты будет использоваться для уведомлений, восстановления пароля и веб-операций Git. password_username_disabled=Нелокальным пользователям запрещено изменение их имени пользователя. Для получения более подробной информации обратитесь к администратору сайта. full_name=Имя и фамилия website=Веб-сайт @@ -621,6 +648,8 @@ update_language_not_found=Язык «%s» недоступен. update_language_success=Язык обновлён. update_profile_success=Ваш профиль успешно обновлён. change_username=Ваше имя пользователя было изменено. +change_username_prompt=Обратите внимание: изменение имени пользователя также меняет URL вашей учётной записи. +change_username_redirect_prompt=Старое имя пользователя будет перенаправлять на новое до тех пор, пока его не займут. continue=Далее cancel=Отмена language=Язык @@ -645,6 +674,7 @@ comment_type_group_project=Проект comment_type_group_issue_ref=Ссылка на задачу saved_successfully=Ваши настройки успешно сохранены. privacy=Приватность +keep_activity_private=Скрыть активность со страницы профиля keep_activity_private_popup=Делает активность видимой только для вас и администраторов lookup_avatar_by_mail=Найти аватар по адресу эл. почты @@ -654,12 +684,14 @@ choose_new_avatar=Выбрать новый аватар update_avatar=Обновить аватар delete_current_avatar=Удалить текущий аватар uploaded_avatar_not_a_image=Загружаемый файл не является изображением. +uploaded_avatar_is_too_big=Размер загружаемого файла (%d КиБ) превышает максимальный размер (%d КиБ). update_avatar_success=Ваш аватар был изменен. update_user_avatar_success=Аватар пользователя обновлён. change_password=Обновить пароль old_password=Текущий пароль new_password=Новый пароль +retype_new_password=Подтвердите новый пароль password_incorrect=Текущий пароль неправильный. change_password_success=Ваш пароль был изменён. С этого момента необходимо использовать новый пароль для входа. password_change_disabled=Нелокальные аккаунты не могут изменить пароль через Gitea. @@ -668,6 +700,7 @@ emails=Email адреса manage_emails=Управление адресами электронной почты manage_themes=Выберите тему по умолчанию manage_openid=Управление OpenID +email_desc=Ваш основной адрес электронной почты будет использоваться для уведомлений, восстановления пароля и, если он не скрыт, для действий с Git в веб-интерфейсе. theme_desc=Это будет темой по умолчанию для всего сайта. primary=Основной activated=Активирован @@ -701,7 +734,7 @@ manage_gpg_keys=Управление ключами GPG add_key=Добавить ключ ssh_desc=Эти открытые ключи SSH связаны с вашей учётной записью. Соответствующие закрытые ключи обеспечивают полный доступ к вашим хранилищам. principal_desc=Эти принципалы сертификатов SSH привязаны к вашей учётной записи и разрешают полный доступ к вашим хранилищам. -gpg_desc=Эти открытые GPG ключи связаны с вашей учетной записью. Храните закрытые ключи в безопасности, так как они позволяют проверять подлинности коммитов. +gpg_desc=Эти открытые GPG ключи связаны с вашей учётной записью. Храните закрытые ключи в безопасности, так как они позволяют проверять подлинности коммитов. ssh_helper=Нужна помощь? Ознакомьтесь с руководством GitHub по созданию ключей SSH или решению возникающих проблем при использовании SSH. gpg_helper=Нужна помощь? Взгляните на руководство GitHub по GPG. add_new_key=Добавить ключ SSH @@ -713,7 +746,7 @@ ssh_key_been_used=Этот ключ SSH уже был добавлен на се ssh_key_name_used=Ключ SSH с этим именем уже есть в вашем аккаунте. ssh_principal_been_used=Принципал уже был добавлен на сервер. gpg_key_id_used=Публичный ключ GPG с таким же идентификатором уже существует. -gpg_no_key_email_found=Этот ключ GPG не соответствует ни одному активному адресу электронной почты, связанному с вашей учетной записью. Он по-прежнему может быть добавлен, если вы подписали указанный токен. +gpg_no_key_email_found=Этот ключ GPG не соответствует ни одному активному адресу электронной почты, связанному с вашей учётной записью. Он по-прежнему может быть добавлен, если вы подписали указанный токен. gpg_key_matched_identities=Соответствующие идентификаторы: gpg_key_matched_identities_long=Встроенные в этот ключ идентификаторы соответствуют следующим активным email-адресам этого пользователя и коммиты, соответствующие этим email-адресам могут быть проверены с помощью этого ключа. gpg_key_verified=Проверенный ключ @@ -749,7 +782,7 @@ delete_key=Удалить ssh_key_deletion=Удалить ключ SSH gpg_key_deletion=Удалить ключ GPG ssh_principal_deletion=Удалить принципала сертификата SSH -ssh_key_deletion_desc=Удаление ключа SSH аннулирует его доступ к вашей учетной записи. Продолжить? +ssh_key_deletion_desc=Удаление ключа SSH аннулирует его доступ к вашей учётной записи. Продолжить? gpg_key_deletion_desc=Удаление ключа GPG отменяет проверку подписанных им коммитов. Продолжить? ssh_principal_deletion_desc=Удаление принципала сертификата SSH отзывает доступ к вашей учётной записи. Продолжить? ssh_key_deletion_success=Ключ SSH удален. @@ -770,12 +803,14 @@ hide_openid=Скрыть из профиля ssh_disabled=SSH отключён ssh_signonly=SSH в настоящее время отключён, поэтому эти ключи используются только для проверки подписей коммитов. ssh_externally_managed=Этот ключ SSH управляется извне для этого пользователя -manage_social=Управление привязанными учетными записями в соцсетях +manage_social=Управление привязанными учётными записями в соцсетях +social_desc=Эти учётные записи социальных сетей можно использовать для входа в вашу учётную запись. Убедитесь, что они все принадлежат вам. unbind=Удалить связь +unbind_success=Учётная запись социальной сети успешно удалена. manage_access_token=Управление токенами generate_new_token=Создать новый токен -tokens_desc=Эти токены предоставляют доступ к вашей учетной записи с помощью Gitea API. +tokens_desc=Эти токены предоставляют доступ к вашей учётной записи с помощью Gitea API. token_name=Имя токена generate_token=Генерировать токен generate_token_success=Новый токен создан. Скопируйте и сохраните его сейчас, так как он не будет показан снова. @@ -784,7 +819,7 @@ delete_token=Удалить access_token_deletion=Удалить токен доступа access_token_deletion_cancel_action=Отменить access_token_deletion_confirm_action=Удалить -access_token_deletion_desc=Удаление токена отзовёт доступ к вашей учетной записи у приложений, использующих его. Это действие не может быть отменено. Продолжить? +access_token_deletion_desc=Удаление токена отзовёт доступ к вашей учётной записи у приложений, использующих его. Это действие не может быть отменено. Продолжить? delete_token_success=Токен удалён. Приложения, использующие его, больше не имеют доступа к вашему аккаунту. repo_and_org_access=Доступ к репозиторию и организации permissions_public_only=Только публичные @@ -792,6 +827,8 @@ permissions_access_all=Все (публичные, приватные и огр select_permissions=Выбрать разрешения permission_no_access=Нет доступа permission_read=Прочитанные +permission_write=Чтение и запись +access_token_desc=Выбранные области действия токена ограничивают авторизацию только соответствующими маршрутами API. Читайте документацию для получения дополнительной информации. at_least_one_permission=Необходимо выбрать хотя бы одно разрешение для создания токена permissions_list=Разрешения: @@ -803,6 +840,8 @@ remove_oauth2_application_desc=Удаление приложения OAuth2 от remove_oauth2_application_success=Приложение удалено. create_oauth2_application=Создать новое приложение OAuth2 create_oauth2_application_button=Создать приложение +create_oauth2_application_success=Вы успешно создали новое приложение OAuth2. +update_oauth2_application_success=Изменения настроек приложения OAuth2 успешно применены. oauth2_application_name=Имя приложения oauth2_redirect_uris=URI для перенаправления. Используйте новую строку для каждого URI. save_application=Сохранить @@ -812,11 +851,14 @@ oauth2_regenerate_secret=Сгенерировать новый ключ oauth2_regenerate_secret_hint=Потеряли свой ключ? oauth2_application_edit=Изменить oauth2_application_create_description=Приложения OAuth2 предоставляет стороннему приложению доступ к учётным записям пользователей данного сервиса. +oauth2_application_remove_description=Удаление приложения OAuth2 приведёт к отмене его доступа к авторизованным учётным записям пользователей в данном экземпляре. Продолжить? authorized_oauth2_applications=Авторизованные приложения OAuth2 +authorized_oauth2_applications_description=Вы предоставили доступ к вашему персональному аккаунту Gitea этим сторонним приложениям. Пожалуйста, отзовите доступ у приложений, которые больше не используются. revoke_key=Отозвать revoke_oauth2_grant=Отозвать доступ revoke_oauth2_grant_description=Отзыв доступа у этого стороннего приложения не позволит ему получать доступ к вашим данным. Вы уверены? +revoke_oauth2_grant_success=Доступ был успешно отозван. twofa_desc=Двухфакторная аутентификация повышает уровень безопасности вашей учётной записи. twofa_is_enrolled=Ваша учётная запись в настоящее время использует двухфакторную аутентификацию. @@ -846,15 +888,16 @@ manage_account_links_desc=Эти внешние аккаунты привяза account_links_not_available=В настоящее время нет внешних аккаунтов, привязанных к вашему аккаунту Gitea. link_account=Привязать аккаунт remove_account_link=Удалить привязанный аккаунт -remove_account_link_desc=Удаление привязанной учетной записи отменит её доступ к вашей учетной записи Gitea. Продолжить? -remove_account_link_success=Привязанная учетная запись удалена. +remove_account_link_desc=Удаление привязанной учётной записи отменит её доступ к вашей учётной записи Gitea. Продолжить? +remove_account_link_success=Привязанная учётная запись удалена. orgs_none=Вы не состоите ни в одной организации. +repos_none=Вы не владеете ни одним репозиторием. delete_account=Удалить свой аккаунт -delete_prompt=Эта операция навсегда удалит вашу учетную запись. Это НЕВОЗМОЖНО будет отменить. -delete_with_all_comments=Ваша учетная запись младше %s. Чтобы избежать комментариев к плану, все комментарии к ней будут удалены. +delete_prompt=Эта операция навсегда удалит вашу учётную запись. Это НЕВОЗМОЖНО будет отменить. +delete_with_all_comments=Ваша учётная запись младше %s. Чтобы избежать комментариев к плану, все комментарии к ней будут удалены. confirm_delete_account=Подтвердите удаление delete_account_title=Удалить аккаунт delete_account_desc=Вы уверены, что хотите навсегда удалить этот аккаунт? @@ -869,7 +912,9 @@ visibility=Видимость пользователя visibility.public=Публичный visibility.public_tooltip=Видимый для всех visibility.limited=Ограниченный +visibility.limited_tooltip=Виден только выполнившим вход пользователям visibility.private=Приватный +visibility.private_tooltip=Виден только членам организаций, к которым вы присоединились [repo] owner=Владелец @@ -883,6 +928,7 @@ template_helper=Сделать репозиторий шаблоном template_description=Шаблонные репозитории дают возможность пользователям создавать новые репозитории с той же структурой каталогов, файлами и дополнительными настройками. visibility=Видимость visibility_description=Только владелец или члены организации, при наличии прав, смогут увидеть это. +visibility_helper=Сделать репозиторий приватным visibility_helper_forced=Администратор сайта настроил параметр видимости новых репозиториев. Репозиторий приватный по умолчанию. visibility_fork_helper=(Изменение этого повлияет на все форки.) clone_helper=Нужна помощь в клонировании? Посетите страницу помощи. @@ -891,6 +937,7 @@ fork_from=Форк от already_forked=Вы уже форкнули %s fork_to_different_account=Ответвление для другой учётной записи fork_visibility_helper=Видимость форкнутого репозитория изменить нельзя. +all_branches=Все ветки use_template=Использовать этот шаблон clone_in_vsc=Клонировать в VS Code download_zip=Скачать ZIP @@ -919,6 +966,7 @@ trust_model_helper_collaborator_committer=Соавтор+Коммитер: До trust_model_helper_default=По умолчанию: используйте модель доверия по умолчанию для этой установки create_repo=Создать репозиторий default_branch=Ветка по умолчанию +default_branch_label=по умолчанию default_branch_helper=Ветка по умолчанию является базовой веткой для запросов на слияние и коммитов кода. mirror_prune=Очистить mirror_prune_desc=Удаление устаревших отслеживаемых ссылок @@ -926,7 +974,7 @@ mirror_interval=Интервал зеркалирования (допустим mirror_interval_invalid=Недопустимый интервал зеркалирования. mirror_sync_on_commit=Синхронизировать при отправке коммитов mirror_address=Клонировать по URL -mirror_address_desc=Поместите необходимые учетные данные в секцию авторизации. +mirror_address_desc=Поместите необходимые учётные данные в секцию авторизации. mirror_lfs=Хранилище больших файлов (LFS) mirror_lfs_desc=Активировать зеркалирование данных LFS. mirror_lfs_endpoint=LFS Endpoint @@ -954,6 +1002,7 @@ delete_preexisting_success=Удалены непринятые файлы в %s blame_prior=Показать авторство предшествующих изменений author_search_tooltip=Показывает максимум 30 пользователей + transfer.accept=Принять трансфер transfer.accept_desc=Переместить в «%s» transfer.reject=Отказаться от перемещения @@ -1108,11 +1157,15 @@ video_not_supported_in_browser=Ваш браузер не поддерживае audio_not_supported_in_browser=Ваш браузер не поддерживает HTML5 'audio' тэг. stored_lfs=Хранится Git LFS symbolic_link=Символическая ссылка +executable_file=Исполняемый файл commit_graph=Граф коммитов commit_graph.select=Выбрать ветку commit_graph.hide_pr_refs=Скрыть запросы на слияние commit_graph.monochrome=Моно commit_graph.color=Цвет +commit.contained_in=Этот коммит содержится в: +commit.contained_in_default_branch=Этот коммит является частью ветки по умолчанию +commit.load_referencing_branches_and_tags=Загрузить ветки и теги, ссылающиеся на этот коммит blame=Ответственный download_file=Скачать файл normal_view=Обычный вид @@ -1332,6 +1385,7 @@ issues.delete_branch_at=`удалил(а) ветку %s %s` issues.filter_label=Метка issues.filter_label_exclude=`Используйте alt + click/enter, чтобы исключить метки` issues.filter_label_no_select=Все метки +issues.filter_label_select_no_label=Нет метки issues.filter_milestone=Этап issues.filter_milestone_all=Все этапы issues.filter_milestone_none=Нет этапов @@ -1385,6 +1439,7 @@ issues.next=Следующая issues.open_title=Открыто issues.closed_title=Закрыто issues.draft_title=Черновик +issues.num_comments_1=%d комментарий issues.num_comments=комментариев: %d issues.commented_at=`прокомментировал(а) %s` issues.delete_comment_confirm=Вы уверены, что хотите удалить этот комментарий? @@ -1393,6 +1448,7 @@ issues.context.quote_reply=Цитировать ответ issues.context.reference_issue=Ссылка в новой задаче issues.context.edit=Редактировать issues.context.delete=Удалить +issues.no_content=Описание отсутствует. issues.close=Закрыть задачу issues.comment_pull_merged_at=слил(а) коммит %[1]s в %[2]s %[3]s issues.comment_manually_pull_merged_at=вручную слил(а) коммит %[1]s в %[2]s %[3]s @@ -1413,6 +1469,8 @@ issues.ref_from=`из %[1]s` issues.author=Автор issues.role.owner=Владелец issues.role.member=Участник +issues.role.collaborator=Соавтор +issues.role.contributor=Участник issues.re_request_review=Повторить запрос на отзыв issues.is_stale=Со времени этого обзора в этот PR были внесены некоторые изменения issues.remove_request_review=Удалить запрос на отзыв @@ -1427,6 +1485,7 @@ issues.label_title=Имя метки issues.label_description=Описание метки issues.label_color=Цвет метки issues.label_exclusive=Эксклюзивный +issues.label_archive=Метка архива issues.label_exclusive_desc=Назовите метку область/элемент, чтобы сделать ее взаимоисключающей с другими метками область/. issues.label_exclusive_warning=Любые метки с конфликтующей областью будут удалены при редактировании меток задачи или запроса на слияние. issues.label_count=%d меток @@ -1559,6 +1618,8 @@ issues.review.pending.tooltip=Этот комментарий в настоящ issues.review.review=Рецензия issues.review.reviewers=Рецензенты issues.review.outdated=Устаревшее +issues.review.option.show_outdated_comments=Показать устаревшие комментарии +issues.review.option.hide_outdated_comments=Скрыть устаревшие комментарии issues.review.show_outdated=Показать устаревшие issues.review.hide_outdated=Скрыть устаревшие issues.review.show_resolved=Показать разрешенные @@ -1598,6 +1659,11 @@ pulls.switch_comparison_type=Переключить тип сравнения pulls.switch_head_and_base=Поменять исходную и целевую ветки местами pulls.filter_branch=Фильтр по ветке pulls.no_results=Результатов не найдено. +pulls.show_all_commits=Показать все коммиты +pulls.show_changes_since_your_last_review=Показать изменения с момента вашего последнего отзыва +pulls.showing_only_single_commit=Показать только изменения коммита %[1]s +pulls.showing_specified_commit_range=Показаны только изменения между %[1]s..%[2] +pulls.filter_changes_by_commit=Фильтр по коммиту pulls.nothing_to_compare=Нечего сравнивать, родительская и текущая ветка одинаковые. pulls.nothing_to_compare_and_allow_empty_pr=Ветки идентичны. Этот PR будет пустым. pulls.has_pull_request=`Запрос на слияние этих веток уже существует: %[2]s#%[3]d` @@ -1629,6 +1695,7 @@ pulls.is_empty=Изменения из этой ветки уже есть в ц pulls.required_status_check_failed=Некоторые необходимые проверки не были пройдены. pulls.required_status_check_missing=Отсутствуют некоторые обязательные проверки. pulls.required_status_check_administrator=Как администратор, вы все равно можете принять этот запрос на слияние. +pulls.blocked_by_rejection=Официальный рецензент запросил изменения к этому запросу на слияние. pulls.can_auto_merge_desc=Этот запрос на слияние может быть объединён автоматически. pulls.cannot_auto_merge_desc=Этот запрос на слияние не может быть объединён автоматически. pulls.cannot_auto_merge_helper=Пожалуйста, совершите слияние вручную для урегулирования конфликтов. @@ -1704,6 +1771,7 @@ pulls.delete.title=Удалить этот запрос на слияние? pulls.delete.text=Вы действительно хотите удалить этот запрос на слияние? (Это навсегда удалит всё содержимое. Возможно, лучше закрыть запрос в архивных целях.) +pull.deleted_branch=(удалена):%s milestones.new=Новый этап milestones.closed=Закрыт %s @@ -1732,6 +1800,9 @@ milestones.filter_sort.most_complete=Более полное milestones.filter_sort.most_issues=Большинство задач milestones.filter_sort.least_issues=Меньшинство задач +signing.will_sign=Этот коммит будет подписан ключом «%s». +signing.wont_sign.basesigned=Слияние не будет подписано, так как базовый коммит не подписан. +signing.wont_sign.not_signed_in=Вы не вошли в систему. ext_wiki=Доступ к внешней вики ext_wiki.desc=Ссылка на внешнюю вики. @@ -1852,10 +1923,15 @@ settings.hooks=Веб-хуки settings.githooks=Git-хуки settings.basic_settings=Основные параметры settings.mirror_settings=Настройки зеркалирования +settings.mirror_settings.docs=Настройте свой репозиторий для автоматической синхронизации коммитов, тегов и веток с другим репозиторием. +settings.mirror_settings.docs.disabled_pull_mirror.instructions=Настройте свой проект для автоматической отправки коммитов, тегов и веток в другой репозиторий. Pull-зеркала были отключены администратором сайта. +settings.mirror_settings.docs.disabled_push_mirror.instructions=Настройте свой проект, чтобы автоматически получать коммиты, теги и ветки из другого репозитория. settings.mirror_settings.docs.disabled_push_mirror.pull_mirror_warning=В настоящее время это можно сделать только в меню «Новая миграция». Для получения дополнительной информации, пожалуйста, ознакомьтесь: +settings.mirror_settings.docs.disabled_push_mirror.info=Push-зеркала отключены администратором сайта. settings.mirror_settings.docs.no_new_mirrors=Ваш репозиторий зеркалирует изменения в другой репозиторий или из него. Пожалуйста, имейте в виду, что в данный момент невозможно создавать новые зеркала. settings.mirror_settings.docs.can_still_use=Хотя вы не можете изменять существующие зеркала или создавать новые, вы можете по-прежнему использовать существующее зеркало. settings.mirror_settings.docs.pull_mirror_instructions=Чтобы настроить pull-зеркало, пожалуйста, ознакомьтесь: +settings.mirror_settings.docs.more_information_if_disabled=Вы можете узнать больше о зеркалах push и pull здесь: settings.mirror_settings.docs.doc_link_title=Как зеркалировать репозитории? settings.mirror_settings.docs.pulling_remote_title=Получение из удалённого репозитория settings.mirror_settings.mirrored_repository=Синхронизированное хранилище @@ -1868,7 +1944,6 @@ settings.mirror_settings.push_mirror.remote_url=URL удалённого хра settings.mirror_settings.push_mirror.add=Добавить Push-зеркало settings.sync_mirror=Синхронизировать -settings.mirror_sync_in_progress=Синхронизируются репозитории-зеркала. Подождите минуту и обновите страницу. settings.site=Сайт settings.update_settings=Обновить настройки settings.update_mirror_settings=Обновить настройки зеркала @@ -2133,6 +2208,7 @@ settings.protect_disable_push=Отключить отправку settings.protect_disable_push_desc=Отправка не будет разрешена в эту ветку. settings.protect_enable_push=Включить отправку settings.protect_enable_push_desc=Любому, у кого есть доступ на запись, будет разрешена отправка изменений в эту ветку (но не принудительная отправка). +settings.protect_enable_merge_desc=Все, у кого есть доступ на запись, смогут удовлетворять запросы на слияние в эту ветку. settings.protect_whitelist_committers=Ограничение отправки по белому списку settings.protect_whitelist_committers_desc=Только пользователям или командам из белого списка будет разрешена отправка изменений в эту ветку (но не принудительная отправка). settings.protect_whitelist_deploy_keys=Белый список развёртываемых ключей с доступом на запись в push. @@ -2146,8 +2222,10 @@ settings.protect_merge_whitelist_users=Пользователи с правом settings.protect_merge_whitelist_teams=Команды, члены которых обладают правом на слияние: settings.protect_check_status_contexts=Включить проверку статуса settings.protect_status_check_patterns=Шаблоны проверки состояния: +settings.protect_status_check_patterns_desc=Добавьте шаблоны, чтобы указать, какие проверки состояния должны быть пройдены, прежде чем ветви могут быть объединены в ветвь, соответствующую этому правилу. В каждой строке указывается шаблон. Шаблоны не могут быть пустыми. settings.protect_check_status_contexts_desc=Требуется пройти проверку состояния перед слиянием. Выберите, какие проверки состояния должны быть пройдены, прежде чем ветви можно будет объединить в ветвь, соответствующую этому правилу. Если этот параметр включен, коммиты сначала должны быть перемещены в другую ветвь, а затем объединены или перемещены непосредственно в ветвь, соответствующую этому правилу, после прохождения проверки состояния. Если контексты не выбраны, то последняя фиксация должна быть успешной независимо от контекста. settings.protect_check_status_contexts_list=Проверки состояния за последнюю неделю для этого репозитория +settings.protect_status_check_matched=Совпало settings.protect_invalid_status_check_pattern=Неверный шаблон проверки состояния: «%s». settings.protect_no_valid_status_check_patterns=Нет допустимых шаблонов проверки состояния. settings.protect_required_approvals=Необходимые одобрения: @@ -2174,7 +2252,7 @@ settings.remove_protected_branch_failed=Не удалось удалить пр settings.protected_branch_deletion=Отключение защиты ветки settings.protected_branch_deletion_desc=Любой пользователь с разрешениями на запись сможет выполнять push в эту ветку. Вы уверены? settings.block_rejected_reviews=Блокировка слияния по отклоненным отзывам -settings.block_rejected_reviews_desc=Слияние будет не возможным, если будут запрошены официальными рецензентами изменения, даже если имеется достаточное количество одобрений. +settings.block_rejected_reviews_desc=Слияние будет невозможно, если официальными рецензентами будут запрошены изменения, даже если имеется достаточное количество одобрений. settings.block_on_official_review_requests=Блокировать слияние при запросах на официальное рассмотрение settings.block_on_official_review_requests_desc=Слияние невозможно, если не имеется достаточное количество одобрений официальных представителей. settings.block_outdated_branch=Блокировать слияние, если запрос на слияние устарел @@ -2209,6 +2287,10 @@ settings.archive.error=Ошибка при попытке архивироват settings.archive.error_ismirror=Вы не можете поместить зеркалируемый репозиторий в архив. settings.archive.branchsettings_unavailable=Настройки ветки недоступны, если репозиторий архивирован. settings.archive.tagsettings_unavailable=Настройки тегов недоступны, если репозиторий архивирован. +settings.unarchive.button=Разархивировать репозиторий +settings.unarchive.header=Вернуть этот репозиторий из архива +settings.unarchive.text=Разархивирование репозитория восстановит его способность принимать изменения, а также новые задачи и запросы на слияние. +settings.unarchive.success=Репозиторий был успешно разархивирован. settings.update_avatar_success=Аватар репозитория обновлён. settings.lfs=LFS settings.lfs_filelist=Файлы LFS хранятся в этом репозитории @@ -2346,7 +2428,6 @@ release.releases_for=Релизы %s release.tags_for=Теги %s branch.name=Имя ветки -branch.search=Поиск веток branch.already_exists=Ветка с именем «%s» уже существует. branch.delete_head=Удалить branch.delete=Удалить ветку «%s» @@ -2524,6 +2605,7 @@ users=Пользователи organizations=Организации repositories=Репозитории hooks=Веб-хуки +integrations=Интеграции authentication=Аутентификация emails=Адреса эл. почты пользователей config=Конфигурация @@ -2544,6 +2626,7 @@ dashboard.clean_unbind_oauth=Очистить список незавершён dashboard.clean_unbind_oauth_success=Все незавершённые связи OAuth были удалены. dashboard.task.started=Началось задание: %[1]s dashboard.task.process=Задача: %[1]s +dashboard.task.cancelled=Задача: %[1]s отменена: %[3]s dashboard.task.error=Ошибка в Задаче: %[1]s: %[3]s dashboard.task.finished=Задача: %[1]s, начатая %[2]s завершена dashboard.task.unknown=Неизвестная задача: %[1]s @@ -2696,6 +2779,7 @@ repos.stars=Звезды repos.forks=Форки repos.issues=Задачи repos.size=Размер +repos.lfs_size=Размер LFS packages.package_manage_panel=Управление пакетами packages.total_size=Общий размер: %s @@ -3284,6 +3368,7 @@ status.waiting=Ожидает status.running=Запущено status.success=Успешно status.failure=Неудача +status.cancelled=Отменено status.skipped=Пропущено status.blocked=Заблокировано @@ -3331,6 +3416,21 @@ runs.status=Статус need_approval_desc=Требуется одобрение, чтобы запустить рабочие потоки для запроса на слияние. +variables=Переменные +variables.management=Управление переменными +variables.creation=Добавить переменную +variables.none=Переменных пока нет. +variables.deletion=Удалить переменную +variables.deletion.description=Удаление переменной необратимо, его нельзя отменить. Продолжить? +variables.description=Переменные будут передаваться определенным действиям и не могут быть прочитаны иначе. +variables.id_not_exist=Переменная с идентификатором %d не существует. +variables.edit=Изменить переменную +variables.deletion.failed=Не удалось удалить переменную. +variables.deletion.success=Переменная удалена. +variables.creation.failed=Не удалось добавить переменную. +variables.creation.success=Переменная «%s» добавлена. +variables.update.failed=Не удалось изменить переменную. +variables.update.success=Переменная изменена. [projects] type-1.display_name=Индивидуальный проект @@ -3338,5 +3438,10 @@ type-2.display_name=Проект репозитория type-3.display_name=Проект организации [git.filemode] +changed_filemode=%[1]s → %[2]s +directory=Каталог +normal_file=Обычный файл +executable_file=Исполняемый файл symbolic_link=Символическая ссылка +submodule=Подмодуль diff --git a/options/locale/locale_si-LK.ini b/options/locale/locale_si-LK.ini index fd790b14ccf31..930e147c1560b 100644 --- a/options/locale/locale_si-LK.ini +++ b/options/locale/locale_si-LK.ini @@ -94,6 +94,8 @@ never=කිසි විටෙකත් +archived=සංරක්ෂිත + concept_code_repository=කෝෂ්ඨය concept_user_organization=සංවිධානය @@ -229,7 +231,6 @@ filter=වෙනත් පෙරහන් filter_by_team_repositories=කණ්ඩායම් කෝෂ්ඨ අනුව පෙරන්න show_archived=සංරක්ෂිත -archived=සංරක්ෂිත show_both_archived_unarchived=සංරක්ෂිත සහ අක්රීය දෙකම පෙන්වීම show_only_archived=සංරක්ෂිත පමණක් පෙන්වයි show_only_unarchived=සංරක්ෂිත පමණක් පෙන්වීම @@ -777,6 +778,7 @@ delete_preexisting_content=%sහි ගොනු මකන්න delete_preexisting_success=%sදී සම්මත නොකළ ගොනු මකාදැමුවා blame_prior=මෙම වෙනසට පෙර දොස් බලන්න + transfer.accept=මාරු කිරීම පිළිගන්න transfer.accept_desc=`"%s" වෙත මාරු කරන්න` @@ -1494,7 +1496,6 @@ settings.mirror_settings.push_mirror.remote_url=GIT දුරස්ථ ගබඩ settings.mirror_settings.push_mirror.add=Push මිරර් එකතු කරන්න settings.sync_mirror=සමමුහූර්ත කරන්න -settings.mirror_sync_in_progress=මිරර් සමමුහුර්තකරණය ක්රියාත්මක වෙමින් පවතී. විනාඩියකින් නැවත පරීක්ෂා කරන්න. settings.site=වියමන අඩවිය settings.update_settings=යාවත්කාල සැකසුම් settings.branches.update_default_branch=පෙරනිමි ශාඛාව යාවත්කාල කරන්න @@ -1891,7 +1892,6 @@ release.add_tag_msg=ටැග් පණිවිඩයක් ලෙස නික release.add_tag=ටැග පමණක් සාදන්න branch.name=ශාඛාවේ නම -branch.search=ශාඛා සොයන්න branch.delete_head=මකන්න branch.delete_html=ශාඛාව මකන්න branch.create_branch=%s ශාඛාව සාදන්න diff --git a/options/locale/locale_sk-SK.ini b/options/locale/locale_sk-SK.ini index 4dfb27e7daf6f..6a1df50553a6f 100644 --- a/options/locale/locale_sk-SK.ini +++ b/options/locale/locale_sk-SK.ini @@ -108,6 +108,8 @@ rss_feed=RSS kanál +archived=Archivované + @@ -256,7 +258,6 @@ filter_by_team_repositories=Filtrovať podľa tímových repozitárov feed_of=Informačný kanál „%s“ show_archived=Archivované -archived=Archivované show_both_archived_unarchived=Zobrazujú sa archivované aj nearchivované show_only_archived=Zobrazuje sa iba archivované show_only_unarchived=Zobrazuje sa iba nearchivované @@ -826,6 +827,7 @@ delete_preexisting=Vymazať už existujúce súbory delete_preexisting_content=Vymazať súbory v %s delete_preexisting_success=Vymazané neprijaté súbory v %s + transfer.accept=Prijať prevod transfer.accept_desc=`Previesť do "%s"` transfer.reject=Odmietnuť prevod diff --git a/options/locale/locale_sv-SE.ini b/options/locale/locale_sv-SE.ini index f87f22b806f7f..ce3f7d5d9bec4 100644 --- a/options/locale/locale_sv-SE.ini +++ b/options/locale/locale_sv-SE.ini @@ -83,6 +83,8 @@ error404=Sidan du försöker nå finns inte eller så h +archived=Arkiverade + concept_code_repository=Utvecklingskatalog concept_user_organization=Organisation @@ -215,7 +217,6 @@ search_repos=Hitta en utvecklingskatalog… filter=Övriga Filter show_archived=Arkiverade -archived=Arkiverade show_both_archived_unarchived=Visar både arkiverade och icke arkiverade show_only_archived=Visar endast arkiverade show_only_unarchived=Visa endast icke arkiverade @@ -657,6 +658,7 @@ delete_preexisting=Ta bort befintliga filer delete_preexisting_content=Ta bort filer i %s + desc.private=Privat desc.public=Publik desc.private_template=Privat mall @@ -1249,7 +1251,6 @@ settings.basic_settings=Basinställningar settings.mirror_settings=Inställningar för spegling settings.sync_mirror=Synkronisera nu -settings.mirror_sync_in_progress=Synkronisering utav speglingar pågår. Kontrollera igen om en minut. settings.site=Webbplats settings.update_settings=Uppdatera inställningar settings.advanced_settings=Advancerade Inställningar @@ -1525,7 +1526,6 @@ release.downloads=Nedladdningar release.download_count=Nedladdningar: %s branch.name=Branch namn -branch.search=Sök brancher branch.delete_head=Radera branch.delete_html=Radera branch branch.create_branch=Skapa branchen %s diff --git a/options/locale/locale_tr-TR.ini b/options/locale/locale_tr-TR.ini index e35564ee535ea..ae2cdd9dff1f0 100644 --- a/options/locale/locale_tr-TR.ini +++ b/options/locale/locale_tr-TR.ini @@ -123,6 +123,8 @@ unpin=Sabitlemeyi kaldır artifacts=Yapılar +archived=Arşivlenmiş + concept_system_global=Genel concept_user_individual=Bireysel concept_code_repository=Depo @@ -316,7 +318,6 @@ filter_by_team_repositories=Takım depolarına göre süz feed_of=`"%s" beslemesi` show_archived=Arşivlenmiş -archived=Arşivlenmiş show_both_archived_unarchived=Arşivlenenlerin ve arşivlenmeyenlerin tümü gösteriliyor show_only_archived=Yalnızca arşivlenenler gösteriliyor show_only_unarchived=Yalnızca arşivlenmeyenler gösteriliyor @@ -1005,6 +1006,7 @@ delete_preexisting_success=%s içindeki kabul edilmeyen dosyalar silindi blame_prior=Bu değişiklikten önceki suçu görüntüle author_search_tooltip=En fazla 30 kullanıcı görüntüler + transfer.accept=Aktarımı Kabul Et transfer.accept_desc=`"%s" tarafına aktar` transfer.reject=Aktarımı Reddet @@ -1496,7 +1498,6 @@ issues.label_description=Etiket açıklaması issues.label_color=Etiket rengi issues.label_exclusive=Özel issues.label_archive=Etiketi Arşivle -issues.label_archive_tooltip=Arşivlenmiş etiketler, bir konuya etiket uygulanırken etiket aramasından çıkarılıyor. Bir konudaki mevcut etiketler bundan etkilenmiyor, böylece eskimiş etiketleri bilgi kaybına uğramadan kullanımdan kaldırabiliyorsunuz. issues.label_exclusive_desc=Kapsam/öğe etiketini, diğer kapsam/ etiketleriyle ayrışık olacak şekilde adlandırın. issues.label_exclusive_warning=Çakışan kapsamlı etiketler, bir konu veya değişiklik isteği etiketleri düzenlenirken kaldırılacaktır. issues.label_count=%d etiket @@ -1980,7 +1981,6 @@ settings.mirror_settings.push_mirror.add=Yansı Gönderimi Ekle settings.mirror_settings.push_mirror.edit_sync_time=Yansı eşzamanlama aralığını düzenle settings.sync_mirror=Şimdi Eşitle -settings.mirror_sync_in_progress=Yansı senkronizasyonu devam ediyor. Bir dakika sonra tekrar kontrol edin. settings.site=Web Sitesi settings.update_settings=Ayarları Güncelle settings.update_mirror_settings=Yansı Ayarları Güncelle @@ -2473,7 +2473,6 @@ release.releases_for=%s sürümleri release.tags_for=%s etiketleri branch.name=Dal Adı -branch.search=Dalları ara branch.already_exists=`"%s" isimli bir dal zaten mevcut.` branch.delete_head=Sil branch.delete=`"%s" Dalını Sil` diff --git a/options/locale/locale_uk-UA.ini b/options/locale/locale_uk-UA.ini index be686dcdcc293..c1081769b2b8f 100644 --- a/options/locale/locale_uk-UA.ini +++ b/options/locale/locale_uk-UA.ini @@ -95,6 +95,8 @@ never=Ніколи +archived=Архівовані + concept_code_repository=Репозиторій concept_user_organization=Організація @@ -243,7 +245,6 @@ filter_by_team_repositories=Фільтрувати за репозиторіям feed_of=`Стрічка "%s"` show_archived=Архівовані -archived=Архівовані show_both_archived_unarchived=Показано архівовані і не архівовані show_only_archived=Показано тільки архівовані show_only_unarchived=Показано тільки не архівовані @@ -798,6 +799,7 @@ delete_preexisting_content=Видалити файли з %s delete_preexisting_success=Видалено неприйняті файли в %s blame_prior=Переглянути анотацію, що передує цій зміні + transfer.accept=Дозволити трансфер transfer.accept_desc=`Перемістити до "%s"` transfer.reject=Відхилити трансфер @@ -1545,7 +1547,6 @@ settings.mirror_settings.push_mirror.remote_url=URL віддаленого ре settings.mirror_settings.push_mirror.add=Додати Push дзеркало settings.sync_mirror=Синхронізувати зараз -settings.mirror_sync_in_progress=Синхронізуються репозиторії-дзеркала. Зачекайте хвилину і обновіть сторінку. settings.site=Веб-сайт settings.update_settings=Оновити налаштування settings.branches.update_default_branch=Оновити гілку за замовчуванням @@ -1944,7 +1945,6 @@ release.add_tag_msg=Використовуйте заголовок і зміс release.add_tag=Створити тільки мітку branch.name=Ім'я гілки -branch.search=Пошук гілок branch.delete_head=Видалити branch.delete_html=Видалити гілку branch.create_branch=Створити гілку %s diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index 0cd71af710733..856a8e68073ac 100644 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -4,6 +4,7 @@ explore=探索 help=帮助 logo=徽标 sign_in=登录 +sign_in_with_provider=使用 %s 登录 sign_in_or=或 sign_out=退出 sign_up=注册 @@ -79,6 +80,9 @@ milestones=里程碑 ok=确定 cancel=取消 +retry=重试 +rerun=重新运行 +rerun_all=重新运行所有任务 save=保存 add=添加 add_all=添加所有 @@ -89,9 +93,11 @@ edit=编辑 enabled=启用 disabled=禁用 +locked=已锁定 copy=复制 copy_url=复制网址 +copy_hash=复制哈希值 copy_content=复制内容 copy_branch=复制分支名 copy_success=复制成功! @@ -107,6 +113,7 @@ step2=第二步: error=错误 error404=您正尝试访问的页面 不存在您尚未被授权 查看该页面。 +go_back=返回 never=从不 unknown=未知 @@ -114,12 +121,23 @@ unknown=未知 rss_feed=RSS 订阅源 pin=固定 +unpin=取消置顶 +artifacts=制品 +archived=已归档 + +concept_system_global=全局 +concept_user_individual=个人 concept_code_repository=仓库 concept_user_organization=组织 +show_timestamps=显示时间戳 +show_log_seconds=显示秒数 +show_full_screen=全屏显示 +download_logs=下载日志 +confirm_delete_selected=确认删除所有选中项目? name=名称 value=值 @@ -158,6 +176,7 @@ string.desc=Z - A [error] occurred=发生了一个错误 +report_message=如果您确定这是一个 Gitea bug,请在 GitHub 上搜索问题,或在必要时创建一个新工单。 missing_csrf=错误的请求:没有 CSRF 令牌 invalid_csrf=错误的请求:无效的 CSRF 令牌 not_found=找不到目标。 @@ -166,6 +185,7 @@ network_error=网络错误 [startpage] app_desc=一款极易搭建的自助 Git 服务 install=易安装 +install_desc=通过 二进制 来运行;或者通过 docker 来运行;或者通过 安装包 来运行 platform=跨平台 platform_desc=任何 Go 语言 支持的平台都可以运行 Gitea,包括 Windows、Mac、Linux 以及 ARM。挑一个您喜欢的就行! lightweight=轻量级 @@ -210,6 +230,7 @@ repo_path_helper=所有远程 Git 仓库将保存到此目录。 lfs_path=LFS根目录 lfs_path_helper=存储为Git LFS的文件将被存储在此目录。留空禁用LFS run_user=以用户名运行 +run_user_helper=输入 Gitea 运行的操作系统用户名。请注意,此用户必须具有对仓库根路径的访问权限。 domain=服务器域名 domain_helper=服务器的域名或主机地址。 ssh_port=SSH 服务端口 @@ -281,6 +302,8 @@ invalid_password_algorithm=无效的密码哈希算法 password_algorithm_helper=设置密码散列算法。算法有不同的要求和强度。 argon2 算法相当安全,但使用大量内存,因此可能不适合小型系统。 enable_update_checker=启用更新检查 enable_update_checker_helper=通过连接到 gitea.io 定期检查新版本发布。 +env_config_keys=环境配置 +env_config_keys_prompt=以下环境变量也将应用于您的配置文件: [home] uname_holder=用户名或邮箱 @@ -298,7 +321,6 @@ filter_by_team_repositories=按团队仓库筛选 feed_of=`"%s"的源` show_archived=已归档 -archived=已归档 show_both_archived_unarchived=显示已归档和未归档的 show_only_archived=只显示已归档的 show_only_unarchived=只显示未归档的 @@ -315,6 +337,7 @@ repos=仓库 users=用户 organizations=组织 search=搜索 +go_to=转到 code=代码 search.type.tooltip=搜索类型 search.fuzzy=模糊 @@ -343,6 +366,7 @@ remember_me=记住此设备 forgot_password_title=忘记密码 forgot_password=忘记密码? sign_up_now=还没帐户?马上注册。 +sign_up_successful=帐户创建成功。欢迎! confirmation_mail_sent_prompt=一封新的确认邮件已经被发送至 %s,请检查您的收件箱并在 %s 内完成确认注册操作。 must_change_password=更新您的密码 allow_password_change=要求用户更改密码(推荐) @@ -350,6 +374,7 @@ reset_password_mail_sent_prompt=确认电子邮件已被发送到 %s。 active_your_account=激活您的帐户 account_activated=帐户已激活 prohibit_login=禁止登录 +prohibit_login_desc=您的帐户被禁止登录,请与网站管理员联系。 resent_limit_prompt=您请求发送激活邮件过于频繁,请等待 3 分钟后再试! has_unconfirmed_mail=%s 您好,系统检测到您有一封发送至 %s 但未被确认的邮件。如果您未收到激活邮件,或需要重新发送,请单击下方的按钮。 resend_mail=单击此处重新发送确认邮件 @@ -357,8 +382,10 @@ email_not_associate=您输入的邮箱地址未被关联到任何帐号! send_reset_mail=发送账户恢复邮件 reset_password=账户恢复 invalid_code=此确认密钥无效或已过期。 +invalid_code_forgot_password=你的确认码无效或者已过期,点击 这里 开始新的会话。 invalid_password=您的密码与用于创建账户的密码不匹配。 reset_password_helper=恢复账户 +reset_password_wrong_user=您以 %s 登录,但恢复账号链接是用于 %s。 password_too_short=密码长度不能少于 %d 位。 non_local_account=非本地帐户不能通过 Gitea 的 web 界面更改密码。 verify=验证 @@ -383,6 +410,7 @@ openid_connect_title=连接到现有的帐户 openid_connect_desc=所选的 OpenID URI 未知。在这里关联一个新帐户。 openid_register_title=创建新帐户 openid_register_desc=所选的 OpenID URI 未知。在这里关联一个新帐户。 +openid_signin_desc=输入您的OpenID地址。例如:alice.openid.example.org 或 https://openid.example.org/alice. disable_forgot_password_mail=由于未设置电子邮件,帐户恢复被禁用。 请联系您的站点管理员。 disable_forgot_password_mail_admin=帐户恢复仅在设置电子邮件后可用。 请设置电子邮件以启用帐户恢复。 email_domain_blacklisted=您不能使用您的电子邮件地址注册。 @@ -392,7 +420,9 @@ authorize_application_created_by=此应用由%s创建。 authorize_application_description=如果您允许,它将能够读取和修改您的所有帐户信息,包括私人仓库和组织。 authorize_title=授权 %s 访问您的帐户? authorization_failed=授权失败 +authorization_failed_desc=因为检测到无效请求,授权失败。请尝试联系您授权应用的管理员。 sspi_auth_failed=SSPI 认证失败 +password_pwned=此密码出现在 被盗密码 列表上并且曾经被公开。 请使用另一个密码再试一次。 password_pwned_err=无法完成对 HaveIBeenPwned 的请求 [mail] @@ -407,6 +437,7 @@ activate_account.text_1=%[1]s 您好,感谢注册 %[2]s ! activate_account.text_2=请在 %s 时间内,点击以下链接激活您的账户: activate_email=请验证您的邮箱地址 +activate_email.title=%s,请验证您的邮箱 activate_email.text=请在 %s 时间内,点击以下链接,以验证你的电子邮件地址: register_notify=欢迎来到 Gitea @@ -511,6 +542,7 @@ lang_select_error=从列表中选出语言 username_been_taken=用户名已被使用。 username_change_not_local_user=非本地用户不允许更改用户名。 +username_has_not_been_changed=用户名未更改 repo_name_been_taken=仓库名称已被使用。 repository_force_private=“强制私有”已启用:私有仓库不能被公开。 repository_files_already_exist=此仓库已存在文件。请联系系统管理员。 @@ -559,6 +591,7 @@ target_branch_not_exist=目标分支不存在。 [user] change_avatar=修改头像 +joined_on=加入于 %s repositories=仓库列表 activity=公开活动 followers=关注者 @@ -574,6 +607,8 @@ user_bio=简历 disabled_public_activity=该用户已隐藏活动记录。 email_visibility.limited=所有已认证用户均可看到您的电子邮件地址 email_visibility.private=只有你本人和管理员可以看到你的电子邮件地址 +show_on_map=在地图上显示这个位置 +settings=用户设置 form.name_reserved=用户名 "%s" 被保留。 form.name_pattern_not_allowed=用户名中不允许使用 "%s" 格式。 @@ -595,9 +630,13 @@ delete=删除帐户 twofa=两步验证 account_link=已绑定帐户 organization=组织 +uid=UID webauthn=安全密钥 public_profile=公开信息 +biography_placeholder=告诉我们一点您自己! (您可以使用Markdown) +location_placeholder=与他人分享你的大概位置 +profile_desc=控制您的个人资料对其他用户的显示方式。您的主要电子邮件地址将用于通知、密码恢复和基于网页界面的 Git 操作 password_username_disabled=不允许非本地用户更改他们的用户名。更多详情请联系您的系统管理员。 full_name=自定义名称 website=个人网站 @@ -609,6 +648,8 @@ update_language_not_found=语言 %s 不可用。 update_language_success=语言已更新。 update_profile_success=您的资料信息已经更新 change_username=您的用户名已更改。 +change_username_prompt=注意:更改您的用户名也更改您的帐户 URL。 +change_username_redirect_prompt=在其他用户使用您的旧用户名注册前,此旧用户名将会重定向到您的新用户名 continue=继续操作 cancel=取消操作 language=界面语言 @@ -633,6 +674,7 @@ comment_type_group_project=项目 comment_type_group_issue_ref=工单引用 saved_successfully=您的设置已成功保存。 privacy=隐私设置 +keep_activity_private=隐藏个人资料页面中的活动 keep_activity_private_popup=使活动仅对您和管理员可见 lookup_avatar_by_mail=从电子邮箱地址查找头像 @@ -642,12 +684,14 @@ choose_new_avatar=选择新的头像 update_avatar=更新头像 delete_current_avatar=删除当前头像 uploaded_avatar_not_a_image=上传的文件不是一张图片。 +uploaded_avatar_is_too_big=上传的文件大小(%d KiB) 超过最大限制(%d KiB)。 update_avatar_success=您的头像已更新。 update_user_avatar_success=用户头像已更新。 change_password=更新密码 old_password=当前密码 new_password=新的密码 +retype_new_password=确认新密码 password_incorrect=当前密码不正确! change_password_success=您的密码已更新。从现在开始使用您的新密码登录。 password_change_disabled=非本地帐户不能通过 Gitea 的 web 界面更改密码。 @@ -656,6 +700,7 @@ emails=邮箱地址 manage_emails=管理邮箱地址 manage_themes=选择默认主题 manage_openid=管理 OpenID 地址 +email_desc=您的主要电子邮件地址将用于通知、密码恢复,基于网页界面的Git操作(只要它不是设置为隐藏的)。 theme_desc=这将是您在整个网站上的默认主题。 primary=主要 activated=已激活 @@ -663,6 +708,7 @@ requires_activation=需要激活 primary_email=设为主要邮件地址 activate_email=发送激活邮件 activations_pending=等待激活 +can_not_add_email_activations_pending=有一个待处理的激活请求,请稍等几分钟后再尝试添加新的电子邮件地址。 delete_email=移除 email_deletion=移除电子邮件地址 email_deletion_desc=电子邮箱地址和相关信息将会被删除。使用此电子邮箱地址发送的Git提交将会保留,继续? @@ -681,6 +727,7 @@ add_email_success=新的电子邮件地址已添加。 email_preference_set_success=电子邮件首选项已成功设置。 add_openid_success=新的 OpenID 地址已添加。 keep_email_private=隐藏电子邮件地址 +keep_email_private_popup=这将会隐藏您的电子邮件地址,不仅在您的个人资料中,还在您使用Web界面创建拉取请求或编辑文件时。已推送的提交将不会被修改。 openid_desc=OpenID 让你可以将认证转发到外部服务。 manage_ssh_keys=管理 SSH 密钥 @@ -743,6 +790,8 @@ ssh_principal_deletion_desc=删除此 SSH 证书规则将取消它对您的账 ssh_key_deletion_success=GPG 密钥已被删除。 gpg_key_deletion_success=GPG 密钥已被删除。 ssh_principal_deletion_success=此规则删除成功。 +added_on=添加于 %s +valid_until_date=有效期至 %s valid_forever=永久有效 last_used=上次使用在 no_activity=没有最近活动 @@ -757,7 +806,9 @@ ssh_disabled=SSH 被禁用 ssh_signonly=SSH 目前已禁用,因此这些密钥仅用于提交签名验证。 ssh_externally_managed=此 SSH 密钥是由外部管理的 manage_social=管理关联社交帐户 +social_desc=这些社交账户可以用来登录您的账户。确保您认识它们中的所有账户。 unbind=取消链接 +unbind_success=社交账户已成功移除。 manage_access_token=管理 Access Token generate_new_token=生成新的令牌 @@ -772,8 +823,16 @@ access_token_deletion_cancel_action=取消 access_token_deletion_confirm_action=刪除 access_token_deletion_desc=删除令牌将撤销程序对您账户的访问权限。此操作无法撤消。是否继续? delete_token_success=令牌已经被删除。使用该令牌的应用将不再能够访问你的账号。 +repo_and_org_access=仓库和组织访问权限 +permissions_public_only=仅公开 +permissions_access_all=全部(公开、私有和受限) +select_permissions=选择权限 permission_no_access=无访问权限 -permission_read=已读消息 +permission_read=可读 +permission_write=读写 +access_token_desc=所选令牌权限仅限于对应的 API 路由的授权。阅读 文档 以获取更多信息。 +at_least_one_permission=你需要选择至少一个权限才能创建令牌 +permissions_list=权限: manage_oauth2_applications=管理 OAuth2 应用程序 edit_oauth2_application=编辑 OAuth2 应用程序 @@ -783,26 +842,35 @@ remove_oauth2_application_desc=删除 OAuth2 应用将撤销所有签名的访 remove_oauth2_application_success=该应用已被删除。 create_oauth2_application=创建新的 OAuth2 应用程序 create_oauth2_application_button=创建应用 +create_oauth2_application_success=您已成功创建了一个新的 OAuth2 应用。 +update_oauth2_application_success=您已成功更新了此 OAuth2 应用。 oauth2_application_name=应用名称 oauth2_confidential_client=机密客户端。是否是能够维持凭据机密性的应用,比如网页应用程序。如果是本地应用程序请不要勾选,包括桌面和移动端应用。 +oauth2_redirect_uris=重定向 URI。每行一个 URI。 save_application=保存 oauth2_client_id=客户端ID oauth2_client_secret=客户端密钥 oauth2_regenerate_secret=重新生成密钥 oauth2_regenerate_secret_hint=您的密钥已丢失? +oauth2_client_secret_hint=您离开或刷新此页面后将不会再显示此密钥。请确保您已保存它。 oauth2_application_edit=编辑 oauth2_application_create_description=OAuth2 应用允许您的第三方应用程序访问此实例的用户帐户。 +oauth2_application_remove_description=移除一个OAuth2应用将会阻止它访问此实例上的已授权用户账户。是否继续? +oauth2_application_locked=如果配置启用,Gitea预注册一些OAuth2应用程序。 为了防止意外的行为, 这些应用既不能编辑也不能删除。请参阅OAuth2文档以获取更多信息。 authorized_oauth2_applications=已授权的 OAuth2 应用 +authorized_oauth2_applications_description=您已授予这些第三方应用程序访问您的个人 Gitea 账户的权限。请撤销那些您不再需要的应用程序的访问权限。 revoke_key=撤销 revoke_oauth2_grant=撤回权限 revoke_oauth2_grant_description=确定撤销此三方应用程序的授权,并阻止此应用程序访问您的数据? +revoke_oauth2_grant_success=成功撤销了访问权限。 twofa_desc=两步验证可以加强你的账号安全性。 twofa_is_enrolled=你的账号已启用了两步验证。 twofa_not_enrolled=你的账号未开启两步验证。 twofa_disable=禁用两步认证 twofa_scratch_token_regenerate=重新生成初始令牌 +twofa_scratch_token_regenerated=您的临时令牌现在是 %s。将其存放在安全的地方,它将不会再次显示。 twofa_enroll=启用两步验证 twofa_disable_note=如果需要, 可以禁用双因素身份验证。 twofa_disable_desc=关掉两步验证会使得您的账号不安全,继续执行? @@ -829,8 +897,10 @@ remove_account_link=删除已绑定的账号 remove_account_link_desc=删除已绑定帐户将吊销其对您的 Gitea 帐户的访问权限。继续? remove_account_link_success=已取消绑定帐户。 +hooks.desc=添加 Webhooks,它们将会在您拥有的所有仓库上触发 orgs_none=您现在还不是任何组织的成员。 +repos_none=你并不拥有任何仓库。 delete_account=删除当前帐户 delete_prompt=此操作将永久删除您的用户帐户。它 不能 被撤消。 @@ -849,9 +919,12 @@ visibility=用户可见性 visibility.public=公开 visibility.public_tooltip=对所有人可见 visibility.limited=受限 +visibility.limited_tooltip=仅对已认证的用户可见 visibility.private=私有 +visibility.private_tooltip=仅对您已加入的组织的成员可见。 [repo] +new_repo_helper=代码仓库包含了所有的项目文件,包括版本历史记录。已经在其他地方托管了一个?迁移仓库。 owner=拥有者 owner_helper=由于最大仓库数量限制,一些组织可能不会显示在下拉列表中。 repo_name=仓库名称 @@ -863,6 +936,7 @@ template_helper=设置仓库为模板仓库 template_description=模板仓库让用户通过拷贝目录结构,文件和可选设置来生成仓库。 visibility=可见性 visibility_description=只有组织所有人或拥有权利的组织成员才能看到。 +visibility_helper=将仓库设为私有 visibility_helper_forced=站点管理员强制要求新仓库为私有。 visibility_fork_helper=(修改该值将会影响到所有派生仓库) clone_helper=不知道如何克隆?查看帮助 。 @@ -871,6 +945,9 @@ fork_from=派生自 already_forked=你已经派生过 %s fork_to_different_account=派生到其他账号 fork_visibility_helper=无法更改派生仓库的可见性。 +fork_branch=要克隆到 Fork 的分支 +all_branches=所有分支 +fork_no_valid_owners=这个代码仓库无法被派生,因为没有有效的所有者。 use_template=使用此模板 clone_in_vsc=在 VS Code 中克隆 download_zip=下载 ZIP @@ -899,6 +976,7 @@ trust_model_helper_collaborator_committer=协作者+提交者:信任协作者 trust_model_helper_default=默认:使用此安装的默认信任模型 create_repo=创建仓库 default_branch=默认分支 +default_branch_label=默认 default_branch_helper=默认分支是用于合并请求和代码提交的基础分支。 mirror_prune=修剪 mirror_prune_desc=删除过时的远程跟踪引用 @@ -907,6 +985,7 @@ mirror_interval_invalid=镜像间隔无效。 mirror_sync_on_commit=推送提交时同步 mirror_address=从 URL 克隆 mirror_address_desc=在授权框中输入必要的凭据。 +mirror_address_url_invalid=URL无效。请检查您所输入的URL是否正确。 mirror_lfs=大文件存储 (LFS) mirror_lfs_desc=镜像 LFS 数据。 mirror_lfs_endpoint=LFS 网址 @@ -917,6 +996,7 @@ mirror_password_blank_placeholder=(未设置) mirror_password_help=更改用户名以删除已储存的密码。 watchers=关注者 stargazers=称赞者 +stars_remove_warning=这将清除此仓库的所有点赞数。 forks=派生仓库 reactions_more=再加载 %d unit_disabled=站点管理员已禁用此仓库单元。 @@ -931,8 +1011,14 @@ delete_preexisting=删除已存在的文件 delete_preexisting_content=删除 %s 中的文件 delete_preexisting_success=删除 %s 中未收录的文件 blame_prior=查看此更改前的 blame +blame.ignore_revs=忽略 .git-blame-ignore-revs 的修订。点击 绕过 并查看正常的 Blame 视图。 +blame.ignore_revs.failed=忽略 .git-blame-ignore-revs 版本失败。 author_search_tooltip=最多显示30个用户 +tree_path_not_found_commit=路径%[1]s 在提交 %[2]s 中不存在 +tree_path_not_found_branch=路径 %[1]s 不存在于分支 %[2]s 中。 +tree_path_not_found_tag=路径 %[1]s 不存在于标签 %[2]s 中 + transfer.accept=接受转移 transfer.accept_desc=`转移到 "%s"` transfer.reject=拒绝转移 @@ -997,6 +1083,7 @@ migrated_from_fake=从 %[1]s 迁移成功 migrate.migrate=从 %s 迁移 migrate.migrating=正在从 %s 迁移... migrate.migrating_failed=从 %s 迁移失败。 +migrate.migrating_failed.error=迁移失败:%s migrate.migrating_failed_no_addr=迁移失败。 migrate.github.description=从 github.com 或其他 GitHub 实例迁移数据 migrate.git.description=从任意 Git 服务迁移仓库。 @@ -1013,6 +1100,8 @@ migrate.migrating_labels=迁移标签 migrate.migrating_releases=迁移发布 migrate.migrating_issues=迁移工单 migrate.migrating_pulls=迁移合并请求 +migrate.cancel_migrating_title=取消迁移 +migrate.cancel_migrating_confirm=您想要取消此次迁移吗? mirror_from=镜像自地址 forked_from=派生自 @@ -1084,11 +1173,13 @@ video_not_supported_in_browser=您的浏览器不支持使用 HTML5 'video' 标 audio_not_supported_in_browser=您的浏览器不支持使用 HTML5 'video' 标签。 stored_lfs=存储到Git LFS symbolic_link=符号链接 +executable_file=可执行文件 commit_graph=提交图 commit_graph.select=选择分支 commit_graph.hide_pr_refs=隐藏合并请求 commit_graph.monochrome=黑白 commit_graph.color=彩色 +commit.contained_in=这个提交包含在: blame=Blame download_file=下载文件 normal_view=普通视图 @@ -1138,6 +1229,8 @@ editor.filename_is_invalid=文件名 %s 无效 editor.branch_does_not_exist=此仓库中不存在名为 %s 的分支。 editor.branch_already_exists=此仓库已存在名为 %s 的分支。 editor.directory_is_a_file=%s 已经作为文件名在此仓库中存在。 +editor.file_is_a_symlink=`"%s" 是一个符号链接,无法在 web 编辑器中编辑` +editor.filename_is_a_directory=此仓库中已存在名为“%s” 的目录。 editor.file_editing_no_longer_exists=正在编辑的文件 %s 已不存在。 editor.file_deleting_no_longer_exists=正在删除的文件 %s 已不存在。 editor.file_changed_while_editing=文件内容在您进行编辑时已经发生变动。单击此处 查看变动的具体内容,或者 再次提交 覆盖已发生的变动。 @@ -1179,6 +1272,7 @@ commits.signed_by_untrusted_user=由未授信的用户签名 commits.signed_by_untrusted_user_unmatched=由与提交者不匹配的未授信的用户签名 commits.gpg_key_id=GPG 密钥 ID commits.ssh_key_fingerprint=SSH 密钥指纹 +commits.view_path=在历史记录中的此处查看 commit.operations=操作 commit.revert=还原 @@ -1306,7 +1400,12 @@ issues.delete_branch_at=`于 %[2]s 删除了分支 %[1]s` issues.filter_label=标签筛选 issues.filter_label_exclude=`使用 alt + 鼠标左键 / 回车 排除标签` issues.filter_label_no_select=所有标签 +issues.filter_label_select_no_label=无标签 issues.filter_milestone=里程碑筛选 +issues.filter_milestone_all=所有里程碑 +issues.filter_milestone_none=无里程碑 +issues.filter_milestone_open=进行中的里程碑 +issues.filter_milestone_closed=已关闭的里程碑 issues.filter_project=项目 issues.filter_project_all=所有项目 issues.filter_project_none=暂无项目 @@ -1355,6 +1454,7 @@ issues.next=下一页 issues.open_title=开启中 issues.closed_title=已关闭 issues.draft_title=草稿 +issues.num_comments_1=%d 评论 issues.num_comments=%d 条评论 issues.commented_at=`评论于 %s` issues.delete_comment_confirm=您确定要删除该条评论吗? @@ -1363,6 +1463,7 @@ issues.context.quote_reply=引用回复 issues.context.reference_issue=在新工单中引用 issues.context.edit=编辑 issues.context.delete=刪除 +issues.no_content=没有提供说明。 issues.close=关闭工单 issues.close_comment_issue=评论并关闭 issues.reopen_issue=重新开启 @@ -1379,8 +1480,13 @@ issues.ref_closed_from=`关闭了这个工单 %[4]s 重新打开这个工单 %[4]s %[2]s` issues.ref_from=`来自 %[1]s` issues.author=作者 +issues.author_helper=此用户是作者。 issues.role.owner=管理员 +issues.role.owner_helper=该用户是该仓库的所有者。 issues.role.member=普通成员 +issues.role.collaborator=协作者 +issues.role.first_time_contributor=首次贡献者 +issues.role.contributor=贡献者 issues.re_request_review=再次请求审核 issues.is_stale=此评审之后代码有更新 issues.remove_request_review=移除审核请求 @@ -1395,6 +1501,9 @@ issues.label_title=标签名称 issues.label_description=标签描述 issues.label_color=标签颜色 issues.label_exclusive=独有 +issues.label_archive=归档标签 +issues.label_archived_filter=显示存档标签 +issues.label_archive_tooltip=在标签搜索时,默认情况下存档标签将被排除在外。 issues.label_exclusive_desc=命名标签为 scope/item 以使其与其他以 scope/ 开头的标签互斥。 issues.label_exclusive_warning=在编辑工单或合并请求的标签时,任何冲突的范围标签都将被删除。 issues.label_count=%d 个标签 @@ -1414,6 +1523,10 @@ issues.attachment.open_tab=`在新的标签页中查看 '%s'` issues.attachment.download=`点击下载 '%s'` issues.subscribe=订阅 issues.unsubscribe=取消订阅 +issues.unpin_issue=取消置顶 +issues.max_pinned=您不能置顶更多工单 +issues.pin_comment=于 %s 被置顶 +issues.unpin_comment=于 %s 取消置顶 issues.lock=锁定对话 issues.unlock=解锁对话 issues.lock.unknown_reason=由于未知原因无法锁定。 @@ -1445,6 +1558,7 @@ issues.tracking_already_started=`你已经开始对 另一个工单 issues.stop_tracking=停止计时器 issues.stop_tracking_history=`停止工作 %s` issues.cancel_tracking=放弃 +issues.cancel_tracking_history=`取消时间跟踪 %s` issues.add_time=手动添加时间 issues.del_time=删除此时间跟踪日志 issues.add_time_short=添加时间 @@ -1468,6 +1582,7 @@ issues.due_date_form=yyyy年mm月dd日 issues.due_date_form_add=设置到期时间 issues.due_date_form_edit=编辑 issues.due_date_form_remove=删除 +issues.due_date_not_writer=您需要该仓库的写权限才能更新工单的到期日期。 issues.due_date_not_set=未设置到期时间。 issues.due_date_added=于 %[2]s 设置到期时间为 %[1]s issues.due_date_modified=将到期日从 %[2]s 修改为 %[1]s %[3]s @@ -1522,6 +1637,8 @@ issues.review.pending.tooltip=此评论目前对其他用户不可见。 若要 issues.review.review=评审 issues.review.reviewers=评审人 issues.review.outdated=已过期 +issues.review.option.show_outdated_comments=显示过时的评论 +issues.review.option.hide_outdated_comments=隐藏过时的评论 issues.review.show_outdated=显示过时的 issues.review.hide_outdated=隐藏过时的 issues.review.show_resolved=显示已解决的 @@ -1561,6 +1678,11 @@ pulls.switch_comparison_type=切换比较类型 pulls.switch_head_and_base=切换 head 和 base pulls.filter_branch=过滤分支 pulls.no_results=未找到结果 +pulls.show_all_commits=显示所有提交 +pulls.show_changes_since_your_last_review=显示自您上次审核以来的更改 +pulls.showing_only_single_commit=仅显示提交 %[1]s 的更改 +pulls.showing_specified_commit_range=仅显示 %[1]s...%[2]s 之间的更改 +pulls.filter_changes_by_commit=按提交筛选 pulls.nothing_to_compare=分支内容相同,无需创建合并请求。 pulls.nothing_to_compare_and_allow_empty_pr=这些分支是相等的,此合并请求将为空。 pulls.has_pull_request=这些分支之间的合并请求已存在: %[2]s#%[3]d @@ -1592,6 +1714,7 @@ pulls.is_empty=此分支上的更改已经在目标分支上。这将是一个 pulls.required_status_check_failed=一些必要的检查没有成功 pulls.required_status_check_missing=缺少一些必要的检查。 pulls.required_status_check_administrator=作为管理员,您仍可合并此合并请求 +pulls.blocked_by_approvals=此合并请求没有通过审批。已获取审批数%d个,共需要审批数%d个。 pulls.can_auto_merge_desc=该合并请求可以进行自动合并操作。 pulls.cannot_auto_merge_desc=该合并请求存在冲突,无法进行自动合并操作。 pulls.cannot_auto_merge_helper=手动合并解决此冲突 @@ -1667,6 +1790,7 @@ pulls.delete.title=删除此拉取请求? pulls.delete.text=你真的要删除这个拉取请求吗? (这将永久删除所有内容。如果你打算将内容存档,请考虑关闭它) +pull.deleted_branch=(已删除): %s milestones.new=新的里程碑 milestones.closed=于 %s关闭 @@ -1690,11 +1814,17 @@ milestones.edit_success=里程碑 %s 已经更新。 milestones.deletion=删除里程碑 milestones.deletion_desc=删除该里程碑将会移除所有工单中相关的信息。是否继续? milestones.deletion_success=里程碑已被删除。 +milestones.filter_sort.earliest_due_data=到期日从远到近 +milestones.filter_sort.latest_due_date=到期日从近到远 milestones.filter_sort.least_complete=完成度从低到高 milestones.filter_sort.most_complete=完成度从高到低 milestones.filter_sort.most_issues=工单从多到少 milestones.filter_sort.least_issues=工单从少到多 +signing.will_sign=这个提交将用密钥 "%s" 签名。 +signing.wont_sign.never=提交从未签名。 +signing.wont_sign.always=提交总是签名。 +signing.wont_sign.not_signed_in=您还没有登录。 ext_wiki=访问外部百科 ext_wiki.desc=链接到外部 wiki。 @@ -1816,6 +1946,9 @@ settings.hooks=Web 钩子 settings.githooks=管理 Git 钩子 settings.basic_settings=基本设置 settings.mirror_settings=镜像设置 +settings.mirror_settings.docs.pull_mirror_instructions=要创建一个拉取镜像,请参阅: +settings.mirror_settings.docs.doc_link_title=如何镜像仓库? +settings.mirror_settings.docs.pulling_remote_title=从远程仓库拉取代码 settings.mirror_settings.mirrored_repository=镜像库 settings.mirror_settings.direction=方向 settings.mirror_settings.direction.pull=拉取 @@ -1824,11 +1957,15 @@ settings.mirror_settings.last_update=最后更新 settings.mirror_settings.push_mirror.none=未配置推送镜像 settings.mirror_settings.push_mirror.remote_url=Git 远程仓库链接 settings.mirror_settings.push_mirror.add=添加推送镜像 +settings.mirror_settings.push_mirror.edit_sync_time=编辑镜像同步间隔 settings.sync_mirror=同步 -settings.mirror_sync_in_progress=镜像同步正在进行中,请稍后再试。 +settings.pull_mirror_sync_in_progress=正在从远程 %s 拉取更改。 +settings.push_mirror_sync_in_progress=正在推送变更到远程 %s 。 settings.site=网站 settings.update_settings=更新仓库设置 +settings.update_mirror_settings=更新镜像设置 +settings.branches.switch_default_branch=切换默认分支 settings.branches.update_default_branch=更新默认分支 settings.branches.add_new_rule=添加新规则 settings.advanced_settings=高级设置 @@ -1956,12 +2093,14 @@ settings.webhook_deletion_desc=删除 web钩子 将删除其设置和历史记 settings.webhook_deletion_success=Web 钩子删除成功! settings.webhook.test_delivery=测试推送 settings.webhook.test_delivery_desc=用假事件测试这个 web钩子。 +settings.webhook.test_delivery_desc_disabled=要用 虚假事件 测试这个Webhook,请激活它。 settings.webhook.request=请求内容 settings.webhook.response=响应内容 settings.webhook.headers=头信息 settings.webhook.payload=内容 settings.webhook.body=响应体 settings.webhook.replay.description=重放此 webhook。 +settings.webhook.replay.description_disabled=若要重播此 WebHook,请激活它。 settings.webhook.delivery.success=一个事件已被添加到推送队列。可能需要过几秒钟才会显示在推送记录中。 settings.githooks_desc=Git Hook 是 Git 本身提供的功能。您可以在下方编辑 hook 文件以设置自定义操作。 settings.githook_edit_desc=如果钩子未启动,则会显示样例文件中的内容。如果想要删除某个钩子,则提交空白文本即可。 @@ -2023,6 +2162,10 @@ settings.event_pull_request_review=已审核的合并请求 settings.event_pull_request_review_desc=合并请求被批准、拒绝或提出审查意见 settings.event_pull_request_sync=合并请求被同步 settings.event_pull_request_sync_desc=合并请求被同步。 +settings.event_pull_request_review_request=发起合并请求评审 +settings.event_pull_request_review_request_desc=合并请求评审已请求或已取消 +settings.event_pull_request_approvals=合并请求批准 +settings.event_pull_request_merge=合并请求合并 settings.event_package=软件包 settings.event_package_desc=软件包已在仓库中被创建或删除。 settings.branch_filter=分支过滤 @@ -2085,6 +2228,8 @@ settings.protect_disable_push=禁用推送 settings.protect_disable_push_desc=此分支不允许推送。 settings.protect_enable_push=启用推送 settings.protect_enable_push_desc=任何拥有写访问权限的人将被允许推送到此分支(但不能强行推送)。 +settings.protect_enable_merge=启用合并 +settings.protect_enable_merge_desc=任何具有写入权限的人都可以将合并请求合并到此分支中。 settings.protect_whitelist_committers=受白名单限制的推送 settings.protect_whitelist_committers_desc=只有列入白名单的用户或团队才能被允许推送到此分支(但不能强行推送)。 settings.protect_whitelist_deploy_keys=具有推送权限的部署密钥白名单。 @@ -2097,8 +2242,12 @@ settings.protect_merge_whitelist_committers_desc=仅允许白名单用户或团 settings.protect_merge_whitelist_users=合并白名单用户: settings.protect_merge_whitelist_teams=合并白名单团队: settings.protect_check_status_contexts=启用状态检查 +settings.protect_status_check_patterns=状态检查模式: settings.protect_check_status_contexts_desc=要求状态检查通过才能合并,选择必须先通过哪些状态检查才能合并。如果启用,推送的合并请求必须先通过状态检查才能够合并到对应的分支。如果没有选择具体的状态检查上下文,则所有的状态检查都通过才能合并。 settings.protect_check_status_contexts_list=此仓库上周进行过的状态检查 +settings.protect_status_check_matched=匹配 +settings.protect_invalid_status_check_pattern=无效的状态检查规则:“%s”。 +settings.protect_no_valid_status_check_patterns=没有有效的状态检查规则。 settings.protect_required_approvals=所需的批准: settings.protect_required_approvals_desc=只允许合并有足够审核人数的拉取请求。 settings.protect_approvals_whitelist_enabled=批准仅限列入白名单的用户或团队 @@ -2110,6 +2259,8 @@ settings.dismiss_stale_approvals_desc=当新的提交更改合并请求内容被 settings.require_signed_commits=需要签名提交 settings.require_signed_commits_desc=拒绝推送未签名或无法验证的提交到分支 settings.protect_branch_name_pattern=受保护的分支名称模式 +settings.protect_branch_name_pattern_desc=分支保护的名称匹配规则。语法请参阅 文档 。如:main, release/** +settings.protect_patterns=规则 settings.protect_protected_file_patterns=受保护的文件模式(使用分号 ';' 分隔): settings.protect_protected_file_patterns_desc=即使用户有权添加、编辑或删除此分支中的文件,也不允许直接更改受保护的文件。 可以使用分号 (';') 分隔多个模式。 见github.com/gobwas/glob文档了解模式语法。例如: .drone.yml, /docs/**/*.txt settings.protect_unprotected_file_patterns=不受保护的文件模式(使用分号 ';' 分隔): @@ -2147,6 +2298,7 @@ settings.tags.protection.create=保护Git标签 settings.tags.protection.none=没有受保护的Git标签 settings.bot_token=Bot 令牌 settings.chat_id=聊天 ID +settings.thread_id=线程 ID settings.matrix.homeserver_url=主服务器网址 settings.matrix.room_id=房间ID settings.matrix.message_type=消息类型 @@ -2157,6 +2309,10 @@ settings.archive.error=仓库在归档时出现异常。请通过日志获取详 settings.archive.error_ismirror=请不要对镜像仓库归档,谢谢! settings.archive.branchsettings_unavailable=已归档仓库无法进行分支设置。 settings.archive.tagsettings_unavailable=已归档仓库的Git标签设置不可用。 +settings.unarchive.button=撤销仓库归档 +settings.unarchive.header=撤销此仓库归档 +settings.unarchive.text=撤销归档将恢复仓库接收提交、推送,以及新工单和合并请求的能力。 +settings.unarchive.success=仓库已成功撤销归档。 settings.update_avatar_success=仓库头像已经更新。 settings.lfs=LFS settings.lfs_filelist=存储在此仓库中的 LFS 文件 @@ -2223,6 +2379,7 @@ diff.show_more=显示更多 diff.load=加载差异 diff.generated=自动生成的 diff.vendored=vendored +diff.comment.add_line_comment=添加行内评论 diff.comment.placeholder=留下评论 diff.comment.markdown_info=支持使用Markdown格式。 diff.comment.add_single_comment=添加单条评论 @@ -2315,10 +2472,13 @@ branch.protected_deletion_failed=不能删除受保护的分支 "%s"。 branch.default_deletion_failed=不能删除默认分支"%s"。 branch.restore=`还原分支 "%s"` branch.download=`下载分支 "%s"` +branch.rename=`重命名分支 "%s"` branch.included_desc=此分支是默认分支的一部分 branch.included=已包含 branch.create_new_branch=从下列分支创建分支: branch.confirm_create_branch=创建分支 +branch.warning_rename_default_branch=您正在重命名默认分支。 +branch.rename_branch_to=重命名 %s 为: branch.confirm_rename_branch=重命名分支 branch.create_branch_operation=创建分支 branch.new_branch=创建新分支 @@ -2373,6 +2533,7 @@ form.create_org_not_allowed=此账号禁止创建组织 settings=组织设置 settings.options=组织 settings.full_name=组织全名 +settings.email=联系电子邮件 settings.website=网站 settings.location=所在地区 settings.permission=权限 @@ -2422,7 +2583,7 @@ teams.none_access=无访问权限 teams.none_access_helper=成员无法查看此单元或对其执行任何其他操作。 teams.general_access=常规访问 teams.general_access_helper=成员权限将由以下权限表决定。 -teams.read_access=读取 +teams.read_access=可读 teams.read_access_helper=成员可以查看和克隆团队仓库。 teams.write_access=写入 teams.write_access_helper=成员可以查看和推送提交到团队仓库。 @@ -2466,10 +2627,13 @@ teams.invite.description=请点击下面的按钮加入团队。 [admin] dashboard=管理面板 +identity_access=身份及认证 users=帐户管理 organizations=组织管理 +assets=代码资产 repositories=仓库管理 hooks=Web 钩子 +integrations=集成 authentication=认证源 emails=用户邮件 config=应用配置 @@ -2478,6 +2642,7 @@ monitor=监控面板 first_page=首页 last_page=末页 total=总计:%d +settings=管理设置 dashboard.new_version_hint=Gitea %s 现已可用,您正在运行 %s。查看 博客 了解详情。 dashboard.statistic=摘要 @@ -2490,11 +2655,13 @@ dashboard.clean_unbind_oauth=清理未绑定的 OAuth 连接 dashboard.clean_unbind_oauth_success=所有未绑定的 OAuth 连接已被删除。 dashboard.task.started=已开始任务:%[1]s dashboard.task.process=任务: %[1]s +dashboard.task.cancelled=任务: %[1]s 已取消: %[3]s dashboard.task.error=任务中的错误: %[1]s: %[3]s dashboard.task.finished=任务: %[2]s 启动的 %[1]s 已完成 dashboard.task.unknown=未知任务: %[1]s dashboard.cron.started=已开始计划任务:%[1]s dashboard.cron.process=计划任务:%[1]s +dashboard.cron.cancelled=定时任务: %[1]s 已取消: %[3]s dashboard.cron.error=任务中的错误: %s: %[3]s dashboard.cron.finished=任务:%[1]s 已经完成 dashboard.delete_inactive_accounts=删除所有未激活的帐户 @@ -2504,6 +2671,7 @@ dashboard.delete_repo_archives.started=删除所有仓库存档任务已启动 dashboard.delete_missing_repos=删除所有丢失 Git 文件的仓库 dashboard.delete_missing_repos.started=删除所有丢失 Git 文件的仓库任务已启动。 dashboard.delete_generated_repository_avatars=删除生成的仓库头像 +dashboard.sync_repo_branches=将缺少的分支从 git 数据同步到数据库 dashboard.update_mirrors=更新镜像仓库 dashboard.repo_health_check=健康检查所有仓库 dashboard.check_repo_stats=检查所有仓库统计 @@ -2520,6 +2688,7 @@ dashboard.reinit_missing_repos=重新初始化所有丢失的 Git 仓库存在 dashboard.sync_external_users=同步外部用户数据 dashboard.cleanup_hook_task_table=清理 hook_task 表 dashboard.cleanup_packages=清理过期的软件包 +dashboard.cleanup_actions=清理过期的Actions日志和制品 dashboard.server_uptime=服务运行时间 dashboard.current_goroutine=当前 Goroutines 数量 dashboard.current_memory_usage=当前内存使用量 @@ -2557,6 +2726,9 @@ dashboard.gc_lfs=垃圾回收 LFS 元数据 dashboard.stop_zombie_tasks=停止僵尸任务 dashboard.stop_endless_tasks=停止永不停止的任务 dashboard.cancel_abandoned_jobs=取消丢弃的任务 +dashboard.start_schedule_tasks=开始调度任务 +dashboard.sync_branch.started=分支同步已开始 +dashboard.rebuild_issue_indexer=重建工单索引 users.user_manage_panel=用户帐户管理 users.new_account=创建新帐户 @@ -2565,6 +2737,9 @@ users.full_name=全名 users.activated=已激活 users.admin=管理员 users.restricted=受限 +users.reserved=保留 +users.bot=机器人 +users.remote=远程 users.2fa=两步验证 users.repos=仓库数 users.created=创建时间 @@ -2611,6 +2786,7 @@ users.list_status_filter.is_prohibit_login=禁止登录 users.list_status_filter.not_prohibit_login=允许登录 users.list_status_filter.is_2fa_enabled=已启用 2FA users.list_status_filter.not_2fa_enabled=未启用 2FA +users.details=用户详细信息 emails.email_manage_panel=邮件管理 emails.primary=主要的 @@ -2642,10 +2818,12 @@ repos.stars=点赞数 repos.forks=派生数 repos.issues=工单数 repos.size=大小 +repos.lfs_size=LFS 大小 packages.package_manage_panel=软件包管理 packages.total_size=总大小:%s packages.unreferenced_size=未引用大小: %s +packages.cleanup=清理过期数据 packages.owner=所有者 packages.creator=创建者 packages.name=名称 @@ -2792,6 +2970,7 @@ config.disable_router_log=关闭路由日志 config.run_user=以用户名运行 config.run_mode=运行模式 config.git_version=Git 版本 +config.app_data_path=应用数据路径 config.repo_root_path=仓库根目录 config.lfs_root_path=LFS根目录 config.log_file_root_path=日志路径 @@ -2867,6 +3046,7 @@ config.mailer_sendmail_timeout=Sendmail 超时 config.mailer_use_dummy=Dummy config.test_email_placeholder=电子邮址 (例如,test@example.com) config.send_test_mail=发送测试邮件 +config.send_test_mail_submit=发送 config.test_mail_failed=发送测试邮件至 '%s' 时失败:%v config.test_mail_sent=测试邮件已经发送至 '%s'。 @@ -2906,13 +3086,16 @@ config.git_pull_timeout=拉取操作超时 config.git_gc_timeout=GC 操作超时 config.log_config=日志配置 +config.logger_name_fmt=日志:%s config.disabled_logger=禁用 config.access_log_mode=访问日志模式 +config.access_log_template=访问日志模板 config.xorm_log_sql=日志 SQL config.get_setting_failed=获取设置 %s 失败 config.set_setting_failed=设置 %s 失败 +monitor.stats=统计 monitor.cron=Cron 任务 monitor.name=任务名称 @@ -2922,6 +3105,8 @@ monitor.previous=上次执行时间 monitor.execute_times=执行次数 monitor.process=运行中进程 monitor.stacktrace=调用栈踪迹 +monitor.processes_count=%d 个进程 +monitor.download_diagnosis_report=下载诊断报告 monitor.desc=进程描述 monitor.start=开始时间 monitor.execute_time=执行时长 @@ -2937,14 +3122,18 @@ monitor.queue.name=名称 monitor.queue.type=类型 monitor.queue.exemplar=数据类型 monitor.queue.numberworkers=工作者数量 +monitor.queue.activeworkers=活跃工作者 monitor.queue.maxnumberworkers=最大工作者数量 monitor.queue.numberinqueue=队列中的数量 +monitor.queue.review_add=查看 / 添加工作者 monitor.queue.settings.title=池设置 monitor.queue.settings.maxnumberworkers=最大工作者数量 monitor.queue.settings.maxnumberworkers.placeholder=当前 %[1]d monitor.queue.settings.maxnumberworkers.error=最大工作者数必须是数字 monitor.queue.settings.submit=更新设置 monitor.queue.settings.changed=设置已更新 +monitor.queue.settings.remove_all_items=移除全部 +monitor.queue.settings.remove_all_items_done=队列中的所有项目已被移除。 notices.system_notice_list=系统提示管理 notices.view_detail_header=查看提示详情 @@ -3080,8 +3269,10 @@ versions.view_all=查看全部 dependency.id=ID dependency.version=版本 alpine.install=要安装包,请运行以下命令: +alpine.repository=仓库信息 alpine.repository.branches=分支 alpine.repository.repositories=仓库管理 +alpine.repository.architectures=架构 cargo.registry=在 Cargo 配置文件中设置此注册中心(例如:~/.cargo/config.toml): cargo.install=要使用 Cargo 安装软件包,请运行以下命令: cargo.details.repository_site=仓库站点 @@ -3111,7 +3302,12 @@ container.labels.value=值 cran.install=要安装包,请运行以下命令: debian.registry=从命令行设置此注册中心: debian.install=要安装包,请运行以下命令: +debian.repository=仓库信息 +debian.repository.distributions=发行版 +debian.repository.components=组件 +debian.repository.architectures=架构 generic.download=从命令行下载软件包: +go.install=通过命令行安装软件包: helm.registry=从命令行设置此注册中心: helm.install=要安装包,请运行以下命令: maven.registry=在您项目的 pom.xml 文件中设置此注册中心: @@ -3133,6 +3329,8 @@ pub.install=要使用 Dart 安装软件包,请运行以下命令: pypi.requires=需要 Python pypi.install=要使用 pip 安装软件包,请运行以下命令: rpm.registry=从命令行设置此注册中心: +rpm.distros.redhat=在基于 RedHat 的发行版 +rpm.distros.suse=在基于 SUSE 的发行版 rpm.install=要安装包,请运行以下命令: rubygems.install=要使用 gem 安装软件包,请运行以下命令: rubygems.install2=或将它添加到 Gemfile: @@ -3157,14 +3355,17 @@ settings.delete.success=软件包已被删除。 settings.delete.error=删除软件包失败。 owner.settings.cargo.title=Cargo 注册中心索引 owner.settings.cargo.initialize=初始化索引 +owner.settings.cargo.initialize.description=使用 Cargo 注册中心时需要一个特殊索引的 Git 仓库。使用此选项将(重新)创建存储库并自动配置它。 owner.settings.cargo.initialize.error=初始化Cargo索引失败: %v owner.settings.cargo.initialize.success=Cargo索引已经成功创建。 owner.settings.cargo.rebuild=重建索引 +owner.settings.cargo.rebuild.description=如果索引与存储的 Cargo 包不同步,重建可能会有用。 owner.settings.cargo.rebuild.error=无法重建 Cargo 索引: %v owner.settings.cargo.rebuild.success=Cargo 索引已成功重建。 owner.settings.cleanuprules.title=管理清理规则 owner.settings.cleanuprules.add=添加清理规则 owner.settings.cleanuprules.edit=编辑清理规则 +owner.settings.cleanuprules.none=没有可用的清理规则。请查阅文档。 owner.settings.cleanuprules.preview=清理规则预览 owner.settings.cleanuprules.preview.overview=%d 个软件包计划被删除。 owner.settings.cleanuprules.preview.none=清理规则与任何软件包都不匹配。 @@ -3183,6 +3384,7 @@ owner.settings.cleanuprules.success.update=清理规则已更新。 owner.settings.cleanuprules.success.delete=清理规则已删除。 owner.settings.chef.title=Chef 注册中心 owner.settings.chef.keypair=生成密钥对 +owner.settings.chef.keypair.description=需要密钥对才能向 Chef 注册中心进行身份验证。如果您之前已经生成过密钥对,生成新的密钥对将丢弃旧的密钥对。 [secrets] secrets=密钥 @@ -3197,6 +3399,7 @@ deletion=删除密钥 deletion.description=删除密钥是永久性的,无法撤消。继续吗? deletion.success=此Secret已被删除。 deletion.failed=删除密钥失败。 +management=密钥管理 [actions] actions=Actions @@ -3208,6 +3411,7 @@ status.waiting=等待中 status.running=正在运行 status.success=成功 status.failure=失败 +status.cancelled=已取消 status.skipped=已忽略 status.blocked=阻塞中 @@ -3224,6 +3428,7 @@ runners.labels=标签 runners.last_online=上次在线时间 runners.runner_title=Runner runners.task_list=最近在此runner上的任务 +runners.task_list.no_tasks=还没有任务。 runners.task_list.run=执行 runners.task_list.status=状态 runners.task_list.repository=仓库 @@ -3244,17 +3449,45 @@ runners.status.idle=空闲 runners.status.active=激活 runners.status.offline=离线 runners.version=版本 +runners.reset_registration_token=重置注册令牌 runners.reset_registration_token_success=成功重置运行器注册令牌 runs.all_workflows=所有工作流 runs.commit=提交 +runs.scheduled=已计划的 +runs.pushed_by=推送者 runs.invalid_workflow_helper=工作流配置文件无效。请检查您的配置文件: %s runs.no_matching_runner_helper=没有匹配的runner:%s +runs.actor=操作者 runs.status=状态 +runs.actors_no_select=所有操作者 +runs.status_no_select=所有状态 +runs.no_results=没有匹配的结果。 +runs.no_runs=工作流尚未运行过。 +workflow.disable=禁用工作流 +workflow.disable_success=工作流 '%s' 已成功禁用。 +workflow.enable=启用工作流 +workflow.enable_success=工作流 '%s' 已成功启用。 +workflow.disabled=工作流已禁用。 need_approval_desc=该工作流由派生仓库的合并请求所触发,需要批准方可运行。 +variables=变量 +variables.management=变量管理 +variables.creation=添加变量 +variables.none=目前还没有变量。 +variables.deletion=删除变量 +variables.deletion.description=删除变量是永久性的,无法撤消。继续吗? +variables.description=变量将被传给特定的 Actions,其它情况将不能读取 +variables.id_not_exist=ID %d 变量不存在。 +variables.edit=编辑变量 +variables.deletion.failed=删除变量失败。 +variables.deletion.success=变量已被删除。 +variables.creation.failed=添加变量失败。 +variables.creation.success=变量 “%s” 添加成功。 +variables.update.failed=编辑变量失败。 +variables.update.success=该变量已被编辑。 [projects] type-1.display_name=个人项目 @@ -3262,5 +3495,10 @@ type-2.display_name=仓库项目 type-3.display_name=组织项目 [git.filemode] +changed_filemode=%[1]s -> %[2]s +directory=目录 +normal_file=普通文件 +executable_file=可执行文件 symbolic_link=符号链接 +submodule=子模块 diff --git a/options/locale/locale_zh-HK.ini b/options/locale/locale_zh-HK.ini index 2cdea9feadc88..dfa048c5ef0b9 100644 --- a/options/locale/locale_zh-HK.ini +++ b/options/locale/locale_zh-HK.ini @@ -55,6 +55,7 @@ enabled=已啟用 + concept_code_repository=儲存庫 @@ -316,6 +317,7 @@ stargazers=稱讚者 forks=複製儲存庫 + desc.private=私有庫 desc.public_template=樣板 diff --git a/options/locale/locale_zh-TW.ini b/options/locale/locale_zh-TW.ini index 3c23f9eb2037e..5764ebb07fcba 100644 --- a/options/locale/locale_zh-TW.ini +++ b/options/locale/locale_zh-TW.ini @@ -118,6 +118,8 @@ pin=固定 unpin=取消固定 +archived=已封存 + concept_code_repository=儲存庫 concept_user_organization=組織 @@ -299,7 +301,6 @@ filter_by_team_repositories=以團隊儲存庫篩選 feed_of=「%s」的訊息來源 show_archived=已封存 -archived=已封存 show_both_archived_unarchived=顯示已封存和未封存 show_only_archived=只顯示已封存 show_only_unarchived=只顯示未封存 @@ -930,6 +931,7 @@ delete_preexisting_success=刪除 %s 中未接管的檔案 blame_prior=檢視此變更前的 Blame author_search_tooltip=最多顯示 30 位使用者 + transfer.accept=同意轉移 transfer.accept_desc=轉移到「%s」 transfer.reject=拒絕轉移 @@ -1817,7 +1819,6 @@ settings.mirror_settings.push_mirror.remote_url=Git 遠端儲存庫 URL settings.mirror_settings.push_mirror.add=新增推送鏡像 settings.sync_mirror=立即同步 -settings.mirror_sync_in_progress=鏡像同步正在進行中。 請稍後再回來看看。 settings.site=網站 settings.update_settings=更新設定 settings.branches.update_default_branch=更新預設分支 @@ -2282,7 +2283,6 @@ release.releases_for=%s 的版本發佈 release.tags_for=%s 的標籤 branch.name=分支名稱 -branch.search=搜尋分支 branch.already_exists=已存在名為「%s」的分支。 branch.delete_head=刪除 branch.delete=刪除分支「%s」 diff --git a/package-lock.json b/package-lock.json index 095bcf7a1c5a2..b279b8c9935d2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,9 +5,9 @@ "packages": { "": { "dependencies": { - "@citation-js/core": "0.6.9", - "@citation-js/plugin-bibtex": "0.6.9", - "@citation-js/plugin-csl": "0.6.9", + "@citation-js/core": "0.7.1", + "@citation-js/plugin-bibtex": "0.7.1", + "@citation-js/plugin-csl": "0.7.1", "@citation-js/plugin-software-formats": "0.6.1", "@claviska/jquery-minicolors": "2.3.6", "@github/markdown-toolbar-element": "2.2.1", @@ -18,7 +18,7 @@ "@webcomponents/custom-elements": "1.6.0", "add-asset-webpack-plugin": "2.0.1", "ansi_up": "6.0.2", - "asciinema-player": "3.6.1", + "asciinema-player": "3.6.2", "clippie": "4.0.6", "css-loader": "6.8.1", "dropzone": "6.0.0-beta.2", @@ -27,18 +27,18 @@ "escape-goat": "4.0.0", "fast-glob": "3.3.1", "jquery": "3.7.1", - "katex": "0.16.8", + "katex": "0.16.9", "license-checker-webpack-plugin": "0.2.1", "lightningcss-loader": "2.1.0", - "mermaid": "10.4.0", + "mermaid": "10.5.0", "mini-css-extract-plugin": "2.7.6", "minimatch": "9.0.3", - "monaco-editor": "0.43.0", + "monaco-editor": "0.44.0", "monaco-editor-webpack-plugin": "7.1.0", "pdfobject": "2.2.12", "pretty-ms": "8.0.0", "sortablejs": "1.15.0", - "swagger-ui-dist": "5.7.2", + "swagger-ui-dist": "5.9.0", "throttle-debounce": "5.0.0", "tinycolor2": "1.6.0", "tippy.js": "6.3.7", @@ -47,7 +47,7 @@ "uint8-to-base64": "0.2.0", "vue": "3.3.4", "vue-bar-graph": "2.0.0", - "vue-loader": "17.2.2", + "vue-loader": "17.3.0", "vue3-calendar-heatmap": "2.0.5", "webpack": "5.88.2", "webpack-cli": "5.1.4", @@ -57,8 +57,8 @@ "@eslint-community/eslint-plugin-eslint-comments": "4.1.0", "@playwright/test": "1.38.1", "@stoplight/spectral-cli": "6.11.0", - "@vitejs/plugin-vue": "4.3.4", - "eslint": "8.49.0", + "@vitejs/plugin-vue": "4.4.0", + "eslint": "8.51.0", "eslint-plugin-array-func": "4.0.0", "eslint-plugin-import": "2.28.1", "eslint-plugin-jquery": "1.5.1", @@ -69,8 +69,8 @@ "eslint-plugin-unicorn": "48.0.1", "eslint-plugin-vitest-globals": "1.4.0", "eslint-plugin-vue": "9.17.0", - "eslint-plugin-vue-scoped-css": "2.5.0", - "eslint-plugin-wc": "2.0.3", + "eslint-plugin-vue-scoped-css": "2.5.1", + "eslint-plugin-wc": "2.0.4", "jsdom": "22.1.0", "markdownlint-cli": "0.37.0", "postcss-html": "1.5.0", @@ -81,7 +81,7 @@ "svgo": "3.0.2", "updates": "15.0.2", "vite-string-plugin": "1.1.2", - "vitest": "0.34.5" + "vitest": "0.34.6" }, "engines": { "node": ">= 18.0.0" @@ -290,9 +290,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.22.16", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz", - "integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", "bin": { "parser": "bin/babel-parser.js" }, @@ -301,9 +301,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.15.tgz", - "integrity": "sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA==", + "version": "7.23.1", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.1.tgz", + "integrity": "sha512-hC2v6p8ZSI/W0HUzh3V8C5g+NwSKzKPtJwSpTjwl0o297GP9+ZLQSkdvHz46CM3LqyoXxq+5G9komY+eSqSO0g==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -317,9 +317,9 @@ "integrity": "sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A==" }, "node_modules/@citation-js/core": { - "version": "0.6.9", - "resolved": "https://registry.npmjs.org/@citation-js/core/-/core-0.6.9.tgz", - "integrity": "sha512-ElG4cvedkaRm/a40yhWXOUPUzAImwqI7ZmIyL55GIR4EmfQ5PkaSEcFhA3dekMa66l52ddn4lQaNVO+/yECq9A==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@citation-js/core/-/core-0.7.1.tgz", + "integrity": "sha512-vt7O/KbWNj6v0/fTKRJfjLE0VU4bV13LR69bG4V4lvWEq8TqXSNR4TVEINJuAwBLCofTk6LRyF82oGpb9AgaPQ==", "dependencies": { "@citation-js/date": "^0.5.0", "@citation-js/name": "^0.4.2", @@ -327,7 +327,7 @@ "sync-fetch": "^0.4.1" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" } }, "node_modules/@citation-js/date": { @@ -347,19 +347,19 @@ } }, "node_modules/@citation-js/plugin-bibtex": { - "version": "0.6.9", - "resolved": "https://registry.npmjs.org/@citation-js/plugin-bibtex/-/plugin-bibtex-0.6.9.tgz", - "integrity": "sha512-35xHut8rbDAN2ffYt+BPn+DChxXhbVnN86fu2DHDQNWlCqCrUJhQTMRMlD0L1uuyHTDrkTvgLPtcs14WC+xKzA==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@citation-js/plugin-bibtex/-/plugin-bibtex-0.7.1.tgz", + "integrity": "sha512-dj/GzpceS/QNbU8+rVzJfXeli7XSTYVTltGv5w2RHM+CCOdtG3tiFP1Ohu3yWi+8VPMjQJG9u2W789grIqc/ng==", "dependencies": { "@citation-js/date": "^0.5.0", "@citation-js/name": "^0.4.2", "moo": "^0.5.1" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" }, "peerDependencies": { - "@citation-js/core": "^0.6.0" + "@citation-js/core": "^0.7.0" } }, "node_modules/@citation-js/plugin-cff": { @@ -375,18 +375,18 @@ } }, "node_modules/@citation-js/plugin-csl": { - "version": "0.6.9", - "resolved": "https://registry.npmjs.org/@citation-js/plugin-csl/-/plugin-csl-0.6.9.tgz", - "integrity": "sha512-W8AYDK5o6qgkdBWgXPXmpzbTUxyfoADDbiGf1BqMdeD0IH3kSmgvXcsyeh8NMxiaM6B5VDg0k0pHaaxbTm5POA==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@citation-js/plugin-csl/-/plugin-csl-0.7.1.tgz", + "integrity": "sha512-B5Yv1o04Ds8/PF3FYlfL7bL3LFpVUhCEOAEqLFN5qgk785dnU0gMhDYbpJuCbQ8P6lIQpoU7O5x+EcJvWQhqCA==", "dependencies": { "@citation-js/date": "^0.5.0", "citeproc": "^2.4.6" }, "engines": { - "node": ">=14.0.0" + "node": ">=16.0.0" }, "peerDependencies": { - "@citation-js/core": "^0.6.0" + "@citation-js/core": "^0.7.0" } }, "node_modules/@citation-js/plugin-github": { @@ -460,9 +460,9 @@ } }, "node_modules/@csstools/css-parser-algorithms": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.3.1.tgz", - "integrity": "sha512-xrvsmVUtefWMWQsGgFffqWSK03pZ1vfDki4IVIIUxxDKnGBzqNgv0A7SB1oXtVNEkcVO8xi1ZrTL29HhSu5kGA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.3.2.tgz", + "integrity": "sha512-sLYGdAdEY2x7TSw9FtmdaTrh2wFtRJO5VMbBrA8tEqEod7GEggFmxTSK9XqExib3yMuYNcvcTdCZIP6ukdjAIA==", "dev": true, "funding": [ { @@ -478,13 +478,13 @@ "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@csstools/css-tokenizer": "^2.2.0" + "@csstools/css-tokenizer": "^2.2.1" } }, "node_modules/@csstools/css-tokenizer": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.2.0.tgz", - "integrity": "sha512-wErmsWCbsmig8sQKkM6pFhr/oPha1bHfvxsUY5CYSQxwyhA9Ulrs8EqCgClhg4Tgg2XapVstGqSVcz0xOYizZA==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.2.1.tgz", + "integrity": "sha512-Zmsf2f/CaEPWEVgw29odOj+WEVoiJy9s9NOv5GgNY9mZ1CZ7394By6wONrONrTsnNDv6F9hR02nvFihrGVGHBg==", "dev": true, "funding": [ { @@ -501,9 +501,9 @@ } }, "node_modules/@csstools/media-query-list-parser": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.4.tgz", - "integrity": "sha512-V/OUXYX91tAC1CDsiY+HotIcJR+vPtzrX8pCplCpT++i8ThZZsq5F5dzZh/bDM3WUOjrvC1ljed1oSJxMfjqhw==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.5.tgz", + "integrity": "sha512-IxVBdYzR8pYe89JiyXQuYk4aVVoCPhMJkz6ElRwlVysjwURTsTk/bmY/z4FfeRE+CRBMlykPwXEVUg8lThv7AQ==", "dev": true, "funding": [ { @@ -519,8 +519,8 @@ "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@csstools/css-parser-algorithms": "^2.3.1", - "@csstools/css-tokenizer": "^2.2.0" + "@csstools/css-parser-algorithms": "^2.3.2", + "@csstools/css-tokenizer": "^2.2.1" } }, "node_modules/@csstools/selector-specificity": { @@ -554,9 +554,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.3.tgz", - "integrity": "sha512-Lemgw4io4VZl9GHJmjiBGzQ7ONXRfRPHcUEerndjwiSkbxzrpq0Uggku5MxxrXdwJ+pTj1qyw4jwTu7hkPsgIA==", + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.4.tgz", + "integrity": "sha512-uBIbiYMeSsy2U0XQoOGVVcpIktjLMEKa7ryz2RLr7L/vTnANNEsPVAh4xOv7ondGz6ac1zVb0F8Jx20rQikffQ==", "cpu": [ "arm" ], @@ -569,9 +569,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.3.tgz", - "integrity": "sha512-w+Akc0vv5leog550kjJV9Ru+MXMR2VuMrui3C61mnysim0gkFCPOUTAfzTP0qX+HpN9Syu3YA3p1hf3EPqObRw==", + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.4.tgz", + "integrity": "sha512-mRsi2vJsk4Bx/AFsNBqOH2fqedxn5L/moT58xgg51DjX1la64Z3Npicut2VbhvDFO26qjWtPMsVxCd80YTFVeg==", "cpu": [ "arm64" ], @@ -584,9 +584,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.3.tgz", - "integrity": "sha512-FKQJKkK5MXcBHoNZMDNUAg1+WcZlV/cuXrWCoGF/TvdRiYS4znA0m5Il5idUwfxrE20bG/vU1Cr5e1AD6IEIjQ==", + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.4.tgz", + "integrity": "sha512-4iPufZ1TMOD3oBlGFqHXBpa3KFT46aLl6Vy7gwed0ZSYgHaZ/mihbYb4t7Z9etjkC9Al3ZYIoOaHrU60gcMy7g==", "cpu": [ "x64" ], @@ -599,9 +599,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.3.tgz", - "integrity": "sha512-kw7e3FXU+VsJSSSl2nMKvACYlwtvZB8RUIeVShIEY6PVnuZ3c9+L9lWB2nWeeKWNNYDdtL19foCQ0ZyUL7nqGw==", + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.4.tgz", + "integrity": "sha512-Lviw8EzxsVQKpbS+rSt6/6zjn9ashUZ7Tbuvc2YENgRl0yZTktGlachZ9KMJUsVjZEGFVu336kl5lBgDN6PmpA==", "cpu": [ "arm64" ], @@ -614,9 +614,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.3.tgz", - "integrity": "sha512-tPfZiwF9rO0jW6Jh9ipi58N5ZLoSjdxXeSrAYypy4psA2Yl1dAMhM71KxVfmjZhJmxRjSnb29YlRXXhh3GqzYw==", + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.4.tgz", + "integrity": "sha512-YHbSFlLgDwglFn0lAO3Zsdrife9jcQXQhgRp77YiTDja23FrC2uwnhXMNkAucthsf+Psr7sTwYEryxz6FPAVqw==", "cpu": [ "x64" ], @@ -629,9 +629,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.3.tgz", - "integrity": "sha512-ERDyjOgYeKe0Vrlr1iLrqTByB026YLPzTytDTz1DRCYM+JI92Dw2dbpRHYmdqn6VBnQ9Bor6J8ZlNwdZdxjlSg==", + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.4.tgz", + "integrity": "sha512-vz59ijyrTG22Hshaj620e5yhs2dU1WJy723ofc+KUgxVCM6zxQESmWdMuVmUzxtGqtj5heHyB44PjV/HKsEmuQ==", "cpu": [ "arm64" ], @@ -644,9 +644,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.3.tgz", - "integrity": "sha512-nXesBZ2Ad1qL+Rm3crN7NmEVJ5uvfLFPLJev3x1j3feCQXfAhoYrojC681RhpdOph8NsvKBBwpYZHR7W0ifTTA==", + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.4.tgz", + "integrity": "sha512-3sRbQ6W5kAiVQRBWREGJNd1YE7OgzS0AmOGjDmX/qZZecq8NFlQsQH0IfXjjmD0XtUYqr64e0EKNFjMUlPL3Cw==", "cpu": [ "x64" ], @@ -659,9 +659,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.3.tgz", - "integrity": "sha512-zr48Cg/8zkzZCzDHNxXO/89bf9e+r4HtzNUPoz4GmgAkF1gFAFmfgOdCbR8zMbzFDGb1FqBBhdXUpcTQRYS1cQ==", + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.4.tgz", + "integrity": "sha512-z/4ArqOo9EImzTi4b6Vq+pthLnepFzJ92BnofU1jgNlcVb+UqynVFdoXMCFreTK7FdhqAzH0vmdwW5373Hm9pg==", "cpu": [ "arm" ], @@ -674,9 +674,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.3.tgz", - "integrity": "sha512-qXvYKmXj8GcJgWq3aGvxL/JG1ZM3UR272SdPU4QSTzD0eymrM7leiZH77pvY3UetCy0k1xuXZ+VPvoJNdtrsWQ==", + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.4.tgz", + "integrity": "sha512-ZWmWORaPbsPwmyu7eIEATFlaqm0QGt+joRE9sKcnVUG3oBbr/KYdNE2TnkzdQwX6EDRdg/x8Q4EZQTXoClUqqA==", "cpu": [ "arm64" ], @@ -689,9 +689,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.3.tgz", - "integrity": "sha512-7XlCKCA0nWcbvYpusARWkFjRQNWNGlt45S+Q18UeS///K6Aw8bB2FKYe9mhVWy/XLShvCweOLZPrnMswIaDXQA==", + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.4.tgz", + "integrity": "sha512-EGc4vYM7i1GRUIMqRZNCTzJh25MHePYsnQfKDexD8uPTCm9mK56NIL04LUfX2aaJ+C9vyEp2fJ7jbqFEYgO9lQ==", "cpu": [ "ia32" ], @@ -704,9 +704,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.3.tgz", - "integrity": "sha512-qGTgjweER5xqweiWtUIDl9OKz338EQqCwbS9c2Bh5jgEH19xQ1yhgGPNesugmDFq+UUSDtWgZ264st26b3de8A==", + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.4.tgz", + "integrity": "sha512-WVhIKO26kmm8lPmNrUikxSpXcgd6HDog0cx12BUfA2PkmURHSgx9G6vA19lrlQOMw+UjMZ+l3PpbtzffCxFDRg==", "cpu": [ "loong64" ], @@ -719,9 +719,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.3.tgz", - "integrity": "sha512-gy1bFskwEyxVMFRNYSvBauDIWNggD6pyxUksc0MV9UOBD138dKTzr8XnM2R4mBsHwVzeuIH8X5JhmNs2Pzrx+A==", + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.4.tgz", + "integrity": "sha512-keYY+Hlj5w86hNp5JJPuZNbvW4jql7c1eXdBUHIJGTeN/+0QFutU3GrS+c27L+NTmzi73yhtojHk+lr2+502Mw==", "cpu": [ "mips64el" ], @@ -734,9 +734,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.3.tgz", - "integrity": "sha512-UrYLFu62x1MmmIe85rpR3qou92wB9lEXluwMB/STDzPF9k8mi/9UvNsG07Tt9AqwPQXluMQ6bZbTzYt01+Ue5g==", + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.4.tgz", + "integrity": "sha512-tQ92n0WMXyEsCH4m32S21fND8VxNiVazUbU4IUGVXQpWiaAxOBvtOtbEt3cXIV3GEBydYsY8pyeRMJx9kn3rvw==", "cpu": [ "ppc64" ], @@ -749,9 +749,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.3.tgz", - "integrity": "sha512-9E73TfyMCbE+1AwFOg3glnzZ5fBAFK4aawssvuMgCRqCYzE0ylVxxzjEfut8xjmKkR320BEoMui4o/t9KA96gA==", + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.4.tgz", + "integrity": "sha512-tRRBey6fG9tqGH6V75xH3lFPpj9E8BH+N+zjSUCnFOX93kEzqS0WdyJHkta/mmJHn7MBaa++9P4ARiU4ykjhig==", "cpu": [ "riscv64" ], @@ -764,9 +764,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.3.tgz", - "integrity": "sha512-LlmsbuBdm1/D66TJ3HW6URY8wO6IlYHf+ChOUz8SUAjVTuaisfuwCOAgcxo3Zsu3BZGxmI7yt//yGOxV+lHcEA==", + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.4.tgz", + "integrity": "sha512-152aLpQqKZYhThiJ+uAM4PcuLCAOxDsCekIbnGzPKVBRUDlgaaAfaUl5NYkB1hgY6WN4sPkejxKlANgVcGl9Qg==", "cpu": [ "s390x" ], @@ -779,9 +779,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.3.tgz", - "integrity": "sha512-ogV0+GwEmvwg/8ZbsyfkYGaLACBQWDvO0Kkh8LKBGKj9Ru8VM39zssrnu9Sxn1wbapA2qNS6BiLdwJZGouyCwQ==", + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.4.tgz", + "integrity": "sha512-Mi4aNA3rz1BNFtB7aGadMD0MavmzuuXNTaYL6/uiYIs08U7YMPETpgNn5oue3ICr+inKwItOwSsJDYkrE9ekVg==", "cpu": [ "x64" ], @@ -794,9 +794,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.3.tgz", - "integrity": "sha512-o1jLNe4uzQv2DKXMlmEzf66Wd8MoIhLNO2nlQBHLtWyh2MitDG7sMpfCO3NTcoTMuqHjfufgUQDFRI5C+xsXQw==", + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.4.tgz", + "integrity": "sha512-9+Wxx1i5N/CYo505CTT7T+ix4lVzEdz0uCoYGxM5JDVlP2YdDC1Bdz+Khv6IbqmisT0Si928eAxbmGkcbiuM/A==", "cpu": [ "x64" ], @@ -809,9 +809,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.3.tgz", - "integrity": "sha512-AZJCnr5CZgZOdhouLcfRdnk9Zv6HbaBxjcyhq0StNcvAdVZJSKIdOiPB9az2zc06ywl0ePYJz60CjdKsQacp5Q==", + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.4.tgz", + "integrity": "sha512-MFsHleM5/rWRW9EivFssop+OulYVUoVcqkyOkjiynKBCGBj9Lihl7kh9IzrreDyXa4sNkquei5/DTP4uCk25xw==", "cpu": [ "x64" ], @@ -824,9 +824,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.3.tgz", - "integrity": "sha512-Acsujgeqg9InR4glTRvLKGZ+1HMtDm94ehTIHKhJjFpgVzZG9/pIcWW/HA/DoMfEyXmANLDuDZ2sNrWcjq1lxw==", + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.4.tgz", + "integrity": "sha512-6Xq8SpK46yLvrGxjp6HftkDwPP49puU4OF0hEL4dTxqCbfx09LyrbUj/D7tmIRMj5D5FCUPksBbxyQhp8tmHzw==", "cpu": [ "x64" ], @@ -839,9 +839,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.3.tgz", - "integrity": "sha512-FSrAfjVVy7TifFgYgliiJOyYynhQmqgPj15pzLyJk8BUsnlWNwP/IAy6GAiB1LqtoivowRgidZsfpoYLZH586A==", + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.4.tgz", + "integrity": "sha512-PkIl7Jq4mP6ke7QKwyg4fD4Xvn8PXisagV/+HntWoDEdmerB2LTukRZg728Yd1Fj+LuEX75t/hKXE2Ppk8Hh1w==", "cpu": [ "arm64" ], @@ -854,9 +854,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.3.tgz", - "integrity": "sha512-xTScXYi12xLOWZ/sc5RBmMN99BcXp/eEf7scUC0oeiRoiT5Vvo9AycuqCp+xdpDyAU+LkrCqEpUS9fCSZF8J3Q==", + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.4.tgz", + "integrity": "sha512-ga676Hnvw7/ycdKB53qPusvsKdwrWzEyJ+AtItHGoARszIqvjffTwaaW3b2L6l90i7MO9i+dlAW415INuRhSGg==", "cpu": [ "ia32" ], @@ -869,9 +869,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.3.tgz", - "integrity": "sha512-FbUN+0ZRXsypPyWE2IwIkVjDkDnJoMJARWOcFZn4KPPli+QnKqF0z1anvfaYe3ev5HFCpRDLLBDHyOALLppWHw==", + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.4.tgz", + "integrity": "sha512-HP0GDNla1T3ZL8Ko/SHAS2GgtjOg+VmWnnYLhuTksr++EnduYB0f3Y2LzHsUwb2iQ13JGoY6G3R8h6Du/WG6uA==", "cpu": [ "x64" ], @@ -915,9 +915,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.8.1.tgz", - "integrity": "sha512-PWiOzLIUAjN/w5K17PoF4n6sKBw0gqLHPhywmYHP4t1VFQQVYeb1yWsJwnMVEMl3tUHME7X/SJPZLmtG7XBDxQ==", + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.9.1.tgz", + "integrity": "sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" @@ -991,18 +991,18 @@ } }, "node_modules/@eslint/js": { - "version": "8.49.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.49.0.tgz", - "integrity": "sha512-1S8uAY/MTJqVx0SC4epBq+N2yhuwtNwLbJYNZyhL2pO1ZVKn5HFXav5T41Ryzy9K9V7ZId2JB2oy/W4aCd9/2w==", + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.51.0.tgz", + "integrity": "sha512-HxjQ8Qn+4SI3/AFv6sOrDB+g6PpUTDwSJiQqOrnneEk8L71161srI9gjzzZvYVbzHiVg/BvcH95+cK/zfIt4pg==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@github/combobox-nav": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@github/combobox-nav/-/combobox-nav-2.2.0.tgz", - "integrity": "sha512-28kJUfzzPDYNyYsFCP/be8aXvEpjcEuciVENZlopcaUynS/4Pt9ll88Kl9l1D1Vy6a9+k+Km/YGJQ1e+gzG7SQ==" + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@github/combobox-nav/-/combobox-nav-2.3.0.tgz", + "integrity": "sha512-5CX03DbsLZ41dX5hKHyQKtg133U6lruX4TD9G0Zs4W8BpWy7lN8DJ6TYaeZN/V7x8K34coaqNYk/Y5ic7stfkg==" }, "node_modules/@github/markdown-toolbar-element": { "version": "2.2.1", @@ -1767,9 +1767,9 @@ } }, "node_modules/@stoplight/spectral-rulesets": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/@stoplight/spectral-rulesets/-/spectral-rulesets-1.17.0.tgz", - "integrity": "sha512-fRWunqvtP9k0vRonwqXQ663Xt1UfmOZRdaO+S02zA3mlKdA5a1vBQjVV9QYK70TXWmqUfmabc1G35FHNT+7iRw==", + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/@stoplight/spectral-rulesets/-/spectral-rulesets-1.18.0.tgz", + "integrity": "sha512-7LiCteW5pofMuBtf1BO+Ig5pT1XV9oqGrUjqWwSqD6jcy8ejE45pOQpef4h4um9tj3Y+tewfdbthLjhu8sdoeA==", "dev": true, "dependencies": { "@asyncapi/specs": "^4.1.0", @@ -1903,9 +1903,9 @@ } }, "node_modules/@types/d3-scale": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.4.tgz", - "integrity": "sha512-eq1ZeTj0yr72L8MQk6N6heP603ubnywSDRfNpi5enouR112HzGLS6RIvExCzZTraFF4HdzNpJMwA/zGiMoHUUw==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.5.tgz", + "integrity": "sha512-w/C++3W394MHzcLKO2kdsIn5KKNTOqeQVzyPSGPLzQbkPw/jpeaGtSRlakcKevGgGsjJxGsbqS0fPrVFDbHrDA==", "dependencies": { "@types/d3-time": "*" } @@ -1916,40 +1916,40 @@ "integrity": "sha512-dsoJGEIShosKVRBZB0Vo3C8nqSDqVGujJU6tPznsBJxNJNwMF8utmS83nvCBKQYPpjCzaaHcrf66iTRpZosLPw==" }, "node_modules/@types/d3-time": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.0.tgz", - "integrity": "sha512-sZLCdHvBUcNby1cB6Fd3ZBrABbjz3v1Vm90nysCQ6Vt7vd6e/h9Lt7SiJUoEX0l4Dzc7P5llKyhqSi1ycSf1Hg==" + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.1.tgz", + "integrity": "sha512-5j/AnefKAhCw4HpITmLDTPlf4vhi8o/dES+zbegfPb7LaGfNyqkLxBR6E+4yvTAgnJLmhe80EXFMzUs38fw4oA==" }, "node_modules/@types/debug": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.8.tgz", - "integrity": "sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==", + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.9.tgz", + "integrity": "sha512-8Hz50m2eoS56ldRlepxSBa6PWEVCtzUo/92HgLc2qTMnotJNIm7xP+UZhyWoYsyOdd5dxZ+NZLb24rsKyFs2ow==", "dependencies": { "@types/ms": "*" } }, "node_modules/@types/es-aggregate-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/es-aggregate-error/-/es-aggregate-error-1.0.2.tgz", - "integrity": "sha512-erqUpFXksaeR2kejKnhnjZjbFxUpGZx4Z7ydNL9ie8tEhXPiZTsLeUDJ6aR1F8j5wWUAtOAQWUqkc7givBJbBA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/es-aggregate-error/-/es-aggregate-error-1.0.3.tgz", + "integrity": "sha512-GmY61WWXQemfJp+qmMu6RsrNev0eoEWeWtg46w9pdXje23jRJrf7yETbAkl7F+CfQJSKW7w3//sTYtQTt+R5Lg==", "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/eslint": { - "version": "8.44.2", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.2.tgz", - "integrity": "sha512-sdPRb9K6iL5XZOmBubg8yiFp5yS/JdUDQsq5e6h95km91MCYMuvp7mh1fjPEYUhvHepKpZOjnEaMBR4PxjWDzg==", + "version": "8.44.3", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.3.tgz", + "integrity": "sha512-iM/WfkwAhwmPff3wZuPLYiHX18HI24jU8k1ZSH7P8FHwxTjZ2P6CoX2wnF43oprR+YXJM6UUxATkNvyv/JHd+g==", "dependencies": { "@types/estree": "*", "@types/json-schema": "*" } }, "node_modules/@types/eslint-scope": { - "version": "3.7.4", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", - "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", + "version": "3.7.5", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.5.tgz", + "integrity": "sha512-JNvhIEyxVW6EoMIFIvj93ZOywYFatlpu9deeH6eSx6PE3WHYvHaQtmHmQeNw7aA81bYGBPPQqdtBm6b1SsQMmA==", "dependencies": { "@types/eslint": "*", "@types/estree": "*" @@ -1972,44 +1972,44 @@ "dev": true }, "node_modules/@types/marked": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@types/marked/-/marked-4.3.1.tgz", - "integrity": "sha512-vSSbKZFbNktrQ15v7o1EaH78EbWV+sPQbPjHG+Cp8CaNcPFUEfjZ0Iml/V0bFDwsTlYe8o6XC5Hfdp91cqPV2g==" + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@types/marked/-/marked-4.3.2.tgz", + "integrity": "sha512-a79Yc3TOk6dGdituy8hmTTJXjOkZ7zsFYV10L337ttq/rec8lRMDBpV7fL3uLx6TgbFCa5DU/h8FmIBQPSbU0w==" }, "node_modules/@types/mdast": { - "version": "3.0.12", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.12.tgz", - "integrity": "sha512-DT+iNIRNX884cx0/Q1ja7NyUPpZuv0KPyL5rGNxm1WC1OtHstl7n4Jb7nk+xacNShQMbczJjt8uFzznpp6kYBg==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.13.tgz", + "integrity": "sha512-HjiGiWedR0DVFkeNljpa6Lv4/IZU1+30VY5d747K7lBudFc3R0Ibr6yJ9lN3BE28VnZyDfLF/VB1Ql1ZIbKrmg==", "dependencies": { "@types/unist": "^2" } }, "node_modules/@types/minimist": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", - "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.3.tgz", + "integrity": "sha512-ZYFzrvyWUNhaPomn80dsMNgMeXxNWZBdkuG/hWlUvXvbdUH8ZERNBGXnU87McuGcWDsyzX2aChCv/SVN348k3A==", "dev": true }, "node_modules/@types/ms": { - "version": "0.7.31", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", - "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" + "version": "0.7.32", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.32.tgz", + "integrity": "sha512-xPSg0jm4mqgEkNhowKgZFBNtwoEwF6gJ4Dhww+GFpm3IgtNseHQZ5IqdNwnquZEoANxyDAKDRAdVo4Z72VvD/g==" }, "node_modules/@types/node": { - "version": "20.6.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.6.3.tgz", - "integrity": "sha512-HksnYH4Ljr4VQgEy2lTStbCKv/P590tmPe5HqOnv9Gprffgv5WXAY+Y5Gqniu0GGqeTCUdBnzC3QSrzPkBkAMA==" + "version": "20.8.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.3.tgz", + "integrity": "sha512-jxiZQFpb+NlH5kjW49vXxvxTjeeqlbsnTAdBTKpzEdPs9itay7MscYXz3Fo9VYFEsfQ6LJFitHad3faerLAjCw==" }, "node_modules/@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.2.tgz", + "integrity": "sha512-lqa4UEhhv/2sjjIQgjX8B+RBjj47eo0mzGasklVJ78UKGQY1r0VpB9XHDaZZO9qzEFDdy4MrXLuEaSmPrPSe/A==", "dev": true }, "node_modules/@types/sarif": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@types/sarif/-/sarif-2.1.4.tgz", - "integrity": "sha512-4xKHMdg3foh3Va1fxTzY1qt8QVqmaJpGWsVvtjQrJBn+/bkig2pWFKJ4FPI2yLI4PAj0SUKiPO4Vd7ggYIMZjQ==", + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@types/sarif/-/sarif-2.1.5.tgz", + "integrity": "sha512-onJXseJAteCVczKQbO/Tx8zrvhZwZkAd+T7GGYXZvJJ7pzy7We5NJXcNk2oZoUbcnTP/AjkAH7XtPCkpfRBOnQ==", "dev": true }, "node_modules/@types/tern": { @@ -2032,9 +2032,9 @@ "dev": true }, "node_modules/@vitejs/plugin-vue": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.3.4.tgz", - "integrity": "sha512-ciXNIHKPriERBisHFBvnTbfKa6r9SAesOYXeGDzgegcvy9Q4xdScSHAmKbNT0M3O0S9LKhIf5/G+UYG4NnnzYw==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.4.0.tgz", + "integrity": "sha512-xdguqb+VUwiRpSg+nsc2HtbAUSGak25DXYvpQQi4RVU1Xq1uworyoH/md9Rfd8zMmPR/pSghr309QNcftUVseg==", "dev": true, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -2045,26 +2045,26 @@ } }, "node_modules/@vitest/expect": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.34.5.tgz", - "integrity": "sha512-/3RBIV9XEH+nRpRMqDJBufKIOQaYUH2X6bt0rKSCW0MfKhXFLYsR5ivHifeajRSTsln0FwJbitxLKHSQz/Xwkw==", + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.34.6.tgz", + "integrity": "sha512-QUzKpUQRc1qC7qdGo7rMK3AkETI7w18gTCUrsNnyjjJKYiuUB9+TQK3QnR1unhCnWRC0AbKv2omLGQDF/mIjOw==", "dev": true, "dependencies": { - "@vitest/spy": "0.34.5", - "@vitest/utils": "0.34.5", - "chai": "^4.3.7" + "@vitest/spy": "0.34.6", + "@vitest/utils": "0.34.6", + "chai": "^4.3.10" }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/@vitest/runner": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.34.5.tgz", - "integrity": "sha512-RDEE3ViVvl7jFSCbnBRyYuu23XxmvRTSZWW6W4M7eC5dOsK75d5LIf6uhE5Fqf809DQ1+9ICZZNxhIolWHU4og==", + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.34.6.tgz", + "integrity": "sha512-1CUQgtJSLF47NnhN+F9X2ycxUP0kLHQ/JWvNHbeBfwW8CzEGgeskzNnHDyv1ieKTltuR6sdIHV+nmR6kPxQqzQ==", "dev": true, "dependencies": { - "@vitest/utils": "0.34.5", + "@vitest/utils": "0.34.6", "p-limit": "^4.0.0", "pathe": "^1.1.1" }, @@ -2100,9 +2100,9 @@ } }, "node_modules/@vitest/snapshot": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.34.5.tgz", - "integrity": "sha512-+ikwSbhu6z2yOdtKmk/aeoDZ9QPm2g/ZO5rXT58RR9Vmu/kB2MamyDSx77dctqdZfP3Diqv4mbc/yw2kPT8rmA==", + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.34.6.tgz", + "integrity": "sha512-B3OZqYn6k4VaN011D+ve+AA4whM4QkcwcrwaKwAbyyvS/NB1hCWjFIBQxAQQSQir9/RtyAAGuq+4RJmbn2dH4w==", "dev": true, "dependencies": { "magic-string": "^0.30.1", @@ -2114,9 +2114,9 @@ } }, "node_modules/@vitest/snapshot/node_modules/magic-string": { - "version": "0.30.3", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.3.tgz", - "integrity": "sha512-B7xGbll2fG/VjP+SWg4sX3JynwIU0mjoTc6MPpKNuIvftk6u6vqhDnk1R80b8C2GBR6ywqy+1DcKBrevBg+bmw==", + "version": "0.30.4", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.4.tgz", + "integrity": "sha512-Q/TKtsC5BPm0kGqgBIF9oXAs/xEf2vRKiIB4wCRQTJOQIByZ1d+NnUOotvJOvNpi5RNIgVOMC3pOuaP1ZTDlVg==", "dev": true, "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" @@ -2126,9 +2126,9 @@ } }, "node_modules/@vitest/spy": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.34.5.tgz", - "integrity": "sha512-epsicsfhvBjRjCMOC/3k00mP/TBGQy8/P0DxOFiWyLt55gnZ99dqCfCiAsKO17BWVjn4eZRIjKvcqNmSz8gvmg==", + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.34.6.tgz", + "integrity": "sha512-xaCvneSaeBw/cz8ySmF7ZwGvL0lBjfvqc1LpQ/vcdHEvpLn3Ff1vAvjw+CoGn0802l++5L/pxb7whwcWAw+DUQ==", "dev": true, "dependencies": { "tinyspy": "^2.1.1" @@ -2138,9 +2138,9 @@ } }, "node_modules/@vitest/utils": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.34.5.tgz", - "integrity": "sha512-ur6CmmYQoeHMwmGb0v+qwkwN3yopZuZyf4xt1DBBSGBed8Hf9Gmbm/5dEWqgpLPdRx6Av6jcWXrjcKfkTzg/pw==", + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.34.6.tgz", + "integrity": "sha512-IG5aDD8S6zlvloDsnzHw0Ut5xczlF+kv2BOTo+iXfPr54Yhi5qbVOgGB1hZaVq4iJ4C/MZ2J0y15IlsV/ZcI0A==", "dev": true, "dependencies": { "diff-sequences": "^29.4.3", @@ -2189,9 +2189,9 @@ } }, "node_modules/@vue/compiler-sfc/node_modules/magic-string": { - "version": "0.30.3", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.3.tgz", - "integrity": "sha512-B7xGbll2fG/VjP+SWg4sX3JynwIU0mjoTc6MPpKNuIvftk6u6vqhDnk1R80b8C2GBR6ywqy+1DcKBrevBg+bmw==", + "version": "0.30.4", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.4.tgz", + "integrity": "sha512-Q/TKtsC5BPm0kGqgBIF9oXAs/xEf2vRKiIB4wCRQTJOQIByZ1d+NnUOotvJOvNpi5RNIgVOMC3pOuaP1ZTDlVg==", "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" }, @@ -2229,9 +2229,9 @@ } }, "node_modules/@vue/reactivity-transform/node_modules/magic-string": { - "version": "0.30.3", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.3.tgz", - "integrity": "sha512-B7xGbll2fG/VjP+SWg4sX3JynwIU0mjoTc6MPpKNuIvftk6u6vqhDnk1R80b8C2GBR6ywqy+1DcKBrevBg+bmw==", + "version": "0.30.4", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.4.tgz", + "integrity": "sha512-Q/TKtsC5BPm0kGqgBIF9oXAs/xEf2vRKiIB4wCRQTJOQIByZ1d+NnUOotvJOvNpi5RNIgVOMC3pOuaP1ZTDlVg==", "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" }, @@ -2787,9 +2787,9 @@ } }, "node_modules/asciinema-player": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/asciinema-player/-/asciinema-player-3.6.1.tgz", - "integrity": "sha512-FfTABH/N6pjG74A6cCfsrirTSM4UAOLMzcFXb0zS34T5czvg3CyUy2TAqa3WEs5owUFHcuN1Y2y8o0n2yjeMvQ==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/asciinema-player/-/asciinema-player-3.6.2.tgz", + "integrity": "sha512-698O3/Vm2+V6uFlc6oYma67IZByQsiNpduhEGhuqrxBmKpIYpgouLNNJ3R8DrRPTNNMISHfnLgvAp1x8ChgrTw==", "dependencies": { "@babel/runtime": "^7.21.0", "solid-js": "^1.3.0" @@ -2922,9 +2922,9 @@ } }, "node_modules/browserslist": { - "version": "4.21.11", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.11.tgz", - "integrity": "sha512-xn1UXOKUz7DjdGlg9RrUr0GGiWzI97UQJnugHtH0OLDfJB7jMgoIkYvRIEO1l9EeEERVqeqLYOcFBW9ldjypbQ==", + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", + "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", "funding": [ { "type": "opencollective", @@ -2940,8 +2940,8 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001538", - "electron-to-chromium": "^1.4.526", + "caniuse-lite": "^1.0.30001541", + "electron-to-chromium": "^1.4.535", "node-releases": "^2.0.13", "update-browserslist-db": "^1.0.13" }, @@ -3072,9 +3072,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001538", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001538.tgz", - "integrity": "sha512-HWJnhnID+0YMtGlzcp3T9drmBJUVDchPJ08tpUGFLs9CYlwWPH2uLgpHn8fND5pCgXVtnGS3H4QR9XLMHVNkHw==", + "version": "1.0.30001546", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001546.tgz", + "integrity": "sha512-zvtSJwuQFpewSyRrI3AsftF6rM0X80mZkChIt1spBGEvRglCrjTniXvinc8JKRoqTwXAgvqTImaN9igfSMtUBw==", "funding": [ { "type": "opencollective", @@ -3091,18 +3091,18 @@ ] }, "node_modules/chai": { - "version": "4.3.8", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.8.tgz", - "integrity": "sha512-vX4YvVVtxlfSZ2VecZgFUTU5qPCYsobVI2O9FmwEXBhDigYGQA6jRXCycIs1yJnnWbZ6/+a2zNIF5DfVCcJBFQ==", + "version": "4.3.10", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.10.tgz", + "integrity": "sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==", "dev": true, "dependencies": { "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^4.1.2", - "get-func-name": "^2.0.0", - "loupe": "^2.3.1", + "check-error": "^1.0.3", + "deep-eql": "^4.1.3", + "get-func-name": "^2.0.2", + "loupe": "^2.3.6", "pathval": "^1.1.1", - "type-detect": "^4.0.5" + "type-detect": "^4.0.8" }, "engines": { "node": ">=4" @@ -3133,10 +3133,13 @@ } }, "node_modules/check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", + "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", "dev": true, + "dependencies": { + "get-func-name": "^2.0.2" + }, "engines": { "node": "*" } @@ -3150,9 +3153,9 @@ } }, "node_modules/ci-info": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", - "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", "dev": true, "funding": [ { @@ -4346,9 +4349,9 @@ } }, "node_modules/dompurify": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.5.tgz", - "integrity": "sha512-F9e6wPGtY+8KNMRAVfxeCOHU0/NPWMSENNq4pQctuXRqqdEPW7q3CrLbR5Nse044WwacyjHGOMlvNsBe1y6z9A==" + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.6.tgz", + "integrity": "sha512-ilkD8YEnnGh1zJ240uJsW7AzE+2qpbOUYjacomn3AvJ6J4JhKGSZ2nh4wUIXPZrEPppaCLx5jFe8T89Rk8tQ7w==" }, "node_modules/domutils": { "version": "3.1.0", @@ -4391,9 +4394,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.527", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.527.tgz", - "integrity": "sha512-EafxEiEDzk2aLrdbtVczylHflHdHkNrpGNHIgDyA63sUQLQVS2ayj2hPw3RsVB42qkwURH+T2OxV7kGPUuYszA==" + "version": "1.4.544", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.544.tgz", + "integrity": "sha512-54z7squS1FyFRSUqq/knOFSptjjogLZXbKcYk3B0qkE1KZzvqASwRZnY2KzZQJqIYLVD38XZeoiMRflYSwyO4w==" }, "node_modules/elkjs": { "version": "0.8.2", @@ -4587,9 +4590,9 @@ } }, "node_modules/esbuild": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.3.tgz", - "integrity": "sha512-UlJ1qUUA2jL2nNib1JTSkifQTcYTroFqRjwCFW4QYEKEsixXD5Tik9xML7zh2gTxkYTBKGHNH9y7txMwVyPbjw==", + "version": "0.19.4", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.4.tgz", + "integrity": "sha512-x7jL0tbRRpv4QUyuDMjONtWFciygUxWaUM1kMX2zWxI0X2YWOt7MSA0g4UdeSiHM8fcYVzpQhKYOycZwxTdZkA==", "hasInstallScript": true, "bin": { "esbuild": "bin/esbuild" @@ -4598,28 +4601,28 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/android-arm": "0.19.3", - "@esbuild/android-arm64": "0.19.3", - "@esbuild/android-x64": "0.19.3", - "@esbuild/darwin-arm64": "0.19.3", - "@esbuild/darwin-x64": "0.19.3", - "@esbuild/freebsd-arm64": "0.19.3", - "@esbuild/freebsd-x64": "0.19.3", - "@esbuild/linux-arm": "0.19.3", - "@esbuild/linux-arm64": "0.19.3", - "@esbuild/linux-ia32": "0.19.3", - "@esbuild/linux-loong64": "0.19.3", - "@esbuild/linux-mips64el": "0.19.3", - "@esbuild/linux-ppc64": "0.19.3", - "@esbuild/linux-riscv64": "0.19.3", - "@esbuild/linux-s390x": "0.19.3", - "@esbuild/linux-x64": "0.19.3", - "@esbuild/netbsd-x64": "0.19.3", - "@esbuild/openbsd-x64": "0.19.3", - "@esbuild/sunos-x64": "0.19.3", - "@esbuild/win32-arm64": "0.19.3", - "@esbuild/win32-ia32": "0.19.3", - "@esbuild/win32-x64": "0.19.3" + "@esbuild/android-arm": "0.19.4", + "@esbuild/android-arm64": "0.19.4", + "@esbuild/android-x64": "0.19.4", + "@esbuild/darwin-arm64": "0.19.4", + "@esbuild/darwin-x64": "0.19.4", + "@esbuild/freebsd-arm64": "0.19.4", + "@esbuild/freebsd-x64": "0.19.4", + "@esbuild/linux-arm": "0.19.4", + "@esbuild/linux-arm64": "0.19.4", + "@esbuild/linux-ia32": "0.19.4", + "@esbuild/linux-loong64": "0.19.4", + "@esbuild/linux-mips64el": "0.19.4", + "@esbuild/linux-ppc64": "0.19.4", + "@esbuild/linux-riscv64": "0.19.4", + "@esbuild/linux-s390x": "0.19.4", + "@esbuild/linux-x64": "0.19.4", + "@esbuild/netbsd-x64": "0.19.4", + "@esbuild/openbsd-x64": "0.19.4", + "@esbuild/sunos-x64": "0.19.4", + "@esbuild/win32-arm64": "0.19.4", + "@esbuild/win32-ia32": "0.19.4", + "@esbuild/win32-x64": "0.19.4" } }, "node_modules/esbuild-loader": { @@ -4671,15 +4674,15 @@ } }, "node_modules/eslint": { - "version": "8.49.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.49.0.tgz", - "integrity": "sha512-jw03ENfm6VJI0jA9U+8H5zfl5b+FvuU3YYvZRdZHOlU2ggJkxrlkJH4HcDrZpj6YwD8kuYqvQM8LyesoazrSOQ==", + "version": "8.51.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.51.0.tgz", + "integrity": "sha512-2WuxRZBrlwnXi+/vFSJyjMqrNjtJqiasMzehF0shoLaW7DzS3/9Yvrmq5JiT66+pNjiX4UBnLDiKHcWAr/OInA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "8.49.0", + "@eslint/js": "8.51.0", "@humanwhocodes/config-array": "^0.11.11", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -4992,14 +4995,14 @@ } }, "node_modules/eslint-plugin-vue-scoped-css": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue-scoped-css/-/eslint-plugin-vue-scoped-css-2.5.0.tgz", - "integrity": "sha512-vR+raYNE1aQ69lS1lZGiKoz8rXFI3MWf2fxrfns/XCQ0XT5sIguhDtQS+9JmUQJClenLDEe2CQx7P+eeSdF4cA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue-scoped-css/-/eslint-plugin-vue-scoped-css-2.5.1.tgz", + "integrity": "sha512-ynbeCHd0dzkUBoL1q10GNpGh/BZD0Frw8Z8txPFyuhiHN2m5ZT6gvfe2GtdEs0Rq3+NE+5yexfz0PDX/bgKuJw==", "dev": true, "dependencies": { "eslint-utils": "^3.0.0", "lodash": "^4.17.21", - "postcss": "^8.4.6", + "postcss": "^8.4.31", "postcss-safe-parser": "^6.0.0", "postcss-scss": "^4.0.3", "postcss-selector-parser": "^6.0.9", @@ -5017,9 +5020,9 @@ } }, "node_modules/eslint-plugin-wc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-wc/-/eslint-plugin-wc-2.0.3.tgz", - "integrity": "sha512-O3i71FodYMArf8DBs+OuDQ8SH8SMiNaJ4GIcXRDsGURPdvBrVDNS9+GQ0xwmzhqUWV0df5xq8irpceA6YBdJmg==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-wc/-/eslint-plugin-wc-2.0.4.tgz", + "integrity": "sha512-ORu7MBv0hXIvq894EJad70m+AvHGbmrDdKT6lcgtCVVhEbuIAyxg0ilfqqqHOmsh8PfcUBeEae3y7CElKvm1KQ==", "dev": true, "dependencies": { "is-valid-element-name": "^1.0.0", @@ -5363,12 +5366,12 @@ } }, "node_modules/flat-cache": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.0.tgz", - "integrity": "sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz", + "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==", "dev": true, "dependencies": { - "flatted": "^3.2.7", + "flatted": "^3.2.9", "keyv": "^4.5.3", "rimraf": "^3.0.2" }, @@ -5457,7 +5460,8 @@ "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true }, "node_modules/function.prototype.name": { "version": "1.1.6", @@ -5496,9 +5500,9 @@ } }, "node_modules/get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", + "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", "dev": true, "engines": { "node": "*" @@ -5678,9 +5682,9 @@ } }, "node_modules/globals": { - "version": "13.22.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.22.0.tgz", - "integrity": "sha512-H1Ddc/PbZHTDVJSnj8kWptIRSD6AM3pK+mKytuIVF4uoBV7rshFlhhvA58ceJ5wp3Er58w6zj7bykMpYXt3ETw==", + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -5777,12 +5781,9 @@ } }, "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dependencies": { - "function-bind": "^1.1.1" - }, + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz", + "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==", "engines": { "node": ">= 0.4.0" } @@ -6494,9 +6495,9 @@ } }, "node_modules/jackspeak": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.3.tgz", - "integrity": "sha512-R2bUw+kVZFS/h1AZqBKrSgDmdmjApzgY0AlCPumopFiAlbUxE2gf+SCuBzQ0cP5hHmUmFYF5yw55T97Th5Kstg==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", "dev": true, "dependencies": { "@isaacs/cliui": "^8.0.2" @@ -6725,9 +6726,9 @@ "integrity": "sha512-b+z6yF1d4EOyDgylzQo5IminlUmzSeqR1hs/bzjBNjuGras4FXq/6TrzjxfN0j+TmI0ltJzTNlqXUMCniciwKQ==" }, "node_modules/katex": { - "version": "0.16.8", - "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.8.tgz", - "integrity": "sha512-ftuDnJbcbOckGY11OO+zg3OofESlbR5DRl2cmN8HeWeeFIV7wTXvAOx8kEjZjobhA+9wh2fbKeO6cdcA9Mnovg==", + "version": "0.16.9", + "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.9.tgz", + "integrity": "sha512-fsSYjWS0EEOwvy81j3vRA8TEAhQhKiqO+FQaKWp0m39qwOzHVBgAUBIXWj1pB+O2W3fIpNa6Y9KSKCVbfPhyAQ==", "funding": [ "https://opencollective.com/katex", "https://github.com/sponsors/katex" @@ -7311,19 +7312,19 @@ } }, "node_modules/markdownlint-cli/node_modules/glob": { - "version": "10.3.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.5.tgz", - "integrity": "sha512-bYUpUD7XDEHI4Q2O5a7PXGvyw4deKR70kHiDxzQbe925wbZknhOzUt2xBgTkYL6RBcVeXYuD9iNYeqoWbBZQnA==", + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", "dev": true, "dependencies": { "foreground-child": "^3.1.0", - "jackspeak": "^2.0.3", + "jackspeak": "^2.3.5", "minimatch": "^9.0.1", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", "path-scurry": "^1.10.1" }, "bin": { - "glob": "dist/cjs/src/bin.js" + "glob": "dist/esm/bin.mjs" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -7529,9 +7530,9 @@ } }, "node_modules/mermaid": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-10.4.0.tgz", - "integrity": "sha512-4QCQLp79lvz7UZxow5HUX7uWTPJOaQBVExduo91tliXC7v78i6kssZOPHxLL+Xs30KU72cpPn3g3imw/xm/gaw==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-10.5.0.tgz", + "integrity": "sha512-9l0o1uUod78D3/FVYPGSsgV+Z0tSnzLBDiC9rVzvelPxuO80HbN1oDr9ofpPETQy9XpypPQa26fr09VzEPfvWA==", "dependencies": { "@braintree/sanitize-url": "^6.0.1", "@types/d3-scale": "^4.0.3", @@ -8072,9 +8073,9 @@ } }, "node_modules/minipass": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.3.tgz", - "integrity": "sha512-LhbbwCfz3vsb12j/WkWQPZfKTsgqIe1Nf/ti1pKjYESGLHIVjWU96G9/ljLH4F9mWNVhlQOm0VySdAWzf05dpg==", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", "dev": true, "engines": { "node": ">=16 || 14 >=14.17" @@ -8093,9 +8094,9 @@ } }, "node_modules/monaco-editor": { - "version": "0.43.0", - "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.43.0.tgz", - "integrity": "sha512-cnoqwQi/9fml2Szamv1XbSJieGJ1Dc8tENVMD26Kcfl7xGQWp7OBKMjlwKVGYFJ3/AXJjSOGvcqK7Ry/j9BM1Q==" + "version": "0.44.0", + "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.44.0.tgz", + "integrity": "sha512-5SmjNStN6bSuSE5WPT2ZV+iYn1/yI9sd4Igtk23ChvqB7kDk9lZbB9F5frsuvpB+2njdIeGGFf2G4gbE6rCC9Q==" }, "node_modules/monaco-editor-webpack-plugin": { "version": "7.1.0", @@ -8744,9 +8745,9 @@ } }, "node_modules/postcss": { - "version": "8.4.30", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.30.tgz", - "integrity": "sha512-7ZEao1g4kd68l97aWG/etQKPKq07us0ieSZ2TnFDk11i0ZfDW2AwKHYU8qv4MZKqN2fdBfg+7q0ES06UA73C1g==", + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", "funding": [ { "type": "opencollective", @@ -8869,9 +8870,9 @@ } }, "node_modules/postcss-scss": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-4.0.8.tgz", - "integrity": "sha512-Cr0X8Eu7xMhE96PJck6ses/uVVXDtE5ghUTKNUYgm8ozgP2TkgV3LWs3WgLV1xaSSLq8ZFiXaUrj0LVgG1fGEA==", + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-4.0.9.tgz", + "integrity": "sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==", "dev": true, "funding": [ { @@ -9846,9 +9847,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.15", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.15.tgz", - "integrity": "sha512-lpT8hSQp9jAKp9mhtBU4Xjon8LPGBvLIuBiSVhMEtmLecTh2mO0tlqrAMp47tBXzMr13NJMQ2lf7RpQGLJ3HsQ==" + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz", + "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==" }, "node_modules/spdx-ranges": { "version": "2.1.1", @@ -10263,9 +10264,9 @@ } }, "node_modules/swagger-ui-dist": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.7.2.tgz", - "integrity": "sha512-mVZc9QVQ6pTCV5crli3+Ng+DoMPwdtMHK8QLk2oX8Mtamp4D/hV+uYdC3lV0JZrDgpNEcjs0RrWTqMwwosuLPQ==" + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.9.0.tgz", + "integrity": "sha512-NUHSYoe5XRTk/Are8jPJ6phzBh3l9l33nEyXosM17QInoV95/jng8+PuSGtbD407QoPf93MH3Bkh773OgesJpA==" }, "node_modules/symbol-tree": { "version": "3.2.4", @@ -10310,9 +10311,9 @@ } }, "node_modules/terser": { - "version": "5.20.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.20.0.tgz", - "integrity": "sha512-e56ETryaQDyebBwJIWYB2TT6f2EZ0fL0sW/JRXNMN26zZdKi2u/E/5my5lG6jNxym6qsrVXfFRmOdV42zlAgLQ==", + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.21.0.tgz", + "integrity": "sha512-WtnFKrxu9kaoXuiZFSGrcAvvBqAdmKx0SFNmVNYdJamMu9yyN3I/QF0FbH4QcqJQ+y1CJnzxGIKH0cSj+FGYRw==", "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", @@ -10444,9 +10445,9 @@ } }, "node_modules/tinyspy": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.1.1.tgz", - "integrity": "sha512-XPJL2uSzcOyBMky6OFrusqWlzfFrXtE0hPuMgW8A2HmaqrPo4ZQHRN/V0QXN3FSjKxpsbRrFc5LI7KOwBsT1/w==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.2.0.tgz", + "integrity": "sha512-d2eda04AN/cPOR89F7Xv5bK/jrQEhmcLFe6HFldoeO9AJtps+fqEnh486vnT/8y4bw38pSyxDcTCAq+Ks2aJTg==", "dev": true, "engines": { "node": ">=14.0.0" @@ -10677,9 +10678,9 @@ "dev": true }, "node_modules/ufo": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.3.0.tgz", - "integrity": "sha512-bRn3CsoojyNStCZe0BG0Mt4Nr/4KF+rhFlnNXybgqt5pXHNFRlqinSoQaTrGyzE4X8aHplSb+TorH+COin9Yxw==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.3.1.tgz", + "integrity": "sha512-uY/99gMLIOlJPwATcMVYfqDSxUR9//AUcgZMzwfSTJPDKzA1S8mX4VLqa+fiAtveraQUBCz4FFcwVZBGbwBXIw==", "dev": true }, "node_modules/uint8-to-base64": { @@ -10851,9 +10852,9 @@ } }, "node_modules/vite": { - "version": "4.4.9", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.9.tgz", - "integrity": "sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==", + "version": "4.4.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.11.tgz", + "integrity": "sha512-ksNZJlkcU9b0lBwAGZGGaZHCMqHsc8OpgtoYhsQ4/I2v5cnpmmmqe5pM4nv/4Hn6G/2GhTdj0DhZh2e+Er1q5A==", "dev": true, "dependencies": { "esbuild": "^0.18.10", @@ -10906,9 +10907,9 @@ } }, "node_modules/vite-node": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-0.34.5.tgz", - "integrity": "sha512-RNZ+DwbCvDoI5CbCSQSyRyzDTfFvFauvMs6Yq4ObJROKlIKuat1KgSX/Ako5rlDMfVCyMcpMRMTkJBxd6z8YRA==", + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-0.34.6.tgz", + "integrity": "sha512-nlBMJ9x6n7/Amaz6F3zJ97EBwR2FkzhBRxF5e+jE6LA3yi6Wtc2lyTij1OnDMIr34v5g/tVQtsVAzhT0jc5ygA==", "dev": true, "dependencies": { "cac": "^6.7.14", @@ -11327,9 +11328,9 @@ } }, "node_modules/vite/node_modules/rollup": { - "version": "3.29.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.2.tgz", - "integrity": "sha512-CJouHoZ27v6siztc21eEQGo0kIcE5D1gVPA571ez0mMYb25LGYGKnVNXpEj5MGlepmDWGXNjDB5q7uNiPHC11A==", + "version": "3.29.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", + "integrity": "sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==", "dev": true, "bin": { "rollup": "dist/bin/rollup" @@ -11343,23 +11344,23 @@ } }, "node_modules/vitest": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.34.5.tgz", - "integrity": "sha512-CPI68mmnr2DThSB3frSuE5RLm9wo5wU4fbDrDwWQQB1CWgq9jQVoQwnQSzYAjdoBOPoH2UtXpOgHVge/uScfZg==", + "version": "0.34.6", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.34.6.tgz", + "integrity": "sha512-+5CALsOvbNKnS+ZHMXtuUC7nL8/7F1F2DnHGjSsszX8zCjWSSviphCb/NuS9Nzf4Q03KyyDRBAXhF/8lffME4Q==", "dev": true, "dependencies": { "@types/chai": "^4.3.5", "@types/chai-subset": "^1.3.3", "@types/node": "*", - "@vitest/expect": "0.34.5", - "@vitest/runner": "0.34.5", - "@vitest/snapshot": "0.34.5", - "@vitest/spy": "0.34.5", - "@vitest/utils": "0.34.5", + "@vitest/expect": "0.34.6", + "@vitest/runner": "0.34.6", + "@vitest/snapshot": "0.34.6", + "@vitest/spy": "0.34.6", + "@vitest/utils": "0.34.6", "acorn": "^8.9.0", "acorn-walk": "^8.2.0", "cac": "^6.7.14", - "chai": "^4.3.7", + "chai": "^4.3.10", "debug": "^4.3.4", "local-pkg": "^0.4.3", "magic-string": "^0.30.1", @@ -11370,7 +11371,7 @@ "tinybench": "^2.5.0", "tinypool": "^0.7.0", "vite": "^3.1.0 || ^4.0.0 || ^5.0.0-0", - "vite-node": "0.34.5", + "vite-node": "0.34.6", "why-is-node-running": "^2.2.2" }, "bin": { @@ -11420,9 +11421,9 @@ } }, "node_modules/vitest/node_modules/magic-string": { - "version": "0.30.3", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.3.tgz", - "integrity": "sha512-B7xGbll2fG/VjP+SWg4sX3JynwIU0mjoTc6MPpKNuIvftk6u6vqhDnk1R80b8C2GBR6ywqy+1DcKBrevBg+bmw==", + "version": "0.30.4", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.4.tgz", + "integrity": "sha512-Q/TKtsC5BPm0kGqgBIF9oXAs/xEf2vRKiIB4wCRQTJOQIByZ1d+NnUOotvJOvNpi5RNIgVOMC3pOuaP1ZTDlVg==", "dev": true, "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" @@ -11477,9 +11478,9 @@ } }, "node_modules/vue-loader": { - "version": "17.2.2", - "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-17.2.2.tgz", - "integrity": "sha512-aqNvKJvnz2A/6VWeJZodAo8XLoAlVwBv+2Z6dama+LHsAF+P/xijQ+OfWrxIs0wcGSJduvdzvTuATzXbNKkpiw==", + "version": "17.3.0", + "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-17.3.0.tgz", + "integrity": "sha512-VUURABiN0TIUz0yvJJ/V/rZjGUh10JZtD+IDI5bXFslzFi9mV6ebKkPzoqiSi8e0vh8Ip7JHJx+I0AzAG0KsCA==", "dependencies": { "chalk": "^4.1.0", "hash-sum": "^2.0.0", @@ -11667,9 +11668,9 @@ } }, "node_modules/webpack/node_modules/@types/estree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", - "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.2.tgz", + "integrity": "sha512-VeiPZ9MMwXjO32/Xu7+OwflfmeoRwkE/qzndw42gGtgJwZopBnzy2gD//NN1+go1mADzkDcqf/KnFRSjTJ8xJA==" }, "node_modules/webpack/node_modules/ajv": { "version": "6.12.6", diff --git a/package.json b/package.json index fb0ee33998b46..2672067b35ac0 100644 --- a/package.json +++ b/package.json @@ -4,9 +4,9 @@ "node": ">= 18.0.0" }, "dependencies": { - "@citation-js/core": "0.6.9", - "@citation-js/plugin-bibtex": "0.6.9", - "@citation-js/plugin-csl": "0.6.9", + "@citation-js/core": "0.7.1", + "@citation-js/plugin-bibtex": "0.7.1", + "@citation-js/plugin-csl": "0.7.1", "@citation-js/plugin-software-formats": "0.6.1", "@claviska/jquery-minicolors": "2.3.6", "@github/markdown-toolbar-element": "2.2.1", @@ -17,7 +17,7 @@ "@webcomponents/custom-elements": "1.6.0", "add-asset-webpack-plugin": "2.0.1", "ansi_up": "6.0.2", - "asciinema-player": "3.6.1", + "asciinema-player": "3.6.2", "clippie": "4.0.6", "css-loader": "6.8.1", "dropzone": "6.0.0-beta.2", @@ -26,18 +26,18 @@ "escape-goat": "4.0.0", "fast-glob": "3.3.1", "jquery": "3.7.1", - "katex": "0.16.8", + "katex": "0.16.9", "license-checker-webpack-plugin": "0.2.1", "lightningcss-loader": "2.1.0", - "mermaid": "10.4.0", + "mermaid": "10.5.0", "mini-css-extract-plugin": "2.7.6", "minimatch": "9.0.3", - "monaco-editor": "0.43.0", + "monaco-editor": "0.44.0", "monaco-editor-webpack-plugin": "7.1.0", "pdfobject": "2.2.12", "pretty-ms": "8.0.0", "sortablejs": "1.15.0", - "swagger-ui-dist": "5.7.2", + "swagger-ui-dist": "5.9.0", "throttle-debounce": "5.0.0", "tinycolor2": "1.6.0", "tippy.js": "6.3.7", @@ -46,7 +46,7 @@ "uint8-to-base64": "0.2.0", "vue": "3.3.4", "vue-bar-graph": "2.0.0", - "vue-loader": "17.2.2", + "vue-loader": "17.3.0", "vue3-calendar-heatmap": "2.0.5", "webpack": "5.88.2", "webpack-cli": "5.1.4", @@ -56,8 +56,8 @@ "@eslint-community/eslint-plugin-eslint-comments": "4.1.0", "@playwright/test": "1.38.1", "@stoplight/spectral-cli": "6.11.0", - "@vitejs/plugin-vue": "4.3.4", - "eslint": "8.49.0", + "@vitejs/plugin-vue": "4.4.0", + "eslint": "8.51.0", "eslint-plugin-array-func": "4.0.0", "eslint-plugin-import": "2.28.1", "eslint-plugin-jquery": "1.5.1", @@ -68,8 +68,8 @@ "eslint-plugin-unicorn": "48.0.1", "eslint-plugin-vitest-globals": "1.4.0", "eslint-plugin-vue": "9.17.0", - "eslint-plugin-vue-scoped-css": "2.5.0", - "eslint-plugin-wc": "2.0.3", + "eslint-plugin-vue-scoped-css": "2.5.1", + "eslint-plugin-wc": "2.0.4", "jsdom": "22.1.0", "markdownlint-cli": "0.37.0", "postcss-html": "1.5.0", @@ -80,7 +80,7 @@ "svgo": "3.0.2", "updates": "15.0.2", "vite-string-plugin": "1.1.2", - "vitest": "0.34.5" + "vitest": "0.34.6" }, "browserslist": [ "defaults", diff --git a/poetry.lock b/poetry.lock index 2b15fa5ad6e1d..b6e0432058119 100644 --- a/poetry.lock +++ b/poetry.lock @@ -188,99 +188,99 @@ files = [ [[package]] name = "regex" -version = "2023.8.8" +version = "2023.10.3" description = "Alternative regular expression module, to replace re." optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "regex-2023.8.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:88900f521c645f784260a8d346e12a1590f79e96403971241e64c3a265c8ecdb"}, - {file = "regex-2023.8.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3611576aff55918af2697410ff0293d6071b7e00f4b09e005d614686ac4cd57c"}, - {file = "regex-2023.8.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b8a0ccc8f2698f120e9e5742f4b38dc944c38744d4bdfc427616f3a163dd9de5"}, - {file = "regex-2023.8.8-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c662a4cbdd6280ee56f841f14620787215a171c4e2d1744c9528bed8f5816c96"}, - {file = "regex-2023.8.8-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cf0633e4a1b667bfe0bb10b5e53fe0d5f34a6243ea2530eb342491f1adf4f739"}, - {file = "regex-2023.8.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:551ad543fa19e94943c5b2cebc54c73353ffff08228ee5f3376bd27b3d5b9800"}, - {file = "regex-2023.8.8-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54de2619f5ea58474f2ac211ceea6b615af2d7e4306220d4f3fe690c91988a61"}, - {file = "regex-2023.8.8-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5ec4b3f0aebbbe2fc0134ee30a791af522a92ad9f164858805a77442d7d18570"}, - {file = "regex-2023.8.8-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3ae646c35cb9f820491760ac62c25b6d6b496757fda2d51be429e0e7b67ae0ab"}, - {file = "regex-2023.8.8-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ca339088839582d01654e6f83a637a4b8194d0960477b9769d2ff2cfa0fa36d2"}, - {file = "regex-2023.8.8-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:d9b6627408021452dcd0d2cdf8da0534e19d93d070bfa8b6b4176f99711e7f90"}, - {file = "regex-2023.8.8-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:bd3366aceedf274f765a3a4bc95d6cd97b130d1dda524d8f25225d14123c01db"}, - {file = "regex-2023.8.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7aed90a72fc3654fba9bc4b7f851571dcc368120432ad68b226bd593f3f6c0b7"}, - {file = "regex-2023.8.8-cp310-cp310-win32.whl", hash = "sha256:80b80b889cb767cc47f31d2b2f3dec2db8126fbcd0cff31b3925b4dc6609dcdb"}, - {file = "regex-2023.8.8-cp310-cp310-win_amd64.whl", hash = "sha256:b82edc98d107cbc7357da7a5a695901b47d6eb0420e587256ba3ad24b80b7d0b"}, - {file = "regex-2023.8.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1e7d84d64c84ad97bf06f3c8cb5e48941f135ace28f450d86af6b6512f1c9a71"}, - {file = "regex-2023.8.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ce0f9fbe7d295f9922c0424a3637b88c6c472b75eafeaff6f910494a1fa719ef"}, - {file = "regex-2023.8.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:06c57e14ac723b04458df5956cfb7e2d9caa6e9d353c0b4c7d5d54fcb1325c46"}, - {file = "regex-2023.8.8-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e7a9aaa5a1267125eef22cef3b63484c3241aaec6f48949b366d26c7250e0357"}, - {file = "regex-2023.8.8-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b7408511fca48a82a119d78a77c2f5eb1b22fe88b0d2450ed0756d194fe7a9a"}, - {file = "regex-2023.8.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14dc6f2d88192a67d708341f3085df6a4f5a0c7b03dec08d763ca2cd86e9f559"}, - {file = "regex-2023.8.8-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:48c640b99213643d141550326f34f0502fedb1798adb3c9eb79650b1ecb2f177"}, - {file = "regex-2023.8.8-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0085da0f6c6393428bf0d9c08d8b1874d805bb55e17cb1dfa5ddb7cfb11140bf"}, - {file = "regex-2023.8.8-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:964b16dcc10c79a4a2be9f1273fcc2684a9eedb3906439720598029a797b46e6"}, - {file = "regex-2023.8.8-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7ce606c14bb195b0e5108544b540e2c5faed6843367e4ab3deb5c6aa5e681208"}, - {file = "regex-2023.8.8-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:40f029d73b10fac448c73d6eb33d57b34607f40116e9f6e9f0d32e9229b147d7"}, - {file = "regex-2023.8.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3b8e6ea6be6d64104d8e9afc34c151926f8182f84e7ac290a93925c0db004bfd"}, - {file = "regex-2023.8.8-cp311-cp311-win32.whl", hash = "sha256:942f8b1f3b223638b02df7df79140646c03938d488fbfb771824f3d05fc083a8"}, - {file = "regex-2023.8.8-cp311-cp311-win_amd64.whl", hash = "sha256:51d8ea2a3a1a8fe4f67de21b8b93757005213e8ac3917567872f2865185fa7fb"}, - {file = "regex-2023.8.8-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e951d1a8e9963ea51efd7f150450803e3b95db5939f994ad3d5edac2b6f6e2b4"}, - {file = "regex-2023.8.8-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:704f63b774218207b8ccc6c47fcef5340741e5d839d11d606f70af93ee78e4d4"}, - {file = "regex-2023.8.8-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22283c769a7b01c8ac355d5be0715bf6929b6267619505e289f792b01304d898"}, - {file = "regex-2023.8.8-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:91129ff1bb0619bc1f4ad19485718cc623a2dc433dff95baadbf89405c7f6b57"}, - {file = "regex-2023.8.8-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de35342190deb7b866ad6ba5cbcccb2d22c0487ee0cbb251efef0843d705f0d4"}, - {file = "regex-2023.8.8-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b993b6f524d1e274a5062488a43e3f9f8764ee9745ccd8e8193df743dbe5ee61"}, - {file = "regex-2023.8.8-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3026cbcf11d79095a32d9a13bbc572a458727bd5b1ca332df4a79faecd45281c"}, - {file = "regex-2023.8.8-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:293352710172239bf579c90a9864d0df57340b6fd21272345222fb6371bf82b3"}, - {file = "regex-2023.8.8-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:d909b5a3fff619dc7e48b6b1bedc2f30ec43033ba7af32f936c10839e81b9217"}, - {file = "regex-2023.8.8-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:3d370ff652323c5307d9c8e4c62efd1956fb08051b0e9210212bc51168b4ff56"}, - {file = "regex-2023.8.8-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:b076da1ed19dc37788f6a934c60adf97bd02c7eea461b73730513921a85d4235"}, - {file = "regex-2023.8.8-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:e9941a4ada58f6218694f382e43fdd256e97615db9da135e77359da257a7168b"}, - {file = "regex-2023.8.8-cp36-cp36m-win32.whl", hash = "sha256:a8c65c17aed7e15a0c824cdc63a6b104dfc530f6fa8cb6ac51c437af52b481c7"}, - {file = "regex-2023.8.8-cp36-cp36m-win_amd64.whl", hash = "sha256:aadf28046e77a72f30dcc1ab185639e8de7f4104b8cb5c6dfa5d8ed860e57236"}, - {file = "regex-2023.8.8-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:423adfa872b4908843ac3e7a30f957f5d5282944b81ca0a3b8a7ccbbfaa06103"}, - {file = "regex-2023.8.8-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ae594c66f4a7e1ea67232a0846649a7c94c188d6c071ac0210c3e86a5f92109"}, - {file = "regex-2023.8.8-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e51c80c168074faa793685656c38eb7a06cbad7774c8cbc3ea05552d615393d8"}, - {file = "regex-2023.8.8-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:09b7f4c66aa9d1522b06e31a54f15581c37286237208df1345108fcf4e050c18"}, - {file = "regex-2023.8.8-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e73e5243af12d9cd6a9d6a45a43570dbe2e5b1cdfc862f5ae2b031e44dd95a8"}, - {file = "regex-2023.8.8-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:941460db8fe3bd613db52f05259c9336f5a47ccae7d7def44cc277184030a116"}, - {file = "regex-2023.8.8-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f0ccf3e01afeb412a1a9993049cb160d0352dba635bbca7762b2dc722aa5742a"}, - {file = "regex-2023.8.8-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:2e9216e0d2cdce7dbc9be48cb3eacb962740a09b011a116fd7af8c832ab116ca"}, - {file = "regex-2023.8.8-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:5cd9cd7170459b9223c5e592ac036e0704bee765706445c353d96f2890e816c8"}, - {file = "regex-2023.8.8-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:4873ef92e03a4309b3ccd8281454801b291b689f6ad45ef8c3658b6fa761d7ac"}, - {file = "regex-2023.8.8-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:239c3c2a339d3b3ddd51c2daef10874410917cd2b998f043c13e2084cb191684"}, - {file = "regex-2023.8.8-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:1005c60ed7037be0d9dea1f9c53cc42f836188227366370867222bda4c3c6bd7"}, - {file = "regex-2023.8.8-cp37-cp37m-win32.whl", hash = "sha256:e6bd1e9b95bc5614a7a9c9c44fde9539cba1c823b43a9f7bc11266446dd568e3"}, - {file = "regex-2023.8.8-cp37-cp37m-win_amd64.whl", hash = "sha256:9a96edd79661e93327cfeac4edec72a4046e14550a1d22aa0dd2e3ca52aec921"}, - {file = "regex-2023.8.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f2181c20ef18747d5f4a7ea513e09ea03bdd50884a11ce46066bb90fe4213675"}, - {file = "regex-2023.8.8-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a2ad5add903eb7cdde2b7c64aaca405f3957ab34f16594d2b78d53b8b1a6a7d6"}, - {file = "regex-2023.8.8-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9233ac249b354c54146e392e8a451e465dd2d967fc773690811d3a8c240ac601"}, - {file = "regex-2023.8.8-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:920974009fb37b20d32afcdf0227a2e707eb83fe418713f7a8b7de038b870d0b"}, - {file = "regex-2023.8.8-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd2b6c5dfe0929b6c23dde9624483380b170b6e34ed79054ad131b20203a1a63"}, - {file = "regex-2023.8.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:96979d753b1dc3b2169003e1854dc67bfc86edf93c01e84757927f810b8c3c93"}, - {file = "regex-2023.8.8-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2ae54a338191e1356253e7883d9d19f8679b6143703086245fb14d1f20196be9"}, - {file = "regex-2023.8.8-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:2162ae2eb8b079622176a81b65d486ba50b888271302190870b8cc488587d280"}, - {file = "regex-2023.8.8-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:c884d1a59e69e03b93cf0dfee8794c63d7de0ee8f7ffb76e5f75be8131b6400a"}, - {file = "regex-2023.8.8-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:cf9273e96f3ee2ac89ffcb17627a78f78e7516b08f94dc435844ae72576a276e"}, - {file = "regex-2023.8.8-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:83215147121e15d5f3a45d99abeed9cf1fe16869d5c233b08c56cdf75f43a504"}, - {file = "regex-2023.8.8-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:3f7454aa427b8ab9101f3787eb178057c5250478e39b99540cfc2b889c7d0586"}, - {file = "regex-2023.8.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f0640913d2c1044d97e30d7c41728195fc37e54d190c5385eacb52115127b882"}, - {file = "regex-2023.8.8-cp38-cp38-win32.whl", hash = "sha256:0c59122ceccb905a941fb23b087b8eafc5290bf983ebcb14d2301febcbe199c7"}, - {file = "regex-2023.8.8-cp38-cp38-win_amd64.whl", hash = "sha256:c12f6f67495ea05c3d542d119d270007090bad5b843f642d418eb601ec0fa7be"}, - {file = "regex-2023.8.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:82cd0a69cd28f6cc3789cc6adeb1027f79526b1ab50b1f6062bbc3a0ccb2dbc3"}, - {file = "regex-2023.8.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:bb34d1605f96a245fc39790a117ac1bac8de84ab7691637b26ab2c5efb8f228c"}, - {file = "regex-2023.8.8-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:987b9ac04d0b38ef4f89fbc035e84a7efad9cdd5f1e29024f9289182c8d99e09"}, - {file = "regex-2023.8.8-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9dd6082f4e2aec9b6a0927202c85bc1b09dcab113f97265127c1dc20e2e32495"}, - {file = "regex-2023.8.8-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7eb95fe8222932c10d4436e7a6f7c99991e3fdd9f36c949eff16a69246dee2dc"}, - {file = "regex-2023.8.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7098c524ba9f20717a56a8d551d2ed491ea89cbf37e540759ed3b776a4f8d6eb"}, - {file = "regex-2023.8.8-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b694430b3f00eb02c594ff5a16db30e054c1b9589a043fe9174584c6efa8033"}, - {file = "regex-2023.8.8-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b2aeab3895d778155054abea5238d0eb9a72e9242bd4b43f42fd911ef9a13470"}, - {file = "regex-2023.8.8-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:988631b9d78b546e284478c2ec15c8a85960e262e247b35ca5eaf7ee22f6050a"}, - {file = "regex-2023.8.8-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:67ecd894e56a0c6108ec5ab1d8fa8418ec0cff45844a855966b875d1039a2e34"}, - {file = "regex-2023.8.8-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:14898830f0a0eb67cae2bbbc787c1a7d6e34ecc06fbd39d3af5fe29a4468e2c9"}, - {file = "regex-2023.8.8-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:f2200e00b62568cfd920127782c61bc1c546062a879cdc741cfcc6976668dfcf"}, - {file = "regex-2023.8.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9691a549c19c22d26a4f3b948071e93517bdf86e41b81d8c6ac8a964bb71e5a6"}, - {file = "regex-2023.8.8-cp39-cp39-win32.whl", hash = "sha256:6ab2ed84bf0137927846b37e882745a827458689eb969028af8032b1b3dac78e"}, - {file = "regex-2023.8.8-cp39-cp39-win_amd64.whl", hash = "sha256:5543c055d8ec7801901e1193a51570643d6a6ab8751b1f7dd9af71af467538bb"}, - {file = "regex-2023.8.8.tar.gz", hash = "sha256:fcbdc5f2b0f1cd0f6a56cdb46fe41d2cce1e644e3b68832f3eeebc5fb0f7712e"}, + {file = "regex-2023.10.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4c34d4f73ea738223a094d8e0ffd6d2c1a1b4c175da34d6b0de3d8d69bee6bcc"}, + {file = "regex-2023.10.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a8f4e49fc3ce020f65411432183e6775f24e02dff617281094ba6ab079ef0915"}, + {file = "regex-2023.10.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4cd1bccf99d3ef1ab6ba835308ad85be040e6a11b0977ef7ea8c8005f01a3c29"}, + {file = "regex-2023.10.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:81dce2ddc9f6e8f543d94b05d56e70d03a0774d32f6cca53e978dc01e4fc75b8"}, + {file = "regex-2023.10.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c6b4d23c04831e3ab61717a707a5d763b300213db49ca680edf8bf13ab5d91b"}, + {file = "regex-2023.10.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c15ad0aee158a15e17e0495e1e18741573d04eb6da06d8b84af726cfc1ed02ee"}, + {file = "regex-2023.10.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6239d4e2e0b52c8bd38c51b760cd870069f0bdf99700a62cd509d7a031749a55"}, + {file = "regex-2023.10.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4a8bf76e3182797c6b1afa5b822d1d5802ff30284abe4599e1247be4fd6b03be"}, + {file = "regex-2023.10.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:d9c727bbcf0065cbb20f39d2b4f932f8fa1631c3e01fcedc979bd4f51fe051c5"}, + {file = "regex-2023.10.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:3ccf2716add72f80714b9a63899b67fa711b654be3fcdd34fa391d2d274ce767"}, + {file = "regex-2023.10.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:107ac60d1bfdc3edb53be75e2a52aff7481b92817cfdddd9b4519ccf0e54a6ff"}, + {file = "regex-2023.10.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:00ba3c9818e33f1fa974693fb55d24cdc8ebafcb2e4207680669d8f8d7cca79a"}, + {file = "regex-2023.10.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f0a47efb1dbef13af9c9a54a94a0b814902e547b7f21acb29434504d18f36e3a"}, + {file = "regex-2023.10.3-cp310-cp310-win32.whl", hash = "sha256:36362386b813fa6c9146da6149a001b7bd063dabc4d49522a1f7aa65b725c7ec"}, + {file = "regex-2023.10.3-cp310-cp310-win_amd64.whl", hash = "sha256:c65a3b5330b54103e7d21cac3f6bf3900d46f6d50138d73343d9e5b2900b2353"}, + {file = "regex-2023.10.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:90a79bce019c442604662d17bf69df99090e24cdc6ad95b18b6725c2988a490e"}, + {file = "regex-2023.10.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c7964c2183c3e6cce3f497e3a9f49d182e969f2dc3aeeadfa18945ff7bdd7051"}, + {file = "regex-2023.10.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ef80829117a8061f974b2fda8ec799717242353bff55f8a29411794d635d964"}, + {file = "regex-2023.10.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5addc9d0209a9afca5fc070f93b726bf7003bd63a427f65ef797a931782e7edc"}, + {file = "regex-2023.10.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c148bec483cc4b421562b4bcedb8e28a3b84fcc8f0aa4418e10898f3c2c0eb9b"}, + {file = "regex-2023.10.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d1f21af4c1539051049796a0f50aa342f9a27cde57318f2fc41ed50b0dbc4ac"}, + {file = "regex-2023.10.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0b9ac09853b2a3e0d0082104036579809679e7715671cfbf89d83c1cb2a30f58"}, + {file = "regex-2023.10.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ebedc192abbc7fd13c5ee800e83a6df252bec691eb2c4bedc9f8b2e2903f5e2a"}, + {file = "regex-2023.10.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d8a993c0a0ffd5f2d3bda23d0cd75e7086736f8f8268de8a82fbc4bd0ac6791e"}, + {file = "regex-2023.10.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:be6b7b8d42d3090b6c80793524fa66c57ad7ee3fe9722b258aec6d0672543fd0"}, + {file = "regex-2023.10.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4023e2efc35a30e66e938de5aef42b520c20e7eda7bb5fb12c35e5d09a4c43f6"}, + {file = "regex-2023.10.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0d47840dc05e0ba04fe2e26f15126de7c755496d5a8aae4a08bda4dd8d646c54"}, + {file = "regex-2023.10.3-cp311-cp311-win32.whl", hash = "sha256:9145f092b5d1977ec8c0ab46e7b3381b2fd069957b9862a43bd383e5c01d18c2"}, + {file = "regex-2023.10.3-cp311-cp311-win_amd64.whl", hash = "sha256:b6104f9a46bd8743e4f738afef69b153c4b8b592d35ae46db07fc28ae3d5fb7c"}, + {file = "regex-2023.10.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:bff507ae210371d4b1fe316d03433ac099f184d570a1a611e541923f78f05037"}, + {file = "regex-2023.10.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:be5e22bbb67924dea15039c3282fa4cc6cdfbe0cbbd1c0515f9223186fc2ec5f"}, + {file = "regex-2023.10.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a992f702c9be9c72fa46f01ca6e18d131906a7180950958f766c2aa294d4b41"}, + {file = "regex-2023.10.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7434a61b158be563c1362d9071358f8ab91b8d928728cd2882af060481244c9e"}, + {file = "regex-2023.10.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c2169b2dcabf4e608416f7f9468737583ce5f0a6e8677c4efbf795ce81109d7c"}, + {file = "regex-2023.10.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9e908ef5889cda4de038892b9accc36d33d72fb3e12c747e2799a0e806ec841"}, + {file = "regex-2023.10.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:12bd4bc2c632742c7ce20db48e0d99afdc05e03f0b4c1af90542e05b809a03d9"}, + {file = "regex-2023.10.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:bc72c231f5449d86d6c7d9cc7cd819b6eb30134bb770b8cfdc0765e48ef9c420"}, + {file = "regex-2023.10.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bce8814b076f0ce5766dc87d5a056b0e9437b8e0cd351b9a6c4e1134a7dfbda9"}, + {file = "regex-2023.10.3-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:ba7cd6dc4d585ea544c1412019921570ebd8a597fabf475acc4528210d7c4a6f"}, + {file = "regex-2023.10.3-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b0c7d2f698e83f15228ba41c135501cfe7d5740181d5903e250e47f617eb4292"}, + {file = "regex-2023.10.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5a8f91c64f390ecee09ff793319f30a0f32492e99f5dc1c72bc361f23ccd0a9a"}, + {file = "regex-2023.10.3-cp312-cp312-win32.whl", hash = "sha256:ad08a69728ff3c79866d729b095872afe1e0557251da4abb2c5faff15a91d19a"}, + {file = "regex-2023.10.3-cp312-cp312-win_amd64.whl", hash = "sha256:39cdf8d141d6d44e8d5a12a8569d5a227f645c87df4f92179bd06e2e2705e76b"}, + {file = "regex-2023.10.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4a3ee019a9befe84fa3e917a2dd378807e423d013377a884c1970a3c2792d293"}, + {file = "regex-2023.10.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76066d7ff61ba6bf3cb5efe2428fc82aac91802844c022d849a1f0f53820502d"}, + {file = "regex-2023.10.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bfe50b61bab1b1ec260fa7cd91106fa9fece57e6beba05630afe27c71259c59b"}, + {file = "regex-2023.10.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fd88f373cb71e6b59b7fa597e47e518282455c2734fd4306a05ca219a1991b0"}, + {file = "regex-2023.10.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3ab05a182c7937fb374f7e946f04fb23a0c0699c0450e9fb02ef567412d2fa3"}, + {file = "regex-2023.10.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dac37cf08fcf2094159922edc7a2784cfcc5c70f8354469f79ed085f0328ebdf"}, + {file = "regex-2023.10.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e54ddd0bb8fb626aa1f9ba7b36629564544954fff9669b15da3610c22b9a0991"}, + {file = "regex-2023.10.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:3367007ad1951fde612bf65b0dffc8fd681a4ab98ac86957d16491400d661302"}, + {file = "regex-2023.10.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:16f8740eb6dbacc7113e3097b0a36065a02e37b47c936b551805d40340fb9971"}, + {file = "regex-2023.10.3-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:f4f2ca6df64cbdd27f27b34f35adb640b5d2d77264228554e68deda54456eb11"}, + {file = "regex-2023.10.3-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:39807cbcbe406efca2a233884e169d056c35aa7e9f343d4e78665246a332f597"}, + {file = "regex-2023.10.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:7eece6fbd3eae4a92d7c748ae825cbc1ee41a89bb1c3db05b5578ed3cfcfd7cb"}, + {file = "regex-2023.10.3-cp37-cp37m-win32.whl", hash = "sha256:ce615c92d90df8373d9e13acddd154152645c0dc060871abf6bd43809673d20a"}, + {file = "regex-2023.10.3-cp37-cp37m-win_amd64.whl", hash = "sha256:0f649fa32fe734c4abdfd4edbb8381c74abf5f34bc0b3271ce687b23729299ed"}, + {file = "regex-2023.10.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9b98b7681a9437262947f41c7fac567c7e1f6eddd94b0483596d320092004533"}, + {file = "regex-2023.10.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:91dc1d531f80c862441d7b66c4505cd6ea9d312f01fb2f4654f40c6fdf5cc37a"}, + {file = "regex-2023.10.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82fcc1f1cc3ff1ab8a57ba619b149b907072e750815c5ba63e7aa2e1163384a4"}, + {file = "regex-2023.10.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7979b834ec7a33aafae34a90aad9f914c41fd6eaa8474e66953f3f6f7cbd4368"}, + {file = "regex-2023.10.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ef71561f82a89af6cfcbee47f0fabfdb6e63788a9258e913955d89fdd96902ab"}, + {file = "regex-2023.10.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd829712de97753367153ed84f2de752b86cd1f7a88b55a3a775eb52eafe8a94"}, + {file = "regex-2023.10.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00e871d83a45eee2f8688d7e6849609c2ca2a04a6d48fba3dff4deef35d14f07"}, + {file = "regex-2023.10.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:706e7b739fdd17cb89e1fbf712d9dc21311fc2333f6d435eac2d4ee81985098c"}, + {file = "regex-2023.10.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:cc3f1c053b73f20c7ad88b0d1d23be7e7b3901229ce89f5000a8399746a6e039"}, + {file = "regex-2023.10.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6f85739e80d13644b981a88f529d79c5bdf646b460ba190bffcaf6d57b2a9863"}, + {file = "regex-2023.10.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:741ba2f511cc9626b7561a440f87d658aabb3d6b744a86a3c025f866b4d19e7f"}, + {file = "regex-2023.10.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:e77c90ab5997e85901da85131fd36acd0ed2221368199b65f0d11bca44549711"}, + {file = "regex-2023.10.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:979c24cbefaf2420c4e377ecd1f165ea08cc3d1fbb44bdc51bccbbf7c66a2cb4"}, + {file = "regex-2023.10.3-cp38-cp38-win32.whl", hash = "sha256:58837f9d221744d4c92d2cf7201c6acd19623b50c643b56992cbd2b745485d3d"}, + {file = "regex-2023.10.3-cp38-cp38-win_amd64.whl", hash = "sha256:c55853684fe08d4897c37dfc5faeff70607a5f1806c8be148f1695be4a63414b"}, + {file = "regex-2023.10.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2c54e23836650bdf2c18222c87f6f840d4943944146ca479858404fedeb9f9af"}, + {file = "regex-2023.10.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:69c0771ca5653c7d4b65203cbfc5e66db9375f1078689459fe196fe08b7b4930"}, + {file = "regex-2023.10.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ac965a998e1388e6ff2e9781f499ad1eaa41e962a40d11c7823c9952c77123e"}, + {file = "regex-2023.10.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1c0e8fae5b27caa34177bdfa5a960c46ff2f78ee2d45c6db15ae3f64ecadde14"}, + {file = "regex-2023.10.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6c56c3d47da04f921b73ff9415fbaa939f684d47293f071aa9cbb13c94afc17d"}, + {file = "regex-2023.10.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ef1e014eed78ab650bef9a6a9cbe50b052c0aebe553fb2881e0453717573f52"}, + {file = "regex-2023.10.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d29338556a59423d9ff7b6eb0cb89ead2b0875e08fe522f3e068b955c3e7b59b"}, + {file = "regex-2023.10.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9c6d0ced3c06d0f183b73d3c5920727268d2201aa0fe6d55c60d68c792ff3588"}, + {file = "regex-2023.10.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:994645a46c6a740ee8ce8df7911d4aee458d9b1bc5639bc968226763d07f00fa"}, + {file = "regex-2023.10.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:66e2fe786ef28da2b28e222c89502b2af984858091675044d93cb50e6f46d7af"}, + {file = "regex-2023.10.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:11175910f62b2b8c055f2b089e0fedd694fe2be3941b3e2633653bc51064c528"}, + {file = "regex-2023.10.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:06e9abc0e4c9ab4779c74ad99c3fc10d3967d03114449acc2c2762ad4472b8ca"}, + {file = "regex-2023.10.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:fb02e4257376ae25c6dd95a5aec377f9b18c09be6ebdefa7ad209b9137b73d48"}, + {file = "regex-2023.10.3-cp39-cp39-win32.whl", hash = "sha256:3b2c3502603fab52d7619b882c25a6850b766ebd1b18de3df23b2f939360e1bd"}, + {file = "regex-2023.10.3-cp39-cp39-win_amd64.whl", hash = "sha256:adbccd17dcaff65704c856bd29951c58a1bd4b2b0f8ad6b826dbd543fe740988"}, + {file = "regex-2023.10.3.tar.gz", hash = "sha256:3fef4f844d2290ee0ba57addcec17eec9e3df73f10a2748485dfd6a3a188cc0f"}, ] [[package]] diff --git a/routers/api/v1/admin/org.go b/routers/api/v1/admin/org.go index 65620459b7a8a..bf68942a9cade 100644 --- a/routers/api/v1/admin/org.go +++ b/routers/api/v1/admin/org.go @@ -62,7 +62,7 @@ func CreateOrg(ctx *context.APIContext) { Visibility: visibility, } - if err := organization.CreateOrganization(org, ctx.ContextUser); err != nil { + if err := organization.CreateOrganization(ctx, org, ctx.ContextUser); err != nil { if user_model.IsErrUserAlreadyExist(err) || db.IsErrNameReserved(err) || db.IsErrNameCharsNotAllowed(err) || diff --git a/routers/api/v1/misc/nodeinfo.go b/routers/api/v1/misc/nodeinfo.go index 22004a8a88445..f0d8d80dd4e1f 100644 --- a/routers/api/v1/misc/nodeinfo.go +++ b/routers/api/v1/misc/nodeinfo.go @@ -42,7 +42,7 @@ func NodeInfo(ctx *context.APIContext) { usersActiveHalfyear := int(user_model.CountUsers(ctx, &user_model.CountUserFilter{LastLoginSince: &timeHaveYearAgo})) allIssues, _ := issues_model.CountIssues(ctx, &issues_model.IssuesOptions{}) - allComments, _ := issues_model.CountComments(&issues_model.FindCommentsOptions{}) + allComments, _ := issues_model.CountComments(ctx, &issues_model.FindCommentsOptions{}) nodeInfoUsage = structs.NodeInfoUsage{ Users: structs.NodeInfoUsageUsers{ diff --git a/routers/api/v1/notify/repo.go b/routers/api/v1/notify/repo.go index e16c54a2c0bb4..0e4efcc640f44 100644 --- a/routers/api/v1/notify/repo.go +++ b/routers/api/v1/notify/repo.go @@ -127,7 +127,7 @@ func ListRepoNotifications(ctx *context.APIContext) { ctx.SetTotalCountHeader(totalCount) - ctx.JSON(http.StatusOK, convert.ToNotifications(nl)) + ctx.JSON(http.StatusOK, convert.ToNotifications(ctx, nl)) } // ReadRepoNotifications mark notification threads as read on a specific repo @@ -222,7 +222,7 @@ func ReadRepoNotifications(ctx *context.APIContext) { return } _ = notif.LoadAttributes(ctx) - changed = append(changed, convert.ToNotificationThread(notif)) + changed = append(changed, convert.ToNotificationThread(ctx, notif)) } ctx.JSON(http.StatusResetContent, changed) } diff --git a/routers/api/v1/notify/threads.go b/routers/api/v1/notify/threads.go index 6a1bce4de41ab..919e52952dc5c 100644 --- a/routers/api/v1/notify/threads.go +++ b/routers/api/v1/notify/threads.go @@ -46,7 +46,7 @@ func GetThread(ctx *context.APIContext) { return } - ctx.JSON(http.StatusOK, convert.ToNotificationThread(n)) + ctx.JSON(http.StatusOK, convert.ToNotificationThread(ctx, n)) } // ReadThread mark notification as read by ID @@ -97,7 +97,7 @@ func ReadThread(ctx *context.APIContext) { ctx.InternalServerError(err) return } - ctx.JSON(http.StatusResetContent, convert.ToNotificationThread(notif)) + ctx.JSON(http.StatusResetContent, convert.ToNotificationThread(ctx, notif)) } func getThread(ctx *context.APIContext) *activities_model.Notification { diff --git a/routers/api/v1/notify/user.go b/routers/api/v1/notify/user.go index a9c6b4361794d..267b7d8ea8c5d 100644 --- a/routers/api/v1/notify/user.go +++ b/routers/api/v1/notify/user.go @@ -86,7 +86,7 @@ func ListNotifications(ctx *context.APIContext) { } ctx.SetTotalCountHeader(totalCount) - ctx.JSON(http.StatusOK, convert.ToNotifications(nl)) + ctx.JSON(http.StatusOK, convert.ToNotifications(ctx, nl)) } // ReadNotifications mark notification threads as read, unread, or pinned @@ -167,7 +167,7 @@ func ReadNotifications(ctx *context.APIContext) { return } _ = notif.LoadAttributes(ctx) - changed = append(changed, convert.ToNotificationThread(notif)) + changed = append(changed, convert.ToNotificationThread(ctx, notif)) } ctx.JSON(http.StatusResetContent, changed) diff --git a/routers/api/v1/org/member.go b/routers/api/v1/org/member.go index 67956e66bd2be..139e01e1f9899 100644 --- a/routers/api/v1/org/member.go +++ b/routers/api/v1/org/member.go @@ -25,7 +25,7 @@ func listMembers(ctx *context.APIContext, publicOnly bool) { ListOptions: utils.GetListOptions(ctx), } - count, err := organization.CountOrgMembers(opts) + count, err := organization.CountOrgMembers(ctx, opts) if err != nil { ctx.InternalServerError(err) return @@ -75,7 +75,7 @@ func ListMembers(ctx *context.APIContext) { publicOnly := true if ctx.Doer != nil { - isMember, err := ctx.Org.Organization.IsOrgMember(ctx.Doer.ID) + isMember, err := ctx.Org.Organization.IsOrgMember(ctx, ctx.Doer.ID) if err != nil { ctx.Error(http.StatusInternalServerError, "IsOrgMember", err) return @@ -144,12 +144,12 @@ func IsMember(ctx *context.APIContext) { return } if ctx.Doer != nil { - userIsMember, err := ctx.Org.Organization.IsOrgMember(ctx.Doer.ID) + userIsMember, err := ctx.Org.Organization.IsOrgMember(ctx, ctx.Doer.ID) if err != nil { ctx.Error(http.StatusInternalServerError, "IsOrgMember", err) return } else if userIsMember || ctx.Doer.IsAdmin { - userToCheckIsMember, err := ctx.Org.Organization.IsOrgMember(userToCheck.ID) + userToCheckIsMember, err := ctx.Org.Organization.IsOrgMember(ctx, userToCheck.ID) if err != nil { ctx.Error(http.StatusInternalServerError, "IsOrgMember", err) } else if userToCheckIsMember { @@ -194,7 +194,7 @@ func IsPublicMember(ctx *context.APIContext) { if ctx.Written() { return } - is, err := organization.IsPublicMembership(ctx.Org.Organization.ID, userToCheck.ID) + is, err := organization.IsPublicMembership(ctx, ctx.Org.Organization.ID, userToCheck.ID) if err != nil { ctx.Error(http.StatusInternalServerError, "IsPublicMembership", err) return @@ -240,7 +240,7 @@ func PublicizeMember(ctx *context.APIContext) { ctx.Error(http.StatusForbidden, "", "Cannot publicize another member") return } - err := organization.ChangeOrgUserStatus(ctx.Org.Organization.ID, userToPublicize.ID, true) + err := organization.ChangeOrgUserStatus(ctx, ctx.Org.Organization.ID, userToPublicize.ID, true) if err != nil { ctx.Error(http.StatusInternalServerError, "ChangeOrgUserStatus", err) return @@ -282,7 +282,7 @@ func ConcealMember(ctx *context.APIContext) { ctx.Error(http.StatusForbidden, "", "Cannot conceal another member") return } - err := organization.ChangeOrgUserStatus(ctx.Org.Organization.ID, userToConceal.ID, false) + err := organization.ChangeOrgUserStatus(ctx, ctx.Org.Organization.ID, userToConceal.ID, false) if err != nil { ctx.Error(http.StatusInternalServerError, "ChangeOrgUserStatus", err) return diff --git a/routers/api/v1/org/org.go b/routers/api/v1/org/org.go index c5f531923b6f1..2594e4afbb3ee 100644 --- a/routers/api/v1/org/org.go +++ b/routers/api/v1/org/org.go @@ -30,12 +30,12 @@ func listUserOrgs(ctx *context.APIContext, u *user_model.User) { UserID: u.ID, IncludePrivate: showPrivate, } - orgs, err := organization.FindOrgs(opts) + orgs, err := organization.FindOrgs(ctx, opts) if err != nil { ctx.Error(http.StatusInternalServerError, "FindOrgs", err) return } - maxResults, err := organization.CountOrgs(opts) + maxResults, err := organization.CountOrgs(ctx, opts) if err != nil { ctx.Error(http.StatusInternalServerError, "CountOrgs", err) return @@ -145,7 +145,7 @@ func GetUserOrgsPermissions(ctx *context.APIContext) { } org := organization.OrgFromUser(o) - authorizeLevel, err := org.GetOrgUserMaxAuthorizeLevel(ctx.ContextUser.ID) + authorizeLevel, err := org.GetOrgUserMaxAuthorizeLevel(ctx, ctx.ContextUser.ID) if err != nil { ctx.Error(http.StatusInternalServerError, "GetOrgUserAuthorizeLevel", err) return @@ -164,7 +164,7 @@ func GetUserOrgsPermissions(ctx *context.APIContext) { op.IsOwner = true } - op.CanCreateRepository, err = org.CanCreateOrgRepo(ctx.ContextUser.ID) + op.CanCreateRepository, err = org.CanCreateOrgRepo(ctx, ctx.ContextUser.ID) if err != nil { ctx.Error(http.StatusInternalServerError, "CanCreateOrgRepo", err) return @@ -268,7 +268,7 @@ func Create(ctx *context.APIContext) { Visibility: visibility, RepoAdminChangeTeamAccess: form.RepoAdminChangeTeamAccess, } - if err := organization.CreateOrganization(org, ctx.Doer); err != nil { + if err := organization.CreateOrganization(ctx, org, ctx.Doer); err != nil { if user_model.IsErrUserAlreadyExist(err) || db.IsErrNameReserved(err) || db.IsErrNameCharsNotAllowed(err) || @@ -429,7 +429,7 @@ func ListOrgActivityFeeds(ctx *context.APIContext) { includePrivate = true } else { org := organization.OrgFromUser(ctx.ContextUser) - isMember, err := org.IsOrgMember(ctx.Doer.ID) + isMember, err := org.IsOrgMember(ctx, ctx.Doer.ID) if err != nil { ctx.Error(http.StatusInternalServerError, "IsOrgMember", err) return diff --git a/routers/api/v1/repo/branch.go b/routers/api/v1/repo/branch.go index 583b591d10b07..f2386a607e657 100644 --- a/routers/api/v1/repo/branch.go +++ b/routers/api/v1/repo/branch.go @@ -572,7 +572,7 @@ func CreateBranchProtection(ctx *context.APIContext) { } var whitelistTeams, mergeWhitelistTeams, approvalsWhitelistTeams []int64 if repo.Owner.IsOrganization() { - whitelistTeams, err = organization.GetTeamIDsByNames(repo.OwnerID, form.PushWhitelistTeams, false) + whitelistTeams, err = organization.GetTeamIDsByNames(ctx, repo.OwnerID, form.PushWhitelistTeams, false) if err != nil { if organization.IsErrTeamNotExist(err) { ctx.Error(http.StatusUnprocessableEntity, "Team does not exist", err) @@ -581,7 +581,7 @@ func CreateBranchProtection(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "GetTeamIDsByNames", err) return } - mergeWhitelistTeams, err = organization.GetTeamIDsByNames(repo.OwnerID, form.MergeWhitelistTeams, false) + mergeWhitelistTeams, err = organization.GetTeamIDsByNames(ctx, repo.OwnerID, form.MergeWhitelistTeams, false) if err != nil { if organization.IsErrTeamNotExist(err) { ctx.Error(http.StatusUnprocessableEntity, "Team does not exist", err) @@ -590,7 +590,7 @@ func CreateBranchProtection(ctx *context.APIContext) { ctx.Error(http.StatusInternalServerError, "GetTeamIDsByNames", err) return } - approvalsWhitelistTeams, err = organization.GetTeamIDsByNames(repo.OwnerID, form.ApprovalsWhitelistTeams, false) + approvalsWhitelistTeams, err = organization.GetTeamIDsByNames(ctx, repo.OwnerID, form.ApprovalsWhitelistTeams, false) if err != nil { if organization.IsErrTeamNotExist(err) { ctx.Error(http.StatusUnprocessableEntity, "Team does not exist", err) @@ -848,7 +848,7 @@ func EditBranchProtection(ctx *context.APIContext) { var whitelistTeams, mergeWhitelistTeams, approvalsWhitelistTeams []int64 if repo.Owner.IsOrganization() { if form.PushWhitelistTeams != nil { - whitelistTeams, err = organization.GetTeamIDsByNames(repo.OwnerID, form.PushWhitelistTeams, false) + whitelistTeams, err = organization.GetTeamIDsByNames(ctx, repo.OwnerID, form.PushWhitelistTeams, false) if err != nil { if organization.IsErrTeamNotExist(err) { ctx.Error(http.StatusUnprocessableEntity, "Team does not exist", err) @@ -861,7 +861,7 @@ func EditBranchProtection(ctx *context.APIContext) { whitelistTeams = protectBranch.WhitelistTeamIDs } if form.MergeWhitelistTeams != nil { - mergeWhitelistTeams, err = organization.GetTeamIDsByNames(repo.OwnerID, form.MergeWhitelistTeams, false) + mergeWhitelistTeams, err = organization.GetTeamIDsByNames(ctx, repo.OwnerID, form.MergeWhitelistTeams, false) if err != nil { if organization.IsErrTeamNotExist(err) { ctx.Error(http.StatusUnprocessableEntity, "Team does not exist", err) @@ -874,7 +874,7 @@ func EditBranchProtection(ctx *context.APIContext) { mergeWhitelistTeams = protectBranch.MergeWhitelistTeamIDs } if form.ApprovalsWhitelistTeams != nil { - approvalsWhitelistTeams, err = organization.GetTeamIDsByNames(repo.OwnerID, form.ApprovalsWhitelistTeams, false) + approvalsWhitelistTeams, err = organization.GetTeamIDsByNames(ctx, repo.OwnerID, form.ApprovalsWhitelistTeams, false) if err != nil { if organization.IsErrTeamNotExist(err) { ctx.Error(http.StatusUnprocessableEntity, "Team does not exist", err) diff --git a/routers/api/v1/repo/collaborators.go b/routers/api/v1/repo/collaborators.go index 206e3fb29bc9b..2538bcdbc628d 100644 --- a/routers/api/v1/repo/collaborators.go +++ b/routers/api/v1/repo/collaborators.go @@ -53,7 +53,7 @@ func ListCollaborators(ctx *context.APIContext) { // "404": // "$ref": "#/responses/notFound" - count, err := repo_model.CountCollaborators(ctx.Repo.Repository.ID) + count, err := repo_model.CountCollaborators(ctx, ctx.Repo.Repository.ID) if err != nil { ctx.InternalServerError(err) return diff --git a/routers/api/v1/repo/fork.go b/routers/api/v1/repo/fork.go index ef152eef85913..69433bf4cc401 100644 --- a/routers/api/v1/repo/fork.go +++ b/routers/api/v1/repo/fork.go @@ -123,7 +123,7 @@ func CreateFork(ctx *context.APIContext) { } return } - isMember, err := org.IsOrgMember(ctx.Doer.ID) + isMember, err := org.IsOrgMember(ctx, ctx.Doer.ID) if err != nil { ctx.Error(http.StatusInternalServerError, "IsOrgMember", err) return diff --git a/routers/api/v1/repo/issue.go b/routers/api/v1/repo/issue.go index 2bced1f233e78..58689b72a6c54 100644 --- a/routers/api/v1/repo/issue.go +++ b/routers/api/v1/repo/issue.go @@ -805,7 +805,7 @@ func EditIssue(ctx *context.APIContext) { deadlineUnix = timeutil.TimeStamp(deadline.Unix()) } - if err := issues_model.UpdateIssueDeadline(issue, deadlineUnix, ctx.Doer); err != nil { + if err := issues_model.UpdateIssueDeadline(ctx, issue, deadlineUnix, ctx.Doer); err != nil { ctx.Error(http.StatusInternalServerError, "UpdateIssueDeadline", err) return } @@ -844,7 +844,7 @@ func EditIssue(ctx *context.APIContext) { } if form.State != nil { if issue.IsPull { - if pr, err := issue.GetPullRequest(); err != nil { + if pr, err := issue.GetPullRequest(ctx); err != nil { ctx.Error(http.StatusInternalServerError, "GetPullRequest", err) return } else if pr.HasMerged { @@ -854,7 +854,7 @@ func EditIssue(ctx *context.APIContext) { } issue.IsClosed = api.StateClosed == api.StateType(*form.State) } - statusChangeComment, titleChanged, err := issues_model.UpdateIssueByAPI(issue, ctx.Doer) + statusChangeComment, titleChanged, err := issues_model.UpdateIssueByAPI(ctx, issue, ctx.Doer) if err != nil { if issues_model.IsErrDependenciesLeft(err) { ctx.Error(http.StatusPreconditionFailed, "DependenciesLeft", "cannot close this issue because it still has open dependencies") @@ -992,7 +992,7 @@ func UpdateIssueDeadline(ctx *context.APIContext) { deadlineUnix = timeutil.TimeStamp(deadline.Unix()) } - if err := issues_model.UpdateIssueDeadline(issue, deadlineUnix, ctx.Doer); err != nil { + if err := issues_model.UpdateIssueDeadline(ctx, issue, deadlineUnix, ctx.Doer); err != nil { ctx.Error(http.StatusInternalServerError, "UpdateIssueDeadline", err) return } diff --git a/routers/api/v1/repo/issue_attachment.go b/routers/api/v1/repo/issue_attachment.go index b4768004adad3..11d19b21ff5d4 100644 --- a/routers/api/v1/repo/issue_attachment.go +++ b/routers/api/v1/repo/issue_attachment.go @@ -178,7 +178,7 @@ func CreateIssueAttachment(ctx *context.APIContext) { filename = query } - attachment, err := attachment.UploadAttachment(file, setting.Attachment.AllowedTypes, header.Size, &repo_model.Attachment{ + attachment, err := attachment.UploadAttachment(ctx, file, setting.Attachment.AllowedTypes, header.Size, &repo_model.Attachment{ Name: filename, UploaderID: ctx.Doer.ID, RepoID: ctx.Repo.Repository.ID, diff --git a/routers/api/v1/repo/issue_comment.go b/routers/api/v1/repo/issue_comment.go index 8ef968c128d5f..c718424f7ebc2 100644 --- a/routers/api/v1/repo/issue_comment.go +++ b/routers/api/v1/repo/issue_comment.go @@ -86,7 +86,7 @@ func ListIssueComments(ctx *context.APIContext) { return } - totalCount, err := issues_model.CountComments(opts) + totalCount, err := issues_model.CountComments(ctx, opts) if err != nil { ctx.InternalServerError(err) return @@ -285,7 +285,7 @@ func ListRepoIssueComments(ctx *context.APIContext) { return } - totalCount, err := issues_model.CountComments(opts) + totalCount, err := issues_model.CountComments(ctx, opts) if err != nil { ctx.InternalServerError(err) return diff --git a/routers/api/v1/repo/issue_comment_attachment.go b/routers/api/v1/repo/issue_comment_attachment.go index 63ed51c72d903..c327c54d101c0 100644 --- a/routers/api/v1/repo/issue_comment_attachment.go +++ b/routers/api/v1/repo/issue_comment_attachment.go @@ -182,7 +182,7 @@ func CreateIssueCommentAttachment(ctx *context.APIContext) { filename = query } - attachment, err := attachment.UploadAttachment(file, setting.Attachment.AllowedTypes, header.Size, &repo_model.Attachment{ + attachment, err := attachment.UploadAttachment(ctx, file, setting.Attachment.AllowedTypes, header.Size, &repo_model.Attachment{ Name: filename, UploaderID: ctx.Doer.ID, RepoID: ctx.Repo.Repository.ID, diff --git a/routers/api/v1/repo/issue_label.go b/routers/api/v1/repo/issue_label.go index 2f9ad7060ce7b..c2f530956e9b4 100644 --- a/routers/api/v1/repo/issue_label.go +++ b/routers/api/v1/repo/issue_label.go @@ -317,7 +317,7 @@ func prepareForReplaceOrAdd(ctx *context.APIContext, form api.IssueLabelsOption) return nil, nil, err } - labels, err := issues_model.GetLabelsByIDs(ctx, form.Labels, "id", "repo_id", "org_id") + labels, err := issues_model.GetLabelsByIDs(ctx, form.Labels, "id", "repo_id", "org_id", "name", "exclusive") if err != nil { ctx.Error(http.StatusInternalServerError, "GetLabelsByIDs", err) return nil, nil, err diff --git a/routers/api/v1/repo/issue_pin.go b/routers/api/v1/repo/issue_pin.go index d9b1bcc894075..61f88de34eb64 100644 --- a/routers/api/v1/repo/issue_pin.go +++ b/routers/api/v1/repo/issue_pin.go @@ -241,7 +241,7 @@ func ListPinnedPullRequests(ctx *context.APIContext) { apiPrs := make([]*api.PullRequest, len(issues)) for i, currentIssue := range issues { - pr, err := currentIssue.GetPullRequest() + pr, err := currentIssue.GetPullRequest(ctx) if err != nil { ctx.Error(http.StatusInternalServerError, "GetPullRequest", err) return diff --git a/routers/api/v1/repo/issue_subscription.go b/routers/api/v1/repo/issue_subscription.go index ab9a037040377..ece880c03e1a1 100644 --- a/routers/api/v1/repo/issue_subscription.go +++ b/routers/api/v1/repo/issue_subscription.go @@ -206,7 +206,7 @@ func CheckIssueSubscription(ctx *context.APIContext) { Ignored: !watching, Reason: nil, CreatedAt: issue.CreatedUnix.AsTime(), - URL: issue.APIURL() + "/subscriptions", + URL: issue.APIURL(ctx) + "/subscriptions", RepositoryURL: ctx.Repo.Repository.APIURL(), }) } diff --git a/routers/api/v1/repo/issue_tracked_time.go b/routers/api/v1/repo/issue_tracked_time.go index ecbc5cf00f8bc..06cd411ea1e6e 100644 --- a/routers/api/v1/repo/issue_tracked_time.go +++ b/routers/api/v1/repo/issue_tracked_time.go @@ -283,7 +283,7 @@ func ResetIssueTime(ctx *context.APIContext) { return } - err = issues_model.DeleteIssueUserTimes(issue, ctx.Doer) + err = issues_model.DeleteIssueUserTimes(ctx, issue, ctx.Doer) if err != nil { if db.IsErrNotExist(err) { ctx.Error(http.StatusNotFound, "DeleteIssueUserTimes", err) @@ -356,7 +356,7 @@ func DeleteTime(ctx *context.APIContext) { return } - time, err := issues_model.GetTrackedTimeByID(ctx.ParamsInt64(":id")) + time, err := issues_model.GetTrackedTimeByID(ctx, ctx.ParamsInt64(":id")) if err != nil { if db.IsErrNotExist(err) { ctx.NotFound(err) @@ -376,7 +376,7 @@ func DeleteTime(ctx *context.APIContext) { return } - err = issues_model.DeleteTime(time) + err = issues_model.DeleteTime(ctx, time) if err != nil { ctx.Error(http.StatusInternalServerError, "DeleteTime", err) return diff --git a/routers/api/v1/repo/migrate.go b/routers/api/v1/repo/migrate.go index 4ddd452372902..14ff04e7bf72f 100644 --- a/routers/api/v1/repo/migrate.go +++ b/routers/api/v1/repo/migrate.go @@ -93,7 +93,7 @@ func Migrate(ctx *context.APIContext) { if repoOwner.IsOrganization() { // Check ownership of organization. - isOwner, err := organization.OrgFromUser(repoOwner).IsOwnedBy(ctx.Doer.ID) + isOwner, err := organization.OrgFromUser(repoOwner).IsOwnedBy(ctx, ctx.Doer.ID) if err != nil { ctx.Error(http.StatusInternalServerError, "IsOwnedBy", err) return diff --git a/routers/api/v1/repo/mirror.go b/routers/api/v1/repo/mirror.go index 15c7046b49336..72ddc758dce47 100644 --- a/routers/api/v1/repo/mirror.go +++ b/routers/api/v1/repo/mirror.go @@ -176,7 +176,7 @@ func ListPushMirrors(ctx *context.APIContext) { responsePushMirrors := make([]*api.PushMirror, 0, len(pushMirrors)) for _, mirror := range pushMirrors { - m, err := convert.ToPushMirror(mirror) + m, err := convert.ToPushMirror(ctx, mirror) if err == nil { responsePushMirrors = append(responsePushMirrors, m) } @@ -232,7 +232,7 @@ func GetPushMirrorByName(ctx *context.APIContext) { ctx.Error(http.StatusNotFound, "GetPushMirrors", err) return } - m, err := convert.ToPushMirror(pushMirror) + m, err := convert.ToPushMirror(ctx, pushMirror) if err != nil { ctx.ServerError("GetPushMirrorByRemoteName", err) return @@ -381,7 +381,7 @@ func CreatePushMirror(ctx *context.APIContext, mirrorOption *api.CreatePushMirro ctx.ServerError("AddPushMirrorRemote", err) return } - m, err := convert.ToPushMirror(pushMirror) + m, err := convert.ToPushMirror(ctx, pushMirror) if err != nil { ctx.ServerError("ToPushMirror", err) return diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go index 1439d48a8eb1c..586f3385b1883 100644 --- a/routers/api/v1/repo/pull.go +++ b/routers/api/v1/repo/pull.go @@ -524,7 +524,7 @@ func EditPullRequest(ctx *context.APIContext) { deadlineUnix = timeutil.TimeStamp(deadline.Unix()) } - if err := issues_model.UpdateIssueDeadline(issue, deadlineUnix, ctx.Doer); err != nil { + if err := issues_model.UpdateIssueDeadline(ctx, issue, deadlineUnix, ctx.Doer); err != nil { ctx.Error(http.StatusInternalServerError, "UpdateIssueDeadline", err) return } @@ -591,7 +591,7 @@ func EditPullRequest(ctx *context.APIContext) { } issue.IsClosed = api.StateClosed == api.StateType(*form.State) } - statusChangeComment, titleChanged, err := issues_model.UpdateIssueByAPI(issue, ctx.Doer) + statusChangeComment, titleChanged, err := issues_model.UpdateIssueByAPI(ctx, issue, ctx.Doer) if err != nil { if issues_model.IsErrDependenciesLeft(err) { ctx.Error(http.StatusPreconditionFailed, "DependenciesLeft", "cannot close this pull request because it still has open dependencies") @@ -1442,7 +1442,7 @@ func GetPullRequestFiles(ctx *context.APIContext) { maxLines := setting.Git.MaxGitDiffLines // FIXME: If there are too many files in the repo, may cause some unpredictable issues. - diff, err := gitdiff.GetDiff(baseGitRepo, + diff, err := gitdiff.GetDiff(ctx, baseGitRepo, &gitdiff.DiffOptions{ BeforeCommitID: startCommitID, AfterCommitID: endCommitID, diff --git a/routers/api/v1/repo/pull_review.go b/routers/api/v1/repo/pull_review.go index 43379821c90c5..7b9445be4c068 100644 --- a/routers/api/v1/repo/pull_review.go +++ b/routers/api/v1/repo/pull_review.go @@ -260,7 +260,7 @@ func DeletePullReview(ctx *context.APIContext) { return } - if err := issues_model.DeleteReview(review); err != nil { + if err := issues_model.DeleteReview(ctx, review); err != nil { ctx.Error(http.StatusInternalServerError, "DeleteReview", fmt.Errorf("can not delete ReviewID: %d", review.ID)) return } @@ -713,7 +713,7 @@ func apiReviewRequest(ctx *context.APIContext, opts api.PullReviewRequestOptions } if comment != nil && isAdd { - if err = comment.LoadReview(); err != nil { + if err = comment.LoadReview(ctx); err != nil { ctx.ServerError("ReviewRequest", err) return } @@ -757,7 +757,7 @@ func apiReviewRequest(ctx *context.APIContext, opts api.PullReviewRequestOptions } if comment != nil && isAdd { - if err = comment.LoadReview(); err != nil { + if err = comment.LoadReview(ctx); err != nil { ctx.ServerError("ReviewRequest", err) return } diff --git a/routers/api/v1/repo/release_attachment.go b/routers/api/v1/repo/release_attachment.go index e1421831287f5..168ef550c5ea9 100644 --- a/routers/api/v1/repo/release_attachment.go +++ b/routers/api/v1/repo/release_attachment.go @@ -200,7 +200,7 @@ func CreateReleaseAttachment(ctx *context.APIContext) { } // Create a new attachment and save the file - attach, err := attachment.UploadAttachment(file, setting.Repository.Release.AllowedTypes, header.Size, &repo_model.Attachment{ + attach, err := attachment.UploadAttachment(ctx, file, setting.Repository.Release.AllowedTypes, header.Size, &repo_model.Attachment{ Name: filename, UploaderID: ctx.Doer.ID, RepoID: release.RepoID, diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go index 9769668f47afd..64c41d3a97e6c 100644 --- a/routers/api/v1/repo/repo.go +++ b/routers/api/v1/repo/repo.go @@ -396,7 +396,7 @@ func Generate(ctx *context.APIContext) { } if !ctx.Doer.IsAdmin { - canCreate, err := organization.OrgFromUser(ctxUser).CanCreateOrgRepo(ctx.Doer.ID) + canCreate, err := organization.OrgFromUser(ctxUser).CanCreateOrgRepo(ctx, ctx.Doer.ID) if err != nil { ctx.ServerError("CanCreateOrgRepo", err) return @@ -502,7 +502,7 @@ func CreateOrgRepo(ctx *context.APIContext) { } if !ctx.Doer.IsAdmin { - canCreate, err := org.CanCreateOrgRepo(ctx.Doer.ID) + canCreate, err := org.CanCreateOrgRepo(ctx, ctx.Doer.ID) if err != nil { ctx.Error(http.StatusInternalServerError, "CanCreateOrgRepo", err) return @@ -982,7 +982,7 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { } if len(units)+len(deleteUnitTypes) > 0 { - if err := repo_model.UpdateRepositoryUnits(repo, units, deleteUnitTypes); err != nil { + if err := repo_model.UpdateRepositoryUnits(ctx, repo, units, deleteUnitTypes); err != nil { ctx.Error(http.StatusInternalServerError, "UpdateRepositoryUnits", err) return err } diff --git a/routers/api/v1/repo/transfer.go b/routers/api/v1/repo/transfer.go index 326895918e3d0..b3120f4be0898 100644 --- a/routers/api/v1/repo/transfer.go +++ b/routers/api/v1/repo/transfer.go @@ -68,7 +68,7 @@ func Transfer(ctx *context.APIContext) { } if newOwner.Type == user_model.UserTypeOrganization { - if !ctx.Doer.IsAdmin && newOwner.Visibility == api.VisibleTypePrivate && !organization.OrgFromUser(newOwner).HasMemberWithUserID(ctx.Doer.ID) { + if !ctx.Doer.IsAdmin && newOwner.Visibility == api.VisibleTypePrivate && !organization.OrgFromUser(newOwner).HasMemberWithUserID(ctx, ctx.Doer.ID) { // The user shouldn't know about this organization ctx.Error(http.StatusNotFound, "", "The new owner does not exist or cannot be found") return diff --git a/routers/common/db.go b/routers/common/db.go index 2e86fbd0fd42c..547f727ce2478 100644 --- a/routers/common/db.go +++ b/routers/common/db.go @@ -10,8 +10,10 @@ import ( "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/migrations" + system_model "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/setting/config" "xorm.io/xorm" ) @@ -36,6 +38,7 @@ func InitDBEngine(ctx context.Context) (err error) { time.Sleep(setting.Database.DBConnectBackoff) } db.HasEngine = true + config.SetDynGetter(system_model.NewDatabaseDynKeyGetter()) return nil } diff --git a/routers/install/install.go b/routers/install/install.go index 3eb16b9ce8555..185e4bf6bf6c6 100644 --- a/routers/install/install.go +++ b/routers/install/install.go @@ -430,15 +430,14 @@ func SubmitInstall(ctx *context.Context) { cfg.Section("service").Key("ENABLE_NOTIFY_MAIL").SetValue(fmt.Sprint(form.MailNotify)) cfg.Section("server").Key("OFFLINE_MODE").SetValue(fmt.Sprint(form.OfflineMode)) - // if you are reinstalling, this maybe not right because of missing version - if err := system_model.SetSettingNoVersion(ctx, system_model.KeyPictureDisableGravatar, strconv.FormatBool(form.DisableGravatar)); err != nil { - ctx.RenderWithErr(ctx.Tr("install.save_config_failed", err), tplInstall, &form) - return - } - if err := system_model.SetSettingNoVersion(ctx, system_model.KeyPictureEnableFederatedAvatar, strconv.FormatBool(form.EnableFederatedAvatar)); err != nil { + if err := system_model.SetSettings(ctx, map[string]string{ + setting.Config().Picture.DisableGravatar.DynKey(): strconv.FormatBool(form.DisableGravatar), + setting.Config().Picture.EnableFederatedAvatar.DynKey(): strconv.FormatBool(form.EnableFederatedAvatar), + }); err != nil { ctx.RenderWithErr(ctx.Tr("install.save_config_failed", err), tplInstall, &form) return } + cfg.Section("openid").Key("ENABLE_OPENID_SIGNIN").SetValue(fmt.Sprint(form.EnableOpenIDSignIn)) cfg.Section("openid").Key("ENABLE_OPENID_SIGNUP").SetValue(fmt.Sprint(form.EnableOpenIDSignUp)) cfg.Section("service").Key("DISABLE_REGISTRATION").SetValue(fmt.Sprint(form.DisableRegistration)) diff --git a/routers/web/admin/config.go b/routers/web/admin/config.go index c70a2d1c95125..c827f2a4f5042 100644 --- a/routers/web/admin/config.go +++ b/routers/web/admin/config.go @@ -5,19 +5,19 @@ package admin import ( - "fmt" "net/http" "net/url" - "strconv" "strings" system_model "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/modules/base" + "code.gitea.io/gitea/modules/container" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/json" "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/setting/config" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/services/mailer" @@ -101,16 +101,6 @@ func Config(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("admin.config") ctx.Data["PageIsAdminConfig"] = true - systemSettings, err := system_model.GetAllSettings(ctx) - if err != nil { - ctx.ServerError("system_model.GetAllSettings", err) - return - } - - // All editable settings from UI - ctx.Data["SystemSettings"] = systemSettings - ctx.PageData["adminConfigPage"] = true - ctx.Data["CustomConf"] = setting.CustomConf ctx.Data["AppUrl"] = setting.AppURL ctx.Data["AppBuiltWith"] = setting.AppBuiltWith @@ -170,7 +160,8 @@ func Config(ctx *context.Context) { ctx.Data["LogSQL"] = setting.Database.LogSQL ctx.Data["Loggers"] = log.GetManager().DumpLoggers() - + config.GetDynGetter().InvalidateCache() + ctx.Data["SystemConfig"] = setting.Config() prepareDeprecatedWarningsAlert(ctx) ctx.HTML(http.StatusOK, tplConfig) @@ -178,51 +169,19 @@ func Config(ctx *context.Context) { func ChangeConfig(ctx *context.Context) { key := strings.TrimSpace(ctx.FormString("key")) - if key == "" { - ctx.JSONRedirect(ctx.Req.URL.String()) - return - } value := ctx.FormString("value") - version := ctx.FormInt("version") - - if check, ok := changeConfigChecks[key]; ok { - if err := check(ctx, value); err != nil { - log.Warn("refused to set setting: %v", err) - ctx.JSON(http.StatusOK, map[string]string{ - "err": ctx.Tr("admin.config.set_setting_failed", key), - }) - return - } + cfg := setting.Config() + allowedKeys := container.SetOf(cfg.Picture.DisableGravatar.DynKey(), cfg.Picture.EnableFederatedAvatar.DynKey()) + if !allowedKeys.Contains(key) { + ctx.JSONError(ctx.Tr("admin.config.set_setting_failed", key)) + return } - - if err := system_model.SetSetting(ctx, &system_model.Setting{ - SettingKey: key, - SettingValue: value, - Version: version, - }); err != nil { + if err := system_model.SetSettings(ctx, map[string]string{key: value}); err != nil { log.Error("set setting failed: %v", err) - ctx.JSON(http.StatusOK, map[string]string{ - "err": ctx.Tr("admin.config.set_setting_failed", key), - }) + ctx.JSONError(ctx.Tr("admin.config.set_setting_failed", key)) return } - ctx.JSON(http.StatusOK, map[string]any{ - "version": version + 1, - }) -} - -var changeConfigChecks = map[string]func(ctx *context.Context, newValue string) error{ - system_model.KeyPictureDisableGravatar: func(_ *context.Context, newValue string) error { - if v, _ := strconv.ParseBool(newValue); setting.OfflineMode && !v { - return fmt.Errorf("%q should be true when OFFLINE_MODE is true", system_model.KeyPictureDisableGravatar) - } - return nil - }, - system_model.KeyPictureEnableFederatedAvatar: func(_ *context.Context, newValue string) error { - if v, _ := strconv.ParseBool(newValue); setting.OfflineMode && v { - return fmt.Errorf("%q cannot be false when OFFLINE_MODE is true", system_model.KeyPictureEnableFederatedAvatar) - } - return nil - }, + config.GetDynGetter().InvalidateCache() + ctx.JSONOK() } diff --git a/routers/web/admin/notice.go b/routers/web/admin/notice.go index ca85c96e1015c..99039a2a9f901 100644 --- a/routers/web/admin/notice.go +++ b/routers/web/admin/notice.go @@ -24,7 +24,7 @@ func Notices(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("admin.notices") ctx.Data["PageIsAdminNotices"] = true - total := system_model.CountNotices() + total := system_model.CountNotices(ctx) page := ctx.FormInt("page") if page <= 1 { page = 1 diff --git a/routers/web/admin/users.go b/routers/web/admin/users.go index af49b00ad6280..18d7313e7203f 100644 --- a/routers/web/admin/users.go +++ b/routers/web/admin/users.go @@ -15,7 +15,6 @@ import ( "code.gitea.io/gitea/models/db" org_model "code.gitea.io/gitea/models/organization" repo_model "code.gitea.io/gitea/models/repo" - system_model "code.gitea.io/gitea/models/system" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/auth/password" "code.gitea.io/gitea/modules/base" @@ -290,7 +289,7 @@ func ViewUser(ctx *context.Context) { ctx.Data["Emails"] = emails ctx.Data["EmailsTotal"] = len(emails) - orgs, err := org_model.FindOrgs(org_model.FindOrgOptions{ + orgs, err := org_model.FindOrgs(ctx, org_model.FindOrgOptions{ ListOptions: db.ListOptions{ ListAll: true, }, @@ -308,17 +307,18 @@ func ViewUser(ctx *context.Context) { ctx.HTML(http.StatusOK, tplUserView) } -// EditUser show editing user page -func EditUser(ctx *context.Context) { +func editUserCommon(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("admin.users.edit_account") ctx.Data["PageIsAdminUsers"] = true ctx.Data["DisableRegularOrgCreation"] = setting.Admin.DisableRegularOrgCreation ctx.Data["DisableMigrations"] = setting.Repository.DisableMigrations ctx.Data["AllowedUserVisibilityModes"] = setting.Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice() - ctx.Data["DisableGravatar"] = system_model.GetSettingWithCacheBool(ctx, system_model.KeyPictureDisableGravatar, - setting.GetDefaultDisableGravatar(), - ) + ctx.Data["DisableGravatar"] = setting.Config().Picture.DisableGravatar.Value(ctx) +} +// EditUser show editing user page +func EditUser(ctx *context.Context) { + editUserCommon(ctx) prepareUserInfo(ctx) if ctx.Written() { return @@ -329,19 +329,13 @@ func EditUser(ctx *context.Context) { // EditUserPost response for editing user func EditUserPost(ctx *context.Context) { - form := web.GetForm(ctx).(*forms.AdminEditUserForm) - ctx.Data["Title"] = ctx.Tr("admin.users.edit_account") - ctx.Data["PageIsAdminUsers"] = true - ctx.Data["DisableMigrations"] = setting.Repository.DisableMigrations - ctx.Data["AllowedUserVisibilityModes"] = setting.Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice() - ctx.Data["DisableGravatar"] = system_model.GetSettingWithCacheBool(ctx, system_model.KeyPictureDisableGravatar, - setting.GetDefaultDisableGravatar()) - + editUserCommon(ctx) u := prepareUserInfo(ctx) if ctx.Written() { return } + form := web.GetForm(ctx).(*forms.AdminEditUserForm) if ctx.HasError() { ctx.HTML(http.StatusOK, tplUserEdit) return diff --git a/routers/web/auth/oauth.go b/routers/web/auth/oauth.go index 79f4711c26f85..ce58cbdef9994 100644 --- a/routers/web/auth/oauth.go +++ b/routers/web/auth/oauth.go @@ -312,12 +312,12 @@ func getOAuthGroupsForUser(ctx go_context.Context, user *user_model.User) ([]str var groups []string for _, org := range orgs { groups = append(groups, org.Name) - teams, err := org.LoadTeams() + teams, err := org.LoadTeams(ctx) if err != nil { return nil, fmt.Errorf("LoadTeams: %w", err) } for _, team := range teams { - if team.IsMember(user.ID) { + if team.IsMember(ctx, user.ID) { groups = append(groups, org.Name+":"+team.LowerName) } } diff --git a/routers/web/base.go b/routers/web/base.go index e4b7d8ce8db2e..78dde57fa6f85 100644 --- a/routers/web/base.go +++ b/routers/web/base.go @@ -19,81 +19,80 @@ import ( "code.gitea.io/gitea/modules/web/routing" ) -func storageHandler(storageSetting *setting.Storage, prefix string, objStore storage.ObjectStorage) func(next http.Handler) http.Handler { +func storageHandler(storageSetting *setting.Storage, prefix string, objStore storage.ObjectStorage) http.HandlerFunc { prefix = strings.Trim(prefix, "/") funcInfo := routing.GetFuncInfo(storageHandler, prefix) - return func(next http.Handler) http.Handler { - if storageSetting.MinioConfig.ServeDirect { - return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { - if req.Method != "GET" && req.Method != "HEAD" { - next.ServeHTTP(w, req) - return - } - - if !strings.HasPrefix(req.URL.Path, "/"+prefix+"/") { - next.ServeHTTP(w, req) - return - } - routing.UpdateFuncInfo(req.Context(), funcInfo) - - rPath := strings.TrimPrefix(req.URL.Path, "/"+prefix+"/") - rPath = util.PathJoinRelX(rPath) - - u, err := objStore.URL(rPath, path.Base(rPath)) - if err != nil { - if os.IsNotExist(err) || errors.Is(err, os.ErrNotExist) { - log.Warn("Unable to find %s %s", prefix, rPath) - http.Error(w, "file not found", http.StatusNotFound) - return - } - log.Error("Error whilst getting URL for %s %s. Error: %v", prefix, rPath, err) - http.Error(w, fmt.Sprintf("Error whilst getting URL for %s %s", prefix, rPath), http.StatusInternalServerError) - return - } - - http.Redirect(w, req, u.String(), http.StatusTemporaryRedirect) - }) - } + if storageSetting.MinioConfig.ServeDirect { return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { if req.Method != "GET" && req.Method != "HEAD" { - next.ServeHTTP(w, req) + http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) return } if !strings.HasPrefix(req.URL.Path, "/"+prefix+"/") { - next.ServeHTTP(w, req) + http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) return } routing.UpdateFuncInfo(req.Context(), funcInfo) rPath := strings.TrimPrefix(req.URL.Path, "/"+prefix+"/") rPath = util.PathJoinRelX(rPath) - if rPath == "" || rPath == "." { - http.Error(w, "file not found", http.StatusNotFound) - return - } - fi, err := objStore.Stat(rPath) + u, err := objStore.URL(rPath, path.Base(rPath)) if err != nil { if os.IsNotExist(err) || errors.Is(err, os.ErrNotExist) { log.Warn("Unable to find %s %s", prefix, rPath) - http.Error(w, "file not found", http.StatusNotFound) + http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) return } - log.Error("Error whilst opening %s %s. Error: %v", prefix, rPath, err) - http.Error(w, fmt.Sprintf("Error whilst opening %s %s", prefix, rPath), http.StatusInternalServerError) + log.Error("Error whilst getting URL for %s %s. Error: %v", prefix, rPath, err) + http.Error(w, fmt.Sprintf("Error whilst getting URL for %s %s", prefix, rPath), http.StatusInternalServerError) return } - fr, err := objStore.Open(rPath) - if err != nil { - log.Error("Error whilst opening %s %s. Error: %v", prefix, rPath, err) - http.Error(w, fmt.Sprintf("Error whilst opening %s %s", prefix, rPath), http.StatusInternalServerError) - return - } - defer fr.Close() - httpcache.ServeContentWithCacheControl(w, req, path.Base(rPath), fi.ModTime(), fr) + http.Redirect(w, req, u.String(), http.StatusTemporaryRedirect) }) } + + return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + if req.Method != "GET" && req.Method != "HEAD" { + http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) + return + } + + if !strings.HasPrefix(req.URL.Path, "/"+prefix+"/") { + http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) + return + } + routing.UpdateFuncInfo(req.Context(), funcInfo) + + rPath := strings.TrimPrefix(req.URL.Path, "/"+prefix+"/") + rPath = util.PathJoinRelX(rPath) + if rPath == "" || rPath == "." { + http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) + return + } + + fi, err := objStore.Stat(rPath) + if err != nil { + if os.IsNotExist(err) || errors.Is(err, os.ErrNotExist) { + log.Warn("Unable to find %s %s", prefix, rPath) + http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) + return + } + log.Error("Error whilst opening %s %s. Error: %v", prefix, rPath, err) + http.Error(w, fmt.Sprintf("Error whilst opening %s %s", prefix, rPath), http.StatusInternalServerError) + return + } + + fr, err := objStore.Open(rPath) + if err != nil { + log.Error("Error whilst opening %s %s. Error: %v", prefix, rPath, err) + http.Error(w, fmt.Sprintf("Error whilst opening %s %s", prefix, rPath), http.StatusInternalServerError) + return + } + defer fr.Close() + httpcache.ServeContentWithCacheControl(w, req, path.Base(rPath), fi.ModTime(), fr) + }) } diff --git a/routers/web/feed/convert.go b/routers/web/feed/convert.go index 3775ba495a0d3..04078955bbd52 100644 --- a/routers/web/feed/convert.go +++ b/routers/web/feed/convert.go @@ -23,28 +23,28 @@ import ( "github.com/gorilla/feeds" ) -func toBranchLink(act *activities_model.Action) string { - return act.GetRepoAbsoluteLink() + "/src/branch/" + util.PathEscapeSegments(act.GetBranch()) +func toBranchLink(ctx *context.Context, act *activities_model.Action) string { + return act.GetRepoAbsoluteLink(ctx) + "/src/branch/" + util.PathEscapeSegments(act.GetBranch()) } -func toTagLink(act *activities_model.Action) string { - return act.GetRepoAbsoluteLink() + "/src/tag/" + util.PathEscapeSegments(act.GetTag()) +func toTagLink(ctx *context.Context, act *activities_model.Action) string { + return act.GetRepoAbsoluteLink(ctx) + "/src/tag/" + util.PathEscapeSegments(act.GetTag()) } -func toIssueLink(act *activities_model.Action) string { - return act.GetRepoAbsoluteLink() + "/issues/" + url.PathEscape(act.GetIssueInfos()[0]) +func toIssueLink(ctx *context.Context, act *activities_model.Action) string { + return act.GetRepoAbsoluteLink(ctx) + "/issues/" + url.PathEscape(act.GetIssueInfos()[0]) } -func toPullLink(act *activities_model.Action) string { - return act.GetRepoAbsoluteLink() + "/pulls/" + url.PathEscape(act.GetIssueInfos()[0]) +func toPullLink(ctx *context.Context, act *activities_model.Action) string { + return act.GetRepoAbsoluteLink(ctx) + "/pulls/" + url.PathEscape(act.GetIssueInfos()[0]) } -func toSrcLink(act *activities_model.Action) string { - return act.GetRepoAbsoluteLink() + "/src/" + util.PathEscapeSegments(act.GetBranch()) +func toSrcLink(ctx *context.Context, act *activities_model.Action) string { + return act.GetRepoAbsoluteLink(ctx) + "/src/" + util.PathEscapeSegments(act.GetBranch()) } -func toReleaseLink(act *activities_model.Action) string { - return act.GetRepoAbsoluteLink() + "/releases/tag/" + util.PathEscapeSegments(act.GetBranch()) +func toReleaseLink(ctx *context.Context, act *activities_model.Action) string { + return act.GetRepoAbsoluteLink(ctx) + "/releases/tag/" + util.PathEscapeSegments(act.GetBranch()) } // renderMarkdown creates a minimal markdown render context from an action. @@ -52,11 +52,11 @@ func toReleaseLink(act *activities_model.Action) string { func renderMarkdown(ctx *context.Context, act *activities_model.Action, content string) string { markdownCtx := &markup.RenderContext{ Ctx: ctx, - URLPrefix: act.GetRepoLink(), + URLPrefix: act.GetRepoLink(ctx), Type: markdown.MarkupName, Metas: map[string]string{ - "user": act.GetRepoUserName(), - "repo": act.GetRepoName(), + "user": act.GetRepoUserName(ctx), + "repo": act.GetRepoName(ctx), }, } markdown, err := markdown.RenderString(markdownCtx, content) @@ -73,123 +73,123 @@ func feedActionsToFeedItems(ctx *context.Context, actions activities_model.Actio var content, desc, title string - link := &feeds.Link{Href: act.GetCommentHTMLURL()} + link := &feeds.Link{Href: act.GetCommentHTMLURL(ctx)} // title title = act.ActUser.DisplayName() + " " switch act.OpType { case activities_model.ActionCreateRepo: - title += ctx.TrHTMLEscapeArgs("action.create_repo", act.GetRepoAbsoluteLink(), act.ShortRepoPath()) - link.Href = act.GetRepoAbsoluteLink() + title += ctx.TrHTMLEscapeArgs("action.create_repo", act.GetRepoAbsoluteLink(ctx), act.ShortRepoPath(ctx)) + link.Href = act.GetRepoAbsoluteLink(ctx) case activities_model.ActionRenameRepo: - title += ctx.TrHTMLEscapeArgs("action.rename_repo", act.GetContent(), act.GetRepoAbsoluteLink(), act.ShortRepoPath()) - link.Href = act.GetRepoAbsoluteLink() + title += ctx.TrHTMLEscapeArgs("action.rename_repo", act.GetContent(), act.GetRepoAbsoluteLink(ctx), act.ShortRepoPath(ctx)) + link.Href = act.GetRepoAbsoluteLink(ctx) case activities_model.ActionCommitRepo: - link.Href = toBranchLink(act) + link.Href = toBranchLink(ctx, act) if len(act.Content) != 0 { - title += ctx.TrHTMLEscapeArgs("action.commit_repo", act.GetRepoAbsoluteLink(), link.Href, act.GetBranch(), act.ShortRepoPath()) + title += ctx.TrHTMLEscapeArgs("action.commit_repo", act.GetRepoAbsoluteLink(ctx), link.Href, act.GetBranch(), act.ShortRepoPath(ctx)) } else { - title += ctx.TrHTMLEscapeArgs("action.create_branch", act.GetRepoAbsoluteLink(), link.Href, act.GetBranch(), act.ShortRepoPath()) + title += ctx.TrHTMLEscapeArgs("action.create_branch", act.GetRepoAbsoluteLink(ctx), link.Href, act.GetBranch(), act.ShortRepoPath(ctx)) } case activities_model.ActionCreateIssue: - link.Href = toIssueLink(act) - title += ctx.TrHTMLEscapeArgs("action.create_issue", link.Href, act.GetIssueInfos()[0], act.ShortRepoPath()) + link.Href = toIssueLink(ctx, act) + title += ctx.TrHTMLEscapeArgs("action.create_issue", link.Href, act.GetIssueInfos()[0], act.ShortRepoPath(ctx)) case activities_model.ActionCreatePullRequest: - link.Href = toPullLink(act) - title += ctx.TrHTMLEscapeArgs("action.create_pull_request", link.Href, act.GetIssueInfos()[0], act.ShortRepoPath()) + link.Href = toPullLink(ctx, act) + title += ctx.TrHTMLEscapeArgs("action.create_pull_request", link.Href, act.GetIssueInfos()[0], act.ShortRepoPath(ctx)) case activities_model.ActionTransferRepo: - link.Href = act.GetRepoAbsoluteLink() - title += ctx.TrHTMLEscapeArgs("action.transfer_repo", act.GetContent(), act.GetRepoAbsoluteLink(), act.ShortRepoPath()) + link.Href = act.GetRepoAbsoluteLink(ctx) + title += ctx.TrHTMLEscapeArgs("action.transfer_repo", act.GetContent(), act.GetRepoAbsoluteLink(ctx), act.ShortRepoPath(ctx)) case activities_model.ActionPushTag: - link.Href = toTagLink(act) - title += ctx.TrHTMLEscapeArgs("action.push_tag", act.GetRepoAbsoluteLink(), link.Href, act.GetTag(), act.ShortRepoPath()) + link.Href = toTagLink(ctx, act) + title += ctx.TrHTMLEscapeArgs("action.push_tag", act.GetRepoAbsoluteLink(ctx), link.Href, act.GetTag(), act.ShortRepoPath(ctx)) case activities_model.ActionCommentIssue: - issueLink := toIssueLink(act) + issueLink := toIssueLink(ctx, act) if link.Href == "#" { link.Href = issueLink } - title += ctx.TrHTMLEscapeArgs("action.comment_issue", issueLink, act.GetIssueInfos()[0], act.ShortRepoPath()) + title += ctx.TrHTMLEscapeArgs("action.comment_issue", issueLink, act.GetIssueInfos()[0], act.ShortRepoPath(ctx)) case activities_model.ActionMergePullRequest: - pullLink := toPullLink(act) + pullLink := toPullLink(ctx, act) if link.Href == "#" { link.Href = pullLink } - title += ctx.TrHTMLEscapeArgs("action.merge_pull_request", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath()) + title += ctx.TrHTMLEscapeArgs("action.merge_pull_request", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath(ctx)) case activities_model.ActionAutoMergePullRequest: - pullLink := toPullLink(act) + pullLink := toPullLink(ctx, act) if link.Href == "#" { link.Href = pullLink } - title += ctx.TrHTMLEscapeArgs("action.auto_merge_pull_request", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath()) + title += ctx.TrHTMLEscapeArgs("action.auto_merge_pull_request", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath(ctx)) case activities_model.ActionCloseIssue: - issueLink := toIssueLink(act) + issueLink := toIssueLink(ctx, act) if link.Href == "#" { link.Href = issueLink } - title += ctx.TrHTMLEscapeArgs("action.close_issue", issueLink, act.GetIssueInfos()[0], act.ShortRepoPath()) + title += ctx.TrHTMLEscapeArgs("action.close_issue", issueLink, act.GetIssueInfos()[0], act.ShortRepoPath(ctx)) case activities_model.ActionReopenIssue: - issueLink := toIssueLink(act) + issueLink := toIssueLink(ctx, act) if link.Href == "#" { link.Href = issueLink } - title += ctx.TrHTMLEscapeArgs("action.reopen_issue", issueLink, act.GetIssueInfos()[0], act.ShortRepoPath()) + title += ctx.TrHTMLEscapeArgs("action.reopen_issue", issueLink, act.GetIssueInfos()[0], act.ShortRepoPath(ctx)) case activities_model.ActionClosePullRequest: - pullLink := toPullLink(act) + pullLink := toPullLink(ctx, act) if link.Href == "#" { link.Href = pullLink } - title += ctx.TrHTMLEscapeArgs("action.close_pull_request", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath()) + title += ctx.TrHTMLEscapeArgs("action.close_pull_request", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath(ctx)) case activities_model.ActionReopenPullRequest: - pullLink := toPullLink(act) + pullLink := toPullLink(ctx, act) if link.Href == "#" { link.Href = pullLink } - title += ctx.TrHTMLEscapeArgs("action.reopen_pull_request", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath()) + title += ctx.TrHTMLEscapeArgs("action.reopen_pull_request", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath(ctx)) case activities_model.ActionDeleteTag: - link.Href = act.GetRepoAbsoluteLink() - title += ctx.TrHTMLEscapeArgs("action.delete_tag", act.GetRepoAbsoluteLink(), act.GetTag(), act.ShortRepoPath()) + link.Href = act.GetRepoAbsoluteLink(ctx) + title += ctx.TrHTMLEscapeArgs("action.delete_tag", act.GetRepoAbsoluteLink(ctx), act.GetTag(), act.ShortRepoPath(ctx)) case activities_model.ActionDeleteBranch: - link.Href = act.GetRepoAbsoluteLink() - title += ctx.TrHTMLEscapeArgs("action.delete_branch", act.GetRepoAbsoluteLink(), html.EscapeString(act.GetBranch()), act.ShortRepoPath()) + link.Href = act.GetRepoAbsoluteLink(ctx) + title += ctx.TrHTMLEscapeArgs("action.delete_branch", act.GetRepoAbsoluteLink(ctx), html.EscapeString(act.GetBranch()), act.ShortRepoPath(ctx)) case activities_model.ActionMirrorSyncPush: - srcLink := toSrcLink(act) + srcLink := toSrcLink(ctx, act) if link.Href == "#" { link.Href = srcLink } - title += ctx.TrHTMLEscapeArgs("action.mirror_sync_push", act.GetRepoAbsoluteLink(), srcLink, act.GetBranch(), act.ShortRepoPath()) + title += ctx.TrHTMLEscapeArgs("action.mirror_sync_push", act.GetRepoAbsoluteLink(ctx), srcLink, act.GetBranch(), act.ShortRepoPath(ctx)) case activities_model.ActionMirrorSyncCreate: - srcLink := toSrcLink(act) + srcLink := toSrcLink(ctx, act) if link.Href == "#" { link.Href = srcLink } - title += ctx.TrHTMLEscapeArgs("action.mirror_sync_create", act.GetRepoAbsoluteLink(), srcLink, act.GetBranch(), act.ShortRepoPath()) + title += ctx.TrHTMLEscapeArgs("action.mirror_sync_create", act.GetRepoAbsoluteLink(ctx), srcLink, act.GetBranch(), act.ShortRepoPath(ctx)) case activities_model.ActionMirrorSyncDelete: - link.Href = act.GetRepoAbsoluteLink() - title += ctx.TrHTMLEscapeArgs("action.mirror_sync_delete", act.GetRepoAbsoluteLink(), act.GetBranch(), act.ShortRepoPath()) + link.Href = act.GetRepoAbsoluteLink(ctx) + title += ctx.TrHTMLEscapeArgs("action.mirror_sync_delete", act.GetRepoAbsoluteLink(ctx), act.GetBranch(), act.ShortRepoPath(ctx)) case activities_model.ActionApprovePullRequest: - pullLink := toPullLink(act) - title += ctx.TrHTMLEscapeArgs("action.approve_pull_request", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath()) + pullLink := toPullLink(ctx, act) + title += ctx.TrHTMLEscapeArgs("action.approve_pull_request", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath(ctx)) case activities_model.ActionRejectPullRequest: - pullLink := toPullLink(act) - title += ctx.TrHTMLEscapeArgs("action.reject_pull_request", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath()) + pullLink := toPullLink(ctx, act) + title += ctx.TrHTMLEscapeArgs("action.reject_pull_request", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath(ctx)) case activities_model.ActionCommentPull: - pullLink := toPullLink(act) - title += ctx.TrHTMLEscapeArgs("action.comment_pull", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath()) + pullLink := toPullLink(ctx, act) + title += ctx.TrHTMLEscapeArgs("action.comment_pull", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath(ctx)) case activities_model.ActionPublishRelease: - releaseLink := toReleaseLink(act) + releaseLink := toReleaseLink(ctx, act) if link.Href == "#" { link.Href = releaseLink } - title += ctx.TrHTMLEscapeArgs("action.publish_release", act.GetRepoAbsoluteLink(), releaseLink, act.ShortRepoPath(), act.Content) + title += ctx.TrHTMLEscapeArgs("action.publish_release", act.GetRepoAbsoluteLink(ctx), releaseLink, act.ShortRepoPath(ctx), act.Content) case activities_model.ActionPullReviewDismissed: - pullLink := toPullLink(act) - title += ctx.TrHTMLEscapeArgs("action.review_dismissed", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath(), act.GetIssueInfos()[1]) + pullLink := toPullLink(ctx, act) + title += ctx.TrHTMLEscapeArgs("action.review_dismissed", pullLink, act.GetIssueInfos()[0], act.ShortRepoPath(ctx), act.GetIssueInfos()[1]) case activities_model.ActionStarRepo: - link.Href = act.GetRepoAbsoluteLink() - title += ctx.TrHTMLEscapeArgs("action.starred_repo", act.GetRepoAbsoluteLink(), act.GetRepoPath()) + link.Href = act.GetRepoAbsoluteLink(ctx) + title += ctx.TrHTMLEscapeArgs("action.starred_repo", act.GetRepoAbsoluteLink(ctx), act.GetRepoPath(ctx)) case activities_model.ActionWatchRepo: - link.Href = act.GetRepoAbsoluteLink() - title += ctx.TrHTMLEscapeArgs("action.watched_repo", act.GetRepoAbsoluteLink(), act.GetRepoPath()) + link.Href = act.GetRepoAbsoluteLink(ctx) + title += ctx.TrHTMLEscapeArgs("action.watched_repo", act.GetRepoAbsoluteLink(ctx), act.GetRepoPath(ctx)) default: return nil, fmt.Errorf("unknown action type: %v", act.OpType) } @@ -199,14 +199,14 @@ func feedActionsToFeedItems(ctx *context.Context, actions activities_model.Actio switch act.OpType { case activities_model.ActionCommitRepo, activities_model.ActionMirrorSyncPush: push := templates.ActionContent2Commits(act) - repoLink := act.GetRepoAbsoluteLink() + repoLink := act.GetRepoAbsoluteLink(ctx) for _, commit := range push.Commits { if len(desc) != 0 { desc += "\n\n" } desc += fmt.Sprintf("%s\n%s", - html.EscapeString(fmt.Sprintf("%s/commit/%s", act.GetRepoAbsoluteLink(), commit.Sha1)), + html.EscapeString(fmt.Sprintf("%s/commit/%s", act.GetRepoAbsoluteLink(ctx), commit.Sha1)), commit.Sha1, templates.RenderCommitMessage(ctx, commit.Message, repoLink, nil), ) @@ -215,14 +215,14 @@ func feedActionsToFeedItems(ctx *context.Context, actions activities_model.Actio if push.Len > 1 { link = &feeds.Link{Href: fmt.Sprintf("%s/%s", setting.AppSubURL, push.CompareURL)} } else if push.Len == 1 { - link = &feeds.Link{Href: fmt.Sprintf("%s/commit/%s", act.GetRepoAbsoluteLink(), push.Commits[0].Sha1)} + link = &feeds.Link{Href: fmt.Sprintf("%s/commit/%s", act.GetRepoAbsoluteLink(ctx), push.Commits[0].Sha1)} } case activities_model.ActionCreateIssue, activities_model.ActionCreatePullRequest: desc = strings.Join(act.GetIssueInfos(), "#") content = renderMarkdown(ctx, act, act.GetIssueContent(ctx)) case activities_model.ActionCommentIssue, activities_model.ActionApprovePullRequest, activities_model.ActionRejectPullRequest, activities_model.ActionCommentPull: - desc = act.GetIssueTitle() + desc = act.GetIssueTitle(ctx) comment := act.GetIssueInfos()[1] if len(comment) != 0 { desc += "\n\n" + renderMarkdown(ctx, act, comment) @@ -230,7 +230,7 @@ func feedActionsToFeedItems(ctx *context.Context, actions activities_model.Actio case activities_model.ActionMergePullRequest, activities_model.ActionAutoMergePullRequest: desc = act.GetIssueInfos()[1] case activities_model.ActionCloseIssue, activities_model.ActionReopenIssue, activities_model.ActionClosePullRequest, activities_model.ActionReopenPullRequest: - desc = act.GetIssueTitle() + desc = act.GetIssueTitle(ctx) case activities_model.ActionPullReviewDismissed: desc = ctx.Tr("action.review_dismissed_reason") + "\n\n" + act.GetIssueInfos()[2] } diff --git a/routers/web/org/members.go b/routers/web/org/members.go index 34cff05ea0b92..247025a7cb7f1 100644 --- a/routers/web/org/members.go +++ b/routers/web/org/members.go @@ -38,7 +38,7 @@ func Members(ctx *context.Context) { } if ctx.Doer != nil { - isMember, err := ctx.Org.Organization.IsOrgMember(ctx.Doer.ID) + isMember, err := ctx.Org.Organization.IsOrgMember(ctx, ctx.Doer.ID) if err != nil { ctx.Error(http.StatusInternalServerError, "IsOrgMember") return @@ -47,7 +47,7 @@ func Members(ctx *context.Context) { } ctx.Data["PublicOnly"] = opts.PublicOnly - total, err := organization.CountOrgMembers(opts) + total, err := organization.CountOrgMembers(ctx, opts) if err != nil { ctx.Error(http.StatusInternalServerError, "CountOrgMembers") return @@ -70,7 +70,7 @@ func Members(ctx *context.Context) { ctx.Data["Page"] = pager ctx.Data["Members"] = members ctx.Data["MembersIsPublicMember"] = membersIsPublic - ctx.Data["MembersIsUserOrgOwner"] = organization.IsUserOrgOwner(members, org.ID) + ctx.Data["MembersIsUserOrgOwner"] = organization.IsUserOrgOwner(ctx, members, org.ID) ctx.Data["MembersTwoFaStatus"] = members.GetTwoFaStatus(ctx) ctx.HTML(http.StatusOK, tplMembers) @@ -92,13 +92,13 @@ func MembersAction(ctx *context.Context) { ctx.Error(http.StatusNotFound) return } - err = organization.ChangeOrgUserStatus(org.ID, uid, false) + err = organization.ChangeOrgUserStatus(ctx, org.ID, uid, false) case "public": if ctx.Doer.ID != uid && !ctx.Org.IsOwner { ctx.Error(http.StatusNotFound) return } - err = organization.ChangeOrgUserStatus(org.ID, uid, true) + err = organization.ChangeOrgUserStatus(ctx, org.ID, uid, true) case "remove": if !ctx.Org.IsOwner { ctx.Error(http.StatusNotFound) diff --git a/routers/web/org/org.go b/routers/web/org/org.go index f67e7edb4c7cc..52f8df8a1c761 100644 --- a/routers/web/org/org.go +++ b/routers/web/org/org.go @@ -58,7 +58,7 @@ func CreatePost(ctx *context.Context) { RepoAdminChangeTeamAccess: form.RepoAdminChangeTeamAccess, } - if err := organization.CreateOrganization(org, ctx.Doer); err != nil { + if err := organization.CreateOrganization(ctx, org, ctx.Doer); err != nil { ctx.Data["Err_OrgName"] = true switch { case user_model.IsErrUserAlreadyExist(err): diff --git a/routers/web/org/projects.go b/routers/web/org/projects.go index 4032162b5cf24..19d3682f51853 100644 --- a/routers/web/org/projects.go +++ b/routers/web/org/projects.go @@ -179,7 +179,7 @@ func NewProjectPost(ctx *context.Context) { newProject.Type = project_model.TypeIndividual } - if err := project_model.NewProject(&newProject); err != nil { + if err := project_model.NewProject(ctx, &newProject); err != nil { ctx.ServerError("NewProject", err) return } @@ -201,7 +201,7 @@ func ChangeProjectStatus(ctx *context.Context) { } id := ctx.ParamsInt64(":id") - if err := project_model.ChangeProjectStatusByRepoIDAndID(0, id, toClose); err != nil { + if err := project_model.ChangeProjectStatusByRepoIDAndID(ctx, 0, id, toClose); err != nil { if project_model.IsErrProjectNotExist(err) { ctx.NotFound("", err) } else { @@ -320,7 +320,7 @@ func EditProjectPost(ctx *context.Context) { ctx.Flash.Success(ctx.Tr("repo.projects.edit_success", p.Title)) if ctx.FormString("redirect") == "project" { - ctx.Redirect(p.Link()) + ctx.Redirect(p.Link(ctx)) } else { ctx.Redirect(ctx.ContextUser.HomeLink() + "/-/projects") } @@ -515,7 +515,7 @@ func DeleteProjectBoard(ctx *context.Context) { return } - if err := project_model.DeleteBoardByID(ctx.ParamsInt64(":boardID")); err != nil { + if err := project_model.DeleteBoardByID(ctx, ctx.ParamsInt64(":boardID")); err != nil { ctx.ServerError("DeleteProjectBoardByID", err) return } @@ -537,7 +537,7 @@ func AddBoardToProjectPost(ctx *context.Context) { return } - if err := project_model.NewBoard(&project_model.Board{ + if err := project_model.NewBoard(ctx, &project_model.Board{ ProjectID: project.ID, Title: form.Title, Color: form.Color, @@ -623,7 +623,7 @@ func SetDefaultProjectBoard(ctx *context.Context) { return } - if err := project_model.SetDefaultBoard(project.ID, board.ID); err != nil { + if err := project_model.SetDefaultBoard(ctx, project.ID, board.ID); err != nil { ctx.ServerError("SetDefaultBoard", err) return } @@ -638,7 +638,7 @@ func UnsetDefaultProjectBoard(ctx *context.Context) { return } - if err := project_model.SetDefaultBoard(project.ID, 0); err != nil { + if err := project_model.SetDefaultBoard(ctx, project.ID, 0); err != nil { ctx.ServerError("SetDefaultBoard", err) return } @@ -738,7 +738,7 @@ func MoveIssues(ctx *context.Context) { } } - if err = project_model.MoveIssuesOnProjectBoard(board, sortedIssueIDs); err != nil { + if err = project_model.MoveIssuesOnProjectBoard(ctx, board, sortedIssueIDs); err != nil { ctx.ServerError("MoveIssuesOnProjectBoard", err) return } diff --git a/routers/web/org/teams.go b/routers/web/org/teams.go index 90029009fe5e3..98014d99a6ff3 100644 --- a/routers/web/org/teams.go +++ b/routers/web/org/teams.go @@ -159,7 +159,7 @@ func TeamsAction(ctx *context.Context) { return } - if ctx.Org.Team.IsMember(u.ID) { + if ctx.Org.Team.IsMember(ctx, u.ID) { ctx.Flash.Error(ctx.Tr("org.teams.add_duplicate_users")) } else { err = models.AddTeamMember(ctx, ctx.Org.Team, u.ID) diff --git a/routers/web/repo/actions/view.go b/routers/web/repo/actions/view.go index a9c2858303aac..2c69b1361614e 100644 --- a/routers/web/repo/actions/view.go +++ b/routers/web/repo/actions/view.go @@ -608,7 +608,7 @@ func disableOrEnableWorkflowFile(ctx *context_module.Context, isEnable bool) { cfg.DisableWorkflow(workflow) } - if err := repo_model.UpdateRepoUnit(cfgUnit); err != nil { + if err := repo_model.UpdateRepoUnit(ctx, cfgUnit); err != nil { ctx.ServerError("UpdateRepoUnit", err) return } diff --git a/routers/web/repo/attachment.go b/routers/web/repo/attachment.go index 7b7fa9e994ce4..8c322b45e5ec8 100644 --- a/routers/web/repo/attachment.go +++ b/routers/web/repo/attachment.go @@ -45,7 +45,7 @@ func uploadAttachment(ctx *context.Context, repoID int64, allowedTypes string) { } defer file.Close() - attach, err := attachment.UploadAttachment(file, allowedTypes, header.Size, &repo_model.Attachment{ + attach, err := attachment.UploadAttachment(ctx, file, allowedTypes, header.Size, &repo_model.Attachment{ Name: header.Filename, UploaderID: ctx.Doer.ID, RepoID: repoID, diff --git a/routers/web/repo/blame.go b/routers/web/repo/blame.go index e4506a857e730..1f1cca897ef5c 100644 --- a/routers/web/repo/blame.go +++ b/routers/web/repo/blame.go @@ -70,7 +70,7 @@ func RefBlame(ctx *context.Context) { // Get current entry user currently looking at. entry, err := ctx.Repo.Commit.GetTreeEntryByPath(ctx.Repo.TreePath) if err != nil { - ctx.NotFoundOrServerError("Repo.Commit.GetTreeEntryByPath", git.IsErrNotExist, err) + HandleGitError(ctx, "Repo.Commit.GetTreeEntryByPath", err) return } diff --git a/routers/web/repo/commit.go b/routers/web/repo/commit.go index 9a620f6d37226..3587d287fc5ef 100644 --- a/routers/web/repo/commit.go +++ b/routers/web/repo/commit.go @@ -305,7 +305,7 @@ func Diff(ctx *context.Context) { maxLines, maxFiles = -1, -1 } - diff, err := gitdiff.GetDiff(gitRepo, &gitdiff.DiffOptions{ + diff, err := gitdiff.GetDiff(ctx, gitRepo, &gitdiff.DiffOptions{ AfterCommitID: commitID, SkipTo: ctx.FormString("skip-to"), MaxLines: maxLines, @@ -361,7 +361,7 @@ func Diff(ctx *context.Context) { ctx.Data["DiffNotAvailable"] = diff.NumFiles == 0 if err := asymkey_model.CalculateTrustStatus(verification, ctx.Repo.Repository.GetTrustModel(), func(user *user_model.User) (bool, error) { - return repo_model.IsOwnerMemberCollaborator(ctx.Repo.Repository, user.ID) + return repo_model.IsOwnerMemberCollaborator(ctx, ctx.Repo.Repository, user.ID) }, nil); err != nil { ctx.ServerError("CalculateTrustStatus", err) return diff --git a/routers/web/repo/compare.go b/routers/web/repo/compare.go index ecc8e66702b6f..d66dd582a15cd 100644 --- a/routers/web/repo/compare.go +++ b/routers/web/repo/compare.go @@ -252,7 +252,6 @@ func ParseCompareInfo(ctx *context.Context) *CompareInfo { isSameRepo = true ci.HeadUser = ctx.Repo.Owner ci.HeadBranch = headInfos[0] - } else if len(headInfos) == 2 { headInfosSplit := strings.Split(headInfos[0], "/") if len(headInfosSplit) == 1 { @@ -407,6 +406,9 @@ func ParseCompareInfo(ctx *context.Context) *CompareInfo { return nil } defer ci.HeadGitRepo.Close() + } else { + ctx.NotFound("ParseCompareInfo", nil) + return nil } ctx.Data["HeadRepo"] = ci.HeadRepo @@ -609,7 +611,7 @@ func PrepareCompareDiff( maxLines, maxFiles = -1, -1 } - diff, err := gitdiff.GetDiff(ci.HeadGitRepo, + diff, err := gitdiff.GetDiff(ctx, ci.HeadGitRepo, &gitdiff.DiffOptions{ BeforeCommitID: beforeCommitID, AfterCommitID: headCommitID, diff --git a/routers/web/repo/editor.go b/routers/web/repo/editor.go index 9d9fee3a77c37..1ad091b70fd9d 100644 --- a/routers/web/repo/editor.go +++ b/routers/web/repo/editor.go @@ -123,7 +123,7 @@ func editFile(ctx *context.Context, isNewFile bool) { if !isNewFile { entry, err := ctx.Repo.Commit.GetTreeEntryByPath(ctx.Repo.TreePath) if err != nil { - ctx.NotFoundOrServerError("GetTreeEntryByPath", git.IsErrNotExist, err) + HandleGitError(ctx, "Repo.Commit.GetTreeEntryByPath", err) return } diff --git a/routers/web/repo/helper.go b/routers/web/repo/helper.go index f8cdefdc8ef99..a98abe566f843 100644 --- a/routers/web/repo/helper.go +++ b/routers/web/repo/helper.go @@ -4,9 +4,12 @@ package repo import ( + "net/url" "sort" "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/git" ) func MakeSelfOnTop(doer *user.User, users []*user.User) []*user.User { @@ -20,3 +23,22 @@ func MakeSelfOnTop(doer *user.User, users []*user.User) []*user.User { } return users } + +func HandleGitError(ctx *context.Context, msg string, err error) { + if git.IsErrNotExist(err) { + refType := "" + switch { + case ctx.Repo.IsViewBranch: + refType = "branch" + case ctx.Repo.IsViewTag: + refType = "tag" + case ctx.Repo.IsViewCommit: + refType = "commit" + } + ctx.Data["NotFoundPrompt"] = ctx.Locale.Tr("repo.tree_path_not_found_"+refType, ctx.Repo.TreePath, url.PathEscape(ctx.Repo.RefName)) + ctx.Data["NotFoundGoBackURL"] = ctx.Repo.RepoLink + "/src/" + refType + "/" + url.PathEscape(ctx.Repo.RefName) + ctx.NotFound(msg, err) + } else { + ctx.ServerError(msg, err) + } +} diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index c360578f1f0e9..5bee8c76a910b 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -305,7 +305,7 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti // Check read status if !ctx.IsSigned { issues[i].IsRead = true - } else if err = issues[i].GetIsRead(ctx.Doer.ID); err != nil { + } else if err = issues[i].GetIsRead(ctx, ctx.Doer.ID); err != nil { ctx.ServerError("GetIsRead", err) return } @@ -442,6 +442,11 @@ func issues(ctx *context.Context, milestoneID, projectID int64, isPullOption uti pager.AddParam(ctx, "project", "ProjectID") pager.AddParam(ctx, "assignee", "AssigneeID") pager.AddParam(ctx, "poster", "PosterID") + + if ctx.FormBool("archived") { + ctx.Data["ShowArchivedLabels"] = true + pager.AddParam(ctx, "archived", "ShowArchivedLabels") + } ctx.Data["Page"] = pager } @@ -960,10 +965,8 @@ func NewIssue(ctx *context.Context) { _, templateErrs := issue_service.GetTemplatesFromDefaultBranch(ctx.Repo.Repository, ctx.Repo.GitRepo) templateLoaded, errs := setTemplateIfExists(ctx, issueTemplateKey, IssueTemplateCandidates) - if len(errs) > 0 { - for k, v := range errs { - templateErrs[k] = v - } + for k, v := range errs { + templateErrs[k] = v } if ctx.Written() { return @@ -1265,7 +1268,7 @@ func roleDescriptor(ctx stdCtx.Context, repo *repo_model.Repository, poster *use } // Otherwise check if poster is the real repo admin. - ok, err := access_model.IsUserRealRepoAdmin(repo, poster) + ok, err := access_model.IsUserRealRepoAdmin(ctx, repo, poster) if err != nil { return roleDescriptor, err } @@ -1549,8 +1552,8 @@ func ViewIssue(ctx *context.Context) { } else { ctx.Data["CanUseTimetracker"] = false } - if ctx.Data["WorkingUsers"], err = issues_model.TotalTimes(&issues_model.FindTrackedTimesOptions{IssueID: issue.ID}); err != nil { - ctx.ServerError("TotalTimes", err) + if ctx.Data["WorkingUsers"], err = issues_model.TotalTimesForEachUser(ctx, &issues_model.FindTrackedTimesOptions{IssueID: issue.ID}); err != nil { + ctx.ServerError("TotalTimesForEachUser", err) return } } @@ -1608,7 +1611,7 @@ func ViewIssue(ctx *context.Context) { marked[comment.PosterID] = comment.ShowRole participants = addParticipant(comment.Poster, participants) } else if comment.Type == issues_model.CommentTypeLabel { - if err = comment.LoadLabel(); err != nil { + if err = comment.LoadLabel(ctx); err != nil { ctx.ServerError("LoadLabel", err) return } @@ -1629,7 +1632,7 @@ func ViewIssue(ctx *context.Context) { } } else if comment.Type == issues_model.CommentTypeProject { - if err = comment.LoadProject(); err != nil { + if err = comment.LoadProject(ctx); err != nil { ctx.ServerError("LoadProject", err) return } @@ -1648,12 +1651,12 @@ func ViewIssue(ctx *context.Context) { } } else if comment.Type == issues_model.CommentTypeAssignees || comment.Type == issues_model.CommentTypeReviewRequest { - if err = comment.LoadAssigneeUserAndTeam(); err != nil { + if err = comment.LoadAssigneeUserAndTeam(ctx); err != nil { ctx.ServerError("LoadAssigneeUserAndTeam", err) return } } else if comment.Type == issues_model.CommentTypeRemoveDependency || comment.Type == issues_model.CommentTypeAddDependency { - if err = comment.LoadDepIssueDetails(); err != nil { + if err = comment.LoadDepIssueDetails(ctx); err != nil { if !issues_model.IsErrIssueNotExist(err) { ctx.ServerError("LoadDepIssueDetails", err) return @@ -1670,7 +1673,7 @@ func ViewIssue(ctx *context.Context) { ctx.ServerError("RenderString", err) return } - if err = comment.LoadReview(); err != nil && !issues_model.IsErrReviewNotExist(err) { + if err = comment.LoadReview(ctx); err != nil && !issues_model.IsErrReviewNotExist(err) { ctx.ServerError("LoadReview", err) return } @@ -1709,7 +1712,7 @@ func ViewIssue(ctx *context.Context) { } } } - if err = comment.LoadResolveDoer(); err != nil { + if err = comment.LoadResolveDoer(ctx); err != nil { ctx.ServerError("LoadResolveDoer", err) return } @@ -1723,7 +1726,7 @@ func ViewIssue(ctx *context.Context) { comment.Type == issues_model.CommentTypeStopTracking || comment.Type == issues_model.CommentTypeDeleteTimeManual { // drop error since times could be pruned from DB.. - _ = comment.LoadTime() + _ = comment.LoadTime(ctx) if comment.Content != "" { // Content before v1.21 did store the formated string instead of seconds, // so "|" is used as delimeter to mark the new format @@ -1794,7 +1797,7 @@ func ViewIssue(ctx *context.Context) { return } - if ctx.Data["CanMarkConversation"], err = issues_model.CanMarkConversation(issue, ctx.Doer); err != nil { + if ctx.Data["CanMarkConversation"], err = issues_model.CanMarkConversation(ctx, issue, ctx.Doer); err != nil { ctx.ServerError("CanMarkConversation", err) return } @@ -2261,7 +2264,7 @@ func UpdateIssueDeadline(ctx *context.Context) { deadlineUnix = timeutil.TimeStamp(deadline.Unix()) } - if err := issues_model.UpdateIssueDeadline(issue, deadlineUnix, ctx.Doer); err != nil { + if err := issues_model.UpdateIssueDeadline(ctx, issue, deadlineUnix, ctx.Doer); err != nil { ctx.Error(http.StatusInternalServerError, "UpdateIssueDeadline", err.Error()) return } @@ -3319,7 +3322,7 @@ func ChangeCommentReaction(ctx *context.Context) { } // Reload new reactions comment.Reactions = nil - if err = comment.LoadReactions(ctx.Repo.Repository); err != nil { + if err = comment.LoadReactions(ctx, ctx.Repo.Repository); err != nil { log.Info("comment.LoadReactions: %s", err) break } @@ -3333,7 +3336,7 @@ func ChangeCommentReaction(ctx *context.Context) { // Reload new reactions comment.Reactions = nil - if err = comment.LoadReactions(ctx.Repo.Repository); err != nil { + if err = comment.LoadReactions(ctx, ctx.Repo.Repository); err != nil { log.Info("comment.LoadReactions: %s", err) break } @@ -3459,9 +3462,9 @@ func updateAttachments(ctx *context.Context, item any, files []string) error { if len(files) > 0 { switch content := item.(type) { case *issues_model.Issue: - err = issues_model.UpdateIssueAttachments(content.ID, files) + err = issues_model.UpdateIssueAttachments(ctx, content.ID, files) case *issues_model.Comment: - err = content.UpdateAttachments(files) + err = content.UpdateAttachments(ctx, files) default: return fmt.Errorf("unknown Type: %T", content) } @@ -3574,7 +3577,7 @@ func handleTeamMentions(ctx *context.Context) { if ctx.Doer.IsAdmin { isAdmin = true } else { - isAdmin, err = org.IsOwnedBy(ctx.Doer.ID) + isAdmin, err = org.IsOwnedBy(ctx, ctx.Doer.ID) if err != nil { ctx.ServerError("IsOwnedBy", err) return @@ -3582,13 +3585,13 @@ func handleTeamMentions(ctx *context.Context) { } if isAdmin { - teams, err = org.LoadTeams() + teams, err = org.LoadTeams(ctx) if err != nil { ctx.ServerError("LoadTeams", err) return } } else { - teams, err = org.GetUserTeams(ctx.Doer.ID) + teams, err = org.GetUserTeams(ctx, ctx.Doer.ID) if err != nil { ctx.ServerError("GetUserTeams", err) return diff --git a/routers/web/repo/issue_label.go b/routers/web/repo/issue_label.go index 2d129490f5128..dd3e2803b4e43 100644 --- a/routers/web/repo/issue_label.go +++ b/routers/web/repo/issue_label.go @@ -85,7 +85,7 @@ func RetrieveLabels(ctx *context.Context) { return } if ctx.Doer != nil { - ctx.Org.IsOwner, err = org.IsOwnedBy(ctx.Doer.ID) + ctx.Org.IsOwner, err = org.IsOwnedBy(ctx, ctx.Doer.ID) if err != nil { ctx.ServerError("org.IsOwnedBy", err) return diff --git a/routers/web/repo/issue_timetrack.go b/routers/web/repo/issue_timetrack.go index 04ca65dd9a1e3..82d8d8faea953 100644 --- a/routers/web/repo/issue_timetrack.go +++ b/routers/web/repo/issue_timetrack.go @@ -61,7 +61,7 @@ func DeleteTime(c *context.Context) { return } - t, err := issues_model.GetTrackedTimeByID(c.ParamsInt64(":timeid")) + t, err := issues_model.GetTrackedTimeByID(c, c.ParamsInt64(":timeid")) if err != nil { if db.IsErrNotExist(err) { c.NotFound("time not found", err) @@ -77,7 +77,7 @@ func DeleteTime(c *context.Context) { return } - if err = issues_model.DeleteTime(t); err != nil { + if err = issues_model.DeleteTime(c, t); err != nil { c.ServerError("DeleteTime", err) return } diff --git a/routers/web/repo/projects.go b/routers/web/repo/projects.go index eef57f46272f8..33bc79d96d8a9 100644 --- a/routers/web/repo/projects.go +++ b/routers/web/repo/projects.go @@ -142,7 +142,7 @@ func NewProjectPost(ctx *context.Context) { return } - if err := project_model.NewProject(&project_model.Project{ + if err := project_model.NewProject(ctx, &project_model.Project{ RepoID: ctx.Repo.Repository.ID, Title: form.Title, Description: form.Content, @@ -172,7 +172,7 @@ func ChangeProjectStatus(ctx *context.Context) { } id := ctx.ParamsInt64(":id") - if err := project_model.ChangeProjectStatusByRepoIDAndID(ctx.Repo.Repository.ID, id, toClose); err != nil { + if err := project_model.ChangeProjectStatusByRepoIDAndID(ctx, ctx.Repo.Repository.ID, id, toClose); err != nil { if project_model.IsErrProjectNotExist(err) { ctx.NotFound("", err) } else { @@ -279,7 +279,7 @@ func EditProjectPost(ctx *context.Context) { ctx.Flash.Success(ctx.Tr("repo.projects.edit_success", p.Title)) if ctx.FormString("redirect") == "project" { - ctx.Redirect(p.Link()) + ctx.Redirect(p.Link(ctx)) } else { ctx.Redirect(ctx.Repo.RepoLink + "/projects") } @@ -445,7 +445,7 @@ func DeleteProjectBoard(ctx *context.Context) { return } - if err := project_model.DeleteBoardByID(ctx.ParamsInt64(":boardID")); err != nil { + if err := project_model.DeleteBoardByID(ctx, ctx.ParamsInt64(":boardID")); err != nil { ctx.ServerError("DeleteProjectBoardByID", err) return } @@ -473,7 +473,7 @@ func AddBoardToProjectPost(ctx *context.Context) { return } - if err := project_model.NewBoard(&project_model.Board{ + if err := project_model.NewBoard(ctx, &project_model.Board{ ProjectID: project.ID, Title: form.Title, Color: form.Color, @@ -565,7 +565,7 @@ func SetDefaultProjectBoard(ctx *context.Context) { return } - if err := project_model.SetDefaultBoard(project.ID, board.ID); err != nil { + if err := project_model.SetDefaultBoard(ctx, project.ID, board.ID); err != nil { ctx.ServerError("SetDefaultBoard", err) return } @@ -580,7 +580,7 @@ func UnSetDefaultProjectBoard(ctx *context.Context) { return } - if err := project_model.SetDefaultBoard(project.ID, 0); err != nil { + if err := project_model.SetDefaultBoard(ctx, project.ID, 0); err != nil { ctx.ServerError("SetDefaultBoard", err) return } @@ -682,7 +682,7 @@ func MoveIssues(ctx *context.Context) { } } - if err = project_model.MoveIssuesOnProjectBoard(board, sortedIssueIDs); err != nil { + if err = project_model.MoveIssuesOnProjectBoard(ctx, board, sortedIssueIDs); err != nil { ctx.ServerError("MoveIssuesOnProjectBoard", err) return } diff --git a/routers/web/repo/pull.go b/routers/web/repo/pull.go index 63dfd0f7b50be..639c0c74d037c 100644 --- a/routers/web/repo/pull.go +++ b/routers/web/repo/pull.go @@ -180,6 +180,21 @@ func getForkRepository(ctx *context.Context) *repo_model.Repository { return nil } + branches, err := git_model.FindBranchNames(ctx, git_model.FindBranchOptions{ + RepoID: ctx.Repo.Repository.ID, + ListOptions: db.ListOptions{ + ListAll: true, + }, + IsDeletedBranch: util.OptionalBoolFalse, + // Add it as the first option + ExcludeBranchNames: []string{ctx.Repo.Repository.DefaultBranch}, + }) + if err != nil { + ctx.ServerError("FindBranchNames", err) + return nil + } + ctx.Data["Branches"] = append([]string{ctx.Repo.Repository.DefaultBranch}, branches...) + return forkRepo } @@ -250,7 +265,7 @@ func ForkPost(ctx *context.Context) { // Check if user is allowed to create repo's on the organization. if ctxUser.IsOrganization() { - isAllowedToFork, err := organization.OrgFromUser(ctxUser).CanCreateOrgRepo(ctx.Doer.ID) + isAllowedToFork, err := organization.OrgFromUser(ctxUser).CanCreateOrgRepo(ctx, ctx.Doer.ID) if err != nil { ctx.ServerError("CanCreateOrgRepo", err) return @@ -261,9 +276,10 @@ func ForkPost(ctx *context.Context) { } repo, err := repo_service.ForkRepository(ctx, ctx.Doer, ctxUser, repo_service.ForkRepoOptions{ - BaseRepo: forkRepo, - Name: form.RepoName, - Description: form.Description, + BaseRepo: forkRepo, + Name: form.RepoName, + Description: form.Description, + SingleBranch: form.ForkSingleBranch, }) if err != nil { ctx.Data["Err_RepoName"] = true @@ -892,7 +908,7 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi // as the viewed information is designed to be loaded only on latest PR // diff and if you're signed in. if !ctx.IsSigned || willShowSpecifiedCommit || willShowSpecifiedCommitRange { - diff, err = gitdiff.GetDiff(gitRepo, diffOptions, files...) + diff, err = gitdiff.GetDiff(ctx, gitRepo, diffOptions, files...) methodWithError = "GetDiff" } else { diff, err = gitdiff.SyncAndGetUserSpecificDiff(ctx, ctx.Doer.ID, pull, gitRepo, diffOptions, files...) @@ -943,7 +959,7 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi } if ctx.IsSigned && ctx.Doer != nil { - if ctx.Data["CanMarkConversation"], err = issues_model.CanMarkConversation(issue, ctx.Doer); err != nil { + if ctx.Data["CanMarkConversation"], err = issues_model.CanMarkConversation(ctx, issue, ctx.Doer); err != nil { ctx.ServerError("CanMarkConversation", err) return } @@ -970,7 +986,7 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi } numPendingCodeComments := int64(0) if currentReview != nil { - numPendingCodeComments, err = issues_model.CountComments(&issues_model.FindCommentsOptions{ + numPendingCodeComments, err = issues_model.CountComments(ctx, &issues_model.FindCommentsOptions{ Type: issues_model.CommentTypeCode, ReviewID: currentReview.ID, IssueID: issue.ID, diff --git a/routers/web/repo/pull_review.go b/routers/web/repo/pull_review.go index 3e433dcf4d7a9..1359af9d3bfa0 100644 --- a/routers/web/repo/pull_review.go +++ b/routers/web/repo/pull_review.go @@ -101,7 +101,7 @@ func CreateCodeComment(ctx *context.Context) { renderConversation(ctx, comment) return } - ctx.Redirect(comment.Link()) + ctx.Redirect(comment.Link(ctx)) } // UpdateResolveConversation add or remove an Conversation resolved mark @@ -127,7 +127,7 @@ func UpdateResolveConversation(ctx *context.Context) { } var permResult bool - if permResult, err = issues_model.CanMarkConversation(comment.Issue, ctx.Doer); err != nil { + if permResult, err = issues_model.CanMarkConversation(ctx, comment.Issue, ctx.Doer); err != nil { ctx.ServerError("CanMarkConversation", err) return } @@ -142,7 +142,7 @@ func UpdateResolveConversation(ctx *context.Context) { } if action == "Resolve" || action == "UnResolve" { - err = issues_model.MarkConversation(comment, ctx.Doer, action == "Resolve") + err = issues_model.MarkConversation(ctx, comment, ctx.Doer, action == "Resolve") if err != nil { ctx.ServerError("MarkConversation", err) return diff --git a/routers/web/repo/release.go b/routers/web/repo/release.go index 91ade32cccdd2..61f1973125835 100644 --- a/routers/web/repo/release.go +++ b/routers/web/repo/release.go @@ -71,18 +71,6 @@ func calReleaseNumCommitsBehind(repoCtx *context.Repository, release *repo_model func Releases(ctx *context.Context) { ctx.Data["PageIsReleaseList"] = true ctx.Data["Title"] = ctx.Tr("repo.release.releases") - releasesOrTags(ctx, false) -} - -// TagsList render tags list page -func TagsList(ctx *context.Context) { - ctx.Data["PageIsTagList"] = true - ctx.Data["Title"] = ctx.Tr("repo.release.tags") - releasesOrTags(ctx, true) -} - -func releasesOrTags(ctx *context.Context, isTagList bool) { - ctx.Data["DefaultBranch"] = ctx.Repo.Repository.DefaultBranch ctx.Data["IsViewBranch"] = false ctx.Data["IsViewTag"] = true // Disable the showCreateNewBranch form in the dropdown on this page. @@ -100,35 +88,13 @@ func releasesOrTags(ctx *context.Context, isTagList bool) { listOptions.PageSize = setting.API.MaxResponseItems } - // TODO(20073) tags are used for compare feature which needs all tags - // filtering is done on the client-side atm - tagListStart, tagListEnd := 0, 0 - if isTagList { - tagListStart, tagListEnd = listOptions.GetStartEnd() - } - - tags, err := ctx.Repo.GitRepo.GetTags(tagListStart, tagListEnd) - if err != nil { - ctx.ServerError("GetTags", err) - return - } - ctx.Data["Tags"] = tags - writeAccess := ctx.Repo.CanWrite(unit.TypeReleases) ctx.Data["CanCreateRelease"] = writeAccess && !ctx.Repo.Repository.IsArchived opts := repo_model.FindReleasesOptions{ ListOptions: listOptions, - } - if isTagList { - // for the tags list page, show all releases with real tags (having real commit-id), - // the drafts should also be included because a real tag might be used as a draft. - opts.IncludeDrafts = true - opts.IncludeTags = true - opts.HasSha1 = util.OptionalBoolTrue - } else { // only show draft releases for users who can write, read-only users shouldn't see draft releases. - opts.IncludeDrafts = writeAccess + IncludeDrafts: writeAccess, } releases, err := repo_model.GetReleasesByRepoID(ctx, ctx.Repo.Repository.ID, opts) @@ -137,12 +103,6 @@ func releasesOrTags(ctx *context.Context, isTagList bool) { return } - count, err := repo_model.GetReleaseCountByRepoID(ctx, ctx.Repo.Repository.ID, opts) - if err != nil { - ctx.ServerError("GetReleaseCountByRepoID", err) - return - } - for _, release := range releases { release.Repo = ctx.Repo.Repository } @@ -197,16 +157,59 @@ func releasesOrTags(ctx *context.Context, isTagList bool) { ctx.Data["Releases"] = releases - pager := context.NewPagination(int(count), opts.PageSize, opts.Page, 5) + numReleases := ctx.Data["NumReleases"].(int64) + pager := context.NewPagination(int(numReleases), opts.PageSize, opts.Page, 5) pager.SetDefaultParams(ctx) ctx.Data["Page"] = pager - if isTagList { - ctx.Data["PageIsViewCode"] = !ctx.Repo.Repository.UnitEnabled(ctx, unit.TypeReleases) - ctx.HTML(http.StatusOK, tplTagsList) - } else { - ctx.HTML(http.StatusOK, tplReleasesList) + ctx.HTML(http.StatusOK, tplReleasesList) +} + +// TagsList render tags list page +func TagsList(ctx *context.Context) { + ctx.Data["PageIsTagList"] = true + ctx.Data["Title"] = ctx.Tr("repo.release.tags") + ctx.Data["IsViewBranch"] = false + ctx.Data["IsViewTag"] = true + // Disable the showCreateNewBranch form in the dropdown on this page. + ctx.Data["CanCreateBranch"] = false + ctx.Data["HideBranchesInDropdown"] = true + + listOptions := db.ListOptions{ + Page: ctx.FormInt("page"), + PageSize: ctx.FormInt("limit"), + } + if listOptions.PageSize == 0 { + listOptions.PageSize = setting.Repository.Release.DefaultPagingNum + } + if listOptions.PageSize > setting.API.MaxResponseItems { + listOptions.PageSize = setting.API.MaxResponseItems + } + + opts := repo_model.FindReleasesOptions{ + ListOptions: listOptions, + // for the tags list page, show all releases with real tags (having real commit-id), + // the drafts should also be included because a real tag might be used as a draft. + IncludeDrafts: true, + IncludeTags: true, + HasSha1: util.OptionalBoolTrue, + } + + releases, err := repo_model.GetReleasesByRepoID(ctx, ctx.Repo.Repository.ID, opts) + if err != nil { + ctx.ServerError("GetReleasesByRepoID", err) + return } + + ctx.Data["Releases"] = releases + + numTags := ctx.Data["NumTags"].(int64) + pager := context.NewPagination(int(numTags), opts.PageSize, opts.Page, 5) + pager.SetDefaultParams(ctx) + ctx.Data["Page"] = pager + + ctx.Data["PageIsViewCode"] = !ctx.Repo.Repository.UnitEnabled(ctx, unit.TypeReleases) + ctx.HTML(http.StatusOK, tplTagsList) } // ReleasesFeedRSS get feeds for releases in RSS format diff --git a/routers/web/repo/release_test.go b/routers/web/repo/release_test.go index 54118fb6b3e4b..a5a923d464ab9 100644 --- a/routers/web/repo/release_test.go +++ b/routers/web/repo/release_test.go @@ -7,6 +7,7 @@ import ( "testing" repo_model "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/models/unit" "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/contexttest" "code.gitea.io/gitea/modules/web" @@ -65,7 +66,7 @@ func TestNewReleasePost(t *testing.T) { } } -func TestNewReleasesList(t *testing.T) { +func TestCalReleaseNumCommitsBehind(t *testing.T) { unittest.PrepareTestEnv(t) ctx, _ := contexttest.MockContext(t, "user2/repo-release/releases") contexttest.LoadUser(t, ctx, 2) @@ -73,8 +74,17 @@ func TestNewReleasesList(t *testing.T) { contexttest.LoadGitRepo(t, ctx) t.Cleanup(func() { ctx.Repo.GitRepo.Close() }) - Releases(ctx) - releases := ctx.Data["Releases"].([]*repo_model.Release) + releases, err := repo_model.GetReleasesByRepoID(ctx, ctx.Repo.Repository.ID, repo_model.FindReleasesOptions{ + IncludeDrafts: ctx.Repo.CanWrite(unit.TypeReleases), + }) + assert.NoError(t, err) + + countCache := make(map[string]int64) + for _, release := range releases { + err := calReleaseNumCommitsBehind(ctx.Repo, release, countCache) + assert.NoError(t, err) + } + type computedFields struct { NumCommitsBehind int64 TargetBehind string diff --git a/routers/web/repo/repo.go b/routers/web/repo/repo.go index 88cbd701d218e..b3b6b48871a08 100644 --- a/routers/web/repo/repo.go +++ b/routers/web/repo/repo.go @@ -119,7 +119,7 @@ func checkContextUser(ctx *context.Context, uid int64) *user_model.User { return nil } if !ctx.Doer.IsAdmin { - canCreate, err := organization.OrgFromUser(org).CanCreateOrgRepo(ctx.Doer.ID) + canCreate, err := organization.OrgFromUser(org).CanCreateOrgRepo(ctx, ctx.Doer.ID) if err != nil { ctx.ServerError("CanCreateOrgRepo", err) return nil diff --git a/routers/web/repo/setting/protected_branch.go b/routers/web/repo/setting/protected_branch.go index 3138f2327b28d..73adfec95a0ee 100644 --- a/routers/web/repo/setting/protected_branch.go +++ b/routers/web/repo/setting/protected_branch.go @@ -70,7 +70,7 @@ func SettingsProtectedBranch(c *context.Context) { c.Data["PageIsSettingsBranches"] = true c.Data["Title"] = c.Tr("repo.settings.protected_branch") + " - " + rule.RuleName - users, err := access_model.GetRepoReaders(c.Repo.Repository) + users, err := access_model.GetRepoReaders(c, c.Repo.Repository) if err != nil { c.ServerError("Repo.Repository.GetReaders", err) return @@ -84,7 +84,7 @@ func SettingsProtectedBranch(c *context.Context) { c.Data["recent_status_checks"] = contexts if c.Repo.Owner.IsOrganization() { - teams, err := organization.OrgFromUser(c.Repo.Owner).TeamsWithAccessToRepo(c.Repo.Repository.ID, perm.AccessModeRead) + teams, err := organization.OrgFromUser(c.Repo.Owner).TeamsWithAccessToRepo(c, c.Repo.Repository.ID, perm.AccessModeRead) if err != nil { c.ServerError("Repo.Owner.TeamsWithAccessToRepo", err) return diff --git a/routers/web/repo/setting/protected_tag.go b/routers/web/repo/setting/protected_tag.go index aafbd19e80ed2..46addb3f0ac02 100644 --- a/routers/web/repo/setting/protected_tag.go +++ b/routers/web/repo/setting/protected_tag.go @@ -147,7 +147,7 @@ func setTagsContext(ctx *context.Context) error { } ctx.Data["ProtectedTags"] = protectedTags - users, err := access_model.GetRepoReaders(ctx.Repo.Repository) + users, err := access_model.GetRepoReaders(ctx, ctx.Repo.Repository) if err != nil { ctx.ServerError("Repo.Repository.GetReaders", err) return err @@ -155,7 +155,7 @@ func setTagsContext(ctx *context.Context) error { ctx.Data["Users"] = users if ctx.Repo.Owner.IsOrganization() { - teams, err := organization.OrgFromUser(ctx.Repo.Owner).TeamsWithAccessToRepo(ctx.Repo.Repository.ID, perm.AccessModeRead) + teams, err := organization.OrgFromUser(ctx.Repo.Owner).TeamsWithAccessToRepo(ctx, ctx.Repo.Repository.ID, perm.AccessModeRead) if err != nil { ctx.ServerError("Repo.Owner.TeamsWithAccessToRepo", err) return err diff --git a/routers/web/repo/setting/runners.go b/routers/web/repo/setting/runners.go index 2c192e9790a69..8d4112c157b41 100644 --- a/routers/web/repo/setting/runners.go +++ b/routers/web/repo/setting/runners.go @@ -14,6 +14,7 @@ import ( "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/setting" actions_shared "code.gitea.io/gitea/routers/web/shared/actions" + shared_user "code.gitea.io/gitea/routers/web/shared/user" ) const ( @@ -53,6 +54,11 @@ func getRunnersCtx(ctx *context.Context) (*runnersCtx, error) { } if ctx.Data["PageIsOrgSettings"] == true { + err := shared_user.LoadHeaderCount(ctx) + if err != nil { + ctx.ServerError("LoadHeaderCount", err) + return nil, nil + } return &runnersCtx{ RepoID: 0, OwnerID: ctx.Org.Organization.ID, diff --git a/routers/web/repo/setting/secrets.go b/routers/web/repo/setting/secrets.go index 3d7a0576027e9..cf427b2c44bd7 100644 --- a/routers/web/repo/setting/secrets.go +++ b/routers/web/repo/setting/secrets.go @@ -11,6 +11,7 @@ import ( "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/setting" shared "code.gitea.io/gitea/routers/web/shared/secrets" + shared_user "code.gitea.io/gitea/routers/web/shared/user" ) const ( @@ -42,6 +43,11 @@ func getSecretsCtx(ctx *context.Context) (*secretsCtx, error) { } if ctx.Data["PageIsOrgSettings"] == true { + err := shared_user.LoadHeaderCount(ctx) + if err != nil { + ctx.ServerError("LoadHeaderCount", err) + return nil, nil + } return &secretsCtx{ OwnerID: ctx.ContextUser.ID, RepoID: 0, diff --git a/routers/web/repo/setting/setting.go b/routers/web/repo/setting/setting.go index 68943586ef588..0864b1c911ae5 100644 --- a/routers/web/repo/setting/setting.go +++ b/routers/web/repo/setting/setting.go @@ -285,7 +285,7 @@ func SettingsPost(ctx *context.Context) { mirror_service.AddPullMirrorToQueue(repo.ID) - ctx.Flash.Info(ctx.Tr("repo.settings.mirror_sync_in_progress")) + ctx.Flash.Info(ctx.Tr("repo.settings.pull_mirror_sync_in_progress", repo.OriginalURL)) ctx.Redirect(repo.Link() + "/settings") case "push-mirror-sync": @@ -302,7 +302,7 @@ func SettingsPost(ctx *context.Context) { mirror_service.AddPushMirrorToQueue(m.ID) - ctx.Flash.Info(ctx.Tr("repo.settings.mirror_sync_in_progress")) + ctx.Flash.Info(ctx.Tr("repo.settings.push_mirror_sync_in_progress", m.RemoteAddress)) ctx.Redirect(repo.Link() + "/settings") case "push-mirror-update": @@ -594,7 +594,7 @@ func SettingsPost(ctx *context.Context) { return } - if err := repo_model.UpdateRepositoryUnits(repo, units, deleteUnitTypes); err != nil { + if err := repo_model.UpdateRepositoryUnits(ctx, repo, units, deleteUnitTypes); err != nil { ctx.ServerError("UpdateRepositoryUnits", err) return } @@ -695,7 +695,7 @@ func SettingsPost(ctx *context.Context) { if _, err := repo_module.CleanUpMigrateInfo(ctx, repo); err != nil { ctx.ServerError("CleanUpMigrateInfo", err) return - } else if err = repo_model.DeleteMirrorByRepoID(ctx.Repo.Repository.ID); err != nil { + } else if err = repo_model.DeleteMirrorByRepoID(ctx, ctx.Repo.Repository.ID); err != nil { ctx.ServerError("DeleteMirrorByRepoID", err) return } @@ -761,7 +761,7 @@ func SettingsPost(ctx *context.Context) { } if newOwner.Type == user_model.UserTypeOrganization { - if !ctx.Doer.IsAdmin && newOwner.Visibility == structs.VisibleTypePrivate && !organization.OrgFromUser(newOwner).HasMemberWithUserID(ctx.Doer.ID) { + if !ctx.Doer.IsAdmin && newOwner.Visibility == structs.VisibleTypePrivate && !organization.OrgFromUser(newOwner).HasMemberWithUserID(ctx, ctx.Doer.ID) { // The user shouldn't know about this organization ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_owner_name"), tplSettingsOptions, nil) return diff --git a/routers/web/repo/setting/variables.go b/routers/web/repo/setting/variables.go index 1005d1d9c6106..a697a5d8d857f 100644 --- a/routers/web/repo/setting/variables.go +++ b/routers/web/repo/setting/variables.go @@ -11,6 +11,7 @@ import ( "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/setting" shared "code.gitea.io/gitea/routers/web/shared/actions" + shared_user "code.gitea.io/gitea/routers/web/shared/user" ) const ( @@ -40,6 +41,11 @@ func getVariablesCtx(ctx *context.Context) (*variablesCtx, error) { } if ctx.Data["PageIsOrgSettings"] == true { + err := shared_user.LoadHeaderCount(ctx) + if err != nil { + ctx.ServerError("LoadHeaderCount", err) + return nil, nil + } return &variablesCtx{ OwnerID: ctx.ContextUser.ID, IsOrg: true, diff --git a/routers/web/repo/view.go b/routers/web/repo/view.go index 91c00b049e9f7..657179062736c 100644 --- a/routers/web/repo/view.go +++ b/routers/web/repo/view.go @@ -488,8 +488,13 @@ func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink st } else { buf, _ := io.ReadAll(rd) - // empty: 0 lines; "a": one line; "a\n": two lines; "a\nb": two lines; - // the NumLines is only used for the display on the UI: "xxx lines" + // The Open Group Base Specification: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html + // empty: 0 lines; "a": 1 line, 1 incomplete-line; "a\n": 1 line; "a\nb": 1 line, 1 incomplete-line; + // Gitea uses the definition (like most modern editors): + // empty: 0 lines; "a": 1 line; "a\n": 2 lines; "a\nb": 2 lines; + // When rendering, the last empty line is not rendered in UI, while the line-number is still counted, to tell users that the file contains a trailing EOL. + // To make the UI more consistent, it could use an icon mark to indicate that there is no trailing EOL, and show line-number as the rendered lines. + // This NumLines is only used for the display on the UI: "xxx lines" if len(buf) == 0 { ctx.Data["NumLines"] = 0 } else { @@ -692,7 +697,7 @@ func checkCitationFile(ctx *context.Context, entry *git.TreeEntry) { } tree, err := ctx.Repo.Commit.SubTree(ctx.Repo.TreePath) if err != nil { - ctx.NotFoundOrServerError("Repo.Commit.SubTree", git.IsErrNotExist, err) + HandleGitError(ctx, "Repo.Commit.SubTree", err) return } allEntries, err := tree.ListEntries() @@ -783,7 +788,7 @@ func LastCommit(ctx *context.Context) { func renderDirectoryFiles(ctx *context.Context, timeout time.Duration) git.Entries { tree, err := ctx.Repo.Commit.SubTree(ctx.Repo.TreePath) if err != nil { - ctx.NotFoundOrServerError("Repo.Commit.SubTree", git.IsErrNotExist, err) + HandleGitError(ctx, "Repo.Commit.SubTree", err) return nil } @@ -792,12 +797,12 @@ func renderDirectoryFiles(ctx *context.Context, timeout time.Duration) git.Entri // Get current entry user currently looking at. entry, err := ctx.Repo.Commit.GetTreeEntryByPath(ctx.Repo.TreePath) if err != nil { - ctx.NotFoundOrServerError("Repo.Commit.GetTreeEntryByPath", git.IsErrNotExist, err) + HandleGitError(ctx, "Repo.Commit.GetTreeEntryByPath", err) return nil } if !entry.IsDir() { - ctx.NotFoundOrServerError("Repo.Commit.GetTreeEntryByPath", git.IsErrNotExist, err) + HandleGitError(ctx, "Repo.Commit.GetTreeEntryByPath", err) return nil } @@ -843,7 +848,7 @@ func renderDirectoryFiles(ctx *context.Context, timeout time.Duration) git.Entri verification := asymkey_model.ParseCommitWithSignature(ctx, latestCommit) if err := asymkey_model.CalculateTrustStatus(verification, ctx.Repo.Repository.GetTrustModel(), func(user *user_model.User) (bool, error) { - return repo_model.IsOwnerMemberCollaborator(ctx.Repo.Repository, user.ID) + return repo_model.IsOwnerMemberCollaborator(ctx, ctx.Repo.Repository, user.ID) }, nil); err != nil { ctx.ServerError("CalculateTrustStatus", err) return nil @@ -963,7 +968,7 @@ func renderCode(ctx *context.Context) { // Get current entry user currently looking at. entry, err := ctx.Repo.Commit.GetTreeEntryByPath(ctx.Repo.TreePath) if err != nil { - ctx.NotFoundOrServerError("Repo.Commit.GetTreeEntryByPath", git.IsErrNotExist, err) + HandleGitError(ctx, "Repo.Commit.GetTreeEntryByPath", err) return } diff --git a/routers/web/shared/user/header.go b/routers/web/shared/user/header.go index 16d9321e80a14..355f2ddeffedb 100644 --- a/routers/web/shared/user/header.go +++ b/routers/web/shared/user/header.go @@ -32,6 +32,7 @@ func PrepareContextForProfileBigAvatar(ctx *context.Context) { ctx.Data["IsFollowing"] = ctx.Doer != nil && user_model.IsFollowing(ctx, ctx.Doer.ID, ctx.ContextUser.ID) ctx.Data["ShowUserEmail"] = setting.UI.ShowUserEmail && ctx.ContextUser.Email != "" && ctx.IsSigned && !ctx.ContextUser.KeepEmailPrivate + ctx.Data["UserLocationMapURL"] = setting.Service.UserLocationMapURL // Show OpenID URIs openIDs, err := user_model.GetUserOpenIDs(ctx, ctx.ContextUser.ID) @@ -56,7 +57,7 @@ func PrepareContextForProfileBigAvatar(ctx *context.Context) { } showPrivate := ctx.IsSigned && (ctx.Doer.IsAdmin || ctx.Doer.ID == ctx.ContextUser.ID) - orgs, err := organization.FindOrgs(organization.FindOrgOptions{ + orgs, err := organization.FindOrgs(ctx, organization.FindOrgOptions{ UserID: ctx.ContextUser.ID, IncludePrivate: showPrivate, }) @@ -65,7 +66,7 @@ func PrepareContextForProfileBigAvatar(ctx *context.Context) { return } ctx.Data["Orgs"] = orgs - ctx.Data["HasOrgsVisible"] = organization.HasOrgsVisible(orgs, ctx.Doer) + ctx.Data["HasOrgsVisible"] = organization.HasOrgsVisible(ctx, orgs, ctx.Doer) badges, _, err := user_model.GetUserBadges(ctx, ctx.ContextUser) if err != nil { diff --git a/routers/web/user/profile.go b/routers/web/user/profile.go index f52ceb1a642ad..48a4b94c190b6 100644 --- a/routers/web/user/profile.go +++ b/routers/web/user/profile.go @@ -52,7 +52,6 @@ func userProfile(ctx *context.Context) { ctx.Data["Title"] = ctx.ContextUser.DisplayName() ctx.Data["PageIsUserProfile"] = true - ctx.Data["UserLocationMapURL"] = setting.Service.UserLocationMapURL // prepare heatmap data if setting.Service.EnableUserHeatmap { diff --git a/routers/web/user/setting/profile.go b/routers/web/user/setting/profile.go index 2aa6619a4995d..72e60bda587ef 100644 --- a/routers/web/user/setting/profile.go +++ b/routers/web/user/setting/profile.go @@ -17,7 +17,6 @@ import ( "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/organization" repo_model "code.gitea.io/gitea/models/repo" - system_model "code.gitea.io/gitea/models/system" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/base" "code.gitea.io/gitea/modules/context" @@ -44,9 +43,7 @@ func Profile(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("settings.profile") ctx.Data["PageIsSettingsProfile"] = true ctx.Data["AllowedUserVisibilityModes"] = setting.Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice() - ctx.Data["DisableGravatar"] = system_model.GetSettingWithCacheBool(ctx, system_model.KeyPictureDisableGravatar, - setting.GetDefaultDisableGravatar(), - ) + ctx.Data["DisableGravatar"] = setting.Config().Picture.DisableGravatar.Value(ctx) ctx.HTML(http.StatusOK, tplSettingsProfile) } @@ -88,9 +85,7 @@ func ProfilePost(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("settings") ctx.Data["PageIsSettingsProfile"] = true ctx.Data["AllowedUserVisibilityModes"] = setting.Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice() - ctx.Data["DisableGravatar"] = system_model.GetSettingWithCacheBool(ctx, system_model.KeyPictureDisableGravatar, - setting.GetDefaultDisableGravatar(), - ) + ctx.Data["DisableGravatar"] = setting.Config().Picture.DisableGravatar.Value(ctx) if ctx.HasError() { ctx.HTML(http.StatusOK, tplSettingsProfile) @@ -219,12 +214,12 @@ func Organization(ctx *context.Context) { opts.Page = 1 } - orgs, err := organization.FindOrgs(opts) + orgs, err := organization.FindOrgs(ctx, opts) if err != nil { ctx.ServerError("FindOrgs", err) return } - total, err := organization.CountOrgs(opts) + total, err := organization.CountOrgs(ctx, opts) if err != nil { ctx.ServerError("CountOrgs", err) return diff --git a/routers/web/web.go b/routers/web/web.go index 99862505b48a1..215483872670d 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -978,9 +978,6 @@ func registerRoutes(m *web.Route) { }, reqUnitAccess(unit.TypeCode, perm.AccessModeRead, false)) }, ignSignIn, context_service.UserAssignmentWeb(), context.OrgAssignment()) // for "/{username}/-" (packages, projects, code) - // ***** Release Attachment Download without Signin - m.Get("/{username}/{reponame}/releases/download/{vTag}/{fileName}", ignSignIn, context.RepoAssignment, repo.MustBeNotEmpty, repo.RedirectDownload) - m.Group("/{username}/{reponame}", func() { m.Group("/settings", func() { m.Group("", func() { @@ -1240,8 +1237,9 @@ func registerRoutes(m *web.Route) { m.Get(".rss", feedEnabled, repo.ReleasesFeedRSS) m.Get(".atom", feedEnabled, repo.ReleasesFeedAtom) }, ctxDataSet("EnableFeed", setting.Other.EnableFeed), - repo.MustBeNotEmpty, reqRepoReleaseReader, context.RepoRefByType(context.RepoRefTag, true)) - m.Get("/releases/attachments/{uuid}", repo.MustBeNotEmpty, reqRepoReleaseReader, repo.GetAttachment) + repo.MustBeNotEmpty, context.RepoRefByType(context.RepoRefTag, true)) + m.Get("/releases/attachments/{uuid}", repo.MustBeNotEmpty, repo.GetAttachment) + m.Get("/releases/download/{vTag}/{fileName}", repo.MustBeNotEmpty, repo.RedirectDownload) m.Group("/releases", func() { m.Get("/new", repo.NewRelease) m.Post("/new", web.Bind(forms.NewReleaseForm{}), repo.NewReleasePost) diff --git a/services/actions/clear_tasks.go b/services/actions/clear_tasks.go index d2893e4f23e02..7c7043c42f4b8 100644 --- a/services/actions/clear_tasks.go +++ b/services/actions/clear_tasks.go @@ -12,20 +12,15 @@ import ( "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/modules/actions" "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" ) -const ( - zombieTaskTimeout = 10 * time.Minute - endlessTaskTimeout = 3 * time.Hour - abandonedJobTimeout = 24 * time.Hour -) - // StopZombieTasks stops the task which have running status, but haven't been updated for a long time func StopZombieTasks(ctx context.Context) error { return stopTasks(ctx, actions_model.FindTaskOptions{ Status: actions_model.StatusRunning, - UpdatedBefore: timeutil.TimeStamp(time.Now().Add(-zombieTaskTimeout).Unix()), + UpdatedBefore: timeutil.TimeStamp(time.Now().Add(-setting.Actions.ZombieTaskTimeout).Unix()), }) } @@ -33,7 +28,7 @@ func StopZombieTasks(ctx context.Context) error { func StopEndlessTasks(ctx context.Context) error { return stopTasks(ctx, actions_model.FindTaskOptions{ Status: actions_model.StatusRunning, - StartedBefore: timeutil.TimeStamp(time.Now().Add(-endlessTaskTimeout).Unix()), + StartedBefore: timeutil.TimeStamp(time.Now().Add(-setting.Actions.EndlessTaskTimeout).Unix()), }) } @@ -81,7 +76,7 @@ func stopTasks(ctx context.Context, opts actions_model.FindTaskOptions) error { func CancelAbandonedJobs(ctx context.Context) error { jobs, _, err := actions_model.FindRunJobs(ctx, actions_model.FindRunJobOptions{ Statuses: []actions_model.Status{actions_model.StatusWaiting, actions_model.StatusBlocked}, - UpdatedBefore: timeutil.TimeStamp(time.Now().Add(-abandonedJobTimeout).Unix()), + UpdatedBefore: timeutil.TimeStamp(time.Now().Add(-setting.Actions.AbandonedJobTimeout).Unix()), }) if err != nil { log.Warn("find abandoned tasks: %v", err) diff --git a/services/attachment/attachment.go b/services/attachment/attachment.go index 3e7df0cee0c0e..967332fd982f1 100644 --- a/services/attachment/attachment.go +++ b/services/attachment/attachment.go @@ -19,12 +19,12 @@ import ( ) // NewAttachment creates a new attachment object, but do not verify. -func NewAttachment(attach *repo_model.Attachment, file io.Reader, size int64) (*repo_model.Attachment, error) { +func NewAttachment(ctx context.Context, attach *repo_model.Attachment, file io.Reader, size int64) (*repo_model.Attachment, error) { if attach.RepoID == 0 { return nil, fmt.Errorf("attachment %s should belong to a repository", attach.Name) } - err := db.WithTx(db.DefaultContext, func(ctx context.Context) error { + err := db.WithTx(ctx, func(ctx context.Context) error { attach.UUID = uuid.New().String() size, err := storage.Attachments.Save(attach.RelativePath(), file, size) if err != nil { @@ -39,7 +39,7 @@ func NewAttachment(attach *repo_model.Attachment, file io.Reader, size int64) (* } // UploadAttachment upload new attachment into storage and update database -func UploadAttachment(file io.Reader, allowedTypes string, fileSize int64, opts *repo_model.Attachment) (*repo_model.Attachment, error) { +func UploadAttachment(ctx context.Context, file io.Reader, allowedTypes string, fileSize int64, opts *repo_model.Attachment) (*repo_model.Attachment, error) { buf := make([]byte, 1024) n, _ := util.ReadAtMost(file, buf) buf = buf[:n] @@ -48,5 +48,5 @@ func UploadAttachment(file io.Reader, allowedTypes string, fileSize int64, opts return nil, err } - return NewAttachment(opts, io.MultiReader(bytes.NewReader(buf), file), fileSize) + return NewAttachment(ctx, opts, io.MultiReader(bytes.NewReader(buf), file), fileSize) } diff --git a/services/attachment/attachment_test.go b/services/attachment/attachment_test.go index 77ef1cd37ce81..142bcfe62926d 100644 --- a/services/attachment/attachment_test.go +++ b/services/attachment/attachment_test.go @@ -32,7 +32,7 @@ func TestUploadAttachment(t *testing.T) { assert.NoError(t, err) defer f.Close() - attach, err := NewAttachment(&repo_model.Attachment{ + attach, err := NewAttachment(db.DefaultContext, &repo_model.Attachment{ RepoID: 1, UploaderID: user.ID, Name: filepath.Base(fPath), diff --git a/services/auth/oauth2.go b/services/auth/oauth2.go index 6572d661e87f9..38b705cc5b8f7 100644 --- a/services/auth/oauth2.go +++ b/services/auth/oauth2.go @@ -125,7 +125,9 @@ func (o *OAuth2) userIDFromToken(ctx context.Context, tokenSHA string, store Dat // If verification is successful returns an existing user object. // Returns nil if verification fails. func (o *OAuth2) Verify(req *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) (*user_model.User, error) { - if !middleware.IsAPIPath(req) && !isAttachmentDownload(req) && !isAuthenticatedTokenRequest(req) { + // These paths are not API paths, but we still want to check for tokens because they maybe in the API returned URLs + if !middleware.IsAPIPath(req) && !isAttachmentDownload(req) && !isAuthenticatedTokenRequest(req) && + !gitRawReleasePathRe.MatchString(req.URL.Path) { return nil, nil } diff --git a/services/auth/source/ldap/source_authenticate.go b/services/auth/source/ldap/source_authenticate.go index c4808510845fc..9f4d7ed68f5e6 100644 --- a/services/auth/source/ldap/source_authenticate.go +++ b/services/auth/source/ldap/source_authenticate.go @@ -29,7 +29,13 @@ func (source *Source) Authenticate(ctx context.Context, user *user_model.User, u // User not in LDAP, do nothing return nil, user_model.ErrUserNotExist{Name: loginName} } - + // Fallback. + if len(sr.Username) == 0 { + sr.Username = userName + } + if len(sr.Mail) == 0 { + sr.Mail = fmt.Sprintf("%s@localhost.local", sr.Username) + } isAttributeSSHPublicKeySet := len(strings.TrimSpace(source.AttributeSSHPublicKey)) > 0 // Update User admin flag if exist @@ -70,15 +76,6 @@ func (source *Source) Authenticate(ctx context.Context, user *user_model.User, u } } } else { - // Fallback. - if len(sr.Username) == 0 { - sr.Username = userName - } - - if len(sr.Mail) == 0 { - sr.Mail = fmt.Sprintf("%s@localhost.local", sr.Username) - } - user = &user_model.User{ LowerName: strings.ToLower(sr.Username), Name: sr.Username, diff --git a/services/convert/convert.go b/services/convert/convert.go index fcb5dd572f770..366782390a758 100644 --- a/services/convert/convert.go +++ b/services/convert/convert.go @@ -119,15 +119,15 @@ func ToBranchProtection(ctx context.Context, bp *git_model.ProtectedBranch) *api if err != nil { log.Error("GetUserNamesByIDs (ApprovalsWhitelistUserIDs): %v", err) } - pushWhitelistTeams, err := organization.GetTeamNamesByID(bp.WhitelistTeamIDs) + pushWhitelistTeams, err := organization.GetTeamNamesByID(ctx, bp.WhitelistTeamIDs) if err != nil { log.Error("GetTeamNamesByID (WhitelistTeamIDs): %v", err) } - mergeWhitelistTeams, err := organization.GetTeamNamesByID(bp.MergeWhitelistTeamIDs) + mergeWhitelistTeams, err := organization.GetTeamNamesByID(ctx, bp.MergeWhitelistTeamIDs) if err != nil { log.Error("GetTeamNamesByID (MergeWhitelistTeamIDs): %v", err) } - approvalsWhitelistTeams, err := organization.GetTeamNamesByID(bp.ApprovalsWhitelistTeamIDs) + approvalsWhitelistTeams, err := organization.GetTeamNamesByID(ctx, bp.ApprovalsWhitelistTeamIDs) if err != nil { log.Error("GetTeamNamesByID (ApprovalsWhitelistTeamIDs): %v", err) } diff --git a/services/convert/git_commit.go b/services/convert/git_commit.go index ac15719c1cfcc..ed08691c8b1b4 100644 --- a/services/convert/git_commit.go +++ b/services/convert/git_commit.go @@ -210,7 +210,7 @@ func ToCommit(ctx context.Context, repo *repo_model.Repository, gitRepo *git.Rep // Get diff stats for commit if opts.Stat { - diff, err := gitdiff.GetDiff(gitRepo, &gitdiff.DiffOptions{ + diff, err := gitdiff.GetDiff(ctx, gitRepo, &gitdiff.DiffOptions{ AfterCommitID: commit.ID.String(), }) if err != nil { diff --git a/services/convert/issue.go b/services/convert/issue.go index 33fad31d48ae1..708eac36cff79 100644 --- a/services/convert/issue.go +++ b/services/convert/issue.go @@ -62,7 +62,7 @@ func toIssue(ctx context.Context, issue *issues_model.Issue, getDownloadURL func if err := issue.Repo.LoadOwner(ctx); err != nil { return &api.Issue{} } - apiIssue.URL = issue.APIURL() + apiIssue.URL = issue.APIURL(ctx) apiIssue.HTMLURL = issue.HTMLURL() apiIssue.Labels = ToLabelList(issue.Labels, issue.Repo, issue.Repo.Owner) apiIssue.Repo = &api.RepositoryMeta{ diff --git a/services/convert/issue_comment.go b/services/convert/issue_comment.go index 1308051e7c10b..b034a50897190 100644 --- a/services/convert/issue_comment.go +++ b/services/convert/issue_comment.go @@ -19,9 +19,9 @@ func ToAPIComment(ctx context.Context, repo *repo_model.Repository, c *issues_mo return &api.Comment{ ID: c.ID, Poster: ToUser(ctx, c.Poster, nil), - HTMLURL: c.HTMLURL(), - IssueURL: c.IssueURL(), - PRURL: c.PRURL(), + HTMLURL: c.HTMLURL(ctx), + IssueURL: c.IssueURL(ctx), + PRURL: c.PRURL(ctx), Body: c.Content, Attachments: ToAPIAttachments(repo, c.Attachments), Created: c.CreatedUnix.AsTime(), @@ -37,31 +37,31 @@ func ToTimelineComment(ctx context.Context, repo *repo_model.Repository, c *issu return nil } - err = c.LoadAssigneeUserAndTeam() + err = c.LoadAssigneeUserAndTeam(ctx) if err != nil { log.Error("LoadAssigneeUserAndTeam: %v", err) return nil } - err = c.LoadResolveDoer() + err = c.LoadResolveDoer(ctx) if err != nil { log.Error("LoadResolveDoer: %v", err) return nil } - err = c.LoadDepIssueDetails() + err = c.LoadDepIssueDetails(ctx) if err != nil { log.Error("LoadDepIssueDetails: %v", err) return nil } - err = c.LoadTime() + err = c.LoadTime(ctx) if err != nil { log.Error("LoadTime: %v", err) return nil } - err = c.LoadLabel() + err = c.LoadLabel(ctx) if err != nil { log.Error("LoadLabel: %v", err) return nil @@ -82,9 +82,9 @@ func ToTimelineComment(ctx context.Context, repo *repo_model.Repository, c *issu ID: c.ID, Type: c.Type.String(), Poster: ToUser(ctx, c.Poster, nil), - HTMLURL: c.HTMLURL(), - IssueURL: c.IssueURL(), - PRURL: c.PRURL(), + HTMLURL: c.HTMLURL(ctx), + IssueURL: c.IssueURL(ctx), + PRURL: c.PRURL(ctx), Body: c.Content, Created: c.CreatedUnix.AsTime(), Updated: c.UpdatedUnix.AsTime(), diff --git a/services/convert/mirror.go b/services/convert/mirror.go index dade6142a2e0a..249ce2f9689c1 100644 --- a/services/convert/mirror.go +++ b/services/convert/mirror.go @@ -4,13 +4,15 @@ package convert import ( + "context" + repo_model "code.gitea.io/gitea/models/repo" api "code.gitea.io/gitea/modules/structs" ) // ToPushMirror convert from repo_model.PushMirror and remoteAddress to api.TopicResponse -func ToPushMirror(pm *repo_model.PushMirror) (*api.PushMirror, error) { - repo := pm.GetRepository() +func ToPushMirror(ctx context.Context, pm *repo_model.PushMirror) (*api.PushMirror, error) { + repo := pm.GetRepository(ctx) return &api.PushMirror{ RepoName: repo.Name, RemoteName: pm.RemoteName, diff --git a/services/convert/notification.go b/services/convert/notification.go index 3906fa9b388a2..0b97530d8b583 100644 --- a/services/convert/notification.go +++ b/services/convert/notification.go @@ -4,17 +4,17 @@ package convert import ( + "context" "net/url" activities_model "code.gitea.io/gitea/models/activities" - "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/perm" access_model "code.gitea.io/gitea/models/perm/access" api "code.gitea.io/gitea/modules/structs" ) // ToNotificationThread convert a Notification to api.NotificationThread -func ToNotificationThread(n *activities_model.Notification) *api.NotificationThread { +func ToNotificationThread(ctx context.Context, n *activities_model.Notification) *api.NotificationThread { result := &api.NotificationThread{ ID: n.ID, Unread: !(n.Status == activities_model.NotificationStatusRead || n.Status == activities_model.NotificationStatusPinned), @@ -25,7 +25,7 @@ func ToNotificationThread(n *activities_model.Notification) *api.NotificationThr // since user only get notifications when he has access to use minimal access mode if n.Repository != nil { - result.Repository = ToRepo(db.DefaultContext, n.Repository, access_model.Permission{AccessMode: perm.AccessModeRead}) + result.Repository = ToRepo(ctx, n.Repository, access_model.Permission{AccessMode: perm.AccessModeRead}) // This permission is not correct and we should not be reporting it for repository := result.Repository; repository != nil; repository = repository.Parent { @@ -39,29 +39,29 @@ func ToNotificationThread(n *activities_model.Notification) *api.NotificationThr result.Subject = &api.NotificationSubject{Type: api.NotifySubjectIssue} if n.Issue != nil { result.Subject.Title = n.Issue.Title - result.Subject.URL = n.Issue.APIURL() + result.Subject.URL = n.Issue.APIURL(ctx) result.Subject.HTMLURL = n.Issue.HTMLURL() result.Subject.State = n.Issue.State() - comment, err := n.Issue.GetLastComment() + comment, err := n.Issue.GetLastComment(ctx) if err == nil && comment != nil { - result.Subject.LatestCommentURL = comment.APIURL() - result.Subject.LatestCommentHTMLURL = comment.HTMLURL() + result.Subject.LatestCommentURL = comment.APIURL(ctx) + result.Subject.LatestCommentHTMLURL = comment.HTMLURL(ctx) } } case activities_model.NotificationSourcePullRequest: result.Subject = &api.NotificationSubject{Type: api.NotifySubjectPull} if n.Issue != nil { result.Subject.Title = n.Issue.Title - result.Subject.URL = n.Issue.APIURL() + result.Subject.URL = n.Issue.APIURL(ctx) result.Subject.HTMLURL = n.Issue.HTMLURL() result.Subject.State = n.Issue.State() - comment, err := n.Issue.GetLastComment() + comment, err := n.Issue.GetLastComment(ctx) if err == nil && comment != nil { - result.Subject.LatestCommentURL = comment.APIURL() - result.Subject.LatestCommentHTMLURL = comment.HTMLURL() + result.Subject.LatestCommentURL = comment.APIURL(ctx) + result.Subject.LatestCommentHTMLURL = comment.HTMLURL(ctx) } - pr, _ := n.Issue.GetPullRequest() + pr, _ := n.Issue.GetPullRequest(ctx) if pr != nil && pr.HasMerged { result.Subject.State = "merged" } @@ -88,10 +88,10 @@ func ToNotificationThread(n *activities_model.Notification) *api.NotificationThr } // ToNotifications convert list of Notification to api.NotificationThread list -func ToNotifications(nl activities_model.NotificationList) []*api.NotificationThread { +func ToNotifications(ctx context.Context, nl activities_model.NotificationList) []*api.NotificationThread { result := make([]*api.NotificationThread, 0, len(nl)) for _, n := range nl { - result = append(result, ToNotificationThread(n)) + result = append(result, ToNotificationThread(ctx, n)) } return result } diff --git a/services/convert/pull_review.go b/services/convert/pull_review.go index 5d5d5d883c997..0332606285d18 100644 --- a/services/convert/pull_review.go +++ b/services/convert/pull_review.go @@ -36,10 +36,10 @@ func ToPullReview(ctx context.Context, r *issues_model.Review, doer *user_model. Stale: r.Stale, Official: r.Official, Dismissed: r.Dismissed, - CodeCommentsCount: r.GetCodeCommentsCount(), + CodeCommentsCount: r.GetCodeCommentsCount(ctx), Submitted: r.CreatedUnix.AsTime(), Updated: r.UpdatedUnix.AsTime(), - HTMLURL: r.HTMLURL(), + HTMLURL: r.HTMLURL(ctx), HTMLPullURL: r.Issue.HTMLURL(), } @@ -102,7 +102,7 @@ func ToPullReviewCommentList(ctx context.Context, review *issues_model.Review, d CommitID: comment.CommitSHA, OrigCommitID: comment.OldRef, DiffHunk: patch2diff(comment.Patch), - HTMLURL: comment.HTMLURL(), + HTMLURL: comment.HTMLURL(ctx), HTMLPullURL: review.Issue.HTMLURL(), } diff --git a/services/cron/tasks_extended.go b/services/cron/tasks_extended.go index 5b483b000eb42..b9fd1dfcfff13 100644 --- a/services/cron/tasks_extended.go +++ b/services/cron/tasks_extended.go @@ -135,7 +135,7 @@ func registerDeleteOldActions() { OlderThan: 365 * 24 * time.Hour, }, func(ctx context.Context, _ *user_model.User, config Config) error { olderThanConfig := config.(*OlderThanConfig) - return activities_model.DeleteOldActions(olderThanConfig.OlderThan) + return activities_model.DeleteOldActions(ctx, olderThanConfig.OlderThan) }) } diff --git a/services/externalaccount/user.go b/services/externalaccount/user.go index 51a0f9a4ef216..a80ba6fee7c5a 100644 --- a/services/externalaccount/user.go +++ b/services/externalaccount/user.go @@ -82,11 +82,11 @@ func UpdateExternalUser(user *user_model.User, gothUser goth.User) error { // UpdateMigrationsByType updates all migrated repositories' posterid from gitServiceType to replace originalAuthorID to posterID func UpdateMigrationsByType(ctx context.Context, tp structs.GitServiceType, externalUserID string, userID int64) error { - if err := issues_model.UpdateIssuesMigrationsByType(tp, externalUserID, userID); err != nil { + if err := issues_model.UpdateIssuesMigrationsByType(ctx, tp, externalUserID, userID); err != nil { return err } - if err := issues_model.UpdateCommentsMigrationsByType(tp, externalUserID, userID); err != nil { + if err := issues_model.UpdateCommentsMigrationsByType(ctx, tp, externalUserID, userID); err != nil { return err } @@ -94,8 +94,8 @@ func UpdateMigrationsByType(ctx context.Context, tp structs.GitServiceType, exte return err } - if err := issues_model.UpdateReactionsMigrationsByType(tp, externalUserID, userID); err != nil { + if err := issues_model.UpdateReactionsMigrationsByType(ctx, tp, externalUserID, userID); err != nil { return err } - return issues_model.UpdateReviewsMigrationsByType(tp, externalUserID, userID) + return issues_model.UpdateReviewsMigrationsByType(ctx, tp, externalUserID, userID) } diff --git a/services/feed/action.go b/services/feed/action.go index 6bf1158cc9f82..83daaa1438fd5 100644 --- a/services/feed/action.go +++ b/services/feed/action.go @@ -265,7 +265,7 @@ func (a *actionNotifier) PullRequestReview(ctx context.Context, pr *issues_model actions = append(actions, action) } - if err := activities_model.NotifyWatchersActions(actions); err != nil { + if err := activities_model.NotifyWatchersActions(ctx, actions); err != nil { log.Error("notify watchers '%d/%d': %v", review.Reviewer.ID, review.Issue.RepoID, err) } } diff --git a/services/forms/repo_form.go b/services/forms/repo_form.go index b36c8cc9b6613..5df7ec8fd609a 100644 --- a/services/forms/repo_form.go +++ b/services/forms/repo_form.go @@ -51,6 +51,8 @@ type CreateRepoForm struct { Labels bool ProtectedBranch bool TrustModel string + + ForkSingleBranch string } // Validate validates the fields diff --git a/services/gitdiff/csv_test.go b/services/gitdiff/csv_test.go index ac53e2d1efaec..c006a7c2bd8d0 100644 --- a/services/gitdiff/csv_test.go +++ b/services/gitdiff/csv_test.go @@ -8,6 +8,7 @@ import ( "strings" "testing" + "code.gitea.io/gitea/models/db" csv_module "code.gitea.io/gitea/modules/csv" "code.gitea.io/gitea/modules/setting" @@ -190,7 +191,7 @@ c,d,e`, } for n, c := range cases { - diff, err := ParsePatch(setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(c.diff), "") + diff, err := ParsePatch(db.DefaultContext, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(c.diff), "") if err != nil { t.Errorf("ParsePatch failed: %s", err) } diff --git a/services/gitdiff/gitdiff.go b/services/gitdiff/gitdiff.go index fd0f32717c4b6..8bf6cba844d6b 100644 --- a/services/gitdiff/gitdiff.go +++ b/services/gitdiff/gitdiff.go @@ -494,7 +494,7 @@ func (diff *Diff) LoadComments(ctx context.Context, issue *issues_model.Issue, c const cmdDiffHead = "diff --git " // ParsePatch builds a Diff object from a io.Reader and some parameters. -func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader, skipToFile string) (*Diff, error) { +func ParsePatch(ctx context.Context, maxLines, maxLineCharacters, maxFiles int, reader io.Reader, skipToFile string) (*Diff, error) { log.Debug("ParsePatch(%d, %d, %d, ..., %s)", maxLines, maxLineCharacters, maxFiles, skipToFile) var curFile *DiffFile @@ -709,7 +709,7 @@ parsingLoop: curFile.IsAmbiguous = false } // Otherwise do nothing with this line, but now switch to parsing hunks - lineBytes, isFragment, err := parseHunks(curFile, maxLines, maxLineCharacters, input) + lineBytes, isFragment, err := parseHunks(ctx, curFile, maxLines, maxLineCharacters, input) diff.TotalAddition += curFile.Addition diff.TotalDeletion += curFile.Deletion if err != nil { @@ -818,7 +818,7 @@ func skipToNextDiffHead(input *bufio.Reader) (line string, err error) { return line, err } -func parseHunks(curFile *DiffFile, maxLines, maxLineCharacters int, input *bufio.Reader) (lineBytes []byte, isFragment bool, err error) { +func parseHunks(ctx context.Context, curFile *DiffFile, maxLines, maxLineCharacters int, input *bufio.Reader) (lineBytes []byte, isFragment bool, err error) { sb := strings.Builder{} var ( @@ -995,7 +995,7 @@ func parseHunks(curFile *DiffFile, maxLines, maxLineCharacters int, input *bufio oid := strings.TrimPrefix(line[1:], lfs.MetaFileOidPrefix) if len(oid) == 64 { m := &git_model.LFSMetaObject{Pointer: lfs.Pointer{Oid: oid}} - count, err := db.CountByBean(db.DefaultContext, m) + count, err := db.CountByBean(ctx, m) if err == nil && count > 0 { curFile.IsBin = true @@ -1106,7 +1106,7 @@ type DiffOptions struct { // GetDiff builds a Diff between two commits of a repository. // Passing the empty string as beforeCommitID returns a diff from the parent commit. // The whitespaceBehavior is either an empty string or a git flag -func GetDiff(gitRepo *git.Repository, opts *DiffOptions, files ...string) (*Diff, error) { +func GetDiff(ctx context.Context, gitRepo *git.Repository, opts *DiffOptions, files ...string) (*Diff, error) { repoPath := gitRepo.Path commit, err := gitRepo.GetCommit(opts.AfterCommitID) @@ -1165,7 +1165,7 @@ func GetDiff(gitRepo *git.Repository, opts *DiffOptions, files ...string) (*Diff _ = writer.Close() }() - diff, err := ParsePatch(opts.MaxLines, opts.MaxLineCharacters, opts.MaxFiles, reader, parsePatchSkipToFile) + diff, err := ParsePatch(ctx, opts.MaxLines, opts.MaxLineCharacters, opts.MaxFiles, reader, parsePatchSkipToFile) if err != nil { return nil, fmt.Errorf("unable to ParsePatch: %w", err) } @@ -1280,7 +1280,7 @@ func GetPullDiffStats(gitRepo *git.Repository, opts *DiffOptions) (*PullDiffStat // SyncAndGetUserSpecificDiff is like GetDiff, except that user specific data such as which files the given user has already viewed on the given PR will also be set // Additionally, the database asynchronously is updated if files have changed since the last review func SyncAndGetUserSpecificDiff(ctx context.Context, userID int64, pull *issues_model.PullRequest, gitRepo *git.Repository, opts *DiffOptions, files ...string) (*Diff, error) { - diff, err := GetDiff(gitRepo, opts, files...) + diff, err := GetDiff(ctx, gitRepo, opts, files...) if err != nil { return nil, err } @@ -1347,8 +1347,8 @@ outer: } // CommentAsDiff returns c.Patch as *Diff -func CommentAsDiff(c *issues_model.Comment) (*Diff, error) { - diff, err := ParsePatch(setting.Git.MaxGitDiffLines, +func CommentAsDiff(ctx context.Context, c *issues_model.Comment) (*Diff, error) { + diff, err := ParsePatch(ctx, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(c.Patch), "") if err != nil { log.Error("Unable to parse patch: %v", err) @@ -1365,7 +1365,7 @@ func CommentAsDiff(c *issues_model.Comment) (*Diff, error) { } // CommentMustAsDiff executes AsDiff and logs the error instead of returning -func CommentMustAsDiff(c *issues_model.Comment) *Diff { +func CommentMustAsDiff(ctx context.Context, c *issues_model.Comment) *Diff { if c == nil { return nil } @@ -1374,7 +1374,7 @@ func CommentMustAsDiff(c *issues_model.Comment) *Diff { log.Error("PANIC whilst retrieving diff for comment[%d] Error: %v\nStack: %s", c.ID, err, log.Stack(2)) } }() - diff, err := CommentAsDiff(c) + diff, err := CommentAsDiff(ctx, c) if err != nil { log.Warn("CommentMustAsDiff: %v", err) } diff --git a/services/gitdiff/gitdiff_test.go b/services/gitdiff/gitdiff_test.go index e270e46fd453f..adcac355a7bb4 100644 --- a/services/gitdiff/gitdiff_test.go +++ b/services/gitdiff/gitdiff_test.go @@ -175,7 +175,7 @@ diff --git "\\a/README.md" "\\b/README.md" } for _, testcase := range tests { t.Run(testcase.name, func(t *testing.T) { - got, err := ParsePatch(setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(testcase.gitdiff), testcase.skipTo) + got, err := ParsePatch(db.DefaultContext, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(testcase.gitdiff), testcase.skipTo) if (err != nil) != testcase.wantErr { t.Errorf("ParsePatch(%q) error = %v, wantErr %v", testcase.name, err, testcase.wantErr) return @@ -400,7 +400,7 @@ index 6961180..9ba1a00 100644 for _, testcase := range tests { t.Run(testcase.name, func(t *testing.T) { - got, err := ParsePatch(setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(testcase.gitdiff), "") + got, err := ParsePatch(db.DefaultContext, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(testcase.gitdiff), "") if (err != nil) != testcase.wantErr { t.Errorf("ParsePatch(%q) error = %v, wantErr %v", testcase.name, err, testcase.wantErr) return @@ -449,21 +449,21 @@ index 0000000..6bb8f39 diffBuilder.WriteString("+line" + strconv.Itoa(i) + "\n") } diff = diffBuilder.String() - result, err := ParsePatch(20, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff), "") + result, err := ParsePatch(db.DefaultContext, 20, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff), "") if err != nil { t.Errorf("There should not be an error: %v", err) } if !result.Files[0].IsIncomplete { t.Errorf("Files should be incomplete! %v", result.Files[0]) } - result, err = ParsePatch(40, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff), "") + result, err = ParsePatch(db.DefaultContext, 40, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff), "") if err != nil { t.Errorf("There should not be an error: %v", err) } if result.Files[0].IsIncomplete { t.Errorf("Files should not be incomplete! %v", result.Files[0]) } - result, err = ParsePatch(40, 5, setting.Git.MaxGitDiffFiles, strings.NewReader(diff), "") + result, err = ParsePatch(db.DefaultContext, 40, 5, setting.Git.MaxGitDiffFiles, strings.NewReader(diff), "") if err != nil { t.Errorf("There should not be an error: %v", err) } @@ -494,14 +494,14 @@ index 0000000..6bb8f39 diffBuilder.WriteString("+line" + strconv.Itoa(35) + "\n") diff = diffBuilder.String() - result, err = ParsePatch(20, 4096, setting.Git.MaxGitDiffFiles, strings.NewReader(diff), "") + result, err = ParsePatch(db.DefaultContext, 20, 4096, setting.Git.MaxGitDiffFiles, strings.NewReader(diff), "") if err != nil { t.Errorf("There should not be an error: %v", err) } if !result.Files[0].IsIncomplete { t.Errorf("Files should be incomplete! %v", result.Files[0]) } - result, err = ParsePatch(40, 4096, setting.Git.MaxGitDiffFiles, strings.NewReader(diff), "") + result, err = ParsePatch(db.DefaultContext, 40, 4096, setting.Git.MaxGitDiffFiles, strings.NewReader(diff), "") if err != nil { t.Errorf("There should not be an error: %v", err) } @@ -520,7 +520,7 @@ index 0000000..6bb8f39 Docker Pulls + cut off + cut off` - _, err = ParsePatch(setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff), "") + _, err = ParsePatch(db.DefaultContext, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff), "") if err != nil { t.Errorf("ParsePatch failed: %s", err) } @@ -536,7 +536,7 @@ index 0000000..6bb8f39 Docker Pulls + cut off + cut off` - _, err = ParsePatch(setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff2), "") + _, err = ParsePatch(db.DefaultContext, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff2), "") if err != nil { t.Errorf("ParsePatch failed: %s", err) } @@ -552,7 +552,7 @@ index 0000000..6bb8f39 Docker Pulls + cut off + cut off` - _, err = ParsePatch(setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff2a), "") + _, err = ParsePatch(db.DefaultContext, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff2a), "") if err != nil { t.Errorf("ParsePatch failed: %s", err) } @@ -568,7 +568,7 @@ index 0000000..6bb8f39 Docker Pulls + cut off + cut off` - _, err = ParsePatch(setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff3), "") + _, err = ParsePatch(db.DefaultContext, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(diff3), "") if err != nil { t.Errorf("ParsePatch failed: %s", err) } @@ -634,7 +634,7 @@ func TestGetDiffRangeWithWhitespaceBehavior(t *testing.T) { } defer gitRepo.Close() for _, behavior := range []git.TrustedCmdArgs{{"-w"}, {"--ignore-space-at-eol"}, {"-b"}, nil} { - diffs, err := GetDiff(gitRepo, + diffs, err := GetDiff(db.DefaultContext, gitRepo, &DiffOptions{ AfterCommitID: "bd7063cc7c04689c4d082183d32a604ed27a24f9", BeforeCommitID: "559c156f8e0178b71cb44355428f24001b08fc68", @@ -665,6 +665,6 @@ func TestNoCrashes(t *testing.T) { } for _, testcase := range tests { // It shouldn't crash, so don't care about the output. - ParsePatch(setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(testcase.gitdiff), "") + ParsePatch(db.DefaultContext, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, strings.NewReader(testcase.gitdiff), "") } } diff --git a/services/issue/assignee_test.go b/services/issue/assignee_test.go index f47ef45ba00f1..e16b012a1742d 100644 --- a/services/issue/assignee_test.go +++ b/services/issue/assignee_test.go @@ -18,7 +18,7 @@ func TestDeleteNotPassedAssignee(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) // Fake issue with assignees - issue, err := issues_model.GetIssueWithAttrsByID(1) + issue, err := issues_model.GetIssueWithAttrsByID(db.DefaultContext, 1) assert.NoError(t, err) assert.Len(t, issue.Assignees, 1) diff --git a/services/issue/comments.go b/services/issue/comments.go index 4a8574edd51d7..8d8c575c14039 100644 --- a/services/issue/comments.go +++ b/services/issue/comments.go @@ -84,7 +84,7 @@ func UpdateComment(ctx context.Context, c *issues_model.Comment, doer *user_mode } } - if err := issues_model.UpdateComment(c, doer); err != nil { + if err := issues_model.UpdateComment(ctx, c, doer); err != nil { return err } diff --git a/services/issue/content.go b/services/issue/content.go index 41f1bfefe8c4b..6e56714ddfacf 100644 --- a/services/issue/content.go +++ b/services/issue/content.go @@ -15,7 +15,7 @@ import ( func ChangeContent(ctx context.Context, issue *issues_model.Issue, doer *user_model.User, content string) (err error) { oldContent := issue.Content - if err := issues_model.ChangeIssueContent(issue, doer, content); err != nil { + if err := issues_model.ChangeIssueContent(ctx, issue, doer, content); err != nil { return err } diff --git a/services/issue/issue.go b/services/issue/issue.go index 828599be6bcb3..b1f418c32e565 100644 --- a/services/issue/issue.go +++ b/services/issue/issue.go @@ -22,7 +22,7 @@ import ( // NewIssue creates new issue with labels for repository. func NewIssue(ctx context.Context, repo *repo_model.Repository, issue *issues_model.Issue, labelIDs []int64, uuids []string, assigneeIDs []int64) error { - if err := issues_model.NewIssue(repo, issue, labelIDs, uuids); err != nil { + if err := issues_model.NewIssue(ctx, repo, issue, labelIDs, uuids); err != nil { return err } @@ -53,6 +53,10 @@ func ChangeTitle(ctx context.Context, issue *issues_model.Issue, doer *user_mode oldTitle := issue.Title issue.Title = title + if oldTitle == title { + return nil + } + if err := issues_model.ChangeIssueTitle(ctx, issue, doer, oldTitle); err != nil { return err } @@ -73,7 +77,7 @@ func ChangeIssueRef(ctx context.Context, issue *issues_model.Issue, doer *user_m oldRef := issue.Ref issue.Ref = ref - if err := issues_model.ChangeIssueRef(issue, doer, oldRef); err != nil { + if err := issues_model.ChangeIssueRef(ctx, issue, doer, oldRef); err != nil { return err } @@ -262,45 +266,27 @@ func deleteIssue(ctx context.Context, issue *issues_model.Issue) error { } // delete all database data still assigned to this issue - if err := issues_model.DeleteInIssue(ctx, issue.ID, - &issues_model.ContentHistory{}, - &issues_model.Comment{}, - &issues_model.IssueLabel{}, - &issues_model.IssueDependency{}, - &issues_model.IssueAssignees{}, - &issues_model.IssueUser{}, - &activities_model.Notification{}, - &issues_model.Reaction{}, - &issues_model.IssueWatch{}, - &issues_model.Stopwatch{}, - &issues_model.TrackedTime{}, - &project_model.ProjectIssue{}, - &repo_model.Attachment{}, - &issues_model.PullRequest{}, + if err := db.DeleteBeans(ctx, + &issues_model.ContentHistory{IssueID: issue.ID}, + &issues_model.Comment{IssueID: issue.ID}, + &issues_model.IssueLabel{IssueID: issue.ID}, + &issues_model.IssueDependency{IssueID: issue.ID}, + &issues_model.IssueAssignees{IssueID: issue.ID}, + &issues_model.IssueUser{IssueID: issue.ID}, + &activities_model.Notification{IssueID: issue.ID}, + &issues_model.Reaction{IssueID: issue.ID}, + &issues_model.IssueWatch{IssueID: issue.ID}, + &issues_model.Stopwatch{IssueID: issue.ID}, + &issues_model.TrackedTime{IssueID: issue.ID}, + &project_model.ProjectIssue{IssueID: issue.ID}, + &repo_model.Attachment{IssueID: issue.ID}, + &issues_model.PullRequest{IssueID: issue.ID}, + &issues_model.Comment{RefIssueID: issue.ID}, + &issues_model.IssueDependency{DependencyID: issue.ID}, + &issues_model.Comment{DependentIssueID: issue.ID}, ); err != nil { return err } - // References to this issue in other issues - if _, err := db.DeleteByBean(ctx, &issues_model.Comment{ - RefIssueID: issue.ID, - }); err != nil { - return err - } - - // Delete dependencies for issues in other repositories - if _, err := db.DeleteByBean(ctx, &issues_model.IssueDependency{ - DependencyID: issue.ID, - }); err != nil { - return err - } - - // delete from dependent issues - if _, err := db.DeleteByBean(ctx, &issues_model.Comment{ - DependentIssueID: issue.ID, - }); err != nil { - return err - } - return committer.Commit() } diff --git a/services/issue/template.go b/services/issue/template.go index 4f1e3d93a0a8c..b6ae07798783d 100644 --- a/services/issue/template.go +++ b/services/issue/template.go @@ -72,7 +72,7 @@ func GetTemplateConfig(gitRepo *git.Repository, path string, commit *git.Commit) return GetDefaultTemplateConfig(), err } - issueConfig := api.IssueConfig{} + issueConfig := GetDefaultTemplateConfig() if err := yaml.Unmarshal(configContent, &issueConfig); err != nil { return GetDefaultTemplateConfig(), err } diff --git a/services/mailer/incoming/incoming_handler.go b/services/mailer/incoming/incoming_handler.go index 78f9f89fc9eaa..9682c52456d12 100644 --- a/services/mailer/incoming/incoming_handler.go +++ b/services/mailer/incoming/incoming_handler.go @@ -87,7 +87,7 @@ func (h *ReplyHandler) Handle(ctx context.Context, content *MailContent, doer *u attachmentIDs := make([]string, 0, len(content.Attachments)) if setting.Attachment.Enabled { for _, attachment := range content.Attachments { - a, err := attachment_service.UploadAttachment(bytes.NewReader(attachment.Content), setting.Attachment.AllowedTypes, int64(len(attachment.Content)), &repo_model.Attachment{ + a, err := attachment_service.UploadAttachment(ctx, bytes.NewReader(attachment.Content), setting.Attachment.AllowedTypes, int64(len(attachment.Content)), &repo_model.Attachment{ Name: attachment.Name, UploaderID: doer.ID, RepoID: issue.Repo.ID, diff --git a/services/migrations/gitea_uploader.go b/services/migrations/gitea_uploader.go index 1d9ac2964e474..ebf22e0e4094f 100644 --- a/services/migrations/gitea_uploader.go +++ b/services/migrations/gitea_uploader.go @@ -430,7 +430,7 @@ func (g *GiteaLocalUploader) CreateIssues(issues ...*base.Issue) error { } if len(iss) > 0 { - if err := issues_model.InsertIssues(iss...); err != nil { + if err := issues_model.InsertIssues(g.ctx, iss...); err != nil { return err } @@ -510,7 +510,7 @@ func (g *GiteaLocalUploader) CreateComments(comments ...*base.Comment) error { if len(cms) == 0 { return nil } - return issues_model.InsertIssueComments(cms) + return issues_model.InsertIssueComments(g.ctx, cms) } // CreatePullRequests creates pull requests @@ -917,7 +917,7 @@ func (g *GiteaLocalUploader) CreateReviews(reviews ...*base.Review) error { } } - return issues_model.InsertReviews(cms) + return issues_model.InsertReviews(g.ctx, cms) } // Rollback when migrating failed, this will rollback all the changes. diff --git a/services/mirror/mirror.go b/services/mirror/mirror.go index 0fc871b214c9f..72e545581a131 100644 --- a/services/mirror/mirror.go +++ b/services/mirror/mirror.go @@ -46,7 +46,7 @@ func Update(ctx context.Context, pullLimit, pushLimit int) error { var referenceID int64 if m, ok := bean.(*repo_model.Mirror); ok { - if m.GetRepository() == nil { + if m.GetRepository(ctx) == nil { log.Error("Disconnected mirror found: %d", m.ID) return nil } @@ -54,7 +54,7 @@ func Update(ctx context.Context, pullLimit, pushLimit int) error { mirrorType = PullMirrorType referenceID = m.RepoID } else if m, ok := bean.(*repo_model.PushMirror); ok { - if m.GetRepository() == nil { + if m.GetRepository(ctx) == nil { log.Error("Disconnected push-mirror found: %d", m.ID) return nil } @@ -90,7 +90,7 @@ func Update(ctx context.Context, pullLimit, pushLimit int) error { pullMirrorsRequested := 0 if pullLimit != 0 { - if err := repo_model.MirrorsIterate(pullLimit, func(idx int, bean any) error { + if err := repo_model.MirrorsIterate(ctx, pullLimit, func(idx int, bean any) error { if err := handler(idx, bean); err != nil { return err } diff --git a/services/mirror/mirror_pull.go b/services/mirror/mirror_pull.go index 75b367c437809..be426d4312894 100644 --- a/services/mirror/mirror_pull.go +++ b/services/mirror/mirror_pull.go @@ -9,7 +9,6 @@ import ( "strings" "time" - "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" system_model "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/modules/cache" @@ -31,7 +30,7 @@ const gitShortEmptySha = "0000000" // UpdateAddress writes new address to Git repository and database func UpdateAddress(ctx context.Context, m *repo_model.Mirror, addr string) error { remoteName := m.GetRemoteName() - repoPath := m.GetRepository().RepoPath() + repoPath := m.GetRepository(ctx).RepoPath() // Remove old remote _, _, err := git.NewCommand(ctx, "remote", "rm").AddDynamicArguments(remoteName).RunStdString(&git.RunOpts{Dir: repoPath}) if err != nil && !strings.HasPrefix(err.Error(), "exit status 128 - fatal: No such remote ") { @@ -428,7 +427,7 @@ func SyncPullMirror(ctx context.Context, repoID int64) bool { log.Error("SyncMirrors [repo_id: %v]: unable to GetMirrorByRepoID: %v", repoID, err) return false } - _ = m.GetRepository() // force load repository of mirror + _ = m.GetRepository(ctx) // force load repository of mirror ctx, _, finished := process.GetManager().AddContext(ctx, fmt.Sprintf("Syncing Mirror %s/%s", m.Repo.OwnerName, m.Repo.Name)) defer finished() @@ -461,7 +460,7 @@ func SyncPullMirror(ctx context.Context, repoID int64) bool { } defer gitRepo.Close() - if ok := checkAndUpdateEmptyRepository(m, gitRepo, results); !ok { + if ok := checkAndUpdateEmptyRepository(ctx, m, gitRepo, results); !ok { return false } } @@ -550,7 +549,7 @@ func SyncPullMirror(ctx context.Context, repoID int64) bool { return true } -func checkAndUpdateEmptyRepository(m *repo_model.Mirror, gitRepo *git.Repository, results []*mirrorSyncResult) bool { +func checkAndUpdateEmptyRepository(ctx context.Context, m *repo_model.Mirror, gitRepo *git.Repository, results []*mirrorSyncResult) bool { if !m.Repo.IsEmpty { return true } @@ -592,7 +591,7 @@ func checkAndUpdateEmptyRepository(m *repo_model.Mirror, gitRepo *git.Repository if err := gitRepo.SetDefaultBranch(m.Repo.DefaultBranch); err != nil { if !git.IsErrUnsupportedVersion(err) { log.Error("Failed to update default branch of underlying git repository %-v. Error: %v", m.Repo, err) - desc := fmt.Sprintf("Failed to uupdate default branch of underlying git repository '%s': %v", m.Repo.RepoPath(), err) + desc := fmt.Sprintf("Failed to update default branch of underlying git repository '%s': %v", m.Repo.RepoPath(), err) if err = system_model.CreateRepositoryNotice(desc); err != nil { log.Error("CreateRepositoryNotice: %v", err) } @@ -601,9 +600,9 @@ func checkAndUpdateEmptyRepository(m *repo_model.Mirror, gitRepo *git.Repository } m.Repo.IsEmpty = false // Update the is empty and default_branch columns - if err := repo_model.UpdateRepositoryCols(db.DefaultContext, m.Repo, "default_branch", "is_empty"); err != nil { + if err := repo_model.UpdateRepositoryCols(ctx, m.Repo, "default_branch", "is_empty"); err != nil { log.Error("Failed to update default branch of repository %-v. Error: %v", m.Repo, err) - desc := fmt.Sprintf("Failed to uupdate default branch of repository '%s': %v", m.Repo.RepoPath(), err) + desc := fmt.Sprintf("Failed to update default branch of repository '%s': %v", m.Repo.RepoPath(), err) if err = system_model.CreateRepositoryNotice(desc); err != nil { log.Error("CreateRepositoryNotice: %v", err) } diff --git a/services/mirror/mirror_push.go b/services/mirror/mirror_push.go index 594d31df89be1..6eaca71495e4f 100644 --- a/services/mirror/mirror_push.go +++ b/services/mirror/mirror_push.go @@ -65,7 +65,7 @@ func AddPushMirrorRemote(ctx context.Context, m *repo_model.PushMirror, addr str // RemovePushMirrorRemote removes the push mirror remote. func RemovePushMirrorRemote(ctx context.Context, m *repo_model.PushMirror) error { cmd := git.NewCommand(ctx, "remote", "rm").AddDynamicArguments(m.RemoteName) - _ = m.GetRepository() + _ = m.GetRepository(ctx) if _, _, err := cmd.RunStdString(&git.RunOpts{Dir: m.Repo.RepoPath()}); err != nil { return err @@ -99,7 +99,7 @@ func SyncPushMirror(ctx context.Context, mirrorID int64) bool { return false } - _ = m.GetRepository() + _ = m.GetRepository(ctx) m.LastError = "" diff --git a/services/pull/pull.go b/services/pull/pull.go index 8e57aebe3d830..8ef7499ad5e79 100644 --- a/services/pull/pull.go +++ b/services/pull/pull.go @@ -152,14 +152,12 @@ func NewPullRequest(ctx context.Context, repo *repo_model.Repository, issue *iss if issue.Milestone != nil { notify_service.IssueChangeMilestone(ctx, issue.Poster, issue, 0) } - if len(assigneeIDs) > 0 { - for _, assigneeID := range assigneeIDs { - assignee, err := user_model.GetUserByID(ctx, assigneeID) - if err != nil { - return ErrDependenciesLeft - } - notify_service.IssueChangeAssignee(ctx, issue.Poster, issue, assignee, false, assigneeCommentMap[assigneeID]) + for _, assigneeID := range assigneeIDs { + assignee, err := user_model.GetUserByID(ctx, assigneeID) + if err != nil { + return ErrDependenciesLeft } + notify_service.IssueChangeAssignee(ctx, issue.Poster, issue, assignee, false, assigneeCommentMap[assigneeID]) } return nil @@ -336,7 +334,7 @@ func AddTestPullRequestTask(doer *user_model.User, repoID int64, branch string, } if changed { // Mark old reviews as stale if diff to mergebase has changed - if err := issues_model.MarkReviewsAsStale(pr.IssueID); err != nil { + if err := issues_model.MarkReviewsAsStale(ctx, pr.IssueID); err != nil { log.Error("MarkReviewsAsStale: %v", err) } @@ -351,7 +349,7 @@ func AddTestPullRequestTask(doer *user_model.User, repoID int64, branch string, } } } - if err := issues_model.MarkReviewsAsNotStale(pr.IssueID, newCommitID); err != nil { + if err := issues_model.MarkReviewsAsNotStale(ctx, pr.IssueID, newCommitID); err != nil { log.Error("MarkReviewsAsNotStale: %v", err) } divergence, err := GetDiverging(ctx, pr) diff --git a/services/pull/review.go b/services/pull/review.go index c82d1341b6d5a..3f5644b0cd4f9 100644 --- a/services/pull/review.go +++ b/services/pull/review.go @@ -84,7 +84,7 @@ func CreateCodeComment(ctx context.Context, doer *user_model.User, gitRepo *git. if !pendingReview && replyReviewID != 0 { // It's not part of a review; maybe a reply to a review comment or a single comment. // Check if there are reviews for that line already; if there are, this is a reply - if existsReview, err = issues_model.ReviewExists(issue, treePath, line); err != nil { + if existsReview, err = issues_model.ReviewExists(ctx, issue, treePath, line); err != nil { return nil, err } } @@ -264,7 +264,7 @@ func createCodeComment(ctx context.Context, doer *user_model.User, repo *repo_mo // SubmitReview creates a review out of the existing pending review or creates a new one if no pending review exist func SubmitReview(ctx context.Context, doer *user_model.User, gitRepo *git.Repository, issue *issues_model.Issue, reviewType issues_model.ReviewType, content, commitID string, attachmentUUIDs []string) (*issues_model.Review, *issues_model.Comment, error) { - pr, err := issue.GetPullRequest() + pr, err := issue.GetPullRequest(ctx) if err != nil { return nil, nil, err } @@ -288,7 +288,7 @@ func SubmitReview(ctx context.Context, doer *user_model.User, gitRepo *git.Repos } } - review, comm, err := issues_model.SubmitReview(doer, issue, reviewType, content, commitID, stale, attachmentUUIDs) + review, comm, err := issues_model.SubmitReview(ctx, doer, issue, reviewType, content, commitID, stale, attachmentUUIDs) if err != nil { return nil, nil, err } diff --git a/services/release/release_test.go b/services/release/release_test.go index 3f0c67b0e0196..4b57262981b55 100644 --- a/services/release/release_test.go +++ b/services/release/release_test.go @@ -107,7 +107,7 @@ func TestRelease_Create(t *testing.T) { testPlayload := "testtest" - attach, err := attachment.NewAttachment(&repo_model.Attachment{ + attach, err := attachment.NewAttachment(db.DefaultContext, &repo_model.Attachment{ RepoID: repo.ID, UploaderID: user.ID, Name: "test.txt", @@ -241,7 +241,7 @@ func TestRelease_Update(t *testing.T) { // Add new attachments samplePayload := "testtest" - attach, err := attachment.NewAttachment(&repo_model.Attachment{ + attach, err := attachment.NewAttachment(db.DefaultContext, &repo_model.Attachment{ RepoID: repo.ID, UploaderID: user.ID, Name: "test.txt", diff --git a/services/repository/create_test.go b/services/repository/create_test.go index 36065cafff8e0..a9827c6889409 100644 --- a/services/repository/create_test.go +++ b/services/repository/create_test.go @@ -44,7 +44,7 @@ func TestIncludesAllRepositoriesTeams(t *testing.T) { Type: user_model.UserTypeOrganization, Visibility: structs.VisibleTypePublic, } - assert.NoError(t, organization.CreateOrganization(org, user), "CreateOrganization") + assert.NoError(t, organization.CreateOrganization(db.DefaultContext, org, user), "CreateOrganization") // Check Owner team. ownerTeam, err := org.GetOwnerTeam(db.DefaultContext) diff --git a/services/repository/files/temp_repo.go b/services/repository/files/temp_repo.go index 7f6b8137ae195..50c76970fd4a2 100644 --- a/services/repository/files/temp_repo.go +++ b/services/repository/files/temp_repo.go @@ -343,7 +343,7 @@ func (t *TemporaryUploadRepository) DiffIndex() (*gitdiff.Diff, error) { Stderr: stderr, PipelineFunc: func(ctx context.Context, cancel context.CancelFunc) error { _ = stdoutWriter.Close() - diff, finalErr = gitdiff.ParsePatch(setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, stdoutReader, "") + diff, finalErr = gitdiff.ParsePatch(t.ctx, setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles, stdoutReader, "") if finalErr != nil { log.Error("ParsePatch: %v", finalErr) cancel() diff --git a/services/repository/fork.go b/services/repository/fork.go index 397e4cb909337..d5ab42badd8aa 100644 --- a/services/repository/fork.go +++ b/services/repository/fork.go @@ -44,9 +44,10 @@ func (err ErrForkAlreadyExist) Unwrap() error { // ForkRepoOptions contains the fork repository options type ForkRepoOptions struct { - BaseRepo *repo_model.Repository - Name string - Description string + BaseRepo *repo_model.Repository + Name string + Description string + SingleBranch string } // ForkRepository forks a repository @@ -70,6 +71,10 @@ func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts Fork } } + defaultBranch := opts.BaseRepo.DefaultBranch + if opts.SingleBranch != "" { + defaultBranch = opts.SingleBranch + } repo := &repo_model.Repository{ OwnerID: owner.ID, Owner: owner, @@ -77,7 +82,7 @@ func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts Fork Name: opts.Name, LowerName: strings.ToLower(opts.Name), Description: opts.Description, - DefaultBranch: opts.BaseRepo.DefaultBranch, + DefaultBranch: defaultBranch, IsPrivate: opts.BaseRepo.IsPrivate || opts.BaseRepo.Owner.Visibility == structs.VisibleTypePrivate, IsEmpty: opts.BaseRepo.IsEmpty, IsFork: true, @@ -134,9 +139,12 @@ func ForkRepository(ctx context.Context, doer, owner *user_model.User, opts Fork needsRollback = true + cloneCmd := git.NewCommand(txCtx, "clone", "--bare") + if opts.SingleBranch != "" { + cloneCmd.AddArguments("--single-branch", "--branch").AddDynamicArguments(opts.SingleBranch) + } repoPath := repo_model.RepoPath(owner.Name, repo.Name) - if stdout, _, err := git.NewCommand(txCtx, - "clone", "--bare").AddDynamicArguments(oldRepoPath, repoPath). + if stdout, _, err := cloneCmd.AddDynamicArguments(oldRepoPath, repoPath). SetDescription(fmt.Sprintf("ForkRepository(git clone): %s to %s", opts.BaseRepo.FullName(), repo.FullName())). RunStdBytes(&git.RunOpts{Timeout: 10 * time.Minute}); err != nil { log.Error("Fork Repository (git clone) Failed for %v (from %v):\nStdout: %s\nError: %v", repo, opts.BaseRepo, stdout, err) diff --git a/services/task/migrate.go b/services/task/migrate.go index 70e5abdee6ebd..b74e024ba6c3c 100644 --- a/services/task/migrate.go +++ b/services/task/migrate.go @@ -47,11 +47,11 @@ func runMigrateTask(ctx context.Context, t *admin_model.Task) (err error) { err = fmt.Errorf("PANIC whilst trying to do migrate task: %v", e) log.Critical("PANIC during runMigrateTask[%d] by DoerID[%d] to RepoID[%d] for OwnerID[%d]: %v\nStacktrace: %v", t.ID, t.DoerID, t.RepoID, t.OwnerID, e, log.Stack(2)) } - + // fixme: Because ctx is canceled here, so the db.DefaultContext is needed. if err == nil { - err = admin_model.FinishMigrateTask(ctx, t) + err = admin_model.FinishMigrateTask(db.DefaultContext, t) if err == nil { - notify_service.MigrateRepository(ctx, t.Doer, t.Owner, t.Repo) + notify_service.MigrateRepository(db.DefaultContext, t.Doer, t.Owner, t.Repo) return } @@ -63,8 +63,8 @@ func runMigrateTask(ctx context.Context, t *admin_model.Task) (err error) { t.EndTime = timeutil.TimeStampNow() t.Status = structs.TaskStatusFailed t.Message = err.Error() - - if err := t.UpdateCols(ctx, "status", "message", "end_time"); err != nil { + // fixme: Because ctx is canceled here, so the db.DefaultContext is needed. + if err := t.UpdateCols(db.DefaultContext, "status", "message", "end_time"); err != nil { log.Error("Task UpdateCols failed: %v", err) } diff --git a/services/uinotification/notify.go b/services/uinotification/notify.go index 9cf4fe73d78d2..9230d1ee6cee7 100644 --- a/services/uinotification/notify.go +++ b/services/uinotification/notify.go @@ -52,7 +52,7 @@ func NewNotifier() notify_service.Notifier { func handler(items ...issueNotificationOpts) []issueNotificationOpts { for _, opts := range items { - if err := activities_model.CreateOrUpdateIssueNotifications(opts.IssueID, opts.CommentID, opts.NotificationAuthorID, opts.ReceiverID); err != nil { + if err := activities_model.CreateOrUpdateIssueNotifications(db.DefaultContext, opts.IssueID, opts.CommentID, opts.NotificationAuthorID, opts.ReceiverID); err != nil { log.Error("Was unable to create issue notification: %v", err) } } diff --git a/services/user/user.go b/services/user/user.go index 26dab4e1dde83..53cc361107813 100644 --- a/services/user/user.go +++ b/services/user/user.go @@ -189,7 +189,7 @@ func DeleteUser(ctx context.Context, u *user_model.User, purge bool) error { // An alternative option here would be write a function which would delete all organizations but it seems // but such a function would likely get out of date for { - orgs, err := organization.FindOrgs(organization.FindOrgOptions{ + orgs, err := organization.FindOrgs(ctx, organization.FindOrgOptions{ ListOptions: db.ListOptions{ PageSize: repo_model.RepositoryListDefaultPageSize, Page: 1, diff --git a/services/wiki/wiki.go b/services/wiki/wiki.go index 250b539080221..18371efd0988c 100644 --- a/services/wiki/wiki.go +++ b/services/wiki/wiki.go @@ -350,7 +350,7 @@ func DeleteWikiPage(ctx context.Context, doer *user_model.User, repo *repo_model // DeleteWiki removes the actual and local copy of repository wiki. func DeleteWiki(ctx context.Context, repo *repo_model.Repository) error { - if err := repo_model.UpdateRepositoryUnits(repo, nil, []unit.Type{unit.TypeWiki}); err != nil { + if err := repo_model.UpdateRepositoryUnits(ctx, repo, nil, []unit.Type{unit.TypeWiki}); err != nil { return err } diff --git a/templates/admin/config.tmpl b/templates/admin/config.tmpl index 57722f9898877..7eb9d086e61cc 100644 --- a/templates/admin/config.tmpl +++ b/templates/admin/config.tmpl @@ -292,15 +292,15 @@
{{ctx.Locale.Tr "admin.config.disable_gravatar"}}
-
- +
+
{{ctx.Locale.Tr "admin.config.enable_federated_avatar"}}
-
- +
+
diff --git a/templates/admin/org/list.tmpl b/templates/admin/org/list.tmpl index 1c041ca347340..0d79456b47c7f 100644 --- a/templates/admin/org/list.tmpl +++ b/templates/admin/org/list.tmpl @@ -25,7 +25,7 @@ {{ctx.Locale.Tr "admin.users.created"}} {{SortArrow "recentupdate" "leastupdate" $.SortType false}} - {{ctx.Locale.Tr "admin.users.edit"}} + @@ -45,7 +45,7 @@ {{.NumMembers}} {{.NumRepos}} {{DateTime "short" .CreatedUnix}} - {{svg "octicon-pencil"}} + {{svg "octicon-pencil"}} {{end}} diff --git a/templates/admin/user/list.tmpl b/templates/admin/user/list.tmpl index fba67fac156cf..46fd376dae9da 100644 --- a/templates/admin/user/list.tmpl +++ b/templates/admin/user/list.tmpl @@ -77,6 +77,7 @@ {{ctx.Locale.Tr "admin.users.last_login"}} {{SortArrow "lastlogin" "reverselastlogin" $.SortType false}} + @@ -84,7 +85,7 @@ {{.ID}} - {{.Name}} + {{.Name}} {{if .IsAdmin}} {{ctx.Locale.Tr "admin.users.admin"}} {{else if eq 2 .Type}}{{/* Reserved user */}} @@ -105,6 +106,12 @@ {{else}} {{ctx.Locale.Tr "admin.users.never_login"}} {{end}} + + + {{end}} diff --git a/templates/base/head.tmpl b/templates/base/head.tmpl index c3645209cd604..876b42d512b18 100644 --- a/templates/base/head.tmpl +++ b/templates/base/head.tmpl @@ -1,5 +1,5 @@ - + {{if .Title}}{{.Title | RenderEmojiPlain}} - {{end}}{{if .Repository.Name}}{{.Repository.Name}} - {{end}}{{AppName}} diff --git a/templates/base/head_style.tmpl b/templates/base/head_style.tmpl index 7e8cba2aedde0..0793eaca20dc4 100644 --- a/templates/base/head_style.tmpl +++ b/templates/base/head_style.tmpl @@ -1,8 +1,2 @@ -{{if .IsSigned}} - {{if ne .SignedUser.Theme "gitea"}} - - {{end}} -{{else if ne DefaultTheme "gitea"}} - -{{end}} + diff --git a/templates/org/settings/layout_head.tmpl b/templates/org/settings/layout_head.tmpl index c245a3bf62460..31dad2c14124f 100644 --- a/templates/org/settings/layout_head.tmpl +++ b/templates/org/settings/layout_head.tmpl @@ -1,9 +1,9 @@ {{template "base/head" .ctxData}}
{{template "org/header" .ctxData}} -
+
{{template "org/settings/navbar" .ctxData}} -
+
{{template "base/alert" .ctxData}} {{/* block: org-setting-content */}} diff --git a/templates/org/settings/navbar.tmpl b/templates/org/settings/navbar.tmpl index 201ac3b9f297b..64ae20f0a3b72 100644 --- a/templates/org/settings/navbar.tmpl +++ b/templates/org/settings/navbar.tmpl @@ -1,4 +1,4 @@ -
+
- {{ctx.Locale.Tr "repo.issues.filter_milestone_all"}} - {{ctx.Locale.Tr "repo.issues.filter_milestone_none"}} + {{ctx.Locale.Tr "repo.issues.filter_milestone_all"}} + {{ctx.Locale.Tr "repo.issues.filter_milestone_none"}} {{if .OpenMilestones}}
{{ctx.Locale.Tr "repo.issues.filter_milestone_open"}}
{{range .OpenMilestones}} - + {{svg "octicon-milestone" 16 "mr-2"}} {{.Name}} @@ -66,7 +87,7 @@
{{ctx.Locale.Tr "repo.issues.filter_milestone_closed"}}
{{range .ClosedMilestones}} - + {{svg "octicon-milestone" 16 "mr-2"}} {{.Name}} @@ -87,15 +108,15 @@ {{svg "octicon-search" 16}}
- {{ctx.Locale.Tr "repo.issues.filter_project_all"}} - {{ctx.Locale.Tr "repo.issues.filter_project_none"}} + {{ctx.Locale.Tr "repo.issues.filter_project_all"}} + {{ctx.Locale.Tr "repo.issues.filter_project_none"}} {{if .OpenProjects}}
{{ctx.Locale.Tr "repo.issues.new.open_projects"}}
{{range .OpenProjects}} - + {{svg .IconName 18 "gt-mr-3 gt-shrink-0"}}{{.Title}} {{end}} @@ -106,7 +127,7 @@ {{ctx.Locale.Tr "repo.issues.new.closed_projects"}}
{{range .ClosedProjects}} - + {{svg .IconName 18 "gt-mr-3"}}{{.Title}} {{end}} @@ -118,7 +139,7 @@ - {{ctx.Locale.Tr "repo.issues.filter_assginee_no_select"}} - {{ctx.Locale.Tr "repo.issues.filter_assginee_no_assignee"}} + {{ctx.Locale.Tr "repo.issues.filter_assginee_no_select"}} + {{ctx.Locale.Tr "repo.issues.filter_assginee_no_assignee"}}
{{range .Assignees}} - + {{ctx.AvatarUtils.Avatar . 20}}{{template "repo/search_name" .}} {{end}} @@ -163,14 +184,14 @@ {{svg "octicon-triangle-down" 14 "dropdown icon"}}
{{end}} @@ -182,14 +203,14 @@ {{svg "octicon-triangle-down" 14 "dropdown icon"}}
diff --git a/templates/repo/issue/list.tmpl b/templates/repo/issue/list.tmpl index 75d4234324a2d..038526f424f9f 100644 --- a/templates/repo/issue/list.tmpl +++ b/templates/repo/issue/list.tmpl @@ -36,132 +36,7 @@ {{template "repo/issue/openclose" .}}
- + {{template "repo/issue/filter_actions" .}}
{{template "shared/issuelist" dict "." . "listType" "repo"}} diff --git a/templates/repo/issue/new_form.tmpl b/templates/repo/issue/new_form.tmpl index 6502a8d889880..62b6b5ce6f217 100644 --- a/templates/repo/issue/new_form.tmpl +++ b/templates/repo/issue/new_form.tmpl @@ -111,7 +111,7 @@ {{ctx.Locale.Tr "repo.issues.new.open_projects"}} {{range .OpenProjects}} - + {{svg .IconName 18 "gt-mr-3"}}{{.Title}} {{end}} @@ -122,7 +122,7 @@ {{ctx.Locale.Tr "repo.issues.new.closed_projects"}} {{range .ClosedProjects}} - + {{svg .IconName 18 "gt-mr-3"}}{{.Title}} {{end}} diff --git a/templates/repo/issue/openclose.tmpl b/templates/repo/issue/openclose.tmpl index a215922afcb9a..ad8de4013a63f 100644 --- a/templates/repo/issue/openclose.tmpl +++ b/templates/repo/issue/openclose.tmpl @@ -1,5 +1,5 @@ {{else if eq .Type 4}} @@ -468,7 +468,7 @@ {{$resolveDoer := (index $comms 0).ResolveDoer}} {{$isNotPending := (not (eq (index $comms 0).Review.Type 0))}}
- {{$filename}} + {{$filename}} {{if $invalid}} {{ctx.Locale.Tr "repo.issues.review.outdated"}} @@ -496,7 +496,7 @@ {{end}}
- {{$diff := (CommentMustAsDiff (index $comms 0))}} + {{$diff := (CommentMustAsDiff ctx (index $comms 0))}} {{if $diff}} {{$file := (index $diff.Files 0)}}
diff --git a/templates/repo/issue/view_content/sidebar.tmpl b/templates/repo/issue/view_content/sidebar.tmpl index 6692330cbe303..c3ba15390bb4e 100644 --- a/templates/repo/issue/view_content/sidebar.tmpl +++ b/templates/repo/issue/view_content/sidebar.tmpl @@ -173,7 +173,7 @@ {{ctx.Locale.Tr "repo.issues.new.open_projects"}}
{{range .OpenProjects}} - + {{svg .IconName 18 "gt-mr-3"}}{{.Title}} {{end}} @@ -184,7 +184,7 @@ {{ctx.Locale.Tr "repo.issues.new.closed_projects"}} {{range .ClosedProjects}} - + {{svg .IconName 18 "gt-mr-3"}}{{.Title}} {{end}} @@ -195,7 +195,7 @@ {{ctx.Locale.Tr "repo.issues.new.no_projects"}}
{{if .Issue.Project}} - + {{svg .Issue.Project.IconName 18 "gt-mr-3"}}{{.Issue.Project.Title}} {{end}} diff --git a/templates/repo/pulls/fork.tmpl b/templates/repo/pulls/fork.tmpl index 57d2269807bef..94de4d78ebe88 100644 --- a/templates/repo/pulls/fork.tmpl +++ b/templates/repo/pulls/fork.tmpl @@ -51,6 +51,26 @@
{{ctx.Locale.Tr "repo.fork_visibility_helper"}} +
+ + +
diff --git a/templates/repo/settings/layout_head.tmpl b/templates/repo/settings/layout_head.tmpl index 3117309831892..efec9bf87428d 100644 --- a/templates/repo/settings/layout_head.tmpl +++ b/templates/repo/settings/layout_head.tmpl @@ -1,9 +1,9 @@ {{template "base/head" .ctxData}}
{{template "repo/header" .ctxData}} -
+
{{template "repo/settings/navbar" .ctxData}} -
+
{{template "base/alert" .ctxData}} {{/* block: repo-setting-content */}} diff --git a/templates/repo/settings/navbar.tmpl b/templates/repo/settings/navbar.tmpl index 74c4b86c68ede..b16eb6076fad5 100644 --- a/templates/repo/settings/navbar.tmpl +++ b/templates/repo/settings/navbar.tmpl @@ -1,4 +1,4 @@ -
+
@@ -93,7 +93,7 @@ {{end}} {{if .Project}} - + {{svg .Project.IconName 14}}{{.Project.Title}} {{end}} diff --git a/templates/shared/user/profile_big_avatar.tmpl b/templates/shared/user/profile_big_avatar.tmpl index 598c194f19090..a637a9a5f9151 100644 --- a/templates/shared/user/profile_big_avatar.tmpl +++ b/templates/shared/user/profile_big_avatar.tmpl @@ -13,7 +13,11 @@
{{if .ContextUser.FullName}}{{.ContextUser.FullName}}{{end}} - {{.ContextUser.Name}} + {{.ContextUser.Name}} {{if .IsAdmin}} + + {{svg "octicon-gear" 18}} + + {{end}}
{{svg "octicon-person" 18 "gt-mr-2"}}{{.NumFollowers}} {{ctx.Locale.Tr "user.followers"}} · {{.NumFollowing}} {{ctx.Locale.Tr "user.following"}} {{if .EnableFeed}} @@ -83,7 +87,7 @@
  • diff --git a/templates/status/500.tmpl b/templates/status/500.tmpl index 5488976da2884..e5570bde738da 100644 --- a/templates/status/500.tmpl +++ b/templates/status/500.tmpl @@ -1,12 +1,12 @@ {{/* This page should only depend the minimal template functions/variables, to avoid triggering new panics. -* base template functions: AppName, AssetUrlPrefix, AssetVersion, AppSubUrl, DefaultTheme, Str2html +* base template functions: AppName, AssetUrlPrefix, AssetVersion, AppSubUrl, ThemeName, Str2html * locale * Flash * ErrorMsg * SignedUser (optional) */}} - + Internal Server Error - {{AppName}} diff --git a/templates/user/dashboard/feeds.tmpl b/templates/user/dashboard/feeds.tmpl index a03da1072df88..c986dcfb44234 100644 --- a/templates/user/dashboard/feeds.tmpl +++ b/templates/user/dashboard/feeds.tmpl @@ -7,91 +7,94 @@
    {{if gt .ActUser.ID 0}} - {{.GetDisplayName}} + {{.GetDisplayName ctx}} {{else}} - {{.ShortActUserName}} + {{.ShortActUserName ctx}} {{end}} {{if .GetOpType.InActions "create_repo"}} - {{ctx.Locale.Tr "action.create_repo" (.GetRepoLink|Escape) (.ShortRepoPath|Escape) | Str2html}} + {{ctx.Locale.Tr "action.create_repo" ((.GetRepoLink ctx)|Escape) ((.ShortRepoPath ctx)|Escape) | Str2html}} {{else if .GetOpType.InActions "rename_repo"}} - {{ctx.Locale.Tr "action.rename_repo" (.GetContent|Escape) (.GetRepoLink|Escape) (.ShortRepoPath|Escape) | Str2html}} + {{ctx.Locale.Tr "action.rename_repo" (.GetContent|Escape) ((.GetRepoLink ctx)|Escape) ((.ShortRepoPath ctx)|Escape) | Str2html}} {{else if .GetOpType.InActions "commit_repo"}} {{if .Content}} - {{ctx.Locale.Tr "action.commit_repo" (.GetRepoLink|Escape) (.GetRefLink|Escape) (Escape .GetBranch) (.ShortRepoPath|Escape) | Str2html}} + {{ctx.Locale.Tr "action.commit_repo" ((.GetRepoLink ctx)|Escape) ((.GetRefLink ctx)|Escape) (Escape .GetBranch) ((.ShortRepoPath ctx)|Escape) | Str2html}} {{else}} - {{ctx.Locale.Tr "action.create_branch" (.GetRepoLink|Escape) (.GetRefLink|Escape) (Escape .GetBranch) (.ShortRepoPath|Escape) | Str2html}} + {{ctx.Locale.Tr "action.create_branch" ((.GetRepoLink ctx)|Escape) ((.GetRefLink ctx)|Escape) (Escape .GetBranch) ((.ShortRepoPath ctx)|Escape) | Str2html}} {{end}} {{else if .GetOpType.InActions "create_issue"}} {{$index := index .GetIssueInfos 0}} - {{ctx.Locale.Tr "action.create_issue" ((printf "%s/issues/%s" .GetRepoLink $index) |Escape) $index (.ShortRepoPath|Escape) | Str2html}} + {{ctx.Locale.Tr "action.create_issue" ((printf "%s/issues/%s" (.GetRepoLink ctx) $index) |Escape) $index ((.ShortRepoPath ctx)|Escape) | Str2html}} {{else if .GetOpType.InActions "create_pull_request"}} {{$index := index .GetIssueInfos 0}} - {{ctx.Locale.Tr "action.create_pull_request" ((printf "%s/pulls/%s" .GetRepoLink $index) |Escape) $index (.ShortRepoPath|Escape) | Str2html}} + {{ctx.Locale.Tr "action.create_pull_request" ((printf "%s/pulls/%s" (.GetRepoLink ctx) $index) |Escape) $index ((.ShortRepoPath ctx)|Escape) | Str2html}} {{else if .GetOpType.InActions "transfer_repo"}} - {{ctx.Locale.Tr "action.transfer_repo" .GetContent (.GetRepoLink|Escape) (.ShortRepoPath|Escape) | Str2html}} + {{ctx.Locale.Tr "action.transfer_repo" .GetContent ((.GetRepoLink ctx)|Escape) ((.ShortRepoPath ctx)|Escape) | Str2html}} {{else if .GetOpType.InActions "push_tag"}} - {{ctx.Locale.Tr "action.push_tag" (.GetRepoLink|Escape) (.GetRefLink|Escape) (.GetTag|Escape) (.ShortRepoPath|Escape) | Str2html}} + {{ctx.Locale.Tr "action.push_tag" ((.GetRepoLink ctx)|Escape) ((.GetRefLink ctx)|Escape) (.GetTag|Escape) ((.ShortRepoPath ctx)|Escape) | Str2html}} {{else if .GetOpType.InActions "comment_issue"}} {{$index := index .GetIssueInfos 0}} - {{ctx.Locale.Tr "action.comment_issue" ((printf "%s/issues/%s" .GetRepoLink $index) |Escape) $index (.ShortRepoPath|Escape) | Str2html}} + {{ctx.Locale.Tr "action.comment_issue" ((printf "%s/issues/%s" (.GetRepoLink ctx) $index) |Escape) $index ((.ShortRepoPath ctx)|Escape) | Str2html}} {{else if .GetOpType.InActions "merge_pull_request"}} {{$index := index .GetIssueInfos 0}} - {{ctx.Locale.Tr "action.merge_pull_request" ((printf "%s/pulls/%s" .GetRepoLink $index) |Escape) $index (.ShortRepoPath|Escape) | Str2html}} + {{ctx.Locale.Tr "action.merge_pull_request" ((printf "%s/pulls/%s" (.GetRepoLink ctx) $index) |Escape) $index ((.ShortRepoPath ctx)|Escape) | Str2html}} {{else if .GetOpType.InActions "close_issue"}} {{$index := index .GetIssueInfos 0}} - {{ctx.Locale.Tr "action.close_issue" ((printf "%s/issues/%s" .GetRepoLink $index) |Escape) $index (.ShortRepoPath|Escape) | Str2html}} + {{ctx.Locale.Tr "action.close_issue" ((printf "%s/issues/%s" (.GetRepoLink ctx) $index) |Escape) $index ((.ShortRepoPath ctx)|Escape) | Str2html}} {{else if .GetOpType.InActions "reopen_issue"}} {{$index := index .GetIssueInfos 0}} - {{ctx.Locale.Tr "action.reopen_issue" ((printf "%s/issues/%s" .GetRepoLink $index) |Escape) $index (.ShortRepoPath|Escape) | Str2html}} + {{ctx.Locale.Tr "action.reopen_issue" ((printf "%s/issues/%s" (.GetRepoLink ctx) $index) |Escape) $index ((.ShortRepoPath ctx)|Escape) | Str2html}} {{else if .GetOpType.InActions "close_pull_request"}} {{$index := index .GetIssueInfos 0}} - {{ctx.Locale.Tr "action.close_pull_request" ((printf "%s/pulls/%s" .GetRepoLink $index) |Escape) $index (.ShortRepoPath|Escape) | Str2html}} + {{ctx.Locale.Tr "action.close_pull_request" ((printf "%s/pulls/%s" (.GetRepoLink ctx) $index) |Escape) $index ((.ShortRepoPath ctx)|Escape) | Str2html}} {{else if .GetOpType.InActions "reopen_pull_request"}} {{$index := index .GetIssueInfos 0}} - {{ctx.Locale.Tr "action.reopen_pull_request" ((printf "%s/pulls/%s" .GetRepoLink $index) |Escape) $index (.ShortRepoPath|Escape) | Str2html}} + {{ctx.Locale.Tr "action.reopen_pull_request" ((printf "%s/pulls/%s" (.GetRepoLink ctx) $index) |Escape) $index ((.ShortRepoPath ctx)|Escape) | Str2html}} {{else if .GetOpType.InActions "delete_tag"}} {{$index := index .GetIssueInfos 0}} - {{ctx.Locale.Tr "action.delete_tag" (.GetRepoLink|Escape) (.GetTag|Escape) (.ShortRepoPath|Escape) | Str2html}} + {{ctx.Locale.Tr "action.delete_tag" ((.GetRepoLink ctx)|Escape) (.GetTag|Escape) ((.ShortRepoPath ctx)|Escape) | Str2html}} {{else if .GetOpType.InActions "delete_branch"}} {{$index := index .GetIssueInfos 0}} - {{ctx.Locale.Tr "action.delete_branch" (.GetRepoLink|Escape) (.GetBranch|Escape) (.ShortRepoPath|Escape) | Str2html}} + {{ctx.Locale.Tr "action.delete_branch" ((.GetRepoLink ctx)|Escape) (.GetBranch|Escape) ((.ShortRepoPath ctx)|Escape) | Str2html}} {{else if .GetOpType.InActions "mirror_sync_push"}} - {{ctx.Locale.Tr "action.mirror_sync_push" (.GetRepoLink|Escape) (.GetRefLink|Escape) (.GetBranch|Escape) (.ShortRepoPath|Escape) | Str2html}} + {{ctx.Locale.Tr "action.mirror_sync_push" ((.GetRepoLink ctx)|Escape) ((.GetRefLink ctx)|Escape) (.GetBranch|Escape) ((.ShortRepoPath ctx)|Escape) | Str2html}} {{else if .GetOpType.InActions "mirror_sync_create"}} - {{ctx.Locale.Tr "action.mirror_sync_create" (.GetRepoLink|Escape) (.GetRefLink|Escape) (.GetBranch|Escape) (.ShortRepoPath|Escape) | Str2html}} + {{ctx.Locale.Tr "action.mirror_sync_create" ((.GetRepoLink ctx)|Escape) ((.GetRefLink ctx)|Escape) (.GetBranch|Escape) ((.ShortRepoPath ctx)|Escape) | Str2html}} {{else if .GetOpType.InActions "mirror_sync_delete"}} - {{ctx.Locale.Tr "action.mirror_sync_delete" (.GetRepoLink|Escape) (.GetBranch|Escape) (.ShortRepoPath|Escape) | Str2html}} + {{ctx.Locale.Tr "action.mirror_sync_delete" ((.GetRepoLink ctx)|Escape) (.GetBranch|Escape) ((.ShortRepoPath ctx)|Escape) | Str2html}} {{else if .GetOpType.InActions "approve_pull_request"}} {{$index := index .GetIssueInfos 0}} - {{ctx.Locale.Tr "action.approve_pull_request" ((printf "%s/pulls/%s" .GetRepoLink $index) |Escape) $index (.ShortRepoPath|Escape) | Str2html}} + {{ctx.Locale.Tr "action.approve_pull_request" ((printf "%s/pulls/%s" (.GetRepoLink ctx) $index) |Escape) $index ((.ShortRepoPath ctx)|Escape) | Str2html}} {{else if .GetOpType.InActions "reject_pull_request"}} {{$index := index .GetIssueInfos 0}} - {{ctx.Locale.Tr "action.reject_pull_request" ((printf "%s/pulls/%s" .GetRepoLink $index) |Escape) $index (.ShortRepoPath|Escape) | Str2html}} + {{ctx.Locale.Tr "action.reject_pull_request" ((printf "%s/pulls/%s" (.GetRepoLink ctx) $index) |Escape) $index ((.ShortRepoPath ctx)|Escape) | Str2html}} {{else if .GetOpType.InActions "comment_pull"}} {{$index := index .GetIssueInfos 0}} - {{ctx.Locale.Tr "action.comment_pull" ((printf "%s/pulls/%s" .GetRepoLink $index) |Escape) $index (.ShortRepoPath|Escape) | Str2html}} + {{ctx.Locale.Tr "action.comment_pull" ((printf "%s/pulls/%s" (.GetRepoLink ctx) $index) |Escape) $index ((.ShortRepoPath ctx)|Escape) | Str2html}} {{else if .GetOpType.InActions "publish_release"}} {{$linkText := .Content | RenderEmoji $.Context}} - {{ctx.Locale.Tr "action.publish_release" (.GetRepoLink|Escape) ((printf "%s/releases/tag/%s" .GetRepoLink .GetTag)|Escape) (.ShortRepoPath|Escape) $linkText | Str2html}} + {{ctx.Locale.Tr "action.publish_release" ((.GetRepoLink ctx)|Escape) ((printf "%s/releases/tag/%s" (.GetRepoLink ctx) .GetTag)|Escape) ((.ShortRepoPath ctx)|Escape) $linkText | Str2html}} {{else if .GetOpType.InActions "review_dismissed"}} {{$index := index .GetIssueInfos 0}} {{$reviewer := index .GetIssueInfos 1}} - {{ctx.Locale.Tr "action.review_dismissed" ((printf "%s/pulls/%s" .GetRepoLink $index) |Escape) $index (.ShortRepoPath|Escape) $reviewer | Str2html}} + {{ctx.Locale.Tr "action.review_dismissed" ((printf "%s/pulls/%s" (.GetRepoLink ctx) $index) |Escape) $index ((.ShortRepoPath ctx)|Escape) $reviewer | Str2html}} {{end}} + {{TimeSince .GetCreate ctx.Locale}}
    {{if .GetOpType.InActions "commit_repo" "mirror_sync_push"}} {{$push := ActionContent2Commits .}} - {{$repoLink := .GetRepoLink}} - {{range $push.Commits}} - {{$commitLink := printf "%s/commit/%s" $repoLink .Sha1}} -
    - - {{ShortSha .Sha1}} - - {{RenderCommitMessage $.Context .Message $repoLink $.ComposeMetas}} - -
    - {{end}} + {{$repoLink := (.GetRepoLink ctx)}} +
    + {{range $push.Commits}} + {{$commitLink := printf "%s/commit/%s" $repoLink .Sha1}} +
    + + {{ShortSha .Sha1}} + + {{RenderCommitMessage $.Context .Message $repoLink $.ComposeMetas}} + +
    + {{end}} +
    {{if and (gt $push.Len 1) $push.CompareURL}} {{ctx.Locale.Tr "action.compare_commits" $push.Len}} » {{end}} @@ -100,20 +103,19 @@ {{else if .GetOpType.InActions "create_pull_request"}} {{index .GetIssueInfos 1 | RenderEmoji $.Context | RenderCodeBlock}} {{else if .GetOpType.InActions "comment_issue" "approve_pull_request" "reject_pull_request" "comment_pull"}} - {{.GetIssueTitle | RenderEmoji $.Context | RenderCodeBlock}} + {{(.GetIssueTitle ctx) | RenderEmoji $.Context | RenderCodeBlock}} {{$comment := index .GetIssueInfos 1}} {{if gt (len $comment) 0}} -
    {{$comment | RenderEmoji $.Context | RenderCodeBlock}}
    +
    {{RenderMarkdownToHtml ctx $comment}}
    {{end}} {{else if .GetOpType.InActions "merge_pull_request"}} -
    {{index .GetIssueInfos 1}}
    +
    {{index .GetIssueInfos 1}}
    {{else if .GetOpType.InActions "close_issue" "reopen_issue" "close_pull_request" "reopen_pull_request"}} - {{.GetIssueTitle | RenderEmoji $.Context | RenderCodeBlock}} + {{(.GetIssueTitle ctx) | RenderEmoji $.Context | RenderCodeBlock}} {{else if .GetOpType.InActions "pull_review_dismissed"}} -
    {{ctx.Locale.Tr "action.review_dismissed_reason"}}
    -
    {{index .GetIssueInfos 2 | RenderEmoji $.Context}}
    +
    {{ctx.Locale.Tr "action.review_dismissed_reason"}}
    +
    {{index .GetIssueInfos 2 | RenderEmoji $.Context}}
    {{end}} -
    {{TimeSince .GetCreate ctx.Locale}}
    {{svg (printf "octicon-%s" (ActionIcon .GetOpType)) 32 "text grey gt-mr-2"}} diff --git a/templates/user/notification/notification_div.tmpl b/templates/user/notification/notification_div.tmpl index a07f44a06581e..e98eff9cffb46 100644 --- a/templates/user/notification/notification_div.tmpl +++ b/templates/user/notification/notification_div.tmpl @@ -43,7 +43,7 @@ {{svg "octicon-repo" 16 "text grey"}} {{end}}
    - +
    {{.Repository.FullName}} {{if .Issue}}#{{.Issue.Index}}{{end}} {{if eq .Status 3}} diff --git a/tests/e2e/README.md b/tests/e2e/README.md index bf444ddb800e2..e5fd1ca6c07f7 100644 --- a/tests/e2e/README.md +++ b/tests/e2e/README.md @@ -7,7 +7,6 @@ They can be run with make commands for the appropriate backends, namely: make test-sqlite make test-pgsql make test-mysql -make test-mysql8 make test-mssql ``` @@ -76,7 +75,7 @@ For SQLite: make test-e2e-sqlite#example ``` -For other databases(replace `mssql` to `mysql`, `mysql8` or `pgsql`): +For other databases(replace `mssql` to `mysql` or `pgsql`): ``` TEST_MSSQL_HOST=localhost:1433 TEST_MSSQL_DBNAME=test TEST_MSSQL_USERNAME=sa TEST_MSSQL_PASSWORD=MwantsaSecurePassword1 make test-e2e-mssql#example @@ -90,4 +89,4 @@ Although the main goal of e2e is assertion testing, we have added a framework fo VISUAL_TEST=1 will create screenshots in tests/e2e/test-snapshots. The test will fail the first time this is enabled (until we get visual test image persistence figured out), because it will be testing against an empty screenshot folder. -ACCEPT_VISUAL=1 will overwrite the snapshot images with new images. \ No newline at end of file +ACCEPT_VISUAL=1 will overwrite the snapshot images with new images. diff --git a/tests/gitea-repositories-meta/user2/repo2.git/refs/tags/v1.1 b/tests/gitea-repositories-meta/user2/repo2.git/refs/tags/v1.1 new file mode 100644 index 0000000000000..334d09ca02155 --- /dev/null +++ b/tests/gitea-repositories-meta/user2/repo2.git/refs/tags/v1.1 @@ -0,0 +1 @@ +1032bbf17fbc0d9c95bb5418dabe8f8c99278700 diff --git a/tests/integration/README.md b/tests/integration/README.md index f4e0061314668..f6f74ca21ff9a 100644 --- a/tests/integration/README.md +++ b/tests/integration/README.md @@ -6,7 +6,6 @@ appropriate backends, namely: make test-sqlite make test-pgsql make test-mysql -make test-mysql8 make test-mssql ``` @@ -84,7 +83,7 @@ For SQLite: make test-sqlite#GPG ``` -For other databases(replace `mssql` to `mysql`, `mysql8` or `pgsql`): +For other databases(replace `mssql` to `mysql`, or `pgsql`): ``` TEST_MSSQL_HOST=localhost:1433 TEST_MSSQL_DBNAME=test TEST_MSSQL_USERNAME=sa TEST_MSSQL_PASSWORD=MwantsaSecurePassword1 make test-mssql#GPG diff --git a/tests/integration/README_ZH.md b/tests/integration/README_ZH.md index a924892f815d9..6aea4ab212ba7 100644 --- a/tests/integration/README_ZH.md +++ b/tests/integration/README_ZH.md @@ -79,7 +79,7 @@ sqlite 数据库: make test-sqlite#GPG ``` -其它数据库(把 MSSQL 替换为 MYSQL, MYSQL8, PGSQL): +其它数据库(把 MSSQL 替换为 MYSQL, PGSQL): ``` TEST_MSSQL_HOST=localhost:1433 TEST_MSSQL_DBNAME=test TEST_MSSQL_USERNAME=sa TEST_MSSQL_PASSWORD=MwantsaSecurePassword1 make test-mssql#GPG diff --git a/tests/integration/actions_trigger_test.go b/tests/integration/actions_trigger_test.go index 82c1967b5227f..253de70326553 100644 --- a/tests/integration/actions_trigger_test.go +++ b/tests/integration/actions_trigger_test.go @@ -45,7 +45,7 @@ func TestPullRequestTargetEvent(t *testing.T) { assert.NotEmpty(t, baseRepo) // enable actions - err = repo_model.UpdateRepositoryUnits(baseRepo, []repo_model.RepoUnit{{ + err = repo_model.UpdateRepositoryUnits(db.DefaultContext, baseRepo, []repo_model.RepoUnit{{ RepoID: baseRepo.ID, Type: unit_model.TypeActions, }}, nil) diff --git a/tests/integration/api_issue_config_test.go b/tests/integration/api_issue_config_test.go index f3dc663f3bee1..b9125438b6fe2 100644 --- a/tests/integration/api_issue_config_test.go +++ b/tests/integration/api_issue_config_test.go @@ -15,38 +15,167 @@ import ( "code.gitea.io/gitea/tests" "github.com/stretchr/testify/assert" + "gopkg.in/yaml.v3" ) -func TestAPIReposGetDefaultIssueConfig(t *testing.T) { - defer tests.PrepareTestEnv(t)() +func createIssueConfig(t *testing.T, user *user_model.User, repo *repo_model.Repository, issueConfig map[string]any) { + config, err := yaml.Marshal(issueConfig) + assert.NoError(t, err) - repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) + err = createOrReplaceFileInBranch(user, repo, ".gitea/ISSUE_TEMPLATE/config.yaml", repo.DefaultBranch, string(config)) + assert.NoError(t, err) +} - urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issue_config", owner.Name, repo.Name) +func getIssueConfig(t *testing.T, owner, repo string) api.IssueConfig { + urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issue_config", owner, repo) req := NewRequest(t, "GET", urlStr) resp := MakeRequest(t, req, http.StatusOK) var issueConfig api.IssueConfig DecodeJSON(t, resp, &issueConfig) - assert.True(t, issueConfig.BlankIssuesEnabled) - assert.Equal(t, issueConfig.ContactLinks, make([]api.IssueConfigContactLink, 0)) + return issueConfig +} + +func TestAPIRepoGetIssueConfig(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 49}) + owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) + + t.Run("Default", func(t *testing.T) { + issueConfig := getIssueConfig(t, owner.Name, repo.Name) + + assert.True(t, issueConfig.BlankIssuesEnabled) + assert.Len(t, issueConfig.ContactLinks, 0) + }) + + t.Run("DisableBlankIssues", func(t *testing.T) { + config := make(map[string]any) + config["blank_issues_enabled"] = false + + createIssueConfig(t, owner, repo, config) + + issueConfig := getIssueConfig(t, owner.Name, repo.Name) + + assert.False(t, issueConfig.BlankIssuesEnabled) + assert.Len(t, issueConfig.ContactLinks, 0) + }) + + t.Run("ContactLinks", func(t *testing.T) { + contactLink := make(map[string]string) + contactLink["name"] = "TestName" + contactLink["url"] = "https://example.com" + contactLink["about"] = "TestAbout" + + config := make(map[string]any) + config["contact_links"] = []map[string]string{contactLink} + + createIssueConfig(t, owner, repo, config) + + issueConfig := getIssueConfig(t, owner.Name, repo.Name) + + assert.True(t, issueConfig.BlankIssuesEnabled) + assert.Len(t, issueConfig.ContactLinks, 1) + + assert.Equal(t, "TestName", issueConfig.ContactLinks[0].Name) + assert.Equal(t, "https://example.com", issueConfig.ContactLinks[0].URL) + assert.Equal(t, "TestAbout", issueConfig.ContactLinks[0].About) + }) + + t.Run("Full", func(t *testing.T) { + contactLink := make(map[string]string) + contactLink["name"] = "TestName" + contactLink["url"] = "https://example.com" + contactLink["about"] = "TestAbout" + + config := make(map[string]any) + config["blank_issues_enabled"] = false + config["contact_links"] = []map[string]string{contactLink} + + createIssueConfig(t, owner, repo, config) + + issueConfig := getIssueConfig(t, owner.Name, repo.Name) + + assert.False(t, issueConfig.BlankIssuesEnabled) + assert.Len(t, issueConfig.ContactLinks, 1) + + assert.Equal(t, "TestName", issueConfig.ContactLinks[0].Name) + assert.Equal(t, "https://example.com", issueConfig.ContactLinks[0].URL) + assert.Equal(t, "TestAbout", issueConfig.ContactLinks[0].About) + }) } -func TestAPIReposValidateDefaultIssueConfig(t *testing.T) { +func TestAPIRepoIssueConfigPaths(t *testing.T) { defer tests.PrepareTestEnv(t)() - repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 49}) + owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) + + templateConfigCandidates := []string{ + ".gitea/ISSUE_TEMPLATE/config", + ".gitea/issue_template/config", + ".github/ISSUE_TEMPLATE/config", + ".github/issue_template/config", + } + + for _, canidate := range templateConfigCandidates { + for _, extension := range []string{".yaml", ".yml"} { + fullPath := canidate + extension + t.Run(fullPath, func(t *testing.T) { + configMap := make(map[string]any) + configMap["blank_issues_enabled"] = false + + configData, err := yaml.Marshal(configMap) + assert.NoError(t, err) + + _, err = createFileInBranch(owner, repo, fullPath, repo.DefaultBranch, string(configData)) + assert.NoError(t, err) + + issueConfig := getIssueConfig(t, owner.Name, repo.Name) + + assert.False(t, issueConfig.BlankIssuesEnabled) + assert.Len(t, issueConfig.ContactLinks, 0) + + _, err = deleteFileInBranch(owner, repo, fullPath, repo.DefaultBranch) + assert.NoError(t, err) + }) + } + } +} + +func TestAPIRepoValidateIssueConfig(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 49}) owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) urlStr := fmt.Sprintf("/api/v1/repos/%s/%s/issue_config/validate", owner.Name, repo.Name) - req := NewRequest(t, "GET", urlStr) - resp := MakeRequest(t, req, http.StatusOK) - var issueConfigValidation api.IssueConfigValidation - DecodeJSON(t, resp, &issueConfigValidation) + t.Run("Valid", func(t *testing.T) { + req := NewRequest(t, "GET", urlStr) + resp := MakeRequest(t, req, http.StatusOK) + + var issueConfigValidation api.IssueConfigValidation + DecodeJSON(t, resp, &issueConfigValidation) + + assert.True(t, issueConfigValidation.Valid) + assert.Empty(t, issueConfigValidation.Message) + }) + + t.Run("Invalid", func(t *testing.T) { + config := make(map[string]any) + config["blank_issues_enabled"] = "Test" + + createIssueConfig(t, owner, repo, config) + + req := NewRequest(t, "GET", urlStr) + resp := MakeRequest(t, req, http.StatusOK) + + var issueConfigValidation api.IssueConfigValidation + DecodeJSON(t, resp, &issueConfigValidation) - assert.True(t, issueConfigValidation.Valid) - assert.Empty(t, issueConfigValidation.Message) + assert.False(t, issueConfigValidation.Valid) + assert.NotEmpty(t, issueConfigValidation.Message) + }) } diff --git a/tests/integration/api_issue_subscription_test.go b/tests/integration/api_issue_subscription_test.go index 09c83b63b1485..28650a337523f 100644 --- a/tests/integration/api_issue_subscription_test.go +++ b/tests/integration/api_issue_subscription_test.go @@ -9,6 +9,7 @@ import ( "testing" auth_model "code.gitea.io/gitea/models/auth" + "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" @@ -44,7 +45,7 @@ func TestAPIIssueSubscriptions(t *testing.T) { assert.EqualValues(t, isWatching, wi.Subscribed) assert.EqualValues(t, !isWatching, wi.Ignored) - assert.EqualValues(t, issue.APIURL()+"/subscriptions", wi.URL) + assert.EqualValues(t, issue.APIURL(db.DefaultContext)+"/subscriptions", wi.URL) assert.EqualValues(t, issue.CreatedUnix, wi.CreatedAt.Unix()) assert.EqualValues(t, issueRepo.APIURL(), wi.RepositoryURL) } diff --git a/tests/integration/api_notification_test.go b/tests/integration/api_notification_test.go index 222b2c2e07c1d..c6ee576e5921c 100644 --- a/tests/integration/api_notification_test.go +++ b/tests/integration/api_notification_test.go @@ -100,7 +100,7 @@ func TestAPINotification(t *testing.T) { assert.True(t, apiN.Unread) assert.EqualValues(t, "issue4", apiN.Subject.Title) assert.EqualValues(t, "Issue", apiN.Subject.Type) - assert.EqualValues(t, thread5.Issue.APIURL(), apiN.Subject.URL) + assert.EqualValues(t, thread5.Issue.APIURL(db.DefaultContext), apiN.Subject.URL) assert.EqualValues(t, thread5.Repository.HTMLURL(), apiN.Repository.HTMLURL) MakeRequest(t, NewRequest(t, "GET", "/api/v1/notifications/new"), http.StatusUnauthorized) diff --git a/tests/integration/api_pull_review_test.go b/tests/integration/api_pull_review_test.go index dd49cf64386ff..0e9bace44c9d6 100644 --- a/tests/integration/api_pull_review_test.go +++ b/tests/integration/api_pull_review_test.go @@ -76,7 +76,7 @@ func TestAPIPullReview(t *testing.T) { assert.EqualValues(t, "a review from a deleted user", reviewComments[0].Body) assert.EqualValues(t, comment.ID, reviewComments[0].ID) assert.EqualValues(t, comment.UpdatedUnix, reviewComments[0].Updated.Unix()) - assert.EqualValues(t, comment.HTMLURL(), reviewComments[0].HTMLURL) + assert.EqualValues(t, comment.HTMLURL(db.DefaultContext), reviewComments[0].HTMLURL) // test CreatePullReview req = NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/pulls/%d/reviews?token=%s", repo.OwnerName, repo.Name, pullIssue.Index, token), &api.CreatePullReviewOptions{ diff --git a/tests/integration/api_repo_file_helpers.go b/tests/integration/api_repo_file_helpers.go index 27e127fcc88b6..4350092b8b167 100644 --- a/tests/integration/api_repo_file_helpers.go +++ b/tests/integration/api_repo_file_helpers.go @@ -6,6 +6,7 @@ package integration import ( "strings" + "code.gitea.io/gitea/models" repo_model "code.gitea.io/gitea/models/repo" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/git" @@ -29,6 +30,32 @@ func createFileInBranch(user *user_model.User, repo *repo_model.Repository, tree return files_service.ChangeRepoFiles(git.DefaultContext, repo, user, opts) } +func deleteFileInBranch(user *user_model.User, repo *repo_model.Repository, treePath, branchName string) (*api.FilesResponse, error) { + opts := &files_service.ChangeRepoFilesOptions{ + Files: []*files_service.ChangeRepoFile{ + { + Operation: "delete", + TreePath: treePath, + }, + }, + OldBranch: branchName, + Author: nil, + Committer: nil, + } + return files_service.ChangeRepoFiles(git.DefaultContext, repo, user, opts) +} + +func createOrReplaceFileInBranch(user *user_model.User, repo *repo_model.Repository, treePath, branchName, content string) error { + _, err := deleteFileInBranch(user, repo, treePath, branchName) + + if err != nil && !models.IsErrRepoFileDoesNotExist(err) { + return err + } + + _, err = createFileInBranch(user, repo, treePath, branchName, content) + return err +} + func createFile(user *user_model.User, repo *repo_model.Repository, treePath string) (*api.FilesResponse, error) { return createFileInBranch(user, repo, treePath, repo.DefaultBranch, "This is a NEW file") } diff --git a/tests/integration/auth_ldap_test.go b/tests/integration/auth_ldap_test.go index eb6486fde1f0a..ac4c41bf4d62b 100644 --- a/tests/integration/auth_ldap_test.go +++ b/tests/integration/auth_ldap_test.go @@ -414,7 +414,7 @@ func TestLDAPGroupTeamSyncAddMember(t *testing.T) { user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ Name: gitLDAPUser.UserName, }) - usersOrgs, err := organization.FindOrgs(organization.FindOrgOptions{ + usersOrgs, err := organization.FindOrgs(db.DefaultContext, organization.FindOrgOptions{ UserID: user.ID, IncludePrivate: true, }) @@ -458,7 +458,7 @@ func TestLDAPGroupTeamSyncRemoveMember(t *testing.T) { user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ Name: gitLDAPUsers[0].UserName, }) - err = organization.AddOrgUser(org.ID, user.ID) + err = organization.AddOrgUser(db.DefaultContext, org.ID, user.ID) assert.NoError(t, err) err = models.AddTeamMember(db.DefaultContext, team, user.ID) assert.NoError(t, err) diff --git a/tests/integration/links_test.go b/tests/integration/links_test.go index 91655833af041..a3937dd697eeb 100644 --- a/tests/integration/links_test.go +++ b/tests/integration/links_test.go @@ -159,6 +159,7 @@ func testLinksAsUser(userName string, t *testing.T) { "/releases/new", //"/wiki/_pages", "/wiki/?action=_new", + "/activity", } for _, repo := range apiRepos { @@ -174,3 +175,35 @@ func TestLinksLogin(t *testing.T) { testLinksAsUser("user2", t) } + +func TestRepoLinks(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + // repo1 has enabled almost features, so we can test most links + repoLink := "/user2/repo1" + links := []string{ + "/actions", + "/packages", + "/projects", + } + + // anonymous user + for _, link := range links { + req := NewRequest(t, "GET", repoLink+link) + MakeRequest(t, req, http.StatusOK) + } + + // admin/owner user + session := loginUser(t, "user1") + for _, link := range links { + req := NewRequest(t, "GET", repoLink+link) + session.MakeRequest(t, req, http.StatusOK) + } + + // non-admin non-owner user + session = loginUser(t, "user2") + for _, link := range links { + req := NewRequest(t, "GET", repoLink+link) + session.MakeRequest(t, req, http.StatusOK) + } +} diff --git a/tests/integration/org_count_test.go b/tests/integration/org_count_test.go index e46b83169b7f9..d1aa41963eb82 100644 --- a/tests/integration/org_count_test.go +++ b/tests/integration/org_count_test.go @@ -9,6 +9,7 @@ import ( "testing" auth_model "code.gitea.io/gitea/models/auth" + "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/organization" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -117,7 +118,7 @@ func doCheckOrgCounts(username string, orgCounts map[string]int, strict bool, ca Name: username, }) - orgs, err := organization.FindOrgs(organization.FindOrgOptions{ + orgs, err := organization.FindOrgs(db.DefaultContext, organization.FindOrgOptions{ UserID: user.ID, IncludePrivate: true, }) diff --git a/tests/integration/release_test.go b/tests/integration/release_test.go index 8de761ea6cb6e..42d0d00e78698 100644 --- a/tests/integration/release_test.go +++ b/tests/integration/release_test.go @@ -239,3 +239,20 @@ func TestViewTagsList(t *testing.T) { assert.EqualValues(t, []string{"v1.0", "delete-tag", "v1.1"}, tagNames) } + +func TestDownloadReleaseAttachment(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + tests.PrepareAttachmentsStorage(t) + + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2}) + + url := repo.Link() + "/releases/download/v1.1/README.md" + + req := NewRequest(t, "GET", url) + MakeRequest(t, req, http.StatusNotFound) + + req = NewRequest(t, "GET", url) + session := loginUser(t, "user2") + session.MakeRequest(t, req, http.StatusOK) +} diff --git a/tests/integration/repo_test.go b/tests/integration/repo_test.go index 99a27d6a7f786..f5417b100cfef 100644 --- a/tests/integration/repo_test.go +++ b/tests/integration/repo_test.go @@ -302,6 +302,10 @@ func TestViewRepoDirectoryReadme(t *testing.T) { check("plain", "/user2/readme-test/src/branch/plain/", "README", "plain-text", "Birken my stocks gee howdy") check("i18n", "/user2/readme-test/src/branch/i18n/", "README.zh.md", "markdown", "蛋糕是一个谎言") + // using HEAD ref + check("branch-HEAD", "/user2/readme-test/src/branch/HEAD/", "README.md", "markdown", "The cake is a lie.") + check("commit-HEAD", "/user2/readme-test/src/commit/HEAD/", "README.md", "markdown", "The cake is a lie.") + // viewing different subdirectories check("subdir", "/user2/readme-test/src/branch/subdir/libcake", "README.md", "markdown", "Four pints of sugar.") check("docs-direct", "/user2/readme-test/src/branch/special-subdir-docs/docs/", "README.md", "markdown", "This is in docs/") diff --git a/tests/mysql8.ini.tmpl b/tests/mysql8.ini.tmpl deleted file mode 100644 index 7d4c27c03674f..0000000000000 --- a/tests/mysql8.ini.tmpl +++ /dev/null @@ -1,109 +0,0 @@ -APP_NAME = Gitea: Git with a cup of tea -RUN_MODE = prod - -[database] -DB_TYPE = mysql -HOST = {{TEST_MYSQL8_HOST}} -NAME = {{TEST_MYSQL8_DBNAME}} -USER = {{TEST_MYSQL8_USERNAME}} -PASSWD = {{TEST_MYSQL8_PASSWORD}} -SSL_MODE = disable - -[indexer] -REPO_INDEXER_ENABLED = true -REPO_INDEXER_PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql8/indexers/repos.bleve - -[queue.issue_indexer] -TYPE = level -DATADIR = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql8/indexers/issues.queue - -[queue] -TYPE = immediate - -[queue.code_indexer] -TYPE = immediate - -[queue.push_update] -TYPE = immediate - -[repository] -ROOT = {{REPO_TEST_DIR}}tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql8/gitea-repositories - -[repository.local] -LOCAL_COPY_PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql8/tmp/local-repo - -[repository.upload] -TEMP_PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql8/tmp/uploads - -[repository.signing] -SIGNING_KEY = none - -[server] -SSH_DOMAIN = localhost -HTTP_PORT = 3004 -ROOT_URL = http://localhost:3004/ -DISABLE_SSH = false -SSH_LISTEN_HOST = localhost -SSH_PORT = 2204 -START_SSH_SERVER = true -LFS_START_SERVER = true -OFFLINE_MODE = false -LFS_JWT_SECRET = Tv_MjmZuHqpIY6GFl12ebgkRAMt4RlWt0v4EHKSXO0w -APP_DATA_PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql8/data -BUILTIN_SSH_SERVER_USER = git -SSH_TRUSTED_USER_CA_KEYS = ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCb4DC1dMFnJ6pXWo7GMxTchtzmJHYzfN6sZ9FAPFR4ijMLfGki+olvOMO5Fql1/yGnGfbELQa1S6y4shSvj/5K+zUFScmEXYf3Gcr87RqilLkyk16RS+cHNB1u87xTHbETaa3nyCJeGQRpd4IQ4NKob745mwDZ7jQBH8AZEng50Oh8y8fi8skBBBzaYp1ilgvzG740L7uex6fHV62myq0SXeCa+oJUjq326FU8y+Vsa32H8A3e7tOgXZPdt2TVNltx2S9H2WO8RMi7LfaSwARNfy1zu+bfR50r6ef8Yx5YKCMz4wWb1SHU1GS800mjOjlInLQORYRNMlSwR1+vLlVDciOqFapDSbj+YOVOawR0R1aqlSKpZkt33DuOBPx9qe6CVnIi7Z+Px/KqM+OLCzlLY/RS+LbxQpDWcfTVRiP+S5qRTcE3M3UioN/e0BE/1+MpX90IGpvVkA63ILYbKEa4bM3ASL7ChTCr6xN5XT+GpVJveFKK1cfNx9ExHI4rzYE= - -[attachment] -PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql8/data/attachments - -[mailer] -ENABLED = false - -[service] -REGISTER_EMAIL_CONFIRM = false -REGISTER_MANUAL_CONFIRM = false -ENABLE_NOTIFY_MAIL = false -DISABLE_REGISTRATION = false -ENABLE_CAPTCHA = false -REQUIRE_SIGNIN_VIEW = false -DEFAULT_KEEP_EMAIL_PRIVATE = false -DEFAULT_ALLOW_CREATE_ORGANIZATION = true -NO_REPLY_ADDRESS = noreply.example.org - -[picture] -DISABLE_GRAVATAR = false -ENABLE_FEDERATED_AVATAR = false -AVATAR_UPLOAD_PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql8/data/avatars -REPOSITORY_AVATAR_UPLOAD_PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql8/data/repo-avatars - -[session] -PROVIDER = file -PROVIDER_CONFIG = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql8/data/sessions - -[log] -MODE = {{TEST_LOGGER}} -ROOT_PATH = {{REPO_TEST_DIR}}mysql8-log -ENABLE_SSH_LOG = true -logger.xorm.MODE = file - -[log.test] -LEVEL = Info -COLORIZE = true - -[log.file] -LEVEL = Debug - -[security] -DISABLE_GIT_HOOKS = false -INSTALL_LOCK = true -SECRET_KEY = 9pCviYTWSb -INTERNAL_TOKEN = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE0OTU1NTE2MTh9.hhSVGOANkaKk3vfCd2jDOIww4pUk0xtg9JRde5UogyQ - -[lfs] -PATH = tests/{{TEST_TYPE}}/gitea-{{TEST_TYPE}}-mysql8/data/lfs - -[packages] -ENABLED = true - -[actions] -ENABLED = true diff --git a/tests/test_utils.go b/tests/test_utils.go index 089b4dce1cc1d..50049e73f01c9 100644 --- a/tests/test_utils.go +++ b/tests/test_utils.go @@ -179,6 +179,20 @@ func InitTest(requireGitea bool) { routers.InitWebInstalled(graceful.GetManager().HammerContext()) } +func PrepareAttachmentsStorage(t testing.TB) { + // prepare attachments directory and files + assert.NoError(t, storage.Clean(storage.Attachments)) + + s, err := storage.NewStorage(setting.LocalStorageType, &setting.Storage{ + Path: filepath.Join(filepath.Dir(setting.AppPath), "tests", "testdata", "data", "attachments"), + }) + assert.NoError(t, err) + assert.NoError(t, s.IterateObjects("", func(p string, obj storage.Object) error { + _, err = storage.Copy(storage.Attachments, p, s, p) + return err + })) +} + func PrepareTestEnv(t testing.TB, skip ...int) func() { t.Helper() ourSkip := 1 diff --git a/tests/testdata/data/attachments/a/0/a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a22 b/tests/testdata/data/attachments/a/0/a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a22 new file mode 100644 index 0000000000000..96fc98807f411 --- /dev/null +++ b/tests/testdata/data/attachments/a/0/a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a22 @@ -0,0 +1 @@ +# This is a release README diff --git a/web_src/css/base.css b/web_src/css/base.css index 1a4e9d16a1436..efb2553db4c88 100644 --- a/web_src/css/base.css +++ b/web_src/css/base.css @@ -11,252 +11,17 @@ --font-weight-bold: 700; /* line-height: use the default value as "modules/normalize.css" */ --line-height-default: normal; - /* backgrounds */ + /* images */ --checkbox-mask-checked: url('data:image/svg+xml;utf8,'); --checkbox-mask-indeterminate: url('data:image/svg+xml;utf8,'); --octicon-chevron-right: url('data:image/svg+xml;utf8,'); - /* non-color variables */ + /* other variables */ --border-radius: 4px; --border-radius-medium: 6px; --border-radius-circle: 50%; --opacity-disabled: 0.55; --height-loading: 16rem; --tab-size: 4; - /* base colors */ - --color-primary: #4183c4; - --color-primary-contrast: #ffffff; - --color-primary-dark-1: #3876b3; - --color-primary-dark-2: #31699f; - --color-primary-dark-3: #2b5c8b; - --color-primary-dark-4: #254f77; - --color-primary-dark-5: #193450; - --color-primary-dark-6: #0c1a28; - --color-primary-dark-7: #04080c; - --color-primary-light-1: #548fca; - --color-primary-light-2: #679cd0; - --color-primary-light-3: #7aa8d6; - --color-primary-light-4: #8db5dc; - --color-primary-light-5: #b3cde7; - --color-primary-light-6: #d9e6f3; - --color-primary-light-7: #f4f8fb; - --color-primary-alpha-10: #4183c419; - --color-primary-alpha-20: #4183c433; - --color-primary-alpha-30: #4183c44b; - --color-primary-alpha-40: #4183c466; - --color-primary-alpha-50: #4183c480; - --color-primary-alpha-60: #4183c499; - --color-primary-alpha-70: #4183c4b3; - --color-primary-alpha-80: #4183c4cc; - --color-primary-alpha-90: #4183c4e1; - --color-primary-hover: var(--color-primary-dark-1); - --color-primary-active: var(--color-primary-dark-2); - --color-secondary: #dedede; - --color-secondary-dark-1: #cecece; - --color-secondary-dark-2: #bfbfbf; - --color-secondary-dark-3: #a0a0a0; - --color-secondary-dark-4: #909090; - --color-secondary-dark-5: #818181; - --color-secondary-dark-6: #717171; - --color-secondary-dark-7: #626262; - --color-secondary-dark-8: #525252; - --color-secondary-dark-9: #434343; - --color-secondary-dark-10: #333333; - --color-secondary-dark-11: #242424; - --color-secondary-dark-12: #141414; - --color-secondary-dark-13: #040404; - --color-secondary-light-1: #e5e5e5; - --color-secondary-light-2: #ebebeb; - --color-secondary-light-3: #f2f2f2; - --color-secondary-light-4: #f8f8f8; - --color-secondary-alpha-10: #dedede19; - --color-secondary-alpha-20: #dedede33; - --color-secondary-alpha-30: #dedede4b; - --color-secondary-alpha-40: #dedede66; - --color-secondary-alpha-50: #dedede80; - --color-secondary-alpha-60: #dedede99; - --color-secondary-alpha-70: #dededeb3; - --color-secondary-alpha-80: #dededecc; - --color-secondary-alpha-90: #dededee1; - --color-secondary-button: var(--color-secondary-dark-4); - --color-secondary-hover: var(--color-secondary-dark-5); - --color-secondary-active: var(--color-secondary-dark-6); - /* console colors - used for actions console and console files */ - --color-console-fg: #eeeff2; - --color-console-fg-subtle: #959cab; - --color-console-bg: #262936; - --color-console-border: #383c47; - --color-console-hover-bg: #ffffff16; - --color-console-active-bg: #454a57; - --color-console-menu-bg: #383c47; - --color-console-menu-border: #5c6374; - /* named colors */ - --color-red: #db2828; - --color-orange: #f2711c; - --color-yellow: #fbbd08; - --color-olive: #b5cc18; - --color-green: #21ba45; - --color-teal: #00b5ad; - --color-blue: #2185d0; - --color-violet: #6435c9; - --color-purple: #a333c8; - --color-pink: #e03997; - --color-brown: #a5673f; - --color-black: #1b1c1d; - /* light variants - produced via Sass scale-color(color, $lightness: +25%) */ - --color-red-light: #e45e5e; - --color-orange-light: #f59555; - --color-yellow-light: #fcce46; - --color-olive-light: #d3e942; - --color-green-light: #46de6a; - --color-teal-light: #08fff4; - --color-blue-light: #51a5e3; - --color-violet-light: #8b67d7; - --color-purple-light: #bb64d8; - --color-pink-light: #e86bb1; - --color-brown-light: #c58b66; - --color-black-light: #525558; - /* dark 1 variants - produced via Sass scale-color(color, $lightness: -10%) */ - --color-red-dark-1: #c82121; - --color-orange-dark-1: #e6630d; - --color-yellow-dark-1: #e5ac04; - --color-olive-dark-1: #a3b816; - --color-green-dark-1: #1ea73e; - --color-teal-dark-1: #00a39c; - --color-blue-dark-1: #1e78bb; - --color-violet-dark-1: #5a30b5; - --color-purple-dark-1: #932eb4; - --color-pink-dark-1: #db228a; - --color-brown-dark-1: #955d39; - --color-black-dark-1: #18191a; - /* dark 2 variants - produced via Sass scale-color(color, $lightness: -20%) */ - --color-red-dark-2: #b11e1e; - --color-orange-dark-2: #cc580c; - --color-yellow-dark-2: #cc9903; - --color-olive-dark-2: #91a313; - --color-green-dark-2: #1a9537; - --color-teal-dark-2: #00918a; - --color-blue-dark-2: #1a6aa6; - --color-violet-dark-2: #502aa1; - --color-purple-dark-2: #8229a0; - --color-pink-dark-2: #c21e7b; - --color-brown-dark-2: #845232; - --color-black-dark-2: #161617; - /* ansi colors used for actions console and console files */ - --color-ansi-black: var(--color-black); - --color-ansi-red: var(--color-red); - --color-ansi-green: var(--color-green); - --color-ansi-yellow: var(--color-yellow); - --color-ansi-blue: var(--color-blue); - --color-ansi-magenta: var(--color-pink); - --color-ansi-cyan: var(--color-teal); - --color-ansi-white: var(--color-console-fg-subtle); - --color-ansi-bright-black: var(--color-black-light); - --color-ansi-bright-red: var(--color-red-light); - --color-ansi-bright-green: var(--color-green-light); - --color-ansi-bright-yellow: var(--color-yellow-light); - --color-ansi-bright-blue: var(--color-blue-light); - --color-ansi-bright-magenta: var(--color-pink-light); - --color-ansi-bright-cyan: var(--color-teal-light); - --color-ansi-bright-white: var(--color-console-fg); - /* other colors */ - --color-grey: #707070; - --color-grey-light: #838383; - --color-gold: #a1882b; - --color-white: #ffffff; - --color-diff-removed-word-bg: #fdb8c0; - --color-diff-added-word-bg: #acf2bd; - --color-diff-removed-row-bg: #ffeef0; - --color-diff-moved-row-bg: #f1f8d1; - --color-diff-added-row-bg: #e6ffed; - --color-diff-removed-row-border: #f1c0c0; - --color-diff-moved-row-border: #d0e27f; - --color-diff-added-row-border: #e6ffed; - --color-diff-inactive: #f2f2f2; - --color-error-border: #e0b4b4; - --color-error-bg: #fff6f6; - --color-error-bg-active: #fbb; - --color-error-bg-hover: #fdd; - --color-error-text: #9f3a38; - --color-success-border: #a3c293; - --color-success-bg: #fcfff5; - --color-success-text: #2c662d; - --color-warning-border: #c9ba9b; - --color-warning-bg: #fffaf3; - --color-warning-text: #573a08; - --color-info-border: #a9d5de; - --color-info-bg: #f8ffff; - --color-info-text: #276f86; - --color-red-badge: #db2828; - --color-red-badge-bg: #db28281a; - --color-red-badge-hover-bg: #db28284d; - --color-green-badge: #21ba45; - --color-green-badge-bg: #21ba451a; - --color-green-badge-hover-bg: #21ba454d; - --color-yellow-badge: #fbbd08; - --color-yellow-badge-bg: #fbbd081a; - --color-yellow-badge-hover-bg: #fbbd084d; - --color-orange-badge: #f2711c; - --color-orange-badge-bg: #f2711c1a; - --color-orange-badge-hover-bg: #f2711c4d; - --color-git: #f05133; - /* target-based colors */ - --color-body: #ffffff; - --color-text-dark: #080808; - --color-text: #212121; - --color-text-light: #555555; - --color-text-light-1: #6a6a6a; - --color-text-light-2: #808080; - --color-text-light-3: #a0a0a0; - --color-box-header: #f7f7f7; - --color-box-body: #ffffff; - --color-box-body-highlight: #fafafa; - --color-footer: #ffffff; - --color-timeline: #ececec; - --color-input-text: #212121; - --color-input-background: #fafafa; - --color-input-toggle-background: #dedede; - --color-input-border: var(--color-secondary); - --color-input-border-hover: var(--color-secondary-dark-1); - --color-header-wrapper: transparent; - --color-light: #00000006; - --color-light-mimic-enabled: rgba(0, 0, 0, calc(6 / 255 * 222 / 255 / var(--opacity-disabled))); - --color-light-border: #0000001d; - --color-hover: #00000014; - --color-active: #0000001b; - --color-menu: #fafafa; - --color-card: #fafafa; - --color-markup-table-row: #00000008; - --color-markup-code-block: #00000010; - --color-button: #fafafa; - --color-code-bg: #ffffff; - --color-code-sidebar-bg: #f5f5f5; - --color-shadow: #00000026; - --color-secondary-bg: #f4f4f4; - --color-expand-button: #d8efff; - --color-placeholder-text: #aaa; - --color-editor-line-highlight: var(--color-primary-light-6); - --color-project-board-bg: var(--color-secondary-light-4); - --color-project-board-dark-label: #111111; - --color-project-board-light-label: #eeeeee; - --color-caret: var(--color-text-dark); - --color-reaction-bg: #0000000a; - --color-reaction-hover-bg: var(--color-primary-light-5); - --color-reaction-active-bg: var(--color-primary-light-6); - --color-tooltip-text: #ffffff; - --color-tooltip-bg: #000000f0; - --color-nav-bg: #ffffff; - --color-nav-hover-bg: #ebebeb; - --color-nav-text: var(--color-text); - --color-label-text: #232323; - --color-label-bg: #cacaca5b; - --color-label-hover-bg: #cacacaa0; - --color-label-active-bg: #cacacaff; - --color-accent: var(--color-primary-light-1); - --color-small-accent: var(--color-primary-light-6); - --color-active-line: #fffbdd; - --color-overlay-backdrop: #080808c0; - accent-color: var(--color-accent); - color-scheme: light; } :root * { @@ -1328,13 +1093,6 @@ img.ui.avatar, display: inline-block; /* not sure whether it is still needed */ } -.ui .button.copy-commit-sha { - border: 1px solid var(--color-light-border); - margin-right: 3px; - padding: 6px 6px 4px; - background: var(--color-light); -} - .ui .button.truncate { display: inline-block; max-width: 100%; diff --git a/web_src/css/index.css b/web_src/css/index.css index d399f073d557f..c1360bb19446c 100644 --- a/web_src/css/index.css +++ b/web_src/css/index.css @@ -32,11 +32,7 @@ @import "./markup/asciicast.css"; @import "./chroma/base.css"; -@import "./chroma/light.css"; - @import "./codemirror/base.css"; -@import "./codemirror/light.css"; - @import "./font_i18n.css"; @import "./base.css"; @import "./home.css"; diff --git a/web_src/css/markup/content.css b/web_src/css/markup/content.css index 59b34b7dd7cee..caefa1605ccac 100644 --- a/web_src/css/markup/content.css +++ b/web_src/css/markup/content.css @@ -155,23 +155,29 @@ .markup .task-list-item { list-style-type: none; - position: relative; - line-height: 1.5rem; - min-height: 1.5rem; /* // to render a checkbox list without content `- [ ]`, we need this min-height to make sure the
  • can be visible */ +} + +.markup .task-list-item p + ul { + margin-top: 16px; } .markup .task-list-item input[type="checkbox"] { - position: absolute; - top: 0.25em; - left: -1.6em; + margin: 0 .3em .25em -1.4em; + vertical-align: middle; + padding: 0; +} + +.markup .task-list-item input[type="checkbox"] + p { + margin-left: -0.2em; + display: inline; } -.markup .task-list-item p { - line-height: 1.5rem; +.markup .task-list-item > p { + margin-inline: 16px; } .markup .task-list-item + .task-list-item { - margin-top: 3px; + margin-top: 4px; } .markup input[type="checkbox"] { @@ -327,7 +333,7 @@ .markup img[align="left"], .markup video[align="left"] { - padding-right: 20px; + padding-right: 28px; } .markup .emoji { diff --git a/web_src/css/repo.css b/web_src/css/repo.css index d0d001bf52326..8e3448c43aa62 100644 --- a/web_src/css/repo.css +++ b/web_src/css/repo.css @@ -129,11 +129,13 @@ .repository .filter.menu.labels .label-filter .menu .info { display: inline-block; - padding: 0.5rem 0.25rem; + padding: 0.5rem 0; font-size: 12px; width: 100%; white-space: nowrap; - text-align: center; + margin-left: 10px; + margin-right: 8px; + text-align: left; } .repository .filter.menu.labels .label-filter .menu .info code { @@ -3049,9 +3051,6 @@ tbody.commit-list { .commit-table th.sha { display: none !important; } - .commit-table .commit-list .copy-commit-sha { - display: none !important; - } .comment-header { flex-wrap: wrap; } diff --git a/web_src/css/repo/issue-list.css b/web_src/css/repo/issue-list.css index 17ae6ea38fc67..d2f8e429f5880 100644 --- a/web_src/css/repo/issue-list.css +++ b/web_src/css/repo/issue-list.css @@ -80,3 +80,11 @@ #issue-list .flex-item-body .checklist progress::-moz-progress-bar { background-color: var(--color-secondary-dark-4); } + +.archived-label-filter { + margin-left: 10px; + font-size: 12px; + display: flex !important; + margin-bottom: 8px; + min-width: fit-content; +} diff --git a/web_src/css/shared/flex-list.css b/web_src/css/shared/flex-list.css index a7cfc8f163963..93d8c9b49caf6 100644 --- a/web_src/css/shared/flex-list.css +++ b/web_src/css/shared/flex-list.css @@ -69,7 +69,6 @@ } .flex-item .flex-item-body { - font-size: 13px; display: flex; align-items: center; flex-wrap: wrap; diff --git a/web_src/css/themes/theme-auto.css b/web_src/css/themes/theme-auto.css deleted file mode 100644 index e0d31e2cfbb70..0000000000000 --- a/web_src/css/themes/theme-auto.css +++ /dev/null @@ -1 +0,0 @@ -@import "./theme-arc-green.css" (prefers-color-scheme: dark); diff --git a/web_src/css/themes/theme-gitea-auto.css b/web_src/css/themes/theme-gitea-auto.css new file mode 100644 index 0000000000000..509889e80225b --- /dev/null +++ b/web_src/css/themes/theme-gitea-auto.css @@ -0,0 +1,2 @@ +@import "./theme-gitea-light.css" (prefers-color-scheme: light); +@import "./theme-gitea-dark.css" (prefers-color-scheme: dark); diff --git a/web_src/css/themes/theme-arc-green.css b/web_src/css/themes/theme-gitea-dark.css similarity index 98% rename from web_src/css/themes/theme-arc-green.css rename to web_src/css/themes/theme-gitea-dark.css index 96d9f5821c389..bac002e3db5eb 100644 --- a/web_src/css/themes/theme-arc-green.css +++ b/web_src/css/themes/theme-gitea-dark.css @@ -212,11 +212,12 @@ --color-code-sidebar-bg: #232834; --color-shadow: #00000058; --color-secondary-bg: #2a2e3a; - --color-text-focus: #fff; --color-expand-button: #3c404d; --color-placeholder-text: #8a8e99; --color-editor-line-highlight: var(--color-primary-light-5); --color-project-board-bg: var(--color-secondary-light-2); + --color-project-board-dark-label: #111111; + --color-project-board-light-label: #eeeeee; --color-caret: var(--color-text); /* should ideally be --color-text-dark, see #15651 */ --color-reaction-bg: #ffffff12; --color-reaction-hover-bg: var(--color-primary-light-4); @@ -225,6 +226,7 @@ --color-tooltip-bg: #000000f0; --color-nav-bg: #232834; --color-nav-hover-bg: #383c47; + --color-nav-text: var(--color-text); --color-label-text: #dfe3ec; --color-label-bg: #7c84974b; --color-label-hover-bg: #7c8497a0; diff --git a/web_src/css/themes/theme-gitea-light.css b/web_src/css/themes/theme-gitea-light.css new file mode 100644 index 0000000000000..ca5d15cd25bae --- /dev/null +++ b/web_src/css/themes/theme-gitea-light.css @@ -0,0 +1,240 @@ +@import "../chroma/light.css"; +@import "../codemirror/light.css"; + +:root { + --is-dark-theme: false; + --color-primary: #4183c4; + --color-primary-contrast: #ffffff; + --color-primary-dark-1: #3876b3; + --color-primary-dark-2: #31699f; + --color-primary-dark-3: #2b5c8b; + --color-primary-dark-4: #254f77; + --color-primary-dark-5: #193450; + --color-primary-dark-6: #0c1a28; + --color-primary-dark-7: #04080c; + --color-primary-light-1: #548fca; + --color-primary-light-2: #679cd0; + --color-primary-light-3: #7aa8d6; + --color-primary-light-4: #8db5dc; + --color-primary-light-5: #b3cde7; + --color-primary-light-6: #d9e6f3; + --color-primary-light-7: #f4f8fb; + --color-primary-alpha-10: #4183c419; + --color-primary-alpha-20: #4183c433; + --color-primary-alpha-30: #4183c44b; + --color-primary-alpha-40: #4183c466; + --color-primary-alpha-50: #4183c480; + --color-primary-alpha-60: #4183c499; + --color-primary-alpha-70: #4183c4b3; + --color-primary-alpha-80: #4183c4cc; + --color-primary-alpha-90: #4183c4e1; + --color-primary-hover: var(--color-primary-dark-1); + --color-primary-active: var(--color-primary-dark-2); + --color-secondary: #dedede; + --color-secondary-dark-1: #cecece; + --color-secondary-dark-2: #bfbfbf; + --color-secondary-dark-3: #a0a0a0; + --color-secondary-dark-4: #909090; + --color-secondary-dark-5: #818181; + --color-secondary-dark-6: #717171; + --color-secondary-dark-7: #626262; + --color-secondary-dark-8: #525252; + --color-secondary-dark-9: #434343; + --color-secondary-dark-10: #333333; + --color-secondary-dark-11: #242424; + --color-secondary-dark-12: #141414; + --color-secondary-dark-13: #040404; + --color-secondary-light-1: #e5e5e5; + --color-secondary-light-2: #ebebeb; + --color-secondary-light-3: #f2f2f2; + --color-secondary-light-4: #f8f8f8; + --color-secondary-alpha-10: #dedede19; + --color-secondary-alpha-20: #dedede33; + --color-secondary-alpha-30: #dedede4b; + --color-secondary-alpha-40: #dedede66; + --color-secondary-alpha-50: #dedede80; + --color-secondary-alpha-60: #dedede99; + --color-secondary-alpha-70: #dededeb3; + --color-secondary-alpha-80: #dededecc; + --color-secondary-alpha-90: #dededee1; + --color-secondary-button: var(--color-secondary-dark-4); + --color-secondary-hover: var(--color-secondary-dark-5); + --color-secondary-active: var(--color-secondary-dark-6); + /* console colors - used for actions console and console files */ + --color-console-fg: #eeeff2; + --color-console-fg-subtle: #959cab; + --color-console-bg: #262936; + --color-console-border: #383c47; + --color-console-hover-bg: #ffffff16; + --color-console-active-bg: #454a57; + --color-console-menu-bg: #383c47; + --color-console-menu-border: #5c6374; + /* named colors */ + --color-red: #db2828; + --color-orange: #f2711c; + --color-yellow: #fbbd08; + --color-olive: #b5cc18; + --color-green: #21ba45; + --color-teal: #00b5ad; + --color-blue: #2185d0; + --color-violet: #6435c9; + --color-purple: #a333c8; + --color-pink: #e03997; + --color-brown: #a5673f; + --color-black: #1b1c1d; + /* light variants - produced via Sass scale-color(color, $lightness: +25%) */ + --color-red-light: #e45e5e; + --color-orange-light: #f59555; + --color-yellow-light: #fcce46; + --color-olive-light: #d3e942; + --color-green-light: #46de6a; + --color-teal-light: #08fff4; + --color-blue-light: #51a5e3; + --color-violet-light: #8b67d7; + --color-purple-light: #bb64d8; + --color-pink-light: #e86bb1; + --color-brown-light: #c58b66; + --color-black-light: #525558; + /* dark 1 variants - produced via Sass scale-color(color, $lightness: -10%) */ + --color-red-dark-1: #c82121; + --color-orange-dark-1: #e6630d; + --color-yellow-dark-1: #e5ac04; + --color-olive-dark-1: #a3b816; + --color-green-dark-1: #1ea73e; + --color-teal-dark-1: #00a39c; + --color-blue-dark-1: #1e78bb; + --color-violet-dark-1: #5a30b5; + --color-purple-dark-1: #932eb4; + --color-pink-dark-1: #db228a; + --color-brown-dark-1: #955d39; + --color-black-dark-1: #18191a; + /* dark 2 variants - produced via Sass scale-color(color, $lightness: -20%) */ + --color-red-dark-2: #b11e1e; + --color-orange-dark-2: #cc580c; + --color-yellow-dark-2: #cc9903; + --color-olive-dark-2: #91a313; + --color-green-dark-2: #1a9537; + --color-teal-dark-2: #00918a; + --color-blue-dark-2: #1a6aa6; + --color-violet-dark-2: #502aa1; + --color-purple-dark-2: #8229a0; + --color-pink-dark-2: #c21e7b; + --color-brown-dark-2: #845232; + --color-black-dark-2: #161617; + /* ansi colors used for actions console and console files */ + --color-ansi-black: var(--color-black); + --color-ansi-red: var(--color-red); + --color-ansi-green: var(--color-green); + --color-ansi-yellow: var(--color-yellow); + --color-ansi-blue: var(--color-blue); + --color-ansi-magenta: var(--color-pink); + --color-ansi-cyan: var(--color-teal); + --color-ansi-white: var(--color-console-fg-subtle); + --color-ansi-bright-black: var(--color-black-light); + --color-ansi-bright-red: var(--color-red-light); + --color-ansi-bright-green: var(--color-green-light); + --color-ansi-bright-yellow: var(--color-yellow-light); + --color-ansi-bright-blue: var(--color-blue-light); + --color-ansi-bright-magenta: var(--color-pink-light); + --color-ansi-bright-cyan: var(--color-teal-light); + --color-ansi-bright-white: var(--color-console-fg); + /* other colors */ + --color-grey: #707070; + --color-grey-light: #838383; + --color-gold: #a1882b; + --color-white: #ffffff; + --color-diff-removed-word-bg: #fdb8c0; + --color-diff-added-word-bg: #acf2bd; + --color-diff-removed-row-bg: #ffeef0; + --color-diff-moved-row-bg: #f1f8d1; + --color-diff-added-row-bg: #e6ffed; + --color-diff-removed-row-border: #f1c0c0; + --color-diff-moved-row-border: #d0e27f; + --color-diff-added-row-border: #e6ffed; + --color-diff-inactive: #f2f2f2; + --color-error-border: #e0b4b4; + --color-error-bg: #fff6f6; + --color-error-bg-active: #fbb; + --color-error-bg-hover: #fdd; + --color-error-text: #9f3a38; + --color-success-border: #a3c293; + --color-success-bg: #fcfff5; + --color-success-text: #2c662d; + --color-warning-border: #c9ba9b; + --color-warning-bg: #fffaf3; + --color-warning-text: #573a08; + --color-info-border: #a9d5de; + --color-info-bg: #f8ffff; + --color-info-text: #276f86; + --color-red-badge: #db2828; + --color-red-badge-bg: #db28281a; + --color-red-badge-hover-bg: #db28284d; + --color-green-badge: #21ba45; + --color-green-badge-bg: #21ba451a; + --color-green-badge-hover-bg: #21ba454d; + --color-yellow-badge: #fbbd08; + --color-yellow-badge-bg: #fbbd081a; + --color-yellow-badge-hover-bg: #fbbd084d; + --color-orange-badge: #f2711c; + --color-orange-badge-bg: #f2711c1a; + --color-orange-badge-hover-bg: #f2711c4d; + --color-git: #f05133; + /* target-based colors */ + --color-body: #ffffff; + --color-box-header: #f7f7f7; + --color-box-body: #ffffff; + --color-box-body-highlight: #fafafa; + --color-text-dark: #080808; + --color-text: #212121; + --color-text-light: #555555; + --color-text-light-1: #6a6a6a; + --color-text-light-2: #808080; + --color-text-light-3: #a0a0a0; + --color-footer: #ffffff; + --color-timeline: #ececec; + --color-input-text: #212121; + --color-input-background: #fafafa; + --color-input-toggle-background: #dedede; + --color-input-border: var(--color-secondary); + --color-input-border-hover: var(--color-secondary-dark-1); + --color-header-wrapper: transparent; + --color-light: #00000006; + --color-light-mimic-enabled: rgba(0, 0, 0, calc(6 / 255 * 222 / 255 / var(--opacity-disabled))); + --color-light-border: #0000001d; + --color-hover: #00000014; + --color-active: #0000001b; + --color-menu: #fafafa; + --color-card: #fafafa; + --color-markup-table-row: #00000008; + --color-markup-code-block: #00000010; + --color-button: #fafafa; + --color-code-bg: #ffffff; + --color-code-sidebar-bg: #f5f5f5; + --color-shadow: #00000026; + --color-secondary-bg: #f4f4f4; + --color-expand-button: #d8efff; + --color-placeholder-text: #aaa; + --color-editor-line-highlight: var(--color-primary-light-6); + --color-project-board-bg: var(--color-secondary-light-4); + --color-project-board-dark-label: #111111; + --color-project-board-light-label: #eeeeee; + --color-caret: var(--color-text-dark); + --color-reaction-bg: #0000000a; + --color-reaction-hover-bg: var(--color-primary-light-5); + --color-reaction-active-bg: var(--color-primary-light-6); + --color-tooltip-text: #ffffff; + --color-tooltip-bg: #000000f0; + --color-nav-bg: #ffffff; + --color-nav-hover-bg: #ebebeb; + --color-nav-text: var(--color-text); + --color-label-text: #232323; + --color-label-bg: #cacaca5b; + --color-label-hover-bg: #cacacaa0; + --color-label-active-bg: #cacacaff; + --color-accent: var(--color-primary-light-1); + --color-small-accent: var(--color-primary-light-6); + --color-active-line: #fffbdd; + --color-overlay-backdrop: #080808c0; + accent-color: var(--color-accent); + color-scheme: light; +} diff --git a/web_src/js/features/admin/config.js b/web_src/js/features/admin/config.js index f5d8fae8facf3..c3823425adb58 100644 --- a/web_src/js/features/admin/config.js +++ b/web_src/js/features/admin/config.js @@ -1,37 +1,24 @@ -import $ from 'jquery'; import {showTemporaryTooltip} from '../../modules/tippy.js'; +import {POST} from '../../modules/fetch.js'; -const {appSubUrl, csrfToken, pageData} = window.config; +const {appSubUrl} = window.config; export function initAdminConfigs() { - const isAdminConfigPage = pageData?.adminConfigPage; - if (!isAdminConfigPage) return; + const elAdminConfig = document.querySelector('.page-content.admin.config'); + if (!elAdminConfig) return; - $("input[type='checkbox']").on('change', (e) => { - const $this = $(e.currentTarget); - $.ajax({ - url: `${appSubUrl}/admin/config`, - type: 'POST', - data: { - _csrf: csrfToken, - key: $this.attr('name'), - value: $this.is(':checked'), - version: $this.attr('version'), - } - }).done((resp) => { - if (resp) { - if (resp.redirect) { - window.location.href = resp.redirect; - } else if (resp.version) { - $this.attr('version', resp.version); - } else if (resp.err) { - showTemporaryTooltip(e.currentTarget, resp.err); - $this.prop('checked', !$this.is(':checked')); - } + for (const el of elAdminConfig.querySelectorAll('input[type="checkbox"][data-config-dyn-key]')) { + el.addEventListener('change', async () => { + try { + const resp = await POST(`${appSubUrl}/admin/config`, { + data: new URLSearchParams({key: el.getAttribute('data-config-dyn-key'), value: el.checked}), + }); + const json = await resp.json(); + if (json.errorMessage) throw new Error(json.errorMessage); + } catch (ex) { + showTemporaryTooltip(el, ex.toString()); + el.checked = !el.checked; } }); - - e.preventDefault(); - return false; - }); + } } diff --git a/web_src/js/features/emoji.js b/web_src/js/features/emoji.js index d00ff6545658c..032a3efe8aa6a 100644 --- a/web_src/js/features/emoji.js +++ b/web_src/js/features/emoji.js @@ -23,7 +23,7 @@ for (const key of emojiKeys) { // retrieve HTML for given emoji name export function emojiHTML(name) { let inner; - if (Object.prototype.hasOwnProperty.call(customEmojis, name)) { + if (Object.hasOwn(customEmojis, name)) { inner = `:${name}:`; } else { inner = emojiString(name); diff --git a/web_src/js/features/repo-issue-list.js b/web_src/js/features/repo-issue-list.js index af4586121edc4..a9a8628ba77dd 100644 --- a/web_src/js/features/repo-issue-list.js +++ b/web_src/js/features/repo-issue-list.js @@ -73,7 +73,7 @@ function initRepoIssueListCheckboxes() { url, action, issueIDs, - elementId + elementId, ).then(() => { window.location.reload(); }).catch((reason) => { @@ -185,9 +185,42 @@ async function initIssuePinSort() { }); } +function initArchivedLabelFilter() { + const archivedLabelEl = document.querySelector('#archived-filter-checkbox'); + if (!archivedLabelEl) { + return; + } + + const url = new URL(window.location.href); + const archivedLabels = document.querySelectorAll('[data-is-archived]'); + + const selectedLabels = (url.searchParams.get('labels') || '') + .split(',') + .map((id) => id < 0 ? `${~id + 1}` : id); // selectedLabels contains -ve ids, which are excluded so convert any -ve value id to +ve + + const archivedElToggle = () => { + for (const label of archivedLabels) { + const id = label.getAttribute('data-label-id'); + toggleElem(label, archivedLabelEl.checked || selectedLabels.includes(id)); + } + }; + + archivedElToggle(); + archivedLabelEl.addEventListener('change', () => { + archivedElToggle(); + if (archivedLabelEl.checked) { + url.searchParams.set('archived', 'true'); + } else { + url.searchParams.delete('archived'); + } + window.location.href = url.href; + }); +} + export function initRepoIssueList() { if (!document.querySelectorAll('.page-content.repository.issue-list, .page-content.repository.milestone-issue-list').length) return; initRepoIssueListCheckboxes(); initRepoIssueListAuthorDropdown(); initIssuePinSort(); + initArchivedLabelFilter(); } diff --git a/web_src/js/markup/mermaid.js b/web_src/js/markup/mermaid.js index 865a414c93367..84d88a94c3ddb 100644 --- a/web_src/js/markup/mermaid.js +++ b/web_src/js/markup/mermaid.js @@ -4,9 +4,11 @@ import {displayError} from './common.js'; const {mermaidMaxSourceCharacters} = window.config; +// margin removal is for https://github.com/mermaid-js/mermaid/issues/4907 const iframeCss = `:root {color-scheme: normal} body {margin: 0; padding: 0; overflow: hidden} -#mermaid {display: block; margin: 0 auto}`; +#mermaid {display: block; margin: 0 auto} +blockquote, dd, dl, figure, h1, h2, h3, h4, h5, h6, hr, p, pre {margin: 0}`; export async function renderMermaid() { const els = document.querySelectorAll('.markup code.language-mermaid');